src/corelib/ncbistre.cpp

Go to the documentation of this file.
00001 /* $Id: ncbistre.cpp 151811 2009-02-07 02:24:24Z lavr $
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:  Denis Vakatov
00027  *
00028  * File Description:
00029  *   NCBI C++ stream class wrappers
00030  *   Triggering between "new" and "old" C++ stream libraries
00031  *
00032  */
00033 
00034 #include <ncbi_pch.hpp>
00035 #include <corelib/ncbistd.hpp>
00036 #include <corelib/ncbistre.hpp>
00037 #include <corelib/stream_utils.hpp>
00038 #if defined(NCBI_OS_UNIX)
00039 #  include <unistd.h>
00040 #endif
00041 
00042 
00043 BEGIN_NCBI_SCOPE
00044 
00045 
00046 CNcbiIstream& NcbiGetline(CNcbiIstream& is, string& str, const string& delims)
00047 {
00048     CT_INT_TYPE ch;
00049     char        buf[1024];
00050     SIZE_TYPE   pos = 0;
00051 
00052     str.erase();
00053 
00054     IOS_BASE::fmtflags f = is.flags();
00055     is.unsetf(IOS_BASE::skipws);
00056 #ifdef NO_PUBSYNC
00057     if ( !is.ipfx(1) ) {
00058         is.flags(f);
00059         return is;
00060     }
00061 #else
00062     CNcbiIstream::sentry s(is);
00063     if ( !s ) {
00064         is.clear(NcbiFailbit | is.rdstate());
00065         is.flags(f);
00066         return is;
00067     }
00068 #endif
00069 
00070     SIZE_TYPE end = str.max_size();
00071     SIZE_TYPE i = 0;
00072     for (ch = is.rdbuf()->sbumpc();  !CT_EQ_INT_TYPE(ch, CT_EOF);
00073          ch = is.rdbuf()->sbumpc()) {
00074         i++;
00075         SIZE_TYPE delim_pos = delims.find(CT_TO_CHAR_TYPE(ch));
00076         if (delim_pos != NPOS) {
00077             // Special case -- if two different delimiters are back to
00078             // back and in the same order as in delims, treat them as
00079             // a single delimiter (necessary for correct handling of
00080             // DOS-style CRLF endings).
00081             CT_INT_TYPE next = is.rdbuf()->sgetc();
00082             if (!CT_EQ_INT_TYPE(next, CT_EOF)
00083                 &&  delims.find(CT_TO_CHAR_TYPE(next), delim_pos + 1) != NPOS){
00084                 is.rdbuf()->sbumpc();
00085             }
00086             break;
00087         }
00088         if (i == end) {
00089             is.clear(NcbiFailbit | is.rdstate());      
00090             break;
00091         }
00092 
00093         buf[pos++] = CT_TO_CHAR_TYPE(ch);
00094         if (pos == sizeof(buf)) {
00095             str.append(buf, pos);
00096             pos = 0;
00097         }
00098     }
00099     str.append(buf, pos);
00100     if (CT_EQ_INT_TYPE(ch, EOF)) 
00101         is.clear(NcbiEofbit | is.rdstate());      
00102     if ( !i )
00103         is.clear(NcbiFailbit | is.rdstate());      
00104 
00105 #ifdef NO_PUBSYNC
00106     is.isfx();
00107 #endif
00108 
00109     is.flags(f);
00110     return is;
00111 }
00112 
00113 
00114 #ifdef NCBI_COMPILER_GCC
00115 #  if NCBI_COMPILER_VERSION < 300
00116 #    define NCBI_COMPILER_GCC29x
00117 #  endif
00118 #endif
00119 
00120 extern CNcbiIstream& NcbiGetline(CNcbiIstream& is, string& str, char delim)
00121 {
00122 #if defined(NCBI_USE_OLD_IOSTREAM)
00123     return NcbiGetline(is, str, string(1, delim));
00124 #elif defined(NCBI_COMPILER_GCC29x)
00125     // The code below is normally somewhat faster than this call,
00126     // which typically appends one character at a time to str;
00127     // however, it blows up when built with some GCC versions.
00128     return getline(is, str, delim);
00129 #else
00130     char buf[1024];
00131     str.erase();
00132     while (is.good()) {
00133         CT_INT_TYPE nextc = is.get();
00134         if (CT_EQ_INT_TYPE(nextc, CT_EOF) 
00135             ||  CT_EQ_INT_TYPE(nextc, CT_TO_INT_TYPE(delim))) {
00136             break;
00137         }
00138         is.putback(nextc);
00139         is.get(buf, sizeof(buf), delim);
00140         str.append(buf, is.gcount());
00141     }
00142     if (str.empty()  &&  is.eof()) {
00143         is.setstate(NcbiFailbit);
00144     }
00145     return is;
00146 #endif
00147 }
00148 
00149 
00150 // Platform-specific EndOfLine
00151 const char* Endl(void)
00152 {
00153 #if defined(NCBI_OS_MSWIN)
00154     static const char s_Endl[] = "\r\n";
00155 #else /* assume UNIX-like EOLs */
00156     static const char s_Endl[] = "\n";
00157 #endif
00158     return s_Endl;
00159 }
00160 
00161 
00162 // Get the next line taking into account platform specifics of End-of-Line
00163 CNcbiIstream& NcbiGetlineEOL(CNcbiIstream& is, string& str)
00164 {
00165 #if defined(NCBI_OS_MSWIN)
00166     NcbiGetline(is, str, '\n');
00167     if (!str.empty()  &&  str[str.length()-1] == '\r')
00168         str.resize(str.length() - 1);
00169 #elif defined(NCBI_OS_DARWIN)
00170     NcbiGetline(is, str, "\r\n");
00171 #else /* assume UNIX-like EOLs */
00172     NcbiGetline(is, str, '\n');
00173 #endif
00174     // special case -- an empty line
00175     if (is.fail()  &&  !is.eof()  &&  !is.gcount()  &&  str.empty())
00176         is.clear(is.rdstate() & ~NcbiFailbit);
00177     return is;
00178 }
00179 
00180 
00181 bool NcbiStreamCopy(CNcbiOstream& os, CNcbiIstream& is)
00182 {
00183     if (!is.good())
00184         return false;
00185 #ifndef NCBI_COMPILER_GCC
00186     os << is.rdbuf();
00187 #elif   NCBI_COMPILER_VERSION <= 330
00188     // GCC stdlib++ version <= 3.3.0 has a bug in implementation of streamcopy,
00189     // which wrongly assumes that showmanyc() (which is called when no read
00190     // position is available for in_avail()) returns the number of bytes that
00191     // have been placed in the buffer, so it tries to read right off gptr()
00192     // that many bytes, causing bound conditions (ending up with SEGV).
00193     do {
00194         char buf[4096];
00195         is.read(buf, sizeof(buf));
00196         streamsize count = is.gcount();
00197         if (!count)
00198             break;
00199         if (!os.write(buf, count))
00200             break;
00201     } while (is.good());
00202 #else
00203     os << is.rdbuf();
00204 #endif
00205     if (!os.good())
00206         return false;
00207     os.flush();
00208     if (!os.good())
00209         return false;
00210     if (!CT_EQ_INT_TYPE(is.peek(), CT_EOF)) {
00211         os.clear(NcbiFailbit);
00212         return false;
00213     }
00214     return true;
00215 }
00216 
00217 
00218 CNcbiOstrstreamToString::operator string(void) const
00219 {
00220     SIZE_TYPE length = m_Out.pcount();
00221     if ( length == 0 )
00222         return string();
00223     const char* str = m_Out.str();
00224     m_Out.freeze(false);
00225     return string(str, length);
00226 }
00227 
00228 
00229 CNcbiOstream& operator<<(CNcbiOstream& out, const CTempString& str)
00230 {
00231     return out.write(str.data(), str.length());
00232 }
00233 
00234 
00235 CNcbiOstream& operator<<(CNcbiOstream& out, CUpcaseStringConverter s)
00236 {
00237     ITERATE ( string, c, s.m_String ) {
00238         out.put(char(toupper((unsigned char)(*c))));
00239     }
00240     return out;
00241 }
00242 
00243 
00244 CNcbiOstream& operator<<(CNcbiOstream& out, CLocaseStringConverter s)
00245 {
00246     ITERATE ( string, c, s.m_String ) {
00247         out.put(char(tolower((unsigned char)(*c))));
00248     }
00249     return out;
00250 }
00251 
00252 
00253 CNcbiOstream& operator<<(CNcbiOstream& out, CUpcaseCharPtrConverter s)
00254 {
00255     for ( const char* c = s.m_String; *c; ++c ) {
00256         out.put(char(toupper((unsigned char)(*c))));
00257     }
00258     return out;
00259 }
00260 
00261 
00262 CNcbiOstream& operator<<(CNcbiOstream& out, CLocaseCharPtrConverter s)
00263 {
00264     for ( const char* c = s.m_String; *c; ++c ) {
00265         out.put(char(tolower((unsigned char)(*c))));
00266     }
00267     return out;
00268 }
00269 
00270 
00271 #ifdef NCBI_COMPILER_MSVC
00272 #  if _MSC_VER >= 1200  &&  _MSC_VER < 1300
00273 CNcbiOstream& operator<<(CNcbiOstream& out, __int64 val)
00274 {
00275     return (out << NStr::Int8ToString(val));
00276 }
00277 #  endif
00278 #endif
00279 
00280 
00281 static const char s_Hex[] = "0123456789ABCDEF";
00282 
00283 string Printable(char c)
00284 {
00285     string s;
00286     switch ( c ) {
00287     case '\0':  s = "\\0";   break;
00288     case '\\':  s = "\\\\";  break;
00289     case '\n':  s = "\\n";   break;
00290     case '\t':  s = "\\t";   break;
00291     case '\r':  s = "\\r";   break;
00292     case '\v':  s = "\\v";   break;
00293     default:
00294         {
00295             if ( isprint((unsigned char) c) ) {
00296                 s = c;
00297             } else {
00298                 s = "\\x";
00299                 s += s_Hex[(unsigned char) c / 16];
00300                 s += s_Hex[(unsigned char) c % 16];
00301             }
00302         }
00303     }
00304     return s;
00305 }
00306 
00307 
00308 static inline
00309 bool s_IsQuoted(char c)
00310 {
00311     return (c == '\t'  ||   c == '\v'  ||  c == '\b'  ||
00312             c == '\r'  ||   c == '\f'  ||  c == '\a'  ||
00313             c == '\n'  ||   c == '\\'  ||  c == '\''  ||
00314             c == '"'   ||  !isprint((unsigned char) c) ? true : false);
00315 }
00316 
00317 
00318 static inline
00319 void s_WritePrintable(CNcbiOstream& out, char c, char n)
00320 {
00321     switch ( c ) {
00322     case '\t':  out.write("\\t",  2);  return;
00323     case '\v':  out.write("\\v",  2);  return;
00324     case '\b':  out.write("\\b",  2);  return;
00325     case '\r':  out.write("\\r",  2);  return;
00326     case '\f':  out.write("\\f",  2);  return;
00327     case '\a':  out.write("\\a",  2);  return;
00328     case '\n':  out.write("\\n",  2);  return;
00329     case '\\':  out.write("\\\\", 2);  return;
00330     case '\'':  out.write("\\'",  2);  return;
00331     case '"':   out.write("\\\"", 2);  return;
00332     default:
00333         if ( isprint((unsigned char) c) ) {
00334             out.put(c);
00335             return;
00336         }
00337         break;
00338     }
00339 
00340     bool full = !s_IsQuoted(n)  &&  n >= '0'  &&  n <= '7' ? true : false;
00341     unsigned char v;
00342     char octal[4];
00343     int k = 1;
00344 
00345     *octal = '\\';
00346     v =  (unsigned char) c >> 6;
00347     if (v  ||  full) {
00348         octal[k++] = '0' + v;
00349         full = true;
00350     }
00351     v = ((unsigned char) c >> 3) & 7;
00352     if (v  ||  full) {
00353         octal[k++] = '0' + v;
00354     }
00355     v =  (unsigned char) c       & 7;
00356     octal    [k++] = '0' + v;
00357     out.write(octal, k);
00358 }
00359 
00360 
00361 CNcbiOstream& operator<<(CNcbiOstream& out, CPrintableStringConverter s)
00362 {
00363     size_t size = s.m_String.size();
00364     if (size) {
00365         const char* data = s.m_String.data();
00366         for (size_t i = 0;  i < size - 1;  ++i) {
00367             s_WritePrintable(out, data[i], data[i + 1]);
00368         }
00369         s_WritePrintable(out, data[size - 1], '\0');
00370     }
00371     return out;
00372 }
00373 
00374 
00375 CNcbiOstream& operator<<(CNcbiOstream& out, CPrintableCharPtrConverter s)
00376 {
00377     const char* p = s.m_String;
00378     char        c = *p;
00379     while (c) {
00380         char n = *++p;
00381         s_WritePrintable(out, c, n);
00382         c = n;
00383     }
00384     return out;
00385 }
00386 
00387 
00388 #if defined(NCBI_COMPILER_WORKSHOP)
00389 // We have to use two #if's here because KAI C++ cannot handle #if foo == bar
00390 #  if (NCBI_COMPILER_VERSION == 530)
00391 // The version that ships with the compiler is buggy.
00392 // Here's a working (and simpler!) one.
00393 template<>
00394 istream& istream::read(char *s, streamsize n)
00395 {
00396     sentry ipfx(*this, 1);
00397 
00398     try {
00399         if (rdbuf()->sgetc() == traits_type::eof()) {
00400             // Workaround for bug in sgetn.  *SIGH*.
00401             __chcount = 0;
00402             setstate(eofbit);
00403             return *this;
00404         }
00405         __chcount = rdbuf()->sgetn(s, n);
00406         if (__chcount == 0) {
00407             setstate(eofbit);
00408         } else if (__chcount < n) {
00409             setstate(eofbit | failbit);
00410         } else if (!ipfx) {
00411             setstate(failbit);
00412         } 
00413     } catch (...) {
00414         setstate(failbit);
00415         throw;
00416     }
00417 
00418     return *this;
00419 }
00420 #  endif  /* NCBI_COMPILER_VERSION == 530 */
00421 #endif  /* NCBI_COMPILER_WORKSHOP */
00422 
00423 
00424 EEncodingForm ReadIntoUtf8(
00425     CNcbiIstream&     input,
00426     CStringUTF8*      result,
00427     EEncodingForm     ef             /*  = eEncodingForm_Unknown*/,
00428     EReadUnknownNoBOM what_if_no_bom /* = eNoBOM_GuessEncoding*/
00429 )
00430 {
00431     EEncodingForm ef_bom = eEncodingForm_Unknown;
00432     result->erase();
00433     if (!input.good()) {
00434         return ef_bom;
00435     }
00436 
00437     const int buf_size = 4096;//2048;//256;
00438     char tmp[buf_size+2];
00439     Uint2* us = reinterpret_cast<Uint2*>(tmp);
00440 
00441 // check for Byte Order Mark
00442     const int bom_max = 4;
00443     memset(tmp,0,bom_max);
00444     input.read(tmp,bom_max);
00445     int n = input.gcount();
00446     {
00447         int bom_len=0;
00448         Uchar* uc = reinterpret_cast<Uchar*>(tmp);
00449         if (n >= 3 && uc[0] == 0xEF && uc[1] == 0xBB && uc[2] == 0xBF) {
00450             ef_bom = eEncodingForm_Utf8;
00451             uc[0] = uc[3];
00452             bom_len=3;
00453         }
00454         else if (n >= 2 && (us[0] == 0xFEFF || us[0] == 0xFFFE)) {
00455             if (us[0] == 0xFEFF) {
00456                 ef_bom = eEncodingForm_Utf16Native;
00457             } else {
00458                 ef_bom = eEncodingForm_Utf16Foreign;
00459             }
00460             us[0] = us[1];
00461             bom_len=2;
00462         }
00463         if (ef == eEncodingForm_Unknown || ef == ef_bom) {
00464             ef = ef_bom;
00465             n -= bom_len;
00466         }
00467         // else proceed at user's risk
00468     }
00469 
00470 // keep reading
00471     while (n != 0  ||  (input.good()  &&  !input.eof())) {
00472 
00473         if (n == 0) {
00474             input.read(tmp, buf_size);
00475             n = input.gcount();
00476             result->reserve(max(result->capacity(), result->size() + n));
00477         }
00478         tmp[n] = '\0';
00479 
00480         switch (ef) {
00481         case eEncodingForm_Utf16Foreign:
00482             {
00483                 char buf[buf_size];
00484                 swab(tmp,buf,n);
00485                 memcpy(tmp, buf, n);
00486             }
00487             // no break here
00488         case eEncodingForm_Utf16Native:
00489             {
00490                 Uint2* u = us;
00491                 for (n = n/2; n--; ++u) {
00492                     result->Append(*u);
00493                 }
00494             }
00495             break;
00496         case eEncodingForm_ISO8859_1:
00497             result->Append(tmp,eEncoding_ISO8859_1);
00498             break;
00499         case eEncodingForm_Windows_1252:
00500             result->Append(tmp,eEncoding_Windows_1252);
00501             break;
00502         case eEncodingForm_Utf8:
00503 //            result->Append(tmp,eEncoding_UTF8);   
00504             result->append(tmp,n);
00505             break;
00506         default:
00507             if (what_if_no_bom == eNoBOM_GuessEncoding) {
00508                 if (n == bom_max) {
00509                     input.read(tmp + n, buf_size - n);
00510                     n += input.gcount();
00511                     result->reserve(max(result->capacity(), result->size() + n));
00512                 }
00513                 tmp[n] = '\0';
00514                 EEncoding enc = CStringUTF8::GuessEncoding(tmp);
00515                 switch (enc) {
00516                 default:
00517                 case eEncoding_Unknown:
00518                     if (CStringUTF8::GetValidBytesCount(tmp, n) != 0) {
00519                         ef = eEncodingForm_Utf8;
00520                         result->Append(tmp,enc);
00521                     }
00522                     else {
00523                         NCBI_THROW(CCoreException, eCore,
00524                                 "ReadIntoUtf8: cannot guess text encoding");
00525                     }
00526                     break;
00527                 case eEncoding_UTF8:
00528                     ef = eEncodingForm_Utf8;
00529                     // no break here
00530                 case eEncoding_Ascii:
00531                 case eEncoding_ISO8859_1:
00532                 case eEncoding_Windows_1252:
00533                     result->Append(tmp,enc);
00534                     break;
00535                 }
00536             } else {
00537 //                result->Append(tmp,eEncoding_UTF8);
00538                 result->append(tmp,n);
00539             }
00540             break;
00541         }
00542         n = 0;
00543     }
00544     return ef_bom;
00545 }
00546 
00547 
00548 EEncodingForm GetTextEncodingForm(CNcbiIstream& input,
00549                                   EBOMDiscard   discard_bom)
00550 {
00551     EEncodingForm ef = eEncodingForm_Unknown;
00552     if (input.good()) {
00553         const int bom_max = 4;
00554         char tmp[bom_max];
00555         memset(tmp,0,bom_max);
00556         Uint2* us = reinterpret_cast<Uint2*>(tmp);
00557         Uchar* uc = reinterpret_cast<Uchar*>(tmp);
00558         input.get(tmp[0]);
00559         int n = input.gcount();
00560         if (n == 1 && (uc[0] == 0xEF || uc[0] == 0xFE || uc[0] == 0xFF)) {
00561             input.get(tmp[1]);
00562             if (input.gcount()==1) {
00563                 ++n;
00564                 if (us[0] == 0xFEFF) {
00565                     ef = eEncodingForm_Utf16Native;
00566                 } else if (us[0] == 0xFFFE) {
00567                     ef = eEncodingForm_Utf16Foreign;
00568                 } else if (uc[1] == 0xBB) {
00569                     input.get(tmp[2]);
00570                     if (input.gcount()==1) {
00571                         ++n;
00572                         if (uc[2] == 0xBF) {
00573                             ef = eEncodingForm_Utf8;
00574                         }
00575                     }
00576                 }
00577             }
00578         }
00579         if (ef == eEncodingForm_Unknown) {
00580             if (n > 1) {
00581                 CStreamUtils::Pushback(input,tmp,n);
00582             } else if (n == 1) {
00583                 input.unget();
00584             }
00585         } else {
00586             if (discard_bom == eBOM_Keep) {
00587                 CStreamUtils::Pushback(input,tmp,n);
00588             }
00589         }
00590     }
00591     return ef;
00592 }
00593 
00594 
00595 /****************************************************************************
00596  * BASE64- Encoding/Decoding
00597  */
00598 
00599 extern "C" void BASE64_Encode
00600 (const void* src_buf,
00601  size_t      src_size,
00602  size_t*     src_read,
00603  void*       dst_buf,
00604  size_t      dst_size,
00605  size_t*     dst_written,
00606  size_t*     line_len)
00607 {
00608     static const char syms[] =
00609         "ABCDEFGHIJKLMNOPQRSTUVWXYZ" /*26*/
00610         "abcdefghijklmnopqrstuvwxyz" /*52*/
00611         "0123456789+/";              /*64*/
00612     const size_t max_len = line_len ? *line_len : 76;
00613     const size_t max_src =
00614         ((dst_size - (max_len ? dst_size/(max_len + 1) : 0)) >> 2) * 3;
00615     unsigned char* src = (unsigned char*) src_buf;
00616     unsigned char* dst = (unsigned char*) dst_buf;
00617     size_t len = 0, i = 0, j = 0;
00618     unsigned char temp = 0, c;
00619     unsigned char shift = 2;
00620     if (!max_src  ||  !src_size) {
00621         *src_read    = 0;
00622         *dst_written = 0;
00623         if (dst_size > 0) {
00624             *dst = '\0';
00625         }
00626         return;
00627     }
00628     if (src_size > max_src) {
00629         src_size = max_src;
00630     }
00631     c = src[0];
00632     for (;;) {
00633         unsigned char bits = (c >> shift) & 0x3F;
00634         if (max_len  &&  len >= max_len) {
00635             dst[j++] = '\n';
00636             len = 0;
00637         }
00638         _ASSERT((size_t)(temp | bits) < sizeof(syms) - 1);
00639         dst[j++] = syms[temp | bits];
00640         len++;
00641         if (i >= src_size) {
00642             break;
00643         }
00644         shift += 2;
00645         shift &= 7;
00646         temp = (c << (8 - shift)) & 0x3F;
00647         if (shift) {
00648             c = ++i < src_size ? src[i] : 0;
00649         } else if (i + 1 == src_size) {
00650             i++;
00651         }
00652     }
00653     _ASSERT(j <= dst_size);
00654     *src_read = i;
00655     for (i = 0; i < (3 - src_size % 3) % 3; i++) {
00656         if (max_len  &&  len >= max_len) {
00657             dst[j++] = '\n';
00658             len = 0;
00659         }
00660         dst[j++] = '=';
00661         len++;
00662     }
00663     _ASSERT(j <= dst_size);
00664     *dst_written = j;
00665     if (j < dst_size) {
00666         dst[j] = '\0';
00667     }
00668 }
00669 
00670 
00671 extern "C" int/*bool*/ BASE64_Decode
00672 (const void* src_buf,
00673  size_t      src_size,
00674  size_t*     src_read,
00675  void*       dst_buf,
00676  size_t      dst_size,
00677  size_t*     dst_written)
00678 {
00679     unsigned char* src = (unsigned char*) src_buf;
00680     unsigned char* dst = (unsigned char*) dst_buf;
00681     size_t i = 0, j = 0, k = 0, l;
00682     unsigned int temp = 0;
00683     if (src_size < 4  ||  dst_size < 3) {
00684         *src_read    = 0;
00685         *dst_written = 0;
00686         return 0/*false*/;
00687     }
00688     for (;;) {
00689         int/*bool*/  ok = i < src_size ? 1/*true*/ : 0/*false*/;
00690         unsigned char c = ok ? src[i++] : '=';
00691         if (c == '=') {
00692             c  = 64; /*end*/
00693         } else if (c >= 'A'  &&  c <= 'Z') {
00694             c -= 'A';
00695         } else if (c >= 'a'  &&  c <= 'z') {
00696             c -= 'a' - 26;
00697         } else if (c >= '0'  &&  c <= '9') {
00698             c -= '0' - 52;
00699         } else if (c == '+') {
00700             c  = 62;
00701         } else if (c == '/') {
00702             c  = 63;
00703         } else {
00704             continue;
00705         }
00706         temp <<= 6;
00707         temp  |= c & 0x3F;
00708         if (!(++k & 3)  ||  c == 64) {
00709             if (c == 64) {
00710                 if (k < 2) {
00711                     if (ok) {
00712                         /* pushback leading '=' */
00713                         --i;
00714                     }
00715                     break;
00716                 }
00717                 switch (k) {
00718                 case 2:
00719                     temp >>= 4;
00720                     break;
00721                 case 3:
00722                     temp >>= 10;
00723                     break;
00724                 case 4:
00725                     temp >>= 8;
00726                     break;
00727                 default:
00728                     _ASSERT(0);
00729                     break;
00730                 }
00731                 l = 4 - k;
00732                 while (l > 0) {
00733                     /* eat up '='-padding */
00734                     if (i >= src_size)
00735                         break;
00736                     if (src[i] == '=')
00737                         l--;
00738                     else if (src[i] != '\r'  &&  src[i] != '\n')
00739                         break;
00740                     i++;
00741                 }
00742             } else {
00743                 k = 0;
00744             }
00745             switch (k) {
00746             case 0:
00747                 dst[j++] = (temp & 0xFF0000) >> 16;
00748                 /*FALLTHRU*/;
00749             case 4:
00750                 dst[j++] = (temp & 0xFF00) >> 8;
00751                 /*FALLTHRU*/
00752             case 3:
00753                 dst[j++] = (temp & 0xFF);
00754                 break;
00755             default:
00756                 break;
00757             }
00758             if (j + 3 >= dst_size  ||  c == 64) {
00759                 break;
00760             }
00761             temp = 0;
00762         }
00763     }
00764     *src_read    = i;
00765     *dst_written = j;
00766     return i  &&  j ? 1/*true*/ : 0/*false*/;
00767 }
00768 
00769 
00770 END_NCBI_SCOPE
00771 
00772 
00773 // See in the header why it is outside of NCBI scope (SunPro bug workaround...)
00774 
00775 #if defined(NCBI_USE_OLD_IOSTREAM)
00776 extern NCBI_NS_NCBI::CNcbiOstream& operator<<(NCBI_NS_NCBI::CNcbiOstream& os,
00777                                               const NCBI_NS_STD::string& str)
00778 {
00779     return str.empty() ? os : os << str.c_str();
00780 }
00781 
00782 
00783 extern NCBI_NS_NCBI::CNcbiIstream& operator>>(NCBI_NS_NCBI::CNcbiIstream& is,
00784                                               NCBI_NS_STD::string& str)
00785 {
00786     int ch;
00787     if ( !is.ipfx() )
00788         return is;
00789 
00790     str.erase();
00791 
00792     SIZE_TYPE end = str.max_size();
00793     if ( is.width() )
00794         end = (int)end < is.width() ? end : is.width(); 
00795 
00796     SIZE_TYPE i = 0;
00797     for (ch = is.rdbuf()->sbumpc();
00798          ch != EOF  &&  !isspace((unsigned char) ch);
00799          ch = is.rdbuf()->sbumpc()) {
00800         str.append(1, (char)ch);
00801         i++;
00802         if (i == end)
00803             break;
00804     }
00805     if (ch == EOF) 
00806         is.clear(NcbiEofbit | is.rdstate());      
00807     if ( !i )
00808         is.clear(NcbiFailbit | is.rdstate());      
00809 
00810     is.width(0);
00811     return is;
00812 }
00813 
00814 
00815 #endif  /* NCBI_USE_OLD_IOSTREAM */
00816 
00817 

Generated on Sun Dec 6 22:22:39 2009 for NCBI C++ ToolKit by  doxygen 1.4.6
Modified on Mon Dec 07 16:20:57 2009 by modify_doxy.py rev. 173732