blitz_enum.c 4.1 KB

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