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_xwbuf 00005 #define inlib_io_xwbuf 00006 00007 // used to produce exsg XML files. 00008 00009 #include "iwbuf" 00010 00011 #include "../realloc" 00012 00013 #ifdef INLIB_MEM 00014 #include "../mem" 00015 #endif 00016 00017 #include <ostream> 00018 00019 #include "../mnmx" 00020 00021 namespace inlib { 00022 namespace io { 00023 00024 class xwbuf : public virtual iwbuf { 00025 #ifdef INLIB_MEM 00026 static const std::string& s_class() { 00027 static const std::string s_v("inlib::io::xwbuf"); 00028 return s_v; 00029 } 00030 #endif 00031 public: //iwbuf 00032 virtual bool write(uchar a_x) { 00033 if(!_write_cstr("<uchar v=\"")) return false; 00034 if(!_write<uchar>(a_x,write_format(a_x).c_str())) return false; 00035 if(!_write_cstr("\"/>")) return false; 00036 return true; 00037 } 00038 virtual bool write(char a_x) { 00039 if(!_write_cstr("<char v=\"")) return false; 00040 if(!_write<char>(a_x,write_format(a_x).c_str())) return false; 00041 if(!_write_cstr("\"/>")) return false; 00042 return true; 00043 } 00044 virtual bool write(uint16 a_x) { 00045 if(!_write_cstr("<uint16 v=\"")) return false; 00046 if(!_write<uint16>(a_x,write_format(a_x).c_str())) return false; 00047 if(!_write_cstr("\"/>")) return false; 00048 return true; 00049 } 00050 virtual bool write(int16 a_x) { 00051 if(!_write_cstr("<int16 v=\"")) return false; 00052 if(!_write<int16>(a_x,write_format(a_x).c_str())) return false; 00053 if(!_write_cstr("\"/>")) return false; 00054 return true; 00055 } 00056 virtual bool write(uint32 a_x) { 00057 if(!_write_cstr("<uint32 v=\"")) return false; 00058 if(!_write<uint32>(a_x,write_format(a_x).c_str())) return false; 00059 if(!_write_cstr("\"/>")) return false; 00060 return true; 00061 } 00062 virtual bool write(int32 a_x) { 00063 if(!_write_cstr("<int32 v=\"")) return false; 00064 if(!_write<int32>(a_x,write_format(a_x).c_str())) return false; 00065 if(!_write_cstr("\"/>")) return false; 00066 return true; 00067 } 00068 virtual bool write(uint64 a_x) { 00069 if(!_write_cstr("<uint64 v=\"")) return false; 00070 if(!_write<uint64>(a_x,write_format(a_x).c_str())) return false; 00071 if(!_write_cstr("\"/>")) return false; 00072 return true; 00073 } 00074 virtual bool write(int64 a_x) { 00075 if(!_write_cstr("<int64 v=\"")) return false; 00076 if(!_write<int64>(a_x,write_format(a_x).c_str())) return false; 00077 if(!_write_cstr("\"/>")) return false; 00078 return true; 00079 } 00080 virtual bool write(float a_x) { 00081 if(!_write_cstr("<float v=\"")) return false; 00082 if(!_write<float>(a_x,write_format(a_x).c_str())) return false; 00083 if(!_write_cstr("\"/>")) return false; 00084 return true; 00085 } 00086 virtual bool write(double a_x) { 00087 if(!_write_cstr("<double v=\"")) return false; 00088 if(!_write<double>(a_x,write_format(a_x).c_str())) return false; 00089 if(!_write_cstr("\"/>")) return false; 00090 return true; 00091 } 00092 00093 virtual bool write(bool a_v) { 00094 if(!_write_cstr("<bool v=\"")) return false; 00095 if((m_pos+MAX_SPRINTF_SIZE())>m_max) { 00096 if(!expand(inlib::mx<uint32>(2*m_size,m_size+MAX_SPRINTF_SIZE()))) 00097 return false; 00098 } 00099 if(!m_buffer) return false; 00100 //NOTE : the below writes an ending null char. 00101 #ifdef WIN32 00102 int sz = _snprintf(m_pos,MAX_SPRINTF_SIZE(),"%u",a_v?1:0); 00103 #else 00104 int sz = ::snprintf(m_pos,MAX_SPRINTF_SIZE(),"%u",a_v?1:0); 00105 #endif 00106 if(sz>(MAX_SPRINTF_SIZE()-1)) return false; 00107 m_pos += sz; 00108 if(!_write_cstr("\"/>")) return false; 00109 return true; 00110 } 00111 00112 virtual bool write_cstr(const char* a_cstr) { 00113 if(!_write_cstr("<string v=\"")) return false; 00114 if(!_write_xml_cstr(a_cstr)) return false; 00115 if(!_write_cstr("\"/>")) return false; 00116 return true; 00117 } 00118 00119 virtual bool write_vec(uint32 a_n,const uchar* a_x){ 00120 return _write_array<uchar>(a_n,a_x); 00121 } 00122 virtual bool write_vec(uint32 a_n,const char* a_x){ 00123 return _write_array<char>(a_n,a_x); 00124 } 00125 virtual bool write_vec(uint32 a_n,const uint16* a_x){ 00126 return _write_array<uint16>(a_n,a_x); 00127 } 00128 virtual bool write_vec(uint32 a_n,const int16* a_x){ 00129 return _write_array<int16>(a_n,a_x); 00130 } 00131 virtual bool write_vec(uint32 a_n,const uint32* a_x){ 00132 return _write_array<uint32>(a_n,a_x); 00133 } 00134 virtual bool write_vec(uint32 a_n,const int32* a_x){ 00135 return _write_array<int32>(a_n,a_x); 00136 } 00137 virtual bool write_vec(uint32 a_n,const uint64* a_x){ 00138 return _write_array<uint64>(a_n,a_x); 00139 } 00140 virtual bool write_vec(uint32 a_n,const int64* a_x){ 00141 return _write_array<int64>(a_n,a_x); 00142 } 00143 virtual bool write_vec(uint32 a_n,const float* a_x){ 00144 return _write_array<float>(a_n,a_x); 00145 } 00146 virtual bool write_vec(uint32 a_n,const double* a_x){ 00147 return _write_array<double>(a_n,a_x); 00148 } 00149 virtual bool write_vec(uint32 a_n,const bool* a_x){ 00150 return _write_array<bool>(a_n,a_x); 00151 } 00152 00153 virtual bool write_vec(const std::vector<std::string>& a_v){ 00154 // <string>\n<string>\n<string> 00155 if(!_write_cstr("<array>")) return false; 00156 std::vector<std::string>::const_iterator it; 00157 for(it=a_v.begin();it!=a_v.end();++it) { 00158 if(it!=a_v.begin()) {if(!_write_cstr("\\n")) return false;} 00159 if(!_write_xml_cstr((*it).c_str())) return false; 00160 } 00161 if(!_write_cstr("</array>")) return false; 00162 return true; 00163 } 00164 00165 virtual bool write_std_vec_vec(const std_vec_vec_uint_t& a_vv) { 00166 return _write_std_vec_vec<unsigned int>(a_vv); 00167 } 00168 virtual bool write_std_vec_vec(const std_vec_vec_float_t& a_vv) { 00169 return _write_std_vec_vec<float>(a_vv); 00170 } 00171 virtual bool write_std_vec_vec(const std_vec_vec_string_t& a_vv) { 00172 if(!_write_cstr("<array>")) return false; 00173 00174 typedef std::vector<std::string> vec_t; 00175 00176 std::vector<vec_t>::const_iterator it; 00177 for(it=a_vv.begin();it!=a_vv.end();++it) { 00178 if(it!=a_vv.begin()) {if(!_write_cstr("\\t")) return false;} 00179 00180 std::vector<std::string>::const_iterator it2; 00181 for(it2=(*it).begin();it2!=(*it).end();++it2) { 00182 if(it2!=(*it).begin()) {if(!_write_cstr("\\n")) return false;} 00183 if(!_write_xml_cstr((*it2).c_str())) return false; 00184 } 00185 00186 } 00187 00188 if(!_write_cstr("</array>")) return false; 00189 00190 return true; 00191 } 00192 public: 00193 virtual const char* buf() const {return m_buffer;} 00194 virtual uint32 length() const {return m_pos-m_buffer;} 00195 public: 00196 xwbuf(std::ostream& a_out,uint32 a_size = 1014) 00197 :m_out(a_out) 00198 ,m_size(0) 00199 ,m_buffer(0) 00200 ,m_max(0) 00201 ,m_pos(0) 00202 { 00203 #ifdef INLIB_MEM 00204 mem::increment(s_class().c_str()); 00205 #endif 00206 m_size = a_size; 00207 m_buffer = new char[m_size]; 00208 m_max = m_buffer+m_size; 00209 m_pos = m_buffer; 00210 } 00211 virtual ~xwbuf(){ 00212 delete [] m_buffer; 00213 #ifdef INLIB_MEM 00214 mem::decrement(s_class().c_str()); 00215 #endif 00216 } 00217 protected: 00218 xwbuf(const xwbuf& a_from) 00219 : iwbuf(a_from) 00220 ,m_out(a_from.m_out){ 00221 #ifdef INLIB_MEM 00222 mem::decrement(s_class().c_str()); 00223 #endif 00224 } 00225 xwbuf& operator=(const xwbuf&){return *this;} 00226 public: 00227 bool write_verbatim(const char* a_cstr) { 00228 if(!_write_cstr(a_cstr)) return false; 00229 return true; 00230 } 00231 void reset_pos() {m_pos = m_buffer;} 00232 protected: 00236 00237 bool _write_cstr(const char* a_cstr) { 00238 size_t sz = ::strlen(a_cstr); 00239 if((m_pos+sz)>m_max) 00240 if(!expand(inlib::mx<uint32>(2*m_size,m_size+sz))) return false; 00241 if(!m_buffer) return false; 00242 ::memcpy(m_pos,a_cstr,sz); 00243 m_pos += sz; 00244 return true; 00245 } 00246 00247 bool _write_xml_cstr(const char* a_cstr) { 00248 size_t sz = ::strlen(a_cstr); 00249 if((m_pos+sz)>m_max) 00250 if(!expand(inlib::mx<uint32>(2*m_size,m_size+sz))) return false; 00251 if(!m_buffer) return false; 00252 00253 char* pos = (char*)a_cstr; 00254 while(true){ 00255 char c = *pos;pos++; 00256 if(c=='\0') { 00257 break; 00258 } else if(c=='<') { 00259 *m_pos = '&';m_pos++; 00260 *m_pos = 'l';m_pos++; 00261 *m_pos = 't';m_pos++; 00262 *m_pos = ';';m_pos++; 00263 } else if(c=='>') { 00264 *m_pos = '&';m_pos++; 00265 *m_pos = 'g';m_pos++; 00266 *m_pos = 't';m_pos++; 00267 *m_pos = ';';m_pos++; 00268 } else if(c=='&') { 00269 *m_pos = '&';m_pos++; 00270 *m_pos = 'a';m_pos++; 00271 *m_pos = 'm';m_pos++; 00272 *m_pos = 'p';m_pos++; 00273 *m_pos = ';';m_pos++; 00274 } else if(c=='"') { 00275 *m_pos = '&';m_pos++; 00276 *m_pos = 'q';m_pos++; 00277 *m_pos = 'u';m_pos++; 00278 *m_pos = 'o';m_pos++; 00279 *m_pos = 't';m_pos++; 00280 *m_pos = ';';m_pos++; 00281 } else if(c=='\'') { 00282 *m_pos = '&';m_pos++; 00283 *m_pos = 'a';m_pos++; 00284 *m_pos = 'p';m_pos++; 00285 *m_pos = 'o';m_pos++; 00286 *m_pos = 's';m_pos++; 00287 *m_pos = ';';m_pos++; 00288 } else { 00289 *m_pos = c;m_pos++; 00290 } 00291 } 00292 00293 return true; 00294 } 00295 00296 static int MAX_SPRINTF_SIZE() {return 256;} 00297 00298 template <class ta_type> 00299 bool _write(ta_type a_v,const char* a_format) { 00300 if((m_pos+MAX_SPRINTF_SIZE())>m_max) { 00301 if(!expand(inlib::mx<uint32>(2*m_size,m_size+MAX_SPRINTF_SIZE()))) 00302 return false; 00303 } 00304 if(!m_buffer) return false; 00305 #ifdef WIN32 00306 int sz = _snprintf(m_pos,MAX_SPRINTF_SIZE(),a_format,a_v); 00307 #else 00308 int sz = ::snprintf(m_pos,MAX_SPRINTF_SIZE(),a_format,a_v); 00309 #endif 00310 if(sz>(MAX_SPRINTF_SIZE()-1)) return false; 00311 m_pos += sz; 00312 return true; 00313 } 00314 00315 template <class ta_type> 00316 bool _write_array(uint32 a_n,const ta_type* a_a) { 00317 if(!_write_cstr("<array>")) return false; 00318 00319 for(uint32 i=0;i<a_n;i++) { 00320 if(i) {if(!_write_cstr(" ")) return false;} 00321 if(!_write<ta_type>(a_a[i],write_format(a_a[i]).c_str())) return false; 00322 } 00323 00324 if(!_write_cstr("</array>")) return false; 00325 return true; 00326 } 00327 00328 template <class T> 00329 bool _write_std_vec_vec(const std::vector< std::vector<T> >& a_vv) { 00330 // <num> <num> <num>\n<num> <num> <num>\n...\n<num> <num> 00331 if(!_write_cstr("<array>")) return false; 00332 00333 typedef typename std::vector<T> vec_t; 00334 00335 typedef typename std::vector<vec_t>::const_iterator cit_t; 00336 for(cit_t it=a_vv.begin();it!=a_vv.end();++it) { 00337 if(it!=a_vv.begin()) {if(!_write_cstr("\\n")) return false;} 00338 00339 typedef typename std::vector<T>::const_iterator cit2_t; 00340 for(cit2_t it2=(*it).begin();it2!=(*it).end();++it2) { 00341 if(it2!=(*it).begin()) {if(!_write_cstr(" ")) return false;} 00342 if(!_write<T>(*it2,write_format(*it2).c_str())) return false; 00343 } 00344 00345 } 00346 00347 if(!_write_cstr("</array>")) return false; 00348 00349 return true; 00350 } 00351 protected: 00352 static const std::string& write_format(uchar) { 00353 static const std::string s_v("%u"); 00354 return s_v; 00355 } 00356 static const std::string& write_format(char) { 00357 static const std::string s_v("%d"); 00358 return s_v; 00359 } 00360 static const std::string& write_format(uint16) { 00361 static const std::string s_v("%u"); 00362 return s_v; 00363 } 00364 static const std::string& write_format(int16) { 00365 static const std::string s_v("%d"); 00366 return s_v; 00367 } 00368 static const std::string& write_format(uint32) { 00369 static const std::string s_v("%u"); 00370 return s_v; 00371 } 00372 static const std::string& write_format(int32) { 00373 static const std::string s_v("%d"); 00374 return s_v; 00375 } 00376 static const std::string& write_format(uint64) { 00377 static const std::string s_v(uint64_format()); 00378 return s_v; 00379 } 00380 static const std::string& write_format(int64) { 00381 static const std::string s_v(int64_format()); 00382 return s_v; 00383 } 00384 static const std::string& write_format(float) { 00385 static const std::string s_v("%g"); 00386 return s_v; 00387 } 00388 static const std::string& write_format(double) { 00389 static const std::string s_v("%g"); 00390 return s_v; 00391 } 00392 00393 bool expand(uint32 a_new_size) { 00394 unsigned long len = m_pos-m_buffer; 00395 if(!realloc<char>(m_buffer,a_new_size,m_size)) { 00396 m_out << "inlib::io::xwbuf::expand :" 00397 << " can't realloc " << a_new_size << " bytes." 00398 << std::endl; 00399 m_size = 0; 00400 m_max = 0; 00401 m_pos = 0; 00402 return false; 00403 } 00404 m_size = a_new_size; 00405 m_max = m_buffer + m_size; 00406 m_pos = m_buffer + len; 00407 return true; 00408 } 00409 protected: 00410 std::ostream& m_out; 00411 uint32 m_size; 00412 char* m_buffer; 00413 char* m_max; 00414 char* m_pos; 00415 }; 00416 00417 }} 00418 00419 #endif