87 template<
class B>
class limitint
91#if SIZEOF_OFF_T > SIZEOF_TIME_T
92#if SIZEOF_OFF_T > SIZEOF_SIZE_T
94 { limitint_from(a); };
96 limitint(
size_t a = 0)
97 { limitint_from(a); };
100#if SIZEOF_TIME_T > SIZEOF_SIZE_T
101 limitint(time_t a = 0)
102 { limitint_from(a); };
104 limitint(
size_t a = 0)
105 { limitint_from(a); };
112 limitint(
const limitint & ref) =
default;
113 limitint(limitint && ref)
noexcept =
default;
114 limitint & operator = (
const limitint & ref) =
default;
115 limitint & operator = (limitint && ref)
noexcept =
default;
118 ~limitint() =
default;
123 limitint & operator += (
const limitint & ref);
124 limitint & operator -= (
const limitint & ref);
125 limitint & operator *= (
const limitint & ref);
126 template <
class T> limitint power(
const T & exponent)
const;
127 limitint & operator /= (
const limitint & ref);
128 limitint & operator %= (
const limitint & ref);
129 limitint & operator &= (
const limitint & ref);
130 limitint & operator |= (
const limitint & ref);
131 limitint & operator ^= (
const limitint & ref);
132 limitint & operator >>= (U_32 bit);
133 limitint & operator >>= (limitint bit);
134 limitint & operator <<= (U_32 bit);
135 limitint & operator <<= (limitint bit);
136 limitint operator ++(
int a)
137 { limitint ret = *
this; ++(*this);
return ret; };
138 limitint operator --(
int a)
139 { limitint ret = *
this; --(*this);
return ret; };
140 limitint & operator ++()
141 {
return *
this += 1; };
142 limitint & operator --()
143 {
return *
this -= 1; };
145 U_32 operator % (U_32 arg)
const;
150 template <
class T>
void unstack(T &v)
151 { limitint_unstack_to(v); }
153 limitint get_storage_size()
const;
156 unsigned char operator [] (
const limitint & position)
const;
159 bool is_zero()
const {
return field == 0; };
161 bool operator < (
const limitint &x)
const {
return field < x.field; };
162 bool operator == (
const limitint &x)
const {
return field == x.field; };
163 bool operator > (
const limitint &x)
const {
return field > x.field; };
164 bool operator <= (
const limitint &x)
const {
return field <= x.field; };
165 bool operator != (
const limitint &x)
const {
return field != x.field; };
166 bool operator >= (
const limitint &x)
const {
return field >= x.field; };
167 static bool is_system_big_endian();
169 B debug_get_max()
const {
return max_value; };
170 B debug_get_bytesize()
const {
return bytesize; };
171 B debug_get_field()
const {
return field; };
178 template <
class T>
void limitint_from(T a);
179 template <
class T> T max_val_of(T x);
180 template <
class T>
void limitint_unstack_to(T &a);
185 static const int TG = 4;
186 static const U_32 sizeof_field =
sizeof(B);
188 enum endian { big_endian, little_endian, not_initialized };
189 using group =
unsigned char[TG];
191 static endian used_endian;
192 static const U_I bytesize =
sizeof(B);
193 static const B max_value = ~B(0) > 0 ? ~B(0) : ~(B(1) << (bytesize*8 - 1));
194 static U_8 zeroed_field[ZEROED_SIZE];
196 static void setup_endian();
199 template <
class B> U_8 limitint<B>::zeroed_field[ZEROED_SIZE];
204 template <
class B> limitint<B> operator - (
const limitint<B> &,
const limitint<B> &);
205 template <
class B>
inline limitint<B> operator - (
const limitint<B> & a, U_I b)
206 {
return a - limitint<B>(b); }
225 template <
class T>
inline void euclide(T a, T b, T & q, T &r)
236#ifndef INFININT_BASE_TYPE
237#error INFININT_BASE_TYPE not defined cannot instantiate template
249 template <
class B>
typename limitint<B>::endian limitint<B>::used_endian = not_initialized;
263 char *ptr = (
char *)&field;
265 int_tools_bitfield bf;
269 lu = x.read((
char *)&a, 1);
272 throw Erange(
"limitint::build_from_file(proto_generic_file)", gettext(
"Reached end of file before all data could be read"));
281 int_tools_expand_byte(a, bf);
282 for(S_I i = 0; i < 8; ++i)
285 throw Erange(
"limitint::build_from_file(proto_generic_file)", gettext(
"Badly formed \"infinint\" or not supported format"));
296 if(skip.field > bytesize)
300 lu = x.read(ptr, skip.field);
302 if(used_endian == not_initialized)
304 if(used_endian == little_endian)
305 int_tools_swap_bytes((
unsigned char *)ptr, skip.field);
307 field >>= (bytesize - skip.field)*8;
318 unsigned char last_width;
321 unsigned char *ptr, *fin;
324 if(used_endian == not_initialized)
327 if(used_endian == little_endian)
330 ptr = (
unsigned char *)(&field) + (bytesize - 1);
331 fin = (
unsigned char *)(&field) - 1;
336 ptr = (
unsigned char *)(&field);
337 fin = (
unsigned char *)(&field) + bytesize;
340 while(ptr != fin && *ptr == 0)
351 euclide(width, (
const B)(TG), width, justification);
352 if(justification != 0)
356 euclide(width, (
const B)(8), width, pos);
360 last_width = 0x80 >> 7;
365 U_16 pos_s = (U_16)(0xFFFF & pos);
366 last_width = 0x80 >> (pos_s - 1);
372 if(width > ZEROED_SIZE)
374 x.write((
char *)zeroed_field, ZEROED_SIZE);
375 width -= ZEROED_SIZE;
379 x.write((
char *)zeroed_field, width);
385 x.write((
char *)&last_width, 1);
389 if(justification != 0)
391 justification = TG - justification;
392 if(justification > ZEROED_SIZE)
395 x.write((
char *)zeroed_field, justification);
400 x.write((
char *)zeroed_field, 1);
404 x.write((
char *)ptr, 1);
411 B res = field + arg.field;
412 if(res < field || res < arg.field)
422 if(field < arg.field)
423 throw Erange(
"limitint::operator", gettext(
"Subtracting an \"infinint\" greater than the first, \"infinint\" cannot be negative"));
434 static const B max_power = bytesize*8 - 1;
436 B total = int_tools_higher_power_of_2(field) + int_tools_higher_power_of_2(arg.field) + 1;
437 if(total > max_power)
444 total = field*arg.field;
445 if(field != 0 && arg.field != 0)
446 if(total < field || total < arg.field)
452 template <
class B>
template<
class T>
limitint<B> limitint<B>::power(
const T & exponent)
const
455 for(T count = 0; count < exponent; ++count)
464 throw Einfinint(
"limitint.cpp : operator /=", gettext(
"Division by zero"));
473 throw Einfinint(
"limitint.cpp : operator %=", gettext(
"Division by zero"));
481 if(bit >= sizeof_field*8)
496 if(bit + int_tools_higher_power_of_2(field) >= bytesize*8)
504 if(bit.field + int_tools_higher_power_of_2(field) >= bytesize*8)
530 return U_32(field % arg);
533 template <
class B>
template <
class T>
void limitint<B>::limitint_from(T a)
535 if(
sizeof(a) <= bytesize || a <= (T)(max_value))
541 template <
class B>
template <
class T> T limitint<B>::max_val_of(T x)
549 x = int_tools_rotate_right_one_bit(x);
556 template <
class B>
template <
class T>
void limitint<B>::limitint_unstack_to(T &a)
562 static const T max_T = max_val_of(a);
565 if(field < (B)(step) && (T)(field) < step)
577 template <
class B>
limitint<B> limitint<B>::get_storage_size()
const
594 B index = position.field;
602 return (
unsigned char)(tmp & 0xFF);
605 template <
class B>
void limitint<B>::setup_endian()
608 used_endian = big_endian;
610 used_endian = little_endian;
612 (void)memset(zeroed_field, 0, ZEROED_SIZE);
616 template <
class B>
bool limitint<B>::is_system_big_endian()
618 if(used_endian == not_initialized)
627 case not_initialized:
exception used when arithmetic error is detected when operating on infinint
exception used when a limitint overflow is detected, the maximum value of the limitint has been excee...
exception used to signal range error
the arbitrary large positive integer class
ancestor class of generic_file
contains all the excetion class thrown by libdar
std::ostream & operator<<(std::ostream &ref, const infinint &arg)
specific << operator to use infinint in std::ostream
are defined here basic integer types that tend to be portable
include macro defined by the configure script and some specific additional ones
libdar namespace encapsulate all libdar symbols
bool integers_system_is_big_endian()
returns true if the system is big endian, false else
precursor class of generic_file used to avoid cyclic dependencies with storage and infinint