inlib  1.2.0
/Users/barrand/private/dev/softinex/old/inexlib-1.2/inlib/inlib/io/xrbuf
Go to the documentation of this file.
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
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines