Newer
Older
Scratch / mobius / src / kernel / wcstombs.c
#include <wchar.h>

/* 7-bit ASCII maps to bottom 128 characters of UCS */
struct asciimap_t
{
	wchar_t ucs;
	char ascii;
} ascii437_to_ucs[128] =
{
	{ 0x0092,	0x9f },
	{ 0x00A0,	0xff },
	{ 0x00A1,	0xad },
	{ 0x00A2,	0xbd },
	{ 0x00A3,	0x9c },
	{ 0x00A4,	0xcf },
	{ 0x00A5,	0xbe },
	{ 0x00A6,	0xdd },
	{ 0x00A7,	0xf5 },
	{ 0x00A8,	0xf9 },
	{ 0x00A9,	0xb8 },
	{ 0x00AA,	0xa6 },
	{ 0x00AB,	0xae },
	{ 0x00AC,	0xaa },
	{ 0x00AD,	0xf0 },
	{ 0x00AE,	0xa9 },
	{ 0x00AF,	0xee },
	{ 0x00B0,	0xf8 },
	{ 0x00B1,	0xf1 },
	{ 0x00B2,	0xfd },
	{ 0x00B3,	0xfc },
	{ 0x00B4,	0xef },
	{ 0x00B5,	0xe6 },
	{ 0x00B6,	0xf4 },
	{ 0x00B7,	0xfa },
	{ 0x00B8,	0xf7 },
	{ 0x00B9,	0xfb },
	{ 0x00BA,	0xa7 },
	{ 0x00BB,	0xaf },
	{ 0x00BC,	0xac },
	{ 0x00BD,	0xab },
	{ 0x00BE,	0xf3 },
	{ 0x00BF,	0xa8 },
	{ 0x00C0,	0xb7 },
	{ 0x00C1,	0xb5 },
	{ 0x00C2,	0xb6 },
	{ 0x00C3,	0xc7 },
	{ 0x00C4,	0x8e },
	{ 0x00C5,	0x8f },
	{ 0x00C6,	0x92 },
	{ 0x00C7,	0x80 },
	{ 0x00C8,	0xd4 },
	{ 0x00C9,	0x90 },
	{ 0x00CA,	0xd2 },
	{ 0x00CB,	0xd3 },
	{ 0x00CC,	0xde },
	{ 0x00CD,	0xd6 },
	{ 0x00CE,	0xd7 },
	{ 0x00CF,	0xd8 },
	{ 0x00D0,	0xd1 },
	{ 0x00D1,	0xa5 },
	{ 0x00D2,	0xe3 },
	{ 0x00D3,	0xe0 },
	{ 0x00D4,	0xe2 },
	{ 0x00D5,	0xe5 },
	{ 0x00D6,	0x99 },
	{ 0x00D7,	0x9e },
	{ 0x00D8,	0x9d },
	{ 0x00D9,	0xeb },
	{ 0x00DA,	0xe9 },
	{ 0x00DB,	0xea },
	{ 0x00DC,	0x9a },
	{ 0x00DD,	0xed },
	{ 0x00DE,	0xe8 },
	{ 0x00DF,	0xe1 },
	{ 0x00E0,	0x85 },
	{ 0x00E0,	0xa1 },
	{ 0x00E1,	0xa0 },
	{ 0x00E2,	0x83 },
	{ 0x00E3,	0xc6 },
	{ 0x00E4,	0x84 },
	{ 0x00E5,	0x86 },
	{ 0x00E6,	0x91 },
	{ 0x00E7,	0x87 },
	{ 0x00E8,	0x8a },
	{ 0x00E9,	0x82 },
	{ 0x00EA,	0x88 },
	{ 0x00EB,	0x89 },
	{ 0x00EC,	0x8d },
	{ 0x00EE,	0x8c },
	{ 0x00EF,	0x8b },
	{ 0x00F0,	0xd0 },
	{ 0x00F1,	0xa4 },
	{ 0x00F2,	0x95 },
	{ 0x00F3,	0xa2 },
	{ 0x00F4,	0x93 },
	{ 0x00F5,	0xe4 },
	{ 0x00F6,	0x94 },
	{ 0x00F7,	0xf6 },
	{ 0x00F8,	0x9b },
	{ 0x00F9,	0x97 },
	{ 0x00FA,	0xa3 },
	{ 0x00FB,	0x96 },
	{ 0x00FC,	0x81 },
	{ 0x00FD,	0xec },
	{ 0x00FE,	0xe7 },
	{ 0x00FF,	0x98 },
	{ 0x0131,	0xd5 },
	{ 0x2017,	0xf2 },
	{ 0x20A0,	0xfe },
	{ 0x2500,	0xc4 },
	{ 0x2502,	0xb3 },
	{ 0x250C,	0xda },
	{ 0x2510,	0xbf },
	{ 0x2514,	0xc0 },
	{ 0x2518,	0xd9 },
	{ 0x251C,	0xc3 },
	{ 0x2524,	0xb4 },
	{ 0x252C,	0xc2 },
	{ 0x2534,	0xc1 },
	{ 0x253C,	0xc5 },
	{ 0x2550,	0xcd },
	{ 0x2551,	0xba },
	{ 0x2554,	0xc9 },
	{ 0x2557,	0xbb },
	{ 0x255A,	0xc8 },
	{ 0x255D,	0xbc },
	{ 0x2560,	0xcc },
	{ 0x2563,	0xb9 },
	{ 0x2566,	0xcb },
	{ 0x2569,	0xca },
	{ 0x256C,	0xce },
	{ 0x2580,	0xdf },
	{ 0x2584,	0xdc },
	{ 0x2588,	0xdb },
	{ 0x2591,	0xb0 },
	{ 0x2592,	0xb1 },
	{ 0x2593,	0xb2 },
};

void *
bsearch(const void *key, const void *base0, size_t nelem,
	size_t size, int (*cmp)(const void *ck, const void *ce))
{
	char *base = (char*) base0;
	int lim, cmpval;
	void *p;

	for (lim = nelem; lim != 0; lim >>= 1)
	{
		p = base + (lim >> 1) * size;
		cmpval = (*cmp)(key, p);
		if (cmpval == 0)
			return p;

		if (cmpval > 0)
		{				/* key > p: move right */
			base = (char *)p + size;
			lim--;
		} /*,lse move left */
	}
	return 0;
}

static int asciimap_search(const void* ck, const void* ce)
{
	const wchar_t* key = (const wchar_t*) ck;
	const struct asciimap_t* elem = (const struct asciimap_t*) ce;
	return *key - elem->ucs;
}

size_t wcstombs(char *mbstr, const wchar_t *wcstr, size_t count)
{
	struct asciimap_t* map;
	int i;

	for (i = 0; *wcstr && i < count; i++)
	{
		if (*wcstr < 128)
			*mbstr = (unsigned char) *wcstr;
		else
		{
			map = (struct asciimap_t*) bsearch(wcstr, ascii437_to_ucs, 
				sizeof(ascii437_to_ucs) / sizeof(ascii437_to_ucs[0]), 
				sizeof(struct asciimap_t), asciimap_search);

			if (map)
				*mbstr = map->ascii;
			else
				*mbstr = '?';
		}

		wcstr++;
		mbstr++;
	}

	*mbstr = 0;
	return i;
}