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

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: rwstreambuf.cpp,v $
  4.  * PRODUCTION Revision 1000.4  2004/06/01 19:40:26  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.9
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: rwstreambuf.cpp,v 1000.4 2004/06/01 19:40:26 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
  35.  *
  36.  * File Description:
  37.  *   Reader-writer based stream buffer
  38.  *
  39.  */
  40. #include <ncbi_pch.hpp>
  41. #include <corelib/ncbidbg.hpp>
  42. #include <util/rwstreambuf.hpp>
  43. BEGIN_NCBI_SCOPE
  44. static const streamsize kDefaultBufferSize = 4096;
  45. CRWStreambuf::CRWStreambuf(IReaderWriter*           rw,
  46.                            streamsize               n,
  47.                            CT_CHAR_TYPE*            s,
  48.                            CRWStreambuf::TOwnership o)
  49.     : m_OwnRW(o), m_Reader(rw), m_Writer(rw),
  50.       m_ReadBuf(0), m_BufSize(0), m_OwnBuf(false)
  51. {
  52.     setbuf(s  &&  n ? s : 0, n ? n : kDefaultBufferSize);
  53. }
  54. CRWStreambuf::CRWStreambuf(IReader*                 r,
  55.                            IWriter*                 w,
  56.                            streamsize               n,
  57.                            CT_CHAR_TYPE*            s,
  58.                            CRWStreambuf::TOwnership o)
  59.     : m_OwnRW(o), m_Reader(r), m_Writer(w),
  60.       m_ReadBuf(0), m_BufSize(0), m_OwnBuf(false)
  61. {
  62.     setbuf(s  &&  n ? s : 0, n ? n : kDefaultBufferSize);
  63. }
  64. CRWStreambuf::~CRWStreambuf()
  65. {
  66.     sync();
  67.     IReaderWriter* r = dynamic_cast<IReaderWriter*> (m_Reader);
  68.     IReaderWriter* w = dynamic_cast<IReaderWriter*> (m_Writer);
  69.     if ((m_OwnRW & fOwnAll) && r != w) {
  70.         delete m_Writer;
  71.         delete m_Reader;
  72.     } else if (m_OwnRW & fOwnWriter) {
  73.         if (!r || r != w) {
  74.             delete m_Writer;
  75.         }
  76.     } else if (m_OwnRW & fOwnReader) {
  77.         if (!w || w != r) {
  78.             delete m_Reader;
  79.         }
  80.     }
  81.     if ( m_OwnBuf ) {
  82.         delete[] m_ReadBuf;
  83.     }
  84. }
  85. CNcbiStreambuf* CRWStreambuf::setbuf(CT_CHAR_TYPE* s, streamsize n)
  86. {
  87.     if (!s  &&  !n) {
  88.         return this;
  89.     }
  90.     streamsize    x_size = n ? n : kDefaultBufferSize;
  91.     CT_CHAR_TYPE* x_buf  = s ? s : (n == 1? &x_Buf : new CT_CHAR_TYPE[x_size]);
  92.     if ( !x_buf ) {
  93.         return 0;
  94.     }
  95.     if ( m_OwnBuf ) {
  96.         delete[] m_ReadBuf;
  97.     }
  98.     x_size   >>= 1;
  99.     m_BufSize  = x_size ? x_size : 1;
  100.     m_ReadBuf  = x_buf;
  101.     m_WriteBuf = x_size ? x_buf + m_BufSize : 0;
  102.     m_OwnBuf   = x_size  &&  !s;
  103.     setp(m_WriteBuf, m_WriteBuf + x_size);
  104.     setg(m_ReadBuf,  m_ReadBuf, m_ReadBuf);
  105.     return this;
  106. }
  107. CT_INT_TYPE CRWStreambuf::overflow(CT_INT_TYPE c)
  108. {
  109.     if ( !m_Writer )
  110.         return CT_EOF;
  111.     if ( m_WriteBuf ) {
  112.         // send buffer
  113.         size_t n_write = pptr() - m_WriteBuf;
  114.         if ( n_write ) {
  115.             size_t n_written;
  116.             n_write *= sizeof(CT_CHAR_TYPE);
  117.             m_Writer->Write(m_WriteBuf, n_write, &n_written);
  118.             if ( !n_written )
  119.                 return CT_EOF;
  120.             n_written /= sizeof(CT_CHAR_TYPE);
  121.             // update buffer content (get rid of the sent data)
  122.             if (n_written != n_write) {
  123.                 memmove(m_WriteBuf, m_WriteBuf + n_written,
  124.                         (n_write - n_written)*sizeof(CT_CHAR_TYPE));
  125.             }
  126.             setp(m_WriteBuf + n_write - n_written, m_WriteBuf + m_BufSize);
  127.         }
  128.         // store char
  129.         return CT_EQ_INT_TYPE(c, CT_EOF)
  130.             ? CT_NOT_EOF(CT_EOF) : sputc(CT_TO_CHAR_TYPE(c));
  131.     }
  132.     if ( !CT_EQ_INT_TYPE(c, CT_EOF) ) {
  133.         // send char
  134.         size_t n_written;
  135.         CT_CHAR_TYPE b = CT_TO_CHAR_TYPE(c);
  136.         m_Writer->Write(&b, sizeof(b), &n_written);
  137.         return n_written == sizeof(b) ? c : CT_EOF;
  138.     } else {
  139.         switch ( m_Writer->Flush() ) {
  140.         case eRW_Error:
  141.         case eRW_Eof:
  142.             return CT_EOF;
  143.         default:
  144.             break;
  145.         }
  146.     }
  147.     return CT_NOT_EOF(CT_EOF);
  148. }
  149. CT_INT_TYPE CRWStreambuf::underflow(void)
  150. {
  151.     if ( !m_Reader )
  152.         return CT_EOF;
  153.     _ASSERT(!gptr()  ||  gptr() >= egptr());
  154. #ifdef NCBI_COMPILER_MIPSPRO
  155.     if (m_MIPSPRO_ReadsomeGptrSetLevel  &&  m_MIPSPRO_ReadsomeGptr != gptr())
  156.         return CT_EOF;
  157.     m_MIPSPRO_ReadsomeGptr = (CT_CHAR_TYPE*)(-1);
  158. #endif
  159.     // read
  160.     size_t n_read;
  161.     m_Reader->Read(m_ReadBuf, m_BufSize*sizeof(CT_CHAR_TYPE), &n_read);
  162.     if ( !n_read )
  163.         return CT_EOF;
  164.     // update input buffer with the data we have just read
  165.     setg(m_ReadBuf, m_ReadBuf, m_ReadBuf + n_read/sizeof(CT_CHAR_TYPE));
  166.     return CT_TO_INT_TYPE(*m_ReadBuf);
  167. }
  168. streamsize CRWStreambuf::xsgetn(CT_CHAR_TYPE* buf, streamsize m)
  169. {
  170.     if ( !m_Reader )
  171.         return 0;
  172.     if (m <= 0)
  173.         return 0;
  174.     size_t n = (size_t) m;
  175.     size_t n_read;
  176.     // read from the memory buffer
  177.     if (gptr()  &&  gptr() < egptr()) {
  178.         n_read = egptr() - gptr();
  179.         if (n_read > n)
  180.             n_read = n;
  181.         memcpy(buf, gptr(), n_read*sizeof(CT_CHAR_TYPE));
  182.         gbump((int) n_read);
  183.         buf += n_read;
  184.         n   -= n_read;
  185.     } else
  186.         n_read = 0;
  187.     if (n == 0)
  188.         return (streamsize) n_read;
  189.     do {
  190.         size_t       x_read = n < (size_t) m_BufSize? m_BufSize : n;
  191.         CT_CHAR_TYPE* x_buf = n < (size_t) m_BufSize? m_ReadBuf : buf;
  192.         // read directly from device
  193.         ERW_Result   result = m_Reader->Read(x_buf,
  194.                                              x_read*sizeof(CT_CHAR_TYPE),
  195.                                              &x_read);
  196.         if (!(x_read /= sizeof(CT_CHAR_TYPE)))
  197.             break;
  198.         // satisfy "usual backup condition", see standard: 27.5.2.4.3.13
  199.         if (x_buf == m_ReadBuf) {
  200.             size_t xx_read = x_read;
  201.             if (x_read > n)
  202.                 x_read = n;
  203.             memcpy(buf, m_ReadBuf, x_read*sizeof(CT_CHAR_TYPE));
  204.             setg(m_ReadBuf, m_ReadBuf + x_read, m_ReadBuf + xx_read);
  205.         } else {
  206.             _ASSERT(x_read <= n);
  207.             size_t xx_read = x_read > (size_t) m_BufSize ? m_BufSize : x_read;
  208.             memcpy(m_ReadBuf,buf+x_read-xx_read,xx_read*sizeof(CT_CHAR_TYPE));
  209.             setg(m_ReadBuf, m_ReadBuf + xx_read, m_ReadBuf + xx_read);
  210.         }
  211.         n_read += x_read;
  212.         if (result != eRW_Success)
  213.             break;
  214.         buf    += x_read;
  215.         n      -= x_read;
  216.     } while ( n );
  217.     return (streamsize) n_read;
  218. }
  219. streamsize CRWStreambuf::showmanyc(void)
  220. {
  221.     if ( !m_Reader )
  222.         return -1;
  223.     size_t count;
  224.     switch ( m_Reader->PendingCount(&count) ) {
  225.     case eRW_NotImplemented:
  226.         return 0;
  227.     case eRW_Success:
  228.         return count;
  229.     default:
  230.         break;
  231.     }
  232.     return -1;
  233. }
  234. int CRWStreambuf::sync(void)
  235. {
  236.     do {
  237.         if (CT_EQ_INT_TYPE(overflow(CT_EOF), CT_EOF))
  238.             return -1;
  239.     } while (m_WriteBuf  &&  pptr() > m_WriteBuf);
  240.     return 0;
  241. }
  242. END_NCBI_SCOPE
  243. /*
  244.  * ---------------------------------------------------------------------------
  245.  * $Log: rwstreambuf.cpp,v $
  246.  * Revision 1000.4  2004/06/01 19:40:26  gouriano
  247.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.9
  248.  *
  249.  * Revision 1.9  2004/05/17 21:06:02  gorelenk
  250.  * Added include of PCH ncbi_pch.hpp
  251.  *
  252.  * Revision 1.8  2004/05/17 15:49:39  lavr
  253.  * Ownership arguments added, stored and processed in dtor
  254.  *
  255.  * Revision 1.7  2004/01/15 20:06:28  lavr
  256.  * Define kDefaultBufferSize statically in this file
  257.  *
  258.  * Revision 1.6  2004/01/09 17:39:54  lavr
  259.  * Use internal 1-byte buffer for unbuffered streams' get ops
  260.  *
  261.  * Revision 1.5  2003/11/13 17:52:37  lavr
  262.  * No backup area on new get buffer
  263.  *
  264.  * Revision 1.4  2003/11/04 13:38:29  lavr
  265.  * Unique value of visited MIPSPro-special gptr() is changed to (-1)
  266.  *
  267.  * Revision 1.3  2003/11/04 03:09:29  lavr
  268.  * xsgetn() fixed to advance buffer pointer when reading
  269.  *
  270.  * Revision 1.2  2003/11/03 20:05:55  lavr
  271.  * CRWStreambuf::xsgetn() made standard-conforming
  272.  *
  273.  * Revision 1.1  2003/10/22 18:10:41  lavr
  274.  * Initial revision
  275.  *
  276.  * ===========================================================================
  277.  */