00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00032
00033 #ifndef LIMITINT_HPP
00034 #define LIMITINT_HPP
00035
00036 #include "../my_config.h"
00037
00038 extern "C"
00039 {
00040 #if HAVE_SYS_TYPES_H
00041 #include <sys/types.h>
00042 #endif
00043
00044 #if HAVE_UNISTD_H
00045 #include <unistd.h>
00046 #endif
00047 }
00048
00049 #include <typeinfo>
00050 #include "integers.hpp"
00051 #include "erreurs.hpp"
00052 #include "special_alloc.hpp"
00053 #include "int_tools.hpp"
00054
00055 namespace libdar
00056 {
00057
00058 class generic_file;
00059 class user_interaction;
00060
00062
00072
00073 template<class B> class limitint
00074 {
00075 public :
00076
00077 #if SIZEOF_OFF_T > SIZEOF_TIME_T
00078 #if SIZEOF_OFF_T > SIZEOF_SIZE_T
00079 limitint(off_t a = 0)
00080 { E_BEGIN; limitint_from(a); E_END("limitint::limitint", "off_t"); };
00081 #else
00082 limitint(size_t a = 0)
00083 { E_BEGIN; limitint_from(a); E_END("limitint::limitint", "size_t"); };
00084 #endif
00085 #else
00086 #if SIZEOF_TIME_T > SIZEOF_SIZE_T
00087 limitint(time_t a = 0)
00088 { E_BEGIN; limitint_from(a); E_END("limitint::limitint", "time_t"); };
00089 #else
00090 limitint(size_t a = 0)
00091 { E_BEGIN; limitint_from(a); E_END("limitint::limitint", "size_t"); };
00092 #endif
00093 #endif
00094
00095 limitint(user_interaction & dialog, S_I *fd, generic_file *x);
00096
00097
00098 void dump(user_interaction & dialog, S_I fd) const;
00099 void dump(generic_file &x) const;
00100 void read(generic_file &f) { build_from_file(f); };
00101
00102 limitint & operator += (const limitint & ref);
00103 limitint & operator -= (const limitint & ref);
00104 limitint & operator *= (const limitint & ref);
00105 template <class T> limitint power(const T & exponent) const;
00106 limitint & operator /= (const limitint & ref);
00107 limitint & operator %= (const limitint & ref);
00108 limitint & operator &= (const limitint & ref);
00109 limitint & operator |= (const limitint & ref);
00110 limitint & operator ^= (const limitint & ref);
00111 limitint & operator >>= (U_32 bit);
00112 limitint & operator >>= (limitint bit);
00113 limitint & operator <<= (U_32 bit);
00114 limitint & operator <<= (limitint bit);
00115 limitint operator ++(int a)
00116 { E_BEGIN; limitint ret = *this; ++(*this); return ret; E_END("limitint::operator ++", "int"); };
00117 limitint operator --(int a)
00118 { E_BEGIN; limitint ret = *this; --(*this); return ret; E_END("limitint::operator --", "int"); };
00119 limitint & operator ++()
00120 { E_BEGIN; return *this += 1; E_END("limitint::operator ++", "()"); };
00121 limitint & operator --()
00122 { E_BEGIN; return *this -= 1; E_END("limitint::operator --", "()"); };
00123
00124 U_32 operator % (U_32 arg) const;
00125
00126
00127
00128
00129 template <class T>void unstack(T &v)
00130 { E_BEGIN; limitint_unstack_to(v); E_END("limitint::unstack", typeid(v).name()); }
00131
00132 limitint get_storage_size() const;
00133
00134
00135 unsigned char operator [] (const limitint & position) const;
00136
00137
00138
00139 bool operator < (const limitint &x) const { return field < x.field; };
00140 bool operator == (const limitint &x) const { return field == x.field; };
00141 bool operator > (const limitint &x) const { return field > x.field; };
00142 bool operator <= (const limitint &x) const { return field <= x.field; };
00143 bool operator != (const limitint &x) const { return field != x.field; };
00144 bool operator >= (const limitint &x) const { return field >= x.field; };
00145
00146 #ifdef LIBDAR_SPECIAL_ALLOC
00147 USE_SPECIAL_ALLOC(limitint);
00148 #endif
00149
00150 B debug_get_max() const { return max_value; };
00151 B debug_get_bytesize() const { return bytesize; };
00152
00153 private :
00154 static const int TG = 4;
00155 static const U_32 sizeof_field = sizeof(B);
00156
00157 enum endian { big_endian, little_endian, not_initialized };
00158 typedef unsigned char group[TG];
00159
00160 B field;
00161
00162 void build_from_file(generic_file & x);
00163 template <class T> void limitint_from(T a);
00164 template <class T> void limitint_unstack_to(T &a);
00165
00167
00168
00169 static endian used_endian;
00170 static const U_I bytesize = sizeof(B);
00171 static const B max_value = ~B(0) > 0 ? ~B(0) : ~(B(1) << (bytesize*8 - 1));
00172 static void setup_endian();
00173 };
00174
00175 template <class B> limitint<B> operator + (const limitint<B> &, const limitint<B> &);
00176 template <class B> inline limitint<B> operator + (const limitint<B> & a, U_I b)
00177 { return a + limitint<B>(b); }
00178 template <class B> limitint<B> operator - (const limitint<B> &, const limitint<B> &);
00179 template <class B> inline limitint<B> operator - (const limitint<B> & a, U_I b)
00180 { return a - limitint<B>(b); }
00181 template <class B> limitint<B> operator * (const limitint<B> &, const limitint<B> &);
00182 template <class B> inline limitint<B> operator * (const limitint<B> & a, U_I b)
00183 { return a * limitint<B>(b); }
00184 template <class B> limitint<B> operator / (const limitint<B> &, const limitint<B> &);
00185 template <class B> limitint<B> operator / (const limitint<B> & a, U_I b)
00186 { return a / limitint<B>(b); }
00187 template <class B> limitint<B> operator % (const limitint<B> &, const limitint<B> &);
00188 template <class B> limitint<B> operator >> (const limitint<B> & a, U_32 bit);
00189 template <class B> limitint<B> operator >> (const limitint<B> & a, const limitint<B> & bit);
00190 template <class B> limitint<B> operator << (const limitint<B> & a, U_32 bit);
00191 template <class B> limitint<B> operator << (const limitint<B> & a, const limitint<B> & bit);
00192 template <class B> limitint<B> operator & (const limitint<B> & a, U_32 bit);
00193 template <class B> limitint<B> operator & (const limitint<B> & a, const limitint<B> & bit);
00194 template <class B> limitint<B> operator | (const limitint<B> & a, U_32 bit);
00195 template <class B> limitint<B> operator | (const limitint<B> & a, const limitint<B> & bit);
00196 template <class B> limitint<B> operator ^ (const limitint<B> & a, U_32 bit);
00197 template <class B> limitint<B> operator ^ (const limitint<B> & a, const limitint<B> & bit);
00198
00199 template <class T> inline void euclide(T a, T b, T & q, T &r)
00200 {
00201 E_BEGIN;
00202 q = a/b; r = a%b;
00203 E_END("euclide", "");
00204 }
00205
00206 template <class B> inline void euclide(limitint<B> a, U_I b, limitint<B> & q, limitint<B> &r)
00207 {
00208 euclide(a, limitint<B>(b), q, r);
00209 }
00210
00211 #ifndef INFININT_BASE_TYPE
00212 #error INFININT_BASE_TYPE not defined cannot instantiate template
00213 #else
00214 typedef limitint<INFININT_BASE_TYPE> infinint;
00215 #endif
00216 }
00220
00221 #include "generic_file.hpp"
00222 #include "user_interaction.hpp"
00223
00224 namespace libdar
00225 {
00226
00227 template <class B> typename limitint<B>::endian limitint<B>::used_endian = not_initialized;
00228
00229 template <class B> limitint<B>::limitint(user_interaction & dialog, S_I *fd, generic_file *x)
00230 {
00231 if(fd != NULL && x != NULL)
00232 throw Erange("limitint::limitint(file, file)", "Both arguments are not NULL, please choose one or the other, not both");
00233 if(fd != NULL)
00234 {
00235 fichier f = fichier(dialog, dup(*fd));
00236 build_from_file(f);
00237 }
00238 else
00239 if(x != NULL)
00240 build_from_file(*x);
00241 else
00242 throw Erange("limitint::limitint(file, file)", "Cannot read from file, both arguments are NULL");
00243 }
00244
00245 template <class B> void limitint<B>::dump(user_interaction & dialog, S_I fd) const
00246 {
00247 fichier f = fichier(dialog, dup(fd));
00248 dump(f);
00249 }
00250
00251 template <class B> void limitint<B>::build_from_file(generic_file & x)
00252 {
00253 E_BEGIN;
00254 unsigned char a;
00255 bool fin = false;
00256 limitint<B> skip = 0;
00257 char *ptr = (char *)&field;
00258 S_I lu;
00259 int_tools_bitfield bf;
00260
00261 while(!fin)
00262 {
00263 lu = x.read((char *)&a, 1);
00264
00265 if(lu <= 0)
00266 throw Erange("limitint::build_from_file(generic_file)", gettext("Reached end of file before all data could be read"));
00267
00268 if(a == 0)
00269 ++skip;
00270 else
00271 {
00272
00273 U_I pos = 0;
00274
00275 int_tools_expand_byte(a, bf);
00276 for(S_I i = 0; i < 8; ++i)
00277 pos += bf[i];
00278 if(pos != 1)
00279 throw Erange("limitint::build_from_file(generic_file)", gettext("Badly formed infinint or not supported format"));
00280
00281 pos = 0;
00282 while(bf[pos] == 0)
00283 ++pos;
00284 pos += 1;
00285
00286 skip *= 8;
00287 skip += pos;
00288 skip *= TG;
00289
00290 if(skip.field > bytesize)
00291 throw Elimitint();
00292
00293 field = 0;
00294 lu = x.read(ptr, skip.field);
00295
00296 if(used_endian == not_initialized)
00297 setup_endian();
00298 if(used_endian == big_endian)
00299 int_tools_swap_bytes((unsigned char *)ptr, skip.field);
00300 else
00301 field >>= (bytesize - skip.field)*8;
00302 fin = true;
00303 }
00304 }
00305 E_END("limitint::read_from_file", "generic_file");
00306 }
00307
00308
00309 template <class B> void limitint<B>::dump(generic_file & x) const
00310 {
00311 E_BEGIN;
00312 B width = bytesize;
00313 B pos;
00314 unsigned char last_width;
00315 B justification;
00316 S_I direction = +1;
00317 unsigned char *ptr, *fin;
00318
00319
00320 if(used_endian == not_initialized)
00321 setup_endian();
00322
00323 if(used_endian == big_endian)
00324 {
00325 direction = -1;
00326 ptr = (unsigned char *)(&field) + (bytesize - 1);
00327 fin = (unsigned char *)(&field) - 1;
00328 }
00329 else
00330 {
00331 direction = +1;
00332 ptr = (unsigned char *)(&field);
00333 fin = (unsigned char *)(&field) + bytesize;
00334 }
00335
00336 while(ptr != fin && *ptr == 0)
00337 {
00338 ptr += direction;
00339 --width;
00340 }
00341 if(width == 0)
00342 width = 1;
00343
00344
00345
00346
00347 euclide(width, (const B)(TG), width, justification);
00348 if(justification != 0)
00349
00350 ++width;
00351
00352 euclide(width, (const B)(8), width, pos);
00353 if(pos == 0)
00354 {
00355 width--;
00356 last_width = 0x80 >> 7;
00357
00358 }
00359 else
00360 {
00361 U_16 pos_s = (U_16)(0xFFFF & pos);
00362 last_width = 0x80 >> (pos_s - 1);
00363 }
00364
00365
00366
00367 unsigned char u = 0x00;
00368
00369 while(width-- > 0)
00370 if(x.write((char *)(&u), 1) < 1)
00371 throw Erange("limitint::dump(generic_file)", gettext("Cannot write data to file"));
00372
00373
00374
00375
00376 if(x.write((char *)&last_width, 1) < 1)
00377 throw Erange("limitint::dump(generic_file)", gettext("Cannot write data to file"));
00378
00379
00380
00381 if(justification != 0)
00382 {
00383 justification = TG - justification;
00384 while(justification-- > 0)
00385 if(x.write((char *)(&u), 1) < 1)
00386 throw Erange("limitint::dump(generic_file)", gettext("Cannot write data to file"));
00387 }
00388
00389
00390 if(ptr == fin)
00391 {
00392 if(x.write((char *)(&u), 1) < 1)
00393 throw Erange("limitint::dump(generic_file)", gettext("Cannot write data to file"));
00394 }
00395 else
00396 while(ptr != fin)
00397 {
00398 if(x.write((char *)ptr, 1) < 1)
00399 throw Erange("limitint::dump(generic_file)", gettext("Cannot write data to file"));
00400 else
00401 ptr += direction;
00402 }
00403
00404 E_END("limitint::dump", "generic_file");
00405 }
00406
00407 template<class B> limitint<B> & limitint<B>::operator += (const limitint & arg)
00408 {
00409 E_BEGIN;
00410 B res = field + arg.field;
00411 if(res < field || res < arg.field)
00412 throw Elimitint();
00413 else
00414 field = res;
00415
00416 return *this;
00417 E_END("limitint::operator +=", "");
00418 }
00419
00420 template <class B> limitint<B> & limitint<B>::operator -= (const limitint & arg)
00421 {
00422 E_BEGIN;
00423 if(field < arg.field)
00424 throw Erange("limitint::operator", gettext("Subtracting a infinint greater than the first, infinint cannot be negative"));
00425
00426
00427
00428 field -= arg.field;
00429 return *this;
00430 E_END("limitint::operator -=", "");
00431 }
00432
00433
00434 template <class B> limitint<B> & limitint<B>::operator *= (const limitint & arg)
00435 {
00436 E_BEGIN;
00437 static const B max_power = bytesize*8 - 1;
00438
00439 B total = int_tools_higher_power_of_2(field) + int_tools_higher_power_of_2(arg.field) + 1;
00440 if(total > max_power)
00441
00442
00443
00444
00445 throw Elimitint();
00446
00447 total = field*arg.field;
00448 if(field != 0 && arg.field != 0)
00449 if(total < field || total < arg.field)
00450 throw Elimitint();
00451 field = total;
00452 return *this;
00453 E_END("limitint::operator *=", "");
00454 }
00455
00456 template <class B> template<class T> limitint<B> limitint<B>::power(const T & exponent) const
00457 {
00458 limitint ret = 1;
00459 for(T count = 0; count < exponent; ++count)
00460 ret *= *this;
00461
00462 return ret;
00463 }
00464
00465 template <class B> limitint<B> & limitint<B>::operator /= (const limitint & arg)
00466 {
00467 E_BEGIN;
00468 if(arg == 0)
00469 throw Einfinint("limitint.cpp : operator /=", gettext("Division by zero"));
00470
00471 field /= arg.field;
00472 return *this;
00473 E_END("limitint::operator /=", "");
00474 }
00475
00476 template <class B> limitint<B> & limitint<B>::operator %= (const limitint & arg)
00477 {
00478 E_BEGIN;
00479 if(arg == 0)
00480 throw Einfinint("limitint.cpp : operator %=", gettext("Division by zero"));
00481
00482 field %= arg.field;
00483 return *this;
00484 E_END("limitint::operator /=", "");
00485 }
00486
00487 template <class B> limitint<B> & limitint<B>::operator >>= (U_32 bit)
00488 {
00489 E_BEGIN;
00490 if(bit >= sizeof_field)
00491 field = 0;
00492 else
00493 field >>= bit;
00494 return *this;
00495 E_END("limitint::operator >>=", "U_32");
00496 }
00497
00498 template <class B> limitint<B> & limitint<B>::operator >>= (limitint bit)
00499 {
00500 E_BEGIN;
00501 field >>= bit.field;
00502 return *this;
00503 E_END("limitint::operator >>=", "limitint");
00504 }
00505
00506 template <class B> limitint<B> & limitint<B>::operator <<= (U_32 bit)
00507 {
00508 E_BEGIN;
00509 if(bit + int_tools_higher_power_of_2(field) >= bytesize*8)
00510 throw Elimitint();
00511 field <<= bit;
00512 return *this;
00513 E_END("limitint::operator <<=", "U_32");
00514 }
00515
00516 template <class B> limitint<B> & limitint<B>::operator <<= (limitint bit)
00517 {
00518 E_BEGIN;
00519 if(bit.field + int_tools_higher_power_of_2(field) >= bytesize*8)
00520 throw Elimitint();
00521 field <<= bit.field;
00522 return *this;
00523 E_END("limitint::operator <<=", "limitint");
00524 }
00525
00526 template <class B> limitint<B> & limitint<B>::operator &= (const limitint & arg)
00527 {
00528 E_BEGIN;
00529 field &= arg.field;
00530 return *this;
00531 E_END("limitint::operator &=", "");
00532 }
00533
00534 template <class B> limitint<B> & limitint<B>::operator |= (const limitint & arg)
00535 {
00536 E_BEGIN;
00537 field |= arg.field;
00538 return *this;
00539 E_END("limitint::operator |=", "");
00540 }
00541
00542 template <class B> limitint<B> & limitint<B>::operator ^= (const limitint & arg)
00543 {
00544 E_BEGIN;
00545 field ^= arg.field;
00546 return *this;
00547 E_END("limitint::operator ^=", "");
00548 }
00549
00550 template <class B> U_32 limitint<B>::operator % (U_32 arg) const
00551 {
00552 E_BEGIN;
00553 return U_32(field % arg);
00554 E_END("limitint::modulo", "");
00555 }
00556
00557 template <class B> template <class T> void limitint<B>::limitint_from(T a)
00558 {
00559 E_BEGIN;
00560 if(sizeof(a) <= bytesize || a <= (T)(max_value))
00561 field = B(a);
00562 else
00563 throw Elimitint();
00564 E_END("limitint::limitint_from", "");
00565 }
00566
00567 template <class B> template <class T> void limitint<B>::limitint_unstack_to(T &a)
00568 {
00569 E_BEGIN;
00570
00571
00572
00573 static const T max_T = ~T(0) > 0 ? ~T(0) : ~int_tools_rotate_right_one_bit(T(1));
00574 T step = max_T - a;
00575
00576 if(field < (B)(step) && (T)(field) < step)
00577 {
00578 a += field;
00579 field = 0;
00580 }
00581 else
00582 {
00583 field -= step;
00584 a = max_T;
00585 }
00586
00587 E_END("limitint::limitint_unstack_to", "");
00588 }
00589
00590 template <class B> limitint<B> limitint<B>::get_storage_size() const
00591 {
00592 B tmp = field;
00593 B ret = 0;
00594
00595 while(tmp != 0)
00596 {
00597 tmp >>= 8;
00598 ret++;
00599 }
00600
00601 return limitint<B>(ret);
00602 }
00603
00604 template <class B> unsigned char limitint<B>::operator [] (const limitint & position) const
00605 {
00606 B tmp = field;
00607 B index = position.field;
00608
00609 while(index > 0)
00610 {
00611 tmp >>= 8;
00612 index--;
00613 }
00614
00615 return (unsigned char)(tmp & 0xFF);
00616 }
00617
00618 template <class B> void limitint<B>::setup_endian()
00619 {
00620 E_BEGIN;
00621 U_16 u = 1;
00622 unsigned char *ptr = (unsigned char *)(&u);
00623
00624 if(ptr[0] == 1)
00625 used_endian = big_endian;
00626 else
00627 used_endian = little_endian;
00628 E_END("limitint::setup_endian", "");
00629 }
00630
00631
00632
00633
00637
00638 template <class B> limitint<B> operator + (const limitint<B> & a, const limitint<B> & b)
00639 {
00640 E_BEGIN;
00641 limitint<B> ret = a;
00642 ret += b;
00643
00644 return ret;
00645 E_END("operator +", "limitint");
00646 }
00647
00648 template <class B> limitint<B> operator - (const limitint<B> & a, const limitint<B> & b)
00649 {
00650 E_BEGIN;
00651 limitint<B> ret = a;
00652 ret -= b;
00653
00654 return ret;
00655 E_END("operator -", "limitint");
00656 }
00657
00658 template <class B> limitint<B> operator * (const limitint<B> & a, const limitint<B> & b)
00659 {
00660 E_BEGIN;
00661 limitint<B> ret = a;
00662 ret *= b;
00663
00664 return ret;
00665 E_END("operator *", "limitint");
00666 }
00667
00668 template <class B> limitint<B> operator / (const limitint<B> & a, const limitint<B> & b)
00669 {
00670 E_BEGIN;
00671 limitint<B> ret = a;
00672 ret /= b;
00673
00674 return ret;
00675 E_END("operator / ", "limitint");
00676 }
00677
00678 template <class B> limitint<B> operator % (const limitint<B> & a, const limitint<B> & b)
00679 {
00680 E_BEGIN;
00681 limitint<B> ret = a;
00682 ret %= b;
00683
00684 return ret;
00685 E_END("operator %", "limitint");
00686 }
00687
00688 template <class B> limitint<B> operator >> (const limitint<B> & a, U_32 bit)
00689 {
00690 E_BEGIN;
00691 limitint<B> ret = a;
00692 ret >>= bit;
00693 return ret;
00694 E_END("operator >>", "limitint, U_32");
00695 }
00696
00697 template <class B> limitint<B> operator >> (const limitint<B> & a, const limitint<B> & bit)
00698 {
00699 E_BEGIN;
00700 limitint<B> ret = a;
00701 ret >>= bit;
00702 return ret;
00703 E_END("operator >>", "limitint");
00704 }
00705
00706 template <class B> limitint<B> operator << (const limitint<B> & a, U_32 bit)
00707 {
00708 E_BEGIN;
00709 limitint<B> ret = a;
00710 ret <<= bit;
00711 return ret;
00712 E_END("operator <<", "limitint, U_32");
00713 }
00714
00715 template <class B> limitint<B> operator << (const limitint<B> & a, const limitint<B> & bit)
00716 {
00717 E_BEGIN;
00718 limitint<B> ret = a;
00719 ret <<= bit;
00720 return ret;
00721 E_END("operator <<", "limitint");
00722 }
00723
00724 template <class B> limitint<B> operator & (const limitint<B> & a, U_32 bit)
00725 {
00726 E_BEGIN;
00727 limitint<B> ret = a;
00728 ret &= bit;
00729 return ret;
00730 E_END("operator &", "limitint");
00731 }
00732
00733 template <class B> limitint<B> operator & (const limitint<B> & a, const limitint<B> & bit)
00734 {
00735 E_BEGIN;
00736 limitint<B> ret = a;
00737 ret &= bit;
00738 return ret;
00739 E_END("operator &", "limitint");
00740 }
00741
00742 template <class B> limitint<B> operator | (const limitint<B> & a, U_32 bit)
00743 {
00744 E_BEGIN;
00745 limitint<B> ret = a;
00746 ret |= bit;
00747 return ret;
00748 E_END("operator |", "U_32");
00749 }
00750
00751 template <class B> limitint<B> operator | (const limitint<B> & a, const limitint<B> & bit)
00752 {
00753 E_BEGIN;
00754 limitint<B> ret = a;
00755 ret |= bit;
00756 return ret;
00757 E_END("operator |", "limitint");
00758 }
00759
00760 template <class B> limitint<B> operator ^ (const limitint<B> & a, U_32 bit)
00761 {
00762 E_BEGIN;
00763 limitint<B> ret = a;
00764 ret ^= bit;
00765 return ret;
00766 E_END("operator ^", "U_32");
00767 }
00768
00769 template <class B> limitint<B> operator ^ (const limitint<B> & a, const limitint<B> & bit)
00770 {
00771 E_BEGIN;
00772 limitint<B> ret = a;
00773 ret ^= bit;
00774 return ret;
00775 E_END("operator ^", "limitint");
00776 }
00777
00778
00779 }
00780
00781 #endif