4 * Abstract Syntax Notation 1 Encoding Rules
6 * Portable Windows Library
9 * Revision 1.9 2004/03/23 04:53:57 csoutheren
10 * Fixed problem with incorrect encoding of ASN NULL under some circumstances
11 * Thanks to Ed Day of Objective Systems
13 * Revision 1.8 2004/01/17 17:43:42 csoutheren
14 * Fixed problem with the upper limit on various constrained types not being correctly enforced
16 * Revision 1.7 2004/01/17 09:23:43 csoutheren
17 * Fixed problem with the upper limit on constrained unsigned integers not being correctly enforced
19 * Revision 1.6 2003/12/14 10:21:29 rjongbloed
20 * Fixed bug in length incorrectlty decoded from ASN and (apparently) rare circumstances. Thanks pangxg@hotmail.com.
21 * Cleaned up return values to be BOOL rather than int for some functions.
23 * Revision 1.5 2003/12/03 03:50:03 csoutheren
24 * Reversed last change as it broke decoding in some circumstances
29 ///////////////////////////////////////////////////////////////////////
31 BOOL
PPER_Stream::NullDecode(PASN_Null
&)
37 void PPER_Stream::NullEncode(const PASN_Null
&)
41 ///////////////////////////////////////////////////////////////////////
43 BOOL
PASN_ConstrainedObject::ConstrainedLengthDecode(PPER_Stream
& strm
, unsigned & length
)
45 // The execution order is important in the following. The SingleBitDecode() function
46 // must be called if extendable is TRUE, no matter what.
47 if ((extendable
&& strm
.SingleBitDecode()) || constraint
== Unconstrained
)
48 return strm
.LengthDecode(0, INT_MAX
, length
);
50 return strm
.LengthDecode(lowerLimit
, upperLimit
, length
);
54 void PASN_ConstrainedObject::ConstrainedLengthEncode(PPER_Stream
& strm
, unsigned length
) const
56 if (ConstraintEncode(strm
, length
)) // 26.4
57 strm
.LengthEncode(length
, 0, INT_MAX
);
59 strm
.LengthEncode(length
, lowerLimit
, upperLimit
);
63 BOOL
PASN_ConstrainedObject::ConstraintEncode(PPER_Stream
& strm
, unsigned value
) const
66 return constraint
!= FixedConstraint
;
68 BOOL needsExtending
= value
> upperLimit
;
70 if (!needsExtending
) {
72 if ((int)value
< lowerLimit
)
73 needsExtending
= TRUE
;
76 if (value
< (unsigned)lowerLimit
)
77 needsExtending
= TRUE
;
81 strm
.SingleBitEncode(needsExtending
);
83 return needsExtending
;
86 ///////////////////////////////////////////////////////////////////////
88 BOOL
PPER_Stream::BooleanDecode(PASN_Boolean
& value
)
94 value
= (BOOL
)SingleBitDecode();
99 void PPER_Stream::BooleanEncode(const PASN_Boolean
& value
)
102 SingleBitEncode((BOOL
)value
);
105 BOOL
PPER_Stream::IntegerDecode(PASN_Integer
& value
)
107 return value
.DecodePER(*this);
111 void PPER_Stream::IntegerEncode(const PASN_Integer
& value
)
113 value
.EncodePER(*this);
116 ///////////////////////////////////////////////////////////////////////
118 BOOL
PASN_Integer::DecodePER(PPER_Stream
& strm
)
122 switch (constraint
) {
123 case FixedConstraint
: // 12.2.1 & 12.2.2
126 case ExtendableConstraint
:
127 if (!strm
.SingleBitDecode()) // 12.1
129 // Fall into default case for unconstrained or partially constrained
133 if (!strm
.LengthDecode(0, INT_MAX
, len
))
137 if (!strm
.MultiBitDecode(len
, value
))
142 else if ((value
&(1<<(len
-1))) != 0) // Negative
143 value
|= UINT_MAX
<< len
; // Sign extend
147 if ((unsigned)lowerLimit
!= upperLimit
) // 12.2.2
148 return strm
.UnsignedDecode(lowerLimit
, upperLimit
, value
); // which devolves to 10.5
156 void PASN_Integer::EncodePER(PPER_Stream
& strm
) const
161 if (ConstraintEncode(strm
, (int)value
)) {
163 unsigned adjusted_value
= value
- lowerLimit
;
165 PINDEX nBits
= 1; // Allow for sign bit
167 nBits
= CountBits(adjusted_value
+1);
168 else if ((int)adjusted_value
> 0)
169 nBits
+= CountBits(adjusted_value
+1);
171 nBits
+= CountBits(-(int)adjusted_value
+1);
173 // Round up to nearest number of whole octets
174 PINDEX nBytes
= (nBits
+7)/8;
175 strm
.LengthEncode(nBytes
, 0, INT_MAX
);
176 strm
.MultiBitEncode(adjusted_value
, nBytes
*8);
180 if ((unsigned)lowerLimit
== upperLimit
) // 12.2.1
183 // 12.2.2 which devolves to 10.5
184 strm
.UnsignedEncode(value
, lowerLimit
, upperLimit
);
187 ///////////////////////////////////////////////////////////////////////
189 BOOL
PPER_Stream::EnumerationDecode(PASN_Enumeration
& value
)
191 return value
.DecodePER(*this);
195 void PPER_Stream::EnumerationEncode(const PASN_Enumeration
& value
)
197 value
.EncodePER(*this);
201 BOOL
PASN_Enumeration::DecodePER(PPER_Stream
& strm
)
205 if (extendable
) { // 13.3
206 if (strm
.SingleBitDecode()) {
208 return strm
.SmallUnsignedDecode(len
) &&
210 strm
.UnsignedDecode(0, len
-1, value
);
214 return strm
.UnsignedDecode(0, maxEnumValue
, value
); // 13.2
218 void PASN_Enumeration::EncodePER(PPER_Stream
& strm
) const
222 if (extendable
) { // 13.3
223 BOOL extended
= value
> maxEnumValue
;
224 strm
.SingleBitEncode(extended
);
226 strm
.SmallUnsignedEncode(1+value
);
227 strm
.UnsignedEncode(value
, 0, value
);
232 strm
.UnsignedEncode(value
, 0, maxEnumValue
); // 13.2
235 ///////////////////////////////////////////////////////////////////////
237 BOOL
PPER_Stream::RealDecode(PASN_Real
&)
245 if (!MultiBitDecode(8, len
))
248 PAssertAlways(PUnimplementedFunction
);
254 void PPER_Stream::RealEncode(const PASN_Real
&)
258 MultiBitEncode(0, 8);
259 PAssertAlways(PUnimplementedFunction
);
260 MultiBitEncode(0, 8);
263 ///////////////////////////////////////////////////////////////////////
265 BOOL
PPER_Stream::ObjectIdDecode(PASN_ObjectId
& value
)
270 if (!LengthDecode(0, 255, dataLen
))
274 return value
.CommonDecode(*this, dataLen
);
278 void PPER_Stream::ObjectIdEncode(const PASN_ObjectId
& value
)
283 value
.CommonEncode(eObjId
);
284 LengthEncode(eObjId
.GetSize(), 0, 255);
285 BlockEncode(eObjId
, eObjId
.GetSize());
288 ///////////////////////////////////////////////////////////////////////
290 BOOL
PASN_BitString::DecodeSequenceExtensionBitmap(PPER_Stream
& strm
)
292 if (!strm
.SmallUnsignedDecode(totalBits
))
297 if (!SetSize(totalBits
))
300 if (totalBits
> strm
.GetBitsLeft())
306 unsigned bitsLeft
= totalBits
;
307 while (bitsLeft
>= 8) {
308 if (!strm
.MultiBitDecode(8, theBits
))
310 bitData
[idx
++] = (BYTE
)theBits
;
315 if (!strm
.MultiBitDecode(bitsLeft
, theBits
))
317 bitData
[idx
] = (BYTE
)(theBits
<< (8-bitsLeft
));
324 void PASN_BitString::EncodeSequenceExtensionBitmap(PPER_Stream
& strm
) const
326 PAssert(totalBits
> 0, PLogicError
);
328 unsigned bitsLeft
= totalBits
;
329 while (bitsLeft
> 1 && !(*this)[bitsLeft
-1])
332 strm
.SmallUnsignedEncode(bitsLeft
-1);
335 while (bitsLeft
>= 8) {
336 strm
.MultiBitEncode(bitData
[idx
++], 8);
341 strm
.MultiBitEncode(bitData
[idx
] >> (8 - bitsLeft
), bitsLeft
);
345 BOOL
PASN_BitString::DecodePER(PPER_Stream
& strm
)
349 if (!ConstrainedLengthDecode(strm
, totalBits
))
352 if (!SetSize(totalBits
))
358 if (totalBits
> strm
.GetBitsLeft())
361 if (totalBits
> 16) {
362 unsigned nBytes
= (totalBits
+7)/8;
363 return strm
.BlockDecode(bitData
.GetPointer(), nBytes
) == nBytes
; // 15.9
367 if (totalBits
<= 8) {
368 if (!strm
.MultiBitDecode(totalBits
, theBits
))
371 bitData
[0] = (BYTE
)(theBits
<< (8-totalBits
));
374 if (!strm
.MultiBitDecode(8, theBits
))
377 bitData
[0] = (BYTE
)theBits
;
379 if (!strm
.MultiBitDecode(totalBits
-8, theBits
))
382 bitData
[1] = (BYTE
)(theBits
<< (16-totalBits
));
389 void PASN_BitString::EncodePER(PPER_Stream
& strm
) const
393 ConstrainedLengthEncode(strm
, totalBits
);
399 strm
.BlockEncode(bitData
, (totalBits
+7)/8); // 15.9
400 else if (totalBits
<= 8) // 15.8
401 strm
.MultiBitEncode(bitData
[0] >> (8 - totalBits
), totalBits
);
403 strm
.MultiBitEncode(bitData
[0], 8);
404 strm
.MultiBitEncode(bitData
[1] >> (16 - totalBits
), totalBits
-8);
408 ///////////////////////////////////////////////////////////////////////
410 BOOL
PPER_Stream::BitStringDecode(PASN_BitString
& value
)
412 return value
.DecodePER(*this);
416 void PPER_Stream::BitStringEncode(const PASN_BitString
& value
)
418 value
.EncodePER(*this);
421 ///////////////////////////////////////////////////////////////////////
423 BOOL
PASN_OctetString::DecodeSubType(PASN_Object
& obj
) const
425 PPER_Stream stream
= GetValue();
426 return obj
.Decode(stream
);
430 void PASN_OctetString::EncodeSubType(const PASN_Object
& obj
)
434 stream
.CompleteEncoding();
438 BOOL
PASN_OctetString::DecodePER(PPER_Stream
& strm
)
443 if (!ConstrainedLengthDecode(strm
, nBytes
))
446 if (!SetSize(nBytes
)) // 16.5
449 if ((int)upperLimit
!= lowerLimit
)
450 return strm
.BlockDecode(value
.GetPointer(), nBytes
) == nBytes
;
458 if (!strm
.MultiBitDecode(8, theBits
))
460 value
[0] = (BYTE
)theBits
;
464 if (!strm
.MultiBitDecode(8, theBits
))
466 value
[0] = (BYTE
)theBits
;
467 if (!strm
.MultiBitDecode(8, theBits
))
469 value
[1] = (BYTE
)theBits
;
473 return strm
.BlockDecode(value
.GetPointer(), nBytes
) == nBytes
;
480 void PASN_OctetString::EncodePER(PPER_Stream
& strm
) const
484 PINDEX nBytes
= value
.GetSize();
485 ConstrainedLengthEncode(strm
, nBytes
);
487 if ((int)upperLimit
!= lowerLimit
) {
488 strm
.BlockEncode(value
, nBytes
);
497 strm
.MultiBitEncode(value
[0], 8);
501 strm
.MultiBitEncode(value
[0], 8);
502 strm
.MultiBitEncode(value
[1], 8);
506 strm
.BlockEncode(value
, nBytes
);
510 BOOL
PPER_Stream::OctetStringDecode(PASN_OctetString
& value
)
512 return value
.DecodePER(*this);
516 void PPER_Stream::OctetStringEncode(const PASN_OctetString
& value
)
518 value
.EncodePER(*this);
521 ///////////////////////////////////////////////////////////////////////
523 BOOL
PASN_ConstrainedString::DecodePER(PPER_Stream
& strm
)
528 if (!ConstrainedLengthDecode(strm
, len
))
531 if (len
== 0) { // 10.9.3.3
537 unsigned nBits
= strm
.IsAligned() ? charSetAlignedBits
: charSetUnalignedBits
;
538 unsigned totalBits
= upperLimit
*nBits
;
540 if (constraint
== Unconstrained
||
541 (lowerLimit
== (int)upperLimit
? (totalBits
> 16) : (totalBits
>= 16))) {
543 return strm
.BlockDecode((BYTE
*)value
.GetPointer(len
+1), len
) == len
;
544 if (strm
.IsAligned())
548 if ((PINDEX
)len
> MaximumStringSize
)
551 if (!value
.SetSize(len
+1))
555 for (i
= 0; i
< (PINDEX
)len
; i
++) {
557 if (!strm
.MultiBitDecode(nBits
, theBits
))
559 if (nBits
>= canonicalSetBits
&& canonicalSetBits
> 4)
560 value
[i
] = (char)theBits
;
562 value
[i
] = characterSet
[(PINDEX
)theBits
];
570 void PASN_ConstrainedString::EncodePER(PPER_Stream
& strm
) const
574 PINDEX len
= value
.GetSize()-1;
575 ConstrainedLengthEncode(strm
, len
);
577 if (len
== 0) // 10.9.3.3
580 unsigned nBits
= strm
.IsAligned() ? charSetAlignedBits
: charSetUnalignedBits
;
581 unsigned totalBits
= upperLimit
*nBits
;
583 if (constraint
== Unconstrained
||
584 (lowerLimit
== (int)upperLimit
? (totalBits
> 16) : (totalBits
>= 16))) {
587 strm
.BlockEncode((const BYTE
*)(const char *)value
, len
);
590 if (strm
.IsAligned())
594 for (PINDEX i
= 0; i
< len
; i
++) {
595 if (nBits
>= canonicalSetBits
&& canonicalSetBits
> 4)
596 strm
.MultiBitEncode(value
[i
], nBits
);
598 const void * ptr
= memchr(characterSet
, value
[i
], characterSet
.GetSize());
601 pos
= ((const char *)ptr
- (const char *)characterSet
);
602 strm
.MultiBitEncode(pos
, nBits
);
607 ///////////////////////////////////////////////////////////////////////
609 BOOL
PPER_Stream::ConstrainedStringDecode(PASN_ConstrainedString
& value
)
611 return value
.DecodePER(*this);
615 void PPER_Stream::ConstrainedStringEncode(const PASN_ConstrainedString
& value
)
617 value
.EncodePER(*this);
620 ///////////////////////////////////////////////////////////////////////
622 BOOL
PASN_BMPString::DecodePER(PPER_Stream
& strm
)
627 if (!ConstrainedLengthDecode(strm
, len
))
630 if ((PINDEX
)len
> MaximumStringSize
)
633 if (!value
.SetSize(len
))
636 PINDEX nBits
= strm
.IsAligned() ? charSetAlignedBits
: charSetUnalignedBits
;
638 if ((constraint
== Unconstrained
|| upperLimit
*nBits
> 16) && strm
.IsAligned())
641 for (PINDEX i
= 0; i
< (PINDEX
)len
; i
++) {
643 if (!strm
.MultiBitDecode(nBits
, theBits
))
645 if (characterSet
.IsEmpty())
646 value
[i
] = (WORD
)(theBits
+ firstChar
);
648 value
[i
] = characterSet
[(PINDEX
)theBits
];
655 void PASN_BMPString::EncodePER(PPER_Stream
& strm
) const
659 PINDEX len
= value
.GetSize();
660 ConstrainedLengthEncode(strm
, len
);
662 PINDEX nBits
= strm
.IsAligned() ? charSetAlignedBits
: charSetUnalignedBits
;
664 if ((constraint
== Unconstrained
|| upperLimit
*nBits
> 16) && strm
.IsAligned())
667 for (PINDEX i
= 0; i
< len
; i
++) {
668 if (characterSet
.IsEmpty())
669 strm
.MultiBitEncode(value
[i
] - firstChar
, nBits
);
671 for (PINDEX pos
= 0; pos
< characterSet
.GetSize(); pos
++) {
672 if (characterSet
[pos
] == value
[i
]) {
673 strm
.MultiBitEncode(pos
, nBits
);
682 BOOL
PPER_Stream::BMPStringDecode(PASN_BMPString
& value
)
684 return value
.DecodePER(*this);
688 void PPER_Stream::BMPStringEncode(const PASN_BMPString
& value
)
690 value
.EncodePER(*this);
693 ///////////////////////////////////////////////////////////////////////
695 BOOL
PASN_Choice::DecodePER(PPER_Stream
& strm
)
705 if (strm
.SingleBitDecode()) {
706 if (!strm
.SmallUnsignedDecode(tag
))
712 if (!strm
.LengthDecode(0, INT_MAX
, len
))
716 if (CreateObject()) {
717 PINDEX nextPos
= strm
.GetPosition() + len
;
718 ok
= choice
->Decode(strm
);
719 strm
.SetPosition(nextPos
);
722 PASN_OctetString
* open_type
= new PASN_OctetString
;
723 open_type
->SetConstraints(PASN_ConstrainedObject::FixedConstraint
, len
);
724 ok
= open_type
->Decode(strm
);
725 if (open_type
->GetSize() > 0)
739 if (!strm
.UnsignedDecode(0, numChoices
-1, tag
))
743 return CreateObject() && choice
->Decode(strm
);
747 void PASN_Choice::EncodePER(PPER_Stream
& strm
) const
749 PAssert(CheckCreate(), PLogicError
);
752 BOOL extended
= tag
>= numChoices
;
753 strm
.SingleBitEncode(extended
);
755 strm
.SmallUnsignedEncode(tag
- numChoices
);
756 strm
.AnyTypeEncode(choice
);
762 strm
.UnsignedEncode(tag
, 0, numChoices
-1);
764 choice
->Encode(strm
);
768 BOOL
PPER_Stream::ChoiceDecode(PASN_Choice
& value
)
770 return value
.DecodePER(*this);
774 void PPER_Stream::ChoiceEncode(const PASN_Choice
& value
)
776 value
.EncodePER(*this);
779 ///////////////////////////////////////////////////////////////////////
781 BOOL
PASN_Sequence::PreambleDecodePER(PPER_Stream
& strm
)
788 totalExtensions
= strm
.SingleBitDecode() ? -1 : 0; // 18.1
792 return optionMap
.Decode(strm
); // 18.2
796 void PASN_Sequence::PreambleEncodePER(PPER_Stream
& strm
) const
801 BOOL hasExtensions
= FALSE
;
802 for (unsigned i
= 0; i
< extensionMap
.GetSize(); i
++) {
803 if (extensionMap
[i
]) {
804 hasExtensions
= TRUE
;
808 strm
.SingleBitEncode(hasExtensions
); // 18.1
809 ((PASN_Sequence
*)this)->totalExtensions
= hasExtensions
? -1 : 0;
811 optionMap
.Encode(strm
); // 18.2
815 BOOL
PASN_Sequence::NoExtensionsToDecode(PPER_Stream
& strm
)
817 if (totalExtensions
== 0)
820 if (totalExtensions
< 0) {
821 if (!extensionMap
.DecodeSequenceExtensionBitmap(strm
))
823 totalExtensions
= extensionMap
.GetSize();
830 BOOL
PASN_Sequence::NoExtensionsToEncode(PPER_Stream
& strm
)
832 if (totalExtensions
== 0)
835 if (totalExtensions
< 0) {
836 totalExtensions
= extensionMap
.GetSize();
837 extensionMap
.EncodeSequenceExtensionBitmap(strm
);
844 BOOL
PASN_Sequence::KnownExtensionDecodePER(PPER_Stream
& strm
, PINDEX fld
, PASN_Object
& field
)
846 if (NoExtensionsToDecode(strm
))
849 if (!extensionMap
[fld
-optionMap
.GetSize()])
853 if (!strm
.LengthDecode(0, INT_MAX
, len
))
856 PINDEX nextExtensionPosition
= strm
.GetPosition() + len
;
857 BOOL ok
= field
.Decode(strm
);
858 strm
.SetPosition(nextExtensionPosition
);
863 void PASN_Sequence::KnownExtensionEncodePER(PPER_Stream
& strm
, PINDEX fld
, const PASN_Object
& field
) const
865 if (((PASN_Sequence
*)this)->NoExtensionsToEncode(strm
))
868 if (!extensionMap
[fld
-optionMap
.GetSize()])
871 strm
.AnyTypeEncode(&field
);
875 BOOL
PASN_Sequence::UnknownExtensionsDecodePER(PPER_Stream
& strm
)
877 if (NoExtensionsToDecode(strm
))
880 if (totalExtensions
<= knownExtensions
)
881 return TRUE
; // Already read them
883 PINDEX unknownCount
= totalExtensions
- knownExtensions
;
884 if (fields
.GetSize() >= unknownCount
)
885 return TRUE
; // Already read them
887 if (unknownCount
> MaximumArraySize
)
890 if (!fields
.SetSize(unknownCount
))
894 for (i
= 0; i
< fields
.GetSize(); i
++)
895 fields
.SetAt(i
, new PASN_OctetString
);
897 for (i
= knownExtensions
; i
< (PINDEX
)extensionMap
.GetSize(); i
++) {
899 if (!fields
[i
-knownExtensions
].Decode(strm
))
907 void PASN_Sequence::UnknownExtensionsEncodePER(PPER_Stream
& strm
) const
909 if (((PASN_Sequence
*)this)->NoExtensionsToEncode(strm
))
913 for (i
= knownExtensions
; i
< totalExtensions
; i
++) {
914 if (extensionMap
[i
]) {
915 PINDEX f
= i
- knownExtensions
;
916 if (f
< fields
.GetSize())
917 fields
[f
].Encode(strm
);
919 PASN_OctetString dummy
;
927 BOOL
PPER_Stream::SequencePreambleDecode(PASN_Sequence
& seq
)
929 return seq
.PreambleDecodePER(*this);
933 void PPER_Stream::SequencePreambleEncode(const PASN_Sequence
& seq
)
935 seq
.PreambleEncodePER(*this);
939 BOOL
PPER_Stream::SequenceKnownDecode(PASN_Sequence
& seq
, PINDEX fld
, PASN_Object
& field
)
941 return seq
.KnownExtensionDecodePER(*this, fld
, field
);
945 void PPER_Stream::SequenceKnownEncode(const PASN_Sequence
& seq
, PINDEX fld
, const PASN_Object
& field
)
947 seq
.KnownExtensionEncodePER(*this, fld
, field
);
951 BOOL
PPER_Stream::SequenceUnknownDecode(PASN_Sequence
& seq
)
953 return seq
.UnknownExtensionsDecodePER(*this);
957 void PPER_Stream::SequenceUnknownEncode(const PASN_Sequence
& seq
)
959 seq
.UnknownExtensionsEncodePER(*this);
962 ///////////////////////////////////////////////////////////////////////
964 BOOL
PPER_Stream::ArrayDecode(PASN_Array
& array
)
969 if (!array
.ConstrainedLengthDecode(*this, size
))
972 if (!array
.SetSize(size
))
975 for (PINDEX i
= 0; i
< (PINDEX
)size
; i
++) {
976 if (!array
[i
].Decode(*this))
984 void PPER_Stream::ArrayEncode(const PASN_Array
& array
)
986 PINDEX size
= array
.GetSize();
987 array
.ConstrainedLengthEncode(*this, size
);
988 for (PINDEX i
= 0; i
< size
; i
++)
989 array
[i
].Encode(*this);
992 ///////////////////////////////////////////////////////////////////////
994 PPER_Stream::PPER_Stream(BOOL alignment
)
1000 PPER_Stream::PPER_Stream(const PBYTEArray
& bytes
, BOOL alignment
)
1001 : PASN_Stream(bytes
)
1003 aligned
= alignment
;
1007 PPER_Stream::PPER_Stream(const BYTE
* buf
, PINDEX size
, BOOL alignment
)
1008 : PASN_Stream(buf
, size
)
1010 aligned
= alignment
;
1014 PPER_Stream
& PPER_Stream::operator=(const PBYTEArray
& bytes
)
1016 PBYTEArray::operator=(bytes
);
1023 unsigned PPER_Stream::GetBitsLeft() const
1025 return (GetSize() - byteOffset
)*8 - (8 - bitOffset
);
1029 BOOL
PPER_Stream::Read(PChannel
& chan
)
1034 // Get RFC1006 TPKT length
1036 if (!chan
.ReadBlock(tpkt
, sizeof(tpkt
)))
1039 if (tpkt
[0] != 3) // Only support version 3
1042 PINDEX data_len
= ((tpkt
[2] << 8)|tpkt
[3]) - 4;
1044 return chan
.ReadBlock(GetPointer(data_len
), data_len
);
1048 BOOL
PPER_Stream::Write(PChannel
& chan
)
1052 PINDEX size
= GetSize();
1054 // Put RFC1006 TPKT length
1056 tpkt
[0] = 3; // Version 3
1059 PINDEX len
= size
+ sizeof(tpkt
);
1060 tpkt
[2] = (BYTE
)(len
>> 8);
1061 tpkt
[3] = (BYTE
)len
;
1063 return chan
.Write(tpkt
, sizeof(tpkt
)) && chan
.Write(theArray
, size
);
1067 BOOL
PPER_Stream::SingleBitDecode()
1069 if ((GetSize() - byteOffset
)*8 - (8 - bitOffset
) == 0)
1073 BOOL value
= (theArray
[byteOffset
] & (1 << bitOffset
)) != 0;
1075 if (bitOffset
== 0) {
1084 void PPER_Stream::SingleBitEncode(BOOL value
)
1086 PAssert(byteOffset
!= P_MAX_INDEX
, PLogicError
);
1088 if (byteOffset
>= GetSize())
1089 SetSize(byteOffset
+10);
1094 theArray
[byteOffset
] |= 1 << bitOffset
;
1101 BOOL
PPER_Stream::MultiBitDecode(unsigned nBits
, unsigned & value
)
1103 if (nBits
> sizeof(value
)*8)
1106 unsigned bitsLeft
= (GetSize() - byteOffset
)*8 - (8 - bitOffset
);
1107 if (nBits
> bitsLeft
)
1115 if (nBits
< bitOffset
) {
1117 value
= (theArray
[byteOffset
] >> bitOffset
) & ((1 << nBits
) - 1);
1121 value
= theArray
[byteOffset
] & ((1 << bitOffset
) - 1);
1126 while (nBits
>= 8) {
1127 value
= (value
<< 8) | (BYTE
)theArray
[byteOffset
];
1133 bitOffset
= 8 - nBits
;
1134 value
= (value
<< nBits
) | ((BYTE
)theArray
[byteOffset
] >> bitOffset
);
1141 void PPER_Stream::MultiBitEncode(unsigned value
, unsigned nBits
)
1143 PAssert(byteOffset
!= P_MAX_INDEX
, PLogicError
);
1148 if (byteOffset
+nBits
/8+1 >= (unsigned)GetSize())
1149 SetSize(byteOffset
+10);
1151 // Make sure value is in bounds of bit available.
1152 if (nBits
< sizeof(int)*8)
1153 value
&= ((1 << nBits
) - 1);
1155 if (nBits
< bitOffset
) {
1157 theArray
[byteOffset
] |= value
<< bitOffset
;
1162 theArray
[byteOffset
] |= (BYTE
)(value
>> nBits
);
1166 while (nBits
>= 8) {
1168 theArray
[byteOffset
] = (BYTE
)(value
>> nBits
);
1173 bitOffset
= 8 - nBits
;
1174 theArray
[byteOffset
] |= (BYTE
)((value
& ((1 << nBits
)-1)) << bitOffset
);
1179 BOOL
PPER_Stream::SmallUnsignedDecode(unsigned & value
)
1181 // X.691 Section 10.6
1183 if (!SingleBitDecode())
1184 return MultiBitDecode(6, value
); // 10.6.1
1187 if (!LengthDecode(0, INT_MAX
, len
)) // 10.6.2
1191 return MultiBitDecode(len
*8, value
);
1195 void PPER_Stream::SmallUnsignedEncode(unsigned value
)
1198 MultiBitEncode(value
, 7);
1202 SingleBitEncode(1); // 10.6.2
1207 else if (value
< 65536)
1209 else if (value
< 0x1000000)
1211 LengthEncode(len
, 0, INT_MAX
); // 10.9
1213 MultiBitEncode(value
, len
*8);
1217 BOOL
PPER_Stream::UnsignedDecode(unsigned lower
, unsigned upper
, unsigned & value
)
1219 // X.691 section 10.5
1221 if (lower
== upper
) { // 10.5.4
1229 unsigned range
= (upper
- lower
) + 1;
1230 unsigned nBits
= CountBits(range
);
1232 if (aligned
&& (range
== 0 || range
> 255)) { // not 10.5.6 and not 10.5.7.1
1233 if (nBits
> 16) { // not 10.5.7.4
1234 if (!LengthDecode(1, (nBits
+7)/8, nBits
)) // 12.2.6
1238 else if (nBits
> 8) // not 10.5.7.2
1239 nBits
= 16; // 10.5.7.3
1240 ByteAlign(); // 10.7.5.2 - 10.7.5.4
1243 if (!MultiBitDecode(nBits
, value
))
1248 // clamp value to upper limit
1256 void PPER_Stream::UnsignedEncode(int value
, unsigned lower
, unsigned upper
)
1258 // X.691 section 10.5
1260 if (lower
== upper
) // 10.5.4
1263 unsigned range
= (upper
- lower
) + 1;
1264 PINDEX nBits
= CountBits(range
);
1266 if ((unsigned)value
< lower
)
1271 if (aligned
&& (range
== 0 || range
> 255)) { // not 10.5.6 and not 10.5.7.1
1272 if (nBits
> 16) { // not 10.5.7.4
1273 int numBytes
= value
== 0 ? 1 : (((CountBits(value
+ 1))+7)/8);
1274 LengthEncode(numBytes
, 1, (nBits
+7)/8); // 12.2.6
1277 else if (nBits
> 8) // not 10.5.7.2
1278 nBits
= 16; // 10.5.7.3
1279 ByteAlign(); // 10.7.5.2 - 10.7.5.4
1282 MultiBitEncode(value
, nBits
);
1286 BOOL
PPER_Stream::LengthDecode(unsigned lower
, unsigned upper
, unsigned & len
)
1288 // X.691 section 10.9
1290 if (upper
!= INT_MAX
&& !aligned
) {
1291 if (upper
- lower
> 0xffff)
1292 return FALSE
; // 10.9.4.2 unsupported
1294 if (!MultiBitDecode(CountBits(upper
- lower
+ 1), base
))
1296 len
= lower
+ base
; // 10.9.4.1
1298 // clamp value to upper limit
1305 if (upper
< 65536) // 10.9.3.3
1306 return UnsignedDecode(lower
, upper
, len
);
1313 if (SingleBitDecode() == 0) {
1314 if (!MultiBitDecode(7, len
)) // 10.9.3.6
1315 return FALSE
; // 10.9.3.8 unsupported
1318 else if (SingleBitDecode() == 0) {
1319 if (!MultiBitDecode(14, len
)) // 10.9.3.7
1320 return FALSE
; // 10.9.3.8 unsupported
1323 // clamp value to upper limit
1331 void PPER_Stream::LengthEncode(unsigned len
, unsigned lower
, unsigned upper
)
1333 // X.691 section 10.9
1335 if (upper
!= INT_MAX
&& !aligned
) {
1336 PAssert(upper
- lower
< 0x10000, PUnimplementedFunction
); // 10.9.4.2 unsupperted
1337 MultiBitEncode(len
- lower
, CountBits(upper
- lower
+ 1)); // 10.9.4.1
1341 if (upper
< 65536) { // 10.9.3.3
1342 UnsignedEncode(len
, lower
, upper
);
1349 MultiBitEncode(len
, 8); // 10.9.3.6
1353 SingleBitEncode(TRUE
);
1356 MultiBitEncode(len
, 15); // 10.9.3.7
1360 SingleBitEncode(TRUE
);
1361 PAssertAlways(PUnimplementedFunction
); // 10.9.3.8 unsupported
1365 void PPER_Stream::AnyTypeEncode(const PASN_Object
* value
)
1367 PPER_Stream substream
;
1370 value
->Encode(substream
);
1372 substream
.CompleteEncoding();
1374 PINDEX nBytes
= substream
.GetSize();
1376 const BYTE null
[1] = { 0 };
1377 nBytes
= sizeof(null
);
1378 substream
= PBYTEArray(null
, nBytes
, FALSE
);
1381 LengthEncode(nBytes
, 0, INT_MAX
);
1382 BlockEncode(substream
.GetPointer(), nBytes
);
1385 ///////////////////////////////////////////////////////////////////////