📄 objostrasnb.cpp
字号:
/* * =========================================================================== * PRODUCTION $Log: objostrasnb.cpp,v $ * PRODUCTION Revision 1000.3 2004/06/01 19:41:15 gouriano * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.88 * PRODUCTION * =========================================================================== *//* $Id: objostrasnb.cpp,v 1000.3 2004/06/01 19:41:15 gouriano Exp $* ===========================================================================** PUBLIC DOMAIN NOTICE* National Center for Biotechnology Information** This software/database is a "United States Government Work" under the* terms of the United States Copyright Act. It was written as part of* the author's official duties as a United States Government employee and* thus cannot be copyrighted. This software/database is freely available* to the public for use. The National Library of Medicine and the U.S.* Government have not placed any restriction on its use or reproduction.** Although all reasonable efforts have been taken to ensure the accuracy* and reliability of the software and data, the NLM and the U.S.* Government do not and cannot warrant the performance or results that* may be obtained by using this software or data. The NLM and the U.S.* Government disclaim all warranties, express or implied, including* warranties of performance, merchantability or fitness for any particular* purpose.** Please cite the author in any work or product based on this material.** ===========================================================================** Author: Eugene Vasilchenko** File Description:* ASN.1 binary object output stream.*/#include <ncbi_pch.hpp>#include <corelib/ncbistd.hpp>#include <corelib/ncbi_limits.hpp>#include <serial/objostrasnb.hpp>#include <serial/objistr.hpp>#include <serial/objcopy.hpp>#include <serial/objistrasnb.hpp>#include <serial/memberid.hpp>#include <serial/enumvalues.hpp>#include <serial/memberlist.hpp>#include <serial/objhook.hpp>#include <serial/classinfo.hpp>#include <serial/choice.hpp>#include <serial/continfo.hpp>#include <serial/delaybuf.hpp>#include <stdio.h>#include <math.h>using namespace NCBI_NS_NCBI::CObjectStreamAsnBinaryDefs;#undef _TRACE#define _TRACE(arg) ((void)0)BEGIN_NCBI_SCOPECObjectOStream* CObjectOStream::OpenObjectOStreamAsnBinary(CNcbiOstream& out, bool deleteOut){ return new CObjectOStreamAsnBinary(out, deleteOut);}CObjectOStreamAsnBinary::CObjectOStreamAsnBinary(CNcbiOstream& out, EFixNonPrint how) : CObjectOStream(eSerial_AsnBinary, out), m_FixMethod(how){#if CHECK_STREAM_INTEGRITY m_CurrentPosition = 0; m_CurrentTagState = eTagStart; m_CurrentTagLimit = numeric_limits<size_t>::max();#endif}CObjectOStreamAsnBinary::CObjectOStreamAsnBinary(CNcbiOstream& out, bool deleteOut, EFixNonPrint how) : CObjectOStream(eSerial_AsnBinary, out, deleteOut), m_FixMethod(how){#if CHECK_STREAM_INTEGRITY m_CurrentPosition = 0; m_CurrentTagState = eTagStart; m_CurrentTagLimit = numeric_limits<size_t>::max();#endif}CObjectOStreamAsnBinary::~CObjectOStreamAsnBinary(void){#if CHECK_STREAM_INTEGRITY if ( !m_Limits.empty() || m_CurrentTagState != eTagStart ) ERR_POST("CObjectOStreamAsnBinary not finished");#endif}#if CHECK_STREAM_INTEGRITYinlinevoid CObjectOStreamAsnBinary::StartTag(Uint1 code){ m_Limits.push(m_CurrentTagLimit); m_CurrentTagCode = code; m_CurrentTagPosition = m_CurrentPosition; m_CurrentTagState = (code & 0x1f) == eLongTag? eTagValue: eLengthStart;}inlinevoid CObjectOStreamAsnBinary::EndTag(void){ if ( m_Limits.empty() ) ThrowError(fIllegalCall, "too many tag ends"); m_CurrentTagState = eTagStart; m_CurrentTagLimit = m_Limits.top(); m_Limits.pop();}inlinevoid CObjectOStreamAsnBinary::SetTagLength(size_t length){ size_t limit = m_CurrentPosition + 1 + length; if ( limit <= m_CurrentPosition || limit > m_CurrentTagLimit ) ThrowError(fIllegalCall, "tag will overflow enclosing tag"); else m_CurrentTagLimit = limit; if ( m_CurrentTagCode & 0x20 ) // constructed m_CurrentTagState = eTagStart; else m_CurrentTagState = eData; if ( length == 0 ) EndTag();}#endif#if !CHECK_STREAM_INTEGRITYinline#endifvoid CObjectOStreamAsnBinary::WriteByte(Uint1 byte){#if CHECK_STREAM_INTEGRITY //_TRACE("WriteByte: " << NStr::PtrToString(byte)); if ( m_CurrentPosition >= m_CurrentTagLimit ) ThrowError(fOverflow, "tag size overflow"); switch ( m_CurrentTagState ) { case eTagStart: StartTag(byte); break; case eTagValue: if ( (byte & 0x80) == 0) m_CurrentTagState = eLengthStart; break; case eLengthStart: if ( byte == 0 ) { SetTagLength(0); if ( m_CurrentTagCode == 0 ) EndTag(); } else if ( byte == 0x80 ) { if ( !(m_CurrentTagCode & 0x20) ) { ThrowError(fIllegalCall, "cannot use indefinite form for primitive tag"); } m_CurrentTagState = eTagStart; } else if ( byte < 0x80 ) { SetTagLength(byte); } else { m_CurrentTagLengthSize = byte - 0x80; if ( m_CurrentTagLengthSize > sizeof(size_t) ) ThrowError(fOverflow, "tag length is too big"); m_CurrentTagState = eLengthValueFirst; } break; case eLengthValueFirst: if ( byte == 0 ) ThrowError(fFormatError, "first byte of length is zero"); if ( --m_CurrentTagLengthSize == 0 ) { SetTagLength(byte); } else { m_CurrentTagLength = byte; m_CurrentTagState = eLengthValue; } break; // fall down to next case (no break needed) case eLengthValue: m_CurrentTagLength = (m_CurrentTagLength << 8) | byte; if ( --m_CurrentTagLengthSize == 0 ) SetTagLength(m_CurrentTagLength); break; case eData: if ( m_CurrentPosition + 1 == m_CurrentTagLimit ) EndTag(); break; } m_CurrentPosition++;#endif m_Output.PutChar(byte);}#if !CHECK_STREAM_INTEGRITYinline#endifvoid CObjectOStreamAsnBinary::WriteBytes(const char* bytes, size_t size){ if ( size == 0 ) return;#if CHECK_STREAM_INTEGRITY //_TRACE("WriteBytes: " << size); if ( m_CurrentTagState != eData ) ThrowError(fFormatError, "WriteBytes only allowed in DATA"); size_t new_pos = m_CurrentPosition + size; if ( new_pos < m_CurrentPosition || new_pos > m_CurrentTagLimit ) ThrowError(fFormatError, "tag DATA overflow"); m_CurrentPosition = new_pos; if ( new_pos == m_CurrentTagLimit ) EndTag();#endif m_Output.PutString(bytes, size);}template<typename T>void WriteBytesOf(CObjectOStreamAsnBinary& out, const T& value, size_t count){ for ( size_t shift = (count - 1) * 8; shift > 0; shift -= 8 ) { out.WriteByte(Uint1(value >> shift)); } out.WriteByte(Uint1(value));}inlinevoid CObjectOStreamAsnBinary::WriteShortTag(EClass c, bool constructed, TTag tag){ WriteByte((c << 6) | (constructed ? (1<<5) : 0) | tag);}inlinevoid CObjectOStreamAsnBinary::WriteSysTag(ETag tag){ WriteShortTag(eUniversal, false, tag);}void CObjectOStreamAsnBinary::WriteLongTag(EClass c, bool constructed, TTag tag){ if ( tag <= 0 ) ThrowError(fFormatError, "negative tag number"); // long form WriteShortTag(c, constructed, eLongTag); // calculate largest shift enough for TTag to fit size_t shift = (sizeof(TTag) * 8 - 1) / 7 * 7; Uint1 bits; // find first non zero 7bits while ( (bits = (tag >> shift) & 0x7f) == 0 ) { shift -= 7; } // beginning of tag while ( shift != 0 ) { shift -= 7; WriteByte((tag >> shift) | 0x80); } // write remaining bits WriteByte(tag & 0x7f);}inlinevoid CObjectOStreamAsnBinary::WriteTag(EClass c, bool constructed, TTag tag){ if ( tag >= 0 && tag < eLongTag ) WriteShortTag(c, constructed, tag); else WriteLongTag(c, constructed, tag);}void CObjectOStreamAsnBinary::WriteClassTag(TTypeInfo typeInfo){ const string& tag = typeInfo->GetName(); if ( tag.empty() ) ThrowError(fFormatError, "empty tag string"); _ASSERT( tag[0] > eLongTag ); // long form WriteShortTag(eApplication, true, eLongTag); SIZE_TYPE last = tag.size() - 1; for ( SIZE_TYPE i = 0; i <= last; ++i ) { char c = tag[i]; _ASSERT( (c & 0x80) == 0 ); if ( i != last ) c |= 0x80; WriteByte(c); }}inlinevoid CObjectOStreamAsnBinary::WriteIndefiniteLength(void){ WriteByte(0x80);}inlinevoid CObjectOStreamAsnBinary::WriteShortLength(size_t length){ WriteByte(Uint1(length));}void CObjectOStreamAsnBinary::WriteLongLength(size_t length){ // long form size_t count; if ( length <= 0xffU ) count = 1; else if ( length <= 0xffffU ) count = 2; else if ( length <= 0xffffffU ) count = 3; else { count = sizeof(length); if ( sizeof(length) > 4 ) { for ( size_t shift = (count-1)*8; count > 0; --count, shift -= 8 ) { if ( Uint1(length >> shift) != 0 ) break; } } } WriteByte(Uint1(0x80 + count)); WriteBytesOf(*this, length, count);}inlinevoid CObjectOStreamAsnBinary::WriteLength(size_t length){ if ( length <= 127 ) WriteShortLength(length); else WriteLongLength(length);}inlinevoid CObjectOStreamAsnBinary::WriteEndOfContent(void){ WriteSysTag(eNone); WriteShortLength(0);}void CObjectOStreamAsnBinary::WriteNull(void){ WriteSysTag(eNull); WriteShortLength(0);}void CObjectOStreamAsnBinary::WriteAnyContentObject(const CAnyContentObject& ){ NCBI_THROW(CSerialException,eNotImplemented, "CObjectOStreamAsnBinary::WriteAnyContentObject: " "unable to write AnyContent object in ASN");}void CObjectOStreamAsnBinary::CopyAnyContentObject(CObjectIStream& ){ NCBI_THROW(CSerialException,eNotImplemented, "CObjectOStreamAsnBinary::CopyAnyContentObject: " "unable to copy AnyContent object in ASN");}staticvoid WriteNumberValue(CObjectOStreamAsnBinary& out, Int4 data){ size_t length; if ( data >= Int4(-0x80) && data <= Int4(0x7f) ) { // one byte length = 1; } else if ( data >= Int4(-0x8000) && data <= Int4(0x7fff) ) { // two bytes length = 2; } else if ( data >= Int4(-0x800000) && data <= Int4(0x7fffff) ) { // three bytes length = 3; } else { // full length signed length = sizeof(data); } out.WriteShortLength(length); WriteBytesOf(out, data, length);}staticvoid WriteNumberValue(CObjectOStreamAsnBinary& out, Int8 data){ size_t length; if ( data >= -Int8(0x80) && data <= Int8(0x7f) ) { // one byte length = 1; } else if ( data >= Int8(-0x8000) && data <= Int8(0x7fff) ) { // two bytes length = 2; } else if ( data >= Int8(-0x800000) && data <= Int8(0x7fffff) ) { // three bytes length = 3; } else if ( data >= Int8(-0x80000000L) && data <= Int8(0x7fffffffL) ) { // four bytes length = 4; } else { // full length signed length = sizeof(data); } out.WriteShortLength(length); WriteBytesOf(out, data, length);}staticvoid WriteNumberValue(CObjectOStreamAsnBinary& out, Uint4 data){ size_t length; if ( data <= 0x7fU ) { length = 1; } else if ( data <= 0x7fffU ) { // two bytes length = 2; } else if ( data <= 0x7fffffU ) { // three bytes length = 3; } else if ( data <= 0x7fffffffU ) { // four bytes length = 4; } else { // check for high bit to avoid storing unsigned data as negative if ( (data & (Uint4(1) << (sizeof(data) * 8 - 1))) != 0 ) { // full length unsigned - and doesn't fit in signed place out.WriteShortLength(sizeof(data) + 1); out.WriteByte(0); WriteBytesOf(out, data, sizeof(data)); return; } else { // full length length = sizeof(data); } } out.WriteShortLength(length); WriteBytesOf(out, data, length);}staticvoid WriteNumberValue(CObjectOStreamAsnBinary& out, Uint8 data){ size_t length; if ( data <= 0x7fUL ) { length = 1; } else if ( data <= 0x7fffUL ) { // two bytes length = 2; } else if ( data <= 0x7fffffUL ) { // three bytes length = 3; } else if ( data <= 0x7fffffffUL ) { // four bytes length = 4; } else { // check for high bit to avoid storing unsigned data as negative if ( (data & (Uint8(1) << (sizeof(data) * 8 - 1))) != 0 ) { // full length unsigned - and doesn't fit in signed place out.WriteShortLength(sizeof(data) + 1); out.WriteByte(0); WriteBytesOf(out, data, sizeof(data)); return; } else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -