strname.c 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  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. void py_Name__initialize() {
  11. c11_smallmap_s2n__ctor(&_interned);
  12. for(int i = 0; i < _r_interned.length; i++) {
  13. free(c11__at(char*, &_r_interned, i));
  14. }
  15. c11_vector__ctor(&_r_interned, sizeof(c11_sv));
  16. #define MAGIC_METHOD(x) \
  17. if(x != py_name(#x)) abort();
  18. #include "pocketpy/xmacros/magics.h"
  19. #undef MAGIC_METHOD
  20. }
  21. void py_Name__finalize() {
  22. // free all char*
  23. for(int i = 0; i < _r_interned.length; i++) {
  24. free(c11__getitem(char*, &_r_interned, i));
  25. }
  26. c11_smallmap_s2n__dtor(&_interned);
  27. c11_vector__dtor(&_r_interned);
  28. }
  29. py_Name py_name(const char* name) { return py_namev((c11_sv){name, strlen(name)}); }
  30. py_Name py_namev(c11_sv name) {
  31. // TODO: PK_GLOBAL_SCOPE_LOCK()
  32. uint16_t index = c11_smallmap_s2n__get(&_interned, name, 0);
  33. if(index != 0) return index;
  34. // generate new index
  35. if(_interned.length > 65530) c11__abort("py_Name index overflow");
  36. // NOTE: we must allocate the string in the heap so iterators are not invalidated
  37. char* p = PK_MALLOC(name.size + 1);
  38. memcpy(p, name.data, name.size);
  39. p[name.size] = '\0';
  40. c11_vector__push(char*, &_r_interned, p);
  41. index = _r_interned.length; // 1-based
  42. // save to _interned
  43. c11_smallmap_s2n__set(&_interned, (c11_sv){p, name.size}, index);
  44. assert(_interned.length == _r_interned.length);
  45. return index;
  46. }
  47. const char* py_name2str(py_Name index) {
  48. assert(index > 0 && index <= _interned.length);
  49. return c11__getitem(char*, &_r_interned, index - 1);
  50. }
  51. c11_sv py_name2sv(py_Name index) {
  52. assert(index > 0 && index <= _interned.length);
  53. const char* p = py_name2str(index);
  54. return (c11_sv){p, strlen(p)};
  55. }