Disk ARchive  2.4.5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines
.pc/delete2/storage.hpp
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines