blitz_enum.c 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. #include "blitz.h"
  2. BBArray * bbEnumValues(BBEnum * bbEnum) {
  3. BBArray * values = &bbEmptyArray;
  4. int size = 4;
  5. char t = bbEnum->type[0];
  6. switch( t ) {
  7. case 'b':size=1;break;
  8. case 's':size=2;break;
  9. case 'l':size=8;break;
  10. case 'y':size=8;break;
  11. case 'z':size=sizeof(BBSIZET);break;
  12. }
  13. values = bbArrayNew1DStruct(bbEnum->atype, bbEnum->length, size, 0);
  14. char * p = BBARRAYDATA(values, 0);
  15. memcpy(p, bbEnum->values, size * bbEnum->length);
  16. return values;
  17. }
  18. static BBString * bbAppend(BBString * x, BBString * y) {
  19. int n = x != &bbEmptyString;
  20. int len=x->length+y->length + n;
  21. BBString *t=bbStringNew(len);
  22. memcpy( t->buf,x->buf,x->length*sizeof(BBChar) );
  23. if (n) {
  24. t->buf[x->length] = '|';
  25. }
  26. memcpy( t->buf+x->length+n,y->buf,y->length*sizeof(BBChar) );
  27. return t;
  28. }
  29. #define ENUM_TO_STRING(type,chr)\
  30. BBString * bbEnumToString_##chr(BBEnum * bbEnum, type ordinal) {\
  31. type * value = (type*)bbEnum->values;\
  32. int flags = bbEnum->flags;\
  33. BBString * val = &bbEmptyString;\
  34. for (int i = 0; i < bbEnum->length; i++) {\
  35. if (flags) {\
  36. type v = *value++;\
  37. if (v == ordinal || (v & ordinal && v == (v & ordinal))) {\
  38. val = bbAppend(val, bbEnum->names[i]);\
  39. }\
  40. } else {\
  41. if (*value++ == ordinal) {\
  42. return bbEnum->names[i];\
  43. }\
  44. }\
  45. }\
  46. return val;\
  47. }
  48. ENUM_TO_STRING(BBBYTE,b)
  49. ENUM_TO_STRING(BBSHORT,s)
  50. ENUM_TO_STRING(BBINT,i)
  51. ENUM_TO_STRING(BBUINT,u)
  52. ENUM_TO_STRING(BBLONG,l)
  53. ENUM_TO_STRING(BBULONG,y)
  54. ENUM_TO_STRING(BBSIZET,t)
  55. #define TRY_ENUM_CONVERT(type,chr)\
  56. int bbEnumTryConvert_##chr(BBEnum * bbEnum, type ordinalValue, type * ordinalResult) {\
  57. type * value = (type*)bbEnum->values;\
  58. int i;\
  59. if (bbEnum->flags) {\
  60. if (ordinalValue == 0) {\
  61. for (i = 0; i < bbEnum->length; i++) {\
  62. if (*value++ == 0) {\
  63. return 1;\
  64. }\
  65. }\
  66. return 0;\
  67. }\
  68. type val = ordinalValue;\
  69. for (i = 0; i < bbEnum->length; i++) {\
  70. val ^= *value++;\
  71. }\
  72. if (val == 0) {\
  73. *ordinalResult = ordinalValue;\
  74. return 1;\
  75. }\
  76. } else {\
  77. if (ordinalValue < *value || ordinalValue > ((type*)bbEnum->values)[bbEnum->length - 1]) {\
  78. return 0;\
  79. }\
  80. for (i = 0; i < bbEnum->length; i++) {\
  81. if (*value++ == ordinalValue) {\
  82. *ordinalResult = ordinalValue;\
  83. return 1;\
  84. }\
  85. }\
  86. }\
  87. return 0;\
  88. }
  89. TRY_ENUM_CONVERT(BBBYTE,b)
  90. TRY_ENUM_CONVERT(BBSHORT,s)
  91. TRY_ENUM_CONVERT(BBINT,i)
  92. TRY_ENUM_CONVERT(BBUINT,u)
  93. TRY_ENUM_CONVERT(BBLONG,l)
  94. TRY_ENUM_CONVERT(BBULONG,y)
  95. TRY_ENUM_CONVERT(BBSIZET,t)
  96. #ifndef NDEBUG
  97. #define ENUM_CAST(type,chr)\
  98. type bbEnumCast_##chr(BBEnum * bbEnum, type ordinalValue) {\
  99. type result;\
  100. if (!bbEnumTryConvert_##chr(bbEnum, ordinalValue, &result)) {\
  101. brl_blitz_InvalidEnumError();\
  102. }\
  103. return result;\
  104. }
  105. ENUM_CAST(BBBYTE,b)
  106. ENUM_CAST(BBSHORT,s)
  107. ENUM_CAST(BBINT,i)
  108. ENUM_CAST(BBUINT,u)
  109. ENUM_CAST(BBLONG,l)
  110. ENUM_CAST(BBULONG,y)
  111. ENUM_CAST(BBSIZET,t)
  112. #endif
  113. struct enum_info_node {
  114. struct avl_root link;
  115. BBEnum * bbEnum;
  116. };
  117. static struct avl_root *enum_info_root = 0;
  118. static int enum_info_node_compare(const void *x, const void *y) {
  119. struct enum_info_node * node_x = (struct enum_info_node *)x;
  120. struct enum_info_node * node_y = (struct enum_info_node *)y;
  121. return strcmp(node_x->bbEnum->atype, node_y->bbEnum->atype);
  122. }
  123. void bbEnumRegister( BBEnum *p, BBDebugScope *s ) {
  124. bbObjectRegisterEnum(s);
  125. struct enum_info_node * node = (struct enum_info_node *)malloc(sizeof(struct enum_info_node));
  126. node->bbEnum = p;
  127. struct enum_info_node * old_node = (struct enum_info_node *)avl_map(&node->link, enum_info_node_compare, &enum_info_root);
  128. if (&node->link != &old_node->link) {
  129. // this object already exists here...
  130. // delete the new node, since we don't need it
  131. // note : should never happen as enums should only ever be registered once.
  132. free(node);
  133. }
  134. }
  135. BBEnum * bbEnumGetInfo( char * name ) {
  136. // create something to look up
  137. struct enum_info_node node;
  138. BBEnum bbEnum;
  139. bbEnum.atype = name;
  140. node.bbEnum = &bbEnum;
  141. struct enum_info_node * found = (struct enum_info_node *)tree_search((struct tree_root_np *)&node, enum_info_node_compare, (struct tree_root_np *)enum_info_root);
  142. if (found) {
  143. return found->bbEnum;
  144. }
  145. return 0;
  146. }