summaryrefslogtreecommitdiffstats
path: root/library/cpp/string_utils/tskv_format/escape.cpp
diff options
context:
space:
mode:
authorhcpp <[email protected]>2023-11-08 12:09:41 +0300
committerhcpp <[email protected]>2023-11-08 12:56:14 +0300
commita361f5b98b98b44ea510d274f6769164640dd5e1 (patch)
treec47c80962c6e2e7b06798238752fd3da0191a3f6 /library/cpp/string_utils/tskv_format/escape.cpp
parent9478806fde1f4d40bd5a45e7cbe77237dab613e9 (diff)
metrics have been added
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);
+ }
+
+}