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