Disk ARchive 2.3.12
|
00001 /*********************************************************************/ 00002 // dar - disk archive - a backup/restoration program 00003 // Copyright (C) 2002-2052 Denis Corbin 00004 // 00005 // This program is free software; you can redistribute it and/or 00006 // modify it under the terms of the GNU General Public License 00007 // as published by the Free Software Foundation; either version 2 00008 // of the License, or (at your option) any later version. 00009 // 00010 // This program is distributed in the hope that it will be useful, 00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 // GNU General Public License for more details. 00014 // 00015 // You should have received a copy of the GNU General Public License 00016 // along with this program; if not, write to the Free Software 00017 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00018 // 00019 // to contact the author : dar.linux@free.fr 00020 /*********************************************************************/ 00021 // $Id: storage.hpp,v 1.11.4.4 2011/01/22 15:34:17 edrusb Rel $ 00022 // 00023 /*********************************************************************/ 00024 00027 00028 #ifndef STORAGE_HPP 00029 #define STORAGE_HPP 00030 00031 #include "../my_config.h" 00032 #include "erreurs.hpp" 00033 #include "integers.hpp" 00034 00035 #ifndef LIBDAR_MODE 00036 namespace libdar 00037 { 00038 class infinint; 00039 } 00040 #else 00041 #include "infinint.hpp" 00042 #endif 00043 00044 00045 namespace libdar 00046 { 00047 class generic_file; 00048 00050 00053 00054 class storage 00055 { 00056 private: 00057 struct cellule 00058 { 00059 cellule() : next(NULL), prev(NULL), data(NULL), size(0) {}; 00060 struct cellule *next, *prev; 00061 unsigned char *data; 00062 U_32 size; 00063 }; 00064 00065 public: 00066 storage(U_32 size) 00067 { E_BEGIN; make_alloc(size, first, last); E_END("storage::storage","U_32"); }; 00068 storage(const infinint & size); 00069 storage(const storage & ref) 00070 { E_BEGIN; copy_from(ref); E_END("storage::storage", "storage &"); }; 00071 storage(generic_file & f, const infinint &size); 00072 ~storage() 00073 { E_BEGIN; detruit(first); E_END("storage::~storage", ""); }; 00074 00075 storage & operator = (const storage & val) 00076 { E_BEGIN; detruit(first); copy_from(val); return *this; E_END("storage::operator=",""); }; 00077 00078 bool operator < (const storage & ref) const 00079 { E_BEGIN; return difference(ref) < 0; E_END("storage::operator <",""); }; // true if arg uses more space than this 00080 bool operator == (const storage & ref) const 00081 { E_BEGIN; return difference(ref) == 0; E_END("storage::operator ==",""); }; //true if arg have same space than this 00082 bool operator > (const storage & ref) const 00083 { E_BEGIN; return difference(ref) > 0; E_END("storage::operator >", ""); }; 00084 bool operator <= (const storage & ref) const 00085 { E_BEGIN; return difference(ref) <= 0; E_END("storage::operator <=", ""); }; 00086 bool operator >= (const storage & ref) const 00087 { E_BEGIN; return difference(ref) >= 0; E_END("storage::operator >=", ""); }; 00088 bool operator != (const storage & ref) const 00089 { E_BEGIN; return difference(ref) != 0; E_END("storage::operator !=", ""); }; 00090 unsigned char & operator [](infinint position); 00091 unsigned char operator [](const infinint & position) const; 00092 infinint size() const; 00093 void clear(unsigned char val = 0); 00094 void dump(generic_file & f) const; 00095 00096 class iterator 00097 { 00098 public : 00099 iterator() : ref(NULL), cell(NULL), offset(0) {}; 00100 // default constructor by reference is OK 00101 // default destructor is OK 00102 // default operator = is OK 00103 00104 iterator operator ++ (S_I x) 00105 { E_BEGIN; iterator ret = *this; skip_plus_one(); return ret; E_END("storage::iterator::operator++", "(S_I)"); }; 00106 iterator operator -- (S_I x) 00107 { E_BEGIN; iterator ret = *this; skip_less_one(); return ret; E_END("storage::iterator::operator--", "(S_I)");}; 00108 iterator & operator ++ () 00109 { E_BEGIN; skip_plus_one(); return *this; E_END("storage::iterator::operator++", "()"); }; 00110 iterator & operator -- () 00111 { E_BEGIN; skip_less_one(); return *this; E_END("storage::iterator::operator--", "()"); }; 00112 iterator operator + (U_32 s) const 00113 { E_BEGIN; iterator ret = *this; ret += s; return ret; E_END("storage::iterator::operator +", ""); }; 00114 iterator operator - (U_32 s) const 00115 { E_BEGIN; iterator ret = *this; ret -= s; return ret; E_END("storage::iterator::operator -", ""); }; 00116 iterator & operator += (U_32 s); 00117 iterator & operator -= (U_32 s); 00118 unsigned char &operator *() const; 00119 00120 void skip_to(const storage & st, infinint val); // absolute position in st 00121 infinint get_position() const; 00122 00123 bool operator == (const iterator & cmp) const 00124 { E_BEGIN; return ref == cmp.ref && cell == cmp.cell && offset == cmp.offset; E_END("storage::iterator::operator ==", ""); }; 00125 bool operator != (const iterator & cmp) const 00126 { E_BEGIN; return ! (*this == cmp); E_END("storage::iterator::operator !=", ""); }; 00127 00128 private: 00129 static const U_32 OFF_BEGIN = 1; 00130 static const U_32 OFF_END = 2; 00131 00132 const storage *ref; 00133 struct cellule *cell; 00134 U_32 offset; 00135 00136 void relative_skip_to(S_32 val); 00137 bool points_on_data() const 00138 { E_BEGIN; return ref != NULL && cell != NULL && offset < cell->size; E_END("storage::iterator::point_on_data", "");}; 00139 00140 inline void skip_plus_one(); 00141 inline void skip_less_one(); 00142 00143 friend class storage; 00144 }; 00145 00146 // public storage methode using iterator 00147 00148 iterator begin() const 00149 { E_BEGIN; iterator ret; ret.cell = first; ret.offset = 0; ret.ref = this; return ret; E_END("storage::begin", ""); }; 00150 iterator end() const 00151 { E_BEGIN; iterator ret; ret.cell = NULL; ret.offset = iterator::OFF_END; ret.ref = this; return ret; E_END("storage::end", ""); }; 00152 00153 // WARNING for the two following methods : 00154 // there is no "reverse_iterator" type, unlike the standart lib, 00155 // thus when going from rbegin() to rend(), you must use the -- operator 00156 // unlike the stdlib, that uses the ++ operator. this is the only difference in use with stdlib. 00157 iterator rbegin() const 00158 { E_BEGIN; iterator ret; ret.cell = last; ret.offset = last != NULL ? last->size-1 : 0; ret.ref = this; return ret; E_END("storage::rbegin", ""); }; 00159 iterator rend() const 00160 { E_BEGIN; iterator ret; ret.cell = NULL, ret.offset = iterator::OFF_BEGIN; ret.ref = this; return ret; E_END("storage::rend", ""); }; 00161 00163 00167 U_I write(iterator & it, unsigned char *a, U_I size); 00168 U_I read(iterator & it, unsigned char *a, U_I size) const; 00169 bool write(iterator & it, unsigned char a) 00170 { E_BEGIN; return write(it, &a, 1) == 1; E_END("storage::write", "unsigned char"); }; 00171 bool read(iterator & it, unsigned char &a) const 00172 { E_BEGIN; return read(it, &a, 1) == 1; E_END("storage::read", "unsigned char"); }; 00173 00174 // after one of these 3 calls, the iterator given in argument are undefined (they may point nowhere) 00175 void insert_null_bytes_at_iterator(iterator it, U_I size); 00176 void insert_const_bytes_at_iterator(iterator it, unsigned char a, U_I size); 00177 void insert_bytes_at_iterator(iterator it, unsigned char *a, U_I size); 00178 void insert_as_much_as_necessary_const_byte_to_be_as_wider_as(const storage & ref, const iterator & it, unsigned char value); 00179 void remove_bytes_at_iterator(iterator it, U_I number); 00180 void remove_bytes_at_iterator(iterator it, infinint number); 00181 00182 00183 private: 00184 struct cellule *first, *last; 00185 00186 void copy_from(const storage & ref); 00187 S_32 difference(const storage & ref) const; 00188 void reduce(); // heuristic that tries to free some memory; 00189 void insert_bytes_at_iterator_cmn(iterator it, bool constant, unsigned char *a, U_I size); 00190 void fusionne(struct cellule *a_first, struct cellule *a_last, struct cellule *b_first, struct cellule *b_last, 00191 struct cellule *&res_first, struct cellule * & res_last); 00192 00194 // STATIC statments : 00195 // 00196 00197 static void detruit(struct cellule *c); 00198 static void make_alloc(U_32 size, struct cellule * & begin, struct cellule * & end); 00199 static void make_alloc(infinint size, cellule * & begin, struct cellule * & end); 00200 00201 friend class storage::iterator; 00202 }; 00203 00204 inline void storage::iterator::skip_plus_one() 00205 { 00206 E_BEGIN; 00207 if(cell != NULL) 00208 if(++offset >= cell->size) 00209 { 00210 cell = cell->next; 00211 if(cell != NULL) 00212 offset = 0; 00213 else 00214 offset = OFF_END; 00215 } 00216 E_END("storage::iterator::slik_plus_one", ""); 00217 } 00218 00219 inline void storage::iterator::skip_less_one() 00220 { 00221 E_BEGIN; 00222 if(cell != NULL) 00223 { 00224 if(offset > 0) 00225 --offset; 00226 else 00227 { 00228 cell = cell->prev; 00229 if(cell != NULL) 00230 offset = cell->size - 1; 00231 else 00232 offset = OFF_BEGIN; 00233 } 00234 } 00235 E_END("storage::iterator::slik_plus_one", ""); 00236 } 00237 00238 } // end of namespace 00239 00240 #endif