1 2 // Copyright Ferdinand Majerech 2011. 3 // Distributed under the Boost Software License, Version 1.0. 4 // (See accompanying file LICENSE_1_0.txt or copy at 5 // http://www.boost.org/LICENSE_1_0.txt) 6 7 ///Compact storage of multiple boolean values. 8 module dyaml.flags; 9 10 11 import std.conv; 12 13 14 package: 15 16 /** 17 * Struct holding multiple named boolean values in a single byte. 18 * 19 * Can hold at most 8 values. 20 * 21 * Example: 22 * -------------------- 23 * Flags!("empty", "multiline") flags; 24 * assert(flags.empty == false && flags.multiline == false); 25 * flags.multiline = true; 26 * assert(flags.empty == false && flags.multiline == true); 27 * flags.empty = true; 28 * assert(flags.empty == true && flags.multiline == true); 29 * flags.multiline = false; 30 * assert(flags.empty == true && flags.multiline == false); 31 * flags.empty = false; 32 * assert(flags.empty == false && flags.multiline == false); 33 * -------------------- 34 */ 35 struct Flags(names ...) if(names.length <= 8) 36 { 37 private: 38 @disable int opCmp(ref Flags); 39 40 ///Byte storing the flags. 41 ubyte flags_; 42 43 ///Generate a setter and a getter for each flag. 44 static string flags(string[] names ...) @trusted 45 in 46 { 47 assert(names.length <= 8, "Flags struct can only hold 8 flags"); 48 } 49 body 50 { 51 string result; 52 foreach(index, name; names) 53 { 54 string istr = to!string(index); 55 result ~= "\n" 56 "@property bool " ~ name ~ "(bool value) pure @safe nothrow\n" 57 "{\n" 58 " flags_ = value ? flags_ | (1 <<" ~ istr ~ ")\n" 59 " : flags_ & (0xFF ^ (1 << " ~ istr ~"));\n" 60 " return value;\n" 61 "}\n" 62 "\n" 63 "@property bool " ~ name ~ "() const pure @safe nothrow\n" 64 "{\n" 65 " return (flags_ >> " ~ istr ~ ") & 1;\n" 66 "}\n"; 67 } 68 return result; 69 } 70 71 public: 72 ///Flag accessors. 73 mixin(flags(names)); 74 } 75 unittest 76 { 77 import std.stdio; 78 writeln("Flags unittest"); 79 80 Flags!("empty", "multiline") flags; 81 assert(flags.empty == false && flags.multiline == false); 82 flags.multiline = true; 83 assert(flags.empty == false && flags.multiline == true); 84 flags.empty = true; 85 assert(flags.empty == true && flags.multiline == true); 86 flags.multiline = false; 87 assert(flags.empty == true && flags.multiline == false); 88 flags.empty = false; 89 assert(flags.empty == false && flags.multiline == false); 90 } 91