std::string trim

本文介绍如何使用C++标准库函数实现字符串的前导和尾随空白字符的删除,包括ltrim、rtrim及trim函数的具体实现方法。
部署运行你感兴趣的模型镜像

代码来自

https://stackoverflow.com/questions/216823/whats-the-best-way-to-trim-stdstring?page=1&tab=votes#tab-top


std::string 没有trim函数,需要自己实现。

ltrim实现如下:

// trim from start (inplace)

staticinlinevoid ltrim(std::string &s) {

    s.erase(s.begin(), std::find_if(s.begin(),s.end(), [](int ch) {

        return !std::isspace(ch);

    }));

}

std::string的erase()函数有如下三种形式。http://www.cplusplus.com/reference/string/string/erase/

sequence (1)

 string& erase (size_t pos = 0, size_t len = npos);

character (2)

iterator erase (const_iterator p);

range (3)

iterator erase (const_iterator first, const_iterator last);

1 从pos开始删除len个字符

2 删除p指向的字符

3 删除半开区间[first,last)内的字符。(如果first和last一样,则不删除任何字符。)


ltrim使用的是第三种形式。

 

std::find_if函数原型。http://www.cplusplus.com/reference/algorithm/find_if/

 

template<class InputIterator, class UnaryPredicate>
  InputIterator find_if (InputIterator first, InputIterator last, UnaryPredicate pred)
{
  while (first!=last) {
    if (pred(*first)) return first;
    ++first;
  }
  return last;
}

 

其中,第三个参数pred是一个函数,表示搜索的条件,符合条件即返回。如果没有符合条件的iterator,就会返回last。在实际使用中,last经常是end。而end不是最后一个元素,而是位于最后一个元素的后面。因此,不会出现明明没有符合条件的元素,却会把最后一个元素错误的当成符合条件的元素而返回的问题。

 

下面的例子演示了如何找到第一个奇数。

 

// find_if example
#include <iostream>     // std::cout
#include <algorithm>    // std::find_if
#include <vector>       // std::vector
 
bool IsOdd (int i) {
  return ((i%2)==1);
}
 
int main () {
  std::vector<int> myvector;
 
  myvector.push_back(10);
  myvector.push_back(25);
  myvector.push_back(40);
  myvector.push_back(55);
 
  std::vector<int>::iterator it = std::find_if (myvector.begin(), myvector.end(), IsOdd);
  std::cout << "The first odd value is " << *it << '\n';
 
  return 0;
}

Output:

The first odd value is 25

 

如果上面程序中push_back的数字都是偶数的话,也不会把最后一个偶数错误地输出,而是会出现运行时错误。因为*it表示end中的内容,而end中没有任何内容。

 

[](int ch) { return !std::isspace(ch); }

这是一个lambda函数(匿名函数),相当于上面例子中的IsOdd。

在ltrim中的意思是不是空白的字符。

空白字符不只是空格,还包含下表中的字符。http://www.cplusplus.com/reference/cctype/isspace/

For the "C" locale, white-spacecharacters are any of:

' '

(0x20)

space (SPC)

'\t'

(0x09)

horizontal tab (TAB)

'\n'

(0x0a)

newline (LF)

'\v'

(0x0b)

vertical tab (VT)

'\f'

(0x0c)

feed (FF)

'\r'

(0x0d)

carriage return (CR)

 

其实,这里也可以把这个lambda函数写成有名字的函数,就像上面那个IsOdd。使用lambda只是更简洁一点而已。

 

关于lambda函数,这篇文章讲得非常清晰。

https://www.cnblogs.com/pzhfei/archive/2013/01/14/lambda_expression.html


ltrim的机制如下:

find_if会找到第一个不是空白的字符,erase会删除从第一个字符到找到的那个字符之前的所有字符。

如果string的第一个字符就不是空白字符,用半开区间表示就是[0,0),所以不会删除任何字符。

如果string全部是空白字符(比如说10个空格),找到的第一个不是空白的字符就是第11个字符,用半开区间表示就是[0,10),所以不会漏删最后一个空格。


全部的代码如下:

 

#include<algorithm>

#include<cctype>

#include<locale>

 

// trim from start (inplace)

staticinlinevoid ltrim(std::string &s) {

    s.erase(s.begin(), std::find_if(s.begin(),s.end(), [](int ch) {

        return !std::isspace(ch);

    }));

}

 

// trim from end (inplace)

staticinlinevoid rtrim(std::string &s) {

    s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) {

        return !std::isspace(ch);

    }).base(), s.end());

}

 

// trim from both ends (inplace)

staticinlinevoid trim(std::string &s) {

    ltrim(s);

    rtrim(s);

}

 

// trim from start(copying)

staticinline std::string ltrim_copy(std::string s) {

    ltrim(s);

    return s;

}

 

// trim from end (copying)

staticinline std::string rtrim_copy(std::string s) {

    rtrim(s);

    return s;

}

 

// trim from both ends(copying)

staticinline std::string trim_copy(std::string s) {

    trim(s);

    return s;

}



您可能感兴趣的与本文相关的镜像

ACE-Step

ACE-Step

音乐合成
ACE-Step

ACE-Step是由中国团队阶跃星辰(StepFun)与ACE Studio联手打造的开源音乐生成模型。 它拥有3.5B参数量,支持快速高质量生成、强可控性和易于拓展的特点。 最厉害的是,它可以生成多种语言的歌曲,包括但不限于中文、英文、日文等19种语言

// ConfigRemoteSync.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <windows.h> #include <iostream> #include <string> #include <vector> #include <map> #include <fstream> #include <sstream> #include <thread> #include <chrono> #include <algorithm> #include <regex> #include <wininet.h> #include <winsock2.h> #include <ws2tcpip.h> class ConfigSyncManager { private: std::map<std::string, std::string> localConfig; std::map<std::string, std::string> remoteConfig; std::vector<std::string> serverEndpoints; std::string currentServer; std::atomic<bool> shouldStop{ false }; std::thread syncThread; int syncInterval; public: ConfigSyncManager() { std::cout << "=== 配置参数远程同步 ===" << std::endl; initializeSyncManager(); } ~ConfigSyncManager() { cleanup(); } void initializeSyncManager() { // 初始化本地配置 initializeLocalConfig(); // 设置服务器端点 setupServerEndpoints(); // 设置同步间隔 syncInterval = 300; // 5分钟 std::cout << "配置同步管理器初始化完成" << std::endl; std::cout << "同步间隔: " << syncInterval << " 秒" << std::endl; } void initializeLocalConfig() { localConfig["version"] = "1.0.0"; localConfig["update_interval"] = "300"; localConfig["log_level"] = "INFO"; localConfig["max_connections"] = "10"; localConfig["timeout"] = "30"; localConfig["retry_count"] = "3"; localConfig["enable_encryption"] = "true"; localConfig["server_url"] = "https://config.example.com"; std::cout << "本地配置初始化完成" << std::endl; } void setupServerEndpoints() { serverEndpoints = { "https://config1.example.com/api/config", "https://config2.example.com/api/config", "https://backup-config.example.com/api/config" }; currentServer = serverEndpoints[0]; std::cout << "服务器端点配置完成" << std::endl; for (const auto& endpoint : serverEndpoints) { std::cout << "- " << endpoint << std::endl; } } void startSyncThread() { std::cout << "\n启动配置同步线程..." << std::endl; syncThread = std::thread([this]() { while (!shouldStop) { performConfigSync(); std::this_thread::sleep_for(std::chrono::seconds(syncInterval)); } }); } void performConfigSync() { std::cout << "执行配置同步..." << std::endl; // 尝试从远程服务器获取配置 std::string configData = fetchRemoteConfig(); if (!configData.empty()) { // 解析配置数据 parseConfigData(configData); // 比较并更新配置 compareAndUpdateConfig(); // 保存配置到本地 saveConfigToLocal(); } else { std::cout << "无法获取远程配置,使用本地配置" << std::endl; } } std::string fetchRemoteConfig() { std::cout << "从服务器获取配置: " << currentServer << std::endl; // 模拟HTTP请求 std::string configData = simulateHTTPRequest(currentServer); if (configData.empty()) { // 尝试备用服务器 for (size_t i = 1; i < serverEndpoints.size(); ++i) { std::cout << "尝试备用服务器: " << serverEndpoints[i] << std::endl; configData = simulateHTTPRequest(serverEndpoints[i]); if (!configData.empty()) { currentServer = serverEndpoints[i]; break; } } } return configData; } std::string simulateHTTPRequest(const std::string& url) { // 模拟HTTP GET请求 std::cout << "发送HTTP请求到: " << url << std::endl; // 模拟网络延迟 std::this_thread::sleep_for(std::chrono::milliseconds(500)); // 返回模拟的JSON配置数据 return generateMockConfigData(); } std::string generateMockConfigData() { std::stringstream json; json << "{\n"; json << " \"version\": \"1.1.0\",\n"; json << " \"update_interval\": \"180\",\n"; json << " \"log_level\": \"DEBUG\",\n"; json << " \"max_connections\": \"15\",\n"; json << " \"timeout\": \"45\",\n"; json << " \"retry_count\": \"5\",\n"; json << " \"enable_encryption\": \"true\",\n"; json << " \"server_url\": \"https://new-config.example.com\",\n"; json << " \"new_feature\": \"enabled\",\n"; json << " \"security_level\": \"high\",\n"; json << " \"backup_servers\": [\n"; json << " \"https://backup1.example.com\",\n"; json << " \"https://backup2.example.com\"\n"; json << " ]\n"; json << "}"; return json.str(); } void parseConfigData(const std::string& configData) { std::cout << "解析配置数据..." << std::endl; // 清空远程配置 remoteConfig.clear(); // 简单的JSON解析 std::vector<std::string> lines = splitString(configData, "\n"); for (const auto& line : lines) { std::string trimmedLine = trimString(line); // 跳过空行和括号 if (trimmedLine.empty() || trimmedLine == "{" || trimmedLine == "}" || trimmedLine.find("[") != std::string::npos || trimmedLine.find("]") != std::string::npos) { continue; } // 解析键值对 size_t colonPos = trimmedLine.find(":"); if (colonPos != std::string::npos) { std::string key = trimString(trimmedLine.substr(0, colonPos)); std::string value = trimString(trimmedLine.substr(colonPos + 1)); // 移除引号 if (value.length() >= 2 && value[0] == '"' && value[value.length() - 1] == '"') { value = value.substr(1, value.length() - 2); } // 移除逗号 if (!value.empty() && value[value.length() - 1] == ',') { value = value.substr(0, value.length() - 1); } remoteConfig[key] = value; std::cout << "解析配置: " << key << " = " << value << std::endl; } } } void compareAndUpdateConfig() { std::cout << "\n比较配置差异..." << std::endl; std::vector<std::string> updatedKeys; for (const auto& remote : remoteConfig) { auto localIt = localConfig.find(remote.first); if (localIt == localConfig.end()) { // 新配置项 localConfig[remote.first] = remote.second; updatedKeys.push_back("新增: " + remote.first); std::cout << "新增配置: " << remote.first << " = " << remote.second << std::endl; } else if (localIt->second != remote.second) { // 配置值不同 std::cout << "更新配置: " << remote.first << " (" << localIt->second << " -> " << remote.second << ")" << std::endl; localIt->second = remote.second; updatedKeys.push_back("更新: " + remote.first); } } if (!updatedKeys.empty()) { std::cout << "配置更新完成,共 " << updatedKeys.size() << " 项更新" << std::endl; for (const auto& update : updatedKeys) { std::cout << "- " << update << std::endl; } } else { std::cout << "配置无变化" << std::endl; } } void saveConfigToLocal() { std::cout << "保存配置到本地..." << std::endl; std::string configFile = "local_config.json"; std::ofstream file(configFile); if (file.is_open()) { file << "{\n"; bool first = true; for (const auto& config : localConfig) { if (!first) file << ",\n"; file << " \"" << config.first << "\": \"" << config.second << "\""; first = false; } file << "\n}"; file.close(); std::cout << "配置已保存到: " << configFile << std::endl; } } void loadConfigFromLocal() { std::cout << "从本地加载配置..." << std::endl; std::string configFile = "local_config.json"; std::ifstream file(configFile); if (file.is_open()) { std::string content((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>()); file.close(); parseConfigData(content); compareAndUpdateConfig(); } } void validateConfig() { std::cout << "\n验证配置有效性..." << std::endl; std::vector<std::string> errors; // 检查必需配置项 std::vector<std::string> requiredKeys = { "version", "update_interval", "log_level" }; for (const auto& key : requiredKeys) { if (localConfig.find(key) == localConfig.end()) { errors.push_back("缺少必需配置: " + key); } } // 验证数值配置 try { int interval = std::stoi(localConfig["update_interval"]); if (interval < 60 || interval > 3600) { errors.push_back("更新间隔无效: " + std::to_string(interval)); } } catch (...) { errors.push_back("更新间隔格式错误"); } if (errors.empty()) { std::cout << "配置验证通过" << std::endl; } else { std::cout << "配置验证失败:" << std::endl; for (const auto& error : errors) { std::cout << "- " << error << std::endl; } } } void applyConfigChanges() { std::cout << "\n应用配置更改..." << std::endl; // 应用新的同步间隔 if (localConfig.find("update_interval") != localConfig.end()) { try { int newInterval = std::stoi(localConfig["update_interval"]); if (newInterval != syncInterval) { syncInterval = newInterval; std::cout << "同步间隔已更新: " << syncInterval << " 秒" << std::endl; } } catch (...) { std::cout << "同步间隔更新失败" << std::endl; } } // 应用日志级别 if (localConfig.find("log_level") != localConfig.end()) { std::cout << "日志级别已更新: " << localConfig["log_level"] << std::endl; } // 应用连接数限制 if (localConfig.find("max_connections") != localConfig.end()) { std::cout << "最大连接数已更新: " << localConfig["max_connections"] << std::endl; } std::cout << "配置更改应用完成" << std::endl; } std::vector<std::string> splitString(const std::string& str, const std::string& delimiter) { std::vector<std::string> tokens; size_t prev = 0, pos = 0; do { pos = str.find(delimiter, prev); if (pos == std::string::npos) pos = str.length(); std::string token = str.substr(prev, pos - prev); if (!token.empty()) tokens.push_back(token); prev = pos + delimiter.length(); } while (pos < str.length() && prev < str.length()); return tokens; } std::string trimString(const std::string& str) { size_t start = str.find_first_not_of(" \t\r\n"); if (start == std::string::npos) return ""; size_t end = str.find_last_not_of(" \t\r\n"); return str.substr(start, end - start + 1); } void cleanup() { shouldStop = true; if (syncThread.joinable()) { syncThread.join(); } } void executeConfigSync() { std::cout << "开始配置参数远程同步..." << std::endl; // 显示当前配置 std::cout << "\n当前本地配置:" << std::endl; for (const auto& config : localConfig) { std::cout << "- " << config.first << ": " << config.second << std::endl; } // 启动同步线程 startSyncThread(); // 执行初始同步 performConfigSync(); // 验证配置 validateConfig(); // 应用配置更改 applyConfigChanges(); // 运行一段时间 std::this_thread::sleep_for(std::chrono::seconds(10)); // 停止同步 shouldStop = true; if (syncThread.joinable()) { syncThread.join(); } std::cout << "\n配置参数远程同步完成!" << std::endl; } }; int main() { SetConsoleOutputCP(CP_UTF8); ConfigSyncManager syncManager; syncManager.executeConfigSync(); std::cout << "\n按任意键继续..."; std::cin.get(); return 0; }用vs2015编译的时候报错了,修改代码并给出完整的C++代码
07-11
不是,而是修改下面的源代码 /****************************************************************************** * SystemC DLL Modifier for VS2015 (C++11) - Ultimate Template API Fix * Completely fixed template class DLL API marker position issue * Enhanced to support .cpp file class definitions and comment formats ******************************************************************************/ #include <iostream> #include <fstream> #include <string> #include <vector> #include <algorithm> #include <set> #include <cctype> #include <windows.h> // VS2015 Check #ifdef _MSC_VER #if _MSC_VER < 1900 #error "This program requires Visual Studio 2015 or later" #endif #endif // Configuration structure struct Config { std::string systemcDllApi = "SYSTEMC_DLL_API"; std::string tlmDllApi = "TLM_DLL_API"; std::string includeConfig = "#include \"config.hpp\""; std::set<std::string> headerExtensions = { ".h", ".hpp", ".hxx" }; std::set<std::string> sourceExtensions = { ".cpp", ".cxx", ".cc" }; std::set<std::string> excludeFiles = { "config.hpp", "Makefile", "CMakeLists.txt" }; std::set<std::string> excludeDirs = { ".git", ".svn", ".vs", "Debug", "Release", "build", "x64", "x86" }; }; // Statistics struct Statistics { int totalFiles = 0; int processedFiles = 0; int modifiedFiles = 0; int skippedFiles = 0; int errorFiles = 0; }; // String Utilities Class class StringUtils { public: static std::string trim(const std::string& str) { if (str.empty()) return str; size_t start = 0; while (start < str.length() && std::isspace(static_cast<unsigned char>(str[start]))) { ++start; } if (start >= str.length()) return ""; size_t end = str.length() - 1; while (end > start && std::isspace(static_cast<unsigned char>(str[end]))) { --end; } return str.substr(start, end - start + 1); } static bool startsWith(const std::string& str, const std::string& prefix) { if (str.length() < prefix.length()) return false; return str.compare(0, prefix.length(), prefix) == 0; } static bool endsWith(const std::string& str, const std::string& suffix) { if (str.length() < suffix.length()) return false; return str.compare(str.length() - suffix.length(), suffix.length(), suffix) == 0; } static bool contains(const std::string& str, const std::string& substr) { if (substr.empty()) return true; if (str.empty()) return false; return str.find(substr) != std::string::npos; } static std::string replace(const std::string& str, const std::string& from, const std::string& to) { if (from.empty() || str.empty()) return str; std::string result = str; size_t pos = 0; while ((pos = result.find(from, pos)) != std::string::npos) { result.replace(pos, from.length(), to); pos += to.length(); } return result; } static std::string toLower(const std::string& str) { std::string result = str; std::transform(result.begin(), result.end(), result.begin(), [](unsigned char c) { return static_cast<char>(std::tolower(c)); }); return result; } static std::string toUpper(const std::string& str) { std::string result = str; std::transform(result.begin(), result.end(), result.begin(), [](unsigned char c) { return static_cast<char>(std::toupper(c)); }); return result; } static std::string getFileName(const std::string& path) { if (path.empty()) return ""; size_t pos = path.find_last_of("\\/"); if (pos == std::string::npos) return path; return path.substr(pos + 1); } static std::string getExtension(const std::string& path) { if (path.empty()) return ""; size_t pos = path.find_last_of("."); if (pos == std::string::npos) return ""; return path.substr(pos); } static std::string getDirectory(const std::string& path) { if (path.empty()) return ""; size_t pos = path.find_last_of("\\/"); if (pos == std::string::npos) return ""; return path.substr(0, pos); } static std::vector<std::string> split(const std::string& str, char delimiter) { std::vector<std::string> tokens; if (str.empty()) return tokens; size_t start = 0; size_t end = 0; while ((end = str.find(delimiter, start)) != std::string::npos) { if (end != start) { tokens.push_back(str.substr(start, end - start)); } start = end + 1; } if (start < str.length()) { tokens.push_back(str.substr(start)); } return tokens; } // Check if line is a comment separator static bool isCommentSeparator(const std::string& str) { std::string trimmed = trim(str); return startsWith(trimmed, "// ---") || startsWith(trimmed, "/* ---") || (contains(trimmed, "---") && (startsWith(trimmed, "//") || startsWith(trimmed, "/*"))); } // Check if line is a class comment header static bool isClassCommentHeader(const std::string& str) { std::string trimmed = trim(str); return (contains(trimmed, "CLASS :") || contains(trimmed, "class")) && (startsWith(trimmed, "//") || startsWith(trimmed, "/*")); } }; // File System Utilities Class class FileSystemUtils { public: static bool fileExists(const std::string& path) { if (path.empty()) return false; DWORD attrs = GetFileAttributesA(path.c_str()); if (attrs == INVALID_FILE_ATTRIBUTES) return false; return (attrs & FILE_ATTRIBUTE_DIRECTORY) == 0; } static bool directoryExists(const std::string& path) { if (path.empty()) return false; DWORD attrs = GetFileAttributesA(path.c_str()); if (attrs == INVALID_FILE_ATTRIBUTES) return false; return (attrs & FILE_ATTRIBUTE_DIRECTORY) != 0; } static bool createDirectory(const std::string& path) { if (path.empty()) return false; if (directoryExists(path)) return true; return CreateDirectoryA(path.c_str(), NULL) != 0; } static bool createDirectoryRecursive(const std::string& path) { if (path.empty()) return false; if (directoryExists(path)) return true; std::string normalizedPath = path; std::replace(normalizedPath.begin(), normalizedPath.end(), '/', '\\'); std::vector<std::string> components = StringUtils::split(normalizedPath, '\\'); if (components.empty()) return false; std::string currentPath; if (components[0].find(':') != std::string::npos) { currentPath = components[0] + "\\"; components.erase(components.begin()); } for (const auto& component : components) { if (component.empty()) continue; if (!currentPath.empty() && currentPath.back() != '\\') { currentPath += "\\"; } currentPath += component; if (!createDirectory(currentPath)) { return false; } } return true; } static bool copyFile(const std::string& from, const std::string& to) { if (from.empty() || to.empty()) return false; if (!fileExists(from)) return false; std::string targetDir = StringUtils::getDirectory(to); if (!targetDir.empty() && !createDirectoryRecursive(targetDir)) { return false; } return ::CopyFileA(from.c_str(), to.c_str(), FALSE) != 0; } static bool findFiles(const std::string& directory, std::vector<std::string>& files, std::vector<std::string>& directories, bool recursive = true) { if (!directoryExists(directory)) return false; std::string searchPath = directory + "\\*"; WIN32_FIND_DATAA findData; HANDLE hFind = FindFirstFileA(searchPath.c_str(), &findData); if (hFind == INVALID_HANDLE_VALUE) { return false; } do { if (strcmp(findData.cFileName, ".") == 0 || strcmp(findData.cFileName, "..") == 0) { continue; } std::string fullPath = directory + "\\" + findData.cFileName; if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { std::string dirName = findData.cFileName; if (isDirectoryExcluded(dirName)) continue; directories.push_back(fullPath); if (recursive) { findFiles(fullPath, files, directories, recursive); } } else { files.push_back(fullPath); } } while (FindNextFileA(hFind, &findData) != 0); FindClose(hFind); return true; } private: static bool isDirectoryExcluded(const std::string& dirName) { static std::set<std::string> excludedDirs = { ".git", ".svn", ".vs", "Debug", "Release", "build", "x64", "x86", "obj", "bin" }; std::string lowerName = StringUtils::toLower(dirName); return excludedDirs.find(lowerName) != excludedDirs.end(); } }; // Main Processor Class - Ultimate Template API Fix class SystemCDLLModifier { private: Config config; Statistics stats; bool dryRun; bool createBackup; std::string backupDir; public: SystemCDLLModifier(bool dryRunMode = false, bool backup = false) : dryRun(dryRunMode), createBackup(backup) {} bool processDirectory(const std::string& sourceDir) { std::cout << "Processing directory: " << sourceDir << std::endl; if (!FileSystemUtils::directoryExists(sourceDir)) { std::cerr << "Error: Directory does not exist: " << sourceDir << std::endl; return false; } // Create backup if (createBackup && !dryRun) { std::cout << "\nCreating backup..." << std::endl; if (!createBackupDirectory(sourceDir)) { std::cout << "Backup creation had issues!" << std::endl; std::cout << "Do you want to continue without backup? (y/n): "; char response; std::cin >> response; if (response != 'y' && response != 'Y') { return false; } } } // Process files std::vector<std::string> files; std::vector<std::string> directories; if (!FileSystemUtils::findFiles(sourceDir, files, directories, true)) { std::cerr << "Failed to enumerate files" << std::endl; return false; } stats.totalFiles = static_cast<int>(files.size()); std::cout << "Found " << stats.totalFiles << " files to process" << std::endl; for (int i = 0; i < stats.totalFiles; ++i) { processFile(files[i]); if ((i + 1) % 10 == 0 || (i + 1) == stats.totalFiles) { int percent = (i + 1) * 100 / stats.totalFiles; std::cout << "Processing: " << (i + 1) << "/" << stats.totalFiles << " files (" << percent << "%)" << std::endl; } } // Generate config.hpp if (!dryRun) { generateConfigFile(sourceDir); } return true; } const Statistics& getStatistics() const { return stats; } const std::string& getBackupDir() const { return backupDir; } private: void processFile(const std::string& filePath) { if (!FileSystemUtils::fileExists(filePath)) { stats.skippedFiles++; return; } std::string filename = StringUtils::getFileName(filePath); std::string ext = StringUtils::getExtension(filePath); // Check excluded files if (config.excludeFiles.find(StringUtils::toLower(filename)) != config.excludeFiles.end()) { stats.skippedFiles++; return; } // Check extension bool isHeader = config.headerExtensions.find(ext) != config.headerExtensions.end(); bool isSource = config.sourceExtensions.find(ext) != config.sourceExtensions.end(); if (!isHeader && !isSource) { stats.skippedFiles++; return; } stats.processedFiles++; if (isHeader) { processHeaderFile(filePath); } else { processSourceFile(filePath); } } void processHeaderFile(const std::string& filePath) { std::vector<std::string> lines; if (!readFile(filePath, lines)) { stats.errorFiles++; return; } bool isSystemcFile = false; bool isTlmFile = false; std::string filename = StringUtils::getFileName(filePath); // Check file type if (filename == "systemc.h" || StringUtils::startsWith(filename, "sc_") || StringUtils::contains(StringUtils::toLower(filename), "vcd") || StringUtils::contains(StringUtils::toLower(filename), "trace")) { isSystemcFile = true; } else if (filename == "tlm.h" || StringUtils::contains(StringUtils::toLower(filename), "tlm")) { isTlmFile = true; } else { // Check content for (const auto& line : lines) { std::string trimmed = StringUtils::trim(line); if (StringUtils::contains(trimmed, "namespace sc_core") || StringUtils::contains(trimmed, "SC_MODULE") || StringUtils::contains(trimmed, "class sc_") || StringUtils::contains(trimmed, "class vcd_") || StringUtils::contains(trimmed, "vcd_trace")) { isSystemcFile = true; break; } else if (StringUtils::contains(trimmed, "namespace tlm") || StringUtils::contains(trimmed, "class tlm_")) { isTlmFile = true; break; } } } if (!isSystemcFile && !isTlmFile) { stats.skippedFiles++; return; } std::string dllApi = isTlmFile ? config.tlmDllApi : config.systemcDllApi; bool modified = false; // Check if config.hpp is already included bool hasConfigInclude = false; for (size_t i = 0; i < lines.size(); ++i) { std::string trimmed = StringUtils::trim(lines[i]); if (StringUtils::contains(trimmed, "#include \"config.hpp\"") || StringUtils::contains(trimmed, "#include <config.hpp>")) { hasConfigInclude = true; break; } } // Add config.hpp include if (!hasConfigInclude) { bool inserted = false; for (size_t i = 0; i < lines.size(); ++i) { std::string trimmed = StringUtils::trim(lines[i]); if (StringUtils::startsWith(trimmed, "#include")) { lines.insert(lines.begin() + i, config.includeConfig); inserted = true; modified = true; break; } } if (!inserted) { lines.insert(lines.begin(), config.includeConfig); modified = true; } } // Process class declarations and templates with enhanced pattern matching for (size_t i = 0; i < lines.size(); ++i) { std::string line = lines[i]; std::string trimmed = StringUtils::trim(line); // Skip preprocessor directives and comments if (StringUtils::startsWith(trimmed, "#") || StringUtils::startsWith(trimmed, "//") || StringUtils::startsWith(trimmed, "/*")) { continue; } // Process regular classes (including those with comment headers) if (isClassDeclarationLine(trimmed)) { if (!StringUtils::contains(trimmed, config.systemcDllApi) && !StringUtils::contains(trimmed, config.tlmDllApi)) { // Check if this class has a comment header above it if (i > 0 && hasCommentHeader(lines, i)) { // Find the start of the comment block size_t commentStart = findCommentBlockStart(lines, i); if (commentStart != std::string::npos && commentStart < i) { // Insert API after the comment block, before the class declaration lines[i] = addAPIToClassDeclaration(trimmed, dllApi); modified = true; } } else { // No comment header, just add API to the class line lines[i] = addAPIToClassDeclaration(trimmed, dllApi); modified = true; } } } // ULTIMATE FIX: Template class API placement with inheritance support if (isTemplateClassDeclaration(trimmed)) { modified = ultimateTemplateFix(lines, i, dllApi, filePath) || modified; } } if (modified) { if (dryRun) { std::cout << "[DRY RUN] Would modify header: " << filePath << std::endl; stats.modifiedFiles++; } else { if (writeFile(filePath, lines)) { std::cout << "Modified header: " << filePath << std::endl; stats.modifiedFiles++; } else { std::cerr << "Failed to write header: " << filePath << std::endl; stats.errorFiles++; } } } } // Check if line is a class declaration bool isClassDeclarationLine(const std::string& line) { std::string trimmed = StringUtils::trim(line); // Match patterns like: // class class_name // class class_name { // class class_name : if (StringUtils::startsWith(trimmed, "class ") && !StringUtils::contains(trimmed, "template")) { // Extract class name part (after "class ") size_t classPos = trimmed.find("class "); size_t afterClass = classPos + 6; if (afterClass >= trimmed.length()) return false; std::string afterClassStr = trimmed.substr(afterClass); StringUtils::trim(afterClassStr); // Check if it's a real class name (not a template parameter) if (afterClassStr.empty()) return false; // Exclude single-letter template parameters if (afterClassStr.length() == 1 && (afterClassStr[0] == 'T' || afterClassStr[0] == 'U' || afterClassStr[0] == 'V' || afterClassStr[0] == 'W')) { return false; } return true; } return false; } // Check if line is a template class declaration bool isTemplateClassDeclaration(const std::string& line) { std::string trimmed = StringUtils::trim(line); // Match patterns like: // template <class T> class class_name // template <typename T> class class_name // template <class T> class class_name : if (StringUtils::startsWith(trimmed, "template") && (StringUtils::contains(trimmed, "class") || StringUtils::contains(trimmed, "typename")) && StringUtils::contains(trimmed, "class ")) { // Check if it's a template parameter declaration (like template<class T>) if (isTemplateParameterDeclaration(trimmed)) { return false; } return true; } return false; } // Check if line is a template parameter declaration bool isTemplateParameterDeclaration(const std::string& line) { std::string trimmed = StringUtils::trim(line); // Template parameter declarations end with > and don't have a second class keyword if (!StringUtils::contains(trimmed, ">")) return false; // Check if it's a simple template parameter like template<class T> size_t templatePos = trimmed.find("template"); size_t angleBracketPos = trimmed.find(">", templatePos); if (angleBracketPos == std::string::npos) return false; // Check if there's content after the > that indicates it's a real class std::string afterAngleBracket = trimmed.substr(angleBracketPos + 1); StringUtils::trim(afterAngleBracket); // If there's no content after >, it's likely a template parameter declaration if (afterAngleBracket.empty()) return true; // If there's content but it doesn't contain "class", it's probably not a class declaration return !StringUtils::contains(afterAngleBracket, "class"); } // Check if class has a comment header above it bool hasCommentHeader(const std::vector<std::string>& lines, size_t currentLine) { if (currentLine == 0) return false; // Check previous lines for comment patterns for (int i = static_cast<int>(currentLine) - 1; i >= 0 && i >= static_cast<int>(currentLine) - 10; --i) { std::string line = lines[i]; std::string trimmed = StringUtils::trim(line); if (trimmed.empty()) continue; // Check for comment separators or class comment headers if (StringUtils::isCommentSeparator(trimmed) || StringUtils::isClassCommentHeader(trimmed)) { return true; } // If we hit a non-comment, non-empty line, stop searching if (!StringUtils::startsWith(trimmed, "//") && !StringUtils::startsWith(trimmed, "/*") && !trimmed.empty()) { break; } } return false; } // Find the start of a comment block before a class declaration size_t findCommentBlockStart(const std::vector<std::string>& lines, size_t currentLine) { if (currentLine == 0) return std::string::npos; for (int i = static_cast<int>(currentLine) - 1; i >= 0; --i) { std::string line = lines[i]; std::string trimmed = StringUtils::trim(line); if (trimmed.empty()) continue; // Look for the start of the comment block (first comment line) if (StringUtils::startsWith(trimmed, "//") || StringUtils::startsWith(trimmed, "/*")) { // Check if this is the first comment in the block if (i == 0 || !StringUtils::startsWith(StringUtils::trim(lines[i - 1]), "//") && !StringUtils::startsWith(StringUtils::trim(lines[i - 1]), "/*")) { return i; } } else { // Non-comment line, stop searching break; } } return std::string::npos; } // Add API to class declaration (handles inheritance) std::string addAPIToClassDeclaration(const std::string& line, const std::string& dllApi) { std::string result = line; // Find "class " position size_t classPos = result.find("class "); if (classPos == std::string::npos) return line; // Position after "class " size_t afterClass = classPos + 6; while (afterClass < result.length() && std::isspace(result[afterClass])) { afterClass++; } if (afterClass >= result.length()) return line; // Insert API after "class " but before the class name result = result.substr(0, afterClass) + dllApi + " " + result.substr(afterClass); return result; } void processSourceFile(const std::string& filePath) { std::vector<std::string> lines; if (!readFile(filePath, lines)) { stats.errorFiles++; return; } bool isSystemcFile = false; bool isTlmFile = false; std::string filename = StringUtils::getFileName(filePath); // Check file type if (StringUtils::startsWith(filename, "sc_") || StringUtils::contains(filename, "tlm") || StringUtils::contains(filename, "vcd") || StringUtils::contains(filename, "trace")) { isSystemcFile = true; } else { // Check content for SystemC/TLM indicators for (const auto& line : lines) { std::string trimmed = StringUtils::trim(line); if (StringUtils::contains(trimmed, "namespace sc_core") || StringUtils::contains(trimmed, "SC_MODULE") || StringUtils::contains(trimmed, "class sc_") || StringUtils::contains(trimmed, "sc_vcd_trace") || StringUtils::contains(trimmed, "vcd_trace") || StringUtils::contains(trimmed, "sc_main")) { isSystemcFile = true; break; } else if (StringUtils::contains(trimmed, "namespace tlm") || StringUtils::contains(trimmed, "class tlm_")) { isTlmFile = true; break; } } } if (!isSystemcFile && !isTlmFile) { stats.skippedFiles++; return; } std::string dllApi = isTlmFile ? config.tlmDllApi : config.systemcDllApi; bool modified = false; // Check if config.hpp is already included bool hasConfigInclude = false; for (size_t i = 0; i < lines.size(); ++i) { std::string trimmed = StringUtils::trim(lines[i]); if (StringUtils::contains(trimmed, "#include \"config.hpp\"") || StringUtils::contains(trimmed, "#include <config.hpp>")) { hasConfigInclude = true; break; } } // Add config.hpp include to source files if (!hasConfigInclude) { bool inserted = false; for (size_t i = 0; i < lines.size(); ++i) { std::string trimmed = StringUtils::trim(lines[i]); if (StringUtils::startsWith(trimmed, "#include")) { lines.insert(lines.begin() + i, config.includeConfig); inserted = true; modified = true; break; } } if (!inserted) { // If no #include found, add at the beginning lines.insert(lines.begin(), config.includeConfig); modified = true; } } // Process class definitions in .cpp files for (size_t i = 0; i < lines.size(); ++i) { std::string line = lines[i]; std::string trimmed = StringUtils::trim(line); // Skip preprocessor directives and comments if (StringUtils::startsWith(trimmed, "#") || StringUtils::startsWith(trimmed, "//") || StringUtils::startsWith(trimmed, "/*")) { continue; } // Process class member function definitions in .cpp files if (isClassMemberFunctionDefinition(trimmed)) { modified = processClassMemberFunction(lines, i, dllApi, filePath) || modified; } // Process template specializations in .cpp files if (isTemplateSpecialization(trimmed)) { modified = processTemplateSpecialization(lines, i, dllApi, filePath) || modified; } // Process static member definitions in .cpp files if (isStaticMemberDefinition(trimmed)) { modified = processStaticMemberDefinition(lines, i, dllApi, filePath) || modified; } } if (modified) { if (dryRun) { std::cout << "[DRY RUN] Would modify source: " << filePath << std::endl; stats.modifiedFiles++; } else { if (writeFile(filePath, lines)) { std::cout << "Modified source: " << filePath << std::endl; stats.modifiedFiles++; } else { std::cerr << "Failed to write source: " << filePath << std::endl; stats.errorFiles++; } } } } // Check if line is a class member function definition bool isClassMemberFunctionDefinition(const std::string& line) { std::string trimmed = StringUtils::trim(line); // Pattern: return_type class_name::function_name if (!StringUtils::contains(trimmed, "::")) return false; if (!StringUtils::contains(trimmed, "(")) return false; if (!StringUtils::contains(trimmed, ")")) return false; if (StringUtils::contains(trimmed, ";")) return false; // Not a declaration // Check if it's a SystemC related class std::vector<std::string> systemcClasses = { "sc_", "tlm_", "vcd_", "wif_", "signal_", "module_", "port_" }; for (const auto& className : systemcClasses) { if (StringUtils::contains(trimmed, className) && StringUtils::contains(trimmed, "::")) { return true; } } return false; } // Process class member function definition bool processClassMemberFunction(std::vector<std::string>& lines, size_t currentLine, const std::string& dllApi, const std::string& filePath) { std::string line = lines[currentLine]; std::string trimmed = StringUtils::trim(line); // Check if already has API if (StringUtils::contains(trimmed, dllApi)) { return false; } // Add API to function definition std::string fixedLine = addAPIToFunctionDefinition(trimmed, dllApi); if (fixedLine != line) { lines[currentLine] = fixedLine; std::cout << "ADDED API to function definition in " << filePath << ":\n"; std::cout << " BEFORE: " << trimmed << "\n"; std::cout << " AFTER: " << fixedLine << std::endl; return true; } return false; } // Check if line is a template specialization bool isTemplateSpecialization(const std::string& line) { std::string trimmed = StringUtils::trim(line); // Pattern: template class ClassName<Args>; if (!StringUtils::contains(trimmed, "template class")) return false; if (!StringUtils::contains(trimmed, ";")) return false; // Check if it's a SystemC related class std::vector<std::string> systemcClasses = { "sc_", "tlm_", "vcd_", "signal_" }; for (const auto& className : systemcClasses) { if (StringUtils::contains(trimmed, className)) { return true; } } return false; } // Process template specialization bool processTemplateSpecialization(std::vector<std::string>& lines, size_t currentLine, const std::string& dllApi, const std::string& filePath) { std::string line = lines[currentLine]; std::string trimmed = StringUtils::trim(line); // Check if already has API if (StringUtils::contains(trimmed, dllApi)) { return false; } // Add API to template specialization std::string fixedLine = addAPIToTemplateSpecialization(trimmed, dllApi); if (fixedLine != line) { lines[currentLine] = fixedLine; std::cout << "ADDED API to template specialization in " << filePath << ":\n"; std::cout << " BEFORE: " << trimmed << "\n"; std::cout << " AFTER: " << fixedLine << std::endl; return true; } return false; } // Check if line is a static member definition bool isStaticMemberDefinition(const std::string& line) { std::string trimmed = StringUtils::trim(line); // Pattern: type class_name::member = value; if (!StringUtils::contains(trimmed, "::")) return false; if (!StringUtils::contains(trimmed, "=")) return false; if (!StringUtils::contains(trimmed, ";")) return false; // Check if it's a SystemC related class std::vector<std::string> systemcClasses = { "sc_", "tlm_", "vcd_", "signal_" }; for (const auto& className : systemcClasses) { if (StringUtils::contains(trimmed, className) && StringUtils::contains(trimmed, "::")) { return true; } } return false; } // Process static member definition bool processStaticMemberDefinition(std::vector<std::string>& lines, size_t currentLine, const std::string& dllApi, const std::string& filePath) { std::string line = lines[currentLine]; std::string trimmed = StringUtils::trim(line); // Check if already has API if (StringUtils::contains(trimmed, dllApi)) { return false; } // Add API to static member definition std::string fixedLine = addAPIToStaticMemberDefinition(trimmed, dllApi); if (fixedLine != line) { lines[currentLine] = fixedLine; std::cout << "ADDED API to static member definition in " << filePath << ":\n"; std::cout << " BEFORE: " << trimmed << "\n"; std::cout << " AFTER: " << fixedLine << std::endl; return true; } return false; } // Add API to function definition std::string addAPIToFunctionDefinition(const std::string& line, const std::string& dllApi) { // Add API at the beginning of function definition return dllApi + " " + line; } // Add API to template specialization std::string addAPIToTemplateSpecialization(const std::string& line, const std::string& dllApi) { // Pattern: template class ClassName<Args>; // Change to: template class SYSTEMC_DLL_API ClassName<Args>; return StringUtils::replace(line, "template class", "template class " + dllApi); } // Add API to static member definition std::string addAPIToStaticMemberDefinition(const std::string& line, const std::string& dllApi) { // Add API at the beginning of static member definition return dllApi + " " + line; } // ULTIMATE FIX: Template class API placement for header files with inheritance support bool ultimateTemplateFix(std::vector<std::string>& lines, size_t currentLine, const std::string& dllApi, const std::string& filePath) { std::string line = lines[currentLine]; std::string trimmed = StringUtils::trim(line); // Debug output std::cout << "DEBUG Processing template: " << trimmed << std::endl; // Basic checks if (!StringUtils::contains(trimmed, "template") || (!StringUtils::contains(trimmed, "class") && !StringUtils::contains(trimmed, "typename"))) { return false; } // Skip if already has API if (StringUtils::contains(trimmed, dllApi)) { std::cout << "DEBUG: Already has API, skipping" << std::endl; return false; } // Check if this is a template parameter declaration (like template<class T>) if (isTemplateParameterDeclaration(trimmed)) { std::cout << "DEBUG: Skipping template parameter declaration" << std::endl; return false; } // For all other cases, add API std::string fixedLine = addAPIToTemplateClass(trimmed, dllApi); if (fixedLine != line) { lines[currentLine] = fixedLine; std::cout << "SUCCESS: Added API to template in " << filePath << ":\n"; std::cout << " BEFORE: " << trimmed << "\n"; std::cout << " AFTER: " << fixedLine << std::endl; return true; } return false; } // Add API to template class (handles inheritance) std::string addAPIToTemplateClass(const std::string& line, const std::string& dllApi) { std::string result = line; // Find the class keyword after template size_t templatePos = result.find("template"); if (templatePos == std::string::npos) return line; // Find the second "class" keyword (the actual class declaration) size_t firstClassPos = result.find("class", templatePos); if (firstClassPos == std::string::npos) { firstClassPos = result.find("typename", templatePos); if (firstClassPos == std::string::npos) return line; } // Find the actual class declaration (second "class" keyword) size_t secondClassPos = result.find("class", firstClassPos + 5); if (secondClassPos == std::string::npos) { // If no second class, it might be a template alias or other construct return line; } // Position after second "class" size_t afterClass = secondClassPos + 5; while (afterClass < result.length() && std::isspace(result[afterClass])) { afterClass++; } if (afterClass >= result.length()) return line; // Insert API after the second "class" keyword result = result.substr(0, afterClass) + dllApi + " " + result.substr(afterClass); return result; } void generateConfigFile(const std::string& outputDir) { std::string configPath = outputDir + "\\config.hpp"; if (FileSystemUtils::fileExists(configPath)) { std::cout << "config.hpp already exists, skipping generation" << std::endl; return; } std::string content = "#ifndef __CONFIG_HPP__\r\n" "#define __CONFIG_HPP__\r\n" "\r\n" "#undef SYSTEMC_DLL_API\r\n" "#undef TLM_DLL_API\r\n" "\r\n" "// C++11 Configuration for VS2015\r\n" "#if defined(_MSC_VER) && (_MSC_VER < 1900)\r\n" " #error \"Visual Studio 2015 (VC++ 14.0) or later is required for C++11 support\"\r\n" "#endif\r\n" "\r\n" "// DLL Configuration\r\n" "#define SYSTEMC_DLL // Enable DLL support\r\n" "#define SYSTEMC_DLL_EXPORT // Define this to export DLL symbols\r\n" "\r\n" "#if defined(_WIN32) || defined(WIN32) || defined(WINDOWS) || defined(_WINDOWS)\r\n" " #ifdef SYSTEMC_DLL\r\n" " #ifdef SYSTEMC_DLL_EXPORT\r\n" " #define SYSTEMC_DLL_API __declspec(dllexport)\r\n" " #else\r\n" " #define SYSTEMC_DLL_API __declspec(dllimport)\r\n" " #endif\r\n" "\r\n" " // Disable VS2015 warnings for DLL exports\r\n" " #ifdef _MSC_VER\r\n" " #pragma warning(push)\r\n" " #pragma warning(disable: 4251) // class needs dll-interface\r\n" " #pragma warning(disable: 4275) // non dll-interface base class\r\n" " #endif\r\n" "\r\n" " #else\r\n" " #define SYSTEMC_DLL_API\r\n" " #endif\r\n" "#else\r\n" " #define SYSTEMC_DLL_API\r\n" "#endif\r\n" "\r\n" "// TLM DLL API definition\r\n" "#define TLM_DLL_API SYSTEMC_DLL_API\r\n" "\r\n" "// C++11 standard library includes\r\n" "#include <cstdint>\r\n" "#include <memory>\r\n" "#include <string>\r\n" "#include <vector>\r\n" "\r\n" "#endif // __CONFIG_HPP__\r\n"; std::ofstream file(configPath, std::ios::binary); if (file.is_open()) { file.write(content.c_str(), content.length()); file.close(); std::cout << "Generated config.hpp at: " << configPath << std::endl; } else { std::cerr << "Failed to generate config.hpp" << std::endl; } } bool readFile(const std::string& filePath, std::vector<std::string>& lines) { std::ifstream file(filePath, std::ios::binary); if (!file.is_open()) { std::cerr << "Cannot open file for reading: " << filePath << std::endl; return false; } lines.clear(); std::string line; while (std::getline(file, line)) { // Handle Windows line endings if (!line.empty() && line.back() == '\r') { line.pop_back(); } lines.push_back(line); } if (file.bad()) { std::cerr << "Error reading file: " << filePath << std::endl; file.close(); return false; } file.close(); return true; } bool writeFile(const std::string& filePath, const std::vector<std::string>& lines) { std::ofstream file(filePath, std::ios::binary); if (!file.is_open()) { std::cerr << "Cannot open file for writing: " << filePath << std::endl; return false; } for (const auto& line : lines) { file << line << "\r\n"; } if (file.bad()) { std::cerr << "Error writing file: " << filePath << std::endl; file.close(); return false; } file.close(); return true; } bool createBackupDirectory(const std::string& sourceDir) { if (!FileSystemUtils::directoryExists(sourceDir)) { std::cerr << "Source directory does not exist: " << sourceDir << std::endl; return false; } // Generate timestamped backup directory name SYSTEMTIME st; GetLocalTime(&st); char timeBuffer[256]; sprintf_s(timeBuffer, "SystemC_Backup_%04d%02d%02d_%02d%02d%02d", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond); backupDir = timeBuffer; std::cout << "Creating backup: " << backupDir << std::endl; // Create backup directory if (!FileSystemUtils::createDirectoryRecursive(backupDir)) { std::cerr << "Failed to create backup directory: " << backupDir << std::endl; return false; } // Copy files std::vector<std::string> files; std::vector<std::string> directories; if (!FileSystemUtils::findFiles(sourceDir, files, directories, true)) { std::cerr << "Failed to enumerate files for backup" << std::endl; return false; } int copiedFiles = 0; int failedFiles = 0; int totalFiles = static_cast<int>(files.size()); std::cout << "Found " << totalFiles << " files to backup" << std::endl; for (int i = 0; i < totalFiles; ++i) { const auto& file = files[i]; // Calculate relative path std::string relativePath = getRelativePath(sourceDir, file); if (relativePath.empty()) { failedFiles++; continue; } std::string targetPath = backupDir + "\\" + relativePath; if (FileSystemUtils::copyFile(file, targetPath)) { copiedFiles++; } else { failedFiles++; std::cerr << "Failed to copy: " << file << std::endl; } // Show progress if ((i + 1) % 100 == 0 || (i + 1) == totalFiles) { int percent = (i + 1) * 100 / totalFiles; std::cout << "Backup progress: " << (i + 1) << "/" << totalFiles << " files (" << percent << "%)" << std::endl; } } std::cout << "\nBackup completed:" << std::endl; std::cout << " Successfully copied: " << copiedFiles << " files" << std::endl; std::cout << " Failed: " << failedFiles << " files" << std::endl; std::cout << " Backup location: " << backupDir << std::endl; if (failedFiles > 0) { std::cout << "WARNING: " << failedFiles << " files failed to backup!" << std::endl; } return failedFiles == 0; } std::string getRelativePath(const std::string& baseDir, const std::string& fullPath) { if (fullPath.find(baseDir) != 0) { return fullPath; } std::string relative = fullPath.substr(baseDir.length()); // Remove leading path separators while (!relative.empty() && (relative[0] == '\\' || relative[0] == '/')) { relative = relative.substr(1); } return relative; } }; // Help information void printHelp() { std::cout << R"( ======================================================================== SystemC DLL Modifier for VS2015 (C++11) - Ultimate Template API Fix ================================================================ ENHANCED VERSION: Now supports .cpp file class definitions and comment headers! ULTIMATE FIX: - Completely fixed template class DLL API placement error - Now supports .cpp file class definitions - Handles comment headers above class declarations - Supports template class inheritance patterns ================================================================ Usage: systemc_modifier_ultimate.exe <SystemC_directory> [options] Options: /dryrun Dry run mode (test without modifying files) /backup Create backup directory before modifications /help Display this help information /force Force processing even if backup fails Examples: systemc_modifier_ultimate.exe C:\systemc-2.3.1a systemc_modifier_ultimate.exe C:\systemc-2.3.1a /dryrun systemc_modifier_ultimate.exe C:\systemc-2.3.1a /backup systemc_modifier_ultimate.exe /help NEW FEATURES: 1. Support for .cpp file class member function definitions 2. Support for template specializations in .cpp files 3. Support for static member definitions in .cpp files 4. Enhanced pattern matching for comment headers 5. Improved template class API placement Supported Patterns in .cpp files: Pattern 1: Class member function definitions void sc_vcd_trace::write_comment(const std::string& comment) { // implementation } Pattern 2: Template specializations template class vcd_T_trace<bool>; template class vcd_T_trace<sc_dt::sc_logic>; Pattern 3: Static member definitions int sc_vcd_trace::instance_count = 0; Fixed Output for .cpp files: SYSTEMC_DLL_API void sc_vcd_trace::write_comment(const std::string& comment) { // implementation } template class SYSTEMC_DLL_API vcd_T_trace<bool>; template class SYSTEMC_DLL_API vcd_T_trace<sc_dt::sc_logic>; SYSTEMC_DLL_API int sc_vcd_trace::instance_count = 0; Supported Patterns in .h files: Pattern 1: Comment headers // ---------------------------------------------------------------------------- // CLASS : vcd_trace // // Base class for VCD traces. // ---------------------------------------------------------------------------- class vcd_trace { Pattern 2: Template class inheritance template <class T> class vcd_T_trace : public vcd_trace { Fixed Output for .h files: // ---------------------------------------------------------------------------- // CLASS : vcd_trace // // Base class for VCD traces. // ---------------------------------------------------------------------------- class SYSTEMC_DLL_API vcd_trace { template <class T> class SYSTEMC_DLL_API vcd_T_trace : public vcd_trace { Enhanced Features: 1. Automatically add #include "config.hpp" to SystemC headers AND source files 2. Add SYSTEMC_DLL_API or TLM_DLL_API export macros to classes 3. Generate config.hpp configuration file 4. Create timestamped backup directories 5. Process .h and .cpp files recursively 6. Skip build directories and version control directories 7. Retry mechanism for file operations 8. Detailed progress reporting 9. ULTIMATE template API placement fix 10. .cpp file class definition support 11. Comment header support 12. Template inheritance support Important Notes: 1. Always backup your important code before making modifications! 2. Test with /dryrun first to see what will be modified 3. The program will ask for confirmation if backup fails 4. Generated config.hpp includes proper warning suppression 5. Run as Administrator for system-protected directories ================================================================ )" << std::endl; } // Print statistics void printStatistics(const Statistics& stats, bool dryRun, const std::string& backupDir) { std::cout << "\n" << std::string(60, '=') << "\n"; std::cout << "PROCESSING COMPLETED\n"; std::cout << std::string(60, '=') << "\n"; std::cout << "Total files: " << stats.totalFiles << "\n"; std::cout << "Processed files: " << stats.processedFiles << "\n"; std::cout << "Modified files: " << stats.modifiedFiles << "\n"; std::cout << "Skipped files: " << stats.skippedFiles << "\n"; std::cout << "Error files: " << stats.errorFiles << "\n"; if (!backupDir.empty()) { std::cout << "\nBackup created: " << backupDir << "\n"; } if (dryRun) { std::cout << "\nMODE: DRY RUN - No files were actually modified\n"; std::cout << "To actually modify files, run without /dryrun option\n"; } std::cout << std::string(60, '=') << "\n"; } // Main function int main(int argc, char* argv[]) { std::cout << "========================================================================\n"; std::cout << " SystemC DLL Modifier for VS2015 (C++11) - Ultimate Template API Fix\n"; std::cout << " ================================================================\n"; std::cout << " Enhanced Version: Now supports .cpp file class definitions!\n"; std::cout << " Completely fixed template class DLL API position error\n"; std::cout << "========================================================================\n\n"; if (argc < 2) { printHelp(); return 1; } std::string sourceDir = argv[1]; bool dryRun = false; bool createBackup = false; bool forceMode = false; // Parse command line arguments for (int i = 2; i < argc; ++i) { std::string arg = argv[i]; std::string lowerArg = arg; std::transform(lowerArg.begin(), lowerArg.end(), lowerArg.begin(), ::tolower); if (lowerArg == "/dryrun" || lowerArg == "-dryrun" || lowerArg == "/d") { dryRun = true; } else if (lowerArg == "/backup" || lowerArg == "-backup" || lowerArg == "/b") { createBackup = true; } else if (lowerArg == "/help" || lowerArg == "-help" || lowerArg == "/h" || lowerArg == "/?") { printHelp(); return 0; } else if (lowerArg == "/force" || lowerArg == "-force" || lowerArg == "/f") { forceMode = true; } else { std::cout << "Unknown option: " << arg << "\n"; std::cout << "Use /help for usage information\n"; return 1; } } // Display mode information std::cout << "Mode: " << (dryRun ? "Dry Run (no modifications)" : createBackup ? "Normal with Backup" : "Normal") << "\n"; std::cout << "Target: " << sourceDir << "\n"; std::cout << "Force mode: " << (forceMode ? "Yes" : "No") << "\n"; std::cout << "C++ Standard: C++11\n"; std::cout << "Compiler: Visual Studio 2015\n"; std::cout << "Fix: Ultimate template API placement fix\n"; std::cout << "Enhanced: .cpp file class definition support\n"; std::cout << std::string(60, '-') << "\n\n"; // Create processor SystemCDLLModifier modifier(dryRun, createBackup); try { if (modifier.processDirectory(sourceDir)) { Statistics stats = modifier.getStatistics(); std::string backupDir = modifier.getBackupDir(); printStatistics(stats, dryRun, backupDir); std::cout << "\nNEXT STEPS:\n"; std::cout << "1. Review modified files for any issues\n"; std::cout << "2. Create a new DLL project in Visual Studio 2015\n"; std::cout << "3. Add SYSTEMC_DLL_EXPORT to preprocessor definitions\n"; std::cout << "4. Add all SystemC source files to the project\n"; std::cout << "5. Build the systemc.dll\n"; std::cout << "6. Test with your SystemC applications\n"; if (!dryRun && backupDir.empty() && createBackup) { std::cout << "\nWARNING: Backup was not created!\n"; std::cout << "Consider creating a manual backup before proceeding.\n"; } std::cout << "\nProcessing completed " << (dryRun ? "in dry run mode" : "successfully") << "!\n"; } else { std::cout << "\nERROR: Processing failed!\n"; std::cout << "Possible reasons:\n"; std::cout << "1. Invalid SystemC directory\n"; std::cout << "2. Permission issues\n"; std::cout << "3. Disk space problems\n"; std::cout << "4. File system errors\n"; return 1; } } catch (const std::exception& e) { std::cerr << "\nFATAL ERROR: " << e.what() << "\n"; std::cerr << "Please check:\n"; std::cerr << "1. Directory permissions\n"; std::cerr << "2. Disk space\n"; std::cerr << "3. File system integrity\n"; return 1; } return 0; }
最新发布
01-02
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值