use hash instead of checksum to check if content is changed

This commit is contained in:
Daniel Marjamäki 2022-07-07 12:16:01 +02:00
parent 41f6702cc8
commit b888f9cf92
7 changed files with 35 additions and 98 deletions

View File

@ -72,7 +72,7 @@ void AnalyzerInformation::close()
} }
} }
static bool skipAnalysis(const std::string &analyzerInfoFile, unsigned long long checksum, std::list<ErrorMessage> *errors) static bool skipAnalysis(const std::string &analyzerInfoFile, std::size_t hash, std::list<ErrorMessage> *errors)
{ {
tinyxml2::XMLDocument doc; tinyxml2::XMLDocument doc;
const tinyxml2::XMLError error = doc.LoadFile(analyzerInfoFile.c_str()); const tinyxml2::XMLError error = doc.LoadFile(analyzerInfoFile.c_str());
@ -83,8 +83,8 @@ static bool skipAnalysis(const std::string &analyzerInfoFile, unsigned long long
if (rootNode == nullptr) if (rootNode == nullptr)
return false; return false;
const char *attr = rootNode->Attribute("checksum"); const char *attr = rootNode->Attribute("hash");
if (!attr || attr != std::to_string(checksum)) if (!attr || attr != std::to_string(hash))
return false; return false;
for (const tinyxml2::XMLElement *e = rootNode->FirstChildElement(); e; e = e->NextSiblingElement()) { for (const tinyxml2::XMLElement *e = rootNode->FirstChildElement(); e; e = e->NextSiblingElement()) {
@ -125,7 +125,7 @@ std::string AnalyzerInformation::getAnalyzerInfoFile(const std::string &buildDir
return filename; return filename;
} }
bool AnalyzerInformation::analyzeFile(const std::string &buildDir, const std::string &sourcefile, const std::string &cfg, unsigned long long checksum, std::list<ErrorMessage> *errors) bool AnalyzerInformation::analyzeFile(const std::string &buildDir, const std::string &sourcefile, const std::string &cfg, std::size_t hash, std::list<ErrorMessage> *errors)
{ {
if (buildDir.empty() || sourcefile.empty()) if (buildDir.empty() || sourcefile.empty())
return true; return true;
@ -133,13 +133,13 @@ bool AnalyzerInformation::analyzeFile(const std::string &buildDir, const std::st
mAnalyzerInfoFile = AnalyzerInformation::getAnalyzerInfoFile(buildDir,sourcefile,cfg); mAnalyzerInfoFile = AnalyzerInformation::getAnalyzerInfoFile(buildDir,sourcefile,cfg);
if (skipAnalysis(mAnalyzerInfoFile, checksum, errors)) if (skipAnalysis(mAnalyzerInfoFile, hash, errors))
return false; return false;
mOutputStream.open(mAnalyzerInfoFile); mOutputStream.open(mAnalyzerInfoFile);
if (mOutputStream.is_open()) { if (mOutputStream.is_open()) {
mOutputStream << "<?xml version=\"1.0\"?>\n"; mOutputStream << "<?xml version=\"1.0\"?>\n";
mOutputStream << "<analyzerinfo checksum=\"" << checksum << "\">\n"; mOutputStream << "<analyzerinfo hash=\"" << hash << "\">\n";
} else { } else {
mAnalyzerInfoFile.clear(); mAnalyzerInfoFile.clear();
} }

View File

@ -54,7 +54,7 @@ public:
/** Close current TU.analyzerinfo file */ /** Close current TU.analyzerinfo file */
void close(); void close();
bool analyzeFile(const std::string &buildDir, const std::string &sourcefile, const std::string &cfg, unsigned long long checksum, std::list<ErrorMessage> *errors); bool analyzeFile(const std::string &buildDir, const std::string &sourcefile, const std::string &cfg, std::size_t hash, std::list<ErrorMessage> *errors);
void reportErr(const ErrorMessage &msg, bool verbose); void reportErr(const ErrorMessage &msg, bool verbose);
void setFileInfo(const std::string &check, const std::string &fileInfo); void setFileInfo(const std::string &check, const std::string &fileInfo);
static std::string getAnalyzerInfoFile(const std::string &buildDir, const std::string &sourcefile, const std::string &cfg); static std::string getAnalyzerInfoFile(const std::string &buildDir, const std::string &sourcefile, const std::string &cfg);

View File

@ -707,10 +707,10 @@ unsigned int CppCheck::checkFile(const std::string& filename, const std::string
toolinfo << mSettings.userDefines; toolinfo << mSettings.userDefines;
mSettings.nomsg.dump(toolinfo); mSettings.nomsg.dump(toolinfo);
// Calculate checksum so it can be compared with old checksum / future checksums // Calculate hash so it can be compared with old hash / future hashes
const unsigned int checksum = preprocessor.calculateChecksum(tokens1, toolinfo.str()); const std::size_t hash = preprocessor.calculateHash(tokens1, toolinfo.str());
std::list<ErrorMessage> errors; std::list<ErrorMessage> errors;
if (!mAnalyzerInformation.analyzeFile(mSettings.buildDir, filename, cfgname, checksum, &errors)) { if (!mAnalyzerInformation.analyzeFile(mSettings.buildDir, filename, cfgname, hash, &errors)) {
while (!errors.empty()) { while (!errors.empty()) {
reportErr(errors.front()); reportErr(errors.front());
errors.pop_front(); errors.pop_front();
@ -775,7 +775,7 @@ unsigned int CppCheck::checkFile(const std::string& filename, const std::string
} }
} }
std::set<unsigned long long> checksums; std::set<unsigned long long> hashes;
int checkCount = 0; int checkCount = 0;
bool hasValidConfig = false; bool hasValidConfig = false;
std::list<std::string> configurationError; std::list<std::string> configurationError;
@ -871,18 +871,18 @@ unsigned int CppCheck::checkFile(const std::string& filename, const std::string
fdump << "</dump>" << std::endl; fdump << "</dump>" << std::endl;
} }
// Need to call this even if the checksum will skip this configuration // Need to call this even if the hash will skip this configuration
mSettings.nomsg.markUnmatchedInlineSuppressionsAsChecked(tokenizer); mSettings.nomsg.markUnmatchedInlineSuppressionsAsChecked(tokenizer);
// Skip if we already met the same simplified token list // Skip if we already met the same simplified token list
if (mSettings.force || mSettings.maxConfigs > 1) { if (mSettings.force || mSettings.maxConfigs > 1) {
const unsigned long long checksum = tokenizer.list.calculateChecksum(); const std::size_t hash = tokenizer.list.calculateHash();
if (checksums.find(checksum) != checksums.end()) { if (hashes.find(hash) != hashes.end()) {
if (mSettings.debugwarnings) if (mSettings.debugwarnings)
purgedConfigurationMessage(filename, mCurrentConfig); purgedConfigurationMessage(filename, mCurrentConfig);
continue; continue;
} }
checksums.insert(checksum); hashes.insert(hash);
} }
// Check normal tokens // Check normal tokens

View File

@ -30,6 +30,7 @@
#include <algorithm> #include <algorithm>
#include <cstddef> #include <cstddef>
#include <cstdint> #include <cstdint>
#include <functional>
#include <iterator> // back_inserter #include <iterator> // back_inserter
#include <memory> #include <memory>
#include <utility> #include <utility>
@ -971,74 +972,20 @@ void Preprocessor::dump(std::ostream &out) const
} }
} }
static const std::uint32_t crc32Table[] = { std::size_t Preprocessor::calculateHash(const simplecpp::TokenList &tokens1, const std::string &toolinfo) const
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
static void crc32(const std::string &data, uint32_t& crc)
{ {
for (char c : data) { std::string hashData = toolinfo;
crc = crc32Table[(crc ^ (unsigned char)c) & 0xFF] ^ (crc >> 8);
}
}
uint32_t Preprocessor::calculateChecksum(const simplecpp::TokenList &tokens1, const std::string &toolinfo) const
{
std::uint32_t crc = ~0U;
crc32(toolinfo, crc);
for (const simplecpp::Token *tok = tokens1.cfront(); tok; tok = tok->next) { for (const simplecpp::Token *tok = tokens1.cfront(); tok; tok = tok->next) {
if (!tok->comment) if (!tok->comment)
crc32(tok->str(), crc); hashData += tok->str();
} }
for (std::map<std::string, simplecpp::TokenList *>::const_iterator it = mTokenLists.begin(); it != mTokenLists.end(); ++it) { for (std::map<std::string, simplecpp::TokenList *>::const_iterator it = mTokenLists.begin(); it != mTokenLists.end(); ++it) {
for (const simplecpp::Token *tok = it->second->cfront(); tok; tok = tok->next) { for (const simplecpp::Token *tok = it->second->cfront(); tok; tok = tok->next) {
if (!tok->comment) if (!tok->comment)
crc32(tok->str(), crc); hashData += tok->str();
} }
} }
return crc ^ ~0U; return (std::hash<std::string>{})(hashData);
} }
void Preprocessor::simplifyPragmaAsm(simplecpp::TokenList *tokenList) const void Preprocessor::simplifyPragmaAsm(simplecpp::TokenList *tokenList) const

View File

@ -164,13 +164,13 @@ public:
void validateCfgError(const std::string &file, const unsigned int line, const std::string &cfg, const std::string &macro); void validateCfgError(const std::string &file, const unsigned int line, const std::string &cfg, const std::string &macro);
/** /**
* Calculate CRC32 checksum. Using toolinfo, tokens1, filedata. * Calculate HASH. Using toolinfo, tokens1, filedata.
* *
* @param tokens1 Sourcefile tokens * @param tokens1 Sourcefile tokens
* @param toolinfo Arbitrary extra toolinfo * @param toolinfo Arbitrary extra toolinfo
* @return CRC32 checksum * @return HASH
*/ */
uint32_t calculateChecksum(const simplecpp::TokenList &tokens1, const std::string &toolinfo) const; std::size_t calculateHash(const simplecpp::TokenList &tokens1, const std::string &toolinfo) const;
void simplifyPragmaAsm(simplecpp::TokenList *tokenList) const; void simplifyPragmaAsm(simplecpp::TokenList *tokenList) const;

View File

@ -461,27 +461,17 @@ void TokenList::createTokens(simplecpp::TokenList&& tokenList)
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
uint64_t TokenList::calculateChecksum() const std::size_t TokenList::calculateHash() const
{ {
uint64_t checksum = 0; std::string hashData;
for (const Token* tok = front(); tok; tok = tok->next()) { for (const Token* tok = front(); tok; tok = tok->next()) {
const uint32_t subchecksum1 = tok->flags() + tok->varId() + tok->tokType(); hashData += MathLib::toString(tok->flags());
uint32_t subchecksum2 = 0; hashData += MathLib::toString(tok->varId());
for (char i : tok->str()) hashData += MathLib::toString(tok->tokType());
subchecksum2 += (uint32_t)i; hashData += tok->str();
if (!tok->originalName().empty()) { hashData += tok->originalName();
for (char i : tok->originalName())
subchecksum2 += (uint32_t)i;
}
checksum ^= ((static_cast<uint64_t>(subchecksum1) << 32) | subchecksum2);
const bool bit1 = (checksum & 1) != 0;
checksum >>= 1;
if (bit1)
checksum |= (1ULL << 63);
} }
return checksum; return (std::hash<std::string>{})(hashData);
} }

View File

@ -153,10 +153,10 @@ public:
std::string fileLine(const Token *tok) const; std::string fileLine(const Token *tok) const;
/** /**
* Calculates a 64-bit checksum of the token list used to compare * Calculates a hash of the token list used to compare multiple
* multiple token lists with each other as quickly as possible. * token lists with each other as quickly as possible.
*/ */
uint64_t calculateChecksum() const; std::size_t calculateHash() const;
/** /**
* Create abstract syntax tree. * Create abstract syntax tree.