aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/html/pcdata/pcdata.cpp
blob: 1f8d2950de7bdf2e533f19e88efcce8a040f7819 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
#include "pcdata.h" 
 
#include <util/string/strspn.h>

static TCompactStrSpn sspn("\"<>&'"); 
 
static void EncodeHtmlPcdataAppendInternal(const TStringBuf str, TString& strout, bool qAmp) {
    const char* s = str.data(); 
    const char* e = s + str.length(); 
 
    for (;;) { 
        const char* next = sspn.FindFirstOf(s, e); 
 
        strout.AppendNoAlias(s, next - s); 
        s = next; 
 
        if (s == e)
            break;
 
        switch (*s) { 
            case '\"': 
                strout += TStringBuf("&quot;");
                ++s;
                break; 
 
            case '<': 
                strout += TStringBuf("&lt;");
                ++s;
                break; 
 
            case '>': 
                strout += TStringBuf("&gt;");
                ++s;
                break; 
 
            case '\'': 
                strout += TStringBuf("&#39;");
                ++s;
                break; 
 
            case '&': 
                if (qAmp) 
                    strout += TStringBuf("&amp;");
                else 
                    strout += TStringBuf("&");
                ++s;
                break; 
        } 
    } 
}
 
void EncodeHtmlPcdataAppend(const TStringBuf str, TString& strout) {
    EncodeHtmlPcdataAppendInternal(str, strout, true);
}

TString EncodeHtmlPcdata(const TStringBuf str, bool qAmp) {
    TString strout;
    EncodeHtmlPcdataAppendInternal(str, strout, qAmp);
    return strout; 
} 
 
TString DecodeHtmlPcdata(const TString& sz) {
    TString res;
    const char* codes[] = {"&quot;", "&lt;", "&gt;", "&#39;", "&#039;", "&amp;", "&apos;", nullptr};
    const char chars[] = {'\"', '<', '>', '\'', '\'', '&', '\''}; 
    for (size_t i = 0; i < sz.length(); ++i) { 
        char c = sz[i]; 
        if (c == '&') { 
            for (const char** p = codes; *p; ++p) { 
                size_t len = strlen(*p); 
                if (strncmp(sz.c_str() + i, *p, len) == 0) { 
                    i += len - 1; 
                    c = chars[p - codes]; 
                    break; 
                } 
            } 
        } 
        res += c; 
    } 
    return res; 
}