1/*
2 * Copyright 2007-2013, Axel D��rfler, axeld@pinc-software.de.
3 * Copyright 2009, Michael Lotz, mmlr@mlotz.ch. All rights reserved.
4 *
5 * Distributed under the terms of the MIT License.
6 */
7
8
9#include "utility.h"
10
11#include <string.h>
12
13#ifndef _BOOT_MODE
14#	include <utf8_functions.h>
15#endif
16
17#include "gpt_known_guids.h"
18
19
20const guid_t kEmptyGUID = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
21
22
23static void
24put_utf8_byte(char*& to, size_t& left, char c)
25{
26	if (left <= 1)
27		return;
28
29	*(to++) = c;
30	left--;
31}
32
33
34// #pragma mark -
35
36
37size_t
38to_utf8(const uint16* from, size_t maxFromLength, char* to, size_t toSize)
39{
40	const char* start = to;
41	for (uint32 i = 0; i < maxFromLength; i++) {
42		// Decoding UTF-16LE
43		uint32 c = 0;
44		uint16 w1 = B_LENDIAN_TO_HOST_INT16(from[i]);
45		if (!w1)
46			break;
47
48		bool valid = false;
49		if (w1 < 0xD800 || w1 > 0xDFFF) {
50			c = w1;
51			valid = true;
52		}
53
54		if (!valid && (w1 >= 0xD800 && w1 <= 0xDBFF)) {
55			if (i + 1 < maxFromLength) {
56				uint16 w2 = B_LENDIAN_TO_HOST_INT16(from[i + 1]);
57				if (w2 >= 0xDC00 && w2 <= 0xDFFF) {
58					c = ((w1 & 0x3FF) << 10) | (w2 & 0x3FF);
59					c += 0x10000;
60					++i;
61					valid = true;
62				}
63			}
64		}
65
66		if (!valid) break;
67
68		if (c < 0x80)
69			put_utf8_byte(to, toSize, c);
70		else if (c < 0x800) {
71			put_utf8_byte(to, toSize, 0xc0 | (c >> 6));
72			put_utf8_byte(to, toSize, 0x80 | (c & 0x3f));
73		} else if (c < 0x10000) {
74			put_utf8_byte(to, toSize, 0xe0 | (c >> 12));
75			put_utf8_byte(to, toSize, 0x80 | ((c >> 6) & 0x3f));
76			put_utf8_byte(to, toSize, 0x80 | (c & 0x3f));
77		} else if (c <= 0x10ffff) {
78			put_utf8_byte(to, toSize, 0xf0 | (c >> 18));
79			put_utf8_byte(to, toSize, 0x80 | ((c >> 12) & 0x3f));
80			put_utf8_byte(to, toSize, 0x80 | ((c >> 6) & 0x3f));
81			put_utf8_byte(to, toSize, 0x80 | (c & 0x3f));
82		}
83	}
84
85	if (toSize > 0)
86		*to++ = '\0';
87
88	return to - start;
89}
90
91
92#ifndef _BOOT_MODE
93size_t
94to_ucs2(const char* from, size_t fromLength, uint16* to, size_t maxToLength)
95{
96	size_t index = 0;
97	while (from[0] != '\0' && index < maxToLength) {
98		uint32 c = UTF8ToCharCode(&from);
99
100		// Encoding UTF-16LE
101		if (c > 0x10FFFF) break; // invalid
102		if (c < 0x10000) {
103			to[index++] = B_HOST_TO_LENDIAN_INT16(c);
104		} else {
105			if (index + 1 >= maxToLength) break;
106			uint32 c2 = c - 0x10000;
107			uint16 w1 = 0xD800, w2 = 0xDC00;
108			w1 = w1 + ((c2 >> 10) & 0x3FF);
109			w2 = w2 + (c2 & 0x3FF);
110			to[index++] = B_HOST_TO_LENDIAN_INT16(w1);
111			to[index++] = B_HOST_TO_LENDIAN_INT16(w2);
112		}
113	}
114
115	if (index < maxToLength)
116		to[index++] = '\0';
117
118	return index;
119}
120#endif // !_BOOT_MODE
121
122
123const char*
124get_partition_type(const guid_t& guid)
125{
126	for (uint32 i = 0; i < sizeof(kTypeMap) / sizeof(kTypeMap[0]); i++) {
127		if (kTypeMap[i].guid == guid)
128			return kTypeMap[i].type;
129	}
130
131	return NULL;
132}
133
134
135#ifndef _BOOT_MODE
136bool
137get_guid_for_partition_type(const char* type, guid_t& guid)
138{
139	for (uint32 i = 0; i < sizeof(kTypeMap) / sizeof(kTypeMap[0]); i++) {
140		if (strcmp(kTypeMap[i].type, type) == 0) {
141			guid = kTypeMap[i].guid;
142			return true;
143		}
144	}
145
146	return false;
147}
148#endif // !_BOOT_MODE
149