jpayne@69
|
1 // Copyright (c) 2017 Cloudflare, Inc. and contributors
|
jpayne@69
|
2 // Licensed under the MIT License:
|
jpayne@69
|
3 //
|
jpayne@69
|
4 // Permission is hereby granted, free of charge, to any person obtaining a copy
|
jpayne@69
|
5 // of this software and associated documentation files (the "Software"), to deal
|
jpayne@69
|
6 // in the Software without restriction, including without limitation the rights
|
jpayne@69
|
7 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
jpayne@69
|
8 // copies of the Software, and to permit persons to whom the Software is
|
jpayne@69
|
9 // furnished to do so, subject to the following conditions:
|
jpayne@69
|
10 //
|
jpayne@69
|
11 // The above copyright notice and this permission notice shall be included in
|
jpayne@69
|
12 // all copies or substantial portions of the Software.
|
jpayne@69
|
13 //
|
jpayne@69
|
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
jpayne@69
|
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
jpayne@69
|
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
jpayne@69
|
17 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
jpayne@69
|
18 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
jpayne@69
|
19 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
jpayne@69
|
20 // THE SOFTWARE.
|
jpayne@69
|
21
|
jpayne@69
|
22 #pragma once
|
jpayne@69
|
23 // Functions for encoding/decoding bytes and text in common formats, including:
|
jpayne@69
|
24 // - UTF-{8,16,32}
|
jpayne@69
|
25 // - Hex
|
jpayne@69
|
26 // - URI encoding
|
jpayne@69
|
27 // - Base64
|
jpayne@69
|
28
|
jpayne@69
|
29 #include "string.h"
|
jpayne@69
|
30
|
jpayne@69
|
31 KJ_BEGIN_HEADER
|
jpayne@69
|
32
|
jpayne@69
|
33 namespace kj {
|
jpayne@69
|
34
|
jpayne@69
|
35 template <typename ResultType>
|
jpayne@69
|
36 struct EncodingResult: public ResultType {
|
jpayne@69
|
37 // Equivalent to ResultType (a String or wide-char array) for all intents and purposes, except
|
jpayne@69
|
38 // that the bool `hadErrors` can be inspected to see if any errors were encountered in the input.
|
jpayne@69
|
39 // Each encoding/decoding function that returns this type will "work around" errors in some way,
|
jpayne@69
|
40 // so an application doesn't strictly have to check for errors. E.g. the Unicode functions
|
jpayne@69
|
41 // replace errors with U+FFFD in the output.
|
jpayne@69
|
42 //
|
jpayne@69
|
43 // Through magic, KJ_IF_MAYBE() and KJ_{REQUIRE,ASSERT}_NONNULL() work on EncodingResult<T>
|
jpayne@69
|
44 // exactly if it were a Maybe<T> that is null in case of errors.
|
jpayne@69
|
45
|
jpayne@69
|
46 inline EncodingResult(ResultType&& result, bool hadErrors)
|
jpayne@69
|
47 : ResultType(kj::mv(result)), hadErrors(hadErrors) {}
|
jpayne@69
|
48
|
jpayne@69
|
49 const bool hadErrors;
|
jpayne@69
|
50 };
|
jpayne@69
|
51
|
jpayne@69
|
52 template <typename T>
|
jpayne@69
|
53 inline auto KJ_STRINGIFY(const EncodingResult<T>& value)
|
jpayne@69
|
54 -> decltype(toCharSequence(implicitCast<const T&>(value))) {
|
jpayne@69
|
55 return toCharSequence(implicitCast<const T&>(value));
|
jpayne@69
|
56 }
|
jpayne@69
|
57
|
jpayne@69
|
58 EncodingResult<Array<char16_t>> encodeUtf16(ArrayPtr<const char> text, bool nulTerminate = false);
|
jpayne@69
|
59 EncodingResult<Array<char32_t>> encodeUtf32(ArrayPtr<const char> text, bool nulTerminate = false);
|
jpayne@69
|
60 // Convert UTF-8 text (which KJ strings use) to UTF-16 or UTF-32.
|
jpayne@69
|
61 //
|
jpayne@69
|
62 // If `nulTerminate` is true, an extra NUL character will be added to the end of the output.
|
jpayne@69
|
63 //
|
jpayne@69
|
64 // The returned arrays are in platform-native endianness (otherwise they wouldn't really be
|
jpayne@69
|
65 // char16_t / char32_t).
|
jpayne@69
|
66 //
|
jpayne@69
|
67 // Note that the KJ Unicode encoding and decoding functions actually implement
|
jpayne@69
|
68 // [WTF-8 encoding](http://simonsapin.github.io/wtf-8/), which affects how invalid input is
|
jpayne@69
|
69 // handled. See comments on decodeUtf16() for more info.
|
jpayne@69
|
70
|
jpayne@69
|
71 EncodingResult<String> decodeUtf16(ArrayPtr<const char16_t> utf16);
|
jpayne@69
|
72 EncodingResult<String> decodeUtf32(ArrayPtr<const char32_t> utf32);
|
jpayne@69
|
73 // Convert UTF-16 or UTF-32 to UTF-8 (which KJ strings use).
|
jpayne@69
|
74 //
|
jpayne@69
|
75 // The input should NOT include a NUL terminator; any NUL characters in the input array will be
|
jpayne@69
|
76 // preserved in the output.
|
jpayne@69
|
77 //
|
jpayne@69
|
78 // The input must be in platform-native endianness. BOMs are NOT recognized by these functions.
|
jpayne@69
|
79 //
|
jpayne@69
|
80 // Note that the KJ Unicode encoding and decoding functions actually implement
|
jpayne@69
|
81 // [WTF-8 encoding](http://simonsapin.github.io/wtf-8/). This means that if you start with an array
|
jpayne@69
|
82 // of char16_t and you pass it through any number of conversions to other Unicode encodings,
|
jpayne@69
|
83 // eventually returning it to UTF-16, all the while ignoring `hadErrors`, you will end up with
|
jpayne@69
|
84 // exactly the same char16_t array you started with, *even if* the array is not valid UTF-16. This
|
jpayne@69
|
85 // is useful because many real-world systems that were designed for UCS-2 (plain 16-bit Unicode)
|
jpayne@69
|
86 // and later "upgraded" to UTF-16 do not enforce that their UTF-16 is well-formed. For example,
|
jpayne@69
|
87 // file names on Windows NT are encoded using 16-bit characters, without enforcing that the
|
jpayne@69
|
88 // character sequence is valid UTF-16. It is important that programs on Windows be able to handle
|
jpayne@69
|
89 // such filenames, even if they choose to convert the name to UTF-8 for internal processing.
|
jpayne@69
|
90 //
|
jpayne@69
|
91 // Specifically, KJ's Unicode handling allows unpaired surrogate code points to round-trip through
|
jpayne@69
|
92 // UTF-8 and UTF-32. Unpaired surrogates will be flagged as an error (setting `hadErrors` in the
|
jpayne@69
|
93 // result), but will NOT be replaced with the Unicode replacement character as other erroneous
|
jpayne@69
|
94 // sequences would be, but rather encoded as an invalid surrogate codepoint in the target encoding.
|
jpayne@69
|
95 //
|
jpayne@69
|
96 // KJ makes the following guarantees about invalid input:
|
jpayne@69
|
97 // - A round trip from UTF-16 to other encodings and back will produce exactly the original input,
|
jpayne@69
|
98 // with every leg of the trip raising the `hadErrors` flag if the original input was not valid.
|
jpayne@69
|
99 // - A round trip from UTF-8 or UTF-32 to other encodings and back will either produce exactly
|
jpayne@69
|
100 // the original input, or will have replaced some invalid sequences with the Unicode replacement
|
jpayne@69
|
101 // character, U+FFFD. No code units will ever be removed unless they are replaced with U+FFFD,
|
jpayne@69
|
102 // and no code units will ever be added except to encode U+FFFD. If the original input was not
|
jpayne@69
|
103 // valid, the `hadErrors` flag will be raised on the first leg of the trip, and will also be
|
jpayne@69
|
104 // raised on subsequent legs unless all invalid sequences were replaced with U+FFFD (which, after
|
jpayne@69
|
105 // all, is a valid code point).
|
jpayne@69
|
106
|
jpayne@69
|
107 EncodingResult<Array<wchar_t>> encodeWideString(
|
jpayne@69
|
108 ArrayPtr<const char> text, bool nulTerminate = false);
|
jpayne@69
|
109 EncodingResult<String> decodeWideString(ArrayPtr<const wchar_t> wide);
|
jpayne@69
|
110 // Encode / decode strings of wchar_t, aka "wide strings". Unfortunately, different platforms have
|
jpayne@69
|
111 // different definitions for wchar_t. For example, on Windows they are 16-bit and encode UTF-16,
|
jpayne@69
|
112 // but on Linux they are 32-bit and encode UTF-32. Some platforms even define wchar_t as 8-bit,
|
jpayne@69
|
113 // encoding UTF-8 (e.g. BeOS did this).
|
jpayne@69
|
114 //
|
jpayne@69
|
115 // KJ assumes that wide strings use the UTF encoding that corresponds to the size of wchar_t on
|
jpayne@69
|
116 // the target platform. So, these functions are simple aliases for encodeUtf*/decodeUtf*, above
|
jpayne@69
|
117 // (or simply make a copy if wchar_t is 8 bits).
|
jpayne@69
|
118
|
jpayne@69
|
119 String encodeHex(ArrayPtr<const byte> bytes);
|
jpayne@69
|
120 EncodingResult<Array<byte>> decodeHex(ArrayPtr<const char> text);
|
jpayne@69
|
121 // Encode/decode bytes as hex strings.
|
jpayne@69
|
122
|
jpayne@69
|
123 String encodeUriComponent(ArrayPtr<const byte> bytes);
|
jpayne@69
|
124 String encodeUriComponent(ArrayPtr<const char> bytes);
|
jpayne@69
|
125 EncodingResult<String> decodeUriComponent(ArrayPtr<const char> text);
|
jpayne@69
|
126 // Encode/decode URI components using % escapes for characters listed as "reserved" in RFC 2396.
|
jpayne@69
|
127 // This is the same behavior as JavaScript's `encodeURIComponent()`.
|
jpayne@69
|
128 //
|
jpayne@69
|
129 // See https://tools.ietf.org/html/rfc2396#section-2.3
|
jpayne@69
|
130
|
jpayne@69
|
131 String encodeUriFragment(ArrayPtr<const byte> bytes);
|
jpayne@69
|
132 String encodeUriFragment(ArrayPtr<const char> bytes);
|
jpayne@69
|
133 // Encode URL fragment components using the fragment percent encode set defined by the WHATWG URL
|
jpayne@69
|
134 // specification. Use decodeUriComponent() to decode.
|
jpayne@69
|
135 //
|
jpayne@69
|
136 // Quirk: We also percent-encode the '%' sign itself, because we expect to be called on percent-
|
jpayne@69
|
137 // decoded data. In other words, this function is not idempotent, in contrast to the URL spec.
|
jpayne@69
|
138 //
|
jpayne@69
|
139 // See https://url.spec.whatwg.org/#fragment-percent-encode-set
|
jpayne@69
|
140
|
jpayne@69
|
141 String encodeUriPath(ArrayPtr<const byte> bytes);
|
jpayne@69
|
142 String encodeUriPath(ArrayPtr<const char> bytes);
|
jpayne@69
|
143 // Encode URL path components (not entire paths!) using the path percent encode set defined by the
|
jpayne@69
|
144 // WHATWG URL specification. Use decodeUriComponent() to decode.
|
jpayne@69
|
145 //
|
jpayne@69
|
146 // Quirk: We also percent-encode the '%' sign itself, because we expect to be called on percent-
|
jpayne@69
|
147 // decoded data. In other words, this function is not idempotent, in contrast to the URL spec.
|
jpayne@69
|
148 //
|
jpayne@69
|
149 // Quirk: This percent-encodes '/' and '\' characters as well, which are not actually in the set
|
jpayne@69
|
150 // defined by the WHATWG URL spec. Since a conforming URL implementation will only ever call this
|
jpayne@69
|
151 // function on individual path components, and never entire paths, augmenting the character set to
|
jpayne@69
|
152 // include these separators allows this function to be used to implement a URL class that stores
|
jpayne@69
|
153 // its path components in percent-decoded form.
|
jpayne@69
|
154 //
|
jpayne@69
|
155 // See https://url.spec.whatwg.org/#path-percent-encode-set
|
jpayne@69
|
156
|
jpayne@69
|
157 String encodeUriUserInfo(ArrayPtr<const byte> bytes);
|
jpayne@69
|
158 String encodeUriUserInfo(ArrayPtr<const char> bytes);
|
jpayne@69
|
159 // Encode URL userinfo components using the userinfo percent encode set defined by the WHATWG URL
|
jpayne@69
|
160 // specification. Use decodeUriComponent() to decode.
|
jpayne@69
|
161 //
|
jpayne@69
|
162 // Quirk: We also percent-encode the '%' sign itself, because we expect to be called on percent-
|
jpayne@69
|
163 // decoded data. In other words, this function is not idempotent, in contrast to the URL spec.
|
jpayne@69
|
164 //
|
jpayne@69
|
165 // See https://url.spec.whatwg.org/#userinfo-percent-encode-set
|
jpayne@69
|
166
|
jpayne@69
|
167 String encodeWwwForm(ArrayPtr<const byte> bytes);
|
jpayne@69
|
168 String encodeWwwForm(ArrayPtr<const char> bytes);
|
jpayne@69
|
169 EncodingResult<String> decodeWwwForm(ArrayPtr<const char> text);
|
jpayne@69
|
170 // Encode/decode URI components using % escapes and '+' (for spaces) according to the
|
jpayne@69
|
171 // application/x-www-form-urlencoded format defined by the WHATWG URL specification.
|
jpayne@69
|
172 //
|
jpayne@69
|
173 // Note: Like the fragment, path, and userinfo percent-encoding functions above, this function is
|
jpayne@69
|
174 // not idempotent: we percent-encode '%' signs. However, in this particular case the spec happens
|
jpayne@69
|
175 // to agree with us!
|
jpayne@69
|
176 //
|
jpayne@69
|
177 // See https://url.spec.whatwg.org/#concept-urlencoded-byte-serializer
|
jpayne@69
|
178
|
jpayne@69
|
179 struct DecodeUriOptions {
|
jpayne@69
|
180 // Parameter to `decodeBinaryUriComponent()`.
|
jpayne@69
|
181
|
jpayne@69
|
182 // This struct is intentionally convertible from bool, in order to maintain backwards
|
jpayne@69
|
183 // compatibility with code written when `decodeBinaryUriComponent()` took a boolean second
|
jpayne@69
|
184 // parameter.
|
jpayne@69
|
185 DecodeUriOptions(bool nulTerminate = false, bool plusToSpace = false)
|
jpayne@69
|
186 : nulTerminate(nulTerminate), plusToSpace(plusToSpace) {}
|
jpayne@69
|
187
|
jpayne@69
|
188 bool nulTerminate;
|
jpayne@69
|
189 // Append a terminal NUL byte.
|
jpayne@69
|
190
|
jpayne@69
|
191 bool plusToSpace;
|
jpayne@69
|
192 // Convert '+' to ' ' characters before percent decoding. Used to decode
|
jpayne@69
|
193 // application/x-www-form-urlencoded text, such as query strings.
|
jpayne@69
|
194 };
|
jpayne@69
|
195 EncodingResult<Array<byte>> decodeBinaryUriComponent(
|
jpayne@69
|
196 ArrayPtr<const char> text, DecodeUriOptions options = DecodeUriOptions());
|
jpayne@69
|
197 // Decode URI components using % escapes. This is a lower-level interface used to implement both
|
jpayne@69
|
198 // `decodeUriComponent()` and `decodeWwwForm()`
|
jpayne@69
|
199
|
jpayne@69
|
200 String encodeCEscape(ArrayPtr<const byte> bytes);
|
jpayne@69
|
201 String encodeCEscape(ArrayPtr<const char> bytes);
|
jpayne@69
|
202 EncodingResult<Array<byte>> decodeBinaryCEscape(
|
jpayne@69
|
203 ArrayPtr<const char> text, bool nulTerminate = false);
|
jpayne@69
|
204 EncodingResult<String> decodeCEscape(ArrayPtr<const char> text);
|
jpayne@69
|
205
|
jpayne@69
|
206 String encodeBase64(ArrayPtr<const byte> bytes, bool breakLines = false);
|
jpayne@69
|
207 // Encode the given bytes as base64 text. If `breakLines` is true, line breaks will be inserted
|
jpayne@69
|
208 // into the output every 72 characters (e.g. for encoding e-mail bodies).
|
jpayne@69
|
209
|
jpayne@69
|
210 EncodingResult<Array<byte>> decodeBase64(ArrayPtr<const char> text);
|
jpayne@69
|
211 // Decode base64 text. This function reports errors required by the WHATWG HTML/Infra specs: see
|
jpayne@69
|
212 // https://html.spec.whatwg.org/multipage/webappapis.html#atob for details.
|
jpayne@69
|
213
|
jpayne@69
|
214 String encodeBase64Url(ArrayPtr<const byte> bytes);
|
jpayne@69
|
215 // Encode the given bytes as URL-safe base64 text. (RFC 4648, section 5)
|
jpayne@69
|
216
|
jpayne@69
|
217 // =======================================================================================
|
jpayne@69
|
218 // inline implementation details
|
jpayne@69
|
219
|
jpayne@69
|
220 namespace _ { // private
|
jpayne@69
|
221
|
jpayne@69
|
222 template <typename T>
|
jpayne@69
|
223 NullableValue<T> readMaybe(EncodingResult<T>&& value) {
|
jpayne@69
|
224 if (value.hadErrors) {
|
jpayne@69
|
225 return nullptr;
|
jpayne@69
|
226 } else {
|
jpayne@69
|
227 return kj::mv(value);
|
jpayne@69
|
228 }
|
jpayne@69
|
229 }
|
jpayne@69
|
230
|
jpayne@69
|
231 template <typename T>
|
jpayne@69
|
232 T* readMaybe(EncodingResult<T>& value) {
|
jpayne@69
|
233 if (value.hadErrors) {
|
jpayne@69
|
234 return nullptr;
|
jpayne@69
|
235 } else {
|
jpayne@69
|
236 return &value;
|
jpayne@69
|
237 }
|
jpayne@69
|
238 }
|
jpayne@69
|
239
|
jpayne@69
|
240 template <typename T>
|
jpayne@69
|
241 const T* readMaybe(const EncodingResult<T>& value) {
|
jpayne@69
|
242 if (value.hadErrors) {
|
jpayne@69
|
243 return nullptr;
|
jpayne@69
|
244 } else {
|
jpayne@69
|
245 return &value;
|
jpayne@69
|
246 }
|
jpayne@69
|
247 }
|
jpayne@69
|
248
|
jpayne@69
|
249 String encodeCEscapeImpl(ArrayPtr<const byte> bytes, bool isBinary);
|
jpayne@69
|
250
|
jpayne@69
|
251 } // namespace _ (private)
|
jpayne@69
|
252
|
jpayne@69
|
253 inline String encodeUriComponent(ArrayPtr<const char> text) {
|
jpayne@69
|
254 return encodeUriComponent(text.asBytes());
|
jpayne@69
|
255 }
|
jpayne@69
|
256 inline EncodingResult<String> decodeUriComponent(ArrayPtr<const char> text) {
|
jpayne@69
|
257 auto result = decodeBinaryUriComponent(text, DecodeUriOptions { /*.nulTerminate=*/true });
|
jpayne@69
|
258 return { String(result.releaseAsChars()), result.hadErrors };
|
jpayne@69
|
259 }
|
jpayne@69
|
260
|
jpayne@69
|
261 inline String encodeUriFragment(ArrayPtr<const char> text) {
|
jpayne@69
|
262 return encodeUriFragment(text.asBytes());
|
jpayne@69
|
263 }
|
jpayne@69
|
264 inline String encodeUriPath(ArrayPtr<const char> text) {
|
jpayne@69
|
265 return encodeUriPath(text.asBytes());
|
jpayne@69
|
266 }
|
jpayne@69
|
267 inline String encodeUriUserInfo(ArrayPtr<const char> text) {
|
jpayne@69
|
268 return encodeUriUserInfo(text.asBytes());
|
jpayne@69
|
269 }
|
jpayne@69
|
270
|
jpayne@69
|
271 inline String encodeWwwForm(ArrayPtr<const char> text) {
|
jpayne@69
|
272 return encodeWwwForm(text.asBytes());
|
jpayne@69
|
273 }
|
jpayne@69
|
274 inline EncodingResult<String> decodeWwwForm(ArrayPtr<const char> text) {
|
jpayne@69
|
275 auto result = decodeBinaryUriComponent(text, DecodeUriOptions { /*.nulTerminate=*/true,
|
jpayne@69
|
276 /*.plusToSpace=*/true });
|
jpayne@69
|
277 return { String(result.releaseAsChars()), result.hadErrors };
|
jpayne@69
|
278 }
|
jpayne@69
|
279
|
jpayne@69
|
280 inline String encodeCEscape(ArrayPtr<const char> text) {
|
jpayne@69
|
281 return _::encodeCEscapeImpl(text.asBytes(), false);
|
jpayne@69
|
282 }
|
jpayne@69
|
283
|
jpayne@69
|
284 inline String encodeCEscape(ArrayPtr<const byte> bytes) {
|
jpayne@69
|
285 return _::encodeCEscapeImpl(bytes, true);
|
jpayne@69
|
286 }
|
jpayne@69
|
287
|
jpayne@69
|
288 inline EncodingResult<String> decodeCEscape(ArrayPtr<const char> text) {
|
jpayne@69
|
289 auto result = decodeBinaryCEscape(text, true);
|
jpayne@69
|
290 return { String(result.releaseAsChars()), result.hadErrors };
|
jpayne@69
|
291 }
|
jpayne@69
|
292
|
jpayne@69
|
293 // If you pass a string literal to a function taking ArrayPtr<const char>, it'll include the NUL
|
jpayne@69
|
294 // termintator, which is surprising. Let's add overloads that avoid that. In practice this probably
|
jpayne@69
|
295 // only even matters for encoding-test.c++.
|
jpayne@69
|
296
|
jpayne@69
|
297 template <size_t s>
|
jpayne@69
|
298 inline EncodingResult<Array<char16_t>> encodeUtf16(const char (&text)[s], bool nulTerminate=false) {
|
jpayne@69
|
299 return encodeUtf16(arrayPtr(text, s - 1), nulTerminate);
|
jpayne@69
|
300 }
|
jpayne@69
|
301 template <size_t s>
|
jpayne@69
|
302 inline EncodingResult<Array<char32_t>> encodeUtf32(const char (&text)[s], bool nulTerminate=false) {
|
jpayne@69
|
303 return encodeUtf32(arrayPtr(text, s - 1), nulTerminate);
|
jpayne@69
|
304 }
|
jpayne@69
|
305 template <size_t s>
|
jpayne@69
|
306 inline EncodingResult<Array<wchar_t>> encodeWideString(
|
jpayne@69
|
307 const char (&text)[s], bool nulTerminate=false) {
|
jpayne@69
|
308 return encodeWideString(arrayPtr(text, s - 1), nulTerminate);
|
jpayne@69
|
309 }
|
jpayne@69
|
310 template <size_t s>
|
jpayne@69
|
311 inline EncodingResult<String> decodeUtf16(const char16_t (&utf16)[s]) {
|
jpayne@69
|
312 return decodeUtf16(arrayPtr(utf16, s - 1));
|
jpayne@69
|
313 }
|
jpayne@69
|
314 template <size_t s>
|
jpayne@69
|
315 inline EncodingResult<String> decodeUtf32(const char32_t (&utf32)[s]) {
|
jpayne@69
|
316 return decodeUtf32(arrayPtr(utf32, s - 1));
|
jpayne@69
|
317 }
|
jpayne@69
|
318 template <size_t s>
|
jpayne@69
|
319 inline EncodingResult<String> decodeWideString(const wchar_t (&utf32)[s]) {
|
jpayne@69
|
320 return decodeWideString(arrayPtr(utf32, s - 1));
|
jpayne@69
|
321 }
|
jpayne@69
|
322 template <size_t s>
|
jpayne@69
|
323 inline EncodingResult<Array<byte>> decodeHex(const char (&text)[s]) {
|
jpayne@69
|
324 return decodeHex(arrayPtr(text, s - 1));
|
jpayne@69
|
325 }
|
jpayne@69
|
326 template <size_t s>
|
jpayne@69
|
327 inline String encodeUriComponent(const char (&text)[s]) {
|
jpayne@69
|
328 return encodeUriComponent(arrayPtr(text, s - 1));
|
jpayne@69
|
329 }
|
jpayne@69
|
330 template <size_t s>
|
jpayne@69
|
331 inline Array<byte> decodeBinaryUriComponent(const char (&text)[s]) {
|
jpayne@69
|
332 return decodeBinaryUriComponent(arrayPtr(text, s - 1));
|
jpayne@69
|
333 }
|
jpayne@69
|
334 template <size_t s>
|
jpayne@69
|
335 inline EncodingResult<String> decodeUriComponent(const char (&text)[s]) {
|
jpayne@69
|
336 return decodeUriComponent(arrayPtr(text, s-1));
|
jpayne@69
|
337 }
|
jpayne@69
|
338 template <size_t s>
|
jpayne@69
|
339 inline String encodeUriFragment(const char (&text)[s]) {
|
jpayne@69
|
340 return encodeUriFragment(arrayPtr(text, s - 1));
|
jpayne@69
|
341 }
|
jpayne@69
|
342 template <size_t s>
|
jpayne@69
|
343 inline String encodeUriPath(const char (&text)[s]) {
|
jpayne@69
|
344 return encodeUriPath(arrayPtr(text, s - 1));
|
jpayne@69
|
345 }
|
jpayne@69
|
346 template <size_t s>
|
jpayne@69
|
347 inline String encodeUriUserInfo(const char (&text)[s]) {
|
jpayne@69
|
348 return encodeUriUserInfo(arrayPtr(text, s - 1));
|
jpayne@69
|
349 }
|
jpayne@69
|
350 template <size_t s>
|
jpayne@69
|
351 inline String encodeWwwForm(const char (&text)[s]) {
|
jpayne@69
|
352 return encodeWwwForm(arrayPtr(text, s - 1));
|
jpayne@69
|
353 }
|
jpayne@69
|
354 template <size_t s>
|
jpayne@69
|
355 inline EncodingResult<String> decodeWwwForm(const char (&text)[s]) {
|
jpayne@69
|
356 return decodeWwwForm(arrayPtr(text, s-1));
|
jpayne@69
|
357 }
|
jpayne@69
|
358 template <size_t s>
|
jpayne@69
|
359 inline String encodeCEscape(const char (&text)[s]) {
|
jpayne@69
|
360 return encodeCEscape(arrayPtr(text, s - 1));
|
jpayne@69
|
361 }
|
jpayne@69
|
362 template <size_t s>
|
jpayne@69
|
363 inline EncodingResult<Array<byte>> decodeBinaryCEscape(const char (&text)[s]) {
|
jpayne@69
|
364 return decodeBinaryCEscape(arrayPtr(text, s - 1));
|
jpayne@69
|
365 }
|
jpayne@69
|
366 template <size_t s>
|
jpayne@69
|
367 inline EncodingResult<String> decodeCEscape(const char (&text)[s]) {
|
jpayne@69
|
368 return decodeCEscape(arrayPtr(text, s-1));
|
jpayne@69
|
369 }
|
jpayne@69
|
370 template <size_t s>
|
jpayne@69
|
371 EncodingResult<Array<byte>> decodeBase64(const char (&text)[s]) {
|
jpayne@69
|
372 return decodeBase64(arrayPtr(text, s - 1));
|
jpayne@69
|
373 }
|
jpayne@69
|
374
|
jpayne@69
|
375 #if __cpp_char8_t
|
jpayne@69
|
376 template <size_t s>
|
jpayne@69
|
377 inline EncodingResult<Array<char16_t>> encodeUtf16(const char8_t (&text)[s], bool nulTerminate=false) {
|
jpayne@69
|
378 return encodeUtf16(arrayPtr(reinterpret_cast<const char*>(text), s - 1), nulTerminate);
|
jpayne@69
|
379 }
|
jpayne@69
|
380 template <size_t s>
|
jpayne@69
|
381 inline EncodingResult<Array<char32_t>> encodeUtf32(const char8_t (&text)[s], bool nulTerminate=false) {
|
jpayne@69
|
382 return encodeUtf32(arrayPtr(reinterpret_cast<const char*>(text), s - 1), nulTerminate);
|
jpayne@69
|
383 }
|
jpayne@69
|
384 template <size_t s>
|
jpayne@69
|
385 inline EncodingResult<Array<wchar_t>> encodeWideString(
|
jpayne@69
|
386 const char8_t (&text)[s], bool nulTerminate=false) {
|
jpayne@69
|
387 return encodeWideString(arrayPtr(reinterpret_cast<const char*>(text), s - 1), nulTerminate);
|
jpayne@69
|
388 }
|
jpayne@69
|
389 template <size_t s>
|
jpayne@69
|
390 inline EncodingResult<Array<byte>> decodeHex(const char8_t (&text)[s]) {
|
jpayne@69
|
391 return decodeHex(arrayPtr(reinterpret_cast<const char*>(text), s - 1));
|
jpayne@69
|
392 }
|
jpayne@69
|
393 template <size_t s>
|
jpayne@69
|
394 inline String encodeUriComponent(const char8_t (&text)[s]) {
|
jpayne@69
|
395 return encodeUriComponent(arrayPtr(reinterpret_cast<const char*>(text), s - 1));
|
jpayne@69
|
396 }
|
jpayne@69
|
397 template <size_t s>
|
jpayne@69
|
398 inline Array<byte> decodeBinaryUriComponent(const char8_t (&text)[s]) {
|
jpayne@69
|
399 return decodeBinaryUriComponent(arrayPtr(reinterpret_cast<const char*>(text), s - 1));
|
jpayne@69
|
400 }
|
jpayne@69
|
401 template <size_t s>
|
jpayne@69
|
402 inline EncodingResult<String> decodeUriComponent(const char8_t (&text)[s]) {
|
jpayne@69
|
403 return decodeUriComponent(arrayPtr(reinterpret_cast<const char*>(text), s-1));
|
jpayne@69
|
404 }
|
jpayne@69
|
405 template <size_t s>
|
jpayne@69
|
406 inline String encodeUriFragment(const char8_t (&text)[s]) {
|
jpayne@69
|
407 return encodeUriFragment(arrayPtr(reinterpret_cast<const char*>(text), s - 1));
|
jpayne@69
|
408 }
|
jpayne@69
|
409 template <size_t s>
|
jpayne@69
|
410 inline String encodeUriPath(const char8_t (&text)[s]) {
|
jpayne@69
|
411 return encodeUriPath(arrayPtr(reinterpret_cast<const char*>(text), s - 1));
|
jpayne@69
|
412 }
|
jpayne@69
|
413 template <size_t s>
|
jpayne@69
|
414 inline String encodeUriUserInfo(const char8_t (&text)[s]) {
|
jpayne@69
|
415 return encodeUriUserInfo(arrayPtr(reinterpret_cast<const char*>(text), s - 1));
|
jpayne@69
|
416 }
|
jpayne@69
|
417 template <size_t s>
|
jpayne@69
|
418 inline String encodeWwwForm(const char8_t (&text)[s]) {
|
jpayne@69
|
419 return encodeWwwForm(arrayPtr(reinterpret_cast<const char*>(text), s - 1));
|
jpayne@69
|
420 }
|
jpayne@69
|
421 template <size_t s>
|
jpayne@69
|
422 inline EncodingResult<String> decodeWwwForm(const char8_t (&text)[s]) {
|
jpayne@69
|
423 return decodeWwwForm(arrayPtr(reinterpret_cast<const char*>(text), s-1));
|
jpayne@69
|
424 }
|
jpayne@69
|
425 template <size_t s>
|
jpayne@69
|
426 inline String encodeCEscape(const char8_t (&text)[s]) {
|
jpayne@69
|
427 return encodeCEscape(arrayPtr(reinterpret_cast<const char*>(text), s - 1));
|
jpayne@69
|
428 }
|
jpayne@69
|
429 template <size_t s>
|
jpayne@69
|
430 inline EncodingResult<Array<byte>> decodeBinaryCEscape(const char8_t (&text)[s]) {
|
jpayne@69
|
431 return decodeBinaryCEscape(arrayPtr(reinterpret_cast<const char*>(text), s - 1));
|
jpayne@69
|
432 }
|
jpayne@69
|
433 template <size_t s>
|
jpayne@69
|
434 inline EncodingResult<String> decodeCEscape(const char8_t (&text)[s]) {
|
jpayne@69
|
435 return decodeCEscape(arrayPtr(reinterpret_cast<const char*>(text), s-1));
|
jpayne@69
|
436 }
|
jpayne@69
|
437 template <size_t s>
|
jpayne@69
|
438 EncodingResult<Array<byte>> decodeBase64(const char8_t (&text)[s]) {
|
jpayne@69
|
439 return decodeBase64(arrayPtr(reinterpret_cast<const char*>(text), s - 1));
|
jpayne@69
|
440 }
|
jpayne@69
|
441 #endif
|
jpayne@69
|
442
|
jpayne@69
|
443 } // namespace kj
|
jpayne@69
|
444
|
jpayne@69
|
445 KJ_END_HEADER
|