name.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. #if PK_ENABLE_CUSTOM_SNAME == 0
  2. #include "pocketpy/common/name.h"
  3. #include "pocketpy/common/str.h"
  4. #include "pocketpy/pocketpy.h"
  5. #include "pocketpy/common/threads.h"
  6. #include <assert.h>
  7. typedef struct NameBucket NameBucket;
  8. typedef struct NameBucket {
  9. NameBucket* next;
  10. uint64_t hash;
  11. int size; // size of the data excluding the null-terminator
  12. char data[]; // null-terminated data
  13. } NameBucket;
  14. static struct {
  15. NameBucket* table[0x10000];
  16. #if PK_ENABLE_THREADS
  17. atomic_flag lock;
  18. #endif
  19. } pk_string_table;
  20. #define MAGIC_METHOD(x) py_Name x;
  21. #include "pocketpy/xmacros/magics.h"
  22. #undef MAGIC_METHOD
  23. void pk_names_initialize() {
  24. #define MAGIC_METHOD(x) x = py_name(#x);
  25. #include "pocketpy/xmacros/magics.h"
  26. #undef MAGIC_METHOD
  27. }
  28. void pk_names_finalize() {
  29. for(int i = 0; i < 0x10000; i++) {
  30. NameBucket* p = pk_string_table.table[i];
  31. while(p) {
  32. NameBucket* next = p->next;
  33. PK_FREE(p);
  34. p = next;
  35. }
  36. pk_string_table.table[i] = NULL;
  37. }
  38. }
  39. py_Name py_namev(c11_sv name) {
  40. #if PK_ENABLE_THREADS
  41. while(atomic_flag_test_and_set(&pk_string_table.lock)) {
  42. c11_thrd_yield();
  43. }
  44. #endif
  45. uint64_t hash = c11_sv__hash(name);
  46. int index = hash & 0xFFFF;
  47. NameBucket* p = pk_string_table.table[index];
  48. NameBucket* prev = NULL;
  49. bool found = false;
  50. while(p) {
  51. c11_sv p_sv = {p->data, p->size};
  52. if(p->hash == hash && c11__sveq(p_sv, name)) {
  53. found = true;
  54. break;
  55. }
  56. prev = p;
  57. p = p->next;
  58. }
  59. if(found) {
  60. #if PK_ENABLE_THREADS
  61. atomic_flag_clear(&pk_string_table.lock);
  62. #endif
  63. return (py_Name)p;
  64. }
  65. // generate new index
  66. NameBucket* bucket = PK_MALLOC(sizeof(NameBucket) + name.size + 1);
  67. bucket->next = NULL;
  68. bucket->hash = hash;
  69. bucket->size = name.size;
  70. memcpy(bucket->data, name.data, name.size);
  71. bucket->data[name.size] = '\0';
  72. if(prev == NULL) {
  73. pk_string_table.table[index] = bucket;
  74. } else {
  75. assert(prev->next == NULL);
  76. prev->next = bucket;
  77. }
  78. #if PK_ENABLE_THREADS
  79. atomic_flag_clear(&pk_string_table.lock);
  80. #endif
  81. return (py_Name)bucket;
  82. }
  83. c11_sv py_name2sv(py_Name index) {
  84. NameBucket* p = (NameBucket*)index;
  85. return (c11_sv){p->data, p->size};
  86. }
  87. py_Name py_name(const char* name) {
  88. c11_sv sv;
  89. sv.data = name;
  90. sv.size = strlen(name);
  91. return py_namev(sv);
  92. }
  93. const char* py_name2str(py_Name index) {
  94. NameBucket* p = (NameBucket*)index;
  95. return p->data;
  96. }
  97. #endif