inlib
1.2.0
|
00001 // Copyright (C) 2010, Guy Barrand. All rights reserved. 00002 // See the file inlib.license for terms. 00003 00004 #ifndef inlib_wroot_wbuf 00005 #define inlib_wroot_wbuf 00006 00007 #include <ostream> 00008 #include "../pointer" 00009 #include "../stype" 00010 00011 #ifdef INLIB_MEM 00012 #include "../mem" 00013 #endif 00014 00015 #include <cstring> //memcpy 00016 00017 namespace inlib { 00018 namespace wroot { 00019 00020 class wbuf { 00021 00025 // NOTE : on most common platforms (including Android, iPad) 00026 // CERN-ROOT byte swaps ! (Bad luck). We have arranged to 00027 // optimize this operation. The below "_swap_" functions 00028 // do not have local variables and manipulates pointers 00029 // directly. 00030 00031 static void write_swap_2(char* a_pos,char* a_x) { 00032 *a_pos++ = *(a_x+1); 00033 *a_pos++ = *a_x; 00034 } 00035 static void write_swap_4(char* a_pos,char* a_x) { 00036 a_x += 3; 00037 *a_pos++ = *a_x--; 00038 *a_pos++ = *a_x--; 00039 *a_pos++ = *a_x--; 00040 *a_pos++ = *a_x; 00041 } 00042 static void write_swap_8(char* a_pos,char* a_x) { 00043 a_x += 7; 00044 *a_pos++ = *a_x--; 00045 *a_pos++ = *a_x--; 00046 *a_pos++ = *a_x--; 00047 *a_pos++ = *a_x--; 00048 *a_pos++ = *a_x--; 00049 *a_pos++ = *a_x--; 00050 *a_pos++ = *a_x--; 00051 *a_pos++ = *a_x; 00052 } 00056 static void write_nswp_2(char* a_pos,char* a_x) { 00057 ::memcpy(a_pos,a_x,2); 00058 } 00059 static void write_nswp_4(char* a_pos,char* a_x) { 00060 ::memcpy(a_pos,a_x,4); 00061 } 00062 static void write_nswp_8(char* a_pos,char* a_x) { 00063 ::memcpy(a_pos,a_x,8); 00064 } 00068 00069 00070 static const std::string& s_class() { 00071 static const std::string s_v("inlib::wroot::wbuf"); 00072 return s_v; 00073 } 00074 typedef void (*w_2_func)(char*,char*); 00075 typedef void (*w_4_func)(char*,char*); 00076 typedef void (*w_8_func)(char*,char*); 00077 public: 00078 wbuf(std::ostream& a_out,bool a_byte_swap, 00079 const char* a_eob,char*& a_pos) 00080 :m_out(a_out) 00081 ,m_byte_swap(a_byte_swap) 00082 ,m_eob(a_eob) 00083 ,m_pos(a_pos) 00084 00085 ,m_w_2_func(0) 00086 ,m_w_4_func(0) 00087 ,m_w_8_func(0) 00088 { 00089 #ifdef INLIB_MEM 00090 mem::increment(s_class().c_str()); 00091 #endif 00092 if(m_byte_swap) { 00093 m_w_2_func = write_swap_2; 00094 m_w_4_func = write_swap_4; 00095 m_w_8_func = write_swap_8; 00096 } else { 00097 m_w_2_func = write_nswp_2; 00098 m_w_4_func = write_nswp_4; 00099 m_w_8_func = write_nswp_8; 00100 } 00101 } 00102 virtual ~wbuf(){ 00103 #ifdef INLIB_MEM 00104 mem::decrement(s_class().c_str()); 00105 #endif 00106 } 00107 protected: 00108 wbuf(const wbuf& a_from) 00109 :m_out(a_from.m_out),m_eob(a_from.m_eob),m_pos(a_from.m_pos){ 00110 #ifdef INLIB_MEM 00111 mem::increment(s_class().c_str()); 00112 #endif 00113 } 00114 wbuf& operator=(const wbuf&){return *this;} 00115 public: 00116 void set_eob(const char* a_eob){m_eob = a_eob;} 00117 00118 public: 00119 bool write(unsigned char a_x) { 00120 if(!check_eob<unsigned char>()) return false; 00121 *m_pos++ = a_x; 00122 return true; 00123 } 00124 00125 bool write(unsigned short a_x) { 00126 if(!check_eob<unsigned short>()) return false; 00127 m_w_2_func(m_pos,(char*)&a_x); 00128 m_pos += sizeof(unsigned short); 00129 return true; 00130 } 00131 00132 bool write(unsigned int a_x) { 00133 if(!check_eob<unsigned int>()) return false; 00134 m_w_4_func(m_pos,(char*)&a_x); 00135 m_pos += sizeof(unsigned int); 00136 return true; 00137 } 00138 00139 bool write(uint64 a_x){ 00140 if(!check_eob<uint64>()) return false; 00141 m_w_8_func(m_pos,(char*)&a_x); 00142 m_pos += 8; 00143 return true; 00144 } 00145 00146 bool write(float a_x) { 00147 if(!check_eob<float>()) return false; 00148 m_w_4_func(m_pos,(char*)&a_x); 00149 m_pos += sizeof(float); 00150 return true; 00151 } 00152 00153 bool write(double a_x) { 00154 if(!check_eob<double>()) return false; 00155 m_w_8_func(m_pos,(char*)&a_x); 00156 m_pos += sizeof(double); 00157 return true; 00158 } 00159 00160 bool write(char a_x) {return write((unsigned char)a_x);} 00161 bool write(short a_x) {return write((unsigned short)a_x);} 00162 bool write(int a_x) {return write((unsigned int)a_x);} 00163 bool write(int64 a_x) {return write((uint64)a_x);} 00164 00165 bool write(const std::string& a_x) { 00166 unsigned char nwh; 00167 unsigned int nchars = a_x.size(); 00168 if(nchars>254) { 00169 if(!check_eob(1+4,"std::string")) return false; 00170 nwh = 255; 00171 if(!write(nwh)) return false; 00172 if(!write(nchars)) return false; 00173 } else { 00174 if(!check_eob(1,"std::string")) return false; 00175 nwh = (unsigned char)nchars; 00176 if(!write(nwh)) return false; 00177 } 00178 if(!check_eob(nchars,"std::string")) return false; 00179 for (unsigned int i = 0; i < nchars; i++) m_pos[i] = a_x[i]; 00180 m_pos += nchars; 00181 return true; 00182 } 00183 00184 00185 template <class T> 00186 bool write(const T* a_a,uint32 a_n) { 00187 if(!a_n) return true; 00188 uint32 l = a_n * sizeof(T); 00189 if(!check_eob(l,"array")) return false; 00190 if(m_byte_swap) { 00191 for(uint32 i=0;i<a_n;i++) { 00192 if(!write(a_a[i])) return false; 00193 } 00194 } else { 00195 ::memcpy(m_pos,a_a,l); 00196 m_pos += l; 00197 } 00198 return true; 00199 } 00200 00201 protected: 00202 template <class T> 00203 bool check_eob(){ 00204 if((m_pos+sizeof(T))>m_eob) { 00205 m_out << s_class() << " : " << stype(T()) << " : " 00206 << " try to access out of buffer " << long2s(sizeof(T)) << " bytes" 00207 << " (pos=" << char_p2s(m_pos) 00208 << ", eob=" << char_p2s(m_eob) << ")." << std::endl; 00209 return false; 00210 } 00211 return true; 00212 } 00213 bool check_eob(size_t a_n,const char* a_cmt){ 00214 if((m_pos+a_n)>m_eob) { 00215 m_out << s_class() << " : " << a_cmt << " : " 00216 << " try to access out of buffer " << long2s(a_n) << " bytes" 00217 << " (pos=" << char_p2s(m_pos) 00218 << ", eob=" << char_p2s(m_eob) << ")." << std::endl; 00219 return false; 00220 } 00221 return true; 00222 } 00223 protected: 00224 std::ostream& m_out; 00225 bool m_byte_swap; 00226 const char* m_eob; 00227 char*& m_pos; 00228 00229 w_2_func m_w_2_func; 00230 w_4_func m_w_4_func; 00231 w_8_func m_w_8_func; 00232 }; 00233 00234 }} 00235 00236 #endif