Disk ARchive 2.3.10
|
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.4 2009/04/07 08:45:29 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 #ifdef LIBDAR_SPECIAL_ALLOC 00147 USE_SPECIAL_ALLOC(limitint); 00148 #endif 00149 00150 B debug_get_max() const { return max_value; }; 00151 B debug_get_bytesize() const { return bytesize; }; 00152 00153 private : 00154 static const int TG = 4; 00155 static const U_32 sizeof_field = sizeof(B); 00156 00157 enum endian { big_endian, little_endian, not_initialized }; 00158 typedef unsigned char group[TG]; 00159 00160 B field; 00161 00162 void build_from_file(generic_file & x); 00163 template <class T> void limitint_from(T a); 00164 template <class T> void limitint_unstack_to(T &a); 00165 00167 // static statments 00168 // 00169 static endian used_endian; 00170 static const U_I bytesize = sizeof(B); 00171 static const B max_value = ~B(0) > 0 ? ~B(0) : ~(B(1) << (bytesize*8 - 1)); 00172 static void setup_endian(); 00173 }; 00174 00175 template <class B> limitint<B> operator + (const limitint<B> &, const limitint<B> &); 00176 template <class B> inline limitint<B> operator + (const limitint<B> & a, U_I b) 00177 { return a + limitint<B>(b); } 00178 template <class B> limitint<B> operator - (const limitint<B> &, const limitint<B> &); 00179 template <class B> inline limitint<B> operator - (const limitint<B> & a, U_I b) 00180 { return a - limitint<B>(b); } 00181 template <class B> limitint<B> operator * (const limitint<B> &, const limitint<B> &); 00182 template <class B> inline limitint<B> operator * (const limitint<B> & a, U_I b) 00183 { return a * limitint<B>(b); } 00184 template <class B> limitint<B> operator / (const limitint<B> &, const limitint<B> &); 00185 template <class B> limitint<B> operator / (const limitint<B> & a, U_I b) 00186 { return a / limitint<B>(b); } 00187 template <class B> limitint<B> operator % (const limitint<B> &, const limitint<B> &); 00188 template <class B> limitint<B> operator >> (const limitint<B> & a, U_32 bit); 00189 template <class B> limitint<B> operator >> (const limitint<B> & a, const limitint<B> & bit); 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 00199 template <class T> inline void euclide(T a, T b, T & q, T &r) 00200 { 00201 E_BEGIN; 00202 q = a/b; r = a%b; 00203 E_END("euclide", ""); 00204 } 00205 00206 template <class B> inline void euclide(limitint<B> a, U_I b, limitint<B> & q, limitint<B> &r) 00207 { 00208 euclide(a, limitint<B>(b), q, r); 00209 } 00210 00211 #ifndef INFININT_BASE_TYPE 00212 #error INFININT_BASE_TYPE not defined cannot instantiate template 00213 #else 00214 typedef limitint<INFININT_BASE_TYPE> infinint; 00215 #endif 00216 } // end of namespace 00220 00221 #include "generic_file.hpp" 00222 #include "user_interaction.hpp" 00223 00224 namespace libdar 00225 { 00226 00227 template <class B> typename limitint<B>::endian limitint<B>::used_endian = not_initialized; 00228 00229 template <class B> limitint<B>::limitint(user_interaction & dialog, S_I *fd, generic_file *x) 00230 { 00231 if(fd != NULL && x != NULL) 00232 throw Erange("limitint::limitint(file, file)", "Both arguments are not NULL, please choose one or the other, not both"); // message not translated, expected 00233 if(fd != NULL) 00234 { 00235 fichier f = fichier(dialog, dup(*fd)); 00236 build_from_file(f); 00237 } 00238 else 00239 if(x != NULL) 00240 build_from_file(*x); 00241 else 00242 throw Erange("limitint::limitint(file, file)", "Cannot read from file, both arguments are NULL"); // message not translated, expected 00243 } 00244 00245 template <class B> void limitint<B>::dump(user_interaction & dialog, S_I fd) const 00246 { 00247 fichier f = fichier(dialog, dup(fd)); 00248 dump(f); 00249 } 00250 00251 template <class B> void limitint<B>::build_from_file(generic_file & x) 00252 { 00253 E_BEGIN; 00254 unsigned char a; 00255 bool fin = false; 00256 limitint<B> skip = 0; 00257 char *ptr = (char *)&field; 00258 S_I lu; 00259 int_tools_bitfield bf; 00260 00261 while(!fin) 00262 { 00263 lu = x.read((char *)&a, 1); 00264 00265 if(lu <= 0) 00266 throw Erange("limitint::build_from_file(generic_file)", gettext("Reached end of file before all data could be read")); 00267 00268 if(a == 0) 00269 ++skip; 00270 else // end of size field 00271 { 00272 // computing the size to read 00273 U_I pos = 0; 00274 00275 int_tools_expand_byte(a, bf); 00276 for(S_I i = 0; i < 8; ++i) 00277 pos += bf[i]; 00278 if(pos != 1) 00279 throw Erange("limitint::build_from_file(generic_file)", gettext("Badly formed infinint or not supported format")); // more than 1 bit is set to 1 00280 00281 pos = 0; 00282 while(bf[pos] == 0) 00283 ++pos; 00284 pos += 1; // bf starts at zero, but bit zero means 1 TG of length 00285 00286 skip *= 8; 00287 skip += pos; 00288 skip *= TG; 00289 00290 if(skip.field > bytesize) 00291 throw Elimitint(); 00292 00293 field = 0; // important to also clear "unread" bytes by the following call 00294 lu = x.read(ptr, skip.field); 00295 00296 if(used_endian == not_initialized) 00297 setup_endian(); 00298 if(used_endian == big_endian) 00299 int_tools_swap_bytes((unsigned char *)ptr, skip.field); 00300 else 00301 field >>= (bytesize - skip.field)*8; 00302 fin = true; 00303 } 00304 } 00305 E_END("limitint::read_from_file", "generic_file"); 00306 } 00307 00308 00309 template <class B> void limitint<B>::dump(generic_file & x) const 00310 { 00311 E_BEGIN; 00312 B width = bytesize; 00313 B pos; 00314 unsigned char last_width; 00315 B justification; 00316 S_I direction = +1; 00317 unsigned char *ptr, *fin; 00318 00319 00320 if(used_endian == not_initialized) 00321 setup_endian(); 00322 00323 if(used_endian == big_endian) 00324 { 00325 direction = -1; 00326 ptr = (unsigned char *)(&field) + (bytesize - 1); 00327 fin = (unsigned char *)(&field) - 1; 00328 } 00329 else 00330 { 00331 direction = +1; 00332 ptr = (unsigned char *)(&field); 00333 fin = (unsigned char *)(&field) + bytesize; 00334 } 00335 00336 while(ptr != fin && *ptr == 0) 00337 { 00338 ptr += direction; 00339 --width; 00340 } 00341 if(width == 0) 00342 width = 1; // minimum size of information is 1 byte 00343 00344 // "width" is the informational field size in byte 00345 // TG is the width in TG, thus the number of bit that must have 00346 // the preamble 00347 euclide(width, (const B)(TG), width, justification); 00348 if(justification != 0) 00349 // in case we need to add some bytes to have a width multiple of TG 00350 ++width; // we need then one more group to have a width multiple of TG 00351 00352 euclide(width, (const B)(8), width, pos); 00353 if(pos == 0) 00354 { 00355 width--; // division is exact, only last bit of the preambule is set 00356 last_width = 0x80 >> 7; 00357 // as we add the last byte separately width gets shorter by 1 byte 00358 } 00359 else // division non exact, the last_width (last byte), make the rounding 00360 { 00361 U_16 pos_s = (U_16)(0xFFFF & pos); 00362 last_width = 0x80 >> (pos_s - 1); 00363 } 00364 00365 // now we write the preamble except the last byte. All these are zeros. 00366 00367 unsigned char u = 0x00; 00368 00369 while(width-- > 0) 00370 if(x.write((char *)(&u), 1) < 1) 00371 throw Erange("limitint::dump(generic_file)", gettext("Cannot write data to file")); 00372 00373 00374 // now we write the last byte of the preambule, which as only one bit set 00375 00376 if(x.write((char *)&last_width, 1) < 1) 00377 throw Erange("limitint::dump(generic_file)", gettext("Cannot write data to file")); 00378 00379 // we need now to write some justification byte to have an informational field multiple of TG 00380 00381 if(justification != 0) 00382 { 00383 justification = TG - justification; 00384 while(justification-- > 0) 00385 if(x.write((char *)(&u), 1) < 1) 00386 throw Erange("limitint::dump(generic_file)", gettext("Cannot write data to file")); 00387 } 00388 00389 // now we continue dumping the informational bytes: 00390 if(ptr == fin) // field is equal to zero 00391 { 00392 if(x.write((char *)(&u), 1) < 1) 00393 throw Erange("limitint::dump(generic_file)", gettext("Cannot write data to file")); 00394 } 00395 else // we have some bytes to write down 00396 while(ptr != fin) 00397 { 00398 if(x.write((char *)ptr, 1) < 1) 00399 throw Erange("limitint::dump(generic_file)", gettext("Cannot write data to file")); 00400 else 00401 ptr += direction; 00402 } 00403 00404 E_END("limitint::dump", "generic_file"); 00405 } 00406 00407 template<class B> limitint<B> & limitint<B>::operator += (const limitint & arg) 00408 { 00409 E_BEGIN; 00410 B res = field + arg.field; 00411 if(res < field || res < arg.field) 00412 throw Elimitint(); 00413 else 00414 field = res; 00415 00416 return *this; 00417 E_END("limitint::operator +=", ""); 00418 } 00419 00420 template <class B> limitint<B> & limitint<B>::operator -= (const limitint & arg) 00421 { 00422 E_BEGIN; 00423 if(field < arg.field) 00424 throw Erange("limitint::operator", gettext("Subtracting a infinint greater than the first, infinint cannot be negative")); 00425 00426 // now processing the operation 00427 00428 field -= arg.field; 00429 return *this; 00430 E_END("limitint::operator -=", ""); 00431 } 00432 00433 00434 template <class B> limitint<B> & limitint<B>::operator *= (const limitint & arg) 00435 { 00436 E_BEGIN; 00437 static const B max_power = bytesize*8 - 1; 00438 00439 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 00440 if(total > max_power) // this is a bit too much restrictive, but unless remaking bit by bit, the operation, 00441 // I don't see how to simply (and fast) know the result has not overflowed. 00442 // of course, it would be fast and easy to access the CPU flag register to check for overflow, 00443 // but that would not be portable, and unfortunately I haven't found any standart C++ expression that 00444 // could transparently access to it. 00445 throw Elimitint(); 00446 00447 total = field*arg.field; 00448 if(field != 0 && arg.field != 0) 00449 if(total < field || total < arg.field) 00450 throw Elimitint(); 00451 field = total; 00452 return *this; 00453 E_END("limitint::operator *=", ""); 00454 } 00455 00456 template <class B> template<class T> limitint<B> limitint<B>::power(const T & exponent) const 00457 { 00458 limitint ret = 1; 00459 for(T count = 0; count < exponent; ++count) 00460 ret *= *this; 00461 00462 return ret; 00463 } 00464 00465 template <class B> limitint<B> & limitint<B>::operator /= (const limitint & arg) 00466 { 00467 E_BEGIN; 00468 if(arg == 0) 00469 throw Einfinint("limitint.cpp : operator /=", gettext("Division by zero")); 00470 00471 field /= arg.field; 00472 return *this; 00473 E_END("limitint::operator /=", ""); 00474 } 00475 00476 template <class B> limitint<B> & limitint<B>::operator %= (const limitint & arg) 00477 { 00478 E_BEGIN; 00479 if(arg == 0) 00480 throw Einfinint("limitint.cpp : operator %=", gettext("Division by zero")); 00481 00482 field %= arg.field; 00483 return *this; 00484 E_END("limitint::operator /=", ""); 00485 } 00486 00487 template <class B> limitint<B> & limitint<B>::operator >>= (U_32 bit) 00488 { 00489 E_BEGIN; 00490 if(bit >= sizeof_field) 00491 field = 0; 00492 else 00493 field >>= bit; 00494 return *this; 00495 E_END("limitint::operator >>=", "U_32"); 00496 } 00497 00498 template <class B> limitint<B> & limitint<B>::operator >>= (limitint bit) 00499 { 00500 E_BEGIN; 00501 field >>= bit.field; 00502 return *this; 00503 E_END("limitint::operator >>=", "limitint"); 00504 } 00505 00506 template <class B> limitint<B> & limitint<B>::operator <<= (U_32 bit) 00507 { 00508 E_BEGIN; 00509 if(bit + int_tools_higher_power_of_2(field) >= bytesize*8) 00510 throw Elimitint(); 00511 field <<= bit; 00512 return *this; 00513 E_END("limitint::operator <<=", "U_32"); 00514 } 00515 00516 template <class B> limitint<B> & limitint<B>::operator <<= (limitint bit) 00517 { 00518 E_BEGIN; 00519 if(bit.field + int_tools_higher_power_of_2(field) >= bytesize*8) 00520 throw Elimitint(); 00521 field <<= bit.field; 00522 return *this; 00523 E_END("limitint::operator <<=", "limitint"); 00524 } 00525 00526 template <class B> limitint<B> & limitint<B>::operator &= (const limitint & arg) 00527 { 00528 E_BEGIN; 00529 field &= arg.field; 00530 return *this; 00531 E_END("limitint::operator &=", ""); 00532 } 00533 00534 template <class B> limitint<B> & limitint<B>::operator |= (const limitint & arg) 00535 { 00536 E_BEGIN; 00537 field |= arg.field; 00538 return *this; 00539 E_END("limitint::operator |=", ""); 00540 } 00541 00542 template <class B> limitint<B> & limitint<B>::operator ^= (const limitint & arg) 00543 { 00544 E_BEGIN; 00545 field ^= arg.field; 00546 return *this; 00547 E_END("limitint::operator ^=", ""); 00548 } 00549 00550 template <class B> U_32 limitint<B>::operator % (U_32 arg) const 00551 { 00552 E_BEGIN; 00553 return U_32(field % arg); 00554 E_END("limitint::modulo", ""); 00555 } 00556 00557 template <class B> template <class T> void limitint<B>::limitint_from(T a) 00558 { 00559 E_BEGIN; 00560 if(sizeof(a) <= bytesize || a <= (T)(max_value)) 00561 field = B(a); 00562 else 00563 throw Elimitint(); 00564 E_END("limitint::limitint_from", ""); 00565 } 00566 00567 template <class B> template <class T> void limitint<B>::limitint_unstack_to(T &a) 00568 { 00569 E_BEGIN; 00570 // T is supposed to be an unsigned "integer" 00571 // (ie.: sizeof returns the width of the storage bit field and no sign bit is present) 00572 // Note : static here avoids the recalculation of max_T at each call 00573 static const T max_T = ~T(0) > 0 ? ~T(0) : ~int_tools_rotate_right_one_bit(T(1)); 00574 T step = max_T - a; 00575 00576 if(field < (B)(step) && (T)(field) < step) 00577 { 00578 a += field; 00579 field = 0; 00580 } 00581 else 00582 { 00583 field -= step; 00584 a = max_T; 00585 } 00586 00587 E_END("limitint::limitint_unstack_to", ""); 00588 } 00589 00590 template <class B> limitint<B> limitint<B>::get_storage_size() const 00591 { 00592 B tmp = field; 00593 B ret = 0; 00594 00595 while(tmp != 0) 00596 { 00597 tmp >>= 8; 00598 ret++; 00599 } 00600 00601 return limitint<B>(ret); 00602 } 00603 00604 template <class B> unsigned char limitint<B>::operator [] (const limitint & position) const 00605 { 00606 B tmp = field; 00607 B index = position.field; // C++ has only class protection, not object protection 00608 00609 while(index > 0) 00610 { 00611 tmp >>= 8; 00612 index--; 00613 } 00614 00615 return (unsigned char)(tmp & 0xFF); 00616 } 00617 00618 template <class B> void limitint<B>::setup_endian() 00619 { 00620 E_BEGIN; 00621 U_16 u = 1; 00622 unsigned char *ptr = (unsigned char *)(&u); 00623 00624 if(ptr[0] == 1) 00625 used_endian = big_endian; 00626 else 00627 used_endian = little_endian; 00628 E_END("limitint::setup_endian", ""); 00629 } 00630 00631 00632 00633 00637 00638 template <class B> limitint<B> operator + (const limitint<B> & a, const limitint<B> & b) 00639 { 00640 E_BEGIN; 00641 limitint<B> ret = a; 00642 ret += b; 00643 00644 return ret; 00645 E_END("operator +", "limitint"); 00646 } 00647 00648 template <class B> limitint<B> operator - (const limitint<B> & a, const limitint<B> & b) 00649 { 00650 E_BEGIN; 00651 limitint<B> ret = a; 00652 ret -= b; 00653 00654 return ret; 00655 E_END("operator -", "limitint"); 00656 } 00657 00658 template <class B> limitint<B> operator * (const limitint<B> & a, const limitint<B> & b) 00659 { 00660 E_BEGIN; 00661 limitint<B> ret = a; 00662 ret *= b; 00663 00664 return ret; 00665 E_END("operator *", "limitint"); 00666 } 00667 00668 template <class B> limitint<B> operator / (const limitint<B> & a, const limitint<B> & b) 00669 { 00670 E_BEGIN; 00671 limitint<B> ret = a; 00672 ret /= b; 00673 00674 return ret; 00675 E_END("operator / ", "limitint"); 00676 } 00677 00678 template <class B> limitint<B> operator % (const limitint<B> & a, const limitint<B> & b) 00679 { 00680 E_BEGIN; 00681 limitint<B> ret = a; 00682 ret %= b; 00683 00684 return ret; 00685 E_END("operator %", "limitint"); 00686 } 00687 00688 template <class B> limitint<B> operator >> (const limitint<B> & a, U_32 bit) 00689 { 00690 E_BEGIN; 00691 limitint<B> ret = a; 00692 ret >>= bit; 00693 return ret; 00694 E_END("operator >>", "limitint, U_32"); 00695 } 00696 00697 template <class B> limitint<B> operator >> (const limitint<B> & a, const limitint<B> & bit) 00698 { 00699 E_BEGIN; 00700 limitint<B> ret = a; 00701 ret >>= bit; 00702 return ret; 00703 E_END("operator >>", "limitint"); 00704 } 00705 00706 template <class B> limitint<B> operator << (const limitint<B> & a, U_32 bit) 00707 { 00708 E_BEGIN; 00709 limitint<B> ret = a; 00710 ret <<= bit; 00711 return ret; 00712 E_END("operator <<", "limitint, U_32"); 00713 } 00714 00715 template <class B> limitint<B> operator << (const limitint<B> & a, const limitint<B> & bit) 00716 { 00717 E_BEGIN; 00718 limitint<B> ret = a; 00719 ret <<= bit; 00720 return ret; 00721 E_END("operator <<", "limitint"); 00722 } 00723 00724 template <class B> limitint<B> operator & (const limitint<B> & a, U_32 bit) 00725 { 00726 E_BEGIN; 00727 limitint<B> ret = a; 00728 ret &= bit; 00729 return ret; 00730 E_END("operator &", "limitint"); 00731 } 00732 00733 template <class B> limitint<B> operator & (const limitint<B> & a, const limitint<B> & bit) 00734 { 00735 E_BEGIN; 00736 limitint<B> ret = a; 00737 ret &= bit; 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 |", "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 ^", "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 00779 } // end of namespace 00780 00781 #endif