stream_utils.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:21k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: stream_utils.cpp,v $
  4.  * PRODUCTION Revision 1000.4  2004/06/01 19:40:35  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.42
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: stream_utils.cpp,v 1000.4 2004/06/01 19:40:35 gouriano Exp $
  10.  * ===========================================================================
  11.  *
  12.  *                            PUBLIC DOMAIN NOTICE
  13.  *               National Center for Biotechnology Information
  14.  *
  15.  *  This software/database is a "United States Government Work" under the
  16.  *  terms of the United States Copyright Act.  It was written as part of
  17.  *  the author's official duties as a United States Government employee and
  18.  *  thus cannot be copyrighted.  This software/database is freely available
  19.  *  to the public for use. The National Library of Medicine and the U.S.
  20.  *  Government have not placed any restriction on its use or reproduction.
  21.  *
  22.  *  Although all reasonable efforts have been taken to ensure the accuracy
  23.  *  and reliability of the software and data, the NLM and the U.S.
  24.  *  Government do not and cannot warrant the performance or results that
  25.  *  may be obtained by using this software or data. The NLM and the U.S.
  26.  *  Government disclaim all warranties, express or implied, including
  27.  *  warranties of performance, merchantability or fitness for any particular
  28.  *  purpose.
  29.  *
  30.  *  Please cite the author in any work or product based on this material.
  31.  *
  32.  * ===========================================================================
  33.  *
  34.  * Author:  Anton Lavrentiev, Denis Vakatov
  35.  *
  36.  * File Description:
  37.  *   Stream utilities:
  38.  *   1. Push an arbitrary block of data back to a C++ input stream.
  39.  *   2. Non-blocking read.
  40.  *
  41.  */
  42. #include <ncbi_pch.hpp>
  43. #include <corelib/ncbistd.hpp>
  44. #include <util/util_exception.hpp>
  45. #include <util/stream_utils.hpp>
  46. #include <string.h>
  47. #ifdef NCBI_COMPILER_MIPSPRO
  48. #  define CPushback_StreambufBase CMIPSPRO_ReadsomeTolerantStreambuf
  49. #else
  50. #  define CPushback_StreambufBase CNcbiStreambuf
  51. #endif //NCBI_COMPILER_MIPSPRO
  52. #ifdef HAVE_GOOD_IOS_CALLBACKS
  53. #  undef  HAVE_GOOD_IOS_CALLBACKS
  54. #endif
  55. #if defined(HAVE_IOS_REGISTER_CALLBACK)  &&  
  56.   (!defined(NCBI_COMPILER_WORKSHOP)  ||  !defined(_MT))
  57. #  define HAVE_GOOD_IOS_CALLBACKS 1
  58. #endif
  59. BEGIN_NCBI_SCOPE
  60. /*****************************************************************************
  61.  *  Helper class: internal streambuf to be substituted instead of
  62.  *  the original one in the stream, when the data are pushed back.
  63.  */
  64. class CPushback_Streambuf : public CPushback_StreambufBase
  65. {
  66.     friend struct CStreamUtils;
  67. public:
  68.     CPushback_Streambuf(istream& istream, CT_CHAR_TYPE* buf,
  69.                         streamsize buf_size, void* del_ptr);
  70.     virtual ~CPushback_Streambuf();
  71. protected:
  72.     virtual CT_POS_TYPE seekoff(CT_OFF_TYPE off, IOS_BASE::seekdir whence,
  73.                                 IOS_BASE::openmode which);
  74.     virtual CT_POS_TYPE seekpos(CT_POS_TYPE pos, IOS_BASE::openmode which);
  75.     virtual CT_INT_TYPE overflow(CT_INT_TYPE c);
  76.     virtual streamsize  xsputn(const CT_CHAR_TYPE* buf, streamsize n);
  77.     virtual CT_INT_TYPE underflow(void);
  78.     virtual streamsize  xsgetn(CT_CHAR_TYPE* buf, streamsize n);
  79.     virtual streamsize  showmanyc(void);
  80.     virtual CT_INT_TYPE pbackfail(CT_INT_TYPE c = CT_EOF);
  81.     virtual int         sync(void);
  82.     // declared setbuf here to only throw an exception at run-time
  83.     virtual streambuf*  setbuf(CT_CHAR_TYPE* buf, streamsize buf_size);
  84. private:
  85.     void                x_FillBuffer(streamsize max_size);
  86.     void                x_DropBuffer(void);
  87.     istream&            m_Is;      // I/O stream this streambuf is attached to
  88.     streambuf*          m_Sb;      // original streambuf
  89.     CT_CHAR_TYPE*       m_Buf;     // == 0 when the buffer has been emptied
  90.     streamsize          m_BufSize;
  91.     void*               m_DelPtr;
  92. #ifdef HAVE_GOOD_IOS_CALLBACKS
  93.     int                 m_Index;
  94.     static void         x_Callback(IOS_BASE::event, IOS_BASE&, int);
  95. #endif //HAVE_GOOD_IOS_CALLBACKS
  96.     static const streamsize k_MinBufSize;
  97. };
  98. const streamsize CPushback_Streambuf::k_MinBufSize = 4096;
  99. #ifdef HAVE_GOOD_IOS_CALLBACKS
  100. void CPushback_Streambuf::x_Callback(IOS_BASE::event event,
  101.                                      IOS_BASE&       ios,
  102.                                      int             index)
  103. {
  104.     if (event == IOS_BASE::erase_event)
  105.         delete static_cast<streambuf*> (ios.pword(index));
  106. }
  107. #endif //HAVE_GOOD_IOS_CALLBACKS
  108. CPushback_Streambuf::CPushback_Streambuf(istream&      is,
  109.                                          CT_CHAR_TYPE* buf,
  110.                                          streamsize    buf_size,
  111.                                          void*         del_ptr) :
  112.     m_Is(is), m_Buf(buf), m_BufSize(buf_size), m_DelPtr(del_ptr)
  113. {
  114.     setp(0, 0); // unbuffered output at this level of streambuf's hierarchy
  115.     setg(m_Buf, m_Buf, m_Buf + m_BufSize);
  116.     m_Sb = m_Is.rdbuf(this);
  117. #ifdef HAVE_GOOD_IOS_CALLBACKS
  118.     try {
  119.         m_Index             = m_Is.xalloc();
  120.         m_Is.pword(m_Index) = this;
  121.         m_Is.register_callback(x_Callback, m_Index);
  122.     }
  123.     STD_CATCH_ALL("CPushback_Streambuf::CPushback_Streambuf");
  124. #endif //HAVE_GOOD_IOS_CALLBACKS
  125. }
  126. CPushback_Streambuf::~CPushback_Streambuf()
  127. {
  128. #ifdef HAVE_GOOD_IOS_CALLBACKS
  129.     m_Is.pword(m_Index) = 0;
  130. #endif //HAVE_GOOD_IOS_CALLBACKS
  131.     delete[] (CT_CHAR_TYPE*) m_DelPtr;
  132.     if (m_Sb) {
  133.         m_Is.rdbuf(m_Sb);
  134.         if (dynamic_cast<CPushback_Streambuf*> (m_Sb))
  135.             delete m_Sb;
  136.     }
  137. }
  138. CT_POS_TYPE CPushback_Streambuf::seekoff(CT_OFF_TYPE off,
  139.                                          IOS_BASE::seekdir whence,
  140.                                          IOS_BASE::openmode which)
  141. {
  142.     x_DropBuffer();
  143.     if (whence == ios::cur  &&  (which & ios::in)) {
  144.         return (CT_POS_TYPE)((CT_OFF_TYPE)(-1));
  145.     }
  146.     return m_Sb->PUBSEEKOFF(off, whence, which);
  147. }
  148. CT_POS_TYPE CPushback_Streambuf::seekpos(CT_POS_TYPE pos,
  149.                                          IOS_BASE::openmode which)
  150. {
  151.     x_DropBuffer();
  152.     return m_Sb->PUBSEEKPOS(pos, which);
  153. }
  154. CT_INT_TYPE CPushback_Streambuf::overflow(CT_INT_TYPE c)
  155. {
  156.     if ( !CT_EQ_INT_TYPE(c, CT_EOF) ) {
  157.         return m_Sb->sputc(CT_TO_CHAR_TYPE(c));
  158.     }
  159.     return m_Sb->PUBSYNC() == 0 ? CT_NOT_EOF(CT_EOF) : CT_EOF;
  160. }
  161. streamsize CPushback_Streambuf::xsputn(const CT_CHAR_TYPE* buf, streamsize n)
  162. {
  163.     // hope that this is an optimized copy operation (instead of overflow()s)
  164.     return m_Sb->sputn(buf, n);
  165. }
  166. CT_INT_TYPE CPushback_Streambuf::underflow(void)
  167. {
  168.     // we are here because there is no more data in the pushback buffer
  169.     _ASSERT(gptr()  &&  gptr() >= egptr());
  170. #ifdef NCBI_COMPILER_MIPSPRO
  171.     if (m_MIPSPRO_ReadsomeGptrSetLevel  &&  m_MIPSPRO_ReadsomeGptr != gptr())
  172.         return CT_EOF;
  173.     m_MIPSPRO_ReadsomeGptr = (CT_CHAR_TYPE*)(-1L);
  174. #endif //NCBI_COMPILER_MIPSPRO
  175.     x_FillBuffer(m_Sb->in_avail());
  176.     return gptr() < egptr() ? CT_TO_INT_TYPE(*gptr()) : CT_EOF;
  177. }
  178. streamsize CPushback_Streambuf::xsgetn(CT_CHAR_TYPE* buf, streamsize m)
  179. {
  180.     size_t n_total = 0;
  181.     while (m) {
  182.         if (gptr() < egptr()) {
  183.             size_t n       = (size_t) m;
  184.             size_t n_avail = (size_t) (egptr() - gptr());
  185.             size_t n_read  = (n <= n_avail) ? n : n_avail;
  186.             memcpy(buf, gptr(), n_read*sizeof(CT_CHAR_TYPE));
  187.             gbump((int) n_read);
  188.             m       -= (streamsize) n_read;
  189.             buf     += (streamsize) n_read;
  190.             n_total += (streamsize) n_read;
  191.         } else {
  192.             x_FillBuffer(m);
  193.             if (gptr() >= egptr())
  194.                 break;
  195.         }
  196.     }
  197.     return n_total;
  198. }
  199. streamsize CPushback_Streambuf::showmanyc(void)
  200. {
  201.     // we are here because (according to the standard) gptr() >= egptr()
  202.     _ASSERT(gptr()  &&  gptr() >= egptr());
  203.     return m_Sb->in_avail();
  204. }
  205. CT_INT_TYPE CPushback_Streambuf::pbackfail(CT_INT_TYPE /*c*/)
  206. {
  207.     /* We always maintain "usual backup condition" (27.5.2.4.3.13) after
  208.      * underflow(), i.e. 1 byte backup after a good read is always possible.
  209.      * That is, this function gets called only if the user tries to
  210.      * back up more than once (although, some attempts may be successful,
  211.      * this function call denotes that the backup area is full).
  212.      */
  213.     return CT_EOF; // always fail
  214. }
  215. int CPushback_Streambuf::sync(void)
  216. {
  217.     return m_Sb->PUBSYNC();
  218. }
  219. streambuf* CPushback_Streambuf::setbuf(CT_CHAR_TYPE* /*buf*/,
  220.                                        streamsize    /*buf_size*/)
  221. {
  222.     NCBI_THROW(CUtilException, eWrongCommand,
  223.                "CPushback_Streambuf::setbuf: not allowed");
  224.     /*NOTREACHED*/
  225.     return this;
  226. }
  227. void CPushback_Streambuf::x_FillBuffer(streamsize max_size)
  228. {
  229.     _ASSERT(m_Sb);
  230.     if ( !max_size )
  231.         ++max_size;
  232.     CPushback_Streambuf* sb = dynamic_cast<CPushback_Streambuf*> (m_Sb);
  233.     if ( sb ) {
  234.         _ASSERT(&m_Is == &sb->m_Is);
  235.         m_Sb     = sb->m_Sb;
  236.         sb->m_Sb = 0;
  237.         if (sb->gptr() >= sb->egptr()) {
  238.             delete sb;
  239.             x_FillBuffer(max_size);
  240.             return;
  241.         }
  242.         delete[] (CT_CHAR_TYPE*) m_DelPtr;
  243.         m_Buf        = sb->m_Buf;
  244.         m_BufSize    = sb->m_BufSize;
  245.         m_DelPtr     = sb->m_DelPtr;
  246.         sb->m_DelPtr = 0;
  247.         setg(sb->gptr(), sb->gptr(), sb->egptr());
  248.         delete sb;
  249.     } else {
  250.         CT_CHAR_TYPE* bp = 0;
  251.         streamsize buf_size = m_DelPtr
  252.             ? (streamsize)(m_Buf - (CT_CHAR_TYPE*) m_DelPtr) + m_BufSize : 0;
  253.         if (buf_size < k_MinBufSize) {
  254.             buf_size = k_MinBufSize;
  255.             bp = new CT_CHAR_TYPE[buf_size];
  256.         }
  257.         streamsize n = m_Sb->sgetn(bp ? bp : (CT_CHAR_TYPE*) m_DelPtr,
  258.                                    min(buf_size, max_size));
  259.         if (n <= 0) {
  260.             // NB: For unknown reasons WorkShop6 can return -1 from sgetn :-/
  261.             delete bp;
  262.             return;
  263.         }
  264.         if (bp) {
  265.             delete[] (CT_CHAR_TYPE*) m_DelPtr;
  266.             m_DelPtr = bp;
  267.         }
  268.         m_Buf = (CT_CHAR_TYPE*) m_DelPtr;
  269.         m_BufSize = buf_size;
  270.         setg(m_Buf, m_Buf, m_Buf + n);
  271.     }
  272. }
  273. void CPushback_Streambuf::x_DropBuffer()
  274. {
  275.     CPushback_Streambuf* sb = dynamic_cast<CPushback_Streambuf*> (m_Sb);
  276.     if (sb) {
  277.         m_Sb     = sb->m_Sb;
  278.         sb->m_Sb = 0;
  279.         delete sb;
  280.         x_DropBuffer();
  281.         return;
  282.     }
  283.     // nothing in the buffer; no putback area as well
  284.     setg(m_Buf, m_Buf, m_Buf);
  285. }
  286. /*****************************************************************************
  287.  *  Public interface
  288.  */
  289. void CStreamUtils::Pushback(CNcbiIstream& is,
  290.                             CT_CHAR_TYPE* buf,
  291.                             streamsize    buf_size,
  292.                             void*         del_ptr)
  293. {
  294.     CPushback_Streambuf* sb = dynamic_cast<CPushback_Streambuf*> (is.rdbuf());
  295.     _ASSERT(del_ptr <= buf);
  296.     if ( sb ) {
  297.         // We may not need to create another streambuf,
  298.         //     just recycle the existing one here...
  299.         _ASSERT(del_ptr < (sb->m_DelPtr ? sb->m_DelPtr : sb->m_Buf)  ||
  300.                 sb->m_Buf + sb->m_BufSize <= del_ptr);
  301.         // 1/ points to a (adjacent) part of the internal buffer we just read?
  302.         if (sb->m_Buf <= buf  &&  buf + buf_size == sb->gptr()) {
  303.             _ASSERT(!del_ptr  ||  del_ptr == sb->m_DelPtr);
  304.             sb->setg(buf, buf, sb->m_Buf + sb->m_BufSize);
  305.             return;
  306.         }
  307.         // 2/ equal to a (adjacent) part of the internal buffer we just read?
  308.         if ((streamsize)(sb->gptr() - sb->m_Buf) >= buf_size) {
  309.             CT_CHAR_TYPE* bp = sb->gptr() - buf_size;
  310.             if (memcmp(buf, bp, buf_size) == 0) {
  311.                 sb->setg(bp, bp, sb->egptr());
  312.                 if ( del_ptr ) {
  313.                     delete[] (CT_CHAR_TYPE*) del_ptr;
  314.                 }
  315.                 return;
  316.             }
  317.         }
  318.     }
  319.     (void) new CPushback_Streambuf(is, buf, buf_size, del_ptr);
  320. }
  321. void CStreamUtils::Pushback(CNcbiIstream&       is,
  322.                             const CT_CHAR_TYPE* buf,
  323.                             streamsize          buf_size)
  324. {
  325.     CT_CHAR_TYPE* buf_copy = new CT_CHAR_TYPE[buf_size];
  326.     memcpy(buf_copy, buf, buf_size);
  327.     Pushback(is, buf_copy, buf_size, buf_copy);
  328. }
  329. #ifdef NCBI_NO_READSOME
  330. #  undef NCBI_NO_READSOME
  331. #endif /*NCBI_NO_READSOME*/
  332. #if defined(NCBI_COMPILER_GCC)
  333. #  if NCBI_COMPILER_VERSION < 300
  334. #    define NCBI_NO_READSOME 1
  335. #  endif /*NCBI_COMPILER_VERSION*/
  336. #elif defined(NCBI_COMPILER_MSVC)
  337.     /* MSVC's readsome() is buggy [causes 1 byte reads] and is thus avoided.
  338.      * Now when we have worked around the issue by implementing fastopen()
  339.      * in CNcbiFstreams and thus making them fully buffered, we can go back
  340.      * to the use of readsome() in MSVC... */
  341.     //#  define NCBI_NO_READSOME 1
  342. #elif defined(NCBI_COMPILER_MIPSPRO)
  343.     /* MIPSPro does not comply with the standard and always checks for EOF
  344.      * doing one extra read from the stream [which might be a killing idea
  345.      * for network connections]. We introduced an ugly workaround here...
  346.      * Don't use istream::readsome() but istream::read() instead in order to be
  347.      * able to clear fake EOF caused by the unnecessary underflow() upcall.*/
  348. #  define NCBI_NO_READSOME 1
  349. #endif /*NCBI_COMPILER*/
  350. #ifndef NCBI_NO_READSOME
  351. static inline streamsize s_Readsome(CNcbiIstream& is,
  352.                                     CT_CHAR_TYPE* buf,
  353.                                     streamsize    buf_size)
  354. {
  355. #  ifdef NCBI_COMPILER_WORKSHOP
  356.     /* Rogue Wave does not always return correct value from is.readsome() :-/
  357.      * In particular, when streambuf::showmanyc() returns 1 followed by
  358.      * a failed read() [which implements extraction from the stream], which
  359.      * encounters the EOF, the readsome() will blindly return 1, and in
  360.      * general, always exactly the number of bytes showmanyc() reported,
  361.      * regardless of actually extracted by subsequent read operation.  Bug!
  362.      * NOTE that showmanyc() does not guarantee the number of bytes that can
  363.      * be read, but returns a best guess estimate [C++ Standard, footnote 275].
  364.      */
  365.     streamsize n = is.readsome(buf, buf_size);
  366.     return n ? is.gcount() : 0;
  367. #  else
  368.     return is.readsome(buf, buf_size);
  369. #  endif /*NCBI_COMPILER_WORKSHOP*/
  370. }
  371. #endif /*NCBI_NO_READSOME*/
  372. static streamsize s_DoReadsome(CNcbiIstream& is,
  373.                                CT_CHAR_TYPE* buf,
  374.                                streamsize    buf_size)
  375. {
  376.     _ASSERT(buf  &&  buf_size);
  377. #ifdef NCBI_NO_READSOME
  378. #  undef NCBI_NO_READSOME
  379.     // Special case: GCC had no readsome() prior to ver 3.0;
  380.     // read() will set "eof" (and "fail") flag if gcount() < buf_size
  381.     streamsize avail = is.rdbuf()->in_avail();
  382.     if (avail == 0)
  383.         avail++; // we still must read
  384.     else if (buf_size < avail)
  385.         avail = buf_size;
  386.     is.read(buf, avail);
  387.     streamsize count = is.gcount();
  388.     // Reset "eof" flag if some data have been read
  389.     if (count  &&  is.eof()  &&  !is.bad())
  390.         is.clear();
  391.     return count;
  392. #else
  393.     // Try to read data
  394.     streamsize n = s_Readsome(is, buf, buf_size);
  395.     if (n != 0  ||  !is.good())
  396.         return n;
  397.     // No buffered data found, try to read from the real source [still good]
  398.     is.read(buf, 1);
  399.     if ( !is.good() )
  400.         return 0;
  401.     if (buf_size == 1)
  402.         return 1; // do not need more data
  403.     // Read more data (up to "buf_size" bytes)
  404.     return s_Readsome(is, buf + 1, buf_size - 1) + 1;
  405. #endif /*NCBI_NO_READSOME*/
  406. }
  407. streamsize CStreamUtils::Readsome(CNcbiIstream& is,
  408.                                   CT_CHAR_TYPE* buf,
  409.                                   streamsize    buf_size)
  410. {
  411. #  ifdef NCBI_COMPILER_MIPSPRO
  412.     CMIPSPRO_ReadsomeTolerantStreambuf* sb =
  413.         dynamic_cast<CMIPSPRO_ReadsomeTolerantStreambuf*> (is.rdbuf());
  414.     if (sb)
  415.         sb->MIPSPRO_ReadsomeBegin();
  416. #  endif /*NCBI_COMPILER_MIPSPRO*/
  417.     streamsize result = s_DoReadsome(is, buf, buf_size);
  418. #  ifdef NCBI_COMPILER_MIPSPRO
  419.     if (sb)
  420.         sb->MIPSPRO_ReadsomeEnd();
  421. #  endif /*NCBI_COMPILER_MIPSPRO*/
  422.     return result;
  423. }
  424. END_NCBI_SCOPE
  425. /*
  426.  * ---------------------------------------------------------------------------
  427.  * $Log: stream_utils.cpp,v $
  428.  * Revision 1000.4  2004/06/01 19:40:35  gouriano
  429.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.42
  430.  *
  431.  * Revision 1.42  2004/05/17 21:06:02  gorelenk
  432.  * Added include of PCH ncbi_pch.hpp
  433.  *
  434.  * Revision 1.41  2004/02/03 13:13:46  lavr
  435.  * ios::xalloc() is universal; HAVE_XALLOC is deprecated and removed
  436.  *
  437.  * Revision 1.40  2004/01/21 15:34:14  lavr
  438.  * Use proper macro HAVE_IOS_REGISTER_CALLBACK
  439.  *
  440.  * Revision 1.39  2004/01/20 20:39:59  lavr
  441.  * Replace HAVE_BUGGY_IOS_CALLBACKS with (better) HAVE_GOOD_IOS_CALLBACKS
  442.  *
  443.  * Revision 1.38  2003/12/31 16:24:54  lavr
  444.  * Fix istream::readsome() return counter use for Rogue Wave implementations
  445.  *
  446.  * Revision 1.37  2003/12/31 15:31:20  lavr
  447.  * Fix wrong use of istream::readsome() on platforms that lack it
  448.  *
  449.  * Revision 1.36  2003/12/30 17:28:39  lavr
  450.  * Work around buggy implementation of istream::readsome() in Rogue Wave STL
  451.  *
  452.  * Revision 1.35  2003/12/29 15:18:40  lavr
  453.  * Modified CStreamUtils::Readsome() to avoid blocking on GCC2.95
  454.  *
  455.  * Revision 1.34  2003/12/18 13:24:46  ucko
  456.  * It seems MIPSpro also lacks showmanyc, so extend our
  457.  * streambuf-with-showmanyc class to cover it as well and make it
  458.  * CMIPSPRO_ReadsomeTolerantStreambuf's base class; also use it as
  459.  * CPushback_StreambufBase's base class with GCC 2.9x.
  460.  *
  461.  * Revision 1.33  2003/12/18 03:44:29  ucko
  462.  * s_Readsome(): If in_avail() and showmanyc() both return 0, do likewise
  463.  * rather than potentially blocking.
  464.  *
  465.  * Revision 1.32  2003/11/21 19:58:47  lavr
  466.  * x_FillBuffer() not to have default parameter: crucial in underflow()
  467.  *
  468.  * Revision 1.31  2003/11/19 16:49:35  vasilche
  469.  * Fix previous commit to maintain backup condition.
  470.  *
  471.  * Revision 1.30  2003/11/19 15:41:50  vasilche
  472.  * Temporary fix for wrong Readsome() after Pushback().
  473.  *
  474.  * Revision 1.29  2003/11/04 13:39:01  lavr
  475.  * CPushback_Streambuf is conditionally based on MIPSPro
  476.  *
  477.  * Revision 1.28  2003/11/03 20:05:11  lavr
  478.  * CStreamUtils::Readsome() reorganized: s_Readsome() introduced.
  479.  * Add and elaborate notes about I/O on MSVC and MIPSPro.
  480.  * Allow to use stream readsome() on these two compilers.
  481.  *
  482.  * Revision 1.27  2003/10/22 18:11:24  lavr
  483.  * Change base class of CPushback_Streambuf into CNcbiStreambuf
  484.  *
  485.  * Revision 1.26  2003/10/16 19:37:36  lavr
  486.  * Add comments and indentation of conditionals in Readsome()
  487.  *
  488.  * Revision 1.25  2003/05/21 19:34:34  lavr
  489.  * Note that insufficient ios::read() also sets failbit (as per the standard)
  490.  *
  491.  * Revision 1.24  2003/05/20 16:44:59  lavr
  492.  * CStreamUtils::Readsome() not to clear() in a bad() stream
  493.  *
  494.  * Revision 1.23  2003/04/14 21:08:39  lavr
  495.  * Take advantage of HAVE_BUGGY_IOS_CALLBACKS
  496.  *
  497.  * Revision 1.22  2003/04/11 17:57:52  lavr
  498.  * Take advantage of HAVE_IOS_XALLOC
  499.  *
  500.  * Revision 1.21  2003/03/30 07:00:36  lavr
  501.  * MIPS-specific workaround for lame-designed stream read ops
  502.  *
  503.  * Revision 1.20  2003/03/28 03:26:15  lavr
  504.  * Reinstate NCBI_NO_READSOME for MSVC
  505.  *
  506.  * Revision 1.19  2003/03/27 18:40:14  lavr
  507.  * Temporarily remove NCBI_NO_READSOME for MSVC
  508.  *
  509.  * Revision 1.18  2003/03/27 16:50:14  lavr
  510.  * #define NCBI_NO_READSOME for MSVC to prevent 1-byte at a time file input
  511.  * caused by lame unbuffered implementation of basic_filebuf, that defines
  512.  * showmanyc() to return 0 and doing byte-by-byte file input via fgetc()
  513.  *
  514.  * Revision 1.17  2003/03/25 22:14:03  lavr
  515.  * CStreamUtils::Readsome(): Return not only on EOF but on any !good()
  516.  *
  517.  * Revision 1.16  2003/02/27 15:36:23  lavr
  518.  * Preper indentation for NCBI_THROW
  519.  *
  520.  * Revision 1.15  2003/02/26 21:32:00  gouriano
  521.  * modify C++ exceptions thrown by this library
  522.  *
  523.  * Revision 1.14  2002/12/19 14:50:42  dicuccio
  524.  * Changed a friend class -> friend struct (relieves a warning for MSVC)
  525.  *
  526.  * Revision 1.13  2002/11/28 03:28:01  lavr
  527.  * Comments updated
  528.  *
  529.  * Revision 1.12  2002/11/27 21:08:01  lavr
  530.  * Rename "stream_pushback" -> "stream_utils" and enclose utils in a class
  531.  * Add new utility method Readsome() for non-blocking read
  532.  *
  533.  * Revision 1.11  2002/10/29 22:06:27  ucko
  534.  * Make *buf const in the copying version of UTIL_StreamPushback.
  535.  *
  536.  * Revision 1.10  2002/09/17 20:47:05  lavr
  537.  * Add a comment to unreachable return from CPushback_Streambuf::setbuf()
  538.  *
  539.  * Revision 1.9  2002/08/16 17:56:44  lavr
  540.  * PUBSYNC, PUBSEEK* moved to <corelib/ncbistre.hpp>
  541.  *
  542.  * Revision 1.8  2002/02/06 14:38:23  ucko
  543.  * Split up conditional test for GCC2.x to work around KCC preprocessor lossage
  544.  *
  545.  * Revision 1.7  2002/02/05 16:05:43  lavr
  546.  * List of included header files revised
  547.  *
  548.  * Revision 1.6  2002/02/04 20:22:34  lavr
  549.  * Stream positioning added; more assert()'s to check standard compliance
  550.  *
  551.  * Revision 1.5  2002/01/28 20:26:39  lavr
  552.  * Completely redesigned
  553.  *
  554.  * Revision 1.4  2001/12/17 22:18:21  ucko
  555.  * Overload xsgetn unconditionally.
  556.  *
  557.  * Revision 1.3  2001/12/13 17:21:27  vakatov
  558.  * [GCC, NCBI_COMPILER_VERSION > 2.95.X]  Use pubsync() rather than sync()
  559.  *
  560.  * Revision 1.2  2001/12/09 06:31:52  vakatov
  561.  * UTIL_StreamPushback() to return VOID rather than STREAMBUF*.
  562.  * Got rid of a warning;  added comments;  use _ASSERT(), not assert().
  563.  *
  564.  * Revision 1.1  2001/12/07 22:59:36  lavr
  565.  * Initial revision
  566.  *
  567.  * ===========================================================================
  568. */