2011-08-16 12:53:13 +00:00
|
|
|
import std.stdio;
|
|
|
|
import std.string;
|
2018-04-27 03:17:09 +00:00
|
|
|
import dyaml;
|
2011-08-16 12:53:13 +00:00
|
|
|
|
|
|
|
struct Color
|
|
|
|
{
|
|
|
|
ubyte red;
|
|
|
|
ubyte green;
|
|
|
|
ubyte blue;
|
2012-01-23 14:57:26 +00:00
|
|
|
|
|
|
|
const int opCmp(ref const Color c)
|
|
|
|
{
|
|
|
|
if(red != c.red) {return red - c.red;}
|
|
|
|
if(green != c.green){return green - c.green;}
|
|
|
|
if(blue != c.blue) {return blue - c.blue;}
|
|
|
|
return 0;
|
|
|
|
}
|
2011-08-16 12:53:13 +00:00
|
|
|
}
|
|
|
|
|
2011-11-17 22:53:24 +00:00
|
|
|
Color constructColorScalar(ref Node node)
|
2011-08-16 12:53:13 +00:00
|
|
|
{
|
2011-10-22 15:06:32 +00:00
|
|
|
string value = node.as!string;
|
2011-10-17 10:53:38 +00:00
|
|
|
|
|
|
|
if(value.length != 6)
|
|
|
|
{
|
2011-11-17 22:53:24 +00:00
|
|
|
throw new Exception("Invalid color: " ~ value);
|
2011-10-17 10:53:38 +00:00
|
|
|
}
|
|
|
|
//We don't need to check for uppercase chars this way.
|
|
|
|
value = value.toLower();
|
|
|
|
|
|
|
|
//Get value of a hex digit.
|
|
|
|
uint hex(char c)
|
|
|
|
{
|
2014-08-01 15:09:05 +00:00
|
|
|
import std.ascii;
|
2011-10-17 10:53:38 +00:00
|
|
|
if(!std.ascii.isHexDigit(c))
|
|
|
|
{
|
2011-11-17 22:53:24 +00:00
|
|
|
throw new Exception("Invalid color: " ~ value);
|
2011-10-17 10:53:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if(std.ascii.isDigit(c))
|
|
|
|
{
|
|
|
|
return c - '0';
|
|
|
|
}
|
|
|
|
return c - 'a' + 10;
|
|
|
|
}
|
|
|
|
|
|
|
|
Color result;
|
|
|
|
result.red = cast(ubyte)(16 * hex(value[0]) + hex(value[1]));
|
|
|
|
result.green = cast(ubyte)(16 * hex(value[2]) + hex(value[3]));
|
|
|
|
result.blue = cast(ubyte)(16 * hex(value[4]) + hex(value[5]));
|
|
|
|
|
|
|
|
return result;
|
2011-08-16 12:53:13 +00:00
|
|
|
}
|
|
|
|
|
2011-11-17 22:53:24 +00:00
|
|
|
Color constructColorMapping(ref Node node)
|
2011-08-16 12:53:13 +00:00
|
|
|
{
|
2011-10-17 11:13:02 +00:00
|
|
|
ubyte r,g,b;
|
2011-10-17 10:53:38 +00:00
|
|
|
|
2011-10-17 11:13:02 +00:00
|
|
|
//Might throw if a value is missing is not an integer, or is out of range.
|
2011-11-17 22:53:24 +00:00
|
|
|
//If this happens, D:YAML will handle the exception and use its message
|
|
|
|
//in a YAMLException thrown when loading.
|
|
|
|
r = node["r"].as!ubyte;
|
|
|
|
g = node["g"].as!ubyte;
|
|
|
|
b = node["b"].as!ubyte;
|
2011-10-17 10:53:38 +00:00
|
|
|
|
|
|
|
return Color(cast(ubyte)r, cast(ubyte)g, cast(ubyte)b);
|
2011-08-16 12:53:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void main()
|
|
|
|
{
|
|
|
|
auto red = Color(255, 0, 0);
|
|
|
|
auto orange = Color(255, 255, 0);
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
auto constructor = new Constructor;
|
|
|
|
//both functions handle the same tag, but one handles scalar, one mapping.
|
2011-10-17 10:53:38 +00:00
|
|
|
constructor.addConstructorScalar("!color", &constructColorScalar);
|
|
|
|
constructor.addConstructorMapping("!color-mapping", &constructColorMapping);
|
2011-08-16 12:53:13 +00:00
|
|
|
|
|
|
|
auto resolver = new Resolver;
|
2014-08-01 15:09:05 +00:00
|
|
|
import std.regex;
|
2011-08-16 12:53:13 +00:00
|
|
|
resolver.addImplicitResolver("!color", std.regex.regex("[0-9a-fA-F]{6}"),
|
|
|
|
"0123456789abcdefABCDEF");
|
2014-08-01 15:09:05 +00:00
|
|
|
|
2011-10-12 21:49:42 +00:00
|
|
|
auto loader = Loader("input.yaml");
|
|
|
|
loader.constructor = constructor;
|
|
|
|
loader.resolver = resolver;
|
2011-08-16 12:53:13 +00:00
|
|
|
|
2011-10-12 21:49:42 +00:00
|
|
|
auto root = loader.load();
|
2011-08-16 12:53:13 +00:00
|
|
|
|
2014-08-01 15:09:05 +00:00
|
|
|
if(root["scalar-red"].as!Color == red &&
|
|
|
|
root["mapping-red"].as!Color == red &&
|
|
|
|
root["scalar-orange"].as!Color == orange &&
|
2011-10-22 15:06:32 +00:00
|
|
|
root["mapping-orange"].as!Color == orange)
|
2011-08-16 12:53:13 +00:00
|
|
|
{
|
|
|
|
writeln("SUCCESS");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
catch(YAMLException e)
|
|
|
|
{
|
|
|
|
writeln(e.msg);
|
|
|
|
}
|
|
|
|
|
|
|
|
writeln("FAILURE");
|
|
|
|
}
|