storage.hpp

Go to the documentation of this file.
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 2004/11/07 18:21:38 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             struct cellule *next, *prev;
00060             unsigned char *data;
00061             U_32 size;
00062         };
00063 
00064     public:
00065         storage(U_32 size)
00066             { E_BEGIN; make_alloc(size, first, last); E_END("storage::storage","U_32"); };
00067         storage(const infinint & size);
00068         storage(const storage & ref)
00069             { E_BEGIN; copy_from(ref); E_END("storage::storage", "storage &"); };
00070         storage(generic_file & f, const infinint &size);
00071         ~storage()
00072             { E_BEGIN; detruit(first); E_END("storage::~storage", ""); };
00073 
00074         storage & operator = (const storage & val)
00075             { E_BEGIN; detruit(first); copy_from(val); return *this; E_END("storage::operator=",""); };
00076 
00077         bool operator < (const storage & ref) const
00078             { E_BEGIN; return difference(ref) < 0; E_END("storage::operator <",""); }; // true if arg uses more space than this
00079         bool operator == (const storage & ref) const
00080             { E_BEGIN; return difference(ref) == 0; E_END("storage::operator ==",""); }; //true if arg have same space than this
00081         bool operator > (const storage & ref) const
00082             { E_BEGIN; return difference(ref) > 0; E_END("storage::operator >", ""); };
00083         bool operator <= (const storage & ref) const
00084             { E_BEGIN; return difference(ref) <= 0; E_END("storage::operator <=", ""); };
00085         bool operator >= (const storage & ref) const
00086             { E_BEGIN; return difference(ref) >= 0; E_END("storage::operator >=", ""); };
00087         bool operator != (const storage & ref) const
00088             { E_BEGIN; return difference(ref) != 0; E_END("storage::operator !=", ""); };
00089         unsigned char & operator [](infinint position);
00090         unsigned char operator [](const infinint & position) const;
00091         infinint size() const;
00092         void clear(unsigned char val = 0);
00093         void dump(generic_file & f) const;
00094 
00095         class iterator
00096         {
00097         public :
00098             iterator() { ref = NULL; cell = NULL; offset = 0; };
00099                 // default constructor by reference is OK
00100                 // default destructor is OK
00101                 // default operator = is OK
00102 
00103             iterator operator ++ (S_I x)
00104                 { E_BEGIN; iterator ret = *this; skip_plus_one(); return ret;  E_END("storage::iterator::operator++", "(S_I)"); };
00105             iterator operator -- (S_I x)
00106                 { E_BEGIN; iterator ret = *this; skip_less_one(); return ret; E_END("storage::iterator::operator--", "(S_I)");};
00107             iterator & operator ++ ()
00108                 { E_BEGIN; skip_plus_one(); return *this; E_END("storage::iterator::operator++", "()"); };
00109             iterator & operator -- ()
00110                 { E_BEGIN; skip_less_one(); return *this; E_END("storage::iterator::operator--", "()"); };
00111             iterator operator + (U_32 s) const
00112                 { E_BEGIN; iterator ret = *this; ret += s; return ret; E_END("storage::iterator::operator +", ""); };
00113             iterator operator - (U_32 s) const
00114                 { E_BEGIN; iterator ret = *this; ret -= s; return ret; E_END("storage::iterator::operator -", ""); };
00115             iterator & operator += (U_32 s);
00116             iterator & operator -= (U_32 s);
00117             unsigned char &operator *() const;
00118 
00119             void skip_to(const storage & st, infinint val); // absolute position in st
00120             infinint get_position() const;
00121 
00122             bool operator == (const iterator & cmp) const
00123                 { E_BEGIN; return ref == cmp.ref && cell == cmp.cell && offset == cmp.offset; E_END("storage::iterator::operator ==", ""); };
00124             bool operator != (const iterator & cmp) const
00125                 { E_BEGIN; return ! (*this == cmp); E_END("storage::iterator::operator !=", ""); };
00126 
00127         private:
00128             static const U_32 OFF_BEGIN = 1;
00129             static const U_32 OFF_END = 2;
00130 
00131             const storage *ref;
00132             struct cellule *cell;
00133             U_32 offset;
00134 
00135             void relative_skip_to(S_32 val);
00136             bool points_on_data() const
00137                 { E_BEGIN; return ref != NULL && cell != NULL && offset < cell->size; E_END("storage::iterator::point_on_data", "");};
00138 
00139             inline void skip_plus_one();
00140             inline void skip_less_one();
00141 
00142             friend class storage;
00143         };
00144 
00145             // public storage methode using iterator
00146 
00147         iterator begin() const
00148             { E_BEGIN; iterator ret; ret.cell = first; ret.offset = 0; ret.ref = this; return ret; E_END("storage::begin", ""); };
00149         iterator end() const
00150             { E_BEGIN; iterator ret; ret.cell = NULL; ret.offset = iterator::OFF_END; ret.ref = this; return ret; E_END("storage::end", ""); };
00151 
00152             // WARNING for the two following methods :
00153             // there is no "reverse_iterator" type, unlike the standart lib,
00154             // thus when going from rbegin() to rend(), you must use the -- operator
00155             // unlike the stdlib, that uses the ++ operator. this is the only difference in use with stdlib.
00156         iterator rbegin() const
00157             { E_BEGIN; iterator ret; ret.cell = last; ret.offset = last != NULL ? last->size-1 : 0; ret.ref = this; return ret; E_END("storage::rbegin", ""); };
00158         iterator rend() const
00159             { E_BEGIN; iterator ret; ret.cell = NULL, ret.offset = iterator::OFF_BEGIN; ret.ref = this; return ret; E_END("storage::rend", ""); };
00160 
00161         U_I write(iterator & it, unsigned char *a, U_I size);
00162         U_I read(iterator & it, unsigned char *a, U_I size) const;
00163         bool write(iterator & it, unsigned char a)
00164             { E_BEGIN; return write(it, &a, 1) == 1; E_END("storage::write", "unsigned char"); };
00165         bool read(iterator & it, unsigned char &a) const
00166             { E_BEGIN; return read(it, &a, 1) == 1; E_END("storage::read", "unsigned char"); };
00167 
00168             // after one of theses 3 calls, the iterator given in argument are undefined (they may point nowhere)
00169         void insert_null_bytes_at_iterator(iterator it, U_I size);
00170         void insert_const_bytes_at_iterator(iterator it, unsigned char a, U_I size);
00171         void insert_bytes_at_iterator(iterator it, unsigned char *a, U_I size);
00172         void insert_as_much_as_necessary_const_byte_to_be_as_wider_as(const storage & ref, const iterator & it, unsigned char value);
00173         void remove_bytes_at_iterator(iterator it, U_I number);
00174         void remove_bytes_at_iterator(iterator it, infinint number);
00175 
00176 
00177     private:
00178         struct cellule *first, *last;
00179 
00180         void copy_from(const storage & ref);
00181         S_32 difference(const storage & ref) const;
00182         void reduce(); // heuristic that tries to free some memory;
00183         void insert_bytes_at_iterator_cmn(iterator it, bool constant, unsigned char *a, U_I size);
00184         void fusionne(struct cellule *a_first, struct cellule *a_last, struct cellule *b_first, struct cellule *b_last,
00185                       struct cellule *&res_first, struct cellule * & res_last);
00186 
00188             // STATIC statments :
00189             //
00190 
00191         static void detruit(struct cellule *c);
00192         static void make_alloc(U_32 size, struct cellule * & begin, struct cellule * & end);
00193         static void make_alloc(infinint size, cellule * & begin, struct cellule * & end);
00194 
00195         friend class storage::iterator;
00196     };
00197 
00198     inline void storage::iterator::skip_plus_one()
00199     {
00200         E_BEGIN;
00201         if(cell != NULL)
00202             if(++offset >= cell->size)
00203             {
00204                 cell = cell->next;
00205                 if(cell != NULL)
00206                     offset = 0;
00207                 else
00208                     offset = OFF_END;
00209             }
00210         E_END("storage::iterator::slik_plus_one", "");
00211     }
00212 
00213     inline void storage::iterator::skip_less_one()
00214     {
00215         E_BEGIN;
00216         if(cell != NULL)
00217             if(offset > 0)
00218                 offset--;
00219             else
00220             {
00221                 cell = cell->prev;
00222                 if(cell != NULL)
00223                     offset = cell->size - 1;
00224                 else
00225                     offset = OFF_BEGIN;
00226             }
00227         E_END("storage::iterator::slik_plus_one", "");
00228     }
00229 
00230 } // end of namespace
00231 
00232 #endif

Generated on Tue Apr 10 07:56:11 2007 for Disk ARchive by  doxygen 1.5.1