1 module metacall;
2 
3 import std.stdio;
4 import std.exception;
5 import std.string;
6 import std.variant;
7 import core.vararg;
8 import core.stdc.string;
9 
10 enum metacall_value_id_enum : int {
11   METACALL_BOOL		  = 0,
12   METACALL_CHAR		  = 1,
13   METACALL_SHORT	  = 2,
14   METACALL_INT		  = 3,
15   METACALL_LONG		  = 4,
16   METACALL_FLOAT	  = 5,
17   METACALL_DOUBLE	  = 6,
18   METACALL_STRING	  = 7,
19   METACALL_BUFFER	  = 8,
20   METACALL_ARRAY	  = 9,
21   METACALL_MAP		  = 10,
22   METACALL_PTR		  = 11,
23   METACALL_FUTURE	  = 12,
24   METACALL_FUNCTION	= 13,
25   METACALL_NULL		  = 14,
26   METACALL_SIZE,
27   METACALL_INVALID
28 }
29 
30 extern(C) {
31   int metacall_initialize();
32   int metacall_destroy();
33   int metacall_load_from_file(const(char*) tag, const(char**) paths, size_t size, void** handle);
34   void* metacall_value_create_bool(int b);
35   void* metacall_value_create_char(char c);
36   void* metacall_value_create_short(short s);
37   void* metacall_value_create_int(int i);
38   void* metacall_value_create_long(long l);
39   void* metacall_value_create_float(float f);
40   void* metacall_value_create_double(double d);
41   void* metacall_value_create_string(const(char*) str, size_t length);
42   void* metacall_value_create_buffer(const(void*) buffer, size_t size);
43   void* metacall_value_create_array(const(void**) values, size_t size);
44   void* metacall_value_create_ptr(const(void*) ptr);
45   void* metacall_value_create_null();
46   char metacall_value_to_char(void* v);
47   short metacall_value_to_short(void* v);
48   int metacall_value_to_int(void* v);
49   long metacall_value_to_long(void* v);
50   float metacall_value_to_float(void* v);
51   double metacall_value_to_double(void* v);
52   void* metacall_value_to_ptr(void* v);
53   char* metacall_value_to_string(void* v);
54   void metacall_value_destroy(void*);
55   metacall_value_id_enum metacall_value_id(void* v);
56   void* metacall(const(char*) name, ...);
57   void* metacallv(const(char*) name, void** args);
58 }
59 
60 
61 
62 class MetaCallException : Exception {
63   mixin basicExceptionCtors;
64 }
65 
66 int dmetacall_initialize() {
67   if(metacall_initialize() != 0) {
68     throw new MetaCallException("failed to initialize MetaCall");
69   }
70   return 0;
71 }
72 
73 int dmetacall_load_from_file(const char[] tag, string[] paths) {
74   char*[] good_paths;
75   good_paths.length += paths.length;
76   for(int i = 0; i < paths.length; i++) {
77     good_paths[i] = cast(char*)paths[i].toStringz();
78   }
79   if(metacall_load_from_file(tag.ptr,cast(const(char**))good_paths,paths.length,null) != 0) {
80     throw new MetaCallException("MetaCall failed to load script(s)");
81   }
82   return 0;
83 }
84 
85 Variant dmetacall(T...)(string name,T args) {
86   void*[args.length] values;
87   int i = 0;
88   foreach(arg; args) {
89     static if(is(typeof(arg) == bool)) {
90       values[i] = metacall_value_create_bool(cast(int)arg);
91     } else static if(is(typeof(arg) == char)) {
92       values[i] = metacall_value_create_char(arg);
93     } else static if(is(typeof(arg) == short)) {
94       values[i] = metacall_value_create_short(arg);
95     } else static if(is(typeof(arg) == int)) {
96       values[i] = metacall_value_create_int(arg);
97     } else static if(is(typeof(arg) == long)) {
98       values[i] = metacall_value_create_long(arg);
99     } else static if(is(typeof(arg) == float)) {
100       values[i] = metacall_value_create_float(arg);
101     } else static if(is(typeof(arg) == double)) {
102       values[i] = metacall_value_create_double(arg);
103     } else static if(is(typeof(arg) == string) || is(typeof(arg) == char[])) {
104       values[i] = metacall_value_create_string(arg.ptr,arg.sizeof);
105     /*} else static if(is(typeof(arg) == ubyte[]) || is(typeof(arg) == char[]) || is(typeof(arg) == char*)) {
106       values[i] = metacall_value_create_buffer(cast(const(void*))arg.ptr,arg.sizeof);*/
107     } else static if(is(typeof(arg) == void*)) {
108       values[i] = metacall_value_create_ptr(arg);
109     }
110     i++;
111   }
112 
113   void* ret = metacallv(name.toStringz(),cast(void**)values.ptr);
114   foreach(void* value; values) {
115     metacall_value_destroy(value);
116   }
117 
118   Variant returnvariant;
119   switch(metacall_value_id(ret)) {
120     case metacall_value_id_enum.METACALL_CHAR:
121       returnvariant = metacall_value_to_char(ret);
122       break;
123     case metacall_value_id_enum.METACALL_SHORT:
124       returnvariant = metacall_value_to_short(ret);
125       break;
126     case metacall_value_id_enum.METACALL_INT:
127       returnvariant = metacall_value_to_int(ret);
128       break;
129     case metacall_value_id_enum.METACALL_LONG:
130       returnvariant = metacall_value_to_long(ret);
131       break;
132     case metacall_value_id_enum.METACALL_FLOAT:
133       returnvariant = metacall_value_to_float(ret);
134       break;
135     case metacall_value_id_enum.METACALL_DOUBLE:
136       returnvariant = metacall_value_to_double(ret);
137       break;
138     case metacall_value_id_enum.METACALL_STRING:
139       returnvariant = metacall_value_to_string(ret).fromStringz();
140       break;
141     case metacall_value_id_enum.METACALL_PTR:
142       returnvariant = metacall_value_to_ptr(ret);
143       break;
144     case metacall_value_id_enum.METACALL_NULL:
145       returnvariant = null;
146       break;
147     default:
148       returnvariant = null;
149       break;
150   }
151   return returnvariant;
152 }
153 
154 int dmetacall_destroy() {
155   return metacall_destroy();
156 }