⛏️ index : haiku.git

/*
 * Copyright 2007-2013, Axel DΓΆrfler, axeld@pinc-software.de.
 * Copyright 2009, Michael Lotz, mmlr@mlotz.ch. All rights reserved.
 *
 * Distributed under the terms of the MIT License.
 */


#include "utility.h"

#include <string.h>

#ifndef _BOOT_MODE
#	include <utf8_functions.h>
#endif

#include "gpt_known_guids.h"


const guid_t kEmptyGUID = {0, 0, 0, {0, 0, 0, 0, 0, 0, 0, 0}};


static void
put_utf8_byte(char*& to, size_t& left, char c)
{
	if (left <= 1)
		return;

	*(to++) = c;
	left--;
}


// #pragma mark -


size_t
to_utf8(const uint16* from, size_t maxFromLength, char* to, size_t toSize)
{
	const char* start = to;
	for (uint32 i = 0; i < maxFromLength; i++) {
		// Decoding UTF-16LE
		uint32 c = 0;
		uint16 w1 = B_LENDIAN_TO_HOST_INT16(from[i]);
		if (!w1)
			break;

		bool valid = false;
		if (w1 < 0xD800 || w1 > 0xDFFF) {
			c = w1;
			valid = true;
		}

		if (!valid && (w1 >= 0xD800 && w1 <= 0xDBFF)) {
			if (i + 1 < maxFromLength) {
				uint16 w2 = B_LENDIAN_TO_HOST_INT16(from[i + 1]);
				if (w2 >= 0xDC00 && w2 <= 0xDFFF) {
					c = ((w1 & 0x3FF) << 10) | (w2 & 0x3FF);
					c += 0x10000;
					++i;
					valid = true;
				}
			}
		}

		if (!valid) break;

		if (c < 0x80)
			put_utf8_byte(to, toSize, c);
		else if (c < 0x800) {
			put_utf8_byte(to, toSize, 0xc0 | (c >> 6));
			put_utf8_byte(to, toSize, 0x80 | (c & 0x3f));
		} else if (c < 0x10000) {
			put_utf8_byte(to, toSize, 0xe0 | (c >> 12));
			put_utf8_byte(to, toSize, 0x80 | ((c >> 6) & 0x3f));
			put_utf8_byte(to, toSize, 0x80 | (c & 0x3f));
		} else if (c <= 0x10ffff) {
			put_utf8_byte(to, toSize, 0xf0 | (c >> 18));
			put_utf8_byte(to, toSize, 0x80 | ((c >> 12) & 0x3f));
			put_utf8_byte(to, toSize, 0x80 | ((c >> 6) & 0x3f));
			put_utf8_byte(to, toSize, 0x80 | (c & 0x3f));
		}
	}

	if (toSize > 0)
		*to++ = '\0';

	return to - start;
}


#ifndef _BOOT_MODE
size_t
to_ucs2(const char* from, size_t fromLength, uint16* to, size_t maxToLength)
{
	size_t index = 0;
	while (from[0] != '\0' && index < maxToLength) {
		uint32 c = UTF8ToCharCode(&from);

		// Encoding UTF-16LE
		if (c > 0x10FFFF) break; // invalid
		if (c < 0x10000) {
			to[index++] = B_HOST_TO_LENDIAN_INT16(c);
		} else {
			if (index + 1 >= maxToLength) break;
			uint32 c2 = c - 0x10000;
			uint16 w1 = 0xD800, w2 = 0xDC00;
			w1 = w1 + ((c2 >> 10) & 0x3FF);
			w2 = w2 + (c2 & 0x3FF);
			to[index++] = B_HOST_TO_LENDIAN_INT16(w1);
			to[index++] = B_HOST_TO_LENDIAN_INT16(w2);
		}
	}

	if (index < maxToLength)
		to[index++] = '\0';

	return index;
}
#endif // !_BOOT_MODE


const char*
get_partition_type(const guid_t& guid)
{
	for (uint32 i = 0; i < sizeof(kTypeMap) / sizeof(kTypeMap[0]); i++) {
		if (kTypeMap[i].guid == guid)
			return kTypeMap[i].type;
	}

	return NULL;
}


#ifndef _BOOT_MODE
bool
get_guid_for_partition_type(const char* type, guid_t& guid)
{
	for (uint32 i = 0; i < sizeof(kTypeMap) / sizeof(kTypeMap[0]); i++) {
		if (strcmp(kTypeMap[i].type, type) == 0) {
			guid = kTypeMap[i].guid;
			return true;
		}
	}

	return false;
}
#endif // !_BOOT_MODE