/src/util-linux/lib/encode.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Based on code from libblkid, |
3 | | * |
4 | | * Copyright (C) 2008 Kay Sievers <kay.sievers@vrfy.org> |
5 | | * Copyright (C) 2009 Karel Zak <kzak@redhat.com> |
6 | | * Copyright (C) 2020 Pali Rohár <pali.rohar@gmail.com> |
7 | | * |
8 | | * This file may be redistributed under the terms of the |
9 | | * GNU Lesser General Public License. |
10 | | */ |
11 | | #include "c.h" |
12 | | #include "encode.h" |
13 | | |
14 | | size_t ul_encode_to_utf8(int enc, unsigned char *dest, size_t len, |
15 | | const unsigned char *src, size_t count) |
16 | 1.52k | { |
17 | 1.52k | size_t i, j; |
18 | 1.52k | uint32_t c; |
19 | 1.52k | uint16_t c2; |
20 | | |
21 | 36.1k | for (j = i = 0; i < count; i++) { |
22 | 35.3k | if (enc == UL_ENCODE_UTF16LE) { |
23 | 13.1k | if (i+2 > count) |
24 | 9 | break; |
25 | 13.0k | c = (src[i+1] << 8) | src[i]; |
26 | 13.0k | i++; |
27 | 22.2k | } else if (enc == UL_ENCODE_UTF16BE) { |
28 | 20.1k | if (i+2 > count) |
29 | 28 | break; |
30 | 20.0k | c = (src[i] << 8) | src[i+1]; |
31 | 20.0k | i++; |
32 | 20.0k | } else if (enc == UL_ENCODE_LATIN1) { |
33 | 2.09k | c = src[i]; |
34 | 2.09k | } else { |
35 | 0 | return 0; |
36 | 0 | } |
37 | 35.2k | if ((enc == UL_ENCODE_UTF16LE || enc == UL_ENCODE_UTF16BE) && |
38 | 35.2k | c >= 0xD800 && c <= 0xDBFF && i+2 < count) { |
39 | 3.74k | if (enc == UL_ENCODE_UTF16LE) |
40 | 2.30k | c2 = (src[i+2] << 8) | src[i+1]; |
41 | 1.44k | else |
42 | 1.44k | c2 = (src[i+1] << 8) | src[i+2]; |
43 | 3.74k | if (c2 >= 0xDC00 && c2 <= 0xDFFF) { |
44 | 549 | c = 0x10000 + ((c - 0xD800) << 10) + (c2 - 0xDC00); |
45 | 549 | i += 2; |
46 | 549 | } |
47 | 3.74k | } |
48 | 35.2k | if (c == 0) { |
49 | 587 | dest[j] = '\0'; |
50 | 587 | break; |
51 | 587 | } |
52 | | |
53 | 34.6k | if (c < 0x80) { |
54 | 13.0k | if (j+1 >= len) |
55 | 31 | break; |
56 | 13.0k | dest[j++] = (uint8_t) c; |
57 | 21.6k | } else if (c < 0x800) { |
58 | 2.21k | if (j+2 >= len) |
59 | 8 | break; |
60 | 2.20k | dest[j++] = (uint8_t) (0xc0 | (c >> 6)); |
61 | 2.20k | dest[j++] = (uint8_t) (0x80 | (c & 0x3f)); |
62 | 19.3k | } else if (c < 0x10000) { |
63 | 18.8k | if (j+3 >= len) |
64 | 80 | break; |
65 | 18.7k | dest[j++] = (uint8_t) (0xe0 | (c >> 12)); |
66 | 18.7k | dest[j++] = (uint8_t) (0x80 | ((c >> 6) & 0x3f)); |
67 | 18.7k | dest[j++] = (uint8_t) (0x80 | (c & 0x3f)); |
68 | 18.7k | } else { |
69 | 549 | if (j+4 >= len) |
70 | 0 | break; |
71 | 549 | dest[j++] = (uint8_t) (0xf0 | (c >> 18)); |
72 | 549 | dest[j++] = (uint8_t) (0x80 | ((c >> 12) & 0x3f)); |
73 | 549 | dest[j++] = (uint8_t) (0x80 | ((c >> 6) & 0x3f)); |
74 | 549 | dest[j++] = (uint8_t) (0x80 | (c & 0x3f)); |
75 | 549 | } |
76 | 34.6k | } |
77 | 1.52k | dest[j] = '\0'; |
78 | 1.52k | return j; |
79 | 1.52k | } |