|
Disk ARchive
2.4.12
|
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 00030 00031 00032 #ifndef LIMITINT_HPP 00033 #define LIMITINT_HPP 00034 00035 #include "../my_config.h" 00036 00037 extern "C" 00038 { 00039 #if HAVE_SYS_TYPES_H 00040 #include <sys/types.h> 00041 #endif 00042 00043 #if HAVE_UNISTD_H 00044 #include <unistd.h> 00045 #endif 00046 00047 #if HAVE_STRING_H 00048 #include <string.h> 00049 #endif 00050 00051 #if HAVE_STRINGS_H 00052 #include <strings.h> 00053 #endif 00054 } // end extern "C" 00055 00056 #include <typeinfo> 00057 #include "integers.hpp" 00058 #include "erreurs.hpp" 00059 #include "special_alloc.hpp" 00060 #include "int_tools.hpp" 00061 00062 00063 #define ZEROED_SIZE 50 00064 00065 namespace libdar 00066 { 00067 00070 00071 00072 class generic_file; 00073 class user_interaction; 00074 00086 00087 template<class B> class limitint 00088 { 00089 public : 00090 00091 #if SIZEOF_OFF_T > SIZEOF_TIME_T 00092 #if SIZEOF_OFF_T > SIZEOF_SIZE_T 00093 limitint(off_t a = 0) 00094 { limitint_from(a); }; 00095 #else 00096 limitint(size_t a = 0) 00097 { limitint_from(a); }; 00098 #endif 00099 #else 00100 #if SIZEOF_TIME_T > SIZEOF_SIZE_T 00101 limitint(time_t a = 0) 00102 { limitint_from(a); }; 00103 #else 00104 limitint(size_t a = 0) 00105 { limitint_from(a); }; 00106 #endif 00107 #endif 00108 00109 // read an limitint from a file 00110 limitint(user_interaction & dialog, S_I fd); 00111 limitint(generic_file & x); 00112 00113 void dump(user_interaction & dialog, S_I fd) const; // write byte sequence to file 00114 void dump(generic_file &x) const; // write byte sequence to file 00115 void read(generic_file &f) { build_from_file(f); }; 00116 00117 limitint & operator += (const limitint & ref); 00118 limitint & operator -= (const limitint & ref); 00119 limitint & operator *= (const limitint & ref); 00120 template <class T> limitint power(const T & exponent) const; 00121 limitint & operator /= (const limitint & ref); 00122 limitint & operator %= (const limitint & ref); 00123 limitint & operator &= (const limitint & ref); 00124 limitint & operator |= (const limitint & ref); 00125 limitint & operator ^= (const limitint & ref); 00126 limitint & operator >>= (U_32 bit); 00127 limitint & operator >>= (limitint bit); 00128 limitint & operator <<= (U_32 bit); 00129 limitint & operator <<= (limitint bit); 00130 limitint operator ++(int a) 00131 { limitint ret = *this; ++(*this); return ret; }; 00132 limitint operator --(int a) 00133 { limitint ret = *this; --(*this); return ret; }; 00134 limitint & operator ++() 00135 { return *this += 1; }; 00136 limitint & operator --() 00137 { return *this -= 1; }; 00138 00139 U_32 operator % (U_32 arg) const; 00140 00141 // increment the argument up to a legal value for its storage type and decrement the object in consequence 00142 // note that the initial value of the argument is not ignored ! 00143 // when the object is null the value of the argument stays the same as before 00144 template <class T>void unstack(T &v) 00145 { limitint_unstack_to(v); } 00146 00147 limitint get_storage_size() const; 00148 // it returns number of byte of information necessary to store the integer 00149 00150 unsigned char operator [] (const limitint & position) const; 00151 // return in big endian order the information bytes storing the integer 00152 00153 00154 bool operator < (const limitint &x) const { return field < x.field; }; 00155 bool operator == (const limitint &x) const { return field == x.field; }; 00156 bool operator > (const limitint &x) const { return field > x.field; }; 00157 bool operator <= (const limitint &x) const { return field <= x.field; }; 00158 bool operator != (const limitint &x) const { return field != x.field; }; 00159 bool operator >= (const limitint &x) const { return field >= x.field; }; 00160 00161 static bool is_system_big_endian(); 00162 00163 #ifdef LIBDAR_SPECIAL_ALLOC 00164 USE_SPECIAL_ALLOC(limitint); 00165 #endif 00166 00167 B debug_get_max() const { return max_value; }; 00168 B debug_get_bytesize() const { return bytesize; }; 00169 00170 private : 00171 static const int TG = 4; 00172 static const U_32 sizeof_field = sizeof(B); // number of bytes 00173 00174 enum endian { big_endian, little_endian, not_initialized }; 00175 typedef unsigned char group[TG]; 00176 00177 B field; 00178 00179 void build_from_file(generic_file & x); 00180 template <class T> void limitint_from(T a); 00181 template <class T> T max_val_of(T x); 00182 template <class T> void limitint_unstack_to(T &a); 00183 00185 // static statments 00186 // 00187 static endian used_endian; 00188 static const U_I bytesize = sizeof(B); 00189 static const B max_value = ~B(0) > 0 ? ~B(0) : ~(B(1) << (bytesize*8 - 1)); 00190 static U_8 zeroed_field[ZEROED_SIZE]; 00191 00192 static void setup_endian(); 00193 }; 00194 00195 template <class B> U_8 limitint<B>::zeroed_field[ZEROED_SIZE]; 00196 00197 template <class B> limitint<B> operator + (const limitint<B> &, const limitint<B> &); 00198 template <class B> inline limitint<B> operator + (const limitint<B> & a, U_I b) 00199 { return a + limitint<B>(b); } 00200 template <class B> limitint<B> operator - (const limitint<B> &, const limitint<B> &); 00201 template <class B> inline limitint<B> operator - (const limitint<B> & a, U_I b) 00202 { return a - limitint<B>(b); } 00203 template <class B> limitint<B> operator * (const limitint<B> &, const limitint<B> &); 00204 template <class B> inline limitint<B> operator * (const limitint<B> & a, U_I b) 00205 { return a * limitint<B>(b); } 00206 template <class B> limitint<B> operator / (const limitint<B> &, const limitint<B> &); 00207 template <class B> limitint<B> operator / (const limitint<B> & a, U_I b) 00208 { return a / limitint<B>(b); } 00209 template <class B> limitint<B> operator % (const limitint<B> &, const limitint<B> &); 00210 template <class B> limitint<B> operator >> (const limitint<B> & a, U_32 bit); 00211 template <class B> limitint<B> operator >> (const limitint<B> & a, const limitint<B> & bit); 00212 template <class B> limitint<B> operator << (const limitint<B> & a, U_32 bit); 00213 template <class B> limitint<B> operator << (const limitint<B> & a, const limitint<B> & bit); 00214 template <class B> limitint<B> operator & (const limitint<B> & a, U_32 bit); 00215 template <class B> limitint<B> operator & (const limitint<B> & a, const limitint<B> & bit); 00216 template <class B> limitint<B> operator | (const limitint<B> & a, U_32 bit); 00217 template <class B> limitint<B> operator | (const limitint<B> & a, const limitint<B> & bit); 00218 template <class B> limitint<B> operator ^ (const limitint<B> & a, U_32 bit); 00219 template <class B> limitint<B> operator ^ (const limitint<B> & a, const limitint<B> & bit); 00220 00221 template <class T> inline void euclide(T a, T b, T & q, T &r) 00222 { 00223 00224 q = a/b; r = a%b; 00225 } 00226 00227 template <class B> inline void euclide(limitint<B> a, U_I b, limitint<B> & q, limitint<B> &r) 00228 { 00229 euclide(a, limitint<B>(b), q, r); 00230 } 00231 00232 #ifndef INFININT_BASE_TYPE 00233 #error INFININT_BASE_TYPE not defined cannot instantiate template 00234 #else 00235 typedef limitint<INFININT_BASE_TYPE> infinint; 00236 #endif 00237 } // end of namespace 00241 00242 #include "generic_file.hpp" 00243 #include "fichier.hpp" 00244 #include "user_interaction.hpp" 00245 00246 namespace libdar 00247 { 00248 00249 template <class B> typename limitint<B>::endian limitint<B>::used_endian = not_initialized; 00250 00251 00252 00253 template <class B> limitint<B>::limitint(user_interaction & dialog, S_I fd) 00254 { 00255 fichier f = fichier(dialog, dup(fd)); 00256 build_from_file(f); 00257 } 00258 00259 template <class B> limitint<B>::limitint(generic_file & x) 00260 { 00261 build_from_file(x); 00262 } 00263 00264 template <class B> void limitint<B>::dump(user_interaction & dialog, S_I fd) const 00265 { 00266 fichier f = fichier(dialog, dup(fd)); 00267 dump(f); 00268 } 00269 00270 template <class B> void limitint<B>::build_from_file(generic_file & x) 00271 { 00272 unsigned char a; 00273 bool fin = false; 00274 limitint<B> skip = 0; 00275 char *ptr = (char *)&field; 00276 S_I lu; 00277 int_tools_bitfield bf; 00278 00279 while(!fin) 00280 { 00281 lu = x.read((char *)&a, 1); 00282 00283 if(lu <= 0) 00284 throw Erange("limitint::build_from_file(generic_file)", gettext("Reached end of file before all data could be read")); 00285 00286 if(a == 0) 00287 ++skip; 00288 else // end of size field 00289 { 00290 // computing the size to read 00291 U_I pos = 0; 00292 00293 int_tools_expand_byte(a, bf); 00294 for(S_I i = 0; i < 8; ++i) 00295 pos += bf[i]; 00296 if(pos != 1) 00297 throw Erange("limitint::build_from_file(generic_file)", gettext("Badly formed \"infinint\" or not supported format")); // more than 1 bit is set to 1 00298 00299 pos = 0; 00300 while(bf[pos] == 0) 00301 ++pos; 00302 pos += 1; // bf starts at zero, but bit zero means 1 TG of length 00303 00304 skip *= 8; 00305 skip += pos; 00306 skip *= TG; 00307 00308 if(skip.field > bytesize) 00309 throw Elimitint(); 00310 00311 field = 0; // important to also clear "unread" bytes by this call 00312 lu = x.read(ptr, skip.field); 00313 00314 if(used_endian == not_initialized) 00315 setup_endian(); 00316 if(used_endian == little_endian) 00317 int_tools_swap_bytes((unsigned char *)ptr, skip.field); 00318 else 00319 field >>= (bytesize - skip.field)*8; 00320 fin = true; 00321 } 00322 } 00323 } 00324 00325 00326 template <class B> void limitint<B>::dump(generic_file & x) const 00327 { 00328 B width = bytesize; 00329 B pos; 00330 unsigned char last_width; 00331 B justification; 00332 S_I direction = +1; 00333 unsigned char *ptr, *fin; 00334 00335 00336 if(used_endian == not_initialized) 00337 setup_endian(); 00338 00339 if(used_endian == little_endian) 00340 { 00341 direction = -1; 00342 ptr = (unsigned char *)(&field) + (bytesize - 1); 00343 fin = (unsigned char *)(&field) - 1; 00344 } 00345 else 00346 { 00347 direction = +1; 00348 ptr = (unsigned char *)(&field); 00349 fin = (unsigned char *)(&field) + bytesize; 00350 } 00351 00352 while(ptr != fin && *ptr == 0) 00353 { 00354 ptr += direction; 00355 --width; 00356 } 00357 if(width == 0) 00358 width = 1; // minimum size of information is 1 byte 00359 00360 // "width" is the informational field size in byte 00361 // TG is the width in TG, thus the number of bit that must have 00362 // the preamble 00363 euclide(width, (const B)(TG), width, justification); 00364 if(justification != 0) 00365 // in case we need to add some bytes to have a width multiple of TG 00366 ++width; // we need then one more group to have a width multiple of TG 00367 00368 euclide(width, (const B)(8), width, pos); 00369 if(pos == 0) 00370 { 00371 width--; // division is exact, only last bit of the preambule is set 00372 last_width = 0x80 >> 7; 00373 // as we add the last byte separately width gets shorter by 1 byte 00374 } 00375 else // division non exact, the last_width (last byte), make the rounding 00376 { 00377 U_16 pos_s = (U_16)(0xFFFF & pos); 00378 last_width = 0x80 >> (pos_s - 1); 00379 } 00380 00381 // now we write the preamble except the last byte. All these are zeros. 00382 00383 while(width != 0) 00384 if(width > ZEROED_SIZE) 00385 { 00386 x.write((char *)zeroed_field, ZEROED_SIZE); 00387 width -= ZEROED_SIZE; 00388 } 00389 else 00390 { 00391 x.write((char *)zeroed_field, width); 00392 width = 0; 00393 } 00394 00395 // now we write the last byte of the preambule, which as only one bit set 00396 00397 x.write((char *)&last_width, 1); 00398 00399 // we need now to write some justification byte to have an informational field multiple of TG 00400 00401 if(justification != 0) 00402 { 00403 justification = TG - justification; 00404 if(justification > ZEROED_SIZE) 00405 throw SRC_BUG; 00406 else 00407 x.write((char *)zeroed_field, justification); 00408 } 00409 00410 // now we continue dumping the informational bytes: 00411 if(ptr == fin) // field is equal to zero 00412 x.write((char *)zeroed_field, 1); 00413 else // we have some bytes to write down 00414 while(ptr != fin) 00415 { 00416 x.write((char *)ptr, 1); 00417 ptr += direction; 00418 } 00419 } 00420 00421 template<class B> limitint<B> & limitint<B>::operator += (const limitint & arg) 00422 { 00423 B res = field + arg.field; 00424 if(res < field || res < arg.field) 00425 throw Elimitint(); 00426 else 00427 field = res; 00428 00429 return *this; 00430 } 00431 00432 template <class B> limitint<B> & limitint<B>::operator -= (const limitint & arg) 00433 { 00434 if(field < arg.field) 00435 throw Erange("limitint::operator", gettext("Subtracting an \"infinint\" greater than the first, \"infinint\" cannot be negative")); 00436 00437 // now processing the operation 00438 00439 field -= arg.field; 00440 return *this; 00441 } 00442 00443 00444 template <class B> limitint<B> & limitint<B>::operator *= (const limitint & arg) 00445 { 00446 static const B max_power = bytesize*8 - 1; 00447 00448 B total = int_tools_higher_power_of_2(field) + int_tools_higher_power_of_2(arg.field) + 1; // for an explaination about "+2" see NOTES 00449 if(total > max_power) // this is a bit too much restrictive, but unless remaking bit by bit, the operation, 00450 // I don't see how to simply (and fast) know the result has not overflowed. 00451 // of course, it would be fast and easy to access the CPU flag register to check for overflow, 00452 // but that would not be portable, and unfortunately I haven't found any standart C++ expression that 00453 // could transparently access to it. 00454 throw Elimitint(); 00455 00456 total = field*arg.field; 00457 if(field != 0 && arg.field != 0) 00458 if(total < field || total < arg.field) 00459 throw Elimitint(); 00460 field = total; 00461 return *this; 00462 } 00463 00464 template <class B> template<class T> limitint<B> limitint<B>::power(const T & exponent) const 00465 { 00466 limitint ret = 1; 00467 for(T count = 0; count < exponent; ++count) 00468 ret *= *this; 00469 00470 return ret; 00471 } 00472 00473 template <class B> limitint<B> & limitint<B>::operator /= (const limitint & arg) 00474 { 00475 if(arg == 0) 00476 throw Einfinint("limitint.cpp : operator /=", gettext("Division by zero")); 00477 00478 field /= arg.field; 00479 return *this; 00480 } 00481 00482 template <class B> limitint<B> & limitint<B>::operator %= (const limitint & arg) 00483 { 00484 if(arg == 0) 00485 throw Einfinint("limitint.cpp : operator %=", gettext("Division by zero")); 00486 00487 field %= arg.field; 00488 return *this; 00489 } 00490 00491 template <class B> limitint<B> & limitint<B>::operator >>= (U_32 bit) 00492 { 00493 if(bit >= sizeof_field*8) 00494 field = 0; 00495 else 00496 field >>= bit; 00497 return *this; 00498 } 00499 00500 template <class B> limitint<B> & limitint<B>::operator >>= (limitint bit) 00501 { 00502 field >>= bit.field; 00503 return *this; 00504 } 00505 00506 template <class B> limitint<B> & limitint<B>::operator <<= (U_32 bit) 00507 { 00508 if(bit + int_tools_higher_power_of_2(field) >= bytesize*8) 00509 throw Elimitint(); 00510 field <<= bit; 00511 return *this; 00512 } 00513 00514 template <class B> limitint<B> & limitint<B>::operator <<= (limitint bit) 00515 { 00516 if(bit.field + int_tools_higher_power_of_2(field) >= bytesize*8) 00517 throw Elimitint(); 00518 field <<= bit.field; 00519 return *this; 00520 } 00521 00522 template <class B> limitint<B> & limitint<B>::operator &= (const limitint & arg) 00523 { 00524 field &= arg.field; 00525 return *this; 00526 } 00527 00528 template <class B> limitint<B> & limitint<B>::operator |= (const limitint & arg) 00529 { 00530 field |= arg.field; 00531 return *this; 00532 } 00533 00534 template <class B> limitint<B> & limitint<B>::operator ^= (const limitint & arg) 00535 { 00536 field ^= arg.field; 00537 return *this; 00538 } 00539 00540 template <class B> U_32 limitint<B>::operator % (U_32 arg) const 00541 { 00542 return U_32(field % arg); 00543 } 00544 00545 template <class B> template <class T> void limitint<B>::limitint_from(T a) 00546 { 00547 if(sizeof(a) <= bytesize || a <= (T)(max_value)) 00548 field = B(a); 00549 else 00550 throw Elimitint(); 00551 } 00552 00553 template <class B> template <class T> T limitint<B>::max_val_of(T x) 00554 { 00555 x = 0; 00556 x = ~x; 00557 00558 if(x < 1) // T is a signed integer type, we are not comparing to zero to avoid compiler warning when the template is used against unsigned integers 00559 { 00560 x = 1; 00561 x = int_tools_rotate_right_one_bit(x); 00562 x = ~x; 00563 } 00564 00565 return x; 00566 } 00567 00568 template <class B> template <class T> void limitint<B>::limitint_unstack_to(T &a) 00569 { 00570 00571 // T is supposed to be an unsigned "integer" 00572 // (ie.: sizeof returns the width of the storage bit field and no sign bit is present) 00573 // Note : static here avoids the recalculation of max_T at each call 00574 static const T max_T = max_val_of(a); 00575 T step = max_T - a; 00576 00577 if(field < (B)(step) && (T)(field) < step) 00578 { 00579 a += field; 00580 field = 0; 00581 } 00582 else 00583 { 00584 field -= step; 00585 a = max_T; 00586 } 00587 } 00588 00589 template <class B> limitint<B> limitint<B>::get_storage_size() const 00590 { 00591 B tmp = field; 00592 B ret = 0; 00593 00594 while(tmp != 0) 00595 { 00596 tmp >>= 8; 00597 ret++; 00598 } 00599 00600 return limitint<B>(ret); 00601 } 00602 00603 template <class B> unsigned char limitint<B>::operator [] (const limitint & position) const 00604 { 00605 B tmp = field; 00606 B index = position.field; // C++ has only class protection, not object protection 00607 00608 while(index > 0) 00609 { 00610 tmp >>= 8; 00611 index--; 00612 } 00613 00614 return (unsigned char)(tmp & 0xFF); 00615 } 00616 00617 template <class B> void limitint<B>::setup_endian() 00618 { 00619 if(integers_system_is_big_endian()) 00620 used_endian = big_endian; 00621 else 00622 used_endian = little_endian; 00623 00624 (void)memset(zeroed_field, 0, ZEROED_SIZE); 00625 } 00626 00627 00628 template <class B> bool limitint<B>::is_system_big_endian() 00629 { 00630 if(used_endian == not_initialized) 00631 setup_endian(); 00632 00633 switch(used_endian) 00634 { 00635 case big_endian: 00636 return true; 00637 case little_endian: 00638 return false; 00639 case not_initialized: 00640 throw SRC_BUG; 00641 default: 00642 throw SRC_BUG; 00643 } 00644 } 00645 00646 00650 00651 template <class B> limitint<B> operator + (const limitint<B> & a, const limitint<B> & b) 00652 { 00653 limitint<B> ret = a; 00654 ret += b; 00655 00656 return ret; 00657 } 00658 00659 template <class B> limitint<B> operator - (const limitint<B> & a, const limitint<B> & b) 00660 { 00661 limitint<B> ret = a; 00662 ret -= b; 00663 00664 return ret; 00665 } 00666 00667 template <class B> limitint<B> operator * (const limitint<B> & a, const limitint<B> & b) 00668 { 00669 limitint<B> ret = a; 00670 ret *= b; 00671 00672 return ret; 00673 } 00674 00675 template <class B> limitint<B> operator / (const limitint<B> & a, const limitint<B> & b) 00676 { 00677 limitint<B> ret = a; 00678 ret /= b; 00679 00680 return ret; 00681 } 00682 00683 template <class B> limitint<B> operator % (const limitint<B> & a, const limitint<B> & b) 00684 { 00685 limitint<B> ret = a; 00686 ret %= b; 00687 00688 return ret; 00689 } 00690 00691 template <class B> limitint<B> operator >> (const limitint<B> & a, U_32 bit) 00692 { 00693 limitint<B> ret = a; 00694 ret >>= bit; 00695 return ret; 00696 } 00697 00698 template <class B> limitint<B> operator >> (const limitint<B> & a, const limitint<B> & bit) 00699 { 00700 limitint<B> ret = a; 00701 ret >>= bit; 00702 return ret; 00703 } 00704 00705 template <class B> limitint<B> operator << (const limitint<B> & a, U_32 bit) 00706 { 00707 limitint<B> ret = a; 00708 ret <<= bit; 00709 return ret; 00710 } 00711 00712 template <class B> limitint<B> operator << (const limitint<B> & a, const limitint<B> & bit) 00713 { 00714 limitint<B> ret = a; 00715 ret <<= bit; 00716 return ret; 00717 } 00718 00719 template <class B> limitint<B> operator & (const limitint<B> & a, U_32 bit) 00720 { 00721 limitint<B> ret = a; 00722 ret &= bit; 00723 return ret; 00724 } 00725 00726 template <class B> limitint<B> operator & (const limitint<B> & a, const limitint<B> & bit) 00727 { 00728 limitint<B> ret = a; 00729 ret &= bit; 00730 return ret; 00731 } 00732 00733 template <class B> limitint<B> operator | (const limitint<B> & a, U_32 bit) 00734 { 00735 limitint<B> ret = a; 00736 ret |= bit; 00737 return ret; 00738 } 00739 00740 template <class B> limitint<B> operator | (const limitint<B> & a, const limitint<B> & bit) 00741 { 00742 limitint<B> ret = a; 00743 ret |= bit; 00744 return ret; 00745 } 00746 00747 template <class B> limitint<B> operator ^ (const limitint<B> & a, U_32 bit) 00748 { 00749 limitint<B> ret = a; 00750 ret ^= bit; 00751 return ret; 00752 } 00753 00754 template <class B> limitint<B> operator ^ (const limitint<B> & a, const limitint<B> & bit) 00755 { 00756 limitint<B> ret = a; 00757 ret ^= bit; 00758 return ret; 00759 } 00760 00762 00763 } // end of namespace 00764 00765 #endif
1.7.6.1