hashindex.pyx 4.6 KB

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