2 * Copyright (c) 2011 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 dispatch_release(buffer
.data
);
362 static dispatch_data_t
363 _dispatch_transform_from_utf16(dispatch_data_t data
, int32_t byteOrder
)
365 __block
size_t skip
= 0;
367 __block dispatch_transform_buffer_s buffer
= {
368 .data
= dispatch_data_empty
,
371 bool success
= dispatch_data_apply(data
, ^(
372 DISPATCH_UNUSED dispatch_data_t region
, size_t offset
,
373 const void *_buffer
, size_t size
) {
374 const uint16_t *src
= _buffer
;
377 // Assume first buffer will be mostly single-byte UTF-8 sequences
378 size_t dest_size
= _dispatch_transform_sizet_mul(size
, 2) / 3;
379 if (!_dispatch_transform_buffer_new(&buffer
, dest_size
, 0)) {
384 size_t i
= 0, max
= size
/ 2;
386 // Skip is incremented if the previous block read-ahead into our block
390 } else if (skip
> 0) {
391 src
= (uint16_t *)(((uint8_t *)src
) + skip
);
397 // If the buffer is an odd size, allow read ahead into the next region
398 if ((size
% 2) != 0) {
402 for (i
= 0; i
< max
; i
++) {
406 if ((i
== (max
- 1)) && (max
> (size
/ 2))) {
407 // Last byte of an odd sized range
409 dispatch_data_t range
= _dispatch_data_subrange_map(data
, &p
,
410 offset
+ (i
* 2), 2);
414 ch
= _dispatch_transform_swap_to_host(*(uint64_t*)p
, byteOrder
);
415 dispatch_release(range
);
418 ch
= _dispatch_transform_swap_to_host(src
[i
], byteOrder
);
421 if (ch
== 0xfffe && offset
== 0 && i
== 0) {
422 // Wrong-endian BOM at beginning of data
424 } else if (ch
== 0xfeff && offset
== 0 && i
== 0) {
425 // Correct-endian BOM, skip it
429 if ((ch
>= 0xd800) && (ch
<= 0xdbff)) {
431 wch
= ((ch
- 0xd800) << 10);
433 // Surrogate byte isn't in this block
435 dispatch_data_t range
= _dispatch_data_subrange_map(data
,
436 &p
, offset
+ (i
* 2), 2);
440 ch
= _dispatch_transform_swap_to_host(*(uint16_t *)p
,
442 dispatch_release(range
);
445 ch
= _dispatch_transform_swap_to_host(src
[i
], byteOrder
);
447 if (!((ch
>= 0xdc00) && (ch
<= 0xdfff))) {
450 wch
= (wch
| (ch
& 0x3ff));
452 } else if ((ch
>= 0xdc00) && (ch
<= 0xdfff)) {
458 size_t next
= _dispatch_transform_sizet_mul(max
- i
, 2);
460 if (!_dispatch_transform_buffer_new(&buffer
, 1, next
)) {
463 *(buffer
.ptr
.u8
)++ = (uint8_t)(wch
& 0xff);
464 } else if (wch
< 0x800) {
465 if (!_dispatch_transform_buffer_new(&buffer
, 2, next
)) {
468 *(buffer
.ptr
.u8
)++ = (uint8_t)(0xc0 | (wch
>> 6));
469 *(buffer
.ptr
.u8
)++ = (uint8_t)(0x80 | (wch
& 0x3f));
470 } else if (wch
< 0x10000) {
471 if (!_dispatch_transform_buffer_new(&buffer
, 3, next
)) {
474 *(buffer
.ptr
.u8
)++ = (uint8_t)(0xe0 | (wch
>> 12));
475 *(buffer
.ptr
.u8
)++ = (uint8_t)(0x80 | ((wch
>> 6) & 0x3f));
476 *(buffer
.ptr
.u8
)++ = (uint8_t)(0x80 | (wch
& 0x3f));
477 } else if (wch
< 0x200000) {
478 if (!_dispatch_transform_buffer_new(&buffer
, 4, next
)) {
481 *(buffer
.ptr
.u8
)++ = (uint8_t)(0xf0 | (wch
>> 18));
482 *(buffer
.ptr
.u8
)++ = (uint8_t)(0x80 | ((wch
>> 12) & 0x3f));
483 *(buffer
.ptr
.u8
)++ = (uint8_t)(0x80 | ((wch
>> 6) & 0x3f));
484 *(buffer
.ptr
.u8
)++ = (uint8_t)(0x80 | (wch
& 0x3f));
488 (void)_dispatch_transform_buffer_new(&buffer
, 0, 0);
494 dispatch_release(buffer
.data
);
501 static dispatch_data_t
502 _dispatch_transform_from_utf16le(dispatch_data_t data
)
504 return _dispatch_transform_from_utf16(data
, OSLittleEndian
);
507 static dispatch_data_t
508 _dispatch_transform_from_utf16be(dispatch_data_t data
)
510 return _dispatch_transform_from_utf16(data
, OSBigEndian
);
513 static dispatch_data_t
514 _dispatch_transform_to_utf16le(dispatch_data_t data
)
516 return _dispatch_transform_to_utf16(data
, OSLittleEndian
);
519 static dispatch_data_t
520 _dispatch_transform_to_utf16be(dispatch_data_t data
)
522 return _dispatch_transform_to_utf16(data
, OSBigEndian
);
528 static dispatch_data_t
529 _dispatch_transform_from_base32(dispatch_data_t data
)
531 __block
uint64_t x
= 0, count
= 0, pad
= 0;
533 __block dispatch_data_t rv
= dispatch_data_empty
;
535 bool success
= dispatch_data_apply(data
, ^(
536 DISPATCH_UNUSED dispatch_data_t region
,
537 DISPATCH_UNUSED
size_t offset
, const void *buffer
, size_t size
) {
538 size_t i
, dest_size
= (size
* 5) / 8;
540 uint8_t *dest
= (uint8_t*)malloc(dest_size
* sizeof(char));
546 const uint8_t *bytes
= buffer
;
548 for (i
= 0; i
< size
; i
++) {
549 if (bytes
[i
] == '\n' || bytes
[i
] == '\t' || bytes
[i
] == ' ') {
553 ssize_t index
= bytes
[i
];
554 if (index
>= base32_decode_table_size
||
555 base32_decode_table
[index
] == -1) {
561 char value
= base32_decode_table
[index
];
570 if ((count
& 0x7) == 0) {
571 *ptr
++ = (x
>> 32) & 0xff;
572 *ptr
++ = (x
>> 24) & 0xff;
573 *ptr
++ = (x
>> 16) & 0xff;
574 *ptr
++ = (x
>> 8) & 0xff;
579 size_t final
= (ptr
- dest
);
595 dispatch_data_t val
= dispatch_data_create(dest
, final
, NULL
,
596 DISPATCH_DATA_DESTRUCTOR_FREE
);
597 dispatch_data_t concat
= dispatch_data_create_concat(rv
, val
);
599 dispatch_release(val
);
600 dispatch_release(rv
);
607 dispatch_release(rv
);
614 static dispatch_data_t
615 _dispatch_transform_to_base32(dispatch_data_t data
)
617 size_t total
= dispatch_data_get_size(data
);
618 __block
size_t count
= 0;
620 size_t dest_size
= ((total
+ 4) * 8) / 5;
621 dest_size
-= dest_size
% 8;
623 uint8_t *dest
= (uint8_t*)malloc(dest_size
* sizeof(uint8_t));
628 __block
uint8_t *ptr
= dest
;
632 8-bit bytes: xxxxxxxx yyyyyyyy zzzzzzzz xxxxxxxx yyyyyyyy
633 5-bit chunks: aaaaabbb bbcccccd ddddeeee efffffgg ggghhhhh
636 bool success
= dispatch_data_apply(data
, ^(
637 DISPATCH_UNUSED dispatch_data_t region
,
638 size_t offset
, const void *buffer
, size_t size
) {
639 const uint8_t *bytes
= buffer
;
642 for (i
= 0; i
< size
; i
++, count
++) {
643 uint8_t curr
= bytes
[i
], last
= 0;
645 if ((count
% 5) != 0) {
648 dispatch_data_t subrange
= _dispatch_data_subrange_map(data
,
650 if (subrange
== NULL
) {
654 dispatch_release(subrange
);
663 *ptr
++ = base32_encode_table
[(curr
>> 3) & 0x1f];
667 *ptr
++ = base32_encode_table
[((last
<< 2)|(curr
>> 6)) & 0x1f];
668 *ptr
++ = base32_encode_table
[(curr
>> 1) & 0x1f];
672 *ptr
++ = base32_encode_table
[((last
<< 4)|(curr
>> 4)) & 0x1f];
676 *ptr
++ = base32_encode_table
[((last
<< 1)|(curr
>> 7)) & 0x1f];
677 *ptr
++ = base32_encode_table
[(curr
>> 2) & 0x1f];
681 *ptr
++ = base32_encode_table
[((last
<< 3)|(curr
>> 5)) & 0x1f];
682 *ptr
++ = base32_encode_table
[curr
& 0x1f];
687 // Last region, insert padding bytes, if needed
688 if (offset
+ size
== total
) {
694 *ptr
++ = base32_encode_table
[(bytes
[size
-1] << 2) & 0x1c];
698 *ptr
++ = base32_encode_table
[(bytes
[size
-1] << 4) & 0x10];
702 *ptr
++ = base32_encode_table
[(bytes
[size
-1] << 1) & 0x1e];
706 *ptr
++ = base32_encode_table
[bytes
[size
-1] & 0x18];
733 return dispatch_data_create(dest
, dest_size
, NULL
,
734 DISPATCH_DATA_DESTRUCTOR_FREE
);
740 static dispatch_data_t
741 _dispatch_transform_from_base64(dispatch_data_t data
)
743 __block
uint64_t x
= 0, count
= 0;
744 __block
size_t pad
= 0;
746 __block dispatch_data_t rv
= dispatch_data_empty
;
748 bool success
= dispatch_data_apply(data
, ^(
749 DISPATCH_UNUSED dispatch_data_t region
,
750 DISPATCH_UNUSED
size_t offset
, const void *buffer
, size_t size
) {
751 size_t i
, dest_size
= (size
* 3) / 4;
753 uint8_t *dest
= (uint8_t*)malloc(dest_size
* sizeof(uint8_t));
759 const uint8_t *bytes
= buffer
;
761 for (i
= 0; i
< size
; i
++) {
762 if (bytes
[i
] == '\n' || bytes
[i
] == '\t' || bytes
[i
] == ' ') {
766 ssize_t index
= bytes
[i
];
767 if (index
>= base64_decode_table_size
||
768 base64_decode_table
[index
] == -1) {
774 char value
= base64_decode_table
[index
];
783 if ((count
& 0x3) == 0) {
784 *ptr
++ = (x
>> 16) & 0xff;
785 *ptr
++ = (x
>> 8) & 0xff;
790 size_t final
= (ptr
- dest
);
792 // 2 bytes of pad means only had one char in final group
796 dispatch_data_t val
= dispatch_data_create(dest
, final
, NULL
,
797 DISPATCH_DATA_DESTRUCTOR_FREE
);
798 dispatch_data_t concat
= dispatch_data_create_concat(rv
, val
);
800 dispatch_release(val
);
801 dispatch_release(rv
);
808 dispatch_release(rv
);
815 static dispatch_data_t
816 _dispatch_transform_to_base64(dispatch_data_t data
)
818 // RFC 4648 states that we should not linebreak
819 // http://tools.ietf.org/html/rfc4648
820 size_t total
= dispatch_data_get_size(data
);
821 __block
size_t count
= 0;
823 size_t dest_size
= ((total
+ 2) * 4) / 3;
824 dest_size
-= dest_size
% 4;
826 uint8_t *dest
= (uint8_t*)malloc(dest_size
* sizeof(uint8_t));
831 __block
uint8_t *ptr
= dest
;
834 * 3 8-bit bytes: xxxxxxxx yyyyyyyy zzzzzzzz
835 * 4 6-bit chunks: aaaaaabb bbbbcccc ccdddddd
838 bool success
= dispatch_data_apply(data
, ^(
839 DISPATCH_UNUSED dispatch_data_t region
,
840 size_t offset
, const void *buffer
, size_t size
) {
841 const uint8_t *bytes
= buffer
;
844 for (i
= 0; i
< size
; i
++, count
++) {
845 uint8_t curr
= bytes
[i
], last
= 0;
847 if ((count
% 3) != 0) {
850 dispatch_data_t subrange
= _dispatch_data_subrange_map(data
,
852 if (subrange
== NULL
) {
856 dispatch_release(subrange
);
864 *ptr
++ = base64_encode_table
[(curr
>> 2) & 0x3f];
867 *ptr
++ = base64_encode_table
[((last
<< 4)|(curr
>> 4)) & 0x3f];
870 *ptr
++ = base64_encode_table
[((last
<< 2)|(curr
>> 6)) & 0x3f];
871 *ptr
++ = base64_encode_table
[(curr
& 0x3f)];
876 // Last region, insert padding bytes, if needed
877 if (offset
+ size
== total
) {
882 *ptr
++ = base64_encode_table
[(bytes
[size
-1] << 4) & 0x30];
887 *ptr
++ = base64_encode_table
[(bytes
[size
-1] << 2) & 0x3c];
900 return dispatch_data_create(dest
, dest_size
, NULL
,
901 DISPATCH_DATA_DESTRUCTOR_FREE
);
905 #pragma mark dispatch_data_transform
908 dispatch_data_create_with_transform(dispatch_data_t data
,
909 dispatch_data_format_type_t input
, dispatch_data_format_type_t output
)
911 if (input
->type
== _DISPATCH_DATA_FORMAT_UTF_ANY
) {
912 input
= _dispatch_transform_detect_utf(data
);
915 if ((input
->type
& ~output
->input_mask
) != 0) {
919 if ((output
->type
& ~input
->output_mask
) != 0) {
923 if (dispatch_data_get_size(data
) == 0) {
927 dispatch_data_t temp1
;
929 temp1
= input
->decode(data
);
931 dispatch_retain(data
);
939 dispatch_data_t temp2
;
940 if (output
->encode
) {
941 temp2
= output
->encode(temp1
);
943 dispatch_retain(temp1
);
947 dispatch_release(temp1
);
951 const struct dispatch_data_format_type_s _dispatch_data_format_type_none
= {
952 .type
= _DISPATCH_DATA_FORMAT_NONE
,
959 const struct dispatch_data_format_type_s _dispatch_data_format_type_base32
= {
960 .type
= _DISPATCH_DATA_FORMAT_BASE32
,
961 .input_mask
= (_DISPATCH_DATA_FORMAT_NONE
| _DISPATCH_DATA_FORMAT_BASE32
|
962 _DISPATCH_DATA_FORMAT_BASE64
),
963 .output_mask
= (_DISPATCH_DATA_FORMAT_NONE
| _DISPATCH_DATA_FORMAT_BASE32
|
964 _DISPATCH_DATA_FORMAT_BASE64
),
965 .decode
= _dispatch_transform_from_base32
,
966 .encode
= _dispatch_transform_to_base32
,
969 const struct dispatch_data_format_type_s _dispatch_data_format_type_base64
= {
970 .type
= _DISPATCH_DATA_FORMAT_BASE64
,
971 .input_mask
= (_DISPATCH_DATA_FORMAT_NONE
| _DISPATCH_DATA_FORMAT_BASE32
|
972 _DISPATCH_DATA_FORMAT_BASE64
),
973 .output_mask
= (_DISPATCH_DATA_FORMAT_NONE
| _DISPATCH_DATA_FORMAT_BASE32
|
974 _DISPATCH_DATA_FORMAT_BASE64
),
975 .decode
= _dispatch_transform_from_base64
,
976 .encode
= _dispatch_transform_to_base64
,
979 const struct dispatch_data_format_type_s _dispatch_data_format_type_utf16le
= {
980 .type
= _DISPATCH_DATA_FORMAT_UTF16LE
,
981 .input_mask
= (_DISPATCH_DATA_FORMAT_UTF8
| _DISPATCH_DATA_FORMAT_UTF16BE
|
982 _DISPATCH_DATA_FORMAT_UTF16LE
),
983 .output_mask
= (_DISPATCH_DATA_FORMAT_UTF8
| _DISPATCH_DATA_FORMAT_UTF16BE
|
984 _DISPATCH_DATA_FORMAT_UTF16LE
),
985 .decode
= _dispatch_transform_from_utf16le
,
986 .encode
= _dispatch_transform_to_utf16le
,
989 const struct dispatch_data_format_type_s _dispatch_data_format_type_utf16be
= {
990 .type
= _DISPATCH_DATA_FORMAT_UTF16BE
,
991 .input_mask
= (_DISPATCH_DATA_FORMAT_UTF8
| _DISPATCH_DATA_FORMAT_UTF16BE
|
992 _DISPATCH_DATA_FORMAT_UTF16LE
),
993 .output_mask
= (_DISPATCH_DATA_FORMAT_UTF8
| _DISPATCH_DATA_FORMAT_UTF16BE
|
994 _DISPATCH_DATA_FORMAT_UTF16LE
),
995 .decode
= _dispatch_transform_from_utf16be
,
996 .encode
= _dispatch_transform_to_utf16be
,
999 const struct dispatch_data_format_type_s _dispatch_data_format_type_utf8
= {
1000 .type
= _DISPATCH_DATA_FORMAT_UTF8
,
1001 .input_mask
= (_DISPATCH_DATA_FORMAT_UTF8
| _DISPATCH_DATA_FORMAT_UTF16BE
|
1002 _DISPATCH_DATA_FORMAT_UTF16LE
),
1003 .output_mask
= (_DISPATCH_DATA_FORMAT_UTF8
| _DISPATCH_DATA_FORMAT_UTF16BE
|
1004 _DISPATCH_DATA_FORMAT_UTF16LE
),
1009 const struct dispatch_data_format_type_s _dispatch_data_format_type_utf_any
= {
1010 .type
= _DISPATCH_DATA_FORMAT_UTF_ANY
,