Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-04-09 07:49:33

0001 #pragma once
0002 /**
0003 sdigest.h
0004 ==========
0005 
0006 Header-only hexdigest
0007 
0008 Example from /usr/include/openssl/opensslv.h::
0009 
0010    33 # define OPENSSL_VERSION_NUMBER  0x100020bfL
0011 
0012 **/
0013 
0014 #include <string>
0015 #include <vector>
0016 #include <array>
0017 #include <sstream>
0018 
0019 #if defined __APPLE__
0020 
0021 #   define COMMON_DIGEST_FOR_OPENSSL
0022 #   include <CommonCrypto/CommonDigest.h>
0023 #   define SHA1 CC_SHA1
0024 
0025 #elif defined _MSC_VER
0026 
0027 #   include "md5.hh"
0028 
0029 #elif __linux
0030 
0031 #   include <openssl/md5.h>
0032 #   include <openssl/opensslv.h>
0033 
0034 #endif
0035 
0036 struct NP ;
0037 
0038 
0039 #if defined(__GNUC__) || defined(__clang__)
0040 #pragma GCC diagnostic push
0041 #pragma GCC diagnostic ignored "-Wdeprecated-declarations"
0042 #endif
0043 
0044 struct sdigest
0045 {
0046     static std::string Desc();
0047 
0048     MD5_CTX ctx ;
0049     sdigest();
0050     void add( const std::string& str);
0051     void add( const char* str );
0052     void add( int i );
0053     void add( const char* buffer, int length);
0054     void add( const std::vector<unsigned char>& bytes );
0055 
0056     std::string finalize() ;
0057     std::array<unsigned char,16> finalize_raw() ;
0058 
0059 
0060     static std::string Item(const NP* a, int i=-1, int j=-1, int k=-1, int l=-1, int m=-1, int o=-1);
0061     static std::array<unsigned char,16> ItemRaw(const NP* a, int i=-1, int j=-1, int k=-1, int l=-1, int m=-1, int o=-1);
0062 
0063     static std::string Buf(const char* buffer, int length);
0064     static std::array<unsigned char,16> BufRaw(const char* buffer, int length);
0065     static void BufRaw_(unsigned char* digest_16, const char* buffer, int length);
0066 
0067 
0068     static std::string Int(int i);
0069     static std::string Path(const char* path, unsigned bufsize=8192 );
0070     static std::string Paths(std::vector<std::string>& paths, unsigned bufsize=8192 );
0071 
0072 
0073     static void Update( MD5_CTX& c, const std::string& str);
0074     static void Update( MD5_CTX& c, const char* str );
0075     static void Update( MD5_CTX& c, int i );
0076     static void Update( MD5_CTX& c, const char* buffer, int length);
0077 
0078     //template<typename T> static void Update_(MD5_CTX& c, T v );
0079     template<typename T> static void Update_(MD5_CTX& c, T* vv, size_t count );
0080 
0081     //template<typename T> void add_( T v );
0082     template<typename T> void add_( T* vv, size_t count );
0083 
0084     static std::string DescRaw( unsigned char* digest16 );
0085 
0086     static std::string Finalize(MD5_CTX& c);
0087     static std::array<unsigned char,16> FinalizeRaw(MD5_CTX& c);
0088 
0089     static void FinalizeRaw_(unsigned char* digest_16, MD5_CTX& c );
0090 
0091 
0092 
0093 };
0094 
0095 
0096 inline std::string sdigest::Desc()
0097 {
0098     std::stringstream ss ;
0099 #if OPENSSL_VERSION_NUMBER == 0x100020bfL
0100     ss << "OPENSSL_VERSION_NUMBER == 0x100020bfL" << std::endl ;
0101 #elif OPENSSL_VERSION_NUMBER > 0x100020bfL
0102     ss << "OPENSSL_VERSION_NUMBER > 0x100020bfL" << std::endl ;
0103 #elif OPENSSL_VERSION_NUMBER < 0x100020bfL
0104     ss << "OPENSSL_VERSION_NUMBER < 0x100020bfL" << std::endl ;
0105 #endif
0106 
0107 #if __linux
0108     ss << "Linux : OPENSSL_VERSION_NUMBER is 0x" << std::hex << OPENSSL_VERSION_NUMBER  << std::dec << std::endl ;
0109 #endif
0110 
0111     std::string s = ss.str();
0112     return s ;
0113 }
0114 
0115 
0116 inline sdigest::sdigest(){ MD5_Init(&ctx); }
0117 inline void sdigest::add( const std::string& str){ Update(ctx, str) ; }
0118 inline void sdigest::add( const char* str ){ Update(ctx, str) ; }
0119 inline void sdigest::add( int i ){ Update(ctx, i ) ; }
0120 inline void sdigest::add( const char* str, int length ){ Update(ctx, str, length ) ; }
0121 inline void sdigest::add( const std::vector<unsigned char>& bytes ){ Update(ctx, (char*)bytes.data(), bytes.size() ); }
0122 
0123 inline std::string sdigest::finalize(){ return Finalize(ctx) ; }
0124 inline std::array<unsigned char,16> sdigest::finalize_raw(){ return FinalizeRaw(ctx) ; }
0125 
0126 
0127 
0128 #include "NP.hh"
0129 
0130 inline std::string sdigest::Item( const NP* a, int i, int j, int k, int l, int m, int o ) // static
0131 {
0132     const char* start = nullptr ;
0133     NP::INT num_bytes = 0 ;
0134     a->itembytes_(&start, num_bytes, i, j, k, l, m, o );
0135     assert( start && num_bytes > 0 );
0136     return Buf( start, num_bytes );
0137 }
0138 
0139 /**
0140 sdigest::ItemRaw
0141 -----------------
0142 
0143 For example of using the digests to check for duplicates see 
0144 sysrap/tests/sdigest_duplicate_test/sdigest_duplicate_test.cc
0145 
0146 **/
0147 
0148 
0149 inline std::array<unsigned char,16> sdigest::ItemRaw( const NP* a, int i, int j, int k, int l, int m, int o ) // static
0150 {
0151     const char* start = nullptr ;
0152     NP::INT num_bytes = 0 ;
0153     a->itembytes_(&start, num_bytes, i, j, k, l, m, o );
0154     assert( start && num_bytes > 0 );
0155     return BufRaw( start, num_bytes );
0156 }
0157 
0158 
0159 inline std::string sdigest::Buf(const char* buffer, int length) // static
0160 {
0161     MD5_CTX c;
0162     MD5_Init(&c);
0163     Update(c, buffer, length);
0164     return Finalize(c);
0165 }
0166 inline std::array<unsigned char,16> sdigest::BufRaw(const char* buffer, int length) // static
0167 {
0168     MD5_CTX c;
0169     MD5_Init(&c);
0170     Update(c, buffer, length);
0171     return FinalizeRaw(c);
0172 }
0173 
0174 inline void sdigest::BufRaw_(unsigned char* digest_16, const char* buffer, int length) // static
0175 {
0176     MD5_CTX c;
0177     MD5_Init(&c);
0178     Update(c, buffer, length);
0179     FinalizeRaw_(digest_16, c);
0180 }
0181 
0182 
0183 
0184 
0185 inline std::string sdigest::Int(int i) // static
0186 {
0187     MD5_CTX c;
0188     MD5_Init(&c);
0189     Update(c, i);
0190     return Finalize(c);
0191 }
0192 
0193 
0194 inline std::string sdigest::Path(const char* path, unsigned bufsize )
0195 {
0196     //std::cout << "sdigest::Path [" << path << "]" << std::endl ;
0197 
0198     FILE* fp = fopen(path, "rb");
0199     if (fp == NULL)
0200     {
0201         std::cerr << "failed to open path [" << path << "]" <<  std::endl ;
0202         return "" ;
0203     }
0204 
0205     sdigest dig ;
0206     char* data = new char[bufsize] ;
0207     int bytes ;
0208     while ((bytes = fread (data, 1, bufsize, fp)) != 0) dig.add(data, bytes);
0209     // NB must update just with the bytes read, not the bufsize
0210     delete[] data ;
0211 
0212     std::string out = dig.finalize();
0213     //std::cout << "sdigest::Path out [" << out << "]" << std::endl ;
0214     return out ;
0215 }
0216 
0217 inline std::string sdigest::Paths(std::vector<std::string>& paths, unsigned bufsize )
0218 {
0219     sdigest dig ;
0220     char* data = new char[bufsize] ;
0221 
0222     int num_paths = paths.size();
0223     for(int i=0 ; i < num_paths ; i++)
0224     {
0225         const char* path = paths[i].c_str();
0226 
0227         FILE* fp = fopen(path, "rb");
0228         if (fp == NULL)
0229         {
0230             std::cerr
0231                 << "sdigest::Paths"
0232                 << " failed to open"
0233                 << " path [" << path << "]\n"
0234                 ;
0235             continue ;
0236         }
0237 
0238         int bytes ;
0239         while ((bytes = fread (data, 1, bufsize, fp)) != 0) dig.add(data, bytes);
0240 
0241         fclose(fp);
0242     }
0243 
0244     delete[] data ;
0245 
0246     std::string out = dig.finalize();
0247     //std::cout << "sdigest::Path out [" << out << "]" << std::endl ;
0248     return out ;
0249 }
0250 
0251 
0252 
0253 
0254 
0255 inline void sdigest::Update(MD5_CTX& c, const std::string& str)
0256 {
0257     Update(c, str.c_str() );
0258 }
0259 
0260 inline void sdigest::Update(MD5_CTX& c, const char* str )
0261 {
0262     Update( c, (char*)str, strlen(str) );
0263 }
0264 
0265 inline void sdigest::Update(MD5_CTX& c, int i )
0266 {
0267     Update( c, (char*)&i, sizeof(int) );
0268 }
0269 
0270 inline void sdigest::Update(MD5_CTX& c, const char* buffer, int length) // static
0271 {
0272     const int blocksize = 512 ;
0273     while (length > 0)
0274     {
0275         if (length > blocksize) {
0276             MD5_Update(&c, buffer, blocksize);
0277         } else {
0278             MD5_Update(&c, buffer, length);
0279         }
0280         length -= blocksize ;
0281         buffer += blocksize ;
0282     }
0283 }
0284 
0285 
0286 
0287 /*
0288 template<typename T>
0289 inline void sdigest::Update_(MD5_CTX& c, T v )
0290 {
0291     Update( c, (char*)&v, sizeof(T) );
0292 }
0293 
0294 template<typename T>
0295 inline void sdigest::add_( T v ){ Update_<T>(ctx, v );  }
0296 */
0297 
0298 template<typename T>
0299 inline void sdigest::Update_(MD5_CTX& c, T* vv, size_t count )
0300 {
0301     Update( c, (char*)vv, sizeof(T)*count );
0302 }
0303 
0304 template<typename T>
0305 inline void sdigest::add_( T* vv, size_t count ){ Update_<T>(ctx, vv, count  );  }
0306 
0307 
0308 
0309 inline std::string sdigest::DescRaw( unsigned char* digest16 )
0310 {
0311     char buf[32+1] ;
0312     for (int n = 0; n < 16; ++n)
0313         std::snprintf(&buf[2 * n], 3, "%02x", (unsigned int)digest16[n]);
0314     buf[32] = '\0' ;
0315     return std::string(buf, buf + 32);
0316 }
0317 
0318 
0319 inline std::string sdigest::Finalize(MD5_CTX& c) // static
0320 {
0321     unsigned char digest[16];
0322     MD5_Final(digest, &c);
0323 
0324     // 16 binary bytes, into 32 char hex string
0325 
0326     char buf[32+1] ;
0327     for (int n = 0; n < 16; ++n)
0328         std::snprintf(&buf[2 * n], 3, "%02x", (unsigned int)digest[n]);
0329     buf[32] = '\0' ;
0330 
0331     return std::string(buf, buf + 32);
0332 }
0333 
0334 inline std::array<unsigned char,16> sdigest::FinalizeRaw(MD5_CTX& c) // static
0335 {
0336     unsigned char digest[16];
0337     MD5_Final(digest, &c);
0338 
0339     std::array<unsigned char, 16> result;
0340     std::copy(digest, digest + 16, result.begin());
0341     return result;
0342 }
0343 
0344 inline void sdigest::FinalizeRaw_(unsigned char* digest_16, MD5_CTX& c ) // static
0345 {
0346     MD5_Final(digest_16, &c );
0347 }
0348 
0349 
0350 
0351 
0352 #if defined(__GNUC__) || defined(__clang__)
0353 #pragma GCC diagnostic pop
0354 #endif
0355