📄 ncbi_conn_streambuf.cpp
字号:
/* * =========================================================================== * PRODUCTION $Log: ncbi_conn_streambuf.cpp,v $ * PRODUCTION Revision 1000.5 2004/06/01 18:44:44 gouriano * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R6.46 * PRODUCTION * =========================================================================== *//* $Id: ncbi_conn_streambuf.cpp,v 1000.5 2004/06/01 18:44:44 gouriano Exp $ * =========================================================================== * * PUBLIC DOMAIN NOTICE * National Center for Biotechnology Information * * This software/database is a "United States Government Work" under the * terms of the United States Copyright Act. It was written as part of * the author's official duties as a United States Government employee and * thus cannot be copyrighted. This software/database is freely available * to the public for use. The National Library of Medicine and the U.S. * Government have not placed any restriction on its use or reproduction. * * Although all reasonable efforts have been taken to ensure the accuracy * and reliability of the software and data, the NLM and the U.S. * Government do not and cannot warrant the performance or results that * may be obtained by using this software or data. The NLM and the U.S. * Government disclaim all warranties, express or implied, including * warranties of performance, merchantability or fitness for any particular * purpose. * * Please cite the author in any work or product based on this material. * * =========================================================================== * * Author: Anton Lavrentiev, Denis Vakatov * * File Description: * CONN-based C++ stream buffer * */#include <ncbi_pch.hpp>#include "ncbi_conn_streambuf.hpp"#include <corelib/ncbidbg.hpp>#include <connect/ncbi_conn_exception.hpp>#include <memory>#define LOG_IF_ERROR(status, msg) x_LogIfError(__FILE__, __LINE__, status, msg)BEGIN_NCBI_SCOPECConn_Streambuf::CConn_Streambuf(CONNECTOR connector, const STimeout* timeout, streamsize buf_size, bool tie) : m_Conn(0), m_ReadBuf(0), m_BufSize(buf_size ? buf_size : 1), m_Tie(tie), x_Pos((CT_OFF_TYPE)(0)){ if ( !connector ) { ERR_POST("CConn_Streambuf::CConn_Streambuf(): NULL connector"); return; } if (LOG_IF_ERROR(CONN_Create(connector, &m_Conn), "CConn_Streambuf(): CONN_Create() failed") !=eIO_Success){ return; } _ASSERT(m_Conn != 0); CONN_SetTimeout(m_Conn, eIO_Open, timeout); CONN_SetTimeout(m_Conn, eIO_Read, timeout); CONN_SetTimeout(m_Conn, eIO_Write, timeout); CONN_SetTimeout(m_Conn, eIO_Close, timeout); m_ReadBuf = buf_size ? new CT_CHAR_TYPE[m_BufSize << 1] : &x_Buf; m_WriteBuf = buf_size ? m_ReadBuf + m_BufSize : 0; setg(m_ReadBuf, m_ReadBuf, m_ReadBuf); // Empty get area setp(m_WriteBuf, m_WriteBuf + buf_size); // Put area (if any)}CConn_Streambuf::~CConn_Streambuf(){ sync(); EIO_Status status; if (m_Conn && (status = CONN_Close(m_Conn)) != eIO_Success) { _TRACE("CConn_Streambuf::~CConn_Streambuf(): " "CONN_Close() failed (" << IO_StatusStr(status) << ")"); } if (m_ReadBuf != &x_Buf) delete[] m_ReadBuf;}CT_INT_TYPE CConn_Streambuf::overflow(CT_INT_TYPE c){ if ( !m_Conn ) return CT_EOF; if ( m_WriteBuf ) { // send buffer size_t n_write = pptr() - m_WriteBuf; if ( n_write ) { size_t n_written; n_write *= sizeof(CT_CHAR_TYPE); LOG_IF_ERROR(CONN_Write(m_Conn, m_WriteBuf, n_write, &n_written, eIO_WritePlain), "overflow(): CONN_Write() failed"); if ( !n_written ) return CT_EOF; n_written /= sizeof(CT_CHAR_TYPE); // update buffer content (get rid of data just sent) if (n_written != n_write) { memmove(m_WriteBuf, m_WriteBuf + n_written, (n_write - n_written)*sizeof(CT_CHAR_TYPE)); } x_Pos += (CT_OFF_TYPE)(n_written); setp(m_WriteBuf + n_write - n_written, m_WriteBuf + m_BufSize); } // store char return CT_EQ_INT_TYPE(c, CT_EOF) ? CT_NOT_EOF(CT_EOF) : sputc(CT_TO_CHAR_TYPE(c)); } if ( !CT_EQ_INT_TYPE(c, CT_EOF) ) { // send char size_t n_written; CT_CHAR_TYPE b = CT_TO_CHAR_TYPE(c); LOG_IF_ERROR(CONN_Write(m_Conn, &b, sizeof(b), &n_written, eIO_WritePlain), "overflow(): CONN_Write(1) failed"); return n_written == sizeof(b) ? c : CT_EOF; } else if (CONN_Flush(m_Conn) != eIO_Success) return CT_EOF; return CT_NOT_EOF(CT_EOF);}CT_INT_TYPE CConn_Streambuf::underflow(void){ if ( !m_Conn ) return CT_EOF; // flush output buffer, if tied up to it if ( m_Tie ) { _VERIFY(sync() == 0); } _ASSERT(!gptr() || gptr() >= egptr());#ifdef NCBI_COMPILER_MIPSPRO if (m_MIPSPRO_ReadsomeGptrSetLevel && m_MIPSPRO_ReadsomeGptr != gptr()) return CT_EOF; m_MIPSPRO_ReadsomeGptr = (CT_CHAR_TYPE*)(-1L);#endif // read from connection size_t n_read; EIO_Status status = CONN_Read(m_Conn, m_ReadBuf, m_BufSize*sizeof(CT_CHAR_TYPE), &n_read, eIO_ReadPlain); if ( !n_read ) { if (status != eIO_Closed) LOG_IF_ERROR(status, "underflow(): CONN_Read() failed"); return CT_EOF; } // update input buffer with data just read setg(m_ReadBuf, m_ReadBuf, m_ReadBuf + n_read/sizeof(CT_CHAR_TYPE)); return CT_TO_INT_TYPE(*m_ReadBuf);}streamsize CConn_Streambuf::xsgetn(CT_CHAR_TYPE* buf, streamsize m){ if ( !m_Conn ) return 0; // flush output buffer, if tied up to it if ( m_Tie ) { _VERIFY(sync() == 0); } if (m <= 0) return 0; size_t n = (size_t) m; size_t n_read; // read from the memory buffer if (gptr() && gptr() < egptr()) { n_read = egptr() - gptr(); if (n_read > n) n_read = n; memcpy(buf, gptr(), n_read*sizeof(CT_CHAR_TYPE)); gbump((int) n_read); buf += n_read; n -= n_read; } else n_read = 0; if (n == 0) return (streamsize) n_read; do { size_t x_read = n < (size_t) m_BufSize ? m_BufSize : n; CT_CHAR_TYPE* x_buf = n < (size_t) m_BufSize ? m_ReadBuf : buf; EIO_Status status = CONN_Read(m_Conn, x_buf, x_read*sizeof(CT_CHAR_TYPE), &x_read, eIO_ReadPlain); if (!(x_read /= sizeof(CT_CHAR_TYPE))) break; // satisfy "usual backup condition", see standard: 27.5.2.4.3.13 if (x_buf == m_ReadBuf) { size_t xx_read = x_read; if (x_read > n) x_read = n; memcpy(buf, m_ReadBuf, x_read*sizeof(CT_CHAR_TYPE)); setg(m_ReadBuf, m_ReadBuf + x_read, m_ReadBuf + xx_read); } else { _ASSERT(x_read <= n); size_t xx_read = x_read > (size_t) m_BufSize ? m_BufSize : x_read; memcpy(m_ReadBuf,buf+x_read-xx_read,xx_read*sizeof(CT_CHAR_TYPE)); setg(m_ReadBuf, m_ReadBuf + xx_read, m_ReadBuf + xx_read); } n_read += x_read; if (status != eIO_Success) break; buf += x_read; n -= x_read; } while ( n ); return (streamsize) n_read;}streamsize CConn_Streambuf::showmanyc(void){ if ( !m_Conn ) return -1; // flush output buffer, if tied up to it if ( m_Tie ) { _VERIFY(sync() == 0); } _ASSERT(!gptr() || gptr() >= egptr()); switch (CONN_Wait(m_Conn, eIO_Read, CONN_GetTimeout(m_Conn, eIO_Read))) { case eIO_Success: return 1; // can read at least 1 byte case eIO_Closed: return -1; // EOF default: return 0; // no data available immediately }}int CConn_Streambuf::sync(void){ if ( !m_Conn ) return -1; do { if (CT_EQ_INT_TYPE(overflow(CT_EOF), CT_EOF)) return -1; } while (m_WriteBuf && pptr() > m_WriteBuf); return 0;}CNcbiStreambuf* CConn_Streambuf::setbuf(CT_CHAR_TYPE* /*buf*/, streamsize /*buf_size*/){ NCBI_THROW(CConnException, eConn, "CConn_Streambuf::setbuf() not allowed"); /*NOTREACHED*/ return this; /*dummy for compiler*/}CT_POS_TYPE CConn_Streambuf::seekoff(CT_OFF_TYPE off, IOS_BASE::seekdir whence, IOS_BASE::openmode which){ if (off == 0 && whence == IOS_BASE::cur && which == IOS_BASE::out) return x_Pos + (CT_OFF_TYPE)(pptr() ? pptr() - m_WriteBuf : 0); return (CT_POS_TYPE)((CT_OFF_TYPE)(-1));}EIO_Status CConn_Streambuf::x_LogIfError(const char* file, int line, EIO_Status status, const string& msg){ if (status != eIO_Success) { CNcbiDiag(file, line) << "CConn_Streambuf::" << msg << " (" << IO_StatusStr(status) << ")" << Endm; } return status;}END_NCBI_SCOPE/* * --------------------------------------------------------------------------- * $Log: ncbi_conn_streambuf.cpp,v $ * Revision 1000.5 2004/06/01 18:44:44 gouriano * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R6.46 * * Revision 6.46 2004/05/17 20:58:13 gorelenk * Added include of PCH ncbi_pch.hpp * * Revision 6.45 2004/02/23 15:23:39 lavr * New (last) parameter "how" added in CONN_Write() API call * * Revision 6.44 2004/01/14 22:21:39 vasilche * Removed duplicate default arguments. * * Revision 6.43 2004/01/14 20:24:29 lavr * CConnStreambuf::seekoff(0, cur, out) added and implemented * * Revision 6.42 2004/01/09 17:39:15 lavr * Define and use internal 1-byte buffer for unbuffered streams' get ops * * Revision 6.41 2003/11/12 17:45:20 lavr * Minor cosmetic fix * * Revision 6.40 2003/11/12 16:40:13 ivanov * Fixed initial setup of get pointers (by Anton Lavrentiev) * * Revision 6.39 2003/11/04 03:09:28 lavr * xsgetn() fixed to advance buffer pointer when reading * * Revision 6.38 2003/11/03 20:06:49 lavr * Fix log message of the previous commit: * CConn_Streambuf::xsgetn() made standard-conforming * * Revision 6.36 2003/10/22 18:16:09 lavr * More consistent use of buffer pointers in the implementation * * Revision 6.35 2003/10/07 19:59:40 lavr * Replace '==' with (better) 'CT_EQ_INT_TYPE' * * Revision 6.34 2003/09/23 21:05:50 lavr * Rearranged included headers * * Revision 6.33 2003/05/31 05:24:43 lavr * NOTREACHED added after exception throw * * Revision 6.32 2003/05/20 19:07:57 lavr * Constructor changed (assert -> _ASSERT); better destructor * * Revision 6.31 2003/05/20 18:24:06 lavr * Set non-zero ptrs (but still empty buf) in constructor to explicitly show * (to the stream level) that this streambuf has a memory-resident buffer * * Revision 6.30 2003/05/20 18:05:53 lavr * x_LogIfError() to accept and print approproate file location * * Revision 6.29 2003/05/20 16:46:29 lavr * Check for NULL connection in every streambuf method before proceding * * Revision 6.28 2003/05/12 18:32:27 lavr * Modified not to throw exceptions from stream buffer; few more improvements * * Revision 6.27 2003/04/25 15:20:37 lavr * Avoid GCC signed/unsigned warning by explicit cast * * Revision 6.26 2003/04/11 17:57:11 lavr * Define xsgetn() unconditionally * * Revision 6.25 2003/03/30 07:00:09 lavr * MIPS-specific workaround for lamely-designed stream read ops * * Revision 6.24 2003/03/28 03:58:08 lavr * CConn_Streambuf::xsgetn(): tiny formal fix in backup condition * * Revision 6.23 2003/03/28 03:30:36 lavr * Define CConn_Streambuf::xsgetn() unconditionally of compiler * * Revision 6.22 2002/12/19 17:24:08 lavr * Take advantage of new CConnException * * Revision 6.21 2002/10/28 15:46:20 lavr * Use "ncbi_ansi_ext.h" privately * * Revision 6.20 2002/08/28 03:40:54 lavr * Better buffer filling in xsgetn() * * Revision 6.19 2002/08/27 20:27:36 lavr * xsgetn(): if reading from external source try to pull as much as possible * * Revision 6.18 2002/08/07 16:32:12 lavr * Changed EIO_ReadMethod enums accordingly * * Revision 6.17 2002/06/06 19:03:25 lavr * Take advantage of CConn_Exception class and do not throw from destructor * Some housekeeping: log moved to the end * * Revision 6.16 2002/02/05 22:04:12 lavr * Included header files rearranged * * Revision 6.15 2002/02/05 16:05:26 lavr * List of included header files revised * * Revision 6.14 2002/02/04 20:19:55 lavr * +xsgetn() for MIPSPro compiler (buggy version supplied with std.library) * More assert()'s inserted into the code to check standard compliance * * Revision 6.13 2002/01/30 20:09:00 lavr * Define xsgetn() for WorkShop compiler also; few patches in underflow(); * sync() properly redesigned (now standard-conformant) * * Revision 6.12 2002/01/28 20:20:18 lavr * Use auto_ptr only in constructor; satisfy "usual backup cond" in xsgetn() * * Revision 6.11 2001/12/07 22:58:44 lavr * More comments added * * Revision 6.10 2001/05/29 19:35:21 grichenk * Fixed non-blocking stream reading for GCC * * Revision 6.9 2001/05/17 15:02:50 lavr * Typos corrected * * Revision 6.8 2001/05/14 16:47:45 lavr * streambuf::xsgetn commented out as it badly interferes * with truly-blocking stream reading via istream::read. * * Revision 6.7 2001/05/11 20:40:48 lavr * Workaround of compiler warning about comparison of streamsize and size_t * * Revision 6.6 2001/05/11 14:04:07 grichenk * +CConn_Streambuf::xsgetn(), +CConn_Streambuf::showmanyc() * * Revision 6.5 2001/03/26 18:36:39 lavr * CT_EQ_INT_TYPE used throughout to compare CT_INT_TYPE values * * Revision 6.4 2001/03/24 00:34:40 lavr * Accurate conversions between CT_CHAR_TYPE and CT_INT_TYPE * (BUGFIX: promotion of (signed char)255 to int caused EOF (-1) gets returned) * * Revision 6.3 2001/01/12 23:49:20 lavr * Timeout and GetCONN method added * * Revision 6.2 2001/01/11 23:04:06 lavr * Bugfixes; tie is now done at streambuf level, not in iostream * * Revision 6.1 2001/01/09 23:34:51 vakatov * Initial revision (draft, not tested in run-time) * * =========================================================================== */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -