NCBI C++ ToolKit
objistrasn.cpp
Go to the documentation of this file.

Go to the SVN repository for this file.

00001 /*  $Id: objistrasn.cpp 64633 2014-09-30 15:39:59Z gouriano $
00002 * ===========================================================================
00003 *
00004 *                            PUBLIC DOMAIN NOTICE
00005 *               National Center for Biotechnology Information
00006 *
00007 *  This software/database is a "United States Government Work" under the
00008 *  terms of the United States Copyright Act.  It was written as part of
00009 *  the author's official duties as a United States Government employee and
00010 *  thus cannot be copyrighted.  This software/database is freely available
00011 *  to the public for use. The National Library of Medicine and the U.S.
00012 *  Government have not placed any restriction on its use or reproduction.
00013 *
00014 *  Although all reasonable efforts have been taken to ensure the accuracy
00015 *  and reliability of the software and data, the NLM and the U.S.
00016 *  Government do not and cannot warrant the performance or results that
00017 *  may be obtained by using this software or data. The NLM and the U.S.
00018 *  Government disclaim all warranties, express or implied, including
00019 *  warranties of performance, merchantability or fitness for any particular
00020 *  purpose.
00021 *
00022 *  Please cite the author in any work or product based on this material.
00023 *
00024 * ===========================================================================
00025 *
00026 * Author: Eugene Vasilchenko
00027 *
00028 * File Description:
00029 *   !!! PUT YOUR DESCRIPTION HERE !!!
00030 */
00031 
00032 #include <ncbi_pch.hpp>
00033 #include <corelib/ncbistd.hpp>
00034 #include <corelib/ncbiutil.hpp>
00035 #include <corelib/ncbifloat.h>
00036 #include <serial/objistrasn.hpp>
00037 #include <serial/impl/member.hpp>
00038 #include <serial/enumvalues.hpp>
00039 #include <serial/impl/memberlist.hpp>
00040 #include <serial/objhook.hpp>
00041 #include <serial/impl/classinfo.hpp>
00042 #include <serial/impl/choice.hpp>
00043 #include <serial/impl/continfo.hpp>
00044 #include <serial/impl/objistrimpl.hpp>
00045 #include <math.h>
00046 #if !defined(DBL_MAX_10_EXP) || !defined(FLT_MAX)
00047 # include <float.h>
00048 #endif
00049 
00050 BEGIN_NCBI_SCOPE
00051 
00052 CObjectIStream* CObjectIStream::CreateObjectIStreamAsn(void)
00053 {
00054     return new CObjectIStreamAsn();
00055 }
00056 
00057 CObjectIStreamAsn::CObjectIStreamAsn(EFixNonPrint how)
00058     : CObjectIStream(eSerial_AsnText)
00059 {
00060     FixNonPrint(how);
00061 }
00062 
00063 CObjectIStreamAsn::CObjectIStreamAsn(CNcbiIstream& in,
00064                                      EFixNonPrint how)
00065     : CObjectIStream(eSerial_AsnText)
00066 {
00067     FixNonPrint(how);
00068     Open(in);
00069 }
00070 
00071 CObjectIStreamAsn::CObjectIStreamAsn(CNcbiIstream& in,
00072                                      bool deleteIn,
00073                                      EFixNonPrint how)
00074     : CObjectIStream(eSerial_AsnText)
00075 {
00076     FixNonPrint(how);
00077     Open(in, deleteIn ? eTakeOwnership : eNoOwnership);
00078 }
00079 
00080 CObjectIStreamAsn::CObjectIStreamAsn(CNcbiIstream& in,
00081                                      EOwnership deleteIn,
00082                                      EFixNonPrint how)
00083     : CObjectIStream(eSerial_AsnText)
00084 {
00085     FixNonPrint(how);
00086     Open(in, deleteIn);
00087 }
00088 
00089 CObjectIStreamAsn::CObjectIStreamAsn(const char* buffer,
00090                                      size_t size,
00091                                      EFixNonPrint how)
00092     : CObjectIStream(eSerial_AsnText)
00093 {
00094     FixNonPrint(how);
00095     OpenFromBuffer(buffer, size);
00096 }
00097 
00098 bool CObjectIStreamAsn::EndOfData(void)
00099 {
00100     if (CObjectIStream::EndOfData()) {
00101         return true;
00102     }
00103     try {
00104         SkipWhiteSpace();
00105     } catch (...) {
00106         return true;
00107     }
00108     return false;
00109 }
00110 
00111 string CObjectIStreamAsn::GetPosition(void) const
00112 {
00113     return "line "+NStr::SizetToString(m_Input.GetLine());
00114 }
00115 
00116 inline
00117 bool CObjectIStreamAsn::FirstIdChar(char c)
00118 {
00119     return isalpha((unsigned char) c) || c == '_';
00120 }
00121 
00122 inline
00123 bool CObjectIStreamAsn::IdChar(char c)
00124 {
00125     return isalnum((unsigned char) c) || c == '_' || c == '.';
00126 }
00127 
00128 inline
00129 char CObjectIStreamAsn::GetChar(void)
00130 {
00131     return m_Input.GetChar();
00132 }
00133 
00134 inline
00135 char CObjectIStreamAsn::PeekChar(void)
00136 {
00137     return m_Input.PeekChar();
00138 }
00139 
00140 inline
00141 void CObjectIStreamAsn::SkipEndOfLine(char c)
00142 {
00143     m_Input.SkipEndOfLine(c);
00144 }
00145 
00146 inline
00147 char CObjectIStreamAsn::SkipWhiteSpaceAndGetChar(void)
00148 {
00149     char c = SkipWhiteSpace();
00150     m_Input.SkipChar();
00151     return c;
00152 }
00153 
00154 inline
00155 char CObjectIStreamAsn::GetChar(bool skipWhiteSpace)
00156 {
00157     return skipWhiteSpace? SkipWhiteSpaceAndGetChar(): m_Input.GetChar();
00158 }
00159 
00160 inline
00161 char CObjectIStreamAsn::PeekChar(bool skipWhiteSpace)
00162 {
00163     return skipWhiteSpace? SkipWhiteSpace(): m_Input.PeekChar();
00164 }
00165 
00166 inline
00167 bool CObjectIStreamAsn::GetChar(char expect, bool skipWhiteSpace)
00168 {
00169     if ( PeekChar(skipWhiteSpace) != expect ) {
00170         return false;
00171     }
00172     m_Input.SkipChar();
00173     return true;
00174 }
00175 
00176 void CObjectIStreamAsn::Expect(char expect, bool skipWhiteSpace)
00177 {
00178     if ( !GetChar(expect, skipWhiteSpace) ) {
00179         string msg("\'");
00180         msg += expect;
00181         msg += "' expected";
00182         ThrowError(fFormatError, msg);
00183     }
00184 }
00185 
00186 bool CObjectIStreamAsn::Expect(char choiceTrue, char choiceFalse,
00187                                bool skipWhiteSpace)
00188 {
00189     char c = GetChar(skipWhiteSpace);
00190     if ( c == choiceTrue ) {
00191         return true;
00192     }
00193     else if ( c == choiceFalse ) {
00194         return false;
00195     }
00196     m_Input.UngetChar(c);
00197     string msg("\'");
00198     msg += choiceTrue;
00199     msg += "' or '";
00200     msg += choiceFalse;
00201     msg += "' expected";
00202     ThrowError(fFormatError, msg);
00203     return false;
00204 }
00205 
00206 char CObjectIStreamAsn::SkipWhiteSpace(void)
00207 {
00208     try { // catch CEofException
00209         for ( ;; ) {
00210             char c = m_Input.SkipSpaces();
00211             switch ( c ) {
00212             case '\t':
00213                 m_Input.SkipChar();
00214                 continue;
00215             case '\r':
00216             case '\n':
00217                 m_Input.SkipChar();
00218                 SkipEndOfLine(c);
00219                 continue;
00220             case '-':
00221                 // check for comments
00222                 if ( m_Input.PeekChar(1) != '-' ) {
00223                     return '-';
00224                 }
00225                 m_Input.SkipChars(2);
00226                 // skip comments
00227                 SkipComments();
00228                 continue;
00229             default:
00230                 return c;
00231             }
00232         }
00233     } catch (CEofException& e) {
00234         if (GetStackDepth() <= 2) {
00235             throw;
00236         } else {
00237             // There should be no eof here, report as error
00238             ThrowError(fEOF, e.what());
00239         }
00240     }
00241     return '\0';
00242 }
00243 
00244 void CObjectIStreamAsn::SkipComments(void)
00245 {
00246     try {
00247         for ( ;; ) {
00248             char c = GetChar();
00249             switch ( c ) {
00250             case '\r':
00251             case '\n':
00252                 SkipEndOfLine(c);
00253                 return;
00254             case '-':
00255                 c = GetChar();
00256                 switch ( c ) {
00257                 case '\r':
00258                 case '\n':
00259                     SkipEndOfLine(c);
00260                     return;
00261                 case '-':
00262                     return;
00263                 }
00264                 continue;
00265             default:
00266                 continue;
00267             }
00268         }
00269     }
00270     catch ( CEofException& /* ignored */ ) {
00271         return;
00272     }
00273 }
00274 
00275 CTempString CObjectIStreamAsn::ScanEndOfId(bool isId)
00276 {
00277     if ( isId ) {
00278         for ( size_t i = 1; ; ++i ) {
00279             char c = m_Input.PeekCharNoEOF(i);
00280             if ( !IdChar(c) &&
00281                  (c != '-' || !IdChar(m_Input.PeekChar(i + 1))) ) {
00282                 const char* ptr = m_Input.GetCurrentPos();
00283                 m_Input.SkipChars(i);
00284                 return CTempString(ptr, i);
00285             }
00286         }
00287     }
00288     return CTempString();
00289 }
00290 
00291 CTempString CObjectIStreamAsn::ReadTypeId(char c)
00292 {
00293     if ( c == '[' ) {
00294         for ( size_t i = 1; ; ++i ) {
00295             switch ( m_Input.PeekChar(i) ) {
00296             case '\r':
00297             case '\n':
00298                 ThrowError(fFormatError, "end of line: expected ']'");
00299                 break;
00300             case ']':
00301                 {
00302                     const char* ptr = m_Input.GetCurrentPos();
00303                     m_Input.SkipChars(i);
00304                     return CTempString(ptr + 1, i - 2);
00305                 }
00306             }
00307         }
00308     }
00309     else {
00310         return ScanEndOfId(FirstIdChar(c));
00311     }
00312 }
00313 
00314 CTempString CObjectIStreamAsn::ReadNumber(void)
00315 {
00316     char c = SkipWhiteSpace();
00317     if ( c != '-' && c != '+' && !isdigit((unsigned char) c) )
00318         ThrowError(fFormatError, "invalid number");
00319     for ( size_t i = 1; ; ++i ) {
00320         c = m_Input.PeekChar(i);
00321         if ( !isdigit((unsigned char) c) ) {
00322             const char* ptr = m_Input.GetCurrentPos();
00323             m_Input.SkipChars(i);
00324             return CTempString(ptr, i);
00325         }
00326     }
00327 }
00328 
00329 inline
00330 CTempString CObjectIStreamAsn::ReadUCaseId(char c)
00331 {
00332     return ScanEndOfId(isupper((unsigned char) c) != 0);
00333 }
00334 
00335 inline
00336 CTempString CObjectIStreamAsn::ReadLCaseId(char c)
00337 {
00338     return ScanEndOfId(islower((unsigned char) c) != 0);
00339 }
00340 
00341 inline
00342 CTempString CObjectIStreamAsn::ReadMemberId(char c)
00343 {
00344     if ( c == '[' ) {
00345         for ( size_t i = 1; ; ++i ) {
00346             switch ( m_Input.PeekChar(i) ) {
00347             case '\r':
00348             case '\n':
00349                 ThrowError(fFormatError, "end of line: expected ']'");
00350                 break;
00351             case ']':
00352                 {
00353                     const char* ptr = m_Input.GetCurrentPos();
00354                     m_Input.SkipChars(++i);
00355                     return CTempString(ptr + 1, i - 2);
00356                 }
00357             }
00358         }
00359     }
00360     else {
00361         return ScanEndOfId(islower((unsigned char) c) != 0);
00362     }
00363 }
00364 
00365 TMemberIndex CObjectIStreamAsn::GetAltItemIndex(
00366     const CClassTypeInfoBase* classType,
00367     const CTempString& id,
00368     const TMemberIndex pos /*= kInvalidMember*/)
00369 {
00370     TMemberIndex idx = kInvalidMember;
00371     if (!id.empty()) {
00372         const CItemsInfo& info = classType->GetItems();
00373         string id_alt = string(id);
00374         id_alt[0] = toupper((unsigned char)id_alt[0]);
00375         if (pos != kInvalidMember) {
00376             idx = info.Find(CTempString(id_alt),pos);
00377         } else {
00378             idx = info.Find(CTempString(id_alt));
00379         }
00380         if (idx != kInvalidMember &&
00381             !info.GetItemInfo(idx)->GetId().HaveNoPrefix()) {
00382             idx = kInvalidMember;
00383         }
00384     }
00385     return idx;
00386 }
00387 
00388 TMemberIndex CObjectIStreamAsn::GetMemberIndex
00389     (const CClassTypeInfo* classType,
00390      const CTempString& id)
00391 {
00392     TMemberIndex idx;
00393     if (!id.empty()  &&  isdigit((unsigned char) id[0])) {
00394         idx = classType->GetMembers().Find
00395             (CMemberId::TTag(NStr::StringToInt(id)), CAsnBinaryDefs::eContextSpecific);
00396     }
00397     else {
00398         idx = classType->GetMembers().Find(id);
00399         if (idx == kInvalidMember) {
00400             idx = GetAltItemIndex(classType,id);
00401         }
00402     }
00403     return idx;
00404 }
00405 
00406 TMemberIndex CObjectIStreamAsn::GetMemberIndex
00407     (const CClassTypeInfo* classType,
00408      const CTempString& id,
00409      const TMemberIndex pos)
00410 {
00411     TMemberIndex idx;
00412     if (!id.empty()  &&  isdigit((unsigned char) id[0])) {
00413         idx = classType->GetMembers().Find
00414             (CMemberId::TTag(NStr::StringToInt(id)), CAsnBinaryDefs::eContextSpecific, pos);
00415     }
00416     else {
00417         idx = classType->GetMembers().Find(id, pos);
00418         if (idx == kInvalidMember) {
00419             idx = GetAltItemIndex(classType,id,pos);
00420         }
00421     }
00422     return idx;
00423 }
00424 
00425 TMemberIndex CObjectIStreamAsn::GetChoiceIndex
00426     (const CChoiceTypeInfo* choiceType,
00427      const CTempString& id)
00428 {
00429     TMemberIndex idx;
00430     if (!id.empty()  &&  isdigit((unsigned char) id[0])) {
00431         idx = choiceType->GetVariants().Find
00432             (CMemberId::TTag(NStr::StringToInt(id)), CAsnBinaryDefs::eContextSpecific);
00433     }
00434     else {
00435         idx = choiceType->GetVariants().Find(id);
00436         if (idx == kInvalidMember) {
00437             idx = GetAltItemIndex(choiceType,id);
00438         }
00439     }
00440     return idx;
00441 }
00442 
00443 void CObjectIStreamAsn::ReadNull(void)
00444 {
00445     if ( SkipWhiteSpace() == 'N' && 
00446          m_Input.PeekCharNoEOF(1) == 'U' &&
00447          m_Input.PeekCharNoEOF(2) == 'L' &&
00448          m_Input.PeekCharNoEOF(3) == 'L' &&
00449          !IdChar(m_Input.PeekCharNoEOF(4)) ) {
00450         m_Input.SkipChars(4);
00451     }
00452     else
00453         ThrowError(fFormatError, "'NULL' expected");
00454 }
00455 
00456 void CObjectIStreamAsn::ReadAnyContent(string& value)
00457 {
00458     char buf[128];
00459     size_t pos=0;
00460     const size_t maxpos=128;
00461 
00462     char to = GetChar(true);
00463     buf[pos++] = to;
00464     if (to == '{') {
00465         to = '}';
00466     } else if (to == '\"') {
00467     } else {
00468         to = '\0';
00469     }
00470 
00471     bool space = false;
00472     for (char c = m_Input.PeekChar(); ; c = m_Input.PeekChar()) {
00473         if (to != '\"') {
00474             if (to != '}' && c == '\n') {
00475                 value.append(buf,pos);
00476                 return;
00477             }
00478             if (isspace((unsigned char) c)) {
00479                 if (space) {
00480                     m_Input.SkipChar();
00481                     continue;
00482                 }
00483                 c = ' ';
00484                 space = true;
00485             } else {
00486                 space = false;;
00487             }
00488             if (to != '}' && (c == ',' || c == '}')) {
00489                 value.append(buf,pos);
00490                 return;
00491             } else if (c == '\"' || c == '{') {
00492                 value.append(buf,pos);
00493                 ReadAnyContent(value);
00494                 pos = 0;
00495                 continue;
00496             }
00497         }
00498         if (c == to) {
00499             if (pos >= maxpos) {
00500                 value.append(buf,pos);
00501                 pos = 0;
00502             }
00503             buf[pos++] = c;
00504             value.append(buf,pos);
00505             m_Input.SkipChar();
00506             return;
00507         }
00508         if (c == '\"' || c == '{') {
00509             value.append(buf,pos);
00510             ReadAnyContent(value);
00511             pos = 0;
00512             continue;
00513         }
00514         if (pos >= maxpos) {
00515             value.append(buf,pos);
00516             pos = 0;
00517         }
00518         buf[pos++] = c;
00519         m_Input.SkipChar();
00520     }
00521 }
00522 
00523 void CObjectIStreamAsn::ReadAnyContentObject(CAnyContentObject& obj)
00524 {
00525     string value;
00526     ReadAnyContent(value);
00527     obj.SetValue(CUtf8::AsUTF8(value,eEncoding_UTF8));
00528 }
00529 
00530 void CObjectIStreamAsn::SkipAnyContent(void)
00531 {
00532     char to = GetChar(true);
00533     if (to == '{') {
00534         to = '}';
00535     } else if (to == '\"') {
00536     } else {
00537         to = '\0';
00538     }
00539     for (char c = m_Input.PeekChar(); ; c = m_Input.PeekChar()) {
00540         if (to != '\"') {
00541             if (to != '}' && (c == '\n' || c == ',' || c == '}')) {
00542                 return;
00543             } else if (c == '\"' || c == '{') {
00544                 SkipAnyContent();
00545                 continue;
00546             }
00547         }
00548         if (c == to) {
00549             m_Input.SkipChar();
00550             if (c == '\n') {
00551                 SkipEndOfLine(c);
00552             }
00553             return;
00554         }
00555         if (c == '\"' || (c == '{' && to != '\"')) {
00556             SkipAnyContent();
00557             continue;
00558         }
00559         m_Input.SkipChar();
00560         if (c == '\n') {
00561             SkipEndOfLine(c);
00562         }
00563     }
00564 }
00565 
00566 void CObjectIStreamAsn::SkipAnyContentObject(void)
00567 {
00568     SkipAnyContent();
00569 }
00570 
00571 void CObjectIStreamAsn::ReadBitString(CBitString& obj)
00572 {
00573     obj.clear();
00574 #if BITSTRING_AS_VECTOR
00575 // CBitString is vector<bool>
00576     Expect('\'', true);
00577     string data;
00578     size_t reserve;
00579     const size_t step=128;
00580     data.reserve(reserve=step);
00581     bool hex=false;
00582     int c;
00583     for ( ; !hex; hex= c > 0x1) {
00584         c = GetHexChar();
00585         if (c < 0) {
00586             break;
00587         }
00588         data.append(1, char(c));
00589         if (--reserve == 0) {
00590             data.reserve(data.size() + (reserve=step));
00591         }
00592     }
00593     if (c<0 && !hex) {
00594         hex = m_Input.PeekChar() == 'H';
00595     }
00596     if (hex) {
00597         obj.reserve( data.size() * 4 );
00598         Uint1 byte;
00599         ITERATE( string, i, data) {
00600             byte = *i;
00601             for (Uint1 mask= 0x8; mask != 0; mask >>= 1) {
00602                 obj.push_back( (byte & mask) != 0 );
00603             }
00604         }
00605         if (c > 0) {
00606             obj.reserve(obj.size() + (reserve=step));
00607             for (c= GetHexChar(); c >= 0; c= GetHexChar()) {
00608                 byte = c;
00609                 for (Uint1 mask= 0x8; mask != 0; mask >>= 1) {
00610                     obj.push_back( (byte & mask) != 0 );
00611                     if (--reserve == 0) {
00612                         obj.reserve(obj.size() + (reserve=step));
00613                     }
00614                 }
00615             }
00616         }
00617         Expect('H');
00618     } else {
00619         obj.reserve( data.size() );
00620         ITERATE( string, i, data) {
00621             obj.push_back( *i != 0 );
00622         }
00623         Expect('B');
00624     }
00625     obj.reserve(obj.size());
00626 #else
00627     obj.resize(0);
00628     if (TopFrame().HasMemberId() && TopFrame().GetMemberId().IsCompressed()) {
00629         ReadCompressedBitString(obj);
00630         return;
00631     }
00632     Expect('\'', true);
00633     string data;
00634     size_t reserve;
00635     const size_t step=128;
00636     data.reserve(reserve=step);
00637     bool hex=false;
00638     int c;
00639     for ( ; !hex; hex= c > 0x1) {
00640         c = GetHexChar();
00641         if (c < 0) {
00642             break;
00643         }
00644         data.append(1, char(c));
00645         if (--reserve == 0) {
00646             data.reserve(data.size() + (reserve=step));
00647         }
00648     }
00649     if (c<0 && !hex) {
00650         hex = m_Input.PeekChar() == 'H';
00651     }
00652     CBitString::size_type len = 0;
00653     if (hex) {
00654         Uint1 byte;
00655         obj.resize(CBitString::size_type(4*data.size()));
00656         ITERATE( string, i, data) {
00657             byte = *i;
00658             if (byte) {
00659                 for (Uint1 mask= 0x8; mask != 0; mask >>= 1, ++len) {
00660                     if ((byte & mask) != 0) {
00661                         obj.set_bit(len);
00662                     }
00663                 }
00664             } else {
00665                 len += 4;
00666             }
00667         }
00668         if (c > 0) {
00669             for (c= GetHexChar(); c >= 0; c= GetHexChar()) {
00670                 obj.resize( 4 + obj.size());
00671                 byte = c;
00672                 if (byte) {
00673                     for (Uint1 mask= 0x8; mask != 0; mask >>= 1, ++len) {
00674                         if ((byte & mask) != 0) {
00675                             obj.set_bit(len);
00676                         }
00677                     }
00678                 } else {
00679                     len += 4;
00680                 }
00681             }
00682         }
00683         Expect('H');
00684     } else {
00685         obj.resize(CBitString::size_type(data.size()));
00686         ITERATE( string, i, data) {
00687             if ( *i != 0 ) {
00688                 obj.set_bit(len);
00689             }
00690             ++len;
00691         }
00692         Expect('B');
00693     }
00694     obj.resize(len);
00695 #endif
00696 }
00697 
00698 void CObjectIStreamAsn::SkipBitString(void)
00699 {
00700     SkipByteBlock();
00701 }
00702 
00703 string CObjectIStreamAsn::ReadFileHeader()
00704 {
00705     CTempString id = ReadTypeId(SkipWhiteSpace());
00706     string s(id);
00707     if ( SkipWhiteSpace() == ':' && 
00708          m_Input.PeekCharNoEOF(1) == ':' &&
00709          m_Input.PeekCharNoEOF(2) == '=' ) {
00710         m_Input.SkipChars(3);
00711     }
00712     else
00713         ThrowError(fFormatError, "'::=' expected");
00714     return s;
00715 }
00716 
00717 TEnumValueType CObjectIStreamAsn::ReadEnum(const CEnumeratedTypeValues& values)
00718 {
00719     // not integer
00720     CTempString id = ReadLCaseId(SkipWhiteSpace());
00721     if ( !id.empty() ) {
00722         // enum element by name
00723         return values.FindValue(id);
00724     }
00725     // enum element by value
00726     TEnumValueType value = m_Input.GetInt4();
00727     if ( !values.IsInteger() ) // check value
00728         values.FindName(value, false);
00729     
00730     return value;
00731 }
00732 
00733 bool CObjectIStreamAsn::ReadBool(void)
00734 {
00735     switch ( SkipWhiteSpace() ) {
00736     case 'T':
00737         if ( m_Input.PeekCharNoEOF(1) == 'R' &&
00738              m_Input.PeekCharNoEOF(2) == 'U' &&
00739              m_Input.PeekCharNoEOF(3) == 'E' &&
00740              !IdChar(m_Input.PeekCharNoEOF(4)) ) {
00741             m_Input.SkipChars(4);
00742             return true;
00743         }
00744         break;
00745     case 'F':
00746         if ( m_Input.PeekCharNoEOF(1) == 'A' &&
00747              m_Input.PeekCharNoEOF(2) == 'L' &&
00748              m_Input.PeekCharNoEOF(3) == 'S' &&
00749              m_Input.PeekCharNoEOF(4) == 'E' &&
00750              !IdChar(m_Input.PeekCharNoEOF(5)) ) {
00751             m_Input.SkipChars(5);
00752             return false;
00753         }
00754         break;
00755     }
00756     ThrowError(fFormatError, "TRUE or FALSE expected");
00757     return false;
00758 }
00759 
00760 char CObjectIStreamAsn::ReadChar(void)
00761 {
00762     string s;
00763     ReadString(s);
00764     if ( s.size() != 1 ) {
00765         ThrowError(fFormatError,
00766                    "\"" + s + "\": one char string expected");
00767     }
00768     return s[0];
00769 }
00770 
00771 Int4 CObjectIStreamAsn::ReadInt4(void)
00772 {
00773     SkipWhiteSpace();
00774     return m_Input.GetInt4();
00775 }
00776 
00777 Uint4 CObjectIStreamAsn::ReadUint4(void)
00778 {
00779     SkipWhiteSpace();
00780     return m_Input.GetUint4();
00781 }
00782 
00783 Int8 CObjectIStreamAsn::ReadInt8(void)
00784 {
00785     SkipWhiteSpace();
00786     return m_Input.GetInt8();
00787 }
00788 
00789 Uint8 CObjectIStreamAsn::ReadUint8(void)
00790 {
00791     SkipWhiteSpace();
00792     return m_Input.GetUint8();
00793 }
00794 
00795 double CObjectIStreamAsn::ReadDouble(void)
00796 {
00797     double result = 0;
00798     if (PeekChar(true) != '{') {
00799         CTempString tmp( ScanEndOfId(true) );
00800         if (NStr::strncasecmp(tmp.data(), "PLUS-INFINITY", 13) == 0) {
00801             return HUGE_VAL;
00802         } else if (NStr::strncasecmp(tmp.data(),"MINUS-INFINITY", 14) == 0) {
00803             return -HUGE_VAL;
00804         } else if (NStr::strncasecmp(tmp.data(),"NOT-A-NUMBER", 12) == 0) {
00805         return HUGE_VAL/HUGE_VAL; /* NCBI_FAKE_WARNING */
00806         }
00807         char* endptr;
00808         return NStr::StringToDoublePosix( string(tmp).c_str(), &endptr, NStr::fDecimalPosixFinite );
00809     }
00810     Expect('{', true);
00811     bool is_negative = PeekChar(true) == '-';
00812     CTempString mantissaStr = ReadNumber();
00813     size_t mantissaLength = mantissaStr.size();
00814     char buffer[128];
00815     if ( mantissaLength >= sizeof(buffer) - 1 )
00816         ThrowError(fOverflow, "buffer overflow");
00817     memcpy(buffer, mantissaStr.data(), mantissaLength);
00818     buffer[mantissaLength] = '\0';
00819     char* endptr;
00820     double mantissa = NStr::StringToDoublePosix(buffer, &endptr);
00821     if ( *endptr != 0 )
00822         ThrowError(fFormatError, "bad double in line "
00823             + NStr::SizetToString(m_Input.GetLine()));
00824     Expect(',', true);
00825     unsigned base = ReadUint4();
00826     Expect(',', true);
00827     int exp = ReadInt4();
00828     Expect('}', true);
00829     if ( base != 2 && base != 10 ) {
00830         ThrowError(fFormatError, "illegal REAL base (must be 2 or 10)");
00831     }
00832     if (mantissa == 0.) {
00833         return mantissa;
00834     }
00835     if (is_negative) {
00836         mantissa = -mantissa;
00837     }
00838 
00839     if ( base == 10 ) {
00840         result = mantissa * pow((double)10.0, exp);
00841     } else {
00842         result = ldexp( mantissa, exp);
00843     }
00844 
00845     if (result >= 0 && result <= DBL_MIN) {
00846         result = DBL_MIN;
00847     } else if (!finite(result)) {
00848         result = DBL_MAX;
00849     }
00850     return is_negative ? -result : result;
00851 }
00852 
00853 void CObjectIStreamAsn::BadStringChar(size_t startLine, char c)
00854 {
00855     ThrowError(fFormatError,
00856                "bad char in string starting at line "+
00857                NStr::SizetToString(startLine)+": "+
00858                NStr::IntToString(c));
00859 }
00860 
00861 void CObjectIStreamAsn::UnendedString(size_t startLine)
00862 {
00863     ThrowError(fFormatError,
00864                "unclosed string starts at line "+
00865                NStr::SizetToString(startLine));
00866 }
00867 
00868 
00869 inline
00870 void CObjectIStreamAsn::AppendStringData(string& s,
00871                                          size_t count,
00872                                          EFixNonPrint fix_method,
00873                                          size_t line)
00874 {
00875     const char* data = m_Input.GetCurrentPos();
00876     if ( fix_method != eFNP_Allow ) {
00877         size_t done = 0;
00878         for ( size_t i = 0; i < count; ++i ) {
00879             char c = data[i];
00880             if ( !GoodVisibleChar(c) ) {
00881                 if ( i > done ) {
00882                     s.append(data + done, i - done);
00883                 }
00884                 FixVisibleChar(c, fix_method, this, string(data,count));
00885                 s += c;
00886                 done = i + 1;
00887             }
00888         }
00889         if ( done < count ) {
00890             s.append(data + done, count - done);
00891         }
00892     }
00893     else {
00894         s.append(data, count);
00895     }
00896     if ( count > 0 ) {
00897         m_Input.SkipChars(count);
00898     }
00899 }
00900 
00901 
00902 void CObjectIStreamAsn::AppendLongStringData(string& s,
00903                                              size_t count,
00904                                              EFixNonPrint fix_method,
00905                                              size_t line)
00906 {
00907     // Reserve extra-space to reduce heap reallocation
00908     if ( s.empty() ) {
00909         s.reserve(count*2);
00910     }
00911     else if ( s.capacity() < (s.size()+1)*1.1 ) {
00912         s.reserve(s.size()*2);
00913     }
00914     AppendStringData(s, count, fix_method, line);
00915 }
00916 
00917 
00918 void CObjectIStreamAsn::ReadStringValue(string& s, EFixNonPrint fix_method)
00919 {
00920     Expect('\"', true);
00921     size_t startLine = m_Input.GetLine();
00922     size_t i = 0;
00923     s.erase();
00924     try {
00925         for (;;) {
00926             char c = m_Input.PeekChar(i);
00927             switch ( c ) {
00928             case '\r':
00929             case '\n':
00930                 // flush string
00931                 AppendLongStringData(s, i, fix_method, startLine);
00932                 m_Input.SkipChar(); // '\r' or '\n'
00933                 i = 0;
00934                 // skip end of line
00935                 SkipEndOfLine(c);
00936                 break;
00937             case '\"':
00938                 s.reserve(s.size() + i);
00939                 AppendStringData(s, i, fix_method, startLine);
00940                 m_Input.SkipChar(); // quote
00941                 if ( m_Input.PeekCharNoEOF() != '\"' ) {
00942                     // end of string
00943                     return;
00944                 }
00945                 else {
00946                     // double quote -> one quote
00947                     i = 1;
00948                 }
00949                 break;
00950             default:
00951                 // ok: append char
00952                 if ( ++i == 128 ) {
00953                     // too long string -> flush it
00954                     AppendLongStringData(s, i, fix_method, startLine);
00955                     i = 0;
00956                 }
00957                 break;
00958             }
00959         }
00960     }
00961     catch ( CEofException& ) {
00962         SetFailFlags(fEOF);
00963         UnendedString(startLine);
00964         throw;
00965     }
00966 }
00967 
00968 void CObjectIStreamAsn::ReadString(string& s, EStringType type)
00969 {
00970     ReadStringValue(s, type == eStringTypeUTF8? eFNP_Allow: x_FixCharsMethod());
00971 }
00972 
00973 void CObjectIStreamAsn::SkipBool(void)
00974 {
00975     switch ( SkipWhiteSpace() ) {
00976     case 'T':
00977         if ( m_Input.PeekCharNoEOF(1) == 'R' &&
00978              m_Input.PeekCharNoEOF(2) == 'U' &&
00979              m_Input.PeekCharNoEOF(3) == 'E' &&
00980              !IdChar(m_Input.PeekCharNoEOF(4)) ) {
00981             m_Input.SkipChars(4);
00982             return;
00983         }
00984         break;
00985     case 'F':
00986         if ( m_Input.PeekCharNoEOF(1) == 'A' &&
00987              m_Input.PeekCharNoEOF(2) == 'L' &&
00988              m_Input.PeekCharNoEOF(3) == 'S' &&
00989              m_Input.PeekCharNoEOF(4) == 'E' &&
00990              !IdChar(m_Input.PeekCharNoEOF(5)) ) {
00991             m_Input.SkipChars(5);
00992             return;
00993         }
00994         break;
00995     }
00996     ThrowError(fFormatError, "TRUE or FALSE expected");
00997 }
00998 
00999 void CObjectIStreamAsn::SkipChar(void)
01000 {
01001     // TODO: check string length to be 1
01002     SkipString();
01003 }
01004 
01005 void CObjectIStreamAsn::SkipSNumber(void)
01006 {
01007     size_t i;
01008     char c = SkipWhiteSpace();
01009     switch ( c ) {
01010     case '-':
01011     case '+':
01012         c = m_Input.PeekChar(1);
01013         // next char
01014         i = 2;
01015         break;
01016     default:
01017         // next char
01018         i = 1;
01019         break;
01020     }
01021     if ( c < '0' || c > '9' ) {
01022         ThrowError(fFormatError, "bad signed integer in line "
01023             + NStr::SizetToString(m_Input.GetLine()));
01024     }
01025     while ( (c = m_Input.PeekChar(i)) >= '0' && c <= '9' ) {
01026         ++i;
01027     }
01028     m_Input.SkipChars(i);
01029 }
01030 
01031 void CObjectIStreamAsn::SkipUNumber(void)
01032 {
01033     size_t i;
01034     char c = SkipWhiteSpace();
01035     switch ( c ) {
01036     case '+':
01037         c = m_Input.PeekChar(1);
01038         // next char
01039         i = 2;
01040         break;
01041     default:
01042         // next char
01043         i = 1;
01044         break;
01045     }
01046     if ( c < '0' || c > '9' ) {
01047         ThrowError(fFormatError, "bad unsigned integer in line "
01048             + NStr::SizetToString(m_Input.GetLine()));
01049     }
01050     while ( (c = m_Input.PeekCharNoEOF(i)) >= '0' && c <= '9' ) {
01051         ++i;
01052     }
01053     m_Input.SkipChars(i);
01054 }
01055 
01056 void CObjectIStreamAsn::SkipFNumber(void)
01057 {
01058     if (PeekChar(true) != '{') {
01059         ScanEndOfId(true);
01060         return;
01061     }
01062     Expect('{', true);
01063     SkipSNumber();
01064     Expect(',', true);
01065     unsigned base = ReadUint4();
01066     Expect(',', true);
01067     SkipSNumber();
01068     Expect('}', true);
01069     if ( base != 2 && base != 10 )
01070         ThrowError(fFormatError, "illegal REAL base (must be 2 or 10)");
01071 }
01072 
01073 void CObjectIStreamAsn::SkipString(EStringType type)
01074 {
01075     Expect('\"', true);
01076     size_t startLine = m_Input.GetLine();
01077     size_t i = 0;
01078     try {
01079         for (;;) {
01080             char c = m_Input.PeekChar(i);
01081             switch ( c ) {
01082             case '\r':
01083             case '\n':
01084                 // flush string
01085                 m_Input.SkipChars(i + 1);
01086                 i = 0;
01087                 // skip end of line
01088                 SkipEndOfLine(c);
01089                 break;
01090             case '\"':
01091                 if ( m_Input.PeekChar(i + 1) == '\"' ) {
01092                     // double quote -> one quote
01093                     m_Input.SkipChars(i + 2);
01094                     i = 0;
01095                 }
01096                 else {
01097                     // end of string
01098                     m_Input.SkipChars(i + 1);
01099                     return;
01100                 }
01101                 break;
01102             default:
01103                 if (type == eStringTypeVisible) {
01104                     if ( !GoodVisibleChar(c) ) {
01105                         FixVisibleChar(c, x_FixCharsMethod(), this, kEmptyStr);
01106                     }
01107                 }
01108                 // ok: skip char
01109                 if ( ++i == 128 ) {
01110                     // too long string -> flush it
01111                     m_Input.SkipChars(i);
01112                     i = 0;
01113                 }
01114                 break;
01115             }
01116         }
01117     }
01118     catch ( CEofException& ) {
01119         SetFailFlags(fEOF);
01120         UnendedString(startLine);
01121         throw;
01122     }
01123 }
01124 
01125 void CObjectIStreamAsn::SkipNull(void)
01126 {
01127     if ( SkipWhiteSpace() == 'N' &&
01128          m_Input.PeekCharNoEOF(1) == 'U' &&
01129          m_Input.PeekCharNoEOF(2) == 'L' &&
01130          m_Input.PeekCharNoEOF(3) == 'L' &&
01131          !IdChar(m_Input.PeekCharNoEOF(4)) ) {
01132         m_Input.SkipChars(4);
01133         return;
01134     }
01135     ThrowError(fFormatError, "NULL expected");
01136 }
01137 
01138 void CObjectIStreamAsn::SkipByteBlock(void)
01139 {
01140     Expect('\'', true);
01141     for ( ;; ) {
01142         char c = GetChar();
01143         if ( c >= '0' && c <= '9' ) {
01144             continue;
01145         }
01146         else if ( c >= 'A' && c <= 'F' ) {
01147             continue;
01148         }
01149         else if ( c >= 'a' && c <= 'f' ) {
01150             continue;
01151         }
01152         else if ( c == '\'' ) {
01153             break;
01154         }
01155         else if ( c == '\r' || c == '\n' ) {
01156             SkipEndOfLine(c);
01157         }
01158         else {
01159             m_Input.UngetChar(c);
01160             ThrowError(fFormatError, "bad char in octet string: #"
01161                 + NStr::IntToString(c));
01162         }
01163     }
01164     Expect('H', 'B', true);
01165 }
01166 
01167 void CObjectIStreamAsn::StartBlock(void)
01168 {
01169     Expect('{', true);
01170     m_BlockStart = true;
01171 }
01172 
01173 bool CObjectIStreamAsn::NextElement(void)
01174 {
01175     char c = SkipWhiteSpace();
01176     if ( m_BlockStart ) {
01177         // first element
01178         m_BlockStart = false;
01179         return c != '}';
01180     }
01181     else {
01182         // next element
01183         if ( c == ',' ) {
01184             m_Input.SkipChar();
01185             return true;
01186         }
01187         else if ( c != '}' )
01188             ThrowError(fFormatError, "',' or '}' expected");
01189         return false;
01190     }
01191 }
01192 
01193 void CObjectIStreamAsn::EndBlock(void)
01194 {
01195     Expect('}');
01196 }
01197 
01198 void CObjectIStreamAsn::BeginContainer(const CContainerTypeInfo* /*cType*/)
01199 {
01200     StartBlock();
01201 }
01202 
01203 void CObjectIStreamAsn::EndContainer(void)
01204 {
01205     EndBlock();
01206 }
01207 
01208 bool CObjectIStreamAsn::BeginContainerElement(TTypeInfo /*elementType*/)
01209 {
01210     return NextElement();
01211 }
01212 
01213 #ifdef VIRTUAL_MID_LEVEL_IO
01214 void CObjectIStreamAsn::ReadContainer(const CContainerTypeInfo* contType,
01215                                       TObjectPtr contPtr)
01216 {
01217     StartBlock();
01218     
01219     BEGIN_OBJECT_FRAME(eFrameArrayElement);
01220 
01221     CContainerTypeInfo::CIterator iter;
01222     bool old_element = contType->InitIterator(iter, contPtr);
01223     TTypeInfo elementType = contType->GetElementType();
01224     while ( NextElement() ) {
01225         if ( old_element ) {
01226             elementType->ReadData(*this, contType->GetElementPtr(iter));
01227             old_element = contType->NextElement(iter);
01228         }
01229         else {
01230             contType->AddElement(contPtr, *this);
01231         }
01232     }
01233     if ( old_element ) {
01234         contType->EraseAllElements(iter);
01235     }
01236 
01237     END_OBJECT_FRAME();
01238 
01239     EndBlock();
01240 }
01241 
01242 void CObjectIStreamAsn::SkipContainer(const CContainerTypeInfo* contType)
01243 {
01244     StartBlock();
01245 
01246     TTypeInfo elementType = contType->GetElementType();
01247     BEGIN_OBJECT_FRAME(eFrameArrayElement);
01248 
01249     while ( NextElement() ) {
01250         SkipObject(elementType);
01251     }
01252 
01253     END_OBJECT_FRAME();
01254 
01255     EndBlock();
01256 }
01257 #endif
01258 
01259 void CObjectIStreamAsn::BeginClass(const CClassTypeInfo* /*classInfo*/)
01260 {
01261     StartBlock();
01262 }
01263 
01264 void CObjectIStreamAsn::EndClass(void)
01265 {
01266     EndBlock();
01267 }
01268 
01269 void CObjectIStreamAsn::UnexpectedMember(const CTempString& id,
01270                                          const CItemsInfo& items)
01271 {
01272     string message =
01273         "\""+string(id)+"\": unexpected member, should be one of: ";
01274     for ( CItemsInfo::CIterator i(items); i.Valid(); ++i ) {
01275         message += '\"' + items.GetItemInfo(i)->GetId().ToString() + "\" ";
01276     }
01277     ThrowError(fFormatError, message);
01278 }
01279 
01280 TMemberIndex
01281 CObjectIStreamAsn::BeginClassMember(const CClassTypeInfo* classType)
01282 {
01283     if ( !NextElement() )
01284         return kInvalidMember;
01285 
01286     CTempString id = ReadMemberId(SkipWhiteSpace());
01287     TMemberIndex index = GetMemberIndex(classType, id);
01288     if ( index == kInvalidMember ) {
01289         if (CanSkipUnknownMembers()) {
01290             SetFailFlags(fUnknownValue);
01291             SkipAnyContent();
01292             return BeginClassMember(classType);
01293         } else {
01294             UnexpectedMember(id, classType->GetMembers());
01295         }
01296     }
01297     return index;
01298 }
01299 
01300 TMemberIndex
01301 CObjectIStreamAsn::BeginClassMember(const CClassTypeInfo* classType,
01302                                     TMemberIndex pos)
01303 {
01304     if ( !NextElement() )
01305         return kInvalidMember;
01306 
01307     CTempString id = ReadMemberId(SkipWhiteSpace());
01308     TMemberIndex index = GetMemberIndex(classType, id, pos);
01309     if ( index == kInvalidMember ) {
01310         if (CanSkipUnknownMembers()) {
01311             SetFailFlags(fUnknownValue);
01312             SkipAnyContent();
01313             return BeginClassMember(classType, pos);
01314         } else {
01315             UnexpectedMember(id, classType->GetMembers());
01316         }
01317     }
01318     return index;
01319 }
01320 
01321 #ifdef VIRTUAL_MID_LEVEL_IO
01322 void CObjectIStreamAsn::ReadClassRandom(const CClassTypeInfo* classType,
01323                                         TObjectPtr classPtr)
01324 {
01325     BEGIN_OBJECT_FRAME3(eFrameClass, classType, classPtr);
01326     StartBlock();
01327     
01328     ReadClassRandomContentsBegin(classType);
01329 
01330     TMemberIndex index;
01331     while ( (index = BeginClassMember(classType)) != kInvalidMember ) {
01332         ReadClassRandomContentsMember(classPtr);
01333     }
01334 
01335     ReadClassRandomContentsEnd();
01336     
01337     EndBlock();
01338     END_OBJECT_FRAME();
01339 }
01340 
01341 void CObjectIStreamAsn::ReadClassSequential(const CClassTypeInfo* classType,
01342                                             TObjectPtr classPtr)
01343 {
01344     BEGIN_OBJECT_FRAME3(eFrameClass, classType, classPtr);
01345     StartBlock();
01346     
01347     ReadClassSequentialContentsBegin(classType);
01348 
01349     TMemberIndex index;
01350     while ( (index = BeginClassMember(classType,*pos)) != kInvalidMember ) {
01351         ReadClassSequentialContentsMember(classPtr);
01352     }
01353 
01354     ReadClassSequentialContentsEnd(classPtr);
01355     
01356     EndBlock();
01357     END_OBJECT_FRAME();
01358 }
01359 
01360 void CObjectIStreamAsn::SkipClassRandom(const CClassTypeInfo* classType)
01361 {
01362     BEGIN_OBJECT_FRAME2(eFrameClass, classType);
01363     StartBlock();
01364     
01365     SkipClassRandomContentsBegin(classType);
01366 
01367     TMemberIndex index;
01368     while ( (index = BeginClassMember(classType)) != kInvalidMember ) {
01369         SkipClassRandomContentsMember();
01370     }
01371 
01372     SkipClassRandomContentsEnd();
01373     
01374     EndBlock();
01375     END_OBJECT_FRAME();
01376 }
01377 
01378 void CObjectIStreamAsn::SkipClassSequential(const CClassTypeInfo* classType)
01379 {
01380     BEGIN_OBJECT_FRAME2(eFrameClass, classType);
01381     StartBlock();
01382     
01383     SkipClassSequentialContentsBegin(classType);
01384 
01385     TMemberIndex index;
01386     while ( (index = BeginClassMember(classType,*pos)) != kInvalidMember ) {
01387         SkipClassSequentialContentsMember();
01388     }
01389 
01390     SkipClassSequentialContentsEnd();
01391     
01392     EndBlock();
01393     END_OBJECT_FRAME();
01394 }
01395 #endif
01396 
01397 void CObjectIStreamAsn::BeginChoice(const CChoiceTypeInfo* choiceType)
01398 {
01399     if (choiceType->GetVariantInfo(kFirstMemberIndex)->GetId().IsAttlist()) {
01400         TopFrame().SetNotag();
01401         StartBlock();
01402     }
01403     m_BlockStart = true;
01404 }
01405 void CObjectIStreamAsn::EndChoice(void)
01406 {
01407     if (TopFrame().GetNotag()) {
01408         SkipWhiteSpace();
01409         EndBlock();
01410     }
01411     m_BlockStart = false;
01412 }
01413 
01414 TMemberIndex CObjectIStreamAsn::BeginChoiceVariant(const CChoiceTypeInfo* choiceType)
01415 {
01416     bool skipname = !m_BlockStart;
01417     if ( !NextElement() )
01418         return kInvalidMember;
01419     CTempString id = ReadMemberId(SkipWhiteSpace());
01420     if (skipname) {
01421         id = ReadMemberId(SkipWhiteSpace());
01422     }
01423     if ( id.empty() )
01424         ThrowError(fFormatError, "choice variant id expected");
01425 
01426     TMemberIndex index = GetChoiceIndex(choiceType, id);
01427     if ( index == kInvalidMember ) {
01428         if (CanSkipUnknownVariants()) {
01429             SetFailFlags(fUnknownValue);
01430         } else {
01431             UnexpectedMember(id, choiceType->GetVariants());
01432         }
01433     }
01434 
01435     return index;
01436 }
01437 
01438 void CObjectIStreamAsn::BeginBytes(ByteBlock& )
01439 {
01440     Expect('\'', true);
01441 }
01442 
01443 int CObjectIStreamAsn::GetHexChar(void)
01444 {
01445     for ( ;; ) {
01446         char c = GetChar();
01447         if ( c >= '0' && c <= '9' ) {
01448             return c - '0';
01449         }
01450         else if ( c >= 'A' && c <= 'F' ) {
01451             return c - 'A' + 10;
01452         }
01453         else if ( c >= 'a' && c <= 'f' ) {
01454             return c - 'a' + 10;
01455         }
01456         switch ( c ) {
01457         case '\'':
01458             return -1;
01459         case '\r':
01460         case '\n':
01461             SkipEndOfLine(c);
01462             break;
01463         default:
01464             m_Input.UngetChar(c);
01465             ThrowError(fFormatError, "bad char in octet string: #"
01466                 + NStr::IntToString(c));
01467         }
01468     }
01469 }
01470 
01471 size_t CObjectIStreamAsn::ReadBytes(ByteBlock& block,
01472                                     char* dst, size_t length)
01473 {
01474     size_t count = 0;
01475     while ( length-- > 0 ) {
01476         int c1 = GetHexChar();
01477         if ( c1 < 0 ) {
01478             block.EndOfBlock();
01479             return count;
01480         }
01481         int c2 = GetHexChar();
01482         if ( c2 < 0 ) {
01483             *dst++ = c1 << 4;
01484             count++;
01485             block.EndOfBlock();
01486             return count;
01487         }
01488         else {
01489             *dst++ = (c1 << 4) | c2;
01490             count++;
01491         }
01492     }
01493     return count;
01494 }
01495 
01496 void CObjectIStreamAsn::EndBytes(const ByteBlock& )
01497 {
01498     Expect('H');
01499 }
01500 
01501 void CObjectIStreamAsn::BeginChars(CharBlock& )
01502 {
01503     Expect('\"', true);
01504 }
01505 
01506 size_t CObjectIStreamAsn::ReadChars(CharBlock& block,
01507                                     char* dst, size_t length)
01508 {
01509     size_t count = 0;
01510     try {
01511         while (length-- > 0) {
01512             char c = m_Input.GetChar();
01513             switch ( c ) {
01514             case '\r':
01515             case '\n':
01516                 break;
01517             case '\"':
01518                 if ( m_Input.PeekCharNoEOF() == '\"' ) {
01519                     m_Input.SkipChar();
01520                     dst[count++] = c;
01521                 }
01522                 else {
01523                     // end of string
01524                     // Check the string for non-printable characters
01525                     EFixNonPrint fix_method = x_FixCharsMethod();
01526                     if ( fix_method != eFNP_Allow ) {
01527                         for (size_t i = 0;  i < count;  i++) {
01528                             if ( !GoodVisibleChar(dst[i]) ) {
01529                                 FixVisibleChar(dst[i], fix_method,
01530                                     this, string(dst, count));
01531                             }
01532                         }
01533                     }
01534                     block.EndOfBlock();
01535                     return count;
01536                 }
01537                 break;
01538             default:
01539                 // ok: append char
01540                 {
01541                     dst[count++] = c;
01542                 }
01543                 break;
01544             }
01545         }
01546     }
01547     catch ( CEofException& ) {
01548         SetFailFlags(fEOF);
01549         UnendedString(m_Input.GetLine());
01550         throw;
01551     }
01552     return count;
01553 }
01554 
01555 CObjectIStream::EPointerType CObjectIStreamAsn::ReadPointerType(void)
01556 {
01557     switch ( PeekChar(true) ) {
01558     case 'N':
01559         if ( m_Input.PeekCharNoEOF(1) == 'U' &&
01560              m_Input.PeekCharNoEOF(2) == 'L' &&
01561              m_Input.PeekCharNoEOF(3) == 'L' &&
01562              !IdChar(m_Input.PeekCharNoEOF(4)) ) {
01563             // "NULL"
01564             m_Input.SkipChars(4);
01565             return eNullPointer;
01566         }
01567         break;
01568     case '@':
01569         m_Input.SkipChar();
01570         return eObjectPointer;
01571     case ':':
01572         m_Input.SkipChar();
01573         return eOtherPointer;
01574     default:
01575         break;
01576     }
01577     return eThisPointer;
01578 }
01579 
01580 CObjectIStream::TObjectIndex CObjectIStreamAsn::ReadObjectPointer(void)
01581 {
01582     if ( sizeof(TObjectIndex) == sizeof(Int4) )
01583         return ReadInt4();
01584     else if ( sizeof(TObjectIndex) == sizeof(Int8) )
01585         return TObjectIndex(ReadInt8());
01586     else
01587         ThrowError(fIllegalCall, "invalid size of TObjectIndex:"
01588             " must be either sizeof(Int4) or sizeof(Int8)");
01589     return 0;
01590 }
01591 
01592 string CObjectIStreamAsn::ReadOtherPointer(void)
01593 {
01594     return ReadTypeId(SkipWhiteSpace());
01595 }
01596 
01597 END_NCBI_SCOPE
Modified on Sun Mar 01 14:31:17 2015 by modify_doxy.py rev. 426318