4 * Abstract Syntax Notation 1 Encoding Rules
6 * Portable Windows Library
9 * Revision 1.10 2004/07/11 12:33:47 csoutheren
10 * Added guards against illegal PDU values causing crashes
12 * Revision 1.9 2004/03/23 04:53:57 csoutheren
13 * Fixed problem with incorrect encoding of ASN NULL under some circumstances
14 * Thanks to Ed Day of Objective Systems
16 * Revision 1.8 2004/01/17 17:43:42 csoutheren
17 * Fixed problem with the upper limit on various constrained types not being correctly enforced
19 * Revision 1.7 2004/01/17 09:23:43 csoutheren
20 * Fixed problem with the upper limit on constrained unsigned integers not being correctly enforced
22 * Revision 1.6 2003/12/14 10:21:29 rjongbloed
23 * Fixed bug in length incorrectlty decoded from ASN and (apparently) rare circumstances. Thanks pangxg@hotmail.com.
24 * Cleaned up return values to be BOOL rather than int for some functions.
26 * Revision 1.5 2003/12/03 03:50:03 csoutheren
27 * Reversed last change as it broke decoding in some circumstances
32 ///////////////////////////////////////////////////////////////////////
34 BOOL
PPER_Stream::NullDecode(PASN_Null
&)
40 void PPER_Stream::NullEncode(const PASN_Null
&)
44 ///////////////////////////////////////////////////////////////////////
46 BOOL
PASN_ConstrainedObject::ConstrainedLengthDecode(PPER_Stream
& strm
, unsigned & length
)
48 // The execution order is important in the following. The SingleBitDecode() function
49 // must be called if extendable is TRUE, no matter what.
50 if ((extendable
&& strm
.SingleBitDecode()) || constraint
== Unconstrained
)
51 return strm
.LengthDecode(0, INT_MAX
, length
);
53 return strm
.LengthDecode(lowerLimit
, upperLimit
, length
);
57 void PASN_ConstrainedObject::ConstrainedLengthEncode(PPER_Stream
& strm
, unsigned length
) const
59 if (ConstraintEncode(strm
, length
)) // 26.4
60 strm
.LengthEncode(length
, 0, INT_MAX
);
62 strm
.LengthEncode(length
, lowerLimit
, upperLimit
);
66 BOOL
PASN_ConstrainedObject::ConstraintEncode(PPER_Stream
& strm
, unsigned value
) const
69 return constraint
!= FixedConstraint
;
71 BOOL needsExtending
= value
> upperLimit
;
73 if (!needsExtending
) {
75 if ((int)value
< lowerLimit
)
76 needsExtending
= TRUE
;
79 if (value
< (unsigned)lowerLimit
)
80 needsExtending
= TRUE
;
84 strm
.SingleBitEncode(needsExtending
);
86 return needsExtending
;
89 ///////////////////////////////////////////////////////////////////////
91 BOOL
PPER_Stream::BooleanDecode(PASN_Boolean
& value
)
97 value
= (BOOL
)SingleBitDecode();
102 void PPER_Stream::BooleanEncode(const PASN_Boolean
& value
)
105 SingleBitEncode((BOOL
)value
);
108 BOOL
PPER_Stream::IntegerDecode(PASN_Integer
& value
)
110 return value
.DecodePER(*this);
114 void PPER_Stream::IntegerEncode(const PASN_Integer
& value
)
116 value
.EncodePER(*this);
119 ///////////////////////////////////////////////////////////////////////
121 BOOL
PASN_Integer::DecodePER(PPER_Stream
& strm
)
125 switch (constraint
) {
126 case FixedConstraint
: // 12.2.1 & 12.2.2
129 case ExtendableConstraint
:
130 if (!strm
.SingleBitDecode()) // 12.1
132 // Fall into default case for unconstrained or partially constrained
136 if (!strm
.LengthDecode(0, INT_MAX
, len
))
140 if (!strm
.MultiBitDecode(len
, value
))
145 else if ((value
&(1<<(len
-1))) != 0) // Negative
146 value
|= UINT_MAX
<< len
; // Sign extend
150 if ((unsigned)lowerLimit
!= upperLimit
) // 12.2.2
151 return strm
.UnsignedDecode(lowerLimit
, upperLimit
, value
); // which devolves to 10.5
159 void PASN_Integer::EncodePER(PPER_Stream
& strm
) const
164 if (ConstraintEncode(strm
, (int)value
)) {
166 unsigned adjusted_value
= value
- lowerLimit
;
168 PINDEX nBits
= 1; // Allow for sign bit
170 nBits
= CountBits(adjusted_value
+1);
171 else if ((int)adjusted_value
> 0)
172 nBits
+= CountBits(adjusted_value
+1);
174 nBits
+= CountBits(-(int)adjusted_value
+1);
176 // Round up to nearest number of whole octets
177 PINDEX nBytes
= (nBits
+7)/8;
178 strm
.LengthEncode(nBytes
, 0, INT_MAX
);
179 strm
.MultiBitEncode(adjusted_value
, nBytes
*8);
183 if ((unsigned)lowerLimit
== upperLimit
) // 12.2.1
186 // 12.2.2 which devolves to 10.5
187 strm
.UnsignedEncode(value
, lowerLimit
, upperLimit
);
190 ///////////////////////////////////////////////////////////////////////
192 BOOL
PPER_Stream::EnumerationDecode(PASN_Enumeration
& value
)
194 return value
.DecodePER(*this);
198 void PPER_Stream::EnumerationEncode(const PASN_Enumeration
& value
)
200 value
.EncodePER(*this);
204 BOOL
PASN_Enumeration::DecodePER(PPER_Stream
& strm
)
208 if (extendable
) { // 13.3
209 if (strm
.SingleBitDecode()) {
211 return strm
.SmallUnsignedDecode(len
) &&
213 strm
.UnsignedDecode(0, len
-1, value
);
217 return strm
.UnsignedDecode(0, maxEnumValue
, value
); // 13.2
221 void PASN_Enumeration::EncodePER(PPER_Stream
& strm
) const
225 if (extendable
) { // 13.3
226 BOOL extended
= value
> maxEnumValue
;
227 strm
.SingleBitEncode(extended
);
229 strm
.SmallUnsignedEncode(1+value
);
230 strm
.UnsignedEncode(value
, 0, value
);
235 strm
.UnsignedEncode(value
, 0, maxEnumValue
); // 13.2
238 ///////////////////////////////////////////////////////////////////////
240 BOOL
PPER_Stream::RealDecode(PASN_Real
&)
248 if (!MultiBitDecode(8, len
))
251 PAssertAlways(PUnimplementedFunction
);
257 void PPER_Stream::RealEncode(const PASN_Real
&)
261 MultiBitEncode(0, 8);
262 PAssertAlways(PUnimplementedFunction
);
263 MultiBitEncode(0, 8);
266 ///////////////////////////////////////////////////////////////////////
268 BOOL
PPER_Stream::ObjectIdDecode(PASN_ObjectId
& value
)
273 if (!LengthDecode(0, 255, dataLen
))
277 return value
.CommonDecode(*this, dataLen
);
281 void PPER_Stream::ObjectIdEncode(const PASN_ObjectId
& value
)
286 value
.CommonEncode(eObjId
);
287 LengthEncode(eObjId
.GetSize(), 0, 255);
288 BlockEncode(eObjId
, eObjId
.GetSize());
291 ///////////////////////////////////////////////////////////////////////
293 BOOL
PASN_BitString::DecodeSequenceExtensionBitmap(PPER_Stream
& strm
)
295 if (!strm
.SmallUnsignedDecode(totalBits
))
300 if (!SetSize(totalBits
))
303 if (totalBits
> strm
.GetBitsLeft())
309 unsigned bitsLeft
= totalBits
;
310 while (bitsLeft
>= 8) {
311 if (!strm
.MultiBitDecode(8, theBits
))
313 bitData
[idx
++] = (BYTE
)theBits
;
318 if (!strm
.MultiBitDecode(bitsLeft
, theBits
))
320 bitData
[idx
] = (BYTE
)(theBits
<< (8-bitsLeft
));
327 void PASN_BitString::EncodeSequenceExtensionBitmap(PPER_Stream
& strm
) const
329 PAssert(totalBits
> 0, PLogicError
);
331 unsigned bitsLeft
= totalBits
;
332 while (bitsLeft
> 1 && !(*this)[bitsLeft
-1])
335 strm
.SmallUnsignedEncode(bitsLeft
-1);
338 while (bitsLeft
>= 8) {
339 strm
.MultiBitEncode(bitData
[idx
++], 8);
344 strm
.MultiBitEncode(bitData
[idx
] >> (8 - bitsLeft
), bitsLeft
);
348 BOOL
PASN_BitString::DecodePER(PPER_Stream
& strm
)
352 if (!ConstrainedLengthDecode(strm
, totalBits
))
355 if (!SetSize(totalBits
))
361 if (totalBits
> strm
.GetBitsLeft())
364 if (totalBits
> 16) {
365 unsigned nBytes
= (totalBits
+7)/8;
366 return strm
.BlockDecode(bitData
.GetPointer(), nBytes
) == nBytes
; // 15.9
370 if (totalBits
<= 8) {
371 if (!strm
.MultiBitDecode(totalBits
, theBits
))
374 bitData
[0] = (BYTE
)(theBits
<< (8-totalBits
));
377 if (!strm
.MultiBitDecode(8, theBits
))
380 bitData
[0] = (BYTE
)theBits
;
382 if (!strm
.MultiBitDecode(totalBits
-8, theBits
))
385 bitData
[1] = (BYTE
)(theBits
<< (16-totalBits
));
392 void PASN_BitString::EncodePER(PPER_Stream
& strm
) const
396 ConstrainedLengthEncode(strm
, totalBits
);
402 strm
.BlockEncode(bitData
, (totalBits
+7)/8); // 15.9
403 else if (totalBits
<= 8) // 15.8
404 strm
.MultiBitEncode(bitData
[0] >> (8 - totalBits
), totalBits
);
406 strm
.MultiBitEncode(bitData
[0], 8);
407 strm
.MultiBitEncode(bitData
[1] >> (16 - totalBits
), totalBits
-8);
411 ///////////////////////////////////////////////////////////////////////
413 BOOL
PPER_Stream::BitStringDecode(PASN_BitString
& value
)
415 return value
.DecodePER(*this);
419 void PPER_Stream::BitStringEncode(const PASN_BitString
& value
)
421 value
.EncodePER(*this);
424 ///////////////////////////////////////////////////////////////////////
426 BOOL
PASN_OctetString::DecodeSubType(PASN_Object
& obj
) const
428 PPER_Stream stream
= GetValue();
429 return obj
.Decode(stream
);
433 void PASN_OctetString::EncodeSubType(const PASN_Object
& obj
)
437 stream
.CompleteEncoding();
441 BOOL
PASN_OctetString::DecodePER(PPER_Stream
& strm
)
446 if (!ConstrainedLengthDecode(strm
, nBytes
))
449 if (!SetSize(nBytes
)) // 16.5
452 if ((int)upperLimit
!= lowerLimit
)
453 return strm
.BlockDecode(value
.GetPointer(), nBytes
) == nBytes
;
461 if (!strm
.MultiBitDecode(8, theBits
))
463 value
[0] = (BYTE
)theBits
;
467 if (!strm
.MultiBitDecode(8, theBits
))
469 value
[0] = (BYTE
)theBits
;
470 if (!strm
.MultiBitDecode(8, theBits
))
472 value
[1] = (BYTE
)theBits
;
476 return strm
.BlockDecode(value
.GetPointer(), nBytes
) == nBytes
;
483 void PASN_OctetString::EncodePER(PPER_Stream
& strm
) const
487 PINDEX nBytes
= value
.GetSize();
488 ConstrainedLengthEncode(strm
, nBytes
);
490 if ((int)upperLimit
!= lowerLimit
) {
491 strm
.BlockEncode(value
, nBytes
);
500 strm
.MultiBitEncode(value
[0], 8);
504 strm
.MultiBitEncode(value
[0], 8);
505 strm
.MultiBitEncode(value
[1], 8);
509 strm
.BlockEncode(value
, nBytes
);
513 BOOL
PPER_Stream::OctetStringDecode(PASN_OctetString
& value
)
515 return value
.DecodePER(*this);
519 void PPER_Stream::OctetStringEncode(const PASN_OctetString
& value
)
521 value
.EncodePER(*this);
524 ///////////////////////////////////////////////////////////////////////
526 BOOL
PASN_ConstrainedString::DecodePER(PPER_Stream
& strm
)
531 if (!ConstrainedLengthDecode(strm
, len
))
534 if (len
== 0) { // 10.9.3.3
540 unsigned nBits
= strm
.IsAligned() ? charSetAlignedBits
: charSetUnalignedBits
;
541 unsigned totalBits
= upperLimit
*nBits
;
543 if (constraint
== Unconstrained
||
544 (lowerLimit
== (int)upperLimit
? (totalBits
> 16) : (totalBits
>= 16))) {
546 return strm
.BlockDecode((BYTE
*)value
.GetPointer(len
+1), len
) == len
;
547 if (strm
.IsAligned())
551 if ((PINDEX
)len
> MaximumStringSize
)
554 if (!value
.SetSize(len
+1))
558 for (i
= 0; i
< (PINDEX
)len
; i
++) {
560 if (!strm
.MultiBitDecode(nBits
, theBits
))
562 if (nBits
>= canonicalSetBits
&& canonicalSetBits
> 4)
563 value
[i
] = (char)theBits
;
565 value
[i
] = characterSet
[(PINDEX
)theBits
];
573 void PASN_ConstrainedString::EncodePER(PPER_Stream
& strm
) const
577 PINDEX len
= value
.GetSize()-1;
578 ConstrainedLengthEncode(strm
, len
);
580 if (len
== 0) // 10.9.3.3
583 unsigned nBits
= strm
.IsAligned() ? charSetAlignedBits
: charSetUnalignedBits
;
584 unsigned totalBits
= upperLimit
*nBits
;
586 if (constraint
== Unconstrained
||
587 (lowerLimit
== (int)upperLimit
? (totalBits
> 16) : (totalBits
>= 16))) {
590 strm
.BlockEncode((const BYTE
*)(const char *)value
, len
);
593 if (strm
.IsAligned())
597 for (PINDEX i
= 0; i
< len
; i
++) {
598 if (nBits
>= canonicalSetBits
&& canonicalSetBits
> 4)
599 strm
.MultiBitEncode(value
[i
], nBits
);
601 const void * ptr
= memchr(characterSet
, value
[i
], characterSet
.GetSize());
604 pos
= ((const char *)ptr
- (const char *)characterSet
);
605 strm
.MultiBitEncode(pos
, nBits
);
610 ///////////////////////////////////////////////////////////////////////
612 BOOL
PPER_Stream::ConstrainedStringDecode(PASN_ConstrainedString
& value
)
614 return value
.DecodePER(*this);
618 void PPER_Stream::ConstrainedStringEncode(const PASN_ConstrainedString
& value
)
620 value
.EncodePER(*this);
623 ///////////////////////////////////////////////////////////////////////
625 BOOL
PASN_BMPString::DecodePER(PPER_Stream
& strm
)
630 if (!ConstrainedLengthDecode(strm
, len
))
633 if ((PINDEX
)len
> MaximumStringSize
)
636 if (!value
.SetSize(len
))
639 PINDEX nBits
= strm
.IsAligned() ? charSetAlignedBits
: charSetUnalignedBits
;
641 if ((constraint
== Unconstrained
|| upperLimit
*nBits
> 16) && strm
.IsAligned())
644 for (PINDEX i
= 0; i
< (PINDEX
)len
; i
++) {
646 if (!strm
.MultiBitDecode(nBits
, theBits
))
648 if (characterSet
.IsEmpty())
649 value
[i
] = (WORD
)(theBits
+ firstChar
);
651 value
[i
] = characterSet
[(PINDEX
)theBits
];
658 void PASN_BMPString::EncodePER(PPER_Stream
& strm
) const
662 PINDEX len
= value
.GetSize();
663 ConstrainedLengthEncode(strm
, len
);
665 PINDEX nBits
= strm
.IsAligned() ? charSetAlignedBits
: charSetUnalignedBits
;
667 if ((constraint
== Unconstrained
|| upperLimit
*nBits
> 16) && strm
.IsAligned())
670 for (PINDEX i
= 0; i
< len
; i
++) {
671 if (characterSet
.IsEmpty())
672 strm
.MultiBitEncode(value
[i
] - firstChar
, nBits
);
674 for (PINDEX pos
= 0; pos
< characterSet
.GetSize(); pos
++) {
675 if (characterSet
[pos
] == value
[i
]) {
676 strm
.MultiBitEncode(pos
, nBits
);
685 BOOL
PPER_Stream::BMPStringDecode(PASN_BMPString
& value
)
687 return value
.DecodePER(*this);
691 void PPER_Stream::BMPStringEncode(const PASN_BMPString
& value
)
693 value
.EncodePER(*this);
696 ///////////////////////////////////////////////////////////////////////
698 BOOL
PASN_Choice::DecodePER(PPER_Stream
& strm
)
708 if (strm
.SingleBitDecode()) {
709 if (!strm
.SmallUnsignedDecode(tag
))
715 if (!strm
.LengthDecode(0, INT_MAX
, len
))
719 if (CreateObject()) {
720 PINDEX nextPos
= strm
.GetPosition() + len
;
721 ok
= choice
->Decode(strm
);
722 strm
.SetPosition(nextPos
);
725 PASN_OctetString
* open_type
= new PASN_OctetString
;
726 open_type
->SetConstraints(PASN_ConstrainedObject::FixedConstraint
, len
);
727 ok
= open_type
->Decode(strm
);
728 if (open_type
->GetSize() > 0)
742 if (!strm
.UnsignedDecode(0, numChoices
-1, tag
))
746 return CreateObject() && choice
->Decode(strm
);
750 void PASN_Choice::EncodePER(PPER_Stream
& strm
) const
752 PAssert(CheckCreate(), PLogicError
);
755 BOOL extended
= tag
>= numChoices
;
756 strm
.SingleBitEncode(extended
);
758 strm
.SmallUnsignedEncode(tag
- numChoices
);
759 strm
.AnyTypeEncode(choice
);
765 strm
.UnsignedEncode(tag
, 0, numChoices
-1);
767 choice
->Encode(strm
);
771 BOOL
PPER_Stream::ChoiceDecode(PASN_Choice
& value
)
773 return value
.DecodePER(*this);
777 void PPER_Stream::ChoiceEncode(const PASN_Choice
& value
)
779 value
.EncodePER(*this);
782 ///////////////////////////////////////////////////////////////////////
784 BOOL
PASN_Sequence::PreambleDecodePER(PPER_Stream
& strm
)
791 totalExtensions
= strm
.SingleBitDecode() ? -1 : 0; // 18.1
795 return optionMap
.Decode(strm
); // 18.2
799 void PASN_Sequence::PreambleEncodePER(PPER_Stream
& strm
) const
804 BOOL hasExtensions
= FALSE
;
805 for (unsigned i
= 0; i
< extensionMap
.GetSize(); i
++) {
806 if (extensionMap
[i
]) {
807 hasExtensions
= TRUE
;
811 strm
.SingleBitEncode(hasExtensions
); // 18.1
812 ((PASN_Sequence
*)this)->totalExtensions
= hasExtensions
? -1 : 0;
814 optionMap
.Encode(strm
); // 18.2
818 BOOL
PASN_Sequence::NoExtensionsToDecode(PPER_Stream
& strm
)
820 if (totalExtensions
== 0)
823 if (totalExtensions
< 0) {
824 if (!extensionMap
.DecodeSequenceExtensionBitmap(strm
))
826 totalExtensions
= extensionMap
.GetSize();
833 BOOL
PASN_Sequence::NoExtensionsToEncode(PPER_Stream
& strm
)
835 if (totalExtensions
== 0)
838 if (totalExtensions
< 0) {
839 totalExtensions
= extensionMap
.GetSize();
840 extensionMap
.EncodeSequenceExtensionBitmap(strm
);
847 BOOL
PASN_Sequence::KnownExtensionDecodePER(PPER_Stream
& strm
, PINDEX fld
, PASN_Object
& field
)
849 if (NoExtensionsToDecode(strm
))
852 if (!extensionMap
[fld
-optionMap
.GetSize()])
856 if (!strm
.LengthDecode(0, INT_MAX
, len
))
859 PINDEX nextExtensionPosition
= strm
.GetPosition() + len
;
860 BOOL ok
= field
.Decode(strm
);
861 strm
.SetPosition(nextExtensionPosition
);
866 void PASN_Sequence::KnownExtensionEncodePER(PPER_Stream
& strm
, PINDEX fld
, const PASN_Object
& field
) const
868 if (((PASN_Sequence
*)this)->NoExtensionsToEncode(strm
))
871 if (!extensionMap
[fld
-optionMap
.GetSize()])
874 strm
.AnyTypeEncode(&field
);
878 BOOL
PASN_Sequence::UnknownExtensionsDecodePER(PPER_Stream
& strm
)
880 if (NoExtensionsToDecode(strm
))
883 if (totalExtensions
<= knownExtensions
)
884 return TRUE
; // Already read them
886 PINDEX unknownCount
= totalExtensions
- knownExtensions
;
887 if (fields
.GetSize() >= unknownCount
)
888 return TRUE
; // Already read them
890 if (unknownCount
> MaximumArraySize
)
893 if (!fields
.SetSize(unknownCount
))
897 for (i
= 0; i
< fields
.GetSize(); i
++)
898 fields
.SetAt(i
, new PASN_OctetString
);
900 for (i
= knownExtensions
; i
< (PINDEX
)extensionMap
.GetSize(); i
++) {
902 if (!fields
[i
-knownExtensions
].Decode(strm
))
910 void PASN_Sequence::UnknownExtensionsEncodePER(PPER_Stream
& strm
) const
912 if (((PASN_Sequence
*)this)->NoExtensionsToEncode(strm
))
916 for (i
= knownExtensions
; i
< totalExtensions
; i
++) {
917 if (extensionMap
[i
]) {
918 PINDEX f
= i
- knownExtensions
;
919 if (f
< fields
.GetSize())
920 fields
[f
].Encode(strm
);
922 PASN_OctetString dummy
;
930 BOOL
PPER_Stream::SequencePreambleDecode(PASN_Sequence
& seq
)
932 return seq
.PreambleDecodePER(*this);
936 void PPER_Stream::SequencePreambleEncode(const PASN_Sequence
& seq
)
938 seq
.PreambleEncodePER(*this);
942 BOOL
PPER_Stream::SequenceKnownDecode(PASN_Sequence
& seq
, PINDEX fld
, PASN_Object
& field
)
944 return seq
.KnownExtensionDecodePER(*this, fld
, field
);
948 void PPER_Stream::SequenceKnownEncode(const PASN_Sequence
& seq
, PINDEX fld
, const PASN_Object
& field
)
950 seq
.KnownExtensionEncodePER(*this, fld
, field
);
954 BOOL
PPER_Stream::SequenceUnknownDecode(PASN_Sequence
& seq
)
956 return seq
.UnknownExtensionsDecodePER(*this);
960 void PPER_Stream::SequenceUnknownEncode(const PASN_Sequence
& seq
)
962 seq
.UnknownExtensionsEncodePER(*this);
965 ///////////////////////////////////////////////////////////////////////
967 BOOL
PPER_Stream::ArrayDecode(PASN_Array
& array
)
972 if (!array
.ConstrainedLengthDecode(*this, size
))
975 if (!array
.SetSize(size
))
978 for (PINDEX i
= 0; i
< (PINDEX
)size
; i
++) {
979 if (!array
[i
].Decode(*this))
987 void PPER_Stream::ArrayEncode(const PASN_Array
& array
)
989 PINDEX size
= array
.GetSize();
990 array
.ConstrainedLengthEncode(*this, size
);
991 for (PINDEX i
= 0; i
< size
; i
++)
992 array
[i
].Encode(*this);
995 ///////////////////////////////////////////////////////////////////////
997 PPER_Stream::PPER_Stream(BOOL alignment
)
1003 PPER_Stream::PPER_Stream(const PBYTEArray
& bytes
, BOOL alignment
)
1004 : PASN_Stream(bytes
)
1006 aligned
= alignment
;
1010 PPER_Stream::PPER_Stream(const BYTE
* buf
, PINDEX size
, BOOL alignment
)
1011 : PASN_Stream(buf
, size
)
1013 aligned
= alignment
;
1017 PPER_Stream
& PPER_Stream::operator=(const PBYTEArray
& bytes
)
1019 PBYTEArray::operator=(bytes
);
1026 unsigned PPER_Stream::GetBitsLeft() const
1028 return (GetSize() - byteOffset
)*8 - (8 - bitOffset
);
1032 BOOL
PPER_Stream::Read(PChannel
& chan
)
1037 // Get RFC1006 TPKT length
1039 if (!chan
.ReadBlock(tpkt
, sizeof(tpkt
)))
1042 if (tpkt
[0] != 3) // Only support version 3
1045 PINDEX data_len
= ((tpkt
[2] << 8)|tpkt
[3]) - 4;
1047 return chan
.ReadBlock(GetPointer(data_len
), data_len
);
1051 BOOL
PPER_Stream::Write(PChannel
& chan
)
1055 PINDEX size
= GetSize();
1057 // Put RFC1006 TPKT length
1059 tpkt
[0] = 3; // Version 3
1062 PINDEX len
= size
+ sizeof(tpkt
);
1063 tpkt
[2] = (BYTE
)(len
>> 8);
1064 tpkt
[3] = (BYTE
)len
;
1066 return chan
.Write(tpkt
, sizeof(tpkt
)) && chan
.Write(theArray
, size
);
1070 BOOL
PPER_Stream::SingleBitDecode()
1072 if (!CheckByteOffset(byteOffset
) || ((GetSize() - byteOffset
)*8 - (8 - bitOffset
) == 0))
1077 BOOL value
= (theArray
[byteOffset
] & (1 << bitOffset
)) != 0;
1079 if (bitOffset
== 0) {
1088 void PPER_Stream::SingleBitEncode(BOOL value
)
1090 if (!CheckByteOffset(byteOffset
))
1093 if (byteOffset
>= GetSize())
1094 SetSize(byteOffset
+10);
1099 theArray
[byteOffset
] |= 1 << bitOffset
;
1106 BOOL
PPER_Stream::MultiBitDecode(unsigned nBits
, unsigned & value
)
1108 if (nBits
> sizeof(value
)*8)
1111 unsigned bitsLeft
= (GetSize() - byteOffset
)*8 - (8 - bitOffset
);
1112 if (nBits
> bitsLeft
)
1120 if (!CheckByteOffset(byteOffset
))
1123 if (nBits
< bitOffset
) {
1125 value
= (theArray
[byteOffset
] >> bitOffset
) & ((1 << nBits
) - 1);
1129 value
= theArray
[byteOffset
] & ((1 << bitOffset
) - 1);
1134 while (nBits
>= 8) {
1135 value
= (value
<< 8) | (BYTE
)theArray
[byteOffset
];
1141 bitOffset
= 8 - nBits
;
1142 value
= (value
<< nBits
) | ((BYTE
)theArray
[byteOffset
] >> bitOffset
);
1149 void PPER_Stream::MultiBitEncode(unsigned value
, unsigned nBits
)
1151 PAssert(byteOffset
!= P_MAX_INDEX
, PLogicError
);
1156 if (byteOffset
+nBits
/8+1 >= (unsigned)GetSize())
1157 SetSize(byteOffset
+10);
1159 // Make sure value is in bounds of bit available.
1160 if (nBits
< sizeof(int)*8)
1161 value
&= ((1 << nBits
) - 1);
1163 if (!CheckByteOffset(byteOffset
))
1166 if (nBits
< bitOffset
) {
1168 theArray
[byteOffset
] |= value
<< bitOffset
;
1173 theArray
[byteOffset
] |= (BYTE
)(value
>> nBits
);
1177 while (nBits
>= 8) {
1179 theArray
[byteOffset
] = (BYTE
)(value
>> nBits
);
1184 bitOffset
= 8 - nBits
;
1185 theArray
[byteOffset
] |= (BYTE
)((value
& ((1 << nBits
)-1)) << bitOffset
);
1190 BOOL
PPER_Stream::SmallUnsignedDecode(unsigned & value
)
1192 // X.691 Section 10.6
1194 if (!SingleBitDecode())
1195 return MultiBitDecode(6, value
); // 10.6.1
1198 if (!LengthDecode(0, INT_MAX
, len
)) // 10.6.2
1202 return MultiBitDecode(len
*8, value
);
1206 void PPER_Stream::SmallUnsignedEncode(unsigned value
)
1209 MultiBitEncode(value
, 7);
1213 SingleBitEncode(1); // 10.6.2
1218 else if (value
< 65536)
1220 else if (value
< 0x1000000)
1222 LengthEncode(len
, 0, INT_MAX
); // 10.9
1224 MultiBitEncode(value
, len
*8);
1228 BOOL
PPER_Stream::UnsignedDecode(unsigned lower
, unsigned upper
, unsigned & value
)
1230 // X.691 section 10.5
1232 if (lower
== upper
) { // 10.5.4
1240 unsigned range
= (upper
- lower
) + 1;
1241 unsigned nBits
= CountBits(range
);
1243 if (aligned
&& (range
== 0 || range
> 255)) { // not 10.5.6 and not 10.5.7.1
1244 if (nBits
> 16) { // not 10.5.7.4
1245 if (!LengthDecode(1, (nBits
+7)/8, nBits
)) // 12.2.6
1249 else if (nBits
> 8) // not 10.5.7.2
1250 nBits
= 16; // 10.5.7.3
1251 ByteAlign(); // 10.7.5.2 - 10.7.5.4
1254 if (!MultiBitDecode(nBits
, value
))
1259 // clamp value to upper limit
1267 void PPER_Stream::UnsignedEncode(int value
, unsigned lower
, unsigned upper
)
1269 // X.691 section 10.5
1271 if (lower
== upper
) // 10.5.4
1274 unsigned range
= (upper
- lower
) + 1;
1275 PINDEX nBits
= CountBits(range
);
1277 if ((unsigned)value
< lower
)
1282 if (aligned
&& (range
== 0 || range
> 255)) { // not 10.5.6 and not 10.5.7.1
1283 if (nBits
> 16) { // not 10.5.7.4
1284 int numBytes
= value
== 0 ? 1 : (((CountBits(value
+ 1))+7)/8);
1285 LengthEncode(numBytes
, 1, (nBits
+7)/8); // 12.2.6
1288 else if (nBits
> 8) // not 10.5.7.2
1289 nBits
= 16; // 10.5.7.3
1290 ByteAlign(); // 10.7.5.2 - 10.7.5.4
1293 MultiBitEncode(value
, nBits
);
1297 BOOL
PPER_Stream::LengthDecode(unsigned lower
, unsigned upper
, unsigned & len
)
1299 // X.691 section 10.9
1301 if (upper
!= INT_MAX
&& !aligned
) {
1302 if (upper
- lower
> 0xffff)
1303 return FALSE
; // 10.9.4.2 unsupported
1305 if (!MultiBitDecode(CountBits(upper
- lower
+ 1), base
))
1307 len
= lower
+ base
; // 10.9.4.1
1309 // clamp value to upper limit
1316 if (upper
< 65536) // 10.9.3.3
1317 return UnsignedDecode(lower
, upper
, len
);
1324 if (SingleBitDecode() == 0) {
1325 if (!MultiBitDecode(7, len
)) // 10.9.3.6
1326 return FALSE
; // 10.9.3.8 unsupported
1329 else if (SingleBitDecode() == 0) {
1330 if (!MultiBitDecode(14, len
)) // 10.9.3.7
1331 return FALSE
; // 10.9.3.8 unsupported
1334 // clamp value to upper limit
1342 void PPER_Stream::LengthEncode(unsigned len
, unsigned lower
, unsigned upper
)
1344 // X.691 section 10.9
1346 if (upper
!= INT_MAX
&& !aligned
) {
1347 PAssert(upper
- lower
< 0x10000, PUnimplementedFunction
); // 10.9.4.2 unsupperted
1348 MultiBitEncode(len
- lower
, CountBits(upper
- lower
+ 1)); // 10.9.4.1
1352 if (upper
< 65536) { // 10.9.3.3
1353 UnsignedEncode(len
, lower
, upper
);
1360 MultiBitEncode(len
, 8); // 10.9.3.6
1364 SingleBitEncode(TRUE
);
1367 MultiBitEncode(len
, 15); // 10.9.3.7
1371 SingleBitEncode(TRUE
);
1372 PAssertAlways(PUnimplementedFunction
); // 10.9.3.8 unsupported
1376 void PPER_Stream::AnyTypeEncode(const PASN_Object
* value
)
1378 PPER_Stream substream
;
1381 value
->Encode(substream
);
1383 substream
.CompleteEncoding();
1385 PINDEX nBytes
= substream
.GetSize();
1387 const BYTE null
[1] = { 0 };
1388 nBytes
= sizeof(null
);
1389 substream
= PBYTEArray(null
, nBytes
, FALSE
);
1392 LengthEncode(nBytes
, 0, INT_MAX
);
1393 BlockEncode(substream
.GetPointer(), nBytes
);
1396 ///////////////////////////////////////////////////////////////////////