root/trunk/src/semitwist/refbox.d

Revision 202, 3.4 kB (checked in by Abscissa, 1 year ago)

(NB) all: Fixed: In D2, compile-time constants use the 'enum' abomination, not 'const'.

  • Property svn:eol-style set to native
Line 
1 // SemiTwist Library
2 // Written in the D programming language.
3
4 module semitwist.refbox;
5
6 import std.stdio;
7 import std.math;
8 import std.string;
9 import std.algorithm : find;
10
11 import semitwist.util.all;
12
13 //TODO: Does phobos's Variant make this obsolete?
14 //TODO? convert to struct
15 /// A boxable wrapper useful for variables of primitive types.
16 class RefBox(T)
17 {
18     private T* val;
19     private T optionalValSrc;
20    
21     this()
22     {
23         this.val = &optionalValSrc;
24     }
25    
26     this(T* val)
27     {
28         this.val = val;
29     }
30    
31     T opCall()
32     {
33         return *val;
34     }
35    
36     void opAssign(T val)
37     {
38         *this.val = val;
39     }
40    
41     const bool opEquals(ref const(RefBox!(T)) val)
42     {
43         return *this.val == *val.val;
44     }
45    
46     const bool opEquals(ref const(T) val)
47     {
48         return *this.val == val;
49     }
50    
51     RefBox!(T) dup()
52     {
53         auto newBox = new RefBox!(T)();
54         newBox.optionalValSrc = *this.val;
55         return newBox;
56     }
57 }
58
59 string getRefBoxTypeName(Object o)
60 {
61     string head = RefBox.stringof[0..$-3]~"!(";
62     string unknown = "{unknown}";
63     string typeName = o.classinfo.name;
64    
65     //TODO?: Replace this with a regex search (if possible) and handle nested ()'s
66    
67     auto start = locatePrior(typeName, head);
68     if(start == typeName.length)
69         return unknown;
70     start += head.length;
71        
72     auto end = locate(typeName[start..$], ')')+start;
73     if(end == typeName.length)
74         return unknown;
75    
76     // Nested () inside "RefBox!(...)" is not currently supported
77     if(std.algorithm.find(typeName[start..end], '(') != [])
78         return unknown;
79        
80     return typeName[start..end];
81 }
82
83 /// Helpful templates
84 template unbox(alias obj, string name)
85 {
86     enum unbox =
87         unboxToTypeAndArray!(obj, name~"AsInt",  int   )~
88         unboxToTypeAndArray!(obj, name~"AsBool", bool  )~
89         unboxToTypeAndArray!(obj, name~"AsStr",  string);
90     //pragma(msg, "unbox:\n" ~ unbox);
91 }
92
93 private template unboxToTypeAndArray(alias obj, string name, type)
94 {
95     enum unboxToTypeAndArray =
96         unboxTo!(obj, name,     type.stringof     )~
97         unboxTo!(obj, name~"s", type.stringof~"[]");
98 }
99
100 private template unboxTo(alias obj, string name, string type)
101 {
102     enum unboxTo = "auto "~name~" = cast(RefBox!("~type~"))"~obj.stringof~";\n";
103 }
104
105
106 template dupRefBox(alias from, string tempName, alias to)
107 {
108     enum dupRefBox =
109         unbox!(from, tempName)~
110         "if(false) {}\n"~
111         dupRefBoxTypeAndArray!(from, tempName~"AsInt",  int   , to)~
112         dupRefBoxTypeAndArray!(from, tempName~"AsBool", bool  , to)~
113         dupRefBoxTypeAndArray!(from, tempName~"AsStr",  string, to)~
114         "else "~to.stringof~" = null;\n";
115     //pragma(msg, "dupRefBox:\n" ~ dupRefBox);
116 }
117
118 private template dupRefBoxTypeAndArray(alias from, string tempName, type, alias to)
119 {
120     enum dupRefBoxTypeAndArray =
121         dupRefBoxFrom!(from, tempName,     type.stringof     , to)~
122         dupRefBoxFrom!(from, tempName~"s", type.stringof~"[]", to);
123 }
124
125 private template dupRefBoxFrom(alias from, string tempName, string type, alias to)
126 {
127     enum dupRefBoxFrom = "else if("~tempName~") "~to.stringof~" = "~tempName~".dup();\n";
128 }
129
130
131 template isKnownRefBox(alias obj)
132 {
133     enum isKnownRefBox =
134         isKnownRefBoxTypeAndArray!(obj, int   )~
135         isKnownRefBoxTypeAndArray!(obj, bool  )~
136         isKnownRefBoxTypeAndArray!(obj, string)~
137         "false ";
138     //pragma(msg, "isKnownRefBox:\n" ~ isKnownRefBox);
139 }
140
141 private template isKnownRefBoxTypeAndArray(alias obj, type)
142 {
143     enum isKnownRefBoxTypeAndArray =
144         isKnownRefBoxOf!(obj, type.stringof     )~
145         isKnownRefBoxOf!(obj, type.stringof~"[]");
146 }
147
148 private template isKnownRefBoxOf(alias obj, string type)
149 {
150     enum isKnownRefBoxOf = "cast(RefBox!("~type~"))"~obj.stringof~" ||\n";
151 }
Note: See TracBrowser for help on using the browser.