hashindex.pyx 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. # -*- coding: utf-8 -*-
  2. import os
  3. cdef extern from "_hashindex.c":
  4. ctypedef struct HashIndex:
  5. pass
  6. HashIndex *hashindex_open(char *path)
  7. HashIndex *hashindex_create(char *path, int capacity, int key_size, int value_size)
  8. int hashindex_get_size(HashIndex *index)
  9. int hashindex_clear(HashIndex *index)
  10. int hashindex_close(HashIndex *index)
  11. int hashindex_flush(HashIndex *index)
  12. void *hashindex_get(HashIndex *index, void *key)
  13. void *hashindex_next_key(HashIndex *index, void *key)
  14. int hashindex_delete(HashIndex *index, void *key)
  15. int hashindex_set(HashIndex *index, void *key, void *value)
  16. _NoDefault = object()
  17. cdef class IndexBase:
  18. cdef HashIndex *index
  19. key_size = 32
  20. def __cinit__(self, path):
  21. self.index = hashindex_open(<bytes>os.fsencode(path))
  22. if not self.index:
  23. raise Exception('Failed to open %s' % path)
  24. def __dealloc__(self):
  25. if self.index:
  26. if not hashindex_close(self.index):
  27. raise Exception('hashindex_close failed')
  28. @classmethod
  29. def create(cls, path):
  30. index = hashindex_create(<bytes>os.fsencode(path), 0, cls.key_size, cls.value_size)
  31. if not index:
  32. raise Exception('Failed to create %s' % path)
  33. hashindex_close(index)
  34. return cls(path)
  35. def clear(self):
  36. if not hashindex_clear(self.index):
  37. raise Exception('hashindex_clear failed')
  38. def flush(self):
  39. if not hashindex_flush(self.index):
  40. raise Exception('hashindex_flush failed')
  41. def setdefault(self, key, value):
  42. if not key in self:
  43. self[key] = value
  44. def __delitem__(self, key):
  45. assert len(key) == 32
  46. if not hashindex_delete(self.index, <char *>key):
  47. raise Exception('hashindex_delete failed')
  48. def get(self, key, default=None):
  49. try:
  50. return self[key]
  51. except KeyError:
  52. return default
  53. def pop(self, key, default=_NoDefault):
  54. try:
  55. value = self[key]
  56. del self[key]
  57. return value
  58. except KeyError:
  59. if default != _NoDefault:
  60. return default
  61. raise
  62. def __len__(self):
  63. return hashindex_get_size(self.index)
  64. cdef class NSIndex(IndexBase):
  65. value_size = 8
  66. def __getitem__(self, key):
  67. assert len(key) == 32
  68. data = <int *>hashindex_get(self.index, <char *>key)
  69. if not data:
  70. raise KeyError
  71. return data[0], data[1]
  72. def __setitem__(self, key, value):
  73. assert len(key) == 32
  74. cdef int[2] data
  75. data[0] = value[0]
  76. data[1] = value[1]
  77. if not hashindex_set(self.index, <char *>key, data):
  78. raise Exception('hashindex_set failed')
  79. def __contains__(self, key):
  80. assert len(key) == 32
  81. data = <int *>hashindex_get(self.index, <char *>key)
  82. return data != NULL
  83. def iteritems(self, marker=None, limit=0):
  84. iter = NSKeyIterator()
  85. iter.index = self.index
  86. return iter
  87. cdef class NSKeyIterator:
  88. cdef HashIndex *index
  89. cdef char *key
  90. def __cinit__(self):
  91. self.key = NULL
  92. def __iter__(self):
  93. return self
  94. def __next__(self):
  95. self.key = <char *>hashindex_next_key(self.index, <char *>self.key)
  96. if not self.key:
  97. raise StopIteration
  98. cdef int *value = <int *>(self.key + 32)
  99. return self.key[:32], (value[0], value[1])
  100. cdef class ChunkIndex(IndexBase):
  101. value_size = 12
  102. def __getitem__(self, key):
  103. assert len(key) == 32
  104. data = <int *>hashindex_get(self.index, <char *>key)
  105. if not data:
  106. raise KeyError
  107. return data[0], data[1], data[2]
  108. def __setitem__(self, key, value):
  109. assert len(key) == 32
  110. cdef int[3] data
  111. data[0] = value[0]
  112. data[1] = value[1]
  113. data[2] = value[2]
  114. if not hashindex_set(self.index, <char *>key, data):
  115. raise Exception('hashindex_set failed')
  116. def __contains__(self, key):
  117. assert len(key) == 32
  118. data = <int *>hashindex_get(self.index, <char *>key)
  119. return data != NULL
  120. def iteritems(self, marker=None, limit=0):
  121. iter = ChunkKeyIterator()
  122. iter.index = self.index
  123. return iter
  124. cdef class ChunkKeyIterator:
  125. cdef HashIndex *index
  126. cdef char *key
  127. def __cinit__(self):
  128. self.key = NULL
  129. def __iter__(self):
  130. return self
  131. def __next__(self):
  132. self.key = <char *>hashindex_next_key(self.index, <char *>self.key)
  133. if not self.key:
  134. raise StopIteration
  135. cdef int *value = <int *>(self.key + 32)
  136. return self.key[:32], (value[0], value[1], value[2])