1 module dcompute.driver.ocl.util;
2 
3 import std.range;
4 import std.meta;
5 import std.traits;
6 
7 //deal with arrays seperately, in part to avoid any
8 //narrow-string idiocy
9 @property auto memSize(R)(R r)
10 if (is(R : T[], T))
11 {
12     static if (is(R : T[], T))
13         return r.length * T.sizeof;
14     else
15         static assert(false);
16 }
17 
18 @property auto memSize(R)(R r)
19 if(isInputRange!R && hasLength!R && !is(R : T[], T))
20 {
21     return r.length * (ElementType!R).sizeof;
22 }
23 
24 T[Args.length + 1] propertyList(T,Args...)(Args args)
25 {
26     T[Args.length + 1] props;
27     foreach(i, arg; args)
28         props[i] = *cast(T*)(&arg);
29     props[$-1] = cast(T)0;
30     return props;
31 }
32 
33 struct ArrayAccesssor(alias ptr, alias len) {}
34 
35 struct StringzAccessor(alias ptr) {}
36 
37 struct ZeroTerminatedArrayAccessor(alias ptr) {}
38 
39 struct ArrayAccesssor2D(alias ptr, alias lens, alias len) {}
40 
41 // Returned by ArrayAccesssor2D
42 struct RangeOfArray(T)
43 {
44     T**     ptr;
45     size_t* lengths;
46     size_t  length;
47     size_t  index;
48 
49     bool empty()
50     {
51         return index == length;
52     }
53 
54     @property T[] front()
55     {
56         return ptr[index][0 .. lengths[index]];
57     }
58 
59     T[] opIndex(size_t i)
60     {
61         return ptr[i][0 .. lengths[i]];
62     }
63     void popFront()
64     {
65         ++index;
66     }
67     
68     @property size_t opDollar() { return length; }
69 }
70 
71 string generateGetInfo(Info,alias func,string args = "raw")()
72 {
73     import std..string;
74     return helper!(Info.tupleof).format(func.stringof,args);
75 }
76 
77 // A substitute for fullyQualifiedName to speed up compile time
78 private template isModule(alias a) {
79     static if (is(a) || is(typeof(a)) || a.stringof.length < 7) {
80         enum isModule = false;
81     } else {
82         enum isModule = a.stringof[0..7] == "module ";
83     }
84 }
85 
86 private template partiallyQualifiedName(alias a) {
87     static if (isModule!a) {
88         enum partiallyQualifiedName = "";
89     } else {
90         static if (!isModule!(__traits(parent, a))) {
91             enum prefix = partiallyQualifiedName!(__traits(parent, a)) ~ ".";
92         } else {
93             enum prefix = "";
94         }
95         enum partiallyQualifiedName = prefix ~ __traits(identifier, a);
96     }
97 }
98 
99 private template helper(Fields...)
100 {
101     static if (Fields.length == 0)
102         enum helper = "";
103 
104     else static if (is(typeof(Fields[0]) : ArrayAccesssor!(ptr,len),alias ptr,alias len))
105     {
106         enum helper = "@property " ~ typeof(*ptr).stringof ~ "[] " ~ Fields[0].stringof ~ "()\n" ~
107             "{\n" ~
108             "    return " ~ ptr.stringof ~ "[0 .. " ~ len.stringof ~"];"~
109             "}\n" ~ helper!(Fields[1 .. $]);
110     }
111     else static if (is(typeof(Fields[0]) : StringzAccessor!ptr,alias ptr))
112     {
113         enum helper = "@property char[] " ~ Fields[0].stringof ~ "()\n" ~
114             "{\n" ~
115             "    import std.typecons; char[] ret;" ~
116             "    size_t len;" ~
117             "    %1$s(%2$s," ~ __traits(getAttributes, ptr).stringof ~ "[0], 0, null, &len);" ~
118             "    ret.length = len;" ~
119             "    %1$s(%2$s," ~ __traits(getAttributes, ptr).stringof ~ "[0], memSize(ret), ret.ptr, null);" ~
120             "    return ret;" ~
121             "}\n" ~ helper!(Fields[1 .. $]);
122     }
123     else static if (is(typeof(Fields[0]) : ArrayAccesssor2D!(ptr,lens,len) , alias ptr, alias lens, alias len))
124     {
125         enum helper = "@property RangeOfArray!(" ~ typeof(**ptr).stringof ~ ") " ~ Fields[0].stringof ~ "()\n" ~
126             "{\n" ~
127             "   import std.typecons; size_t length; size_t* lengths; " ~ typeof(ptr).stringof ~ " ptr;" ~
128             "   %1$s(%2$s," ~ __traits(getAttributes, len).stringof ~ "[0],length.sizeof, &length,null);" ~
129             "   lengths = (new size_t[length]).ptr; ptr = (new " ~ typeof(*ptr).stringof ~ "[length]).ptr;" ~
130             "   %1$s(%2$s," ~ __traits(getAttributes, lens).stringof ~ "[0],lengths.sizeof, lengths,null);" ~
131             "   if (lengths[length - 1] == 0) length--;" ~
132             "   foreach(i; 0 .. length) \n{" ~
133             "       ptr[i] = (new " ~ typeof(**ptr).stringof ~ "[lengths[i]]).ptr;" ~
134             "   }\n" ~
135             "   %1$s(%2$s," ~ __traits(getAttributes, ptr).stringof ~ "[0], ptr.sizeof, ptr, null);" ~
136             "   return typeof(return)(ptr,lengths,length,0);" ~
137             "}\n" ~ helper!(Fields[1 .. $]);
138     }
139     else
140     {
141         static if (is(typeof(Fields[0]) == enum))
142         {
143             enum helper = "@property " ~ partiallyQualifiedName!(typeof(Fields[0])) ~ " " ~ Fields[0].stringof ~ "()\n" ~
144                 "{\n" ~
145                 "    import std.typecons; typeof(return) ret;" ~
146                 "%1$s(%2$s,"~ __traits(getAttributes, Fields[0]).stringof ~ "[0], ret.sizeof, &ret, null);" ~
147                 "return ret; " ~ 
148                 "}\n" ~ helper!(Fields[1 .. $]);
149     
150         }
151         else 
152         {
153             enum helper = "@property " ~ typeof(Fields[0]).stringof ~ " " ~ Fields[0].stringof ~ "()\n" ~
154                 "{\n" ~
155                 "    import std.typecons; typeof(return) ret;" ~
156                 "%1$s(%2$s,"~ __traits(getAttributes, Fields[0]).stringof ~ "[0], ret.sizeof, &ret, null);" ~
157                 "return ret; " ~ 
158                 "}\n" ~ helper!(Fields[1 .. $]);
159         }
160     }
161 }