1 // ANNA - Anna is Not Nothingness Anymore
3 // (c) Copyright 2005-2014 Eduardo Ramos Testillano & Francisco Ruiz Rayo
5 // http://redmine.teslayout.com/projects/anna-suite
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions
11 // * Redistributions of source code must retain the above copyright
12 // notice, this list of conditions and the following disclaimer.
13 // * Redistributions in binary form must reproduce the above
14 // copyright notice, this list of conditions and the following disclaimer
15 // in the documentation and/or other materials provided with the
17 // * Neither the name of the copyright holder nor the names of its
18 // contributors may be used to endorse or promote products derived from
19 // this software without specific prior written permission.
21 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 // Authors: eduardo.ramos.testillano@gmail.com
34 // cisco.tierra@gmail.com
40 #include <anna/core/DataBlock.hpp>
41 #include <anna/core/RuntimeException.hpp>
42 #include <anna/core/functions.hpp>
47 #define anna_call_extend(a) \
48 if ((a_size + (a)) >= a_maxSize) extend ((a));
50 DataBlock::DataBlock(const char* buffer, const int size, const bool deepCopy)
51 throw(RuntimeException) :
56 initialize(buffer, size);
59 DataBlock::DataBlock(const DataBlock& other)
60 throw(RuntimeException) :
63 a_deepCopy(other.a_deepCopy),
65 initialize(other.a_buffer, other.a_size);
68 DataBlock::~DataBlock() {
73 void DataBlock::initialize(const char* buffer, const int size)
74 throw(RuntimeException) {
75 if(a_deepCopy == false) {
76 a_buffer = const_cast <char*>(buffer);
79 if((a_maxSize = a_size = size) > 0) {
80 if((a_buffer = new char [size]) != NULL)
81 anna_memcpy(a_buffer, buffer, size);
83 throw RuntimeException("Insufficient memory", ANNA_FILE_LOCATION);
89 void DataBlock::setSize(const int size)
90 throw(RuntimeException) {
91 // if (size > a_maxSize) {
92 // string msg ("DataBlock::setSize | MaxSize: ");
93 // msg += functions::asString (a_maxSize);
94 // msg += " | Size: ";
95 // msg += functions::asString (size);
96 // msg += " | Invalid size";
97 // throw RuntimeException (msg, ANNA_FILE_LOCATION);
100 // a_currentMessage.assign (a_buffer.getData () + a_offset, remainingSize);
102 // Sin embargo, el fetch() de nuestro clientSocket hace esto:
103 // a_buffer.setup (a_data.getData () + a_offset, remainingSize);
105 // Y el setup no hace reserva, solo asocia (buffer y size)
109 void DataBlock::allocate(const int nbytes)
110 throw(RuntimeException) {
111 if(nbytes > a_size) {
113 if(a_deepCopy == false)
114 throw RuntimeException("Deep-Copy was not active", ANNA_FILE_LOCATION);
116 if((a_buffer = new char [a_maxSize = nbytes]) == NULL)
117 throw RuntimeException("Insufficient memory", ANNA_FILE_LOCATION);
119 extend(nbytes - a_size);
125 void DataBlock::assign(const char* buffer, const int size)
126 throw(RuntimeException) {
127 if(a_deepCopy == false) {
128 a_buffer = const_cast <char*>(buffer);
132 a_maxSize = a_size = 0;
133 initialize(buffer, size);
137 DataBlock& DataBlock::operator = (const DataBlock & right)
138 throw(RuntimeException) {
142 append(right.a_buffer, right.a_size);
144 a_buffer = right.a_buffer;
145 a_size = right.a_size;
152 const char DataBlock::operator [](const int pos) const
153 throw(RuntimeException) {
155 std::string msg("Position: ");
156 msg += functions::asString(pos);
157 msg += " | Out of range [0,";
158 msg += functions::asString(a_size);
160 throw RuntimeException(msg, ANNA_FILE_LOCATION);
163 return a_buffer [pos];
166 char& DataBlock::operator [](const int pos)
167 throw(RuntimeException) {
169 std::string msg("Position: ");
170 msg += functions::asString(pos);
171 msg += " | Out of range [0,";
172 msg += functions::asString(a_size);
174 throw RuntimeException(msg, ANNA_FILE_LOCATION);
177 char* aux = const_cast <char*>(a_buffer);
181 void DataBlock::append(const char* data, const int len)
182 throw(RuntimeException) {
183 if(a_buffer == data && data != NULL && len > 0)
184 throw RuntimeException("Can not append myself", ANNA_FILE_LOCATION);
186 if((a_size + len) >= a_maxSize) extend(len);
188 char* w = a_buffer + a_size;
192 case 1: *w = *data; a_size ++; break;
193 case 2: *w = *data; *(w + 1) = *(data + 1); a_size += 2; break;
194 case 3: *w = *data; *(w + 1) = *(data + 1); *(w + 2) = *(data + 2); a_size += 3; break;
195 case 4: *w = *data; *(w + 1) = *(data + 1); *(w + 2) = *(data + 2); *(w + 3) = *(data + 3); a_size += 4; break;
196 default: anna_memcpy(w, data, len); a_size += len; break;
200 void DataBlock::remove(const int pos, const int nbytes)
201 throw(RuntimeException) {
202 if(a_deepCopy == false)
203 throw RuntimeException("Deep copy not activated", ANNA_FILE_LOCATION);
205 if(pos >= a_size || pos < 0)
206 throw RuntimeException("Position to remove is out of range", ANNA_FILE_LOCATION);
208 const int nbytesToMove = a_size - (pos + nbytes);
211 throw RuntimeException("nbytes to remove are out of range", ANNA_FILE_LOCATION);
214 anna_memmove(a_buffer + pos, a_buffer + pos + nbytes, nbytesToMove);
219 void DataBlock::remove(const int nbytes)
220 throw(RuntimeException) {
221 if(a_deepCopy == false)
222 throw RuntimeException("Deep copy not activated", ANNA_FILE_LOCATION);
227 const int nbytesToMove = a_size - nbytes;
230 throw RuntimeException("nbytes to remove are out of range", ANNA_FILE_LOCATION);
233 anna_memmove(a_buffer, a_buffer + nbytes, nbytesToMove);
238 void DataBlock::extend(const int nbytes)
239 throw(RuntimeException) {
240 if(a_deepCopy == false)
241 throw RuntimeException("Deep copy not activated", ANNA_FILE_LOCATION);
243 if((a_size + nbytes) < a_maxSize)
246 int newSize = ((a_size + nbytes) << 1) - ((a_size + nbytes) >> 1);
247 char* newBuffer = new char [newSize];
249 if(newBuffer == NULL)
250 throw RuntimeException("Insufficient memory", ANNA_FILE_LOCATION);
253 anna_memcpy(newBuffer, a_buffer, a_size);
256 a_buffer = newBuffer;
260 std::string DataBlock::asString(const int characterByLine) const
264 std::string characters;
275 result += functions::asHexString(anna_ptrnumber_cast(a_buffer));
278 for(i = 0; i < a_size; i ++) {
279 if((i % characterByLine) == 0) {
284 result += characters;
288 sprintf(aux, "%4d: ", i);
292 c = (unsigned char) a_buffer [i];
293 sprintf(aux, "%02x ", c);
295 characters += (isprint(c) ? (char) c : '.');
301 while((i % characterByLine) != 0) {
307 return result += characters;