From de99c5d410c942b18b1933d1acb13d6933025a0d Mon Sep 17 00:00:00 2001 From: glank Date: Thu, 19 Jun 2025 14:39:25 +0200 Subject: [PATCH 01/18] optimize paths --- integration_test.py | 20 ++- main.cpp | 3 +- simplecpp.cpp | 391 ++++++++++++++++++-------------------------- simplecpp.h | 94 ++++++++++- test.cpp | 88 +++++----- 5 files changed, 310 insertions(+), 286 deletions(-) diff --git a/integration_test.py b/integration_test.py index 27528e16..a59ae338 100644 --- a/integration_test.py +++ b/integration_test.py @@ -237,7 +237,13 @@ def test_same_name_header(record_property, tmpdir): assert stderr == "" def test_pragma_once_matching(record_property, tmpdir): - if platform.system() == "win32": + test_dir = os.path.join(tmpdir, "test_dir") + test_subdir = os.path.join(test_dir, "test_subdir") + + test_file = os.path.join(test_dir, "test.c") + once_header = os.path.join(test_dir, "once.h") + + if platform.system() == "Windows": names_to_test = [ '"once.h"', '"Once.h"', @@ -251,6 +257,10 @@ def test_pragma_once_matching(record_property, tmpdir): '"test_subdir/../Once.h"', '"Test_Subdir/../once.h"', '"Test_Subdir/../Once.h"', + f"\"{test_dir}/once.h\"", + f"\"{test_dir}/Once.h\"", + f"<{test_dir}/once.h>", + f"<{test_dir}/Once.h>", ] else: names_to_test = [ @@ -258,14 +268,10 @@ def test_pragma_once_matching(record_property, tmpdir): '', '"../test_dir/once.h"', '"test_subdir/../once.h"', + f"\"{test_dir}/once.h\"", + f"<{test_dir}/once.h>", ] - test_dir = os.path.join(tmpdir, "test_dir") - test_subdir = os.path.join(test_dir, "test_subdir") - - test_file = os.path.join(test_dir, "test.c") - once_header = os.path.join(test_dir, "once.h") - os.mkdir(test_dir) os.mkdir(test_subdir) diff --git a/main.cpp b/main.cpp index 424ef6fa..a6d14386 100644 --- a/main.cpp +++ b/main.cpp @@ -9,7 +9,6 @@ #include #include #include -#include #include #include @@ -128,7 +127,7 @@ int main(int argc, char **argv) } rawtokens->removeComments(); simplecpp::TokenList outputTokens(files); - std::map filedata; + simplecpp::FileDataCache filedata; simplecpp::preprocess(outputTokens, *rawtokens, files, filedata, dui, &outputList); simplecpp::cleanup(filedata); delete rawtokens; diff --git a/simplecpp.cpp b/simplecpp.cpp index 599ffdfe..05c99ba6 100755 --- a/simplecpp.cpp +++ b/simplecpp.cpp @@ -49,6 +49,8 @@ #ifdef SIMPLECPP_WINDOWS #include #undef ERROR +#else +#include #endif #if __cplusplus >= 201103L @@ -2422,127 +2424,6 @@ class MyLock { }; #endif -class RealFileNameMap { -public: - RealFileNameMap() {} - - bool getCacheEntry(const std::string& path, std::string& returnPath) { - MyLock lock(m_mutex); - - const std::map::iterator it = m_fileMap.find(path); - if (it != m_fileMap.end()) { - returnPath = it->second; - return true; - } - return false; - } - - void addToCache(const std::string& path, const std::string& actualPath) { - MyLock lock(m_mutex); - m_fileMap[path] = actualPath; - } - -private: - std::map m_fileMap; - MyMutex m_mutex; -}; - -static RealFileNameMap realFileNameMap; - -static bool realFileName(const std::string &f, std::string &result) -{ - // are there alpha characters in last subpath? - bool alpha = false; - for (std::string::size_type pos = 1; pos <= f.size(); ++pos) { - const unsigned char c = f[f.size() - pos]; - if (c == '/' || c == '\\') - break; - if (std::isalpha(c)) { - alpha = true; - break; - } - } - - // do not convert this path if there are no alpha characters (either pointless or cause wrong results for . and ..) - if (!alpha) - return false; - - // Lookup filename or foldername on file system - if (!realFileNameMap.getCacheEntry(f, result)) { - - WIN32_FIND_DATAA FindFileData; - -#ifdef __CYGWIN__ - const std::string fConverted = simplecpp::convertCygwinToWindowsPath(f); - const HANDLE hFind = FindFirstFileExA(fConverted.c_str(), FindExInfoBasic, &FindFileData, FindExSearchNameMatch, NULL, 0); -#else - HANDLE hFind = FindFirstFileExA(f.c_str(), FindExInfoBasic, &FindFileData, FindExSearchNameMatch, NULL, 0); -#endif - - if (INVALID_HANDLE_VALUE == hFind) - return false; - result = FindFileData.cFileName; - realFileNameMap.addToCache(f, result); - FindClose(hFind); - } - return true; -} - -static RealFileNameMap realFilePathMap; - -/** Change case in given path to match filesystem */ -static std::string realFilename(const std::string &f) -{ - std::string ret; - ret.reserve(f.size()); // this will be the final size - if (realFilePathMap.getCacheEntry(f, ret)) - return ret; - - // Current subpath - std::string subpath; - - for (std::string::size_type pos = 0; pos < f.size(); ++pos) { - const unsigned char c = f[pos]; - - // Separator.. add subpath and separator - if (c == '/' || c == '\\') { - // if subpath is empty just add separator - if (subpath.empty()) { - ret += c; - continue; - } - - const bool isDriveSpecification = - (pos == 2 && subpath.size() == 2 && std::isalpha(subpath[0]) && subpath[1] == ':'); - - // Append real filename (proper case) - std::string f2; - if (!isDriveSpecification && realFileName(f.substr(0, pos), f2)) - ret += f2; - else - ret += subpath; - - subpath.clear(); - - // Append separator - ret += c; - } else { - subpath += c; - } - } - - if (!subpath.empty()) { - std::string f2; - if (realFileName(f,f2)) - ret += f2; - else - ret += subpath; - } - - realFilePathMap.addToCache(f, ret); - return ret; -} - static bool isAbsolutePath(const std::string &path) { if (path.length() >= 3 && path[0] > 0 && std::isalpha(path[0]) && path[1] == ':' && (path[2] == '\\' || path[2] == '/')) @@ -2550,7 +2431,6 @@ static bool isAbsolutePath(const std::string &path) return path.length() > 1U && (path[0] == '/' || path[0] == '\\'); } #else -#define realFilename(f) f static bool isAbsolutePath(const std::string &path) { @@ -2629,8 +2509,7 @@ namespace simplecpp { if (unc) path = '/' + path; - // cppcheck-suppress duplicateExpressionTernary - platform-dependent implementation - return strpbrk(path.c_str(), "*?") == nullptr ? realFilename(path) : path; + return path; } } @@ -2801,10 +2680,8 @@ static void simplifyHasInclude(simplecpp::TokenList &expr, const simplecpp::DUI for (simplecpp::Token *headerToken = tok1->next; headerToken != tok3; headerToken = headerToken->next) header += headerToken->str(); - // cppcheck-suppress selfAssignment - platform-dependent implementation - header = realFilename(header); } else { - header = realFilename(tok1->str().substr(1U, tok1->str().size() - 2U)); + header = tok1->str().substr(1U, tok1->str().size() - 2U); } std::ifstream f; const std::string header2 = openHeader(f,dui,sourcefile,header,systemheader); @@ -3239,101 +3116,179 @@ static std::string openHeader(std::ifstream &f, const simplecpp::DUI &dui, const return openHeaderIncludePath(f, dui, header); } -static std::string findPathInMapBothRelativeAndAbsolute(const std::map &filedata, const std::string& path) { - // here there are two possibilities - either we match this from absolute path or from a relative one - if (filedata.find(path) != filedata.end()) {// try first to respect the exact match - return path; - } +simplecpp::TokenList *simplecpp::FileDataCache::get(const std::string &sourcefile, const std::string &header, std::string *header2, const simplecpp::DUI &dui, bool systemheader) +{ + if (mDataMap.empty()) + return nullptr; - // otherwise - try to use the normalize to the correct representation - std::string alternativePath; - if (isAbsolutePath(path)) { - alternativePath = extractRelativePathFromAbsolute(simplecpp::simplifyPath(path)); - } else { - alternativePath = toAbsolutePath(path); - } + if (isAbsolutePath(header)) { + std::string path = simplecpp::simplifyPath(header); + const auto data = mDataMap.find(path); - if (filedata.find(alternativePath) != filedata.end()) { - return alternativePath; - } - return ""; -} + if (data != mDataMap.end()) { + if (header2 != nullptr) { + const auto uniquePath = mAliasMap.find(path); -static std::string getFileIdPath(const std::map &filedata, const std::string &sourcefile, const std::string &header, const simplecpp::DUI &dui, bool systemheader) -{ - if (filedata.empty()) { - return ""; - } - if (isAbsolutePath(header)) { - const std::string simplifiedHeaderPath = simplecpp::simplifyPath(header); - const std::string match = findPathInMapBothRelativeAndAbsolute(filedata, simplifiedHeaderPath); - if (!match.empty()) { - return match; + if (uniquePath != mAliasMap.end()) + *header2 = uniquePath->second; + else + *header2 = std::move(path); + } + + return data->second.get(); } } if (!systemheader) { - const std::string relativeFilename = getRelativeFileName(sourcefile, header, true); - const std::string match = findPathInMapBothRelativeAndAbsolute(filedata, relativeFilename); - if (!match.empty()) { - return match; + std::string path = getRelativeFileName(sourcefile, header, true); + const auto data = mDataMap.find(path); + + if (data != mDataMap.end()) { + if (header2 != nullptr) { + const auto uniquePath = mAliasMap.find(path); + + if (uniquePath != mAliasMap.end()) + *header2 = uniquePath->second; + else + *header2 = std::move(path); + } + + return data->second.get(); } - // if the file exists but hasn't been loaded yet then we need to stop searching here or we could get a false match + + // If the file exists but hasn't been loaded yet then we need to stop searching here or we could get a false match std::ifstream f; - openHeader(f, relativeFilename); - if (f.is_open()) { - f.close(); - return ""; - } - } else if (filedata.find(header) != filedata.end()) { - return header;// system header that its file is already in the filedata - return that as is + openHeader(f, path); + if (f.is_open()) + return nullptr; } for (std::list::const_iterator it = dui.includePaths.begin(); it != dui.includePaths.end(); ++it) { - const std::string match = findPathInMapBothRelativeAndAbsolute(filedata, getIncludePathFileName(*it, header)); - if (!match.empty()) { - return match; + std::string path = getIncludePathFileName(*it, header); + const auto data = mDataMap.find(path); + + if (data != mDataMap.end()) { + if (header2 != nullptr) { + const auto uniquePath = mAliasMap.find(path); + + if (uniquePath != mAliasMap.end()) + *header2 = uniquePath->second; + else + *header2 = std::move(path); + } + + return data->second.get(); } } - return ""; + return nullptr; } -static bool hasFile(const std::map &filedata, const std::string &sourcefile, const std::string &header, const simplecpp::DUI &dui, bool systemheader) +simplecpp::TokenList *simplecpp::FileDataCache::load(const std::string &sourcefile, const std::string &header, std::string *header2, const simplecpp::DUI &dui, bool systemheader, std::vector &filenames, simplecpp::OutputList *outputList) { - return !getFileIdPath(filedata, sourcefile, header, dui, systemheader).empty(); + std::ifstream f; + std::string path = openHeader(f, dui, sourcefile, header, systemheader); + + if (path.empty()) + return nullptr; + + FileID fileId; + + if (!getFileId(path, fileId)) + return nullptr; + + const auto id = mIdMap.find(fileId); + if (id != mIdMap.end()) { + const auto &data = mDataMap.at(id->second); + + mAliasMap.insert(std::make_pair(path, id->second)); + mDataMap.insert(std::make_pair(path, data)); + + if (header2 != nullptr) + *header2 = id->second; + + return data.get(); + } + else { + auto data = std::make_shared(f, filenames, path, outputList); + simplecpp::TokenList *const tokens = data.get(); + + if (dui.removeComments) + tokens->removeComments(); + + mIdMap.insert(std::make_pair(fileId, path)); + mDataMap.insert(std::make_pair(path, std::move(data))); + + if (header2 != nullptr) + *header2 = std::move(path); + + return tokens; + } } -static void safeInsertTokenListToMap(std::map &filedata, const std::string &header2, simplecpp::TokenList *tokens, const std::string &header, const std::string &sourcefile, bool systemheader, const char* contextDesc) +simplecpp::TokenList *simplecpp::FileDataCache::get_or_load(const std::string &sourcefile, const std::string &header, std::string *header2, const simplecpp::DUI &dui, bool systemheader, std::vector &filenames, simplecpp::OutputList *outputList) { - const bool inserted = filedata.insert(std::make_pair(header2, tokens)).second; - if (!inserted) { - std::cerr << "error in " << contextDesc << " - attempt to add a tokenized file to the file map, but this file is already in the map! Details:" << - "header: " << header << " header2: " << header2 << " source: " << sourcefile << " systemheader: " << systemheader << std::endl; - std::abort(); - } + simplecpp::TokenList *tokens = get(sourcefile, header, header2, dui, systemheader); + + if (tokens == nullptr) + tokens = load(sourcefile, header, header2, dui, systemheader, filenames, outputList); + + return tokens; +} + +bool simplecpp::FileDataCache::getFileId(const std::string &path, FileID &id) +{ +#ifdef SIMPLECPP_WINDOWS + HANDLE hFile = CreateFileA(path.c_str(), 0, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + + if (hFile == INVALID_HANDLE_VALUE) + return false; + + const BOOL ret = GetFileInformationByHandleEx(hFile, FileIdInfo, &id.fileIdInfo, sizeof(id.fileIdInfo)); + + CloseHandle(hFile); + + return ret == TRUE; +#else + struct stat statbuf; + + if (stat(path.c_str(), &statbuf) != 0) + return false; + + id.dev = statbuf.st_dev; + id.ino = statbuf.st_ino; + + return true; +#endif } -std::map simplecpp::load(const simplecpp::TokenList &rawtokens, std::vector &filenames, const simplecpp::DUI &dui, simplecpp::OutputList *outputList) +bool simplecpp::FileDataCache::FileID::operator< (const FileID &that) const +{ +#ifdef SIMPLECPP_WINDOWS + return std::memcmp(&fileIdInfo, &that.fileIdInfo, sizeof(fileIdInfo)) < 0; +#else + return dev < that.dev || (dev == that.dev && ino < that.ino); +#endif +} + +simplecpp::FileDataCache simplecpp::load(const simplecpp::TokenList &rawtokens, std::vector &filenames, const simplecpp::DUI &dui, simplecpp::OutputList *outputList) { #ifdef SIMPLECPP_WINDOWS if (dui.clearIncludeCache) nonExistingFilesCache.clear(); #endif - std::map ret; + FileDataCache filedata; std::list filelist; // -include files for (std::list::const_iterator it = dui.includes.begin(); it != dui.includes.end(); ++it) { - const std::string &filename = realFilename(*it); + const std::string &filename = *it; - if (ret.find(filename) != ret.end()) - continue; + TokenList *tokenlist = filedata.get_or_load("", filename, nullptr, dui, false, filenames, outputList); - std::ifstream fin(filename.c_str()); - if (!fin.is_open()) { + if (tokenlist == nullptr) { if (outputList) { simplecpp::Output err(filenames); err.type = simplecpp::Output::EXPLICIT_INCLUDE_NOT_FOUND; @@ -3343,17 +3298,14 @@ std::map simplecpp::load(const simplecpp::To } continue; } - fin.close(); - TokenList *tokenlist = new TokenList(filename, filenames, outputList); if (!tokenlist->front()) { - delete tokenlist; continue; } if (dui.removeComments) tokenlist->removeComments(); - ret[filename] = tokenlist; + filelist.push_back(tokenlist->front()); } @@ -3377,25 +3329,20 @@ std::map simplecpp::load(const simplecpp::To continue; const bool systemheader = (htok->str()[0] == '<'); - const std::string header(realFilename(htok->str().substr(1U, htok->str().size() - 2U))); - if (hasFile(ret, sourcefile, header, dui, systemheader)) - continue; + const std::string header(htok->str().substr(1U, htok->str().size() - 2U)); - std::ifstream f; - const std::string header2 = openHeader(f,dui,sourcefile,header,systemheader); - if (!f.is_open()) + TokenList *tokenlist = filedata.get_or_load(sourcefile, header, nullptr, dui, systemheader, filenames, outputList); + if (!tokenlist) continue; - f.close(); - TokenList *tokens = new TokenList(header2, filenames, outputList); if (dui.removeComments) - tokens->removeComments(); - safeInsertTokenListToMap(ret, header2, tokens, header, rawtok->location.file(), systemheader, "simplecpp::load"); - if (tokens->front()) - filelist.push_back(tokens->front()); + tokenlist->removeComments(); + + if (tokenlist->front()) + filelist.push_back(tokenlist->front()); } - return ret; + return filedata; } static bool preprocessToken(simplecpp::TokenList &output, const simplecpp::Token **tok1, simplecpp::MacroMap ¯os, std::vector &files, simplecpp::OutputList *outputList) @@ -3451,7 +3398,7 @@ static std::string getTimeDefine(const struct tm *timep) return std::string("\"").append(buf).append("\""); } -void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenList &rawtokens, std::vector &files, std::map &filedata, const simplecpp::DUI &dui, simplecpp::OutputList *outputList, std::list *macroUsage, std::list *ifCond) +void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenList &rawtokens, std::vector &files, simplecpp::FileDataCache &filedata, const simplecpp::DUI &dui, simplecpp::OutputList *outputList, std::list *macroUsage, std::list *ifCond) { #ifdef SIMPLECPP_WINDOWS if (dui.clearIncludeCache) @@ -3543,9 +3490,9 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL includetokenstack.push(rawtokens.cfront()); for (std::list::const_iterator it = dui.includes.begin(); it != dui.includes.end(); ++it) { - const std::map::const_iterator f = filedata.find(*it); - if (f != filedata.end()) - includetokenstack.push(f->second->cfront()); + const TokenList *const includetokens = filedata.get_or_load("", *it, nullptr, dui, false, files, outputList); + if (includetokens != nullptr) + includetokenstack.push(includetokens->cfront()); } std::map > maybeUsedMacros; @@ -3666,21 +3613,10 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL const Token * const inctok = inc2.cfront(); const bool systemheader = (inctok->str()[0] == '<'); - const std::string header(realFilename(inctok->str().substr(1U, inctok->str().size() - 2U))); - std::string header2 = getFileIdPath(filedata, rawtok->location.file(), header, dui, systemheader); - if (header2.empty()) { - // try to load file.. - std::ifstream f; - header2 = openHeader(f, dui, rawtok->location.file(), header, systemheader); - if (f.is_open()) { - f.close(); - TokenList * const tokens = new TokenList(header2, files, outputList); - if (dui.removeComments) - tokens->removeComments(); - safeInsertTokenListToMap(filedata, header2, tokens, header, rawtok->location.file(), systemheader, "simplecpp::preprocess"); - } - } - if (header2.empty()) { + const std::string header(inctok->str().substr(1U, inctok->str().size() - 2U)); + std::string header2; + const TokenList *const includetokens = filedata.get_or_load(rawtok->location.file(), header, &header2, dui, systemheader, files, outputList); + if (includetokens == nullptr) { if (outputList) { simplecpp::Output out(files); out.type = Output::MISSING_HEADER; @@ -3698,7 +3634,6 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL } } else if (pragmaOnce.find(header2) == pragmaOnce.end()) { includetokenstack.push(gotoNextLine(rawtok)); - const TokenList * const includetokens = filedata.find(header2)->second; rawtok = includetokens ? includetokens->cfront() : nullptr; continue; } @@ -3776,12 +3711,10 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL if (systemheader) { while ((tok = tok->next) && tok->op != '>') header += tok->str(); - // cppcheck-suppress selfAssignment - platform-dependent implementation - header = realFilename(header); if (tok && tok->op == '>') closingAngularBracket = true; } else { - header = realFilename(tok->str().substr(1U, tok->str().size() - 2U)); + header = tok->str().substr(1U, tok->str().size() - 2U); closingAngularBracket = true; } std::ifstream f; @@ -3929,11 +3862,9 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL } } -void simplecpp::cleanup(std::map &filedata) +void simplecpp::cleanup(FileDataCache &filedata) { - for (std::map::iterator it = filedata.begin(); it != filedata.end(); ++it) - delete it->second; - filedata.clear(); + (void) filedata; } simplecpp::cstd_t simplecpp::getCStd(const std::string &std) diff --git a/simplecpp.h b/simplecpp.h index f5c69593..31cce632 100755 --- a/simplecpp.h +++ b/simplecpp.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -27,6 +28,10 @@ # define SIMPLECPP_LIB #endif +#ifndef _WIN32 +# include +#endif + #if (__cplusplus < 201103L) && !defined(__APPLE__) #define nullptr NULL #endif @@ -47,6 +52,7 @@ namespace simplecpp { typedef std::string TokenString; class Macro; + class FileDataCache; /** * Location in source code @@ -349,7 +355,7 @@ namespace simplecpp { SIMPLECPP_LIB long long characterLiteralToLL(const std::string& str); - SIMPLECPP_LIB std::map load(const TokenList &rawtokens, std::vector &filenames, const DUI &dui, OutputList *outputList = nullptr); + SIMPLECPP_LIB FileDataCache load(const TokenList &rawtokens, std::vector &filenames, const DUI &dui, OutputList *outputList = nullptr); /** * Preprocess @@ -363,12 +369,12 @@ namespace simplecpp { * @param macroUsage output: macro usage * @param ifCond output: #if/#elif expressions */ - SIMPLECPP_LIB void preprocess(TokenList &output, const TokenList &rawtokens, std::vector &files, std::map &filedata, const DUI &dui, OutputList *outputList = nullptr, std::list *macroUsage = nullptr, std::list *ifCond = nullptr); + SIMPLECPP_LIB void preprocess(TokenList &output, const TokenList &rawtokens, std::vector &files, FileDataCache &filedata, const DUI &dui, OutputList *outputList = nullptr, std::list *macroUsage = nullptr, std::list *ifCond = nullptr); /** * Deallocate data */ - SIMPLECPP_LIB void cleanup(std::map &filedata); + SIMPLECPP_LIB void cleanup(FileDataCache &filedata); /** Simplify path */ SIMPLECPP_LIB std::string simplifyPath(std::string path); @@ -389,6 +395,88 @@ namespace simplecpp { /** Returns the __cplusplus value for a given standard */ SIMPLECPP_LIB std::string getCppStdString(const std::string &std); SIMPLECPP_LIB std::string getCppStdString(cppstd_t std); + + class SIMPLECPP_LIB FileDataCache + { + public: + FileDataCache() {} + + TokenList *get(const std::string &sourcefile, const std::string &header, std::string *header2, const DUI &dui, bool systemheader); + + TokenList *load(const std::string &sourcefile, const std::string &header, std::string *header2, const DUI &dui, bool systemheader, std::vector &filenames, OutputList *outputList); + + TokenList *get_or_load(const std::string &sourcefile, const std::string &header, std::string *header2, const DUI &dui, bool systemheader, std::vector &filenames, OutputList *outputList); + + void insert(const std::string &path, const TokenList &tokens) + { + mDataMap.insert(std::make_pair(path, std::make_shared(tokens))); + } + + typedef std::map>::iterator iterator; + typedef std::map>::const_iterator const_iterator; + typedef std::map>::size_type size_type; + + size_type size() const + { + return mDataMap.size(); + } + + iterator begin() + { + return mDataMap.begin(); + } + + iterator end() + { + return mDataMap.end(); + } + + const_iterator begin() const + { + return mDataMap.begin(); + } + + const_iterator end() const + { + return mDataMap.end(); + } + + const_iterator cbegin() const + { + return mDataMap.cbegin(); + } + + const_iterator cend() const + { + return mDataMap.cend(); + } + + private: + struct FileID + { + bool operator< (const FileID &that) const; + +#ifdef SIMPLECPP_WINDOWS + struct + { + uint64_t VolumeSerialNumber; + struct + { + uint8_t Identifier[16]; + } FileId; + } fileIdInfo; +#else + dev_t dev; + ino_t ino; +#endif + }; + + static bool getFileId(const std::string &path, FileID &id); + + std::map> mDataMap; + std::map mIdMap; + std::map mAliasMap; + }; } #if defined(_MSC_VER) diff --git a/test.cpp b/test.cpp index cec253b8..c23f9108 100644 --- a/test.cpp +++ b/test.cpp @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include @@ -100,13 +99,12 @@ static std::string readfile(const char code[], std::size_t size, simplecpp::Outp static std::string preprocess(const char code[], const simplecpp::DUI &dui, simplecpp::OutputList *outputList) { std::vector files; - std::map filedata; + simplecpp::FileDataCache filedata; simplecpp::TokenList tokens = makeTokenList(code,files); tokens.removeComments(); simplecpp::TokenList tokens2(files); simplecpp::preprocess(tokens2, tokens, files, filedata, dui, outputList); - for (auto &i : filedata) - delete i.second; + simplecpp::cleanup(filedata); return tokens2.stringify(); } @@ -1038,7 +1036,7 @@ static void error4() // "#error x\n1" const char code[] = "\xFE\xFF\x00\x23\x00\x65\x00\x72\x00\x72\x00\x6f\x00\x72\x00\x20\x00\x78\x00\x0a\x00\x31"; std::vector files; - std::map filedata; + simplecpp::FileDataCache filedata; simplecpp::OutputList outputList; simplecpp::TokenList tokens2(files); const simplecpp::TokenList rawtoken = makeTokenList(code, sizeof(code),files,"test.c"); @@ -1051,7 +1049,7 @@ static void error5() // "#error x\n1" const char code[] = "\xFF\xFE\x23\x00\x65\x00\x72\x00\x72\x00\x6f\x00\x72\x00\x20\x00\x78\x00\x0a\x00\x78\x00\x31\x00"; std::vector files; - std::map filedata; + simplecpp::FileDataCache filedata; simplecpp::OutputList outputList; simplecpp::TokenList tokens2(files); const simplecpp::TokenList rawtokens = makeTokenList(code, sizeof(code),files,"test.c"); @@ -1896,8 +1894,8 @@ static void missingHeader2() { const char code[] = "#include \"foo.h\"\n"; // this file exists std::vector files; - std::map filedata; - filedata["foo.h"] = nullptr; + simplecpp::FileDataCache filedata; + filedata.insert("foo.h", simplecpp::TokenList(files)); simplecpp::OutputList outputList; simplecpp::TokenList tokens2(files); const simplecpp::TokenList rawtokens = makeTokenList(code,files); @@ -1926,8 +1924,8 @@ static void nestedInclude() const char code[] = "#include \"test.h\"\n"; std::vector files; simplecpp::TokenList rawtokens = makeTokenList(code,files,"test.h"); - std::map filedata; - filedata["test.h"] = &rawtokens; + simplecpp::FileDataCache filedata; + filedata.insert("test.h", rawtokens); simplecpp::OutputList outputList; simplecpp::TokenList tokens2(files); @@ -1941,13 +1939,15 @@ static void systemInclude() const char code[] = "#include \n"; std::vector files; simplecpp::TokenList rawtokens = makeTokenList(code,files,"local/limits.h"); - std::map filedata; - filedata["limits.h"] = nullptr; - filedata["local/limits.h"] = &rawtokens; + simplecpp::FileDataCache filedata; + filedata.insert("include/limits.h", simplecpp::TokenList(files)); + filedata.insert("local/limits.h", rawtokens); simplecpp::OutputList outputList; simplecpp::TokenList tokens2(files); - simplecpp::preprocess(tokens2, rawtokens, files, filedata, simplecpp::DUI(), &outputList); + simplecpp::DUI dui; + dui.includePaths.push_back("include"); + simplecpp::preprocess(tokens2, rawtokens, files, filedata, dui, &outputList); ASSERT_EQUALS("", toString(outputList)); } @@ -1969,7 +1969,7 @@ static void multiline2() simplecpp::TokenList rawtokens = makeTokenList(code,files); ASSERT_EQUALS("# define A /**/ 1\n\nA", rawtokens.stringify()); rawtokens.removeComments(); - std::map filedata; + simplecpp::FileDataCache filedata; simplecpp::TokenList tokens2(files); simplecpp::preprocess(tokens2, rawtokens, files, filedata, simplecpp::DUI()); ASSERT_EQUALS("\n\n1", tokens2.stringify()); @@ -1984,7 +1984,7 @@ static void multiline3() // #28 - macro with multiline comment simplecpp::TokenList rawtokens = makeTokenList(code,files); ASSERT_EQUALS("# define A /* */ 1\n\nA", rawtokens.stringify()); rawtokens.removeComments(); - std::map filedata; + simplecpp::FileDataCache filedata; simplecpp::TokenList tokens2(files); simplecpp::preprocess(tokens2, rawtokens, files, filedata, simplecpp::DUI()); ASSERT_EQUALS("\n\n1", tokens2.stringify()); @@ -2000,7 +2000,7 @@ static void multiline4() // #28 - macro with multiline comment simplecpp::TokenList rawtokens = makeTokenList(code,files); ASSERT_EQUALS("# define A /* */ 1\n\n\nA", rawtokens.stringify()); rawtokens.removeComments(); - std::map filedata; + simplecpp::FileDataCache filedata; simplecpp::TokenList tokens2(files); simplecpp::preprocess(tokens2, rawtokens, files, filedata, simplecpp::DUI()); ASSERT_EQUALS("\n\n\n1", tokens2.stringify()); @@ -2123,9 +2123,9 @@ static void include3() // #16 - crash when expanding macro from header ASSERT_EQUALS("A.c", files[0]); ASSERT_EQUALS("A.h", files[1]); - std::map filedata; - filedata["A.c"] = &rawtokens_c; - filedata["A.h"] = &rawtokens_h; + simplecpp::FileDataCache filedata; + filedata.insert("A.c", rawtokens_c); + filedata.insert("A.h", rawtokens_h); simplecpp::TokenList out(files); simplecpp::preprocess(out, rawtokens_c, files, filedata, simplecpp::DUI()); @@ -2148,9 +2148,9 @@ static void include4() // #27 - -include ASSERT_EQUALS("27.c", files[0]); ASSERT_EQUALS("27.h", files[1]); - std::map filedata; - filedata["27.c"] = &rawtokens_c; - filedata["27.h"] = &rawtokens_h; + simplecpp::FileDataCache filedata; + filedata.insert("27.c", rawtokens_c); + filedata.insert("27.h", rawtokens_h); simplecpp::TokenList out(files); simplecpp::DUI dui; @@ -2174,9 +2174,9 @@ static void include5() // #3 - handle #include MACRO ASSERT_EQUALS("3.c", files[0]); ASSERT_EQUALS("3.h", files[1]); - std::map filedata; - filedata["3.c"] = &rawtokens_c; - filedata["3.h"] = &rawtokens_h; + simplecpp::FileDataCache filedata; + filedata.insert("3.c", rawtokens_c); + filedata.insert("3.h", rawtokens_h); simplecpp::TokenList out(files); simplecpp::preprocess(out, rawtokens_c, files, filedata, simplecpp::DUI()); @@ -2195,8 +2195,8 @@ static void include6() // #57 - incomplete macro #include MACRO(,) ASSERT_EQUALS(1U, files.size()); ASSERT_EQUALS("57.c", files[0]); - std::map filedata; - filedata["57.c"] = &rawtokens; + simplecpp::FileDataCache filedata; + filedata.insert("57.c", rawtokens); simplecpp::TokenList out(files); simplecpp::preprocess(out, rawtokens, files, filedata, simplecpp::DUI()); @@ -2218,9 +2218,9 @@ static void include7() // #include MACRO ASSERT_EQUALS("3.c", files[0]); ASSERT_EQUALS("3.h", files[1]); - std::map filedata; - filedata["3.c"] = &rawtokens_c; - filedata["3.h"] = &rawtokens_h; + simplecpp::FileDataCache filedata; + filedata.insert("3.c", rawtokens_c); + filedata.insert("3.h", rawtokens_h); simplecpp::TokenList out(files); simplecpp::DUI dui; @@ -2256,9 +2256,9 @@ static void include9() ASSERT_EQUALS("1.c", files[0]); ASSERT_EQUALS("1.h", files[1]); - std::map filedata; - filedata["1.c"] = &rawtokens_c; - filedata["1.h"] = &rawtokens_h; + simplecpp::FileDataCache filedata; + filedata.insert("1.c", rawtokens_c); + filedata.insert("1.h", rawtokens_h); simplecpp::TokenList out(files); simplecpp::DUI dui; @@ -2438,9 +2438,9 @@ static void stringify1() ASSERT_EQUALS("A.c", files[0]); ASSERT_EQUALS("A.h", files[1]); - std::map filedata; - filedata["A.c"] = &rawtokens_c; - filedata["A.h"] = &rawtokens_h; + simplecpp::FileDataCache filedata; + filedata.insert("A.c", rawtokens_c); + filedata.insert("A.h", rawtokens_h); simplecpp::TokenList out(files); simplecpp::preprocess(out, rawtokens_c, files, filedata, simplecpp::DUI()); @@ -2453,7 +2453,7 @@ static void tokenMacro1() const char code[] = "#define A 123\n" "A"; std::vector files; - std::map filedata; + simplecpp::FileDataCache filedata; simplecpp::TokenList tokenList(files); const simplecpp::TokenList rawtokens = makeTokenList(code,files); simplecpp::preprocess(tokenList, rawtokens, files, filedata, simplecpp::DUI()); @@ -2465,7 +2465,7 @@ static void tokenMacro2() const char code[] = "#define ADD(X,Y) X+Y\n" "ADD(1,2)"; std::vector files; - std::map filedata; + simplecpp::FileDataCache filedata; simplecpp::TokenList tokenList(files); const simplecpp::TokenList rawtokens = makeTokenList(code,files); simplecpp::preprocess(tokenList, rawtokens, files, filedata, simplecpp::DUI()); @@ -2486,7 +2486,7 @@ static void tokenMacro3() "#define FRED 1\n" "ADD(FRED,2)"; std::vector files; - std::map filedata; + simplecpp::FileDataCache filedata; simplecpp::TokenList tokenList(files); const simplecpp::TokenList rawtokens = makeTokenList(code,files); simplecpp::preprocess(tokenList, rawtokens, files, filedata, simplecpp::DUI()); @@ -2507,7 +2507,7 @@ static void tokenMacro4() "#define B 1\n" "A"; std::vector files; - std::map filedata; + simplecpp::FileDataCache filedata; simplecpp::TokenList tokenList(files); const simplecpp::TokenList rawtokens = makeTokenList(code,files); simplecpp::preprocess(tokenList, rawtokens, files, filedata, simplecpp::DUI()); @@ -2522,7 +2522,7 @@ static void tokenMacro5() "#define SET_BPF_JUMP(code) SET_BPF(D | code)\n" "SET_BPF_JUMP(A | B | C);"; std::vector files; - std::map filedata; + simplecpp::FileDataCache filedata; simplecpp::TokenList tokenList(files); const simplecpp::TokenList rawtokens = makeTokenList(code,files); simplecpp::preprocess(tokenList, rawtokens, files, filedata, simplecpp::DUI()); @@ -2959,7 +2959,7 @@ static void preprocess_files() ASSERT_EQUALS(1, files.size()); ASSERT_EQUALS("", *files.cbegin()); - std::map filedata; + simplecpp::FileDataCache filedata; simplecpp::preprocess(tokens2, tokens, files, filedata, simplecpp::DUI(), nullptr); ASSERT_EQUALS(1, files.size()); ASSERT_EQUALS("", *files.cbegin()); @@ -2976,7 +2976,7 @@ static void preprocess_files() ASSERT_EQUALS(1, files.size()); ASSERT_EQUALS("test.cpp", *files.cbegin()); - std::map filedata; + simplecpp::FileDataCache filedata; simplecpp::preprocess(tokens2, tokens, files, filedata, simplecpp::DUI(), nullptr); ASSERT_EQUALS(1, files.size()); ASSERT_EQUALS("test.cpp", *files.cbegin()); From a3300df9b1312561818cb1cc1c418cdb9c42b46d Mon Sep 17 00:00:00 2001 From: glank Date: Fri, 27 Jun 2025 15:52:27 +0200 Subject: [PATCH 02/18] Cleanup and fixes --- simplecpp.cpp | 195 +++++++++++++++++++++----------------------------- simplecpp.h | 116 ++++++++++++++++-------------- test.cpp | 139 ++++++++++++++++++----------------- 3 files changed, 221 insertions(+), 229 deletions(-) diff --git a/simplecpp.cpp b/simplecpp.cpp index 05c99ba6..0ac111fc 100755 --- a/simplecpp.cpp +++ b/simplecpp.cpp @@ -8,6 +8,14 @@ #define NOMINMAX #endif +#ifdef SIMPLECPP_WINDOWS +#define _WIN32_WINNT 0x0602 +#include +#undef ERROR +#else +#include +#endif + #include "simplecpp.h" #include @@ -26,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -46,13 +55,6 @@ #include #endif -#ifdef SIMPLECPP_WINDOWS -#include -#undef ERROR -#else -#include -#endif - #if __cplusplus >= 201103L #define OVERRIDE override #define EXPLICIT explicit @@ -155,7 +157,7 @@ static unsigned long long stringToULL(const std::string &s) return ret; } -// TODO: added an undercore since this conflicts with a function of the same name in utils.h from Cppcheck source when building Cppcheck with MSBuild +// TODO: added an undercore since this conflicts with a function of the same name in utils.h from Cppcheck source when building Cppcheck with MSBuild static bool startsWith_(const std::string &s, const std::string &p) { return (s.size() >= p.size()) && std::equal(p.begin(), p.end(), s.begin()); @@ -2568,7 +2570,8 @@ static bool isCpp17OrLater(const simplecpp::DUI &dui) } -static std::string currentDirectoryOSCalc() { +static std::string currentDirectoryOSCalc() +{ const std::size_t size = 4096; char currentPath[size]; @@ -2582,12 +2585,14 @@ static std::string currentDirectoryOSCalc() { return ""; } -static const std::string& currentDirectory() { +static const std::string& currentDirectory() +{ static const std::string curdir = simplecpp::simplifyPath(currentDirectoryOSCalc()); return curdir; } -static std::string toAbsolutePath(const std::string& path) { +static std::string toAbsolutePath(const std::string& path) +{ if (path.empty()) { return path;// preserve error file path that is indicated by an empty string } @@ -2598,7 +2603,8 @@ static std::string toAbsolutePath(const std::string& path) { return simplecpp::simplifyPath(path); } -static std::string dirPath(const std::string& path, bool withTrailingSlash=true) { +static std::string dirPath(const std::string& path, bool withTrailingSlash=true) +{ const std::size_t lastSlash = path.find_last_of("\\/"); if (lastSlash == std::string::npos) { return ""; @@ -2606,14 +2612,16 @@ static std::string dirPath(const std::string& path, bool withTrailingSlash=true) return path.substr(0, lastSlash + (withTrailingSlash ? 1U : 0U)); } -static std::string omitPathTrailingSlash(const std::string& path) { +static std::string omitPathTrailingSlash(const std::string& path) +{ if (endsWith(path, "/")) { return path.substr(0, path.size() - 1U); } return path; } -static std::string extractRelativePathFromAbsolute(const std::string& absoluteSimplifiedPath, const std::string& prefixSimplifiedAbsoluteDir = currentDirectory()) { +static std::string extractRelativePathFromAbsolute(const std::string& absoluteSimplifiedPath, const std::string& prefixSimplifiedAbsoluteDir = currentDirectory()) +{ const std::string normalizedAbsolutePath = omitPathTrailingSlash(absoluteSimplifiedPath); std::string currentPrefix = omitPathTrailingSlash(prefixSimplifiedAbsoluteDir); std::string leadingParenting; @@ -3054,13 +3062,13 @@ static std::string getRelativeFileName(const std::string &baseFile, const std::s { const std::string baseFileSimplified = simplecpp::simplifyPath(baseFile); const std::string baseFileAbsolute = isAbsolutePath(baseFileSimplified) ? - baseFileSimplified : - simplecpp::simplifyPath(currentDirectory() + "/" + baseFileSimplified); + baseFileSimplified : + simplecpp::simplifyPath(currentDirectory() + "/" + baseFileSimplified); const std::string headerSimplified = simplecpp::simplifyPath(header); const std::string path = isAbsolutePath(headerSimplified) ? - headerSimplified : - simplecpp::simplifyPath(dirPath(baseFileAbsolute) + headerSimplified); + headerSimplified : + simplecpp::simplifyPath(dirPath(baseFileAbsolute) + headerSimplified); return returnAbsolutePath ? toAbsolutePath(path) : extractRelativePathFromAbsolute(path); } @@ -3116,45 +3124,25 @@ static std::string openHeader(std::ifstream &f, const simplecpp::DUI &dui, const return openHeaderIncludePath(f, dui, header); } -simplecpp::TokenList *simplecpp::FileDataCache::get(const std::string &sourcefile, const std::string &header, std::string *header2, const simplecpp::DUI &dui, bool systemheader) +simplecpp::FileData *simplecpp::FileDataCache::lookup(const std::string &sourcefile, const std::string &header, const simplecpp::DUI &dui, bool systemheader) { - if (mDataMap.empty()) + if (mData.empty()) return nullptr; if (isAbsolutePath(header)) { std::string path = simplecpp::simplifyPath(header); - const auto data = mDataMap.find(path); - - if (data != mDataMap.end()) { - if (header2 != nullptr) { - const auto uniquePath = mAliasMap.find(path); - - if (uniquePath != mAliasMap.end()) - *header2 = uniquePath->second; - else - *header2 = std::move(path); - } + const auto name_it = mNameMap.find(path); - return data->second.get(); - } + if (name_it != mNameMap.end()) + return name_it->second; } if (!systemheader) { std::string path = getRelativeFileName(sourcefile, header, true); - const auto data = mDataMap.find(path); - - if (data != mDataMap.end()) { - if (header2 != nullptr) { - const auto uniquePath = mAliasMap.find(path); - - if (uniquePath != mAliasMap.end()) - *header2 = uniquePath->second; - else - *header2 = std::move(path); - } + const auto name_it = mNameMap.find(path); - return data->second.get(); - } + if (name_it != mNameMap.end()) + return name_it->second; // If the file exists but hasn't been loaded yet then we need to stop searching here or we could get a false match std::ifstream f; @@ -3165,75 +3153,55 @@ simplecpp::TokenList *simplecpp::FileDataCache::get(const std::string &sourcefil for (std::list::const_iterator it = dui.includePaths.begin(); it != dui.includePaths.end(); ++it) { std::string path = getIncludePathFileName(*it, header); - const auto data = mDataMap.find(path); - - if (data != mDataMap.end()) { - if (header2 != nullptr) { - const auto uniquePath = mAliasMap.find(path); - - if (uniquePath != mAliasMap.end()) - *header2 = uniquePath->second; - else - *header2 = std::move(path); - } + const auto name_it = mNameMap.find(path); - return data->second.get(); - } + if (name_it != mNameMap.end()) + return name_it->second; } return nullptr; } -simplecpp::TokenList *simplecpp::FileDataCache::load(const std::string &sourcefile, const std::string &header, std::string *header2, const simplecpp::DUI &dui, bool systemheader, std::vector &filenames, simplecpp::OutputList *outputList) +std::pair simplecpp::FileDataCache::load(const std::string &sourcefile, const std::string &header, const simplecpp::DUI &dui, bool systemheader, std::vector &filenames, simplecpp::OutputList *outputList) { std::ifstream f; std::string path = openHeader(f, dui, sourcefile, header, systemheader); if (path.empty()) - return nullptr; + return std::make_pair(false, nullptr); FileID fileId; if (!getFileId(path, fileId)) - return nullptr; + return std::make_pair(false, nullptr); - const auto id = mIdMap.find(fileId); - if (id != mIdMap.end()) { - const auto &data = mDataMap.at(id->second); + const auto id_it = mIdMap.find(fileId); + if (id_it != mIdMap.end()) { + mNameMap.insert(std::make_pair(std::move(path), id_it->second)); - mAliasMap.insert(std::make_pair(path, id->second)); - mDataMap.insert(std::make_pair(path, data)); - - if (header2 != nullptr) - *header2 = id->second; - - return data.get(); - } - else { - auto data = std::make_shared(f, filenames, path, outputList); - simplecpp::TokenList *const tokens = data.get(); + return std::make_pair(false, id_it->second); + } else { + FileData *data = new FileData {path, TokenList(f, filenames, path, outputList)}; if (dui.removeComments) - tokens->removeComments(); - - mIdMap.insert(std::make_pair(fileId, path)); - mDataMap.insert(std::make_pair(path, std::move(data))); + data->tokens.removeComments(); - if (header2 != nullptr) - *header2 = std::move(path); + mNameMap.insert(std::make_pair(std::move(path), data)); + mIdMap.insert(std::make_pair(fileId, data)); + mData.push_back(std::unique_ptr(data)); - return tokens; + return std::make_pair(true, data); } } -simplecpp::TokenList *simplecpp::FileDataCache::get_or_load(const std::string &sourcefile, const std::string &header, std::string *header2, const simplecpp::DUI &dui, bool systemheader, std::vector &filenames, simplecpp::OutputList *outputList) +std::pair simplecpp::FileDataCache::get(const std::string &sourcefile, const std::string &header, const simplecpp::DUI &dui, bool systemheader, std::vector &filenames, simplecpp::OutputList *outputList) { - simplecpp::TokenList *tokens = get(sourcefile, header, header2, dui, systemheader); + FileData *data = lookup(sourcefile, header, dui, systemheader); - if (tokens == nullptr) - tokens = load(sourcefile, header, header2, dui, systemheader, filenames, outputList); + if (data != nullptr) + return std::make_pair(false, data); - return tokens; + return load(sourcefile, header, dui, systemheader, filenames, outputList); } bool simplecpp::FileDataCache::getFileId(const std::string &path, FileID &id) @@ -3278,7 +3246,7 @@ simplecpp::FileDataCache simplecpp::load(const simplecpp::TokenList &rawtokens, nonExistingFilesCache.clear(); #endif - FileDataCache filedata; + FileDataCache cache; std::list filelist; @@ -3286,9 +3254,11 @@ simplecpp::FileDataCache simplecpp::load(const simplecpp::TokenList &rawtokens, for (std::list::const_iterator it = dui.includes.begin(); it != dui.includes.end(); ++it) { const std::string &filename = *it; - TokenList *tokenlist = filedata.get_or_load("", filename, nullptr, dui, false, filenames, outputList); + const auto loadResult = cache.get("", filename, dui, false, filenames, outputList); + const bool loaded = loadResult.first; + FileData *const filedata = loadResult.second; - if (tokenlist == nullptr) { + if (filedata == nullptr) { if (outputList) { simplecpp::Output err(filenames); err.type = simplecpp::Output::EXPLICIT_INCLUDE_NOT_FOUND; @@ -3299,14 +3269,16 @@ simplecpp::FileDataCache simplecpp::load(const simplecpp::TokenList &rawtokens, continue; } - if (!tokenlist->front()) { + if (!loaded) + continue; + + if (!filedata->tokens.front()) continue; - } if (dui.removeComments) - tokenlist->removeComments(); + filedata->tokens.removeComments(); - filelist.push_back(tokenlist->front()); + filelist.push_back(filedata->tokens.front()); } for (const Token *rawtok = rawtokens.cfront(); rawtok || !filelist.empty(); rawtok = rawtok ? rawtok->next : nullptr) { @@ -3331,18 +3303,18 @@ simplecpp::FileDataCache simplecpp::load(const simplecpp::TokenList &rawtokens, const bool systemheader = (htok->str()[0] == '<'); const std::string header(htok->str().substr(1U, htok->str().size() - 2U)); - TokenList *tokenlist = filedata.get_or_load(sourcefile, header, nullptr, dui, systemheader, filenames, outputList); - if (!tokenlist) + FileData *const filedata = cache.get(sourcefile, header, dui, systemheader, filenames, outputList).second; + if (!filedata) continue; if (dui.removeComments) - tokenlist->removeComments(); + filedata->tokens.removeComments(); - if (tokenlist->front()) - filelist.push_back(tokenlist->front()); + if (filedata->tokens.front()) + filelist.push_back(filedata->tokens.front()); } - return filedata; + return cache; } static bool preprocessToken(simplecpp::TokenList &output, const simplecpp::Token **tok1, simplecpp::MacroMap ¯os, std::vector &files, simplecpp::OutputList *outputList) @@ -3398,7 +3370,7 @@ static std::string getTimeDefine(const struct tm *timep) return std::string("\"").append(buf).append("\""); } -void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenList &rawtokens, std::vector &files, simplecpp::FileDataCache &filedata, const simplecpp::DUI &dui, simplecpp::OutputList *outputList, std::list *macroUsage, std::list *ifCond) +void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenList &rawtokens, std::vector &files, simplecpp::FileDataCache &cache, const simplecpp::DUI &dui, simplecpp::OutputList *outputList, std::list *macroUsage, std::list *ifCond) { #ifdef SIMPLECPP_WINDOWS if (dui.clearIncludeCache) @@ -3490,9 +3462,9 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL includetokenstack.push(rawtokens.cfront()); for (std::list::const_iterator it = dui.includes.begin(); it != dui.includes.end(); ++it) { - const TokenList *const includetokens = filedata.get_or_load("", *it, nullptr, dui, false, files, outputList); - if (includetokens != nullptr) - includetokenstack.push(includetokens->cfront()); + const FileData *const filedata = cache.get("", *it, dui, false, files, outputList).second; + if (filedata != nullptr && filedata->tokens.cfront() != nullptr) + includetokenstack.push(filedata->tokens.cfront()); } std::map > maybeUsedMacros; @@ -3614,9 +3586,8 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL const bool systemheader = (inctok->str()[0] == '<'); const std::string header(inctok->str().substr(1U, inctok->str().size() - 2U)); - std::string header2; - const TokenList *const includetokens = filedata.get_or_load(rawtok->location.file(), header, &header2, dui, systemheader, files, outputList); - if (includetokens == nullptr) { + const FileData *const filedata = cache.get(rawtok->location.file(), header, dui, systemheader, files, outputList).second; + if (filedata == nullptr) { if (outputList) { simplecpp::Output out(files); out.type = Output::MISSING_HEADER; @@ -3632,9 +3603,9 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL out.msg = "#include nested too deeply"; outputList->push_back(out); } - } else if (pragmaOnce.find(header2) == pragmaOnce.end()) { + } else if (pragmaOnce.find(filedata->filename) == pragmaOnce.end()) { includetokenstack.push(gotoNextLine(rawtok)); - rawtok = includetokens ? includetokens->cfront() : nullptr; + rawtok = filedata->tokens.cfront(); continue; } } else if (rawtok->str() == IF || rawtok->str() == IFDEF || rawtok->str() == IFNDEF || rawtok->str() == ELIF) { @@ -3862,9 +3833,9 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL } } -void simplecpp::cleanup(FileDataCache &filedata) +void simplecpp::cleanup(FileDataCache &cache) { - (void) filedata; + cache.clear(); } simplecpp::cstd_t simplecpp::getCStd(const std::string &std) diff --git a/simplecpp.h b/simplecpp.h index 31cce632..76faac6b 100755 --- a/simplecpp.h +++ b/simplecpp.h @@ -28,7 +28,9 @@ # define SIMPLECPP_LIB #endif -#ifndef _WIN32 +#ifdef _WIN32 +# include +#else # include #endif @@ -363,18 +365,18 @@ namespace simplecpp { * @param output TokenList that receives the preprocessing output * @param rawtokens Raw tokenlist for top sourcefile * @param files internal data of simplecpp - * @param filedata output from simplecpp::load() + * @param cache output from simplecpp::load() * @param dui defines, undefs, and include paths * @param outputList output: list that will receive output messages * @param macroUsage output: macro usage * @param ifCond output: #if/#elif expressions */ - SIMPLECPP_LIB void preprocess(TokenList &output, const TokenList &rawtokens, std::vector &files, FileDataCache &filedata, const DUI &dui, OutputList *outputList = nullptr, std::list *macroUsage = nullptr, std::list *ifCond = nullptr); + SIMPLECPP_LIB void preprocess(TokenList &output, const TokenList &rawtokens, std::vector &files, FileDataCache &cache, const DUI &dui, OutputList *outputList = nullptr, std::list *macroUsage = nullptr, std::list *ifCond = nullptr); /** * Deallocate data */ - SIMPLECPP_LIB void cleanup(FileDataCache &filedata); + SIMPLECPP_LIB void cleanup(FileDataCache &cache); /** Simplify path */ SIMPLECPP_LIB std::string simplifyPath(std::string path); @@ -396,73 +398,81 @@ namespace simplecpp { SIMPLECPP_LIB std::string getCppStdString(const std::string &std); SIMPLECPP_LIB std::string getCppStdString(cppstd_t std); - class SIMPLECPP_LIB FileDataCache - { + struct SIMPLECPP_LIB FileData { + /** The canonical filename associated with this data */ + std::string filename; + /** The tokens associated with this file */ + TokenList tokens; + }; + + class SIMPLECPP_LIB FileDataCache { public: - FileDataCache() {} + FileDataCache() = default; - TokenList *get(const std::string &sourcefile, const std::string &header, std::string *header2, const DUI &dui, bool systemheader); + FileDataCache(const FileDataCache &) = delete; + FileDataCache(FileDataCache &&) = default; - TokenList *load(const std::string &sourcefile, const std::string &header, std::string *header2, const DUI &dui, bool systemheader, std::vector &filenames, OutputList *outputList); + FileDataCache &operator=(const FileDataCache &) = delete; + FileDataCache &operator=(FileDataCache &&) = default; - TokenList *get_or_load(const std::string &sourcefile, const std::string &header, std::string *header2, const DUI &dui, bool systemheader, std::vector &filenames, OutputList *outputList); + /** Fetch the data for a file if it exists in the cache */ + FileData *lookup(const std::string &sourcefile, const std::string &header, const DUI &dui, bool systemheader); - void insert(const std::string &path, const TokenList &tokens) - { - mDataMap.insert(std::make_pair(path, std::make_shared(tokens))); - } + /** Load a file into the cache and return the loaded data, or return the cached data if the file id is cached */ + std::pair load(const std::string &sourcefile, const std::string &header, const DUI &dui, bool systemheader, std::vector &filenames, OutputList *outputList); - typedef std::map>::iterator iterator; - typedef std::map>::const_iterator const_iterator; - typedef std::map>::size_type size_type; + /** Get the cached data for a file, or load and then return it if it isn't cached */ + std::pair get(const std::string &sourcefile, const std::string &header, const DUI &dui, bool systemheader, std::vector &filenames, OutputList *outputList); - size_type size() const - { - return mDataMap.size(); - } + void insert(FileData data) { + FileData *newdata = new FileData(std::move(data)); - iterator begin() - { - return mDataMap.begin(); + mData.push_back(std::unique_ptr(newdata)); + mNameMap.insert(std::make_pair(newdata->filename, newdata)); } - iterator end() - { - return mDataMap.end(); + void clear() { + mNameMap.clear(); + mIdMap.clear(); + mData.clear(); } - const_iterator begin() const - { - return mDataMap.begin(); - } + typedef std::vector> container_type; + typedef container_type::iterator iterator; + typedef container_type::const_iterator const_iterator; + typedef container_type::size_type size_type; - const_iterator end() const - { - return mDataMap.end(); + size_type size() const { + return mData.size(); } - - const_iterator cbegin() const - { - return mDataMap.cbegin(); + iterator begin() { + return mData.begin(); } - - const_iterator cend() const - { - return mDataMap.cend(); + iterator end() { + return mData.end(); + } + const_iterator begin() const { + return mData.begin(); + } + const_iterator end() const { + return mData.end(); + } + const_iterator cbegin() const { + return mData.cbegin(); + } + const_iterator cend() const { + return mData.cend(); } private: - struct FileID - { + struct FileID { bool operator< (const FileID &that) const; #ifdef SIMPLECPP_WINDOWS - struct - { - uint64_t VolumeSerialNumber; - struct - { - uint8_t Identifier[16]; + struct { + std::uint64_t VolumeSerialNumber; + struct { + std::uint8_t Identifier[16]; } FileId; } fileIdInfo; #else @@ -473,9 +483,9 @@ namespace simplecpp { static bool getFileId(const std::string &path, FileID &id); - std::map> mDataMap; - std::map mIdMap; - std::map mAliasMap; + container_type mData; + std::map mNameMap; + std::map mIdMap; }; } diff --git a/test.cpp b/test.cpp index c23f9108..5b8ecc02 100644 --- a/test.cpp +++ b/test.cpp @@ -99,12 +99,12 @@ static std::string readfile(const char code[], std::size_t size, simplecpp::Outp static std::string preprocess(const char code[], const simplecpp::DUI &dui, simplecpp::OutputList *outputList) { std::vector files; - simplecpp::FileDataCache filedata; + simplecpp::FileDataCache cache; simplecpp::TokenList tokens = makeTokenList(code,files); tokens.removeComments(); simplecpp::TokenList tokens2(files); - simplecpp::preprocess(tokens2, tokens, files, filedata, dui, outputList); - simplecpp::cleanup(filedata); + simplecpp::preprocess(tokens2, tokens, files, cache, dui, outputList); + simplecpp::cleanup(cache); return tokens2.stringify(); } @@ -1036,11 +1036,11 @@ static void error4() // "#error x\n1" const char code[] = "\xFE\xFF\x00\x23\x00\x65\x00\x72\x00\x72\x00\x6f\x00\x72\x00\x20\x00\x78\x00\x0a\x00\x31"; std::vector files; - simplecpp::FileDataCache filedata; + simplecpp::FileDataCache cache; simplecpp::OutputList outputList; simplecpp::TokenList tokens2(files); const simplecpp::TokenList rawtoken = makeTokenList(code, sizeof(code),files,"test.c"); - simplecpp::preprocess(tokens2, rawtoken, files, filedata, simplecpp::DUI(), &outputList); + simplecpp::preprocess(tokens2, rawtoken, files, cache, simplecpp::DUI(), &outputList); ASSERT_EQUALS("file0,1,#error,#error x\n", toString(outputList)); } @@ -1049,11 +1049,11 @@ static void error5() // "#error x\n1" const char code[] = "\xFF\xFE\x23\x00\x65\x00\x72\x00\x72\x00\x6f\x00\x72\x00\x20\x00\x78\x00\x0a\x00\x78\x00\x31\x00"; std::vector files; - simplecpp::FileDataCache filedata; + simplecpp::FileDataCache cache; simplecpp::OutputList outputList; simplecpp::TokenList tokens2(files); const simplecpp::TokenList rawtokens = makeTokenList(code, sizeof(code),files,"test.c"); - simplecpp::preprocess(tokens2, rawtokens, files, filedata, simplecpp::DUI(), &outputList); + simplecpp::preprocess(tokens2, rawtokens, files, cache, simplecpp::DUI(), &outputList); ASSERT_EQUALS("file0,1,#error,#error x\n", toString(outputList)); } @@ -1894,12 +1894,14 @@ static void missingHeader2() { const char code[] = "#include \"foo.h\"\n"; // this file exists std::vector files; - simplecpp::FileDataCache filedata; - filedata.insert("foo.h", simplecpp::TokenList(files)); + simplecpp::FileDataCache cache; + cache.insert({"foo.h", simplecpp::TokenList(files)}); simplecpp::OutputList outputList; simplecpp::TokenList tokens2(files); const simplecpp::TokenList rawtokens = makeTokenList(code,files); - simplecpp::preprocess(tokens2, rawtokens, files, filedata, simplecpp::DUI(), &outputList); + simplecpp::DUI dui; + dui.includePaths.push_back("."); + simplecpp::preprocess(tokens2, rawtokens, files, cache, dui, &outputList); ASSERT_EQUALS("", toString(outputList)); } @@ -1924,12 +1926,14 @@ static void nestedInclude() const char code[] = "#include \"test.h\"\n"; std::vector files; simplecpp::TokenList rawtokens = makeTokenList(code,files,"test.h"); - simplecpp::FileDataCache filedata; - filedata.insert("test.h", rawtokens); + simplecpp::FileDataCache cache; + cache.insert({"test.h", rawtokens}); simplecpp::OutputList outputList; simplecpp::TokenList tokens2(files); - simplecpp::preprocess(tokens2, rawtokens, files, filedata, simplecpp::DUI(), &outputList); + simplecpp::DUI dui; + dui.includePaths.push_back("."); + simplecpp::preprocess(tokens2, rawtokens, files, cache, dui, &outputList); ASSERT_EQUALS("file0,1,include_nested_too_deeply,#include nested too deeply\n", toString(outputList)); } @@ -1939,15 +1943,15 @@ static void systemInclude() const char code[] = "#include \n"; std::vector files; simplecpp::TokenList rawtokens = makeTokenList(code,files,"local/limits.h"); - simplecpp::FileDataCache filedata; - filedata.insert("include/limits.h", simplecpp::TokenList(files)); - filedata.insert("local/limits.h", rawtokens); + simplecpp::FileDataCache cache; + cache.insert({"include/limits.h", simplecpp::TokenList(files)}); + cache.insert({"local/limits.h", rawtokens}); simplecpp::OutputList outputList; simplecpp::TokenList tokens2(files); simplecpp::DUI dui; dui.includePaths.push_back("include"); - simplecpp::preprocess(tokens2, rawtokens, files, filedata, dui, &outputList); + simplecpp::preprocess(tokens2, rawtokens, files, cache, dui, &outputList); ASSERT_EQUALS("", toString(outputList)); } @@ -1969,9 +1973,9 @@ static void multiline2() simplecpp::TokenList rawtokens = makeTokenList(code,files); ASSERT_EQUALS("# define A /**/ 1\n\nA", rawtokens.stringify()); rawtokens.removeComments(); - simplecpp::FileDataCache filedata; + simplecpp::FileDataCache cache; simplecpp::TokenList tokens2(files); - simplecpp::preprocess(tokens2, rawtokens, files, filedata, simplecpp::DUI()); + simplecpp::preprocess(tokens2, rawtokens, files, cache, simplecpp::DUI()); ASSERT_EQUALS("\n\n1", tokens2.stringify()); } @@ -1984,9 +1988,9 @@ static void multiline3() // #28 - macro with multiline comment simplecpp::TokenList rawtokens = makeTokenList(code,files); ASSERT_EQUALS("# define A /* */ 1\n\nA", rawtokens.stringify()); rawtokens.removeComments(); - simplecpp::FileDataCache filedata; + simplecpp::FileDataCache cache; simplecpp::TokenList tokens2(files); - simplecpp::preprocess(tokens2, rawtokens, files, filedata, simplecpp::DUI()); + simplecpp::preprocess(tokens2, rawtokens, files, cache, simplecpp::DUI()); ASSERT_EQUALS("\n\n1", tokens2.stringify()); } @@ -2000,9 +2004,9 @@ static void multiline4() // #28 - macro with multiline comment simplecpp::TokenList rawtokens = makeTokenList(code,files); ASSERT_EQUALS("# define A /* */ 1\n\n\nA", rawtokens.stringify()); rawtokens.removeComments(); - simplecpp::FileDataCache filedata; + simplecpp::FileDataCache cache; simplecpp::TokenList tokens2(files); - simplecpp::preprocess(tokens2, rawtokens, files, filedata, simplecpp::DUI()); + simplecpp::preprocess(tokens2, rawtokens, files, cache, simplecpp::DUI()); ASSERT_EQUALS("\n\n\n1", tokens2.stringify()); } @@ -2123,12 +2127,14 @@ static void include3() // #16 - crash when expanding macro from header ASSERT_EQUALS("A.c", files[0]); ASSERT_EQUALS("A.h", files[1]); - simplecpp::FileDataCache filedata; - filedata.insert("A.c", rawtokens_c); - filedata.insert("A.h", rawtokens_h); + simplecpp::FileDataCache cache; + cache.insert({"A.c", rawtokens_c}); + cache.insert({"A.h", rawtokens_h}); simplecpp::TokenList out(files); - simplecpp::preprocess(out, rawtokens_c, files, filedata, simplecpp::DUI()); + simplecpp::DUI dui; + dui.includePaths.push_back("."); + simplecpp::preprocess(out, rawtokens_c, files, cache, dui); ASSERT_EQUALS("\n1234", out.stringify()); } @@ -2148,14 +2154,15 @@ static void include4() // #27 - -include ASSERT_EQUALS("27.c", files[0]); ASSERT_EQUALS("27.h", files[1]); - simplecpp::FileDataCache filedata; - filedata.insert("27.c", rawtokens_c); - filedata.insert("27.h", rawtokens_h); + simplecpp::FileDataCache cache; + cache.insert({"27.c", rawtokens_c}); + cache.insert({"27.h", rawtokens_h}); simplecpp::TokenList out(files); simplecpp::DUI dui; + dui.includePaths.push_back("."); dui.includes.push_back("27.h"); - simplecpp::preprocess(out, rawtokens_c, files, filedata, dui); + simplecpp::preprocess(out, rawtokens_c, files, cache, dui); ASSERT_EQUALS("123", out.stringify()); } @@ -2174,12 +2181,14 @@ static void include5() // #3 - handle #include MACRO ASSERT_EQUALS("3.c", files[0]); ASSERT_EQUALS("3.h", files[1]); - simplecpp::FileDataCache filedata; - filedata.insert("3.c", rawtokens_c); - filedata.insert("3.h", rawtokens_h); + simplecpp::FileDataCache cache; + cache.insert({"3.c", rawtokens_c}); + cache.insert({"3.h", rawtokens_h}); simplecpp::TokenList out(files); - simplecpp::preprocess(out, rawtokens_c, files, filedata, simplecpp::DUI()); + simplecpp::DUI dui; + dui.includePaths.push_back("."); + simplecpp::preprocess(out, rawtokens_c, files, cache, dui); ASSERT_EQUALS("\n#line 1 \"3.h\"\n123", out.stringify()); } @@ -2195,11 +2204,11 @@ static void include6() // #57 - incomplete macro #include MACRO(,) ASSERT_EQUALS(1U, files.size()); ASSERT_EQUALS("57.c", files[0]); - simplecpp::FileDataCache filedata; - filedata.insert("57.c", rawtokens); + simplecpp::FileDataCache cache; + cache.insert({"57.c", rawtokens}); simplecpp::TokenList out(files); - simplecpp::preprocess(out, rawtokens, files, filedata, simplecpp::DUI()); + simplecpp::preprocess(out, rawtokens, files, cache, simplecpp::DUI()); } @@ -2218,14 +2227,14 @@ static void include7() // #include MACRO ASSERT_EQUALS("3.c", files[0]); ASSERT_EQUALS("3.h", files[1]); - simplecpp::FileDataCache filedata; - filedata.insert("3.c", rawtokens_c); - filedata.insert("3.h", rawtokens_h); + simplecpp::FileDataCache cache; + cache.insert({"3.c", rawtokens_c}); + cache.insert({"3.h", rawtokens_h}); simplecpp::TokenList out(files); simplecpp::DUI dui; dui.includePaths.push_back("."); - simplecpp::preprocess(out, rawtokens_c, files, filedata, dui); + simplecpp::preprocess(out, rawtokens_c, files, cache, dui); ASSERT_EQUALS("\n#line 1 \"3.h\"\n123", out.stringify()); } @@ -2256,14 +2265,14 @@ static void include9() ASSERT_EQUALS("1.c", files[0]); ASSERT_EQUALS("1.h", files[1]); - simplecpp::FileDataCache filedata; - filedata.insert("1.c", rawtokens_c); - filedata.insert("1.h", rawtokens_h); + simplecpp::FileDataCache cache; + cache.insert({"1.c", rawtokens_c}); + cache.insert({"1.h", rawtokens_h}); simplecpp::TokenList out(files); simplecpp::DUI dui; dui.includePaths.push_back("."); - simplecpp::preprocess(out, rawtokens_c, files, filedata, dui); + simplecpp::preprocess(out, rawtokens_c, files, cache, dui); ASSERT_EQUALS("\n#line 2 \"1.h\"\nx = 1 ;", out.stringify()); } @@ -2438,12 +2447,14 @@ static void stringify1() ASSERT_EQUALS("A.c", files[0]); ASSERT_EQUALS("A.h", files[1]); - simplecpp::FileDataCache filedata; - filedata.insert("A.c", rawtokens_c); - filedata.insert("A.h", rawtokens_h); + simplecpp::FileDataCache cache; + cache.insert({"A.c", rawtokens_c}); + cache.insert({"A.h", rawtokens_h}); simplecpp::TokenList out(files); - simplecpp::preprocess(out, rawtokens_c, files, filedata, simplecpp::DUI()); + simplecpp::DUI dui; + dui.includePaths.push_back("."); + simplecpp::preprocess(out, rawtokens_c, files, cache, dui); ASSERT_EQUALS("\n#line 1 \"A.h\"\n1\n2\n#line 1 \"A.h\"\n1\n2", out.stringify()); } @@ -2453,10 +2464,10 @@ static void tokenMacro1() const char code[] = "#define A 123\n" "A"; std::vector files; - simplecpp::FileDataCache filedata; + simplecpp::FileDataCache cache; simplecpp::TokenList tokenList(files); const simplecpp::TokenList rawtokens = makeTokenList(code,files); - simplecpp::preprocess(tokenList, rawtokens, files, filedata, simplecpp::DUI()); + simplecpp::preprocess(tokenList, rawtokens, files, cache, simplecpp::DUI()); ASSERT_EQUALS("A", tokenList.cback()->macro); } @@ -2465,10 +2476,10 @@ static void tokenMacro2() const char code[] = "#define ADD(X,Y) X+Y\n" "ADD(1,2)"; std::vector files; - simplecpp::FileDataCache filedata; + simplecpp::FileDataCache cache; simplecpp::TokenList tokenList(files); const simplecpp::TokenList rawtokens = makeTokenList(code,files); - simplecpp::preprocess(tokenList, rawtokens, files, filedata, simplecpp::DUI()); + simplecpp::preprocess(tokenList, rawtokens, files, cache, simplecpp::DUI()); const simplecpp::Token *tok = tokenList.cfront(); ASSERT_EQUALS("1", tok->str()); ASSERT_EQUALS("", tok->macro); @@ -2486,10 +2497,10 @@ static void tokenMacro3() "#define FRED 1\n" "ADD(FRED,2)"; std::vector files; - simplecpp::FileDataCache filedata; + simplecpp::FileDataCache cache; simplecpp::TokenList tokenList(files); const simplecpp::TokenList rawtokens = makeTokenList(code,files); - simplecpp::preprocess(tokenList, rawtokens, files, filedata, simplecpp::DUI()); + simplecpp::preprocess(tokenList, rawtokens, files, cache, simplecpp::DUI()); const simplecpp::Token *tok = tokenList.cfront(); ASSERT_EQUALS("1", tok->str()); ASSERT_EQUALS("FRED", tok->macro); @@ -2507,10 +2518,10 @@ static void tokenMacro4() "#define B 1\n" "A"; std::vector files; - simplecpp::FileDataCache filedata; + simplecpp::FileDataCache cache; simplecpp::TokenList tokenList(files); const simplecpp::TokenList rawtokens = makeTokenList(code,files); - simplecpp::preprocess(tokenList, rawtokens, files, filedata, simplecpp::DUI()); + simplecpp::preprocess(tokenList, rawtokens, files, cache, simplecpp::DUI()); const simplecpp::Token * const tok = tokenList.cfront(); ASSERT_EQUALS("1", tok->str()); ASSERT_EQUALS("A", tok->macro); @@ -2522,10 +2533,10 @@ static void tokenMacro5() "#define SET_BPF_JUMP(code) SET_BPF(D | code)\n" "SET_BPF_JUMP(A | B | C);"; std::vector files; - simplecpp::FileDataCache filedata; + simplecpp::FileDataCache cache; simplecpp::TokenList tokenList(files); const simplecpp::TokenList rawtokens = makeTokenList(code,files); - simplecpp::preprocess(tokenList, rawtokens, files, filedata, simplecpp::DUI()); + simplecpp::preprocess(tokenList, rawtokens, files, cache, simplecpp::DUI()); const simplecpp::Token * const tok = tokenList.cfront()->next; ASSERT_EQUALS("D", tok->str()); ASSERT_EQUALS("SET_BPF_JUMP", tok->macro); @@ -2959,8 +2970,8 @@ static void preprocess_files() ASSERT_EQUALS(1, files.size()); ASSERT_EQUALS("", *files.cbegin()); - simplecpp::FileDataCache filedata; - simplecpp::preprocess(tokens2, tokens, files, filedata, simplecpp::DUI(), nullptr); + simplecpp::FileDataCache cache; + simplecpp::preprocess(tokens2, tokens, files, cache, simplecpp::DUI(), nullptr); ASSERT_EQUALS(1, files.size()); ASSERT_EQUALS("", *files.cbegin()); } @@ -2976,8 +2987,8 @@ static void preprocess_files() ASSERT_EQUALS(1, files.size()); ASSERT_EQUALS("test.cpp", *files.cbegin()); - simplecpp::FileDataCache filedata; - simplecpp::preprocess(tokens2, tokens, files, filedata, simplecpp::DUI(), nullptr); + simplecpp::FileDataCache cache; + simplecpp::preprocess(tokens2, tokens, files, cache, simplecpp::DUI(), nullptr); ASSERT_EQUALS(1, files.size()); ASSERT_EQUALS("test.cpp", *files.cbegin()); } From fd848706314a146e825b22c5fcf4641269c22bf1 Mon Sep 17 00:00:00 2001 From: glank Date: Sat, 28 Jun 2025 23:21:02 +0200 Subject: [PATCH 03/18] Update to c++11 --- .github/workflows/clang-tidy.yml | 2 +- CMakeLists.txt | 21 +------ Makefile | 4 +- simplecpp.cpp | 99 ++++++-------------------------- simplecpp.h | 12 ---- 5 files changed, 20 insertions(+), 118 deletions(-) diff --git a/.github/workflows/clang-tidy.yml b/.github/workflows/clang-tidy.yml index 9a4f43c9..a2f7b6dc 100644 --- a/.github/workflows/clang-tidy.yml +++ b/.github/workflows/clang-tidy.yml @@ -30,7 +30,7 @@ jobs: - name: Prepare CMake run: | - cmake -S . -B cmake.output -G "Unix Makefiles" -DCMAKE_EXPORT_COMPILE_COMMANDS=ON -DDISABLE_CPP03_SYNTAX_CHECK=ON + cmake -S . -B cmake.output -G "Unix Makefiles" -DCMAKE_EXPORT_COMPILE_COMMANDS=ON env: CXX: clang-20 diff --git a/CMakeLists.txt b/CMakeLists.txt index 672e63bb..6ab0166e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,8 @@ cmake_minimum_required (VERSION 3.10) project (simplecpp LANGUAGES CXX) -option(DISABLE_CPP03_SYNTAX_CHECK "Disable the C++03 syntax check." OFF) +set(CMAKE_CXX_STANDARD 11) +set(CMAKE_CXX_STANDARD_REQUIRED ON) include(CheckCXXCompilerFlag) @@ -70,25 +71,7 @@ endif() add_library(simplecpp_obj OBJECT simplecpp.cpp) add_executable(simplecpp $ main.cpp) -set_property(TARGET simplecpp PROPERTY CXX_STANDARD 11) - -if (NOT DISABLE_CPP03_SYNTAX_CHECK) - # it is not possible to set a standard older than C++14 with Visual Studio - if (CMAKE_CXX_COMPILER_ID MATCHES "GNU" OR CMAKE_CXX_COMPILER_ID MATCHES "Clang") - # we need to create a dummy library as -fsyntax-only will not produce any output files causing the build to fail - add_library(simplecpp-03-syntax OBJECT simplecpp.cpp) - target_compile_options(simplecpp-03-syntax PRIVATE -std=c++03) - if (CMAKE_CXX_COMPILER_ID MATCHES "GNU") - target_compile_options(simplecpp-03-syntax PRIVATE -Wno-long-long) - elseif (CMAKE_CXX_COMPILER_ID MATCHES "Clang") - target_compile_options(simplecpp-03-syntax PRIVATE -Wno-c++11-long-long -Wno-c++11-compat) - endif() - add_dependencies(simplecpp simplecpp-03-syntax) - endif() -endif() - add_executable(testrunner $ test.cpp) -set_property(TARGET testrunner PROPERTY CXX_STANDARD 11) enable_testing() add_test(NAME testrunner COMMAND testrunner) diff --git a/Makefile b/Makefile index db1ca257..73977517 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ all: testrunner simplecpp -CXXFLAGS = -Wall -Wextra -pedantic -Wcast-qual -Wfloat-equal -Wmissing-declarations -Wmissing-format-attribute -Wredundant-decls -Wundef -Wno-multichar -Wold-style-cast -std=c++0x -g +CXXFLAGS = -Wall -Wextra -pedantic -Wcast-qual -Wfloat-equal -Wmissing-declarations -Wmissing-format-attribute -Wredundant-decls -Wundef -Wno-multichar -Wold-style-cast -std=c++11 -g LDFLAGS = -g %.o: %.cpp simplecpp.h @@ -11,8 +11,6 @@ testrunner: test.o simplecpp.o $(CXX) $(LDFLAGS) simplecpp.o test.o -o testrunner test: testrunner simplecpp - # The -std=c++03 makes sure that simplecpp.cpp is C++03 conformant. We don't require a C++11 compiler - g++ -std=c++03 -fsyntax-only simplecpp.cpp ./testrunner python3 run-tests.py diff --git a/simplecpp.cpp b/simplecpp.cpp index 0ac111fc..de2e5d7e 100755 --- a/simplecpp.cpp +++ b/simplecpp.cpp @@ -12,8 +12,6 @@ #define _WIN32_WINNT 0x0602 #include #undef ERROR -#else -#include #endif #include "simplecpp.h" @@ -40,33 +38,20 @@ #include #include #include -#if __cplusplus >= 201103L #ifdef SIMPLECPP_WINDOWS #include #endif #include -#endif #include #include #ifdef _WIN32 #include #else +#include #include #endif -#if __cplusplus >= 201103L -#define OVERRIDE override -#define EXPLICIT explicit -#else -#define OVERRIDE -#define EXPLICIT -#endif - -#if (__cplusplus < 201103L) && !defined(__APPLE__) -#define nullptr NULL -#endif - static bool isHex(const std::string &s) { return s.size()>2 && (s.compare(0,2,"0x")==0 || s.compare(0,2,"0X")==0); @@ -372,22 +357,22 @@ class simplecpp::TokenList::Stream { class StdIStream : public simplecpp::TokenList::Stream { public: // cppcheck-suppress uninitDerivedMemberVar - we call Stream::init() to initialize the private members - EXPLICIT StdIStream(std::istream &istr) + explicit StdIStream(std::istream &istr) : istr(istr) { assert(istr.good()); init(); } - virtual int get() OVERRIDE { + virtual int get() override { return istr.get(); } - virtual int peek() OVERRIDE { + virtual int peek() override { return istr.peek(); } - virtual void unget() OVERRIDE { + virtual void unget() override { istr.unget(); } - virtual bool good() OVERRIDE { + virtual bool good() override { return istr.good(); } @@ -406,20 +391,20 @@ class StdCharBufStream : public simplecpp::TokenList::Stream { init(); } - virtual int get() OVERRIDE { + virtual int get() override { if (pos >= size) return lastStatus = EOF; return str[pos++]; } - virtual int peek() OVERRIDE { + virtual int peek() override { if (pos >= size) return lastStatus = EOF; return str[pos]; } - virtual void unget() OVERRIDE { + virtual void unget() override { --pos; } - virtual bool good() OVERRIDE { + virtual bool good() override { return lastStatus != EOF; } @@ -433,7 +418,7 @@ class StdCharBufStream : public simplecpp::TokenList::Stream { class FileStream : public simplecpp::TokenList::Stream { public: // cppcheck-suppress uninitDerivedMemberVar - we call Stream::init() to initialize the private members - EXPLICIT FileStream(const std::string &filename, std::vector &files) + explicit FileStream(const std::string &filename, std::vector &files) : file(fopen(filename.c_str(), "rb")) , lastCh(0) , lastStatus(0) { @@ -444,25 +429,25 @@ class FileStream : public simplecpp::TokenList::Stream { init(); } - ~FileStream() OVERRIDE { + ~FileStream() override { fclose(file); file = nullptr; } - virtual int get() OVERRIDE { + virtual int get() override { lastStatus = lastCh = fgetc(file); return lastCh; } - virtual int peek() OVERRIDE{ + virtual int peek() override{ // keep lastCh intact const int ch = fgetc(file); unget_internal(ch); return ch; } - virtual void unget() OVERRIDE { + virtual void unget() override { unget_internal(lastCh); } - virtual bool good() OVERRIDE { + virtual bool good() override { return lastStatus != EOF; } @@ -523,12 +508,10 @@ simplecpp::TokenList::TokenList(const TokenList &other) : frontToken(nullptr), b *this = other; } -#if __cplusplus >= 201103L simplecpp::TokenList::TokenList(TokenList &&other) : frontToken(nullptr), backToken(nullptr), files(other.files) { *this = std::move(other); } -#endif simplecpp::TokenList::~TokenList() { @@ -547,7 +530,6 @@ simplecpp::TokenList &simplecpp::TokenList::operator=(const TokenList &other) return *this; } -#if __cplusplus >= 201103L simplecpp::TokenList &simplecpp::TokenList::operator=(TokenList &&other) { if (this != &other) { @@ -561,7 +543,6 @@ simplecpp::TokenList &simplecpp::TokenList::operator=(TokenList &&other) } return *this; } -#endif void simplecpp::TokenList::clear() { @@ -1481,11 +1462,7 @@ unsigned int simplecpp::TokenList::fileIndex(const std::string &filename) namespace simplecpp { class Macro; -#if __cplusplus >= 201103L using MacroMap = std::unordered_map; -#else - typedef std::map MacroMap; -#endif class Macro { public: @@ -2383,48 +2360,9 @@ namespace simplecpp { } #ifdef SIMPLECPP_WINDOWS - -#if __cplusplus >= 201103L using MyMutex = std::mutex; template using MyLock = std::lock_guard; -#else -class MyMutex { -public: - MyMutex() { - InitializeCriticalSection(&m_criticalSection); - } - - ~MyMutex() { - DeleteCriticalSection(&m_criticalSection); - } - - CRITICAL_SECTION* lock() { - return &m_criticalSection; - } -private: - CRITICAL_SECTION m_criticalSection; -}; - -template -class MyLock { -public: - explicit MyLock(T& m) - : m_mutex(m) { - EnterCriticalSection(m_mutex.lock()); - } - - ~MyLock() { - LeaveCriticalSection(m_mutex.lock()); - } - -private: - MyLock& operator=(const MyLock&); - MyLock(const MyLock&); - - T& m_mutex; -}; -#endif static bool isAbsolutePath(const std::string &path) { @@ -2433,7 +2371,6 @@ static bool isAbsolutePath(const std::string &path) return path.length() > 1U && (path[0] == '/' || path[0] == '\\'); } #else - static bool isAbsolutePath(const std::string &path) { return path.length() > 1U && path[0] == '/'; @@ -3934,7 +3871,3 @@ std::string simplecpp::getCppStdString(const std::string &std) { return getCppStdString(getCppStd(std)); } - -#if (__cplusplus < 201103L) && !defined(__APPLE__) -#undef nullptr -#endif diff --git a/simplecpp.h b/simplecpp.h index 76faac6b..7814eb83 100755 --- a/simplecpp.h +++ b/simplecpp.h @@ -34,10 +34,6 @@ # include #endif -#if (__cplusplus < 201103L) && !defined(__APPLE__) -#define nullptr NULL -#endif - #if defined(_MSC_VER) # pragma warning(push) // suppress warnings about "conversion from 'type1' to 'type2', possible loss of data" @@ -222,14 +218,10 @@ namespace simplecpp { /** generates a token list from the given filename parameter */ TokenList(const std::string &filename, std::vector &filenames, OutputList *outputList = nullptr); TokenList(const TokenList &other); -#if __cplusplus >= 201103L TokenList(TokenList &&other); -#endif ~TokenList(); TokenList &operator=(const TokenList &other); -#if __cplusplus >= 201103L TokenList &operator=(TokenList &&other); -#endif void clear(); bool empty() const { @@ -493,8 +485,4 @@ namespace simplecpp { # pragma warning(pop) #endif -#if (__cplusplus < 201103L) && !defined(__APPLE__) -#undef nullptr -#endif - #endif From 08bd742d884a47f7f2f239180e0831a1e41a485c Mon Sep 17 00:00:00 2001 From: glank Date: Sat, 28 Jun 2025 23:54:01 +0200 Subject: [PATCH 04/18] Fix clang-tidy issues --- simplecpp.cpp | 26 +++++++++++++------------- simplecpp.h | 2 +- test.cpp | 30 +++++++++++++++--------------- 3 files changed, 29 insertions(+), 29 deletions(-) diff --git a/simplecpp.cpp b/simplecpp.cpp index de2e5d7e..9155bea7 100755 --- a/simplecpp.cpp +++ b/simplecpp.cpp @@ -3067,7 +3067,7 @@ simplecpp::FileData *simplecpp::FileDataCache::lookup(const std::string &sourcef return nullptr; if (isAbsolutePath(header)) { - std::string path = simplecpp::simplifyPath(header); + const std::string path = simplecpp::simplifyPath(header); const auto name_it = mNameMap.find(path); if (name_it != mNameMap.end()) @@ -3075,7 +3075,7 @@ simplecpp::FileData *simplecpp::FileDataCache::lookup(const std::string &sourcef } if (!systemheader) { - std::string path = getRelativeFileName(sourcefile, header, true); + const std::string path = getRelativeFileName(sourcefile, header, true); const auto name_it = mNameMap.find(path); if (name_it != mNameMap.end()) @@ -3089,7 +3089,7 @@ simplecpp::FileData *simplecpp::FileDataCache::lookup(const std::string &sourcef } for (std::list::const_iterator it = dui.includePaths.begin(); it != dui.includePaths.end(); ++it) { - std::string path = getIncludePathFileName(*it, header); + const std::string path = getIncludePathFileName(*it, header); const auto name_it = mNameMap.find(path); if (name_it != mNameMap.end()) @@ -3117,23 +3117,23 @@ std::pair simplecpp::FileDataCache::load(const std: mNameMap.insert(std::make_pair(std::move(path), id_it->second)); return std::make_pair(false, id_it->second); - } else { - FileData *data = new FileData {path, TokenList(f, filenames, path, outputList)}; + } - if (dui.removeComments) - data->tokens.removeComments(); + FileData *const data = new FileData {path, TokenList(f, filenames, path, outputList)}; - mNameMap.insert(std::make_pair(std::move(path), data)); - mIdMap.insert(std::make_pair(fileId, data)); - mData.push_back(std::unique_ptr(data)); + if (dui.removeComments) + data->tokens.removeComments(); - return std::make_pair(true, data); - } + mNameMap.insert(std::make_pair(std::move(path), data)); + mIdMap.insert(std::make_pair(fileId, data)); + mData.push_back(std::unique_ptr(data)); + + return std::make_pair(true, data); } std::pair simplecpp::FileDataCache::get(const std::string &sourcefile, const std::string &header, const simplecpp::DUI &dui, bool systemheader, std::vector &filenames, simplecpp::OutputList *outputList) { - FileData *data = lookup(sourcefile, header, dui, systemheader); + FileData *const data = lookup(sourcefile, header, dui, systemheader); if (data != nullptr) return std::make_pair(false, data); diff --git a/simplecpp.h b/simplecpp.h index 7814eb83..f2217d03 100755 --- a/simplecpp.h +++ b/simplecpp.h @@ -417,7 +417,7 @@ namespace simplecpp { std::pair get(const std::string &sourcefile, const std::string &header, const DUI &dui, bool systemheader, std::vector &filenames, OutputList *outputList); void insert(FileData data) { - FileData *newdata = new FileData(std::move(data)); + FileData *const newdata = new FileData(std::move(data)); mData.push_back(std::unique_ptr(newdata)); mNameMap.insert(std::make_pair(newdata->filename, newdata)); diff --git a/test.cpp b/test.cpp index 5b8ecc02..c19c942d 100644 --- a/test.cpp +++ b/test.cpp @@ -1925,7 +1925,7 @@ static void nestedInclude() { const char code[] = "#include \"test.h\"\n"; std::vector files; - simplecpp::TokenList rawtokens = makeTokenList(code,files,"test.h"); + const simplecpp::TokenList rawtokens = makeTokenList(code,files,"test.h"); simplecpp::FileDataCache cache; cache.insert({"test.h", rawtokens}); @@ -1942,7 +1942,7 @@ static void systemInclude() { const char code[] = "#include \n"; std::vector files; - simplecpp::TokenList rawtokens = makeTokenList(code,files,"local/limits.h"); + const simplecpp::TokenList rawtokens = makeTokenList(code,files,"local/limits.h"); simplecpp::FileDataCache cache; cache.insert({"include/limits.h", simplecpp::TokenList(files)}); cache.insert({"local/limits.h", rawtokens}); @@ -2120,8 +2120,8 @@ static void include3() // #16 - crash when expanding macro from header std::vector files; - simplecpp::TokenList rawtokens_c = makeTokenList(code_c, files, "A.c"); - simplecpp::TokenList rawtokens_h = makeTokenList(code_h, files, "A.h"); + const simplecpp::TokenList rawtokens_c = makeTokenList(code_c, files, "A.c"); + const simplecpp::TokenList rawtokens_h = makeTokenList(code_h, files, "A.h"); ASSERT_EQUALS(2U, files.size()); ASSERT_EQUALS("A.c", files[0]); @@ -2147,8 +2147,8 @@ static void include4() // #27 - -include std::vector files; - simplecpp::TokenList rawtokens_c = makeTokenList(code_c, files, "27.c"); - simplecpp::TokenList rawtokens_h = makeTokenList(code_h, files, "27.h"); + const simplecpp::TokenList rawtokens_c = makeTokenList(code_c, files, "27.c"); + const simplecpp::TokenList rawtokens_h = makeTokenList(code_h, files, "27.h"); ASSERT_EQUALS(2U, files.size()); ASSERT_EQUALS("27.c", files[0]); @@ -2174,8 +2174,8 @@ static void include5() // #3 - handle #include MACRO std::vector files; - simplecpp::TokenList rawtokens_c = makeTokenList(code_c, files, "3.c"); - simplecpp::TokenList rawtokens_h = makeTokenList(code_h, files, "3.h"); + const simplecpp::TokenList rawtokens_c = makeTokenList(code_c, files, "3.c"); + const simplecpp::TokenList rawtokens_h = makeTokenList(code_h, files, "3.h"); ASSERT_EQUALS(2U, files.size()); ASSERT_EQUALS("3.c", files[0]); @@ -2199,7 +2199,7 @@ static void include6() // #57 - incomplete macro #include MACRO(,) std::vector files; - simplecpp::TokenList rawtokens = makeTokenList(code, files, "57.c"); + const simplecpp::TokenList rawtokens = makeTokenList(code, files, "57.c"); ASSERT_EQUALS(1U, files.size()); ASSERT_EQUALS("57.c", files[0]); @@ -2220,8 +2220,8 @@ static void include7() // #include MACRO std::vector files; - simplecpp::TokenList rawtokens_c = makeTokenList(code_c, files, "3.c"); - simplecpp::TokenList rawtokens_h = makeTokenList(code_h, files, "3.h"); + const simplecpp::TokenList rawtokens_c = makeTokenList(code_c, files, "3.c"); + const simplecpp::TokenList rawtokens_h = makeTokenList(code_h, files, "3.h"); ASSERT_EQUALS(2U, files.size()); ASSERT_EQUALS("3.c", files[0]); @@ -2258,8 +2258,8 @@ static void include9() std::vector files; - simplecpp::TokenList rawtokens_c = makeTokenList(code_c, files, "1.c"); - simplecpp::TokenList rawtokens_h = makeTokenList(code_h, files, "1.h"); + const simplecpp::TokenList rawtokens_c = makeTokenList(code_c, files, "1.c"); + const simplecpp::TokenList rawtokens_h = makeTokenList(code_h, files, "1.h"); ASSERT_EQUALS(2U, files.size()); ASSERT_EQUALS("1.c", files[0]); @@ -2440,8 +2440,8 @@ static void stringify1() std::vector files; - simplecpp::TokenList rawtokens_c = makeTokenList(code_c, files, "A.c"); - simplecpp::TokenList rawtokens_h = makeTokenList(code_h, files, "A.h"); + const simplecpp::TokenList rawtokens_c = makeTokenList(code_c, files, "A.c"); + const simplecpp::TokenList rawtokens_h = makeTokenList(code_h, files, "A.h"); ASSERT_EQUALS(2U, files.size()); ASSERT_EQUALS("A.c", files[0]); From 791d4bbe26f61f877cc553cc00edbd3f138fa53c Mon Sep 17 00:00:00 2001 From: glank Date: Mon, 30 Jun 2025 12:18:52 +0200 Subject: [PATCH 05/18] Fix windows definitions --- simplecpp.cpp | 22 +++++++++------------- simplecpp.h | 6 +++++- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/simplecpp.cpp b/simplecpp.cpp index 9155bea7..71d6490b 100755 --- a/simplecpp.cpp +++ b/simplecpp.cpp @@ -3,19 +3,15 @@ * Copyright (C) 2016-2023 simplecpp team */ -#if defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) -#define SIMPLECPP_WINDOWS -#define NOMINMAX -#endif +#include "simplecpp.h" #ifdef SIMPLECPP_WINDOWS -#define _WIN32_WINNT 0x0602 -#include -#undef ERROR +# define _WIN32_WINNT 0x0602 +# define NOMINMAX +# include +# undef ERROR #endif -#include "simplecpp.h" - #include #include #include @@ -39,17 +35,17 @@ #include #include #ifdef SIMPLECPP_WINDOWS -#include +# include #endif #include #include #include #ifdef _WIN32 -#include +# include #else -#include -#include +# include +# include #endif static bool isHex(const std::string &s) diff --git a/simplecpp.h b/simplecpp.h index f2217d03..4ca31697 100755 --- a/simplecpp.h +++ b/simplecpp.h @@ -6,6 +6,10 @@ #ifndef simplecppH #define simplecppH +#if defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) +# define SIMPLECPP_WINDOWS +#endif + #include #include #include @@ -28,7 +32,7 @@ # define SIMPLECPP_LIB #endif -#ifdef _WIN32 +#ifdef SIMPLECPP_WINDOWS # include #else # include From d3fb4245e510b939d32e13ba86556fb7a094fa1f Mon Sep 17 00:00:00 2001 From: glank Date: Thu, 3 Jul 2025 12:23:34 +0200 Subject: [PATCH 06/18] Remove MyMutex and MyLock --- simplecpp.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/simplecpp.cpp b/simplecpp.cpp index b85c78f3..6577ee1d 100755 --- a/simplecpp.cpp +++ b/simplecpp.cpp @@ -2408,10 +2408,6 @@ namespace simplecpp { } #ifdef SIMPLECPP_WINDOWS -using MyMutex = std::mutex; -template -using MyLock = std::lock_guard; - static bool isAbsolutePath(const std::string &path) { if (path.length() >= 3 && path[0] > 0 && std::isalpha(path[0]) && path[1] == ':' && (path[2] == '\\' || path[2] == '/')) @@ -3004,23 +3000,23 @@ class NonExistingFilesCache { NonExistingFilesCache() {} bool contains(const std::string& path) { - MyLock lock(m_mutex); + std::lock_guard lock(m_mutex); return (m_pathSet.find(path) != m_pathSet.end()); } void add(const std::string& path) { - MyLock lock(m_mutex); + std::lock_guard lock(m_mutex); m_pathSet.insert(path); } void clear() { - MyLock lock(m_mutex); + std::lock_guard lock(m_mutex); m_pathSet.clear(); } private: std::set m_pathSet; - MyMutex m_mutex; + std::mutex m_mutex; }; static NonExistingFilesCache nonExistingFilesCache; From 60250e602ea790ab43bbec55237e4eaf976e389e Mon Sep 17 00:00:00 2001 From: glank Date: Thu, 3 Jul 2025 12:55:58 +0200 Subject: [PATCH 07/18] Simplify path calculations --- simplecpp.cpp | 156 +++++++------------------------------------------- 1 file changed, 21 insertions(+), 135 deletions(-) diff --git a/simplecpp.cpp b/simplecpp.cpp index 6577ee1d..ffd8ab12 100755 --- a/simplecpp.cpp +++ b/simplecpp.cpp @@ -138,12 +138,6 @@ static unsigned long long stringToULL(const std::string &s) return ret; } -// TODO: added an undercore since this conflicts with a function of the same name in utils.h from Cppcheck source when building Cppcheck with MSBuild -static bool startsWith_(const std::string &s, const std::string &p) -{ - return (s.size() >= p.size()) && std::equal(p.begin(), p.end(), s.begin()); -} - static bool endsWith(const std::string &s, const std::string &e) { return (s.size() >= e.size()) && std::equal(e.rbegin(), e.rend(), s.rbegin()); @@ -2551,39 +2545,6 @@ static bool isCpp17OrLater(const simplecpp::DUI &dui) } -static std::string currentDirectoryOSCalc() -{ - const std::size_t size = 4096; - char currentPath[size]; - -#ifndef _WIN32 - if (getcwd(currentPath, size) != nullptr) -#else - if (_getcwd(currentPath, size) != nullptr) -#endif - return std::string(currentPath); - - return ""; -} - -static const std::string& currentDirectory() -{ - static const std::string curdir = simplecpp::simplifyPath(currentDirectoryOSCalc()); - return curdir; -} - -static std::string toAbsolutePath(const std::string& path) -{ - if (path.empty()) { - return path;// preserve error file path that is indicated by an empty string - } - if (!isAbsolutePath(path)) { - return simplecpp::simplifyPath(currentDirectory() + "/" + path); - } - // otherwise - return simplecpp::simplifyPath(path); -} - static std::string dirPath(const std::string& path, bool withTrailingSlash=true) { const std::size_t lastSlash = path.find_last_of("\\/"); @@ -2593,38 +2554,6 @@ static std::string dirPath(const std::string& path, bool withTrailingSlash=true) return path.substr(0, lastSlash + (withTrailingSlash ? 1U : 0U)); } -static std::string omitPathTrailingSlash(const std::string& path) -{ - if (endsWith(path, "/")) { - return path.substr(0, path.size() - 1U); - } - return path; -} - -static std::string extractRelativePathFromAbsolute(const std::string& absoluteSimplifiedPath, const std::string& prefixSimplifiedAbsoluteDir = currentDirectory()) -{ - const std::string normalizedAbsolutePath = omitPathTrailingSlash(absoluteSimplifiedPath); - std::string currentPrefix = omitPathTrailingSlash(prefixSimplifiedAbsoluteDir); - std::string leadingParenting; - while (!startsWith_(normalizedAbsolutePath, currentPrefix)) { - leadingParenting = "../" + leadingParenting; - currentPrefix = dirPath(currentPrefix, false); - } - const std::size_t size = currentPrefix.size(); - std::string relativeFromMeetingPath = normalizedAbsolutePath.substr(size, normalizedAbsolutePath.size() - size); - if (currentPrefix.empty() && !(startsWith_(absoluteSimplifiedPath, "/") && startsWith_(prefixSimplifiedAbsoluteDir, "/"))) { - // In the case that there is no common prefix path, - // and at not both of the paths start with `/` (can happen only in Windows paths on distinct partitions), - // return the absolute simplified path as is because no relative path can match. - return absoluteSimplifiedPath; - } - if (startsWith_(relativeFromMeetingPath, "/")) { - // omit the leading slash - relativeFromMeetingPath = relativeFromMeetingPath.substr(1, relativeFromMeetingPath.size()); - } - return leadingParenting + relativeFromMeetingPath; -} - static std::string openHeader(std::ifstream &f, const simplecpp::DUI &dui, const std::string &sourcefile, const std::string &header, bool systemheader); static void simplifyHasInclude(simplecpp::TokenList &expr, const simplecpp::DUI &dui) { @@ -3023,86 +2952,41 @@ static NonExistingFilesCache nonExistingFilesCache; #endif -static std::string openHeader(std::ifstream &f, const std::string &path) +static std::string openHeaderDirect(std::ifstream &f, const std::string &path) { - std::string simplePath = simplecpp::simplifyPath(path); #ifdef SIMPLECPP_WINDOWS - if (nonExistingFilesCache.contains(simplePath)) + if (nonExistingFilesCache.contains(path)) return ""; // file is known not to exist, skip expensive file open call #endif - f.open(simplePath.c_str()); + f.open(path.c_str()); if (f.is_open()) - return simplePath; + return path; #ifdef SIMPLECPP_WINDOWS - nonExistingFilesCache.add(simplePath); + nonExistingFilesCache.add(path); #endif return ""; } -static std::string getRelativeFileName(const std::string &baseFile, const std::string &header, bool returnAbsolutePath) -{ - const std::string baseFileSimplified = simplecpp::simplifyPath(baseFile); - const std::string baseFileAbsolute = isAbsolutePath(baseFileSimplified) ? - baseFileSimplified : - simplecpp::simplifyPath(currentDirectory() + "/" + baseFileSimplified); - - const std::string headerSimplified = simplecpp::simplifyPath(header); - const std::string path = isAbsolutePath(headerSimplified) ? - headerSimplified : - simplecpp::simplifyPath(dirPath(baseFileAbsolute) + headerSimplified); - - return returnAbsolutePath ? toAbsolutePath(path) : extractRelativePathFromAbsolute(path); -} - -static std::string openHeaderRelative(std::ifstream &f, const std::string &sourcefile, const std::string &header) -{ - return openHeader(f, getRelativeFileName(sourcefile, header, isAbsolutePath(sourcefile))); -} - -// returns the simplified header path: -// * If the header path is absolute, returns it in absolute path -// * Otherwise, returns it in relative path with respect to the current directory -static std::string getIncludePathFileName(const std::string &includePath, const std::string &header) -{ - std::string simplifiedHeader = simplecpp::simplifyPath(header); - - if (isAbsolutePath(simplifiedHeader)) { - return simplifiedHeader; - } - - std::string basePath = toAbsolutePath(includePath); - if (!basePath.empty() && basePath[basePath.size()-1U]!='/' && basePath[basePath.size()-1U]!='\\') - basePath += '/'; - const std::string absoluteSimplifiedHeaderPath = simplecpp::simplifyPath(basePath + simplifiedHeader); - // preserve absoluteness/relativieness of the including dir - return isAbsolutePath(includePath) ? absoluteSimplifiedHeaderPath : extractRelativePathFromAbsolute(absoluteSimplifiedHeaderPath); -} - -static std::string openHeaderIncludePath(std::ifstream &f, const simplecpp::DUI &dui, const std::string &header) -{ - for (std::list::const_iterator it = dui.includePaths.begin(); it != dui.includePaths.end(); ++it) { - std::string path = openHeader(f, getIncludePathFileName(*it, header)); - if (!path.empty()) - return path; - } - return ""; -} - static std::string openHeader(std::ifstream &f, const simplecpp::DUI &dui, const std::string &sourcefile, const std::string &header, bool systemheader) { if (isAbsolutePath(header)) - return openHeader(f, header); + return openHeaderDirect(f, simplecpp::simplifyPath(header)); // prefer first to search the header relatively to source file if found, when not a system header if (!systemheader) { - std::string relativeHeader = openHeaderRelative(f, sourcefile, header); - if (!relativeHeader.empty()) { - return relativeHeader; + std::string path = openHeaderDirect(f, simplecpp::simplifyPath(dirPath(sourcefile) + header)); + if (!path.empty()) { + return path; } } // search the header on the include paths (provided by the flags "-I...") - return openHeaderIncludePath(f, dui, header); + for (const auto &includePath : dui.includePaths) { + std::string path = openHeaderDirect(f, simplecpp::simplifyPath(includePath + "/" + header)); + if (!path.empty()) + return path; + } + return ""; } simplecpp::FileData *simplecpp::FileDataCache::lookup(const std::string &sourcefile, const std::string &header, const simplecpp::DUI &dui, bool systemheader) @@ -3116,10 +3000,12 @@ simplecpp::FileData *simplecpp::FileDataCache::lookup(const std::string &sourcef if (name_it != mNameMap.end()) return name_it->second; + + return nullptr; } if (!systemheader) { - const std::string path = getRelativeFileName(sourcefile, header, true); + const std::string path = simplecpp::simplifyPath(dirPath(sourcefile) + header); const auto name_it = mNameMap.find(path); if (name_it != mNameMap.end()) @@ -3127,13 +3013,13 @@ simplecpp::FileData *simplecpp::FileDataCache::lookup(const std::string &sourcef // If the file exists but hasn't been loaded yet then we need to stop searching here or we could get a false match std::ifstream f; - openHeader(f, path); + openHeaderDirect(f, path); if (f.is_open()) return nullptr; } - for (std::list::const_iterator it = dui.includePaths.begin(); it != dui.includePaths.end(); ++it) { - const std::string path = getIncludePathFileName(*it, header); + for (const auto &includePath : dui.includePaths) { + const std::string path = simplecpp::simplifyPath(includePath + "/" + header); const auto name_it = mNameMap.find(path); if (name_it != mNameMap.end()) From 0c99e2cb6aa51cd7a5089368b87911f5b66830ca Mon Sep 17 00:00:00 2001 From: glank Date: Thu, 3 Jul 2025 15:30:48 +0200 Subject: [PATCH 08/18] Rework lookup procedure --- simplecpp.cpp | 113 ++++++++++++++++++-------------------------------- simplecpp.h | 53 +++++++++++++++++------ 2 files changed, 81 insertions(+), 85 deletions(-) diff --git a/simplecpp.cpp b/simplecpp.cpp index ffd8ab12..07ed0ecf 100755 --- a/simplecpp.cpp +++ b/simplecpp.cpp @@ -2989,86 +2989,64 @@ static std::string openHeader(std::ifstream &f, const simplecpp::DUI &dui, const return ""; } -simplecpp::FileData *simplecpp::FileDataCache::lookup(const std::string &sourcefile, const std::string &header, const simplecpp::DUI &dui, bool systemheader) +std::pair simplecpp::FileDataCache::tryload(const FileDataCache::name_map_type::iterator &name_it, const simplecpp::DUI &dui, std::vector &filenames, simplecpp::OutputList *outputList) { - if (mData.empty()) - return nullptr; - - if (isAbsolutePath(header)) { - const std::string path = simplecpp::simplifyPath(header); - const auto name_it = mNameMap.find(path); - - if (name_it != mNameMap.end()) - return name_it->second; - - return nullptr; - } - - if (!systemheader) { - const std::string path = simplecpp::simplifyPath(dirPath(sourcefile) + header); - const auto name_it = mNameMap.find(path); - - if (name_it != mNameMap.end()) - return name_it->second; - - // If the file exists but hasn't been loaded yet then we need to stop searching here or we could get a false match - std::ifstream f; - openHeaderDirect(f, path); - if (f.is_open()) - return nullptr; - } - - for (const auto &includePath : dui.includePaths) { - const std::string path = simplecpp::simplifyPath(includePath + "/" + header); - const auto name_it = mNameMap.find(path); - - if (name_it != mNameMap.end()) - return name_it->second; - } - - return nullptr; -} - -std::pair simplecpp::FileDataCache::load(const std::string &sourcefile, const std::string &header, const simplecpp::DUI &dui, bool systemheader, std::vector &filenames, simplecpp::OutputList *outputList) -{ - std::ifstream f; - std::string path = openHeader(f, dui, sourcefile, header, systemheader); - - if (path.empty()) - return std::make_pair(false, nullptr); - + const std::string &path = name_it->first; FileID fileId; if (!getFileId(path, fileId)) - return std::make_pair(false, nullptr); + return std::make_pair(nullptr, false); const auto id_it = mIdMap.find(fileId); if (id_it != mIdMap.end()) { - mNameMap.insert(std::make_pair(std::move(path), id_it->second)); - - return std::make_pair(false, id_it->second); + name_it->second = id_it->second; + return std::make_pair(id_it->second, false); } + std::ifstream f(path); FileData *const data = new FileData {path, TokenList(f, filenames, path, outputList)}; if (dui.removeComments) data->tokens.removeComments(); - mNameMap.insert(std::make_pair(std::move(path), data)); + name_it->second = data; mIdMap.insert(std::make_pair(fileId, data)); mData.push_back(std::unique_ptr(data)); - return std::make_pair(true, data); + return std::make_pair(data, true); } -std::pair simplecpp::FileDataCache::get(const std::string &sourcefile, const std::string &header, const simplecpp::DUI &dui, bool systemheader, std::vector &filenames, simplecpp::OutputList *outputList) +std::pair simplecpp::FileDataCache::get(const std::string &sourcefile, const std::string &header, const simplecpp::DUI &dui, bool systemheader, std::vector &filenames, simplecpp::OutputList *outputList) { - FileData *const data = lookup(sourcefile, header, dui, systemheader); +#define TRYLOAD(path) \ +{ \ + const auto ins = mNameMap.insert(std::make_pair(path, nullptr)); \ + if (ins.second) { \ + const auto load = tryload(ins.first, dui, filenames, outputList); \ + if (load.first != nullptr) \ + return load; \ + } \ + else { \ + return std::make_pair(ins.first->second, false); \ + } \ +} + + if (isAbsolutePath(header)) { + TRYLOAD(simplecpp::simplifyPath(header)) + return std::make_pair(nullptr, false); + } - if (data != nullptr) - return std::make_pair(false, data); + if (!systemheader) { + TRYLOAD(simplecpp::simplifyPath(dirPath(sourcefile) + header)) + } - return load(sourcefile, header, dui, systemheader, filenames, outputList); + for (const auto &includePath : dui.includePaths) { + TRYLOAD(simplecpp::simplifyPath(includePath + "/" + header)) + } + +#undef TRYLOAD + + return std::make_pair(nullptr, false); } bool simplecpp::FileDataCache::getFileId(const std::string &path, FileID &id) @@ -3097,15 +3075,6 @@ bool simplecpp::FileDataCache::getFileId(const std::string &path, FileID &id) #endif } -bool simplecpp::FileDataCache::FileID::operator< (const FileID &that) const -{ -#ifdef SIMPLECPP_WINDOWS - return std::memcmp(&fileIdInfo, &that.fileIdInfo, sizeof(fileIdInfo)) < 0; -#else - return dev < that.dev || (dev == that.dev && ino < that.ino); -#endif -} - simplecpp::FileDataCache simplecpp::load(const simplecpp::TokenList &rawtokens, std::vector &filenames, const simplecpp::DUI &dui, simplecpp::OutputList *outputList) { #ifdef SIMPLECPP_WINDOWS @@ -3122,8 +3091,8 @@ simplecpp::FileDataCache simplecpp::load(const simplecpp::TokenList &rawtokens, const std::string &filename = *it; const auto loadResult = cache.get("", filename, dui, false, filenames, outputList); - const bool loaded = loadResult.first; - FileData *const filedata = loadResult.second; + const bool loaded = loadResult.second; + FileData *const filedata = loadResult.first; if (filedata == nullptr) { if (outputList) { @@ -3170,7 +3139,7 @@ simplecpp::FileDataCache simplecpp::load(const simplecpp::TokenList &rawtokens, const bool systemheader = (htok->str()[0] == '<'); const std::string header(htok->str().substr(1U, htok->str().size() - 2U)); - FileData *const filedata = cache.get(sourcefile, header, dui, systemheader, filenames, outputList).second; + FileData *const filedata = cache.get(sourcefile, header, dui, systemheader, filenames, outputList).first; if (!filedata) continue; @@ -3329,7 +3298,7 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL includetokenstack.push(rawtokens.cfront()); for (std::list::const_iterator it = dui.includes.begin(); it != dui.includes.end(); ++it) { - const FileData *const filedata = cache.get("", *it, dui, false, files, outputList).second; + const FileData *const filedata = cache.get("", *it, dui, false, files, outputList).first; if (filedata != nullptr && filedata->tokens.cfront() != nullptr) includetokenstack.push(filedata->tokens.cfront()); } @@ -3463,7 +3432,7 @@ void simplecpp::preprocess(simplecpp::TokenList &output, const simplecpp::TokenL const bool systemheader = (inctok->str()[0] == '<'); const std::string header(inctok->str().substr(1U, inctok->str().size() - 2U)); - const FileData *const filedata = cache.get(rawtok->location.file(), header, dui, systemheader, files, outputList).second; + const FileData *const filedata = cache.get(rawtok->location.file(), header, dui, systemheader, files, outputList).first; if (filedata == nullptr) { if (outputList) { simplecpp::Output out(files); diff --git a/simplecpp.h b/simplecpp.h index 4ca31697..46c6a8ad 100755 --- a/simplecpp.h +++ b/simplecpp.h @@ -18,6 +18,7 @@ #include #include #include +#include #include #ifdef _WIN32 @@ -411,14 +412,9 @@ namespace simplecpp { FileDataCache &operator=(const FileDataCache &) = delete; FileDataCache &operator=(FileDataCache &&) = default; - /** Fetch the data for a file if it exists in the cache */ - FileData *lookup(const std::string &sourcefile, const std::string &header, const DUI &dui, bool systemheader); - - /** Load a file into the cache and return the loaded data, or return the cached data if the file id is cached */ - std::pair load(const std::string &sourcefile, const std::string &header, const DUI &dui, bool systemheader, std::vector &filenames, OutputList *outputList); - - /** Get the cached data for a file, or load and then return it if it isn't cached */ - std::pair get(const std::string &sourcefile, const std::string &header, const DUI &dui, bool systemheader, std::vector &filenames, OutputList *outputList); + /** Get the cached data for a file, or load and then return it if it isn't cached. + * returns the file data and true if the file was loaded, false if it was cached. */ + std::pair get(const std::string &sourcefile, const std::string &header, const DUI &dui, bool systemheader, std::vector &filenames, OutputList *outputList); void insert(FileData data) { FileData *const newdata = new FileData(std::move(data)); @@ -462,26 +458,57 @@ namespace simplecpp { private: struct FileID { - bool operator< (const FileID &that) const; + struct Hasher; + friend class FileDataCache; #ifdef SIMPLECPP_WINDOWS struct { std::uint64_t VolumeSerialNumber; struct { - std::uint8_t Identifier[16]; + std::uint64_t IdentifierHi; + std::uint64_t IdentifierLo; } FileId; } fileIdInfo; + + bool operator==(const FileID &that) const noexcept + { + return fileIdInfo.VolumeSerialNumber == that.fileIdInfo.VolumeSerialNumber && + fileIdInfo.FileId.IdentifierHi == that.fileIdInfo.FileId.IdentifierHi && + fileIdInfo.FileId.IdentifierLo == that.fileIdInfo.FileId.IdentifierLo; + } #else dev_t dev; ino_t ino; + + bool operator==(const FileID& that) const noexcept + { + return dev == that.dev && ino == that.ino; + } #endif - }; + struct Hasher { + std::size_t operator()(const FileID &id) const + { +#ifdef SIMPLECPP_WINDOWS + return static_cast(id.fileIdInfo.FileId.IdentifierHi ^ id.fileIdInfo.FileId.IdentifierLo ^ + id.fileIdInfo.VolumeSerialNumber); +#else + return static_cast(id.dev << 32) | static_cast(id.ino); +#endif + } + }; + }; + + using name_map_type = std::unordered_map; + using id_map_type = std::unordered_map; static bool getFileId(const std::string &path, FileID &id); + std::pair tryload(const name_map_type::iterator &name_it, const DUI &dui, std::vector &filenames, OutputList *outputList); + container_type mData; - std::map mNameMap; - std::map mIdMap; + name_map_type mNameMap; + id_map_type mIdMap; + }; } From 06c2e8d603c52ef13531843480c11d3f28f6c3a2 Mon Sep 17 00:00:00 2001 From: glank Date: Thu, 3 Jul 2025 15:31:45 +0200 Subject: [PATCH 09/18] Run astyle --- simplecpp.cpp | 2 +- simplecpp.h | 17 +++++++---------- 2 files changed, 8 insertions(+), 11 deletions(-) diff --git a/simplecpp.cpp b/simplecpp.cpp index 07ed0ecf..cb253f14 100755 --- a/simplecpp.cpp +++ b/simplecpp.cpp @@ -428,7 +428,7 @@ class FileStream : public simplecpp::TokenList::Stream { lastStatus = lastCh = fgetc(file); return lastCh; } - virtual int peek() override{ + virtual int peek() override { // keep lastCh intact const int ch = fgetc(file); unget_internal(ch); diff --git a/simplecpp.h b/simplecpp.h index 46c6a8ad..21c984f6 100755 --- a/simplecpp.h +++ b/simplecpp.h @@ -470,33 +470,30 @@ namespace simplecpp { } FileId; } fileIdInfo; - bool operator==(const FileID &that) const noexcept - { + bool operator==(const FileID &that) const noexcept { return fileIdInfo.VolumeSerialNumber == that.fileIdInfo.VolumeSerialNumber && - fileIdInfo.FileId.IdentifierHi == that.fileIdInfo.FileId.IdentifierHi && - fileIdInfo.FileId.IdentifierLo == that.fileIdInfo.FileId.IdentifierLo; + fileIdInfo.FileId.IdentifierHi == that.fileIdInfo.FileId.IdentifierHi && + fileIdInfo.FileId.IdentifierLo == that.fileIdInfo.FileId.IdentifierLo; } #else dev_t dev; ino_t ino; - bool operator==(const FileID& that) const noexcept - { + bool operator==(const FileID& that) const noexcept { return dev == that.dev && ino == that.ino; } #endif struct Hasher { - std::size_t operator()(const FileID &id) const - { + std::size_t operator()(const FileID &id) const { #ifdef SIMPLECPP_WINDOWS return static_cast(id.fileIdInfo.FileId.IdentifierHi ^ id.fileIdInfo.FileId.IdentifierLo ^ - id.fileIdInfo.VolumeSerialNumber); + id.fileIdInfo.VolumeSerialNumber); #else return static_cast(id.dev << 32) | static_cast(id.ino); #endif } }; - }; + }; using name_map_type = std::unordered_map; using id_map_type = std::unordered_map; From 4033f629961952841487f7d86b59e0975614cd29 Mon Sep 17 00:00:00 2001 From: glank Date: Thu, 3 Jul 2025 15:40:54 +0200 Subject: [PATCH 10/18] Fix clang-tidy issues --- simplecpp.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/simplecpp.cpp b/simplecpp.cpp index cb253f14..c68decf0 100755 --- a/simplecpp.cpp +++ b/simplecpp.cpp @@ -45,7 +45,6 @@ # include #else # include -# include #endif static bool isHex(const std::string &s) From c40cf32a6899c2a7315dba608f26b2423959d972 Mon Sep 17 00:00:00 2001 From: glank Date: Thu, 3 Jul 2025 15:57:59 +0200 Subject: [PATCH 11/18] Fix windows include order --- simplecpp.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/simplecpp.cpp b/simplecpp.cpp index c68decf0..b96196bd 100755 --- a/simplecpp.cpp +++ b/simplecpp.cpp @@ -3,15 +3,15 @@ * Copyright (C) 2016-2023 simplecpp team */ -#include "simplecpp.h" - -#ifdef SIMPLECPP_WINDOWS +#if defined(_WIN32) || defined(__CYGWIN__) || defined(__MINGW32__) # define _WIN32_WINNT 0x0602 # define NOMINMAX # include # undef ERROR #endif +#include "simplecpp.h" + #include #include #include From f97e0936ad93a26850c534a864876feb03a069d4 Mon Sep 17 00:00:00 2001 From: glank Date: Thu, 3 Jul 2025 16:02:09 +0200 Subject: [PATCH 12/18] Fix FileID Hash for 32-bit hash --- simplecpp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/simplecpp.h b/simplecpp.h index 21c984f6..ead944d5 100755 --- a/simplecpp.h +++ b/simplecpp.h @@ -489,7 +489,7 @@ namespace simplecpp { return static_cast(id.fileIdInfo.FileId.IdentifierHi ^ id.fileIdInfo.FileId.IdentifierLo ^ id.fileIdInfo.VolumeSerialNumber); #else - return static_cast(id.dev << 32) | static_cast(id.ino); + return static_cast(id.dev) ^ static_cast(id.ino); #endif } }; From c47159dd73e3bfae2e42cc473d05b74b8131fcf4 Mon Sep 17 00:00:00 2001 From: glank Date: Thu, 3 Jul 2025 18:58:09 +0200 Subject: [PATCH 13/18] Fix early rejection --- simplecpp.cpp | 49 +++++++++++++++++++++++++++++++------------------ 1 file changed, 31 insertions(+), 18 deletions(-) diff --git a/simplecpp.cpp b/simplecpp.cpp index b96196bd..5e35c11f 100755 --- a/simplecpp.cpp +++ b/simplecpp.cpp @@ -3017,33 +3017,46 @@ std::pair simplecpp::FileDataCache::tryload(const F std::pair simplecpp::FileDataCache::get(const std::string &sourcefile, const std::string &header, const simplecpp::DUI &dui, bool systemheader, std::vector &filenames, simplecpp::OutputList *outputList) { -#define TRYLOAD(path) \ -{ \ - const auto ins = mNameMap.insert(std::make_pair(path, nullptr)); \ - if (ins.second) { \ - const auto load = tryload(ins.first, dui, filenames, outputList); \ - if (load.first != nullptr) \ - return load; \ - } \ - else { \ - return std::make_pair(ins.first->second, false); \ - } \ -} - if (isAbsolutePath(header)) { - TRYLOAD(simplecpp::simplifyPath(header)) + const auto ins = mNameMap.insert(std::make_pair(simplecpp::simplifyPath(header), nullptr)); + + if (ins.second) { + const auto load = tryload(ins.first, dui, filenames, outputList); + if (load.first != nullptr) + return load; + } + else { + return std::make_pair(ins.first->second, false); + } + return std::make_pair(nullptr, false); } if (!systemheader) { - TRYLOAD(simplecpp::simplifyPath(dirPath(sourcefile) + header)) + const auto ins = mNameMap.insert(std::make_pair(simplecpp::simplifyPath(dirPath(sourcefile) + header), nullptr)); + + if (ins.second) { + const auto load = tryload(ins.first, dui, filenames, outputList); + if (load.first != nullptr) + return load; + } + else if (ins.first->second != nullptr) { + return std::make_pair(ins.first->second, false); + } } for (const auto &includePath : dui.includePaths) { - TRYLOAD(simplecpp::simplifyPath(includePath + "/" + header)) - } + const auto ins = mNameMap.insert(std::make_pair(simplecpp::simplifyPath(includePath + "/" + header), nullptr)); -#undef TRYLOAD + if (ins.second) { + const auto load = tryload(ins.first, dui, filenames, outputList); + if (load.first != nullptr) + return load; + } + else if (ins.first->second != nullptr) { + return std::make_pair(ins.first->second, false); + } + } return std::make_pair(nullptr, false); } From 91b0bf75520fa6a4de29cb6645a8d2695ea733ec Mon Sep 17 00:00:00 2001 From: glank Date: Thu, 3 Jul 2025 19:50:02 +0200 Subject: [PATCH 14/18] Fix shadowing style issue --- simplecpp.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/simplecpp.cpp b/simplecpp.cpp index 5e35c11f..a9e773d1 100755 --- a/simplecpp.cpp +++ b/simplecpp.cpp @@ -3021,9 +3021,9 @@ std::pair simplecpp::FileDataCache::get(const std:: const auto ins = mNameMap.insert(std::make_pair(simplecpp::simplifyPath(header), nullptr)); if (ins.second) { - const auto load = tryload(ins.first, dui, filenames, outputList); - if (load.first != nullptr) - return load; + const auto ret = tryload(ins.first, dui, filenames, outputList); + if (ret.first != nullptr) + return ret; } else { return std::make_pair(ins.first->second, false); @@ -3036,9 +3036,9 @@ std::pair simplecpp::FileDataCache::get(const std:: const auto ins = mNameMap.insert(std::make_pair(simplecpp::simplifyPath(dirPath(sourcefile) + header), nullptr)); if (ins.second) { - const auto load = tryload(ins.first, dui, filenames, outputList); - if (load.first != nullptr) - return load; + const auto ret = tryload(ins.first, dui, filenames, outputList); + if (ret.first != nullptr) + return ret; } else if (ins.first->second != nullptr) { return std::make_pair(ins.first->second, false); @@ -3049,9 +3049,9 @@ std::pair simplecpp::FileDataCache::get(const std:: const auto ins = mNameMap.insert(std::make_pair(simplecpp::simplifyPath(includePath + "/" + header), nullptr)); if (ins.second) { - const auto load = tryload(ins.first, dui, filenames, outputList); - if (load.first != nullptr) - return load; + const auto ret = tryload(ins.first, dui, filenames, outputList); + if (ret.first != nullptr) + return ret; } else if (ins.first->second != nullptr) { return std::make_pair(ins.first->second, false); From 6c728b6cf12699a7d1c77c7a232a2ffc5f0b3546 Mon Sep 17 00:00:00 2001 From: glank Date: Thu, 3 Jul 2025 19:55:50 +0200 Subject: [PATCH 15/18] Run astyle --- simplecpp.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/simplecpp.cpp b/simplecpp.cpp index a9e773d1..46647d65 100755 --- a/simplecpp.cpp +++ b/simplecpp.cpp @@ -3024,8 +3024,7 @@ std::pair simplecpp::FileDataCache::get(const std:: const auto ret = tryload(ins.first, dui, filenames, outputList); if (ret.first != nullptr) return ret; - } - else { + } else { return std::make_pair(ins.first->second, false); } @@ -3039,8 +3038,7 @@ std::pair simplecpp::FileDataCache::get(const std:: const auto ret = tryload(ins.first, dui, filenames, outputList); if (ret.first != nullptr) return ret; - } - else if (ins.first->second != nullptr) { + } else if (ins.first->second != nullptr) { return std::make_pair(ins.first->second, false); } } @@ -3052,8 +3050,7 @@ std::pair simplecpp::FileDataCache::get(const std:: const auto ret = tryload(ins.first, dui, filenames, outputList); if (ret.first != nullptr) return ret; - } - else if (ins.first->second != nullptr) { + } else if (ins.first->second != nullptr) { return std::make_pair(ins.first->second, false); } } From 946c3441d2b997384d126f041611e8390c6d383e Mon Sep 17 00:00:00 2001 From: glank Date: Fri, 4 Jul 2025 10:31:15 +0200 Subject: [PATCH 16/18] Fix nits --- simplecpp.cpp | 37 ++++++++++++++++++++----------------- simplecpp.h | 6 +++--- 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/simplecpp.cpp b/simplecpp.cpp index 46647d65..62c5100f 100755 --- a/simplecpp.cpp +++ b/simplecpp.cpp @@ -2988,18 +2988,18 @@ static std::string openHeader(std::ifstream &f, const simplecpp::DUI &dui, const return ""; } -std::pair simplecpp::FileDataCache::tryload(const FileDataCache::name_map_type::iterator &name_it, const simplecpp::DUI &dui, std::vector &filenames, simplecpp::OutputList *outputList) +std::pair simplecpp::FileDataCache::tryload(FileDataCache::name_map_type::iterator &name_it, const simplecpp::DUI &dui, std::vector &filenames, simplecpp::OutputList *outputList) { const std::string &path = name_it->first; FileID fileId; if (!getFileId(path, fileId)) - return std::make_pair(nullptr, false); + return {nullptr, false}; const auto id_it = mIdMap.find(fileId); if (id_it != mIdMap.end()) { name_it->second = id_it->second; - return std::make_pair(id_it->second, false); + return {id_it->second, false}; } std::ifstream f(path); @@ -3009,53 +3009,56 @@ std::pair simplecpp::FileDataCache::tryload(const F data->tokens.removeComments(); name_it->second = data; - mIdMap.insert(std::make_pair(fileId, data)); - mData.push_back(std::unique_ptr(data)); + mIdMap.emplace(fileId, data); + mData.emplace_back(data); - return std::make_pair(data, true); + return {data, true}; } std::pair simplecpp::FileDataCache::get(const std::string &sourcefile, const std::string &header, const simplecpp::DUI &dui, bool systemheader, std::vector &filenames, simplecpp::OutputList *outputList) { if (isAbsolutePath(header)) { - const auto ins = mNameMap.insert(std::make_pair(simplecpp::simplifyPath(header), nullptr)); + auto ins = mNameMap.emplace(simplecpp::simplifyPath(header), nullptr); if (ins.second) { const auto ret = tryload(ins.first, dui, filenames, outputList); - if (ret.first != nullptr) + if (ret.first != nullptr) { return ret; + } } else { - return std::make_pair(ins.first->second, false); + return {ins.first->second, false}; } - return std::make_pair(nullptr, false); + return {nullptr, false}; } if (!systemheader) { - const auto ins = mNameMap.insert(std::make_pair(simplecpp::simplifyPath(dirPath(sourcefile) + header), nullptr)); + auto ins = mNameMap.emplace(simplecpp::simplifyPath(dirPath(sourcefile) + header), nullptr); if (ins.second) { const auto ret = tryload(ins.first, dui, filenames, outputList); - if (ret.first != nullptr) + if (ret.first != nullptr) { return ret; + } } else if (ins.first->second != nullptr) { - return std::make_pair(ins.first->second, false); + return {ins.first->second, false}; } } for (const auto &includePath : dui.includePaths) { - const auto ins = mNameMap.insert(std::make_pair(simplecpp::simplifyPath(includePath + "/" + header), nullptr)); + auto ins = mNameMap.emplace(simplecpp::simplifyPath(includePath + "/" + header), nullptr); if (ins.second) { const auto ret = tryload(ins.first, dui, filenames, outputList); - if (ret.first != nullptr) + if (ret.first != nullptr) { return ret; + } } else if (ins.first->second != nullptr) { - return std::make_pair(ins.first->second, false); + return {ins.first->second, false}; } } - return std::make_pair(nullptr, false); + return {nullptr, false}; } bool simplecpp::FileDataCache::getFileId(const std::string &path, FileID &id) diff --git a/simplecpp.h b/simplecpp.h index ead944d5..0931fb22 100755 --- a/simplecpp.h +++ b/simplecpp.h @@ -419,8 +419,8 @@ namespace simplecpp { void insert(FileData data) { FileData *const newdata = new FileData(std::move(data)); - mData.push_back(std::unique_ptr(newdata)); - mNameMap.insert(std::make_pair(newdata->filename, newdata)); + mData.emplace_back(newdata); + mNameMap.emplace(newdata->filename, newdata); } void clear() { @@ -500,7 +500,7 @@ namespace simplecpp { static bool getFileId(const std::string &path, FileID &id); - std::pair tryload(const name_map_type::iterator &name_it, const DUI &dui, std::vector &filenames, OutputList *outputList); + std::pair tryload(name_map_type::iterator &name_it, const DUI &dui, std::vector &filenames, OutputList *outputList); container_type mData; name_map_type mNameMap; From 4e4936653fd26ead66dd55ab4e9f93154562be4e Mon Sep 17 00:00:00 2001 From: glank Date: Fri, 4 Jul 2025 10:35:26 +0200 Subject: [PATCH 17/18] Fix clang-tidy issues --- simplecpp.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/simplecpp.cpp b/simplecpp.cpp index 62c5100f..a471190a 100755 --- a/simplecpp.cpp +++ b/simplecpp.cpp @@ -28,7 +28,6 @@ #include #include #include -#include #include #include #include From 80860b2c5f98041bedd2a5346872af2687db0dbf Mon Sep 17 00:00:00 2001 From: glank Date: Fri, 4 Jul 2025 10:52:37 +0200 Subject: [PATCH 18/18] Remove left over friend and forward declaration --- simplecpp.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/simplecpp.h b/simplecpp.h index 0931fb22..b69bfee4 100755 --- a/simplecpp.h +++ b/simplecpp.h @@ -458,9 +458,6 @@ namespace simplecpp { private: struct FileID { - struct Hasher; - friend class FileDataCache; - #ifdef SIMPLECPP_WINDOWS struct { std::uint64_t VolumeSerialNumber;