4 * Abstract Syntax Notation 1 Encoding Rules
6 * Portable Windows Library
8 * Copyright (c) 1993-1998 Equivalence Pty. Ltd.
10 * The contents of this file are subject to the Mozilla Public License
11 * Version 1.0 (the "License"); you may not use this file except in
12 * compliance with the License. You may obtain a copy of the License at
13 * http://www.mozilla.org/MPL/
15 * Software distributed under the License is distributed on an "AS IS"
16 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
17 * the License for the specific language governing rights and limitations
20 * The Original Code is Portable Windows Library.
22 * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
24 * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
25 * All Rights Reserved.
27 * Contributor(s): ______________________________________.
30 * Revision 1.50 2001/08/07 04:37:03 robertj
31 * Simplified &#num; parsing.
33 * Revision 1.49 2001/08/07 02:49:05 robertj
34 * Fixed incorrect alignment if constrained string upper bound is exactly
35 * 16 bits long. thanks Guntram Diehl & Thomas Arimont.
37 * Revision 1.48 2001/08/06 09:35:25 robertj
38 * Fixed GNU compatibility.
40 * Revision 1.47 2001/08/06 09:31:48 robertj
41 * Added conversion of BMPString to PString without losing special characters.
43 * Revision 1.46 2001/08/06 01:39:02 robertj
44 * Added assignement operator with RHS of PASN_BMPString to classes
45 * descended from PASN_BMPString.
47 * Revision 1.45 2001/06/14 02:14:12 robertj
48 * Added functions to encode and decode another ASN type that is inside
49 * an octet string, useful for ANY or EXTERNAL types etc.
51 * Revision 1.44 2001/05/29 00:59:16 robertj
52 * Fixed excessive padding on constrained strings.
54 * Revision 1.43 2001/05/22 23:37:42 robertj
55 * Fixed problem with assigning a constrained string value to itself, which
56 * can occur when changing constraints.
58 * Revision 1.42 2001/04/30 10:47:33 robertj
59 * Fixed stupid error in last patch.
61 * Revision 1.41 2001/04/30 06:47:04 robertj
62 * Fixed problem with en/decoding more than 16 extension fields in a sequence.
64 * Revision 1.40 2001/04/26 08:15:58 robertj
65 * Fixed problem with ASN compile of single constraints on enumerations.
67 * Revision 1.39 2001/04/23 05:46:06 robertj
68 * Fixed problem with unconstrained PASN_NumericString coding in 8 bits
69 * instead of 4, thanks Chew Kuan.
71 * Revision 1.38 2001/04/23 04:40:14 robertj
72 * Added ASN standard types GeneralizedTime and UTCTime
74 * Revision 1.37 2001/04/12 03:26:59 robertj
75 * Fixed PASN_Boolean cosntructor to be compatible with usage in ASN parser.
76 * Changed all PASN_xxx types so constructor can take real type as only
77 * parameter. eg PASN_OctetString s = "fred";
78 * Changed block encode/decode so does not do a ByteAlign() if zero
79 * length, required for interoperability even though spec implies otherwise..
81 * Revision 1.36 2001/01/24 04:37:07 robertj
82 * Added more bulletproofing to ASN structures to obey constraints.
84 * Revision 1.35 2001/01/03 01:20:13 robertj
85 * Fixed error in BlockEncode, should ByteAlign() even on zero length strings.
87 * Revision 1.34 2000/10/26 11:09:16 robertj
88 * More bullet proofing of PER decoder, changed bit type to be unsigned.
90 * Revision 1.33 2000/10/26 01:29:32 robertj
93 * Revision 1.32 2000/10/25 04:05:38 robertj
94 * More bullet proofing of PER decoder.
96 * Revision 1.31 2000/09/29 04:11:51 robertj
97 * Fixed possible out of range memory access, thanks Petr Parýzek <paryzek@wo.cz>
99 * Revision 1.30 2000/02/29 06:32:12 robertj
100 * Added ability to remove optional field in sequence, thanks Dave Harvey.
102 * Revision 1.29 2000/01/20 06:22:22 robertj
103 * Fixed boundary condition error for constrained integer encoding (values 1, 256 etc)
105 * Revision 1.28 1999/11/22 23:15:43 robertj
106 * Fixed bug in PASN_Choice::Compare(), should make sure choices are the same before comparing.
108 * Revision 1.27 1999/08/19 15:43:07 robertj
109 * Fixed incorrect size of OID if zero length encoded.
111 * Revision 1.26 1999/08/09 13:02:45 robertj
112 * dded ASN compiler #defines for backward support of pre GCC 2.9 compilers.
113 * Added ASN compiler #defines to reduce its memory footprint.
115 * Revision 1.25 1999/08/08 15:45:59 robertj
116 * Fixed incorrect encoding of unknown extensions.
118 * Revision 1.24 1999/08/05 00:44:28 robertj
119 * Fixed PER encoding problems for large integer values.
121 * Revision 1.23 1999/07/22 06:48:54 robertj
122 * Added comparison operation to base ASN classes and compiled ASN code.
123 * Added support for ANY type in ASN parser.
125 * Revision 1.22 1999/07/08 08:39:12 robertj
126 * Fixed bug when assigning negative number ot cosntrained PASN_Integer
128 * Revision 1.21 1999/06/30 08:58:12 robertj
129 * Fixed bug in encoding/decoding OID greater than 2.39
131 * Revision 1.20 1999/06/17 13:27:09 robertj
132 * Fixed bug causing crashes on pass through of unknown extensions.
134 * Revision 1.19 1999/06/07 00:31:25 robertj
135 * Fixed signed/unsigned problem with number of unknown extensions check.
137 * Revision 1.18 1999/04/26 05:58:48 craigs
138 * Fixed problems with encoding of extensions
140 * Revision 1.17 1999/03/09 08:12:38 robertj
141 * Fixed problem with closing a steam encoding twice.
143 * Revision 1.16 1999/01/16 01:28:25 robertj
144 * Fixed problems with reading stream multiple times.
146 * Revision 1.15 1998/11/30 04:50:44 robertj
147 * New directory structure
149 * Revision 1.14 1998/10/22 04:33:11 robertj
150 * Fixed bug in constrained strings and PER, incorrect order of character set.
152 * Revision 1.13 1998/09/23 06:21:49 robertj
153 * Added open source copyright license.
155 * Revision 1.12 1998/05/26 05:29:23 robertj
156 * Workaroung for g++ iostream bug.
158 * Revision 1.11 1998/05/21 04:58:54 robertj
161 * Revision 1.10 1998/05/21 04:26:54 robertj
162 * Fixed numerous PER problems.
164 * Revision 1.9 1998/05/11 06:01:55 robertj
165 * Why did this compile under MSC?
167 * Revision 1.8 1998/05/07 05:19:29 robertj
168 * Fixed problems with using copy constructor/assignment oeprator on PASN_Objects.
170 * Revision 1.7 1998/03/05 12:49:50 robertj
173 * Revision 1.6 1998/02/03 06:28:27 robertj
174 * Fixed length calculation of integers in BER.
175 * Added new function to read a block with minimum number of bytes.
177 * Revision 1.5 1998/01/26 01:51:20 robertj
178 * Removed uninitialised variable warnings.
180 * Revision 1.4 1997/12/18 05:07:56 robertj
181 * Fixed bug in choice name display.
182 * Added function to get choice discriminator name.
183 * Fixed bug in encoding extensions.
185 * Revision 1.3 1997/12/11 10:36:22 robertj
186 * Support for new ASN parser.
193 #pragma implementation "asner.h"
196 #include <ptclib/asner.h>
201 static PINDEX
CountBits(unsigned range
)
204 return sizeof(unsigned)*8;
207 while (nBits
< (sizeof(unsigned)*8) && range
> (unsigned)(1 << nBits
))
213 ///////////////////////////////////////////////////////////////////////
215 PASN_Object::PASN_Object(unsigned theTag
, TagClass theTagClass
, BOOL extend
)
221 if (theTagClass
!= DefaultTagClass
)
222 tagClass
= theTagClass
;
224 tagClass
= ContextSpecificTagClass
;
228 void PASN_Object::SetTag(unsigned newTag
, TagClass tagClass_
)
231 if (tagClass_
!= DefaultTagClass
)
232 tagClass
= tagClass_
;
236 PINDEX
PASN_Object::GetObjectLength() const
241 len
+= (CountBits(tag
)+6)/7;
243 PINDEX dataLen
= GetDataLength();
247 len
+= (CountBits(dataLen
)+7)/8 + 1;
249 return len
+ dataLen
;
253 void PASN_Object::SetConstraintBounds(ConstraintType
, int, unsigned)
258 void PASN_Object::SetCharacterSet(ConstraintType
, const char *)
263 void PASN_Object::SetCharacterSet(ConstraintType
, unsigned, unsigned)
268 ///////////////////////////////////////////////////////////////////////
270 PASN_ConstrainedObject::PASN_ConstrainedObject(unsigned tag
, TagClass tagClass
)
271 : PASN_Object(tag
, tagClass
)
273 constraint
= Unconstrained
;
275 upperLimit
= UINT_MAX
;
279 void PASN_ConstrainedObject::SetConstraintBounds(ConstraintType ctype
,
280 int lower
, unsigned upper
)
283 if (constraint
== Unconstrained
) {
288 extendable
= ctype
== ExtendableConstraint
;
289 PAssert((lower
>= 0 || upper
< 0x7fffffff) &&
290 (lower
< 0 || (unsigned)lower
<= upper
), PInvalidParameter
);
296 int PASN_ConstrainedObject::ConstrainedLengthDecode(PPER_Stream
& strm
, unsigned & length
)
298 // The execution order is important in the following. The SingleBitDecode() function
299 // must be called if extendable is TRUE, no matter what.
300 if ((extendable
&& strm
.SingleBitDecode()) || constraint
== Unconstrained
)
301 return strm
.LengthDecode(0, INT_MAX
, length
);
303 return strm
.LengthDecode(lowerLimit
, upperLimit
, length
);
307 void PASN_ConstrainedObject::ConstrainedLengthEncode(PPER_Stream
& strm
, unsigned length
) const
309 if (ConstraintEncode(strm
, length
)) // 26.4
310 strm
.LengthEncode(length
, 0, INT_MAX
);
312 strm
.LengthEncode(length
, lowerLimit
, upperLimit
);
316 BOOL
PASN_ConstrainedObject::ConstraintEncode(PPER_Stream
& strm
, unsigned value
) const
319 return constraint
!= FixedConstraint
;
321 BOOL needsExtending
= value
> upperLimit
;
323 if (!needsExtending
) {
324 if (lowerLimit
< 0) {
325 if ((int)value
< lowerLimit
)
326 needsExtending
= TRUE
;
329 if (value
< (unsigned)lowerLimit
)
330 needsExtending
= TRUE
;
334 strm
.SingleBitEncode(needsExtending
);
336 return needsExtending
|| constraint
!= FixedConstraint
;
340 ///////////////////////////////////////////////////////////////////////
342 PASN_Null::PASN_Null(unsigned tag
, TagClass tagClass
)
343 : PASN_Object(tag
, tagClass
)
348 PObject::Comparison
PASN_Null::Compare(const PObject
& obj
) const
350 PAssert(obj
.IsDescendant(PASN_Null::Class()), PInvalidCast
);
355 PObject
* PASN_Null::Clone() const
357 PAssert(IsClass(PASN_Null::Class()), PInvalidCast
);
358 return new PASN_Null(*this);
362 void PASN_Null::PrintOn(ostream
& strm
) const
368 PString
PASN_Null::GetTypeAsString() const
374 PINDEX
PASN_Null::GetDataLength() const
380 BOOL
PASN_Null::Decode(PASN_Stream
& strm
)
382 return strm
.NullDecode(*this);
386 void PASN_Null::Encode(PASN_Stream
& strm
) const
388 strm
.NullEncode(*this);
392 BOOL
PBER_Stream::NullDecode(PASN_Null
& value
)
395 if (!HeaderDecode(value
, len
))
403 void PBER_Stream::NullEncode(const PASN_Null
& value
)
409 BOOL
PPER_Stream::NullDecode(PASN_Null
&)
415 void PPER_Stream::NullEncode(const PASN_Null
&)
420 ///////////////////////////////////////////////////////////////////////
422 PASN_Boolean::PASN_Boolean(BOOL val
)
423 : PASN_Object(UniversalBoolean
, UniversalTagClass
)
429 PASN_Boolean::PASN_Boolean(unsigned tag
, TagClass tagClass
, BOOL val
)
430 : PASN_Object(tag
, tagClass
)
436 PObject::Comparison
PASN_Boolean::Compare(const PObject
& obj
) const
438 PAssert(obj
.IsDescendant(PASN_Boolean::Class()), PInvalidCast
);
439 return value
== ((const PASN_Boolean
&)obj
).value
? EqualTo
: GreaterThan
;
443 PObject
* PASN_Boolean::Clone() const
445 PAssert(IsClass(PASN_Boolean::Class()), PInvalidCast
);
446 return new PASN_Boolean(*this);
450 void PASN_Boolean::PrintOn(ostream
& strm
) const
459 PString
PASN_Boolean::GetTypeAsString() const
465 PINDEX
PASN_Boolean::GetDataLength() const
471 BOOL
PASN_Boolean::Decode(PASN_Stream
& strm
)
473 return strm
.BooleanDecode(*this);
477 void PASN_Boolean::Encode(PASN_Stream
& strm
) const
479 strm
.BooleanEncode(*this);
483 BOOL
PBER_Stream::BooleanDecode(PASN_Boolean
& value
)
486 if (!HeaderDecode(value
, len
))
492 value
= (BOOL
)ByteDecode();
499 void PBER_Stream::BooleanEncode(const PASN_Boolean
& value
)
502 ByteEncode((BOOL
)value
);
506 BOOL
PPER_Stream::BooleanDecode(PASN_Boolean
& value
)
512 value
= (BOOL
)SingleBitDecode();
517 void PPER_Stream::BooleanEncode(const PASN_Boolean
& value
)
520 SingleBitEncode((BOOL
)value
);
524 ///////////////////////////////////////////////////////////////////////
526 PASN_Integer::PASN_Integer(unsigned val
)
527 : PASN_ConstrainedObject(UniversalInteger
, UniversalTagClass
)
533 PASN_Integer::PASN_Integer(unsigned tag
, TagClass tagClass
, unsigned val
)
534 : PASN_ConstrainedObject(tag
, tagClass
)
540 PASN_Integer
& PASN_Integer::operator=(unsigned val
)
542 if (constraint
== Unconstrained
)
544 else if (lowerLimit
>= 0) { // Is unsigned integer
545 if (val
< (unsigned)lowerLimit
)
547 else if (val
> upperLimit
)
554 if (ival
< lowerLimit
)
556 else if (upperLimit
< INT_MAX
&& ival
> (int)upperLimit
)
566 PObject::Comparison
PASN_Integer::Compare(const PObject
& obj
) const
568 PAssert(obj
.IsDescendant(PASN_Integer::Class()), PInvalidCast
);
569 const PASN_Integer
& other
= (const PASN_Integer
&)obj
;
571 if (value
< other
.value
)
574 if (value
> other
.value
)
581 PObject
* PASN_Integer::Clone() const
583 PAssert(IsClass(PASN_Integer::Class()), PInvalidCast
);
584 return new PASN_Integer(*this);
588 void PASN_Integer::PrintOn(ostream
& strm
) const
597 void PASN_Integer::SetConstraintBounds(ConstraintType type
, int lower
, unsigned upper
)
599 PASN_ConstrainedObject::SetConstraintBounds(type
, lower
, upper
);
600 if (constraint
!= Unconstrained
) {
601 if ((int)value
< lowerLimit
)
603 else if (value
> upperLimit
)
609 PString
PASN_Integer::GetTypeAsString() const
615 static PINDEX
GetIntegerDataLength(int value
)
617 // create a mask which is the top nine bits of a DWORD, or 0xFF800000
618 // on a big endian machine
619 int shift
= (sizeof(value
)-1)*8-1;
621 // remove all sequences of nine 0's or 1's at the start of the value
622 while (shift
> 0 && ((value
>> shift
)&0x1ff) == (value
< 0 ? 0x1ff : 0))
629 PINDEX
PASN_Integer::GetDataLength() const
631 return GetIntegerDataLength(value
);
635 BOOL
PASN_Integer::Decode(PASN_Stream
& strm
)
637 return strm
.IntegerDecode(*this);
641 void PASN_Integer::Encode(PASN_Stream
& strm
) const
643 strm
.IntegerEncode(*this);
647 BOOL
PBER_Stream::IntegerDecode(PASN_Integer
& value
)
650 if (!HeaderDecode(value
, len
) || len
== 0 || IsAtEnd())
653 int accumulator
= (char)ByteDecode(); // sign extended first byte
657 accumulator
= (accumulator
<< 8) | ByteDecode();
665 void PBER_Stream::IntegerEncode(const PASN_Integer
& value
)
668 // output the integer bits
669 for (int count
= GetIntegerDataLength(value
)-1; count
>= 0; count
--)
670 ByteEncode(value
>> (count
*8));
674 BOOL
PPER_Stream::IntegerDecode(PASN_Integer
& value
)
676 return value
.DecodePER(*this);
680 void PPER_Stream::IntegerEncode(const PASN_Integer
& value
)
682 value
.EncodePER(*this);
686 BOOL
PASN_Integer::DecodePER(PPER_Stream
& strm
)
690 if ((extendable
&& strm
.SingleBitDecode()) || constraint
!= FixedConstraint
) { // 12.1
692 if (strm
.LengthDecode(0, INT_MAX
, len
) != 0)
694 return strm
.MultiBitDecode(len
*8, value
);
697 if ((unsigned)lowerLimit
!= upperLimit
) // 12.2.1
698 return strm
.UnsignedDecode(lowerLimit
, upperLimit
, value
) == 0; // 12.2.2 which devolves to 10.5
705 void PASN_Integer::EncodePER(PPER_Stream
& strm
) const
709 if (ConstraintEncode(strm
, (int)value
)) { // 12.1
711 unsigned adjusted_value
= value
- lowerLimit
;
712 if (adjusted_value
== 0)
715 PINDEX nBits
= CountBits(adjusted_value
+1);
716 nBytes
= (nBits
+7)/8;
718 strm
.LengthEncode(nBytes
, 0, INT_MAX
);
719 strm
.MultiBitEncode(adjusted_value
, nBytes
*8);
723 if ((unsigned)lowerLimit
== upperLimit
) // 12.2.1
726 // 12.2.2 which devolves to 10.5
727 strm
.UnsignedEncode(value
, lowerLimit
, upperLimit
);
731 ///////////////////////////////////////////////////////////////////////
733 PASN_Enumeration::PASN_Enumeration(unsigned val
)
734 : PASN_Object(UniversalEnumeration
, UniversalTagClass
, FALSE
)
737 maxEnumValue
= P_MAX_INDEX
;
741 PASN_Enumeration::PASN_Enumeration(unsigned tag
, TagClass tagClass
,
742 unsigned maxEnum
, BOOL extend
,
744 : PASN_Object(tag
, tagClass
, extend
)
747 maxEnumValue
= maxEnum
;
751 static POrdinalToString
BuildNamesDict(const PString
& nameSpec
)
753 POrdinalToString names
;
755 PStringArray nameList
= nameSpec
.Tokenise(' ', FALSE
);
758 for (PINDEX i
= 0; i
< nameList
.GetSize(); i
++) {
759 const PString
& thisName
= nameList
[i
];
761 PINDEX equalPos
= thisName
.Find('=');
762 if (equalPos
!= P_MAX_INDEX
)
763 num
= (int)thisName
.Mid(equalPos
+1).AsInteger();
764 names
.SetAt(POrdinalKey(num
), thisName
.Left(equalPos
));
773 PASN_Enumeration::PASN_Enumeration(unsigned tag
, TagClass tagClass
,
774 unsigned maxEnum
, BOOL extend
,
775 const PString
& nameSpec
,
777 : PASN_Object(tag
, tagClass
, extend
),
778 names(BuildNamesDict(nameSpec
))
780 PAssert(maxEnum
> 0, PInvalidParameter
);
781 maxEnumValue
= maxEnum
;
783 PAssert(val
< maxEnum
, PInvalidParameter
);
788 PObject::Comparison
PASN_Enumeration::Compare(const PObject
& obj
) const
790 PAssert(obj
.IsDescendant(PASN_Enumeration::Class()), PInvalidCast
);
791 const PASN_Enumeration
& other
= (const PASN_Enumeration
&)obj
;
793 if (value
< other
.value
)
796 if (value
> other
.value
)
803 PObject
* PASN_Enumeration::Clone() const
805 PAssert(IsClass(PASN_Enumeration::Class()), PInvalidCast
);
806 return new PASN_Enumeration(*this);
810 void PASN_Enumeration::PrintOn(ostream
& strm
) const
812 if (names
.Contains(value
))
813 strm
<< names
[value
];
815 strm
<< '<' << value
<< '>';
819 PString
PASN_Enumeration::GetTypeAsString() const
821 return "Enumeration";
825 PINDEX
PASN_Enumeration::GetDataLength() const
827 return GetIntegerDataLength(value
);
831 BOOL
PASN_Enumeration::Decode(PASN_Stream
& strm
)
833 return strm
.EnumerationDecode(*this);
837 void PASN_Enumeration::Encode(PASN_Stream
& strm
) const
839 strm
.EnumerationEncode(*this);
843 BOOL
PBER_Stream::EnumerationDecode(PASN_Enumeration
& value
)
846 if (!HeaderDecode(value
, len
) || len
== 0 || IsAtEnd())
853 val
= (val
<< 8) | ByteDecode();
861 void PBER_Stream::EnumerationEncode(const PASN_Enumeration
& value
)
864 // output the integer bits
865 for (int count
= GetIntegerDataLength(value
)-1; count
>= 0; count
--)
866 ByteEncode(value
>> (count
*8));
870 BOOL
PPER_Stream::EnumerationDecode(PASN_Enumeration
& value
)
872 return value
.DecodePER(*this);
876 void PPER_Stream::EnumerationEncode(const PASN_Enumeration
& value
)
878 value
.EncodePER(*this);
882 BOOL
PASN_Enumeration::DecodePER(PPER_Stream
& strm
)
886 if (extendable
) { // 13.3
887 if (strm
.SingleBitDecode()) {
889 return strm
.SmallUnsignedDecode(len
) &&
891 strm
.UnsignedDecode(0, len
-1, value
) == 0;
895 return strm
.UnsignedDecode(0, maxEnumValue
, value
) == 0; // 13.2
899 void PASN_Enumeration::EncodePER(PPER_Stream
& strm
) const
903 if (extendable
) { // 13.3
904 BOOL extended
= value
> maxEnumValue
;
905 strm
.SingleBitEncode(extended
);
907 strm
.SmallUnsignedEncode(1+value
);
908 strm
.UnsignedEncode(value
, 0, value
);
913 strm
.UnsignedEncode(value
, 0, maxEnumValue
); // 13.2
917 ///////////////////////////////////////////////////////////////////////
919 PASN_Real::PASN_Real(double val
)
920 : PASN_Object(UniversalReal
, UniversalTagClass
)
926 PASN_Real::PASN_Real(unsigned tag
, TagClass tagClass
, double val
)
927 : PASN_Object(tag
, tagClass
)
933 PObject::Comparison
PASN_Real::Compare(const PObject
& obj
) const
935 PAssert(obj
.IsDescendant(PASN_Real::Class()), PInvalidCast
);
936 const PASN_Real
& other
= (const PASN_Real
&)obj
;
938 if (value
< other
.value
)
941 if (value
> other
.value
)
948 PObject
* PASN_Real::Clone() const
950 PAssert(IsClass(PASN_Real::Class()), PInvalidCast
);
951 return new PASN_Real(*this);
955 void PASN_Real::PrintOn(ostream
& strm
) const
961 PString
PASN_Real::GetTypeAsString() const
967 PINDEX
PASN_Real::GetDataLength() const
969 PAssertAlways(PUnimplementedFunction
);
974 BOOL
PASN_Real::Decode(PASN_Stream
& strm
)
976 return strm
.RealDecode(*this);
980 void PASN_Real::Encode(PASN_Stream
& strm
) const
982 strm
.RealEncode(*this);
986 BOOL
PBER_Stream::RealDecode(PASN_Real
& value
)
989 if (!HeaderDecode(value
, len
) || len
== 0 || IsAtEnd())
992 PAssertAlways(PUnimplementedFunction
);
999 void PBER_Stream::RealEncode(const PASN_Real
&)
1001 PAssertAlways(PUnimplementedFunction
);
1005 BOOL
PPER_Stream::RealDecode(PASN_Real
&)
1013 if (!MultiBitDecode(8, len
))
1016 PAssertAlways(PUnimplementedFunction
);
1017 byteOffset
+= len
+1;
1022 void PPER_Stream::RealEncode(const PASN_Real
&)
1026 MultiBitEncode(0, 8);
1027 PAssertAlways(PUnimplementedFunction
);
1028 MultiBitEncode(0, 8);
1032 ///////////////////////////////////////////////////////////////////////
1034 PASN_ObjectId::PASN_ObjectId(const char * dotstr
)
1035 : PASN_Object(UniversalObjectId
, UniversalTagClass
)
1042 PASN_ObjectId::PASN_ObjectId(unsigned tag
, TagClass tagClass
)
1043 : PASN_Object(tag
, tagClass
)
1048 PASN_ObjectId::PASN_ObjectId(const PASN_ObjectId
& other
)
1049 : PASN_Object(other
),
1050 value(other
.value
, other
.GetSize())
1055 PASN_ObjectId
& PASN_ObjectId::operator=(const PASN_ObjectId
& other
)
1057 PASN_Object::operator=(other
);
1058 value
= PUnsignedArray(other
.value
, other
.GetSize());
1063 PASN_ObjectId
& PASN_ObjectId::operator=(const char * dotstr
)
1073 PASN_ObjectId
& PASN_ObjectId::operator=(const PString
& dotstr
)
1080 void PASN_ObjectId::SetValue(const PString
& dotstr
)
1082 PStringArray parts
= dotstr
.Tokenise('.');
1083 value
.SetSize(parts
.GetSize());
1084 for (PINDEX i
= 0; i
< parts
.GetSize(); i
++)
1085 value
[i
] = parts
[i
].AsUnsigned();
1089 BOOL
PASN_ObjectId::operator==(const char * dotstr
) const
1092 id
.SetValue(dotstr
);
1097 PObject::Comparison
PASN_ObjectId::Compare(const PObject
& obj
) const
1099 PAssert(obj
.IsDescendant(PASN_ObjectId::Class()), PInvalidCast
);
1100 const PASN_ObjectId
& other
= (const PASN_ObjectId
&)obj
;
1101 return value
.Compare(other
.value
);
1105 PObject
* PASN_ObjectId::Clone() const
1107 PAssert(IsClass(PASN_ObjectId::Class()), PInvalidCast
);
1108 return new PASN_ObjectId(*this);
1112 void PASN_ObjectId::PrintOn(ostream
& strm
) const
1114 for (PINDEX i
= 0; i
< value
.GetSize(); i
++) {
1115 strm
<< (unsigned)value
[i
];
1116 if (i
< value
.GetSize()-1)
1122 PString
PASN_ObjectId::GetTypeAsString() const
1128 BOOL
PASN_ObjectId::CommonDecode(PASN_Stream
& strm
, unsigned dataLen
)
1132 // handle zero length strings correctly
1138 // start at the second identifier in the buffer, because we will later
1139 // expand the first number into the first two IDs
1141 while (dataLen
> 0) {
1144 do { /* shift and add in low order 7 bits */
1147 byte
= strm
.ByteDecode();
1148 subId
= (subId
<< 7) + (byte
& 0x7f);
1150 } while ((byte
& 0x80) != 0);
1151 value
.SetAt(i
++, subId
);
1155 * The first two subidentifiers are encoded into the first component
1156 * with the value (X * 40) + Y, where:
1157 * X is the value of the first subidentifier.
1158 * Y is the value of the second subidentifier.
1165 else if (subId
< 80) {
1167 value
[1] = subId
-40;
1171 value
[1] = subId
-80;
1178 void PASN_ObjectId::CommonEncode(PBYTEArray
& encodecObjectId
) const
1180 PINDEX length
= value
.GetSize();
1181 const unsigned * objId
= value
;
1184 // Thise case is really illegal, but we have to do SOMETHING
1185 encodecObjectId
.SetSize(0);
1189 unsigned subId
= (objId
[0] * 40) + objId
[1];
1192 PINDEX outputPosition
= 0;
1194 while (--length
> 0) {
1196 encodecObjectId
[outputPosition
++] = (BYTE
)subId
;
1198 unsigned mask
= 0x7F; /* handle subid == 0 case */
1201 /* testmask *MUST* !!!! be of an unsigned type */
1202 unsigned testmask
= 0x7F;
1204 while (testmask
!= 0) {
1205 if (subId
& testmask
) { /* if any bits set */
1213 /* mask can't be zero here */
1214 while (mask
!= 0x7F) {
1215 /* fix a mask that got truncated above */
1216 if (mask
== 0x1E00000)
1219 encodecObjectId
[outputPosition
++] = (BYTE
)(((subId
& mask
) >> bits
) | 0x80);
1225 encodecObjectId
[outputPosition
++] = (BYTE
)(subId
& mask
);
1234 PINDEX
PASN_ObjectId::GetDataLength() const
1237 CommonEncode(dummy
);
1238 return dummy
.GetSize();
1242 BOOL
PASN_ObjectId::Decode(PASN_Stream
& strm
)
1244 return strm
.ObjectIdDecode(*this);
1248 void PASN_ObjectId::Encode(PASN_Stream
& strm
) const
1250 strm
.ObjectIdEncode(*this);
1254 BOOL
PBER_Stream::ObjectIdDecode(PASN_ObjectId
& value
)
1257 if (!HeaderDecode(value
, len
))
1260 return value
.CommonDecode(*this, len
);
1264 void PBER_Stream::ObjectIdEncode(const PASN_ObjectId
& value
)
1266 HeaderEncode(value
);
1268 value
.CommonEncode(data
);
1269 BlockEncode(data
, data
.GetSize());
1273 BOOL
PPER_Stream::ObjectIdDecode(PASN_ObjectId
& value
)
1278 if (LengthDecode(0, 255, dataLen
) < 0)
1282 return value
.CommonDecode(*this, dataLen
);
1286 void PPER_Stream::ObjectIdEncode(const PASN_ObjectId
& value
)
1291 value
.CommonEncode(eObjId
);
1292 LengthEncode(eObjId
.GetSize(), 0, 255);
1293 BlockEncode(eObjId
, eObjId
.GetSize());
1297 ///////////////////////////////////////////////////////////////////////
1299 PASN_BitString::PASN_BitString(unsigned nBits
, const BYTE
* buf
)
1300 : PASN_ConstrainedObject(UniversalBitString
, UniversalTagClass
),
1302 bitData((totalBits
+7)/8)
1305 memcpy(bitData
.GetPointer(), buf
, bitData
.GetSize());
1309 PASN_BitString::PASN_BitString(unsigned tag
, TagClass tagClass
, unsigned nBits
)
1310 : PASN_ConstrainedObject(tag
, tagClass
),
1312 bitData((totalBits
+7)/8)
1317 PASN_BitString::PASN_BitString(const PASN_BitString
& other
)
1318 : PASN_ConstrainedObject(other
),
1319 bitData(other
.bitData
, other
.bitData
.GetSize())
1321 totalBits
= other
.totalBits
;
1325 PASN_BitString
& PASN_BitString::operator=(const PASN_BitString
& other
)
1327 PASN_ConstrainedObject::operator=(other
);
1328 totalBits
= other
.totalBits
;
1329 bitData
= PBYTEArray(other
.bitData
, other
.bitData
.GetSize());
1334 void PASN_BitString::SetData(unsigned nBits
, const PBYTEArray
& bytes
)
1341 void PASN_BitString::SetData(unsigned nBits
, const BYTE
* buf
, PINDEX size
)
1345 memcpy(bitData
.GetPointer(size
), buf
, size
);
1350 BOOL
PASN_BitString::SetSize(unsigned nBits
)
1352 if (constraint
== Unconstrained
)
1354 else if (totalBits
< (unsigned)lowerLimit
)
1355 totalBits
= lowerLimit
;
1356 else if ((unsigned)totalBits
> upperLimit
)
1357 totalBits
= upperLimit
;
1360 return bitData
.SetSize((nBits
+7)/8);
1364 BOOL
PASN_BitString::operator[](PINDEX bit
) const
1366 if ((unsigned)bit
< totalBits
)
1367 return (bitData
[bit
>>3] & (1 << (7 - (bit
&7)))) != 0;
1372 void PASN_BitString::Set(unsigned bit
)
1374 if (bit
< totalBits
)
1375 bitData
[(PINDEX
)(bit
>>3)] |= 1 << (7 - (bit
&7));
1379 void PASN_BitString::Clear(unsigned bit
)
1381 if (bit
< totalBits
)
1382 bitData
[(PINDEX
)(bit
>>3)] &= ~(1 << (7 - (bit
&7)));
1386 void PASN_BitString::Invert(unsigned bit
)
1388 if (bit
< totalBits
)
1389 bitData
[(PINDEX
)(bit
>>3)] ^= 1 << (7 - (bit
&7));
1393 PObject::Comparison
PASN_BitString::Compare(const PObject
& obj
) const
1395 PAssert(obj
.IsDescendant(PASN_BitString::Class()), PInvalidCast
);
1396 const PASN_BitString
& other
= (const PASN_BitString
&)obj
;
1397 if (totalBits
< other
.totalBits
)
1399 if (totalBits
> other
.totalBits
)
1401 return bitData
.Compare(other
.bitData
);
1405 PObject
* PASN_BitString::Clone() const
1407 PAssert(IsClass(PASN_BitString::Class()), PInvalidCast
);
1408 return new PASN_BitString(*this);
1412 void PASN_BitString::PrintOn(ostream
& strm
) const
1416 for (unsigned i
= 0; i
< totalBits
; i
++) {
1417 strm
<< ((bitData
[offset
]&mask
) != 0 ? '1' : '0');
1427 void PASN_BitString::SetConstraintBounds(ConstraintType type
, int lower
, unsigned upper
)
1429 PAssert(lower
>= 0, PInvalidParameter
);
1430 PASN_ConstrainedObject::SetConstraintBounds(type
, lower
, upper
);
1435 PString
PASN_BitString::GetTypeAsString() const
1437 return "Bit String";
1441 PINDEX
PASN_BitString::GetDataLength() const
1443 return (totalBits
+7)/8 + 1;
1447 BOOL
PASN_BitString::Decode(PASN_Stream
& strm
)
1449 return strm
.BitStringDecode(*this);
1453 void PASN_BitString::Encode(PASN_Stream
& strm
) const
1455 strm
.BitStringEncode(*this);
1459 BOOL
PASN_BitString::DecodeBER(PBER_Stream
& strm
, unsigned len
)
1461 totalBits
= len
*8 - strm
.ByteDecode();
1462 unsigned nBytes
= (totalBits
+7)/8;
1463 return strm
.BlockDecode(bitData
.GetPointer(nBytes
), nBytes
) == nBytes
;
1467 void PASN_BitString::EncodeBER(PBER_Stream
& strm
) const
1472 strm
.ByteEncode(8-totalBits
%8);
1473 strm
.BlockEncode(bitData
, (totalBits
+7)/8);
1478 BOOL
PASN_BitString::DecodePER(PPER_Stream
& strm
)
1482 if (ConstrainedLengthDecode(strm
, totalBits
) < 0)
1488 return TRUE
; // 15.7
1490 if (totalBits
> strm
.GetBitsLeft())
1493 if (totalBits
> 16) {
1494 unsigned nBytes
= (totalBits
+7)/8;
1495 return strm
.BlockDecode(bitData
.GetPointer(), nBytes
) == nBytes
; // 15.9
1499 if (totalBits
<= 8) {
1500 if (!strm
.MultiBitDecode(totalBits
, theBits
))
1503 bitData
[0] = (BYTE
)(theBits
<< (8-totalBits
));
1506 if (!strm
.MultiBitDecode(8, theBits
))
1509 bitData
[0] = (BYTE
)theBits
;
1511 if (!strm
.MultiBitDecode(totalBits
-8, theBits
))
1514 bitData
[1] = (BYTE
)(theBits
<< (16-totalBits
));
1521 void PASN_BitString::EncodePER(PPER_Stream
& strm
) const
1525 ConstrainedLengthEncode(strm
, totalBits
);
1531 strm
.BlockEncode(bitData
, (totalBits
+7)/8); // 15.9
1532 else if (totalBits
<= 8) // 15.8
1533 strm
.MultiBitEncode(bitData
[0] >> (8 - totalBits
), totalBits
);
1535 strm
.MultiBitEncode(bitData
[0], 8);
1536 strm
.MultiBitEncode(bitData
[1] >> (16 - totalBits
), totalBits
-8);
1541 BOOL
PASN_BitString::DecodeSequenceExtensionBitmap(PPER_Stream
& strm
)
1543 if (!strm
.SmallUnsignedDecode(totalBits
))
1550 if (totalBits
> strm
.GetBitsLeft())
1556 unsigned bitsLeft
= totalBits
;
1557 while (bitsLeft
>= 8) {
1558 if (!strm
.MultiBitDecode(8, theBits
))
1560 bitData
[idx
++] = (BYTE
)theBits
;
1565 if (!strm
.MultiBitDecode(bitsLeft
, theBits
))
1567 bitData
[idx
] = (BYTE
)(theBits
<< (8-bitsLeft
));
1574 void PASN_BitString::EncodeSequenceExtensionBitmap(PPER_Stream
& strm
) const
1576 PAssert(totalBits
> 0, PLogicError
);
1578 strm
.SmallUnsignedEncode(totalBits
-1);
1581 unsigned bitsLeft
= totalBits
;
1582 while (bitsLeft
>= 8) {
1583 strm
.MultiBitEncode(bitData
[idx
++], 8);
1588 strm
.MultiBitEncode(bitData
[idx
] >> (8 - bitsLeft
), bitsLeft
);
1592 BOOL
PBER_Stream::BitStringDecode(PASN_BitString
& value
)
1595 if (!HeaderDecode(value
, len
) || len
== 0 || IsAtEnd())
1598 return value
.DecodeBER(*this, len
);
1602 void PBER_Stream::BitStringEncode(const PASN_BitString
& value
)
1604 HeaderEncode(value
);
1605 value
.EncodeBER(*this);
1609 BOOL
PPER_Stream::BitStringDecode(PASN_BitString
& value
)
1611 return value
.DecodePER(*this);
1615 void PPER_Stream::BitStringEncode(const PASN_BitString
& value
)
1617 value
.EncodePER(*this);
1621 ///////////////////////////////////////////////////////////////////////
1623 PASN_OctetString::PASN_OctetString(const char * str
, PINDEX size
)
1624 : PASN_ConstrainedObject(UniversalOctetString
, UniversalTagClass
)
1628 size
= ::strlen(str
);
1629 SetValue((const BYTE
*)str
, size
);
1634 PASN_OctetString::PASN_OctetString(unsigned tag
, TagClass tagClass
)
1635 : PASN_ConstrainedObject(tag
, tagClass
)
1640 PASN_OctetString::PASN_OctetString(const PASN_OctetString
& other
)
1641 : PASN_ConstrainedObject(other
),
1642 value(other
.value
, other
.GetSize())
1647 PASN_OctetString
& PASN_OctetString::operator=(const PASN_OctetString
& other
)
1649 PASN_ConstrainedObject::operator=(other
);
1650 value
= PBYTEArray(other
.value
, other
.GetSize());
1655 PASN_OctetString
& PASN_OctetString::operator=(const char * str
)
1658 value
.SetSize(lowerLimit
);
1660 SetValue((const BYTE
*)str
, strlen(str
));
1665 PASN_OctetString
& PASN_OctetString::operator=(const PString
& str
)
1667 SetValue((const BYTE
*)(const char *)str
, str
.GetSize()-1);
1672 PASN_OctetString
& PASN_OctetString::operator=(const PBYTEArray
& arr
)
1674 PINDEX len
= arr
.GetSize();
1675 if ((unsigned)len
> upperLimit
|| (int)len
< lowerLimit
)
1683 void PASN_OctetString::SetValue(const BYTE
* data
, PINDEX len
)
1685 if ((unsigned)len
> upperLimit
)
1687 value
.SetSize((int)len
< lowerLimit
? lowerLimit
: len
);
1688 memcpy(value
.GetPointer(), data
, len
);
1692 PString
PASN_OctetString::AsString() const
1694 if (value
.IsEmpty())
1696 return PString((const char *)(const BYTE
*)value
, value
.GetSize());
1700 PObject::Comparison
PASN_OctetString::Compare(const PObject
& obj
) const
1702 PAssert(obj
.IsDescendant(PASN_OctetString::Class()), PInvalidCast
);
1703 const PASN_OctetString
& other
= (const PASN_OctetString
&)obj
;
1704 return value
.Compare(other
.value
);
1708 PObject
* PASN_OctetString::Clone() const
1710 PAssert(IsClass(PASN_OctetString::Class()), PInvalidCast
);
1711 return new PASN_OctetString(*this);
1715 void PASN_OctetString::PrintOn(ostream
& strm
) const
1717 int indent
= strm
.precision() + 2;
1718 strm
<< ' ' << value
.GetSize() << " octets {\n";
1720 while (i
< value
.GetSize()) {
1721 strm
<< setw(indent
) << " " << hex
<< setfill('0');
1723 for (j
= 0; j
< 16; j
++) {
1724 if (i
+j
< value
.GetSize())
1725 strm
<< setw(2) << (unsigned)value
[i
+j
] << ' ';
1730 for (j
= 0; j
< 16; j
++) {
1731 if (i
+j
< value
.GetSize()) {
1732 if (isprint(value
[i
+j
]))
1738 strm
<< dec
<< setfill(' ') << '\n';
1741 strm
<< setw(indent
-1) << "}";
1745 void PASN_OctetString::SetConstraintBounds(ConstraintType type
, int lower
, unsigned upper
)
1747 PAssert(lower
>= 0, PInvalidParameter
);
1748 PASN_ConstrainedObject::SetConstraintBounds(type
, lower
, upper
);
1749 if (constraint
!= Unconstrained
) {
1750 if (value
.GetSize() < (PINDEX
)lowerLimit
)
1751 value
.SetSize(lowerLimit
);
1752 else if ((unsigned)value
.GetSize() > upperLimit
)
1753 value
.SetSize(upperLimit
);
1758 PString
PASN_OctetString::GetTypeAsString() const
1760 return "Octet String";
1764 PINDEX
PASN_OctetString::GetDataLength() const
1766 return value
.GetSize();
1770 BOOL
PASN_OctetString::Decode(PASN_Stream
& strm
)
1772 return strm
.OctetStringDecode(*this);
1776 void PASN_OctetString::Encode(PASN_Stream
& strm
) const
1778 strm
.OctetStringEncode(*this);
1782 BOOL
PASN_OctetString::DecodePER(PPER_Stream
& strm
)
1787 if (ConstrainedLengthDecode(strm
, nBytes
) < 0)
1790 value
.SetSize(nBytes
); // 16.5
1798 if (!strm
.MultiBitDecode(8, theBits
))
1800 value
[0] = (BYTE
)theBits
;
1804 if (!strm
.MultiBitDecode(8, theBits
))
1806 value
[0] = (BYTE
)theBits
;
1807 if (!strm
.MultiBitDecode(8, theBits
))
1809 value
[1] = (BYTE
)theBits
;
1813 return strm
.BlockDecode(value
.GetPointer(), nBytes
) == nBytes
;
1820 void PASN_OctetString::EncodePER(PPER_Stream
& strm
) const
1824 PINDEX nBytes
= value
.GetSize();
1825 ConstrainedLengthEncode(strm
, nBytes
);
1832 strm
.MultiBitEncode(value
[0], 8);
1836 strm
.MultiBitEncode(value
[0], 8);
1837 strm
.MultiBitEncode(value
[1], 8);
1841 strm
.BlockEncode(value
, nBytes
);
1846 BOOL
PBER_Stream::OctetStringDecode(PASN_OctetString
& value
)
1849 if (!HeaderDecode(value
, len
))
1852 return BlockDecode(value
.GetPointer(len
), len
) == len
;
1856 void PBER_Stream::OctetStringEncode(const PASN_OctetString
& value
)
1858 HeaderEncode(value
);
1859 BlockEncode(value
, value
.GetSize());
1863 BOOL
PPER_Stream::OctetStringDecode(PASN_OctetString
& value
)
1865 return value
.DecodePER(*this);
1869 void PPER_Stream::OctetStringEncode(const PASN_OctetString
& value
)
1871 value
.EncodePER(*this);
1875 BOOL
PASN_OctetString::DecodeSubType(PASN_Object
& obj
)
1877 PPER_Stream stream
= GetValue();
1878 return obj
.Decode(stream
);
1882 void PASN_OctetString::EncodeSubType(const PASN_Object
& obj
)
1886 stream
.CompleteEncoding();
1891 ///////////////////////////////////////////////////////////////////////
1893 PASN_ConstrainedString::PASN_ConstrainedString(const char * canonical
, PINDEX size
,
1894 unsigned tag
, TagClass tagClass
)
1895 : PASN_ConstrainedObject(tag
, tagClass
)
1897 canonicalSet
= canonical
;
1898 canonicalSetSize
= size
;
1899 canonicalSetBits
= CountBits(size
);
1900 SetCharacterSet(canonicalSet
, canonicalSetSize
, Unconstrained
);
1904 PASN_ConstrainedString
& PASN_ConstrainedString::operator=(const char * str
)
1909 PStringStream newValue
;
1911 PINDEX len
= strlen(str
);
1913 // Can't copy any more characters than the upper constraint
1914 if ((unsigned)len
> upperLimit
)
1917 // Now copy individual characters, if they are in character set constraint
1918 for (PINDEX i
= 0; i
< len
; i
++) {
1919 PINDEX sz
= characterSet
.GetSize();
1920 if (sz
== 0 || memchr(characterSet
, str
[i
], sz
) != NULL
)
1924 // Make sure string meets minimum length constraint
1925 while ((int)len
< lowerLimit
) {
1926 newValue
<< characterSet
[0];
1931 value
.MakeMinimumSize();
1936 void PASN_ConstrainedString::SetCharacterSet(ConstraintType ctype
, const char * set
)
1938 SetCharacterSet(set
, strlen(set
), ctype
);
1942 void PASN_ConstrainedString::SetCharacterSet(ConstraintType ctype
, unsigned firstChar
, unsigned lastChar
)
1945 for (unsigned i
= firstChar
; i
< lastChar
; i
++)
1946 buffer
[i
] = (char)i
;
1947 SetCharacterSet(buffer
, lastChar
- firstChar
+ 1, ctype
);
1951 void PASN_ConstrainedString::SetCharacterSet(const char * set
, PINDEX setSize
, ConstraintType ctype
)
1953 if (ctype
== Unconstrained
) {
1954 characterSet
.SetSize(canonicalSetSize
);
1955 memcpy(characterSet
.GetPointer(), canonicalSet
, canonicalSetSize
);
1958 characterSet
.SetSize(setSize
);
1960 for (PINDEX i
= 0; i
< canonicalSetSize
; i
++) {
1961 if (memchr(set
, canonicalSet
[i
], setSize
) != NULL
)
1962 characterSet
[count
++] = canonicalSet
[i
];
1964 PAssert(count
> 0, PInvalidParameter
);
1965 characterSet
.SetSize(count
);
1968 charSetUnalignedBits
= CountBits(characterSet
.GetSize());
1970 charSetAlignedBits
= 1;
1971 while (charSetUnalignedBits
> charSetAlignedBits
)
1972 charSetAlignedBits
<<= 1;
1974 operator=((const char *)value
);
1978 PObject::Comparison
PASN_ConstrainedString::Compare(const PObject
& obj
) const
1980 PAssert(obj
.IsDescendant(PASN_ConstrainedString::Class()), PInvalidCast
);
1981 const PASN_ConstrainedString
& other
= (const PASN_ConstrainedString
&)obj
;
1982 return value
.Compare(other
.value
);
1986 void PASN_ConstrainedString::PrintOn(ostream
& strm
) const
1988 strm
<< value
.ToLiteral();
1992 void PASN_ConstrainedString::SetConstraintBounds(ConstraintType type
,
1993 int lower
, unsigned upper
)
1995 PAssert(lower
>= 0, PInvalidParameter
);
1996 PASN_ConstrainedObject::SetConstraintBounds(type
, lower
, upper
);
1997 if (constraint
!= Unconstrained
) {
1998 if (value
.GetSize() < (PINDEX
)lowerLimit
)
1999 value
.SetSize(lowerLimit
);
2000 else if ((unsigned)value
.GetSize() > upperLimit
)
2001 value
.SetSize(upperLimit
);
2006 PINDEX
PASN_ConstrainedString::GetDataLength() const
2008 return value
.GetSize()-1;
2012 BOOL
PASN_ConstrainedString::Decode(PASN_Stream
& strm
)
2014 return strm
.ConstrainedStringDecode(*this);
2018 void PASN_ConstrainedString::Encode(PASN_Stream
& strm
) const
2020 strm
.ConstrainedStringEncode(*this);
2024 BOOL
PASN_ConstrainedString::DecodeBER(PBER_Stream
& strm
, unsigned len
)
2026 return strm
.BlockDecode((BYTE
*)value
.GetPointer(len
+1), len
) == len
;
2030 void PASN_ConstrainedString::EncodeBER(PBER_Stream
& strm
) const
2032 strm
.BlockEncode(value
, value
.GetSize()-1);
2036 BOOL
PASN_ConstrainedString::DecodePER(PPER_Stream
& strm
)
2041 if (ConstrainedLengthDecode(strm
, len
) < 0)
2044 unsigned nBits
= strm
.IsAligned() ? charSetAlignedBits
: charSetUnalignedBits
;
2045 unsigned totalBits
= upperLimit
*nBits
;
2047 if (constraint
== Unconstrained
||
2048 (lowerLimit
== (int)upperLimit
? (totalBits
> 16) : (totalBits
>= 16))) {
2050 return strm
.BlockDecode((BYTE
*)value
.GetPointer(len
+1), len
) == len
;
2051 if (strm
.IsAligned())
2055 value
.SetSize(len
+1);
2058 for (i
= 0; i
< (PINDEX
)len
; i
++) {
2060 if (!strm
.MultiBitDecode(nBits
, theBits
))
2062 if (nBits
>= canonicalSetBits
&& canonicalSetBits
> 4)
2063 value
[i
] = (char)theBits
;
2065 value
[i
] = characterSet
[(PINDEX
)theBits
];
2073 void PASN_ConstrainedString::EncodePER(PPER_Stream
& strm
) const
2077 PINDEX len
= value
.GetSize()-1;
2078 ConstrainedLengthEncode(strm
, len
);
2080 unsigned nBits
= strm
.IsAligned() ? charSetAlignedBits
: charSetUnalignedBits
;
2081 unsigned totalBits
= upperLimit
*nBits
;
2083 if (constraint
== Unconstrained
||
2084 (lowerLimit
== (int)upperLimit
? (totalBits
> 16) : (totalBits
>= 16))) {
2086 strm
.BlockEncode((const BYTE
*)(const char *)value
, len
);
2089 if (strm
.IsAligned())
2093 for (PINDEX i
= 0; i
< len
; i
++) {
2094 if (nBits
>= canonicalSetBits
&& canonicalSetBits
> 4)
2095 strm
.MultiBitEncode(value
[i
], nBits
);
2097 const void * ptr
= memchr(characterSet
, value
[i
], characterSet
.GetSize());
2100 pos
= ((const char *)ptr
- (const char *)characterSet
);
2101 strm
.MultiBitEncode(pos
, nBits
);
2107 BOOL
PBER_Stream::ConstrainedStringDecode(PASN_ConstrainedString
& value
)
2110 if (!HeaderDecode(value
, len
))
2113 return value
.DecodeBER(*this, len
);
2117 void PBER_Stream::ConstrainedStringEncode(const PASN_ConstrainedString
& value
)
2119 HeaderEncode(value
);
2120 value
.Encode(*this);
2124 BOOL
PPER_Stream::ConstrainedStringDecode(PASN_ConstrainedString
& value
)
2126 return value
.DecodePER(*this);
2130 void PPER_Stream::ConstrainedStringEncode(const PASN_ConstrainedString
& value
)
2132 value
.EncodePER(*this);
2136 #define DEFINE_STRING_CLASS(name, set) \
2137 static const char name##StringSet[] = set; \
2138 PASN_##name##String::PASN_##name##String(const char * str) \
2139 : PASN_ConstrainedString(name##StringSet, sizeof(name##StringSet)-1, \
2140 Universal##name##String, UniversalTagClass) \
2141 { PASN_ConstrainedString::SetValue(str); } \
2142 PASN_##name##String::PASN_##name##String(unsigned tag, TagClass tagClass) \
2143 : PASN_ConstrainedString(name##StringSet, sizeof(name##StringSet)-1, tag, tagClass) \
2145 PASN_##name##String & PASN_##name##String::operator=(const char * str) \
2146 { PASN_ConstrainedString::SetValue(str); return *this; } \
2147 PASN_##name##String & PASN_##name##String::operator=(const PString & str) \
2148 { PASN_ConstrainedString::SetValue(str); return *this; } \
2149 PObject * PASN_##name##String::Clone() const \
2150 { PAssert(IsClass(PASN_##name##String::Class()), PInvalidCast); \
2151 return new PASN_##name##String(*this); } \
2152 PString PASN_##name##String::GetTypeAsString() const \
2153 { return #name " String"; }
2155 DEFINE_STRING_CLASS(Numeric
, " 0123456789")
2156 DEFINE_STRING_CLASS(Printable
, " '()+,-./0123456789:=?"
2157 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
2158 "abcdefghijklmnopqrstuvwxyz")
2159 DEFINE_STRING_CLASS(Visible
, " !\"#$%&'()*+,-./0123456789:;<=>?"
2160 "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
2161 "`abcdefghijklmnopqrstuvwxyz{|}~")
2162 DEFINE_STRING_CLASS(IA5
, "\000\001\002\003\004\005\006\007"
2163 "\010\011\012\013\014\015\016\017"
2164 "\020\021\022\023\024\025\026\027"
2165 "\030\031\032\033\034\035\036\037"
2166 " !\"#$%&'()*+,-./0123456789:;<=>?"
2167 "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
2168 "`abcdefghijklmnopqrstuvwxyz{|}~\177")
2169 DEFINE_STRING_CLASS(General
, "\000\001\002\003\004\005\006\007"
2170 "\010\011\012\013\014\015\016\017"
2171 "\020\021\022\023\024\025\026\027"
2172 "\030\031\032\033\034\035\036\037"
2173 " !\"#$%&'()*+,-./0123456789:;<=>?"
2174 "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
2175 "`abcdefghijklmnopqrstuvwxyz{|}~\177"
2176 "\200\201\202\203\204\205\206\207"
2177 "\210\211\212\213\214\215\216\217"
2178 "\220\221\222\223\224\225\226\227"
2179 "\230\231\232\233\234\235\236\237"
2180 "\240\241\242\243\244\245\246\247"
2181 "\250\251\252\253\254\255\256\257"
2182 "\260\261\262\263\264\265\266\267"
2183 "\270\271\272\273\274\275\276\277"
2184 "\300\301\302\303\304\305\306\307"
2185 "\310\311\312\313\314\315\316\317"
2186 "\320\321\322\323\324\325\326\327"
2187 "\330\331\332\333\334\335\336\337"
2188 "\340\341\342\343\344\345\346\347"
2189 "\350\351\352\353\354\355\356\357"
2190 "\360\361\362\363\364\365\366\367"
2191 "\370\371\372\373\374\375\376\377")
2194 ///////////////////////////////////////////////////////////////////////
2196 PASN_BMPString::PASN_BMPString(const char * str
)
2197 : PASN_ConstrainedObject(UniversalBMPString
, UniversalTagClass
)
2205 PASN_BMPString::PASN_BMPString(const PWORDArray
& wstr
)
2206 : PASN_ConstrainedObject(UniversalBMPString
, UniversalTagClass
)
2213 PASN_BMPString::PASN_BMPString(unsigned tag
, TagClass tagClass
)
2214 : PASN_ConstrainedObject(tag
, tagClass
)
2220 void PASN_BMPString::Construct()
2224 charSetAlignedBits
= 16;
2225 charSetUnalignedBits
= 16;
2229 PASN_BMPString::PASN_BMPString(const PASN_BMPString
& other
)
2230 : PASN_ConstrainedObject(other
),
2231 value(other
.value
, other
.value
.GetSize()),
2232 characterSet(other
.characterSet
)
2234 firstChar
= other
.firstChar
;
2235 lastChar
= other
.lastChar
;
2236 charSetAlignedBits
= other
.charSetAlignedBits
;
2237 charSetUnalignedBits
= other
.charSetUnalignedBits
;
2241 PASN_BMPString
& PASN_BMPString::operator=(const PASN_BMPString
& other
)
2243 PASN_ConstrainedObject::operator=(other
);
2245 value
= PWORDArray(other
.value
, other
.value
.GetSize());
2246 characterSet
= other
.characterSet
;
2247 firstChar
= other
.firstChar
;
2248 lastChar
= other
.lastChar
;
2249 charSetAlignedBits
= other
.charSetAlignedBits
;
2250 charSetUnalignedBits
= other
.charSetUnalignedBits
;
2256 BOOL
PASN_BMPString::IsLegalCharacter(WORD ch
)
2264 if (characterSet
.IsEmpty())
2267 const WORD
* wptr
= characterSet
;
2268 PINDEX count
= characterSet
.GetSize();
2269 while (count
-- > 0) {
2279 PASN_BMPString
& PASN_BMPString::operator=(const char * str
)
2281 // Must be at least this big for string conversion
2282 value
.SetSize(::strlen(str
));
2284 // Convert string looking for "Ӓ" style characters for 16 bit stuff
2286 while (*str
!= '\0') {
2287 WORD c
= (BYTE
)*str
++;
2289 if (c
== '&' && *str
== '#') {
2290 unsigned bigChar
= 0;
2291 const char * p
= str
+1;
2293 bigChar
= bigChar
*10 + *p
++ - '0';
2294 if (*p
== ';' && bigChar
< 65536) {
2300 if (IsLegalCharacter(c
))
2304 // Can't have any more than the upper constraint
2305 if ((unsigned)count
> upperLimit
)
2308 // Number of bytes must be at least lhe lower constraint
2309 PINDEX newSize
= (int)count
< lowerLimit
? lowerLimit
: count
;
2310 value
.SetSize(newSize
);
2312 // Pad out with the first character till required size
2313 while (count
< newSize
)
2314 value
[count
++] = firstChar
;
2320 PASN_BMPString
& PASN_BMPString::operator=(const PWORDArray
& array
)
2322 PINDEX paramSize
= array
.GetSize();
2324 // Can't copy any more than the upper constraint
2325 if ((unsigned)paramSize
> upperLimit
)
2326 paramSize
= upperLimit
;
2328 // Number of bytes must be at least lhe lower constraint
2329 PINDEX newSize
= (int)paramSize
< lowerLimit
? lowerLimit
: paramSize
;
2330 value
.SetSize(newSize
);
2333 for (PINDEX i
= 0; i
< paramSize
; i
++) {
2335 if (IsLegalCharacter(c
))
2339 // Pad out with the first character till required size
2340 while (count
< newSize
)
2341 value
[count
++] = firstChar
;
2347 PString
PASN_BMPString::GetValue() const
2350 for (PINDEX i
= 0; i
< value
.GetSize(); i
++) {
2352 str
+= (char)value
[i
];
2354 str
.sprintf("&#%u;", value
[i
]);
2360 void PASN_BMPString::SetCharacterSet(ConstraintType ctype
, const char * charSet
)
2362 PWORDArray
array(strlen(charSet
));
2365 while (*charSet
!= '\0')
2366 array
[count
++] = (BYTE
)*charSet
++;
2368 SetCharacterSet(ctype
, array
);
2372 void PASN_BMPString::SetCharacterSet(ConstraintType ctype
, const PWORDArray
& charSet
)
2374 if (ctype
== Unconstrained
) {
2377 characterSet
.SetSize(0);
2380 characterSet
= charSet
;
2382 charSetUnalignedBits
= CountBits(lastChar
- firstChar
+ 1);
2383 if (!charSet
.IsEmpty()) {
2385 for (PINDEX i
= 0; i
< charSet
.GetSize(); i
++) {
2386 if (characterSet
[i
] >= firstChar
&& characterSet
[i
] <= lastChar
)
2389 count
= CountBits(count
);
2390 if (charSetUnalignedBits
> count
)
2391 charSetUnalignedBits
= count
;
2394 charSetAlignedBits
= 1;
2395 while (charSetUnalignedBits
> charSetAlignedBits
)
2396 charSetAlignedBits
<<= 1;
2403 void PASN_BMPString::SetCharacterSet(ConstraintType ctype
, unsigned first
, unsigned last
)
2405 if (ctype
!= Unconstrained
) {
2406 PAssert(first
< 0x10000 && last
< 0x10000 && last
> first
, PInvalidParameter
);
2407 firstChar
= (WORD
)first
;
2408 lastChar
= (WORD
)last
;
2410 SetCharacterSet(ctype
, characterSet
);
2414 PObject
* PASN_BMPString::Clone() const
2416 PAssert(IsClass(PASN_BMPString::Class()), PInvalidCast
);
2417 return new PASN_BMPString(*this);
2421 PObject::Comparison
PASN_BMPString::Compare(const PObject
& obj
) const
2423 PAssert(obj
.IsDescendant(PASN_BMPString::Class()), PInvalidCast
);
2424 const PASN_BMPString
& other
= (const PASN_BMPString
&)obj
;
2425 return value
.Compare(other
.value
);
2429 void PASN_BMPString::PrintOn(ostream
& strm
) const
2431 int indent
= strm
.precision() + 2;
2432 PINDEX sz
= value
.GetSize();
2433 strm
<< ' ' << sz
<< " characters {\n";
2436 strm
<< setw(indent
) << " " << hex
<< setfill('0');
2438 for (j
= 0; j
< 8; j
++)
2440 strm
<< setw(4) << value
[i
+j
] << ' ';
2444 for (j
= 0; j
< 8; j
++) {
2446 WORD c
= value
[i
+j
];
2447 if (c
< 128 && isprint(c
))
2453 strm
<< dec
<< setfill(' ') << '\n';
2456 strm
<< setw(indent
-1) << "}";
2460 PString
PASN_BMPString::GetTypeAsString() const
2462 return "BMP String";
2466 PINDEX
PASN_BMPString::GetDataLength() const
2468 return value
.GetSize()*2;
2472 BOOL
PASN_BMPString::Decode(PASN_Stream
& strm
)
2474 return strm
.BMPStringDecode(*this);
2478 void PASN_BMPString::Encode(PASN_Stream
& strm
) const
2480 strm
.BMPStringEncode(*this);
2484 BOOL
PASN_BMPString::DecodeBER(PBER_Stream
& strm
, unsigned len
)
2486 value
.SetSize(len
/2);
2487 return strm
.BlockDecode((BYTE
*)value
.GetPointer(len
), len
) == len
;
2491 void PASN_BMPString::EncodeBER(PBER_Stream
& strm
) const
2493 strm
.BlockEncode((const BYTE
*)(const WORD
*)value
, value
.GetSize()*2);
2497 BOOL
PASN_BMPString::DecodePER(PPER_Stream
& strm
)
2502 if (ConstrainedLengthDecode(strm
, len
) < 0)
2507 PINDEX nBits
= strm
.IsAligned() ? charSetAlignedBits
: charSetUnalignedBits
;
2509 if ((constraint
== Unconstrained
|| upperLimit
*nBits
> 16) && strm
.IsAligned())
2512 for (PINDEX i
= 0; i
< (PINDEX
)len
; i
++) {
2514 if (!strm
.MultiBitDecode(nBits
, theBits
))
2516 if (characterSet
.IsEmpty())
2517 value
[i
] = (WORD
)(theBits
+ firstChar
);
2519 value
[i
] = characterSet
[(PINDEX
)theBits
];
2526 void PASN_BMPString::EncodePER(PPER_Stream
& strm
) const
2530 PINDEX len
= value
.GetSize();
2531 ConstrainedLengthEncode(strm
, len
);
2533 PINDEX nBits
= strm
.IsAligned() ? charSetAlignedBits
: charSetUnalignedBits
;
2535 if ((constraint
== Unconstrained
|| upperLimit
*nBits
> 16) && strm
.IsAligned())
2538 for (PINDEX i
= 0; i
< len
; i
++) {
2539 if (characterSet
.IsEmpty())
2540 strm
.MultiBitEncode(value
[i
] - firstChar
, nBits
);
2542 for (PINDEX pos
= 0; pos
< characterSet
.GetSize(); pos
++) {
2543 if (characterSet
[pos
] == value
[i
]) {
2544 strm
.MultiBitEncode(pos
, nBits
);
2553 BOOL
PBER_Stream::BMPStringDecode(PASN_BMPString
& value
)
2556 if (!HeaderDecode(value
, len
))
2559 return value
.DecodeBER(*this, len
);
2563 void PBER_Stream::BMPStringEncode(const PASN_BMPString
& value
)
2565 HeaderEncode(value
);
2566 value
.EncodeBER(*this);
2570 BOOL
PPER_Stream::BMPStringDecode(PASN_BMPString
& value
)
2572 return value
.DecodePER(*this);
2576 void PPER_Stream::BMPStringEncode(const PASN_BMPString
& value
)
2578 value
.EncodePER(*this);
2582 ///////////////////////////////////////////////////////////////////////
2584 PASN_GeneralisedTime
& PASN_GeneralisedTime::operator=(const PTime
& time
)
2586 value
= time
.AsString("yyyyMMddhhmmss.uz");
2587 value
.Replace("GMT", "Z");
2592 PTime
PASN_GeneralisedTime::GetValue() const
2594 int year
= value(0,3).AsInteger();
2595 int month
= value(4,5).AsInteger();
2596 int day
= value(6,7).AsInteger();
2597 int hour
= value(8,9).AsInteger();
2598 int minute
= value(10,11).AsInteger();
2602 if (isdigit(value
[12])) {
2603 seconds
= value(12,13).AsInteger();
2604 if (value
[14] != '.')
2608 while (isdigit(value
[zonePos
]))
2613 int zone
= PTime::Local
;
2614 switch (value
[zonePos
]) {
2620 zone
= value(zonePos
+1,zonePos
+2).AsInteger()*60 +
2621 value(zonePos
+3,zonePos
+4).AsInteger();
2624 return PTime(seconds
, minute
, hour
, day
, month
, year
, zone
);
2628 ///////////////////////////////////////////////////////////////////////
2630 PASN_UniversalTime
& PASN_UniversalTime::operator=(const PTime
& time
)
2632 value
= time
.AsString("yyMMddhhmmssz");
2633 value
.Replace("GMT", "Z");
2638 PTime
PASN_UniversalTime::GetValue() const
2640 int year
= value(0,1).AsInteger();
2646 int month
= value(2,3).AsInteger();
2647 int day
= value(4,5).AsInteger();
2648 int hour
= value(6,7).AsInteger();
2649 int minute
= value(8,9).AsInteger();
2653 if (isdigit(value
[10])) {
2654 seconds
= value(10,11).AsInteger();
2658 int zone
= PTime::UTC
;
2659 if (value
[zonePos
] != 'Z')
2660 zone
= value(zonePos
+1,zonePos
+2).AsInteger()*60 +
2661 value(zonePos
+3,zonePos
+4).AsInteger();
2663 return PTime(seconds
, minute
, hour
, day
, month
, year
, zone
);
2667 ///////////////////////////////////////////////////////////////////////
2669 PASN_Choice::PASN_Choice(unsigned nChoices
, BOOL extend
)
2670 : PASN_Object(0, ApplicationTagClass
, extend
)
2672 numChoices
= nChoices
;
2677 PASN_Choice::PASN_Choice(unsigned tag
, TagClass tagClass
,
2678 unsigned upper
, BOOL extend
)
2679 : PASN_Object(tag
, tagClass
, extend
)
2686 PASN_Choice::PASN_Choice(unsigned tag
, TagClass tagClass
,
2687 unsigned upper
, BOOL extend
, const PString
& nameSpec
)
2688 : PASN_Object(tag
, tagClass
, extend
),
2689 names(BuildNamesDict(nameSpec
))
2696 PASN_Choice::PASN_Choice(const PASN_Choice
& other
)
2697 : PASN_Object(other
),
2700 numChoices
= other
.numChoices
;
2702 if (other
.choice
!= NULL
)
2703 choice
= (PASN_Object
*)other
.choice
->Clone();
2709 PASN_Choice
& PASN_Choice::operator=(const PASN_Choice
& other
)
2713 PASN_Object::operator=(other
);
2715 numChoices
= other
.numChoices
;
2716 names
= other
.names
;
2718 if (other
.choice
!= NULL
)
2719 choice
= (PASN_Object
*)other
.choice
->Clone();
2727 PASN_Choice::~PASN_Choice()
2733 void PASN_Choice::SetTag(unsigned newTag
, TagClass tagClass
)
2735 PASN_Object::SetTag(newTag
, tagClass
);
2740 choice
->SetTag(newTag
, tagClass
);
2744 PString
PASN_Choice::GetTagName() const
2746 if (tag
== UINT_MAX
)
2747 return "<uninitialised>";
2749 if (names
.Contains(tag
))
2752 if (choice
!= NULL
&& choice
->IsDescendant(PASN_Choice::Class()) &&
2753 choice
->GetTag() == tag
&& choice
->GetTagClass() == tagClass
)
2754 return PString(choice
->GetClass()) + "->" + ((PASN_Choice
*)choice
)->GetTagName();
2756 return psprintf("<%u>", tag
);
2760 PASN_Object
& PASN_Choice::GetObject() const
2762 PAssert(choice
!= NULL
, "NULL Choice");
2767 #if defined(__GNUC__) && __GNUC__ <= 2 && __GNUC_MINOR__ < 9
2769 PASN_Choice::operator PASN_Null
&() const
2771 PAssert(PAssertNULL(choice
)->IsDescendant(PASN_Null::Class()), PInvalidCast
);
2772 return *(PASN_Null
*)choice
;
2776 PASN_Choice::operator PASN_Boolean
&() const
2778 PAssert(PAssertNULL(choice
)->IsDescendant(PASN_Boolean::Class()), PInvalidCast
);
2779 return *(PASN_Boolean
*)choice
;
2783 PASN_Choice::operator PASN_Integer
&() const
2785 PAssert(PAssertNULL(choice
)->IsDescendant(PASN_Integer::Class()), PInvalidCast
);
2786 return *(PASN_Integer
*)choice
;
2790 PASN_Choice::operator PASN_Enumeration
&() const
2792 PAssert(PAssertNULL(choice
)->IsDescendant(PASN_Enumeration::Class()), PInvalidCast
);
2793 return *(PASN_Enumeration
*)choice
;
2797 PASN_Choice::operator PASN_Real
&() const
2799 PAssert(PAssertNULL(choice
)->IsDescendant(PASN_Real::Class()), PInvalidCast
);
2800 return *(PASN_Real
*)choice
;
2804 PASN_Choice::operator PASN_ObjectId
&() const
2806 PAssert(PAssertNULL(choice
)->IsDescendant(PASN_ObjectId::Class()), PInvalidCast
);
2807 return *(PASN_ObjectId
*)choice
;
2811 PASN_Choice::operator PASN_BitString
&() const
2813 PAssert(PAssertNULL(choice
)->IsDescendant(PASN_BitString::Class()), PInvalidCast
);
2814 return *(PASN_BitString
*)choice
;
2818 PASN_Choice::operator PASN_OctetString
&() const
2820 PAssert(PAssertNULL(choice
)->IsDescendant(PASN_OctetString::Class()), PInvalidCast
);
2821 return *(PASN_OctetString
*)choice
;
2825 PASN_Choice::operator PASN_NumericString
&() const
2827 PAssert(PAssertNULL(choice
)->IsDescendant(PASN_NumericString::Class()), PInvalidCast
);
2828 return *(PASN_NumericString
*)choice
;
2832 PASN_Choice::operator PASN_PrintableString
&() const
2834 PAssert(PAssertNULL(choice
)->IsDescendant(PASN_PrintableString::Class()), PInvalidCast
);
2835 return *(PASN_PrintableString
*)choice
;
2839 PASN_Choice::operator PASN_VisibleString
&() const
2841 PAssert(PAssertNULL(choice
)->IsDescendant(PASN_VisibleString::Class()), PInvalidCast
);
2842 return *(PASN_VisibleString
*)choice
;
2846 PASN_Choice::operator PASN_IA5String
&() const
2848 PAssert(PAssertNULL(choice
)->IsDescendant(PASN_IA5String::Class()), PInvalidCast
);
2849 return *(PASN_IA5String
*)choice
;
2853 PASN_Choice::operator PASN_GeneralString
&() const
2855 PAssert(PAssertNULL(choice
)->IsDescendant(PASN_GeneralString::Class()), PInvalidCast
);
2856 return *(PASN_GeneralString
*)choice
;
2860 PASN_Choice::operator PASN_BMPString
&() const
2862 PAssert(PAssertNULL(choice
)->IsDescendant(PASN_BMPString::Class()), PInvalidCast
);
2863 return *(PASN_BMPString
*)choice
;
2867 PASN_Choice::operator PASN_Sequence
&() const
2869 PAssert(PAssertNULL(choice
)->IsDescendant(PASN_Sequence::Class()), PInvalidCast
);
2870 return *(PASN_Sequence
*)choice
;
2877 PASN_Choice::operator PASN_Null
&()
2879 PAssert(PAssertNULL(choice
)->IsDescendant(PASN_Null::Class()), PInvalidCast
);
2880 return *(PASN_Null
*)choice
;
2884 PASN_Choice::operator PASN_Boolean
&()
2886 PAssert(PAssertNULL(choice
)->IsDescendant(PASN_Boolean::Class()), PInvalidCast
);
2887 return *(PASN_Boolean
*)choice
;
2891 PASN_Choice::operator PASN_Integer
&()
2893 PAssert(PAssertNULL(choice
)->IsDescendant(PASN_Integer::Class()), PInvalidCast
);
2894 return *(PASN_Integer
*)choice
;
2898 PASN_Choice::operator PASN_Enumeration
&()
2900 PAssert(PAssertNULL(choice
)->IsDescendant(PASN_Enumeration::Class()), PInvalidCast
);
2901 return *(PASN_Enumeration
*)choice
;
2905 PASN_Choice::operator PASN_Real
&()
2907 PAssert(PAssertNULL(choice
)->IsDescendant(PASN_Real::Class()), PInvalidCast
);
2908 return *(PASN_Real
*)choice
;
2912 PASN_Choice::operator PASN_ObjectId
&()
2914 PAssert(PAssertNULL(choice
)->IsDescendant(PASN_ObjectId::Class()), PInvalidCast
);
2915 return *(PASN_ObjectId
*)choice
;
2919 PASN_Choice::operator PASN_BitString
&()
2921 PAssert(PAssertNULL(choice
)->IsDescendant(PASN_BitString::Class()), PInvalidCast
);
2922 return *(PASN_BitString
*)choice
;
2926 PASN_Choice::operator PASN_OctetString
&()
2928 PAssert(PAssertNULL(choice
)->IsDescendant(PASN_OctetString::Class()), PInvalidCast
);
2929 return *(PASN_OctetString
*)choice
;
2933 PASN_Choice::operator PASN_NumericString
&()
2935 PAssert(PAssertNULL(choice
)->IsDescendant(PASN_NumericString::Class()), PInvalidCast
);
2936 return *(PASN_NumericString
*)choice
;
2940 PASN_Choice::operator PASN_PrintableString
&()
2942 PAssert(PAssertNULL(choice
)->IsDescendant(PASN_PrintableString::Class()), PInvalidCast
);
2943 return *(PASN_PrintableString
*)choice
;
2947 PASN_Choice::operator PASN_VisibleString
&()
2949 PAssert(PAssertNULL(choice
)->IsDescendant(PASN_VisibleString::Class()), PInvalidCast
);
2950 return *(PASN_VisibleString
*)choice
;
2954 PASN_Choice::operator PASN_IA5String
&()
2956 PAssert(PAssertNULL(choice
)->IsDescendant(PASN_IA5String::Class()), PInvalidCast
);
2957 return *(PASN_IA5String
*)choice
;
2961 PASN_Choice::operator PASN_GeneralString
&()
2963 PAssert(PAssertNULL(choice
)->IsDescendant(PASN_GeneralString::Class()), PInvalidCast
);
2964 return *(PASN_GeneralString
*)choice
;
2968 PASN_Choice::operator PASN_BMPString
&()
2970 PAssert(PAssertNULL(choice
)->IsDescendant(PASN_BMPString::Class()), PInvalidCast
);
2971 return *(PASN_BMPString
*)choice
;
2975 PASN_Choice::operator PASN_Sequence
&()
2977 PAssert(PAssertNULL(choice
)->IsDescendant(PASN_Sequence::Class()), PInvalidCast
);
2978 return *(PASN_Sequence
*)choice
;
2982 PASN_Choice::operator const PASN_Null
&() const
2984 PAssert(PAssertNULL(choice
)->IsDescendant(PASN_Null::Class()), PInvalidCast
);
2985 return *(const PASN_Null
*)choice
;
2989 PASN_Choice::operator const PASN_Boolean
&() const
2991 PAssert(PAssertNULL(choice
)->IsDescendant(PASN_Boolean::Class()), PInvalidCast
);
2992 return *(const PASN_Boolean
*)choice
;
2996 PASN_Choice::operator const PASN_Integer
&() const
2998 PAssert(PAssertNULL(choice
)->IsDescendant(PASN_Integer::Class()), PInvalidCast
);
2999 return *(const PASN_Integer
*)choice
;
3003 PASN_Choice::operator const PASN_Enumeration
&() const
3005 PAssert(PAssertNULL(choice
)->IsDescendant(PASN_Enumeration::Class()), PInvalidCast
);
3006 return *(const PASN_Enumeration
*)choice
;
3010 PASN_Choice::operator const PASN_Real
&() const
3012 PAssert(PAssertNULL(choice
)->IsDescendant(PASN_Real::Class()), PInvalidCast
);
3013 return *(const PASN_Real
*)choice
;
3017 PASN_Choice::operator const PASN_ObjectId
&() const
3019 PAssert(PAssertNULL(choice
)->IsDescendant(PASN_ObjectId::Class()), PInvalidCast
);
3020 return *(const PASN_ObjectId
*)choice
;
3024 PASN_Choice::operator const PASN_BitString
&() const
3026 PAssert(PAssertNULL(choice
)->IsDescendant(PASN_BitString::Class()), PInvalidCast
);
3027 return *(const PASN_BitString
*)choice
;
3031 PASN_Choice::operator const PASN_OctetString
&() const
3033 PAssert(PAssertNULL(choice
)->IsDescendant(PASN_OctetString::Class()), PInvalidCast
);
3034 return *(const PASN_OctetString
*)choice
;
3038 PASN_Choice::operator const PASN_NumericString
&() const
3040 PAssert(PAssertNULL(choice
)->IsDescendant(PASN_NumericString::Class()), PInvalidCast
);
3041 return *(const PASN_NumericString
*)choice
;
3045 PASN_Choice::operator const PASN_PrintableString
&() const
3047 PAssert(PAssertNULL(choice
)->IsDescendant(PASN_PrintableString::Class()), PInvalidCast
);
3048 return *(const PASN_PrintableString
*)choice
;
3052 PASN_Choice::operator const PASN_VisibleString
&() const
3054 PAssert(PAssertNULL(choice
)->IsDescendant(PASN_VisibleString::Class()), PInvalidCast
);
3055 return *(const PASN_VisibleString
*)choice
;
3059 PASN_Choice::operator const PASN_IA5String
&() const
3061 PAssert(PAssertNULL(choice
)->IsDescendant(PASN_IA5String::Class()), PInvalidCast
);
3062 return *(const PASN_IA5String
*)choice
;
3066 PASN_Choice::operator const PASN_GeneralString
&() const
3068 PAssert(PAssertNULL(choice
)->IsDescendant(PASN_GeneralString::Class()), PInvalidCast
);
3069 return *(const PASN_GeneralString
*)choice
;
3073 PASN_Choice::operator const PASN_BMPString
&() const
3075 PAssert(PAssertNULL(choice
)->IsDescendant(PASN_BMPString::Class()), PInvalidCast
);
3076 return *(const PASN_BMPString
*)choice
;
3080 PASN_Choice::operator const PASN_Sequence
&() const
3082 PAssert(PAssertNULL(choice
)->IsDescendant(PASN_Sequence::Class()), PInvalidCast
);
3083 return *(const PASN_Sequence
*)choice
;
3090 PObject::Comparison
PASN_Choice::Compare(const PObject
& obj
) const
3092 PAssert(obj
.IsDescendant(PASN_Choice::Class()), PInvalidCast
);
3093 const PASN_Choice
& other
= (const PASN_Choice
&)obj
;
3095 if (choice
== other
.choice
)
3101 if (other
.choice
== NULL
)
3104 if (tag
< other
.tag
)
3107 if (tag
> other
.tag
)
3110 return choice
->Compare(*other
.choice
);
3114 void PASN_Choice::PrintOn(ostream
& strm
) const
3116 strm
<< GetTagName();
3119 strm
<< ' ' << *choice
;
3125 PString
PASN_Choice::GetTypeAsString() const
3131 PINDEX
PASN_Choice::GetDataLength() const
3134 return choice
->GetDataLength();
3139 BOOL
PASN_Choice::IsPrimitive() const
3142 return choice
->IsPrimitive();
3147 BOOL
PASN_Choice::Decode(PASN_Stream
& strm
)
3149 return strm
.ChoiceDecode(*this);
3153 void PASN_Choice::Encode(PASN_Stream
& strm
) const
3155 strm
.ChoiceEncode(*this);
3159 BOOL
PASN_Choice::DecodePER(PPER_Stream
& strm
)
3164 if (strm
.IsAtEnd()) {
3172 if (strm
.SingleBitDecode()) {
3173 if (!strm
.SmallUnsignedDecode(tag
))
3177 if (strm
.LengthDecode(0, INT_MAX
, len
) != 0)
3179 if (CreateObject()) {
3180 PINDEX nextPos
= strm
.GetPosition() + len
;
3181 ok
= choice
->Decode(strm
);
3182 strm
.SetPosition(nextPos
);
3185 PASN_OctetString
* open_type
= new PASN_OctetString
;
3186 open_type
->SetConstraints(PASN_ConstrainedObject::FixedConstraint
, len
);
3187 open_type
->Decode(strm
);
3188 if (open_type
->GetSize() > 0)
3202 if (strm
.UnsignedDecode(0, numChoices
-1, tag
) < 0)
3207 ok
= choice
->Decode(strm
);
3213 void PASN_Choice::EncodePER(PPER_Stream
& strm
) const
3215 PAssert(tag
!= UINT_MAX
, PLogicError
);
3218 BOOL extended
= tag
>= numChoices
;
3219 strm
.SingleBitEncode(extended
);
3221 strm
.SmallUnsignedEncode(tag
- numChoices
);
3222 strm
.AnyTypeEncode(choice
);
3228 strm
.UnsignedEncode(tag
, 0, numChoices
-1);
3231 choice
->Encode(strm
);
3235 BOOL
PBER_Stream::ChoiceDecode(PASN_Choice
& value
)
3237 PINDEX savedPosition
= GetPosition();
3240 PASN_Object::TagClass tagClass
;
3243 if (!HeaderDecode(tag
, tagClass
, primitive
, entryLen
))
3246 SetPosition(savedPosition
);
3248 value
.SetTag(tag
, tagClass
);
3249 if (value
.IsValid())
3250 return value
.GetObject().Decode(*this);
3256 void PBER_Stream::ChoiceEncode(const PASN_Choice
& value
)
3258 if (value
.IsValid())
3259 value
.GetObject().Encode(*this);
3263 BOOL
PPER_Stream::ChoiceDecode(PASN_Choice
& value
)
3265 return value
.DecodePER(*this);
3269 void PPER_Stream::ChoiceEncode(const PASN_Choice
& value
)
3271 value
.EncodePER(*this);
3275 ///////////////////////////////////////////////////////////////////////
3277 PASN_Sequence::PASN_Sequence(unsigned tag
, TagClass tagClass
,
3278 unsigned nOpts
, BOOL extend
, unsigned nExtend
)
3279 : PASN_Object(tag
, tagClass
, extend
)
3281 optionMap
.SetConstraints(PASN_ConstrainedObject::FixedConstraint
, nOpts
);
3282 knownExtensions
= nExtend
;
3283 totalExtensions
= 0;
3284 endBasicEncoding
= 0;
3288 PASN_Sequence::PASN_Sequence(const PASN_Sequence
& other
)
3289 : PASN_Object(other
),
3290 fields(other
.fields
.GetSize()),
3291 optionMap(other
.optionMap
),
3292 extensionMap(other
.extensionMap
)
3294 for (PINDEX i
= 0; i
< other
.fields
.GetSize(); i
++)
3295 fields
.SetAt(i
, other
.fields
[i
].Clone());
3297 knownExtensions
= other
.knownExtensions
;
3298 totalExtensions
= other
.totalExtensions
;
3299 endBasicEncoding
= 0;
3303 PASN_Sequence
& PASN_Sequence::operator=(const PASN_Sequence
& other
)
3305 PASN_Object::operator=(other
);
3307 fields
.SetSize(other
.fields
.GetSize());
3308 for (PINDEX i
= 0; i
< other
.fields
.GetSize(); i
++)
3309 fields
.SetAt(i
, other
.fields
[i
].Clone());
3311 optionMap
= other
.optionMap
;
3312 knownExtensions
= other
.knownExtensions
;
3313 totalExtensions
= other
.totalExtensions
;
3314 extensionMap
= other
.extensionMap
;
3320 BOOL
PASN_Sequence::HasOptionalField(PINDEX opt
) const
3322 if (opt
< (PINDEX
)optionMap
.GetSize())
3323 return optionMap
[opt
];
3325 return extensionMap
[opt
- optionMap
.GetSize()];
3329 void PASN_Sequence::IncludeOptionalField(PINDEX opt
)
3331 if (opt
< (PINDEX
)optionMap
.GetSize())
3334 PAssert(extendable
, "Must be extendable type");
3335 opt
-= optionMap
.GetSize();
3336 if (opt
>= (PINDEX
)extensionMap
.GetSize())
3337 extensionMap
.SetSize(opt
+1);
3338 extensionMap
.Set(opt
);
3343 void PASN_Sequence::RemoveOptionalField(PINDEX opt
)
3345 if (opt
< (PINDEX
)optionMap
.GetSize())
3346 optionMap
.Clear(opt
);
3348 PAssert(extendable
, "Must be extendable type");
3349 opt
-= optionMap
.GetSize();
3350 extensionMap
.Clear(opt
);
3355 PObject::Comparison
PASN_Sequence::Compare(const PObject
& obj
) const
3357 PAssert(obj
.IsDescendant(PASN_Sequence::Class()), PInvalidCast
);
3358 const PASN_Sequence
& other
= (const PASN_Sequence
&)obj
;
3359 return fields
.Compare(other
.fields
);
3363 PObject
* PASN_Sequence::Clone() const
3365 PAssert(IsClass(PASN_Sequence::Class()), PInvalidCast
);
3366 return new PASN_Sequence(*this);
3370 void PASN_Sequence::PrintOn(ostream
& strm
) const
3372 int indent
= strm
.precision() + 2;
3374 for (PINDEX i
= 0; i
< fields
.GetSize(); i
++) {
3375 strm
<< setw(indent
+6) << "field[" << i
<< "] <";
3376 switch (fields
[i
].GetTagClass()) {
3377 case UniversalTagClass
:
3378 strm
<< "Universal";
3380 case ApplicationTagClass
:
3381 strm
<< "Application";
3383 case ContextSpecificTagClass
:
3384 strm
<< "ContextSpecific";
3386 case PrivateTagClass
:
3391 strm
<< '-' << fields
[i
].GetTag() << '-'
3392 << fields
[i
].GetTypeAsString() << "> = "
3393 << fields
[i
] << '\n';
3395 strm
<< setw(indent
-1) << "}";
3399 PString
PASN_Sequence::GetTypeAsString() const
3405 PINDEX
PASN_Sequence::GetDataLength() const
3408 for (PINDEX i
= 0; i
< fields
.GetSize(); i
++)
3409 len
+= fields
[i
].GetObjectLength();
3414 BOOL
PASN_Sequence::IsPrimitive() const
3420 BOOL
PASN_Sequence::Decode(PASN_Stream
& strm
)
3422 return PreambleDecode(strm
) && UnknownExtensionsDecode(strm
);
3426 void PASN_Sequence::Encode(PASN_Stream
& strm
) const
3428 PreambleEncode(strm
);
3429 UnknownExtensionsEncode(strm
);
3433 BOOL
PASN_Sequence::PreambleDecode(PASN_Stream
& strm
)
3435 return strm
.SequencePreambleDecode(*this);
3439 void PASN_Sequence::PreambleEncode(PASN_Stream
& strm
) const
3441 strm
.SequencePreambleEncode(*this);
3445 BOOL
PASN_Sequence::KnownExtensionDecode(PASN_Stream
& strm
, PINDEX fld
, PASN_Object
& field
)
3447 return strm
.SequenceKnownDecode(*this, fld
, field
);
3451 void PASN_Sequence::KnownExtensionEncode(PASN_Stream
& strm
, PINDEX fld
, const PASN_Object
& field
) const
3453 strm
.SequenceKnownEncode(*this, fld
, field
);
3457 BOOL
PASN_Sequence::UnknownExtensionsDecode(PASN_Stream
& strm
)
3459 return strm
.SequenceUnknownDecode(*this);
3463 void PASN_Sequence::UnknownExtensionsEncode(PASN_Stream
& strm
) const
3465 strm
.SequenceUnknownEncode(*this);
3469 BOOL
PASN_Sequence::PreambleDecodeBER(PBER_Stream
& strm
)
3474 if (!strm
.HeaderDecode(*this, len
))
3477 endBasicEncoding
= strm
.GetPosition() + len
;
3478 return !strm
.IsAtEnd();
3482 void PASN_Sequence::PreambleEncodeBER(PBER_Stream
& strm
) const
3484 strm
.HeaderEncode(*this);
3488 BOOL
PASN_Sequence::KnownExtensionDecodeBER(PBER_Stream
& strm
, PINDEX
, PASN_Object
& field
)
3490 if (strm
.GetPosition() >= endBasicEncoding
)
3493 return field
.Decode(strm
);
3497 void PASN_Sequence::KnownExtensionEncodeBER(PBER_Stream
& strm
, PINDEX
, const PASN_Object
& field
) const
3503 BOOL
PASN_Sequence::UnknownExtensionsDecodeBER(PBER_Stream
& strm
)
3505 while (strm
.GetPosition() < endBasicEncoding
) {
3506 PINDEX savedPosition
= strm
.GetPosition();
3509 PASN_Object::TagClass tagClass
;
3512 if (!strm
.HeaderDecode(tag
, tagClass
, primitive
, entryLen
))
3515 PINDEX nextEntryPosition
= strm
.GetPosition() + entryLen
;
3516 strm
.SetPosition(savedPosition
);
3518 PASN_Object
* obj
= strm
.CreateObject(tag
, tagClass
, primitive
);
3520 strm
.SetPosition(nextEntryPosition
);
3522 if (!obj
->Decode(strm
))
3533 void PASN_Sequence::UnknownExtensionsEncodeBER(PBER_Stream
& strm
) const
3535 for (PINDEX i
= 0; i
< fields
.GetSize(); i
++)
3536 fields
[i
].Encode(strm
);
3540 BOOL
PASN_Sequence::PreambleDecodePER(PPER_Stream
& strm
)
3547 totalExtensions
= strm
.SingleBitDecode() ? -1 : 0; // 18.1
3550 totalExtensions
= 0;
3551 return optionMap
.Decode(strm
); // 18.2
3555 void PASN_Sequence::PreambleEncodePER(PPER_Stream
& strm
) const
3560 BOOL hasExtensions
= FALSE
;
3561 for (unsigned i
= 0; i
< extensionMap
.GetSize(); i
++) {
3562 if (extensionMap
[i
]) {
3563 hasExtensions
= TRUE
;
3567 strm
.SingleBitEncode(hasExtensions
); // 18.1
3568 ((PASN_Sequence
*)this)->totalExtensions
= hasExtensions
? -1 : 0;
3570 optionMap
.Encode(strm
); // 18.2
3574 BOOL
PASN_Sequence::NoExtensionsToDecode(PPER_Stream
& strm
)
3576 if (totalExtensions
== 0)
3579 if (totalExtensions
< 0) {
3580 if (!extensionMap
.DecodeSequenceExtensionBitmap(strm
))
3582 totalExtensions
= extensionMap
.GetSize();
3589 BOOL
PASN_Sequence::NoExtensionsToEncode(PPER_Stream
& strm
)
3591 if (totalExtensions
== 0)
3594 if (totalExtensions
< 0) {
3595 totalExtensions
= extensionMap
.GetSize();
3596 extensionMap
.EncodeSequenceExtensionBitmap(strm
);
3603 BOOL
PASN_Sequence::KnownExtensionDecodePER(PPER_Stream
& strm
, PINDEX fld
, PASN_Object
& field
)
3605 if (NoExtensionsToDecode(strm
))
3608 if (!extensionMap
[fld
-optionMap
.GetSize()])
3612 if (strm
.LengthDecode(0, INT_MAX
, len
) != 0)
3615 PINDEX nextExtensionPosition
= strm
.GetPosition() + len
;
3616 BOOL ok
= field
.Decode(strm
);
3617 strm
.SetPosition(nextExtensionPosition
);
3622 void PASN_Sequence::KnownExtensionEncodePER(PPER_Stream
& strm
, PINDEX fld
, const PASN_Object
& field
) const
3624 if (((PASN_Sequence
*)this)->NoExtensionsToEncode(strm
))
3627 if (!extensionMap
[fld
-optionMap
.GetSize()])
3630 strm
.AnyTypeEncode(&field
);
3634 BOOL
PASN_Sequence::UnknownExtensionsDecodePER(PPER_Stream
& strm
)
3636 if (NoExtensionsToDecode(strm
))
3639 if (totalExtensions
<= knownExtensions
)
3640 return TRUE
; // Already read them
3642 PINDEX unknownCount
= totalExtensions
- knownExtensions
;
3643 if (fields
.GetSize() >= unknownCount
)
3644 return TRUE
; // Already read them
3646 fields
.SetSize(unknownCount
);
3649 for (i
= 0; i
< fields
.GetSize(); i
++)
3650 fields
.SetAt(i
, new PASN_OctetString
);
3652 for (i
= knownExtensions
; i
< (PINDEX
)extensionMap
.GetSize(); i
++) {
3653 if (extensionMap
[i
])
3654 if (!fields
[i
-knownExtensions
].Decode(strm
))
3662 void PASN_Sequence::UnknownExtensionsEncodePER(PPER_Stream
& strm
) const
3664 if (((PASN_Sequence
*)this)->NoExtensionsToEncode(strm
))
3668 for (i
= knownExtensions
; i
< totalExtensions
; i
++) {
3669 if (extensionMap
[i
])
3670 fields
[i
-knownExtensions
].Encode(strm
);
3675 BOOL
PBER_Stream::SequencePreambleDecode(PASN_Sequence
& seq
)
3677 return seq
.PreambleDecodeBER(*this);
3681 void PBER_Stream::SequencePreambleEncode(const PASN_Sequence
& seq
)
3683 seq
.PreambleEncodeBER(*this);
3687 BOOL
PBER_Stream::SequenceKnownDecode(PASN_Sequence
& seq
, PINDEX fld
, PASN_Object
& field
)
3689 return seq
.KnownExtensionDecodeBER(*this, fld
, field
);
3693 void PBER_Stream::SequenceKnownEncode(const PASN_Sequence
& seq
, PINDEX fld
, const PASN_Object
& field
)
3695 seq
.KnownExtensionEncodeBER(*this, fld
, field
);
3699 BOOL
PBER_Stream::SequenceUnknownDecode(PASN_Sequence
& seq
)
3701 return seq
.UnknownExtensionsDecodeBER(*this);
3705 void PBER_Stream::SequenceUnknownEncode(const PASN_Sequence
& seq
)
3707 seq
.UnknownExtensionsEncodeBER(*this);
3711 BOOL
PPER_Stream::SequencePreambleDecode(PASN_Sequence
& seq
)
3713 return seq
.PreambleDecodePER(*this);
3717 void PPER_Stream::SequencePreambleEncode(const PASN_Sequence
& seq
)
3719 seq
.PreambleEncodePER(*this);
3723 BOOL
PPER_Stream::SequenceKnownDecode(PASN_Sequence
& seq
, PINDEX fld
, PASN_Object
& field
)
3725 return seq
.KnownExtensionDecodePER(*this, fld
, field
);
3729 void PPER_Stream::SequenceKnownEncode(const PASN_Sequence
& seq
, PINDEX fld
, const PASN_Object
& field
)
3731 seq
.KnownExtensionEncodePER(*this, fld
, field
);
3735 BOOL
PPER_Stream::SequenceUnknownDecode(PASN_Sequence
& seq
)
3737 return seq
.UnknownExtensionsDecodePER(*this);
3741 void PPER_Stream::SequenceUnknownEncode(const PASN_Sequence
& seq
)
3743 seq
.UnknownExtensionsEncodePER(*this);
3747 ///////////////////////////////////////////////////////////////////////
3749 PASN_Set::PASN_Set(unsigned tag
, TagClass tagClass
,
3750 unsigned nOpts
, BOOL extend
, unsigned nExtend
)
3751 : PASN_Sequence(tag
, tagClass
, nOpts
, extend
, nExtend
)
3756 PObject
* PASN_Set::Clone() const
3758 PAssert(IsClass(PASN_Set::Class()), PInvalidCast
);
3759 return new PASN_Set(*this);
3763 PString
PASN_Set::GetTypeAsString() const
3769 ///////////////////////////////////////////////////////////////////////
3771 PASN_Array::PASN_Array(unsigned tag
, TagClass tagClass
)
3772 : PASN_ConstrainedObject(tag
, tagClass
)
3777 PASN_Array::PASN_Array(const PASN_Array
& other
)
3778 : PASN_ConstrainedObject(other
),
3779 array(other
.array
.GetSize())
3781 for (PINDEX i
= 0; i
< other
.array
.GetSize(); i
++)
3782 array
.SetAt(i
, other
.array
[i
].Clone());
3786 PASN_Array
& PASN_Array::operator=(const PASN_Array
& other
)
3788 PASN_ConstrainedObject::operator=(other
);
3790 array
.SetSize(other
.array
.GetSize());
3791 for (PINDEX i
= 0; i
< other
.array
.GetSize(); i
++)
3792 array
.SetAt(i
, other
.array
[i
].Clone());
3798 void PASN_Array::SetSize(PINDEX newSize
)
3800 PINDEX originalSize
= array
.GetSize();
3801 array
.SetSize(newSize
);
3802 for (PINDEX i
= originalSize
; i
< newSize
; i
++)
3803 array
.SetAt(i
, CreateObject());
3807 PObject::Comparison
PASN_Array::Compare(const PObject
& obj
) const
3809 PAssert(obj
.IsDescendant(PASN_Array::Class()), PInvalidCast
);
3810 const PASN_Array
& other
= (const PASN_Array
&)obj
;
3811 return array
.Compare(other
.array
);
3815 void PASN_Array::PrintOn(ostream
& strm
) const
3817 int indent
= strm
.precision() + 2;
3818 strm
<< array
.GetSize() << " entries {\n";
3819 for (PINDEX i
= 0; i
< array
.GetSize(); i
++)
3820 strm
<< setw(indent
+1) << "[" << i
<< "]=" << setprecision(indent
) << array
[i
] << '\n';
3821 strm
<< setw(indent
-1) << "}";
3825 void PASN_Array::SetConstraintBounds(ConstraintType type
, int lower
, unsigned upper
)
3827 PAssert(lower
>= 0, PInvalidParameter
);
3828 PASN_ConstrainedObject::SetConstraintBounds(type
, lower
, upper
);
3829 if (constraint
!= Unconstrained
) {
3830 if (GetSize() < (PINDEX
)lowerLimit
)
3831 SetSize(lowerLimit
);
3832 else if (GetSize() > (PINDEX
)upperLimit
)
3833 SetSize(upperLimit
);
3838 PString
PASN_Array::GetTypeAsString() const
3844 PINDEX
PASN_Array::GetDataLength() const
3847 for (PINDEX i
= 0; i
< array
.GetSize(); i
++)
3848 len
+= array
[i
].GetObjectLength();
3853 BOOL
PASN_Array::IsPrimitive() const
3859 BOOL
PASN_Array::Decode(PASN_Stream
& strm
)
3861 return strm
.ArrayDecode(*this);
3865 void PASN_Array::Encode(PASN_Stream
& strm
) const
3867 strm
.ArrayEncode(*this);
3871 BOOL
PBER_Stream::ArrayDecode(PASN_Array
& array
)
3876 if (!HeaderDecode(array
, len
))
3879 PINDEX endOffset
= byteOffset
+ len
;
3881 while (byteOffset
< endOffset
) {
3882 array
.SetSize(count
+1);
3883 if (!array
[count
].Decode(*this))
3888 byteOffset
= endOffset
;
3894 void PBER_Stream::ArrayEncode(const PASN_Array
& array
)
3896 HeaderEncode(array
);
3897 for (PINDEX i
= 0; i
< array
.GetSize(); i
++)
3898 array
[i
].Encode(*this);
3902 BOOL
PPER_Stream::ArrayDecode(PASN_Array
& array
)
3907 if (array
.ConstrainedLengthDecode(*this, size
) < 0)
3910 array
.SetSize(size
);
3912 for (PINDEX i
= 0; i
< (PINDEX
)size
; i
++) {
3913 if (!array
[i
].Decode(*this))
3921 void PPER_Stream::ArrayEncode(const PASN_Array
& array
)
3923 PINDEX size
= array
.GetSize();
3924 array
.ConstrainedLengthEncode(*this, size
);
3925 for (PINDEX i
= 0; i
< size
; i
++)
3926 array
[i
].Encode(*this);
3930 ///////////////////////////////////////////////////////////////////////
3932 PASN_Stream::PASN_Stream()
3938 PASN_Stream::PASN_Stream(const PBYTEArray
& bytes
)
3945 PASN_Stream::PASN_Stream(const BYTE
* buf
, PINDEX size
)
3946 : PBYTEArray(buf
, size
)
3952 void PASN_Stream::Construct()
3959 void PASN_Stream::PrintOn(ostream
& strm
) const
3961 int indent
= strm
.precision() + 2;
3962 strm
<< " size=" << GetSize()
3963 << " pos=" << byteOffset
<< '.' << (8-bitOffset
)
3966 while (i
< GetSize()) {
3967 strm
<< setw(indent
) << " " << hex
<< setfill('0');
3969 for (j
= 0; j
< 16; j
++)
3970 if (i
+j
< GetSize())
3971 strm
<< setw(2) << (unsigned)(BYTE
)theArray
[i
+j
] << ' ';
3975 for (j
= 0; j
< 16; j
++) {
3976 if (i
+j
< GetSize()) {
3977 if (isprint(theArray
[i
+j
]))
3978 strm
<< theArray
[i
+j
];
3983 strm
<< dec
<< setfill(' ') << '\n';
3986 strm
<< setw(indent
-1) << "}";
3990 void PASN_Stream::SetPosition(PINDEX newPos
)
3992 PAssert(byteOffset
!= P_MAX_INDEX
, PLogicError
);
3994 if (newPos
> GetSize())
3995 byteOffset
= GetSize();
3997 byteOffset
= newPos
;
4002 void PASN_Stream::ResetDecoder()
4009 void PASN_Stream::BeginEncoding()
4013 PBYTEArray::operator=(PBYTEArray(20));
4017 void PASN_Stream::CompleteEncoding()
4019 if (byteOffset
!= P_MAX_INDEX
) {
4020 if (bitOffset
!= 8) {
4024 SetSize(byteOffset
);
4025 byteOffset
= P_MAX_INDEX
;
4030 BYTE
PASN_Stream::ByteDecode()
4032 if (byteOffset
>= GetSize())
4036 return theArray
[byteOffset
++];
4040 void PASN_Stream::ByteEncode(unsigned value
)
4042 PAssert(byteOffset
!= P_MAX_INDEX
, PLogicError
);
4044 if (bitOffset
!= 8) {
4048 if (byteOffset
>= GetSize())
4049 SetSize(byteOffset
+10);
4050 theArray
[byteOffset
++] = (BYTE
)value
;
4054 unsigned PASN_Stream::BlockDecode(BYTE
* bufptr
, unsigned nBytes
)
4061 if (byteOffset
+nBytes
> (unsigned)GetSize()) {
4062 nBytes
= GetSize() - byteOffset
;
4067 memcpy(bufptr
, &theArray
[byteOffset
], nBytes
);
4068 byteOffset
+= nBytes
;
4073 void PASN_Stream::BlockEncode(const BYTE
* bufptr
, PINDEX nBytes
)
4075 PAssert(byteOffset
!= P_MAX_INDEX
, PLogicError
);
4082 if (byteOffset
+nBytes
>= GetSize())
4083 SetSize(byteOffset
+nBytes
+10);
4085 memcpy(theArray
+byteOffset
, bufptr
, nBytes
);
4086 byteOffset
+= nBytes
;
4090 void PASN_Stream::ByteAlign()
4092 PAssert(byteOffset
!= P_MAX_INDEX
, PLogicError
);
4094 if (bitOffset
!= 8) {
4101 ///////////////////////////////////////////////////////////////////////
4103 PBER_Stream::PBER_Stream()
4108 PBER_Stream::PBER_Stream(const PBYTEArray
& bytes
)
4109 : PASN_Stream(bytes
)
4114 PBER_Stream::PBER_Stream(const BYTE
* buf
, PINDEX size
)
4115 : PASN_Stream(buf
, size
)
4120 PBER_Stream
& PBER_Stream::operator=(const PBYTEArray
& bytes
)
4122 PBYTEArray::operator=(bytes
);
4128 BOOL
PBER_Stream::Read(PChannel
& chan
)
4133 // read the sequence header
4135 if ((b
= chan
.ReadChar()) < 0)
4138 SetAt(offset
++, (char)b
);
4140 // only support direct read of simple sequences
4141 if ((b
&0x1f) == 0x1f) {
4143 if ((b
= chan
.ReadChar()) < 0)
4145 SetAt(offset
++, (char)b
);
4146 } while ((b
& 0x80) != 0);
4149 // read the first byte of the ASN length
4150 if ((b
= chan
.ReadChar()) < 0)
4153 SetAt(offset
++, (char)b
);
4155 // determine how many bytes in the length
4157 if ((b
& 0x80) == 0)
4160 PINDEX lenLen
= b
&0x7f;
4162 while (lenLen
-- > 0) {
4164 if ((b
= chan
.ReadChar()) < 0)
4166 dataLen
= (dataLen
<< 8) | b
;
4167 SetAt(offset
++, (char)b
);
4171 // read the data, all of it
4172 BYTE
* bufptr
= GetPointer(dataLen
+offset
) + offset
;
4173 while (dataLen
> 0) {
4174 if (!chan
.Read(bufptr
, dataLen
))
4176 PINDEX readbytes
= chan
.GetLastReadCount();
4177 bufptr
+= readbytes
;
4178 dataLen
-= readbytes
;
4184 BOOL
PBER_Stream::Write(PChannel
& chan
)
4187 return chan
.Write(theArray
, GetSize());
4191 PASN_Object
* PBER_Stream::CreateObject(unsigned tag
,
4192 PASN_Object::TagClass tagClass
,
4193 BOOL primitive
) const
4195 if (tagClass
== PASN_Object::UniversalTagClass
) {
4197 case PASN_Object::UniversalBoolean
:
4198 return new PASN_Boolean();
4200 case PASN_Object::UniversalInteger
:
4201 return new PASN_Integer();
4203 case PASN_Object::UniversalBitString
:
4204 return new PASN_BitString();
4206 case PASN_Object::UniversalOctetString
:
4207 return new PASN_OctetString();
4209 case PASN_Object::UniversalNull
:
4210 return new PASN_Null();
4212 case PASN_Object::UniversalObjectId
:
4213 return new PASN_ObjectId();
4215 case PASN_Object::UniversalReal
:
4216 return new PASN_Real();
4218 case PASN_Object::UniversalEnumeration
:
4219 return new PASN_Enumeration();
4221 case PASN_Object::UniversalSequence
:
4222 return new PASN_Sequence();
4224 case PASN_Object::UniversalSet
:
4225 return new PASN_Set();
4227 case PASN_Object::UniversalNumericString
:
4228 return new PASN_NumericString();
4230 case PASN_Object::UniversalPrintableString
:
4231 return new PASN_PrintableString();
4233 case PASN_Object::UniversalIA5String
:
4234 return new PASN_IA5String();
4236 case PASN_Object::UniversalVisibleString
:
4237 return new PASN_VisibleString();
4239 case PASN_Object::UniversalGeneralString
:
4240 return new PASN_GeneralString();
4242 case PASN_Object::UniversalBMPString
:
4243 return new PASN_BMPString();
4248 return new PASN_OctetString(tag
, tagClass
);
4250 return new PASN_Sequence(tag
, tagClass
, 0, FALSE
, 0);
4254 BOOL
PBER_Stream::HeaderDecode(unsigned & tagVal
,
4255 PASN_Object::TagClass
& tagClass
,
4259 BYTE ident
= ByteDecode();
4260 tagClass
= (PASN_Object::TagClass
)(ident
>>6);
4261 primitive
= (ident
&0x20) == 0;
4271 tagVal
= (tagVal
<< 7) | (b
&0x7f);
4272 } while ((b
&0x80) != 0);
4278 BYTE len_len
= ByteDecode();
4279 if ((len_len
& 0x80) == 0) {
4287 while (len_len
-- > 0) {
4291 len
= (len
<< 8) | ByteDecode();
4298 BOOL
PBER_Stream::HeaderDecode(PASN_Object
& obj
, unsigned & len
)
4300 PINDEX pos
= byteOffset
;
4303 PASN_Object::TagClass tagClass
;
4305 if (HeaderDecode(tagVal
, tagClass
, primitive
, len
) &&
4306 tagVal
== obj
.GetTag() && tagClass
== obj
.GetTagClass())
4314 void PBER_Stream::HeaderEncode(const PASN_Object
& obj
)
4316 BYTE ident
= (BYTE
)(obj
.GetTagClass() << 6);
4317 if (!obj
.IsPrimitive())
4319 unsigned tag
= obj
.GetTag();
4321 ByteEncode(ident
|tag
);
4323 ByteEncode(ident
|31);
4324 unsigned count
= (CountBits(tag
)+6)/7;
4326 ByteEncode((tag
>> (count
*7))&0x7f);
4327 ByteEncode(tag
&0x7f);
4330 PINDEX len
= obj
.GetDataLength();
4334 PINDEX count
= (CountBits(len
+1)+7)/8;
4335 ByteEncode(count
|0x80);
4337 ByteEncode(len
>> (count
*8));
4343 ///////////////////////////////////////////////////////////////////////
4345 PPER_Stream::PPER_Stream(BOOL alignment
)
4347 aligned
= alignment
;
4351 PPER_Stream::PPER_Stream(const PBYTEArray
& bytes
, BOOL alignment
)
4352 : PASN_Stream(bytes
)
4354 aligned
= alignment
;
4358 PPER_Stream::PPER_Stream(const BYTE
* buf
, PINDEX size
, BOOL alignment
)
4359 : PASN_Stream(buf
, size
)
4361 aligned
= alignment
;
4365 PPER_Stream
& PPER_Stream::operator=(const PBYTEArray
& bytes
)
4367 PBYTEArray::operator=(bytes
);
4374 unsigned PPER_Stream::GetBitsLeft() const
4376 return (GetSize() - byteOffset
)*8 - (8 - bitOffset
);
4380 BOOL
PPER_Stream::Read(PChannel
& chan
)
4385 // Get RFC1006 TPKT length
4387 if (!chan
.ReadBlock(tpkt
, sizeof(tpkt
)))
4390 if (tpkt
[0] != 3) // Only support version 3
4393 PINDEX data_len
= ((tpkt
[2] << 8)|tpkt
[3]) - 4;
4395 return chan
.ReadBlock(GetPointer(data_len
), data_len
);
4399 BOOL
PPER_Stream::Write(PChannel
& chan
)
4403 PINDEX size
= GetSize();
4405 // Put RFC1006 TPKT length
4407 tpkt
[0] = 3; // Version 3
4410 PINDEX len
= size
+ sizeof(tpkt
);
4411 tpkt
[2] = (BYTE
)(len
>> 8);
4412 tpkt
[3] = (BYTE
)len
;
4414 return chan
.Write(tpkt
, sizeof(tpkt
)) && chan
.Write(theArray
, size
);
4418 BOOL
PPER_Stream::SingleBitDecode()
4420 if ((GetSize() - byteOffset
)*8 - (8 - bitOffset
) == 0)
4424 BOOL value
= (theArray
[byteOffset
] & (1 << bitOffset
)) != 0;
4426 if (bitOffset
== 0) {
4435 void PPER_Stream::SingleBitEncode(BOOL value
)
4437 PAssert(byteOffset
!= P_MAX_INDEX
, PLogicError
);
4439 if (byteOffset
>= GetSize())
4440 SetSize(byteOffset
+10);
4445 theArray
[byteOffset
] |= 1 << bitOffset
;
4452 BOOL
PPER_Stream::MultiBitDecode(unsigned nBits
, unsigned & value
)
4454 if (nBits
> sizeof(value
)*8)
4457 unsigned bitsLeft
= (GetSize() - byteOffset
)*8 - (8 - bitOffset
);
4458 if (nBits
> bitsLeft
)
4466 if (nBits
< bitOffset
) {
4468 value
= (theArray
[byteOffset
] >> bitOffset
) & ((1 << nBits
) - 1);
4472 value
= theArray
[byteOffset
] & ((1 << bitOffset
) - 1);
4477 while (nBits
>= 8) {
4478 value
= (value
<< 8) | (BYTE
)theArray
[byteOffset
];
4484 bitOffset
= 8 - nBits
;
4485 value
= (value
<< nBits
) | ((BYTE
)theArray
[byteOffset
] >> bitOffset
);
4492 void PPER_Stream::MultiBitEncode(unsigned value
, unsigned nBits
)
4494 PAssert(byteOffset
!= P_MAX_INDEX
, PLogicError
);
4499 if (byteOffset
+nBits
/8+1 >= (unsigned)GetSize())
4500 SetSize(byteOffset
+10);
4502 // Make sure value is in bounds of bit available.
4503 if (nBits
< sizeof(int)*8)
4504 value
&= ((1 << nBits
) - 1);
4506 if (nBits
< bitOffset
) {
4508 theArray
[byteOffset
] |= value
<< bitOffset
;
4513 theArray
[byteOffset
] |= (BYTE
)(value
>> nBits
);
4517 while (nBits
>= 8) {
4519 theArray
[byteOffset
] = (BYTE
)(value
>> nBits
);
4524 bitOffset
= 8 - nBits
;
4525 theArray
[byteOffset
] |= (BYTE
)((value
& ((1 << nBits
)-1)) << bitOffset
);
4530 BOOL
PPER_Stream::SmallUnsignedDecode(unsigned & value
)
4532 // X.691 Section 10.6
4534 if (!SingleBitDecode())
4535 return MultiBitDecode(6, value
); // 10.6.1
4538 if (LengthDecode(0, INT_MAX
, len
) != 0) // 10.6.2
4542 return MultiBitDecode(len
*8, value
);
4546 void PPER_Stream::SmallUnsignedEncode(unsigned value
)
4549 MultiBitEncode(value
, 7);
4553 SingleBitEncode(1); // 10.6.2
4558 else if (value
< 65536)
4560 else if (value
< 0x1000000)
4562 LengthEncode(len
, 0, INT_MAX
); // 10.9
4564 MultiBitEncode(value
, len
*8);
4568 int PPER_Stream::UnsignedDecode(unsigned lower
, unsigned upper
, unsigned & value
)
4570 // X.691 section 10.5
4572 if (lower
== upper
) { // 10.5.4
4580 unsigned range
= (upper
- lower
) + 1;
4581 unsigned nBits
= CountBits(range
);
4583 if (aligned
&& (range
== 0 || range
> 255)) { // not 10.5.6 and not 10.5.7.1
4584 if (nBits
> 16) { // not 10.5.7.4
4585 LengthDecode(1, (nBits
+7)/8, nBits
); // 12.2.6
4588 else if (nBits
> 8) // not 10.5.7.2
4589 nBits
= 16; // 10.5.7.3
4590 ByteAlign(); // 10.7.5.2 - 10.7.5.4
4593 if (!MultiBitDecode(nBits
, value
))
4601 void PPER_Stream::UnsignedEncode(int value
, unsigned lower
, unsigned upper
)
4603 // X.691 section 10.5
4605 if (lower
== upper
) // 10.5.4
4608 unsigned range
= (upper
- lower
) + 1;
4609 PINDEX nBits
= CountBits(range
);
4611 if (aligned
&& (range
== 0 || range
> 255)) { // not 10.5.6 and not 10.5.7.1
4612 if (nBits
> 16) { // not 10.5.7.4
4613 int numBytes
= value
== 0 ? 1 : (((CountBits(value
- lower
+ 1))+7)/8);
4614 LengthEncode(numBytes
, 1, (nBits
+7)/8); // 12.2.6
4617 else if (nBits
> 8) // not 10.5.7.2
4618 nBits
= 16; // 10.5.7.3
4619 ByteAlign(); // 10.7.5.2 - 10.7.5.4
4622 MultiBitEncode(value
- lower
, nBits
);
4626 int PPER_Stream::LengthDecode(unsigned lower
, unsigned upper
, unsigned & len
)
4628 // X.691 section 10.9
4630 if (upper
!= INT_MAX
&& !aligned
) {
4631 if (upper
- lower
> 0xffff)
4632 return -1; // 10.9.4.2 unsupported
4634 if (!MultiBitDecode(CountBits(upper
- lower
+ 1), base
))
4636 return lower
+ base
; // 10.9.4.1
4639 if (upper
< 65536) // 10.9.3.3
4640 return UnsignedDecode(lower
, upper
, len
);
4647 if (SingleBitDecode() == 0)
4648 return MultiBitDecode(7, len
) ? 0 : -1; // 10.9.3.6
4650 if (SingleBitDecode() == 0)
4651 return MultiBitDecode(14, len
) ? 0 : -1; // 10.9.3.7
4653 return -1; // 10.9.3.8 unsupported
4657 void PPER_Stream::LengthEncode(unsigned len
, unsigned lower
, unsigned upper
)
4659 // X.691 section 10.9
4661 if (upper
!= INT_MAX
&& !aligned
) {
4662 PAssert(upper
- lower
< 0x10000, PUnimplementedFunction
); // 10.9.4.2 unsupperted
4663 MultiBitEncode(len
- lower
, CountBits(upper
- lower
+ 1)); // 10.9.4.1
4667 if (upper
< 65536) { // 10.9.3.3
4668 UnsignedEncode(len
, lower
, upper
);
4675 MultiBitEncode(len
, 8); // 10.9.3.6
4679 SingleBitEncode(TRUE
);
4682 MultiBitEncode(len
, 15); // 10.9.3.7
4686 SingleBitEncode(TRUE
);
4687 PAssert(len
< 0x2000, PUnimplementedFunction
); // 10.9.3.8 unsupported
4691 void PPER_Stream::AnyTypeEncode(const PASN_Object
* value
)
4693 PPER_Stream substream
;
4696 value
->Encode(substream
);
4698 if (substream
.GetPosition() == 0) // Make sure extension has at least one
4699 substream
.SingleBitEncode(FALSE
); // byte in its ANY type encoding.
4701 substream
.CompleteEncoding();
4703 PINDEX nBytes
= substream
.GetSize();
4704 LengthEncode(nBytes
, 0, INT_MAX
);
4705 BlockEncode(substream
.GetPointer(), nBytes
);