[ create a new paste ] login | about

Link: http://codepad.org/Y2TDmHn3    [ raw code | fork ]

C++, pasted on Oct 29:
#include <iostream>
#include <string>
#include <stdio.h>
#include <assert.h>
//#include <ctype.h>
#include <string.h>

static const struct {
	const char *name;
	const char *hex_string;
} named_colors[] = {
	{ "AliceBlue",            "#F0F8FF" },
	{ "AntiqueWhite",         "#FAEBD7" },
	{ "Aqua",                 "#00FFFF" },
	{ "Aquamarine",           "#7FFFD4" },
	{ "Azure",                "#F0FFFF" },
	{ "Beige",                "#F5F5DC" },
	{ "Bisque",               "#FFE4C4" },
	{ "Black",                "#000000" },
	{ "BlanchedAlmond",       "#FFEBCD" },
	{ "Blue",                 "#0000FF" },
	{ "BlueViolet",           "#8A2BE2" },
	{ "Brown",                "#A52A2A" },
	{ "BurlyWood",            "#DEB887" },
	{ "CadetBlue",            "#5F9EA0" },
	{ "Chartreuse",           "#7FFF00" },
	{ "Chocolate",            "#D2691E" },
	{ "Coral",                "#FF7F50" },
	{ "CornflowerBlue",       "#6495ED" },
	{ "Cornsilk",             "#FFF8DC" },
	{ "Crimson",              "#DC143C" },
	{ "Cyan",                 "#00FFFF" },
	{ "DarkBlue",             "#00008B" },
	{ "DarkCyan",             "#008B8B" },
	{ "DarkGoldenRod",        "#B8860B" },
	{ "DarkGray",             "#A9A9A9" },
	{ "DarkGreen",            "#006400" },
	{ "DarkKhaki",            "#BDB76B" },
	{ "DarkMagenta",          "#8B008B" },
	{ "DarkOliveGreen",       "#556B2F" },
	{ "DarkOrange",           "#FF8C00" },
	{ "DarkOrchid",           "#9932CC" },
	{ "DarkRed",              "#8B0000" },
	{ "DarkSalmon",           "#E9967A" },
	{ "DarkSeaGreen",         "#8FBC8F" },
	{ "DarkSlateBlue",        "#483D8B" },
	{ "DarkSlateGray",        "#2F4F4F" },
	{ "DarkTurquoise",        "#00CED1" },
	{ "DarkViolet",           "#9400D3" },
	{ "DeepPink",             "#FF1493" },
	{ "DeepSkyBlue",          "#00BFFF" },
	{ "DimGray",              "#696969" },
	{ "DodgerBlue",           "#1E90FF" },
	{ "FireBrick",            "#B22222" },
	{ "FloralWhite",          "#FFFAF0" },
	{ "ForestGreen",          "#228B22" },
	{ "Fuchsia",              "#FF00FF" },
	{ "Gainsboro",            "#DCDCDC" },
	{ "GhostWhite",           "#F8F8FF" },
	{ "Gold",                 "#FFD700" },
	{ "GoldenRod",            "#DAA520" },
	{ "Gray",                 "#808080" },
	{ "Green",                "#008000" },
	{ "GreenYellow",          "#ADFF2F" },
	{ "HoneyDew",             "#F0FFF0" },
	{ "HotPink",              "#FF69B4" },
	{ "IndianRed ",           "#CD5C5C" },
	{ "Indigo ",              "#4B0082" },
	{ "Ivory",                "#FFFFF0" },
	{ "Khaki",                "#F0E68C" },
	{ "Lavender",             "#E6E6FA" },
	{ "LavenderBlush",        "#FFF0F5" },
	{ "LawnGreen",            "#7CFC00" },
	{ "LemonChiffon",         "#FFFACD" },
	{ "LightBlue",            "#ADD8E6" },
	{ "LightCoral",           "#F08080" },
	{ "LightCyan",            "#E0FFFF" },
	{ "LightGoldenRodYellow", "#FAFAD2" },
	{ "LightGray",            "#D3D3D3" },
	{ "LightGreen",           "#90EE90" },
	{ "LightPink",            "#FFB6C1" },
	{ "LightSalmon",          "#FFA07A" },
	{ "LightSeaGreen",        "#20B2AA" },
	{ "LightSkyBlue",         "#87CEFA" },
	{ "LightSlateGray",       "#778899" },
	{ "LightSteelBlue",       "#B0C4DE" },
	{ "LightYellow",          "#FFFFE0" },
	{ "Lime",                 "#00FF00" },
	{ "LimeGreen",            "#32CD32" },
	{ "Linen",                "#FAF0E6" },
	{ "Magenta",              "#FF00FF" },
	{ "Maroon",               "#800000" },
	{ "MediumAquaMarine",     "#66CDAA" },
	{ "MediumBlue",           "#0000CD" },
	{ "MediumOrchid",         "#BA55D3" },
	{ "MediumPurple",         "#9370DB" },
	{ "MediumSeaGreen",       "#3CB371" },
	{ "MediumSlateBlue",      "#7B68EE" },
	{ "MediumSpringGreen",    "#00FA9A" },
	{ "MediumTurquoise",      "#48D1CC" },
	{ "MediumVioletRed",      "#C71585" },
	{ "MidnightBlue",         "#191970" },
	{ "MintCream",            "#F5FFFA" },
	{ "MistyRose",            "#FFE4E1" },
	{ "Moccasin",             "#FFE4B5" },
	{ "NavajoWhite",          "#FFDEAD" },
	{ "Navy",                 "#000080" },
	{ "OldLace",              "#FDF5E6" },
	{ "Olive",                "#808000" },
	{ "OliveDrab",            "#6B8E23" },
	{ "Orange",               "#FFA500" },
	{ "OrangeRed",            "#FF4500" },
	{ "Orchid",               "#DA70D6" },
	{ "PaleGoldenRod",        "#EEE8AA" },
	{ "PaleGreen",            "#98FB98" },
	{ "PaleTurquoise",        "#AFEEEE" },
	{ "PaleVioletRed",        "#DB7093" },
	{ "PapayaWhip",           "#FFEFD5" },
	{ "PeachPuff",            "#FFDAB9" },
	{ "Peru",                 "#CD853F" },
	{ "Pink",                 "#FFC0CB" },
	{ "Plum",                 "#DDA0DD" },
	{ "PowderBlue",           "#B0E0E6" },
	{ "Purple",               "#800080" },
	{ "Red",                  "#FF0000" },
	{ "RosyBrown",            "#BC8F8F" },
	{ "RoyalBlue",            "#4169E1" },
	{ "SaddleBrown",          "#8B4513" },
	{ "Salmon",               "#FA8072" },
	{ "SandyBrown",           "#F4A460" },
	{ "SeaGreen",             "#2E8B57" },
	{ "SeaShell",             "#FFF5EE" },
	{ "Sienna",               "#A0522D" },
	{ "Silver",               "#C0C0C0" },
	{ "SkyBlue",              "#87CEEB" },
	{ "SlateBlue",            "#6A5ACD" },
	{ "SlateGray",            "#708090" },
	{ "Snow",                 "#FFFAFA" },
	{ "SpringGreen",          "#00FF7F" },
	{ "SteelBlue",            "#4682B4" },
	{ "Tan",                  "#D2B48C" },
	{ "Teal",                 "#008080" },
	{ "Thistle",              "#D8BFD8" },
	{ "Tomato",               "#FF6347" },
	{ "Turquoise",            "#40E0D0" },
	{ "Violet",               "#EE82EE" },
	{ "Wheat",                "#F5DEB3" },
	{ "White",                "#FFFFFF" },
	{ "WhiteSmoke",           "#F5F5F5" },
	{ "Yellow",               "#FFFF00" },
	{ "YellowGreen",          "#9ACD32" }
};

static inline bool hex_digit_decode(char hexdigit, unsigned char &value)
{
	if(hexdigit >= '0' && hexdigit <= '9')
		value = hexdigit - '0';
	else if(hexdigit >= 'A' && hexdigit <= 'F')
		value = hexdigit - 'A' + 10;
	else if(hexdigit >= 'a' && hexdigit <= 'f')
		value = hexdigit - 'a' + 10;
	else
		return false;
	return true;
}


static bool parseHexColorString(const std::string &value, unsigned *colour)
{
	unsigned char components[] = { 0x00, 0x00, 0x00, 0xff }; // R,G,B,A

	if (value[0] != '#')
		return false;

	size_t len = value.size();
	bool short_form;

	if (len == 9 || len == 7) // #RRGGBBAA or #RRGGBB
		short_form = false;
	else if (len == 5 || len == 4) // #RGBA or #RGB
		short_form = true;
	else
		return false;

	bool success = true;

	for (size_t pos = 1, cc = 0; pos < len; pos++, cc++) {
		assert(cc < sizeof components / sizeof components[0]);
		if (short_form) {
			unsigned char d;
			if (!hex_digit_decode(value[pos], d)) {
				success = false;
				break;
			}
			components[cc] = (d & 0xf) << 4 | (d & 0xf);
		} else {
			unsigned char d1, d2;
			if (!hex_digit_decode(value[pos], d1) ||
					!hex_digit_decode(value[pos+1], d2)) {
				success = false;
				break;
			}
			components[cc] = (d1 & 0xf) << 4 | (d2 & 0xf);
			pos++;	// skip the second digit -- it's already used
		}
	}

	if (success) {
		*colour = (components[3] << 24) | (components[0] << 16) | (components[1] << 8) | (components[2]);
	}

	return success;
}

static bool parseNamedColorString(const std::string &value, unsigned *colour)
{
	int found_color = -1;

	size_t alpha_pos = value.find('#');
	std::string color_name;
	std::string alpha_string;

	if (alpha_pos != std::string::npos) {
		color_name = value.substr(0, alpha_pos);
		alpha_string = value.substr(alpha_pos + 1);
	} else {
		color_name = value;
		alpha_string = "FF";
	}

	/* Not exactly efficient, but named colors (or hex strings) shouldn't be
	   used in time-critical areas anyway.
	 */
	for (size_t i = 0; i < sizeof named_colors / sizeof named_colors[0]; i++) {
		// TODO: Make the comparison insensitive to case
		if (color_name == named_colors[i].name) {
			found_color = i;
			break;
		}
	}
	return found_color == -1
			? false
			: parseHexColorString(named_colors[found_color].hex_string + alpha_string, colour);
}

bool parseColor(const std::string &value, unsigned *colour)
{
	bool success;

	if (value[0] == '#')
		success = parseHexColorString(value, colour);
	else
		success = parseNamedColorString(value, colour);

	return success;
}
#if 0
void convert(void)
{
	char buff[1024];
	for (size_t i = 0; i < sizeof named_colors / sizeof named_colors[0]; i++) {
		size_t j = 0;
		for ( ; j < strlen(named_colors[i].name); j++) {
			buff[j] = tolower(named_colors[i].name[j]);
		}
		buff[j] = '\0';
		printf("{\"%s\",", buff);
		for (j = 0; j < 22-strlen(buff); j++)
			printf(" ");
		printf("\"%s\" },\n", named_colors[i].hex_string);
	}
}
#endif

int main(void)
{

	unsigned colour;

	assert(parseColor("YellowGreen", &colour) && colour == 0xFF9ACD32);
	assert(parseColor("YellowGreen#87", &colour) && colour == 0x879ACD32);
	assert(parseColor("RosyBrown#ba", &colour) && colour == 0xBABC8F8F);

#if 0
	assert(parseColor("FF-DD-E2", &colour) == false);
	assert(parseColor("#FF-DD-E2", &colour) == false);
	assert(parseColor("#AABBCP", &colour) == false);
	parseColor("#AABBCCDD", &colour);
	assert(parseColor("#AABBCCDD", &colour) && colour == 0xddaabbcc);
	assert(parseColor("#f00d", &colour) && colour == 0xddff0000);
	assert(parseColor("YellowGreen", &colour));
	assert(parseColor("sdsdYellowGreen", &colour) == false);
	assert(parseColor("#ffffff00", &colour));
	assert(parseColor("#ffffffddddddddddddddd", &colour) == false);


	for (unsigned i = 0; i < 65535; i++) {
		char buff[20];
		sprintf(buff, "#%06x", i);
		assert(parseColor(buff, &colour) && colour == (0xff000000 | i));
	}
#endif
	return 0;
}


Output:
No errors or program output.


Create a new paste based on this one


Comments: