Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00025
00026 #include "../my_config.h"
00027 #include "erreurs.hpp"
00028 #include "integers.hpp"
00029 #include "special_alloc.hpp"
00030
00031 #ifdef LIBDAR_MODE
00032 #include "infinint.hpp"
00033 #endif
00034
00035
00036
00037
00038 #ifndef STORAGE_HPP
00039 #define STORAGE_HPP
00040
00041 #ifndef LIBDAR_MODE
00042 namespace libdar
00043 {
00044 class infinint;
00045 }
00046 #endif
00047
00048 namespace libdar
00049 {
00050 class generic_file;
00051
00053
00056
00057 class storage
00058 {
00059 private:
00060 struct cellule
00061 {
00062 cellule() : next(NULL), prev(NULL), data(NULL), size(0) {};
00063 struct cellule *next, *prev;
00064 unsigned char *data;
00065 U_32 size;
00066 };
00067
00068 public:
00069 storage(U_32 size)
00070 { make_alloc(size, first, last); };
00071 storage(const infinint & size);
00072 storage(const storage & ref)
00073 { copy_from(ref); };
00074 storage(generic_file & f, const infinint &size);
00075 ~storage()
00076 { detruit(first); };
00077
00078 const storage & operator = (const storage & val)
00079 { detruit(first); copy_from(val); return *this; };
00080
00081 bool operator < (const storage & ref) const
00082 { return difference(ref) < 0; };
00083 bool operator == (const storage & ref) const
00084 { return difference(ref) == 0; };
00085 bool operator > (const storage & ref) const
00086 { return difference(ref) > 0; };
00087 bool operator <= (const storage & ref) const
00088 { return difference(ref) <= 0; };
00089 bool operator >= (const storage & ref) const
00090 { return difference(ref) >= 0; };
00091 bool operator != (const storage & ref) const
00092 { return difference(ref) != 0; };
00093 unsigned char & operator [](infinint position);
00094 unsigned char operator [](const infinint & position) const;
00095 infinint size() const;
00096 void clear(unsigned char val = 0);
00097 void dump(generic_file & f) const;
00098
00099 class iterator
00100 {
00101 public :
00102 iterator() : ref(NULL), cell(NULL), offset(0) {};
00103
00104
00105
00106
00107 iterator operator ++ (S_I x)
00108 { iterator ret = *this; skip_plus_one(); return ret; };
00109 iterator operator -- (S_I x)
00110 { iterator ret = *this; skip_less_one(); return ret; };
00111 iterator & operator ++ ()
00112 { skip_plus_one(); return *this; };
00113 iterator & operator -- ()
00114 { skip_less_one(); return *this; };
00115 iterator operator + (U_32 s) const
00116 { iterator ret = *this; ret += s; return ret; };
00117 iterator operator - (U_32 s) const
00118 { iterator ret = *this; ret -= s; return ret; };
00119 iterator & operator += (U_32 s);
00120 iterator & operator -= (U_32 s);
00121 unsigned char &operator *() const;
00122
00123 void skip_to(const storage & st, infinint val);
00124 infinint get_position() const;
00125
00126 bool operator == (const iterator & cmp) const
00127 { return ref == cmp.ref && cell == cmp.cell && offset == cmp.offset; };
00128 bool operator != (const iterator & cmp) const
00129 { return ! (*this == cmp); };
00130
00131 private:
00132 static const U_32 OFF_BEGIN = 1;
00133 static const U_32 OFF_END = 2;
00134
00135 const storage *ref;
00136 struct cellule *cell;
00137 U_32 offset;
00138
00139 void relative_skip_to(S_32 val);
00140 bool points_on_data() const
00141 { return ref != NULL && cell != NULL && offset < cell->size; };
00142
00143 inline void skip_plus_one();
00144 inline void skip_less_one();
00145
00146 friend class storage;
00147 };
00148
00149
00150
00151 iterator begin() const
00152 { iterator ret; ret.cell = first; if(ret.cell != NULL) ret.offset = 0; else ret.offset = iterator::OFF_END; ret.ref = this; return ret; };
00153 iterator end() const
00154 { iterator ret; ret.cell = NULL; ret.offset = iterator::OFF_END; ret.ref = this; return ret; };
00155
00156
00157
00158
00159
00160 iterator rbegin() const
00161 { iterator ret; ret.cell = last; ret.offset = last != NULL ? last->size-1 : 0; ret.ref = this; return ret; };
00162 iterator rend() const
00163 { iterator ret; ret.cell = NULL, ret.offset = iterator::OFF_BEGIN; ret.ref = this; return ret; };
00164
00166
00170 U_I write(iterator & it, unsigned char *a, U_I size);
00171 U_I read(iterator & it, unsigned char *a, U_I size) const;
00172 bool write(iterator & it, unsigned char a)
00173 { return write(it, &a, 1) == 1; };
00174 bool read(iterator & it, unsigned char &a) const
00175 { return read(it, &a, 1) == 1; };
00176
00177
00178 void insert_null_bytes_at_iterator(iterator it, U_I size);
00179 void insert_const_bytes_at_iterator(iterator it, unsigned char a, U_I size);
00180 void insert_bytes_at_iterator(iterator it, unsigned char *a, U_I size);
00181 void insert_as_much_as_necessary_const_byte_to_be_as_wider_as(const storage & ref, const iterator & it, unsigned char value);
00182 void remove_bytes_at_iterator(iterator it, U_I number);
00183 void remove_bytes_at_iterator(iterator it, infinint number);
00184
00185 #ifdef LIBDAR_SPECIAL_ALLOC
00186 USE_SPECIAL_ALLOC(storage);
00187 #endif
00188 private:
00189 struct cellule *first, *last;
00190
00191 void copy_from(const storage & ref);
00192 S_32 difference(const storage & ref) const;
00193 void reduce();
00194 void insert_bytes_at_iterator_cmn(iterator it, bool constant, unsigned char *a, U_I size);
00195 void fusionne(struct cellule *a_first, struct cellule *a_last, struct cellule *b_first, struct cellule *b_last,
00196 struct cellule *&res_first, struct cellule * & res_last);
00197
00199
00200
00201
00202 static void detruit(struct cellule *c);
00203 static void make_alloc(U_32 size, struct cellule * & begin, struct cellule * & end);
00204 static void make_alloc(infinint size, cellule * & begin, struct cellule * & end);
00205
00206 friend class storage::iterator;
00207 };
00208
00209 inline void storage::iterator::skip_plus_one()
00210 {
00211 if(cell != NULL)
00212 if(++offset >= cell->size)
00213 {
00214 cell = cell->next;
00215 if(cell != NULL)
00216 offset = 0;
00217 else
00218 offset = OFF_END;
00219 }
00220 }
00221
00222 inline void storage::iterator::skip_less_one()
00223 {
00224 if(cell != NULL)
00225 {
00226 if(offset > 0)
00227 --offset;
00228 else
00229 {
00230 cell = cell->prev;
00231 if(cell != NULL)
00232 offset = cell->size - 1;
00233 else
00234 offset = OFF_BEGIN;
00235 }
00236 }
00237 }
00238
00239 }
00240
00241 #endif