1 /*
2 * asner.cxx
3 *
4 * Abstract Syntax Notation 1 Encoding Rules
5 *
6 * Portable Windows Library
7 *
8 * Copyright (c) 1993-2002 Equivalence Pty. Ltd.
9 *
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/
14 *
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
18 * under the License.
19 *
20 * The Original Code is Portable Windows Library.
21 *
22 * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
23 *
24 * Contributor(s): ______________________________________.
25 *
26 * $Log: asner.cxx,v $
27 * Revision 1.93 2005/11/30 12:47:41 csoutheren
28 * $Revision: 23918 $
29 * $Author: rjongbloed $
30 * $Date: 2010-01-10 22:03:52 -0600 (Sun, 10 Jan 2010) $
31 */
32
33 #include <ptlib.h>
34
35 #ifdef __GNUC__
36 #pragma implementation "asner.h"
37 #endif
38
39 #include <ptclib/asner.h>
40
41 #ifdef P_EXPAT
42 #include <ptclib/pxml.h>
43 #endif
44
45 #define new PNEW
46
47
48 static PINDEX MaximumArraySize = 128;
49 static PINDEX MaximumStringSize = 16*1024;
50 static PINDEX MaximumSetSize = 512;
51
52
CountBits(unsigned range)53 static PINDEX CountBits(unsigned range)
54 {
55 switch (range) {
56 case 0 :
57 return sizeof(unsigned)*8;
58 case 1:
59 return 1;
60 }
61
62 size_t nBits = 0;
63 while (nBits < (sizeof(unsigned)*8) && range > (unsigned)(1 << nBits))
64 nBits++;
65 return nBits;
66 }
67
CheckByteOffset(PINDEX offset,PINDEX upper=MaximumStringSize)68 inline PBoolean CheckByteOffset(PINDEX offset, PINDEX upper = MaximumStringSize)
69 {
70 // a 1mbit PDU has got to be an error
71 return (0 <= offset && offset <= upper);
72 }
73
FindNameByValue(const PASN_Names * names,unsigned namesCount,PINDEX value)74 static PINDEX FindNameByValue(const PASN_Names *names, unsigned namesCount, PINDEX value)
75 {
76 if (names != NULL) {
77 for (unsigned int i = 0;i < namesCount;i++) {
78 if (names[i].value == value)
79 return i;
80 }
81 }
82 return P_MAX_INDEX;
83 }
84
85 ///////////////////////////////////////////////////////////////////////
86
PASN_Object(unsigned theTag,TagClass theTagClass,PBoolean extend)87 PASN_Object::PASN_Object(unsigned theTag, TagClass theTagClass, PBoolean extend)
88 {
89 extendable = extend;
90
91 tag = theTag;
92
93 if (theTagClass != DefaultTagClass)
94 tagClass = theTagClass;
95 else
96 tagClass = ContextSpecificTagClass;
97 }
98
99
SetTag(unsigned newTag,TagClass tagClass_)100 void PASN_Object::SetTag(unsigned newTag, TagClass tagClass_)
101 {
102 tag = newTag;
103 if (tagClass_ != DefaultTagClass)
104 tagClass = tagClass_;
105 }
106
107
GetObjectLength() const108 PINDEX PASN_Object::GetObjectLength() const
109 {
110 PINDEX len = 1;
111
112 if (tag >= 31)
113 len += (CountBits(tag)+6)/7;
114
115 PINDEX dataLen = GetDataLength();
116 if (dataLen < 128)
117 len++;
118 else
119 len += (CountBits(dataLen)+7)/8 + 1;
120
121 return len + dataLen;
122 }
123
124
SetConstraintBounds(ConstraintType,int,unsigned)125 void PASN_Object::SetConstraintBounds(ConstraintType, int, unsigned)
126 {
127 }
128
129
SetCharacterSet(ConstraintType,const char *)130 void PASN_Object::SetCharacterSet(ConstraintType, const char *)
131 {
132 }
133
134
SetCharacterSet(ConstraintType,unsigned,unsigned)135 void PASN_Object::SetCharacterSet(ConstraintType, unsigned, unsigned)
136 {
137 }
138
139
GetMaximumArraySize()140 PINDEX PASN_Object::GetMaximumArraySize()
141 {
142 return MaximumArraySize;
143 }
144
145
SetMaximumArraySize(PINDEX sz)146 void PASN_Object::SetMaximumArraySize(PINDEX sz)
147 {
148 MaximumArraySize = sz;
149 }
150
151
GetMaximumStringSize()152 PINDEX PASN_Object::GetMaximumStringSize()
153 {
154 return MaximumStringSize;
155 }
156
157
SetMaximumStringSize(PINDEX sz)158 void PASN_Object::SetMaximumStringSize(PINDEX sz)
159 {
160 MaximumStringSize = sz;
161 }
162
163
164 ///////////////////////////////////////////////////////////////////////
165
PASN_ConstrainedObject(unsigned tag,TagClass tagClass)166 PASN_ConstrainedObject::PASN_ConstrainedObject(unsigned tag, TagClass tagClass)
167 : PASN_Object(tag, tagClass)
168 {
169 constraint = Unconstrained;
170 lowerLimit = 0;
171 upperLimit = UINT_MAX;
172 }
173
174
SetConstraintBounds(ConstraintType ctype,int lower,unsigned upper)175 void PASN_ConstrainedObject::SetConstraintBounds(ConstraintType ctype,
176 int lower, unsigned upper)
177 {
178 constraint = ctype;
179 if (constraint == Unconstrained) {
180 lower = 0;
181 upper = UINT_MAX;
182 }
183
184 extendable = ctype == ExtendableConstraint;
185 // if ((lower >= 0 && upper < 0x7fffffff) ||
186 // (lower < 0 && (unsigned)lower <= upper)) {
187 lowerLimit = lower;
188 upperLimit = upper;
189 // }
190 }
191
192
193 ///////////////////////////////////////////////////////////////////////
194
PASN_Null(unsigned tag,TagClass tagClass)195 PASN_Null::PASN_Null(unsigned tag, TagClass tagClass)
196 : PASN_Object(tag, tagClass)
197 {
198 }
199
200
Compare(const PObject & obj) const201 PObject::Comparison PASN_Null::Compare(const PObject & obj) const
202 {
203 PAssert(PIsDescendant(&obj, PASN_Null), PInvalidCast);
204 return EqualTo;
205 }
206
207
Clone() const208 PObject * PASN_Null::Clone() const
209 {
210 PAssert(IsClass(PASN_Null::Class()), PInvalidCast);
211 return new PASN_Null(*this);
212 }
213
214
PrintOn(ostream & strm) const215 void PASN_Null::PrintOn(ostream & strm) const
216 {
217 strm << "<<null>>";
218 }
219
220
GetTypeAsString() const221 PString PASN_Null::GetTypeAsString() const
222 {
223 return "Null";
224 }
225
226
GetDataLength() const227 PINDEX PASN_Null::GetDataLength() const
228 {
229 return 0;
230 }
231
232
Decode(PASN_Stream & strm)233 PBoolean PASN_Null::Decode(PASN_Stream & strm)
234 {
235 return strm.NullDecode(*this);
236 }
237
238
Encode(PASN_Stream & strm) const239 void PASN_Null::Encode(PASN_Stream & strm) const
240 {
241 strm.NullEncode(*this);
242 }
243
244
245 ///////////////////////////////////////////////////////////////////////
246
PASN_Boolean(PBoolean val)247 PASN_Boolean::PASN_Boolean(PBoolean val)
248 : PASN_Object(UniversalBoolean, UniversalTagClass)
249 {
250 value = val;
251 }
252
253
PASN_Boolean(unsigned tag,TagClass tagClass,PBoolean val)254 PASN_Boolean::PASN_Boolean(unsigned tag, TagClass tagClass, PBoolean val)
255 : PASN_Object(tag, tagClass)
256 {
257 value = val;
258 }
259
260
Compare(const PObject & obj) const261 PObject::Comparison PASN_Boolean::Compare(const PObject & obj) const
262 {
263 PAssert(PIsDescendant(&obj, PASN_Boolean), PInvalidCast);
264 return value == ((const PASN_Boolean &)obj).value ? EqualTo : GreaterThan;
265 }
266
267
Clone() const268 PObject * PASN_Boolean::Clone() const
269 {
270 PAssert(IsClass(PASN_Boolean::Class()), PInvalidCast);
271 return new PASN_Boolean(*this);
272 }
273
274
PrintOn(ostream & strm) const275 void PASN_Boolean::PrintOn(ostream & strm) const
276 {
277 if (value)
278 strm << "true";
279 else
280 strm << "false";
281 }
282
283
GetTypeAsString() const284 PString PASN_Boolean::GetTypeAsString() const
285 {
286 return "Boolean";
287 }
288
289
GetDataLength() const290 PINDEX PASN_Boolean::GetDataLength() const
291 {
292 return 1;
293 }
294
295
Decode(PASN_Stream & strm)296 PBoolean PASN_Boolean::Decode(PASN_Stream & strm)
297 {
298 return strm.BooleanDecode(*this);
299 }
300
301
Encode(PASN_Stream & strm) const302 void PASN_Boolean::Encode(PASN_Stream & strm) const
303 {
304 strm.BooleanEncode(*this);
305 }
306
307
308 ///////////////////////////////////////////////////////////////////////
309
PASN_Integer(unsigned val)310 PASN_Integer::PASN_Integer(unsigned val)
311 : PASN_ConstrainedObject(UniversalInteger, UniversalTagClass)
312 {
313 value = val;
314 }
315
316
PASN_Integer(unsigned tag,TagClass tagClass,unsigned val)317 PASN_Integer::PASN_Integer(unsigned tag, TagClass tagClass, unsigned val)
318 : PASN_ConstrainedObject(tag, tagClass)
319 {
320 value = val;
321 }
322
323
IsUnsigned() const324 PBoolean PASN_Integer::IsUnsigned() const
325 {
326 return constraint != Unconstrained && lowerLimit >= 0;
327 }
328
329
operator =(unsigned val)330 PASN_Integer & PASN_Integer::operator=(unsigned val)
331 {
332 if (constraint == Unconstrained)
333 value = val;
334 else if (lowerLimit >= 0) { // Is unsigned integer
335 if (val < (unsigned)lowerLimit)
336 value = lowerLimit;
337 else if (val > upperLimit)
338 value = upperLimit;
339 else
340 value = val;
341 }
342 else {
343 int ival = (int)val;
344 if (ival < lowerLimit)
345 value = lowerLimit;
346 else if (upperLimit < INT_MAX && ival > (int)upperLimit)
347 value = upperLimit;
348 else
349 value = val;
350 }
351
352 return *this;
353 }
354
355
Compare(const PObject & obj) const356 PObject::Comparison PASN_Integer::Compare(const PObject & obj) const
357 {
358 PAssert(PIsDescendant(&obj, PASN_Integer), PInvalidCast);
359 const PASN_Integer & other = (const PASN_Integer &)obj;
360
361 if (IsUnsigned()) {
362 if (value < other.value)
363 return LessThan;
364 if (value > other.value)
365 return GreaterThan;
366 }
367 else {
368 if ((int)value < (int)other.value)
369 return LessThan;
370 if ((int)value > (int)other.value)
371 return GreaterThan;
372 }
373 return EqualTo;
374 }
375
376
Clone() const377 PObject * PASN_Integer::Clone() const
378 {
379 PAssert(IsClass(PASN_Integer::Class()), PInvalidCast);
380 return new PASN_Integer(*this);
381 }
382
383
PrintOn(ostream & strm) const384 void PASN_Integer::PrintOn(ostream & strm) const
385 {
386 if (constraint == Unconstrained || lowerLimit < 0)
387 strm << (int)value;
388 else
389 strm << value;
390 }
391
392
SetConstraintBounds(ConstraintType type,int lower,unsigned upper)393 void PASN_Integer::SetConstraintBounds(ConstraintType type, int lower, unsigned upper)
394 {
395 PASN_ConstrainedObject::SetConstraintBounds(type, lower, upper);
396 operator=(value);
397 }
398
399
GetTypeAsString() const400 PString PASN_Integer::GetTypeAsString() const
401 {
402 return "Integer";
403 }
404
405
GetIntegerDataLength(int value)406 static PINDEX GetIntegerDataLength(int value)
407 {
408 // create a mask which is the top nine bits of a DWORD, or 0xFF800000
409 // on a big endian machine
410 int shift = (sizeof(value)-1)*8-1;
411
412 // remove all sequences of nine 0's or 1's at the start of the value
413 while (shift > 0 && ((value >> shift)&0x1ff) == (value < 0 ? 0x1ff : 0))
414 shift -= 8;
415
416 return (shift+9)/8;
417 }
418
419
GetDataLength() const420 PINDEX PASN_Integer::GetDataLength() const
421 {
422 return GetIntegerDataLength(value);
423 }
424
425
Decode(PASN_Stream & strm)426 PBoolean PASN_Integer::Decode(PASN_Stream & strm)
427 {
428 return strm.IntegerDecode(*this);
429 }
430
431
Encode(PASN_Stream & strm) const432 void PASN_Integer::Encode(PASN_Stream & strm) const
433 {
434 strm.IntegerEncode(*this);
435 }
436
437
438 ///////////////////////////////////////////////////////////////////////
439
PASN_Enumeration(unsigned val)440 PASN_Enumeration::PASN_Enumeration(unsigned val)
441 : PASN_Object(UniversalEnumeration, UniversalTagClass, PFalse),names(NULL),namesCount(0)
442 {
443 value = val;
444 maxEnumValue = P_MAX_INDEX;
445 }
446
447
PASN_Enumeration(unsigned tag,TagClass tagClass,unsigned maxEnum,PBoolean extend,unsigned val)448 PASN_Enumeration::PASN_Enumeration(unsigned tag, TagClass tagClass,
449 unsigned maxEnum, PBoolean extend,
450 unsigned val)
451 : PASN_Object(tag, tagClass, extend),names(NULL),namesCount(0)
452 {
453 value = val;
454 maxEnumValue = maxEnum;
455 }
456
457
458
PASN_Enumeration(unsigned tag,TagClass tagClass,unsigned maxEnum,PBoolean extend,const PASN_Names * nameSpec,unsigned namesCnt,unsigned val)459 PASN_Enumeration::PASN_Enumeration(unsigned tag, TagClass tagClass,
460 unsigned maxEnum, PBoolean extend,
461 const PASN_Names * nameSpec,
462 unsigned namesCnt,
463 unsigned val)
464 : PASN_Object(tag, tagClass, extend),
465 names(nameSpec),namesCount(namesCnt)
466 {
467 maxEnumValue = maxEnum;
468
469 PAssert(val <= maxEnum, PInvalidParameter);
470 value = val;
471 }
472
473
Compare(const PObject & obj) const474 PObject::Comparison PASN_Enumeration::Compare(const PObject & obj) const
475 {
476 PAssert(PIsDescendant(&obj, PASN_Enumeration), PInvalidCast);
477 const PASN_Enumeration & other = (const PASN_Enumeration &)obj;
478
479 if (value < other.value)
480 return LessThan;
481
482 if (value > other.value)
483 return GreaterThan;
484
485 return EqualTo;
486 }
487
488
Clone() const489 PObject * PASN_Enumeration::Clone() const
490 {
491 PAssert(IsClass(PASN_Enumeration::Class()), PInvalidCast);
492 return new PASN_Enumeration(*this);
493 }
494
495
PrintOn(ostream & strm) const496 void PASN_Enumeration::PrintOn(ostream & strm) const
497 {
498 PINDEX idx = FindNameByValue(names, namesCount, value);
499 if (idx != P_MAX_INDEX)
500 strm << names[idx].name;
501 else
502 strm << '<' << value << '>';
503 }
504
505
GetTypeAsString() const506 PString PASN_Enumeration::GetTypeAsString() const
507 {
508 return "Enumeration";
509 }
510
511
GetDataLength() const512 PINDEX PASN_Enumeration::GetDataLength() const
513 {
514 return GetIntegerDataLength(value);
515 }
516
517
Decode(PASN_Stream & strm)518 PBoolean PASN_Enumeration::Decode(PASN_Stream & strm)
519 {
520 return strm.EnumerationDecode(*this);
521 }
522
523
Encode(PASN_Stream & strm) const524 void PASN_Enumeration::Encode(PASN_Stream & strm) const
525 {
526 strm.EnumerationEncode(*this);
527 }
528
GetValueByName(PString name) const529 PINDEX PASN_Enumeration::GetValueByName(PString name) const
530 {
531 for(unsigned uiIndex = 0; uiIndex < namesCount; uiIndex++){
532 if(strcmp(names[uiIndex].name, name) == 0){
533 return (maxEnumValue - namesCount + uiIndex + 1);
534 }
535 }
536 return UINT_MAX;
537 }
538
539 ///////////////////////////////////////////////////////////////////////
540
PASN_Real(double val)541 PASN_Real::PASN_Real(double val)
542 : PASN_Object(UniversalReal, UniversalTagClass)
543 {
544 value = val;
545 }
546
547
PASN_Real(unsigned tag,TagClass tagClass,double val)548 PASN_Real::PASN_Real(unsigned tag, TagClass tagClass, double val)
549 : PASN_Object(tag, tagClass)
550 {
551 value = val;
552 }
553
554
Compare(const PObject & obj) const555 PObject::Comparison PASN_Real::Compare(const PObject & obj) const
556 {
557 PAssert(PIsDescendant(&obj, PASN_Real), PInvalidCast);
558 const PASN_Real & other = (const PASN_Real &)obj;
559
560 if (value < other.value)
561 return LessThan;
562
563 if (value > other.value)
564 return GreaterThan;
565
566 return EqualTo;
567 }
568
569
Clone() const570 PObject * PASN_Real::Clone() const
571 {
572 PAssert(IsClass(PASN_Real::Class()), PInvalidCast);
573 return new PASN_Real(*this);
574 }
575
576
PrintOn(ostream & strm) const577 void PASN_Real::PrintOn(ostream & strm) const
578 {
579 strm << value;
580 }
581
582
GetTypeAsString() const583 PString PASN_Real::GetTypeAsString() const
584 {
585 return "Real";
586 }
587
588
GetDataLength() const589 PINDEX PASN_Real::GetDataLength() const
590 {
591 PAssertAlways(PUnimplementedFunction);
592 return 0;
593 }
594
595
Decode(PASN_Stream & strm)596 PBoolean PASN_Real::Decode(PASN_Stream & strm)
597 {
598 return strm.RealDecode(*this);
599 }
600
601
Encode(PASN_Stream & strm) const602 void PASN_Real::Encode(PASN_Stream & strm) const
603 {
604 strm.RealEncode(*this);
605 }
606
607
608 ///////////////////////////////////////////////////////////////////////
609
PASN_ObjectId(const char * dotstr)610 PASN_ObjectId::PASN_ObjectId(const char * dotstr)
611 : PASN_Object(UniversalObjectId, UniversalTagClass)
612 {
613 if (dotstr != NULL)
614 SetValue(dotstr);
615 }
616
617
PASN_ObjectId(unsigned tag,TagClass tagClass)618 PASN_ObjectId::PASN_ObjectId(unsigned tag, TagClass tagClass)
619 : PASN_Object(tag, tagClass)
620 {
621 }
622
623
PASN_ObjectId(const PASN_ObjectId & other)624 PASN_ObjectId::PASN_ObjectId(const PASN_ObjectId & other)
625 : PASN_Object(other),
626 value(other.value, other.GetSize())
627 {
628 }
629
630
operator =(const PASN_ObjectId & other)631 PASN_ObjectId & PASN_ObjectId::operator=(const PASN_ObjectId & other)
632 {
633 PASN_Object::operator=(other);
634 value = PUnsignedArray(other.value, other.GetSize());
635 return *this;
636 }
637
638
operator =(const char * dotstr)639 PASN_ObjectId & PASN_ObjectId::operator=(const char * dotstr)
640 {
641 if (dotstr != NULL)
642 SetValue(dotstr);
643 else
644 value.SetSize(0);
645 return *this;
646 }
647
648
operator =(const PString & dotstr)649 PASN_ObjectId & PASN_ObjectId::operator=(const PString & dotstr)
650 {
651 SetValue(dotstr);
652 return *this;
653 }
654
655
operator =(const PUnsignedArray & numbers)656 PASN_ObjectId & PASN_ObjectId::operator=(const PUnsignedArray & numbers)
657 {
658 SetValue(numbers);
659 return *this;
660 }
661
662
SetValue(const PString & dotstr)663 void PASN_ObjectId::SetValue(const PString & dotstr)
664 {
665 PStringArray parts = dotstr.Tokenise('.');
666 value.SetSize(parts.GetSize());
667 for (PINDEX i = 0; i < parts.GetSize(); i++)
668 value[i] = parts[i].AsUnsigned();
669 }
670
671
SetValue(const unsigned * numbers,PINDEX size)672 void PASN_ObjectId::SetValue(const unsigned * numbers, PINDEX size)
673 {
674 value = PUnsignedArray(numbers, size);
675 }
676
677
operator ==(const char * dotstr) const678 bool PASN_ObjectId::operator==(const char * dotstr) const
679 {
680 PASN_ObjectId id;
681 id.SetValue(dotstr);
682 return *this == id;
683 }
684
685
Compare(const PObject & obj) const686 PObject::Comparison PASN_ObjectId::Compare(const PObject & obj) const
687 {
688 PAssert(PIsDescendant(&obj, PASN_ObjectId), PInvalidCast);
689 const PASN_ObjectId & other = (const PASN_ObjectId &)obj;
690 return value.Compare(other.value);
691 }
692
693
Clone() const694 PObject * PASN_ObjectId::Clone() const
695 {
696 PAssert(IsClass(PASN_ObjectId::Class()), PInvalidCast);
697 return new PASN_ObjectId(*this);
698 }
699
700
PrintOn(ostream & strm) const701 void PASN_ObjectId::PrintOn(ostream & strm) const
702 {
703 for (PINDEX i = 0; i < value.GetSize(); i++) {
704 strm << (unsigned)value[i];
705 if (i < value.GetSize()-1)
706 strm << '.';
707 }
708 }
709
710
AsString() const711 PString PASN_ObjectId::AsString() const
712 {
713 PStringStream s;
714 PrintOn(s);
715 return s;
716 }
717
718
GetTypeAsString() const719 PString PASN_ObjectId::GetTypeAsString() const
720 {
721 return "Object ID";
722 }
723
724
CommonDecode(PASN_Stream & strm,unsigned dataLen)725 PBoolean PASN_ObjectId::CommonDecode(PASN_Stream & strm, unsigned dataLen)
726 {
727 value.SetSize(0);
728
729 // handle zero length strings correctly
730 if (dataLen == 0)
731 return PTrue;
732
733 unsigned subId;
734
735 // start at the second identifier in the buffer, because we will later
736 // expand the first number into the first two IDs
737 PINDEX i = 1;
738 while (dataLen > 0) {
739 unsigned byte;
740 subId = 0;
741 do { /* shift and add in low order 7 bits */
742 if (strm.IsAtEnd())
743 return PFalse;
744 byte = strm.ByteDecode();
745 subId = (subId << 7) + (byte & 0x7f);
746 dataLen--;
747 } while ((byte & 0x80) != 0);
748 value.SetAt(i++, subId);
749 }
750
751 /*
752 * The first two subidentifiers are encoded into the first component
753 * with the value (X * 40) + Y, where:
754 * X is the value of the first subidentifier.
755 * Y is the value of the second subidentifier.
756 */
757 subId = value[1];
758 if (subId < 40) {
759 value[0] = 0;
760 value[1] = subId;
761 }
762 else if (subId < 80) {
763 value[0] = 1;
764 value[1] = subId-40;
765 }
766 else {
767 value[0] = 2;
768 value[1] = subId-80;
769 }
770
771 return PTrue;
772 }
773
774
CommonEncode(PBYTEArray & encodecObjectId) const775 void PASN_ObjectId::CommonEncode(PBYTEArray & encodecObjectId) const
776 {
777 PINDEX length = value.GetSize();
778 const unsigned * objId = value;
779
780 if (length < 2) {
781 // Thise case is really illegal, but we have to do SOMETHING
782 encodecObjectId.SetSize(0);
783 return;
784 }
785
786 unsigned subId = (objId[0] * 40) + objId[1];
787 objId += 2;
788
789 PINDEX outputPosition = 0;
790
791 while (--length > 0) {
792 if (subId < 128)
793 encodecObjectId[outputPosition++] = (BYTE)subId;
794 else {
795 unsigned mask = 0x7F; /* handle subid == 0 case */
796 int bits = 0;
797
798 /* testmask *MUST* !!!! be of an unsigned type */
799 unsigned testmask = 0x7F;
800 int testbits = 0;
801 while (testmask != 0) {
802 if (subId & testmask) { /* if any bits set */
803 mask = testmask;
804 bits = testbits;
805 }
806 testmask <<= 7;
807 testbits += 7;
808 }
809
810 /* mask can't be zero here */
811 while (mask != 0x7F) {
812 /* fix a mask that got truncated above */
813 if (mask == 0x1E00000)
814 mask = 0xFE00000;
815
816 encodecObjectId[outputPosition++] = (BYTE)(((subId & mask) >> bits) | 0x80);
817
818 mask >>= 7;
819 bits -= 7;
820 }
821
822 encodecObjectId[outputPosition++] = (BYTE)(subId & mask);
823 }
824
825 if (length > 1)
826 subId = *objId++;
827 }
828 }
829
830
GetDataLength() const831 PINDEX PASN_ObjectId::GetDataLength() const
832 {
833 PBYTEArray dummy;
834 CommonEncode(dummy);
835 return dummy.GetSize();
836 }
837
838
Decode(PASN_Stream & strm)839 PBoolean PASN_ObjectId::Decode(PASN_Stream & strm)
840 {
841 return strm.ObjectIdDecode(*this);
842 }
843
844
Encode(PASN_Stream & strm) const845 void PASN_ObjectId::Encode(PASN_Stream & strm) const
846 {
847 strm.ObjectIdEncode(*this);
848 }
849
850
851 ///////////////////////////////////////////////////////////////////////
852
PASN_BitString(unsigned nBits,const BYTE * buf)853 PASN_BitString::PASN_BitString(unsigned nBits, const BYTE * buf)
854 : PASN_ConstrainedObject(UniversalBitString, UniversalTagClass),
855 totalBits(nBits),
856 bitData((totalBits+7)/8)
857 {
858 if (buf != NULL)
859 memcpy(bitData.GetPointer(), buf, bitData.GetSize());
860 }
861
862
PASN_BitString(unsigned tag,TagClass tagClass,unsigned nBits)863 PASN_BitString::PASN_BitString(unsigned tag, TagClass tagClass, unsigned nBits)
864 : PASN_ConstrainedObject(tag, tagClass),
865 totalBits(nBits),
866 bitData((totalBits+7)/8)
867 {
868 }
869
870
PASN_BitString(const PASN_BitString & other)871 PASN_BitString::PASN_BitString(const PASN_BitString & other)
872 : PASN_ConstrainedObject(other),
873 bitData(other.bitData, other.bitData.GetSize())
874 {
875 totalBits = other.totalBits;
876 }
877
878
operator =(const PASN_BitString & other)879 PASN_BitString & PASN_BitString::operator=(const PASN_BitString & other)
880 {
881 PASN_ConstrainedObject::operator=(other);
882 totalBits = other.totalBits;
883 bitData = PBYTEArray(other.bitData, other.bitData.GetSize());
884 return *this;
885 }
886
887
SetData(unsigned nBits,const PBYTEArray & bytes)888 void PASN_BitString::SetData(unsigned nBits, const PBYTEArray & bytes)
889 {
890 if ((PINDEX)nBits >= MaximumStringSize)
891 return;
892
893 bitData = bytes;
894 SetSize(nBits);
895 }
896
897
SetData(unsigned nBits,const BYTE * buf,PINDEX size)898 void PASN_BitString::SetData(unsigned nBits, const BYTE * buf, PINDEX size)
899 {
900 if ((PINDEX)nBits >= MaximumStringSize)
901 return;
902
903 if (size == 0)
904 size = (nBits+7)/8;
905 memcpy(bitData.GetPointer(size), buf, size);
906 SetSize(nBits);
907 }
908
909
SetSize(unsigned nBits)910 PBoolean PASN_BitString::SetSize(unsigned nBits)
911 {
912 if (!CheckByteOffset(nBits))
913 return PFalse;
914
915 if (constraint == Unconstrained)
916 totalBits = nBits;
917 else if (totalBits < (unsigned)lowerLimit) {
918 if (lowerLimit < 0)
919 return PFalse;
920 totalBits = lowerLimit;
921 } else if ((unsigned)totalBits > upperLimit) {
922 if (upperLimit > (unsigned)MaximumSetSize)
923 return PFalse;
924 totalBits = upperLimit;
925 } else
926 totalBits = nBits;
927 return bitData.SetSize((totalBits+7)/8);
928 }
929
930
operator [](PINDEX bit) const931 bool PASN_BitString::operator[](PINDEX bit) const
932 {
933 if ((unsigned)bit < totalBits)
934 return (bitData[bit>>3] & (1 << (7 - (bit&7)))) != 0;
935 return PFalse;
936 }
937
938
Set(unsigned bit)939 void PASN_BitString::Set(unsigned bit)
940 {
941 if (bit < totalBits)
942 bitData[(PINDEX)(bit>>3)] |= 1 << (7 - (bit&7));
943 }
944
945
Clear(unsigned bit)946 void PASN_BitString::Clear(unsigned bit)
947 {
948 if (bit < totalBits)
949 bitData[(PINDEX)(bit>>3)] &= ~(1 << (7 - (bit&7)));
950 }
951
952
Invert(unsigned bit)953 void PASN_BitString::Invert(unsigned bit)
954 {
955 if (bit < totalBits)
956 bitData[(PINDEX)(bit>>3)] ^= 1 << (7 - (bit&7));
957 }
958
959
Compare(const PObject & obj) const960 PObject::Comparison PASN_BitString::Compare(const PObject & obj) const
961 {
962 PAssert(PIsDescendant(&obj, PASN_BitString), PInvalidCast);
963 const PASN_BitString & other = (const PASN_BitString &)obj;
964 if (totalBits < other.totalBits)
965 return LessThan;
966 if (totalBits > other.totalBits)
967 return GreaterThan;
968 return bitData.Compare(other.bitData);
969 }
970
971
Clone() const972 PObject * PASN_BitString::Clone() const
973 {
974 PAssert(IsClass(PASN_BitString::Class()), PInvalidCast);
975 return new PASN_BitString(*this);
976 }
977
978
PrintOn(ostream & strm) const979 void PASN_BitString::PrintOn(ostream & strm) const
980 {
981 int indent = (int)strm.precision() + 2;
982 ios::fmtflags flags = strm.flags();
983
984 if (totalBits > 128)
985 strm << "Hex {\n"
986 << hex << setfill('0') << resetiosflags(ios::floatfield) << setiosflags(ios::fixed)
987 << setw(16) << setprecision(indent) << bitData
988 << dec << setfill(' ') << resetiosflags(ios::floatfield)
989 << setw(indent-1) << "}";
990 else if (totalBits > 32)
991 strm << "Hex:"
992 << hex << setfill('0') << resetiosflags(ios::floatfield) << setiosflags(ios::fixed)
993 << setprecision(2) << setw(16) << bitData
994 << dec << setfill(' ') << resetiosflags(ios::floatfield);
995 else {
996 BYTE mask = 0x80;
997 PINDEX offset = 0;
998 for (unsigned i = 0; i < totalBits; i++) {
999 strm << ((bitData[offset]&mask) != 0 ? '1' : '0');
1000 mask >>= 1;
1001 if (mask == 0) {
1002 mask = 0x80;
1003 offset++;
1004 }
1005 }
1006 }
1007
1008 strm.flags(flags);
1009 }
1010
1011
SetConstraintBounds(ConstraintType type,int lower,unsigned upper)1012 void PASN_BitString::SetConstraintBounds(ConstraintType type, int lower, unsigned upper)
1013 {
1014 if (lower < 0)
1015 return;
1016
1017 PASN_ConstrainedObject::SetConstraintBounds(type, lower, upper);
1018 SetSize(GetSize());
1019 }
1020
1021
GetTypeAsString() const1022 PString PASN_BitString::GetTypeAsString() const
1023 {
1024 return "Bit String";
1025 }
1026
1027
GetDataLength() const1028 PINDEX PASN_BitString::GetDataLength() const
1029 {
1030 return (totalBits+7)/8 + 1;
1031 }
1032
1033
Decode(PASN_Stream & strm)1034 PBoolean PASN_BitString::Decode(PASN_Stream & strm)
1035 {
1036 return strm.BitStringDecode(*this);
1037 }
1038
1039
Encode(PASN_Stream & strm) const1040 void PASN_BitString::Encode(PASN_Stream & strm) const
1041 {
1042 strm.BitStringEncode(*this);
1043 }
1044
1045
1046 ///////////////////////////////////////////////////////////////////////
1047
PASN_OctetString(const char * str,PINDEX size)1048 PASN_OctetString::PASN_OctetString(const char * str, PINDEX size)
1049 : PASN_ConstrainedObject(UniversalOctetString, UniversalTagClass)
1050 {
1051 if (str != NULL) {
1052 if (size == 0)
1053 size = ::strlen(str);
1054 SetValue((const BYTE *)str, size);
1055 }
1056 }
1057
1058
PASN_OctetString(unsigned tag,TagClass tagClass)1059 PASN_OctetString::PASN_OctetString(unsigned tag, TagClass tagClass)
1060 : PASN_ConstrainedObject(tag, tagClass)
1061 {
1062 }
1063
1064
PASN_OctetString(const PASN_OctetString & other)1065 PASN_OctetString::PASN_OctetString(const PASN_OctetString & other)
1066 : PASN_ConstrainedObject(other),
1067 value(other.value, other.GetSize())
1068 {
1069 }
1070
1071
operator =(const PASN_OctetString & other)1072 PASN_OctetString & PASN_OctetString::operator=(const PASN_OctetString & other)
1073 {
1074 PASN_ConstrainedObject::operator=(other);
1075 value = PBYTEArray(other.value, other.GetSize());
1076 return *this;
1077 }
1078
1079
operator =(const char * str)1080 PASN_OctetString & PASN_OctetString::operator=(const char * str)
1081 {
1082 if (str == NULL)
1083 value.SetSize(lowerLimit);
1084 else
1085 SetValue((const BYTE *)str, strlen(str));
1086 return *this;
1087 }
1088
1089
operator =(const PString & str)1090 PASN_OctetString & PASN_OctetString::operator=(const PString & str)
1091 {
1092 SetValue((const BYTE *)(const char *)str, str.GetSize()-1);
1093 return *this;
1094 }
1095
1096
operator =(const PBYTEArray & arr)1097 PASN_OctetString & PASN_OctetString::operator=(const PBYTEArray & arr)
1098 {
1099 PINDEX len = arr.GetSize();
1100 if ((unsigned)len > upperLimit || (int)len < lowerLimit)
1101 SetValue(arr, len);
1102 else
1103 value = arr;
1104 return *this;
1105 }
1106
1107
SetValue(const BYTE * data,PINDEX len)1108 void PASN_OctetString::SetValue(const BYTE * data, PINDEX len)
1109 {
1110 if ((unsigned)len > upperLimit)
1111 len = upperLimit;
1112 if (SetSize((int)len < lowerLimit ? lowerLimit : len))
1113 memcpy(value.GetPointer(), data, len);
1114 }
1115
1116
AsString() const1117 PString PASN_OctetString::AsString() const
1118 {
1119 if (value.IsEmpty())
1120 return PString();
1121 return PString((const char *)(const BYTE *)value, value.GetSize());
1122 }
1123
1124
Compare(const PObject & obj) const1125 PObject::Comparison PASN_OctetString::Compare(const PObject & obj) const
1126 {
1127 PAssert(PIsDescendant(&obj, PASN_OctetString), PInvalidCast);
1128 const PASN_OctetString & other = (const PASN_OctetString &)obj;
1129 return value.Compare(other.value);
1130 }
1131
1132
Clone() const1133 PObject * PASN_OctetString::Clone() const
1134 {
1135 PAssert(IsClass(PASN_OctetString::Class()), PInvalidCast);
1136 return new PASN_OctetString(*this);
1137 }
1138
1139
PrintOn(ostream & strm) const1140 void PASN_OctetString::PrintOn(ostream & strm) const
1141 {
1142 int indent = (int)strm.precision() + 2;
1143 ios::fmtflags flags = strm.flags();
1144
1145 strm << ' ' << value.GetSize() << " octets {\n"
1146 << hex << setfill('0') << resetiosflags(ios::floatfield)
1147 << setprecision(indent) << setw(16);
1148
1149 if (value.GetSize() <= 32 || (flags&ios::floatfield) != ios::fixed)
1150 strm << value << '\n';
1151 else {
1152 PBYTEArray truncatedArray(value, 32);
1153 strm << truncatedArray << '\n'
1154 << setfill(' ')
1155 << setw(indent+4) << "...\n";
1156 }
1157
1158 strm << dec << setfill(' ')
1159 << setw(indent-1) << "}";
1160
1161 strm.flags(flags);
1162 }
1163
1164
SetConstraintBounds(ConstraintType type,int lower,unsigned upper)1165 void PASN_OctetString::SetConstraintBounds(ConstraintType type, int lower, unsigned upper)
1166 {
1167 if (lower < 0)
1168 return;
1169
1170 PASN_ConstrainedObject::SetConstraintBounds(type, lower, upper);
1171 SetSize(GetSize());
1172 }
1173
1174
GetTypeAsString() const1175 PString PASN_OctetString::GetTypeAsString() const
1176 {
1177 return "Octet String";
1178 }
1179
1180
GetDataLength() const1181 PINDEX PASN_OctetString::GetDataLength() const
1182 {
1183 return value.GetSize();
1184 }
1185
1186
SetSize(PINDEX newSize)1187 PBoolean PASN_OctetString::SetSize(PINDEX newSize)
1188 {
1189 if (!CheckByteOffset(newSize, MaximumStringSize))
1190 return PFalse;
1191
1192 if (constraint != Unconstrained) {
1193 if (newSize < (PINDEX)lowerLimit) {
1194 if (lowerLimit < 0)
1195 return PFalse;
1196 newSize = lowerLimit;
1197 } else if ((unsigned)newSize > upperLimit) {
1198 if (upperLimit > (unsigned)MaximumStringSize)
1199 return PFalse;
1200 newSize = upperLimit;
1201 }
1202 }
1203
1204 return value.SetSize(newSize);
1205 }
1206
1207
Decode(PASN_Stream & strm)1208 PBoolean PASN_OctetString::Decode(PASN_Stream & strm)
1209 {
1210 return strm.OctetStringDecode(*this);
1211 }
1212
1213
Encode(PASN_Stream & strm) const1214 void PASN_OctetString::Encode(PASN_Stream & strm) const
1215 {
1216 strm.OctetStringEncode(*this);
1217 }
1218
1219 ///////////////////////////////////////////////////////////////////////
1220
PASN_ConstrainedString(const char * canonical,PINDEX size,unsigned tag,TagClass tagClass)1221 PASN_ConstrainedString::PASN_ConstrainedString(const char * canonical, PINDEX size,
1222 unsigned tag, TagClass tagClass)
1223 : PASN_ConstrainedObject(tag, tagClass)
1224 {
1225 canonicalSet = canonical;
1226 canonicalSetSize = size;
1227 canonicalSetBits = CountBits(size);
1228 SetCharacterSet(canonicalSet, canonicalSetSize, Unconstrained);
1229 }
1230
1231
operator =(const char * str)1232 PASN_ConstrainedString & PASN_ConstrainedString::operator=(const char * str)
1233 {
1234 if (str == NULL)
1235 str = "";
1236
1237 PStringStream newValue;
1238
1239 PINDEX len = strlen(str);
1240
1241 // Can't copy any more characters than the upper constraint
1242 if ((unsigned)len > upperLimit)
1243 len = upperLimit;
1244
1245 // Now copy individual characters, if they are in character set constraint
1246 for (PINDEX i = 0; i < len; i++) {
1247 PINDEX sz = characterSet.GetSize();
1248 if (sz == 0 || memchr(characterSet, str[i], sz) != NULL)
1249 newValue << str[i];
1250 }
1251
1252 // Make sure string meets minimum length constraint
1253 while ((int)len < lowerLimit) {
1254 newValue << characterSet[0];
1255 len++;
1256 }
1257
1258 value = newValue;
1259 value.MakeMinimumSize();
1260 return *this;
1261 }
1262
1263
SetCharacterSet(ConstraintType ctype,const char * set)1264 void PASN_ConstrainedString::SetCharacterSet(ConstraintType ctype, const char * set)
1265 {
1266 SetCharacterSet(set, strlen(set), ctype);
1267 }
1268
1269
SetCharacterSet(ConstraintType ctype,unsigned firstChar,unsigned lastChar)1270 void PASN_ConstrainedString::SetCharacterSet(ConstraintType ctype, unsigned firstChar, unsigned lastChar)
1271 {
1272 char buffer[256];
1273 for (unsigned i = firstChar; i < lastChar; i++)
1274 buffer[i] = (char)i;
1275 SetCharacterSet(buffer, lastChar - firstChar + 1, ctype);
1276 }
1277
1278
SetCharacterSet(const char * set,PINDEX setSize,ConstraintType ctype)1279 void PASN_ConstrainedString::SetCharacterSet(const char * set, PINDEX setSize, ConstraintType ctype)
1280 {
1281 if (ctype == Unconstrained) {
1282 characterSet.SetSize(canonicalSetSize);
1283 memcpy(characterSet.GetPointer(), canonicalSet, canonicalSetSize);
1284 }
1285 else if (setSize >= MaximumSetSize ||
1286 canonicalSetSize >= MaximumSetSize ||
1287 characterSet.GetSize() >= MaximumSetSize)
1288 return;
1289 else {
1290 characterSet.SetSize(setSize);
1291 PINDEX count = 0;
1292 for (PINDEX i = 0; i < canonicalSetSize; i++) {
1293 if (memchr(set, canonicalSet[i], setSize) != NULL)
1294 characterSet[count++] = canonicalSet[i];
1295 }
1296 if (count < 0)
1297 return;
1298 characterSet.SetSize(count);
1299 }
1300
1301 charSetUnalignedBits = CountBits(characterSet.GetSize());
1302
1303 charSetAlignedBits = 1;
1304 while (charSetUnalignedBits > charSetAlignedBits)
1305 charSetAlignedBits <<= 1;
1306
1307 operator=((const char *)value);
1308 }
1309
1310
Compare(const PObject & obj) const1311 PObject::Comparison PASN_ConstrainedString::Compare(const PObject & obj) const
1312 {
1313 PAssert(PIsDescendant(&obj, PASN_ConstrainedString), PInvalidCast);
1314 const PASN_ConstrainedString & other = (const PASN_ConstrainedString &)obj;
1315 return value.Compare(other.value);
1316 }
1317
1318
PrintOn(ostream & strm) const1319 void PASN_ConstrainedString::PrintOn(ostream & strm) const
1320 {
1321 strm << value.ToLiteral();
1322 }
1323
1324
SetConstraintBounds(ConstraintType type,int lower,unsigned upper)1325 void PASN_ConstrainedString::SetConstraintBounds(ConstraintType type,
1326 int lower, unsigned upper)
1327 {
1328 if (lower < 0)
1329 return;
1330
1331 PASN_ConstrainedObject::SetConstraintBounds(type, lower, upper);
1332 if (constraint != Unconstrained) {
1333 if (value.GetSize() < (PINDEX)lowerLimit)
1334 value.SetSize(lowerLimit);
1335 else if ((unsigned)value.GetSize() > upperLimit)
1336 value.SetSize(upperLimit);
1337 }
1338 }
1339
1340
GetDataLength() const1341 PINDEX PASN_ConstrainedString::GetDataLength() const
1342 {
1343 return value.GetSize()-1;
1344 }
1345
1346
Decode(PASN_Stream & strm)1347 PBoolean PASN_ConstrainedString::Decode(PASN_Stream & strm)
1348 {
1349 return strm.ConstrainedStringDecode(*this);
1350 }
1351
1352
Encode(PASN_Stream & strm) const1353 void PASN_ConstrainedString::Encode(PASN_Stream & strm) const
1354 {
1355 strm.ConstrainedStringEncode(*this);
1356 }
1357
1358
1359 #define DEFINE_STRING_CLASS(name, set) \
1360 static const char name##StringSet[] = set; \
1361 PASN_##name##String::PASN_##name##String(const char * str) \
1362 : PASN_ConstrainedString(name##StringSet, sizeof(name##StringSet)-1, \
1363 Universal##name##String, UniversalTagClass) \
1364 { PASN_ConstrainedString::SetValue(str); } \
1365 PASN_##name##String::PASN_##name##String(unsigned tag, TagClass tagClass) \
1366 : PASN_ConstrainedString(name##StringSet, sizeof(name##StringSet)-1, tag, tagClass) \
1367 { } \
1368 PASN_##name##String & PASN_##name##String::operator=(const char * str) \
1369 { PASN_ConstrainedString::SetValue(str); return *this; } \
1370 PASN_##name##String & PASN_##name##String::operator=(const PString & str) \
1371 { PASN_ConstrainedString::SetValue(str); return *this; } \
1372 PObject * PASN_##name##String::Clone() const \
1373 { PAssert(IsClass(PASN_##name##String::Class()), PInvalidCast); \
1374 return new PASN_##name##String(*this); } \
1375 PString PASN_##name##String::GetTypeAsString() const \
1376 { return #name " String"; }
1377
1378 DEFINE_STRING_CLASS(Numeric, " 0123456789")
1379 DEFINE_STRING_CLASS(Printable, " '()+,-./0123456789:=?"
1380 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
1381 "abcdefghijklmnopqrstuvwxyz")
1382 DEFINE_STRING_CLASS(Visible, " !\"#$%&'()*+,-./0123456789:;<=>?"
1383 "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
1384 "`abcdefghijklmnopqrstuvwxyz{|}~")
1385 DEFINE_STRING_CLASS(IA5, "\000\001\002\003\004\005\006\007"
1386 "\010\011\012\013\014\015\016\017"
1387 "\020\021\022\023\024\025\026\027"
1388 "\030\031\032\033\034\035\036\037"
1389 " !\"#$%&'()*+,-./0123456789:;<=>?"
1390 "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
1391 "`abcdefghijklmnopqrstuvwxyz{|}~\177")
1392 DEFINE_STRING_CLASS(General, "\000\001\002\003\004\005\006\007"
1393 "\010\011\012\013\014\015\016\017"
1394 "\020\021\022\023\024\025\026\027"
1395 "\030\031\032\033\034\035\036\037"
1396 " !\"#$%&'()*+,-./0123456789:;<=>?"
1397 "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
1398 "`abcdefghijklmnopqrstuvwxyz{|}~\177"
1399 "\200\201\202\203\204\205\206\207"
1400 "\210\211\212\213\214\215\216\217"
1401 "\220\221\222\223\224\225\226\227"
1402 "\230\231\232\233\234\235\236\237"
1403 "\240\241\242\243\244\245\246\247"
1404 "\250\251\252\253\254\255\256\257"
1405 "\260\261\262\263\264\265\266\267"
1406 "\270\271\272\273\274\275\276\277"
1407 "\300\301\302\303\304\305\306\307"
1408 "\310\311\312\313\314\315\316\317"
1409 "\320\321\322\323\324\325\326\327"
1410 "\330\331\332\333\334\335\336\337"
1411 "\340\341\342\343\344\345\346\347"
1412 "\350\351\352\353\354\355\356\357"
1413 "\360\361\362\363\364\365\366\367"
1414 "\370\371\372\373\374\375\376\377")
1415
1416
1417 ///////////////////////////////////////////////////////////////////////
1418
PASN_BMPString(const char * str)1419 PASN_BMPString::PASN_BMPString(const char * str)
1420 : PASN_ConstrainedObject(UniversalBMPString, UniversalTagClass)
1421 {
1422 Construct();
1423 if (str != NULL)
1424 SetValue(str);
1425 }
1426
1427
PASN_BMPString(const PWCharArray & wstr)1428 PASN_BMPString::PASN_BMPString(const PWCharArray & wstr)
1429 : PASN_ConstrainedObject(UniversalBMPString, UniversalTagClass)
1430 {
1431 Construct();
1432 SetValue(wstr);
1433 }
1434
1435
PASN_BMPString(unsigned tag,TagClass tagClass)1436 PASN_BMPString::PASN_BMPString(unsigned tag, TagClass tagClass)
1437 : PASN_ConstrainedObject(tag, tagClass)
1438 {
1439 Construct();
1440 }
1441
1442
Construct()1443 void PASN_BMPString::Construct()
1444 {
1445 firstChar = 0;
1446 lastChar = 0xffff;
1447 charSetAlignedBits = 16;
1448 charSetUnalignedBits = 16;
1449 }
1450
1451
PASN_BMPString(const PASN_BMPString & other)1452 PASN_BMPString::PASN_BMPString(const PASN_BMPString & other)
1453 : PASN_ConstrainedObject(other),
1454 value(other.value, other.value.GetSize()),
1455 characterSet(other.characterSet)
1456 {
1457 firstChar = other.firstChar;
1458 lastChar = other.lastChar;
1459 charSetAlignedBits = other.charSetAlignedBits;
1460 charSetUnalignedBits = other.charSetUnalignedBits;
1461 }
1462
1463
operator =(const PASN_BMPString & other)1464 PASN_BMPString & PASN_BMPString::operator=(const PASN_BMPString & other)
1465 {
1466 PASN_ConstrainedObject::operator=(other);
1467
1468 value = PWCharArray(other.value, other.value.GetSize());
1469 characterSet = other.characterSet;
1470 firstChar = other.firstChar;
1471 lastChar = other.lastChar;
1472 charSetAlignedBits = other.charSetAlignedBits;
1473 charSetUnalignedBits = other.charSetUnalignedBits;
1474
1475 return *this;
1476 }
1477
1478
IsLegalCharacter(WORD ch)1479 PBoolean PASN_BMPString::IsLegalCharacter(WORD ch)
1480 {
1481 if (ch < firstChar)
1482 return PFalse;
1483
1484 if (ch > lastChar)
1485 return PFalse;
1486
1487 if (characterSet.IsEmpty())
1488 return PTrue;
1489
1490 const wchar_t * wptr = characterSet;
1491 PINDEX count = characterSet.GetSize();
1492 while (count-- > 0) {
1493 if (*wptr == ch)
1494 return PTrue;
1495 wptr++;
1496 }
1497
1498 return PFalse;
1499 }
1500
SetValueRaw(const wchar_t * array,PINDEX paramSize)1501 void PASN_BMPString::SetValueRaw(const wchar_t * array, PINDEX paramSize)
1502 {
1503 // Can't copy any more than the upper constraint
1504 if ((unsigned)paramSize > upperLimit)
1505 paramSize = upperLimit;
1506
1507 // Number of bytes must be at least lhe lower constraint
1508 PINDEX newSize = (int)paramSize < lowerLimit ? lowerLimit : paramSize;
1509 value.SetSize(newSize);
1510
1511 PINDEX count = 0;
1512 for (PINDEX i = 0; i < paramSize; i++) {
1513 WORD c = array[i];
1514 if (IsLegalCharacter(c))
1515 value[count++] = c;
1516 }
1517
1518 // Pad out with the first character till required size
1519 while (count < newSize)
1520 value[count++] = firstChar;
1521
1522 }
1523
operator =(const PWCharArray & array)1524 PASN_BMPString & PASN_BMPString::operator=(const PWCharArray & array)
1525 {
1526 PINDEX paramSize = array.GetSize();
1527
1528 // Remove trailing NULL character, if present
1529 if (paramSize > 0 && array[paramSize-1] == 0)
1530 paramSize--;
1531
1532 SetValueRaw(array, paramSize);
1533
1534 return *this;
1535 }
1536
1537
SetCharacterSet(ConstraintType ctype,const char * charSet)1538 void PASN_BMPString::SetCharacterSet(ConstraintType ctype, const char * charSet)
1539 {
1540 PWCharArray array(strlen(charSet));
1541
1542 PINDEX count = 0;
1543 while (*charSet != '\0')
1544 array[count++] = (BYTE)*charSet++;
1545
1546 SetCharacterSet(ctype, array);
1547 }
1548
1549
SetCharacterSet(ConstraintType ctype,const PWCharArray & charSet)1550 void PASN_BMPString::SetCharacterSet(ConstraintType ctype, const PWCharArray & charSet)
1551 {
1552 if (ctype == Unconstrained) {
1553 firstChar = 0;
1554 lastChar = 0xffff;
1555 characterSet.SetSize(0);
1556 }
1557 else {
1558 characterSet = charSet;
1559
1560 charSetUnalignedBits = CountBits(lastChar - firstChar + 1);
1561 if (!charSet.IsEmpty()) {
1562 unsigned count = 0;
1563 for (PINDEX i = 0; i < charSet.GetSize(); i++) {
1564 if (characterSet[i] >= firstChar && characterSet[i] <= lastChar)
1565 count++;
1566 }
1567 count = CountBits(count);
1568 if (charSetUnalignedBits > count)
1569 charSetUnalignedBits = count;
1570 }
1571
1572 charSetAlignedBits = 1;
1573 while (charSetUnalignedBits > charSetAlignedBits)
1574 charSetAlignedBits <<= 1;
1575
1576 SetValue(value);
1577 }
1578 }
1579
1580
SetCharacterSet(ConstraintType ctype,unsigned first,unsigned last)1581 void PASN_BMPString::SetCharacterSet(ConstraintType ctype, unsigned first, unsigned last)
1582 {
1583 if (ctype != Unconstrained) {
1584 PAssert(first < 0x10000 && last < 0x10000 && last > first, PInvalidParameter);
1585 firstChar = (WORD)first;
1586 lastChar = (WORD)last;
1587 }
1588 SetCharacterSet(ctype, characterSet);
1589 }
1590
1591
Clone() const1592 PObject * PASN_BMPString::Clone() const
1593 {
1594 PAssert(IsClass(PASN_BMPString::Class()), PInvalidCast);
1595 return new PASN_BMPString(*this);
1596 }
1597
1598
Compare(const PObject & obj) const1599 PObject::Comparison PASN_BMPString::Compare(const PObject & obj) const
1600 {
1601 PAssert(PIsDescendant(&obj, PASN_BMPString), PInvalidCast);
1602 const PASN_BMPString & other = (const PASN_BMPString &)obj;
1603 return value.Compare(other.value);
1604 }
1605
1606
PrintOn(ostream & strm) const1607 void PASN_BMPString::PrintOn(ostream & strm) const
1608 {
1609 int indent = (int)strm.precision() + 2;
1610 PINDEX sz = value.GetSize();
1611 strm << ' ' << sz << " characters {\n";
1612 PINDEX i = 0;
1613 while (i < sz) {
1614 strm << setw(indent) << " " << hex << setfill('0');
1615 PINDEX j;
1616 for (j = 0; j < 8; j++)
1617 if (i+j < sz)
1618 strm << setw(4) << value[i+j] << ' ';
1619 else
1620 strm << " ";
1621 strm << " ";
1622 for (j = 0; j < 8; j++) {
1623 if (i+j < sz) {
1624 WORD c = value[i+j];
1625 if (c < 128 && isprint(c))
1626 strm << (char)c;
1627 else
1628 strm << ' ';
1629 }
1630 }
1631 strm << dec << setfill(' ') << '\n';
1632 i += 8;
1633 }
1634 strm << setw(indent-1) << "}";
1635 }
1636
1637
GetTypeAsString() const1638 PString PASN_BMPString::GetTypeAsString() const
1639 {
1640 return "BMP String";
1641 }
1642
1643
GetDataLength() const1644 PINDEX PASN_BMPString::GetDataLength() const
1645 {
1646 return value.GetSize()*2;
1647 }
1648
1649
Decode(PASN_Stream & strm)1650 PBoolean PASN_BMPString::Decode(PASN_Stream & strm)
1651 {
1652 return strm.BMPStringDecode(*this);
1653 }
1654
1655
Encode(PASN_Stream & strm) const1656 void PASN_BMPString::Encode(PASN_Stream & strm) const
1657 {
1658 strm.BMPStringEncode(*this);
1659 }
1660
1661
1662 ///////////////////////////////////////////////////////////////////////
1663
operator =(const PTime & time)1664 PASN_GeneralisedTime & PASN_GeneralisedTime::operator=(const PTime & time)
1665 {
1666 value = time.AsString("yyyyMMddhhmmss.uz");
1667 value.Replace("GMT", "Z");
1668 return *this;
1669 }
1670
1671
GetValue() const1672 PTime PASN_GeneralisedTime::GetValue() const
1673 {
1674 int year = value(0,3).AsInteger();
1675 int month = value(4,5).AsInteger();
1676 int day = value(6,7).AsInteger();
1677 int hour = value(8,9).AsInteger();
1678 int minute = value(10,11).AsInteger();
1679 int seconds = 0;
1680 int zonePos = 12;
1681
1682 if (isdigit(value[12])) {
1683 seconds = value(12,13).AsInteger();
1684 if (value[14] != '.')
1685 zonePos = 14;
1686 else {
1687 zonePos = 15;
1688 while (isdigit(value[zonePos]))
1689 zonePos++;
1690 }
1691 }
1692
1693 int zone = PTime::Local;
1694 switch (value[zonePos]) {
1695 case 'Z' :
1696 zone = PTime::UTC;
1697 break;
1698 case '+' :
1699 case '-' :
1700 zone = value(zonePos+1,zonePos+2).AsInteger()*60 +
1701 value(zonePos+3,zonePos+4).AsInteger();
1702 }
1703
1704 return PTime(seconds, minute, hour, day, month, year, zone);
1705 }
1706
1707
1708 ///////////////////////////////////////////////////////////////////////
1709
operator =(const PTime & time)1710 PASN_UniversalTime & PASN_UniversalTime::operator=(const PTime & time)
1711 {
1712 value = time.AsString("yyMMddhhmmssz");
1713 value.Replace("GMT", "Z");
1714 value.MakeMinimumSize();
1715 return *this;
1716 }
1717
1718
GetValue() const1719 PTime PASN_UniversalTime::GetValue() const
1720 {
1721 int year = value(0,1).AsInteger();
1722 if (year < 36)
1723 year += 2000;
1724 else
1725 year += 1900;
1726
1727 int month = value(2,3).AsInteger();
1728 int day = value(4,5).AsInteger();
1729 int hour = value(6,7).AsInteger();
1730 int minute = value(8,9).AsInteger();
1731 int seconds = 0;
1732 int zonePos = 10;
1733
1734 if (isdigit(value[10])) {
1735 seconds = value(10,11).AsInteger();
1736 zonePos = 12;
1737 }
1738
1739 int zone = PTime::UTC;
1740 if (value[zonePos] != 'Z')
1741 zone = value(zonePos+1,zonePos+2).AsInteger()*60 +
1742 value(zonePos+3,zonePos+4).AsInteger();
1743
1744 return PTime(seconds, minute, hour, day, month, year, zone);
1745 }
1746
1747
1748 ///////////////////////////////////////////////////////////////////////
1749
PASN_Choice(unsigned nChoices,PBoolean extend)1750 PASN_Choice::PASN_Choice(unsigned nChoices, PBoolean extend)
1751 : PASN_Object(0, ApplicationTagClass, extend),names(NULL),namesCount(0)
1752 {
1753 numChoices = nChoices;
1754 choice = NULL;
1755 }
1756
1757
PASN_Choice(unsigned tag,TagClass tagClass,unsigned upper,PBoolean extend)1758 PASN_Choice::PASN_Choice(unsigned tag, TagClass tagClass,
1759 unsigned upper, PBoolean extend)
1760 : PASN_Object(tag, tagClass, extend),names(NULL),namesCount(0)
1761 {
1762 numChoices = upper;
1763 choice = NULL;
1764 }
1765
1766
PASN_Choice(unsigned tag,TagClass tagClass,unsigned upper,PBoolean extend,const PASN_Names * nameSpec,unsigned namesCnt)1767 PASN_Choice::PASN_Choice(unsigned tag, TagClass tagClass,
1768 unsigned upper, PBoolean extend, const PASN_Names * nameSpec,unsigned namesCnt)
1769 : PASN_Object(tag, tagClass, extend),
1770 names(nameSpec),namesCount(namesCnt)
1771 {
1772 numChoices = upper;
1773 choice = NULL;
1774 }
1775
1776
PASN_Choice(const PASN_Choice & other)1777 PASN_Choice::PASN_Choice(const PASN_Choice & other)
1778 : PASN_Object(other),
1779 names(other.names),namesCount(other.namesCount)
1780 {
1781 numChoices = other.numChoices;
1782
1783 if (other.CheckCreate())
1784 choice = (PASN_Object *)other.choice->Clone();
1785 else
1786 choice = NULL;
1787 }
1788
1789
operator =(const PASN_Choice & other)1790 PASN_Choice & PASN_Choice::operator=(const PASN_Choice & other)
1791 {
1792 if (&other == this) // Assigning to ourself, just do nothing.
1793 return *this;
1794
1795 delete choice;
1796
1797 PASN_Object::operator=(other);
1798
1799 numChoices = other.numChoices;
1800 names = other.names;
1801 namesCount = other.namesCount;
1802
1803 if (other.CheckCreate())
1804 choice = (PASN_Object *)other.choice->Clone();
1805 else
1806 choice = NULL;
1807
1808 return *this;
1809 }
1810
1811
~PASN_Choice()1812 PASN_Choice::~PASN_Choice()
1813 {
1814 delete choice;
1815 }
1816
1817
SetTag(unsigned newTag,TagClass tagClass)1818 void PASN_Choice::SetTag(unsigned newTag, TagClass tagClass)
1819 {
1820 PASN_Object::SetTag(newTag, tagClass);
1821
1822 delete choice;
1823
1824 if (CreateObject())
1825 choice->SetTag(newTag, tagClass);
1826 }
1827
1828
GetTagName() const1829 PString PASN_Choice::GetTagName() const
1830 {
1831 PINDEX idx = FindNameByValue(names, namesCount, tag);
1832 if (idx != P_MAX_INDEX)
1833 return names[idx].name;
1834
1835 if (CheckCreate() &&
1836 PIsDescendant(choice, PASN_Choice) &&
1837 choice->GetTag() == tag &&
1838 choice->GetTagClass() == tagClass)
1839 return PString(choice->GetClass()) + "->" + ((PASN_Choice *)choice)->GetTagName();
1840
1841 return psprintf("<%u>", tag);
1842 }
1843
1844
CheckCreate() const1845 PBoolean PASN_Choice::CheckCreate() const
1846 {
1847 if (choice != NULL)
1848 return PTrue;
1849
1850 return ((PASN_Choice *)this)->CreateObject();
1851 }
1852
1853
GetObject() const1854 PASN_Object & PASN_Choice::GetObject() const
1855 {
1856 PAssert(CheckCreate(), "NULL Choice");
1857 return *choice;
1858 }
1859
1860
1861 #if defined(__GNUC__) && __GNUC__ <= 2 && __GNUC_MINOR__ < 9
1862
1863 #define CHOICE_CAST_OPERATOR(cls) \
1864 PASN_Choice::operator cls &() const \
1865 { \
1866 PAssert(CheckCreate(), "Cast of NULL choice"); \
1867 PAssert(choice->IsDescendant(cls::Class()), PInvalidCast); \
1868 return *(cls *)choice; \
1869 } \
1870
1871 #else
1872
1873 #define CHOICE_CAST_OPERATOR(cls) \
1874 PASN_Choice::operator cls &() \
1875 { \
1876 PAssert(CheckCreate(), "Cast of NULL choice"); \
1877 PAssert(PIsDescendant(choice, cls), PInvalidCast); \
1878 return *(cls *)choice; \
1879 } \
1880 PASN_Choice::operator const cls &() const \
1881 { \
1882 PAssert(CheckCreate(), "Cast of NULL choice"); \
1883 PAssert(PIsDescendant(choice, cls), PInvalidCast); \
1884 return *(const cls *)choice; \
1885 } \
1886
1887 #endif
1888
1889
1890 CHOICE_CAST_OPERATOR(PASN_Null)
CHOICE_CAST_OPERATOR(PASN_Boolean)1891 CHOICE_CAST_OPERATOR(PASN_Boolean)
1892 CHOICE_CAST_OPERATOR(PASN_Integer)
1893 CHOICE_CAST_OPERATOR(PASN_Enumeration)
1894 CHOICE_CAST_OPERATOR(PASN_Real)
1895 CHOICE_CAST_OPERATOR(PASN_ObjectId)
1896 CHOICE_CAST_OPERATOR(PASN_BitString)
1897 CHOICE_CAST_OPERATOR(PASN_OctetString)
1898 CHOICE_CAST_OPERATOR(PASN_NumericString)
1899 CHOICE_CAST_OPERATOR(PASN_PrintableString)
1900 CHOICE_CAST_OPERATOR(PASN_VisibleString)
1901 CHOICE_CAST_OPERATOR(PASN_IA5String)
1902 CHOICE_CAST_OPERATOR(PASN_GeneralString)
1903 CHOICE_CAST_OPERATOR(PASN_BMPString)
1904 CHOICE_CAST_OPERATOR(PASN_Sequence)
1905
1906
1907 PObject::Comparison PASN_Choice::Compare(const PObject & obj) const
1908 {
1909 PAssert(PIsDescendant(&obj, PASN_Choice), PInvalidCast);
1910 const PASN_Choice & other = (const PASN_Choice &)obj;
1911
1912 CheckCreate();
1913 other.CheckCreate();
1914
1915 if (choice == other.choice)
1916 return EqualTo;
1917
1918 if (choice == NULL)
1919 return LessThan;
1920
1921 if (other.choice == NULL)
1922 return GreaterThan;
1923
1924 if (tag < other.tag)
1925 return LessThan;
1926
1927 if (tag > other.tag)
1928 return GreaterThan;
1929
1930 return choice->Compare(*other.choice);
1931 }
1932
1933
PrintOn(ostream & strm) const1934 void PASN_Choice::PrintOn(ostream & strm) const
1935 {
1936 strm << GetTagName();
1937
1938 if (choice != NULL)
1939 strm << ' ' << *choice;
1940 else
1941 strm << " (NULL)";
1942 }
1943
1944
GetTypeAsString() const1945 PString PASN_Choice::GetTypeAsString() const
1946 {
1947 return "Choice";
1948 }
1949
1950
GetDataLength() const1951 PINDEX PASN_Choice::GetDataLength() const
1952 {
1953 if (CheckCreate())
1954 return choice->GetDataLength();
1955
1956 return 0;
1957 }
1958
1959
IsPrimitive() const1960 PBoolean PASN_Choice::IsPrimitive() const
1961 {
1962 if (CheckCreate())
1963 return choice->IsPrimitive();
1964 return PFalse;
1965 }
1966
1967
Decode(PASN_Stream & strm)1968 PBoolean PASN_Choice::Decode(PASN_Stream & strm)
1969 {
1970 return strm.ChoiceDecode(*this);
1971 }
1972
1973
Encode(PASN_Stream & strm) const1974 void PASN_Choice::Encode(PASN_Stream & strm) const
1975 {
1976 strm.ChoiceEncode(*this);
1977 }
1978
1979
GetValueByName(PString name) const1980 PINDEX PASN_Choice::GetValueByName(PString name) const
1981 {
1982 for(unsigned uiIndex = 0; uiIndex < numChoices; uiIndex++){
1983 if(strcmp(names[uiIndex].name, name) == 0){
1984 return names[uiIndex].value;
1985 }
1986 }
1987 return UINT_MAX;
1988 }
1989 ///////////////////////////////////////////////////////////////////////
1990
PASN_Sequence(unsigned tag,TagClass tagClass,unsigned nOpts,PBoolean extend,unsigned nExtend)1991 PASN_Sequence::PASN_Sequence(unsigned tag, TagClass tagClass,
1992 unsigned nOpts, PBoolean extend, unsigned nExtend)
1993 : PASN_Object(tag, tagClass, extend)
1994 {
1995 optionMap.SetConstraints(PASN_ConstrainedObject::FixedConstraint, nOpts);
1996 knownExtensions = nExtend;
1997 totalExtensions = 0;
1998 endBasicEncoding = 0;
1999 }
2000
2001
PASN_Sequence(const PASN_Sequence & other)2002 PASN_Sequence::PASN_Sequence(const PASN_Sequence & other)
2003 : PASN_Object(other),
2004 fields(other.fields.GetSize()),
2005 optionMap(other.optionMap),
2006 extensionMap(other.extensionMap)
2007 {
2008 for (PINDEX i = 0; i < other.fields.GetSize(); i++)
2009 fields.SetAt(i, other.fields[i].Clone());
2010
2011 knownExtensions = other.knownExtensions;
2012 totalExtensions = other.totalExtensions;
2013 endBasicEncoding = 0;
2014 }
2015
2016
operator =(const PASN_Sequence & other)2017 PASN_Sequence & PASN_Sequence::operator=(const PASN_Sequence & other)
2018 {
2019 PASN_Object::operator=(other);
2020
2021 fields.SetSize(other.fields.GetSize());
2022 for (PINDEX i = 0; i < other.fields.GetSize(); i++)
2023 fields.SetAt(i, other.fields[i].Clone());
2024
2025 optionMap = other.optionMap;
2026 knownExtensions = other.knownExtensions;
2027 totalExtensions = other.totalExtensions;
2028 extensionMap = other.extensionMap;
2029
2030 return *this;
2031 }
2032
2033
HasOptionalField(PINDEX opt) const2034 PBoolean PASN_Sequence::HasOptionalField(PINDEX opt) const
2035 {
2036 if (opt < (PINDEX)optionMap.GetSize())
2037 return optionMap[opt];
2038 else
2039 return extensionMap[opt - optionMap.GetSize()];
2040 }
2041
2042
IncludeOptionalField(PINDEX opt)2043 void PASN_Sequence::IncludeOptionalField(PINDEX opt)
2044 {
2045 if (opt < (PINDEX)optionMap.GetSize())
2046 optionMap.Set(opt);
2047 else {
2048 PAssert(extendable, "Must be extendable type");
2049 opt -= optionMap.GetSize();
2050 if (opt >= (PINDEX)extensionMap.GetSize())
2051 extensionMap.SetSize(opt+1);
2052 extensionMap.Set(opt);
2053 }
2054 }
2055
2056
RemoveOptionalField(PINDEX opt)2057 void PASN_Sequence::RemoveOptionalField(PINDEX opt)
2058 {
2059 if (opt < (PINDEX)optionMap.GetSize())
2060 optionMap.Clear(opt);
2061 else {
2062 PAssert(extendable, "Must be extendable type");
2063 opt -= optionMap.GetSize();
2064 extensionMap.Clear(opt);
2065 }
2066 }
2067
2068
Compare(const PObject & obj) const2069 PObject::Comparison PASN_Sequence::Compare(const PObject & obj) const
2070 {
2071 PAssert(PIsDescendant(&obj, PASN_Sequence), PInvalidCast);
2072 const PASN_Sequence & other = (const PASN_Sequence &)obj;
2073 return fields.Compare(other.fields);
2074 }
2075
2076
Clone() const2077 PObject * PASN_Sequence::Clone() const
2078 {
2079 PAssert(IsClass(PASN_Sequence::Class()), PInvalidCast);
2080 return new PASN_Sequence(*this);
2081 }
2082
2083
PrintOn(ostream & strm) const2084 void PASN_Sequence::PrintOn(ostream & strm) const
2085 {
2086 int indent = (int)strm.precision() + 2;
2087 strm << "{\n";
2088 for (PINDEX i = 0; i < fields.GetSize(); i++) {
2089 strm << setw(indent+6) << "field[" << i << "] <";
2090 switch (fields[i].GetTagClass()) {
2091 case UniversalTagClass :
2092 strm << "Universal";
2093 break;
2094 case ApplicationTagClass :
2095 strm << "Application";
2096 break;
2097 case ContextSpecificTagClass :
2098 strm << "ContextSpecific";
2099 break;
2100 case PrivateTagClass :
2101 strm << "Private";
2102 default :
2103 break;
2104 }
2105 strm << '-' << fields[i].GetTag() << '-'
2106 << fields[i].GetTypeAsString() << "> = "
2107 << fields[i] << '\n';
2108 }
2109 strm << setw(indent-1) << "}";
2110 }
2111
2112
GetTypeAsString() const2113 PString PASN_Sequence::GetTypeAsString() const
2114 {
2115 return "Sequence";
2116 }
2117
2118
GetDataLength() const2119 PINDEX PASN_Sequence::GetDataLength() const
2120 {
2121 PINDEX len = 0;
2122 for (PINDEX i = 0; i < fields.GetSize(); i++)
2123 len += fields[i].GetObjectLength();
2124 return len;
2125 }
2126
2127
IsPrimitive() const2128 PBoolean PASN_Sequence::IsPrimitive() const
2129 {
2130 return PFalse;
2131 }
2132
2133
Decode(PASN_Stream & strm)2134 PBoolean PASN_Sequence::Decode(PASN_Stream & strm)
2135 {
2136 return PreambleDecode(strm) && UnknownExtensionsDecode(strm);
2137 }
2138
2139
Encode(PASN_Stream & strm) const2140 void PASN_Sequence::Encode(PASN_Stream & strm) const
2141 {
2142 PreambleEncode(strm);
2143 UnknownExtensionsEncode(strm);
2144 }
2145
2146
PreambleDecode(PASN_Stream & strm)2147 PBoolean PASN_Sequence::PreambleDecode(PASN_Stream & strm)
2148 {
2149 return strm.SequencePreambleDecode(*this);
2150 }
2151
2152
PreambleEncode(PASN_Stream & strm) const2153 void PASN_Sequence::PreambleEncode(PASN_Stream & strm) const
2154 {
2155 strm.SequencePreambleEncode(*this);
2156 }
2157
2158
KnownExtensionDecode(PASN_Stream & strm,PINDEX fld,PASN_Object & field)2159 PBoolean PASN_Sequence::KnownExtensionDecode(PASN_Stream & strm, PINDEX fld, PASN_Object & field)
2160 {
2161 return strm.SequenceKnownDecode(*this, fld, field);
2162 }
2163
2164
KnownExtensionEncode(PASN_Stream & strm,PINDEX fld,const PASN_Object & field) const2165 void PASN_Sequence::KnownExtensionEncode(PASN_Stream & strm, PINDEX fld, const PASN_Object & field) const
2166 {
2167 strm.SequenceKnownEncode(*this, fld, field);
2168 }
2169
2170
UnknownExtensionsDecode(PASN_Stream & strm)2171 PBoolean PASN_Sequence::UnknownExtensionsDecode(PASN_Stream & strm)
2172 {
2173 return strm.SequenceUnknownDecode(*this);
2174 }
2175
2176
UnknownExtensionsEncode(PASN_Stream & strm) const2177 void PASN_Sequence::UnknownExtensionsEncode(PASN_Stream & strm) const
2178 {
2179 strm.SequenceUnknownEncode(*this);
2180 }
2181
2182
2183 ///////////////////////////////////////////////////////////////////////
2184
PASN_Set(unsigned tag,TagClass tagClass,unsigned nOpts,PBoolean extend,unsigned nExtend)2185 PASN_Set::PASN_Set(unsigned tag, TagClass tagClass,
2186 unsigned nOpts, PBoolean extend, unsigned nExtend)
2187 : PASN_Sequence(tag, tagClass, nOpts, extend, nExtend)
2188 {
2189 }
2190
2191
Clone() const2192 PObject * PASN_Set::Clone() const
2193 {
2194 PAssert(IsClass(PASN_Set::Class()), PInvalidCast);
2195 return new PASN_Set(*this);
2196 }
2197
2198
GetTypeAsString() const2199 PString PASN_Set::GetTypeAsString() const
2200 {
2201 return "Set";
2202 }
2203
2204 ///////////////////////////////////////////////////////////////////////
2205
PASN_Array(unsigned tag,TagClass tagClass)2206 PASN_Array::PASN_Array(unsigned tag, TagClass tagClass)
2207 : PASN_ConstrainedObject(tag, tagClass)
2208 {
2209 }
2210
2211
PASN_Array(const PASN_Array & other)2212 PASN_Array::PASN_Array(const PASN_Array & other)
2213 : PASN_ConstrainedObject(other),
2214 array(other.array.GetSize())
2215 {
2216 for (PINDEX i = 0; i < other.array.GetSize(); i++)
2217 array.SetAt(i, other.array[i].Clone());
2218 }
2219
2220
operator =(const PASN_Array & other)2221 PASN_Array & PASN_Array::operator=(const PASN_Array & other)
2222 {
2223 PASN_ConstrainedObject::operator=(other);
2224
2225 array.SetSize(other.array.GetSize());
2226 for (PINDEX i = 0; i < other.array.GetSize(); i++)
2227 array.SetAt(i, other.array[i].Clone());
2228
2229 return *this;
2230 }
2231
2232
SetSize(PINDEX newSize)2233 PBoolean PASN_Array::SetSize(PINDEX newSize)
2234 {
2235 if (newSize > MaximumArraySize)
2236 return PFalse;
2237
2238 PINDEX originalSize = array.GetSize();
2239 if (!array.SetSize(newSize))
2240 return PFalse;
2241
2242 for (PINDEX i = originalSize; i < newSize; i++) {
2243 PASN_Object * obj = CreateObject();
2244 if (obj == NULL)
2245 return PFalse;
2246
2247 array.SetAt(i, obj);
2248 }
2249
2250 return PTrue;
2251 }
2252
2253
Compare(const PObject & obj) const2254 PObject::Comparison PASN_Array::Compare(const PObject & obj) const
2255 {
2256 PAssert(PIsDescendant(&obj, PASN_Array), PInvalidCast);
2257 const PASN_Array & other = (const PASN_Array &)obj;
2258 return array.Compare(other.array);
2259 }
2260
2261
PrintOn(ostream & strm) const2262 void PASN_Array::PrintOn(ostream & strm) const
2263 {
2264 int indent = (int)strm.precision() + 2;
2265 strm << array.GetSize() << " entries {\n";
2266 for (PINDEX i = 0; i < array.GetSize(); i++)
2267 strm << setw(indent+1) << "[" << i << "]=" << setprecision(indent) << array[i] << '\n';
2268 strm << setw(indent-1) << "}";
2269 }
2270
2271
SetConstraintBounds(ConstraintType type,int lower,unsigned upper)2272 void PASN_Array::SetConstraintBounds(ConstraintType type, int lower, unsigned upper)
2273 {
2274 if (lower < 0)
2275 return;
2276
2277 PASN_ConstrainedObject::SetConstraintBounds(type, lower, upper);
2278 if (constraint != Unconstrained) {
2279 if (GetSize() < (PINDEX)lowerLimit)
2280 SetSize(lowerLimit);
2281 else if (GetSize() > (PINDEX)upperLimit)
2282 SetSize(upperLimit);
2283 }
2284 }
2285
2286
GetTypeAsString() const2287 PString PASN_Array::GetTypeAsString() const
2288 {
2289 return "Array";
2290 }
2291
2292
GetDataLength() const2293 PINDEX PASN_Array::GetDataLength() const
2294 {
2295 PINDEX len = 0;
2296 for (PINDEX i = 0; i < array.GetSize(); i++)
2297 len += array[i].GetObjectLength();
2298 return len;
2299 }
2300
2301
IsPrimitive() const2302 PBoolean PASN_Array::IsPrimitive() const
2303 {
2304 return PFalse;
2305 }
2306
2307
Decode(PASN_Stream & strm)2308 PBoolean PASN_Array::Decode(PASN_Stream & strm)
2309 {
2310 return strm.ArrayDecode(*this);
2311 }
2312
2313
Encode(PASN_Stream & strm) const2314 void PASN_Array::Encode(PASN_Stream & strm) const
2315 {
2316 strm.ArrayEncode(*this);
2317 }
2318
2319
2320 ///////////////////////////////////////////////////////////////////////
2321
PASN_Stream()2322 PASN_Stream::PASN_Stream()
2323 {
2324 Construct();
2325 }
2326
2327
PASN_Stream(const PBYTEArray & bytes)2328 PASN_Stream::PASN_Stream(const PBYTEArray & bytes)
2329 : PBYTEArray(bytes)
2330 {
2331 Construct();
2332 }
2333
2334
PASN_Stream(const BYTE * buf,PINDEX size)2335 PASN_Stream::PASN_Stream(const BYTE * buf, PINDEX size)
2336 : PBYTEArray(buf, size)
2337 {
2338 Construct();
2339 }
2340
2341
Construct()2342 void PASN_Stream::Construct()
2343 {
2344 byteOffset = 0;
2345 bitOffset = 8;
2346 }
2347
2348
PrintOn(ostream & strm) const2349 void PASN_Stream::PrintOn(ostream & strm) const
2350 {
2351 int indent = (int)strm.precision() + 2;
2352 strm << " size=" << GetSize()
2353 << " pos=" << byteOffset << '.' << (8-bitOffset)
2354 << " {\n";
2355 PINDEX i = 0;
2356 while (i < GetSize()) {
2357 strm << setw(indent) << " " << hex << setfill('0');
2358 PINDEX j;
2359 for (j = 0; j < 16; j++)
2360 if (i+j < GetSize())
2361 strm << setw(2) << (unsigned)(BYTE)theArray[i+j] << ' ';
2362 else
2363 strm << " ";
2364 strm << " ";
2365 for (j = 0; j < 16; j++) {
2366 if (i+j < GetSize()) {
2367 BYTE c = theArray[i+j];
2368 if (c < 128 && isprint(c))
2369 strm << c;
2370 else
2371 strm << ' ';
2372 }
2373 }
2374 strm << dec << setfill(' ') << '\n';
2375 i += 16;
2376 }
2377 strm << setw(indent-1) << "}";
2378 }
2379
2380
SetPosition(PINDEX newPos)2381 void PASN_Stream::SetPosition(PINDEX newPos)
2382 {
2383 if (!CheckByteOffset(byteOffset))
2384 return;
2385
2386 if (newPos > GetSize())
2387 byteOffset = GetSize();
2388 else
2389 byteOffset = newPos;
2390 bitOffset = 8;
2391 }
2392
2393
ResetDecoder()2394 void PASN_Stream::ResetDecoder()
2395 {
2396 byteOffset = 0;
2397 bitOffset = 8;
2398 }
2399
2400
BeginEncoding()2401 void PASN_Stream::BeginEncoding()
2402 {
2403 bitOffset = 8;
2404 byteOffset = 0;
2405 PBYTEArray::operator=(PBYTEArray(20));
2406 }
2407
2408
CompleteEncoding()2409 void PASN_Stream::CompleteEncoding()
2410 {
2411 if (byteOffset != P_MAX_INDEX) {
2412 if (bitOffset != 8) {
2413 bitOffset = 8;
2414 byteOffset++;
2415 }
2416 SetSize(byteOffset);
2417 byteOffset = P_MAX_INDEX;
2418 }
2419 }
2420
2421
ByteDecode()2422 BYTE PASN_Stream::ByteDecode()
2423 {
2424 if (!CheckByteOffset(byteOffset, GetSize()))
2425 return 0;
2426
2427 bitOffset = 8;
2428 return theArray[byteOffset++];
2429 }
2430
2431
ByteEncode(unsigned value)2432 void PASN_Stream::ByteEncode(unsigned value)
2433 {
2434 if (!CheckByteOffset(byteOffset))
2435 return;
2436
2437 if (bitOffset != 8) {
2438 bitOffset = 8;
2439 byteOffset++;
2440 }
2441 if (byteOffset >= GetSize())
2442 SetSize(byteOffset+10);
2443 theArray[byteOffset++] = (BYTE)value;
2444 }
2445
2446
BlockDecode(BYTE * bufptr,unsigned nBytes)2447 unsigned PASN_Stream::BlockDecode(BYTE * bufptr, unsigned nBytes)
2448 {
2449 if (nBytes == 0 || bufptr == NULL || !CheckByteOffset(byteOffset+nBytes))
2450 return 0;
2451
2452 ByteAlign();
2453
2454 if (byteOffset+nBytes > (unsigned)GetSize()) {
2455 nBytes = GetSize() - byteOffset;
2456 if (nBytes <= 0)
2457 return 0;
2458 }
2459
2460 memcpy(bufptr, &theArray[byteOffset], nBytes);
2461 byteOffset += nBytes;
2462 return nBytes;
2463 }
2464
2465
BlockEncode(const BYTE * bufptr,PINDEX nBytes)2466 void PASN_Stream::BlockEncode(const BYTE * bufptr, PINDEX nBytes)
2467 {
2468 if (!CheckByteOffset(byteOffset, GetSize()))
2469 return;
2470
2471 if (nBytes == 0)
2472 return;
2473
2474 ByteAlign();
2475
2476 if (byteOffset+nBytes >= GetSize())
2477 SetSize(byteOffset+nBytes+10);
2478
2479 memcpy(theArray+byteOffset, bufptr, nBytes);
2480 byteOffset += nBytes;
2481 }
2482
2483
ByteAlign()2484 void PASN_Stream::ByteAlign()
2485 {
2486 if (!CheckByteOffset(byteOffset, GetSize()))
2487 return;
2488
2489 if (bitOffset != 8) {
2490 bitOffset = 8;
2491 byteOffset++;
2492 }
2493 }
2494
2495
2496 ///////////////////////////////////////////////////////////////////////
2497
2498 #ifdef P_INCLUDE_PER
2499 #include "asnper.cxx"
2500 #endif
2501
2502 #ifdef P_INCLUDE_BER
2503 #include "asnber.cxx"
2504 #endif
2505
2506 #ifdef P_INCLUDE_XER
2507 #include "asnxer.cxx"
2508 #endif
2509
2510 // End of file ////////////////////////////////////////////////////////////////
2511