00001 /*************************************************************************** 00002 * Copyright (C) 2001 by Rick L. Vinyard, Jr. * 00003 * rvinyard@cs.nmsu.edu * 00004 * * 00005 * This file is part of the bit library. * 00006 * * 00007 * The bit library is free software; you can redistribute it and/or * 00008 * modify it under the terms of the GNU General Public License * 00009 * version 3 as published by the Free Software Foundation. * 00010 * * 00011 * The bit library is distributed in the hope that it will be useful, * 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 00014 * General Public License for more details. * 00015 * * 00016 * You should have received a copy of the GNU General Public License * 00017 * along with this software. If not see <http://www.gnu.org/licenses/>. * 00018 ***************************************************************************/ 00019 #ifndef BITFIELDBUFFER_H 00020 #define BITFIELDBUFFER_H 00021 00022 #include <bit/fieldbase.h> 00023 #include <bit/data.h> 00024 00025 #include <sstream> 00026 00027 namespace bit 00028 { 00029 00030 class RecordBuffer; 00031 00032 00040 class FieldBuffer 00041 { 00042 public: 00043 00044 FieldBuffer(); 00045 00046 FieldBuffer(RecordBuffer& b, FieldBase::pointer f); 00047 00048 virtual ~FieldBuffer(); 00049 00050 void set_record_field( RecordBuffer& b, FieldBase::pointer f ); 00051 00052 void set_record_field( RecordBuffer* b=NULL, FieldBase::pointer f=FieldBase::pointer() ); 00053 00054 std::string xml(const std::string& padding=std::string()); 00055 00056 std::string value(); 00057 00058 FieldBuffer field(size_t index) throw (exception::invalid_index); 00059 00060 FieldBuffer field(const std::string& index) throw (exception::invalid_index); 00061 00062 FieldBuffer operator[](size_t index) throw (exception::invalid_index); 00063 00064 FieldBuffer operator[](const std::string& index) throw (exception::invalid_index); 00065 00066 FieldBuffer operator[](const char* index) throw (exception::invalid_index); 00067 00068 template <typename T> 00069 operator T(); 00070 00074 Data data(); 00075 00076 bool unpack(void* mem, size_t mem_octets); 00077 00078 template <typename T> 00079 bool unpack(T& val); 00080 00081 bool pack(const void* mem, size_t mem_octets); 00082 bool pack(const void* mem, size_t mem_octets, size_t n); 00083 00084 template <typename T> 00085 bool pack(const T& val); 00086 00087 template <typename T> 00088 FieldBuffer& operator=(const T& t); 00089 00090 FieldBase::pointer field(); 00091 00092 RecordBuffer* buffer(); 00093 00094 protected: 00095 RecordBuffer* m_buffer; 00096 FieldBase::pointer m_field; 00097 00102 bool unpack_uint64(uint64_t& ui64 ); 00103 00104 bool unpack_int64(int64_t& i64 ); 00105 00106 bool unpack_float(float& f); 00107 bool unpack_double(double& d); 00108 00109 bool unpack_string(std::string& s); 00110 00115 bool pack_uint64(uint64_t data); 00116 bool pack_float(float f); 00117 bool pack_double(double d); 00118 00119 }; 00120 00121 template <typename T> 00122 inline 00123 FieldBuffer::operator T() 00124 { 00125 T t; 00126 if ( ! m_buffer || ! m_field ) 00127 throw exception::no_recordbuffer(); 00128 this->unpack(t); 00129 return t; 00130 } 00131 00132 template <typename T> 00133 inline 00134 bool FieldBuffer::unpack(T& val) 00135 { 00136 bool b; 00137 float f; 00138 double d; 00139 uint64_t ui64; 00140 int64_t i64; 00141 size_t length; 00142 00143 if ( ! m_buffer || ! m_field ) 00144 throw exception::no_recordbuffer(); 00145 00146 // TODO finish this section for all allowed types 00147 switch ( m_field->type().type() ) 00148 { 00149 case TYPE_INTEGER: 00150 switch ( m_field->type().sign() ) 00151 { 00152 case SIGN_UNSIGNED: 00153 b = this->unpack_uint64(ui64); 00154 val = static_cast<T>(ui64); 00155 return b; 00156 case SIGN_TWOS_COMPLEMENT: 00157 case SIGN_ONES_COMPLEMENT: 00158 case SIGN_BIT: 00159 b = this->unpack_int64(i64); 00160 val = static_cast<T>(i64); 00161 return b; 00162 } 00163 00164 case TYPE_FLOATING: 00165 length = m_field->length(BITS); 00166 if ( ! (length == 64 || length == 32 ) ) 00167 throw exception::type::floating_point_length(); 00168 if (length == 64) 00169 { 00170 b = this->unpack_double(d); 00171 val = static_cast<T>(d); 00172 } 00173 else 00174 { 00175 b = this->unpack_float(f); 00176 val = static_cast<T>(f); 00177 } 00178 return b; 00179 case TYPE_NONE: 00180 case TYPE_ASCII: 00181 case TYPE_UTF8: 00182 case TYPE_BCD: 00183 break; 00184 } 00185 return this->unpack(&val, sizeof(T)); 00186 } 00187 00188 // TODO finish this section for string conversions 00189 // probably need to check that length%8 == 0 or throw 00190 template <> 00191 inline 00192 bool FieldBuffer::unpack(std::string& val) 00193 { 00194 double d; 00195 float f; 00196 uint64_t ui64; 00197 int64_t i64; 00198 size_t length; 00199 std::ostringstream sout; 00200 00201 if ( ! m_buffer || ! m_field ) 00202 throw exception::no_recordbuffer(); 00203 00204 // TODO finish this section for all allowed types 00205 switch ( m_field->type().type() ) 00206 { 00207 case TYPE_INTEGER: 00208 switch ( m_field->type().sign() ) 00209 { 00210 case SIGN_UNSIGNED: 00211 if ( this->unpack_uint64(ui64) ) 00212 { 00213 sout << ui64; 00214 val = sout.str(); 00215 return true; 00216 } 00217 else 00218 return false; 00219 case SIGN_TWOS_COMPLEMENT: 00220 case SIGN_ONES_COMPLEMENT: 00221 case SIGN_BIT: 00222 if ( this->unpack_int64(i64) ) 00223 { 00224 sout << i64; 00225 val = sout.str(); 00226 return true; 00227 } 00228 else 00229 return false; 00230 break; 00231 } 00232 00233 case TYPE_FLOATING: 00234 length = m_field->length(BITS); 00235 if ( ! (length == 64 || length == 32 ) ) 00236 throw exception::type::floating_point_length(); 00237 if (length == 64) 00238 { 00239 if ( this->unpack_double(d) ) 00240 { 00241 sout << d; 00242 val = sout.str(); 00243 return true; 00244 } 00245 else 00246 return false; 00247 } 00248 else 00249 { 00250 if ( this->unpack_float(f) ) 00251 { 00252 sout << f; 00253 val = sout.str(); 00254 return true; 00255 } 00256 else 00257 return false; 00258 } 00259 case TYPE_ASCII: 00260 return this->unpack_string( val ); 00261 default: 00262 return false; 00263 } 00264 return false; 00265 } 00266 00267 template <typename T> 00268 inline 00269 bool FieldBuffer::pack(const T& val) 00270 { 00271 uint64_t ui64; 00272 double d; 00273 float f; 00274 size_t length; 00275 00276 if ( ! m_buffer || ! m_field ) 00277 throw exception::no_recordbuffer(); 00278 00279 switch ( m_field->type().type() ) 00280 { 00281 case TYPE_INTEGER: 00282 ui64 = val; 00283 return this->pack_uint64(ui64); 00284 00285 case TYPE_FLOATING: 00286 length = m_field->length(BITS); 00287 if ( ! (length == 64 || length == 32 ) ) 00288 throw exception::type::floating_point_length(); 00289 if (length == 64) 00290 { 00291 d = static_cast<double>(val); 00292 return this->pack_double(d); 00293 } 00294 else 00295 { 00296 f = static_cast<float>(val); 00297 return this->pack_float(f); 00298 } 00299 case TYPE_NONE: 00300 case TYPE_ASCII: 00301 case TYPE_UTF8: 00302 case TYPE_BCD: 00303 break; 00304 } 00305 00306 return this->pack(&val, sizeof(T)); 00307 } 00308 00309 template <> 00310 inline 00311 bool FieldBuffer::pack(const std::string& val) 00312 { 00313 uint64_t ui64; 00314 double d; 00315 float f; 00316 size_t length; 00317 std::istringstream sin(val); 00318 00319 if ( ! m_buffer || ! m_field ) 00320 throw exception::no_recordbuffer(); 00321 00322 switch ( m_field->type().type() ) 00323 { 00324 case TYPE_INTEGER: 00325 sin >> ui64; 00326 return this->pack_uint64(ui64); 00327 00328 case TYPE_FLOATING: 00329 length = m_field->length(BITS); 00330 if ( ! (length == 64 || length == 32 ) ) 00331 throw exception::type::floating_point_length(); 00332 if (length == 64) 00333 { 00334 sin >> d; 00335 return this->pack_double(d); 00336 } 00337 else 00338 { 00339 sin >> f; 00340 return this->pack_float(f); 00341 } 00342 default: 00343 return false; 00344 } 00345 00346 return false; 00347 } 00348 00349 template <typename T> 00350 inline 00351 FieldBuffer& FieldBuffer::operator=(const T& t) 00352 { 00353 if ( ! m_buffer || ! m_field ) 00354 throw exception::no_recordbuffer(); 00355 this->pack(t); 00356 return *this; 00357 } 00358 00359 00360 } 00361 00362 #endif