The Sol Programming Language!
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

cdata.c 8.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. #include "cdata.h"
  2. #include <stdint.h>
  3. #include <string.h>
  4. #include <stdlib.h>
  5. #define AS(arg, tp) ((tp *) (arg))
  6. #define AT(loc, tp, off) (*((tp *) ((char *) loc) + off))
  7. #define NEW(tp) malloc(sizeof(tp))
  8. #define ENSURE() if(!sol_cstruct_is_init) sol_cstruct_init()
  9. int sol_cstruct_is_init = 0;
  10. sol_ops_t sol_cstruct_spec_ops;
  11. sol_ops_t sol_cstruct_ops;
  12. void sol_cstruct_init(void) {
  13. sol_ops_init(&sol_cstruct_spec_ops);
  14. sol_ops_init(&sol_cstruct_ops);
  15. sol_cstruct_ops.index = sol_f_cstruct_index;
  16. sol_cstruct_ops.setindex = sol_f_cstruct_setindex;
  17. sol_cstruct_is_init = 1;
  18. }
  19. sol_object_t *sol_new_cstruct_specs(sol_state_t *state) {
  20. return sol_new_map(state);
  21. }
  22. sol_object_t *sol_new_cstruct_spec(sol_state_t *state, sol_spec_t type) {
  23. ENSURE();
  24. sol_object_t *res = sol_new_cdata(state, NEW(sol_memspec_t), &sol_cstruct_spec_ops);
  25. AS(res->cdata, sol_memspec_t)->type = type;
  26. return res;
  27. }
  28. void sol_cstruct_add_member(sol_state_t *state, sol_object_t *specs, sol_object_t *key, sol_memtype_t memtype, int offset) {
  29. sol_object_t *spec = sol_new_cstruct_spec(state, SOL_CS_MEMBER);
  30. AS(spec->cdata, sol_memspec_t)->memtype = memtype;
  31. AS(spec->cdata, sol_memspec_t)->offset = offset;
  32. sol_map_set(state, specs, key, spec);
  33. sol_obj_free(spec);
  34. }
  35. void sol_cstruct_add_member_name(sol_state_t *state, sol_object_t *specs, char *name, sol_memtype_t memtype, int offset) {
  36. sol_object_t *spec = sol_new_cstruct_spec(state, SOL_CS_MEMBER);
  37. AS(spec->cdata, sol_memspec_t)->memtype = memtype;
  38. AS(spec->cdata, sol_memspec_t)->offset = offset;
  39. sol_map_set_name(state, specs, name, spec);
  40. sol_obj_free(spec);
  41. }
  42. void sol_cstruct_add_pointer(sol_state_t *state, sol_object_t *pspecs, sol_object_t *key, sol_object_t *specs, int offset) {
  43. sol_object_t *spec = sol_new_cstruct_spec(state, SOL_CS_MEMBER);
  44. AS(spec->cdata, sol_memspec_t)->memtype = SOL_MT_PTR;
  45. AS(spec->cdata, sol_memspec_t)->offset = offset;
  46. AS(spec->cdata, sol_memspec_t)->specs = pspecs;
  47. sol_map_set(state, specs, key, spec);
  48. sol_obj_free(spec);
  49. }
  50. void sol_cstruct_add_pointer_name(sol_state_t *state, sol_object_t *pspecs, char *name, sol_object_t *specs, int offset) {
  51. sol_object_t *spec = sol_new_cstruct_spec(state, SOL_CS_MEMBER);
  52. AS(spec->cdata, sol_memspec_t)->memtype = SOL_MT_PTR;
  53. AS(spec->cdata, sol_memspec_t)->offset = offset;
  54. AS(spec->cdata, sol_memspec_t)->specs = pspecs;
  55. sol_map_set_name(state, specs, name, spec);
  56. sol_obj_free(spec);
  57. }
  58. void sol_cstruct_add_func(sol_state_t *state, sol_object_t *specs, sol_object_t *key, sol_cfunc_t cfunc) {
  59. sol_object_t *spec = sol_new_cstruct_spec(state, SOL_CS_CFUNC);
  60. AS(spec->cdata, sol_memspec_t)->cfunc = cfunc;
  61. sol_map_set(state, specs, key, spec);
  62. sol_obj_free(spec);
  63. }
  64. void sol_cstruct_add_func_name(sol_state_t *state, sol_object_t *specs, char *name, sol_cfunc_t cfunc) {
  65. sol_object_t *spec = sol_new_cstruct_spec(state, SOL_CS_CFUNC);
  66. AS(spec->cdata, sol_memspec_t)->cfunc = cfunc;
  67. sol_map_set_name(state, specs, name, spec);
  68. sol_obj_free(spec);
  69. }
  70. sol_object_t *sol_new_cstruct(sol_state_t *state, void *data, sol_object_t *specs) {
  71. sol_object_t *res = sol_new_cdata(state, NEW(sol_cstruct_t), &sol_cstruct_ops);
  72. AS(res->cdata, sol_cstruct_t)->data = data;
  73. AS(res->cdata, sol_cstruct_t)->specs = sol_incref(specs);
  74. return res;
  75. }
  76. sol_object_t *sol_f_cstruct_index(sol_state_t *state, sol_object_t *args) {
  77. sol_object_t *cstructobj = sol_list_get_index(state, args, 0), *idx = sol_list_get_index(state, args, 1);
  78. sol_cstruct_t *cstruct = cstructobj->cdata;
  79. sol_object_t *specobj = sol_map_get(state, cstruct->specs, idx), *res = NULL;
  80. sol_memspec_t *spec;
  81. char cbuf[2] = {0, 0};
  82. if(sol_is_none(state, specobj)) {
  83. sol_obj_free(specobj);
  84. sol_obj_free(idx);
  85. sol_obj_free(cstructobj);
  86. return sol_set_error_string(state, "No such CStruct index");
  87. }
  88. spec = specobj->cdata;
  89. switch(spec->type) {
  90. case SOL_CS_MEMBER:
  91. switch(spec->memtype) {
  92. case SOL_MT_INT:
  93. res = sol_new_int(state, AT(cstruct->data, int, spec->offset));
  94. break;
  95. case SOL_MT_INT8:
  96. res = sol_new_int(state, AT(cstruct->data, int8_t, spec->offset));
  97. break;
  98. case SOL_MT_INT16:
  99. res = sol_new_int(state, AT(cstruct->data, int16_t, spec->offset));
  100. break;
  101. case SOL_MT_INT32:
  102. res = sol_new_int(state, AT(cstruct->data, int32_t, spec->offset));
  103. break;
  104. case SOL_MT_INT64:
  105. res = sol_new_int(state, AT(cstruct->data, int64_t, spec->offset));
  106. break;
  107. case SOL_MT_UINT:
  108. res = sol_new_int(state, AT(cstruct->data, unsigned int, spec->offset));
  109. break;
  110. case SOL_MT_UINT8:
  111. res = sol_new_int(state, AT(cstruct->data, uint8_t, spec->offset));
  112. break;
  113. case SOL_MT_UINT16:
  114. res = sol_new_int(state, AT(cstruct->data, uint16_t, spec->offset));
  115. break;
  116. case SOL_MT_UINT32:
  117. res = sol_new_int(state, AT(cstruct->data, uint32_t, spec->offset));
  118. break;
  119. /*case SOL_MT_UINT64:
  120. res = sol_new_int(state, AT(cstruct->data, uint64_t, spec->offset));
  121. break;*/
  122. case SOL_MT_FLOAT:
  123. res = sol_new_float(state, AT(cstruct->data, float, spec->offset));
  124. break;
  125. case SOL_MT_DOUBLE:
  126. res = sol_new_float(state, AT(cstruct->data, double, spec->offset));
  127. break;
  128. case SOL_MT_CHAR:
  129. cbuf[0] = AT(cstruct->data, char, spec->offset);
  130. res = sol_new_string(state, cbuf);
  131. break;
  132. case SOL_MT_CSTR:
  133. res = sol_new_string(state, AT(cstruct->data, char *, spec->offset));
  134. break;
  135. case SOL_MT_CFUNC:
  136. res = sol_new_cfunc(state, AT(cstruct->data, sol_cfunc_t, spec->offset), NULL);
  137. break;
  138. case SOL_MT_PTR:
  139. res = sol_new_cstruct(state, AT(cstruct->data, void *, spec->offset), spec->specs);
  140. break;
  141. }
  142. break;
  143. case SOL_CS_CFUNC:
  144. res = sol_new_cfunc(state, spec->cfunc, NULL);
  145. break;
  146. }
  147. if(!res) {
  148. res = sol_incref(state->None);
  149. }
  150. return res;
  151. }
  152. sol_object_t *sol_f_cstruct_setindex(sol_state_t *state, sol_object_t *args) {
  153. sol_object_t *cstructobj = sol_list_get_index(state, args, 0), *idx = sol_list_get_index(state, args, 1), *val = sol_list_get_index(state, args, 2);
  154. sol_cstruct_t *cstruct = cstructobj->cdata;
  155. sol_object_t *specobj = sol_map_get(state, cstruct->specs, idx);
  156. sol_memspec_t *spec;
  157. char cbuf[2] = {0, 0};
  158. if(sol_is_none(state, specobj)) {
  159. sol_obj_free(specobj);
  160. sol_obj_free(idx);
  161. sol_obj_free(cstructobj);
  162. return sol_set_error_string(state, "No such CStruct index");
  163. }
  164. spec = specobj->cdata;
  165. switch(spec->type) {
  166. case SOL_CS_MEMBER:
  167. switch(spec->memtype) {
  168. case SOL_MT_INT:
  169. AT(cstruct->data, int, spec->offset) = sol_cast_int(state, val)->ival;
  170. break;
  171. case SOL_MT_INT8:
  172. AT(cstruct->data, int8_t, spec->offset) = sol_cast_int(state, val)->ival;
  173. break;
  174. case SOL_MT_INT16:
  175. AT(cstruct->data, int16_t, spec->offset) = sol_cast_int(state, val)->ival;
  176. break;
  177. case SOL_MT_INT32:
  178. AT(cstruct->data, int32_t, spec->offset) = sol_cast_int(state, val)->ival;
  179. break;
  180. case SOL_MT_INT64:
  181. AT(cstruct->data, int64_t, spec->offset) = sol_cast_int(state, val)->ival;
  182. break;
  183. case SOL_MT_UINT:
  184. AT(cstruct->data, unsigned int, spec->offset) = sol_cast_int(state, val)->ival;
  185. break;
  186. case SOL_MT_UINT8:
  187. AT(cstruct->data, uint8_t, spec->offset) = sol_cast_int(state, val)->ival;
  188. break;
  189. case SOL_MT_UINT16:
  190. AT(cstruct->data, uint16_t, spec->offset) = sol_cast_int(state, val)->ival;
  191. break;
  192. case SOL_MT_UINT32:
  193. AT(cstruct->data, uint32_t, spec->offset) = sol_cast_int(state, val)->ival;
  194. break;
  195. /*case SOL_MT_UINT64:
  196. AT(cstruct->data, uint64_t, spec->offset) = sol_cast_int(state, val)->ival;
  197. break;*/
  198. case SOL_MT_FLOAT:
  199. AT(cstruct->data, float, spec->offset) = sol_cast_float(state, val)->fval;
  200. break;
  201. case SOL_MT_DOUBLE:
  202. AT(cstruct->data, double, spec->offset) = sol_cast_float(state, val)->fval;
  203. break;
  204. case SOL_MT_CHAR:
  205. AT(cstruct->data, char, spec->offset) = sol_cast_string(state, val)->str[0];
  206. break;
  207. case SOL_MT_CSTR:
  208. AT(cstruct->data, char *, spec->offset) = strdup(sol_cast_string(state, val)->str);
  209. break;
  210. case SOL_MT_CFUNC:
  211. return sol_set_error_string(state, "Can't assign CFunc members");
  212. break;
  213. case SOL_MT_PTR:
  214. if(!sol_is_cdata(val) || spec->specs != AS(val->cdata, sol_cstruct_t)->specs) {
  215. return sol_set_error_string(state, "Invalid type for PTR assignment");
  216. }
  217. AT(cstruct->data, void *, spec->offset) = AS(val->cdata, sol_cstruct_t)->data;
  218. }
  219. break;
  220. case SOL_CS_CFUNC:
  221. return sol_set_error_string(state, "Can't assign CFunc members");
  222. break;
  223. }
  224. return sol_incref(state->None);
  225. }