asner.cxx
上传用户:hzhsqp
上传日期:2007-01-06
资源大小:1600k
文件大小:96k
源码类别:

IP电话/视频会议

开发平台:

Visual C++

  1. /*
  2.  * asner.cxx
  3.  *
  4.  * Abstract Syntax Notation 1 Encoding Rules
  5.  *
  6.  * Portable Windows Library
  7.  *
  8.  * Copyright (c) 1993-1998 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.  * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
  25.  * All Rights Reserved.
  26.  *
  27.  * Contributor(s): ______________________________________.
  28.  *
  29.  * $Log: asner.cxx,v $
  30.  * Revision 1.30  2000/02/29 06:32:12  robertj
  31.  * Added ability to remove optional field in sequence, thanks Dave Harvey.
  32.  *
  33.  * Revision 1.29  2000/01/20 06:22:22  robertj
  34.  * Fixed boundary condition error for constrained integer encoding (values 1, 256 etc)
  35.  *
  36.  * Revision 1.28  1999/11/22 23:15:43  robertj
  37.  * Fixed bug in PASN_Choice::Compare(), should make sure choices are the same before comparing.
  38.  *
  39.  * Revision 1.27  1999/08/19 15:43:07  robertj
  40.  * Fixed incorrect size of OID if zero length encoded.
  41.  *
  42.  * Revision 1.26  1999/08/09 13:02:45  robertj
  43.  * dded ASN compiler #defines for backward support of pre GCC 2.9 compilers.
  44.  * Added ASN compiler #defines to reduce its memory footprint.
  45.  *
  46.  * Revision 1.25  1999/08/08 15:45:59  robertj
  47.  * Fixed incorrect encoding of unknown extensions.
  48.  *
  49.  * Revision 1.24  1999/08/05 00:44:28  robertj
  50.  * Fixed PER encoding problems for large integer values.
  51.  *
  52.  * Revision 1.23  1999/07/22 06:48:54  robertj
  53.  * Added comparison operation to base ASN classes and compiled ASN code.
  54.  * Added support for ANY type in ASN parser.
  55.  *
  56.  * Revision 1.22  1999/07/08 08:39:12  robertj
  57.  * Fixed bug when assigning negative number ot cosntrained PASN_Integer
  58.  *
  59.  * Revision 1.21  1999/06/30 08:58:12  robertj
  60.  * Fixed bug in encoding/decoding OID greater than 2.39
  61.  *
  62.  * Revision 1.20  1999/06/17 13:27:09  robertj
  63.  * Fixed bug causing crashes on pass through of unknown extensions.
  64.  *
  65.  * Revision 1.19  1999/06/07 00:31:25  robertj
  66.  * Fixed signed/unsigned problem with number of unknown extensions check.
  67.  *
  68.  * Revision 1.18  1999/04/26 05:58:48  craigs
  69.  * Fixed problems with encoding of extensions
  70.  *
  71.  * Revision 1.17  1999/03/09 08:12:38  robertj
  72.  * Fixed problem with closing a steam encoding twice.
  73.  *
  74.  * Revision 1.16  1999/01/16 01:28:25  robertj
  75.  * Fixed problems with reading stream multiple times.
  76.  *
  77.  * Revision 1.15  1998/11/30 04:50:44  robertj
  78.  * New directory structure
  79.  *
  80.  * Revision 1.14  1998/10/22 04:33:11  robertj
  81.  * Fixed bug in constrained strings and PER, incorrect order of character set.
  82.  *
  83.  * Revision 1.13  1998/09/23 06:21:49  robertj
  84.  * Added open source copyright license.
  85.  *
  86.  * Revision 1.12  1998/05/26 05:29:23  robertj
  87.  * Workaroung for g++ iostream bug.
  88.  *
  89.  * Revision 1.11  1998/05/21 04:58:54  robertj
  90.  * GCC comptaibility.
  91.  *
  92.  * Revision 1.10  1998/05/21 04:26:54  robertj
  93.  * Fixed numerous PER problems.
  94.  *
  95.  * Revision 1.9  1998/05/11 06:01:55  robertj
  96.  * Why did this compile under MSC?
  97.  *
  98.  * Revision 1.8  1998/05/07 05:19:29  robertj
  99.  * Fixed problems with using copy constructor/assignment oeprator on PASN_Objects.
  100.  *
  101.  * Revision 1.7  1998/03/05 12:49:50  robertj
  102.  * MemCheck fixes.
  103.  *
  104.  * Revision 1.6  1998/02/03 06:28:27  robertj
  105.  * Fixed length calculation of integers in BER.
  106.  * Added new function to read a block with minimum number of bytes.
  107.  *
  108.  * Revision 1.5  1998/01/26 01:51:20  robertj
  109.  * Removed uninitialised variable warnings.
  110.  *
  111.  * Revision 1.4  1997/12/18 05:07:56  robertj
  112.  * Fixed bug in choice name display.
  113.  * Added function to get choice discriminator name.
  114.  * Fixed bug in encoding extensions.
  115.  *
  116.  * Revision 1.3  1997/12/11 10:36:22  robertj
  117.  * Support for new ASN parser.
  118.  *
  119.  */
  120. #include <ptlib.h>
  121. #ifdef __GNUC__
  122. #pragma implementation "asner.h"
  123. #endif
  124. #include <ptclib/asner.h>
  125. #define new PNEW
  126. static PINDEX CountBits(unsigned range)
  127. {
  128.   if (range == 0)
  129.     return sizeof(unsigned)*8;
  130.   PINDEX nBits = 0;
  131.   while (nBits < (sizeof(unsigned)*8) && range > (unsigned)(1 << nBits))
  132.     nBits++;
  133.   return nBits;
  134. }
  135. ///////////////////////////////////////////////////////////////////////
  136. PASN_Object::PASN_Object(unsigned theTag, TagClass theTagClass, BOOL extend)
  137. {
  138.   extendable = extend;
  139.   tag = theTag;
  140.   if (theTagClass != DefaultTagClass)
  141.     tagClass = theTagClass;
  142.   else
  143.     tagClass = ContextSpecificTagClass;
  144. }
  145. void PASN_Object::SetTag(unsigned newTag, TagClass tagClass_)
  146. {
  147.   tag = newTag;
  148.   if (tagClass_ != DefaultTagClass)
  149.     tagClass = tagClass_;
  150. }
  151. PINDEX PASN_Object::GetObjectLength() const
  152. {
  153.   PINDEX len = 1;
  154.   if (tag >= 31)
  155.     len += (CountBits(tag)+6)/7;
  156.   PINDEX dataLen = GetDataLength();
  157.   if (dataLen < 128)
  158.     len++;
  159.   else
  160.     len += (CountBits(dataLen)+7)/8 + 1;
  161.   return len + dataLen;
  162. }
  163. void PASN_Object::SetConstraints(ConstraintType, MinimumValueTag lower, unsigned upper)
  164. {
  165.   SetConstraints(PartiallyConstrained, (int)lower, upper);
  166. }
  167. void PASN_Object::SetConstraints(ConstraintType, int lower, MaximumValueTag upper)
  168. {
  169.   SetConstraints(PartiallyConstrained, lower, (unsigned)upper);
  170. }
  171. void PASN_Object::SetConstraints(ConstraintType, MinimumValueTag lower, MaximumValueTag upper)
  172. {
  173.   SetConstraints(PartiallyConstrained, (int)lower, (unsigned)upper);
  174. }
  175. void PASN_Object::SetConstraints(ConstraintType, int, unsigned)
  176. {
  177. }
  178. void PASN_Object::SetCharacterSet(ConstraintType, const char *)
  179. {
  180. }
  181. void PASN_Object::SetCharacterSet(ConstraintType, unsigned, unsigned)
  182. {
  183. }
  184. ///////////////////////////////////////////////////////////////////////
  185. PASN_ConstrainedObject::PASN_ConstrainedObject(unsigned tag, TagClass tagClass)
  186.   : PASN_Object(tag, tagClass)
  187. {
  188.   constraint = Unconstrained;
  189.   lowerLimit = 0;
  190.   upperLimit =  UINT_MAX;
  191. }
  192. void PASN_ConstrainedObject::SetConstraints(ConstraintType ctype,
  193.                                             int lower, unsigned upper)
  194. {
  195.   constraint = ctype;
  196.   if (constraint == Unconstrained) {
  197.     lower = 0;
  198.     upper = UINT_MAX;
  199.   }
  200.   extendable = ctype == ExtendableConstraint;
  201.   PAssert((lower >= 0 || upper < 0x7fffffff) &&
  202.           (lower < 0 || (unsigned)lower <= upper), PInvalidParameter);
  203.   lowerLimit = lower;
  204.   upperLimit = upper;
  205. }
  206. int PASN_ConstrainedObject::ConstrainedLengthDecode(PPER_Stream & strm, unsigned & length)
  207. {
  208.   // The execution order is important in the following. The SingleBitDecode() function
  209.   // must be called if extendable is TRUE, no matter what.
  210.   if ((extendable && strm.SingleBitDecode()) || constraint == Unconstrained)
  211.     return strm.LengthDecode(0, INT_MAX, length);
  212.   else
  213.     return strm.LengthDecode(lowerLimit, upperLimit, length);
  214. }
  215. void PASN_ConstrainedObject::ConstrainedLengthEncode(PPER_Stream & strm, unsigned length) const
  216. {
  217.   if (ConstraintEncode(strm, length)) // 26.4
  218.     strm.LengthEncode(length, 0, INT_MAX);
  219.   else
  220.     strm.LengthEncode(length, lowerLimit, upperLimit);
  221. }
  222. BOOL PASN_ConstrainedObject::ConstraintEncode(PPER_Stream & strm, unsigned value) const
  223. {
  224.   if (!extendable)
  225.     return constraint != FixedConstraint;
  226.   BOOL needsExtending = value > upperLimit;
  227.   if (!needsExtending) {
  228.     if (lowerLimit < 0) {
  229.       if ((int)value < lowerLimit)
  230.         needsExtending = TRUE;
  231.     }
  232.     else {
  233.       if (value < (unsigned)lowerLimit)
  234.         needsExtending = TRUE;
  235.     }
  236.   }
  237.   strm.SingleBitEncode(needsExtending);
  238.   return needsExtending || constraint != FixedConstraint;
  239. }
  240. ///////////////////////////////////////////////////////////////////////
  241. PASN_Null::PASN_Null(unsigned tag, TagClass tagClass)
  242.   : PASN_Object(tag, tagClass)
  243. {
  244. }
  245. PObject::Comparison PASN_Null::Compare(const PObject & obj) const
  246. {
  247.   PAssert(obj.IsDescendant(PASN_Null::Class()), PInvalidCast);
  248.   return EqualTo;
  249. }
  250. PObject * PASN_Null::Clone() const
  251. {
  252.   PAssert(IsClass(PASN_Null::Class()), PInvalidCast);
  253.   return new PASN_Null(*this);
  254. }
  255. void PASN_Null::PrintOn(ostream & strm) const
  256. {
  257.   strm << "<<null>>";
  258. }
  259. PString PASN_Null::GetTypeAsString() const
  260. {
  261.   return "Null";
  262. }
  263. PINDEX PASN_Null::GetDataLength() const
  264. {
  265.   return 0;
  266. }
  267. BOOL PASN_Null::Decode(PASN_Stream & strm)
  268. {
  269.   return strm.NullDecode(*this);
  270. }
  271. void PASN_Null::Encode(PASN_Stream & strm) const
  272. {
  273.   strm.NullEncode(*this);
  274. }
  275. BOOL PBER_Stream::NullDecode(PASN_Null & value)
  276. {
  277.   unsigned len;
  278.   if (!HeaderDecode(value, len))
  279.     return FALSE;
  280.   byteOffset += len;
  281.   return TRUE;
  282. }
  283. void PBER_Stream::NullEncode(const PASN_Null & value)
  284. {
  285.   HeaderEncode(value);
  286. }
  287. BOOL PPER_Stream::NullDecode(PASN_Null &)
  288. {
  289.   return TRUE;
  290. }
  291. void PPER_Stream::NullEncode(const PASN_Null &)
  292. {
  293. }
  294. ///////////////////////////////////////////////////////////////////////
  295. PASN_Boolean::PASN_Boolean(BOOL val, unsigned tag, TagClass tagClass)
  296.   : PASN_Object(tag, tagClass)
  297. {
  298.   value = val;
  299. }
  300. PObject::Comparison PASN_Boolean::Compare(const PObject & obj) const
  301. {
  302.   PAssert(obj.IsDescendant(PASN_Boolean::Class()), PInvalidCast);
  303.   return value == ((const PASN_Boolean &)obj).value ? EqualTo : GreaterThan;
  304. }
  305. PObject * PASN_Boolean::Clone() const
  306. {
  307.   PAssert(IsClass(PASN_Boolean::Class()), PInvalidCast);
  308.   return new PASN_Boolean(*this);
  309. }
  310. void PASN_Boolean::PrintOn(ostream & strm) const
  311. {
  312.   if (value)
  313.     strm << "TRUE";
  314.   else
  315.     strm << "FALSE";
  316. }
  317. PString PASN_Boolean::GetTypeAsString() const
  318. {
  319.   return "Boolean";
  320. }
  321. PINDEX PASN_Boolean::GetDataLength() const
  322. {
  323.   return 1;
  324. }
  325. BOOL PASN_Boolean::Decode(PASN_Stream & strm)
  326. {
  327.   return strm.BooleanDecode(*this);
  328. }
  329. void PASN_Boolean::Encode(PASN_Stream & strm) const
  330. {
  331.   strm.BooleanEncode(*this);
  332. }
  333. BOOL PBER_Stream::BooleanDecode(PASN_Boolean & value)
  334. {
  335.   unsigned len;
  336.   if (!HeaderDecode(value, len))
  337.     return FALSE;
  338.   while (len-- > 0) {
  339.     if (IsAtEnd())
  340.       return FALSE;
  341.     value = (BOOL)ByteDecode();
  342.   }
  343.   return TRUE;
  344. }
  345. void PBER_Stream::BooleanEncode(const PASN_Boolean & value)
  346. {
  347.   HeaderEncode(value);
  348.   ByteEncode((BOOL)value);
  349. }
  350. BOOL PPER_Stream::BooleanDecode(PASN_Boolean & value)
  351. {
  352.   if (IsAtEnd())
  353.     return FALSE;
  354.   // X.931 Section 11
  355.   value = (BOOL)SingleBitDecode();
  356.   return TRUE;
  357. }
  358. void PPER_Stream::BooleanEncode(const PASN_Boolean & value)
  359. {
  360.   // X.931 Section 11
  361.   SingleBitEncode((BOOL)value);
  362. }
  363. ///////////////////////////////////////////////////////////////////////
  364. PASN_Integer::PASN_Integer(unsigned tag, TagClass tagClass, unsigned val)
  365.   : PASN_ConstrainedObject(tag, tagClass)
  366. {
  367.   value = val;
  368. }
  369. PASN_Integer & PASN_Integer::operator=(unsigned val)
  370. {
  371.   if (constraint == Unconstrained)
  372.     value = val;
  373.   else if (lowerLimit >= 0) { // Is unsigned integer
  374.     if (val < (unsigned)lowerLimit)
  375.       value = lowerLimit;
  376.     else if (val > upperLimit)
  377.       value = upperLimit;
  378.     else
  379.       value = val;
  380.   }
  381.   else {
  382.     int ival = (int)val;
  383.     if (ival < lowerLimit)
  384.       value = lowerLimit;
  385.     else if (upperLimit < INT_MAX && ival > (int)upperLimit)
  386.       value = upperLimit;
  387.     else
  388.       value = val;
  389.   }
  390.   return *this;
  391. }
  392. PObject::Comparison PASN_Integer::Compare(const PObject & obj) const
  393. {
  394.   PAssert(obj.IsDescendant(PASN_Integer::Class()), PInvalidCast);
  395.   const PASN_Integer & other = (const PASN_Integer &)obj;
  396.   if (value < other.value)
  397.     return LessThan;
  398.   if (value > other.value)
  399.     return GreaterThan;
  400.   return EqualTo;
  401. }
  402. PObject * PASN_Integer::Clone() const
  403. {
  404.   PAssert(IsClass(PASN_Integer::Class()), PInvalidCast);
  405.   return new PASN_Integer(*this);
  406. }
  407. void PASN_Integer::PrintOn(ostream & strm) const
  408. {
  409.   if (lowerLimit < 0)
  410.     strm << (int)value;
  411.   else
  412.     strm << value;
  413. }
  414. PString PASN_Integer::GetTypeAsString() const
  415. {
  416.   return "Integer";
  417. }
  418. static PINDEX GetIntegerDataLength(int value)
  419. {
  420.   // create a mask which is the top nine bits of a DWORD, or 0xFF800000
  421.   // on a big endian machine
  422.   int shift = (sizeof(value)-1)*8-1;
  423.   // remove all sequences of nine 0's or 1's at the start of the value
  424.   while (shift > 0 && ((value >> shift)&0x1ff) == (value < 0 ? 0x1ff : 0))
  425.     shift -= 8;
  426.   return (shift+9)/8;
  427. }
  428. PINDEX PASN_Integer::GetDataLength() const
  429. {
  430.   return GetIntegerDataLength(value);
  431. }
  432. BOOL PASN_Integer::Decode(PASN_Stream & strm)
  433. {
  434.   return strm.IntegerDecode(*this);
  435. }
  436. void PASN_Integer::Encode(PASN_Stream & strm) const
  437. {
  438.   strm.IntegerEncode(*this);
  439. }
  440. BOOL PBER_Stream::IntegerDecode(PASN_Integer & value)
  441. {
  442.   unsigned len;
  443.   if (!HeaderDecode(value, len) || len == 0 || IsAtEnd())
  444.     return FALSE;
  445.   int accumulator = (char)ByteDecode(); // sign extended first byte
  446.   while (--len > 0) {
  447.     if (IsAtEnd())
  448.       return FALSE;
  449.     accumulator = (accumulator << 8) | ByteDecode();
  450.   }
  451.   value = accumulator;
  452.   return TRUE;
  453. }
  454. void PBER_Stream::IntegerEncode(const PASN_Integer & value)
  455. {
  456.   HeaderEncode(value);
  457.   // output the integer bits
  458.   for (int count = GetIntegerDataLength(value)-1; count >= 0; count--)
  459.     ByteEncode(value >> (count*8));
  460. }
  461. BOOL PPER_Stream::IntegerDecode(PASN_Integer & value)
  462. {
  463.   return value.DecodePER(*this);
  464. }
  465. void PPER_Stream::IntegerEncode(const PASN_Integer & value)
  466. {
  467.   value.EncodePER(*this);
  468. }
  469. BOOL PASN_Integer::DecodePER(PPER_Stream & strm)
  470. {
  471.   // X.931 Sections 12
  472.   if ((extendable && strm.SingleBitDecode()) || constraint != FixedConstraint) { //  12.1
  473.     unsigned len;
  474.     if (strm.LengthDecode(0, INT_MAX, len) != 0)
  475.       return FALSE;
  476.     value = strm.MultiBitDecode(len*8);
  477.     return TRUE;
  478.   }
  479.   if ((unsigned)lowerLimit != upperLimit)  // 12.2.1
  480.     return strm.UnsignedDecode(lowerLimit, upperLimit, value) == 0; // 12.2.2 which devolves to 10.5
  481.   value = lowerLimit;
  482.   return TRUE;
  483. }
  484. void PASN_Integer::EncodePER(PPER_Stream & strm) const
  485. {
  486.   // X.931 Sections 12
  487.   if (ConstraintEncode(strm, (int)value)) { //  12.1
  488.     PINDEX nBytes;
  489.     unsigned adjusted_value = value - lowerLimit;
  490.     if (adjusted_value == 0)
  491.       nBytes = 1;
  492.     else {
  493.       PINDEX nBits = CountBits(adjusted_value+1);
  494.       nBytes = (nBits+7)/8;
  495.     }
  496.     strm.LengthEncode(nBytes, 0, INT_MAX);
  497.     strm.MultiBitEncode(adjusted_value, nBytes*8);
  498.     return;
  499.   }
  500.   if ((unsigned)lowerLimit == upperLimit) // 12.2.1
  501.     return;
  502.   // 12.2.2 which devolves to 10.5
  503.   strm.UnsignedEncode(value, lowerLimit, upperLimit);
  504. }
  505. ///////////////////////////////////////////////////////////////////////
  506. PASN_Enumeration::PASN_Enumeration(unsigned tag, TagClass tagClass,
  507.                                    unsigned maxEnum, BOOL extend,
  508.                                    unsigned val)
  509.   : PASN_Object(tag, tagClass, extend)
  510. {
  511.   value = val;
  512.   maxEnumValue = maxEnum;
  513. }
  514. static POrdinalToString BuildNamesDict(const PString & nameSpec)
  515. {
  516.   POrdinalToString names;
  517.   PStringArray nameList = nameSpec.Tokenise(' ', FALSE);
  518.   int num = 0;
  519.   for (PINDEX i = 0; i < nameList.GetSize(); i++) {
  520.     const PString & thisName = nameList[i];
  521.     if (!thisName) {
  522.       PINDEX equalPos = thisName.Find('=');
  523.       if (equalPos != P_MAX_INDEX)
  524.         num = (int)thisName.Mid(equalPos+1).AsInteger();
  525.       names.SetAt(POrdinalKey(num), thisName.Left(equalPos));
  526.       num++;
  527.     }
  528.   }
  529.   return names;
  530. }
  531. PASN_Enumeration::PASN_Enumeration(unsigned tag, TagClass tagClass,
  532.                                    unsigned maxEnum, BOOL extend,
  533.                                    const PString & nameSpec,
  534.                                    unsigned val)
  535.   : PASN_Object(tag, tagClass, extend),
  536.     names(BuildNamesDict(nameSpec))
  537. {
  538.   PAssert(maxEnum > 0, PInvalidParameter);
  539.   maxEnumValue = maxEnum;
  540.   PAssert(val < maxEnum, PInvalidParameter);
  541.   value = val;
  542. }
  543. PObject::Comparison PASN_Enumeration::Compare(const PObject & obj) const
  544. {
  545.   PAssert(obj.IsDescendant(PASN_Enumeration::Class()), PInvalidCast);
  546.   const PASN_Enumeration & other = (const PASN_Enumeration &)obj;
  547.   if (value < other.value)
  548.     return LessThan;
  549.   if (value > other.value)
  550.     return GreaterThan;
  551.   return EqualTo;
  552. }
  553. PObject * PASN_Enumeration::Clone() const
  554. {
  555.   PAssert(IsClass(PASN_Enumeration::Class()), PInvalidCast);
  556.   return new PASN_Enumeration(*this);
  557. }
  558. void PASN_Enumeration::PrintOn(ostream & strm) const
  559. {
  560.   if (names.Contains(value))
  561.     strm << names[value];
  562.   else
  563.     strm << '<' << value << '>';
  564. }
  565. PString PASN_Enumeration::GetTypeAsString() const
  566. {
  567.   return "Enumeration";
  568. }
  569. PINDEX PASN_Enumeration::GetDataLength() const
  570. {
  571.   return GetIntegerDataLength(value);
  572. }
  573. BOOL PASN_Enumeration::Decode(PASN_Stream & strm)
  574. {
  575.   return strm.EnumerationDecode(*this);
  576. }
  577. void PASN_Enumeration::Encode(PASN_Stream & strm) const
  578. {
  579.   strm.EnumerationEncode(*this);
  580. }
  581. BOOL PBER_Stream::EnumerationDecode(PASN_Enumeration & value)
  582. {
  583.   unsigned len;
  584.   if (!HeaderDecode(value, len) || len == 0 || IsAtEnd())
  585.     return FALSE;
  586.   unsigned val = 0;
  587.   while (len-- > 0) {
  588.     if (IsAtEnd())
  589.       return FALSE;
  590.     val = (val << 8) | ByteDecode();
  591.   }
  592.   value = val;
  593.   return TRUE;
  594. }
  595. void PBER_Stream::EnumerationEncode(const PASN_Enumeration & value)
  596. {
  597.   HeaderEncode(value);
  598.   // output the integer bits
  599.   for (int count = GetIntegerDataLength(value)-1; count >= 0; count--)
  600.     ByteEncode(value >> (count*8));
  601. }
  602. BOOL PPER_Stream::EnumerationDecode(PASN_Enumeration & value)
  603. {
  604.   return value.DecodePER(*this);
  605. }
  606. void PPER_Stream::EnumerationEncode(const PASN_Enumeration & value)
  607. {
  608.   value.EncodePER(*this);
  609. }
  610. BOOL PASN_Enumeration::DecodePER(PPER_Stream & strm)
  611. {
  612.   // X.691 Section 13
  613.   if (extendable) {  // 13.3
  614.     if (strm.SingleBitDecode())
  615.       return strm.UnsignedDecode(0, strm.SmallUnsignedDecode()-1, value) == 0;
  616.   }
  617.   return strm.UnsignedDecode(0, maxEnumValue, value) == 0;  // 13.2
  618. }
  619. void PASN_Enumeration::EncodePER(PPER_Stream & strm) const
  620. {
  621.   // X.691 Section 13
  622.   if (extendable) {  // 13.3
  623.     BOOL extended = value > maxEnumValue;
  624.     strm.SingleBitEncode(extended);
  625.     if (extended) {
  626.       strm.SmallUnsignedEncode(1+value);
  627.       strm.UnsignedEncode(value, 0, value);
  628.       return;
  629.     }
  630.   }
  631.   strm.UnsignedEncode(value, 0, maxEnumValue);  // 13.2
  632. }
  633. ///////////////////////////////////////////////////////////////////////
  634. PASN_Real::PASN_Real(unsigned tag, TagClass tagClass, double val)
  635.   : PASN_Object(tag, tagClass)
  636. {
  637.   value = val;
  638. }
  639. PObject::Comparison PASN_Real::Compare(const PObject & obj) const
  640. {
  641.   PAssert(obj.IsDescendant(PASN_Real::Class()), PInvalidCast);
  642.   const PASN_Real & other = (const PASN_Real &)obj;
  643.   if (value < other.value)
  644.     return LessThan;
  645.   if (value > other.value)
  646.     return GreaterThan;
  647.   return EqualTo;
  648. }
  649. PObject * PASN_Real::Clone() const
  650. {
  651.   PAssert(IsClass(PASN_Real::Class()), PInvalidCast);
  652.   return new PASN_Real(*this);
  653. }
  654. void PASN_Real::PrintOn(ostream & strm) const
  655. {
  656.   strm << value;
  657. }
  658. PString PASN_Real::GetTypeAsString() const
  659. {
  660.   return "Real";
  661. }
  662. PINDEX PASN_Real::GetDataLength() const
  663. {
  664.   PAssertAlways(PUnimplementedFunction);
  665.   return 0;
  666. }
  667. BOOL PASN_Real::Decode(PASN_Stream & strm)
  668. {
  669.   return strm.RealDecode(*this);
  670. }
  671. void PASN_Real::Encode(PASN_Stream & strm) const
  672. {
  673.   strm.RealEncode(*this);
  674. }
  675. BOOL PBER_Stream::RealDecode(PASN_Real & value)
  676. {
  677.   unsigned len;
  678.   if (!HeaderDecode(value, len) || len == 0 || IsAtEnd())
  679.     return FALSE;
  680.   PAssertAlways(PUnimplementedFunction);
  681.   byteOffset += len;
  682.   return TRUE;
  683. }
  684. void PBER_Stream::RealEncode(const PASN_Real &)
  685. {
  686.   PAssertAlways(PUnimplementedFunction);
  687. }
  688. BOOL PPER_Stream::RealDecode(PASN_Real &)
  689. {
  690.   // X.691 Section 14
  691.   if (IsAtEnd())
  692.     return FALSE;
  693.   PINDEX len = MultiBitDecode(8)+1;
  694.   PAssertAlways(PUnimplementedFunction);
  695.   byteOffset += len;
  696.   return TRUE;
  697. }
  698. void PPER_Stream::RealEncode(const PASN_Real &)
  699. {
  700.   // X.691 Section 14
  701.   MultiBitEncode(0, 8);
  702.   PAssertAlways(PUnimplementedFunction);
  703.   MultiBitEncode(0, 8);
  704. }
  705. ///////////////////////////////////////////////////////////////////////
  706. PASN_ObjectId::PASN_ObjectId(unsigned tag, TagClass tagClass)
  707.   : PASN_Object(tag, tagClass)
  708. {
  709. }
  710. PASN_ObjectId::PASN_ObjectId(const PASN_ObjectId & other)
  711.   : PASN_Object(other),
  712.     value(other.value, other.GetSize())
  713. {
  714. }
  715. PASN_ObjectId & PASN_ObjectId::operator=(const PASN_ObjectId & other)
  716. {
  717.   PASN_Object::operator=(other);
  718.   value = PUnsignedArray(other.value, other.GetSize());
  719.   return *this;
  720. }
  721. PASN_ObjectId & PASN_ObjectId::operator=(const char * dotstr)
  722. {
  723.   SetValue(dotstr);
  724.   return *this;
  725. }
  726. PASN_ObjectId & PASN_ObjectId::operator=(const PString & dotstr)
  727. {
  728.   SetValue(dotstr);
  729.   return *this;
  730. }
  731. void PASN_ObjectId::SetValue(const PString & dotstr)
  732. {
  733.   PStringArray parts = dotstr.Tokenise('.');
  734.   value.SetSize(parts.GetSize());
  735.   for (PINDEX i = 0; i < parts.GetSize(); i++)
  736.     value[i] = parts[i].AsUnsigned();
  737. }
  738. BOOL PASN_ObjectId::operator==(const char * dotstr) const
  739. {
  740.   PASN_ObjectId id;
  741.   id.SetValue(dotstr);
  742.   return *this == id;
  743. }
  744. PObject::Comparison PASN_ObjectId::Compare(const PObject & obj) const
  745. {
  746.   PAssert(obj.IsDescendant(PASN_ObjectId::Class()), PInvalidCast);
  747.   const PASN_ObjectId & other = (const PASN_ObjectId &)obj;
  748.   return value.Compare(other.value);
  749. }
  750. PObject * PASN_ObjectId::Clone() const
  751. {
  752.   PAssert(IsClass(PASN_ObjectId::Class()), PInvalidCast);
  753.   return new PASN_ObjectId(*this);
  754. }
  755. void PASN_ObjectId::PrintOn(ostream & strm) const
  756. {
  757.   for (PINDEX i = 0; i < value.GetSize(); i++) {
  758.     strm << (unsigned)value[i];
  759.     if (i < value.GetSize()-1)
  760.       strm << '.';
  761.   }
  762. }
  763. PString PASN_ObjectId::GetTypeAsString() const
  764. {
  765.   return "Object ID";
  766. }
  767. BOOL PASN_ObjectId::CommonDecode(PASN_Stream & strm, unsigned dataLen)
  768. {
  769.   value.SetSize(0);
  770.   // handle zero length strings correctly
  771.   if (dataLen == 0)
  772.     return TRUE;
  773.   unsigned subId;
  774.   // start at the second identifier in the buffer, because we will later
  775.   // expand the first number into the first two IDs
  776.   PINDEX i = 1;
  777.   while (dataLen > 0) {
  778.     unsigned byte;
  779.     subId = 0;
  780.     do {    /* shift and add in low order 7 bits */
  781.       if (strm.IsAtEnd())
  782.         return FALSE;
  783.       byte = strm.ByteDecode();
  784.       subId = (subId << 7) + (byte & 0x7f);
  785.       dataLen--;
  786.     } while ((byte & 0x80) != 0);
  787.     value.SetAt(i++, subId);
  788.   }
  789.   /*
  790.    * The first two subidentifiers are encoded into the first component
  791.    * with the value (X * 40) + Y, where:
  792.    *  X is the value of the first subidentifier.
  793.    *  Y is the value of the second subidentifier.
  794.    */
  795.   subId = value[1];
  796.   if (subId < 40) {
  797.     value[0] = 0;
  798.     value[1] = subId;
  799.   }
  800.   else if (subId < 80) {
  801.     value[0] = 1;
  802.     value[1] = subId-40;
  803.   }
  804.   else {
  805.     value[0] = 2;
  806.     value[1] = subId-80;
  807.   }
  808.   return TRUE;
  809. }
  810. void PASN_ObjectId::CommonEncode(PBYTEArray & encodecObjectId) const
  811. {
  812.   PINDEX length = value.GetSize();
  813.   const unsigned * objId = value;
  814.   if (length < 2) {
  815.     // Thise case is really illegal, but we have to do SOMETHING
  816.     encodecObjectId.SetSize(0);
  817.     return;
  818.   }
  819.   unsigned subId = (objId[0] * 40) + objId[1];
  820.   objId += 2;
  821.   PINDEX outputPosition = 0;
  822.   while (--length > 0) {
  823.     if (subId < 128)
  824.       encodecObjectId[outputPosition++] = (BYTE)subId;
  825.     else {
  826.       unsigned mask = 0x7F; /* handle subid == 0 case */
  827.       int bits = 0;
  828.       /* testmask *MUST* !!!! be of an unsigned type */
  829.       unsigned testmask = 0x7F;
  830.       int      testbits = 0;
  831.       while (testmask != 0) {
  832.         if (subId & testmask) {  /* if any bits set */
  833.           mask = testmask;
  834.         bits = testbits;
  835.       }
  836.         testmask <<= 7;
  837.         testbits += 7;
  838.       }
  839.       /* mask can't be zero here */
  840.       while (mask != 0x7F) {
  841.         /* fix a mask that got truncated above */
  842.        if (mask == 0x1E00000)
  843.         mask = 0xFE00000;
  844.         encodecObjectId[outputPosition++] = (BYTE)(((subId & mask) >> bits) | 0x80);
  845.         mask >>= 7;
  846.         bits -= 7;
  847.       }
  848.       encodecObjectId[outputPosition++] = (BYTE)(subId & mask);
  849.     }
  850.     subId = *objId++;
  851.   }
  852. }
  853. PINDEX PASN_ObjectId::GetDataLength() const
  854. {
  855.   PBYTEArray dummy;
  856.   CommonEncode(dummy);
  857.   return dummy.GetSize();
  858. }
  859. BOOL PASN_ObjectId::Decode(PASN_Stream & strm)
  860. {
  861.   return strm.ObjectIdDecode(*this);
  862. }
  863. void PASN_ObjectId::Encode(PASN_Stream & strm) const
  864. {
  865.   strm.ObjectIdEncode(*this);
  866. }
  867. BOOL PBER_Stream::ObjectIdDecode(PASN_ObjectId & value)
  868. {
  869.   unsigned len;
  870.   if (!HeaderDecode(value, len))
  871.     return FALSE;
  872.   return value.CommonDecode(*this, len);
  873. }
  874. void PBER_Stream::ObjectIdEncode(const PASN_ObjectId & value)
  875. {
  876.   HeaderEncode(value);
  877.   PBYTEArray data;
  878.   value.CommonEncode(data);
  879.   BlockEncode(data, data.GetSize());
  880. }
  881. BOOL PPER_Stream::ObjectIdDecode(PASN_ObjectId & value)
  882. {
  883.   // X.691 Section 23
  884.   unsigned dataLen;
  885.   if (LengthDecode(0, 255, dataLen) < 0)
  886.     return FALSE;
  887.   ByteAlign();
  888.   return value.CommonDecode(*this, dataLen);
  889. }
  890. void PPER_Stream::ObjectIdEncode(const PASN_ObjectId & value)
  891. {
  892.   // X.691 Section 23
  893.   PBYTEArray eObjId;
  894.   value.CommonEncode(eObjId);
  895.   LengthEncode(eObjId.GetSize(), 0, 255);
  896.   BlockEncode(eObjId, eObjId.GetSize());
  897. }
  898. ///////////////////////////////////////////////////////////////////////
  899. PASN_BitString::PASN_BitString(unsigned tag, TagClass tagClass, unsigned nBits)
  900.   : PASN_ConstrainedObject(tag, tagClass),
  901.     totalBits(nBits),
  902.     bitData((totalBits+7)/8)
  903. {
  904. }
  905. PASN_BitString::PASN_BitString(const PASN_BitString & other)
  906.   : PASN_ConstrainedObject(other),
  907.     bitData(other.bitData, other.bitData.GetSize())
  908. {
  909.   totalBits = other.totalBits;
  910. }
  911. PASN_BitString & PASN_BitString::operator=(const PASN_BitString & other)
  912. {
  913.   PASN_ConstrainedObject::operator=(other);
  914.   totalBits = other.totalBits;
  915.   bitData = PBYTEArray(other.bitData, other.bitData.GetSize());
  916.   return *this;
  917. }
  918. void PASN_BitString::SetData(unsigned nBits, const PBYTEArray & bytes)
  919. {
  920.   bitData = bytes;
  921.   totalBits = nBits;
  922. }
  923. void PASN_BitString::SetData(unsigned nBits, const BYTE * buf, PINDEX size)
  924. {
  925.   bitData = PBYTEArray(buf, size);
  926.   totalBits = nBits;
  927. }
  928. BOOL PASN_BitString::SetSize(unsigned nBits)
  929. {
  930.   totalBits = nBits;
  931.   return bitData.SetSize((nBits+7)/8);
  932. }
  933. BOOL PASN_BitString::operator[](PINDEX bit) const
  934. {
  935.   if ((unsigned)bit < totalBits)
  936.     return (bitData[bit>>3] & (1 << (7 - (bit&7)))) != 0;
  937.   return FALSE;
  938. }
  939. void PASN_BitString::Set(unsigned bit)
  940. {
  941.   if (bit < totalBits)
  942.     bitData[(PINDEX)(bit>>3)] |= 1 << (7 - (bit&7));
  943. }
  944. void PASN_BitString::Clear(unsigned bit)
  945. {
  946.   if (bit < totalBits)
  947.     bitData[(PINDEX)(bit>>3)] &= ~(1 << (7 - (bit&7)));
  948. }
  949. void PASN_BitString::Invert(unsigned bit)
  950. {
  951.   if (bit < totalBits)
  952.     bitData[(PINDEX)(bit>>3)] ^= 1 << (7 - (bit&7));
  953. }
  954. void PASN_BitString::SetConstraints(ConstraintType type, int lower, unsigned upper)
  955. {
  956.   PAssert(lower >= 0, PInvalidParameter);
  957.   PASN_ConstrainedObject::SetConstraints(type, lower, upper);
  958.   if (constraint != Unconstrained) {
  959.     if (totalBits < (unsigned)lowerLimit)
  960.       SetSize(lowerLimit);
  961.     else if ((unsigned)totalBits > upperLimit)
  962.       SetSize(upperLimit);
  963.   }
  964. }
  965. PObject::Comparison PASN_BitString::Compare(const PObject & obj) const
  966. {
  967.   PAssert(obj.IsDescendant(PASN_BitString::Class()), PInvalidCast);
  968.   const PASN_BitString & other = (const PASN_BitString &)obj;
  969.   if (totalBits < other.totalBits)
  970.     return LessThan;
  971.   if (totalBits > other.totalBits)
  972.     return GreaterThan;
  973.   return bitData.Compare(other.bitData);
  974. }
  975. PObject * PASN_BitString::Clone() const
  976. {
  977.   PAssert(IsClass(PASN_BitString::Class()), PInvalidCast);
  978.   return new PASN_BitString(*this);
  979. }
  980. void PASN_BitString::PrintOn(ostream & strm) const
  981. {
  982.   BYTE mask = 0x80;
  983.   PINDEX offset = 0;
  984.   for (unsigned i = 0; i < totalBits; i++) {
  985.     strm << ((bitData[offset]&mask) != 0 ? '1' : '0');
  986.     mask >>= 1;
  987.     if (mask == 0) {
  988.       mask = 0x80;
  989.       offset++;
  990.     }
  991.   }
  992. }
  993. PString PASN_BitString::GetTypeAsString() const
  994. {
  995.   return "Bit String";
  996. }
  997. PINDEX PASN_BitString::GetDataLength() const
  998. {
  999.   return (totalBits+7)/8 + 1;
  1000. }
  1001. BOOL PASN_BitString::Decode(PASN_Stream & strm)
  1002. {
  1003.   return strm.BitStringDecode(*this);
  1004. }
  1005. void PASN_BitString::Encode(PASN_Stream & strm) const
  1006. {
  1007.   strm.BitStringEncode(*this);
  1008. }
  1009. BOOL PASN_BitString::DecodeBER(PBER_Stream & strm, unsigned len)
  1010. {
  1011.   totalBits = len*8 - strm.ByteDecode();
  1012.   unsigned nBytes = (totalBits+7)/8;
  1013.   return strm.BlockDecode(bitData.GetPointer(nBytes), nBytes) == nBytes;
  1014. }
  1015. void PASN_BitString::EncodeBER(PBER_Stream & strm) const
  1016. {
  1017.   if (totalBits == 0)
  1018.     strm.ByteEncode(0);
  1019.   else {
  1020.     strm.ByteEncode(8-totalBits%8);
  1021.     strm.BlockEncode(bitData, (totalBits+7)/8);
  1022.   }
  1023. }
  1024. BOOL PASN_BitString::DecodePER(PPER_Stream & strm)
  1025. {
  1026.   // X.691 Section 15
  1027.   if (ConstrainedLengthDecode(strm, totalBits) < 0)
  1028.     return FALSE;
  1029.   SetSize(totalBits);
  1030.   if (totalBits == 0)
  1031.     return TRUE;   // 15.7
  1032.   if (totalBits > strm.GetBitsLeft())
  1033.     return FALSE;
  1034.   if (totalBits > 16) {
  1035.     unsigned nBytes = (totalBits+7)/8;
  1036.     return strm.BlockDecode(bitData.GetPointer(), nBytes) == nBytes;   // 15.9
  1037.   }
  1038.   if (totalBits <= 8)
  1039.     bitData[0] = (BYTE)(strm.MultiBitDecode(totalBits) << (8-totalBits));
  1040.   else {  // 15.8
  1041.     bitData[0] = (BYTE)strm.MultiBitDecode(8);
  1042.     bitData[1] = (BYTE)(strm.MultiBitDecode(totalBits-8) << (16-totalBits));
  1043.   }
  1044.   return TRUE;
  1045. }
  1046. void PASN_BitString::EncodePER(PPER_Stream & strm) const
  1047. {
  1048.   // X.691 Section 15
  1049.   ConstrainedLengthEncode(strm, totalBits);
  1050.   if (totalBits == 0)
  1051.     return;
  1052.   if (totalBits > 16)
  1053.     strm.BlockEncode(bitData, (totalBits+7)/8);   // 15.9
  1054.   else if (totalBits <= 8)  // 15.8
  1055.     strm.MultiBitEncode(bitData[0] >> (8 - totalBits), totalBits);
  1056.   else {
  1057.     strm.MultiBitEncode(bitData[0], 8);
  1058.     strm.MultiBitEncode(bitData[1] >> (16 - totalBits), totalBits-8);
  1059.   }
  1060. }
  1061. BOOL PBER_Stream::BitStringDecode(PASN_BitString & value)
  1062. {
  1063.   unsigned len;
  1064.   if (!HeaderDecode(value, len) || len == 0 || IsAtEnd())
  1065.     return FALSE;
  1066.   return value.DecodeBER(*this, len);
  1067. }
  1068. void PBER_Stream::BitStringEncode(const PASN_BitString & value)
  1069. {
  1070.   HeaderEncode(value);
  1071.   value.EncodeBER(*this);
  1072. }
  1073. BOOL PPER_Stream::BitStringDecode(PASN_BitString & value)
  1074. {
  1075.   return value.DecodePER(*this);
  1076. }
  1077. void PPER_Stream::BitStringEncode(const PASN_BitString & value)
  1078. {
  1079.   value.EncodePER(*this);
  1080. }
  1081. ///////////////////////////////////////////////////////////////////////
  1082. PASN_OctetString::PASN_OctetString(unsigned tag, TagClass tagClass)
  1083.   : PASN_ConstrainedObject(tag, tagClass)
  1084. {
  1085. }
  1086. PASN_OctetString::PASN_OctetString(const PASN_OctetString & other)
  1087.   : PASN_ConstrainedObject(other),
  1088.     value(other.value, other.GetSize())
  1089. {
  1090. }
  1091. PASN_OctetString & PASN_OctetString::operator=(const PASN_OctetString & other)
  1092. {
  1093.   PASN_ConstrainedObject::operator=(other);
  1094.   value = PBYTEArray(other.value, other.GetSize());
  1095.   return *this;
  1096. }
  1097. PASN_OctetString & PASN_OctetString::operator=(const char * str)
  1098. {
  1099.   SetValue((const BYTE *)str, strlen(str));
  1100.   return *this;
  1101. }
  1102. PASN_OctetString & PASN_OctetString::operator=(const PString & str)
  1103. {
  1104.   SetValue((const BYTE *)(const char *)str, str.GetSize()-1);
  1105.   return *this;
  1106. }
  1107. PASN_OctetString & PASN_OctetString::operator=(const PBYTEArray & arr)
  1108. {
  1109.   PINDEX len = arr.GetSize();
  1110.   if ((unsigned)len > upperLimit || (int)len < lowerLimit)
  1111.     SetValue(arr, len);
  1112.   else
  1113.     value = arr;
  1114.   return *this;
  1115. }
  1116. void PASN_OctetString::SetValue(const BYTE * data, PINDEX len)
  1117. {
  1118.   if ((unsigned)len > upperLimit)
  1119.     len = upperLimit;
  1120.   value.SetSize((int)len < lowerLimit ? lowerLimit : len);
  1121.   memcpy(value.GetPointer(), data, len);
  1122. }
  1123. PString PASN_OctetString::AsString() const
  1124. {
  1125.   if (value.IsEmpty())
  1126.     return PString();
  1127.   return PString((const char *)(const BYTE *)value, value.GetSize());
  1128. }
  1129. void PASN_OctetString::SetConstraints(ConstraintType type, int lower, unsigned upper)
  1130. {
  1131.   PAssert(lower >= 0, PInvalidParameter);
  1132.   PASN_ConstrainedObject::SetConstraints(type, lower, upper);
  1133.   if (constraint != Unconstrained) {
  1134.     if (value.GetSize() < (PINDEX)lowerLimit)
  1135.       value.SetSize(lowerLimit);
  1136.     else if ((unsigned)value.GetSize() > upperLimit)
  1137.       value.SetSize(upperLimit);
  1138.   }
  1139. }
  1140. PObject::Comparison PASN_OctetString::Compare(const PObject & obj) const
  1141. {
  1142.   PAssert(obj.IsDescendant(PASN_OctetString::Class()), PInvalidCast);
  1143.   const PASN_OctetString & other = (const PASN_OctetString &)obj;
  1144.   return value.Compare(other.value);
  1145. }
  1146. PObject * PASN_OctetString::Clone() const
  1147. {
  1148.   PAssert(IsClass(PASN_OctetString::Class()), PInvalidCast);
  1149.   return new PASN_OctetString(*this);
  1150. }
  1151. void PASN_OctetString::PrintOn(ostream & strm) const
  1152. {
  1153.   int indent = strm.precision() + 2;
  1154.   strm << ' ' << value.GetSize() << " octets {n";
  1155.   PINDEX i = 0;
  1156.   while (i < value.GetSize()) {
  1157.     strm << setw(indent) << " " << hex << setfill('0');
  1158.     PINDEX j;
  1159.     for (j = 0; j < 16; j++) {
  1160.       if (i+j < value.GetSize())
  1161.         strm << setw(2) << (unsigned)value[i+j] << ' ';
  1162.       else
  1163.         strm << "   ";
  1164.     }
  1165.     strm << "  ";
  1166.     for (j = 0; j < 16; j++) {
  1167.       if (i+j < value.GetSize()) {
  1168.         if (isprint(value[i+j]))
  1169.           strm << value[i+j];
  1170.         else
  1171.           strm << ' ';
  1172.       }
  1173.     }
  1174.     strm << dec << setfill(' ') << 'n';
  1175.     i += 16;
  1176.   }
  1177.   strm << setw(indent-1) << "}";
  1178. }
  1179. PString PASN_OctetString::GetTypeAsString() const
  1180. {
  1181.   return "Octet String";
  1182. }
  1183. PINDEX PASN_OctetString::GetDataLength() const
  1184. {
  1185.   return value.GetSize();
  1186. }
  1187. BOOL PASN_OctetString::Decode(PASN_Stream & strm)
  1188. {
  1189.   return strm.OctetStringDecode(*this);
  1190. }
  1191. void PASN_OctetString::Encode(PASN_Stream & strm) const
  1192. {
  1193.   strm.OctetStringEncode(*this);
  1194. }
  1195. BOOL PASN_OctetString::DecodePER(PPER_Stream & strm)
  1196. {
  1197.   // X.691 Section 16
  1198.   unsigned nBytes;
  1199.   if (ConstrainedLengthDecode(strm, nBytes) < 0)
  1200.     return FALSE;
  1201.   value.SetSize(nBytes);   // 16.5
  1202.   switch (nBytes) {
  1203.     case 0 :
  1204.       break;
  1205.     case 1 :  // 16.6
  1206.       if (strm.IsAtEnd())
  1207.         return FALSE;
  1208.       value[0] = (BYTE)strm.MultiBitDecode(8);
  1209.       break;
  1210.     case 2 :  // 16.6
  1211.       if (strm.IsAtEnd())
  1212.         return FALSE;
  1213.       value[0] = (BYTE)strm.MultiBitDecode(8);
  1214.       value[1] = (BYTE)strm.MultiBitDecode(8);
  1215.       break;
  1216.     default: // 16.7
  1217.       return strm.BlockDecode(value.GetPointer(), nBytes) == nBytes;
  1218.   }
  1219.   return TRUE;
  1220. }
  1221. void PASN_OctetString::EncodePER(PPER_Stream & strm) const
  1222. {
  1223.   // X.691 Section 16
  1224.   PINDEX nBytes = value.GetSize();
  1225.   ConstrainedLengthEncode(strm, nBytes);
  1226.   switch (nBytes) {
  1227.     case 0 :  // 16.5
  1228.       break;
  1229.     case 1 :  // 16.6
  1230.       strm.MultiBitEncode(value[0], 8);
  1231.       break;
  1232.     case 2 :  // 16.6
  1233.       strm.MultiBitEncode(value[0], 8);
  1234.       strm.MultiBitEncode(value[1], 8);
  1235.       break;
  1236.     default: // 16.7
  1237.       strm.BlockEncode(value, nBytes);
  1238.   }
  1239. }
  1240. BOOL PBER_Stream::OctetStringDecode(PASN_OctetString & value)
  1241. {
  1242.   unsigned len;
  1243.   if (!HeaderDecode(value, len))
  1244.     return FALSE;
  1245.   return BlockDecode(value.GetPointer(len), len) == len;
  1246. }
  1247. void PBER_Stream::OctetStringEncode(const PASN_OctetString & value)
  1248. {
  1249.   HeaderEncode(value);
  1250.   BlockEncode(value, value.GetSize());
  1251. }
  1252. BOOL PPER_Stream::OctetStringDecode(PASN_OctetString & value)
  1253. {
  1254.   return value.DecodePER(*this);
  1255. }
  1256. void PPER_Stream::OctetStringEncode(const PASN_OctetString & value)
  1257. {
  1258.   value.EncodePER(*this);
  1259. }
  1260. ///////////////////////////////////////////////////////////////////////
  1261. PASN_ConstrainedString::PASN_ConstrainedString(const char * canonical, PINDEX size,
  1262.                                                unsigned tag, TagClass tagClass)
  1263.   : PASN_ConstrainedObject(tag, tagClass)
  1264. {
  1265.   canonicalSet = canonical;
  1266.   canonicalSetSize = size;
  1267.   canonicalSetBits = CountBits(size);
  1268.   charSetUnalignedBits = 8;
  1269.   charSetAlignedBits = 8;
  1270. }
  1271. PASN_ConstrainedString & PASN_ConstrainedString::operator=(const char * str)
  1272. {
  1273.   value = PString();
  1274.   PINDEX len = strlen(str);
  1275.   for (PINDEX i = 0; i < len; i++) {
  1276.     PINDEX sz = characterSet.GetSize();
  1277.     if (sz == 0 || memchr(characterSet, str[i], sz) != NULL)
  1278.       value += str[i];
  1279.   }
  1280.   return *this;
  1281. }
  1282. void PASN_ConstrainedString::SetCharacterSet(ConstraintType ctype, const char * set)
  1283. {
  1284.   SetCharacterSet(set, strlen(set), ctype);
  1285. }
  1286. void PASN_ConstrainedString::SetCharacterSet(ConstraintType ctype, unsigned firstChar, unsigned lastChar)
  1287. {
  1288.   char buffer[256];
  1289.   for (unsigned i = firstChar; i < lastChar; i++)
  1290.     buffer[i] = (char)i;
  1291.   SetCharacterSet(buffer, lastChar - firstChar + 1, ctype);
  1292. }
  1293. void PASN_ConstrainedString::SetCharacterSet(const char * set, PINDEX setSize, ConstraintType ctype)
  1294. {
  1295.   if (ctype == Unconstrained)
  1296.     characterSet.SetSize(0);
  1297.   else {
  1298.     characterSet.SetSize(setSize);
  1299.     PINDEX count = 0;
  1300.     for (PINDEX i = 0; i < canonicalSetSize; i++) {
  1301.       if (memchr(set, canonicalSet[i], setSize) != NULL)
  1302.         characterSet[count++] = canonicalSet[i];
  1303.     }
  1304.     PAssert(count > 0, PInvalidParameter);
  1305.     characterSet.SetSize(count);
  1306.   }
  1307.   if (characterSet.IsEmpty())
  1308.     charSetUnalignedBits = 8;
  1309.   else
  1310.     charSetUnalignedBits = CountBits(characterSet.GetSize());
  1311.   charSetAlignedBits = 1;
  1312.   while (charSetUnalignedBits > charSetAlignedBits)
  1313.     charSetAlignedBits <<= 1;
  1314. }
  1315. PObject::Comparison PASN_ConstrainedString::Compare(const PObject & obj) const
  1316. {
  1317.   PAssert(obj.IsDescendant(PASN_ConstrainedString::Class()), PInvalidCast);
  1318.   const PASN_ConstrainedString & other = (const PASN_ConstrainedString &)obj;
  1319.   return value.Compare(other.value);
  1320. }
  1321. void PASN_ConstrainedString::PrintOn(ostream & strm) const
  1322. {
  1323.   strm << value.ToLiteral();
  1324. }
  1325. PINDEX PASN_ConstrainedString::GetDataLength() const
  1326. {
  1327.   return value.GetSize()-1;
  1328. }
  1329. BOOL PASN_ConstrainedString::Decode(PASN_Stream & strm)
  1330. {
  1331.   return strm.ConstrainedStringDecode(*this);
  1332. }
  1333. void PASN_ConstrainedString::Encode(PASN_Stream & strm) const
  1334. {
  1335.   strm.ConstrainedStringEncode(*this);
  1336. }
  1337. BOOL PASN_ConstrainedString::DecodeBER(PBER_Stream & strm, unsigned len)
  1338. {
  1339.   return strm.BlockDecode((BYTE *)value.GetPointer(len+1), len) == len;
  1340. }
  1341. void PASN_ConstrainedString::EncodeBER(PBER_Stream & strm) const
  1342. {
  1343.   strm.BlockEncode(value, value.GetSize()-1);
  1344. }
  1345. BOOL PASN_ConstrainedString::DecodePER(PPER_Stream & strm)
  1346. {
  1347.   // X.691 Section 26
  1348.   unsigned len;
  1349.   if (ConstrainedLengthDecode(strm, len) < 0)
  1350.     return FALSE;
  1351.   unsigned nBits = strm.IsAligned() ? charSetAlignedBits : charSetUnalignedBits;
  1352.   if (constraint == Unconstrained || upperLimit*nBits > 16) {
  1353.     if (nBits == 8)
  1354.       return strm.BlockDecode((BYTE *)value.GetPointer(len+1), len) == len;
  1355.     if (strm.IsAligned())
  1356.       strm.ByteAlign();
  1357.   }
  1358.   value.SetSize(len+1);
  1359.   PINDEX i;
  1360.   for (i = 0; i < (PINDEX)len; i++) {
  1361.     if (strm.IsAtEnd())
  1362.       return FALSE;
  1363.     if (nBits >= canonicalSetBits && canonicalSetBits > 4)
  1364.       value[i] = (char)strm.MultiBitDecode(nBits);
  1365.     else
  1366.       value[i] = characterSet[strm.MultiBitDecode(nBits)];
  1367.   }
  1368.   value[i] = '';
  1369.   return TRUE;
  1370. }
  1371. void PASN_ConstrainedString::EncodePER(PPER_Stream & strm) const
  1372. {
  1373.   // X.691 Section 26
  1374.   PINDEX len = value.GetSize()-1;
  1375.   ConstrainedLengthEncode(strm, len);
  1376.   unsigned nBits = strm.IsAligned() ? charSetAlignedBits : charSetUnalignedBits;
  1377.   if (constraint == Unconstrained || upperLimit*nBits > 16) {
  1378.     if (nBits == 8) {
  1379.       strm.BlockEncode((const BYTE *)(const char *)value, len);
  1380.       return;
  1381.     }
  1382.     if (strm.IsAligned())
  1383.       strm.ByteAlign();
  1384.   }
  1385.   for (PINDEX i = 0; i < len; i++) {
  1386.     if (nBits >= canonicalSetBits && canonicalSetBits > 4)
  1387.       strm.MultiBitEncode(value[i], nBits);
  1388.     else {
  1389.       const void * ptr = memchr(characterSet, value[i], characterSet.GetSize());
  1390.       PINDEX pos = 0;
  1391.       if (ptr != NULL)
  1392.         pos = ((const char *)ptr - (const char *)characterSet);
  1393.       strm.MultiBitEncode(pos, nBits);
  1394.     }
  1395.   }
  1396. }
  1397. BOOL PBER_Stream::ConstrainedStringDecode(PASN_ConstrainedString & value)
  1398. {
  1399.   unsigned len;
  1400.   if (!HeaderDecode(value, len))
  1401.     return FALSE;
  1402.   return value.DecodeBER(*this, len);
  1403. }
  1404. void PBER_Stream::ConstrainedStringEncode(const PASN_ConstrainedString & value)
  1405. {
  1406.   HeaderEncode(value);
  1407.   value.Encode(*this);
  1408. }
  1409. BOOL PPER_Stream::ConstrainedStringDecode(PASN_ConstrainedString & value)
  1410. {
  1411.   return value.DecodePER(*this);
  1412. }
  1413. void PPER_Stream::ConstrainedStringEncode(const PASN_ConstrainedString & value)
  1414. {
  1415.   value.EncodePER(*this);
  1416. }
  1417. #define DEFINE_STRING_CLASS(name, set) 
  1418.   static const char name##StringSet[] = set; 
  1419.   PASN_##name##String::PASN_##name##String(unsigned tag, TagClass tagClass) 
  1420.     : PASN_ConstrainedString(name##StringSet, sizeof(name##StringSet)-1, tag, tagClass) 
  1421.     { } 
  1422.     PASN_##name##String & PASN_##name##String::operator=(const char * str) 
  1423.     { PASN_ConstrainedString::SetValue(str); return *this; } 
  1424.   PASN_##name##String & PASN_##name##String::operator=(const PString & str) 
  1425.     { PASN_ConstrainedString::SetValue(str); return *this; } 
  1426.   PObject * PASN_##name##String::Clone() const 
  1427.     { PAssert(IsClass(PASN_##name##String::Class()), PInvalidCast); 
  1428.       return new PASN_##name##String(*this); } 
  1429.   PString PASN_##name##String::GetTypeAsString() const 
  1430.     { return #name " String"; }
  1431. DEFINE_STRING_CLASS(Numeric,   " 0123456789")
  1432. DEFINE_STRING_CLASS(Printable, " '()+,-./0123456789:=?"
  1433.                                "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  1434.                                "abcdefghijklmnopqrstuvwxyz")
  1435. DEFINE_STRING_CLASS(Visible,   " !"#$%&'()*+,-./0123456789:;<=>?"
  1436.                                "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_"
  1437.                                "`abcdefghijklmnopqrstuvwxyz{|}~")
  1438. DEFINE_STRING_CLASS(IA5,       "0001020304050607"
  1439.                                "1011121314151617"
  1440.                                "2021222324252627"
  1441.                                "3031323334353637"
  1442.                                " !"#$%&'()*+,-./0123456789:;<=>?"
  1443.                                "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_"
  1444.                                "`abcdefghijklmnopqrstuvwxyz{|}~177")
  1445. DEFINE_STRING_CLASS(General,   "0001020304050607"
  1446.                                "1011121314151617"
  1447.                                "2021222324252627"
  1448.                                "3031323334353637"
  1449.                                " !"#$%&'()*+,-./0123456789:;<=>?"
  1450.                                "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_"
  1451.                                "`abcdefghijklmnopqrstuvwxyz{|}~177"
  1452.                                "200201202203204205206207"
  1453.                                "210211212213214215216217"
  1454.                                "220221222223224225226227"
  1455.                                "230231232233234235236237"
  1456.                                "240241242243244245246247"
  1457.                                "250251252253254255256257"
  1458.                                "260261262263264265266267"
  1459.                                "270271272273274275276277"
  1460.                                "300301302303304305306307"
  1461.                                "310311312313314315316317"
  1462.                                "320321322323324325326327"
  1463.                                "330331332333334335336337"
  1464.                                "340341342343344345346347"
  1465.                                "350351352353354355356357"
  1466.                                "360361362363364365366367"
  1467.                                "370371372373374375376377")
  1468. ///////////////////////////////////////////////////////////////////////
  1469. PASN_BMPString::PASN_BMPString(unsigned tag, TagClass tagClass)
  1470.   : PASN_ConstrainedObject(tag, tagClass)
  1471. {
  1472.   firstChar = 0;
  1473.   lastChar = 0xffff;
  1474.   charSetAlignedBits = 16;
  1475.   charSetUnalignedBits = 16;
  1476. }
  1477. PASN_BMPString::PASN_BMPString(const PASN_BMPString & other)
  1478.   : PASN_ConstrainedObject(other),
  1479.     value(other.value, other.value.GetSize()),
  1480.     characterSet(other.characterSet)
  1481. {
  1482.   firstChar = other.firstChar;
  1483.   lastChar = other.lastChar;
  1484.   charSetAlignedBits = other.charSetAlignedBits;
  1485.   charSetUnalignedBits = other.charSetUnalignedBits;
  1486. }
  1487. PASN_BMPString & PASN_BMPString::operator=(const PASN_BMPString & other)
  1488. {
  1489.   PASN_ConstrainedObject::operator=(other);
  1490.   value = PWORDArray(other.value, other.value.GetSize());
  1491.   characterSet = other.characterSet;
  1492.   firstChar = other.firstChar;
  1493.   lastChar = other.lastChar;
  1494.   charSetAlignedBits = other.charSetAlignedBits;
  1495.   charSetUnalignedBits = other.charSetUnalignedBits;
  1496.   return *this;
  1497. }
  1498. BOOL PASN_BMPString::IsLegalCharacter(WORD ch)
  1499. {
  1500.   if (ch < firstChar)
  1501.     return FALSE;
  1502.   if (ch > lastChar)
  1503.     return FALSE;
  1504.   if (characterSet.IsEmpty())
  1505.     return TRUE;
  1506.   const WORD * wptr = characterSet;
  1507.   PINDEX count = characterSet.GetSize();
  1508.   while (count-- > 0) {
  1509.     if (*wptr == ch)
  1510.       return TRUE;
  1511.     wptr++;
  1512.   }
  1513.   return FALSE;
  1514. }
  1515. PASN_BMPString & PASN_BMPString::operator=(const PString & str)
  1516. {
  1517.   PINDEX sz = str.GetLength();
  1518.   value.SetSize(sz);
  1519.   PINDEX count = 0;
  1520.   for (PINDEX i = 0; i < sz; i++) {
  1521.     WORD c = (BYTE)str[i];
  1522.     if (IsLegalCharacter(c))
  1523.       value[count++] = c;
  1524.   }
  1525.   value.SetSize(count);
  1526.   return *this;
  1527. }
  1528. PASN_BMPString & PASN_BMPString::operator=(const PWORDArray & array)
  1529. {
  1530.   PINDEX sz = array.GetSize();
  1531.   value.SetSize(sz);
  1532.   PINDEX count = 0;
  1533.   for (PINDEX i = 0; i < sz; i++) {
  1534.     WORD c = array[i];
  1535.     if (IsLegalCharacter(c))
  1536.       value[count++] = c;
  1537.   }
  1538.   value.SetSize(count);
  1539.   return *this;
  1540. }
  1541. PString PASN_BMPString::GetValue() const
  1542. {
  1543.   PString str;
  1544.   for (PINDEX i = 0; i < value.GetSize(); i++) {
  1545.     if (value[i] < 256)
  1546.       str += (char)value[i];
  1547.   }
  1548.   return str;
  1549. }
  1550. void PASN_BMPString::SetCharacterSet(ConstraintType ctype, const char * charSet)
  1551. {
  1552.   PWORDArray array(strlen(charSet));
  1553.   PINDEX count = 0;
  1554.   while (*charSet != '')
  1555.     array[count++] = (BYTE)*charSet++;
  1556.   SetCharacterSet(ctype, array);
  1557. }
  1558. void PASN_BMPString::SetCharacterSet(ConstraintType ctype, const PWORDArray & charSet)
  1559. {
  1560.   if (ctype == Unconstrained) {
  1561.     firstChar = 0;
  1562.     lastChar = 0xffff;
  1563.     characterSet.SetSize(0);
  1564.   }
  1565.   else {
  1566.     characterSet = charSet;
  1567.     charSetUnalignedBits = CountBits(lastChar - firstChar + 1);
  1568.     if (!charSet.IsEmpty()) {
  1569.       unsigned count = 0;
  1570.       for (PINDEX i = 0; i < charSet.GetSize(); i++) {
  1571.         if (characterSet[i] >= firstChar && characterSet[i] <= lastChar)
  1572.           count++;
  1573.       }
  1574.       count = CountBits(count);
  1575.       if (charSetUnalignedBits > count)
  1576.         charSetUnalignedBits = count;
  1577.     }
  1578.     charSetAlignedBits = 1;
  1579.     while (charSetUnalignedBits > charSetAlignedBits)
  1580.       charSetAlignedBits <<= 1;
  1581.     SetValue(value);
  1582.   }
  1583. }
  1584. void PASN_BMPString::SetCharacterSet(ConstraintType ctype, unsigned first, unsigned last)
  1585. {
  1586.   if (ctype != Unconstrained) {
  1587.     PAssert(first < 0x10000 && last < 0x10000 && last > first, PInvalidParameter);
  1588.     firstChar = (WORD)first;
  1589.     lastChar = (WORD)last;
  1590.   }
  1591.   SetCharacterSet(ctype, characterSet);
  1592. }
  1593. PObject * PASN_BMPString::Clone() const
  1594. {
  1595.   PAssert(IsClass(PASN_BMPString::Class()), PInvalidCast);
  1596.   return new PASN_BMPString(*this);
  1597. }
  1598. PObject::Comparison PASN_BMPString::Compare(const PObject & obj) const
  1599. {
  1600.   PAssert(obj.IsDescendant(PASN_BMPString::Class()), PInvalidCast);
  1601.   const PASN_BMPString & other = (const PASN_BMPString &)obj;
  1602.   return value.Compare(other.value);
  1603. }
  1604. void PASN_BMPString::PrintOn(ostream & strm) const
  1605. {
  1606.   int indent = strm.precision() + 2;
  1607.   PINDEX sz = value.GetSize();
  1608.   strm << ' ' << sz << " characters {n";
  1609.   PINDEX i = 0;
  1610.   while (i < sz) {
  1611.     strm << setw(indent) << " " << hex << setfill('0');
  1612.     PINDEX j;
  1613.     for (j = 0; j < 8; j++)
  1614.       if (i+j < sz)
  1615.         strm << setw(4) << value[i+j] << ' ';
  1616.       else
  1617.         strm << "     ";
  1618.     strm << "  ";
  1619.     for (j = 0; j < 8; j++) {
  1620.       if (i+j < sz) {
  1621.         WORD c = value[i+j];
  1622.         if (c < 128 && isprint(c))
  1623.           strm << (char)c;
  1624.         else
  1625.           strm << ' ';
  1626.       }
  1627.     }
  1628.     strm << dec << setfill(' ') << 'n';
  1629.     i += 8;
  1630.   }
  1631.   strm << setw(indent-1) << "}";
  1632. }
  1633. PString PASN_BMPString::GetTypeAsString() const
  1634. {
  1635.   return "BMP String";
  1636. }
  1637. PINDEX PASN_BMPString::GetDataLength() const
  1638. {
  1639.   return value.GetSize()*2;
  1640. }
  1641. BOOL PASN_BMPString::Decode(PASN_Stream & strm)
  1642. {
  1643.   return strm.BMPStringDecode(*this);
  1644. }
  1645. void PASN_BMPString::Encode(PASN_Stream & strm) const
  1646. {
  1647.   strm.BMPStringEncode(*this);
  1648. }
  1649. BOOL PASN_BMPString::DecodeBER(PBER_Stream & strm, unsigned len)
  1650. {
  1651.   value.SetSize(len/2);
  1652.   return strm.BlockDecode((BYTE *)value.GetPointer(len), len) == len;
  1653. }
  1654. void PASN_BMPString::EncodeBER(PBER_Stream & strm) const
  1655. {
  1656.   strm.BlockEncode((const BYTE *)(const WORD *)value, value.GetSize()*2);
  1657. }
  1658. BOOL PASN_BMPString::DecodePER(PPER_Stream & strm)
  1659. {
  1660.   // X.691 Section 26
  1661.   unsigned len;
  1662.   if (ConstrainedLengthDecode(strm, len) < 0)
  1663.     return FALSE;
  1664.   value.SetSize(len);
  1665.   PINDEX nBits = strm.IsAligned() ? charSetAlignedBits : charSetUnalignedBits;
  1666.   if ((constraint == Unconstrained || upperLimit*nBits > 16) && strm.IsAligned())
  1667.     strm.ByteAlign();
  1668.   for (PINDEX i = 0; i < (PINDEX)len; i++) {
  1669.     if (strm.IsAtEnd())
  1670.       return FALSE;
  1671.     if (characterSet.IsEmpty())
  1672.       value[i] = (WORD)(strm.MultiBitDecode(nBits) + firstChar);
  1673.     else
  1674.       value[i] = characterSet[strm.MultiBitDecode(nBits)];
  1675.   }
  1676.   return TRUE;
  1677. }
  1678. void PASN_BMPString::EncodePER(PPER_Stream & strm) const
  1679. {
  1680.   // X.691 Section 26
  1681.   PINDEX len = value.GetSize();
  1682.   ConstrainedLengthEncode(strm, len);
  1683.   PINDEX nBits = strm.IsAligned() ? charSetAlignedBits : charSetUnalignedBits;
  1684.   if ((constraint == Unconstrained || upperLimit*nBits > 16) && strm.IsAligned())
  1685.     strm.ByteAlign();
  1686.   for (PINDEX i = 0; i < len; i++) {
  1687.     if (characterSet.IsEmpty())
  1688.       strm.MultiBitEncode(value[i] - firstChar, nBits);
  1689.     else {
  1690.       for (PINDEX pos = 0; pos < characterSet.GetSize(); pos++) {
  1691.         if (characterSet[pos] == value[i]) {
  1692.           strm.MultiBitEncode(pos, nBits);
  1693.           break;
  1694.         }
  1695.       }
  1696.     }
  1697.   }
  1698. }
  1699. BOOL PBER_Stream::BMPStringDecode(PASN_BMPString & value)
  1700. {
  1701.   unsigned len;
  1702.   if (!HeaderDecode(value, len))
  1703.     return FALSE;
  1704.   return value.DecodeBER(*this, len);
  1705. }
  1706. void PBER_Stream::BMPStringEncode(const PASN_BMPString & value)
  1707. {
  1708.   HeaderEncode(value);
  1709.   value.EncodeBER(*this);
  1710. }
  1711. BOOL PPER_Stream::BMPStringDecode(PASN_BMPString & value)
  1712. {
  1713.   return value.DecodePER(*this);
  1714. }
  1715. void PPER_Stream::BMPStringEncode(const PASN_BMPString & value)
  1716. {
  1717.   value.EncodePER(*this);
  1718. }
  1719. ///////////////////////////////////////////////////////////////////////
  1720. PASN_Choice::PASN_Choice(unsigned nChoices, BOOL extend)
  1721.   : PASN_Object(0, ApplicationTagClass, extend)
  1722. {
  1723.   numChoices = nChoices;
  1724.   choice = NULL;
  1725. }
  1726. PASN_Choice::PASN_Choice(unsigned tag, TagClass tagClass,
  1727.                          unsigned upper, BOOL extend)
  1728.   : PASN_Object(tag, tagClass, extend)
  1729. {
  1730.   numChoices = upper;
  1731.   choice = NULL;
  1732. }
  1733. PASN_Choice::PASN_Choice(unsigned tag, TagClass tagClass,
  1734.                          unsigned upper, BOOL extend, const PString & nameSpec)
  1735.   : PASN_Object(tag, tagClass, extend),
  1736.     names(BuildNamesDict(nameSpec))
  1737. {
  1738.   numChoices = upper;
  1739.   choice = NULL;
  1740. }
  1741. PASN_Choice::PASN_Choice(const PASN_Choice & other)
  1742.   : PASN_Object(other),
  1743.     names(other.names)
  1744. {
  1745.   numChoices = other.numChoices;
  1746.   if (other.choice != NULL)
  1747.     choice = (PASN_Object *)other.choice->Clone();
  1748.   else
  1749.     choice = NULL;
  1750. }
  1751. PASN_Choice & PASN_Choice::operator=(const PASN_Choice & other)
  1752. {
  1753.   delete choice;
  1754.   PASN_Object::operator=(other);
  1755.   numChoices = other.numChoices;
  1756.   names = other.names;
  1757.   if (other.choice != NULL)
  1758.     choice = (PASN_Object *)other.choice->Clone();
  1759.   else
  1760.     choice = NULL;
  1761.   return *this;
  1762. }
  1763. PASN_Choice::~PASN_Choice()
  1764. {
  1765.   delete choice;
  1766. }
  1767. void PASN_Choice::SetTag(unsigned newTag, TagClass tagClass)
  1768. {
  1769.   PASN_Object::SetTag(newTag, tagClass);
  1770.   delete choice;
  1771.   if (CreateObject())
  1772.     choice->SetTag(newTag, tagClass);
  1773. }
  1774. PString PASN_Choice::GetTagName() const
  1775. {
  1776.   if (tag == UINT_MAX)
  1777.     return "<uninitialised>";
  1778.   if (names.Contains(tag))
  1779.     return names[tag];
  1780.   if (choice != NULL && choice->IsDescendant(PASN_Choice::Class()) &&
  1781.       choice->GetTag() == tag && choice->GetTagClass() == tagClass)
  1782.     return PString(choice->GetClass()) + "->" + ((PASN_Choice *)choice)->GetTagName();
  1783.   return psprintf("<%u>", tag);
  1784. }
  1785. PASN_Object & PASN_Choice::GetObject() const
  1786. {
  1787.   PAssert(choice != NULL, "NULL Choice");
  1788.   return *choice;
  1789. }
  1790. #if defined(__GNUC__) && __GNUC__ <= 2 && __GNUC_MINOR__ < 9
  1791. PASN_Choice::operator PASN_Null &() const
  1792. {
  1793.   PAssert(PAssertNULL(choice)->IsDescendant(PASN_Null::Class()), PInvalidCast);
  1794.   return *(PASN_Null *)choice;
  1795. }
  1796. PASN_Choice::operator PASN_Boolean &() const
  1797. {
  1798.   PAssert(PAssertNULL(choice)->IsDescendant(PASN_Boolean::Class()), PInvalidCast);
  1799.   return *(PASN_Boolean *)choice;
  1800. }
  1801. PASN_Choice::operator PASN_Integer &() const
  1802. {
  1803.   PAssert(PAssertNULL(choice)->IsDescendant(PASN_Integer::Class()), PInvalidCast);
  1804.   return *(PASN_Integer *)choice;
  1805. }
  1806. PASN_Choice::operator PASN_Enumeration &() const
  1807. {
  1808.   PAssert(PAssertNULL(choice)->IsDescendant(PASN_Enumeration::Class()), PInvalidCast);
  1809.   return *(PASN_Enumeration *)choice;
  1810. }
  1811. PASN_Choice::operator PASN_Real &() const
  1812. {
  1813.   PAssert(PAssertNULL(choice)->IsDescendant(PASN_Real::Class()), PInvalidCast);
  1814.   return *(PASN_Real *)choice;
  1815. }
  1816. PASN_Choice::operator PASN_ObjectId &() const
  1817. {
  1818.   PAssert(PAssertNULL(choice)->IsDescendant(PASN_ObjectId::Class()), PInvalidCast);
  1819.   return *(PASN_ObjectId *)choice;
  1820. }
  1821. PASN_Choice::operator PASN_BitString &() const
  1822. {
  1823.   PAssert(PAssertNULL(choice)->IsDescendant(PASN_BitString::Class()), PInvalidCast);
  1824.   return *(PASN_BitString *)choice;
  1825. }
  1826. PASN_Choice::operator PASN_OctetString &() const
  1827. {
  1828.   PAssert(PAssertNULL(choice)->IsDescendant(PASN_OctetString::Class()), PInvalidCast);
  1829.   return *(PASN_OctetString *)choice;
  1830. }
  1831. PASN_Choice::operator PASN_NumericString &() const
  1832. {
  1833.   PAssert(PAssertNULL(choice)->IsDescendant(PASN_NumericString::Class()), PInvalidCast);
  1834.   return *(PASN_NumericString *)choice;
  1835. }
  1836. PASN_Choice::operator PASN_PrintableString &() const
  1837. {
  1838.   PAssert(PAssertNULL(choice)->IsDescendant(PASN_PrintableString::Class()), PInvalidCast);
  1839.   return *(PASN_PrintableString *)choice;
  1840. }
  1841. PASN_Choice::operator PASN_VisibleString &() const
  1842. {
  1843.   PAssert(PAssertNULL(choice)->IsDescendant(PASN_VisibleString::Class()), PInvalidCast);
  1844.   return *(PASN_VisibleString *)choice;
  1845. }
  1846. PASN_Choice::operator PASN_IA5String &() const
  1847. {
  1848.   PAssert(PAssertNULL(choice)->IsDescendant(PASN_IA5String::Class()), PInvalidCast);
  1849.   return *(PASN_IA5String *)choice;
  1850. }
  1851. PASN_Choice::operator PASN_GeneralString &() const
  1852. {
  1853.   PAssert(PAssertNULL(choice)->IsDescendant(PASN_GeneralString::Class()), PInvalidCast);
  1854.   return *(PASN_GeneralString *)choice;
  1855. }
  1856. PASN_Choice::operator PASN_BMPString &() const
  1857. {
  1858.   PAssert(PAssertNULL(choice)->IsDescendant(PASN_BMPString::Class()), PInvalidCast);
  1859.   return *(PASN_BMPString *)choice;
  1860. }
  1861. PASN_Choice::operator PASN_Sequence &() const
  1862. {
  1863.   PAssert(PAssertNULL(choice)->IsDescendant(PASN_Sequence::Class()), PInvalidCast);
  1864.   return *(PASN_Sequence *)choice;
  1865. }
  1866. #else
  1867. PASN_Choice::operator PASN_Null &()
  1868. {
  1869.   PAssert(PAssertNULL(choice)->IsDescendant(PASN_Null::Class()), PInvalidCast);
  1870.   return *(PASN_Null *)choice;
  1871. }
  1872. PASN_Choice::operator PASN_Boolean &()
  1873. {
  1874.   PAssert(PAssertNULL(choice)->IsDescendant(PASN_Boolean::Class()), PInvalidCast);
  1875.   return *(PASN_Boolean *)choice;
  1876. }
  1877. PASN_Choice::operator PASN_Integer &()
  1878. {
  1879.   PAssert(PAssertNULL(choice)->IsDescendant(PASN_Integer::Class()), PInvalidCast);
  1880.   return *(PASN_Integer *)choice;
  1881. }
  1882. PASN_Choice::operator PASN_Enumeration &()
  1883. {
  1884.   PAssert(PAssertNULL(choice)->IsDescendant(PASN_Enumeration::Class()), PInvalidCast);
  1885.   return *(PASN_Enumeration *)choice;
  1886. }
  1887. PASN_Choice::operator PASN_Real &()
  1888. {
  1889.   PAssert(PAssertNULL(choice)->IsDescendant(PASN_Real::Class()), PInvalidCast);
  1890.   return *(PASN_Real *)choice;
  1891. }
  1892. PASN_Choice::operator PASN_ObjectId &()
  1893. {
  1894.   PAssert(PAssertNULL(choice)->IsDescendant(PASN_ObjectId::Class()), PInvalidCast);
  1895.   return *(PASN_ObjectId *)choice;
  1896. }
  1897. PASN_Choice::operator PASN_BitString &()
  1898. {
  1899.   PAssert(PAssertNULL(choice)->IsDescendant(PASN_BitString::Class()), PInvalidCast);
  1900.   return *(PASN_BitString *)choice;
  1901. }
  1902. PASN_Choice::operator PASN_OctetString &()
  1903. {
  1904.   PAssert(PAssertNULL(choice)->IsDescendant(PASN_OctetString::Class()), PInvalidCast);
  1905.   return *(PASN_OctetString *)choice;
  1906. }
  1907. PASN_Choice::operator PASN_NumericString &()
  1908. {
  1909.   PAssert(PAssertNULL(choice)->IsDescendant(PASN_NumericString::Class()), PInvalidCast);
  1910.   return *(PASN_NumericString *)choice;
  1911. }
  1912. PASN_Choice::operator PASN_PrintableString &()
  1913. {
  1914.   PAssert(PAssertNULL(choice)->IsDescendant(PASN_PrintableString::Class()), PInvalidCast);
  1915.   return *(PASN_PrintableString *)choice;
  1916. }
  1917. PASN_Choice::operator PASN_VisibleString &()
  1918. {
  1919.   PAssert(PAssertNULL(choice)->IsDescendant(PASN_VisibleString::Class()), PInvalidCast);
  1920.   return *(PASN_VisibleString *)choice;
  1921. }
  1922. PASN_Choice::operator PASN_IA5String &()
  1923. {
  1924.   PAssert(PAssertNULL(choice)->IsDescendant(PASN_IA5String::Class()), PInvalidCast);
  1925.   return *(PASN_IA5String *)choice;
  1926. }
  1927. PASN_Choice::operator PASN_GeneralString &()
  1928. {
  1929.   PAssert(PAssertNULL(choice)->IsDescendant(PASN_GeneralString::Class()), PInvalidCast);
  1930.   return *(PASN_GeneralString *)choice;
  1931. }
  1932. PASN_Choice::operator PASN_BMPString &()
  1933. {
  1934.   PAssert(PAssertNULL(choice)->IsDescendant(PASN_BMPString::Class()), PInvalidCast);
  1935.   return *(PASN_BMPString *)choice;
  1936. }
  1937. PASN_Choice::operator PASN_Sequence &()
  1938. {
  1939.   PAssert(PAssertNULL(choice)->IsDescendant(PASN_Sequence::Class()), PInvalidCast);
  1940.   return *(PASN_Sequence *)choice;
  1941. }
  1942. PASN_Choice::operator const PASN_Null &() const
  1943. {
  1944.   PAssert(PAssertNULL(choice)->IsDescendant(PASN_Null::Class()), PInvalidCast);
  1945.   return *(const PASN_Null *)choice;
  1946. }
  1947. PASN_Choice::operator const PASN_Boolean &() const
  1948. {
  1949.   PAssert(PAssertNULL(choice)->IsDescendant(PASN_Boolean::Class()), PInvalidCast);
  1950.   return *(const PASN_Boolean *)choice;
  1951. }
  1952. PASN_Choice::operator const PASN_Integer &() const
  1953. {
  1954.   PAssert(PAssertNULL(choice)->IsDescendant(PASN_Integer::Class()), PInvalidCast);
  1955.   return *(const PASN_Integer *)choice;
  1956. }
  1957. PASN_Choice::operator const PASN_Enumeration &() const
  1958. {
  1959.   PAssert(PAssertNULL(choice)->IsDescendant(PASN_Enumeration::Class()), PInvalidCast);
  1960.   return *(const PASN_Enumeration *)choice;
  1961. }
  1962. PASN_Choice::operator const PASN_Real &() const
  1963. {
  1964.   PAssert(PAssertNULL(choice)->IsDescendant(PASN_Real::Class()), PInvalidCast);
  1965.   return *(const PASN_Real *)choice;
  1966. }
  1967. PASN_Choice::operator const PASN_ObjectId &() const
  1968. {
  1969.   PAssert(PAssertNULL(choice)->IsDescendant(PASN_ObjectId::Class()), PInvalidCast);
  1970.   return *(const PASN_ObjectId *)choice;
  1971. }
  1972. PASN_Choice::operator const PASN_BitString &() const
  1973. {
  1974.   PAssert(PAssertNULL(choice)->IsDescendant(PASN_BitString::Class()), PInvalidCast);
  1975.   return *(const PASN_BitString *)choice;
  1976. }
  1977. PASN_Choice::operator const PASN_OctetString &() const
  1978. {
  1979.   PAssert(PAssertNULL(choice)->IsDescendant(PASN_OctetString::Class()), PInvalidCast);
  1980.   return *(const PASN_OctetString *)choice;
  1981. }
  1982. PASN_Choice::operator const PASN_NumericString &() const
  1983. {
  1984.   PAssert(PAssertNULL(choice)->IsDescendant(PASN_NumericString::Class()), PInvalidCast);
  1985.   return *(const PASN_NumericString *)choice;
  1986. }
  1987. PASN_Choice::operator const PASN_PrintableString &() const
  1988. {
  1989.   PAssert(PAssertNULL(choice)->IsDescendant(PASN_PrintableString::Class()), PInvalidCast);
  1990.   return *(const PASN_PrintableString *)choice;
  1991. }
  1992. PASN_Choice::operator const PASN_VisibleString &() const
  1993. {
  1994.   PAssert(PAssertNULL(choice)->IsDescendant(PASN_VisibleString::Class()), PInvalidCast);
  1995.   return *(const PASN_VisibleString *)choice;
  1996. }
  1997. PASN_Choice::operator const PASN_IA5String &() const
  1998. {
  1999.   PAssert(PAssertNULL(choice)->IsDescendant(PASN_IA5String::Class()), PInvalidCast);
  2000.   return *(const PASN_IA5String *)choice;
  2001. }
  2002. PASN_Choice::operator const PASN_GeneralString &() const
  2003. {
  2004.   PAssert(PAssertNULL(choice)->IsDescendant(PASN_GeneralString::Class()), PInvalidCast);
  2005.   return *(const PASN_GeneralString *)choice;
  2006. }
  2007. PASN_Choice::operator const PASN_BMPString &() const
  2008. {
  2009.   PAssert(PAssertNULL(choice)->IsDescendant(PASN_BMPString::Class()), PInvalidCast);
  2010.   return *(const PASN_BMPString *)choice;
  2011. }
  2012. PASN_Choice::operator const PASN_Sequence &() const
  2013. {
  2014.   PAssert(PAssertNULL(choice)->IsDescendant(PASN_Sequence::Class()), PInvalidCast);
  2015.   return *(const PASN_Sequence *)choice;
  2016. }
  2017. #endif
  2018. PObject::Comparison PASN_Choice::Compare(const PObject & obj) const
  2019. {
  2020.   PAssert(obj.IsDescendant(PASN_Choice::Class()), PInvalidCast);
  2021.   const PASN_Choice & other = (const PASN_Choice &)obj;
  2022.   if (choice == other.choice)
  2023.     return EqualTo;
  2024.   if (choice == NULL)
  2025.     return LessThan;
  2026.   if (other.choice == NULL)
  2027.     return GreaterThan;
  2028.   if (tag < other.tag)
  2029.     return LessThan;
  2030.   if (tag > other.tag)
  2031.     return GreaterThan;
  2032.   return choice->Compare(*other.choice);
  2033. }
  2034. void PASN_Choice::PrintOn(ostream & strm) const
  2035. {
  2036.   strm << GetTagName();
  2037.   if (choice != NULL)
  2038.     strm << ' ' << *choice;
  2039.   else
  2040.     strm << " (NULL)";
  2041. }
  2042. PString PASN_Choice::GetTypeAsString() const
  2043. {
  2044.   return "Choice";
  2045. }
  2046. PINDEX PASN_Choice::GetDataLength() const
  2047. {
  2048.   if (choice != NULL)
  2049.     return choice->GetDataLength();
  2050.   return 0;
  2051. }
  2052. BOOL PASN_Choice::IsPrimitive() const
  2053. {
  2054.   if (choice != NULL)
  2055.     return choice->IsPrimitive();
  2056.   return FALSE;
  2057. }
  2058. BOOL PASN_Choice::Decode(PASN_Stream & strm)
  2059. {
  2060.   return strm.ChoiceDecode(*this);
  2061. }
  2062. void PASN_Choice::Encode(PASN_Stream & strm) const
  2063. {
  2064.   strm.ChoiceEncode(*this);
  2065. }
  2066. BOOL PASN_Choice::DecodePER(PPER_Stream & strm)
  2067. {
  2068.   // X.691 Section 22
  2069.   delete choice;
  2070.   if (strm.IsAtEnd()) {
  2071.     choice = NULL;
  2072.     return FALSE;
  2073.   }
  2074.   BOOL ok = TRUE;
  2075.   if (extendable) {
  2076.     if (strm.SingleBitDecode()) {
  2077.       tag = strm.SmallUnsignedDecode() + numChoices;
  2078.       unsigned len;
  2079.       if (strm.LengthDecode(0, INT_MAX, len) != 0)
  2080.         return FALSE;
  2081.       if (CreateObject()) {
  2082.         PINDEX nextPos = strm.GetPosition() + len;
  2083.         ok = choice->Decode(strm);
  2084.         strm.SetPosition(nextPos);
  2085.       }
  2086.       else {
  2087.         PASN_OctetString * open_type = new PASN_OctetString;
  2088.         open_type->SetConstraints(PASN_ConstrainedObject::FixedConstraint, len, len);
  2089.         open_type->Decode(strm);
  2090.         if (open_type->GetSize() > 0)
  2091.           choice = open_type;
  2092.         else {
  2093.           delete open_type;
  2094.           ok = FALSE;
  2095.         }
  2096.       }
  2097.       return ok;
  2098.     }
  2099.   }
  2100.   if (numChoices < 2)
  2101.     tag = 0;
  2102.   else {
  2103.     if (strm.UnsignedDecode(0, numChoices-1, tag) < 0)
  2104.       return FALSE;
  2105.   }
  2106.   if (CreateObject())
  2107.     ok = choice->Decode(strm);
  2108.   return ok;
  2109. }
  2110. void PASN_Choice::EncodePER(PPER_Stream & strm) const
  2111. {
  2112.   PAssert(tag != UINT_MAX, PLogicError);
  2113.   if (extendable) {
  2114.     BOOL extended = tag >= numChoices;
  2115.     strm.SingleBitEncode(extended);
  2116.     if (extended) {
  2117.       strm.SmallUnsignedEncode(tag - numChoices);
  2118.       strm.AnyTypeEncode(choice);
  2119.       return;
  2120.     }
  2121.   }
  2122.   if (numChoices > 1)
  2123.     strm.UnsignedEncode(tag, 0, numChoices-1);
  2124.   if (choice != NULL)
  2125.     choice->Encode(strm);
  2126. }
  2127. BOOL PBER_Stream::ChoiceDecode(PASN_Choice & value)
  2128. {
  2129.   PINDEX savedPosition = GetPosition();
  2130.   unsigned tag;
  2131.   PASN_Object::TagClass tagClass;
  2132.   BOOL primitive;
  2133.   unsigned entryLen;
  2134.   if (!HeaderDecode(tag, tagClass, primitive, entryLen))
  2135.     return FALSE;
  2136.   SetPosition(savedPosition);
  2137.   value.SetTag(tag, tagClass);
  2138.   if (value.IsValid())
  2139.     return value.GetObject().Decode(*this);
  2140.   return TRUE;
  2141. }
  2142. void PBER_Stream::ChoiceEncode(const PASN_Choice & value)
  2143. {
  2144.   if (value.IsValid())
  2145.     value.GetObject().Encode(*this);
  2146. }
  2147. BOOL PPER_Stream::ChoiceDecode(PASN_Choice & value)
  2148. {
  2149.   return value.DecodePER(*this);
  2150. }
  2151. void PPER_Stream::ChoiceEncode(const PASN_Choice & value)
  2152. {
  2153.   value.EncodePER(*this);
  2154. }
  2155. ///////////////////////////////////////////////////////////////////////
  2156. PASN_Sequence::PASN_Sequence(unsigned tag, TagClass tagClass,
  2157.                              unsigned nOpts, BOOL extend, unsigned nExtend)
  2158.   : PASN_Object(tag, tagClass, extend)
  2159. {
  2160.   optionMap.SetConstraints(PASN_ConstrainedObject::FixedConstraint, nOpts, nOpts);
  2161.   knownExtensions = nExtend;
  2162.   totalExtensions = 0;
  2163.   endBasicEncoding = 0;
  2164. }
  2165. PASN_Sequence::PASN_Sequence(const PASN_Sequence & other)
  2166.   : PASN_Object(other),
  2167.     fields(other.fields.GetSize()),
  2168.     optionMap(other.optionMap),
  2169.     extensionMap(other.extensionMap)
  2170. {
  2171.   for (PINDEX i = 0; i < other.fields.GetSize(); i++)
  2172.     fields.SetAt(i, other.fields[i].Clone());
  2173.   knownExtensions = other.knownExtensions;
  2174.   totalExtensions = other.totalExtensions;
  2175.   endBasicEncoding = 0;
  2176. }
  2177. PASN_Sequence & PASN_Sequence::operator=(const PASN_Sequence & other)
  2178. {
  2179.   PASN_Object::operator=(other);
  2180.   fields.SetSize(other.fields.GetSize());
  2181.   for (PINDEX i = 0; i < other.fields.GetSize(); i++)
  2182.     fields.SetAt(i, other.fields[i].Clone());
  2183.   optionMap = other.optionMap;
  2184.   knownExtensions = other.knownExtensions;
  2185.   totalExtensions = other.totalExtensions;
  2186.   extensionMap = other.extensionMap;
  2187.   return *this;
  2188. }
  2189. BOOL PASN_Sequence::HasOptionalField(PINDEX opt) const
  2190. {
  2191.   if (opt < (PINDEX)optionMap.GetSize())
  2192.     return optionMap[opt];
  2193.   else
  2194.     return extensionMap[opt - optionMap.GetSize()];
  2195. }
  2196. void PASN_Sequence::IncludeOptionalField(PINDEX opt)
  2197. {
  2198.   if (opt < (PINDEX)optionMap.GetSize())
  2199.     optionMap.Set(opt);
  2200.   else {
  2201.     PAssert(extendable, "Must be extendable type");
  2202.     opt -= optionMap.GetSize();
  2203.     if (opt >= (PINDEX)extensionMap.GetSize())
  2204.       extensionMap.SetSize(opt+1);
  2205.     extensionMap.Set(opt);
  2206.   }
  2207. }
  2208. void PASN_Sequence::RemoveOptionalField(PINDEX opt)
  2209. {
  2210.   if (opt < (PINDEX)optionMap.GetSize())
  2211.     optionMap.Clear(opt);
  2212.   else {
  2213.     PAssert(extendable, "Must be extendable type");
  2214.     opt -= optionMap.GetSize();
  2215.     extensionMap.Clear(opt);
  2216.   }
  2217. }
  2218. PObject::Comparison PASN_Sequence::Compare(const PObject & obj) const
  2219. {
  2220.   PAssert(obj.IsDescendant(PASN_Sequence::Class()), PInvalidCast);
  2221.   const PASN_Sequence & other = (const PASN_Sequence &)obj;
  2222.   return fields.Compare(other.fields);
  2223. }
  2224. PObject * PASN_Sequence::Clone() const
  2225. {
  2226.   PAssert(IsClass(PASN_Sequence::Class()), PInvalidCast);
  2227.   return new PASN_Sequence(*this);
  2228. }
  2229. void PASN_Sequence::PrintOn(ostream & strm) const
  2230. {
  2231.   int indent = strm.precision() + 2;
  2232.   strm << "{n";
  2233.   for (PINDEX i = 0; i < fields.GetSize(); i++) {
  2234.     strm << setw(indent+6) << "field[" << i << "] <";
  2235.     switch (fields[i].GetTagClass()) {
  2236.       case UniversalTagClass :
  2237.         strm << "Universal";
  2238.         break;
  2239.       case ApplicationTagClass :
  2240.         strm << "Application";
  2241.         break;
  2242.       case ContextSpecificTagClass :
  2243.         strm << "ContextSpecific";
  2244.         break;
  2245.       case PrivateTagClass :
  2246.         strm << "Private";
  2247.       default :
  2248.         break;
  2249.     }
  2250.     strm << '-' << fields[i].GetTag() << '-'
  2251.          << fields[i].GetTypeAsString() << "> = "
  2252.          << fields[i] << 'n';
  2253.   }
  2254.   strm << setw(indent-1) << "}";
  2255. }
  2256. PString PASN_Sequence::GetTypeAsString() const
  2257. {
  2258.   return "Sequence";
  2259. }
  2260. PINDEX PASN_Sequence::GetDataLength() const
  2261. {
  2262.   PINDEX len = 0;
  2263.   for (PINDEX i = 0; i < fields.GetSize(); i++)
  2264.     len += fields[i].GetObjectLength();
  2265.   return len;
  2266. }
  2267. BOOL PASN_Sequence::IsPrimitive() const
  2268. {
  2269.   return FALSE;
  2270. }
  2271. BOOL PASN_Sequence::Decode(PASN_Stream & strm)
  2272. {
  2273.   return PreambleDecode(strm) && UnknownExtensionsDecode(strm);
  2274. }
  2275. void PASN_Sequence::Encode(PASN_Stream & strm) const
  2276. {
  2277.   PreambleEncode(strm);
  2278.   UnknownExtensionsEncode(strm);
  2279. }
  2280. BOOL PASN_Sequence::PreambleDecode(PASN_Stream & strm)
  2281. {
  2282.   return strm.SequencePreambleDecode(*this);
  2283. }
  2284. void PASN_Sequence::PreambleEncode(PASN_Stream & strm) const
  2285. {
  2286.   strm.SequencePreambleEncode(*this);
  2287. }
  2288. BOOL PASN_Sequence::KnownExtensionDecode(PASN_Stream & strm, PINDEX fld, PASN_Object & field)
  2289. {
  2290.   return strm.SequenceKnownDecode(*this, fld, field);
  2291. }
  2292. void PASN_Sequence::KnownExtensionEncode(PASN_Stream & strm, PINDEX fld, const PASN_Object & field) const
  2293. {
  2294.   strm.SequenceKnownEncode(*this, fld, field);
  2295. }
  2296. BOOL PASN_Sequence::UnknownExtensionsDecode(PASN_Stream & strm)
  2297. {
  2298.   return strm.SequenceUnknownDecode(*this);
  2299. }
  2300. void PASN_Sequence::UnknownExtensionsEncode(PASN_Stream & strm) const
  2301. {
  2302.   strm.SequenceUnknownEncode(*this);
  2303. }
  2304. BOOL PASN_Sequence::PreambleDecodeBER(PBER_Stream & strm)
  2305. {
  2306.   fields.RemoveAll();
  2307.   unsigned len;
  2308.   if (!strm.HeaderDecode(*this, len))
  2309.     return FALSE;
  2310.   endBasicEncoding = strm.GetPosition() + len;
  2311.   return !strm.IsAtEnd();
  2312. }
  2313. void PASN_Sequence::PreambleEncodeBER(PBER_Stream & strm) const
  2314. {
  2315.   strm.HeaderEncode(*this);
  2316. }
  2317. BOOL PASN_Sequence::KnownExtensionDecodeBER(PBER_Stream & strm, PINDEX, PASN_Object & field)
  2318. {
  2319.   if (strm.GetPosition() >= endBasicEncoding)
  2320.     return FALSE;
  2321.   return field.Decode(strm);
  2322. }
  2323. void PASN_Sequence::KnownExtensionEncodeBER(PBER_Stream & strm, PINDEX, const PASN_Object & field) const
  2324. {
  2325.   field.Encode(strm);
  2326. }
  2327. BOOL PASN_Sequence::UnknownExtensionsDecodeBER(PBER_Stream & strm)
  2328. {
  2329.   while (strm.GetPosition() < endBasicEncoding) {
  2330.     PINDEX savedPosition = strm.GetPosition();
  2331.     unsigned tag;
  2332.     PASN_Object::TagClass tagClass;
  2333.     BOOL primitive;
  2334.     unsigned entryLen;
  2335.     if (!strm.HeaderDecode(tag, tagClass, primitive, entryLen))
  2336.       return FALSE;
  2337.     PINDEX nextEntryPosition = strm.GetPosition() + entryLen;
  2338.     strm.SetPosition(savedPosition);
  2339.     PASN_Object * obj = strm.CreateObject(tag, tagClass, primitive);
  2340.     if (obj == NULL)
  2341.       strm.SetPosition(nextEntryPosition);
  2342.     else {
  2343.       if (!obj->Decode(strm))
  2344.         return FALSE;
  2345.       fields.Append(obj);
  2346.     }
  2347.   }
  2348.   return TRUE;
  2349. }
  2350. void PASN_Sequence::UnknownExtensionsEncodeBER(PBER_Stream & strm) const
  2351. {
  2352.   for (PINDEX i = 0; i < fields.GetSize(); i++)
  2353.     fields[i].Encode(strm);
  2354. }
  2355. BOOL PASN_Sequence::PreambleDecodePER(PPER_Stream & strm)
  2356. {
  2357.   // X.691 Section 18
  2358.   if (extendable) {
  2359.     if (strm.IsAtEnd())
  2360.       return FALSE;
  2361.     totalExtensions = strm.SingleBitDecode() ? -1 : 0;  // 18.1
  2362.   }
  2363.   else
  2364.     totalExtensions = 0;
  2365.   return optionMap.Decode(strm);  // 18.2
  2366. }
  2367. void PASN_Sequence::PreambleEncodePER(PPER_Stream & strm) const
  2368. {
  2369.   // X.691 Section 18
  2370.   if (extendable) {
  2371.     BOOL hasExtensions = FALSE;
  2372.     for (unsigned i = 0; i < extensionMap.GetSize(); i++) {
  2373.       if (extensionMap[i]) {
  2374.         hasExtensions = TRUE;
  2375.         break;
  2376.       }
  2377.     }
  2378.     strm.SingleBitEncode(hasExtensions);  // 18.1
  2379.     ((PASN_Sequence*)this)->totalExtensions = hasExtensions ? -1 : 0;
  2380.   }
  2381.   optionMap.Encode(strm);  // 18.2
  2382. }
  2383. BOOL PASN_Sequence::NoExtensionsToDecode(PPER_Stream & strm)
  2384. {
  2385.   if (totalExtensions == 0)
  2386.     return TRUE;
  2387.   if (totalExtensions < 0) {
  2388.     totalExtensions = strm.SmallUnsignedDecode() + 1;
  2389.     extensionMap.SetConstraints(PASN_ConstrainedObject::FixedConstraint,
  2390.                                 totalExtensions, totalExtensions);
  2391.     extensionMap.Decode(strm);
  2392.   }
  2393.   return FALSE;
  2394. }
  2395. BOOL PASN_Sequence::NoExtensionsToEncode(PPER_Stream & strm)
  2396. {
  2397.   if (totalExtensions == 0)
  2398.     return TRUE;
  2399.   if (totalExtensions < 0) {
  2400.     totalExtensions = extensionMap.GetSize();
  2401.     strm.SmallUnsignedEncode(totalExtensions-1);
  2402.     extensionMap.SetConstraints(PASN_ConstrainedObject::FixedConstraint,
  2403.                                 totalExtensions, totalExtensions);
  2404.     extensionMap.Encode(strm);
  2405.   }
  2406.   return FALSE;
  2407. }
  2408. BOOL PASN_Sequence::KnownExtensionDecodePER(PPER_Stream & strm, PINDEX fld, PASN_Object & field)
  2409. {
  2410.   if (NoExtensionsToDecode(strm))
  2411.     return TRUE;
  2412.   if (!extensionMap[fld-optionMap.GetSize()])
  2413.     return TRUE;
  2414.   unsigned len;
  2415.   if (strm.LengthDecode(0, INT_MAX, len) != 0)
  2416.     return FALSE;
  2417.   PINDEX nextExtensionPosition = strm.GetPosition() + len;
  2418.   BOOL ok = field.Decode(strm);
  2419.   strm.SetPosition(nextExtensionPosition);
  2420.   return ok;
  2421. }
  2422. void PASN_Sequence::KnownExtensionEncodePER(PPER_Stream & strm, PINDEX fld, const PASN_Object & field) const
  2423. {
  2424.   if (((PASN_Sequence*)this)->NoExtensionsToEncode(strm))
  2425.     return;
  2426.   if (!extensionMap[fld-optionMap.GetSize()])
  2427.     return;
  2428.   strm.AnyTypeEncode(&field);
  2429. }
  2430. BOOL PASN_Sequence::UnknownExtensionsDecodePER(PPER_Stream & strm)
  2431. {
  2432.   if (NoExtensionsToDecode(strm))
  2433.     return TRUE;
  2434.   if (totalExtensions <= knownExtensions)
  2435.     return TRUE;  // Already read them
  2436.   PINDEX unknownCount = totalExtensions - knownExtensions;
  2437.   if (fields.GetSize() >= unknownCount)
  2438.     return TRUE;  // Already read them
  2439.   fields.SetSize(unknownCount);
  2440.   PINDEX i;
  2441.   for (i = 0; i < fields.GetSize(); i++)
  2442.     fields.SetAt(i, new PASN_OctetString);
  2443.   for (i = knownExtensions; i < (PINDEX)extensionMap.GetSize(); i++) {
  2444.     if (extensionMap[i])
  2445.       if (!fields[i-knownExtensions].Decode(strm))
  2446.         return FALSE;
  2447.   }
  2448.   return TRUE;
  2449. }
  2450. void PASN_Sequence::UnknownExtensionsEncodePER(PPER_Stream & strm) const
  2451. {
  2452.   if (((PASN_Sequence*)this)->NoExtensionsToEncode(strm))
  2453.     return;
  2454.   int i;
  2455.   for (i = knownExtensions; i < totalExtensions; i++) {
  2456.     if (extensionMap[i])
  2457.       fields[i-knownExtensions].Encode(strm);
  2458.   }
  2459. }
  2460. BOOL PBER_Stream::SequencePreambleDecode(PASN_Sequence & seq)
  2461. {
  2462.   return seq.PreambleDecodeBER(*this);
  2463. }
  2464. void PBER_Stream::SequencePreambleEncode(const PASN_Sequence & seq)
  2465. {
  2466.   seq.PreambleEncodeBER(*this);
  2467. }
  2468. BOOL PBER_Stream::SequenceKnownDecode(PASN_Sequence & seq, PINDEX fld, PASN_Object & field)
  2469. {
  2470.   return seq.KnownExtensionDecodeBER(*this, fld, field);
  2471. }
  2472. void PBER_Stream::SequenceKnownEncode(const PASN_Sequence & seq, PINDEX fld, const PASN_Object & field)
  2473. {
  2474.   seq.KnownExtensionEncodeBER(*this, fld, field);
  2475. }
  2476. BOOL PBER_Stream::SequenceUnknownDecode(PASN_Sequence & seq)
  2477. {
  2478.   return seq.UnknownExtensionsDecodeBER(*this);
  2479. }
  2480. void PBER_Stream::SequenceUnknownEncode(const PASN_Sequence & seq)
  2481. {
  2482.   seq.UnknownExtensionsEncodeBER(*this);
  2483. }
  2484. BOOL PPER_Stream::SequencePreambleDecode(PASN_Sequence & seq)
  2485. {
  2486.   return seq.PreambleDecodePER(*this);
  2487. }
  2488. void PPER_Stream::SequencePreambleEncode(const PASN_Sequence & seq)
  2489. {
  2490.   seq.PreambleEncodePER(*this);
  2491. }
  2492. BOOL PPER_Stream::SequenceKnownDecode(PASN_Sequence & seq, PINDEX fld, PASN_Object & field)
  2493. {
  2494.   return seq.KnownExtensionDecodePER(*this, fld, field);
  2495. }
  2496. void PPER_Stream::SequenceKnownEncode(const PASN_Sequence & seq, PINDEX fld, const PASN_Object & field)
  2497. {
  2498.   seq.KnownExtensionEncodePER(*this, fld, field);
  2499. }
  2500. BOOL PPER_Stream::SequenceUnknownDecode(PASN_Sequence & seq)
  2501. {
  2502.   return seq.UnknownExtensionsDecodePER(*this);
  2503. }
  2504. void PPER_Stream::SequenceUnknownEncode(const PASN_Sequence & seq)
  2505. {
  2506.   seq.UnknownExtensionsEncodePER(*this);
  2507. }
  2508. ///////////////////////////////////////////////////////////////////////
  2509. PASN_Set::PASN_Set(unsigned tag, TagClass tagClass,
  2510.                    unsigned nOpts, BOOL extend, unsigned nExtend)
  2511.   : PASN_Sequence(tag, tagClass, nOpts, extend, nExtend)
  2512. {
  2513. }
  2514. PObject * PASN_Set::Clone() const
  2515. {
  2516.   PAssert(IsClass(PASN_Set::Class()), PInvalidCast);
  2517.   return new PASN_Set(*this);
  2518. }
  2519. PString PASN_Set::GetTypeAsString() const
  2520. {
  2521.   return "Set";
  2522. }
  2523. ///////////////////////////////////////////////////////////////////////
  2524. PASN_Array::PASN_Array(unsigned tag, TagClass tagClass)
  2525.   : PASN_ConstrainedObject(tag, tagClass)
  2526. {
  2527. }
  2528. PASN_Array::PASN_Array(const PASN_Array & other)
  2529.   : PASN_ConstrainedObject(other),
  2530.     array(other.array.GetSize())
  2531. {
  2532.   for (PINDEX i = 0; i < other.array.GetSize(); i++)
  2533.     array.SetAt(i, other.array[i].Clone());
  2534. }
  2535. PASN_Array & PASN_Array::operator=(const PASN_Array & other)
  2536. {
  2537.   PASN_ConstrainedObject::operator=(other);
  2538.   array.SetSize(other.array.GetSize());
  2539.   for (PINDEX i = 0; i < other.array.GetSize(); i++)
  2540.     array.SetAt(i, other.array[i].Clone());
  2541.   return *this;
  2542. }
  2543. void PASN_Array::SetSize(PINDEX newSize)
  2544. {
  2545.   PINDEX originalSize = array.GetSize();
  2546.   array.SetSize(newSize);
  2547.   for (PINDEX i = originalSize; i < newSize; i++)
  2548.     array.SetAt(i, CreateObject());
  2549. }
  2550. PObject::Comparison PASN_Array::Compare(const PObject & obj) const
  2551. {
  2552.   PAssert(obj.IsDescendant(PASN_Array::Class()), PInvalidCast);
  2553.   const PASN_Array & other = (const PASN_Array &)obj;
  2554.   return array.Compare(other.array);
  2555. }
  2556. void PASN_Array::PrintOn(ostream & strm) const
  2557. {
  2558.   int indent = strm.precision() + 2;
  2559.   strm << array.GetSize() << " entries {n";
  2560.   for (PINDEX i = 0; i < array.GetSize(); i++)
  2561.     strm << setw(indent+1) << "[" << i << "]=" << setprecision(indent) << array[i] << 'n';
  2562.   strm << setw(indent-1) << "}";
  2563. }
  2564. PString PASN_Array::GetTypeAsString() const
  2565. {
  2566.   return "Array";
  2567. }
  2568. PINDEX PASN_Array::GetDataLength() const
  2569. {
  2570.   PINDEX len = 0;
  2571.   for (PINDEX i = 0; i < array.GetSize(); i++)
  2572.     len += array[i].GetObjectLength();
  2573.   return len;
  2574. }
  2575. BOOL PASN_Array::IsPrimitive() const
  2576. {
  2577.   return FALSE;
  2578. }
  2579. BOOL PASN_Array::Decode(PASN_Stream & strm)
  2580. {
  2581.   return strm.ArrayDecode(*this);
  2582. }
  2583. void PASN_Array::Encode(PASN_Stream & strm) const
  2584. {
  2585.   strm.ArrayEncode(*this);
  2586. }
  2587. BOOL PBER_Stream::ArrayDecode(PASN_Array & array)
  2588. {
  2589.   array.RemoveAll();
  2590.   unsigned len;
  2591.   if (!HeaderDecode(array, len))
  2592.     return FALSE;
  2593.   PINDEX endOffset = byteOffset + len;
  2594.   PINDEX count = 0;
  2595.   while (byteOffset < endOffset) {
  2596.     array.SetSize(count+1);
  2597.     if (!array[count].Decode(*this))
  2598.       return FALSE;
  2599.     count++;
  2600.   }
  2601.   byteOffset = endOffset;
  2602.   return TRUE;
  2603. }
  2604. void PBER_Stream::ArrayEncode(const PASN_Array & array)
  2605. {
  2606.   HeaderEncode(array);
  2607.   for (PINDEX i = 0; i < array.GetSize(); i++)
  2608.     array[i].Encode(*this);
  2609. }
  2610. BOOL PPER_Stream::ArrayDecode(PASN_Array & array)
  2611. {
  2612.   array.RemoveAll();
  2613.   unsigned size;
  2614.   if (array.ConstrainedLengthDecode(*this, size) < 0)
  2615.     return FALSE;
  2616.   array.SetSize(size);
  2617.   for (PINDEX i = 0; i < (PINDEX)size; i++) {
  2618.     if (!array[i].Decode(*this))
  2619.       return FALSE;
  2620.   }
  2621.   return TRUE;
  2622. }
  2623. void PPER_Stream::ArrayEncode(const PASN_Array & array)
  2624. {
  2625.   PINDEX size = array.GetSize();
  2626.   array.ConstrainedLengthEncode(*this, size);
  2627.   for (PINDEX i = 0; i < size; i++)
  2628.     array[i].Encode(*this);
  2629. }
  2630. ///////////////////////////////////////////////////////////////////////
  2631. PASN_Stream::PASN_Stream()
  2632. {
  2633.   Construct();
  2634. }
  2635. PASN_Stream::PASN_Stream(const PBYTEArray & bytes)
  2636.   : PBYTEArray(bytes)
  2637. {
  2638.   Construct();
  2639. }
  2640. PASN_Stream::PASN_Stream(const BYTE * buf, PINDEX size)
  2641.   : PBYTEArray(buf, size)
  2642. {
  2643.   Construct();
  2644. }
  2645. void PASN_Stream::Construct()
  2646. {
  2647.   byteOffset = 0;
  2648.   bitOffset = 8;
  2649. }
  2650. void PASN_Stream::PrintOn(ostream & strm) const
  2651. {
  2652.   int indent = strm.precision() + 2;
  2653.   strm << " size=" << GetSize()
  2654.        << " pos=" << byteOffset << '.' << (8-bitOffset)
  2655.        << " {n";
  2656.   PINDEX i = 0;
  2657.   while (i < GetSize()) {
  2658.     strm << setw(indent) << " " << hex << setfill('0');
  2659.     PINDEX j;
  2660.     for (j = 0; j < 16; j++)
  2661.       if (i+j < GetSize())
  2662.         strm << setw(2) << (unsigned)(BYTE)theArray[i+j] << ' ';
  2663.       else
  2664.         strm << "   ";
  2665.     strm << "  ";
  2666.     for (j = 0; j < 16; j++) {
  2667.       if (i+j < GetSize()) {
  2668.         if (isprint(theArray[i+j]))
  2669.           strm << theArray[i+j];
  2670.         else
  2671.           strm << ' ';
  2672.       }
  2673.     }
  2674.     strm << dec << setfill(' ') << 'n';
  2675.     i += 16;
  2676.   }
  2677.   strm << setw(indent-1) << "}";
  2678. }
  2679. void PASN_Stream::SetPosition(PINDEX newPos)
  2680. {
  2681.   PAssert(byteOffset != P_MAX_INDEX, PLogicError);
  2682.   if (newPos > GetSize())
  2683.     byteOffset = GetSize();
  2684.   else
  2685.     byteOffset = newPos;
  2686.   bitOffset = 8;
  2687. }
  2688. void PASN_Stream::ResetDecoder()
  2689. {
  2690.   byteOffset = 0;
  2691.   bitOffset = 8;
  2692. }
  2693. void PASN_Stream::BeginEncoding()
  2694. {
  2695.   bitOffset = 8;
  2696.   byteOffset = 0;
  2697.   PBYTEArray::operator=(PBYTEArray(20));
  2698. }
  2699. void PASN_Stream::CompleteEncoding()
  2700. {
  2701.   if (byteOffset != P_MAX_INDEX) {
  2702.     if (bitOffset != 8) {
  2703.       bitOffset = 8;
  2704.       byteOffset++;
  2705.     }
  2706.     SetSize(byteOffset);
  2707.     byteOffset = P_MAX_INDEX;
  2708.   }
  2709. }
  2710. BYTE PASN_Stream::ByteDecode()
  2711. {
  2712.   if (byteOffset >= GetSize())
  2713.     return 0;
  2714.   bitOffset = 8;
  2715.   return theArray[byteOffset++];
  2716. }
  2717. void PASN_Stream::ByteEncode(unsigned value)
  2718. {
  2719.   PAssert(byteOffset != P_MAX_INDEX, PLogicError);
  2720.   if (bitOffset != 8) {
  2721.     bitOffset = 8;
  2722.     byteOffset++;
  2723.   }
  2724.   if (byteOffset >= GetSize())
  2725.     SetSize(byteOffset+10);
  2726.   theArray[byteOffset++] = (BYTE)value;
  2727. }
  2728. unsigned PASN_Stream::BlockDecode(BYTE * bufptr, unsigned nBytes)
  2729. {
  2730.   ByteAlign();
  2731.   if (byteOffset+nBytes > (unsigned)GetSize())
  2732.     nBytes = GetSize() - byteOffset;
  2733.   if (nBytes == 0)
  2734.     return 0;
  2735.   memcpy(bufptr, &theArray[byteOffset], nBytes);
  2736.   byteOffset += nBytes;
  2737.   return nBytes;
  2738. }
  2739. void PASN_Stream::BlockEncode(const BYTE * bufptr, PINDEX nBytes)
  2740. {
  2741.   PAssert(byteOffset != P_MAX_INDEX, PLogicError);
  2742.   if (nBytes == 0)
  2743.     return;
  2744.   ByteAlign();
  2745.   if (byteOffset+nBytes >= GetSize())
  2746.     SetSize(byteOffset+nBytes+10);
  2747.   memcpy(theArray+byteOffset, bufptr, nBytes);
  2748.   byteOffset += nBytes;
  2749. }
  2750. void PASN_Stream::ByteAlign()
  2751. {
  2752.   PAssert(byteOffset != P_MAX_INDEX, PLogicError);
  2753.   if (bitOffset != 8) {
  2754.     bitOffset = 8;
  2755.     byteOffset++;
  2756.   }
  2757. }
  2758. ///////////////////////////////////////////////////////////////////////
  2759. PBER_Stream::PBER_Stream()
  2760. {
  2761. }
  2762. PBER_Stream::PBER_Stream(const PBYTEArray & bytes)
  2763.   : PASN_Stream(bytes)
  2764. {
  2765. }
  2766. PBER_Stream::PBER_Stream(const BYTE * buf, PINDEX size)
  2767.   : PASN_Stream(buf, size)
  2768. {
  2769. }
  2770. PBER_Stream & PBER_Stream::operator=(const PBYTEArray & bytes)
  2771. {
  2772.   PBYTEArray::operator=(bytes);
  2773.   ResetDecoder();
  2774.   return *this;
  2775. }
  2776. BOOL PBER_Stream::Read(PChannel & chan)
  2777. {
  2778.   SetSize(0);
  2779.   PINDEX offset = 0;
  2780.   // read the sequence header
  2781.   int b;
  2782.   if ((b = chan.ReadChar()) < 0)
  2783.     return FALSE;
  2784.   SetAt(offset++, (char)b);
  2785.   // only support direct read of simple sequences
  2786.   if ((b&0x1f) == 0x1f) {
  2787.     do {
  2788.       if ((b = chan.ReadChar()) < 0)
  2789.         return FALSE;
  2790.       SetAt(offset++, (char)b);
  2791.     } while ((b & 0x80) != 0);
  2792.   }
  2793.   // read the first byte of the ASN length
  2794.   if ((b = chan.ReadChar()) < 0)
  2795.     return FALSE;
  2796.   SetAt(offset++, (char)b);
  2797.   // determine how many bytes in the length
  2798.   PINDEX dataLen = 0;
  2799.   if ((b & 0x80) == 0)
  2800.     dataLen = b;
  2801.   else {
  2802.     PINDEX lenLen = b&0x7f;
  2803.     SetSize(lenLen+2);
  2804.     while (lenLen-- > 0) {
  2805.       // read the length
  2806.       if ((b = chan.ReadChar()) < 0)
  2807.         return FALSE;
  2808.       dataLen = (dataLen << 8) | b;
  2809.       SetAt(offset++, (char)b);
  2810.     }
  2811.   }
  2812.   // read the data, all of it
  2813.   BYTE * bufptr = GetPointer(dataLen+offset) + offset;
  2814.   while (dataLen > 0) {
  2815.     if (!chan.Read(bufptr, dataLen))
  2816.       return FALSE;
  2817.     PINDEX readbytes = chan.GetLastReadCount();
  2818.     bufptr += readbytes;
  2819.     dataLen -= readbytes;
  2820.   }
  2821.   return TRUE;
  2822. }
  2823. BOOL PBER_Stream::Write(PChannel & chan)
  2824. {
  2825.   CompleteEncoding();
  2826.   return chan.Write(theArray, GetSize());
  2827. }
  2828. PASN_Object * PBER_Stream::CreateObject(unsigned tag,
  2829.                                         PASN_Object::TagClass tagClass,
  2830.                                         BOOL primitive) const
  2831. {
  2832.   if (tagClass == PASN_Object::UniversalTagClass) {
  2833.     switch (tag) {
  2834.       case PASN_Object::UniversalBoolean :
  2835.         return new PASN_Boolean();
  2836.       case PASN_Object::UniversalInteger :
  2837.         return new PASN_Integer();
  2838.       case PASN_Object::UniversalBitString :
  2839.         return new PASN_BitString();
  2840.       case PASN_Object::UniversalOctetString :
  2841.         return new PASN_OctetString();
  2842.       case PASN_Object::UniversalNull :
  2843.         return new PASN_Null();
  2844.       case PASN_Object::UniversalObjectId :
  2845.         return new PASN_ObjectId();
  2846.       case PASN_Object::UniversalReal :
  2847.         return new PASN_Real();
  2848.       case PASN_Object::UniversalEnumeration :
  2849.         return new PASN_Enumeration();
  2850.       case PASN_Object::UniversalSequence :
  2851.         return new PASN_Sequence();
  2852.       case PASN_Object::UniversalSet :
  2853.         return new PASN_Set();
  2854.       case PASN_Object::UniversalNumericString :
  2855.         return new PASN_NumericString();
  2856.       case PASN_Object::UniversalPrintableString :
  2857.         return new PASN_PrintableString();
  2858.       case PASN_Object::UniversalIA5String :
  2859.         return new PASN_IA5String();
  2860.       case PASN_Object::UniversalVisibleString :
  2861.         return new PASN_VisibleString();
  2862.       case PASN_Object::UniversalGeneralString :
  2863.         return new PASN_GeneralString();
  2864.       case PASN_Object::UniversalBMPString :
  2865.         return new PASN_BMPString();
  2866.     }
  2867.   }
  2868.   if (primitive)
  2869.     return new PASN_OctetString(tag, tagClass);
  2870.   else
  2871.     return new PASN_Sequence(tag, tagClass, 0, FALSE, 0);
  2872. }
  2873. BOOL PBER_Stream::HeaderDecode(unsigned & tagVal,
  2874.                                PASN_Object::TagClass & tagClass,
  2875.                                BOOL & primitive,
  2876.                                unsigned & len)
  2877. {
  2878.   BYTE ident = ByteDecode();
  2879.   tagClass = (PASN_Object::TagClass)(ident>>6);
  2880.   primitive = (ident&0x20) == 0;
  2881.   tagVal = ident&31;
  2882.   if (tagVal == 31) {
  2883.     BYTE b;
  2884.     tagVal = 0;
  2885.     do {
  2886.       if (IsAtEnd())
  2887.         return FALSE;
  2888.       b = ByteDecode();
  2889.       tagVal = (tagVal << 7) | (b&0x7f);
  2890.     } while ((b&0x80) != 0);
  2891.   }
  2892.   if (IsAtEnd())
  2893.     return FALSE;
  2894.   BYTE len_len = ByteDecode();
  2895.   if ((len_len & 0x80) == 0) {
  2896.     len = len_len;
  2897.     return TRUE;
  2898.   }
  2899.   len_len &= 0x7f;
  2900.   len = 0;
  2901.   while (len_len-- > 0) {
  2902.     if (IsAtEnd())
  2903.       return FALSE;
  2904.     len = (len << 8) | ByteDecode();
  2905.   }
  2906.   return TRUE;
  2907. }
  2908. BOOL PBER_Stream::HeaderDecode(PASN_Object & obj, unsigned & len)
  2909. {
  2910.   PINDEX pos = byteOffset;
  2911.   unsigned tagVal;
  2912.   PASN_Object::TagClass tagClass;
  2913.   BOOL primitive;
  2914.   if (HeaderDecode(tagVal, tagClass, primitive, len) &&
  2915.               tagVal == obj.GetTag() && tagClass == obj.GetTagClass())
  2916.     return TRUE;
  2917.   byteOffset = pos;
  2918.   return FALSE;
  2919. }
  2920. void PBER_Stream::HeaderEncode(const PASN_Object & obj)
  2921. {
  2922.   BYTE ident = (BYTE)(obj.GetTagClass() << 6);
  2923.   if (!obj.IsPrimitive())
  2924.     ident |= 0x20;
  2925.   unsigned tag = obj.GetTag();
  2926.   if (tag < 31)
  2927.     ByteEncode(ident|tag);
  2928.   else {
  2929.     ByteEncode(ident|31);
  2930.     unsigned count = (CountBits(tag)+6)/7;
  2931.     while (count-- > 1)
  2932.       ByteEncode((tag >> (count*7))&0x7f);
  2933.     ByteEncode(tag&0x7f);
  2934.   }
  2935.   PINDEX len = obj.GetDataLength();
  2936.   if (len < 128)
  2937.     ByteEncode(len);
  2938.   else {
  2939.     PINDEX count = (CountBits(len+1)+7)/8;
  2940.     ByteEncode(count|0x80);
  2941.     while (count-- > 0)
  2942.       ByteEncode(len >> (count*8));
  2943.   }
  2944. }
  2945. ///////////////////////////////////////////////////////////////////////
  2946. PPER_Stream::PPER_Stream(BOOL alignment)
  2947. {
  2948.   aligned = alignment;
  2949. }
  2950. PPER_Stream::PPER_Stream(const PBYTEArray & bytes, BOOL alignment)
  2951.   : PASN_Stream(bytes)
  2952. {
  2953.   aligned = alignment;
  2954. }
  2955. PPER_Stream::PPER_Stream(const BYTE * buf, PINDEX size, BOOL alignment)
  2956.   : PASN_Stream(buf, size)
  2957. {
  2958.   aligned = alignment;
  2959. }
  2960. PPER_Stream & PPER_Stream::operator=(const PBYTEArray & bytes)
  2961. {
  2962.   PBYTEArray::operator=(bytes);
  2963.   ResetDecoder();
  2964.   aligned = TRUE;
  2965.   return *this;
  2966. }
  2967. unsigned PPER_Stream::GetBitsLeft() const
  2968. {
  2969.   return (GetSize() - byteOffset)*8 - (8 - bitOffset);
  2970. }
  2971. BOOL PPER_Stream::Read(PChannel & chan)
  2972. {
  2973.   ResetDecoder();
  2974.   SetSize(0);
  2975.   // Get RFC1006 TPKT length
  2976.   BYTE tpkt[4];
  2977.   if (!chan.ReadBlock(tpkt, sizeof(tpkt)))
  2978.     return FALSE;
  2979.   if (tpkt[0] != 3) // Only support version 3
  2980.     return TRUE;
  2981.   PINDEX data_len = ((tpkt[2] << 8)|tpkt[3]) - 4;
  2982.   return chan.ReadBlock(GetPointer(data_len), data_len);
  2983. }
  2984. BOOL PPER_Stream::Write(PChannel & chan)
  2985. {
  2986.   CompleteEncoding();
  2987.   PINDEX size = GetSize();
  2988.   // Put RFC1006 TPKT length
  2989.   BYTE tpkt[4];
  2990.   tpkt[0] = 3;  // Version 3
  2991.   tpkt[1] = 0;
  2992.   PINDEX len = size + sizeof(tpkt);
  2993.   tpkt[2] = (BYTE)(len >> 8);
  2994.   tpkt[3] = (BYTE)len;
  2995.   return chan.Write(tpkt, sizeof(tpkt)) && chan.Write(theArray, size);
  2996. }
  2997. BOOL PPER_Stream::SingleBitDecode()
  2998. {
  2999.   if ((GetSize() - byteOffset)*8 - (8 - bitOffset) == 0)
  3000.     return FALSE;
  3001.   bitOffset--;
  3002.   BOOL value = (theArray[byteOffset] & (1 << bitOffset)) != 0;
  3003.   if (bitOffset == 0) {
  3004.     bitOffset = 8;
  3005.     byteOffset++;
  3006.   }
  3007.   return value;
  3008. }
  3009. void PPER_Stream::SingleBitEncode(BOOL value)
  3010. {
  3011.   PAssert(byteOffset != P_MAX_INDEX, PLogicError);
  3012.   if (byteOffset >= GetSize())
  3013.     SetSize(byteOffset+10);
  3014.   bitOffset--;
  3015.   if (value)
  3016.     theArray[byteOffset] |= 1 << bitOffset;
  3017.   if (bitOffset == 0)
  3018.     ByteAlign();
  3019. }
  3020. int PPER_Stream::MultiBitDecode(unsigned nBits)
  3021. {
  3022.   PAssert(nBits <= 32, PInvalidParameter);
  3023.   unsigned bitsLeft = (GetSize() - byteOffset)*8 - (8 - bitOffset);
  3024.   if (nBits > bitsLeft)
  3025.     nBits = bitsLeft;
  3026.   if (nBits == 0)
  3027.     return 0;
  3028.   if (nBits < bitOffset) {
  3029.     bitOffset -= nBits;
  3030.     return (theArray[byteOffset] >> bitOffset) & ((1 << nBits) - 1);
  3031.   }
  3032.   int val = theArray[byteOffset] & ((1 << bitOffset) - 1);
  3033.   nBits -= bitOffset;
  3034.   bitOffset = 8;
  3035.   byteOffset++;
  3036.   while (nBits >= 8) {
  3037.     val = (val << 8) | (BYTE)theArray[byteOffset];
  3038.     byteOffset++;
  3039.     nBits -= 8;
  3040.   }
  3041.   if (nBits > 0) {
  3042.     bitOffset = 8 - nBits;
  3043.     val = (val << nBits) | ((BYTE)theArray[byteOffset] >> bitOffset);
  3044.   }
  3045.   return val;
  3046. }
  3047. void PPER_Stream::MultiBitEncode(int value, unsigned nBits)
  3048. {
  3049.   PAssert(byteOffset != P_MAX_INDEX, PLogicError);
  3050.   if (nBits == 0)
  3051.     return;
  3052.   if (byteOffset+nBits/8+1 >= (unsigned)GetSize())
  3053.     SetSize(byteOffset+10);
  3054.   // Make sure value is in bounds of bit available.
  3055.   if (nBits < sizeof(int)*8)
  3056.     value &= ((1 << nBits) - 1);
  3057.   if (nBits < bitOffset) {
  3058.     bitOffset -= nBits;
  3059.     theArray[byteOffset] |= value << bitOffset;
  3060.     return;
  3061.   }
  3062.   nBits -= bitOffset;
  3063.   theArray[byteOffset] |= (BYTE)(value >> nBits);
  3064.   bitOffset = 8;
  3065.   byteOffset++;
  3066.   while (nBits >= 8) {
  3067.     nBits -= 8;
  3068.     theArray[byteOffset] = (BYTE)(value >> nBits);
  3069.     byteOffset++;
  3070.   }
  3071.   if (nBits > 0) {
  3072.     bitOffset = 8 - nBits;
  3073.     theArray[byteOffset] |= (BYTE)((value & ((1 << nBits)-1)) << bitOffset);
  3074.   }
  3075. }
  3076. unsigned PPER_Stream::SmallUnsignedDecode()
  3077. {
  3078.   // X.691 Section 10.6
  3079.   if (!SingleBitDecode())
  3080.     return MultiBitDecode(6);      // 10.6.1
  3081.   unsigned len;
  3082.   if (LengthDecode(0, INT_MAX, len) != 0)  // 10.6.2
  3083.     return FALSE;
  3084.   ByteAlign();
  3085.   return MultiBitDecode(len*8);
  3086. }
  3087. void PPER_Stream::SmallUnsignedEncode(unsigned value)
  3088. {
  3089.   if (value < 64) {
  3090.     MultiBitEncode(value, 7);
  3091.     return;
  3092.   }
  3093.   SingleBitEncode(1);  // 10.6.2
  3094.   PINDEX len = 4;
  3095.   if (value < 256)
  3096.     len = 1;
  3097.   else if (value < 65536)
  3098.     len = 2;
  3099.   else if (value < 0x1000000)
  3100.     len = 3;
  3101.   LengthEncode(len, 0, INT_MAX);  // 10.9
  3102.   ByteAlign();
  3103.   MultiBitEncode(value, len*8);
  3104. }
  3105. int PPER_Stream::UnsignedDecode(unsigned lower, unsigned upper, unsigned & value)
  3106. {
  3107.   // X.691 section 10.5
  3108.   if (lower == upper) { // 10.5.4
  3109.     value = lower;
  3110.     return 0;
  3111.   }
  3112.   if (IsAtEnd())
  3113.     return -1;
  3114.   unsigned range = (upper - lower) + 1;
  3115.   unsigned nBits = CountBits(range);
  3116.   if (aligned && (range == 0 || range > 255)) { // not 10.5.6 and not 10.5.7.1
  3117.     if (nBits > 16) {                           // not 10.5.7.4
  3118.       LengthDecode(1, (nBits+7)/8, nBits);      // 12.2.6
  3119.       nBits *= 8;
  3120.     }
  3121.     else if (nBits > 8)    // not 10.5.7.2
  3122.       nBits = 16;          // 10.5.7.3
  3123.     ByteAlign();           // 10.7.5.2 - 10.7.5.4
  3124.   }
  3125.   value = MultiBitDecode(nBits) + lower;
  3126.   return 0;
  3127. }
  3128. void PPER_Stream::UnsignedEncode(int value, unsigned lower, unsigned upper)
  3129. {
  3130.   // X.691 section 10.5
  3131.   if (lower == upper) // 10.5.4
  3132.     return;
  3133.   unsigned range = (upper - lower) + 1;
  3134.   PINDEX nBits = CountBits(range);
  3135.   if (aligned && (range == 0 || range > 255)) { // not 10.5.6 and not 10.5.7.1
  3136.     if (nBits > 16) {                           // not 10.5.7.4
  3137.       int numBytes = value == 0 ? 1 : (((CountBits(value - lower + 1))+7)/8);
  3138.       LengthEncode(numBytes, 1, (nBits+7)/8);    // 12.2.6
  3139.       nBits = numBytes*8;
  3140.     }
  3141.     else if (nBits > 8)      // not 10.5.7.2
  3142.       nBits = 16;            // 10.5.7.3
  3143.     ByteAlign();             // 10.7.5.2 - 10.7.5.4
  3144.   }
  3145.   MultiBitEncode(value - lower, nBits);
  3146. }
  3147. int PPER_Stream::LengthDecode(unsigned lower, unsigned upper, unsigned & len)
  3148. {
  3149.   // X.691 section 10.9
  3150.   if (upper != INT_MAX && !aligned) {
  3151.     PAssert(upper - lower < 0x10000, PUnimplementedFunction);  // 10.9.4.2 unsupported
  3152.     return lower + MultiBitDecode(CountBits(upper - lower + 1));   // 10.9.4.1
  3153.   }
  3154.   if (upper < 65536)  // 10.9.3.3
  3155.     return UnsignedDecode(lower, upper, len);
  3156.   // 10.9.3.5
  3157.   ByteAlign();
  3158.   if (IsAtEnd())
  3159.     return -1;
  3160.   if (SingleBitDecode() == 0) {
  3161.     len = MultiBitDecode(7);   // 10.9.3.6
  3162.     return 0;
  3163.   }
  3164.   if (SingleBitDecode() == 0) {
  3165.     len = MultiBitDecode(14);    // 10.9.3.7
  3166.     return 0;
  3167.   }
  3168.   PAssertAlways(PUnimplementedFunction);  // 10.9.3.8 unsupported
  3169.   return 1;
  3170. }
  3171. void PPER_Stream::LengthEncode(unsigned len, unsigned lower, unsigned upper)
  3172. {
  3173.   // X.691 section 10.9
  3174.   if (upper != INT_MAX && !aligned) {
  3175.     PAssert(upper - lower < 0x10000, PUnimplementedFunction);  // 10.9.4.2 unsupperted
  3176.     MultiBitEncode(len - lower, CountBits(upper - lower + 1));   // 10.9.4.1
  3177.     return;
  3178.   }
  3179.   if (upper < 65536) { // 10.9.3.3
  3180.     UnsignedEncode(len, lower, upper);
  3181.     return;
  3182.   }
  3183.   ByteAlign();
  3184.   if (len < 128) {
  3185.     MultiBitEncode(len, 8);   // 10.9.3.6
  3186.     return;
  3187.   }
  3188.   SingleBitEncode(TRUE);
  3189.   if (len < 0x2000) {
  3190.     MultiBitEncode(len, 15);    // 10.9.3.7
  3191.     return;
  3192.   }
  3193.   SingleBitEncode(TRUE);
  3194.   PAssert(len < 0x2000, PUnimplementedFunction);  // 10.9.3.8 unsupported
  3195. }
  3196. void PPER_Stream::AnyTypeEncode(const PASN_Object * value)
  3197. {
  3198.   PPER_Stream substream;
  3199.   if (value != NULL)
  3200.     value->Encode(substream);
  3201.   if (substream.GetPosition() == 0)   // Make sure extension has at least one
  3202.     substream.SingleBitEncode(FALSE); // byte in its ANY type encoding.
  3203.   substream.CompleteEncoding();
  3204.   PINDEX nBytes = substream.GetSize();
  3205.   LengthEncode(nBytes, 0, INT_MAX);
  3206.   BlockEncode(substream.GetPointer(), nBytes);
  3207. }
  3208. // PERASN.CXX