// -*- c++ -*- //------------------------------------------------------------------------------ // CharInBuffer.h //------------------------------------------------------------------------------ // Copyright (C) 2002,2005 Vladislav Grinchenko // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. //------------------------------------------------------------------------------ #ifndef CHAR_IN_BUFFER_H #define CHAR_IN_BUFFER_H /** @file CharInBuffer.h A bucket for collecting character-based stream records of certain length or terminated by designated character(s). */ #include #include "assa/Assure.h" #include "assa/Socket.h" #include using std::string; namespace ASSA { /** * CharInBuffer is a bucket for the character-based streams/messages. * It helps in reading, parsing, and storing record-oriented character * streams from Socket stream asynchronously. The record terminator can * be multibyte. The terminator is detected and removed from the bucket. * When terminator is detected, the block of characters collected in the bucket * is ready to be processed further by the application according to its * communication protocol. * If either Socket read() error is encountered, or an overflow occurs * (number of characters read exceeds the maximum limit), the object goes into * the error state and won't accept further input, unless reset. */ class CharInBuffer { public: /** Constructor * @param size_ Maximum expected size before buffer overflow * @param delimiter_ End-of-record character(s). Can be multi-byte. */ CharInBuffer (size_t size_, const string& delimiter_); /** Read bytes from Socket stream until either record delimiter is * detected, or EOF occured, or Socket stream is exhausted. * @return Socket reference */ friend ASSA::Socket& operator>>(ASSA::Socket&, ASSA::CharInBuffer&); /** Test the state of an object * @return true if the object holds a complete message; * false otherwise (eof, buffer overflow, or incomplete) */ operator void* () const; /// Get the constant character pointer to the buffer const char* c_str () const { return m_buffer.c_str (); } /// Bytes in the buffer so far size_t length () const { return m_buffer.length (); } /// Bytes in the buffer so far size_t size () const { return m_buffer.size (); } /** Discard all accumulated characters and be ready to receive * a new message. */ void reset (); /// Write the state of an object to the log file. void dump () const; /** @enum state_t * States: start, waiting, complete, error */ enum state_t { start, /**< start state */ waiting, /**< incomplete record is in the buffer */ complete, /**< matched end-of-record - full record */ error /**< overflow or Socket I/O error */ }; /// Report the current state of the object state_t state () const { return m_state; } private: /// Report the state name static const char* state_name (state_t state_); /// Go to the new state void state (state_t new_state_) { m_state = new_state_; } /// Remove the delimiter from the end of the buffer void chop (); private: /// Internal state of an object state_t m_state; /// Buffer to store the bytes received std::string m_buffer; /// Maximum allowable size (delimiter included) before overflow occurs size_t m_max_size; /// Delimiter. Multibyte delimiter is allowed. std::string m_delimiter; }; } // end namespace ASSA /******************************************************************************* Inline member functions *******************************************************************************/ using namespace ASSA; inline CharInBuffer:: operator void* () const { return (m_state == complete ? (void *) (-1) // good state : (void *) 0); // bad state } inline void CharInBuffer:: reset () { m_buffer = ""; state (waiting); } inline void CharInBuffer:: chop () { m_buffer.replace (m_buffer.find (m_delimiter), m_delimiter.length (), ""); } #endif /* CHAR_IN_BUFFER_H */