diff options
| author | qrort <[email protected]> | 2022-11-30 23:47:12 +0300 | 
|---|---|---|
| committer | qrort <[email protected]> | 2022-11-30 23:47:12 +0300 | 
| commit | 22f8ae0e3f5d68b92aecccdf96c1d841a0334311 (patch) | |
| tree | bffa27765faf54126ad44bcafa89fadecb7a73d7 /library/cpp/string_utils/tskv_format/escape.cpp | |
| parent | 332b99e2173f0425444abb759eebcb2fafaa9209 (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.cpp | 112 | 
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); +    } + +} | 
