Semi Automated Object wrapping
Rory McGuire
rjmcguire at gmail.com
Thu Aug 13 00:43:31 PDT 2009
On Wed, 12 Aug 2009 17:03:17 -0700, Bill Baxter wrote:
> On Wed, Aug 12, 2009 at 4:52 PM, Rory McGuire<rjmcguire at gmail.com>
> wrote:
>> Here is some code I wrote which enables wrapping a proxy around an
>> object. I am using it for my serialization library. It works in
>> D1(1.046) and D2 (2.031)
>>
>> Posting it here for reference by all before I add to much of the stuff
>> specific to my use, should make it easier to follow.
>>
>> usage: new ProxyClass!(A, cast(string)"getInt setInt getString"); would
>> implement the methods getInt setInt and getString from A in the new
>> class.
>>
>> the code below will fail to compile but not before printing the
>> generated code to stdout.
>>
>> Shin Fujishiro has made some new templates for D2 which will make it so
>> I can get rid of the "setInt getInt getString" part which would make
>> the usage for D2: new ProxyClass!A;
>> which would be great!
>>
>> -Rory
>>
>> ============================================ // author: Rory McGuire,
>> rjmcguire at gmail.com import std.stdio;
>> import std.typetuple;
>> import std.traits;
>> import std.metastrings;
>>
>> //import serializer;
>>
>> // this CTF from somewhere on news.digitalmars.com string[]
>> splitFuncs(string str) {
>> string[] res;
>> while (str.length > 0) {
>> while (str.length > 0 && (' ' == str[0] || ',' == str[0])) {
>> str = str[1..$];
>> }
>> int to = 0;
>> for (; to < str.length && str[to] != ' ' && str[to] != ',';
>> ++to)
>> {}
>> if (to > 0) {
>> res ~= str[0..to];
>> str = str[to..$];
>> }
>> }
>> return res;
>> }
>>
>> string MethodTypeTuple_mixin(alias a)(string[] methods) {
>> string ret = "TypeTuple!("~
>> "typeof(&C.init."~methods[0]~")"; foreach (method;
>> methods[1..$]) {
>> ret ~= ",typeof(&C.init."~method~")";
>> }
>> ret ~= ")";
>> return ret;
>> }
>>
>>
>>
>> // test case
>>
>> class A {
>> int a;
>> this(int a) {
>> this.a = a;
>> }
>> int getInt(string intname) {
>> return a;
>> }
>>
>> void setInt(int i) {
>> a = i;
>> }
>> string getString(string s) {
>> return s ~"1234";
>> }
>> }
>>
>>
>> string ProxyMethods_mixin(alias C, string methodstr)() {
>> string ret;
>> foreach(i, t; mixin(MethodTypeTuple_mixin!(C)(splitFuncs
>> (methodstr)))) {
>> // output function header
>> ret ~= "\t"~ReturnType!(t).stringof ~" "~
>> splitFuncs
>> (methodstr)[i]~"(";
>> // output first arg
>> ret ~= ParameterTypeTuple!(t)[0].stringof~"
>> arg"; // output remainder of args
>> foreach (j, t1; ParameterTypeTuple!(t)[1..$]) {
>> ret ~= ","~t1.stringof~"
>> arg"~std.metastrings.ToString!(j);
>> }
>> // output body
>> ret ~= ") {\n";
>> // output serialization code
>> // send method name
>> ret ~= "\t\twritefln(\"serialize docall id\");
>> // the
>> method call byte id\n";
>> ret ~= "\t\tbuffer ~=
>> serialize!(string)(\""~splitFuncs
>> (methodstr)[i]~"\", s_state); /+ the method name +/\n";
>> // send args
>> ret ~= "\t\tbuffer ~= serialize!("~
>> ParameterTypeTuple!(t)
>> [0].stringof~")(arg, s_state); /+ the first argument +/\n";
>> foreach (j, t1; ParameterTypeTuple!(t)[1..$]) {
>> ret ~= "\t\tbuffer ~= serialize!("~
>> t1.stringof
>> ~")(arg"~ToString!(j)~", s_state); /+ argument "~ToString!(j)~" +/\n";
>> }
>> // receive return type
>> static if (!is(ReturnType!(t) == void)) {
>> ret ~= "\t\treturn deserialize!("~
>> ReturnType!
>> (t).stringof ~")(buffer, des_state);\n";
>> }
>> ret ~= "\t}\n";
>> }
>> return ret;
>> }
>>
>>
>> class ProxyClass(alias C, string methodstr) {
>> ubyte[] buffer;
>> mixin(ProxyMethods_mixin!(C,methodstr)());
>> pragma(msg, "class ProxyClass!("~C.stringof~",
>> \""~
>> methodstr ~"\") {\n\tubyte[] buffer;\n SerializerState s_state;\n
>> DeserializerState des_state;\n this() {s_state = new
>> SerializerState(); des_state = new DeserializerState(); }\n\n"~
>> ProxyMethods_mixin! (C,methodstr)() ~"\n}\n");
>>
>> }
>>
>> void main() {
>> auto pc = new ProxyClass!(A, cast(string)"getInt setInt
>> getString");
>> writefln("ProxyClass: "~ pc.getString("asdf"));
>> }
>>
>>
> That code is screaming for some macros. Or variable interpolation at
> least.
>
> --bb
Where would you propose that one would use 'macro'?
More information about the Digitalmars-d-learn
mailing list