Disk ARchive 2.4.2
|
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