json: support any ASCII-compliant char type

Signed-off-by: Simon Rozman <simon@rozman.si>
This commit is contained in:
Simon Rozman
2025-09-11 12:16:49 +02:00
parent b2f0ac3a3b
commit 2785ee68f3

View File

@@ -7,6 +7,7 @@
#include "assert.hpp"
#include "compat.hpp"
#include "string.hpp"
#include <string>
namespace stdex
@@ -20,50 +21,23 @@ namespace stdex
/// \param[in] src Source string
/// \param[in] num_chars Code unit limit in string `src`
///
template<class TR = std::char_traits<char>, class AX = std::allocator<char>>
template<class T, class TR = std::char_traits<T>, class AX = std::allocator<T>>
void escape(
_Inout_ std::basic_string<char, TR, AX>& dst,
_In_reads_or_z_opt_(num_chars) const char* src, _In_ size_t num_chars = SIZE_MAX)
_Inout_ std::basic_string<T, TR, AX>& dst,
_In_reads_or_z_opt_(num_chars) const T* src, _In_ size_t num_chars = SIZE_MAX)
{
stdex_assert(src || !num_chars);
for (size_t i = 0; i < num_chars && src[i]; ++i) {
num_chars = stdex::strnlen(src, num_chars);
dst.reserve(dst.size() + num_chars + (num_chars >> 3));
for (size_t i = 0; i < num_chars; ++i) {
switch (src[i]) {
case '\"': dst += "\\\""; break;
case '\\': dst += "\\\\"; break;
case '/' : dst += "\\/"; break;
case '\b': dst += "\\b"; break;
case '\f': dst += "\\f"; break;
case '\n': dst += "\\n"; break;
case '\r': dst += "\\r"; break;
case '\t': dst += "\\t"; break;
default: dst += src[i]; break;
}
}
}
///
/// Appends escaped JSON string
///
/// \param[in,out] dst String to append to
/// \param[in] src Source string
/// \param[in] num_chars Code unit limit in string `src`
///
template<class TR = std::char_traits<wchar_t>, class AX = std::allocator<wchar_t>>
void escape(
_Inout_ std::basic_string<wchar_t, TR, AX>& dst,
_In_reads_or_z_opt_(num_chars) const wchar_t* src, _In_ size_t num_chars = SIZE_MAX)
{
stdex_assert(src || !num_chars);
for (size_t i = 0; i < num_chars && src[i]; ++i) {
switch (src[i]) {
case L'\"': dst += L"\\\""; break;
case L'\\': dst += L"\\\\"; break;
case L'/' : dst += L"\\/"; break;
case L'\b': dst += L"\\b"; break;
case L'\f': dst += L"\\f"; break;
case L'\n': dst += L"\\n"; break;
case L'\r': dst += L"\\r"; break;
case L'\t': dst += L"\\t"; break;
case '\"': dst += '\\'; dst += '"'; break;
case '\\': dst += '\\'; dst += '\\'; break;
case '/' : dst += '\\'; dst += '/'; break;
case '\b': dst += '\\'; dst += 'b'; break;
case '\f': dst += '\\'; dst += 'f'; break;
case '\n': dst += '\\'; dst += 'n'; break;
case '\r': dst += '\\'; dst += 'r'; break;
case '\t': dst += '\\'; dst += 't'; break;
default: dst += src[i]; break;
}
}
@@ -97,4 +71,4 @@ namespace stdex
escape(dst, src.data(), src.size());
}
}
}
}