diff options
author | Alex Turbov <i.zaufi@gmail.com> | 2022-08-23 14:15:41 (GMT) |
---|---|---|
committer | Alex Turbov <i.zaufi@gmail.com> | 2022-11-17 12:37:10 (GMT) |
commit | 09fdfe5afa2983fb2a0297505f257d03227c9823 (patch) | |
tree | fc362b761b6630424f1046e544eda61b0a7e88f6 | |
parent | 3feac60591ea0a4b010c7f21eb9e8854d159d9a0 (diff) | |
download | CMake-09fdfe5afa2983fb2a0297505f257d03227c9823.zip CMake-09fdfe5afa2983fb2a0297505f257d03227c9823.tar.gz CMake-09fdfe5afa2983fb2a0297505f257d03227c9823.tar.bz2 |
cmDocumentationFormatter: Improve `PrintFormatted`
Instead of one char at time copy (append), use lines.
-rw-r--r-- | Source/cmDocumentationFormatter.cxx | 88 |
1 files changed, 54 insertions, 34 deletions
diff --git a/Source/cmDocumentationFormatter.cxx b/Source/cmDocumentationFormatter.cxx index 6d170ab..70ba1fc 100644 --- a/Source/cmDocumentationFormatter.cxx +++ b/Source/cmDocumentationFormatter.cxx @@ -7,12 +7,10 @@ #include <iomanip> #include <ostream> #include <string> -#include <utility> #include <vector> #include "cmDocumentationEntry.h" #include "cmDocumentationSection.h" -#include "cmSystemTools.h" namespace { const char* skipSpaces(const char* ptr) @@ -40,33 +38,63 @@ void cmDocumentationFormatter::PrintFormatted(std::ostream& os, return; } - for (const char* ptr = text.c_str(); *ptr;) { - // Any ptrs starting in a space are treated as preformatted text. - std::string preformatted; - while (*ptr == ' ') { - for (char ch = *ptr; ch && ch != '\n'; ++ptr, ch = *ptr) { - preformatted.append(1, ch); - } - if (*ptr) { - ++ptr; - preformatted.append(1, '\n'); - } - } - if (!preformatted.empty()) { - this->PrintPreformatted(os, preformatted); + struct Buffer + { + // clang-format off + using PrinterFn = void (cmDocumentationFormatter::*)( + std::ostream&, std::string const& + ) const; + // clang-format on + std::string collected; + const PrinterFn printer; + }; + // const auto NORMAL_IDX = 0u; + const auto PREFORMATTED_IDX = 1u; + const auto HANDLERS_SIZE = 2u; + Buffer buffers[HANDLERS_SIZE] = { + { {}, &cmDocumentationFormatter::PrintParagraph }, + { {}, &cmDocumentationFormatter::PrintPreformatted } + }; + + const auto padding = std::string(this->TextIndent, ' '); + + for (std::size_t pos = 0u, eol = 0u; pos < text.size(); pos = eol) { + const auto current_idx = std::size_t(text[pos] == ' '); + // size_t(!bool(current_idx)) + const auto other_idx = current_idx ^ 1u; + + // Flush the other buffer if anything has been collected + if (!buffers[other_idx].collected.empty()) { + // NOTE Whatever the other index is, the current buffered + // string expected to be empty. + assert(buffers[current_idx].collected.empty()); + + (this->*buffers[other_idx].printer)(os, buffers[other_idx].collected); + buffers[other_idx].collected.clear(); } - // Other ptrs are treated as paragraphs. - std::string paragraph; - for (char ch = *ptr; ch && ch != '\n'; ++ptr, ch = *ptr) { - paragraph.append(1, ch); + // ATTENTION The previous implementation had called `PrintParagraph()` + // **for every processed (char by char) input line**. + // The method unconditionally append the `\n' character after the + // printed text. To keep the backward-compatible behavior it's needed to + // add the '\n' character to the previously collected line... + if (!buffers[current_idx].collected.empty() && + current_idx != PREFORMATTED_IDX) { + buffers[current_idx].collected += '\n'; } - if (*ptr) { - ++ptr; - paragraph.append(1, '\n'); + + // Lookup EOL + eol = text.find('\n', pos); + if (current_idx == PREFORMATTED_IDX) { + buffers[current_idx].collected.append(padding); } - if (!paragraph.empty()) { - this->PrintParagraph(os, paragraph); + buffers[current_idx].collected.append( + text, pos, eol == std::string::npos ? eol : ++eol - pos); + } + + for (auto& buf : buffers) { + if (!buf.collected.empty()) { + (this->*buf.printer)(os, buf.collected); } } } @@ -74,15 +102,7 @@ void cmDocumentationFormatter::PrintFormatted(std::ostream& os, void cmDocumentationFormatter::PrintPreformatted(std::ostream& os, std::string const& text) const { - if (this->TextIndent) { - auto indented = text; - auto padding = std::string(this->TextIndent, ' '); - cmSystemTools::ReplaceString(indented, "\n", "\n" + padding); - indented = std::move(padding) + indented; - os << indented << '\n'; - } else { - os << text << '\n'; - } + os << text << '\n'; } void cmDocumentationFormatter::PrintParagraph(std::ostream& os, |