1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118
|
// -*- 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 <errno.h>
#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
|