CMS 3D CMS Logo

/data/refman/pasoursint/CMSSW_5_3_0/src/FWCore/Utilities/src/Digest.cc

Go to the documentation of this file.
00001 #include <iomanip>
00002 #include <sstream>
00003 
00004 #include "FWCore/Utilities/interface/EDMException.h"
00005 #include "FWCore/Utilities/interface/Digest.h"
00006 
00007 namespace cms
00008 {
00009   namespace
00010   {
00011     MD5Result const& invalidResult()
00012     {
00013       static const MD5Result val;      
00014       return val;
00015     }
00016 
00017     char unhexify(char hexed)
00018     {
00019       switch (hexed) 
00020         {
00021         case '0': case '1': case '2': case '3': case '4':
00022         case '5': case '6': case '7': case '8': case '9':
00023           return hexed - '0';
00024         case 'a': case 'b': case 'c': case 'd': case 'e': case 'f':
00025           return hexed - 'a' + 10;
00026         case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
00027           return hexed - 'A' + 10;
00028         default:
00029           throw edm::Exception(edm::errors::LogicError)
00030             << "Non-hex character in Hash "
00031             << "Please report this to the core framework developers";
00032         }
00033       // We never get here; return put in place to calm the compiler's
00034       // anxieties.
00035       return '\0';
00036     }
00037   }
00038 
00039   //--------------------------------------------------------------------
00040   //
00041   // MD5Result and associated free functions
00042   //
00043 
00044   void set_to_default(MD5Result& val)
00045   {
00046     val.bytes[0] = 0xd4;
00047     val.bytes[1] = 0x1d;
00048     val.bytes[2] = 0x8c;
00049     val.bytes[3] = 0xd9;
00050     val.bytes[4] = 0x8f;
00051     val.bytes[5] = 0x00;
00052     val.bytes[6] = 0xb2;
00053     val.bytes[7] = 0x04;
00054     val.bytes[8] = 0xe9;
00055     val.bytes[9] = 0x80;
00056     val.bytes[10] = 0x09;
00057     val.bytes[11] = 0x98;
00058     val.bytes[12] = 0xec;
00059     val.bytes[13] = 0xf8;
00060     val.bytes[14] = 0x42;
00061     val.bytes[15] = 0x7e;
00062   }
00063 
00064   MD5Result::MD5Result() 
00065   {
00066     set_to_default(*this);
00067   }
00068 
00069   static const char * s_hexValues =
00070   "000102030405060708090a0b0c0d0e0f"
00071   "101112131415161718191a1b1c1d1e1f"
00072   "202122232425262728292a2b2c2d2e2f"
00073   "303132333435363738393a3b3c3d3e3f"
00074   "404142434445464748494a4b4c4d4e4f"
00075   "505152535455565758595a5b5c5d5e5f"
00076   "606162636465666768696a6b6c6d6e6f"
00077   "707172737475767778797a7b7c7d7e7f"
00078   "808182838485868788898a8b8c8d8e8f"
00079   "909192939495969798999a9b9c9d9e9f"
00080   "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf"
00081   "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
00082   "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
00083   "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
00084   "e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
00085   "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff";
00086 
00087   std::string MD5Result::toString() const
00088   {
00089     char buf[16*2];
00090     char* pBuf=buf;
00091     for(unsigned int i=0; i<sizeof(bytes);++i){
00092       const char* p = s_hexValues+2*bytes[i];
00093       *pBuf = *p;
00094       ++pBuf;
00095       ++p;
00096       *pBuf=*p;
00097       ++pBuf;
00098     }
00099     return std::string(buf, sizeof(buf));
00100   }
00101 
00102   std::string MD5Result::compactForm() const
00103   {
00104     // This is somewhat dangerous, because the conversion of 'unsigned
00105     // char' to 'char' may be undefined if 'char' is a signed type
00106     // (4.7p3 in the Standard).
00107     const char* p = reinterpret_cast<const char*>(&bytes[0]);
00108     return std::string(p, p+sizeof(bytes));
00109   }
00110 
00111   void MD5Result::fromHexifiedString(std::string const& hexy)
00112   {
00113     switch (hexy.size())
00114       {
00115       case 0:
00116         {
00117           set_to_default(*this);
00118         }
00119         break;
00120       case 32:
00121         {
00122           std::string::const_iterator it = hexy.begin();
00123           for (size_t i = 0; i != 16; ++i)
00124             {
00125               // first nybble
00126               bytes[i] = ( unhexify(*it++) << 4 );
00127               // second nybble
00128               bytes[i] += ( unhexify(*it++) );
00129             }
00130         }
00131         break;
00132       default:
00133         {
00134           // Not really sure of what sort of exception to throw...
00135           throw edm::Exception(edm::errors::LogicError)
00136             << "String of illegal length: "
00137             << hexy.size()
00138             << " given to MD5Result::fromHexifiedString";         
00139         }
00140       }
00141   }
00142 
00143   bool MD5Result::isValid() const
00144   {
00145     return (*this != invalidResult());
00146   }
00147 
00148   bool operator==(MD5Result const& a, MD5Result const& b)
00149   {
00150     return std::equal(a.bytes, a.bytes+sizeof(a.bytes), b.bytes);
00151   }
00152 
00153 
00154   bool operator< (MD5Result const& a, MD5Result const& b)
00155   {
00156     return std::lexicographical_compare(a.bytes, 
00157                                         a.bytes+sizeof(a.bytes), 
00158                                         b.bytes,
00159                                         b.bytes+sizeof(b.bytes));
00160   }
00161 
00162 
00163 
00164   //--------------------------------------------------------------------
00165   //
00166   // Digest
00167   //
00168 
00169   Digest::Digest() :
00170     state_()
00171   {
00172     md5_init(&state_);
00173   }
00174 
00175   Digest::Digest(std::string const& s) :
00176     state_()
00177   {
00178     md5_init(&state_);
00179     this->append(s);
00180   }
00181 
00182   void Digest::append(std::string const& s) 
00183   {
00184     const md5_byte_t* data = reinterpret_cast<const md5_byte_t*>(s.data());
00185     md5_append(&state_, const_cast<md5_byte_t*>(data), s.size());
00186   }
00187 
00188   void Digest::append(const char *s, size_t size)
00189   {
00190     const md5_byte_t* data = reinterpret_cast<const md5_byte_t*>(s);
00191     md5_append(&state_, const_cast<md5_byte_t*>(data), size);
00192   }
00193 
00194   MD5Result Digest::digest() const
00195   {
00196     MD5Result aDigest;
00197     md5_finish(&state_, aDigest.bytes);
00198     return aDigest;
00199   }
00200 }