File: CharInBuffer.cpp

package info (click to toggle)
libassa 3.5.1-2
  • links: PTS, VCS
  • area: main
  • in suites: wheezy
  • size: 3,268 kB
  • sloc: cpp: 15,703; sh: 12,083; makefile: 379; perl: 51
file content (118 lines) | stat: -rw-r--r-- 3,179 bytes parent folder | download | duplicates (9)
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