checksum.cpp
上传用户:yhdzpy8989
上传日期:2007-06-13
资源大小:13604k
文件大小:9k
源码类别:

生物技术

开发平台:

C/C++

  1. /*
  2.  * ===========================================================================
  3.  * PRODUCTION $Log: checksum.cpp,v $
  4.  * PRODUCTION Revision 1000.1  2004/06/01 19:39:56  gouriano
  5.  * PRODUCTION PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.11
  6.  * PRODUCTION
  7.  * ===========================================================================
  8.  */
  9. /*  $Id: checksum.cpp,v 1000.1 2004/06/01 19:39:56 gouriano Exp $
  10.  * ===========================================================================
  11.  *
  12.  *                            PUBLIC DOMAIN NOTICE
  13.  *               National Center for Biotechnology Information
  14.  *
  15.  *  This software/database is a "United States Government Work" under the
  16.  *  terms of the United States Copyright Act.  It was written as part of
  17.  *  the author's official duties as a United States Government employee and
  18.  *  thus cannot be copyrighted.  This software/database is freely available
  19.  *  to the public for use. The National Library of Medicine and the U.S.
  20.  *  Government have not placed any restriction on its use or reproduction.
  21.  *
  22.  *  Although all reasonable efforts have been taken to ensure the accuracy
  23.  *  and reliability of the software and data, the NLM and the U.S.
  24.  *  Government do not and cannot warrant the performance or results that
  25.  *  may be obtained by using this software or data. The NLM and the U.S.
  26.  *  Government disclaim all warranties, express or implied, including
  27.  *  warranties of performance, merchantability or fitness for any particular
  28.  *  purpose.
  29.  *
  30.  *  Please cite the author in any work or product based on this material.
  31.  *
  32.  * ===========================================================================
  33.  *
  34.  * Author: Eugene Vasilchenko
  35.  *
  36.  * File Description:  Checksum (CRC32 or MD5) calculation class
  37.  *
  38.  */
  39. #include <ncbi_pch.hpp>
  40. #include <corelib/ncbistd.hpp>
  41. #include <util/checksum.hpp>
  42. BEGIN_NCBI_SCOPE
  43. // sx_Start must begin with "/* O" (see ValidChecksumLine() in checksum.inl)
  44. static const char sx_Start[]     = "/* Original file checksum: ";
  45. static const char sx_End[]       = " */";
  46. static const char sx_LineCount[] = "lines: ";
  47. static const char sx_CharCount[] = "chars: ";
  48. CChecksum::CChecksum(EMethod method)
  49.     : m_LineCount(0), m_CharCount(0), m_Method(method)
  50. {
  51.     switch ( GetMethod() ) {
  52.     case eCRC32:
  53.         InitTables();
  54.         m_Checksum.m_CRC32 = 0;
  55.         break;
  56.     case eMD5:
  57.         m_Checksum.m_MD5 = new CMD5;
  58.         break;
  59.     default:
  60.         break;
  61.     }
  62. }
  63. CChecksum::CChecksum(const CChecksum& cks)
  64.     : m_LineCount(cks.m_LineCount), m_CharCount(cks.m_CharCount),
  65.       m_Method(cks.m_Method)
  66. {
  67.     switch ( GetMethod() ) {
  68.     case eCRC32:
  69.         m_Checksum.m_CRC32 = cks.m_Checksum.m_CRC32;
  70.         break;
  71.     case eMD5:
  72.         m_Checksum.m_MD5 = new CMD5(*cks.m_Checksum.m_MD5);
  73.         break;
  74.     default:
  75.         break;
  76.     }
  77. }
  78. CChecksum::~CChecksum()
  79. {
  80.     x_Free();
  81. }
  82. void CChecksum::x_Free()
  83. {
  84.     switch ( GetMethod() ) {
  85.     case eMD5:
  86.         delete m_Checksum.m_MD5;
  87.         m_Checksum.m_MD5 = 0;
  88.         break;
  89.     default:
  90.         break;
  91.     }
  92. }
  93. CChecksum& CChecksum::operator= (const CChecksum& cks)
  94. {
  95.     x_Free();
  96.     m_LineCount = cks.m_LineCount;
  97.     m_CharCount = cks.m_CharCount;
  98.     m_Method    = cks.m_Method;
  99.     switch ( GetMethod() ) {
  100.     case eCRC32:
  101.         m_Checksum.m_CRC32 = cks.m_Checksum.m_CRC32;
  102.         break;
  103.     case eMD5:        
  104.         m_Checksum.m_MD5 = new CMD5(*cks.m_Checksum.m_MD5);
  105.         break;
  106.     default:
  107.         break;
  108.     }
  109.     return *this;
  110. }
  111. void CChecksum::Reset()
  112. {
  113.     m_LineCount = 0;
  114.     m_CharCount = 0;
  115.     switch ( GetMethod() ) {
  116.     case eCRC32:
  117.         m_Checksum.m_CRC32 = 0;
  118.         break;
  119.     case eMD5:
  120.         delete m_Checksum.m_MD5;
  121.         m_Checksum.m_MD5 = new CMD5();
  122.         break;
  123.     default:
  124.         break;
  125.     }
  126. }
  127. CNcbiOstream& CChecksum::WriteChecksum(CNcbiOstream& out) const
  128. {
  129.     if ( !Valid() ) {
  130.         return out;
  131.     }
  132.     out << sx_Start <<
  133.         sx_LineCount << m_LineCount << ", " <<
  134.         sx_CharCount << m_CharCount << ", ";
  135.     WriteChecksumData(out);
  136.     return out << sx_End << 'n';
  137. }
  138. bool CChecksum::ValidChecksumLineLong(const char* line, size_t length) const
  139. {
  140.     if ( !Valid() ) {
  141.         return false;
  142.     }
  143.     CNcbiOstrstream buffer;
  144.     WriteChecksum(buffer);
  145.     size_t bufferLength = buffer.pcount() - 1; // do not include 'n'
  146.     if ( bufferLength != length ) {
  147.         return false;
  148.     }
  149.     const char* bufferPtr = buffer.str();
  150.     buffer.freeze(false);
  151.     return memcmp(line, bufferPtr, length) == 0;
  152. }
  153. CNcbiOstream& CChecksum::WriteChecksumData(CNcbiOstream& out) const
  154. {
  155.     switch ( GetMethod() ) {
  156.     case eCRC32:
  157.         return out << "CRC32: " << hex << setprecision(8)
  158.                    << m_Checksum.m_CRC32;
  159.     case eMD5:
  160.         return out << "MD5: " << m_Checksum.m_MD5->GetHexSum();
  161.     default:
  162.         return out << "none";
  163.     }
  164. }
  165. void CChecksum::AddChars(const char* str, size_t count)
  166. {
  167.     switch ( GetMethod() ) {
  168.     case eCRC32:
  169.         m_Checksum.m_CRC32 = UpdateCRC32(m_Checksum.m_CRC32, str, count);
  170.         break;
  171.     case eMD5:
  172.         m_Checksum.m_MD5->Update(str, count);
  173.         break;
  174.     default:
  175.         break;
  176.     }
  177.     m_CharCount += count;
  178. }
  179. void CChecksum::NextLine(void)
  180. {
  181.     char eol = 'n';
  182.     switch ( GetMethod() ) {
  183.     case eCRC32:
  184.         m_Checksum.m_CRC32 = UpdateCRC32(m_Checksum.m_CRC32, &eol, 1);
  185.         break;
  186.     case eMD5:
  187.         m_Checksum.m_MD5->Update(&eol, 1);
  188.         break;
  189.     default:
  190.         break;
  191.     }
  192.     ++m_LineCount;
  193. }
  194. //  This code assumes that an unsigned is at least 32 bits wide and
  195. //  that the predefined type char occupies one 8-bit byte of storage.
  196. //  The polynomial used is
  197. //  x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x^1+x^0
  198. #define CRC32_POLYNOM 0x04c11db7
  199. Uint4 CChecksum::sm_CRC32Table[256];
  200. void CChecksum::InitTables(void)
  201. {
  202.     if ( sm_CRC32Table[0] == 0 ) {
  203.         for ( size_t i = 0;  i < 256;  ++i ) {
  204.             Uint4 byteCRC = Uint4(i) << 24;
  205.             for ( int j = 0;  j < 8;  ++j ) {
  206.                 if ( byteCRC & 0x80000000L )
  207.                     byteCRC = (byteCRC << 1) ^ CRC32_POLYNOM;
  208.                 else
  209.                     byteCRC = (byteCRC << 1);
  210.             }
  211.             sm_CRC32Table[i] = byteCRC;
  212.         }
  213.     }
  214. }
  215. Uint4 CChecksum::UpdateCRC32(Uint4 checksum, const char *str, size_t count)
  216. {
  217.     for ( size_t j = 0;  j < count;  ++j ) {
  218.         size_t tableIndex = (int(checksum >> 24) ^ *str++) & 0xff;
  219.         checksum = ((checksum << 8) ^ sm_CRC32Table[tableIndex]) & 0xffffffff;
  220.     }
  221.     return checksum;
  222. }
  223. CChecksum ComputeFileChecksum(const string& path, CChecksum::EMethod method)
  224. {
  225.     CNcbiIfstream input(path.c_str(), IOS_BASE::in | IOS_BASE::binary);
  226.     CChecksum cks(method);
  227.     return ComputeFileChecksum(path, cks);
  228. }
  229. CChecksum& ComputeFileChecksum(const string& path,
  230.                                CChecksum& checksum)
  231. {
  232.     CNcbiIfstream input(path.c_str(), IOS_BASE::in | IOS_BASE::binary);
  233.     if ( !input.is_open() ) {
  234.         return checksum;
  235.     }
  236.     while ( !input.eof() ) {
  237.         char buf[1024*4];
  238.         input.read(buf, sizeof(buf));
  239.         size_t count = input.gcount();
  240.         if ( count ) {
  241.             checksum.AddChars(buf, count);
  242.         }
  243.     }
  244.     input.close();
  245.     return checksum;
  246. }
  247. END_NCBI_SCOPE
  248. /*
  249.  * ===========================================================================
  250.  * $Log: checksum.cpp,v $
  251.  * Revision 1000.1  2004/06/01 19:39:56  gouriano
  252.  * PRODUCTION: UPGRADED [GCC34_MSVC7] Dev-tree R1.11
  253.  *
  254.  * Revision 1.11  2004/05/17 21:06:02  gorelenk
  255.  * Added include of PCH ncbi_pch.hpp
  256.  *
  257.  * Revision 1.10  2003/10/17 20:22:30  kuznets
  258.  * Minor code clean-up.
  259.  * Also increased checksum buffer up to 4K
  260.  * (better performance on Windows and most likely other platforms too)
  261.  *
  262.  * Revision 1.9  2003/10/01 21:15:15  ivanov
  263.  * Get rid of compilation warnings; some formal code rearrangement
  264.  *
  265.  * Revision 1.8  2003/08/11 16:54:20  kuznets
  266.  * Improved Reset() implementation
  267.  *
  268.  * Revision 1.7  2003/08/11 16:47:02  kuznets
  269.  * + Reset() implementation.
  270.  * Fixed memory leak in assignment operator (MD5) mode.
  271.  *
  272.  * Revision 1.6  2003/07/29 21:29:26  ucko
  273.  * Add MD5 support (cribbed from the C Toolkit)
  274.  *
  275.  * Revision 1.5  2003/05/09 14:08:28  ucko
  276.  * ios_base:: -> IOS_BASE:: for gcc 2.9x compatibility
  277.  *
  278.  * Revision 1.4  2003/05/08 19:11:16  kuznets
  279.  * + ComputeFileCRC32
  280.  *
  281.  * Revision 1.3  2001/05/17 15:07:15  lavr
  282.  * Typos corrected
  283.  *
  284.  * Revision 1.2  2001/01/05 20:09:05  vasilche
  285.  * Added util directory for various algorithms and utility classes.
  286.  *
  287.  * Revision 1.1  2000/11/22 16:26:29  vasilche
  288.  * Added generation/checking of checksum to user files.
  289.  *
  290.  * ===========================================================================
  291.  */