2 * Copyright (c) 2011-2012 Apple Inc. All rights reserved.
4 * @APPLE_APACHE_LICENSE_HEADER_START@
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 * @APPLE_APACHE_LICENSE_HEADER_END@
23 #include <libkern/OSByteOrder.h>
25 #if defined(__LITTLE_ENDIAN__)
26 #define DISPATCH_DATA_FORMAT_TYPE_UTF16_HOST DISPATCH_DATA_FORMAT_TYPE_UTF16LE
27 #define DISPATCH_DATA_FORMAT_TYPE_UTF16_REV DISPATCH_DATA_FORMAT_TYPE_UTF16BE
28 #elif defined(__BIG_ENDIAN__)
29 #define DISPATCH_DATA_FORMAT_TYPE_UTF16_HOST DISPATCH_DATA_FORMAT_TYPE_UTF16BE
30 #define DISPATCH_DATA_FORMAT_TYPE_UTF16_REV DISPATCH_DATA_FORMAT_TYPE_UTF16LE
34 _DISPATCH_DATA_FORMAT_NONE = 0x1,
35 _DISPATCH_DATA_FORMAT_UTF8 = 0x2,
36 _DISPATCH_DATA_FORMAT_UTF16LE = 0x4,
37 _DISPATCH_DATA_FORMAT_UTF16BE = 0x8,
38 _DISPATCH_DATA_FORMAT_UTF_ANY = 0x10,
39 _DISPATCH_DATA_FORMAT_BASE32 = 0x20,
40 _DISPATCH_DATA_FORMAT_BASE64 = 0x40,
44 #pragma mark baseXX tables
46 static const char base32_encode_table[] =
47 "ABCDEFGHIJKLMNOPQRSTUVWXYZ23456789";
49 static const char base32_decode_table[] = {
50 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
51 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
52 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 26,
53 27, 28, 29, 30, 31, -1, -1, -1, -1, -1, -2, -1, -1, -1, 0, 1, 2,
54 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
55 20, 21, 22, 23, 24, 25
57 static const ssize_t base32_decode_table_size = sizeof(base32_decode_table)
58 / sizeof(*base32_decode_table);
60 static const char base64_encode_table[] =
61 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
63 static const char base64_decode_table[] = {
64 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
65 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
66 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
67 -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59,
68 60, 61, -1, -1, -1, -2, -1, -1, -1, 0, 1, 2, 3, 4,
69 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
70 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26,
71 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
72 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
75 static const ssize_t base64_decode_table_size = sizeof(base64_decode_table)
76 / sizeof(*base64_decode_table);
79 #pragma mark dispatch_transform_buffer
81 typedef struct dispatch_transform_buffer_s {
89 } dispatch_transform_buffer_s;
92 _dispatch_transform_sizet_mul(size_t a, size_t b)
95 if (a == 0 || rv/a >= b) {
101 #define BUFFER_MALLOC_MAX (100*1024*1024)
104 _dispatch_transform_buffer_new(dispatch_transform_buffer_s *buffer,
105 size_t required, size_t size)
107 size_t remaining = buffer->size - (buffer->ptr.u8 - buffer->start);
108 if (required == 0 || remaining < required) {
110 if (buffer->ptr.u8 > buffer->start) {
111 dispatch_data_t _new = dispatch_data_create(buffer->start,
112 buffer->ptr.u8 - buffer->start, NULL,
113 DISPATCH_DATA_DESTRUCTOR_FREE);
114 dispatch_data_t _concat = dispatch_data_create_concat(
116 dispatch_release(_new);
117 dispatch_release(buffer->data);
118 buffer->data = _concat;
123 buffer->size = required + size;
124 buffer->start = NULL;
125 if (buffer->size > 0) {
126 if (buffer->size > BUFFER_MALLOC_MAX) {
129 buffer->start = (uint8_t*)malloc(buffer->size);
130 if (buffer->start == NULL) {
134 buffer->ptr.u8 = buffer->start;
140 #pragma mark dispatch_transform_helpers
142 static dispatch_data_t
143 _dispatch_data_subrange_map(dispatch_data_t data, const void **ptr,
144 size_t offset, size_t size)
146 dispatch_data_t subrange, map = NULL;
148 subrange = dispatch_data_create_subrange(data, offset, size);
149 if (dispatch_data_get_size(subrange) == size) {
150 map = dispatch_data_create_map(subrange, ptr, NULL);
152 dispatch_release(subrange);
156 static dispatch_data_format_type_t
157 _dispatch_transform_detect_utf(dispatch_data_t data)
160 dispatch_data_t subrange = _dispatch_data_subrange_map(data, &p, 0, 2);
162 if (subrange == NULL) {
166 const uint16_t ch = *(const uint16_t *)p;
167 dispatch_data_format_type_t type = DISPATCH_DATA_FORMAT_TYPE_UTF8;
170 type = DISPATCH_DATA_FORMAT_TYPE_UTF16_HOST;
171 } else if (ch == 0xfffe) {
172 type = DISPATCH_DATA_FORMAT_TYPE_UTF16_REV;
175 dispatch_release(subrange);
181 _dispatch_transform_swap_to_host(uint16_t x, int32_t byteOrder)
183 if (byteOrder == OSLittleEndian) {
184 return OSSwapLittleToHostInt16(x);
186 return OSSwapBigToHostInt16(x);
190 _dispatch_transform_swap_from_host(uint16_t x, int32_t byteOrder)
192 if (byteOrder == OSLittleEndian) {
193 return OSSwapHostToLittleInt16(x);
195 return OSSwapHostToBigInt16(x);
202 _dispatch_transform_utf8_length(uint8_t byte)
204 if ((byte & 0x80) == 0) {
206 } else if ((byte & 0xe0) == 0xc0) {
208 } else if ((byte & 0xf0) == 0xe0) {
210 } else if ((byte & 0xf8) == 0xf0) {
217 _dispatch_transform_read_utf8_sequence(const uint8_t *bytes)
220 uint8_t seq_length = _dispatch_transform_utf8_length(*bytes);
222 switch (seq_length) {
224 wch |= (*bytes & 0x7);
228 wch |= (*bytes & 0xf);
232 wch |= (*bytes & 0x1f);
236 wch = (*bytes & 0x7f);
239 // Not a utf-8 sequence
246 while (seq_length > 0) {
247 wch |= (*bytes & 0x3f);
251 if (seq_length > 0) {
261 static dispatch_data_t
262 _dispatch_transform_to_utf16(dispatch_data_t data, int32_t byteOrder)
264 __block size_t skip = 0;
266 __block dispatch_transform_buffer_s buffer = {
267 .data = dispatch_data_empty,
270 bool success = dispatch_data_apply(data, ^(
271 DISPATCH_UNUSED dispatch_data_t region,
272 size_t offset, const void *_buffer, size_t size) {
273 const uint8_t *src = _buffer;
277 size_t dest_size = 2 + _dispatch_transform_sizet_mul(size,
279 if (!_dispatch_transform_buffer_new(&buffer, dest_size, 0)) {
283 *(buffer.ptr.u16)++ = _dispatch_transform_swap_from_host(0xfeff,
287 // Skip is incremented if the previous block read-ahead into our block
291 } else if (skip > 0) {
297 for (i = 0; i < size;) {
299 uint8_t byte_size = _dispatch_transform_utf8_length(*src);
301 if (byte_size == 0) {
303 } else if (byte_size + i > size) {
304 // UTF-8 byte sequence spans over into the next block(s)
306 dispatch_data_t subrange = _dispatch_data_subrange_map(data, &p,
307 offset + i, byte_size);
308 if (subrange == NULL) {
312 wch = _dispatch_transform_read_utf8_sequence(p);
313 skip += byte_size - (size - i);
317 dispatch_release(subrange);
319 wch = _dispatch_transform_read_utf8_sequence(src);
324 size_t next = _dispatch_transform_sizet_mul(size - i, sizeof(uint16_t));
325 if (wch >= 0xd800 && wch < 0xdfff) {
326 // Illegal range (surrogate pair)
328 } else if (wch >= 0x10000) {
330 if (!_dispatch_transform_buffer_new(&buffer, 2 *
331 sizeof(uint16_t), next)) {
335 *(buffer.ptr.u16)++ = _dispatch_transform_swap_from_host(
336 ((wch >> 10) & 0x3ff) + 0xd800, byteOrder);
337 *(buffer.ptr.u16)++ = _dispatch_transform_swap_from_host(
338 (wch & 0x3ff) + 0xdc00, byteOrder);
340 if (!_dispatch_transform_buffer_new(&buffer, 1 *
341 sizeof(uint16_t), next)) {
344 *(buffer.ptr.u16)++ = _dispatch_transform_swap_from_host(
345 (wch & 0xffff), byteOrder);
349 (void)_dispatch_transform_buffer_new(&buffer, 0, 0);
355 (void)_dispatch_transform_buffer_new(&buffer, 0, 0);
356 dispatch_release(buffer.data);
363 static dispatch_data_t
364 _dispatch_transform_from_utf16(dispatch_data_t data, int32_t byteOrder)
366 __block size_t skip = 0;
368 __block dispatch_transform_buffer_s buffer = {
369 .data = dispatch_data_empty,
372 bool success = dispatch_data_apply(data, ^(
373 DISPATCH_UNUSED dispatch_data_t region, size_t offset,
374 const void *_buffer, size_t size) {
375 const uint16_t *src = _buffer;
378 // Assume first buffer will be mostly single-byte UTF-8 sequences
379 size_t dest_size = _dispatch_transform_sizet_mul(size, 2) / 3;
380 if (!_dispatch_transform_buffer_new(&buffer, dest_size, 0)) {
385 size_t i = 0, max = size / 2;
387 // Skip is incremented if the previous block read-ahead into our block
391 } else if (skip > 0) {
392 src = (uint16_t *)(((uint8_t *)src) + skip);
398 // If the buffer is an odd size, allow read ahead into the next region
399 if ((size % 2) != 0) {
403 for (i = 0; i < max; i++) {
407 if ((i == (max - 1)) && (max > (size / 2))) {
408 // Last byte of an odd sized range
410 dispatch_data_t range = _dispatch_data_subrange_map(data, &p,
411 offset + (i * 2), 2);
415 ch = _dispatch_transform_swap_to_host(*(uint64_t*)p, byteOrder);
416 dispatch_release(range);
419 ch = _dispatch_transform_swap_to_host(src[i], byteOrder);
422 if (ch == 0xfffe && offset == 0 && i == 0) {
423 // Wrong-endian BOM at beginning of data
425 } else if (ch == 0xfeff && offset == 0 && i == 0) {
426 // Correct-endian BOM, skip it
430 if ((ch >= 0xd800) && (ch <= 0xdbff)) {
432 wch = ((ch - 0xd800) << 10);
434 // Surrogate byte isn't in this block
436 dispatch_data_t range = _dispatch_data_subrange_map(data,
437 &p, offset + (i * 2), 2);
441 ch = _dispatch_transform_swap_to_host(*(uint16_t *)p,
443 dispatch_release(range);
446 ch = _dispatch_transform_swap_to_host(src[i], byteOrder);
448 if (!((ch >= 0xdc00) && (ch <= 0xdfff))) {
451 wch = (wch | (ch & 0x3ff));
453 } else if ((ch >= 0xdc00) && (ch <= 0xdfff)) {
459 size_t next = _dispatch_transform_sizet_mul(max - i, 2);
461 if (!_dispatch_transform_buffer_new(&buffer, 1, next)) {
464 *(buffer.ptr.u8)++ = (uint8_t)(wch & 0xff);
465 } else if (wch < 0x800) {
466 if (!_dispatch_transform_buffer_new(&buffer, 2, next)) {
469 *(buffer.ptr.u8)++ = (uint8_t)(0xc0 | (wch >> 6));
470 *(buffer.ptr.u8)++ = (uint8_t)(0x80 | (wch & 0x3f));
471 } else if (wch < 0x10000) {
472 if (!_dispatch_transform_buffer_new(&buffer, 3, next)) {
475 *(buffer.ptr.u8)++ = (uint8_t)(0xe0 | (wch >> 12));
476 *(buffer.ptr.u8)++ = (uint8_t)(0x80 | ((wch >> 6) & 0x3f));
477 *(buffer.ptr.u8)++ = (uint8_t)(0x80 | (wch & 0x3f));
478 } else if (wch < 0x200000) {
479 if (!_dispatch_transform_buffer_new(&buffer, 4, next)) {
482 *(buffer.ptr.u8)++ = (uint8_t)(0xf0 | (wch >> 18));
483 *(buffer.ptr.u8)++ = (uint8_t)(0x80 | ((wch >> 12) & 0x3f));
484 *(buffer.ptr.u8)++ = (uint8_t)(0x80 | ((wch >> 6) & 0x3f));
485 *(buffer.ptr.u8)++ = (uint8_t)(0x80 | (wch & 0x3f));
489 (void)_dispatch_transform_buffer_new(&buffer, 0, 0);
495 (void)_dispatch_transform_buffer_new(&buffer, 0, 0);
496 dispatch_release(buffer.data);
503 static dispatch_data_t
504 _dispatch_transform_from_utf16le(dispatch_data_t data)
506 return _dispatch_transform_from_utf16(data, OSLittleEndian);
509 static dispatch_data_t
510 _dispatch_transform_from_utf16be(dispatch_data_t data)
512 return _dispatch_transform_from_utf16(data, OSBigEndian);
515 static dispatch_data_t
516 _dispatch_transform_to_utf16le(dispatch_data_t data)
518 return _dispatch_transform_to_utf16(data, OSLittleEndian);
521 static dispatch_data_t
522 _dispatch_transform_to_utf16be(dispatch_data_t data)
524 return _dispatch_transform_to_utf16(data, OSBigEndian);
530 static dispatch_data_t
531 _dispatch_transform_from_base32(dispatch_data_t data)
533 __block uint64_t x = 0, count = 0, pad = 0;
535 __block dispatch_data_t rv = dispatch_data_empty;
537 bool success = dispatch_data_apply(data, ^(
538 DISPATCH_UNUSED dispatch_data_t region,
539 DISPATCH_UNUSED size_t offset, const void *buffer, size_t size) {
540 size_t i, dest_size = (size * 5) / 8;
542 uint8_t *dest = (uint8_t*)malloc(dest_size * sizeof(char));
548 const uint8_t *bytes = buffer;
550 for (i = 0; i < size; i++) {
551 if (bytes[i] == '\n' || bytes[i] == '\t' || bytes[i] == ' ') {
555 ssize_t index = bytes[i];
556 if (index >= base32_decode_table_size ||
557 base32_decode_table[index] == -1) {
563 char value = base32_decode_table[index];
572 if ((count & 0x7) == 0) {
573 *ptr++ = (x >> 32) & 0xff;
574 *ptr++ = (x >> 24) & 0xff;
575 *ptr++ = (x >> 16) & 0xff;
576 *ptr++ = (x >> 8) & 0xff;
581 size_t final = (ptr - dest);
597 dispatch_data_t val = dispatch_data_create(dest, final, NULL,
598 DISPATCH_DATA_DESTRUCTOR_FREE);
599 dispatch_data_t concat = dispatch_data_create_concat(rv, val);
601 dispatch_release(val);
602 dispatch_release(rv);
609 dispatch_release(rv);
616 static dispatch_data_t
617 _dispatch_transform_to_base32(dispatch_data_t data)
619 size_t total = dispatch_data_get_size(data);
620 __block size_t count = 0;
622 size_t dest_size = ((total + 4) * 8) / 5;
623 dest_size -= dest_size % 8;
625 uint8_t *dest = (uint8_t*)malloc(dest_size * sizeof(uint8_t));
630 __block uint8_t *ptr = dest;
634 8-bit bytes: xxxxxxxx yyyyyyyy zzzzzzzz xxxxxxxx yyyyyyyy
635 5-bit chunks: aaaaabbb bbcccccd ddddeeee efffffgg ggghhhhh
638 bool success = dispatch_data_apply(data, ^(
639 DISPATCH_UNUSED dispatch_data_t region,
640 size_t offset, const void *buffer, size_t size) {
641 const uint8_t *bytes = buffer;
644 for (i = 0; i < size; i++, count++) {
645 uint8_t curr = bytes[i], last = 0;
647 if ((count % 5) != 0) {
650 dispatch_data_t subrange = _dispatch_data_subrange_map(data,
652 if (subrange == NULL) {
656 dispatch_release(subrange);
665 *ptr++ = base32_encode_table[(curr >> 3) & 0x1f];
669 *ptr++ = base32_encode_table[((last << 2)|(curr >> 6)) & 0x1f];
670 *ptr++ = base32_encode_table[(curr >> 1) & 0x1f];
674 *ptr++ = base32_encode_table[((last << 4)|(curr >> 4)) & 0x1f];
678 *ptr++ = base32_encode_table[((last << 1)|(curr >> 7)) & 0x1f];
679 *ptr++ = base32_encode_table[(curr >> 2) & 0x1f];
683 *ptr++ = base32_encode_table[((last << 3)|(curr >> 5)) & 0x1f];
684 *ptr++ = base32_encode_table[curr & 0x1f];
689 // Last region, insert padding bytes, if needed
690 if (offset + size == total) {
696 *ptr++ = base32_encode_table[(bytes[size-1] << 2) & 0x1c];
700 *ptr++ = base32_encode_table[(bytes[size-1] << 4) & 0x10];
704 *ptr++ = base32_encode_table[(bytes[size-1] << 1) & 0x1e];
708 *ptr++ = base32_encode_table[bytes[size-1] & 0x18];
735 return dispatch_data_create(dest, dest_size, NULL,
736 DISPATCH_DATA_DESTRUCTOR_FREE);
742 static dispatch_data_t
743 _dispatch_transform_from_base64(dispatch_data_t data)
745 __block uint64_t x = 0, count = 0;
746 __block size_t pad = 0;
748 __block dispatch_data_t rv = dispatch_data_empty;
750 bool success = dispatch_data_apply(data, ^(
751 DISPATCH_UNUSED dispatch_data_t region,
752 DISPATCH_UNUSED size_t offset, const void *buffer, size_t size) {
753 size_t i, dest_size = (size * 3) / 4;
755 uint8_t *dest = (uint8_t*)malloc(dest_size * sizeof(uint8_t));
761 const uint8_t *bytes = buffer;
763 for (i = 0; i < size; i++) {
764 if (bytes[i] == '\n' || bytes[i] == '\t' || bytes[i] == ' ') {
768 ssize_t index = bytes[i];
769 if (index >= base64_decode_table_size ||
770 base64_decode_table[index] == -1) {
776 char value = base64_decode_table[index];
785 if ((count & 0x3) == 0) {
786 *ptr++ = (x >> 16) & 0xff;
787 *ptr++ = (x >> 8) & 0xff;
792 size_t final = (ptr - dest);
794 // 2 bytes of pad means only had one char in final group
798 dispatch_data_t val = dispatch_data_create(dest, final, NULL,
799 DISPATCH_DATA_DESTRUCTOR_FREE);
800 dispatch_data_t concat = dispatch_data_create_concat(rv, val);
802 dispatch_release(val);
803 dispatch_release(rv);
810 dispatch_release(rv);
817 static dispatch_data_t
818 _dispatch_transform_to_base64(dispatch_data_t data)
820 // RFC 4648 states that we should not linebreak
821 // http://tools.ietf.org/html/rfc4648
822 size_t total = dispatch_data_get_size(data);
823 __block size_t count = 0;
825 size_t dest_size = ((total + 2) * 4) / 3;
826 dest_size -= dest_size % 4;
828 uint8_t *dest = (uint8_t*)malloc(dest_size * sizeof(uint8_t));
833 __block uint8_t *ptr = dest;
836 * 3 8-bit bytes: xxxxxxxx yyyyyyyy zzzzzzzz
837 * 4 6-bit chunks: aaaaaabb bbbbcccc ccdddddd
840 bool success = dispatch_data_apply(data, ^(
841 DISPATCH_UNUSED dispatch_data_t region,
842 size_t offset, const void *buffer, size_t size) {
843 const uint8_t *bytes = buffer;
846 for (i = 0; i < size; i++, count++) {
847 uint8_t curr = bytes[i], last = 0;
849 if ((count % 3) != 0) {
852 dispatch_data_t subrange = _dispatch_data_subrange_map(data,
854 if (subrange == NULL) {
858 dispatch_release(subrange);
866 *ptr++ = base64_encode_table[(curr >> 2) & 0x3f];
869 *ptr++ = base64_encode_table[((last << 4)|(curr >> 4)) & 0x3f];
872 *ptr++ = base64_encode_table[((last << 2)|(curr >> 6)) & 0x3f];
873 *ptr++ = base64_encode_table[(curr & 0x3f)];
878 // Last region, insert padding bytes, if needed
879 if (offset + size == total) {
884 *ptr++ = base64_encode_table[(bytes[size-1] << 4) & 0x30];
889 *ptr++ = base64_encode_table[(bytes[size-1] << 2) & 0x3c];
902 return dispatch_data_create(dest, dest_size, NULL,
903 DISPATCH_DATA_DESTRUCTOR_FREE);
907 #pragma mark dispatch_data_transform
910 dispatch_data_create_with_transform(dispatch_data_t data,
911 dispatch_data_format_type_t input, dispatch_data_format_type_t output)
913 if (input->type == _DISPATCH_DATA_FORMAT_UTF_ANY) {
914 input = _dispatch_transform_detect_utf(data);
920 if ((input->type & ~output->input_mask) != 0) {
924 if ((output->type & ~input->output_mask) != 0) {
928 if (dispatch_data_get_size(data) == 0) {
932 dispatch_data_t temp1;
934 temp1 = input->decode(data);
936 dispatch_retain(data);
944 dispatch_data_t temp2;
945 if (output->encode) {
946 temp2 = output->encode(temp1);
948 dispatch_retain(temp1);
952 dispatch_release(temp1);
956 const struct dispatch_data_format_type_s _dispatch_data_format_type_none = {
957 .type = _DISPATCH_DATA_FORMAT_NONE,
964 const struct dispatch_data_format_type_s _dispatch_data_format_type_base32 = {
965 .type = _DISPATCH_DATA_FORMAT_BASE32,
966 .input_mask = (_DISPATCH_DATA_FORMAT_NONE | _DISPATCH_DATA_FORMAT_BASE32 |
967 _DISPATCH_DATA_FORMAT_BASE64),
968 .output_mask = (_DISPATCH_DATA_FORMAT_NONE | _DISPATCH_DATA_FORMAT_BASE32 |
969 _DISPATCH_DATA_FORMAT_BASE64),
970 .decode = _dispatch_transform_from_base32,
971 .encode = _dispatch_transform_to_base32,
974 const struct dispatch_data_format_type_s _dispatch_data_format_type_base64 = {
975 .type = _DISPATCH_DATA_FORMAT_BASE64,
976 .input_mask = (_DISPATCH_DATA_FORMAT_NONE | _DISPATCH_DATA_FORMAT_BASE32 |
977 _DISPATCH_DATA_FORMAT_BASE64),
978 .output_mask = (_DISPATCH_DATA_FORMAT_NONE | _DISPATCH_DATA_FORMAT_BASE32 |
979 _DISPATCH_DATA_FORMAT_BASE64),
980 .decode = _dispatch_transform_from_base64,
981 .encode = _dispatch_transform_to_base64,
984 const struct dispatch_data_format_type_s _dispatch_data_format_type_utf16le = {
985 .type = _DISPATCH_DATA_FORMAT_UTF16LE,
986 .input_mask = (_DISPATCH_DATA_FORMAT_UTF8 | _DISPATCH_DATA_FORMAT_UTF16BE |
987 _DISPATCH_DATA_FORMAT_UTF16LE),
988 .output_mask = (_DISPATCH_DATA_FORMAT_UTF8 | _DISPATCH_DATA_FORMAT_UTF16BE |
989 _DISPATCH_DATA_FORMAT_UTF16LE),
990 .decode = _dispatch_transform_from_utf16le,
991 .encode = _dispatch_transform_to_utf16le,
994 const struct dispatch_data_format_type_s _dispatch_data_format_type_utf16be = {
995 .type = _DISPATCH_DATA_FORMAT_UTF16BE,
996 .input_mask = (_DISPATCH_DATA_FORMAT_UTF8 | _DISPATCH_DATA_FORMAT_UTF16BE |
997 _DISPATCH_DATA_FORMAT_UTF16LE),
998 .output_mask = (_DISPATCH_DATA_FORMAT_UTF8 | _DISPATCH_DATA_FORMAT_UTF16BE |
999 _DISPATCH_DATA_FORMAT_UTF16LE),
1000 .decode = _dispatch_transform_from_utf16be,
1001 .encode = _dispatch_transform_to_utf16be,
1004 const struct dispatch_data_format_type_s _dispatch_data_format_type_utf8 = {
1005 .type = _DISPATCH_DATA_FORMAT_UTF8,
1006 .input_mask = (_DISPATCH_DATA_FORMAT_UTF8 | _DISPATCH_DATA_FORMAT_UTF16BE |
1007 _DISPATCH_DATA_FORMAT_UTF16LE),
1008 .output_mask = (_DISPATCH_DATA_FORMAT_UTF8 | _DISPATCH_DATA_FORMAT_UTF16BE |
1009 _DISPATCH_DATA_FORMAT_UTF16LE),
1014 const struct dispatch_data_format_type_s _dispatch_data_format_type_utf_any = {
1015 .type = _DISPATCH_DATA_FORMAT_UTF_ANY,