timestamp-store 1.0.0__tar.gz

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.
@@ -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,11 @@
1
+ include README.md
2
+ include LICENSE
3
+ include pyproject.toml
4
+
5
+ recursive-include timestamp_store/src *.cpp *.h *.hpp
6
+ recursive-include timestamp_store *.so *.dylib *.dll
7
+
8
+ global-exclude __pycache__
9
+ global-exclude *.py[cod]
10
+ global-exclude *.so.*
11
+ global-exclude .git*
@@ -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,60 @@
1
+ # TimestampStore
2
+
3
+ Fast data structure for (id, timestamp) pairs with O(log N) operations.
4
+ Warning! Created by claude-opus-4.5 without human intervention.
5
+
6
+ ## Installation
7
+
8
+ ```bash
9
+ pip install git+https://github.com/shutkanos/timestamp_store.git
10
+ ```
11
+
12
+ **Requirements:** C++ compiler (g++, clang++, or MSVC)
13
+
14
+ ### Installing compiler
15
+
16
+ - **Ubuntu/Debian:** `sudo apt install g++`
17
+ - **macOS:** `xcode-select --install`
18
+ - **Windows:** Install [Visual Studio Build Tools](https://visualstudio.microsoft.com/visual-cpp-build-tools/) or:
19
+
20
+ PowerShell:
21
+ ```PowerShell
22
+ winget install -e --id MSYS2.MSYS2
23
+ ```
24
+ MSYS2:
25
+ ```
26
+ pacman -S mingw-w64-x86_64-gcc
27
+ ```
28
+
29
+ ## Usage
30
+
31
+ ```python
32
+ from timestamp_store import TimestampStore
33
+
34
+ store = TimestampStore()
35
+
36
+ # Add pairs
37
+ store.add(1, 100)
38
+ store.add(2, 50)
39
+ store.add(3, 150)
40
+
41
+ # Remove all with timestamp < 120
42
+ removed = store.remove_timestamp(120)
43
+ print(removed) # [2, 1]
44
+
45
+ # Remove by id
46
+ store.remove(3)
47
+
48
+ # Create from list
49
+ store = TimestampStore([(1, 100), (2, 200)])
50
+ # Create from dict
51
+ store = TimestampStore({1: 100, 2: 200})
52
+ ```
53
+
54
+ ## Complexity
55
+
56
+ | Operation | Complexity |
57
+ |-----------|------------|
58
+ | `add(id, timestamp)` | O(log N) |
59
+ | `remove(id)` | O(log N) |
60
+ | `remove_timestamp(ts)` | O(K) where K = removed count |
@@ -0,0 +1,42 @@
1
+ [build-system]
2
+ requires = ["setuptools>=45", "wheel", "setuptools-scm>=6.2"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "timestamp-store"
7
+ version = "1.0.0"
8
+ description = "Fast timestamp-based data structure with O(log N) operations"
9
+ readme = "README.md"
10
+ license = {text = "MIT"}
11
+ requires-python = ">=3.7"
12
+ authors = [
13
+ {name = "Shutkanos", email = "Shutkanos836926@mail.ru"}
14
+ ]
15
+ classifiers = [
16
+ "Development Status :: 4 - Beta",
17
+ "Intended Audience :: Developers",
18
+ "License :: OSI Approved :: MIT License",
19
+ "Programming Language :: Python :: 3",
20
+ "Programming Language :: Python :: 3.7",
21
+ "Programming Language :: Python :: 3.8",
22
+ "Programming Language :: Python :: 3.9",
23
+ "Programming Language :: Python :: 3.10",
24
+ "Programming Language :: Python :: 3.11",
25
+ "Programming Language :: Python :: 3.12",
26
+ "Programming Language :: Python :: 3.13",
27
+ "Programming Language :: Python :: 3.14",
28
+ "Programming Language :: C++",
29
+ "Operating System :: OS Independent",
30
+ ]
31
+ keywords = ["timestamp", "data-structure", "ctypes"]
32
+
33
+ [project.urls]
34
+ Homepage = "https://github.com/shutkanos/timestamp_store"
35
+ Repository = "https://github.com/shutkanos/timestamp_store"
36
+
37
+ [tool.setuptools.packages.find]
38
+ where = ["."]
39
+ include = ["timestamp_store*"]
40
+
41
+ [tool.setuptools.package-data]
42
+ timestamp_store = ["src/*.cpp", "*.so", "*.dylib", "*.dll"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,360 @@
1
+ import os
2
+ import sys
3
+ import platform
4
+ import subprocess
5
+ import shutil
6
+ from pathlib import Path
7
+
8
+ from setuptools import setup, find_packages
9
+ from setuptools.command.build_py import build_py
10
+ from setuptools.command.develop import develop
11
+ from setuptools.command.install import install
12
+ from setuptools.command.egg_info import egg_info
13
+
14
+
15
+ def get_library_name():
16
+ system = platform.system()
17
+ if system == "Windows":
18
+ return "timestamp_store.dll"
19
+ elif system == "Darwin":
20
+ return "libtimestamp_store.dylib"
21
+ else:
22
+ return "libtimestamp_store.so"
23
+
24
+
25
+ def find_mingw_path():
26
+ mingw_search_paths = [
27
+ Path("C:/msys64/mingw64/bin"),
28
+ Path("C:/msys64/ucrt64/bin"),
29
+ Path("C:/msys64/clang64/bin"),
30
+ Path("C:/msys64/mingw32/bin"),
31
+ Path("C:/msys2/mingw64/bin"),
32
+ Path("C:/msys2/ucrt64/bin"),
33
+ Path("C:/mingw64/bin"),
34
+ Path("C:/mingw/bin"),
35
+ Path("C:/MinGW/bin"),
36
+ Path("C:/tools/mingw64/bin"),
37
+ Path(os.environ.get("USERPROFILE", "")) / "scoop/apps/mingw/current/bin",
38
+ Path(os.environ.get("ProgramFiles", "C:\\Program Files")) / "mingw-w64/x86_64-8.1.0-posix-seh-rt_v6-rev0/mingw64/bin",
39
+ Path(os.environ.get("ProgramFiles", "C:\\Program Files")) / "mingw64/bin",
40
+ ]
41
+
42
+ for env_var in ["MINGW_HOME", "MINGW64_HOME", "MSYS2_HOME"]:
43
+ if env_var in os.environ:
44
+ env_path = Path(os.environ[env_var])
45
+ if (env_path / "bin" / "g++.exe").exists():
46
+ mingw_search_paths.insert(0, env_path / "bin")
47
+ elif (env_path / "g++.exe").exists():
48
+ mingw_search_paths.insert(0, env_path)
49
+
50
+ for path in mingw_search_paths:
51
+ if path.exists() and (path / "g++.exe").exists():
52
+ print(f"Found MinGW at: {path}")
53
+ return path
54
+
55
+ return None
56
+
57
+
58
+ def find_msvc_vcvarsall():
59
+ program_files_x86 = os.environ.get("ProgramFiles(x86)", "C:\\Program Files (x86)")
60
+ program_files = os.environ.get("ProgramFiles", "C:\\Program Files")
61
+
62
+ vswhere_paths = [
63
+ Path(program_files_x86) / "Microsoft Visual Studio/Installer/vswhere.exe",
64
+ Path(program_files) / "Microsoft Visual Studio/Installer/vswhere.exe",
65
+ ]
66
+
67
+ vswhere = None
68
+ for p in vswhere_paths:
69
+ if p.exists():
70
+ vswhere = p
71
+ break
72
+
73
+ if vswhere:
74
+ try:
75
+ result = subprocess.run(
76
+ [
77
+ str(vswhere),
78
+ "-latest",
79
+ "-property", "installationPath",
80
+ "-requires", "Microsoft.VisualStudio.Component.VC.Tools.x86.x64"
81
+ ],
82
+ capture_output=True,
83
+ text=True,
84
+ check=True
85
+ )
86
+ vs_path = Path(result.stdout.strip())
87
+ vcvarsall = vs_path / "VC/Auxiliary/Build/vcvarsall.bat"
88
+ if vcvarsall.exists():
89
+ print(f"Found MSVC vcvarsall at: {vcvarsall}")
90
+ return vcvarsall
91
+ except subprocess.CalledProcessError:
92
+ pass
93
+
94
+ vs_years = ["2022", "2019", "2017"]
95
+ vs_editions = ["Enterprise", "Professional", "Community", "BuildTools"]
96
+
97
+ for year in vs_years:
98
+ for edition in vs_editions:
99
+ for pf in [program_files, program_files_x86]:
100
+ vcvarsall = Path(pf) / f"Microsoft Visual Studio/{year}/{edition}/VC/Auxiliary/Build/vcvarsall.bat"
101
+ if vcvarsall.exists():
102
+ print(f"Found MSVC vcvarsall at: {vcvarsall}")
103
+ return vcvarsall
104
+
105
+ return None
106
+
107
+
108
+ def get_msvc_environment(vcvarsall):
109
+ arch = "x64" if platform.machine().endswith('64') else "x86"
110
+
111
+ cmd = f'"{vcvarsall}" {arch} >nul 2>&1 && set'
112
+
113
+ try:
114
+ result = subprocess.run(
115
+ cmd,
116
+ shell=True,
117
+ capture_output=True,
118
+ text=True,
119
+ check=True
120
+ )
121
+
122
+ env = {}
123
+ for line in result.stdout.splitlines():
124
+ if '=' in line:
125
+ key, _, value = line.partition('=')
126
+ env[key] = value
127
+
128
+ return env
129
+ except subprocess.CalledProcessError as e:
130
+ print(f"Warning: Failed to setup MSVC environment: {e}")
131
+ return None
132
+
133
+
134
+ def get_compiler_command():
135
+ system = platform.system()
136
+ lib_name = get_library_name()
137
+
138
+ src_dir = Path(__file__).parent / "timestamp_store" / "src"
139
+ cpp_file = src_dir / "timestamp_store.cpp"
140
+ output_dir = Path(__file__).parent / "timestamp_store"
141
+ output_file = output_dir / lib_name
142
+
143
+ env = os.environ.copy()
144
+
145
+ if system == "Windows":
146
+ mingw_path = find_mingw_path()
147
+ if mingw_path:
148
+ env["PATH"] = str(mingw_path) + os.pathsep + env.get("PATH", "")
149
+
150
+ gpp_path = mingw_path / "g++.exe"
151
+
152
+ return [
153
+ str(gpp_path),
154
+ "-O3", "-std=c++17", "-shared",
155
+ "-static-libgcc",
156
+ "-static-libstdc++",
157
+ "-static",
158
+ "-o", str(output_file),
159
+ str(cpp_file)
160
+ ], env
161
+
162
+ vcvarsall = find_msvc_vcvarsall()
163
+ if vcvarsall:
164
+ msvc_env = get_msvc_environment(vcvarsall)
165
+ if msvc_env:
166
+ return [
167
+ "cl",
168
+ "/O2",
169
+ "/LD",
170
+ "/EHsc",
171
+ "/std:c++17",
172
+ "/MT",
173
+ str(cpp_file),
174
+ f"/Fe:{output_file}",
175
+ f"/Fo:{output_dir}\\",
176
+ ], msvc_env
177
+
178
+ if shutil.which("g++"):
179
+ print("Using g++ from PATH")
180
+ return [
181
+ "g++", "-O3", "-std=c++17", "-shared",
182
+ "-static-libgcc", "-static-libstdc++",
183
+ "-o", str(output_file),
184
+ str(cpp_file)
185
+ ], env
186
+
187
+ if shutil.which("cl"):
188
+ print("Using cl from PATH")
189
+ return [
190
+ "cl", "/O2", "/LD", "/EHsc",
191
+ "/std:c++17", "/MT",
192
+ str(cpp_file),
193
+ f"/Fe:{output_file}"
194
+ ], env
195
+ raise RuntimeError(
196
+ "No C++ compiler found on Windows!\n\n"
197
+ "Please install one of the following:\n"
198
+ "1. MSYS2 MinGW: https://www.msys2.org/\n"
199
+ " Then run: pacman -S mingw-w64-x86_64-gcc\n\n"
200
+ "2. Visual Studio Build Tools: https://visualstudio.microsoft.com/visual-cpp-build-tools/\n"
201
+ " Select 'Desktop development with C++'\n\n"
202
+ "3. Standalone MinGW-w64: https://www.mingw-w64.org/downloads/"
203
+ )
204
+
205
+ elif system == "Darwin":
206
+ compiler = "clang++" if shutil.which("clang++") else "g++"
207
+ return [
208
+ compiler, "-O3", "-std=c++17",
209
+ "-shared", "-fPIC",
210
+ "-o", str(output_file),
211
+ str(cpp_file)
212
+ ], env
213
+
214
+ else:
215
+ if not shutil.which("g++"):
216
+ raise RuntimeError(
217
+ "g++ not found. Please install:\n"
218
+ "Ubuntu/Debian: sudo apt install g++\n"
219
+ "Fedora: sudo dnf install gcc-c++\n"
220
+ "Arch: sudo pacman -S gcc"
221
+ )
222
+ return [
223
+ "g++", "-O3", "-std=c++17",
224
+ "-shared", "-fPIC",
225
+ "-o", str(output_file),
226
+ str(cpp_file)
227
+ ], env
228
+
229
+
230
+ def compile_cpp_library():
231
+ lib_name = get_library_name()
232
+ output_dir = Path(__file__).parent / "timestamp_store"
233
+ output_file = output_dir / lib_name
234
+
235
+ if output_file.exists():
236
+ print(f"Library {lib_name} already exists, skipping compilation")
237
+ return
238
+
239
+ print(f"Compiling C++ library: {lib_name}")
240
+ print(f"Platform: {platform.system()} {platform.machine()}")
241
+
242
+ try:
243
+ cmd, env = get_compiler_command()
244
+ print(f"Running: {' '.join(cmd)}")
245
+
246
+ path_preview = env.get("PATH", "").split(os.pathsep)[:3]
247
+ print(f"PATH preview: {path_preview}")
248
+
249
+ result = subprocess.run(
250
+ cmd,
251
+ check=True,
252
+ capture_output=True,
253
+ text=True,
254
+ env=env,
255
+ cwd=str(output_dir)
256
+ )
257
+
258
+ if result.stdout:
259
+ print(result.stdout)
260
+
261
+ if output_file.exists():
262
+ print(f"Successfully compiled {lib_name}")
263
+ print(f"Library size: {output_file.stat().st_size} bytes")
264
+ else:
265
+ raise RuntimeError(f"Compilation succeeded but {lib_name} not found")
266
+
267
+ except subprocess.CalledProcessError as e:
268
+ print(f"Compilation failed!")
269
+ print(f"Command: {' '.join(cmd)}")
270
+ print(f"stdout: {e.stdout}")
271
+ print(f"stderr: {e.stderr}")
272
+ raise RuntimeError(f"Failed to compile C++ library: {e}")
273
+ except FileNotFoundError as e:
274
+ raise RuntimeError(
275
+ f"C++ compiler not found: {e}\n"
276
+ f"Please install g++, clang++, or MSVC."
277
+ )
278
+ finally:
279
+ if platform.system() == "Windows":
280
+ for ext in [".obj", ".exp", ".lib"]:
281
+ for f in output_dir.glob(f"*{ext}"):
282
+ try:
283
+ f.unlink()
284
+ except:
285
+ pass
286
+
287
+
288
+ class BuildPyWithCompile(build_py):
289
+ def run(self):
290
+ compile_cpp_library()
291
+ super().run()
292
+
293
+ lib_name = get_library_name()
294
+ src_lib = Path(__file__).parent / "timestamp_store" / lib_name
295
+
296
+ if src_lib.exists():
297
+ dest_dir = Path(self.build_lib) / "timestamp_store"
298
+ dest_dir.mkdir(parents=True, exist_ok=True)
299
+ dest_lib = dest_dir / lib_name
300
+ shutil.copy2(src_lib, dest_lib)
301
+ print(f"Copied {lib_name} to {dest_lib}")
302
+
303
+
304
+ class DevelopWithCompile(develop):
305
+ def run(self):
306
+ compile_cpp_library()
307
+ super().run()
308
+
309
+
310
+ class InstallWithCompile(install):
311
+ def run(self):
312
+ compile_cpp_library()
313
+ super().run()
314
+
315
+
316
+ class EggInfoWithCompile(egg_info):
317
+ def run(self):
318
+ compile_cpp_library()
319
+ super().run()
320
+
321
+ long_description = ""
322
+ if os.path.exists("README.md"):
323
+ with open("README.md", encoding="utf-8") as f:
324
+ long_description = f.read()
325
+
326
+ setup(
327
+ name="timestamp-store",
328
+ version="1.0.0",
329
+ description="Fast timestamp-based data structure with O(log N) operations",
330
+ long_description=long_description,
331
+ long_description_content_type="text/markdown",
332
+ author='Shutkanos',
333
+ author_email='Shutkanos836926@mail.ru',
334
+ url="https://github.com/shutkanos/timestamp_store",
335
+ packages=find_packages(),
336
+ package_data={
337
+ "timestamp_store": [
338
+ "src/*.cpp",
339
+ "*.so",
340
+ "*.dylib",
341
+ "*.dll",
342
+ ],
343
+ },
344
+ include_package_data=True,
345
+ python_requires=">=3.7",
346
+ classifiers=[
347
+ "Development Status :: 4 - Beta",
348
+ "Intended Audience :: Developers",
349
+ "License :: OSI Approved :: MIT License",
350
+ "Programming Language :: Python :: 3",
351
+ "Programming Language :: C++",
352
+ "Operating System :: OS Independent",
353
+ ],
354
+ cmdclass={
355
+ "build_py": BuildPyWithCompile,
356
+ "develop": DevelopWithCompile,
357
+ "install": InstallWithCompile,
358
+ "egg_info": EggInfoWithCompile,
359
+ },
360
+ )
@@ -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
+ }
@@ -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,13 @@
1
+ LICENSE
2
+ MANIFEST.in
3
+ README.md
4
+ pyproject.toml
5
+ setup.py
6
+ timestamp_store/__init__.py
7
+ timestamp_store/timestamp_store.dll
8
+ timestamp_store/wrapper.py
9
+ timestamp_store.egg-info/PKG-INFO
10
+ timestamp_store.egg-info/SOURCES.txt
11
+ timestamp_store.egg-info/dependency_links.txt
12
+ timestamp_store.egg-info/top_level.txt
13
+ timestamp_store/src/timestamp_store.cpp
@@ -0,0 +1 @@
1
+ timestamp_store