![]() |
Disk ARchive
2.5.2
Full featured and portable backup and archiving tool
|
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 00025 00026 #include "../my_config.h" 00027 #include "erreurs.hpp" 00028 #include "integers.hpp" 00029 #include "on_pool.hpp" 00030 00031 #ifdef LIBDAR_MODE 00032 #include "infinint.hpp" 00033 #endif 00034 00035 // it is necessary to not protect the previous inclusion inside 00036 // the STORAGE_HPP protection to avoid cyclic dependancies. 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 : public on_pool 00058 { 00059 private: 00060 struct cellule 00061 { 00062 cellule() : next(nullptr), prev(nullptr), data(nullptr), 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() throw(Ebug) 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; }; // true if arg uses more space than this 00083 bool operator == (const storage & ref) const 00084 { return difference(ref) == 0; }; //true if arg have same space than this 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 : public on_pool 00100 { 00101 public : 00102 iterator() : ref(nullptr), cell(nullptr), offset(0) {}; 00103 // default constructor by reference is OK 00104 // default destructor is OK 00105 // default operator = is OK 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); // absolute position in st 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 != nullptr && cell != nullptr && offset < cell->size; }; 00142 00143 inline void skip_plus_one(); 00144 inline void skip_less_one(); 00145 00146 friend class storage; 00147 }; 00148 00149 // public storage methode using iterator 00150 00151 iterator begin() const 00152 { iterator ret; ret.cell = first; if(ret.cell != nullptr) ret.offset = 0; else ret.offset = iterator::OFF_END; ret.ref = this; return ret; }; 00153 iterator end() const 00154 { iterator ret; ret.cell = nullptr; ret.offset = iterator::OFF_END; ret.ref = this; return ret; }; 00155 00156 // WARNING for the two following methods : 00157 // there is no "reverse_iterator" type, unlike the standart lib, 00158 // thus when going from rbegin() to rend(), you must use the -- operator 00159 // unlike the stdlib, that uses the ++ operator. this is the only difference in use with stdlib. 00160 iterator rbegin() const 00161 { iterator ret; ret.cell = last; ret.offset = last != nullptr ? last->size-1 : 0; ret.ref = this; return ret; }; 00162 iterator rend() const 00163 { iterator ret; ret.cell = nullptr, 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 // after one of these 3 calls, the iterator given in argument are undefined (they may point nowhere) 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 private: 00186 struct cellule *first, *last; 00187 00188 void copy_from(const storage & ref); 00189 S_32 difference(const storage & ref) const; 00190 void reduce(); // heuristic that tries to free some memory; 00191 void insert_bytes_at_iterator_cmn(iterator it, bool constant, unsigned char *a, U_I size); 00192 void fusionne(struct cellule *a_first, struct cellule *a_last, struct cellule *b_first, struct cellule *b_last, 00193 struct cellule *&res_first, struct cellule * & res_last); 00194 00196 // these were STATIC statments, but now object methods 00197 // because they rely on on_pool templates that require object field 00198 00199 void detruit(struct cellule *c); 00200 void make_alloc(U_32 size, struct cellule * & begin, struct cellule * & end); 00201 void make_alloc(infinint size, cellule * & begin, struct cellule * & end); 00202 00203 friend class storage::iterator; 00204 }; 00205 00206 inline void storage::iterator::skip_plus_one() 00207 { 00208 if(cell != nullptr) 00209 if(++offset >= cell->size) 00210 { 00211 cell = cell->next; 00212 if(cell != nullptr) 00213 offset = 0; 00214 else 00215 offset = OFF_END; 00216 } 00217 } 00218 00219 inline void storage::iterator::skip_less_one() 00220 { 00221 if(cell != nullptr) 00222 { 00223 if(offset > 0) 00224 --offset; 00225 else 00226 { 00227 cell = cell->prev; 00228 if(cell != nullptr) 00229 offset = cell->size - 1; 00230 else 00231 offset = OFF_BEGIN; 00232 } 00233 } 00234 } 00235 00236 } // end of namespace 00237 00238 #endif