File: ucs2.h

package info (click to toggle)
fwupdate 12-7
  • links: PTS, VCS
  • area: main
  • in suites: bookworm, bullseye
  • size: 588 kB
  • sloc: ansic: 4,329; makefile: 358; sh: 49
file content (133 lines) | stat: -rw-r--r-- 3,822 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#ifndef _EFIVAR_UCS2_H
#define _EFIVAR_UCS2_H

#define ev_bits(val, mask, shift) \
	(((val) & ((mask) << (shift))) >> (shift))

/*
 * Translate from ucs2 to utf8.
 * This is used to read old firmware paths from our stored state variables.
 */
static inline char *
__attribute__((__unused__))
ucs2_to_utf8(const uint16_t *chars, size_t max)
{
	size_t i, j;
	char *ret = alloca(max * 3 + 1); /* would be s/3/6 if this were UCS-4 */
	if (!ret)
		return NULL;
	memset(ret, 0, max * 3 +1); /* would be s/3/6 if this were UCS-4 */

	for (i=0, j=0; i < max && chars[i]; i++,j++) {
		if (chars[i] <= 0x7f) {
			ret[j] = chars[i];
		} else if (chars[i] > 0x7f && chars[i] <= 0x7ff) {
			ret[j++] = 0xc0 | ev_bits(chars[i], 0x1f, 6);
			ret[j]   = 0x80 | ev_bits(chars[i], 0x3f, 0);
		} else if (chars[i] > 0x7ff /* && chars[i] < 0x10000 */ ) {
			ret[j++] = 0xe0 | ev_bits(chars[i], 0xf, 12);
			ret[j++] = 0x80 | ev_bits(chars[i], 0x3f, 6);
			ret[j]   = 0x80| ev_bits(chars[i], 0x3f, 0);
#if 0 /*
       * and since this is UCS-2, which has no surrogates, we don't actually
       * need to check for the rest of the unicode codepoints.  They don't
       * exist in this representation.
       */
		} else if (chars[i] > 0xffff && chars[i] < 0x200000) {
			ret[j++] = 0xf0 | ev_bits(chars[i], 0x7, 18);
			ret[j++] = 0x80 | ev_bits(chars[i], 0x3f, 12);
			ret[j++] = 0x80 | ev_bits(chars[i], 0x3f, 6);
			ret[j]   = 0x80| ev_bits(chars[i], 0x3f, 0);
		} else if (chars[i] > 0x1fffff && chars[i] < 0x4000000) {
			ret[j++] = 0xf8 | ev_bits(chars[i], 0x3, 24);
			ret[j++] = 0x80 | ev_bits(chars[i], 0x3f, 18);
			ret[j++] = 0x80 | ev_bits(chars[i], 0x3f, 12);
			ret[j++] = 0x80 | ev_bits(chars[i], 0x3f, 6);
			ret[j]   = 0x80 | ev_bits(chars[i], 0x3f, 0);
		} else if (chars[i] > 0x3ffffff) {
			ret[j++] = 0xfc | ev_bits(chars[i], 0x1, 30);
			ret[j++] = 0x80 | ev_bits(chars[i], 0x3f, 24);
			ret[j++] = 0x80 | ev_bits(chars[i], 0x3f, 18);
			ret[j++] = 0x80 | ev_bits(chars[i], 0x3f, 12);
			ret[j++] = 0x80 | ev_bits(chars[i], 0x3f, 6);
			ret[j]   = 0x80 | ev_bits(chars[i], 0x3f, 0);
#endif
		}
	}
	ret[j] = '\0';
	return strdup(ret);
}


/*
 * Find the length of a utf8 string, not counting nulls.
 * This is only ever used on string literal utf8 text from libfwup source.
 */
static inline size_t
__attribute__((__unused__))
utf8len(uint8_t *s, ssize_t limit)
{
	ssize_t i, j;
	for (i = 0, j = 0; i < (limit >= 0 ? limit : i+1) && s[i] != '\0';
	     j++, i++) {
		if (!(s[i] & 0x80)) {
			;
		} else if ((s[i] & 0xc0) == 0xc0 && !(s[i] & 0x20)) {
			i += 1;
		} else if ((s[i] & 0xe0) == 0xe0 && !(s[i] & 0x10)) {
			i += 2;
		}
	}
	return j;
}

/*
 * Convert a utf8 string to a ucs2 string.
 * This is only ever used on string literal utf8 text from libfwup source.
 */
static inline uint16_t *
__attribute__((__unused__))
utf8_to_ucs2(uint8_t *utf8, ssize_t max)
{
	ssize_t i, j;
	uint16_t *ret = calloc(utf8len(utf8, max) + 1, sizeof (uint16_t));
	if (!ret)
		return NULL;

	for (i=0, j=0; i < (max >= 0 ? max : i+1) && utf8[i] != '\0'; j++) {
		uint32_t val = 0;

		if ((utf8[i] & 0xe0) == 0xe0 && !(utf8[i] & 0x10)) {
			val = ((utf8[i+0] & 0x0f) << 10)
			     |((utf8[i+1] & 0x3f) << 6)
			     |((utf8[i+2] & 0x3f) << 0);
			i += 3;
		} else if ((utf8[i] & 0xc0) == 0xc0 && !(utf8[i] & 0x20)) {
			val = ((utf8[i+0] & 0x1f) << 6)
			     |((utf8[i+1] & 0x3f) << 0);
			i += 2;
		} else {
			val = utf8[i] & 0x7f;
			i += 1;
		}
		ret[j] = val;
	}
	ret[j] = L'\0';
	return ret;
};

/*
 * Find the length of a ucs2 string
 * This is basically only ever called on the output from utf8_to_ucs2()
 */
static inline size_t
__attribute__((__unused__))
ucs2len(uint16_t *s, ssize_t limit)
{
	ssize_t i;
	for (i = 0; i < (limit >= 0 ? limit : i + 1) && s[i] != L'\0'; i++)
		;
	return i;
}

#endif /* _EFIVAR_UCS2_H */