diff options
Diffstat (limited to 'source/compiler-core')
| -rw-r--r-- | source/compiler-core/slang-pretty-writer.cpp | 85 | ||||
| -rw-r--r-- | source/compiler-core/slang-pretty-writer.h | 122 |
2 files changed, 207 insertions, 0 deletions
diff --git a/source/compiler-core/slang-pretty-writer.cpp b/source/compiler-core/slang-pretty-writer.cpp new file mode 100644 index 000000000..682b02c1e --- /dev/null +++ b/source/compiler-core/slang-pretty-writer.cpp @@ -0,0 +1,85 @@ +#include "slang-pretty-writer.h" + +#include "../core/slang-string-escape-util.h" + +namespace Slang +{ + +void PrettyWriter::writeRaw(char const* begin, char const* end) +{ + SLANG_ASSERT(end >= begin); + writeRaw(UnownedStringSlice(begin, end)); +} + +void PrettyWriter::adjust() +{ + // Only indent if at start of a line + if (m_startOfLine) + { + // Output current indentation + m_builder.appendRepeatedChar(' ', m_indent * 4); + m_startOfLine = false; + } +} + +void PrettyWriter::dedent() +{ + SLANG_ASSERT(m_indent > 0); + m_indent--; +} + +void PrettyWriter::write(const UnownedStringSlice& slice) +{ + const auto end = slice.end(); + auto start = slice.begin(); + + while (start < end) + { + const char* cur = start; + + // Search for \n if there is one + while (cur < end && *cur != '\n') + cur++; + + // If there were some chars, adjust and write + if (cur > start) + { + adjust(); + writeRaw(UnownedStringSlice(start, cur)); + } + + if (cur < end && *cur == '\n') + { + writeRawChar('\n'); + // Skip the CR + cur++; + // Mark we are at the start of a line + m_startOfLine = true; + } + + start = cur; + } +} + +void PrettyWriter::writeEscapedString(const UnownedStringSlice& slice) +{ + adjust(); + auto handler = StringEscapeUtil::getHandler(StringEscapeUtil::Style::Cpp); + StringEscapeUtil::appendQuoted(handler, slice, m_builder); +} + +void PrettyWriter::maybeComma() +{ + if (auto state = m_commaState) + { + if (!state->needComma) + { + state->needComma = true; + return; + } + } + + write(toSlice(",\n")); +} + +} // namespace Slang diff --git a/source/compiler-core/slang-pretty-writer.h b/source/compiler-core/slang-pretty-writer.h new file mode 100644 index 000000000..6817047a2 --- /dev/null +++ b/source/compiler-core/slang-pretty-writer.h @@ -0,0 +1,122 @@ +#ifndef SLANG_CORE_PRETTY_WRITER_H +#define SLANG_CORE_PRETTY_WRITER_H + + +#include "../core/slang-char-util.h" +#include "../core/slang-string-util.h" +#include "../core/slang-string.h" + +namespace Slang +{ + +struct PrettyWriter +{ + typedef PrettyWriter ThisType; + + friend struct CommaTrackerRAII; + + struct CommaState + { + bool needComma = false; + }; + + void writeRaw(const UnownedStringSlice& slice) { m_builder.append(slice); } + void writeRaw(char const* begin, char const* end); + void writeRaw(char const* begin) { writeRaw(UnownedStringSlice(begin)); } + + void writeRawChar(int c) { m_builder.appendChar(char(c)); } + + void writeHexChar(int c) { writeRawChar(CharUtil::getHexChar(Index(c))); } + + /// Adjusts indentation if at start of a line + void adjust(); + + /// Increase indentation + void indent() { m_indent++; } + /// Decreate indentation + void dedent(); + + /// Write taking into account any CR that might be in a slice + void write(const UnownedStringSlice& slice); + void write(char const* text) { write(UnownedStringSlice(text)); } + void write(char const* text, size_t length) { write(UnownedStringSlice(text, length)); } + + /// Write the slice as an escaped string + void writeEscapedString(const UnownedStringSlice& slice); + + /// Call before items in a comma-separated JSON list to emit the comma if/when needed + void maybeComma(); + + /// Get the builder the result is being constructed in + StringBuilder& getBuilder() { return m_builder; } + + ThisType& operator<<(const UnownedStringSlice& slice) + { + write(slice); + return *this; + } + ThisType& operator<<(const char* text) + { + write(text); + return *this; + } + ThisType& operator<<(uint64_t val) + { + adjust(); + m_builder << val; + return *this; + } + ThisType& operator<<(int64_t val) + { + adjust(); + m_builder << val; + return *this; + } + ThisType& operator<<(int32_t val) + { + adjust(); + m_builder << val; + return *this; + } + ThisType& operator<<(uint32_t val) + { + adjust(); + m_builder << val; + return *this; + } + ThisType& operator<<(float val) + { + adjust(); + // We want to use a specific format, so we use the StringUtil to specify format, and not + // just use << + StringUtil::appendFormat(m_builder, "%f", val); + return *this; + } + + bool m_startOfLine = true; + int m_indent = 0; + CommaState* m_commaState = nullptr; + StringBuilder m_builder; +}; + +/// Type for tracking whether a comma is needed in a comma-separated JSON list +struct CommaTrackerRAII +{ + CommaTrackerRAII(PrettyWriter& writer) + : m_writer(&writer), m_previousState(writer.m_commaState) + { + writer.m_commaState = &m_state; + } + + ~CommaTrackerRAII() { m_writer->m_commaState = m_previousState; } + +private: + PrettyWriter::CommaState m_state; + PrettyWriter* m_writer; + PrettyWriter::CommaState* m_previousState; +}; + +} // namespace Slang + + +#endif |
