📄 asner.cxx
字号:
/* * 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 PNEWstatic 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;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -