blob: ff1110af79cf283a801e9843ec97ccdf48232b86 [file] [log] [blame]
//#####################################################################
// Copyright 2004, Eran Guendelman, Igor Neverov, Andrew Selle, Eftychios Sifakis.
// This file is part of PhysBAM whose distribution is governed by the license contained in the accompanying file PHYSBAM_COPYRIGHT.txt.
//#####################################################################
// Class READ_WRITE_FUNCTIONS
//#####################################################################
//
// Functions for reading and writing which do the correct thing for objects, pointers, primitive types, etc. In general, use Read/Write_Binary (and Read/Write_Binary_Array) using T for the type
// of the object you're reading/writing and RW the underlying floating point scalar type (float/double).
//
//#####################################################################
#ifndef __READ_WRITE_FUNCTIONS__
#define __READ_WRITE_FUNCTIONS__
#include <iostream>
#include <assert.h>
namespace PhysBAM
{
//#####################################################################
// Function isLittleEndian
//#####################################################################
static inline int isLittleEndian()
{
union
{
unsigned short int word;
unsigned char byte;
} endian_test;
endian_test.word = 0x00FF;
return (endian_test.byte == 0xFF);
}
//#####################################################################
// Function Swap_Endianity
//#####################################################################
template<class T>
inline void Swap_Endianity (T& x)
{
assert (sizeof (T) <= 8);
if (sizeof (T) > 1)
{
T old = x;
for (unsigned int k = 1; k <= sizeof (T); k++) ( (char*) &x) [k - 1] = ( (char*) &old) [sizeof (T) - k];
}
}
//#####################################################################
// Read/Write_Primitive (handles endianness)
//#####################################################################
#ifdef __sparc__
void sparc_seg_fault_prevent_dummy (void *ptr);
#endif
template<class T>
inline void Read_Primitive (std::istream& input_stream, T& d)
{
input_stream.read ( (char*) &d, sizeof (T));
if (!isLittleEndian()) Swap_Endianity (d);
#ifdef __sparc__
/* For unknown reasons I am getting a segfault on my sparc box compiling
with -O3, unless I place a dummy use of the value just read here.
Might just be an issue with a particular gcc version. Unfortunately,
this function call does affect the region of interest. */
sparc_seg_fault_prevent_dummy ( (void *) &d);
#endif
}
template<class T>
inline void Write_Primitive (std::ostream& output_stream, const T& d)
{
T d2 = d;
if (!isLittleEndian()) Swap_Endianity (d2);
output_stream.write ( (const char*) &d2, sizeof (T));
}
#ifdef __APPLE__ // PhysBAM data formats assume sizeof(bool)==1 but the Mac apparently has bool==int with sizeof(bool)==4, so need to specialize these
template<>
inline void Read_Primitive<bool> (std::istream& input_stream, bool& d)
{
char c;
input_stream.read (&c, 1);
d = (bool) c;
}
template<>
inline void Write_Primitive<bool> (std::ostream& output_stream, const bool& d)
{
char c = (char) d;
output_stream.write (&c, 1);
}
#endif
//#####################################################################
// Read/Write_Float_Or_Double
//#####################################################################
template<class T, class RW>
inline void Read_Float_Or_Double (std::istream& input_stream, T& d)
{
std::cerr << "Read_Float_Or_Double called with bad types" << std::endl;
exit (1);
}
template<class T, class RW>
inline void Write_Float_Or_Double (std::ostream& output_stream, T d)
{
std::cerr << "Write_Float_Or_Double called with bad types" << std::endl;
exit (1);
}
template<> inline void Read_Float_Or_Double<float, float> (std::istream& input_stream, float& d)
{
Read_Primitive (input_stream, d); // no conversion
}
template<> inline void Read_Float_Or_Double<double, double> (std::istream& input_stream, double& d)
{
Read_Primitive (input_stream, d); // no conversion
}
template<> inline void Read_Float_Or_Double<float, double> (std::istream& input_stream, float& d)
{
double tmp; // convert types
Read_Primitive (input_stream, tmp);
d = (float) tmp;
}
template<> inline void Read_Float_Or_Double<double, float> (std::istream& input_stream, double& d)
{
float tmp; // convert types
Read_Primitive (input_stream, tmp);
d = (double) tmp;
}
template<> inline void Write_Float_Or_Double<float, float> (std::ostream& output_stream, float d)
{
Write_Primitive (output_stream, d); // no conversion
}
template<> inline void Write_Float_Or_Double<double, double> (std::ostream& output_stream, double d)
{
Write_Primitive (output_stream, d); // no conversion
}
template<> inline void Write_Float_Or_Double<float, double> (std::ostream& output_stream, float d)
{
Write_Primitive (output_stream, (double) d); // convert types
}
template<> inline void Write_Float_Or_Double<double, float> (std::ostream& output_stream, double d)
{
Write_Primitive (output_stream, (float) d); // convert types
}
//#####################################################################
// Read_Write for objects
//#####################################################################
template<class T>
struct Read_Write
{
template<class RW>
static void Read (std::istream& input_stream, T& d)
{
d.template Read<RW> (input_stream);
}
template<class RW>
static void Write (std::ostream& output_stream, const T& d)
{
d.template Write<RW> (output_stream);
}
};
//#####################################################################
// Read_Write for primitive types (other than float and double)
//#####################################################################
#define DEFINE_READ_WRITE_FOR_PRIMITIVE_TYPE(TYPE) \
template<> struct Read_Write<TYPE> { \
template<class RW> static void Read(std::istream& input_stream,TYPE& d){Read_Primitive(input_stream,d);} \
template<class RW> static void Write(std::ostream& output_stream,const TYPE& d) {Write_Primitive(output_stream,d);} \
};
DEFINE_READ_WRITE_FOR_PRIMITIVE_TYPE (bool);
DEFINE_READ_WRITE_FOR_PRIMITIVE_TYPE (char);
DEFINE_READ_WRITE_FOR_PRIMITIVE_TYPE (unsigned char);
DEFINE_READ_WRITE_FOR_PRIMITIVE_TYPE (short);
DEFINE_READ_WRITE_FOR_PRIMITIVE_TYPE (unsigned short);
DEFINE_READ_WRITE_FOR_PRIMITIVE_TYPE (int);
DEFINE_READ_WRITE_FOR_PRIMITIVE_TYPE (unsigned int);
//#####################################################################
// Specializations for float and double
//#####################################################################
template<> struct Read_Write<float>
{
template<class RW>
static void Read (std::istream& input_stream, float& d)
{
Read_Float_Or_Double<float, RW> (input_stream, d);
}
template<class RW>
static void Write (std::ostream& output_stream, const float& d)
{
Write_Float_Or_Double<float, RW> (output_stream, d);
}
};
template<> struct Read_Write<double>
{
template<class RW>
static void Read (std::istream& input_stream, double& d)
{
Read_Float_Or_Double<double, RW> (input_stream, d);
}
template<class RW>
static void Write (std::ostream& output_stream, const double& d)
{
Write_Float_Or_Double<double, RW> (output_stream, d);
}
};
//#####################################################################
// Read_Write for pointers to data
//#####################################################################
template<class T>
struct Read_Write<T*>
{
template<class RW>
static void Read (std::istream& input_stream, T*& d)
{
bool data_exists;
Read_Write<bool>::template Read<RW> (input_stream, data_exists);
if (data_exists)
{
d = new T(); // potential memory leak if d pointed elsewhere
Read_Write<T>::template Read<RW> (input_stream, *d);
}
else d = 0;
}
template<class RW>
static void Write (std::ostream& output_stream, T* const& d)
{
Read_Write<bool>::template Write<RW> (output_stream, d != 0); // Write a bool tag indicating whether pointer's data follows
if (d) Read_Write<T>::template Write<RW> (output_stream, *d);
}
};
//#####################################################################
// Read_Write for std::string's
//#####################################################################
template<>
struct Read_Write<std::string>
{
template<class RW>
static void Read (std::istream& input_stream, std::string& d)
{
int n;
Read_Write<int>::template Read<RW> (input_stream, n);
char* buffer = new char[n];
input_stream.read (buffer, n);
d.assign (buffer, buffer + n);
delete buffer;
}
template<class RW>
static void Write (std::ostream& output_stream, const std::string& d)
{
int n = int (d.size());
Read_Write<int>::template Write<RW> (output_stream, n);
const char* s = d.c_str();
output_stream.write (s, n);
}
};
//#####################################################################
// Read_Binary
//#####################################################################
template<class RW, class T1>
inline void Read_Binary (std::istream& input_stream, T1& d1)
{
Read_Write<T1>::template Read<RW> (input_stream, d1);
}
template<class RW, class T1, class T2>
inline void Read_Binary (std::istream& input_stream, T1& d1, T2& d2)
{
Read_Write<T1>::template Read<RW> (input_stream, d1);
Read_Write<T2>::template Read<RW> (input_stream, d2);
}
template<class RW, class T1, class T2, class T3>
inline void Read_Binary (std::istream& input_stream, T1& d1, T2& d2, T3& d3)
{
Read_Write<T1>::template Read<RW> (input_stream, d1);
Read_Write<T2>::template Read<RW> (input_stream, d2);
Read_Write<T3>::template Read<RW> (input_stream, d3);
}
template<class RW, class T1, class T2, class T3, class T4>
inline void Read_Binary (std::istream& input_stream, T1& d1, T2& d2, T3& d3, T4& d4)
{
Read_Write<T1>::template Read<RW> (input_stream, d1);
Read_Write<T2>::template Read<RW> (input_stream, d2);
Read_Write<T3>::template Read<RW> (input_stream, d3);
Read_Write<T4>::template Read<RW> (input_stream, d4);
}
template<class RW, class T1, class T2, class T3, class T4, class T5>
inline void Read_Binary (std::istream& input_stream, T1& d1, T2& d2, T3& d3, T4& d4, T5& d5)
{
Read_Write<T1>::template Read<RW> (input_stream, d1);
Read_Write<T2>::template Read<RW> (input_stream, d2);
Read_Write<T3>::template Read<RW> (input_stream, d3);
Read_Write<T4>::template Read<RW> (input_stream, d4);
Read_Write<T5>::template Read<RW> (input_stream, d5);
}
template<class RW, class T1, class T2, class T3, class T4, class T5, class T6>
inline void Read_Binary (std::istream& input_stream, T1& d1, T2& d2, T3& d3, T4& d4, T5& d5, T6& d6)
{
Read_Write<T1>::template Read<RW> (input_stream, d1);
Read_Write<T2>::template Read<RW> (input_stream, d2);
Read_Write<T3>::template Read<RW> (input_stream, d3);
Read_Write<T4>::template Read<RW> (input_stream, d4);
Read_Write<T5>::template Read<RW> (input_stream, d5);
Read_Write<T6>::template Read<RW> (input_stream, d6);
}
template<class RW, class T1, class T2, class T3, class T4, class T5, class T6, class T7>
inline void Read_Binary (std::istream& input_stream, T1& d1, T2& d2, T3& d3, T4& d4, T5& d5, T6& d6, T7& d7)
{
Read_Write<T1>::template Read<RW> (input_stream, d1);
Read_Write<T2>::template Read<RW> (input_stream, d2);
Read_Write<T3>::template Read<RW> (input_stream, d3);
Read_Write<T4>::template Read<RW> (input_stream, d4);
Read_Write<T5>::template Read<RW> (input_stream, d5);
Read_Write<T6>::template Read<RW> (input_stream, d6);
Read_Write<T7>::template Read<RW> (input_stream, d7);
}
template<class RW, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8>
inline void Read_Binary (std::istream& input_stream, T1& d1, T2& d2, T3& d3, T4& d4, T5& d5, T6& d6, T7& d7, T8& d8)
{
Read_Write<T1>::template Read<RW> (input_stream, d1);
Read_Write<T2>::template Read<RW> (input_stream, d2);
Read_Write<T3>::template Read<RW> (input_stream, d3);
Read_Write<T4>::template Read<RW> (input_stream, d4);
Read_Write<T5>::template Read<RW> (input_stream, d5);
Read_Write<T6>::template Read<RW> (input_stream, d6);
Read_Write<T7>::template Read<RW> (input_stream, d7);
Read_Write<T8>::template Read<RW> (input_stream, d8);
}
template<class RW, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9>
inline void Read_Binary (std::istream& input_stream, T1& d1, T2& d2, T3& d3, T4& d4, T5& d5, T6& d6, T7& d7, T8& d8, T9& d9)
{
Read_Write<T1>::template Read<RW> (input_stream, d1);
Read_Write<T2>::template Read<RW> (input_stream, d2);
Read_Write<T3>::template Read<RW> (input_stream, d3);
Read_Write<T4>::template Read<RW> (input_stream, d4);
Read_Write<T5>::template Read<RW> (input_stream, d5);
Read_Write<T6>::template Read<RW> (input_stream, d6);
Read_Write<T7>::template Read<RW> (input_stream, d7);
Read_Write<T8>::template Read<RW> (input_stream, d8);
Read_Write<T9>::template Read<RW> (input_stream, d9);
}
//#####################################################################
// Write_Binary
//#####################################################################
template<class RW, class T1>
inline void Write_Binary (std::ostream& output_stream, const T1& d1)
{
Read_Write<T1>::template Write<RW> (output_stream, d1);
}
template<class RW, class T1, class T2>
inline void Write_Binary (std::ostream& output_stream, const T1& d1, const T2& d2)
{
Read_Write<T1>::template Write<RW> (output_stream, d1);
Read_Write<T2>::template Write<RW> (output_stream, d2);
}
template<class RW, class T1, class T2, class T3>
inline void Write_Binary (std::ostream& output_stream, const T1& d1, const T2& d2, const T3& d3)
{
Read_Write<T1>::template Write<RW> (output_stream, d1);
Read_Write<T2>::template Write<RW> (output_stream, d2);
Read_Write<T3>::template Write<RW> (output_stream, d3);
}
template<class RW, class T1, class T2, class T3, class T4>
inline void Write_Binary (std::ostream& output_stream, const T1& d1, const T2& d2, const T3& d3, const T4& d4)
{
Read_Write<T1>::template Write<RW> (output_stream, d1);
Read_Write<T2>::template Write<RW> (output_stream, d2);
Read_Write<T3>::template Write<RW> (output_stream, d3);
Read_Write<T4>::template Write<RW> (output_stream, d4);
}
template<class RW, class T1, class T2, class T3, class T4, class T5>
inline void Write_Binary (std::ostream& output_stream, const T1& d1, const T2& d2, const T3& d3, const T4& d4, const T5& d5)
{
Read_Write<T1>::template Write<RW> (output_stream, d1);
Read_Write<T2>::template Write<RW> (output_stream, d2);
Read_Write<T3>::template Write<RW> (output_stream, d3);
Read_Write<T4>::template Write<RW> (output_stream, d4);
Read_Write<T5>::template Write<RW> (output_stream, d5);
}
template<class RW, class T1, class T2, class T3, class T4, class T5, class T6>
inline void Write_Binary (std::ostream& output_stream, const T1& d1, const T2& d2, const T3& d3, const T4& d4, const T5& d5, const T6& d6)
{
Read_Write<T1>::template Write<RW> (output_stream, d1);
Read_Write<T2>::template Write<RW> (output_stream, d2);
Read_Write<T3>::template Write<RW> (output_stream, d3);
Read_Write<T4>::template Write<RW> (output_stream, d4);
Read_Write<T5>::template Write<RW> (output_stream, d5);
Read_Write<T6>::template Write<RW> (output_stream, d6);
}
template<class RW, class T1, class T2, class T3, class T4, class T5, class T6, class T7>
inline void Write_Binary (std::ostream& output_stream, const T1& d1, const T2& d2, const T3& d3, const T4& d4, const T5& d5, const T6& d6, const T7& d7)
{
Read_Write<T1>::template Write<RW> (output_stream, d1);
Read_Write<T2>::template Write<RW> (output_stream, d2);
Read_Write<T3>::template Write<RW> (output_stream, d3);
Read_Write<T4>::template Write<RW> (output_stream, d4);
Read_Write<T5>::template Write<RW> (output_stream, d5);
Read_Write<T6>::template Write<RW> (output_stream, d6);
Read_Write<T7>::template Write<RW> (output_stream, d7);
}
template<class RW, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8>
inline void Write_Binary (std::ostream& output_stream, const T1& d1, const T2& d2, const T3& d3, const T4& d4, const T5& d5, const T6& d6, const T7& d7, const T8& d8)
{
Read_Write<T1>::template Write<RW> (output_stream, d1);
Read_Write<T2>::template Write<RW> (output_stream, d2);
Read_Write<T3>::template Write<RW> (output_stream, d3);
Read_Write<T4>::template Write<RW> (output_stream, d4);
Read_Write<T5>::template Write<RW> (output_stream, d5);
Read_Write<T6>::template Write<RW> (output_stream, d6);
Read_Write<T7>::template Write<RW> (output_stream, d7);
Read_Write<T8>::template Write<RW> (output_stream, d8);
}
template<class RW, class T1, class T2, class T3, class T4, class T5, class T6, class T7, class T8, class T9>
inline void Write_Binary (std::ostream& output_stream, const T1& d1, const T2& d2, const T3& d3, const T4& d4, const T5& d5, const T6& d6, const T7& d7, const T8& d8, const T9& d9)
{
Read_Write<T1>::template Write<RW> (output_stream, d1);
Read_Write<T2>::template Write<RW> (output_stream, d2);
Read_Write<T3>::template Write<RW> (output_stream, d3);
Read_Write<T4>::template Write<RW> (output_stream, d4);
Read_Write<T5>::template Write<RW> (output_stream, d5);
Read_Write<T6>::template Write<RW> (output_stream, d6);
Read_Write<T7>::template Write<RW> (output_stream, d7);
Read_Write<T8>::template Write<RW> (output_stream, d8);
Read_Write<T9>::template Write<RW> (output_stream, d9);
}
//#####################################################################
// Read/Write_Binary_Array
//#####################################################################
// array is C-style (zero-based) array
template<class RW, class T>
inline void Read_Binary_Array (std::istream& input_stream, T* array, const int number_of_elements)
{
for (int i = 0; i < number_of_elements; i++) Read_Write<T>::template Read<RW> (input_stream, array[i]);
}
template<class RW, class T>
inline void Write_Binary_Array (std::ostream& output_stream, const T* array, const int number_of_elements)
{
for (int i = 0; i < number_of_elements; i++) Read_Write<T>::template Write<RW> (output_stream, array[i]);
}
//#####################################################################
}
#endif