00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef _binary_stream_
00023 #define _binary_stream_
00024
00025 #include <istream>
00026 #include <ostream>
00027
00028 #include "endian.hh"
00029
00030 #if defined (DEBUG)
00031
00032
00033
00034 #define DEBUG_BINARY_IO (1 << 13)
00035
00036
00037 #if (DEBUG +0 == DEBUG_BINARY_IO)
00038 #define BINARY_IO_DEBUG
00039 #endif
00040
00041 #include <iostream>
00042 using std::cerr;
00043
00044 #include <iomanip>
00045 using std::endl;
00046
00047 #endif // DEBUG
00048
00049
00050 namespace PIRL
00051 {
00052
00053
00054
00068 template<typename Bindor_object>
00069 class Data_Binder
00070 {
00071 public:
00073 Bindor_object&
00074 Bindor;
00075
00077 mutable char*
00078 Data;
00080 unsigned long
00081 Amount;
00082
00089 Data_Binder
00090 (
00091 const Bindor_object& bindor,
00092 char* data,
00093 unsigned long amount
00094 )
00095 : Bindor (const_cast<Bindor_object&>(bindor)),
00096 Data (data),
00097 Amount (amount)
00098 {}
00099 };
00100
00101
00102
00103
00146 class Binary_IO
00147 {
00148 public:
00149
00150
00151
00152 typedef std::istream& (* Reader) (std::istream&, char*, unsigned long);
00153 typedef std::ostream& (* Writer) (std::ostream&, const char*, unsigned long);
00154
00155 typedef Data_Binder<Binary_IO> Binder;
00156
00157
00158
00159
00161 static const char*
00162 ID;
00163
00165 enum Data_Order
00166 {
00167 MSB,
00168 LSB
00169 };
00170
00172 #define REVERSED true
00173 #define NATIVE false
00174
00175
00176
00177
00183 explicit Binary_IO
00184 (
00185 bool reverse = false
00186 )
00187 {reversed (reverse);}
00188
00194 explicit Binary_IO
00195 (
00196 Data_Order data_order
00197 )
00198 {IO (data_order);}
00199
00200
00201
00202
00207 bool reversed () const
00208 {return Reversed;}
00209
00214 Binary_IO& reversed (bool reverse)
00215 {
00216 if ((Reversed = reverse))
00217 {
00218 read = &read_backwards;
00219 write = &write_backwards;
00220 }
00221 else
00222 {
00223 read = &read_forwards;
00224 write = &write_forwards;
00225 }
00226 return *this;
00227 }
00228
00233 Data_Order IO ()
00234 {
00235 if (Reversed)
00236 return low_endian_host () ? MSB : LSB;
00237 return high_endian_host () ? MSB : LSB;
00238 }
00239
00244 Binary_IO& IO (Data_Order data_order)
00245 {
00246 return reversed ((data_order == MSB) ?
00247 low_endian_host () :
00248 high_endian_host ());
00249 }
00250
00251
00252
00253
00261 template<typename T>
00262 Binder operator() (T& value) const
00263 {return Binder (*this, reinterpret_cast<char*>(&value), sizeof (T));}
00264
00265
00266
00267
00268
00269
00270
00273 template<typename T>
00274 Binary_IO& get (std::istream& stream, T& value)
00275 {
00276 read (stream, reinterpret_cast<char*>(&value), sizeof (T));
00277 return *this;
00278 }
00279
00282 template<typename T>
00283 Binary_IO& put (std::ostream& stream, T& value)
00284 {
00285 write (stream, reinterpret_cast<const char*>(&value), sizeof (T));
00286 return *this;
00287 }
00288
00291 template<typename T>
00292 Binary_IO& get (std::istream& stream, T* value, unsigned int amount)
00293 {
00294 if (sizeof (T) == 1)
00295 read (stream, reinterpret_cast<char*>(value), amount);
00296 else
00297 {
00298
00299 while (amount--)
00300 {
00301 read (stream, reinterpret_cast<char*>(value), sizeof (T));
00302 ++value;
00303 }
00304 }
00305 return *this;
00306 }
00307
00310 template<typename T>
00311 Binary_IO& put (std::ostream& stream, T* value, unsigned int amount)
00312 {
00313 if (sizeof (T) == 1)
00314 write (stream, reinterpret_cast<const char*>(value), sizeof (T));
00315 else
00316 {
00317
00318 while (amount--)
00319 {
00320 write (stream, reinterpret_cast<const char*>(value), sizeof (T));
00321 ++value;
00322 }
00323 }
00324 return *this;
00325 }
00326
00329 Binary_IO& get_3 (std::istream& stream, int& value)
00330 {
00331 static const int
00332 offset = (high_endian_host () ? 1 : 0);
00333 read (stream, reinterpret_cast<char*>(&value) + offset, 3);
00334 return *this;
00335 }
00336
00339 Binary_IO& put_3 (std::ostream& stream, const int& value)
00340 {
00341 static const int
00342 offset = (high_endian_host () ? 1 : 0);
00343 write (stream, reinterpret_cast<const char*>(&value) + offset, 3);
00344 return *this;
00345 }
00346
00347
00348
00349
00359 Reader
00360 read;
00361
00371 Writer
00372 write;
00373
00374
00375
00376
00377 protected:
00387 static std::istream&
00388 read_forwards (std::istream& stream, char* data, unsigned long amount)
00389 {
00390 #ifdef BINARY_IO_DEBUG
00391 cerr << ">-< Binary_IO::read_forwards: "
00392 << " data @ " << (void*)data << ", amount = " << amount << endl;
00393 #endif
00394 return stream.read (data, amount);
00395 }
00396
00406 static std::istream&
00407 read_backwards (std::istream& stream, char* data, unsigned long amount)
00408 {
00409 #ifdef BINARY_IO_DEBUG
00410 cerr << ">-< Binary_IO::read_backwards: "
00411 << " data @ " << (void*)data << ", amount = " << amount << endl;
00412 #endif
00413 data += amount;
00414 while (amount--)
00415 stream.get (*--data);
00416 return stream;
00417 }
00418
00428 static std::ostream&
00429 write_forwards (std::ostream& stream, const char* data, unsigned long amount)
00430 {
00431 #ifdef BINARY_IO_DEBUG
00432 cerr << ">-< Binary_IO::write_forwards: "
00433 << " data @ " << (void*)data << ", amount = " << amount << endl;
00434 #endif
00435 return stream.write (data, amount);
00436 }
00437
00447 static std::ostream&
00448 write_backwards (std::ostream& stream, const char* data, unsigned long amount)
00449 {
00450 #ifdef BINARY_IO_DEBUG
00451 cerr << ">-< Binary_IO::write_backwards: "
00452 << " data @ " << (void*)data << ", amount = " << amount << endl;
00453 #endif
00454 data += amount;
00455 while (amount--)
00456 stream.put (*--data);
00457 return stream;
00458 }
00459
00460
00461 private:
00462
00464 bool
00465 Reversed;
00466
00467 };
00468
00469
00470
00471
00475 struct Binary_Input
00476 : public Binary_IO
00477 {
00478 explicit Binary_Input (std::istream& stream, bool reversed = false)
00479 : Binary_IO (reversed),
00480 Stream (stream)
00481 {}
00482
00483 explicit Binary_Input (std::istream& stream, Data_Order data_order)
00484 : Binary_IO (data_order),
00485 Stream (stream)
00486 {}
00487
00490 template<typename T>
00491 Binary_Input& get (T& value)
00492 {
00493 Binary_IO::read (Stream, reinterpret_cast<char*>(&value), sizeof (T));
00494 return *this;
00495 }
00496
00499 template<typename T>
00500 Binary_Input& get (T* value, unsigned int amount)
00501 {
00502 Binary_IO::get (Stream, value, amount);
00503 return *this;
00504 }
00505
00506 Binary_Input& get_3 (int& value)
00507 {
00508 Binary_IO::get_3 (Stream, value);
00509 return *this;
00510 }
00511
00512 std::istream&
00513 Stream;
00514 };
00515
00519 struct Binary_Output
00520 : public Binary_IO
00521 {
00522 explicit Binary_Output (std::ostream& stream, bool reversed = false)
00523 : Binary_IO (reversed),
00524 Stream (stream)
00525 {}
00526
00527 explicit Binary_Output (std::ostream& stream, Data_Order data_order)
00528 : Binary_IO (data_order),
00529 Stream (stream)
00530 {}
00531
00534 template<typename T>
00535 Binary_Output& put (T& value)
00536 {
00537 Binary_IO::write (Stream, reinterpret_cast<const char*>(&value), sizeof (T));
00538 return *this;
00539 }
00540
00543 template<typename T>
00544 Binary_Output& put (T* value, unsigned int amount)
00545 {
00546 Binary_IO::put (Stream, value, amount);
00547 return *this;
00548 }
00549
00550 Binary_Output& put_3 (const int& value)
00551 {
00552 Binary_IO::put_3 (Stream, value);
00553 return *this;
00554 }
00555
00556 std::ostream&
00557 Stream;
00558 };
00559
00560
00561
00562
00565 inline std::istream&
00566 operator>> (std::istream& stream, const Binary_IO::Binder& binder)
00567 {
00568 #ifdef BINARY_IO_DEBUG
00569 cerr << ">-< operator>> (std::ostream& stream, const Binary_IO::Binder& binder)"
00570 << endl
00571 << " binder.Data @ " << (void*)(binder.Data) << endl
00572 << " binder.Amount = " << binder.Amount << endl;
00573 #endif
00574 return binder.Bindor.read (stream, binder.Data, binder.Amount);
00575 }
00576
00579 inline std::ostream&
00580 operator<< (std::ostream& stream, const Binary_IO::Binder& binder)
00581 {
00582 #ifdef BINARY_IO_DEBUG
00583 cerr << ">-< operator<< (std::ostream& stream, const Binary_IO::Binder& binder)"
00584 << endl
00585 << " binder.Data @ " << (void*)(binder.Data) << endl
00586 << " binder.Amount = " << binder.Amount << endl;
00587 #endif
00588 return binder.Bindor.write (stream, binder.Data, binder.Amount);
00589 }
00590
00591 }
00592 #endif