35#include "//include/dar/libdar_my_config.h"
39#if LIBDAR_HAS_SYS_TYPES_H
43#if LIBDAR_HAS_UNISTD_H
47#if LIBDAR_HAS_STRING_H
51#if LIBDAR_HAS_STRINGS_H
57#include "//include/dar/integers.hpp"
58#include "//include/dar/erreurs.hpp"
59#include "//include/dar/int_tools.hpp"
60#include "//include/dar/proto_generic_file.hpp"
87 template<
class B>
class limitint
91#if LIBDAR_SIZEOF_OFF_T > LIBDAR_SIZEOF_TIME_T
92#if LIBDAR_SIZEOF_OFF_T > LIBDAR_SIZEOF_SIZE_T
94 { limitint_from(a); };
96 limitint(
size_t a = 0)
97 { limitint_from(a); };
100#if LIBDAR_SIZEOF_TIME_T > LIBDAR_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
std::ostream & operator<<(std::ostream &ref, const infinint &arg)
specific << operator to use infinint in std::ostream
libdar namespace encapsulate all libdar symbols
bool integers_system_is_big_endian()
returns true if the system is big endian, false else