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