timestamp-store 1.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- timestamp_store/__init__.py +18 -0
- timestamp_store/src/timestamp_store.cpp +203 -0
- timestamp_store/timestamp_store.dll +0 -0
- timestamp_store/wrapper.py +175 -0
- timestamp_store-1.0.0.dist-info/METADATA +93 -0
- timestamp_store-1.0.0.dist-info/RECORD +9 -0
- timestamp_store-1.0.0.dist-info/WHEEL +5 -0
- timestamp_store-1.0.0.dist-info/licenses/LICENSE +21 -0
- timestamp_store-1.0.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"""
|
|
2
|
+
TimestampStore - fast data structure for pairs (id, timestamp)
|
|
3
|
+
|
|
4
|
+
Usage example:
|
|
5
|
+
from timestamp_store import TimestampStore
|
|
6
|
+
|
|
7
|
+
store = TimestampStore()
|
|
8
|
+
store.add(1, 100)
|
|
9
|
+
store.add(2, 50)
|
|
10
|
+
|
|
11
|
+
removed = store.remove_timestamp(80) # [2]
|
|
12
|
+
removed = store.remove_timestamp(120) # [1]
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from .wrapper import TimestampStore
|
|
16
|
+
|
|
17
|
+
__version__ = "1.0.0"
|
|
18
|
+
__all__ = ["TimestampStore"]
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
#include <map>
|
|
2
|
+
#include <unordered_map>
|
|
3
|
+
#include <unordered_set>
|
|
4
|
+
#include <vector>
|
|
5
|
+
#include <cstdint>
|
|
6
|
+
#include <algorithm>
|
|
7
|
+
|
|
8
|
+
class TimestampStore {
|
|
9
|
+
private:
|
|
10
|
+
std::map<int64_t, std::unordered_set<int64_t>> time_to_ids_;
|
|
11
|
+
|
|
12
|
+
std::unordered_map<int64_t, int64_t> id_to_time_;
|
|
13
|
+
|
|
14
|
+
public:
|
|
15
|
+
TimestampStore() = default;
|
|
16
|
+
|
|
17
|
+
void add(int64_t id, int64_t timestamp) {
|
|
18
|
+
auto it = id_to_time_.find(id);
|
|
19
|
+
|
|
20
|
+
if (it != id_to_time_.end()) {
|
|
21
|
+
int64_t old_time = it->second;
|
|
22
|
+
|
|
23
|
+
if (old_time == timestamp) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
auto old_time_it = time_to_ids_.find(old_time);
|
|
28
|
+
if (old_time_it != time_to_ids_.end()) {
|
|
29
|
+
old_time_it->second.erase(id);
|
|
30
|
+
if (old_time_it->second.empty()) {
|
|
31
|
+
time_to_ids_.erase(old_time_it);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
it->second = timestamp;
|
|
36
|
+
} else {
|
|
37
|
+
id_to_time_[id] = timestamp;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
time_to_ids_[timestamp].insert(id);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
bool remove(int64_t id) {
|
|
44
|
+
auto it = id_to_time_.find(id);
|
|
45
|
+
if (it == id_to_time_.end()) {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
int64_t timestamp = it->second;
|
|
50
|
+
id_to_time_.erase(it);
|
|
51
|
+
|
|
52
|
+
auto time_it = time_to_ids_.find(timestamp);
|
|
53
|
+
if (time_it != time_to_ids_.end()) {
|
|
54
|
+
time_it->second.erase(id);
|
|
55
|
+
if (time_it->second.empty()) {
|
|
56
|
+
time_to_ids_.erase(time_it);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
std::vector<int64_t> remove_before_timestamp(int64_t timestamp) {
|
|
64
|
+
std::vector<int64_t> removed_ids;
|
|
65
|
+
|
|
66
|
+
while (!time_to_ids_.empty()) {
|
|
67
|
+
auto it = time_to_ids_.begin();
|
|
68
|
+
|
|
69
|
+
if (it->first >= timestamp) {
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
for (int64_t id : it->second) {
|
|
74
|
+
removed_ids.push_back(id);
|
|
75
|
+
id_to_time_.erase(id);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
time_to_ids_.erase(it);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
return removed_ids;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
size_t size() const {
|
|
85
|
+
return id_to_time_.size();
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
bool empty() const {
|
|
89
|
+
return id_to_time_.empty();
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
int64_t get_min_timestamp() const {
|
|
93
|
+
if (time_to_ids_.empty()) {
|
|
94
|
+
return -1;
|
|
95
|
+
}
|
|
96
|
+
return time_to_ids_.begin()->first;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
bool contains(int64_t id) const {
|
|
100
|
+
return id_to_time_.count(id) > 0;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
int64_t get_timestamp(int64_t id) const {
|
|
104
|
+
auto it = id_to_time_.find(id);
|
|
105
|
+
if (it == id_to_time_.end()) {
|
|
106
|
+
return -1;
|
|
107
|
+
}
|
|
108
|
+
return it->second;
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
// ============================================================================
|
|
114
|
+
// C API ctypes
|
|
115
|
+
// ============================================================================
|
|
116
|
+
|
|
117
|
+
#ifdef _WIN32
|
|
118
|
+
#define EXPORT extern "C" __declspec(dllexport)
|
|
119
|
+
#else
|
|
120
|
+
#define EXPORT extern "C" __attribute__((visibility("default")))
|
|
121
|
+
#endif
|
|
122
|
+
|
|
123
|
+
EXPORT TimestampStore* ts_create() {
|
|
124
|
+
return new TimestampStore();
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
EXPORT TimestampStore* ts_create_from_arrays(
|
|
128
|
+
const int64_t* ids,
|
|
129
|
+
const int64_t* timestamps,
|
|
130
|
+
int64_t count
|
|
131
|
+
) {
|
|
132
|
+
TimestampStore* store = new TimestampStore();
|
|
133
|
+
for (int64_t i = 0; i < count; ++i) {
|
|
134
|
+
store->add(ids[i], timestamps[i]);
|
|
135
|
+
}
|
|
136
|
+
return store;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
EXPORT void ts_destroy(TimestampStore* store) {
|
|
140
|
+
delete store;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
EXPORT void ts_add(TimestampStore* store, int64_t id, int64_t timestamp) {
|
|
144
|
+
if (store) {
|
|
145
|
+
store->add(id, timestamp);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
EXPORT int32_t ts_remove(TimestampStore* store, int64_t id) {
|
|
150
|
+
if (!store) return 0;
|
|
151
|
+
return store->remove(id) ? 1 : 0;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
EXPORT int64_t* ts_remove_before_timestamp(
|
|
155
|
+
TimestampStore* store,
|
|
156
|
+
int64_t timestamp,
|
|
157
|
+
int64_t* out_size
|
|
158
|
+
) {
|
|
159
|
+
if (!store || !out_size) {
|
|
160
|
+
if (out_size) *out_size = 0;
|
|
161
|
+
return nullptr;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
std::vector<int64_t> result = store->remove_before_timestamp(timestamp);
|
|
165
|
+
*out_size = static_cast<int64_t>(result.size());
|
|
166
|
+
|
|
167
|
+
if (result.empty()) {
|
|
168
|
+
return nullptr;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
int64_t* arr = new int64_t[result.size()];
|
|
172
|
+
std::copy(result.begin(), result.end(), arr);
|
|
173
|
+
return arr;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
EXPORT void ts_free_array(int64_t* arr) {
|
|
177
|
+
delete[] arr;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
EXPORT int64_t ts_size(TimestampStore* store) {
|
|
181
|
+
if (!store) return 0;
|
|
182
|
+
return static_cast<int64_t>(store->size());
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
EXPORT int32_t ts_empty(TimestampStore* store) {
|
|
186
|
+
if (!store) return 1;
|
|
187
|
+
return store->empty() ? 1 : 0;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
EXPORT int64_t ts_get_min_timestamp(TimestampStore* store) {
|
|
191
|
+
if (!store) return -1;
|
|
192
|
+
return store->get_min_timestamp();
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
EXPORT int32_t ts_contains(TimestampStore* store, int64_t id) {
|
|
196
|
+
if (!store) return 0;
|
|
197
|
+
return store->contains(id) ? 1 : 0;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
EXPORT int64_t ts_get_timestamp(TimestampStore* store, int64_t id) {
|
|
201
|
+
if (!store) return -1;
|
|
202
|
+
return store->get_timestamp(id);
|
|
203
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
import ctypes
|
|
2
|
+
import platform
|
|
3
|
+
from pathlib import Path
|
|
4
|
+
from typing import List, Tuple, Optional, Union, Dict
|
|
5
|
+
|
|
6
|
+
class TimestampStore:
|
|
7
|
+
_lib: ctypes.CDLL = None
|
|
8
|
+
_lib_path: str = None
|
|
9
|
+
|
|
10
|
+
@classmethod
|
|
11
|
+
def _get_lib_name(cls) -> str:
|
|
12
|
+
system = platform.system()
|
|
13
|
+
if system == "Windows":
|
|
14
|
+
return "timestamp_store.dll"
|
|
15
|
+
elif system == "Darwin":
|
|
16
|
+
return "libtimestamp_store.dylib"
|
|
17
|
+
else:
|
|
18
|
+
return "libtimestamp_store.so"
|
|
19
|
+
|
|
20
|
+
@classmethod
|
|
21
|
+
def _find_library(cls) -> str:
|
|
22
|
+
lib_name = cls._get_lib_name()
|
|
23
|
+
|
|
24
|
+
search_paths = [
|
|
25
|
+
Path(__file__).parent / lib_name,
|
|
26
|
+
Path(__file__).parent / "src" / lib_name,
|
|
27
|
+
Path.cwd() / lib_name,
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
for path in search_paths:
|
|
31
|
+
if path.exists():
|
|
32
|
+
return str(path)
|
|
33
|
+
|
|
34
|
+
raise FileNotFoundError(
|
|
35
|
+
f"Could not find {lib_name}. "
|
|
36
|
+
f"Searched in: {[str(p) for p in search_paths]}. "
|
|
37
|
+
f"Try reinstalling the package: pip install --force-reinstall git+https://github.com/shutkanos/timestamp_store.git"
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
@classmethod
|
|
41
|
+
def _load_library(cls, lib_path: Optional[str] = None) -> ctypes.CDLL:
|
|
42
|
+
if lib_path is None:
|
|
43
|
+
lib_path = cls._find_library()
|
|
44
|
+
|
|
45
|
+
if cls._lib is not None and cls._lib_path == lib_path:
|
|
46
|
+
return cls._lib
|
|
47
|
+
|
|
48
|
+
lib = ctypes.CDLL(lib_path)
|
|
49
|
+
|
|
50
|
+
lib.ts_create.restype = ctypes.c_void_p
|
|
51
|
+
lib.ts_create.argtypes = []
|
|
52
|
+
|
|
53
|
+
lib.ts_create_from_arrays.restype = ctypes.c_void_p
|
|
54
|
+
lib.ts_create_from_arrays.argtypes = [
|
|
55
|
+
ctypes.POINTER(ctypes.c_int64),
|
|
56
|
+
ctypes.POINTER(ctypes.c_int64),
|
|
57
|
+
ctypes.c_int64
|
|
58
|
+
]
|
|
59
|
+
|
|
60
|
+
lib.ts_destroy.restype = None
|
|
61
|
+
lib.ts_destroy.argtypes = [ctypes.c_void_p]
|
|
62
|
+
|
|
63
|
+
lib.ts_add.restype = None
|
|
64
|
+
lib.ts_add.argtypes = [ctypes.c_void_p, ctypes.c_int64, ctypes.c_int64]
|
|
65
|
+
|
|
66
|
+
lib.ts_remove.restype = ctypes.c_int32
|
|
67
|
+
lib.ts_remove.argtypes = [ctypes.c_void_p, ctypes.c_int64]
|
|
68
|
+
|
|
69
|
+
lib.ts_remove_before_timestamp.restype = ctypes.POINTER(ctypes.c_int64)
|
|
70
|
+
lib.ts_remove_before_timestamp.argtypes = [
|
|
71
|
+
ctypes.c_void_p,
|
|
72
|
+
ctypes.c_int64,
|
|
73
|
+
ctypes.POINTER(ctypes.c_int64)
|
|
74
|
+
]
|
|
75
|
+
|
|
76
|
+
lib.ts_free_array.restype = None
|
|
77
|
+
lib.ts_free_array.argtypes = [ctypes.POINTER(ctypes.c_int64)]
|
|
78
|
+
|
|
79
|
+
lib.ts_size.restype = ctypes.c_int64
|
|
80
|
+
lib.ts_size.argtypes = [ctypes.c_void_p]
|
|
81
|
+
|
|
82
|
+
lib.ts_empty.restype = ctypes.c_int32
|
|
83
|
+
lib.ts_empty.argtypes = [ctypes.c_void_p]
|
|
84
|
+
|
|
85
|
+
lib.ts_get_min_timestamp.restype = ctypes.c_int64
|
|
86
|
+
lib.ts_get_min_timestamp.argtypes = [ctypes.c_void_p]
|
|
87
|
+
|
|
88
|
+
lib.ts_contains.restype = ctypes.c_int32
|
|
89
|
+
lib.ts_contains.argtypes = [ctypes.c_void_p, ctypes.c_int64]
|
|
90
|
+
|
|
91
|
+
lib.ts_get_timestamp.restype = ctypes.c_int64
|
|
92
|
+
lib.ts_get_timestamp.argtypes = [ctypes.c_void_p, ctypes.c_int64]
|
|
93
|
+
|
|
94
|
+
cls._lib = lib
|
|
95
|
+
cls._lib_path = lib_path
|
|
96
|
+
return lib
|
|
97
|
+
|
|
98
|
+
def __init__(self, data: Optional[Union[List[Tuple[int, int]], Dict[int, int]]] = None, *, lib_path: Optional[str] = None):
|
|
99
|
+
self._lib_instance = self._load_library(lib_path)
|
|
100
|
+
|
|
101
|
+
if data is None:
|
|
102
|
+
self._store = self._lib_instance.ts_create()
|
|
103
|
+
else:
|
|
104
|
+
if isinstance(data, dict):
|
|
105
|
+
pairs = list(data.items())
|
|
106
|
+
else:
|
|
107
|
+
pairs = list(data)
|
|
108
|
+
|
|
109
|
+
if not pairs:
|
|
110
|
+
self._store = self._lib_instance.ts_create()
|
|
111
|
+
else:
|
|
112
|
+
n = len(pairs)
|
|
113
|
+
ids_array = (ctypes.c_int64 * n)()
|
|
114
|
+
timestamps_array = (ctypes.c_int64 * n)()
|
|
115
|
+
|
|
116
|
+
for i, (id_val, ts_val) in enumerate(pairs):
|
|
117
|
+
ids_array[i] = id_val
|
|
118
|
+
timestamps_array[i] = ts_val
|
|
119
|
+
|
|
120
|
+
self._store = self._lib_instance.ts_create_from_arrays(
|
|
121
|
+
ids_array, timestamps_array, n
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
if not self._store:
|
|
125
|
+
raise MemoryError("Failed to create TimestampStore")
|
|
126
|
+
|
|
127
|
+
def __del__(self):
|
|
128
|
+
if hasattr(self, '_store') and self._store and hasattr(self, '_lib_instance'):
|
|
129
|
+
self._lib_instance.ts_destroy(self._store)
|
|
130
|
+
self._store = None
|
|
131
|
+
|
|
132
|
+
def add(self, id: int, timestamp: int) -> None:
|
|
133
|
+
self._lib_instance.ts_add(self._store, id, timestamp)
|
|
134
|
+
|
|
135
|
+
def remove(self, id: int) -> bool:
|
|
136
|
+
return bool(self._lib_instance.ts_remove(self._store, id))
|
|
137
|
+
|
|
138
|
+
def remove_timestamp(self, timestamp: int) -> List[int]:
|
|
139
|
+
"""
|
|
140
|
+
Delete all elements with a timestamp value less than the specified argument
|
|
141
|
+
:return: list of deleted IDs.
|
|
142
|
+
"""
|
|
143
|
+
size = ctypes.c_int64(0)
|
|
144
|
+
arr_ptr = self._lib_instance.ts_remove_before_timestamp(
|
|
145
|
+
self._store,
|
|
146
|
+
timestamp,
|
|
147
|
+
ctypes.byref(size)
|
|
148
|
+
)
|
|
149
|
+
|
|
150
|
+
if size.value == 0 or not arr_ptr:
|
|
151
|
+
return []
|
|
152
|
+
|
|
153
|
+
try:
|
|
154
|
+
result = [arr_ptr[i] for i in range(size.value)]
|
|
155
|
+
finally:
|
|
156
|
+
self._lib_instance.ts_free_array(arr_ptr)
|
|
157
|
+
|
|
158
|
+
return result
|
|
159
|
+
|
|
160
|
+
def get_timestamp(self, id: int) -> Optional[int]:
|
|
161
|
+
ts = self._lib_instance.ts_get_timestamp(self._store, id)
|
|
162
|
+
return ts if ts >= 0 else None
|
|
163
|
+
|
|
164
|
+
def get_min_timestamp(self) -> Optional[int]:
|
|
165
|
+
ts = self._lib_instance.ts_get_min_timestamp(self._store)
|
|
166
|
+
return ts if ts >= 0 else None
|
|
167
|
+
|
|
168
|
+
def __len__(self) -> int:
|
|
169
|
+
return self._lib_instance.ts_size(self._store)
|
|
170
|
+
|
|
171
|
+
def __bool__(self) -> bool:
|
|
172
|
+
return not self._lib_instance.ts_empty(self._store)
|
|
173
|
+
|
|
174
|
+
def __contains__(self, id: int) -> bool:
|
|
175
|
+
return bool(self._lib_instance.ts_contains(self._store, id))
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: timestamp-store
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Fast timestamp-based data structure with O(log N) operations
|
|
5
|
+
Home-page: https://github.com/shutkanos/timestamp_store
|
|
6
|
+
Author: Shutkanos
|
|
7
|
+
Author-email: Shutkanos <Shutkanos836926@mail.ru>
|
|
8
|
+
License: MIT
|
|
9
|
+
Project-URL: Homepage, https://github.com/shutkanos/timestamp_store
|
|
10
|
+
Project-URL: Repository, https://github.com/shutkanos/timestamp_store
|
|
11
|
+
Keywords: timestamp,data-structure,ctypes
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
15
|
+
Classifier: Programming Language :: Python :: 3
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.7
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
24
|
+
Classifier: Programming Language :: C++
|
|
25
|
+
Classifier: Operating System :: OS Independent
|
|
26
|
+
Requires-Python: >=3.7
|
|
27
|
+
Description-Content-Type: text/markdown
|
|
28
|
+
License-File: LICENSE
|
|
29
|
+
Dynamic: author
|
|
30
|
+
Dynamic: home-page
|
|
31
|
+
Dynamic: license-file
|
|
32
|
+
Dynamic: requires-python
|
|
33
|
+
|
|
34
|
+
# TimestampStore
|
|
35
|
+
|
|
36
|
+
Fast data structure for (id, timestamp) pairs with O(log N) operations.
|
|
37
|
+
Warning! Created by claude-opus-4.5 without human intervention.
|
|
38
|
+
|
|
39
|
+
## Installation
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
pip install git+https://github.com/shutkanos/timestamp_store.git
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**Requirements:** C++ compiler (g++, clang++, or MSVC)
|
|
46
|
+
|
|
47
|
+
### Installing compiler
|
|
48
|
+
|
|
49
|
+
- **Ubuntu/Debian:** `sudo apt install g++`
|
|
50
|
+
- **macOS:** `xcode-select --install`
|
|
51
|
+
- **Windows:** Install [Visual Studio Build Tools](https://visualstudio.microsoft.com/visual-cpp-build-tools/) or:
|
|
52
|
+
|
|
53
|
+
PowerShell:
|
|
54
|
+
```PowerShell
|
|
55
|
+
winget install -e --id MSYS2.MSYS2
|
|
56
|
+
```
|
|
57
|
+
MSYS2:
|
|
58
|
+
```
|
|
59
|
+
pacman -S mingw-w64-x86_64-gcc
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## Usage
|
|
63
|
+
|
|
64
|
+
```python
|
|
65
|
+
from timestamp_store import TimestampStore
|
|
66
|
+
|
|
67
|
+
store = TimestampStore()
|
|
68
|
+
|
|
69
|
+
# Add pairs
|
|
70
|
+
store.add(1, 100)
|
|
71
|
+
store.add(2, 50)
|
|
72
|
+
store.add(3, 150)
|
|
73
|
+
|
|
74
|
+
# Remove all with timestamp < 120
|
|
75
|
+
removed = store.remove_timestamp(120)
|
|
76
|
+
print(removed) # [2, 1]
|
|
77
|
+
|
|
78
|
+
# Remove by id
|
|
79
|
+
store.remove(3)
|
|
80
|
+
|
|
81
|
+
# Create from list
|
|
82
|
+
store = TimestampStore([(1, 100), (2, 200)])
|
|
83
|
+
# Create from dict
|
|
84
|
+
store = TimestampStore({1: 100, 2: 200})
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Complexity
|
|
88
|
+
|
|
89
|
+
| Operation | Complexity |
|
|
90
|
+
|-----------|------------|
|
|
91
|
+
| `add(id, timestamp)` | O(log N) |
|
|
92
|
+
| `remove(id)` | O(log N) |
|
|
93
|
+
| `remove_timestamp(ts)` | O(K) where K = removed count |
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
timestamp_store/__init__.py,sha256=TGRhO4_Fs0QnCgx6jYLlbIsuv0I7vMjVUqKspdbp32Q,409
|
|
2
|
+
timestamp_store/timestamp_store.dll,sha256=SgRDJZ6UGQmUh2WLtEDriXyDEF3kEmBX1CNNm232SmY,731228
|
|
3
|
+
timestamp_store/wrapper.py,sha256=xuoPlaVgl19DQcJbvmmnoqPRhsBnTaTxrLqgw-hbZsA,5935
|
|
4
|
+
timestamp_store/src/timestamp_store.cpp,sha256=cxu0BDutMk498rR1MGB0KF-d6fP0oWztLTx0M4B-y1s,5038
|
|
5
|
+
timestamp_store-1.0.0.dist-info/licenses/LICENSE,sha256=K7_kNJPZ5f_96bFuI_3LzOuIigXOx8q4pA9Z5sZ18Pc,1086
|
|
6
|
+
timestamp_store-1.0.0.dist-info/METADATA,sha256=IE_k9DKNRoeAM9qLhKdcWsC-zToHHihJ6hLLSgZgwc8,2632
|
|
7
|
+
timestamp_store-1.0.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
8
|
+
timestamp_store-1.0.0.dist-info/top_level.txt,sha256=SYxzkaPTIfm4d0Zbo6qSNINe6kIhTwc_HxmKHEENTdY,16
|
|
9
|
+
timestamp_store-1.0.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Shutkanos
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
timestamp_store
|