1 // ANNA - Anna is Not Nothingness Anymore //
3 // (c) Copyright 2005-2015 Eduardo Ramos Testillano & Francisco Ruiz Rayo //
5 // See project site at http://redmine.teslayout.com/projects/anna-suite //
6 // See accompanying file LICENSE or copy at http://www.teslayout.com/projects/public/anna.LICENSE //
12 #include <anna/core/DataBlock.hpp>
13 #include <anna/core/RuntimeException.hpp>
14 #include <anna/core/functions.hpp>
19 #define anna_call_extend(a) \
20 if ((a_size + (a)) >= a_maxSize) extend ((a));
22 DataBlock::DataBlock(const char* buffer, const int size, const bool deepCopy)
23 throw(RuntimeException) :
28 initialize(buffer, size);
31 DataBlock::DataBlock(const DataBlock& other)
32 throw(RuntimeException) :
35 a_deepCopy(other.a_deepCopy),
37 initialize(other.a_buffer, other.a_size);
40 DataBlock::~DataBlock() {
45 void DataBlock::initialize(const char* buffer, const int size)
46 throw(RuntimeException) {
47 if(a_deepCopy == false) {
48 a_buffer = const_cast <char*>(buffer);
51 if((a_maxSize = a_size = size) > 0) {
52 if((a_buffer = new char [size]) != NULL)
53 anna_memcpy(a_buffer, buffer, size);
55 throw RuntimeException("Insufficient memory", ANNA_FILE_LOCATION);
61 void DataBlock::setSize(const int size)
62 throw(RuntimeException) {
63 // if (size > a_maxSize) {
64 // string msg ("DataBlock::setSize | MaxSize: ");
65 // msg += functions::asString (a_maxSize);
66 // msg += " | Size: ";
67 // msg += functions::asString (size);
68 // msg += " | Invalid size";
69 // throw RuntimeException (msg, ANNA_FILE_LOCATION);
72 // a_currentMessage.assign (a_buffer.getData () + a_offset, remainingSize);
74 // Sin embargo, el fetch() de nuestro clientSocket hace esto:
75 // a_buffer.setup (a_data.getData () + a_offset, remainingSize);
77 // Y el setup no hace reserva, solo asocia (buffer y size)
81 void DataBlock::allocate(const int nbytes)
82 throw(RuntimeException) {
85 if(a_deepCopy == false)
86 throw RuntimeException("Deep-Copy was not active", ANNA_FILE_LOCATION);
88 if((a_buffer = new char [a_maxSize = nbytes]) == NULL)
89 throw RuntimeException("Insufficient memory", ANNA_FILE_LOCATION);
91 extend(nbytes - a_size);
97 void DataBlock::assign(const char* buffer, const int size)
98 throw(RuntimeException) {
99 if(a_deepCopy == false) {
100 a_buffer = const_cast <char*>(buffer);
104 a_maxSize = a_size = 0;
105 initialize(buffer, size);
109 DataBlock& DataBlock::operator = (const DataBlock & right)
110 throw(RuntimeException) {
114 append(right.a_buffer, right.a_size);
116 a_buffer = right.a_buffer;
117 a_size = right.a_size;
124 const char DataBlock::operator [](const int pos) const
125 throw(RuntimeException) {
127 std::string msg("Position: ");
128 msg += functions::asString(pos);
129 msg += " | Out of range [0,";
130 msg += functions::asString(a_size);
132 throw RuntimeException(msg, ANNA_FILE_LOCATION);
135 return a_buffer [pos];
138 char& DataBlock::operator [](const int pos)
139 throw(RuntimeException) {
141 std::string msg("Position: ");
142 msg += functions::asString(pos);
143 msg += " | Out of range [0,";
144 msg += functions::asString(a_size);
146 throw RuntimeException(msg, ANNA_FILE_LOCATION);
149 char* aux = const_cast <char*>(a_buffer);
153 void DataBlock::append(const char* data, const int len)
154 throw(RuntimeException) {
155 if(a_buffer == data && data != NULL && len > 0)
156 throw RuntimeException("Can not append myself", ANNA_FILE_LOCATION);
158 if((a_size + len) >= a_maxSize) extend(len);
160 char* w = a_buffer + a_size;
164 case 1: *w = *data; a_size ++; break;
165 case 2: *w = *data; *(w + 1) = *(data + 1); a_size += 2; break;
166 case 3: *w = *data; *(w + 1) = *(data + 1); *(w + 2) = *(data + 2); a_size += 3; break;
167 case 4: *w = *data; *(w + 1) = *(data + 1); *(w + 2) = *(data + 2); *(w + 3) = *(data + 3); a_size += 4; break;
168 default: anna_memcpy(w, data, len); a_size += len; break;
172 void DataBlock::remove(const int pos, const int nbytes)
173 throw(RuntimeException) {
174 if(a_deepCopy == false)
175 throw RuntimeException("Deep copy not activated", ANNA_FILE_LOCATION);
177 if(pos >= a_size || pos < 0)
178 throw RuntimeException("Position to remove is out of range", ANNA_FILE_LOCATION);
180 const int nbytesToMove = a_size - (pos + nbytes);
183 throw RuntimeException("nbytes to remove are out of range", ANNA_FILE_LOCATION);
186 anna_memmove(a_buffer + pos, a_buffer + pos + nbytes, nbytesToMove);
191 void DataBlock::remove(const int nbytes)
192 throw(RuntimeException) {
193 if(a_deepCopy == false)
194 throw RuntimeException("Deep copy not activated", ANNA_FILE_LOCATION);
199 const int nbytesToMove = a_size - nbytes;
202 throw RuntimeException("nbytes to remove are out of range", ANNA_FILE_LOCATION);
205 anna_memmove(a_buffer, a_buffer + nbytes, nbytesToMove);
210 void DataBlock::extend(const int nbytes)
211 throw(RuntimeException) {
212 if(a_deepCopy == false)
213 throw RuntimeException("Deep copy not activated", ANNA_FILE_LOCATION);
215 if((a_size + nbytes) < a_maxSize)
218 int newSize = ((a_size + nbytes) << 1) - ((a_size + nbytes) >> 1);
219 char* newBuffer = new char [newSize];
221 if(newBuffer == NULL)
222 throw RuntimeException("Insufficient memory", ANNA_FILE_LOCATION);
225 anna_memcpy(newBuffer, a_buffer, a_size);
228 a_buffer = newBuffer;
232 std::string DataBlock::asString(const int characterByLine) const
236 std::string characters;
247 result += functions::asHexString(anna_ptrnumber_cast(a_buffer));
250 for(i = 0; i < a_size; i ++) {
251 if((i % characterByLine) == 0) {
256 result += characters;
260 sprintf(aux, "%4d: ", i);
264 c = (unsigned char) a_buffer [i];
265 sprintf(aux, "%02x ", c);
267 characters += (isprint(c) ? (char) c : '.');
273 while((i % characterByLine) != 0) {
279 return result += characters;