// -*- c++ -*- //------------------------------------------------------------------------------ // CharInBuffer.cpp //------------------------------------------------------------------------------ // Copyright (C) 2002 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. //------------------------------------------------------------------------------ #include #include "assa/CharInBuffer.h" #include "assa/MemDump.h" #include "assa/Logger.h" using namespace ASSA; /******************************************************************************* Member functions *******************************************************************************/ CharInBuffer:: CharInBuffer (size_t size_, const string& delimiter_) : m_state (start), m_max_size (size_), m_delimiter (delimiter_) { trace_with_mask ("CharInBuffer::CharInBuffer", CHARINBUF); if (m_max_size == 0 || m_delimiter.length () == 0) { state (error); } state (waiting); } const char* CharInBuffer:: state_name (state_t state_) { static const char* vmsg[] = { "start", "waiting", "complete", "error", "unknown state" }; if (state_ < CharInBuffer::start || state_ > CharInBuffer::error) { return vmsg [sizeof (vmsg)-1]; } return vmsg [state_]; } void CharInBuffer:: dump () const { DL((CHARINBUF,"== CharInBuffer state ==\n")); DL((CHARINBUF,"m_state = %s\n", state_name (m_state))); DL((CHARINBUF,"m_max_size = %d\n", m_max_size)); MemDump::dump_to_log (TRACE, "m_delimiter:\n", m_delimiter.c_str (), m_delimiter.length ()); MemDump::dump_to_log (TRACE, "m_buffer:\n", m_buffer.c_str (), m_buffer.length ()); DL((CHARINBUF,"========================\n")); } namespace ASSA { /** * Regardless of the delimeter size, which can be >1, add the character * received to the buffer and compare the end of the buffer with the * delimeter. * * If match, bite off delimiter and set the state to complete. * If not, continue reading till either there is no more characters to read, * or Socket error (Fail or EOF), or buffer overflow. * If overflow occurs, set the state to 'error' and terminate. * */ Socket& operator>> (Socket& s_, CharInBuffer& b_) { trace_with_mask ("Socket >> CharInBuffer", CHARINBUF); register char c; if (b_.state () != CharInBuffer::waiting) { DL((CHARINBUF,"Wrong state %s\n", b_.state_name (b_.state ()))); return s_; } while (s_.read (&c, 1) == 1) { b_.m_buffer += c; if (b_.m_buffer.size() < b_.m_delimiter.size()) { // Bug # 1252926 continue; } if (b_.m_buffer.substr ( b_.m_buffer.size ()-b_.m_delimiter.size ()) == b_.m_delimiter) { b_.chop (); b_.m_state = CharInBuffer::complete; return s_; } if (b_.m_buffer.length () >= b_.m_max_size) { b_.m_state = CharInBuffer::error; break; } } if (!s_) { // EOF or error b_.state (CharInBuffer::error); } return s_; } } // end namespace ASSA