Created
October 4, 2018 18:08
-
-
Save N-Dekker/b3b66878f1ab242fd0dce170113f1e86 to your computer and use it in GitHub Desktop.
Script to replace leading stars by spaces in Doxygen code blocks, for patch http://review.source.kitware.com/#/c/23782
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/ | |
/* Script to replace leading stars ('*') by spaces in Doxygen code blocks | |
* Used for patch http://review.source.kitware.com/#/c/23782/ | |
* | |
* Initial version by Niels Dekker, LKEB, Leiden University Medical Center, 2018 | |
*/ | |
#include <cassert> | |
#include <cctype> | |
#include <deque> | |
#include <experimental/filesystem> | |
#include <fstream> | |
#include <iostream> | |
#include <cstring> | |
#include <string> | |
using namespace std::experimental::filesystem::v1; | |
namespace | |
{ | |
using Lines = std::deque<std::string>; | |
auto ReadFile(const path& filePath) | |
{ | |
Lines result; | |
std::ifstream inputFileStream{ filePath }; | |
std::string line; | |
while (std::getline(inputFileStream, line)) | |
{ | |
result.push_back(line); | |
} | |
return result; | |
} | |
void WriteFile(const path& filePath, const Lines& lines) | |
{ | |
std::ofstream outputFileStream{ filePath }; | |
for (const auto& line : lines) | |
{ | |
outputFileStream << line << '\n'; | |
} | |
} | |
const char* GoToFirstNonSpace(const char* ptr) | |
{ | |
while (*ptr == ' ') | |
{ | |
++ptr; | |
} | |
return ptr; | |
} | |
template <unsigned N> | |
bool StringStartsWithPrefix(const char*& str, const char(&prefix)[N]) | |
{ | |
assert(prefix[N - 1] == '\0'); | |
if ((std::strlen(str) + 1 >= N) && (std::memcmp(str, prefix, N - 1) == 0)) | |
{ | |
// Move the 'str' pointer beyond the prefix. | |
str += N - 1; | |
return true; | |
} | |
return false; | |
} | |
struct Statistics | |
{ | |
unsigned numberOfModifiedLines; | |
}; | |
Statistics ModifyLines(Lines& lines) | |
{ | |
Statistics statistics = {}; | |
auto className = std::string{}; | |
auto publicLineNumber = Lines::size_type{}; | |
auto isInsideCodeSection = false; | |
for (auto lineNumber = Lines::size_type{}; lineNumber < lines.size(); ++lineNumber) | |
{ | |
auto& line = lines[lineNumber]; | |
const auto numberOfChars = line.size(); | |
if (numberOfChars > 1) | |
{ | |
const char* c_str = line.c_str(); | |
if (StringStartsWithPrefix(c_str, " *")) | |
{ | |
if (isInsideCodeSection) | |
{ | |
if (numberOfChars == 2) | |
{ | |
line.clear(); | |
} | |
else | |
{ | |
line[1] = ' '; | |
} | |
++statistics.numberOfModifiedLines; | |
} | |
else | |
{ | |
c_str = GoToFirstNonSpace(c_str); | |
if (StringStartsWithPrefix(c_str, "\\code")) | |
{ | |
isInsideCodeSection = true; | |
} | |
} | |
} | |
if (isInsideCodeSection && (std::strstr(c_str, "\\endcode") != nullptr)) | |
{ | |
isInsideCodeSection = false; | |
} | |
} | |
} | |
return statistics; | |
} | |
auto ProcessFile(const path& filePath) | |
{ | |
auto lines = ReadFile(filePath); | |
const auto statistics = ModifyLines(lines); | |
if (statistics.numberOfModifiedLines > 0) | |
{ | |
WriteFile(filePath, lines); | |
} | |
return statistics; | |
} | |
void ProcessDirectory(const path& directoryPath) | |
{ | |
Statistics statistics = {}; | |
const recursive_directory_iterator end; | |
unsigned numberOfModifiedFiles = 0; | |
for (recursive_directory_iterator it{ directoryPath }; it != end; ++it) | |
{ | |
const auto& path = it->path(); | |
const auto& extension = path.extension(); | |
if ((!extension.empty()) && | |
(extension.string() == ".h") && | |
is_regular_file(path)) | |
{ | |
const auto statisticsPerFile = ProcessFile(path); | |
if (statisticsPerFile.numberOfModifiedLines > 0) | |
{ | |
++numberOfModifiedFiles; | |
statistics.numberOfModifiedLines += statisticsPerFile.numberOfModifiedLines; | |
std::cout << numberOfModifiedFiles << ' ' << statisticsPerFile.numberOfModifiedLines << ' ' << path << std::endl; | |
} | |
} | |
} | |
std::cout | |
<< "numberOfModifiedFiles:\t" << numberOfModifiedFiles | |
<< "\nNumberOfModifiedLines:\t" << statistics.numberOfModifiedLines | |
<< std::endl; | |
} | |
} | |
int main(int argc, char** argv) | |
{ | |
if (argc != 2) | |
{ | |
std::cout << | |
"Please specify the source directory path as command-line argument." | |
"\nNote: This program will modify the source files in-place!!!" | |
<< std::endl; | |
} | |
else | |
{ | |
if (argv == nullptr) | |
{ | |
return EXIT_FAILURE; | |
} | |
const char* const arg = argv[1]; | |
if (arg == nullptr) | |
{ | |
return EXIT_FAILURE; | |
} | |
ProcessDirectory(arg); | |
} | |
std::cout << "Press anything to continue" << std::endl; | |
std::cin.get(); | |
return EXIT_SUCCESS; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment