strname.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. #include "pocketpy/common/strname.h"
  2. #include "pocketpy/common/smallmap.h"
  3. #include "pocketpy/common/utils.h"
  4. #include "pocketpy/common/vector.h"
  5. #include "pocketpy/pocketpy.h"
  6. #include <stdio.h>
  7. // TODO: use a more efficient data structure
  8. static c11_smallmap_s2n _interned;
  9. static c11_vector /*T=char* */ _r_interned;
  10. static bool _initialized = false;
  11. void pk_StrName__initialize() {
  12. if(_initialized) return;
  13. c11_smallmap_s2n__ctor(&_interned);
  14. for(int i = 0; i < _r_interned.count; i++) {
  15. free(c11__at(char*, &_r_interned, i));
  16. }
  17. c11_vector__ctor(&_r_interned, sizeof(c11_sv));
  18. _initialized = true;
  19. #define MAGIC_METHOD(x) assert(x == py_name(#x));
  20. #include "pocketpy/xmacros/magics.h"
  21. #undef MAGIC_METHOD
  22. // print all names
  23. for(int i = 0; i < _interned.count; i++) {
  24. printf("%d: %s\n", i + 1, c11__getitem(char*, &_r_interned, i));
  25. }
  26. }
  27. void pk_StrName__finalize() {
  28. if(!_initialized) return;
  29. // free all char*
  30. for(int i = 0; i < _r_interned.count; i++) {
  31. free(c11__getitem(char*, &_r_interned, i));
  32. }
  33. c11_smallmap_s2n__dtor(&_interned);
  34. c11_vector__dtor(&_r_interned);
  35. }
  36. uint16_t pk_StrName__map(const char* name) {
  37. return pk_StrName__map2((c11_sv){name, strlen(name)});
  38. }
  39. uint16_t pk_StrName__map2(c11_sv name) {
  40. // TODO: PK_GLOBAL_SCOPE_LOCK()
  41. if(!_initialized) {
  42. pk_StrName__initialize(); // lazy init
  43. }
  44. uint16_t index = c11_smallmap_s2n__get(&_interned, name, 0);
  45. if(index != 0) return index;
  46. // generate new index
  47. if(_interned.count > 65530) { PK_FATAL_ERROR("StrName index overflow\n"); }
  48. // NOTE: we must allocate the string in the heap so iterators are not invalidated
  49. char* p = malloc(name.size + 1);
  50. memcpy(p, name.data, name.size);
  51. p[name.size] = '\0';
  52. c11_vector__push(char*, &_r_interned, p);
  53. index = _r_interned.count; // 1-based
  54. // save to _interned
  55. c11_smallmap_s2n__set(&_interned, (c11_sv){p, name.size}, index);
  56. assert(_interned.count == _r_interned.count);
  57. return index;
  58. }
  59. const char* pk_StrName__rmap(uint16_t index) {
  60. assert(_initialized);
  61. assert(index > 0 && index <= _interned.count);
  62. return c11__getitem(char*, &_r_interned, index - 1);
  63. }
  64. c11_sv pk_StrName__rmap2(uint16_t index) {
  65. const char* p = pk_StrName__rmap(index);
  66. return (c11_sv){p, strlen(p)};
  67. }
  68. py_Name py_name(const char* name) {
  69. return pk_StrName__map(name);
  70. }
  71. const char* py_name2str(py_Name name) {
  72. return pk_StrName__rmap(name);
  73. }
  74. bool py_ismagicname(py_Name name){
  75. return name <= __missing__;
  76. }