asner.cxx
上传用户:hzhsqp
上传日期:2007-01-06
资源大小:1600k
文件大小:96k
- /*
- * asner.cxx
- *
- * Abstract Syntax Notation 1 Encoding Rules
- *
- * Portable Windows Library
- *
- * Copyright (c) 1993-1998 Equivalence Pty. Ltd.
- *
- * The contents of this file are subject to the Mozilla Public License
- * Version 1.0 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS IS"
- * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
- * the License for the specific language governing rights and limitations
- * under the License.
- *
- * The Original Code is Portable Windows Library.
- *
- * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
- *
- * Portions are Copyright (C) 1993 Free Software Foundation, Inc.
- * All Rights Reserved.
- *
- * Contributor(s): ______________________________________.
- *
- * $Log: asner.cxx,v $
- * Revision 1.30 2000/02/29 06:32:12 robertj
- * Added ability to remove optional field in sequence, thanks Dave Harvey.
- *
- * Revision 1.29 2000/01/20 06:22:22 robertj
- * Fixed boundary condition error for constrained integer encoding (values 1, 256 etc)
- *
- * Revision 1.28 1999/11/22 23:15:43 robertj
- * Fixed bug in PASN_Choice::Compare(), should make sure choices are the same before comparing.
- *
- * Revision 1.27 1999/08/19 15:43:07 robertj
- * Fixed incorrect size of OID if zero length encoded.
- *
- * Revision 1.26 1999/08/09 13:02:45 robertj
- * dded ASN compiler #defines for backward support of pre GCC 2.9 compilers.
- * Added ASN compiler #defines to reduce its memory footprint.
- *
- * Revision 1.25 1999/08/08 15:45:59 robertj
- * Fixed incorrect encoding of unknown extensions.
- *
- * Revision 1.24 1999/08/05 00:44:28 robertj
- * Fixed PER encoding problems for large integer values.
- *
- * Revision 1.23 1999/07/22 06:48:54 robertj
- * Added comparison operation to base ASN classes and compiled ASN code.
- * Added support for ANY type in ASN parser.
- *
- * Revision 1.22 1999/07/08 08:39:12 robertj
- * Fixed bug when assigning negative number ot cosntrained PASN_Integer
- *
- * Revision 1.21 1999/06/30 08:58:12 robertj
- * Fixed bug in encoding/decoding OID greater than 2.39
- *
- * Revision 1.20 1999/06/17 13:27:09 robertj
- * Fixed bug causing crashes on pass through of unknown extensions.
- *
- * Revision 1.19 1999/06/07 00:31:25 robertj
- * Fixed signed/unsigned problem with number of unknown extensions check.
- *
- * Revision 1.18 1999/04/26 05:58:48 craigs
- * Fixed problems with encoding of extensions
- *
- * Revision 1.17 1999/03/09 08:12:38 robertj
- * Fixed problem with closing a steam encoding twice.
- *
- * Revision 1.16 1999/01/16 01:28:25 robertj
- * Fixed problems with reading stream multiple times.
- *
- * Revision 1.15 1998/11/30 04:50:44 robertj
- * New directory structure
- *
- * Revision 1.14 1998/10/22 04:33:11 robertj
- * Fixed bug in constrained strings and PER, incorrect order of character set.
- *
- * Revision 1.13 1998/09/23 06:21:49 robertj
- * Added open source copyright license.
- *
- * Revision 1.12 1998/05/26 05:29:23 robertj
- * Workaroung for g++ iostream bug.
- *
- * Revision 1.11 1998/05/21 04:58:54 robertj
- * GCC comptaibility.
- *
- * Revision 1.10 1998/05/21 04:26:54 robertj
- * Fixed numerous PER problems.
- *
- * Revision 1.9 1998/05/11 06:01:55 robertj
- * Why did this compile under MSC?
- *
- * Revision 1.8 1998/05/07 05:19:29 robertj
- * Fixed problems with using copy constructor/assignment oeprator on PASN_Objects.
- *
- * Revision 1.7 1998/03/05 12:49:50 robertj
- * MemCheck fixes.
- *
- * Revision 1.6 1998/02/03 06:28:27 robertj
- * Fixed length calculation of integers in BER.
- * Added new function to read a block with minimum number of bytes.
- *
- * Revision 1.5 1998/01/26 01:51:20 robertj
- * Removed uninitialised variable warnings.
- *
- * Revision 1.4 1997/12/18 05:07:56 robertj
- * Fixed bug in choice name display.
- * Added function to get choice discriminator name.
- * Fixed bug in encoding extensions.
- *
- * Revision 1.3 1997/12/11 10:36:22 robertj
- * Support for new ASN parser.
- *
- */
- #include <ptlib.h>
- #ifdef __GNUC__
- #pragma implementation "asner.h"
- #endif
- #include <ptclib/asner.h>
- #define new PNEW
- static PINDEX CountBits(unsigned range)
- {
- if (range == 0)
- return sizeof(unsigned)*8;
- PINDEX nBits = 0;
- while (nBits < (sizeof(unsigned)*8) && range > (unsigned)(1 << nBits))
- nBits++;
- return nBits;
- }
- ///////////////////////////////////////////////////////////////////////
- PASN_Object::PASN_Object(unsigned theTag, TagClass theTagClass, BOOL extend)
- {
- extendable = extend;
- tag = theTag;
- if (theTagClass != DefaultTagClass)
- tagClass = theTagClass;
- else
- tagClass = ContextSpecificTagClass;
- }
- void PASN_Object::SetTag(unsigned newTag, TagClass tagClass_)
- {
- tag = newTag;
- if (tagClass_ != DefaultTagClass)
- tagClass = tagClass_;
- }
- PINDEX PASN_Object::GetObjectLength() const
- {
- PINDEX len = 1;
- if (tag >= 31)
- len += (CountBits(tag)+6)/7;
- PINDEX dataLen = GetDataLength();
- if (dataLen < 128)
- len++;
- else
- len += (CountBits(dataLen)+7)/8 + 1;
- return len + dataLen;
- }
- void PASN_Object::SetConstraints(ConstraintType, MinimumValueTag lower, unsigned upper)
- {
- SetConstraints(PartiallyConstrained, (int)lower, upper);
- }
- void PASN_Object::SetConstraints(ConstraintType, int lower, MaximumValueTag upper)
- {
- SetConstraints(PartiallyConstrained, lower, (unsigned)upper);
- }
- void PASN_Object::SetConstraints(ConstraintType, MinimumValueTag lower, MaximumValueTag upper)
- {
- SetConstraints(PartiallyConstrained, (int)lower, (unsigned)upper);
- }
- void PASN_Object::SetConstraints(ConstraintType, int, unsigned)
- {
- }
- void PASN_Object::SetCharacterSet(ConstraintType, const char *)
- {
- }
- void PASN_Object::SetCharacterSet(ConstraintType, unsigned, unsigned)
- {
- }
- ///////////////////////////////////////////////////////////////////////
- PASN_ConstrainedObject::PASN_ConstrainedObject(unsigned tag, TagClass tagClass)
- : PASN_Object(tag, tagClass)
- {
- constraint = Unconstrained;
- lowerLimit = 0;
- upperLimit = UINT_MAX;
- }
- void PASN_ConstrainedObject::SetConstraints(ConstraintType ctype,
- int lower, unsigned upper)
- {
- constraint = ctype;
- if (constraint == Unconstrained) {
- lower = 0;
- upper = UINT_MAX;
- }
- extendable = ctype == ExtendableConstraint;
- PAssert((lower >= 0 || upper < 0x7fffffff) &&
- (lower < 0 || (unsigned)lower <= upper), PInvalidParameter);
- lowerLimit = lower;
- upperLimit = upper;
- }
- int PASN_ConstrainedObject::ConstrainedLengthDecode(PPER_Stream & strm, unsigned & length)
- {
- // The execution order is important in the following. The SingleBitDecode() function
- // must be called if extendable is TRUE, no matter what.
- if ((extendable && strm.SingleBitDecode()) || constraint == Unconstrained)
- return strm.LengthDecode(0, INT_MAX, length);
- else
- return strm.LengthDecode(lowerLimit, upperLimit, length);
- }
- void PASN_ConstrainedObject::ConstrainedLengthEncode(PPER_Stream & strm, unsigned length) const
- {
- if (ConstraintEncode(strm, length)) // 26.4
- strm.LengthEncode(length, 0, INT_MAX);
- else
- strm.LengthEncode(length, lowerLimit, upperLimit);
- }
- BOOL PASN_ConstrainedObject::ConstraintEncode(PPER_Stream & strm, unsigned value) const
- {
- if (!extendable)
- return constraint != FixedConstraint;
- BOOL needsExtending = value > upperLimit;
- if (!needsExtending) {
- if (lowerLimit < 0) {
- if ((int)value < lowerLimit)
- needsExtending = TRUE;
- }
- else {
- if (value < (unsigned)lowerLimit)
- needsExtending = TRUE;
- }
- }
- strm.SingleBitEncode(needsExtending);
- return needsExtending || constraint != FixedConstraint;
- }
- ///////////////////////////////////////////////////////////////////////
- PASN_Null::PASN_Null(unsigned tag, TagClass tagClass)
- : PASN_Object(tag, tagClass)
- {
- }
- PObject::Comparison PASN_Null::Compare(const PObject & obj) const
- {
- PAssert(obj.IsDescendant(PASN_Null::Class()), PInvalidCast);
- return EqualTo;
- }
- PObject * PASN_Null::Clone() const
- {
- PAssert(IsClass(PASN_Null::Class()), PInvalidCast);
- return new PASN_Null(*this);
- }
- void PASN_Null::PrintOn(ostream & strm) const
- {
- strm << "<<null>>";
- }
- PString PASN_Null::GetTypeAsString() const
- {
- return "Null";
- }
- PINDEX PASN_Null::GetDataLength() const
- {
- return 0;
- }
- BOOL PASN_Null::Decode(PASN_Stream & strm)
- {
- return strm.NullDecode(*this);
- }
- void PASN_Null::Encode(PASN_Stream & strm) const
- {
- strm.NullEncode(*this);
- }
- BOOL PBER_Stream::NullDecode(PASN_Null & value)
- {
- unsigned len;
- if (!HeaderDecode(value, len))
- return FALSE;
- byteOffset += len;
- return TRUE;
- }
- void PBER_Stream::NullEncode(const PASN_Null & value)
- {
- HeaderEncode(value);
- }
- BOOL PPER_Stream::NullDecode(PASN_Null &)
- {
- return TRUE;
- }
- void PPER_Stream::NullEncode(const PASN_Null &)
- {
- }
- ///////////////////////////////////////////////////////////////////////
- PASN_Boolean::PASN_Boolean(BOOL val, unsigned tag, TagClass tagClass)
- : PASN_Object(tag, tagClass)
- {
- value = val;
- }
- PObject::Comparison PASN_Boolean::Compare(const PObject & obj) const
- {
- PAssert(obj.IsDescendant(PASN_Boolean::Class()), PInvalidCast);
- return value == ((const PASN_Boolean &)obj).value ? EqualTo : GreaterThan;
- }
- PObject * PASN_Boolean::Clone() const
- {
- PAssert(IsClass(PASN_Boolean::Class()), PInvalidCast);
- return new PASN_Boolean(*this);
- }
- void PASN_Boolean::PrintOn(ostream & strm) const
- {
- if (value)
- strm << "TRUE";
- else
- strm << "FALSE";
- }
- PString PASN_Boolean::GetTypeAsString() const
- {
- return "Boolean";
- }
- PINDEX PASN_Boolean::GetDataLength() const
- {
- return 1;
- }
- BOOL PASN_Boolean::Decode(PASN_Stream & strm)
- {
- return strm.BooleanDecode(*this);
- }
- void PASN_Boolean::Encode(PASN_Stream & strm) const
- {
- strm.BooleanEncode(*this);
- }
- BOOL PBER_Stream::BooleanDecode(PASN_Boolean & value)
- {
- unsigned len;
- if (!HeaderDecode(value, len))
- return FALSE;
- while (len-- > 0) {
- if (IsAtEnd())
- return FALSE;
- value = (BOOL)ByteDecode();
- }
- return TRUE;
- }
- void PBER_Stream::BooleanEncode(const PASN_Boolean & value)
- {
- HeaderEncode(value);
- ByteEncode((BOOL)value);
- }
- BOOL PPER_Stream::BooleanDecode(PASN_Boolean & value)
- {
- if (IsAtEnd())
- return FALSE;
- // X.931 Section 11
- value = (BOOL)SingleBitDecode();
- return TRUE;
- }
- void PPER_Stream::BooleanEncode(const PASN_Boolean & value)
- {
- // X.931 Section 11
- SingleBitEncode((BOOL)value);
- }
- ///////////////////////////////////////////////////////////////////////
- PASN_Integer::PASN_Integer(unsigned tag, TagClass tagClass, unsigned val)
- : PASN_ConstrainedObject(tag, tagClass)
- {
- value = val;
- }
- PASN_Integer & PASN_Integer::operator=(unsigned val)
- {
- if (constraint == Unconstrained)
- value = val;
- else if (lowerLimit >= 0) { // Is unsigned integer
- if (val < (unsigned)lowerLimit)
- value = lowerLimit;
- else if (val > upperLimit)
- value = upperLimit;
- else
- value = val;
- }
- else {
- int ival = (int)val;
- if (ival < lowerLimit)
- value = lowerLimit;
- else if (upperLimit < INT_MAX && ival > (int)upperLimit)
- value = upperLimit;
- else
- value = val;
- }
- return *this;
- }
- PObject::Comparison PASN_Integer::Compare(const PObject & obj) const
- {
- PAssert(obj.IsDescendant(PASN_Integer::Class()), PInvalidCast);
- const PASN_Integer & other = (const PASN_Integer &)obj;
- if (value < other.value)
- return LessThan;
- if (value > other.value)
- return GreaterThan;
- return EqualTo;
- }
- PObject * PASN_Integer::Clone() const
- {
- PAssert(IsClass(PASN_Integer::Class()), PInvalidCast);
- return new PASN_Integer(*this);
- }
- void PASN_Integer::PrintOn(ostream & strm) const
- {
- if (lowerLimit < 0)
- strm << (int)value;
- else
- strm << value;
- }
- PString PASN_Integer::GetTypeAsString() const
- {
- return "Integer";
- }
- static PINDEX GetIntegerDataLength(int value)
- {
- // create a mask which is the top nine bits of a DWORD, or 0xFF800000
- // on a big endian machine
- int shift = (sizeof(value)-1)*8-1;
- // remove all sequences of nine 0's or 1's at the start of the value
- while (shift > 0 && ((value >> shift)&0x1ff) == (value < 0 ? 0x1ff : 0))
- shift -= 8;
- return (shift+9)/8;
- }
- PINDEX PASN_Integer::GetDataLength() const
- {
- return GetIntegerDataLength(value);
- }
- BOOL PASN_Integer::Decode(PASN_Stream & strm)
- {
- return strm.IntegerDecode(*this);
- }
- void PASN_Integer::Encode(PASN_Stream & strm) const
- {
- strm.IntegerEncode(*this);
- }
- BOOL PBER_Stream::IntegerDecode(PASN_Integer & value)
- {
- unsigned len;
- if (!HeaderDecode(value, len) || len == 0 || IsAtEnd())
- return FALSE;
- int accumulator = (char)ByteDecode(); // sign extended first byte
- while (--len > 0) {
- if (IsAtEnd())
- return FALSE;
- accumulator = (accumulator << 8) | ByteDecode();
- }
- value = accumulator;
- return TRUE;
- }
- void PBER_Stream::IntegerEncode(const PASN_Integer & value)
- {
- HeaderEncode(value);
- // output the integer bits
- for (int count = GetIntegerDataLength(value)-1; count >= 0; count--)
- ByteEncode(value >> (count*8));
- }
- BOOL PPER_Stream::IntegerDecode(PASN_Integer & value)
- {
- return value.DecodePER(*this);
- }
- void PPER_Stream::IntegerEncode(const PASN_Integer & value)
- {
- value.EncodePER(*this);
- }
- BOOL PASN_Integer::DecodePER(PPER_Stream & strm)
- {
- // X.931 Sections 12
- if ((extendable && strm.SingleBitDecode()) || constraint != FixedConstraint) { // 12.1
- unsigned len;
- if (strm.LengthDecode(0, INT_MAX, len) != 0)
- return FALSE;
- value = strm.MultiBitDecode(len*8);
- return TRUE;
- }
- if ((unsigned)lowerLimit != upperLimit) // 12.2.1
- return strm.UnsignedDecode(lowerLimit, upperLimit, value) == 0; // 12.2.2 which devolves to 10.5
- value = lowerLimit;
- return TRUE;
- }
- void PASN_Integer::EncodePER(PPER_Stream & strm) const
- {
- // X.931 Sections 12
- if (ConstraintEncode(strm, (int)value)) { // 12.1
- PINDEX nBytes;
- unsigned adjusted_value = value - lowerLimit;
- if (adjusted_value == 0)
- nBytes = 1;
- else {
- PINDEX nBits = CountBits(adjusted_value+1);
- nBytes = (nBits+7)/8;
- }
- strm.LengthEncode(nBytes, 0, INT_MAX);
- strm.MultiBitEncode(adjusted_value, nBytes*8);
- return;
- }
- if ((unsigned)lowerLimit == upperLimit) // 12.2.1
- return;
- // 12.2.2 which devolves to 10.5
- strm.UnsignedEncode(value, lowerLimit, upperLimit);
- }
- ///////////////////////////////////////////////////////////////////////
- PASN_Enumeration::PASN_Enumeration(unsigned tag, TagClass tagClass,
- unsigned maxEnum, BOOL extend,
- unsigned val)
- : PASN_Object(tag, tagClass, extend)
- {
- value = val;
- maxEnumValue = maxEnum;
- }
- static POrdinalToString BuildNamesDict(const PString & nameSpec)
- {
- POrdinalToString names;
- PStringArray nameList = nameSpec.Tokenise(' ', FALSE);
- int num = 0;
- for (PINDEX i = 0; i < nameList.GetSize(); i++) {
- const PString & thisName = nameList[i];
- if (!thisName) {
- PINDEX equalPos = thisName.Find('=');
- if (equalPos != P_MAX_INDEX)
- num = (int)thisName.Mid(equalPos+1).AsInteger();
- names.SetAt(POrdinalKey(num), thisName.Left(equalPos));
- num++;
- }
- }
- return names;
- }
- PASN_Enumeration::PASN_Enumeration(unsigned tag, TagClass tagClass,
- unsigned maxEnum, BOOL extend,
- const PString & nameSpec,
- unsigned val)
- : PASN_Object(tag, tagClass, extend),
- names(BuildNamesDict(nameSpec))
- {
- PAssert(maxEnum > 0, PInvalidParameter);
- maxEnumValue = maxEnum;
- PAssert(val < maxEnum, PInvalidParameter);
- value = val;
- }
- PObject::Comparison PASN_Enumeration::Compare(const PObject & obj) const
- {
- PAssert(obj.IsDescendant(PASN_Enumeration::Class()), PInvalidCast);
- const PASN_Enumeration & other = (const PASN_Enumeration &)obj;
- if (value < other.value)
- return LessThan;
- if (value > other.value)
- return GreaterThan;
- return EqualTo;
- }
- PObject * PASN_Enumeration::Clone() const
- {
- PAssert(IsClass(PASN_Enumeration::Class()), PInvalidCast);
- return new PASN_Enumeration(*this);
- }
- void PASN_Enumeration::PrintOn(ostream & strm) const
- {
- if (names.Contains(value))
- strm << names[value];
- else
- strm << '<' << value << '>';
- }
- PString PASN_Enumeration::GetTypeAsString() const
- {
- return "Enumeration";
- }
- PINDEX PASN_Enumeration::GetDataLength() const
- {
- return GetIntegerDataLength(value);
- }
- BOOL PASN_Enumeration::Decode(PASN_Stream & strm)
- {
- return strm.EnumerationDecode(*this);
- }
- void PASN_Enumeration::Encode(PASN_Stream & strm) const
- {
- strm.EnumerationEncode(*this);
- }
- BOOL PBER_Stream::EnumerationDecode(PASN_Enumeration & value)
- {
- unsigned len;
- if (!HeaderDecode(value, len) || len == 0 || IsAtEnd())
- return FALSE;
- unsigned val = 0;
- while (len-- > 0) {
- if (IsAtEnd())
- return FALSE;
- val = (val << 8) | ByteDecode();
- }
- value = val;
- return TRUE;
- }
- void PBER_Stream::EnumerationEncode(const PASN_Enumeration & value)
- {
- HeaderEncode(value);
- // output the integer bits
- for (int count = GetIntegerDataLength(value)-1; count >= 0; count--)
- ByteEncode(value >> (count*8));
- }
- BOOL PPER_Stream::EnumerationDecode(PASN_Enumeration & value)
- {
- return value.DecodePER(*this);
- }
- void PPER_Stream::EnumerationEncode(const PASN_Enumeration & value)
- {
- value.EncodePER(*this);
- }
- BOOL PASN_Enumeration::DecodePER(PPER_Stream & strm)
- {
- // X.691 Section 13
- if (extendable) { // 13.3
- if (strm.SingleBitDecode())
- return strm.UnsignedDecode(0, strm.SmallUnsignedDecode()-1, value) == 0;
- }
- return strm.UnsignedDecode(0, maxEnumValue, value) == 0; // 13.2
- }
- void PASN_Enumeration::EncodePER(PPER_Stream & strm) const
- {
- // X.691 Section 13
- if (extendable) { // 13.3
- BOOL extended = value > maxEnumValue;
- strm.SingleBitEncode(extended);
- if (extended) {
- strm.SmallUnsignedEncode(1+value);
- strm.UnsignedEncode(value, 0, value);
- return;
- }
- }
- strm.UnsignedEncode(value, 0, maxEnumValue); // 13.2
- }
- ///////////////////////////////////////////////////////////////////////
- PASN_Real::PASN_Real(unsigned tag, TagClass tagClass, double val)
- : PASN_Object(tag, tagClass)
- {
- value = val;
- }
- PObject::Comparison PASN_Real::Compare(const PObject & obj) const
- {
- PAssert(obj.IsDescendant(PASN_Real::Class()), PInvalidCast);
- const PASN_Real & other = (const PASN_Real &)obj;
- if (value < other.value)
- return LessThan;
- if (value > other.value)
- return GreaterThan;
- return EqualTo;
- }
- PObject * PASN_Real::Clone() const
- {
- PAssert(IsClass(PASN_Real::Class()), PInvalidCast);
- return new PASN_Real(*this);
- }
- void PASN_Real::PrintOn(ostream & strm) const
- {
- strm << value;
- }
- PString PASN_Real::GetTypeAsString() const
- {
- return "Real";
- }
- PINDEX PASN_Real::GetDataLength() const
- {
- PAssertAlways(PUnimplementedFunction);
- return 0;
- }
- BOOL PASN_Real::Decode(PASN_Stream & strm)
- {
- return strm.RealDecode(*this);
- }
- void PASN_Real::Encode(PASN_Stream & strm) const
- {
- strm.RealEncode(*this);
- }
- BOOL PBER_Stream::RealDecode(PASN_Real & value)
- {
- unsigned len;
- if (!HeaderDecode(value, len) || len == 0 || IsAtEnd())
- return FALSE;
- PAssertAlways(PUnimplementedFunction);
- byteOffset += len;
- return TRUE;
- }
- void PBER_Stream::RealEncode(const PASN_Real &)
- {
- PAssertAlways(PUnimplementedFunction);
- }
- BOOL PPER_Stream::RealDecode(PASN_Real &)
- {
- // X.691 Section 14
- if (IsAtEnd())
- return FALSE;
- PINDEX len = MultiBitDecode(8)+1;
- PAssertAlways(PUnimplementedFunction);
- byteOffset += len;
- return TRUE;
- }
- void PPER_Stream::RealEncode(const PASN_Real &)
- {
- // X.691 Section 14
- MultiBitEncode(0, 8);
- PAssertAlways(PUnimplementedFunction);
- MultiBitEncode(0, 8);
- }
- ///////////////////////////////////////////////////////////////////////
- PASN_ObjectId::PASN_ObjectId(unsigned tag, TagClass tagClass)
- : PASN_Object(tag, tagClass)
- {
- }
- PASN_ObjectId::PASN_ObjectId(const PASN_ObjectId & other)
- : PASN_Object(other),
- value(other.value, other.GetSize())
- {
- }
- PASN_ObjectId & PASN_ObjectId::operator=(const PASN_ObjectId & other)
- {
- PASN_Object::operator=(other);
- value = PUnsignedArray(other.value, other.GetSize());
- return *this;
- }
- PASN_ObjectId & PASN_ObjectId::operator=(const char * dotstr)
- {
- SetValue(dotstr);
- return *this;
- }
- PASN_ObjectId & PASN_ObjectId::operator=(const PString & dotstr)
- {
- SetValue(dotstr);
- return *this;
- }
- void PASN_ObjectId::SetValue(const PString & dotstr)
- {
- PStringArray parts = dotstr.Tokenise('.');
- value.SetSize(parts.GetSize());
- for (PINDEX i = 0; i < parts.GetSize(); i++)
- value[i] = parts[i].AsUnsigned();
- }
- BOOL PASN_ObjectId::operator==(const char * dotstr) const
- {
- PASN_ObjectId id;
- id.SetValue(dotstr);
- return *this == id;
- }
- PObject::Comparison PASN_ObjectId::Compare(const PObject & obj) const
- {
- PAssert(obj.IsDescendant(PASN_ObjectId::Class()), PInvalidCast);
- const PASN_ObjectId & other = (const PASN_ObjectId &)obj;
- return value.Compare(other.value);
- }
- PObject * PASN_ObjectId::Clone() const
- {
- PAssert(IsClass(PASN_ObjectId::Class()), PInvalidCast);
- return new PASN_ObjectId(*this);
- }
- void PASN_ObjectId::PrintOn(ostream & strm) const
- {
- for (PINDEX i = 0; i < value.GetSize(); i++) {
- strm << (unsigned)value[i];
- if (i < value.GetSize()-1)
- strm << '.';
- }
- }
- PString PASN_ObjectId::GetTypeAsString() const
- {
- return "Object ID";
- }
- BOOL PASN_ObjectId::CommonDecode(PASN_Stream & strm, unsigned dataLen)
- {
- value.SetSize(0);
- // handle zero length strings correctly
- if (dataLen == 0)
- return TRUE;
- unsigned subId;
- // start at the second identifier in the buffer, because we will later
- // expand the first number into the first two IDs
- PINDEX i = 1;
- while (dataLen > 0) {
- unsigned byte;
- subId = 0;
- do { /* shift and add in low order 7 bits */
- if (strm.IsAtEnd())
- return FALSE;
- byte = strm.ByteDecode();
- subId = (subId << 7) + (byte & 0x7f);
- dataLen--;
- } while ((byte & 0x80) != 0);
- value.SetAt(i++, subId);
- }
- /*
- * The first two subidentifiers are encoded into the first component
- * with the value (X * 40) + Y, where:
- * X is the value of the first subidentifier.
- * Y is the value of the second subidentifier.
- */
- subId = value[1];
- if (subId < 40) {
- value[0] = 0;
- value[1] = subId;
- }
- else if (subId < 80) {
- value[0] = 1;
- value[1] = subId-40;
- }
- else {
- value[0] = 2;
- value[1] = subId-80;
- }
- return TRUE;
- }
- void PASN_ObjectId::CommonEncode(PBYTEArray & encodecObjectId) const
- {
- PINDEX length = value.GetSize();
- const unsigned * objId = value;
- if (length < 2) {
- // Thise case is really illegal, but we have to do SOMETHING
- encodecObjectId.SetSize(0);
- return;
- }
- unsigned subId = (objId[0] * 40) + objId[1];
- objId += 2;
- PINDEX outputPosition = 0;
- while (--length > 0) {
- if (subId < 128)
- encodecObjectId[outputPosition++] = (BYTE)subId;
- else {
- unsigned mask = 0x7F; /* handle subid == 0 case */
- int bits = 0;
- /* testmask *MUST* !!!! be of an unsigned type */
- unsigned testmask = 0x7F;
- int testbits = 0;
- while (testmask != 0) {
- if (subId & testmask) { /* if any bits set */
- mask = testmask;
- bits = testbits;
- }
- testmask <<= 7;
- testbits += 7;
- }
- /* mask can't be zero here */
- while (mask != 0x7F) {
- /* fix a mask that got truncated above */
- if (mask == 0x1E00000)
- mask = 0xFE00000;
- encodecObjectId[outputPosition++] = (BYTE)(((subId & mask) >> bits) | 0x80);
- mask >>= 7;
- bits -= 7;
- }
- encodecObjectId[outputPosition++] = (BYTE)(subId & mask);
- }
- subId = *objId++;
- }
- }
- PINDEX PASN_ObjectId::GetDataLength() const
- {
- PBYTEArray dummy;
- CommonEncode(dummy);
- return dummy.GetSize();
- }
- BOOL PASN_ObjectId::Decode(PASN_Stream & strm)
- {
- return strm.ObjectIdDecode(*this);
- }
- void PASN_ObjectId::Encode(PASN_Stream & strm) const
- {
- strm.ObjectIdEncode(*this);
- }
- BOOL PBER_Stream::ObjectIdDecode(PASN_ObjectId & value)
- {
- unsigned len;
- if (!HeaderDecode(value, len))
- return FALSE;
- return value.CommonDecode(*this, len);
- }
- void PBER_Stream::ObjectIdEncode(const PASN_ObjectId & value)
- {
- HeaderEncode(value);
- PBYTEArray data;
- value.CommonEncode(data);
- BlockEncode(data, data.GetSize());
- }
- BOOL PPER_Stream::ObjectIdDecode(PASN_ObjectId & value)
- {
- // X.691 Section 23
- unsigned dataLen;
- if (LengthDecode(0, 255, dataLen) < 0)
- return FALSE;
- ByteAlign();
- return value.CommonDecode(*this, dataLen);
- }
- void PPER_Stream::ObjectIdEncode(const PASN_ObjectId & value)
- {
- // X.691 Section 23
- PBYTEArray eObjId;
- value.CommonEncode(eObjId);
- LengthEncode(eObjId.GetSize(), 0, 255);
- BlockEncode(eObjId, eObjId.GetSize());
- }
- ///////////////////////////////////////////////////////////////////////
- PASN_BitString::PASN_BitString(unsigned tag, TagClass tagClass, unsigned nBits)
- : PASN_ConstrainedObject(tag, tagClass),
- totalBits(nBits),
- bitData((totalBits+7)/8)
- {
- }
- PASN_BitString::PASN_BitString(const PASN_BitString & other)
- : PASN_ConstrainedObject(other),
- bitData(other.bitData, other.bitData.GetSize())
- {
- totalBits = other.totalBits;
- }
- PASN_BitString & PASN_BitString::operator=(const PASN_BitString & other)
- {
- PASN_ConstrainedObject::operator=(other);
- totalBits = other.totalBits;
- bitData = PBYTEArray(other.bitData, other.bitData.GetSize());
- return *this;
- }
- void PASN_BitString::SetData(unsigned nBits, const PBYTEArray & bytes)
- {
- bitData = bytes;
- totalBits = nBits;
- }
- void PASN_BitString::SetData(unsigned nBits, const BYTE * buf, PINDEX size)
- {
- bitData = PBYTEArray(buf, size);
- totalBits = nBits;
- }
- BOOL PASN_BitString::SetSize(unsigned nBits)
- {
- totalBits = nBits;
- return bitData.SetSize((nBits+7)/8);
- }
- BOOL PASN_BitString::operator[](PINDEX bit) const
- {
- if ((unsigned)bit < totalBits)
- return (bitData[bit>>3] & (1 << (7 - (bit&7)))) != 0;
- return FALSE;
- }
- void PASN_BitString::Set(unsigned bit)
- {
- if (bit < totalBits)
- bitData[(PINDEX)(bit>>3)] |= 1 << (7 - (bit&7));
- }
- void PASN_BitString::Clear(unsigned bit)
- {
- if (bit < totalBits)
- bitData[(PINDEX)(bit>>3)] &= ~(1 << (7 - (bit&7)));
- }
- void PASN_BitString::Invert(unsigned bit)
- {
- if (bit < totalBits)
- bitData[(PINDEX)(bit>>3)] ^= 1 << (7 - (bit&7));
- }
- void PASN_BitString::SetConstraints(ConstraintType type, int lower, unsigned upper)
- {
- PAssert(lower >= 0, PInvalidParameter);
- PASN_ConstrainedObject::SetConstraints(type, lower, upper);
- if (constraint != Unconstrained) {
- if (totalBits < (unsigned)lowerLimit)
- SetSize(lowerLimit);
- else if ((unsigned)totalBits > upperLimit)
- SetSize(upperLimit);
- }
- }
- PObject::Comparison PASN_BitString::Compare(const PObject & obj) const
- {
- PAssert(obj.IsDescendant(PASN_BitString::Class()), PInvalidCast);
- const PASN_BitString & other = (const PASN_BitString &)obj;
- if (totalBits < other.totalBits)
- return LessThan;
- if (totalBits > other.totalBits)
- return GreaterThan;
- return bitData.Compare(other.bitData);
- }
- PObject * PASN_BitString::Clone() const
- {
- PAssert(IsClass(PASN_BitString::Class()), PInvalidCast);
- return new PASN_BitString(*this);
- }
- void PASN_BitString::PrintOn(ostream & strm) const
- {
- BYTE mask = 0x80;
- PINDEX offset = 0;
- for (unsigned i = 0; i < totalBits; i++) {
- strm << ((bitData[offset]&mask) != 0 ? '1' : '0');
- mask >>= 1;
- if (mask == 0) {
- mask = 0x80;
- offset++;
- }
- }
- }
- PString PASN_BitString::GetTypeAsString() const
- {
- return "Bit String";
- }
- PINDEX PASN_BitString::GetDataLength() const
- {
- return (totalBits+7)/8 + 1;
- }
- BOOL PASN_BitString::Decode(PASN_Stream & strm)
- {
- return strm.BitStringDecode(*this);
- }
- void PASN_BitString::Encode(PASN_Stream & strm) const
- {
- strm.BitStringEncode(*this);
- }
- BOOL PASN_BitString::DecodeBER(PBER_Stream & strm, unsigned len)
- {
- totalBits = len*8 - strm.ByteDecode();
- unsigned nBytes = (totalBits+7)/8;
- return strm.BlockDecode(bitData.GetPointer(nBytes), nBytes) == nBytes;
- }
- void PASN_BitString::EncodeBER(PBER_Stream & strm) const
- {
- if (totalBits == 0)
- strm.ByteEncode(0);
- else {
- strm.ByteEncode(8-totalBits%8);
- strm.BlockEncode(bitData, (totalBits+7)/8);
- }
- }
- BOOL PASN_BitString::DecodePER(PPER_Stream & strm)
- {
- // X.691 Section 15
- if (ConstrainedLengthDecode(strm, totalBits) < 0)
- return FALSE;
- SetSize(totalBits);
- if (totalBits == 0)
- return TRUE; // 15.7
- if (totalBits > strm.GetBitsLeft())
- return FALSE;
- if (totalBits > 16) {
- unsigned nBytes = (totalBits+7)/8;
- return strm.BlockDecode(bitData.GetPointer(), nBytes) == nBytes; // 15.9
- }
- if (totalBits <= 8)
- bitData[0] = (BYTE)(strm.MultiBitDecode(totalBits) << (8-totalBits));
- else { // 15.8
- bitData[0] = (BYTE)strm.MultiBitDecode(8);
- bitData[1] = (BYTE)(strm.MultiBitDecode(totalBits-8) << (16-totalBits));
- }
- return TRUE;
- }
- void PASN_BitString::EncodePER(PPER_Stream & strm) const
- {
- // X.691 Section 15
- ConstrainedLengthEncode(strm, totalBits);
- if (totalBits == 0)
- return;
- if (totalBits > 16)
- strm.BlockEncode(bitData, (totalBits+7)/8); // 15.9
- else if (totalBits <= 8) // 15.8
- strm.MultiBitEncode(bitData[0] >> (8 - totalBits), totalBits);
- else {
- strm.MultiBitEncode(bitData[0], 8);
- strm.MultiBitEncode(bitData[1] >> (16 - totalBits), totalBits-8);
- }
- }
- BOOL PBER_Stream::BitStringDecode(PASN_BitString & value)
- {
- unsigned len;
- if (!HeaderDecode(value, len) || len == 0 || IsAtEnd())
- return FALSE;
- return value.DecodeBER(*this, len);
- }
- void PBER_Stream::BitStringEncode(const PASN_BitString & value)
- {
- HeaderEncode(value);
- value.EncodeBER(*this);
- }
- BOOL PPER_Stream::BitStringDecode(PASN_BitString & value)
- {
- return value.DecodePER(*this);
- }
- void PPER_Stream::BitStringEncode(const PASN_BitString & value)
- {
- value.EncodePER(*this);
- }
- ///////////////////////////////////////////////////////////////////////
- PASN_OctetString::PASN_OctetString(unsigned tag, TagClass tagClass)
- : PASN_ConstrainedObject(tag, tagClass)
- {
- }
- PASN_OctetString::PASN_OctetString(const PASN_OctetString & other)
- : PASN_ConstrainedObject(other),
- value(other.value, other.GetSize())
- {
- }
- PASN_OctetString & PASN_OctetString::operator=(const PASN_OctetString & other)
- {
- PASN_ConstrainedObject::operator=(other);
- value = PBYTEArray(other.value, other.GetSize());
- return *this;
- }
- PASN_OctetString & PASN_OctetString::operator=(const char * str)
- {
- SetValue((const BYTE *)str, strlen(str));
- return *this;
- }
- PASN_OctetString & PASN_OctetString::operator=(const PString & str)
- {
- SetValue((const BYTE *)(const char *)str, str.GetSize()-1);
- return *this;
- }
- PASN_OctetString & PASN_OctetString::operator=(const PBYTEArray & arr)
- {
- PINDEX len = arr.GetSize();
- if ((unsigned)len > upperLimit || (int)len < lowerLimit)
- SetValue(arr, len);
- else
- value = arr;
- return *this;
- }
- void PASN_OctetString::SetValue(const BYTE * data, PINDEX len)
- {
- if ((unsigned)len > upperLimit)
- len = upperLimit;
- value.SetSize((int)len < lowerLimit ? lowerLimit : len);
- memcpy(value.GetPointer(), data, len);
- }
- PString PASN_OctetString::AsString() const
- {
- if (value.IsEmpty())
- return PString();
- return PString((const char *)(const BYTE *)value, value.GetSize());
- }
- void PASN_OctetString::SetConstraints(ConstraintType type, int lower, unsigned upper)
- {
- PAssert(lower >= 0, PInvalidParameter);
- PASN_ConstrainedObject::SetConstraints(type, lower, upper);
- if (constraint != Unconstrained) {
- if (value.GetSize() < (PINDEX)lowerLimit)
- value.SetSize(lowerLimit);
- else if ((unsigned)value.GetSize() > upperLimit)
- value.SetSize(upperLimit);
- }
- }
- PObject::Comparison PASN_OctetString::Compare(const PObject & obj) const
- {
- PAssert(obj.IsDescendant(PASN_OctetString::Class()), PInvalidCast);
- const PASN_OctetString & other = (const PASN_OctetString &)obj;
- return value.Compare(other.value);
- }
- PObject * PASN_OctetString::Clone() const
- {
- PAssert(IsClass(PASN_OctetString::Class()), PInvalidCast);
- return new PASN_OctetString(*this);
- }
- void PASN_OctetString::PrintOn(ostream & strm) const
- {
- int indent = strm.precision() + 2;
- strm << ' ' << value.GetSize() << " octets {n";
- PINDEX i = 0;
- while (i < value.GetSize()) {
- strm << setw(indent) << " " << hex << setfill('0');
- PINDEX j;
- for (j = 0; j < 16; j++) {
- if (i+j < value.GetSize())
- strm << setw(2) << (unsigned)value[i+j] << ' ';
- else
- strm << " ";
- }
- strm << " ";
- for (j = 0; j < 16; j++) {
- if (i+j < value.GetSize()) {
- if (isprint(value[i+j]))
- strm << value[i+j];
- else
- strm << ' ';
- }
- }
- strm << dec << setfill(' ') << 'n';
- i += 16;
- }
- strm << setw(indent-1) << "}";
- }
- PString PASN_OctetString::GetTypeAsString() const
- {
- return "Octet String";
- }
- PINDEX PASN_OctetString::GetDataLength() const
- {
- return value.GetSize();
- }
- BOOL PASN_OctetString::Decode(PASN_Stream & strm)
- {
- return strm.OctetStringDecode(*this);
- }
- void PASN_OctetString::Encode(PASN_Stream & strm) const
- {
- strm.OctetStringEncode(*this);
- }
- BOOL PASN_OctetString::DecodePER(PPER_Stream & strm)
- {
- // X.691 Section 16
- unsigned nBytes;
- if (ConstrainedLengthDecode(strm, nBytes) < 0)
- return FALSE;
- value.SetSize(nBytes); // 16.5
- switch (nBytes) {
- case 0 :
- break;
- case 1 : // 16.6
- if (strm.IsAtEnd())
- return FALSE;
- value[0] = (BYTE)strm.MultiBitDecode(8);
- break;
- case 2 : // 16.6
- if (strm.IsAtEnd())
- return FALSE;
- value[0] = (BYTE)strm.MultiBitDecode(8);
- value[1] = (BYTE)strm.MultiBitDecode(8);
- break;
- default: // 16.7
- return strm.BlockDecode(value.GetPointer(), nBytes) == nBytes;
- }
- return TRUE;
- }
- void PASN_OctetString::EncodePER(PPER_Stream & strm) const
- {
- // X.691 Section 16
- PINDEX nBytes = value.GetSize();
- ConstrainedLengthEncode(strm, nBytes);
- switch (nBytes) {
- case 0 : // 16.5
- break;
- case 1 : // 16.6
- strm.MultiBitEncode(value[0], 8);
- break;
- case 2 : // 16.6
- strm.MultiBitEncode(value[0], 8);
- strm.MultiBitEncode(value[1], 8);
- break;
- default: // 16.7
- strm.BlockEncode(value, nBytes);
- }
- }
- BOOL PBER_Stream::OctetStringDecode(PASN_OctetString & value)
- {
- unsigned len;
- if (!HeaderDecode(value, len))
- return FALSE;
- return BlockDecode(value.GetPointer(len), len) == len;
- }
- void PBER_Stream::OctetStringEncode(const PASN_OctetString & value)
- {
- HeaderEncode(value);
- BlockEncode(value, value.GetSize());
- }
- BOOL PPER_Stream::OctetStringDecode(PASN_OctetString & value)
- {
- return value.DecodePER(*this);
- }
- void PPER_Stream::OctetStringEncode(const PASN_OctetString & value)
- {
- value.EncodePER(*this);
- }
- ///////////////////////////////////////////////////////////////////////
- PASN_ConstrainedString::PASN_ConstrainedString(const char * canonical, PINDEX size,
- unsigned tag, TagClass tagClass)
- : PASN_ConstrainedObject(tag, tagClass)
- {
- canonicalSet = canonical;
- canonicalSetSize = size;
- canonicalSetBits = CountBits(size);
- charSetUnalignedBits = 8;
- charSetAlignedBits = 8;
- }
- PASN_ConstrainedString & PASN_ConstrainedString::operator=(const char * str)
- {
- value = PString();
- PINDEX len = strlen(str);
- for (PINDEX i = 0; i < len; i++) {
- PINDEX sz = characterSet.GetSize();
- if (sz == 0 || memchr(characterSet, str[i], sz) != NULL)
- value += str[i];
- }
- return *this;
- }
- void PASN_ConstrainedString::SetCharacterSet(ConstraintType ctype, const char * set)
- {
- SetCharacterSet(set, strlen(set), ctype);
- }
- void PASN_ConstrainedString::SetCharacterSet(ConstraintType ctype, unsigned firstChar, unsigned lastChar)
- {
- char buffer[256];
- for (unsigned i = firstChar; i < lastChar; i++)
- buffer[i] = (char)i;
- SetCharacterSet(buffer, lastChar - firstChar + 1, ctype);
- }
- void PASN_ConstrainedString::SetCharacterSet(const char * set, PINDEX setSize, ConstraintType ctype)
- {
- if (ctype == Unconstrained)
- characterSet.SetSize(0);
- else {
- characterSet.SetSize(setSize);
- PINDEX count = 0;
- for (PINDEX i = 0; i < canonicalSetSize; i++) {
- if (memchr(set, canonicalSet[i], setSize) != NULL)
- characterSet[count++] = canonicalSet[i];
- }
- PAssert(count > 0, PInvalidParameter);
- characterSet.SetSize(count);
- }
- if (characterSet.IsEmpty())
- charSetUnalignedBits = 8;
- else
- charSetUnalignedBits = CountBits(characterSet.GetSize());
- charSetAlignedBits = 1;
- while (charSetUnalignedBits > charSetAlignedBits)
- charSetAlignedBits <<= 1;
- }
- PObject::Comparison PASN_ConstrainedString::Compare(const PObject & obj) const
- {
- PAssert(obj.IsDescendant(PASN_ConstrainedString::Class()), PInvalidCast);
- const PASN_ConstrainedString & other = (const PASN_ConstrainedString &)obj;
- return value.Compare(other.value);
- }
- void PASN_ConstrainedString::PrintOn(ostream & strm) const
- {
- strm << value.ToLiteral();
- }
- PINDEX PASN_ConstrainedString::GetDataLength() const
- {
- return value.GetSize()-1;
- }
- BOOL PASN_ConstrainedString::Decode(PASN_Stream & strm)
- {
- return strm.ConstrainedStringDecode(*this);
- }
- void PASN_ConstrainedString::Encode(PASN_Stream & strm) const
- {
- strm.ConstrainedStringEncode(*this);
- }
- BOOL PASN_ConstrainedString::DecodeBER(PBER_Stream & strm, unsigned len)
- {
- return strm.BlockDecode((BYTE *)value.GetPointer(len+1), len) == len;
- }
- void PASN_ConstrainedString::EncodeBER(PBER_Stream & strm) const
- {
- strm.BlockEncode(value, value.GetSize()-1);
- }
- BOOL PASN_ConstrainedString::DecodePER(PPER_Stream & strm)
- {
- // X.691 Section 26
- unsigned len;
- if (ConstrainedLengthDecode(strm, len) < 0)
- return FALSE;
- unsigned nBits = strm.IsAligned() ? charSetAlignedBits : charSetUnalignedBits;
- if (constraint == Unconstrained || upperLimit*nBits > 16) {
- if (nBits == 8)
- return strm.BlockDecode((BYTE *)value.GetPointer(len+1), len) == len;
- if (strm.IsAligned())
- strm.ByteAlign();
- }
- value.SetSize(len+1);
- PINDEX i;
- for (i = 0; i < (PINDEX)len; i++) {
- if (strm.IsAtEnd())
- return FALSE;
- if (nBits >= canonicalSetBits && canonicalSetBits > 4)
- value[i] = (char)strm.MultiBitDecode(nBits);
- else
- value[i] = characterSet[strm.MultiBitDecode(nBits)];
- }
- value[i] = ' ';
- return TRUE;
- }
- void PASN_ConstrainedString::EncodePER(PPER_Stream & strm) const
- {
- // X.691 Section 26
- PINDEX len = value.GetSize()-1;
- ConstrainedLengthEncode(strm, len);
- unsigned nBits = strm.IsAligned() ? charSetAlignedBits : charSetUnalignedBits;
- if (constraint == Unconstrained || upperLimit*nBits > 16) {
- if (nBits == 8) {
- strm.BlockEncode((const BYTE *)(const char *)value, len);
- return;
- }
- if (strm.IsAligned())
- strm.ByteAlign();
- }
- for (PINDEX i = 0; i < len; i++) {
- if (nBits >= canonicalSetBits && canonicalSetBits > 4)
- strm.MultiBitEncode(value[i], nBits);
- else {
- const void * ptr = memchr(characterSet, value[i], characterSet.GetSize());
- PINDEX pos = 0;
- if (ptr != NULL)
- pos = ((const char *)ptr - (const char *)characterSet);
- strm.MultiBitEncode(pos, nBits);
- }
- }
- }
- BOOL PBER_Stream::ConstrainedStringDecode(PASN_ConstrainedString & value)
- {
- unsigned len;
- if (!HeaderDecode(value, len))
- return FALSE;
- return value.DecodeBER(*this, len);
- }
- void PBER_Stream::ConstrainedStringEncode(const PASN_ConstrainedString & value)
- {
- HeaderEncode(value);
- value.Encode(*this);
- }
- BOOL PPER_Stream::ConstrainedStringDecode(PASN_ConstrainedString & value)
- {
- return value.DecodePER(*this);
- }
- void PPER_Stream::ConstrainedStringEncode(const PASN_ConstrainedString & value)
- {
- value.EncodePER(*this);
- }
- #define DEFINE_STRING_CLASS(name, set)
- static const char name##StringSet[] = set;
- PASN_##name##String::PASN_##name##String(unsigned tag, TagClass tagClass)
- : PASN_ConstrainedString(name##StringSet, sizeof(name##StringSet)-1, tag, tagClass)
- { }
- PASN_##name##String & PASN_##name##String::operator=(const char * str)
- { PASN_ConstrainedString::SetValue(str); return *this; }
- PASN_##name##String & PASN_##name##String::operator=(const PString & str)
- { PASN_ConstrainedString::SetValue(str); return *this; }
- PObject * PASN_##name##String::Clone() const
- { PAssert(IsClass(PASN_##name##String::Class()), PInvalidCast);
- return new PASN_##name##String(*this); }
- PString PASN_##name##String::GetTypeAsString() const
- { return #name " String"; }
- DEFINE_STRING_CLASS(Numeric, " 0123456789")
- DEFINE_STRING_CLASS(Printable, " '()+,-./0123456789:=?"
- "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "abcdefghijklmnopqrstuvwxyz")
- DEFINE_STRING_CLASS(Visible, " !"#$%&'()*+,-./0123456789:;<=>?"
- "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_"
- "`abcdefghijklmnopqrstuvwxyz{|}~")
- DEFINE_STRING_CLASS(IA5, "