root/trunk/AJAX/bottledAJAX.d

Revision 264, 7.0 kB (checked in by BCS, 4 years ago)

I have gone over to the dark side; I have created an AJAX web app framework. It lets you use AJAXy stuff to, from the client, access a JS proxy to a D object on the server. (and it's all templates ;-)

Line 
1 import cgi.cgi;
2 import std.conv;
3
4 /**********************************
5  handal calls to an object of type
6  T to any of methouds X...
7 **********************************/
8 void Process(T,X...)(CGI c, T f)
9 {
10     if(c.Value("classname") != T.mangleof)
11     {
12         c.writef("ERROR=bad_class");
13         return;
14     }
15     try
16     {
17         switch(c.Value("methname"))
18         {
19                 // handal the use cases
20             foreach(i,str; X)
21                 {
22                     case X[i]:
23                     {
24                         auto r = Call!(T, cast(char[])X[i]).It(f,c);
25                         c.writef("ret=%s\n", r);
26                         return;
27                     }
28                 }
29
30                 // handal Errors
31             case "": c.writef("ERROR=no_method"); return;
32             default: c.writef("ERROR=no_method_%s", c.Value("methname")); return;
33         }
34     }   catch (Object o) { c.writef("ERROR=%s", o.toString); }
35 }
36
37
38 /**********************************
39  generate a JavaScript object
40  decleration named "'Base'_Proxy"
41  to Proxy for Base
42 **********************************/
43 template ClientCode(Base, char[] target, fns...)
44 {
45     debug   pragma(msg, "ClientCode("~Base.stringof~", \""~target~"\", "~fns.stringof~")");
46
47     const char[] ClientCode =
48         "var "~Base.stringof~"_Proxy = {"~\n~
49         methouds!(Base,target,fns).methouds~
50         "   }";
51 }
52
53
54 /**********************************
55  Generate the method definitions
56  for a proxy object.
57 **********************************/
58 template methouds(Base, char[] target, names...)
59 {
60     static if(names.length > 0)
61     {
62         const char[] name = names[0];
63         mixin("alias typeof(Base."~name~") FullName;");
64
65         // extract the return type and args types of FullName
66         static if( is(FullName R == return) && is(FullName argsT == function) )
67         {
68             const char[] methouds =
69                 methoud!(Base, target, names[0], argsT.length) ~\n~
70                 methouds!(Base, target, names[1..$]).methouds;
71         }
72         else
73             static assert(false,"woops, Can't find: "~Base.stringof~"."~names[0]~" from "~FullName.stringof);
74     }
75     else
76     {
77         alias void Null;
78         const char[] methouds = "";
79     }
80 }
81
82
83 /**********************************
84  build the whole method
85 **********************************/
86 template methoud(T,char[] target, char[] name, uint count)
87 {
88     const char[] methoud =
89         \t~ name ~": function("~buildArgs!(Names!(count))~")"
90             " {return Http.waitfor({"
91                 "url:'" ~ target ~ "',"
92                 "method:Http.Method.Post,"
93                 "body:'classname="~T.mangleof~"&methname="~name~buildBody!(Names!(count))[0..$-2]~
94             "}).responseText;},";
95 }
96
97
98 /**********************************
99  build an argument list
100 **********************************/
101 template buildArgs(A...)
102 {
103     static if(A.length > 1)       const char[] buildArgs = A[0] ~ "," ~ buildArgs!(A[1..$]);
104     else static if(A.length == 1) const char[] buildArgs = A[0];
105     else                          const char[] buildArgs = "";
106 }
107
108
109 /**********************************
110  build a argument string
111  construction expression
112 **********************************/
113 template buildBody(A...)
114 {
115     static if(A.length > 0) const char[] buildBody = "&"~A[0]~"='+"~A[0]~"+'" ~ buildBody!(A[1..$]);
116     else                    const char[] buildBody = "";
117 }
118
119
120 /**********************************
121  handal a call to "name" by
122  extracting "args" from a HTTP
123  request and converting them to
124  the type of the args of Base."name"
125 **********************************/
126 template Call(Base, char[] name)
127 {
128     // get the type of Base."name"
129     mixin("typedef typeof(&Base."~name~") A;");
130     alias typeof(*A) FullName;
131
132
133     // extract the return type and args types of FullName
134     static if( is(FullName R == return) && is(FullName argsT == function) )
135     {
136         // the actual function
137         R It(Base b, CGI cgi)
138         {
139             alias Names!(argsT.length) args;
140
141                 // make shure stuff matches (old)
142             //static assert(args.length == argsT.length);
143
144             //pragma(msg, "in "~name~" copy " ~ args.stringof ~ " to " ~ argsT.stringof);
145
146                 // the arrgs
147             argsT ag;
148
149                 // decode
150             foreach(int i, A; ag)
151                 ag[i] = Extract!(typeof(A))(cast(char[])args[i], cgi);
152
153                 // call and return
154             return mixin("b."~name~"(ag)");
155         }
156     }
157     else    /// what to do on error
158         static assert(false,"Can't work with "~FullName.stringof~" from "~Base.stringof~"."~name);
159
160         // translate a named parameter from cgi tp type T
161     T Extract(T)(char[] name, CGI cgi)
162     {
163              static if(is(T == char[])) {debug cgi.writef("char[]: [%s]: %s -> %s\n", name, cgi.Value(name),         cgi.Value(name));  return          cgi.Value(name);}
164         else static if(is(T == int))    {debug cgi.writef("int   : [%s]: %s -> %s\n", name, cgi.Value(name),   toInt(cgi.Value(name))); return    toInt(cgi.Value(name));}
165         else static if(is(T == uint))   {debug cgi.writef("uint  : [%s]: %s -> %s\n", name, cgi.Value(name),  toUint(cgi.Value(name))); return   toUint(cgi.Value(name));}
166         else static if(is(T == long))   {debug cgi.writef("long  : [%s]: %s -> %s\n", name, cgi.Value(name),  toLong(cgi.Value(name))); return   toLong(cgi.Value(name));}
167         else static if(is(T == ulong))  {debug cgi.writef("ulong : [%s]: %s -> %s\n", name, cgi.Value(name), toUlong(cgi.Value(name))); return  toUlong(cgi.Value(name));}
168         else static if(is(T == short))  {debug cgi.writef("short : [%s]: %s -> %s\n", name, cgi.Value(name), toShort(cgi.Value(name))); return  toShort(cgi.Value(name));}
169         else static if(is(T == ushort)) {debug cgi.writef("ushort: [%s]: %s -> %s\n", name, cgi.Value(name),toUshort(cgi.Value(name))); return toUshort(cgi.Value(name));}
170         else static if(is(T == byte))   {debug cgi.writef("byte  : [%s]: %s -> %s\n", name, cgi.Value(name),  toByte(cgi.Value(name))); return   toByte(cgi.Value(name));}
171         else static if(is(T == ubyte))  {debug cgi.writef("ubyte : [%s]: %s -> %s\n", name, cgi.Value(name), toUbyte(cgi.Value(name))); return  toUbyte(cgi.Value(name));}
172         else static if(is(T == float))  {debug cgi.writef("float : [%s]: %s -> %s\n", name, cgi.Value(name), toFloat(cgi.Value(name))); return  toFloat(cgi.Value(name));}
173         else static if(is(T == double)) {debug cgi.writef("double: [%s]: %s -> %s\n", name, cgi.Value(name),toDouble(cgi.Value(name))); return toDouble(cgi.Value(name));}
174         else static if(is(T == real))   {debug cgi.writef("real  : [%s]: %s -> %s\n", name, cgi.Value(name),  toReal(cgi.Value(name))); return   toReal(cgi.Value(name));}
175         else static assert(false, "Can't work with type "~T.stringof);
176     }
177 }
178
179
180 /**********************************
181  Generate a Tuple of names for use.
182  Each name in the tuple is uniqie
183  but the same names are returned
184  each time
185 **********************************/
186 template Names(uint i)
187 {
188     static if(i>0) alias T!(Names!(i-1), itoName!(i-1)) Names;
189     else           alias T!() Names;
190 }
191
192
193 /**********************************
194     based off Don Clugston's itoa.
195     see http://trac.dsource.org/projects/ddl/browser/trunk/meta/conv.d
196 **********************************/
197 template CharDigit(int n) { const char[] CharDigit = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"[n..n+1];}
198 template itoName(ulong n)
199 {
200     static if (n < 26) const char[] itoName = CharDigit!(n);
201     else               const char[] itoName = itoName!(n/10L) ~ CharDigit!(n%26L);
202 }
203
204
205 // helper Tuple template
206 template T(A...){alias A T;}
Note: See TracBrowser for help on using the browser.