dictmaptree.h 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. /*
  2. * Copyright © 2023 Michael Smith <mikesmiffy128@gmail.com>
  3. *
  4. * Permission to use, copy, modify, and/or distribute this software for any
  5. * purpose with or without fee is hereby granted, provided that the above
  6. * copyright notice and this permission notice appear in all copies.
  7. *
  8. * THE SOFTWARE IS PROVIDED “AS IS” AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
  9. * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
  10. * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
  11. * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
  12. * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  13. * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  14. * PERFORMANCE OF THIS SOFTWARE.
  15. */
  16. #ifndef INC_DICTMAPTREE_H
  17. #define INC_DICTMAPTREE_H
  18. #include "engineapi.h"
  19. #include "intdefs.h"
  20. /*
  21. * Valve's dict/map/tree structures come in various shapes and sizes, so here we
  22. * do the generic macro thing for future-proofing. For now we just define a
  23. * CUtlDict (map with string keys) of pointers, with ushort indices, which is
  24. * sufficient for server entity factory lookup, and probably some other stuff.
  25. * Functions for actually modifying the dicts/maps/trees aren't implemented.
  26. */
  27. #define DECL_CUTLRBTREE_NODE(name, ktype, vtype, idxtype) \
  28. typedef typeof(ktype) _cutlrbtree_##name##_key; \
  29. typedef typeof(vtype) _cutlrbtree_##name##_val; \
  30. typedef typeof(idxtype) _cutlrbtree_##name##_idx; \
  31. struct name { \
  32. struct { \
  33. _cutlrbtree_##name##_idx l, r, p, tags; \
  34. } links; \
  35. _cutlrbtree_##name##_key k; \
  36. _cutlrbtree_##name##_val v; \
  37. };
  38. #define DEF_CUTLRBTREE(name, nodetype) \
  39. struct name { \
  40. bool (*cmp)(const _cutlrbtree_##nodetype##_key *, \
  41. const _cutlrbtree_##nodetype##_key *); \
  42. struct CUtlMemory elems; \
  43. _cutlrbtree_##nodetype##_idx root, count, firstfree, lastalloc; \
  44. struct nodetype *nodes; \
  45. }; \
  46. \
  47. static _cutlrbtree_##nodetype##_idx name##_find(const struct name *rb, \
  48. const _cutlrbtree_##nodetype##_key k) { \
  49. _cutlrbtree_##nodetype##_idx idx = rb->root; \
  50. while (idx != (_cutlrbtree_##nodetype##_idx)-1) { \
  51. struct nodetype *nodes = rb->elems.mem; \
  52. if (rb->cmp(&k, &nodes[idx].k)) idx = nodes[idx].links.l; \
  53. else if (rb->cmp(&nodes[idx].k, &k)) idx = nodes[idx].links.r; \
  54. else break; \
  55. } \
  56. return idx; \
  57. } \
  58. \
  59. static inline _cutlrbtree_##nodetype##_val name##_findval(const struct name *rb, \
  60. const _cutlrbtree_##nodetype##_key k) { \
  61. const _cutlrbtree_##nodetype##_idx idx = name##_find(rb, k); \
  62. if (idx == (_cutlrbtree_##nodetype##_idx)-1) { \
  63. return (_cutlrbtree_CUtlDict_node_p_ushort_val){0}; \
  64. } \
  65. struct nodetype *nodes = rb->elems.mem; \
  66. return nodes[idx].v; \
  67. }
  68. DECL_CUTLRBTREE_NODE(CUtlDict_node_p_ushort, const char *, void *, ushort)
  69. DEF_CUTLRBTREE(CUtlDict_p_ushort, CUtlDict_node_p_ushort)
  70. #endif
  71. // vi: sw=4 ts=4 noet tw=80 cc=80