summaryrefslogtreecommitdiffstats
path: root/library/cpp/string_utils/tskv_format/escape.cpp
diff options
context:
space:
mode:
authorqrort <[email protected]>2022-11-30 23:47:12 +0300
committerqrort <[email protected]>2022-11-30 23:47:12 +0300
commit22f8ae0e3f5d68b92aecccdf96c1d841a0334311 (patch)
treebffa27765faf54126ad44bcafa89fadecb7a73d7 /library/cpp/string_utils/tskv_format/escape.cpp
parent332b99e2173f0425444abb759eebcb2fafaa9209 (diff)
validate canons without yatest_common
Diffstat (limited to 'library/cpp/string_utils/tskv_format/escape.cpp')
-rw-r--r--library/cpp/string_utils/tskv_format/escape.cpp112
1 files changed, 112 insertions, 0 deletions
diff --git a/library/cpp/string_utils/tskv_format/escape.cpp b/library/cpp/string_utils/tskv_format/escape.cpp
new file mode 100644
index 00000000000..3dc78bec8c0
--- /dev/null
+++ b/library/cpp/string_utils/tskv_format/escape.cpp
@@ -0,0 +1,112 @@
+#include <util/generic/yexception.h>
+#include "escape.h"
+
+namespace NTskvFormat {
+ namespace {
+ const TStringBuf ESCAPE_CHARS("\t\n\r\\\0=\"", 7);
+
+ TString& EscapeImpl(const char* src, size_t len, TString& dst) {
+ TStringBuf srcStr(src, len);
+ size_t noEscapeStart = 0;
+
+ while (noEscapeStart < len) {
+ size_t noEscapeEnd = srcStr.find_first_of(ESCAPE_CHARS, noEscapeStart);
+
+ if (noEscapeEnd == TStringBuf::npos) {
+ dst.append(src + noEscapeStart, len - noEscapeStart);
+ break;
+ }
+
+ dst.append(src + noEscapeStart, noEscapeEnd - noEscapeStart);
+
+ switch (src[noEscapeEnd]) {
+ case '\t':
+ dst.append(TStringBuf("\\t"));
+ break;
+ case '\n':
+ dst.append(TStringBuf("\\n"));
+ break;
+ case '\r':
+ dst.append(TStringBuf("\\r"));
+ break;
+ case '\0':
+ dst.append(TStringBuf("\\0"));
+ break;
+ case '\\':
+ dst.append(TStringBuf("\\\\"));
+ break;
+ case '=':
+ dst.append(TStringBuf("\\="));
+ break;
+ case '"':
+ dst.append(TStringBuf("\\\""));
+ break;
+ }
+
+ noEscapeStart = noEscapeEnd + 1;
+ }
+
+ return dst;
+ }
+
+ TString& UnescapeImpl(const char* src, const size_t len, TString& dst) {
+ TStringBuf srcStr(src, len);
+ size_t noEscapeStart = 0;
+
+ while (noEscapeStart < len) {
+ size_t noEscapeEnd = srcStr.find('\\', noEscapeStart);
+
+ if (noEscapeEnd == TStringBuf::npos) {
+ dst.append(src + noEscapeStart, len - noEscapeStart);
+ break;
+ }
+
+ dst.append(src + noEscapeStart, noEscapeEnd - noEscapeStart);
+
+ if (noEscapeEnd + 1 >= len) {
+ throw yexception() << "expected (t|n|r|0|\\|=|\"|) after \\. Got end of line.";
+ }
+
+ switch (src[noEscapeEnd + 1]) {
+ case 't':
+ dst.append('\t');
+ break;
+ case 'n':
+ dst.append('\n');
+ break;
+ case 'r':
+ dst.append('\r');
+ break;
+ case '0':
+ dst.append('\0');
+ break;
+ case '\\':
+ dst.append('\\');
+ break;
+ case '=':
+ dst.append('=');
+ break;
+ case '"':
+ dst.append('"');
+ break;
+ default:
+ throw yexception() << "unexpected symbol '" << src[noEscapeEnd + 1] << "' after \\";
+ }
+
+ noEscapeStart = noEscapeEnd + 2;
+ }
+
+ return dst;
+ }
+
+ }
+
+ TString& Escape(const TStringBuf& src, TString& dst) {
+ return EscapeImpl(src.data(), src.size(), dst);
+ }
+
+ TString& Unescape(const TStringBuf& src, TString& dst) {
+ return UnescapeImpl(src.data(), src.size(), dst);
+ }
+
+}