xref: /haiku/src/add-ons/kernel/partitioning_systems/gpt/utility.cpp (revision 222c84407a0c10b93a84a5482da6c8fac9163574)
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 
20 const guid_t kEmptyGUID = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};
21 
22 
23 static void
put_utf8_byte(char * & to,size_t & left,char c)24 put_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 
37 size_t
to_utf8(const uint16 * from,size_t maxFromLength,char * to,size_t toSize)38 to_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
93 size_t
to_ucs2(const char * from,size_t fromLength,uint16 * to,size_t maxToLength)94 to_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 
123 const char*
get_partition_type(const guid_t & guid)124 get_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
136 bool
get_guid_for_partition_type(const char * type,guid_t & guid)137 get_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