Updated license
[anna.git] / include / anna / core / DataBlock.hpp
1 // ANNA - Anna is Not Nothingness Anymore
2 //
3 // (c) Copyright 2005-2014 Eduardo Ramos Testillano & Francisco Ruiz Rayo
4 //
5 // https://bitbucket.org/testillano/anna
6 //
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions
9 // are met:
10 //
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
16 // distribution.
17 //     * Neither the name of Google Inc. 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.
20 //
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.
32 //
33 // Authors: eduardo.ramos.testillano@gmail.com
34 //          cisco.tierra@gmail.com
35
36
37 #ifndef anna_core_DataBlock_hpp
38 #define anna_core_DataBlock_hpp
39
40 #include <anna/core/RuntimeException.hpp>
41 #include <anna/config/defines.hpp>
42
43 namespace anna {
44
45 /**
46    Optimizacion de acceso a la memoria dinamica.
47
48    Incrementa el rendimiento al acceder y reservar de memoria dinamica mediante la reutilizacion controlada.
49
50    Para optimizar el acceso no se ha establecido ningun tipo de proteccion para ejecucion MT.
51 */
52 class DataBlock {
53 public:
54   /**
55     Constructor.
56
57     @param deepCopy Modo de copia de esta instancia. Si activamos el modo de copia profunda al asignar
58     cualquier otro bloque de memoria a este, se reserva (si fuese necesario) la memoria para ubicar el
59     buffer y despues realizara una copia byte a byte.
60   */
61   explicit DataBlock(const bool deepCopy = false) throw() :
62     a_buffer(NULL),
63     a_size(0),
64     a_deepCopy(deepCopy),
65     a_maxSize(0) {}
66
67   /**
68     Constructor.
69
70     @param buffer Bloque de memoria con el que inicializar el buffer de esta instancia.
71     @param size Numero de bytes del bloque de memoria recibido.
72     @param deepCopy Modo de copia de esta instancia. Si activamos el modo de copia profunda al asignar
73     cualquier otro bloque de memoria a este, se reserva la memoria para ubicar el buffer y despues
74     realizara una copia byte a byte.
75   */
76   DataBlock(const char* buffer, const int size, const bool deepCopy = false) throw(RuntimeException);
77
78   /**
79     Constructor copia.
80     El modo de copia sera el mismo que el establecido por la instancia de la que copiar.
81
82     @param other Bloque de memoria con el que instanciar esta instancia.
83   */
84   DataBlock(const DataBlock& other) throw(RuntimeException);
85
86   /**
87      Destructor.
88   */
89   virtual ~DataBlock();
90
91   // Accesores
92   /**
93      Éste metodo solo debe usarse en aplicaciones mono-thread o en situaciones en las que estemos seguros
94      que esta bloque de datos no puede verse afectado por otro thread.
95
96      @return Tamaño de la memoria reservada por esta instancia.
97   */
98   int getMaxSize() const throw() { return a_maxSize; }
99
100   /**
101      Éste metodo solo debe usarse en aplicaciones mono-thread o en situaciones en las que estemos seguros
102      que esta bloque de datos no puede verse afectado por otro thread.
103
104      @return Tamaño del bloque de memoria contenido actualmente.
105   */
106   int getSize() const throw() { return a_size; }
107
108   /**
109      Éste metodo solo debe usarse en aplicaciones mono-thread o en situaciones en las que estemos seguros
110      que esta bloque de datos no puede verse afectado por otro thread.
111
112      @return El contenido del bloque de memoria.
113   */
114   const char* getData() const throw() { return a_buffer; }
115
116   /**
117      Devuelve informacion acerca del estado de ocupacion de este bloque de memoria.
118
119     @return \em true si el bloque de memoria esta vacio o \em false en otro caso.
120   */
121   bool isEmpty() const throw() { return (a_size == 0) ? true : false; }
122
123   /**
124      Devuelve informacion acerca de la configuracion de reserva de memoria de este bloque.
125
126      @return @em true si el bloque de memoria tiene activado el sistema de copia profunda o @em false en otro caso.
127   */
128   bool deepCopy() const throw() { return a_deepCopy; }
129
130   /**
131      Establece el numero de bytes que tiene asociado a este bloque de datos.
132      \param size numero de bytes que tiene asociado a este bloque de datos.
133      \warning El DataBlock delega la gestion de la memoria a la clase heredada.
134   */
135   void setSize(const int size) throw(RuntimeException);
136
137   /**
138     Anade el caracter recibido al bloque de memoria. Para poder usar este operador el bloque de
139     memoria destino debe tener activado el modo de copia profunda. Si la memoria reservada no es
140     suficiente  reservara automaticamente la cantidad de memoria necesaria.
141
142     @param c Caracter a añadir a este bloque de memoria.
143
144     @returns Una referencia a si mismo.
145   */
146   DataBlock& operator += (const char c) throw(RuntimeException) {
147     append(&c, sizeof(c));
148     return *this;
149   }
150
151   /**
152     Anhade el bloque de memoria recibido. Para poder usar este operador el bloque de memoria
153     destino debe tener activado el modo de copia profunda. Si la memoria reservada no es
154     suficiente reservara automaticamente la cantidad de memoria necesaria.
155
156     @param right Bloque de memoria a añadir a este bloque de memoria.
157
158     @returns Una referencia a si mismo.
159   */
160   DataBlock& operator += (const DataBlock& right) throw(RuntimeException) {
161     if(this != &right)
162       append(right.a_buffer, right.a_size);
163
164     return *this;
165   }
166
167   /**
168     Anade la cadena recibida al bloque de memoria. Para poder usar este operador el bloque de
169     memoria destino debe tener activado el modo de copia profunda. Si la memoria reservada no es
170     suficiente  reservara automaticamente la cantidad de memoria necesaria.
171
172     \param str Cadena a añadir a este bloque de memoria.
173
174     @returns Una referencia a si mismo.
175   */
176   DataBlock& operator += (const std::string& str) throw(RuntimeException) {
177     append(str.c_str(), str.length());
178     return *this;
179   }
180
181   /**
182      Devuelve la posicion i-esima del bloque de datos.
183      \param pos Posicion a la que acceder.
184      \return La posicion i-esima del bloque de datos.
185   */
186   const char operator [](const int pos) const throw(RuntimeException);
187
188   /**
189      Devuelve la posicion i-esima del bloque de datos.
190      \param pos Posicion a la que acceder.
191      \return La posicion i-esima del bloque de datos.
192   */
193   char& operator [](const int pos) throw(RuntimeException);
194
195   /**
196      Anade el bloque de memoria recibido. Para poder usar este operador el bloque de memoria
197      destino debe tener activado el modo de copia profunda. Si la memoria reservada no es
198      suficiente reservara automaticamente la cantidad de memoria necesaria.
199
200      \param data Direccion donde comienza el bloque de datos.
201      \param len Longitud del bloque de datos.
202   */
203   void append(const char* data, const int len) throw(RuntimeException);
204
205   /**
206      Anade el bloque de memoria recibido. Para poder usar este operador el bloque de memoria
207      destino debe tener activado el modo de copia profunda. Si la memoria reservada no es
208      suficiente reservara automaticamente la cantidad de memoria necesaria.
209
210      \param other Bloque de memoria a añadir.
211   */
212   void append(const DataBlock& other) throw(RuntimeException) { append(other.a_buffer, other.a_size); }
213
214   /**
215     Copia el contenido del bloque recibido como parámetro.
216     @param right Bloque de memoria del que copiar.
217     @returns Una referencia a si mismo.
218   */
219   void assign(const DataBlock& right) throw(RuntimeException) { *this = right; }
220
221   /**
222     Copia o direcciona el contenido del bloque recibido como parámetro.
223     \param buffer Dirección de memoria a direcionar.
224     \param size Tamaño de la memoria.
225     @returns Una referencia a si mismo.
226   */
227   void assign(const char* buffer, const int size) throw(RuntimeException);
228
229   /**
230     operador copia. El modo de copiar vendra definido por el modo copia con el que hayamos
231     iniciado la instancia destino.
232     @param right Bloque de memoria del que copiar.
233     @returns Una referencia a si mismo.
234   */
235   DataBlock& operator = (const DataBlock& right) throw(RuntimeException);
236
237   /**
238     Operador de inicializacion. El bloque destino debera tener activado el sistema de
239     copia profunda.
240     @param c Caracter con el que vamos a inicializar el contenido del bloque.
241     @returns Una referencia a si mismo.
242   */
243   DataBlock& operator = (const char c) throw(RuntimeException) { clear(); (*this) += c; return *this; }
244
245   /**
246     Operador de inicializacion. El bloque destino debera tener activado el sistema de
247     copia profunda.
248     @param str Cadena con el que vamos a inicializar el contenido del bloque.
249     @returns Una referencia a si mismo.
250   */
251   DataBlock& operator = (const std::string& str) throw(RuntimeException) { clear(); (*this) += str; return *this; }
252
253   // Metodos
254   /**
255      Reserva el numero de bytes indicado por el parametro recibido. Si la cantidad de memoria preasignada es mayor
256      que la solicitada no se realiza ninguna llamada al sistema operativo.
257
258      @param nbytes Numero de bytes a reservar.
259   */
260   void allocate(const int nbytes) throw(RuntimeException);
261
262   /**
263     La reserva de memoria actual pasa a ser memoria pre-asignada, asi libera el bloque
264     de memoria reservado hasta el momento, pero de forma que si posteriormente vuelve a
265     ser necesario puede reutilizarlo sin tener que volver a realizar una llamada al
266     sistema para obtener memoria dinamica.
267   */
268   void clear() throw(RuntimeException) { a_size = 0; }
269
270   /**
271      Elimina del bloque de memoria unos determinados bytes.
272
273      @param pos Posicion del bloque donde empezar a eliminar.
274      @param nbytes Numero de bytes a descartar a partir de la posicion indicada.
275   */
276   void remove(const int pos, const int nbytes) throw(RuntimeException);
277
278   /**
279      Elimina del bloque de memoria los n primeros bytes.
280      @param nbytes Numero de bytes a descartar a partir de la posicion indicada.
281   */
282   void remove(const int nbytes) throw(RuntimeException);
283
284   /**
285    * Muestra el contenido de este buffer en forma de buffer hexadecimal vs bytes.
286    */
287   std::string asString(const int characterByLine = 24) const throw();
288
289 protected:
290   /**
291      Inicializa el contenido de este bloque de datos. Si fue instancia con copia
292      profunda copia el contenido del buffer, en otro caso solo se queda con el
293      valor de la referencia de memoria a la que apunta.
294
295      @param buffer Bloque de memoria con el que inicializar el buffer de esta instancia.
296      @param size Numero de bytes del bloque de memoria recibido.
297   */
298   void initialize(const char* buffer, const int size) throw(RuntimeException);
299
300   /**
301      Establece el espacio de memoria asociado a este bloque de datos.
302      \param buffer Nuevo buffer de datos asociado a este bloque.
303      \warning El DataBlock delega la gestion de la memoria a la clase heredada.
304   */
305   void setBuffer(const char* buffer) throw() { a_buffer = (char*) buffer; }
306
307   /**
308      Establece el numero de bytes que tiene reservados este bloque de datos.
309      \param maxSize numero de bytes que tiene reservados este bloque de datos.
310      \warning El DataBlock delega la gestion de la memoria a la clase heredada.
311   */
312   void setMaxSize(const int maxSize) throw() { a_maxSize = maxSize; }
313
314 private:
315   char* a_buffer;
316   int a_size;
317   bool a_deepCopy;
318   int a_maxSize;
319
320   void extend(const int nbytes) throw(RuntimeException);
321 };
322
323 } //namespace anna
324
325 #endif
326