35 #include "../my_config.h"
40 #include <sys/types.h>
63 #define ZEROED_SIZE 50
91 #if SIZEOF_OFF_T > SIZEOF_TIME_T
92 #if SIZEOF_OFF_T > SIZEOF_SIZE_T
94 { limitint_from(a); };
97 { limitint_from(a); };
100 #if SIZEOF_TIME_T > SIZEOF_SIZE_T
102 { limitint_from(a); };
105 { limitint_from(a); };
126 template <
class T>
limitint power(
const T & exponent)
const;
137 {
limitint ret = *
this; ++(*this);
return ret; };
139 {
limitint ret = *
this; --(*this);
return ret; };
141 {
return *
this += 1; };
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); }
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();
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); }
207 template <
class B> limitint<B> operator * (
const limitint<B> &,
const limitint<B> &);
208 template <
class B>
inline limitint<B> operator * (
const limitint<B> & a, U_I b)
209 {
return a * limitint<B>(b); }
210 template <
class B> limitint<B> operator / (
const limitint<B> &,
const limitint<B> &);
211 template <
class B> limitint<B> operator / (
const limitint<B> & a, U_I b)
212 {
return a / limitint<B>(b); }
213 template <
class B> limitint<B> operator % (
const limitint<B> &,
const limitint<B> &);
214 template <
class B> limitint<B> operator >> (
const limitint<B> & a, U_32 bit);
215 template <
class B> limitint<B> operator >> (
const limitint<B> & a,
const limitint<B> & bit);
216 template <
class B> limitint<B>
operator << (
const limitint<B> & a, U_32 bit);
217 template <
class B> limitint<B>
operator << (
const limitint<B> & a,
const limitint<B> & bit);
218 template <
class B> limitint<B> operator & (
const limitint<B> & a, U_32 bit);
219 template <
class B> limitint<B> operator & (
const limitint<B> & a,
const limitint<B> & bit);
220 template <
class B> limitint<B> operator | (
const limitint<B> & a, U_32 bit);
221 template <
class B> limitint<B> operator | (
const limitint<B> & a,
const limitint<B> & bit);
222 template <
class B> limitint<B> operator ^ (
const limitint<B> & a, U_32 bit);
223 template <
class B> limitint<B> operator ^ (
const limitint<B> & a,
const limitint<B> & bit);
225 template <
class T>
inline void euclide(T a, T b, T & q, T &r)
231 template <
class B>
inline void euclide(limitint<B> a, U_I b, limitint<B> & q, limitint<B> &r)
233 euclide(a, limitint<B>(b), q, r);
236 #ifndef INFININT_BASE_TYPE
237 #error INFININT_BASE_TYPE not defined cannot instantiate template
239 using infinint = limitint<INFININT_BASE_TYPE>;
249 template <
class B>
typename limitint<B>::endian limitint<B>::used_endian = not_initialized;
252 template <
class B> limitint<B>::limitint(proto_generic_file & x)
258 template <
class B>
void limitint<B>::build_from_file(proto_generic_file & x)
262 limitint<B> skip = 0;
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;
314 template <
class B>
void limitint<B>::dump(proto_generic_file & x)
const
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);
409 template<
class B> limitint<B> & limitint<B>::operator += (
const limitint & arg)
411 B res = field + arg.field;
412 if(res < field || res < arg.field)
420 template <
class B> limitint<B> & limitint<B>::operator -= (
const limitint & arg)
422 if(field < arg.field)
423 throw Erange(
"limitint::operator", gettext(
"Subtracting an \"infinint\" greater than the first, \"infinint\" cannot be negative"));
432 template <
class B> limitint<B> & limitint<B>::operator *= (
const limitint & arg)
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)
461 template <
class B> limitint<B> & limitint<B>::operator /= (
const limitint & arg)
464 throw Einfinint(
"limitint.cpp : operator /=", gettext(
"Division by zero"));
470 template <
class B> limitint<B> & limitint<B>::operator %= (
const limitint & arg)
473 throw Einfinint(
"limitint.cpp : operator %=", gettext(
"Division by zero"));
479 template <
class B> limitint<B> & limitint<B>::operator >>= (U_32 bit)
481 if(bit >= sizeof_field*8)
488 template <
class B> limitint<B> & limitint<B>::operator >>= (limitint bit)
494 template <
class B> limitint<B> & limitint<B>::operator <<= (U_32 bit)
496 if(bit + int_tools_higher_power_of_2(field) >= bytesize*8)
502 template <
class B> limitint<B> & limitint<B>::operator <<= (limitint bit)
504 if(bit.field + int_tools_higher_power_of_2(field) >= bytesize*8)
510 template <
class B> limitint<B> & limitint<B>::operator &= (
const limitint & arg)
516 template <
class B> limitint<B> & limitint<B>::operator |= (
const limitint & arg)
522 template <
class B> limitint<B> & limitint<B>::operator ^= (
const limitint & arg)
528 template <
class B> U_32 limitint<B>::operator % (U_32 arg)
const
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
588 return limitint<B>(ret);
591 template <
class B>
unsigned char limitint<B>::operator [] (
const limitint & position)
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:
639 template <
class B> limitint<B> operator + (
const limitint<B> & a,
const limitint<B> & b)
647 template <
class B> limitint<B> operator - (
const limitint<B> & a,
const limitint<B> & b)
655 template <
class B> limitint<B> operator * (
const limitint<B> & a,
const limitint<B> & b)
663 template <
class B> limitint<B> operator / (
const limitint<B> & a,
const limitint<B> & b)
671 template <
class B> limitint<B> operator % (
const limitint<B> & a,
const limitint<B> & b)
679 template <
class B> limitint<B> operator >> (
const limitint<B> & a, U_32 bit)
686 template <
class B> limitint<B> operator >> (
const limitint<B> & a,
const limitint<B> & bit)
693 template <
class B> limitint<B>
operator << (
const limitint<B> & a, U_32 bit)
700 template <
class B> limitint<B>
operator << (
const limitint<B> & a,
const limitint<B> & bit)
707 template <
class B> limitint<B> operator & (
const limitint<B> & a, U_32 bit)
714 template <
class B> limitint<B> operator & (
const limitint<B> & a,
const limitint<B> & bit)
721 template <
class B> limitint<B> operator | (
const limitint<B> & a, U_32 bit)
728 template <
class B> limitint<B> operator | (
const limitint<B> & a,
const limitint<B> & bit)
735 template <
class B> limitint<B> operator ^ (
const limitint<B> & a, U_32 bit)
742 template <
class B> limitint<B> operator ^ (
const limitint<B> & a,
const limitint<B> & bit)
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
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