1 | |
2 | // vim:sw=2:ai |
3 | |
4 | /* |
5 | * Copyright (C) 2010 DeNA Co.,Ltd.. All rights reserved. |
6 | * Copyright (C) 2011-2017 Kentoku SHIBA |
7 | * See COPYRIGHT.txt for details. |
8 | */ |
9 | |
10 | #include <my_global.h> |
11 | #include "mysql_version.h" |
12 | #include "hs_compat.h" |
13 | #include "escape.hpp" |
14 | #include "string_buffer.hpp" |
15 | #include "fatal.hpp" |
16 | #include "string_util.hpp" |
17 | |
18 | #define DBG_OP(x) |
19 | #define DBG_BUF(x) |
20 | |
21 | namespace dena { |
22 | |
23 | enum special_char_t { |
24 | special_char_escape_prefix = 0x01, /* SOH */ |
25 | special_char_noescape_min = 0x10, /* DLE */ |
26 | special_char_escape_shift = 0x40, /* '@' */ |
27 | }; |
28 | |
29 | void |
30 | escape_string(char *& wp, const char *start, const char *finish) |
31 | { |
32 | while (start != finish) { |
33 | const unsigned char c = *start; |
34 | if (c >= special_char_noescape_min) { |
35 | wp[0] = c; /* no need to escape */ |
36 | } else { |
37 | wp[0] = special_char_escape_prefix; |
38 | ++wp; |
39 | wp[0] = c + special_char_escape_shift; |
40 | } |
41 | ++start; |
42 | ++wp; |
43 | } |
44 | } |
45 | |
46 | void |
47 | escape_string(string_buffer& ar, const char *start, const char *finish) |
48 | { |
49 | const size_t buflen = (finish - start) * 2; |
50 | char *const wp_begin = ar.make_space(buflen); |
51 | char *wp = wp_begin; |
52 | escape_string(wp, start, finish); |
53 | ar.space_wrote(wp - wp_begin); |
54 | } |
55 | |
56 | bool |
57 | unescape_string(char *& wp, const char *start, const char *finish) |
58 | { |
59 | /* works even if wp == start */ |
60 | while (start != finish) { |
61 | const unsigned char c = *start; |
62 | if (c != special_char_escape_prefix) { |
63 | wp[0] = c; |
64 | } else if (start + 1 != finish) { |
65 | ++start; |
66 | const unsigned char cn = *start; |
67 | if (cn < special_char_escape_shift) { |
68 | return false; |
69 | } |
70 | wp[0] = cn - special_char_escape_shift; |
71 | } else { |
72 | return false; |
73 | } |
74 | ++start; |
75 | ++wp; |
76 | } |
77 | return true; |
78 | } |
79 | |
80 | bool |
81 | unescape_string(string_buffer& ar, const char *start, const char *finish) |
82 | { |
83 | const size_t buflen = finish - start; |
84 | char *const wp_begin = ar.make_space(buflen); |
85 | char *wp = wp_begin; |
86 | const bool r = unescape_string(wp, start, finish); |
87 | ar.space_wrote(wp - wp_begin); |
88 | return r; |
89 | } |
90 | |
91 | uint32 |
92 | read_ui32(char *& start, char *finish) |
93 | { |
94 | char *const n_begin = start; |
95 | read_token(start, finish); |
96 | char *const n_end = start; |
97 | uint32 v = 0; |
98 | for (char *p = n_begin; p != n_end; ++p) { |
99 | const char ch = p[0]; |
100 | if (ch >= '0' && ch <= '9') { |
101 | v *= 10; |
102 | v += (ch - '0'); |
103 | } |
104 | } |
105 | return v; |
106 | } |
107 | |
108 | void |
109 | write_ui32(string_buffer& buf, uint32 v) |
110 | { |
111 | char *wp = buf.make_space(12); |
112 | int len = snprintf(wp, 12, "%u" , v); |
113 | if (len > 0) { |
114 | buf.space_wrote(len); |
115 | } |
116 | } |
117 | |
118 | void |
119 | write_ui64(string_buffer& buf, uint64 v) |
120 | { |
121 | char *wp = buf.make_space(22); |
122 | int len = snprintf(wp, 22, "%llu" , static_cast<unsigned long long>(v)); |
123 | if (len > 0) { |
124 | buf.space_wrote(len); |
125 | } |
126 | } |
127 | |
128 | }; |
129 | |
130 | |