⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 stream_utils.cpp

📁 ncbi源码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* * =========================================================================== * PRODUCTION $Log: stream_utils.cpp,v $ * PRODUCTION Revision 1000.4  2004/06/01 19:40:35  gouriano * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.42 * PRODUCTION * =========================================================================== *//*  $Id: stream_utils.cpp,v 1000.4 2004/06/01 19:40:35 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: *   Stream utilities: *   1. Push an arbitrary block of data back to a C++ input stream. *   2. Non-blocking read. * */#include <ncbi_pch.hpp>#include <corelib/ncbistd.hpp>#include <util/util_exception.hpp>#include <util/stream_utils.hpp>#include <string.h>#ifdef NCBI_COMPILER_MIPSPRO#  define CPushback_StreambufBase CMIPSPRO_ReadsomeTolerantStreambuf#else#  define CPushback_StreambufBase CNcbiStreambuf#endif //NCBI_COMPILER_MIPSPRO#ifdef HAVE_GOOD_IOS_CALLBACKS#  undef  HAVE_GOOD_IOS_CALLBACKS#endif#if defined(HAVE_IOS_REGISTER_CALLBACK)  &&  \  (!defined(NCBI_COMPILER_WORKSHOP)  ||  !defined(_MT))#  define HAVE_GOOD_IOS_CALLBACKS 1#endifBEGIN_NCBI_SCOPE/***************************************************************************** *  Helper class: internal streambuf to be substituted instead of *  the original one in the stream, when the data are pushed back. */class CPushback_Streambuf : public CPushback_StreambufBase{    friend struct CStreamUtils;public:    CPushback_Streambuf(istream& istream, CT_CHAR_TYPE* buf,                        streamsize buf_size, void* del_ptr);    virtual ~CPushback_Streambuf();protected:    virtual CT_POS_TYPE seekoff(CT_OFF_TYPE off, IOS_BASE::seekdir whence,                                IOS_BASE::openmode which);    virtual CT_POS_TYPE seekpos(CT_POS_TYPE pos, IOS_BASE::openmode which);    virtual CT_INT_TYPE overflow(CT_INT_TYPE c);    virtual streamsize  xsputn(const CT_CHAR_TYPE* buf, streamsize n);    virtual CT_INT_TYPE underflow(void);    virtual streamsize  xsgetn(CT_CHAR_TYPE* buf, streamsize n);    virtual streamsize  showmanyc(void);    virtual CT_INT_TYPE pbackfail(CT_INT_TYPE c = CT_EOF);    virtual int         sync(void);    // declared setbuf here to only throw an exception at run-time    virtual streambuf*  setbuf(CT_CHAR_TYPE* buf, streamsize buf_size);private:    void                x_FillBuffer(streamsize max_size);    void                x_DropBuffer(void);    istream&            m_Is;      // I/O stream this streambuf is attached to    streambuf*          m_Sb;      // original streambuf    CT_CHAR_TYPE*       m_Buf;     // == 0 when the buffer has been emptied    streamsize          m_BufSize;    void*               m_DelPtr;#ifdef HAVE_GOOD_IOS_CALLBACKS    int                 m_Index;    static void         x_Callback(IOS_BASE::event, IOS_BASE&, int);#endif //HAVE_GOOD_IOS_CALLBACKS    static const streamsize k_MinBufSize;};const streamsize CPushback_Streambuf::k_MinBufSize = 4096;#ifdef HAVE_GOOD_IOS_CALLBACKSvoid CPushback_Streambuf::x_Callback(IOS_BASE::event event,                                     IOS_BASE&       ios,                                     int             index){    if (event == IOS_BASE::erase_event)        delete static_cast<streambuf*> (ios.pword(index));}#endif //HAVE_GOOD_IOS_CALLBACKSCPushback_Streambuf::CPushback_Streambuf(istream&      is,                                         CT_CHAR_TYPE* buf,                                         streamsize    buf_size,                                         void*         del_ptr) :    m_Is(is), m_Buf(buf), m_BufSize(buf_size), m_DelPtr(del_ptr){    setp(0, 0); // unbuffered output at this level of streambuf's hierarchy    setg(m_Buf, m_Buf, m_Buf + m_BufSize);    m_Sb = m_Is.rdbuf(this);#ifdef HAVE_GOOD_IOS_CALLBACKS    try {        m_Index             = m_Is.xalloc();        m_Is.pword(m_Index) = this;        m_Is.register_callback(x_Callback, m_Index);    }    STD_CATCH_ALL("CPushback_Streambuf::CPushback_Streambuf");#endif //HAVE_GOOD_IOS_CALLBACKS}CPushback_Streambuf::~CPushback_Streambuf(){#ifdef HAVE_GOOD_IOS_CALLBACKS    m_Is.pword(m_Index) = 0;#endif //HAVE_GOOD_IOS_CALLBACKS    delete[] (CT_CHAR_TYPE*) m_DelPtr;    if (m_Sb) {        m_Is.rdbuf(m_Sb);        if (dynamic_cast<CPushback_Streambuf*> (m_Sb))            delete m_Sb;    }}CT_POS_TYPE CPushback_Streambuf::seekoff(CT_OFF_TYPE off,                                         IOS_BASE::seekdir whence,                                         IOS_BASE::openmode which){    x_DropBuffer();    if (whence == ios::cur  &&  (which & ios::in)) {        return (CT_POS_TYPE)((CT_OFF_TYPE)(-1));    }    return m_Sb->PUBSEEKOFF(off, whence, which);}CT_POS_TYPE CPushback_Streambuf::seekpos(CT_POS_TYPE pos,                                         IOS_BASE::openmode which){    x_DropBuffer();    return m_Sb->PUBSEEKPOS(pos, which);}CT_INT_TYPE CPushback_Streambuf::overflow(CT_INT_TYPE c){    if ( !CT_EQ_INT_TYPE(c, CT_EOF) ) {        return m_Sb->sputc(CT_TO_CHAR_TYPE(c));    }    return m_Sb->PUBSYNC() == 0 ? CT_NOT_EOF(CT_EOF) : CT_EOF;}streamsize CPushback_Streambuf::xsputn(const CT_CHAR_TYPE* buf, streamsize n){    // hope that this is an optimized copy operation (instead of overflow()s)    return m_Sb->sputn(buf, n);}CT_INT_TYPE CPushback_Streambuf::underflow(void){    // we are here because there is no more data in the pushback buffer    _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 //NCBI_COMPILER_MIPSPRO    x_FillBuffer(m_Sb->in_avail());    return gptr() < egptr() ? CT_TO_INT_TYPE(*gptr()) : CT_EOF;}streamsize CPushback_Streambuf::xsgetn(CT_CHAR_TYPE* buf, streamsize m){    size_t n_total = 0;    while (m) {        if (gptr() < egptr()) {            size_t n       = (size_t) m;            size_t n_avail = (size_t) (egptr() - gptr());            size_t n_read  = (n <= n_avail) ? n : n_avail;            memcpy(buf, gptr(), n_read*sizeof(CT_CHAR_TYPE));            gbump((int) n_read);            m       -= (streamsize) n_read;            buf     += (streamsize) n_read;            n_total += (streamsize) n_read;        } else {            x_FillBuffer(m);            if (gptr() >= egptr())                break;        }    }    return n_total;}streamsize CPushback_Streambuf::showmanyc(void){    // we are here because (according to the standard) gptr() >= egptr()    _ASSERT(gptr()  &&  gptr() >= egptr());    return m_Sb->in_avail();}CT_INT_TYPE CPushback_Streambuf::pbackfail(CT_INT_TYPE /*c*/){    /* We always maintain "usual backup condition" (27.5.2.4.3.13) after     * underflow(), i.e. 1 byte backup after a good read is always possible.     * That is, this function gets called only if the user tries to     * back up more than once (although, some attempts may be successful,     * this function call denotes that the backup area is full).     */    return CT_EOF; // always fail}int CPushback_Streambuf::sync(void){    return m_Sb->PUBSYNC();}streambuf* CPushback_Streambuf::setbuf(CT_CHAR_TYPE* /*buf*/,                                       streamsize    /*buf_size*/){    NCBI_THROW(CUtilException, eWrongCommand,               "CPushback_Streambuf::setbuf: not allowed");    /*NOTREACHED*/    return this;}void CPushback_Streambuf::x_FillBuffer(streamsize max_size){    _ASSERT(m_Sb);    if ( !max_size )        ++max_size;    CPushback_Streambuf* sb = dynamic_cast<CPushback_Streambuf*> (m_Sb);    if ( sb ) {        _ASSERT(&m_Is == &sb->m_Is);        m_Sb     = sb->m_Sb;        sb->m_Sb = 0;        if (sb->gptr() >= sb->egptr()) {            delete sb;            x_FillBuffer(max_size);            return;        }        delete[] (CT_CHAR_TYPE*) m_DelPtr;        m_Buf        = sb->m_Buf;        m_BufSize    = sb->m_BufSize;        m_DelPtr     = sb->m_DelPtr;        sb->m_DelPtr = 0;        setg(sb->gptr(), sb->gptr(), sb->egptr());        delete sb;    } else {        CT_CHAR_TYPE* bp = 0;        streamsize buf_size = m_DelPtr            ? (streamsize)(m_Buf - (CT_CHAR_TYPE*) m_DelPtr) + m_BufSize : 0;        if (buf_size < k_MinBufSize) {            buf_size = k_MinBufSize;            bp = new CT_CHAR_TYPE[buf_size];        }        streamsize n = m_Sb->sgetn(bp ? bp : (CT_CHAR_TYPE*) m_DelPtr,                                   min(buf_size, max_size));        if (n <= 0) {            // NB: For unknown reasons WorkShop6 can return -1 from sgetn :-/            delete bp;            return;        }        if (bp) {            delete[] (CT_CHAR_TYPE*) m_DelPtr;            m_DelPtr = bp;        }        m_Buf = (CT_CHAR_TYPE*) m_DelPtr;        m_BufSize = buf_size;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -