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