4 * Abstract Syntax Notation 1 Encoding Rules
6 * Portable Windows Library
10 ///////////////////////////////////////////////////////////////////////
12 BOOL
PBER_Stream::NullDecode(PASN_Null
& value
)
15 if (!HeaderDecode(value
, len
))
23 void PBER_Stream::NullEncode(const PASN_Null
& value
)
28 ///////////////////////////////////////////////////////////////////////
30 BOOL
PBER_Stream::BooleanDecode(PASN_Boolean
& value
)
33 if (!HeaderDecode(value
, len
))
39 value
= (BOOL
)ByteDecode();
46 void PBER_Stream::BooleanEncode(const PASN_Boolean
& value
)
49 ByteEncode((BOOL
)value
);
52 ///////////////////////////////////////////////////////////////////////
54 BOOL
PBER_Stream::IntegerDecode(PASN_Integer
& value
)
57 if (!HeaderDecode(value
, len
) || len
== 0 || IsAtEnd())
60 int accumulator
= (char)ByteDecode(); // sign extended first byte
64 accumulator
= (accumulator
<< 8) | ByteDecode();
72 void PBER_Stream::IntegerEncode(const PASN_Integer
& value
)
75 // output the integer bits
76 for (int count
= GetIntegerDataLength(value
)-1; count
>= 0; count
--)
77 ByteEncode(value
>> (count
*8));
80 ///////////////////////////////////////////////////////////////////////
82 BOOL
PBER_Stream::EnumerationDecode(PASN_Enumeration
& value
)
85 if (!HeaderDecode(value
, len
) || len
== 0 || IsAtEnd())
92 val
= (val
<< 8) | ByteDecode();
100 void PBER_Stream::EnumerationEncode(const PASN_Enumeration
& value
)
103 // output the integer bits
104 for (int count
= GetIntegerDataLength(value
)-1; count
>= 0; count
--)
105 ByteEncode(value
>> (count
*8));
108 ///////////////////////////////////////////////////////////////////////
110 BOOL
PBER_Stream::RealDecode(PASN_Real
& value
)
113 if (!HeaderDecode(value
, len
) || len
== 0 || IsAtEnd())
116 PAssertAlways(PUnimplementedFunction
);
123 void PBER_Stream::RealEncode(const PASN_Real
&)
125 PAssertAlways(PUnimplementedFunction
);
128 ///////////////////////////////////////////////////////////////////////
130 BOOL
PBER_Stream::ObjectIdDecode(PASN_ObjectId
& value
)
133 if (!HeaderDecode(value
, len
))
136 return value
.CommonDecode(*this, len
);
140 void PBER_Stream::ObjectIdEncode(const PASN_ObjectId
& value
)
144 value
.CommonEncode(data
);
145 BlockEncode(data
, data
.GetSize());
148 ///////////////////////////////////////////////////////////////////////
150 BOOL
PASN_BitString::DecodeBER(PBER_Stream
& strm
, unsigned len
)
152 totalBits
= len
*8 - strm
.ByteDecode();
153 unsigned nBytes
= (totalBits
+7)/8;
154 return strm
.BlockDecode(bitData
.GetPointer(nBytes
), nBytes
) == nBytes
;
158 void PASN_BitString::EncodeBER(PBER_Stream
& strm
) const
163 strm
.ByteEncode(8-totalBits
%8);
164 strm
.BlockEncode(bitData
, (totalBits
+7)/8);
168 ///////////////////////////////////////////////////////////////////////
170 BOOL
PBER_Stream::BitStringDecode(PASN_BitString
& value
)
173 if (!HeaderDecode(value
, len
) || len
== 0 || IsAtEnd())
176 return value
.DecodeBER(*this, len
);
180 void PBER_Stream::BitStringEncode(const PASN_BitString
& value
)
183 value
.EncodeBER(*this);
186 ///////////////////////////////////////////////////////////////////////
188 BOOL
PBER_Stream::OctetStringDecode(PASN_OctetString
& value
)
191 if (!HeaderDecode(value
, len
))
194 return BlockDecode(value
.GetPointer(len
), len
) == len
;
198 void PBER_Stream::OctetStringEncode(const PASN_OctetString
& value
)
201 BlockEncode(value
, value
.GetSize());
204 ///////////////////////////////////////////////////////////////////////
206 BOOL
PASN_ConstrainedString::DecodeBER(PBER_Stream
& strm
, unsigned len
)
208 return strm
.BlockDecode((BYTE
*)value
.GetPointer(len
+1), len
) == len
;
212 void PASN_ConstrainedString::EncodeBER(PBER_Stream
& strm
) const
214 strm
.BlockEncode(value
, value
.GetSize()-1);
217 ///////////////////////////////////////////////////////////////////////
219 BOOL
PBER_Stream::ConstrainedStringDecode(PASN_ConstrainedString
& value
)
222 if (!HeaderDecode(value
, len
))
225 return value
.DecodeBER(*this, len
);
229 void PBER_Stream::ConstrainedStringEncode(const PASN_ConstrainedString
& value
)
232 value
.EncodeBER(*this);
235 ///////////////////////////////////////////////////////////////////////
237 BOOL
PASN_BMPString::DecodeBER(PBER_Stream
& strm
, unsigned len
)
239 value
.SetSize(len
/2);
240 return strm
.BlockDecode((BYTE
*)value
.GetPointer(len
), len
) == len
;
244 void PASN_BMPString::EncodeBER(PBER_Stream
& strm
) const
246 strm
.BlockEncode((const BYTE
*)(const WORD
*)value
, value
.GetSize()*2);
249 ///////////////////////////////////////////////////////////////////////
251 BOOL
PBER_Stream::BMPStringDecode(PASN_BMPString
& value
)
254 if (!HeaderDecode(value
, len
))
257 return value
.DecodeBER(*this, len
);
261 void PBER_Stream::BMPStringEncode(const PASN_BMPString
& value
)
264 value
.EncodeBER(*this);
267 ///////////////////////////////////////////////////////////////////////
269 BOOL
PBER_Stream::ChoiceDecode(PASN_Choice
& value
)
271 PINDEX savedPosition
= GetPosition();
274 PASN_Object::TagClass tagClass
;
277 if (!HeaderDecode(tag
, tagClass
, primitive
, entryLen
))
280 SetPosition(savedPosition
);
282 value
.SetTag(tag
, tagClass
);
284 return value
.GetObject().Decode(*this);
289 void PBER_Stream::ChoiceEncode(const PASN_Choice
& value
)
292 value
.GetObject().Encode(*this);
295 ///////////////////////////////////////////////////////////////////////
297 BOOL
PASN_Sequence::PreambleDecodeBER(PBER_Stream
& strm
)
302 if (!strm
.HeaderDecode(*this, len
))
305 endBasicEncoding
= strm
.GetPosition() + len
;
306 return !strm
.IsAtEnd();
310 void PASN_Sequence::PreambleEncodeBER(PBER_Stream
& strm
) const
312 strm
.HeaderEncode(*this);
316 BOOL
PASN_Sequence::KnownExtensionDecodeBER(PBER_Stream
& strm
, PINDEX
, PASN_Object
& field
)
318 if (strm
.GetPosition() >= endBasicEncoding
)
321 return field
.Decode(strm
);
325 void PASN_Sequence::KnownExtensionEncodeBER(PBER_Stream
& strm
, PINDEX
, const PASN_Object
& field
) const
331 BOOL
PASN_Sequence::UnknownExtensionsDecodeBER(PBER_Stream
& strm
)
333 while (strm
.GetPosition() < endBasicEncoding
) {
334 PINDEX savedPosition
= strm
.GetPosition();
337 PASN_Object::TagClass tagClass
;
340 if (!strm
.HeaderDecode(tag
, tagClass
, primitive
, entryLen
))
343 PINDEX nextEntryPosition
= strm
.GetPosition() + entryLen
;
344 strm
.SetPosition(savedPosition
);
346 PASN_Object
* obj
= strm
.CreateObject(tag
, tagClass
, primitive
);
348 strm
.SetPosition(nextEntryPosition
);
350 if (!obj
->Decode(strm
))
361 void PASN_Sequence::UnknownExtensionsEncodeBER(PBER_Stream
& strm
) const
363 for (PINDEX i
= 0; i
< fields
.GetSize(); i
++)
364 fields
[i
].Encode(strm
);
367 ///////////////////////////////////////////////////////////////////////
369 BOOL
PBER_Stream::SequencePreambleDecode(PASN_Sequence
& seq
)
371 return seq
.PreambleDecodeBER(*this);
375 void PBER_Stream::SequencePreambleEncode(const PASN_Sequence
& seq
)
377 seq
.PreambleEncodeBER(*this);
381 BOOL
PBER_Stream::SequenceKnownDecode(PASN_Sequence
& seq
, PINDEX fld
, PASN_Object
& field
)
383 return seq
.KnownExtensionDecodeBER(*this, fld
, field
);
387 void PBER_Stream::SequenceKnownEncode(const PASN_Sequence
& seq
, PINDEX fld
, const PASN_Object
& field
)
389 seq
.KnownExtensionEncodeBER(*this, fld
, field
);
393 BOOL
PBER_Stream::SequenceUnknownDecode(PASN_Sequence
& seq
)
395 return seq
.UnknownExtensionsDecodeBER(*this);
399 void PBER_Stream::SequenceUnknownEncode(const PASN_Sequence
& seq
)
401 seq
.UnknownExtensionsEncodeBER(*this);
404 ///////////////////////////////////////////////////////////////////////
406 BOOL
PBER_Stream::ArrayDecode(PASN_Array
& array
)
411 if (!HeaderDecode(array
, len
))
414 PINDEX endOffset
= byteOffset
+ len
;
416 while (byteOffset
< endOffset
) {
417 if (!array
.SetSize(count
+1))
419 if (!array
[count
].Decode(*this))
424 byteOffset
= endOffset
;
430 void PBER_Stream::ArrayEncode(const PASN_Array
& array
)
433 for (PINDEX i
= 0; i
< array
.GetSize(); i
++)
434 array
[i
].Encode(*this);
437 ///////////////////////////////////////////////////////////////////////
439 PBER_Stream::PBER_Stream()
444 PBER_Stream::PBER_Stream(const PBYTEArray
& bytes
)
450 PBER_Stream::PBER_Stream(const BYTE
* buf
, PINDEX size
)
451 : PASN_Stream(buf
, size
)
456 PBER_Stream
& PBER_Stream::operator=(const PBYTEArray
& bytes
)
458 PBYTEArray::operator=(bytes
);
463 BOOL
PBER_Stream::Read(PChannel
& chan
)
468 // read the sequence header
470 if ((b
= chan
.ReadChar()) < 0)
473 SetAt(offset
++, (char)b
);
475 // only support direct read of simple sequences
476 if ((b
&0x1f) == 0x1f) {
478 if ((b
= chan
.ReadChar()) < 0)
480 SetAt(offset
++, (char)b
);
481 } while ((b
& 0x80) != 0);
484 // read the first byte of the ASN length
485 if ((b
= chan
.ReadChar()) < 0)
488 SetAt(offset
++, (char)b
);
490 // determine how many bytes in the length
495 PINDEX lenLen
= b
&0x7f;
497 while (lenLen
-- > 0) {
499 if ((b
= chan
.ReadChar()) < 0)
501 dataLen
= (dataLen
<< 8) | b
;
502 SetAt(offset
++, (char)b
);
506 // read the data, all of it
507 BYTE
* bufptr
= GetPointer(dataLen
+offset
) + offset
;
508 while (dataLen
> 0) {
509 if (!chan
.Read(bufptr
, dataLen
))
511 PINDEX readbytes
= chan
.GetLastReadCount();
513 dataLen
-= readbytes
;
519 BOOL
PBER_Stream::Write(PChannel
& chan
)
522 return chan
.Write(theArray
, GetSize());
526 PASN_Object
* PBER_Stream::CreateObject(unsigned tag
,
527 PASN_Object::TagClass tagClass
,
528 BOOL primitive
) const
530 if (tagClass
== PASN_Object::UniversalTagClass
) {
532 case PASN_Object::UniversalBoolean
:
533 return new PASN_Boolean();
535 case PASN_Object::UniversalInteger
:
536 return new PASN_Integer();
538 case PASN_Object::UniversalBitString
:
539 return new PASN_BitString();
541 case PASN_Object::UniversalOctetString
:
542 return new PASN_OctetString();
544 case PASN_Object::UniversalNull
:
545 return new PASN_Null();
547 case PASN_Object::UniversalObjectId
:
548 return new PASN_ObjectId();
550 case PASN_Object::UniversalReal
:
551 return new PASN_Real();
553 case PASN_Object::UniversalEnumeration
:
554 return new PASN_Enumeration();
556 case PASN_Object::UniversalSequence
:
557 return new PASN_Sequence();
559 case PASN_Object::UniversalSet
:
560 return new PASN_Set();
562 case PASN_Object::UniversalNumericString
:
563 return new PASN_NumericString();
565 case PASN_Object::UniversalPrintableString
:
566 return new PASN_PrintableString();
568 case PASN_Object::UniversalIA5String
:
569 return new PASN_IA5String();
571 case PASN_Object::UniversalVisibleString
:
572 return new PASN_VisibleString();
574 case PASN_Object::UniversalGeneralString
:
575 return new PASN_GeneralString();
577 case PASN_Object::UniversalBMPString
:
578 return new PASN_BMPString();
583 return new PASN_OctetString(tag
, tagClass
);
585 return new PASN_Sequence(tag
, tagClass
, 0, FALSE
, 0);
588 BOOL
PBER_Stream::HeaderDecode(unsigned & tagVal
,
589 PASN_Object::TagClass
& tagClass
,
593 BYTE ident
= ByteDecode();
594 tagClass
= (PASN_Object::TagClass
)(ident
>>6);
595 primitive
= (ident
&0x20) == 0;
605 tagVal
= (tagVal
<< 7) | (b
&0x7f);
606 } while ((b
&0x80) != 0);
612 BYTE len_len
= ByteDecode();
613 if ((len_len
& 0x80) == 0) {
621 while (len_len
-- > 0) {
625 len
= (len
<< 8) | ByteDecode();
632 BOOL
PBER_Stream::HeaderDecode(PASN_Object
& obj
, unsigned & len
)
634 PINDEX pos
= byteOffset
;
637 PASN_Object::TagClass tagClass
;
639 if (HeaderDecode(tagVal
, tagClass
, primitive
, len
) &&
640 tagVal
== obj
.GetTag() && tagClass
== obj
.GetTagClass())
648 void PBER_Stream::HeaderEncode(const PASN_Object
& obj
)
650 BYTE ident
= (BYTE
)(obj
.GetTagClass() << 6);
651 if (!obj
.IsPrimitive())
653 unsigned tag
= obj
.GetTag();
655 ByteEncode(ident
|tag
);
657 ByteEncode(ident
|31);
658 unsigned count
= (CountBits(tag
)+6)/7;
660 ByteEncode((tag
>> (count
*7))&0x7f);
661 ByteEncode(tag
&0x7f);
664 PINDEX len
= obj
.GetDataLength();
668 PINDEX count
= (CountBits(len
+1)+7)/8;
669 ByteEncode(count
|0x80);
671 ByteEncode(len
>> (count
*8));
675 ///////////////////////////////////////////////////////////////////////