keyset.pyx 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. from libc.string cimport memcmp
  2. from cpython.mem cimport PyMem_Malloc, PyMem_Realloc, PyMem_Free
  3. from lakesuperior.cy_includes cimport collections as cc
  4. from lakesuperior.model.base cimport (
  5. KeyIdx, Key, DoubleKey, TripleKey, Buffer
  6. )
  7. cdef class BaseKeyset:
  8. """
  9. Pre-allocated result set.
  10. Data in the set are stored as a 1D contiguous array of characters.
  11. Access to elements at an arbitrary index position is achieved by using the
  12. ``itemsize`` property multiplied by the index number.
  13. Key properties:
  14. ``ct``: number of elements in the set.
  15. ``itemsize``: size of each element, in bytes. All elements have the same
  16. size.
  17. ``size``: Total size, in bytes, of the data set. This is the product of
  18. ``itemsize`` and ``ct``.
  19. """
  20. def __cinit__(self, size_t ct):
  21. """
  22. Initialize and allocate memory for the data set.
  23. :param size_t ct: Number of elements to be accounted for.
  24. """
  25. self.conf.capacity = ct
  26. self.itemsize = self.get_itemsize() # Set this in concrete classes
  27. self.size = self.itemsize * self.conf.capacity
  28. cc.array_conf_init(&self.conf)
  29. self.conf.capacity = self.conf.capacity
  30. cc.array_init_conf(&self.data
  31. if not self.data:
  32. raise MemoryError()
  33. self._cur = 0
  34. #logger.debug('Got malloc sizes: {}, {}'.format(ct, itemsize))
  35. #logger.debug(
  36. # 'Allocating {0} ({1}x{2}) bytes of Keyset data...'.format(
  37. # self.size, self.conf.capacity, self.itemsize))
  38. #logger.debug('...done allocating @ {0:x}.'.format(
  39. # <unsigned long>self.data))
  40. def __dealloc__(self):
  41. """
  42. Free the memory.
  43. This is called when the Python instance is garbage collected, which
  44. makes it handy to safely pass a Keyset instance across functions.
  45. """
  46. #logger.debug(
  47. # 'Releasing {0} ({1}x{2}) bytes of Keyset @ {3:x}...'.format(
  48. # self.size, self.conf.capacity, self.itemsize,
  49. # <unsigned long>self.data))
  50. PyMem_Free(self.data)
  51. #logger.debug('...done releasing.')
  52. # Access methods.
  53. def iter_init(self):
  54. """
  55. Reset the cursor to the initial position.
  56. """
  57. self._cur = 0
  58. def tell(self):
  59. """
  60. Tell the position of the cursor in the keyset.
  61. """
  62. return self._cur
  63. cdef unsigned char *get_item(self, i):
  64. """
  65. Get an item at a given index position. Cython-level method.
  66. The item size is known by the ``itemsize`` property of the object.
  67. :rtype: unsigned char*
  68. """
  69. self._cur = i
  70. return self.data + self.itemsize * i
  71. cdef bint iter_next(self, unsigned char** val):
  72. """
  73. Populate the current value and advance the cursor by 1.
  74. :param void *val: Addres of value returned. It is NULL if
  75. the end of the buffer was reached.
  76. :rtype: bint
  77. :return: True if a value was found, False if the end of the buffer
  78. has been reached.
  79. """
  80. if self._cur >= self.conf.capacity:
  81. val = NULL
  82. return False
  83. val[0] = self.data + self.itemsize * self._cur
  84. self._cur += 1
  85. return True
  86. cdef bint contains(self, const void *val):
  87. """
  88. Whether a value exists in the set.
  89. """
  90. cdef unsigned char* stored_val
  91. self.iter_init()
  92. while self.iter_next(&stored_val):
  93. if memcmp(val, stored_val, self.itemsize) == 0:
  94. return True
  95. return False
  96. class Keyset(BaseKeyset):
  97. cdef size_t get_itemsize():
  98. return KLEN
  99. class DoubleKeyset(BaseKeyset):
  100. cdef size_t get_itemsize():
  101. return DBL_KLEN
  102. class TripleKeyset(BaseKeyset):
  103. cdef size_t get_itemsize():
  104. return TRP_KLEN