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
,