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