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