Sierra Toolkit Version of the Day
Marshal.cpp
00001 /*------------------------------------------------------------------------*/
00002 /*                 Copyright 2010 Sandia Corporation.                     */
00003 /*  Under terms of Contract DE-AC04-94AL85000, there is a non-exclusive   */
00004 /*  license for use of this work by or on behalf of the U.S. Government.  */
00005 /*  Export of this program may require a license from the                 */
00006 /*  United States Government.                                             */
00007 /*------------------------------------------------------------------------*/
00008 
00009 #include <stdexcept>
00010 #include <map>
00011 #include <cstring>
00012 
00013 #include <stk_util/util/Marshal.hpp>
00014 #include <iostream>
00015 
00016 namespace stk {
00017 
00018 namespace {
00019 
00020 typedef std::map<uint32_t, std::string> TypeNameMap;
00021 
00022 bool            s_crcInitialized = false;               
00023 uint32_t        s_crcTable[256];                        
00024 TypeNameMap     s_typeNameMap;                          
00025 
00026 uint32_t
00027 crc32_reflect(
00028   uint32_t      seed,
00029   const char    c)
00030 {
00031   uint32_t value = 0;
00032 
00033   // Swap bit 0 for bit 7, bit 1 For bit 6, etc....
00034   for(int i = 1; i < (c + 1); i++) {
00035     if (seed & 1) 
00036       value |= (1 << (c - i));
00037     seed >>= 1;
00038   }
00039 
00040   return value;
00041 }
00042 
00043 
00044 void
00045 crc32_initialize()
00046 {
00047   s_crcInitialized = true;
00048   
00049   //0x04C11DB7 is the official polynomial used by PKZip, WinZip and Ethernet.
00050   uint32_t polynomial = 0x04C11DB7;
00051 
00052   std::fill(s_crcTable, s_crcTable + 256, 0);
00053   
00054   // 256 values representing ASCII character codes.
00055   for (int i = 0; i <= 0xFF; i++) {
00056     s_crcTable[i] = crc32_reflect(i, 8) << 24;
00057 
00058     for (int j = 0; j < 8; j++)
00059       s_crcTable[i] = (s_crcTable[i] << 1) ^ ((s_crcTable[i] & (1u << 31)) ? polynomial : 0);
00060     
00061     s_crcTable[i] = crc32_reflect(s_crcTable[i], 32);
00062   }
00063 }
00064 
00065 
00066 void
00067 crc32_part(
00068   uint32_t &            crc,
00069   const unsigned char * s,
00070   unsigned              l)
00071 {
00072   while (l--)
00073     crc = (crc >> 8)^s_crcTable[(crc & 0xFF)^*s++];
00074 }
00075 
00076 
00077 uint32_t
00078 crc32(
00079   const unsigned char * s,
00080   unsigned              l)
00081 {
00082   uint32_t crc = 0xffffffff;
00083   crc32_part(crc, s, l);
00084   return crc ^ 0xffffffff;
00085 }
00086 
00087 
00088 void
00089 crc32_write(
00090   std::stringstream &           os,
00091   const std::type_info &        typeinfo)
00092 {
00093   if (!s_crcInitialized)
00094     crc32_initialize();
00095   
00096   const char *name = typeinfo.name();
00097   unsigned length = std::strlen(name);
00098   
00099   uint32_t      crc = crc32((const unsigned char *) name, length);
00100 
00101   TypeNameMap::iterator it = s_typeNameMap.find(crc);
00102   if (it == s_typeNameMap.end())
00103     s_typeNameMap.insert(std::make_pair(crc, std::string(name)));
00104                          
00105   os.write((const char *) &crc, sizeof(uint32_t));
00106 }
00107 
00108 
00109 void
00110 crc32_check(
00111   std::stringstream &           is,
00112   const std::type_info &        typeinfo)
00113 {
00114   if (!s_crcInitialized)
00115     crc32_initialize();
00116   
00117   const char *name = typeinfo.name();
00118   unsigned length = std::strlen(name);
00119   
00120   uint32_t      crc_check = crc32((const unsigned char *) name, length);
00121   uint32_t      crc = 0;
00122   
00123   {
00124     TypeNameMap::iterator it = s_typeNameMap.find(crc_check);
00125     if (it == s_typeNameMap.end())
00126       s_typeNameMap.insert(std::make_pair(crc_check, std::string(name)));
00127   }
00128                          
00129   is.read((char *) &crc, sizeof(uint32_t));
00130 
00131   if (crc_check != crc) {
00132     std::ostringstream ss;
00133     ss << "Marshaller encountered type ";
00134     TypeNameMap::const_iterator it = s_typeNameMap.find(crc);
00135     if (it == s_typeNameMap.end())
00136       ss << "code " << std::hex << crc;
00137     else
00138       ss << (*it).second;
00139     
00140     ss << " when expecting type ";
00141     it = s_typeNameMap.find(crc_check);
00142     if (it == s_typeNameMap.end())
00143       ss << "code " << std::hex << crc_check;
00144     else
00145       ss << (*it).second;
00146    
00147     throw std::runtime_error(ss.str());
00148   }
00149 }
00150 
00151 } // namespace <empty>
00152 
00153 Marshal::Marshal(
00154   unsigned              type_check)
00155   : stream(std::ios_base::out),
00156     m_typeCheck(TYPE_CHECK_NONE)
00157 {
00158   (*this) << type_check;
00159   m_typeCheck = type_check;
00160 }
00161 
00162 
00163 Marshal::Marshal(
00164   const std::string &   s)
00165   : stream(s, std::ios_base::in),
00166     m_typeCheck(TYPE_CHECK_NONE)
00167 {
00168   (*this) >> m_typeCheck;
00169 }
00170 
00171 
00172 std::string
00173 Marshal::str() const
00174 {
00175   return stream.str();
00176 }
00177 
00178 
00179 size_t
00180 Marshal::size() const
00181 {
00182   return stream.str().size();
00183 }
00184 
00185 
00186 Marshal::operator void * () const
00187 {
00188   return static_cast<void *>(const_cast<std::stringstream*>(&stream));
00189 }
00190 
00191 
00192 void
00193 Marshal::write(
00194   const char *          address, 
00195   size_t                byte_count)
00196 {
00197   stream.write(address, byte_count);
00198 }
00199 
00200   
00201 void
00202 Marshal::read(
00203   char *                address,
00204   size_t                byte_count)
00205 {
00206   stream.read(address, byte_count);
00207 }
00208 
00209 
00210 template<>
00211 Marshal &operator<<(Marshal &mout, const std::type_info &t) {
00212   crc32_write(mout.stream, t);
00213   return mout;
00214 }
00215 
00216 template<>
00217 Marshal &operator>>(Marshal &min, const std::type_info &t) {
00218   crc32_check(min.stream, t);
00219   return min;
00220 }
00221 
00222 template<>
00223 Marshal &operator<<(Marshal &mout, const signed char &t) {
00224   if (mout.m_typeCheck & Marshal::TYPE_CHECK_POD)
00225     mout << typeid(t);
00226   return write(mout, t);
00227 }
00228 
00229 template<>
00230 Marshal &operator<<(Marshal &mout, const unsigned char &t) {
00231   if (mout.m_typeCheck & Marshal::TYPE_CHECK_POD)
00232     mout << typeid(t);
00233   return write(mout, t);
00234 }
00235 
00236 template<>
00237 Marshal &operator<<(Marshal &mout, const char &t) {
00238   if (mout.m_typeCheck & Marshal::TYPE_CHECK_POD)
00239     mout << typeid(t);
00240   return write(mout, t);
00241 }
00242 
00243 template<>
00244 Marshal &operator<<(Marshal &mout, const short &t) {
00245   if (mout.m_typeCheck & Marshal::TYPE_CHECK_POD)
00246     mout << typeid(t);
00247   return write(mout, t);
00248 }
00249 
00250 template<>
00251 Marshal &operator<<(Marshal &mout, const unsigned short &t) {
00252   if (mout.m_typeCheck & Marshal::TYPE_CHECK_POD)
00253     mout << typeid(t);
00254   return write(mout, t);
00255 }
00256 
00257 template<>
00258 Marshal &operator<<(Marshal &mout, const int &t) {
00259   if (mout.m_typeCheck & Marshal::TYPE_CHECK_POD)
00260     mout << typeid(t);
00261   return write(mout, t);
00262 }
00263 
00264 template<>
00265 Marshal &operator<<(Marshal &mout, const unsigned int &t) {
00266   if (mout.m_typeCheck & Marshal::TYPE_CHECK_POD)
00267     mout << typeid(t);
00268   return write(mout, t);
00269 }
00270 
00271 template<>
00272 Marshal &operator<<(Marshal &mout, const long &t) {
00273   if (mout.m_typeCheck & Marshal::TYPE_CHECK_POD)
00274     mout << typeid(t);
00275   return write(mout, t);
00276 }
00277 
00278 template<>
00279 Marshal &operator<<(Marshal &mout, const unsigned long &t) {
00280   if (mout.m_typeCheck & Marshal::TYPE_CHECK_POD)
00281     mout << typeid(t);
00282   return write(mout, t);
00283 }
00284 
00285 template<>
00286 Marshal &operator<<(Marshal &mout, const long long &t) {
00287   if (mout.m_typeCheck & Marshal::TYPE_CHECK_POD)
00288     mout << typeid(t);
00289   return write(mout, t);
00290 }
00291 
00292 template<>
00293 Marshal &operator<<(Marshal &mout, const unsigned long long &t) {
00294   if (mout.m_typeCheck & Marshal::TYPE_CHECK_POD)
00295     mout << typeid(t);
00296   return write(mout, t);
00297 }
00298 
00299 template<>
00300 Marshal &operator<<(Marshal &mout, const float &t) {
00301   if (mout.m_typeCheck & Marshal::TYPE_CHECK_POD)
00302     mout << typeid(t);
00303   return write(mout, t);
00304 }
00305 
00306 template<>
00307 Marshal &operator<<(Marshal &mout, const double &t) {
00308   if (mout.m_typeCheck & Marshal::TYPE_CHECK_POD)
00309     mout << typeid(t);
00310   return write(mout, t);
00311 }
00312 
00313 template<>
00314 Marshal &operator<<(Marshal &mout, const std::string &s)  {
00315   if (mout.m_typeCheck & Marshal::TYPE_CHECK_POD)
00316     mout << typeid(s);
00317 
00318   size_t ul = s.size();
00319   mout << ul;
00320   mout.stream.write(s.data(), s.size());
00321   return mout;
00322 }
00323 
00324 
00325 template<>
00326 Marshal &operator>>(Marshal &min, signed char &t) {
00327   if (min.m_typeCheck & Marshal::TYPE_CHECK_POD)
00328     min >> typeid(t);
00329   return read(min, t);
00330 }
00331 
00332 template<>
00333 Marshal &operator>>(Marshal &min, unsigned char &t) {
00334   if (min.m_typeCheck & Marshal::TYPE_CHECK_POD)
00335     min >> typeid(t);
00336   return read(min, t);
00337 }
00338 
00339 template<>
00340 Marshal &operator>>(Marshal &min, char &t) {
00341   if (min.m_typeCheck & Marshal::TYPE_CHECK_POD)
00342     min >> typeid(t);
00343   return read(min, t);
00344 }
00345 
00346 template<>
00347 Marshal &operator>>(Marshal &min, short &t) {
00348   if (min.m_typeCheck & Marshal::TYPE_CHECK_POD)
00349     min >> typeid(t);
00350   return read(min, t);
00351 }
00352 
00353 template<>
00354 Marshal &operator>>(Marshal &min, unsigned short &t) {
00355   if (min.m_typeCheck & Marshal::TYPE_CHECK_POD)
00356     min >> typeid(t);
00357   return read(min, t);
00358 }
00359 
00360 template<>
00361 Marshal &operator>>(Marshal &min, int &t) {
00362   if (min.m_typeCheck & Marshal::TYPE_CHECK_POD)
00363     min >> typeid(t);
00364   return read(min, t);
00365 }
00366 
00367 template<>
00368 Marshal &operator>>(Marshal &min, unsigned int &t) {
00369   if (min.m_typeCheck & Marshal::TYPE_CHECK_POD)
00370     min >> typeid(t);
00371   return read(min, t);
00372 }
00373 
00374 template<>
00375 Marshal &operator>>(Marshal &min, long &t) {
00376   if (min.m_typeCheck & Marshal::TYPE_CHECK_POD)
00377     min >> typeid(t);
00378   return read(min, t);
00379 }
00380 
00381 template<>
00382 Marshal &operator>>(Marshal &min, unsigned long &t) {
00383   if (min.m_typeCheck & Marshal::TYPE_CHECK_POD)
00384     min >> typeid(t);
00385   return read(min, t);
00386 }
00387 
00388 template<>
00389 Marshal &operator>>(Marshal &min, long long &t) {
00390   if (min.m_typeCheck & Marshal::TYPE_CHECK_POD)
00391     min >> typeid(t);
00392   return read(min, t);
00393 }
00394 
00395 template<>
00396 Marshal &operator>>(Marshal &min, unsigned long long &t) {
00397   if (min.m_typeCheck & Marshal::TYPE_CHECK_POD)
00398     min >> typeid(t);
00399   return read(min, t);
00400 }
00401 
00402 template<>
00403 Marshal &operator>>(Marshal &min, float &t) {
00404   if (min.m_typeCheck & Marshal::TYPE_CHECK_POD)
00405     min >> typeid(t);
00406   return read(min, t);
00407 }
00408 
00409 template<>
00410 Marshal &operator>>(Marshal &min, double &t) {
00411   if (min.m_typeCheck & Marshal::TYPE_CHECK_POD)
00412     min >> typeid(t);
00413   return read(min, t);
00414 }
00415 
00416 template<>
00417 Marshal &operator>>(Marshal &min, std::string &s)  {
00418   if (min.m_typeCheck & Marshal::TYPE_CHECK_POD)
00419     min >> typeid(s);
00420 
00421   size_t size = 0;
00422   min >> size;
00423   std::vector<char> c(size);
00424   
00425   min.stream.read(&c[0], size);
00426   s.assign(&c[0], size);
00427   
00428   return min;
00429 }
00430 
00431 } // namespace stk
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines