/******************************************************************************
 *    strtocolor.cpp
 *
 *    This file is part of Object Script Library
 *    Copyright (C) 2005-2009 Tom N Harris <telliamed@whoopdedo.org>
 *
 *    Permission is hereby granted, free of charge, to any person obtaining
 *    a copy of this software and associated documentation files (the 
 *    "Software"), to deal in the Software without restriction, including 
 *    without limitation the rights to use, copy, modify, merge, publish, 
 *    distribute, sublicense, and/or sell copies of the Software, and to 
 *    permit persons to whom the Software is furnished to do so.
 *    
 *    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
 *    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
 *    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-
 *    INFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 
 *    BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 
 *    AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 
 *    IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 
 *    THE SOFTWARE.
 *
 *****************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

static const unsigned char g_cHexTable[] = {
	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,        0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,        0,1,2,3,4,5,6,7,8,9,0,0,0,0,0,0,
	0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	0,10,11,12,13,14,15,0,0,0,0,0,0,0,0,0,  0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,        0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,        0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,        0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,        0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
};

typedef struct _colorname
{
	const char* n;
	unsigned long c;
} colorname;
static const colorname g_sColorNames[] = {
	{ "aqua",    0xFFFF00 },
	{ "black",   0x080808 },
	{ "blue",    0xFF0000 },
	{ "chartreuse", 0x80FF80 },
	{ "dodger",     0x0080FF },
	{ "fuchsia", 0xFF00FF },
	{ "gold",       0x80FFFF },
	{ "gray",    0x808080 },
	{ "green",   0x008000 },
	{ "grey",    0x808080 },
	{ "lawn",       0x00FF80 },
	{ "lime",    0x00FF00 },
	{ "maroon",  0x000080 },
	{ "navy",    0x800000 },
	{ "olive",   0x008080 },
	{ "orange",     0x0080FF },
	{ "orchid",     0xFF80FF },
	{ "pink",       0x8000FF },
	{ "purple",  0x800080 },
	{ "red",     0x0000FF },
	{ "rose",       0x8080FF },
	{ "silver",  0xC0C0C0 },
	{ "slate",      0xFF8080 },
	{ "spring",     0x80FF00 },
	{ "steel",      0xFF8000 },
	{ "teal",    0x808000 },
	{ "turquoise",  0xFFFF80 },
	{ "violet",     0xFF0080 },
	{ "white",   0xFFFFFF },
	{ "yellow",  0x00FFFF }
};
static const unsigned int g_iNumColors = sizeof(g_sColorNames)/sizeof(g_sColorNames[0]);
//static const colorname* g_sColorNameLast = g_sColorNames + g_iNumColors;

int colornamecmp(const void* key, const void* elem)
{
	return stricmp(reinterpret_cast<const char*>(key),
		reinterpret_cast<const colorname*>(elem)->n);
}

int strtocolor(const char* str)
{
	register const unsigned char* c = reinterpret_cast<const unsigned char*>(str);
	if (*c == '#')
	{
		if (strlen(reinterpret_cast<const char*>(++c)) < 6)
			return 0;
		unsigned char r,g,b;
		r  = g_cHexTable[*c++] << 4;
		r |= g_cHexTable[*c++];
		g  = g_cHexTable[*c++] << 4;
		g |= g_cHexTable[*c++];
		b  = g_cHexTable[*c++] << 4;
		b |= g_cHexTable[*c];
		return (r|(g<<8)|(b<<16));
	}
	if (strchr(str, ','))
	{
		unsigned int r,g,b;
		if (3 == sscanf(str, "%u , %u , %u", &r, &g, &b))
		{
			return ((r&0xFF)|((g&0xFF)<<8)|((b&0xFF)<<16));
		}
	}
	else
	{
		const colorname* clr = reinterpret_cast<const colorname*>(
			bsearch(reinterpret_cast<const void*>(str), 
				reinterpret_cast<const void*>(g_sColorNames), 
				g_iNumColors, 
				sizeof(colorname), 
				colornamecmp)
			);
		if (clr)
			return clr->c;
		/*
		unsigned int r,b,n;
		for (r=0, b=g_iNumColors-1, n=g_iNumColors>>1; 1; )
		{
			int cmp = g_sColorNames[n].cmp(str);
			if (cmp == 0)
			{
				return g_sColorNames[n].c;
			}
			if (cmp > 0)
			{
				if (n == b)
					break;
				r = n + 1;
				n = r + ((b - n) >> 1);
			}
			else
			{
				if (n == r)
					break;
				b = n - 1;
				n = b - ((n - r) >> 1);
			}
		}
		*/
		/*
		for (unsigned int n=0; n < sizeof(g_sColorNames)/sizeof(g_sColorNames[0]); ++n)
		{
			if (!stricmp(str,g_sColorNames[n].n))
				return g_sColorNames[n].c;
		}
		*/
	}
	return 0;
}
