Disk ARchive  2.5.2
Full featured and portable backup and archiving tool
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 : 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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines