/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 | 2.23k | { |
17 | 2.23k | size_t i, j; |
18 | 2.23k | uint32_t c; |
19 | 2.23k | uint16_t c2; |
20 | | |
21 | 57.5k | for (j = i = 0; i < count; i++) { |
22 | 55.9k | if (enc == UL_ENCODE_UTF16LE) { |
23 | 13.3k | if (i+2 > count) |
24 | 15 | break; |
25 | 13.3k | c = (src[i+1] << 8) | src[i]; |
26 | 13.3k | i++; |
27 | 42.5k | } else if (enc == UL_ENCODE_UTF16BE) { |
28 | 25.5k | if (i+2 > count) |
29 | 18 | break; |
30 | 25.5k | c = (src[i] << 8) | src[i+1]; |
31 | 25.5k | i++; |
32 | 25.5k | } else if (enc == UL_ENCODE_LATIN1) { |
33 | 17.0k | c = src[i]; |
34 | 17.0k | } else { |
35 | 0 | return 0; |
36 | 0 | } |
37 | 55.9k | if ((enc == UL_ENCODE_UTF16LE || enc == UL_ENCODE_UTF16BE) && |
38 | 55.9k | c >= 0xD800 && c <= 0xDBFF && i+2 < count) { |
39 | 4.10k | if (enc == UL_ENCODE_UTF16LE) |
40 | 2.54k | c2 = (src[i+2] << 8) | src[i+1]; |
41 | 1.55k | else |
42 | 1.55k | c2 = (src[i+1] << 8) | src[i+2]; |
43 | 4.10k | if (c2 >= 0xDC00 && c2 <= 0xDFFF) { |
44 | 934 | c = 0x10000 + ((c - 0xD800) << 10) + (c2 - 0xDC00); |
45 | 934 | i += 2; |
46 | 934 | } |
47 | 4.10k | } |
48 | 55.9k | if (c == 0) { |
49 | 435 | dest[j] = '\0'; |
50 | 435 | break; |
51 | 435 | } |
52 | | |
53 | 55.5k | if (c < 0x80) { |
54 | 33.9k | if (j+1 >= len) |
55 | 202 | break; |
56 | 33.7k | dest[j++] = (uint8_t) c; |
57 | 33.7k | } else if (c < 0x800) { |
58 | 1.47k | if (j+2 >= len) |
59 | 4 | break; |
60 | 1.46k | dest[j++] = (uint8_t) (0xc0 | (c >> 6)); |
61 | 1.46k | dest[j++] = (uint8_t) (0x80 | (c & 0x3f)); |
62 | 20.0k | } else if (c < 0x10000) { |
63 | 19.1k | if (j+3 >= len) |
64 | 43 | break; |
65 | 19.1k | dest[j++] = (uint8_t) (0xe0 | (c >> 12)); |
66 | 19.1k | dest[j++] = (uint8_t) (0x80 | ((c >> 6) & 0x3f)); |
67 | 19.1k | dest[j++] = (uint8_t) (0x80 | (c & 0x3f)); |
68 | 19.1k | } else { |
69 | 934 | if (j+4 >= len) |
70 | 0 | break; |
71 | 934 | dest[j++] = (uint8_t) (0xf0 | (c >> 18)); |
72 | 934 | dest[j++] = (uint8_t) (0x80 | ((c >> 12) & 0x3f)); |
73 | 934 | dest[j++] = (uint8_t) (0x80 | ((c >> 6) & 0x3f)); |
74 | 934 | dest[j++] = (uint8_t) (0x80 | (c & 0x3f)); |
75 | 934 | } |
76 | 55.5k | } |
77 | 2.23k | dest[j] = '\0'; |
78 | 2.23k | return j; |
79 | 2.23k | } |