/lib/lua_extensions/pbc/register.c

https://bitbucket.org/kevin_sun/sanguo_client · C · 337 lines · 291 code · 40 blank · 6 comment · 52 complexity · 7b7696cc4efcd1691a8b30e9d891faf9 MD5 · raw file

  1. #include "pbc.h"
  2. #include "proto.h"
  3. #include "alloc.h"
  4. #include "map.h"
  5. #include "bootstrap.h"
  6. #include "context.h"
  7. #include "stringpool.h"
  8. #include <string.h>
  9. #include <stdlib.h>
  10. static const char *
  11. _concat_name(struct _stringpool *p , const char *prefix , int prefix_sz , const char *name , int name_sz, int *sz) {
  12. if (prefix_sz == 0) {
  13. if (sz) {
  14. *sz = name_sz;
  15. }
  16. return _pbcS_build(p , name, name_sz);
  17. }
  18. char temp[name_sz + prefix_sz + 2];
  19. memcpy(temp,prefix,prefix_sz);
  20. temp[prefix_sz] = '.';
  21. memcpy(temp+prefix_sz+1,name,name_sz);
  22. temp[name_sz + prefix_sz + 1] = '\0';
  23. if (sz) {
  24. *sz = name_sz + prefix_sz + 1;
  25. }
  26. return _pbcS_build(p , temp, name_sz + prefix_sz + 1);
  27. }
  28. static void
  29. _register_enum(struct pbc_env *p, struct _stringpool *pool, struct pbc_rmessage * enum_type, const char *prefix, int prefix_sz) {
  30. int field_count = pbc_rmessage_size(enum_type, "value");
  31. struct map_kv *table = malloc(field_count * sizeof(struct map_kv));
  32. int i;
  33. for (i=0;i<field_count;i++) {
  34. struct pbc_rmessage * value = pbc_rmessage_message(enum_type, "value", i);
  35. int enum_name_sz;
  36. const char *enum_name = pbc_rmessage_string(value , "name" , 0 , &enum_name_sz);
  37. table[i].pointer = (void *)_pbcS_build(pool, enum_name , enum_name_sz);
  38. table[i].id = pbc_rmessage_integer(value , "number", 0 , 0);
  39. }
  40. int name_sz;
  41. const char * name = pbc_rmessage_string(enum_type, "name", 0 , &name_sz);
  42. const char *temp = _concat_name(pool, prefix , prefix_sz , name , name_sz, NULL);
  43. _pbcP_push_enum(p,temp,table,field_count);
  44. free(table);
  45. }
  46. static void
  47. _set_default(struct _stringpool *pool, struct _field *f , int ptype, const char *value, int sz) {
  48. if (value == NULL || sz == 0) {
  49. if (f->type == PTYPE_STRING || f->type == PTYPE_BYTES) {
  50. f->default_v->s.str = "";
  51. f->default_v->s.len = 0;
  52. } else {
  53. f->default_v->integer.low = 0;
  54. f->default_v->integer.hi = 0;
  55. }
  56. return;
  57. }
  58. switch (f->type) {
  59. case PTYPE_DOUBLE:
  60. case PTYPE_FLOAT:
  61. f->default_v->real = strtod(value,NULL);
  62. break;
  63. case PTYPE_STRING:
  64. f->default_v->s.str = _pbcS_build(pool, value , sz);
  65. f->default_v->s.len = sz;
  66. break;
  67. case PTYPE_ENUM:
  68. // enum default value will be converted to f->default_v->e in bootstrap.c : set_field_one()
  69. f->default_v->s.str = value;
  70. f->default_v->s.len = sz;
  71. break;
  72. case PTYPE_BOOL:
  73. if (strcmp(value,"true") == 0) {
  74. f->default_v->integer.low = 1;
  75. } else {
  76. f->default_v->integer.low = 0;
  77. }
  78. f->default_v->integer.hi = 0;
  79. break;
  80. case PTYPE_UINT64:
  81. case PTYPE_INT64:
  82. case PTYPE_SFIXED64:
  83. case PTYPE_SINT64: {
  84. long long v = strtoll(value, NULL, 10);
  85. f->default_v->integer.low = (long) v;
  86. f->default_v->integer.hi = (long)(v >> 32);
  87. break;
  88. }
  89. case PTYPE_INT32:
  90. case PTYPE_FIXED32:
  91. case PTYPE_SFIXED32:
  92. case PTYPE_SINT32: {
  93. int low = strtol(value, NULL, 10);
  94. f->default_v->integer.low = low;
  95. if (low < 0) {
  96. f->default_v->integer.hi = -1;
  97. } else {
  98. f->default_v->integer.hi = 0;
  99. }
  100. break;
  101. }
  102. case PTYPE_UINT32:
  103. f->default_v->integer.low = strtoul(value, NULL, 10);
  104. f->default_v->integer.hi = 0;
  105. break;
  106. case PTYPE_BYTES:
  107. case PTYPE_MESSAGE:
  108. // bytes and message types have no default value
  109. f->default_v->m.buffer = 0;
  110. f->default_v->m.len = 0;
  111. break;
  112. default:
  113. f->default_v->integer.low = 0;
  114. f->default_v->integer.hi = 0;
  115. break;
  116. }
  117. }
  118. static void
  119. _register_field(struct pbc_rmessage * field, struct _field * f, struct _stringpool *pool) {
  120. f->id = pbc_rmessage_integer(field, "number", 0 , 0);
  121. f->type = pbc_rmessage_integer(field, "type", 0 , 0); // enum
  122. f->label = pbc_rmessage_integer(field, "label", 0, 0) - 1; // LABEL_OPTIONAL = 0
  123. if (pbc_rmessage_size(field , "options") > 0) {
  124. struct pbc_rmessage * options = pbc_rmessage_message(field, "options" , 0);
  125. int packed = pbc_rmessage_integer(options , "packed" , 0 , NULL);
  126. if (packed) {
  127. f->label = LABEL_PACKED;
  128. }
  129. }
  130. f->type_name.n = pbc_rmessage_string(field, "type_name", 0 , NULL) +1; // abandon prefix '.'
  131. int vsz;
  132. const char * default_value = pbc_rmessage_string(field, "default_value", 0 , &vsz);
  133. _set_default(pool , f , f->type, default_value , vsz);
  134. }
  135. static void
  136. _register_extension(struct pbc_env *p, struct _stringpool *pool , const char * prefix, int prefix_sz, struct pbc_rmessage * msg, pbc_array queue) {
  137. int extension_count = pbc_rmessage_size(msg , "extension");
  138. if (extension_count <= 0)
  139. return;
  140. int i;
  141. const char * last = NULL;
  142. for (i=0;i<extension_count;i++) {
  143. struct pbc_rmessage * extension = pbc_rmessage_message(msg, "extension", i);
  144. int field_name_sz = 0;
  145. struct _field f;
  146. const char * field_name = pbc_rmessage_string(extension , "name" , 0, &field_name_sz);
  147. f.name = _concat_name(pool, prefix, prefix_sz, field_name, field_name_sz, NULL);
  148. _register_field(extension, &f , pool);
  149. const char * extendee = pbc_rmessage_string(extension , "extendee" , 0, NULL);
  150. _pbcP_push_message(p, extendee + 1 , &f , queue);
  151. if (last == NULL) {
  152. last = extendee;
  153. } else if (strcmp(extendee,last) != 0) {
  154. _pbcP_init_message(p, last+1);
  155. last = extendee;
  156. }
  157. }
  158. _pbcP_init_message(p, last+1);
  159. }
  160. static void
  161. _register_message(struct pbc_env *p, struct _stringpool *pool, struct pbc_rmessage * message_type, const char *prefix, int prefix_sz, pbc_array queue) {
  162. int name_sz;
  163. const char * name = pbc_rmessage_string(message_type, "name", 0 , &name_sz);
  164. int sz = 0;
  165. const char *temp = _concat_name(pool, prefix , prefix_sz , name , name_sz, &sz);
  166. int field_count = pbc_rmessage_size(message_type, "field");
  167. int i;
  168. for (i=0;i<field_count;i++) {
  169. struct pbc_rmessage * field = pbc_rmessage_message(message_type, "field" , i);
  170. struct _field f;
  171. int field_name_sz;
  172. const char * field_name = pbc_rmessage_string(field, "name", 0 , &field_name_sz);
  173. f.name = _pbcS_build(pool,field_name,field_name_sz);
  174. _register_field(field, &f , pool);
  175. _pbcP_push_message(p, temp , &f , queue);
  176. }
  177. _pbcP_init_message(p, temp);
  178. _register_extension(p, pool, temp, sz,message_type, queue);
  179. // nested enum
  180. int enum_count = pbc_rmessage_size(message_type, "enum_type");
  181. for (i=0;i<enum_count;i++) {
  182. struct pbc_rmessage * enum_type = pbc_rmessage_message(message_type, "enum_type", i);
  183. _register_enum(p, pool, enum_type, temp, sz);
  184. }
  185. // nested type
  186. int message_count = pbc_rmessage_size(message_type, "nested_type");
  187. for (i=0;i<message_count;i++) {
  188. struct pbc_rmessage * nested_type = pbc_rmessage_message(message_type, "nested_type", i);
  189. _register_message(p, pool, nested_type, temp, sz, queue);
  190. }
  191. }
  192. static void
  193. _register(struct pbc_env *p, struct pbc_rmessage * file, struct _stringpool *pool) {
  194. int package_sz;
  195. const char *package = pbc_rmessage_string(file, "package", 0, &package_sz);
  196. pbc_array queue;
  197. _pbcA_open(queue);
  198. int enum_count = pbc_rmessage_size(file, "enum_type");
  199. int i;
  200. for (i=0;i<enum_count;i++) {
  201. struct pbc_rmessage * enum_type = pbc_rmessage_message(file, "enum_type", i);
  202. _register_enum(p, pool , enum_type, package, package_sz);
  203. }
  204. int message_count = pbc_rmessage_size(file, "message_type");
  205. for (i=0;i<message_count;i++) {
  206. struct pbc_rmessage * message_type = pbc_rmessage_message(file, "message_type", i);
  207. _register_message(p, pool, message_type, package, package_sz, queue);
  208. }
  209. _register_extension(p, pool, package, package_sz, file , queue);
  210. _pbcB_register_fields(p, queue);
  211. _pbcA_close(queue);
  212. }
  213. #define CHECK_FILE_OK 0
  214. #define CHECK_FILE_EXIST 1
  215. #define CHECK_FILE_DEPENDENCY 2
  216. static int
  217. _check_file_name(struct pbc_env * p , struct pbc_rmessage * file, const char ** fname) {
  218. const char * filename = pbc_rmessage_string(file, "name", 0, NULL);
  219. // printf("reg :%s\n",filename);
  220. if (_pbcM_sp_query(p->files, filename)) {
  221. return CHECK_FILE_EXIST;
  222. }
  223. int sz = pbc_rmessage_size(file, "dependency");
  224. int i;
  225. for (i=0;i<sz;i++) {
  226. const char *dname = pbc_rmessage_string(file,"dependency",i,NULL);
  227. // printf("dependency :%s\n",dname);
  228. if (_pbcM_sp_query(p->files, dname) == NULL) {
  229. return CHECK_FILE_DEPENDENCY;
  230. }
  231. }
  232. *fname = filename;
  233. return CHECK_FILE_OK;
  234. }
  235. static int
  236. _register_no_dependency(struct pbc_env * p,struct pbc_rmessage ** files , int n ) {
  237. int r = 0;
  238. int i;
  239. for (i=0;i<n;i++) {
  240. if (files[i] == NULL)
  241. continue;
  242. const char *filename = NULL;
  243. int err = _check_file_name(p, files[i], &filename);
  244. switch(err) {
  245. case CHECK_FILE_EXIST:
  246. break;
  247. case CHECK_FILE_DEPENDENCY:
  248. ++r;
  249. break;
  250. case CHECK_FILE_OK: {
  251. struct _stringpool *pool = _pbcS_new();
  252. filename = _pbcS_build(pool, filename , strlen(filename));
  253. _pbcM_sp_insert(p->files , filename, pool);
  254. _register(p,files[i],pool);
  255. files[i] = NULL;
  256. }
  257. break;
  258. }
  259. }
  260. return r;
  261. }
  262. int
  263. pbc_register(struct pbc_env * p, struct pbc_slice *slice) {
  264. struct pbc_rmessage * message = pbc_rmessage_new(p, "google.protobuf.FileDescriptorSet", slice);
  265. if (message == NULL) {
  266. p->lasterror = "register open google.protobuf.FileDescriptorSet fail";
  267. return 1;
  268. }
  269. int n = pbc_rmessage_size(message, "file");
  270. struct pbc_rmessage * files[n];
  271. int i;
  272. if (n == 0) {
  273. p->lasterror = "register empty";
  274. goto _error;
  275. }
  276. for (i=0;i<n;i++) {
  277. files[i] = pbc_rmessage_message(message, "file", i);
  278. if (files[i] == NULL) {
  279. p->lasterror = "register open fail";
  280. goto _error;
  281. }
  282. }
  283. int r = n;
  284. do {
  285. int rr = _register_no_dependency(p,files , n);
  286. if (rr == r) {
  287. p->lasterror = "register dependency error";
  288. goto _error;
  289. }
  290. r = rr;
  291. } while (r>0);
  292. pbc_rmessage_delete(message);
  293. return 0;
  294. _error:
  295. pbc_rmessage_delete(message);
  296. return 1;
  297. }