9template<
typename S = std::
string>
10requires std::convertible_to<S, std::string>
14 [[nodiscard]] std::string_view
getKey()
const {
24 [[nodiscard]] std::string_view
getValue()
const {
29 template<KV1ValueType V>
31 if constexpr (std::convertible_to<V, std::string_view>) {
33 }
else if constexpr (std::same_as<V, bool>) {
35 }
else if constexpr (std::same_as<V, int32_t> || std::same_as<V, int64_t>) {
43 }
else if constexpr (std::same_as<V, float>) {
52 template<KV1ValueType V>
54 if constexpr (std::convertible_to<V, std::string_view>) {
55 this->
value = std::string_view{value_};
57 this->
setValue(std::to_string(value_));
62 template<KV1ValueType V>
79 [[nodiscard]]
bool hasChild(std::string_view childKey)
const {
84 template<KV1ValueType V = std::
string_view>
102 for (
const auto& element : this->
children) {
111 [[nodiscard]]
const std::vector<KV1ElementWritable>&
getChildren()
const {
120 using iterator = std::vector<KV1ElementWritable>::iterator;
170 for (
const auto& element : this->
children) {
180 for (
auto& element : this->
children) {
190 unsigned int count = 0;
191 for (
const auto& element : this->
children) {
206 unsigned int count = 0;
207 for (
auto& element: this->
children) {
229 unsigned int count = 0;
230 for (
auto element = this->
children.begin(); element != this->children.end(); ++element) {
232 if (n < 0 || count == n) {
233 element = this->
children.erase(element);
253 [[nodiscard]]
explicit operator bool()
const {
265 if (stream.peek<
char>() ==
'}') {
276 if (stream.peek<
char>() !=
'{') {
281 if (stream.peek<
char>() ==
'[') {
286 if (stream.peek<
char>() ==
'{') {
289 if (stream.peek<
char>() !=
'}') {
300 constexpr auto writeIndentation = [](BufferStream& stream_,
unsigned short indentLevel_) {
301 for (
unsigned short i = 0; i < indentLevel_; i++) {
305 constexpr auto writeQuotedString = [](BufferStream& stream_, std::string_view str,
const parser::text::EscapeSequenceMap& escapeSequences_,
char quoteStart =
'\"',
char quoteEnd =
'\"') {
306 stream_.write(quoteStart);
310 stream_.write(quoteEnd);
313 for (
const auto& e : elements) {
314 writeIndentation(stream, indentLevel);
315 writeQuotedString(stream, e.key, escapeSequences);
316 if (!e.value.empty() || e.children.empty()) {
318 writeQuotedString(stream, e.value, escapeSequences);
320 if (!e.conditional.empty()) {
322 writeQuotedString(stream, e.conditional, escapeSequences,
'[',
']');
325 if (!e.children.empty()) {
326 writeIndentation(stream, indentLevel);
327 stream <<
'{' <<
'\n';
328 write(stream, e.children, indentLevel + 1, escapeSequences);
329 writeIndentation(stream, indentLevel);
330 stream <<
'}' <<
'\n';
341template<
typename S = std::
string>
342requires std::convertible_to<S, std::string_view>
345 explicit KV1Writer(std::string_view kv1Data =
"",
bool useEscapeSequences_ =
false)
348 if (kv1Data.empty()) {
351 BufferStreamReadOnly stream{kv1Data};
353 KV1ElementWritable<S>::read(stream, this->children, sourcepp::parser::text::getDefaultEscapeSequencesOrNone(this->useEscapeSequences));
354 } catch (
const std::overflow_error&) {}
357 [[nodiscard]] std::string
bake()
const {
359 BufferStream stream{buffer};
361 buffer.resize(stream.size());
365 void bake(
const std::filesystem::path& kv1Path)
const {
383inline KV1Writer<> operator""_kv1w(
const char* str,
const std::size_t len) {
384 return KV1Writer{std::string_view{str, len}};
std::vector< KV1ElementWritable > & getChildren()
Get the child elements of the element.
constexpr const_iterator end() const
void setKey(std::string_view key_)
Set the key associated with the element.
std::string_view getConditional() const
Get the conditional associated with the element.
bool isInvalid() const
Check if the given element is invalid.
constexpr const_iterator begin() const
const std::vector< KV1ElementWritable > & getChildren() const
Get the child elements of the element.
void removeChild(std::string_view childKey, int n=-1)
Remove a child element from the element with the given key. -1 means all children with the given key.
const KV1ElementWritable & operator()(std::string_view childKey) const
Get the first child element of the element with the given key.
KV1ElementWritable()=default
void removeChild(unsigned int n)
Remove a child element from the element.
static void write(BufferStream &stream, const std::vector< KV1ElementWritable > &elements, unsigned short indentLevel, const sourcepp::parser::text::EscapeSequenceMap &escapeSequences)
constexpr iterator begin()
KV1ElementWritable & operator=(V value_)
Set the value associated with the element.
void setConditional(std::string_view conditional_)
Set the conditional associated with the element.
KV1ElementWritable & operator()(std::string_view childKey, unsigned int n)
Get the nth child element of the element with the given key, or create a new element if it doesn't ex...
std::vector< KV1ElementWritable > children
KV1ElementWritable & addChild(std::string_view key_, V value_={}, std::string_view conditional_="")
void setValue(V value_)
Set the value associated with the element.
constexpr const_iterator cend() const
std::vector< KV1ElementWritable >::iterator iterator
KV1ElementWritable & operator[](unsigned int n)
Get the child element of the element at the given index.
KV1ElementWritable & operator()(std::string_view childKey)
Get the first child element of the element with the given key, or create a new element if it doesn't ...
std::vector< KV1ElementWritable >::const_iterator const_iterator
const KV1ElementWritable & operator[](unsigned int n) const
Get the child element of the element at the given index.
uint64_t getChildCount(std::string_view childKey) const
Get the number of child elements with the given key.
static void read(BufferStreamReadOnly &stream, std::vector< KV1ElementWritable > &elements, const sourcepp::parser::text::EscapeSequenceMap &escapeSequences)
std::string_view getValue() const
Get the value associated with the element.
bool hasChild(std::string_view childKey) const
Check if the element has one or more children with the given key.
KV1ElementWritable & operator[](std::string_view childKey)
Get the first child element of the element with the given key, or create a new element if it doesn't ...
const KV1ElementWritable & operator()(std::string_view childKey, unsigned int n) const
Get the nth child element of the element with the given key.
constexpr const_iterator cbegin() const
static const KV1ElementWritable & getInvalid()
uint64_t getChildCount() const
Get the number of child elements.
std::string_view getKey() const
Get the key associated with the element.
const KV1ElementWritable & operator[](std::string_view childKey) const
Get the first child element of the element with the given key.
V getValue() const
Get the value associated with the element as the given type.
void bake(const std::filesystem::path &kv1Path) const
KV1Writer(std::string_view kv1Data="", bool useEscapeSequences_=false)
bool writeFileText(const std::filesystem::path &filepath, std::string_view text)
std::string convertSpecialCharsToEscapes(std::string_view str, const EscapeSequenceMap &escapeSequences)
Convert special characters like \n to escaped special characters like \\n.
std::unordered_map< char, char > EscapeSequenceMap
void eatWhitespaceAndSingleLineComments(BufferStream &stream, std::string_view singleLineCommentStart=DEFAULT_SINGLE_LINE_COMMENT_START)
Eat all whitespace and single line comments after the current stream position.
std::string readString(BufferStream &stream, std::string_view start=DEFAULT_STRING_START, std::string_view end=DEFAULT_STRING_END, const EscapeSequenceMap &escapeSequences=getDefaultEscapeSequences())
Read a string starting at the current stream position.
constexpr std::string_view DEFAULT_STRING_END
constexpr std::string_view DEFAULT_STRING_START
const EscapeSequenceMap & getDefaultEscapeSequencesOrNone(bool useEscapes)
bool isNumber(char c)
If a char is a numerical character (0-9).
std::from_chars_result toFloat(std::string_view number, std::floating_point auto &out)
std::from_chars_result toInt(std::string_view number, std::integral auto &out, int base=10)
bool iequals(std::string_view s1, std::string_view s2)