Disk ARchive 2.4.2
|
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 : http://dar.linux.free.fr/email.html 00020 /*********************************************************************/ 00021 // $Id: storage.hpp,v 1.20 2011/01/22 22:39:10 edrusb Rel $ 00022 // 00023 /*********************************************************************/ 00024 00028 00029 #include "../my_config.h" 00030 #include "erreurs.hpp" 00031 #include "integers.hpp" 00032 00033 #ifdef LIBDAR_MODE 00034 #include "infinint.hpp" 00035 #endif 00036 00037 // it is necessary to not protect the previous inclusion inside 00038 // the STORAGE_HPP protection to avoid cyclic dependancies. 00039 00040 #ifndef STORAGE_HPP 00041 #define STORAGE_HPP 00042 00043 #ifndef LIBDAR_MODE 00044 namespace libdar 00045 { 00046 class infinint; 00047 } 00048 #endif 00049 00050 namespace libdar 00051 { 00052 class generic_file; 00053 00055 00058 00059 class storage 00060 { 00061 private: 00062 struct cellule 00063 { 00064 cellule() : next(NULL), prev(NULL), data(NULL), size(0) {}; 00065 struct cellule *next, *prev; 00066 unsigned char *data; 00067 U_32 size; 00068 }; 00069 00070 public: 00071 storage(U_32 size) 00072 { E_BEGIN; make_alloc(size, first, last); E_END("storage::storage","U_32"); }; 00073 storage(const infinint & size); 00074 storage(const storage & ref) 00075 { E_BEGIN; copy_from(ref); E_END("storage::storage", "storage &"); }; 00076 storage(generic_file & f, const infinint &size); 00077 ~storage() 00078 { E_BEGIN; detruit(first); E_END("storage::~storage", ""); }; 00079 00080 const storage & operator = (const storage & val) 00081 { E_BEGIN; detruit(first); copy_from(val); return *this; E_END("storage::operator=",""); }; 00082 00083 bool operator < (const storage & ref) const 00084 { E_BEGIN; return difference(ref) < 0; E_END("storage::operator <",""); }; // true if arg uses more space than this 00085 bool operator == (const storage & ref) const 00086 { E_BEGIN; return difference(ref) == 0; E_END("storage::operator ==",""); }; //true if arg have same space than this 00087 bool operator > (const storage & ref) const 00088 { E_BEGIN; return difference(ref) > 0; E_END("storage::operator >", ""); }; 00089 bool operator <= (const storage & ref) const 00090 { E_BEGIN; return difference(ref) <= 0; E_END("storage::operator <=", ""); }; 00091 bool operator >= (const storage & ref) const 00092 { E_BEGIN; return difference(ref) >= 0; E_END("storage::operator >=", ""); }; 00093 bool operator != (const storage & ref) const 00094 { E_BEGIN; return difference(ref) != 0; E_END("storage::operator !=", ""); }; 00095 unsigned char & operator [](infinint position); 00096 unsigned char operator [](const infinint & position) const; 00097 infinint size() const; 00098 void clear(unsigned char val = 0); 00099 void dump(generic_file & f) const; 00100 00101 class iterator 00102 { 00103 public : 00104 iterator() : ref(NULL), cell(NULL), offset(0) {}; 00105 // default constructor by reference is OK 00106 // default destructor is OK 00107 // default operator = is OK 00108 00109 iterator operator ++ (S_I x) 00110 { E_BEGIN; iterator ret = *this; skip_plus_one(); return ret; E_END("storage::iterator::operator++", "(S_I)"); }; 00111 iterator operator -- (S_I x) 00112 { E_BEGIN; iterator ret = *this; skip_less_one(); return ret; E_END("storage::iterator::operator--", "(S_I)");}; 00113 iterator & operator ++ () 00114 { E_BEGIN; skip_plus_one(); return *this; E_END("storage::iterator::operator++", "()"); }; 00115 iterator & operator -- () 00116 { E_BEGIN; skip_less_one(); return *this; E_END("storage::iterator::operator--", "()"); }; 00117 iterator operator + (U_32 s) const 00118 { E_BEGIN; iterator ret = *this; ret += s; return ret; E_END("storage::iterator::operator +", ""); }; 00119 iterator operator - (U_32 s) const 00120 { E_BEGIN; iterator ret = *this; ret -= s; return ret; E_END("storage::iterator::operator -", ""); }; 00121 iterator & operator += (U_32 s); 00122 iterator & operator -= (U_32 s); 00123 unsigned char &operator *() const; 00124 00125 void skip_to(const storage & st, infinint val); // absolute position in st 00126 infinint get_position() const; 00127 00128 bool operator == (const iterator & cmp) const 00129 { E_BEGIN; return ref == cmp.ref && cell == cmp.cell && offset == cmp.offset; E_END("storage::iterator::operator ==", ""); }; 00130 bool operator != (const iterator & cmp) const 00131 { E_BEGIN; return ! (*this == cmp); E_END("storage::iterator::operator !=", ""); }; 00132 00133 private: 00134 static const U_32 OFF_BEGIN = 1; 00135 static const U_32 OFF_END = 2; 00136 00137 const storage *ref; 00138 struct cellule *cell; 00139 U_32 offset; 00140 00141 void relative_skip_to(S_32 val); 00142 bool points_on_data() const 00143 { E_BEGIN; return ref != NULL && cell != NULL && offset < cell->size; E_END("storage::iterator::point_on_data", "");}; 00144 00145 inline void skip_plus_one(); 00146 inline void skip_less_one(); 00147 00148 friend class storage; 00149 }; 00150 00151 // public storage methode using iterator 00152 00153 iterator begin() const 00154 { E_BEGIN; iterator ret; ret.cell = first; if(ret.cell != NULL) ret.offset = 0; else ret.offset = iterator::OFF_END; ret.ref = this; return ret; E_END("storage::begin", ""); }; 00155 iterator end() const 00156 { E_BEGIN; iterator ret; ret.cell = NULL; ret.offset = iterator::OFF_END; ret.ref = this; return ret; E_END("storage::end", ""); }; 00157 00158 // WARNING for the two following methods : 00159 // there is no "reverse_iterator" type, unlike the standart lib, 00160 // thus when going from rbegin() to rend(), you must use the -- operator 00161 // unlike the stdlib, that uses the ++ operator. this is the only difference in use with stdlib. 00162 iterator rbegin() const 00163 { E_BEGIN; iterator ret; ret.cell = last; ret.offset = last != NULL ? last->size-1 : 0; ret.ref = this; return ret; E_END("storage::rbegin", ""); }; 00164 iterator rend() const 00165 { E_BEGIN; iterator ret; ret.cell = NULL, ret.offset = iterator::OFF_BEGIN; ret.ref = this; return ret; E_END("storage::rend", ""); }; 00166 00168 00172 U_I write(iterator & it, unsigned char *a, U_I size); 00173 U_I read(iterator & it, unsigned char *a, U_I size) const; 00174 bool write(iterator & it, unsigned char a) 00175 { E_BEGIN; return write(it, &a, 1) == 1; E_END("storage::write", "unsigned char"); }; 00176 bool read(iterator & it, unsigned char &a) const 00177 { E_BEGIN; return read(it, &a, 1) == 1; E_END("storage::read", "unsigned char"); }; 00178 00179 // after one of these 3 calls, the iterator given in argument are undefined (they may point nowhere) 00180 void insert_null_bytes_at_iterator(iterator it, U_I size); 00181 void insert_const_bytes_at_iterator(iterator it, unsigned char a, U_I size); 00182 void insert_bytes_at_iterator(iterator it, unsigned char *a, U_I size); 00183 void insert_as_much_as_necessary_const_byte_to_be_as_wider_as(const storage & ref, const iterator & it, unsigned char value); 00184 void remove_bytes_at_iterator(iterator it, U_I number); 00185 void remove_bytes_at_iterator(iterator it, infinint number); 00186 00187 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(); // heuristic that tries to free some memory; 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 // STATIC statments : 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 E_BEGIN; 00212 if(cell != NULL) 00213 if(++offset >= cell->size) 00214 { 00215 cell = cell->next; 00216 if(cell != NULL) 00217 offset = 0; 00218 else 00219 offset = OFF_END; 00220 } 00221 E_END("storage::iterator::slik_plus_one", ""); 00222 } 00223 00224 inline void storage::iterator::skip_less_one() 00225 { 00226 E_BEGIN; 00227 if(cell != NULL) 00228 { 00229 if(offset > 0) 00230 --offset; 00231 else 00232 { 00233 cell = cell->prev; 00234 if(cell != NULL) 00235 offset = cell->size - 1; 00236 else 00237 offset = OFF_BEGIN; 00238 } 00239 } 00240 E_END("storage::iterator::slik_plus_one", ""); 00241 } 00242 00243 } // end of namespace 00244 00245 #endif