Disk ARchive
2.4.5
|
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$ 00022 // 00023 /*********************************************************************/ 00024 00025 #ifndef STORAGE_HPP 00026 #define STORAGE_HPP 00027 00028 #pragma interface 00029 00030 #include "erreurs.hpp" 00031 #include "integers.hpp" 00032 00033 class infinint; 00034 class generic_file; 00035 00036 class storage 00037 { 00038 private: 00039 struct cellule 00040 { 00041 struct cellule *next, *prev; 00042 unsigned char *data; 00043 U_32 size; 00044 }; 00045 00046 public: 00047 storage(U_32 size) throw(Ememory, Ebug) 00048 { E_BEGIN; make_alloc(size, first, last); E_END("storage::storage","U_32"); }; 00049 storage(const infinint & size) throw(Ememory, Erange, Ebug); 00050 storage(const storage & ref) throw(Ememory, Ebug) 00051 { E_BEGIN; copy_from(ref); E_END("storage::storage", "storage &"); }; 00052 storage(generic_file & f, const infinint &size); 00053 ~storage() throw(Ebug) 00054 { E_BEGIN; detruit(first); E_END("storage::~storage", ""); }; 00055 00056 storage & operator = (const storage & val) throw(Ememory, Ebug) 00057 { E_BEGIN; detruit(first); copy_from(val); return *this; E_END("storage::operator=",""); }; 00058 00059 bool operator < (const storage & ref) const throw() 00060 { E_BEGIN; return difference(ref) < 0; E_END("storage::operator <",""); }; // true if arg uses more space than this 00061 bool operator == (const storage & ref) const throw() 00062 { E_BEGIN; return difference(ref) == 0; E_END("storage::operator ==",""); }; //true if arg have same space than this 00063 bool operator > (const storage & ref) const throw() 00064 { E_BEGIN; return difference(ref) > 0; E_END("storage::operator >", ""); }; 00065 bool operator <= (const storage & ref) const throw() 00066 { E_BEGIN; return difference(ref) <= 0; E_END("storage::operator <=", ""); }; 00067 bool operator >= (const storage & ref) const throw() 00068 { E_BEGIN; return difference(ref) >= 0; E_END("storage::operator >=", ""); }; 00069 bool operator != (const storage & ref) const throw() 00070 { E_BEGIN; return difference(ref) != 0; E_END("storage::operator !=", ""); }; 00071 unsigned char & operator [](infinint position) throw(Ememory, Erange, Ebug); 00072 unsigned char operator [](const infinint & position) const throw(Ememory, Erange, Ebug); 00073 infinint size() const throw(Ememory, Erange, Ebug); 00074 void clear(unsigned char val = 0) throw(); 00075 void dump(generic_file & f) const; 00076 00077 class iterator 00078 { 00079 public : 00080 iterator() { ref = NULL; cell = NULL; offset = 0; }; 00081 // default constructor by reference is OK 00082 // default destructor is OK 00083 // default operator = is OK 00084 00085 iterator operator ++ (S_I x) throw() 00086 { E_BEGIN; iterator ret = *this; skip_plus_one(); return ret; E_END("storage::iterator::operator++", "(S_I)"); }; 00087 iterator operator -- (S_I x) throw() 00088 { E_BEGIN; iterator ret = *this; skip_less_one(); return ret; E_END("storage::iterator::operator--", "(S_I)");}; 00089 iterator & operator ++ () throw() 00090 { E_BEGIN; skip_plus_one(); return *this; E_END("storage::iterator::operator++", "()"); }; 00091 iterator & operator -- () throw() 00092 { E_BEGIN; skip_less_one(); return *this; E_END("storage::iterator::operator--", "()"); }; 00093 iterator operator + (U_32 s) const throw() 00094 { E_BEGIN; iterator ret = *this; ret += s; return ret; E_END("storage::iterator::operator +", ""); }; 00095 iterator operator - (U_32 s) const throw() 00096 { E_BEGIN; iterator ret = *this; ret -= s; return ret; E_END("storage::iterator::operator -", ""); }; 00097 iterator & operator += (U_32 s) throw(); 00098 iterator & operator -= (U_32 s) throw(); 00099 unsigned char &operator *() const throw(Erange); 00100 00101 void skip_to(const storage & st, infinint val) throw(); // absolute position in st 00102 infinint get_position() const throw(Erange, Ememory, Ebug); 00103 00104 bool operator == (const iterator & cmp) const throw() 00105 { E_BEGIN; return ref == cmp.ref && cell == cmp.cell && offset == cmp.offset; E_END("storage::iterator::operator ==", ""); }; 00106 bool operator != (const iterator & cmp) const throw() 00107 { E_BEGIN; return ! (*this == cmp); E_END("storage::iterator::operator !=", ""); }; 00108 00109 private: 00110 static const U_32 OFF_BEGIN = 1; 00111 static const U_32 OFF_END = 2; 00112 00113 const storage *ref; 00114 struct cellule *cell; 00115 U_32 offset; 00116 00117 void relative_skip_to(S_32 val) throw(); 00118 bool points_on_data() const throw() 00119 { E_BEGIN; return ref != NULL && cell != NULL && offset < cell->size; E_END("storage::iterator::point_on_data", "");}; 00120 00121 inline void skip_plus_one(); 00122 inline void skip_less_one(); 00123 00124 friend class storage; 00125 }; 00126 00127 // public storage methode using iterator 00128 00129 iterator begin() const throw() 00130 { E_BEGIN; iterator ret; ret.cell = first; ret.offset = 0; ret.ref = this; return ret; E_END("storage::begin", ""); }; 00131 iterator end() const throw() 00132 { E_BEGIN; iterator ret; ret.cell = NULL; ret.offset = iterator::OFF_END; ret.ref = this; return ret; E_END("storage::end", ""); }; 00133 00134 // WARNING for the two following methods : 00135 // there is no "reverse_iterator" type, unlike the standart lib, 00136 // thus when going from rbegin() to rend(), you must use the -- operator 00137 // unlike the stdlib, that uses the ++ operator. this is the only difference in use with stdlib. 00138 iterator rbegin() const throw() 00139 { E_BEGIN; iterator ret; ret.cell = last; ret.offset = last != NULL ? last->size-1 : 0; ret.ref = this; return ret; E_END("storage::rbegin", ""); }; 00140 iterator rend() const throw() 00141 { E_BEGIN; iterator ret; ret.cell = NULL, ret.offset = iterator::OFF_BEGIN; ret.ref = this; return ret; E_END("storage::rend", ""); }; 00142 00143 U_I write(iterator & it, unsigned char *a, U_I size) throw(Erange); 00144 U_I read(iterator & it, unsigned char *a, U_I size) const throw(Erange); 00145 bool write(iterator & it, unsigned char a) throw(Erange) 00146 { E_BEGIN; return write(it, &a, 1) == 1; E_END("storage::write", "unsigned char"); }; 00147 bool read(iterator & it, unsigned char &a) const throw(Erange) 00148 { E_BEGIN; return read(it, &a, 1) == 1; E_END("storage::read", "unsigned char"); }; 00149 00150 // after one of theses 3 calls, the iterator given in argument are undefined (they may point nowhere) 00151 void insert_null_bytes_at_iterator(iterator it, U_I size) throw(Erange, Ememory, Ebug); 00152 void insert_const_bytes_at_iterator(iterator it, unsigned char a, U_I size) throw(Erange, Ememory, Ebug); 00153 void insert_bytes_at_iterator(iterator it, unsigned char *a, U_I size) throw(Erange, Ememory, Ebug); 00154 void insert_as_much_as_necessary_const_byte_to_be_as_wider_as(const storage & ref, const iterator & it, unsigned char value); 00155 void remove_bytes_at_iterator(iterator it, U_I number) throw(Ememory, Ebug); 00156 void remove_bytes_at_iterator(iterator it, infinint number) throw(Ememory, Erange, Ebug); 00157 private: 00158 struct cellule *first, *last; 00159 00160 void copy_from(const storage & ref) throw(Ememory, Erange, Ebug); 00161 S_32 difference(const storage & ref) const throw(); 00162 void reduce() throw(Ebug); // heuristic that tries to free some memory; 00163 void insert_bytes_at_iterator_cmn(iterator it, bool constant, unsigned char *a, U_I size) throw(Erange, Ememory, Ebug); 00164 void fusionne(struct cellule *a_first, struct cellule *a_last, struct cellule *b_first, struct cellule *b_last, 00165 struct cellule *&res_first, struct cellule * & res_last) throw(Ebug); 00166 00168 // STATIC statments : 00169 // 00170 00171 static U_32 alloc_size; // stores the last biggest memory allocation successfully realized 00172 00173 static void detruit(struct cellule *c) throw(Ebug); 00174 static void make_alloc(U_32 size, struct cellule * & begin, struct cellule * & end) throw(Ememory, Ebug); 00175 static void make_alloc(infinint size, cellule * & begin, struct cellule * & end) throw(Ememory, Erange, Ebug); 00176 00177 friend class storage::iterator; 00178 }; 00179 00180 inline void storage::iterator::skip_plus_one() 00181 { 00182 E_BEGIN; 00183 if(cell != NULL) 00184 if(++offset >= cell->size) 00185 { 00186 cell = cell->next; 00187 if(cell != NULL) 00188 offset = 0; 00189 else 00190 offset = OFF_END; 00191 } 00192 E_END("storage::iterator::slik_plus_one", ""); 00193 } 00194 00195 inline void storage::iterator::skip_less_one() 00196 { 00197 E_BEGIN; 00198 if(cell != NULL) 00199 if(offset > 0) 00200 offset--; 00201 else 00202 { 00203 cell = cell->prev; 00204 if(cell != NULL) 00205 offset = cell->size - 1; 00206 else 00207 offset = OFF_BEGIN; 00208 } 00209 E_END("storage::iterator::slik_plus_one", ""); 00210 } 00211 00212 #endif