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