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_io_xrbuf 00005 #define inlib_io_xrbuf 00006 00007 #include "irbuf" 00008 00009 #ifdef INLIB_MEM 00010 #include "../mem" 00011 #endif 00012 00013 #include <ostream> 00014 00015 #include "../realloc" 00016 #include "../s2int64" 00017 #include "../cstr" 00018 00019 namespace inlib { 00020 namespace io { 00021 00022 class xrbuf : public virtual irbuf { 00023 #ifdef INLIB_MEM 00024 static const std::string& s_class() { 00025 static const std::string s_v("inlib::io::xrbuf"); 00026 return s_v; 00027 } 00028 #endif 00029 public: //irbuf 00030 virtual bool read(uchar& a_x){return _read_strtol<uchar>(a_x);} 00031 virtual bool read(char& a_x){return _read_strtol<char>(a_x);} 00032 virtual bool read(uint16& a_x){return _read_strtol<uint16>(a_x);} 00033 virtual bool read(int16& a_x){return _read_strtol<int16>(a_x);} 00034 virtual bool read(uint32& a_x){return _read_strtol<uint32>(a_x);} 00035 virtual bool read(int32& a_x){return _read_strtol<int32>(a_x);} 00036 00037 virtual bool read(uint64& a_x){ 00038 return _read<uint64,int64>(a_x,inlib::s2int64); 00039 } 00040 virtual bool read(int64& a_x){ 00041 return _read<int64,int64>(a_x,inlib::s2int64); 00042 } 00043 00044 virtual bool read(bool& a_v) { 00045 uchar v; 00046 bool status = read(v); 00047 a_v = (v==1?true:false); 00048 return status; 00049 } 00050 00051 virtual bool read(float& a_v){ 00052 char* end; 00053 #ifdef WIN32 00054 double v = ::strtod(m_pos,&end); 00055 a_v = (float)v; 00056 #else 00057 a_v = ::strtof(m_pos,&end); 00058 #endif 00059 if(end==m_pos) return false; 00060 if((end+1)>m_max) return false; 00061 m_pos = end+1; 00062 return true; 00063 } 00064 virtual bool read(double& a_v){ 00065 char* end; 00066 a_v = ::strtod(m_pos,&end); 00067 if(end==m_pos) return false; 00068 if((end+1)>m_max) return false; 00069 m_pos = end+1; 00070 return true; 00071 } 00072 00073 virtual bool read_cstr(char*& a_cstr) { 00074 char* pos = m_pos; 00075 char* begin = m_pos; 00076 uint32 sz = _remaining(); 00077 for(uint32 index=0;index<sz;index++,pos++) { 00078 if((*pos)=='\0') { 00079 diff_pointer_t l = pos-begin; 00080 a_cstr = str_new(l); 00081 ::memcpy(a_cstr,begin,l); 00082 begin = pos+1; 00083 m_pos = begin; 00084 return true; //stop at first string found. 00085 } 00086 } 00087 a_cstr = 0; 00088 return false; 00089 } 00090 00091 virtual bool read_vec(uint32& a_n,uchar*& a_x){ 00092 return _read_array<uchar>(a_n,a_x); 00093 } 00094 virtual bool read_vec(uint32& a_n,char*& a_x){ 00095 return _read_array<char>(a_n,a_x); 00096 } 00097 virtual bool read_vec(uint32& a_n,uint16*& a_x){ 00098 return _read_array<uint16>(a_n,a_x); 00099 } 00100 virtual bool read_vec(uint32& a_n,int16*& a_x){ 00101 return _read_array<int16>(a_n,a_x); 00102 } 00103 virtual bool read_vec(uint32& a_n,uint32*& a_x){ 00104 return _read_array<uint32>(a_n,a_x); 00105 } 00106 virtual bool read_vec(uint32& a_n,int32*& a_x){ 00107 return _read_array<int32>(a_n,a_x); 00108 } 00109 virtual bool read_vec(uint32& a_n,uint64*& a_x){ 00110 return _read_array<uint64>(a_n,a_x); 00111 } 00112 virtual bool read_vec(uint32& a_n,int64*& a_x){ 00113 return _read_array<int64>(a_n,a_x); 00114 } 00115 virtual bool read_vec(uint32& a_n,float*& a_x){ 00116 return _read_array<float>(a_n,a_x); 00117 } 00118 virtual bool read_vec(uint32& a_n,double*& a_x){ 00119 return _read_array<double>(a_n,a_x); 00120 } 00121 virtual bool read_vec(uint32& a_n,bool*& a_x){ 00122 return _read_array<bool>(a_n,a_x); 00123 } 00124 00125 virtual bool read_vec(std::vector<std::string>& a_a){ 00126 // <chars>\n<chars>\n<chars>0 00127 a_a.clear(); 00128 typedef cstr_t ta_type; 00129 char* pos = m_pos; 00130 char* begin = m_pos; 00131 uint32 sz = _remaining(); 00132 for(uint32 index=0;index<sz;index++,pos++) { 00133 if((*pos)=='\0') { 00134 m_pos = begin; 00135 ta_type v; 00136 if(!read_cstr(v)) { //v is allocated with str_new. 00137 a_a.clear(); 00138 return false; 00139 } 00140 if(v) a_a.push_back(v); 00141 begin = pos+1; 00142 return true; 00143 00144 } else if( ((*pos)=='\\') && 00145 ((pos+1)<=m_max) && 00146 ((*(pos+1))=='n') ){ 00147 m_pos = begin; 00148 char old_char = *pos; 00149 *pos = '\0'; 00150 ta_type v; 00151 if(!read_cstr(v)) { //v is allocated with str_new. 00152 *pos = old_char; 00153 a_a.clear(); 00154 return false; 00155 } 00156 *pos = old_char; 00157 if(v) a_a.push_back(v); 00158 begin = pos+2; 00159 } 00160 } 00161 //FIXME : return false if not ending with null char. 00162 return true; 00163 } 00164 00165 virtual bool read_std_vec_vec(std_vec_vec_uint_t& a_vv) { 00166 return _read_std_vec_vec<unsigned int>(a_vv); 00167 } 00168 virtual bool read_std_vec_vec(std_vec_vec_float_t& a_vv) { 00169 return _read_std_vec_vec<float>(a_vv); 00170 } 00171 virtual bool read_std_vec_vec(std_vec_vec_string_t& a_vv) { 00172 // <str>\n<str>\n<num>\t<str>\n<str>\n<str>\t...\t<str>\n<str>0 00173 a_vv.clear(); 00174 char* pos = m_pos; 00175 char* begin = m_pos; 00176 uint32 sz = _remaining(); 00177 for(uint32 index=0;index<sz;index++,pos++) { 00178 if((*pos)=='\0') { 00179 m_pos = begin; 00180 std::vector<std::string> v; 00181 if(!read_vec(v)) { 00182 a_vv.clear(); 00183 return false; 00184 } 00185 a_vv.push_back(v); 00186 return true; 00187 00188 } else if( ((*pos)=='\\') && 00189 ((pos+1)<=m_max) && 00190 ((*(pos+1))=='t') ){ 00191 m_pos = begin; 00192 char old_char = *pos; 00193 *pos = '\0'; 00194 00195 std::vector<std::string> v; 00196 if(!read_vec(v)) { 00197 *pos = old_char; 00198 a_vv.clear(); 00199 return false; 00200 } 00201 *pos = old_char; 00202 00203 a_vv.push_back(v); 00204 00205 begin = pos+2; 00206 } 00207 } 00208 00209 return true; 00210 } 00211 public: 00212 xrbuf(std::ostream& a_out,uint32 a_size = 1014) 00213 :m_out(a_out) 00214 ,m_size(0) 00215 ,m_buffer(0) 00216 ,m_max(0) 00217 ,m_pos(0) 00218 { 00219 #ifdef INLIB_MEM 00220 mem::increment(s_class().c_str()); 00221 #endif 00222 m_size = a_size; 00223 m_buffer = new char[m_size]; 00224 m_max = m_buffer+m_size; 00225 m_pos = m_buffer; 00226 } 00227 virtual ~xrbuf(){ 00228 delete [] m_buffer; 00229 #ifdef INLIB_MEM 00230 mem::decrement(s_class().c_str()); 00231 #endif 00232 } 00233 protected: 00234 xrbuf(const xrbuf& a_from) 00235 : irbuf(a_from) 00236 ,m_out(a_from.m_out){ 00237 #ifdef INLIB_MEM 00238 mem::increment(s_class().c_str()); 00239 #endif 00240 } 00241 xrbuf& operator=(const xrbuf&){return *this;} 00242 public: 00243 bool copy(uint32 a_size,const char* a_buffer) { 00244 delete [] m_buffer; 00245 m_buffer = new char[a_size]; 00246 if(!m_buffer) {m_size = 0;m_max = 0;m_pos = 0;return false;} 00247 ::memcpy(m_buffer,a_buffer,a_size); 00248 m_size = a_size; 00249 m_max = m_buffer + m_size; 00250 m_pos = m_buffer; 00251 return true; 00252 } 00253 protected: 00254 template <class ta_type> 00255 bool _read_strtol(ta_type& a_v) { 00256 //introduced to compile on Android. 00257 //we expect at m_pos a C string (null terminated). 00258 char* end; 00259 long v = ::strtol(m_pos,&end,10); 00260 if(end==m_pos) return false; 00261 if((end+1)>m_max) return false; 00262 m_pos = end+1; 00263 a_v = (ta_type)v; 00264 return true; 00265 } 00266 00267 template <class ta_type,class ta_ret_type> 00268 bool _read(ta_type& a_v,inlib::s2int64_func a_func) { 00269 //we expect at m_pos a C string (null terminated). 00270 char* end; 00271 ta_ret_type v = a_func(m_pos,&end,10); 00272 if(end==m_pos) return false; 00273 if((end+1)>m_max) return false; 00274 m_pos = end+1; 00275 a_v = (ta_type)v; 00276 return true; 00277 } 00278 00279 template <class ta_type> 00280 inline bool _read_array(uint32& a_n,ta_type*& a_a){ 00281 // assume that the whole remaining buffer containes {xxx0}. 00282 // a_a is allocated by this method. 00283 a_n = 0; 00284 uint32 a_size = 100; 00285 a_a = new ta_type[a_size]; 00286 if(!a_a) return false; 00287 char* pos = m_pos; 00288 char* begin = m_pos; 00289 uint32 sz = _remaining(); 00290 if(sz==1) {a_n = 0;return true;} 00291 for(uint32 index=0;index<sz;index++,pos++) { 00292 if( ((*pos)==' ') || 00293 ((*pos)=='\0') ){ 00294 m_pos = begin; 00295 ta_type v; 00296 if(!read(v)) { 00297 delete [] a_a; 00298 a_a = 0; 00299 a_n = 0; 00300 return false; 00301 } 00302 if((a_n+1)>a_size) { 00303 uint32 new_a_size = 2*a_size; 00304 if(!realloc<ta_type>(a_a,new_a_size,a_size)) {a_n=0;return false;} 00305 a_size = new_a_size; 00306 } 00307 a_a[a_n] = v; 00308 a_n++; 00309 begin = pos+1; 00310 00311 if((*pos)=='\0') return true; 00312 } 00313 } 00314 //FIXME : return false if not ending with null char. 00315 return true; 00316 } 00317 00318 template <class T> 00319 bool _read_std_vec_vec(std::vector< std::vector<T> >& a_vv) { 00320 // <num> <num> <num>\n<num> <num> <num>\n...\n<num> <num>0 00321 a_vv.clear(); 00322 char* pos = m_pos; 00323 char* begin = m_pos; 00324 uint32 sz = _remaining(); 00325 for(uint32 index=0;index<sz;index++,pos++) { 00326 if((*pos)=='\0') { 00327 m_pos = begin; 00328 00329 uint32 n; 00330 T* v; 00331 if(!_read_array<T>(n,v)) { //v is allocated with new T[]. 00332 a_vv.clear(); 00333 return false; 00334 } 00335 if(n) { 00336 std::vector<T> sv(n); 00337 for(unsigned int i=0;i<n;i++) sv[i] = v[i]; 00338 a_vv.push_back(sv); 00339 } 00340 00341 delete [] v; 00342 00343 return true; 00344 00345 } else if( ((*pos)=='\\') && 00346 ((pos+1)<=m_max) && 00347 ((*(pos+1))=='n') ){ 00348 m_pos = begin; 00349 char old_char = *pos; 00350 *pos = '\0'; 00351 00352 uint32 n; 00353 T* v; 00354 if(!_read_array<T>(n,v)) { //v is allocated with new T[]. 00355 *pos = old_char; 00356 a_vv.clear(); 00357 return false; 00358 } 00359 *pos = old_char; 00360 00361 if(n) { 00362 std::vector<T> sv(n); 00363 for(unsigned int i=0;i<n;i++) sv[i] = v[i]; 00364 a_vv.push_back(sv); 00365 } 00366 00367 delete [] v; 00368 00369 begin = pos+2; 00370 } 00371 } 00372 00373 return true; 00374 } 00375 00376 uint32 _remaining() const {return (uint32)(m_max - m_pos);} 00377 protected: 00378 std::ostream& m_out; 00379 uint32 m_size; 00380 char* m_buffer; 00381 char* m_max; 00382 char* m_pos; 00383 }; 00384 00385 }} 00386 00387 #endif