fieldbuffer.h

00001 /***************************************************************************
00002 *   Copyright (C) 2001 by Rick L. Vinyard, Jr.                            *
00003 *   rvinyard@cs.nmsu.edu                                                  *
00004 *                                                                         *
00005 *   This program is free software; you can redistribute it and/or modify  *
00006 *   it under the terms of the GNU Lesser General Public License as        *
00007 *   published by the Free Software Foundation version 2.1.                *
00008 *                                                                         *
00009 *   This program is distributed in the hope that it will be useful,       *
00010 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00011 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
00012 *   GNU General Public License for more details.                          *
00013 *                                                                         *
00014 *   You should have received a copy of the GNU Lesser General Public      *
00015 *   License along with this library; if not, write to the                 *
00016 *   Free Software Foundation, Inc.,                                       *
00017 *   51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA              *
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(RecordBuffer& b, FieldBase::pointer f);
00045 
00046       virtual ~FieldBuffer();
00047 
00048       FieldBuffer operator[](size_t index) throw (error::invalid_index);
00049 
00050       FieldBuffer operator[](std::string index) throw (error::invalid_index);
00051 
00052       template <typename T>
00053       operator T();
00054 
00058       Data data();
00059 
00060       bool unpack(void* mem, size_t mem_octets);
00061 
00062       template <typename T>
00063       bool unpack(T& val);
00064 
00065       bool pack(const void* mem, size_t mem_octets);
00066       bool pack(const void* mem, size_t mem_octets, size_t n);
00067 
00068       template <typename T>
00069       bool pack(const T& val);
00070       template <typename T>
00071       FieldBuffer& operator=(const T& t);
00072 
00073       FieldBase::pointer field();
00074       RecordBuffer& buffer();
00075 
00076       //       template <typename T>
00077       //       bool pack(const T& val, size_t n)
00078       //       {
00079       //         return pack(&val, sizeof(T), n);
00080       //       }
00081 
00082 
00083 
00084     protected:
00085       RecordBuffer& m_buffer;
00086       FieldBase::pointer m_field;
00087 
00092       bool unpack_uint64(uint64_t& ui64 );
00093 
00094       bool unpack_float(float& f);
00095       bool unpack_double(double& d);
00096 
00101       bool pack_uint64(uint64_t data);
00102       bool pack_float(float f);
00103       bool pack_double(double d);
00104 
00105     };
00106 
00107   template <typename T>
00108   inline
00109   FieldBuffer::operator T()
00110   {
00111     T t;
00112     unpack(t);
00113     return t;
00114   }
00115 
00116   template <typename T>
00117   inline
00118   bool FieldBuffer::unpack(T& val)
00119   {
00120     bool b;
00121     float f;
00122     double d;
00123     uint64_t ui64;
00124 
00125     // TODO finish this section for all allowed types
00126     switch ( m_field->type().type() )
00127       {
00128       case TYPE_INTEGER:
00129         b = unpack_uint64(ui64);
00130         val = static_cast<uint64_t>(ui64);
00131         return b;
00132 
00133       case TYPE_FLOATING:
00134         size_t length = m_field->length(BITS);
00135         if ( ! (length == 64 || length == 32 ) )
00136           throw error::type::floating_point_length();
00137         if (length == 64)
00138           {
00139             b = unpack_double(d);
00140             val = static_cast<T>(d);
00141             return b;
00142           }
00143         else
00144           {
00145             b = unpack_float(f);
00146             val = static_cast<T>(f);
00147             return b;
00148           }
00149       }
00150     return unpack(&val, sizeof(T));
00151   }
00152 
00153   // TODO finish this section for string conversions
00154   // probably need to check that length%8 == 0 or throw
00155   template <>
00156   inline
00157   bool FieldBuffer::unpack(std::string& val)
00158   {
00159     double d;
00160     float f;
00161     uint64_t ui64;
00162     size_t length;
00163     std::ostringstream sout;
00164 
00165     // TODO finish this section for all allowed types
00166     switch ( m_field->type().type() )
00167       {
00168       case TYPE_INTEGER:
00169         if ( unpack_uint64(ui64) )
00170           {
00171             sout << ui64;
00172             val = sout.str();
00173             return true;
00174           }
00175         else
00176           return false;
00177 
00178       case TYPE_FLOATING:
00179         length = m_field->length(BITS);
00180         if ( ! (length == 64 || length == 32 ) )
00181           throw error::type::floating_point_length();
00182         if (length == 64)
00183           {
00184             if ( unpack_double(d) )
00185               {
00186                 sout << d;
00187                 val = sout.str();
00188                 return true;
00189               }
00190             else
00191               return false;
00192           }
00193         else
00194           {
00195             if ( unpack_float(f) )
00196               {
00197                 sout << f;
00198                 val = sout.str();
00199                 return true;
00200               }
00201             else
00202               return false;
00203           }
00204         default:
00205           return false;
00206       }
00207     return false;
00208   }
00209 
00210   template <typename T>
00211   inline
00212   bool FieldBuffer::pack(const T& val)
00213   {
00214     uint64_t ui64;
00215     double d;
00216     float f;
00217 
00218     switch ( m_field->type().type() )
00219       {
00220       case TYPE_INTEGER:
00221         ui64 = val;
00222         return pack_uint64(ui64);
00223 
00224       case TYPE_FLOATING:
00225         size_t length = m_field->length(BITS);
00226         if ( ! (length == 64 || length == 32 ) )
00227           throw error::type::floating_point_length();
00228         if (length == 64)
00229           {
00230             d = static_cast<double>(val);
00231             return pack_double(d);
00232           }
00233         else
00234           {
00235             f = static_cast<float>(val);
00236             return pack_float(f);
00237           }
00238       }
00239 
00240     return pack(&val, sizeof(T));
00241   }
00242 
00243   template <>
00244   inline
00245   bool FieldBuffer::pack(const std::string& val)
00246   {
00247     uint64_t ui64;
00248     double d;
00249     float f;
00250     size_t length;
00251     std::istringstream sin(val);
00252 
00253     switch ( m_field->type().type() )
00254       {
00255       case TYPE_INTEGER:
00256         sin >> ui64;
00257         return pack_uint64(ui64);
00258 
00259       case TYPE_FLOATING:
00260         length = m_field->length(BITS);
00261         if ( ! (length == 64 || length == 32 ) )
00262           throw error::type::floating_point_length();
00263         if (length == 64)
00264           {
00265             sin >> d;
00266             return pack_double(d);
00267           }
00268         else
00269           {
00270             sin >> f;
00271             return pack_float(f);
00272           }
00273         default:
00274           return false;
00275       }
00276 
00277     return false;
00278   }
00279 
00280   template <typename T>
00281   inline
00282   FieldBuffer& FieldBuffer::operator=(const T& t)
00283   {
00284     pack(t);
00285     return *this;
00286   }
00287 
00288 
00289 }
00290 
00291 #endif

Generated on Thu Jul 6 14:38:08 2006 by  doxygen 1.4.6