Uncommented beaudio code
[pwlib.git] / src / ptclib / asnper.cxx
blobcdf0180d9304a832842e47a79137e52f6f1ed64c
1 /*
2 * asnper.cxx
4 * Abstract Syntax Notation 1 Encoding Rules
6 * Portable Windows Library
8 * $Log$
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 &)
33 return TRUE;
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);
49 else
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);
58 else
59 strm.LengthEncode(length, lowerLimit, upperLimit);
63 BOOL PASN_ConstrainedObject::ConstraintEncode(PPER_Stream & strm, unsigned value) const
65 if (!extendable)
66 return constraint != FixedConstraint;
68 BOOL needsExtending = value > upperLimit;
70 if (!needsExtending) {
71 if (lowerLimit < 0) {
72 if ((int)value < lowerLimit)
73 needsExtending = TRUE;
75 else {
76 if (value < (unsigned)lowerLimit)
77 needsExtending = TRUE;
81 strm.SingleBitEncode(needsExtending);
83 return needsExtending;
86 ///////////////////////////////////////////////////////////////////////
88 BOOL PPER_Stream::BooleanDecode(PASN_Boolean & value)
90 if (IsAtEnd())
91 return FALSE;
93 // X.691 Section 11
94 value = (BOOL)SingleBitDecode();
95 return TRUE;
99 void PPER_Stream::BooleanEncode(const PASN_Boolean & value)
101 // X.691 Section 11
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)
120 // X.691 Sections 12
122 switch (constraint) {
123 case FixedConstraint : // 12.2.1 & 12.2.2
124 break;
126 case ExtendableConstraint :
127 if (!strm.SingleBitDecode()) // 12.1
128 break;
129 // Fall into default case for unconstrained or partially constrained
131 default : // 12.2.6
132 unsigned len;
133 if (!strm.LengthDecode(0, INT_MAX, len))
134 return FALSE;
136 len *= 8;
137 if (!strm.MultiBitDecode(len, value))
138 return FALSE;
140 if (IsUnsigned())
141 value += lowerLimit;
142 else if ((value&(1<<(len-1))) != 0) // Negative
143 value |= UINT_MAX << len; // Sign extend
144 return TRUE;
147 if ((unsigned)lowerLimit != upperLimit) // 12.2.2
148 return strm.UnsignedDecode(lowerLimit, upperLimit, value); // which devolves to 10.5
150 // 12.2.1
151 value = lowerLimit;
152 return TRUE;
156 void PASN_Integer::EncodePER(PPER_Stream & strm) const
158 // X.691 Sections 12
160 // 12.1
161 if (ConstraintEncode(strm, (int)value)) {
162 // 12.2.6
163 unsigned adjusted_value = value - lowerLimit;
165 PINDEX nBits = 1; // Allow for sign bit
166 if (IsUnsigned())
167 nBits = CountBits(adjusted_value+1);
168 else if ((int)adjusted_value > 0)
169 nBits += CountBits(adjusted_value+1);
170 else
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);
177 return;
180 if ((unsigned)lowerLimit == upperLimit) // 12.2.1
181 return;
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)
203 // X.691 Section 13
205 if (extendable) { // 13.3
206 if (strm.SingleBitDecode()) {
207 unsigned len = 0;
208 return strm.SmallUnsignedDecode(len) &&
209 len > 0 &&
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
220 // X.691 Section 13
222 if (extendable) { // 13.3
223 BOOL extended = value > maxEnumValue;
224 strm.SingleBitEncode(extended);
225 if (extended) {
226 strm.SmallUnsignedEncode(1+value);
227 strm.UnsignedEncode(value, 0, value);
228 return;
232 strm.UnsignedEncode(value, 0, maxEnumValue); // 13.2
235 ///////////////////////////////////////////////////////////////////////
237 BOOL PPER_Stream::RealDecode(PASN_Real &)
239 // X.691 Section 14
241 if (IsAtEnd())
242 return FALSE;
244 unsigned len;
245 if (!MultiBitDecode(8, len))
246 return FALSE;
248 PAssertAlways(PUnimplementedFunction);
249 byteOffset += len+1;
250 return TRUE;
254 void PPER_Stream::RealEncode(const PASN_Real &)
256 // X.691 Section 14
258 MultiBitEncode(0, 8);
259 PAssertAlways(PUnimplementedFunction);
260 MultiBitEncode(0, 8);
263 ///////////////////////////////////////////////////////////////////////
265 BOOL PPER_Stream::ObjectIdDecode(PASN_ObjectId & value)
267 // X.691 Section 23
269 unsigned dataLen;
270 if (!LengthDecode(0, 255, dataLen))
271 return FALSE;
273 ByteAlign();
274 return value.CommonDecode(*this, dataLen);
278 void PPER_Stream::ObjectIdEncode(const PASN_ObjectId & value)
280 // X.691 Section 23
282 PBYTEArray eObjId;
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))
293 return FALSE;
295 totalBits++;
297 if (!SetSize(totalBits))
298 return FALSE;
300 if (totalBits > strm.GetBitsLeft())
301 return FALSE;
303 unsigned theBits;
305 PINDEX idx = 0;
306 unsigned bitsLeft = totalBits;
307 while (bitsLeft >= 8) {
308 if (!strm.MultiBitDecode(8, theBits))
309 return FALSE;
310 bitData[idx++] = (BYTE)theBits;
311 bitsLeft -= 8;
314 if (bitsLeft > 0) {
315 if (!strm.MultiBitDecode(bitsLeft, theBits))
316 return FALSE;
317 bitData[idx] = (BYTE)(theBits << (8-bitsLeft));
320 return TRUE;
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])
330 bitsLeft--;
332 strm.SmallUnsignedEncode(bitsLeft-1);
334 PINDEX idx = 0;
335 while (bitsLeft >= 8) {
336 strm.MultiBitEncode(bitData[idx++], 8);
337 bitsLeft -= 8;
340 if (bitsLeft > 0)
341 strm.MultiBitEncode(bitData[idx] >> (8 - bitsLeft), bitsLeft);
345 BOOL PASN_BitString::DecodePER(PPER_Stream & strm)
347 // X.691 Section 15
349 if (!ConstrainedLengthDecode(strm, totalBits))
350 return FALSE;
352 if (!SetSize(totalBits))
353 return FALSE;
355 if (totalBits == 0)
356 return TRUE; // 15.7
358 if (totalBits > strm.GetBitsLeft())
359 return FALSE;
361 if (totalBits > 16) {
362 unsigned nBytes = (totalBits+7)/8;
363 return strm.BlockDecode(bitData.GetPointer(), nBytes) == nBytes; // 15.9
366 unsigned theBits;
367 if (totalBits <= 8) {
368 if (!strm.MultiBitDecode(totalBits, theBits))
369 return FALSE;
371 bitData[0] = (BYTE)(theBits << (8-totalBits));
373 else { // 15.8
374 if (!strm.MultiBitDecode(8, theBits))
375 return FALSE;
377 bitData[0] = (BYTE)theBits;
379 if (!strm.MultiBitDecode(totalBits-8, theBits))
380 return FALSE;
382 bitData[1] = (BYTE)(theBits << (16-totalBits));
385 return TRUE;
389 void PASN_BitString::EncodePER(PPER_Stream & strm) const
391 // X.691 Section 15
393 ConstrainedLengthEncode(strm, totalBits);
395 if (totalBits == 0)
396 return;
398 if (totalBits > 16)
399 strm.BlockEncode(bitData, (totalBits+7)/8); // 15.9
400 else if (totalBits <= 8) // 15.8
401 strm.MultiBitEncode(bitData[0] >> (8 - totalBits), totalBits);
402 else {
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)
432 PPER_Stream stream;
433 obj.Encode(stream);
434 stream.CompleteEncoding();
435 SetValue(stream);
438 BOOL PASN_OctetString::DecodePER(PPER_Stream & strm)
440 // X.691 Section 16
442 unsigned nBytes;
443 if (!ConstrainedLengthDecode(strm, nBytes))
444 return FALSE;
446 if (!SetSize(nBytes)) // 16.5
447 return FALSE;
449 if ((int)upperLimit != lowerLimit)
450 return strm.BlockDecode(value.GetPointer(), nBytes) == nBytes;
452 unsigned theBits;
453 switch (nBytes) {
454 case 0 :
455 break;
457 case 1 : // 16.6
458 if (!strm.MultiBitDecode(8, theBits))
459 return FALSE;
460 value[0] = (BYTE)theBits;
461 break;
463 case 2 : // 16.6
464 if (!strm.MultiBitDecode(8, theBits))
465 return FALSE;
466 value[0] = (BYTE)theBits;
467 if (!strm.MultiBitDecode(8, theBits))
468 return FALSE;
469 value[1] = (BYTE)theBits;
470 break;
472 default: // 16.7
473 return strm.BlockDecode(value.GetPointer(), nBytes) == nBytes;
476 return TRUE;
480 void PASN_OctetString::EncodePER(PPER_Stream & strm) const
482 // X.691 Section 16
484 PINDEX nBytes = value.GetSize();
485 ConstrainedLengthEncode(strm, nBytes);
487 if ((int)upperLimit != lowerLimit) {
488 strm.BlockEncode(value, nBytes);
489 return;
492 switch (nBytes) {
493 case 0 : // 16.5
494 break;
496 case 1 : // 16.6
497 strm.MultiBitEncode(value[0], 8);
498 break;
500 case 2 : // 16.6
501 strm.MultiBitEncode(value[0], 8);
502 strm.MultiBitEncode(value[1], 8);
503 break;
505 default: // 16.7
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)
525 // X.691 Section 26
527 unsigned len;
528 if (!ConstrainedLengthDecode(strm, len))
529 return FALSE;
531 if (len == 0) { // 10.9.3.3
532 value.SetSize(1);
533 value[0] = '\0';
534 return TRUE;
537 unsigned nBits = strm.IsAligned() ? charSetAlignedBits : charSetUnalignedBits;
538 unsigned totalBits = upperLimit*nBits;
540 if (constraint == Unconstrained ||
541 (lowerLimit == (int)upperLimit ? (totalBits > 16) : (totalBits >= 16))) {
542 if (nBits == 8)
543 return strm.BlockDecode((BYTE *)value.GetPointer(len+1), len) == len;
544 if (strm.IsAligned())
545 strm.ByteAlign();
548 if ((PINDEX)len > MaximumStringSize)
549 return FALSE;
551 if (!value.SetSize(len+1))
552 return FALSE;
554 PINDEX i;
555 for (i = 0; i < (PINDEX)len; i++) {
556 unsigned theBits;
557 if (!strm.MultiBitDecode(nBits, theBits))
558 return FALSE;
559 if (nBits >= canonicalSetBits && canonicalSetBits > 4)
560 value[i] = (char)theBits;
561 else
562 value[i] = characterSet[(PINDEX)theBits];
564 value[i] = '\0';
566 return TRUE;
570 void PASN_ConstrainedString::EncodePER(PPER_Stream & strm) const
572 // X.691 Section 26
574 PINDEX len = value.GetSize()-1;
575 ConstrainedLengthEncode(strm, len);
577 if (len == 0) // 10.9.3.3
578 return;
580 unsigned nBits = strm.IsAligned() ? charSetAlignedBits : charSetUnalignedBits;
581 unsigned totalBits = upperLimit*nBits;
583 if (constraint == Unconstrained ||
584 (lowerLimit == (int)upperLimit ? (totalBits > 16) : (totalBits >= 16))) {
585 // 26.5.7
586 if (nBits == 8) {
587 strm.BlockEncode((const BYTE *)(const char *)value, len);
588 return;
590 if (strm.IsAligned())
591 strm.ByteAlign();
594 for (PINDEX i = 0; i < len; i++) {
595 if (nBits >= canonicalSetBits && canonicalSetBits > 4)
596 strm.MultiBitEncode(value[i], nBits);
597 else {
598 const void * ptr = memchr(characterSet, value[i], characterSet.GetSize());
599 PINDEX pos = 0;
600 if (ptr != NULL)
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)
624 // X.691 Section 26
626 unsigned len;
627 if (!ConstrainedLengthDecode(strm, len))
628 return FALSE;
630 if ((PINDEX)len > MaximumStringSize)
631 return FALSE;
633 if (!value.SetSize(len))
634 return FALSE;
636 PINDEX nBits = strm.IsAligned() ? charSetAlignedBits : charSetUnalignedBits;
638 if ((constraint == Unconstrained || upperLimit*nBits > 16) && strm.IsAligned())
639 strm.ByteAlign();
641 for (PINDEX i = 0; i < (PINDEX)len; i++) {
642 unsigned theBits;
643 if (!strm.MultiBitDecode(nBits, theBits))
644 return FALSE;
645 if (characterSet.IsEmpty())
646 value[i] = (WORD)(theBits + firstChar);
647 else
648 value[i] = characterSet[(PINDEX)theBits];
651 return TRUE;
655 void PASN_BMPString::EncodePER(PPER_Stream & strm) const
657 // X.691 Section 26
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())
665 strm.ByteAlign();
667 for (PINDEX i = 0; i < len; i++) {
668 if (characterSet.IsEmpty())
669 strm.MultiBitEncode(value[i] - firstChar, nBits);
670 else {
671 for (PINDEX pos = 0; pos < characterSet.GetSize(); pos++) {
672 if (characterSet[pos] == value[i]) {
673 strm.MultiBitEncode(pos, nBits);
674 break;
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)
697 // X.691 Section 22
698 delete choice;
699 choice = NULL;
701 if (strm.IsAtEnd())
702 return FALSE;
704 if (extendable) {
705 if (strm.SingleBitDecode()) {
706 if (!strm.SmallUnsignedDecode(tag))
707 return FALSE;
709 tag += numChoices;
711 unsigned len;
712 if (!strm.LengthDecode(0, INT_MAX, len))
713 return FALSE;
715 BOOL ok;
716 if (CreateObject()) {
717 PINDEX nextPos = strm.GetPosition() + len;
718 ok = choice->Decode(strm);
719 strm.SetPosition(nextPos);
721 else {
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)
726 choice = open_type;
727 else {
728 delete open_type;
729 ok = FALSE;
732 return ok;
736 if (numChoices < 2)
737 tag = 0;
738 else {
739 if (!strm.UnsignedDecode(0, numChoices-1, tag))
740 return FALSE;
743 return CreateObject() && choice->Decode(strm);
747 void PASN_Choice::EncodePER(PPER_Stream & strm) const
749 PAssert(CheckCreate(), PLogicError);
751 if (extendable) {
752 BOOL extended = tag >= numChoices;
753 strm.SingleBitEncode(extended);
754 if (extended) {
755 strm.SmallUnsignedEncode(tag - numChoices);
756 strm.AnyTypeEncode(choice);
757 return;
761 if (numChoices > 1)
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)
783 // X.691 Section 18
785 if (extendable) {
786 if (strm.IsAtEnd())
787 return FALSE;
788 totalExtensions = strm.SingleBitDecode() ? -1 : 0; // 18.1
790 else
791 totalExtensions = 0;
792 return optionMap.Decode(strm); // 18.2
796 void PASN_Sequence::PreambleEncodePER(PPER_Stream & strm) const
798 // X.691 Section 18
800 if (extendable) {
801 BOOL hasExtensions = FALSE;
802 for (unsigned i = 0; i < extensionMap.GetSize(); i++) {
803 if (extensionMap[i]) {
804 hasExtensions = TRUE;
805 break;
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)
818 return TRUE;
820 if (totalExtensions < 0) {
821 if (!extensionMap.DecodeSequenceExtensionBitmap(strm))
822 return FALSE;
823 totalExtensions = extensionMap.GetSize();
826 return FALSE;
830 BOOL PASN_Sequence::NoExtensionsToEncode(PPER_Stream & strm)
832 if (totalExtensions == 0)
833 return TRUE;
835 if (totalExtensions < 0) {
836 totalExtensions = extensionMap.GetSize();
837 extensionMap.EncodeSequenceExtensionBitmap(strm);
840 return FALSE;
844 BOOL PASN_Sequence::KnownExtensionDecodePER(PPER_Stream & strm, PINDEX fld, PASN_Object & field)
846 if (NoExtensionsToDecode(strm))
847 return TRUE;
849 if (!extensionMap[fld-optionMap.GetSize()])
850 return TRUE;
852 unsigned len;
853 if (!strm.LengthDecode(0, INT_MAX, len))
854 return FALSE;
856 PINDEX nextExtensionPosition = strm.GetPosition() + len;
857 BOOL ok = field.Decode(strm);
858 strm.SetPosition(nextExtensionPosition);
859 return ok;
863 void PASN_Sequence::KnownExtensionEncodePER(PPER_Stream & strm, PINDEX fld, const PASN_Object & field) const
865 if (((PASN_Sequence*)this)->NoExtensionsToEncode(strm))
866 return;
868 if (!extensionMap[fld-optionMap.GetSize()])
869 return;
871 strm.AnyTypeEncode(&field);
875 BOOL PASN_Sequence::UnknownExtensionsDecodePER(PPER_Stream & strm)
877 if (NoExtensionsToDecode(strm))
878 return TRUE;
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)
888 return FALSE;
890 if (!fields.SetSize(unknownCount))
891 return FALSE;
893 PINDEX i;
894 for (i = 0; i < fields.GetSize(); i++)
895 fields.SetAt(i, new PASN_OctetString);
897 for (i = knownExtensions; i < (PINDEX)extensionMap.GetSize(); i++) {
898 if (extensionMap[i])
899 if (!fields[i-knownExtensions].Decode(strm))
900 return FALSE;
903 return TRUE;
907 void PASN_Sequence::UnknownExtensionsEncodePER(PPER_Stream & strm) const
909 if (((PASN_Sequence*)this)->NoExtensionsToEncode(strm))
910 return;
912 int i;
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);
918 else {
919 PASN_OctetString dummy;
920 dummy.Encode(strm);
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)
966 array.RemoveAll();
968 unsigned size;
969 if (!array.ConstrainedLengthDecode(*this, size))
970 return FALSE;
972 if (!array.SetSize(size))
973 return FALSE;
975 for (PINDEX i = 0; i < (PINDEX)size; i++) {
976 if (!array[i].Decode(*this))
977 return FALSE;
980 return TRUE;
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)
996 aligned = 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);
1017 ResetDecoder();
1018 aligned = TRUE;
1019 return *this;
1023 unsigned PPER_Stream::GetBitsLeft() const
1025 return (GetSize() - byteOffset)*8 - (8 - bitOffset);
1029 BOOL PPER_Stream::Read(PChannel & chan)
1031 ResetDecoder();
1032 SetSize(0);
1034 // Get RFC1006 TPKT length
1035 BYTE tpkt[4];
1036 if (!chan.ReadBlock(tpkt, sizeof(tpkt)))
1037 return FALSE;
1039 if (tpkt[0] != 3) // Only support version 3
1040 return TRUE;
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)
1050 CompleteEncoding();
1052 PINDEX size = GetSize();
1054 // Put RFC1006 TPKT length
1055 BYTE tpkt[4];
1056 tpkt[0] = 3; // Version 3
1057 tpkt[1] = 0;
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)
1070 return FALSE;
1072 bitOffset--;
1073 BOOL value = (theArray[byteOffset] & (1 << bitOffset)) != 0;
1075 if (bitOffset == 0) {
1076 bitOffset = 8;
1077 byteOffset++;
1080 return value;
1084 void PPER_Stream::SingleBitEncode(BOOL value)
1086 PAssert(byteOffset != P_MAX_INDEX, PLogicError);
1088 if (byteOffset >= GetSize())
1089 SetSize(byteOffset+10);
1091 bitOffset--;
1093 if (value)
1094 theArray[byteOffset] |= 1 << bitOffset;
1096 if (bitOffset == 0)
1097 ByteAlign();
1101 BOOL PPER_Stream::MultiBitDecode(unsigned nBits, unsigned & value)
1103 if (nBits > sizeof(value)*8)
1104 return FALSE;
1106 unsigned bitsLeft = (GetSize() - byteOffset)*8 - (8 - bitOffset);
1107 if (nBits > bitsLeft)
1108 return FALSE;
1110 if (nBits == 0) {
1111 value = 0;
1112 return TRUE;
1115 if (nBits < bitOffset) {
1116 bitOffset -= nBits;
1117 value = (theArray[byteOffset] >> bitOffset) & ((1 << nBits) - 1);
1118 return TRUE;
1121 value = theArray[byteOffset] & ((1 << bitOffset) - 1);
1122 nBits -= bitOffset;
1123 bitOffset = 8;
1124 byteOffset++;
1126 while (nBits >= 8) {
1127 value = (value << 8) | (BYTE)theArray[byteOffset];
1128 byteOffset++;
1129 nBits -= 8;
1132 if (nBits > 0) {
1133 bitOffset = 8 - nBits;
1134 value = (value << nBits) | ((BYTE)theArray[byteOffset] >> bitOffset);
1137 return TRUE;
1141 void PPER_Stream::MultiBitEncode(unsigned value, unsigned nBits)
1143 PAssert(byteOffset != P_MAX_INDEX, PLogicError);
1145 if (nBits == 0)
1146 return;
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) {
1156 bitOffset -= nBits;
1157 theArray[byteOffset] |= value << bitOffset;
1158 return;
1161 nBits -= bitOffset;
1162 theArray[byteOffset] |= (BYTE)(value >> nBits);
1163 bitOffset = 8;
1164 byteOffset++;
1166 while (nBits >= 8) {
1167 nBits -= 8;
1168 theArray[byteOffset] = (BYTE)(value >> nBits);
1169 byteOffset++;
1172 if (nBits > 0) {
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
1186 unsigned len;
1187 if (!LengthDecode(0, INT_MAX, len)) // 10.6.2
1188 return FALSE;
1190 ByteAlign();
1191 return MultiBitDecode(len*8, value);
1195 void PPER_Stream::SmallUnsignedEncode(unsigned value)
1197 if (value < 64) {
1198 MultiBitEncode(value, 7);
1199 return;
1202 SingleBitEncode(1); // 10.6.2
1204 PINDEX len = 4;
1205 if (value < 256)
1206 len = 1;
1207 else if (value < 65536)
1208 len = 2;
1209 else if (value < 0x1000000)
1210 len = 3;
1211 LengthEncode(len, 0, INT_MAX); // 10.9
1212 ByteAlign();
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
1222 value = lower;
1223 return TRUE;
1226 if (IsAtEnd())
1227 return FALSE;
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
1235 return FALSE;
1236 nBits *= 8;
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))
1244 return FALSE;
1246 value += lower;
1248 // clamp value to upper limit
1249 if (value > upper)
1250 value = upper;
1252 return TRUE;
1256 void PPER_Stream::UnsignedEncode(int value, unsigned lower, unsigned upper)
1258 // X.691 section 10.5
1260 if (lower == upper) // 10.5.4
1261 return;
1263 unsigned range = (upper - lower) + 1;
1264 PINDEX nBits = CountBits(range);
1266 if ((unsigned)value < lower)
1267 value = 0;
1268 else
1269 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
1275 nBits = numBytes*8;
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
1293 unsigned base;
1294 if (!MultiBitDecode(CountBits(upper - lower + 1), base))
1295 return FALSE;
1296 len = lower + base; // 10.9.4.1
1298 // clamp value to upper limit
1299 if (len > upper)
1300 len = upper;
1302 return TRUE;
1305 if (upper < 65536) // 10.9.3.3
1306 return UnsignedDecode(lower, upper, len);
1308 // 10.9.3.5
1309 ByteAlign();
1310 if (IsAtEnd())
1311 return FALSE;
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
1324 if (len > upper)
1325 len = upper;
1327 return TRUE;
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
1338 return;
1341 if (upper < 65536) { // 10.9.3.3
1342 UnsignedEncode(len, lower, upper);
1343 return;
1346 ByteAlign();
1348 if (len < 128) {
1349 MultiBitEncode(len, 8); // 10.9.3.6
1350 return;
1353 SingleBitEncode(TRUE);
1355 if (len < 0x4000) {
1356 MultiBitEncode(len, 15); // 10.9.3.7
1357 return;
1360 SingleBitEncode(TRUE);
1361 PAssertAlways(PUnimplementedFunction); // 10.9.3.8 unsupported
1365 void PPER_Stream::AnyTypeEncode(const PASN_Object * value)
1367 PPER_Stream substream;
1369 if (value != NULL)
1370 value->Encode(substream);
1372 substream.CompleteEncoding();
1374 PINDEX nBytes = substream.GetSize();
1375 if (nBytes == 0) {
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 ///////////////////////////////////////////////////////////////////////