PyPcre 0.2.0__tar.gz → 0.2.2__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.
Files changed (49) hide show
  1. pypcre-0.2.2/MANIFEST.in +1 -0
  2. {pypcre-0.2.0 → pypcre-0.2.2}/PKG-INFO +2 -2
  3. {pypcre-0.2.0 → pypcre-0.2.2}/PyPcre.egg-info/PKG-INFO +2 -2
  4. {pypcre-0.2.0 → pypcre-0.2.2}/PyPcre.egg-info/SOURCES.txt +5 -0
  5. {pypcre-0.2.0 → pypcre-0.2.2}/PyPcre.egg-info/top_level.txt +1 -0
  6. {pypcre-0.2.0 → pypcre-0.2.2}/README.md +1 -1
  7. {pypcre-0.2.0 → pypcre-0.2.2}/pcre/pcre.py +11 -10
  8. pypcre-0.2.2/pcre_ext/atomic_compat.h +365 -0
  9. pypcre-0.2.2/pcre_ext/pcre2.h +1069 -0
  10. pypcre-0.2.2/pcre_ext/pcre2_module.h +124 -0
  11. {pypcre-0.2.0 → pypcre-0.2.2}/pyproject.toml +2 -1
  12. pypcre-0.2.2/setup_utils.py +1111 -0
  13. {pypcre-0.2.0 → pypcre-0.2.2}/LICENSE +0 -0
  14. {pypcre-0.2.0 → pypcre-0.2.2}/PyPcre.egg-info/dependency_links.txt +0 -0
  15. {pypcre-0.2.0 → pypcre-0.2.2}/pcre/__init__.py +0 -0
  16. {pypcre-0.2.0 → pypcre-0.2.2}/pcre/cache.py +0 -0
  17. {pypcre-0.2.0 → pypcre-0.2.2}/pcre/error.py +0 -0
  18. {pypcre-0.2.0 → pypcre-0.2.2}/pcre/flags.py +0 -0
  19. {pypcre-0.2.0 → pypcre-0.2.2}/pcre/re_compat.py +0 -0
  20. {pypcre-0.2.0 → pypcre-0.2.2}/pcre/threads.py +0 -0
  21. {pypcre-0.2.0 → pypcre-0.2.2}/pcre_ext/cache.c +0 -0
  22. {pypcre-0.2.0 → pypcre-0.2.2}/pcre_ext/error.c +0 -0
  23. {pypcre-0.2.0 → pypcre-0.2.2}/pcre_ext/flag.c +0 -0
  24. {pypcre-0.2.0 → pypcre-0.2.2}/pcre_ext/memory.c +0 -0
  25. {pypcre-0.2.0 → pypcre-0.2.2}/pcre_ext/pcre2.c +0 -0
  26. {pypcre-0.2.0 → pypcre-0.2.2}/pcre_ext/util.c +0 -0
  27. {pypcre-0.2.0 → pypcre-0.2.2}/setup.cfg +0 -0
  28. {pypcre-0.2.0 → pypcre-0.2.2}/setup.py +0 -0
  29. {pypcre-0.2.0 → pypcre-0.2.2}/tests/test_accuracy.py +0 -0
  30. {pypcre-0.2.0 → pypcre-0.2.2}/tests/test_api_parity.py +0 -0
  31. {pypcre-0.2.0 → pypcre-0.2.2}/tests/test_basic.py +0 -0
  32. {pypcre-0.2.0 → pypcre-0.2.2}/tests/test_bench_string.py +0 -0
  33. {pypcre-0.2.0 → pypcre-0.2.2}/tests/test_benchmark.py +0 -0
  34. {pypcre-0.2.0 → pypcre-0.2.2}/tests/test_bytes.py +0 -0
  35. {pypcre-0.2.0 → pypcre-0.2.2}/tests/test_cache.py +0 -0
  36. {pypcre-0.2.0 → pypcre-0.2.2}/tests/test_clobber.py +0 -0
  37. {pypcre-0.2.0 → pypcre-0.2.2}/tests/test_clobber_thread.py +0 -0
  38. {pypcre-0.2.0 → pypcre-0.2.2}/tests/test_core.py +0 -0
  39. {pypcre-0.2.0 → pypcre-0.2.2}/tests/test_errors.py +0 -0
  40. {pypcre-0.2.0 → pypcre-0.2.2}/tests/test_flags.py +0 -0
  41. {pypcre-0.2.0 → pypcre-0.2.2}/tests/test_jit.py +0 -0
  42. {pypcre-0.2.0 → pypcre-0.2.2}/tests/test_memory.py +0 -0
  43. {pypcre-0.2.0 → pypcre-0.2.2}/tests/test_module.py +0 -0
  44. {pypcre-0.2.0 → pypcre-0.2.2}/tests/test_pattern.py +0 -0
  45. {pypcre-0.2.0 → pypcre-0.2.2}/tests/test_simd.py +0 -0
  46. {pypcre-0.2.0 → pypcre-0.2.2}/tests/test_threaded_backend.py +0 -0
  47. {pypcre-0.2.0 → pypcre-0.2.2}/tests/test_transformers_regex.py +0 -0
  48. {pypcre-0.2.0 → pypcre-0.2.2}/tests/test_utf8.py +0 -0
  49. {pypcre-0.2.0 → pypcre-0.2.2}/tests/test_version.py +0 -0
@@ -0,0 +1 @@
1
+ include pcre_ext/*.h
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PyPcre
3
- Version: 0.2.0
3
+ Version: 0.2.2
4
4
  Summary: Modern, GIL-friendly, Fast Python bindings for PCRE2 with auto caching and JIT of compiled patterns.
5
5
  Author-email: ModelCloud <qubitium@modelcloud.ai>
6
6
  License-Expression: Apache-2.0
@@ -43,7 +43,7 @@ Python bindings for the system PCRE2 library with a familiar `re`-style API.
43
43
  </p>
44
44
 
45
45
  ## Latest News
46
- * 10/11/2025 [0.2.0](https://github.com/ModelCloud/PyPcre/releases/tag/v0.2.0): 🤗 Full `GIL=0` compliance for Python >= 3.13T. Reduced cache thread contention. Improved performance for all api. Expanded ci testing coverage. FreeBSD, Solaris, and Windows compatibility validated.
46
+ * 10/11/2025 [0.2.1](https://github.com/ModelCloud/PyPcre/releases/tag/v0.2.1): 🤗 Full `GIL=0` compliance for Python >= 3.13T. Reduced cache thread contention. Improved performance for all api. Expanded ci testing coverage. FreeBSD, Solaris, and Windows compatibility validated.
47
47
  * 10/09/2025 [0.1.0](https://github.com/ModelCloud/PyPcre/releases/tag/v0.1.0): 🎉 First release. Thread safe, auto JIT, auto pattern caching and optimistic linking to system library for fast install.
48
48
 
49
49
  ## Why PyPcre:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: PyPcre
3
- Version: 0.2.0
3
+ Version: 0.2.2
4
4
  Summary: Modern, GIL-friendly, Fast Python bindings for PCRE2 with auto caching and JIT of compiled patterns.
5
5
  Author-email: ModelCloud <qubitium@modelcloud.ai>
6
6
  License-Expression: Apache-2.0
@@ -43,7 +43,7 @@ Python bindings for the system PCRE2 library with a familiar `re`-style API.
43
43
  </p>
44
44
 
45
45
  ## Latest News
46
- * 10/11/2025 [0.2.0](https://github.com/ModelCloud/PyPcre/releases/tag/v0.2.0): 🤗 Full `GIL=0` compliance for Python >= 3.13T. Reduced cache thread contention. Improved performance for all api. Expanded ci testing coverage. FreeBSD, Solaris, and Windows compatibility validated.
46
+ * 10/11/2025 [0.2.1](https://github.com/ModelCloud/PyPcre/releases/tag/v0.2.1): 🤗 Full `GIL=0` compliance for Python >= 3.13T. Reduced cache thread contention. Improved performance for all api. Expanded ci testing coverage. FreeBSD, Solaris, and Windows compatibility validated.
47
47
  * 10/09/2025 [0.1.0](https://github.com/ModelCloud/PyPcre/releases/tag/v0.1.0): 🎉 First release. Thread safe, auto JIT, auto pattern caching and optimistic linking to system library for fast install.
48
48
 
49
49
  ## Why PyPcre:
@@ -1,7 +1,9 @@
1
1
  LICENSE
2
+ MANIFEST.in
2
3
  README.md
3
4
  pyproject.toml
4
5
  setup.py
6
+ setup_utils.py
5
7
  PyPcre.egg-info/PKG-INFO
6
8
  PyPcre.egg-info/SOURCES.txt
7
9
  PyPcre.egg-info/dependency_links.txt
@@ -13,11 +15,14 @@ pcre/flags.py
13
15
  pcre/pcre.py
14
16
  pcre/re_compat.py
15
17
  pcre/threads.py
18
+ pcre_ext/atomic_compat.h
16
19
  pcre_ext/cache.c
17
20
  pcre_ext/error.c
18
21
  pcre_ext/flag.c
19
22
  pcre_ext/memory.c
20
23
  pcre_ext/pcre2.c
24
+ pcre_ext/pcre2.h
25
+ pcre_ext/pcre2_module.h
21
26
  pcre_ext/util.c
22
27
  tests/test_accuracy.py
23
28
  tests/test_api_parity.py
@@ -1,2 +1,3 @@
1
1
  pcre
2
2
  pcre_ext_c
3
+ setup_utils
@@ -18,7 +18,7 @@ Python bindings for the system PCRE2 library with a familiar `re`-style API.
18
18
  </p>
19
19
 
20
20
  ## Latest News
21
- * 10/11/2025 [0.2.0](https://github.com/ModelCloud/PyPcre/releases/tag/v0.2.0): 🤗 Full `GIL=0` compliance for Python >= 3.13T. Reduced cache thread contention. Improved performance for all api. Expanded ci testing coverage. FreeBSD, Solaris, and Windows compatibility validated.
21
+ * 10/11/2025 [0.2.1](https://github.com/ModelCloud/PyPcre/releases/tag/v0.2.1): 🤗 Full `GIL=0` compliance for Python >= 3.13T. Reduced cache thread contention. Improved performance for all api. Expanded ci testing coverage. FreeBSD, Solaris, and Windows compatibility validated.
22
22
  * 10/09/2025 [0.1.0](https://github.com/ModelCloud/PyPcre/releases/tag/v0.1.0): 🎉 First release. Thread safe, auto JIT, auto pattern caching and optimistic linking to system library for fast install.
23
23
 
24
24
  ## Why PyPcre:
@@ -16,16 +16,17 @@ import pcre_ext_c as _pcre2
16
16
 
17
17
  from .cache import cached_compile
18
18
  from .cache import clear_cache as _clear_cache
19
- from .flags import (
20
- COMPAT_UNICODE_ESCAPE,
21
- JIT,
22
- NO_JIT,
23
- NO_THREADS,
24
- NO_UCP,
25
- NO_UTF,
26
- THREADS,
27
- strip_py_only_flags,
28
- )
19
+ from .flags import Flag, strip_py_only_flags
20
+
21
+ # Cache frequently used flag values as plain integers to avoid the overhead of
22
+ # IntFlag arithmetic in hot paths such as module-level search helpers.
23
+ COMPAT_UNICODE_ESCAPE: int = int(Flag.COMPAT_UNICODE_ESCAPE)
24
+ THREADS: int = int(Flag.THREADS)
25
+ NO_THREADS: int = int(Flag.NO_THREADS)
26
+ JIT: int = int(Flag.JIT)
27
+ NO_JIT: int = int(Flag.NO_JIT)
28
+ NO_UTF: int = int(Flag.NO_UTF)
29
+ NO_UCP: int = int(Flag.NO_UCP)
29
30
  from .re_compat import (
30
31
  Match,
31
32
  TemplatePatternStub,
@@ -0,0 +1,365 @@
1
+ // SPDX-FileCopyrightText: 2025 ModelCloud.ai
2
+ // SPDX-FileCopyrightText: 2025 qubitium@modelcloud.ai
3
+ // SPDX-License-Identifier: Apache-2.0
4
+ // Contact: qubitium@modelcloud.ai, x.com/qubitium
5
+
6
+ #ifndef ATOMIC_COMPAT_H
7
+ #define ATOMIC_COMPAT_H
8
+
9
+ #include <stddef.h>
10
+ #include <stdint.h>
11
+
12
+ #ifdef __cplusplus
13
+ extern "C" {
14
+ #endif
15
+
16
+ /* ===================================================================== */
17
+ /* MSVC IMPLEMENTATION */
18
+ /* ===================================================================== */
19
+ #if defined(_MSC_VER)
20
+
21
+ #if defined(__has_include)
22
+ # if !defined(__STDC_NO_ATOMICS__) && __has_include(<stdatomic.h>)
23
+ # include <stdatomic.h>
24
+ # define ATOMIC_COMPAT_USE_NATIVE_ATOMICS 1
25
+ # endif
26
+ #endif
27
+
28
+ #if defined(ATOMIC_COMPAT_USE_NATIVE_ATOMICS)
29
+
30
+ #define ATOMIC_COMPAT_HAVE_ATOMICS 1
31
+ #define ATOMIC_VAR(type) _Atomic(type)
32
+ #ifndef ATOMIC_VAR_INIT
33
+ # define ATOMIC_VAR_INIT(value) (value)
34
+ #endif
35
+
36
+ #else /* !ATOMIC_COMPAT_USE_NATIVE_ATOMICS */
37
+
38
+ #include <windows.h>
39
+ #include <intrin.h>
40
+
41
+ /* Feature flag & storage qualifier (GNU-style on MSVC). */
42
+ #define ATOMIC_COMPAT_HAVE_ATOMICS 1
43
+ #define ATOMIC_VAR(type) volatile type
44
+ #ifndef ATOMIC_VAR_INIT
45
+ # define ATOMIC_VAR_INIT(value) (value)
46
+ #endif
47
+
48
+ /* --------------------------------------------------------------------- */
49
+ /* 1) Nuke vcruntime <stdatomic.h> macros if they were included already. */
50
+ /* This prevents expansions to __c11_atomic_* builtins on MSVC. */
51
+ /* --------------------------------------------------------------------- */
52
+
53
+ #if defined(atomic_init)
54
+ # undef atomic_init
55
+ #endif
56
+
57
+ #if defined(atomic_thread_fence)
58
+ # undef atomic_thread_fence
59
+ #endif
60
+ #if defined(atomic_signal_fence)
61
+ # undef atomic_signal_fence
62
+ #endif
63
+
64
+ #if defined(atomic_load)
65
+ # undef atomic_load
66
+ #endif
67
+ #if defined(atomic_load_explicit)
68
+ # undef atomic_load_explicit
69
+ #endif
70
+
71
+ #if defined(atomic_store)
72
+ # undef atomic_store
73
+ #endif
74
+ #if defined(atomic_store_explicit)
75
+ # undef atomic_store_explicit
76
+ #endif
77
+
78
+ #if defined(atomic_exchange)
79
+ # undef atomic_exchange
80
+ #endif
81
+ #if defined(atomic_exchange_explicit)
82
+ # undef atomic_exchange_explicit
83
+ #endif
84
+
85
+ #if defined(atomic_fetch_add)
86
+ # undef atomic_fetch_add
87
+ #endif
88
+ #if defined(atomic_fetch_add_explicit)
89
+ # undef atomic_fetch_add_explicit
90
+ #endif
91
+
92
+ #if defined(atomic_fetch_sub)
93
+ # undef atomic_fetch_sub
94
+ #endif
95
+ #if defined(atomic_fetch_sub_explicit)
96
+ # undef atomic_fetch_sub_explicit
97
+ #endif
98
+
99
+ #if defined(atomic_compare_exchange_strong)
100
+ # undef atomic_compare_exchange_strong
101
+ #endif
102
+ #if defined(atomic_compare_exchange_strong_explicit)
103
+ # undef atomic_compare_exchange_strong_explicit
104
+ #endif
105
+ #if defined(atomic_compare_exchange_weak)
106
+ # undef atomic_compare_exchange_weak
107
+ #endif
108
+ #if defined(atomic_compare_exchange_weak_explicit)
109
+ # undef atomic_compare_exchange_weak_explicit
110
+ #endif
111
+
112
+ #if defined(atomic_flag_test_and_set)
113
+ # undef atomic_flag_test_and_set
114
+ #endif
115
+ #if defined(atomic_flag_test_and_set_explicit)
116
+ # undef atomic_flag_test_and_set_explicit
117
+ #endif
118
+ #if defined(atomic_flag_clear)
119
+ # undef atomic_flag_clear
120
+ #endif
121
+ #if defined(atomic_flag_clear_explicit)
122
+ # undef atomic_flag_clear_explicit
123
+ #endif
124
+
125
+ /* --------------------------------------------------------------------- */
126
+ /* 2) C11 memory orders (accepted, enforced >= seq_cst where relevant). */
127
+ /* --------------------------------------------------------------------- */
128
+ typedef enum {
129
+ memory_order_relaxed = 0,
130
+ memory_order_consume = 1, /* treat as acquire */
131
+ memory_order_acquire = 2,
132
+ memory_order_release = 3,
133
+ memory_order_acq_rel = 4,
134
+ memory_order_seq_cst = 5
135
+ } memory_order;
136
+
137
+ static __forceinline void atomic_thread_fence(memory_order order) {
138
+ (void)order;
139
+ /* Full fence (at-least seq_cst). */
140
+ MemoryBarrier();
141
+ }
142
+ static __forceinline void atomic_signal_fence(memory_order order) {
143
+ (void)order;
144
+ /* Compiler barrier only. */
145
+ _ReadWriteBarrier();
146
+ }
147
+
148
+ /* --------------------------------------------------------------------- */
149
+ /* 3) Low-level typed helpers backed by Interlocked primitives. */
150
+ /* (All provide at-least seq_cst.) */
151
+ /* --------------------------------------------------------------------- */
152
+
153
+ /* 32-bit */
154
+ static __forceinline int32_t ac_load_i32 (volatile int32_t *p) { return (int32_t)InterlockedCompareExchange((volatile LONG*)p, 0, 0); }
155
+ static __forceinline uint32_t ac_load_u32 (volatile uint32_t *p) { return (uint32_t)InterlockedCompareExchange((volatile LONG*)p, 0, 0); }
156
+ static __forceinline void ac_store_i32(volatile int32_t *p, int32_t v) { InterlockedExchange((volatile LONG*)p, (LONG)v); }
157
+ static __forceinline void ac_store_u32(volatile uint32_t *p, uint32_t v) { InterlockedExchange((volatile LONG*)p, (LONG)v); }
158
+ static __forceinline int32_t ac_xchg_i32 (volatile int32_t *p, int32_t v) { return (int32_t)InterlockedExchange((volatile LONG*)p, (LONG)v); }
159
+ static __forceinline uint32_t ac_xchg_u32 (volatile uint32_t *p, uint32_t v) { return (uint32_t)InterlockedExchange((volatile LONG*)p, (LONG)v); }
160
+ static __forceinline int32_t ac_fadd_i32 (volatile int32_t *p, int32_t v) { return (int32_t)InterlockedExchangeAdd((volatile LONG*)p, (LONG)v); }
161
+ static __forceinline uint32_t ac_fadd_u32 (volatile uint32_t *p, uint32_t v) { return (uint32_t)InterlockedExchangeAdd((volatile LONG*)p, (LONG)v); }
162
+ static __forceinline int ac_cas_i32 (volatile int32_t *p, int32_t *e, int32_t d) {
163
+ LONG orig = InterlockedCompareExchange((volatile LONG*)p, (LONG)d, (LONG)*e);
164
+ if ((int32_t)orig == *e) return 1;
165
+ *e = (int32_t)orig; return 0;
166
+ }
167
+ static __forceinline int ac_cas_u32 (volatile uint32_t *p, uint32_t *e, uint32_t d) {
168
+ LONG orig = InterlockedCompareExchange((volatile LONG*)p, (LONG)d, (LONG)*e);
169
+ if ((uint32_t)orig == *e) return 1;
170
+ *e = (uint32_t)orig; return 0;
171
+ }
172
+
173
+ /* 64-bit */
174
+ static __forceinline int64_t ac_load_i64 (volatile int64_t *p) { return (int64_t)InterlockedCompareExchange64((volatile LONGLONG*)p, 0, 0); }
175
+ static __forceinline uint64_t ac_load_u64 (volatile uint64_t *p) { return (uint64_t)InterlockedCompareExchange64((volatile LONGLONG*)p, 0, 0); }
176
+ static __forceinline void ac_store_i64(volatile int64_t *p, int64_t v) { InterlockedExchange64((volatile LONGLONG*)p, (LONGLONG)v); }
177
+ static __forceinline void ac_store_u64(volatile uint64_t *p, uint64_t v) { InterlockedExchange64((volatile LONGLONG*)p, (LONGLONG)v); }
178
+ static __forceinline int64_t ac_xchg_i64 (volatile int64_t *p, int64_t v) { return (int64_t)InterlockedExchange64((volatile LONGLONG*)p, (LONGLONG)v); }
179
+ static __forceinline uint64_t ac_xchg_u64 (volatile uint64_t *p, uint64_t v) { return (uint64_t)InterlockedExchange64((volatile LONGLONG*)p, (LONGLONG)v); }
180
+ static __forceinline int64_t ac_fadd_i64 (volatile int64_t *p, int64_t v) { return (int64_t)InterlockedExchangeAdd64((volatile LONGLONG*)p, (LONGLONG)v); }
181
+ static __forceinline uint64_t ac_fadd_u64 (volatile uint64_t *p, uint64_t v) { return (uint64_t)InterlockedExchangeAdd64((volatile LONGLONG*)p, (LONGLONG)v); }
182
+ static __forceinline int ac_cas_i64 (volatile int64_t *p, int64_t *e, int64_t d) {
183
+ LONGLONG orig = InterlockedCompareExchange64((volatile LONGLONG*)p, (LONGLONG)d, (LONGLONG)*e);
184
+ if ((int64_t)orig == *e) return 1;
185
+ *e = (int64_t)orig; return 0;
186
+ }
187
+ static __forceinline int ac_cas_u64 (volatile uint64_t *p, uint64_t *e, uint64_t d) {
188
+ LONGLONG orig = InterlockedCompareExchange64((volatile LONGLONG*)p, (LONGLONG)d, (LONGLONG)*e);
189
+ if ((uint64_t)orig == *e) return 1;
190
+ *e = (uint64_t)orig; return 0;
191
+ }
192
+
193
+ /* size_t */
194
+ static __forceinline size_t ac_load_size (volatile size_t *p) {
195
+ #if defined(_WIN64)
196
+ return (size_t)InterlockedCompareExchange64((volatile LONGLONG*)p, 0, 0);
197
+ #else
198
+ return (size_t)InterlockedCompareExchange((volatile LONG*)p, 0, 0);
199
+ #endif
200
+ }
201
+ static __forceinline void ac_store_size(volatile size_t *p, size_t v) {
202
+ #if defined(_WIN64)
203
+ InterlockedExchange64((volatile LONGLONG*)p, (LONGLONG)v);
204
+ #else
205
+ InterlockedExchange((volatile LONG*)p, (LONG)v);
206
+ #endif
207
+ }
208
+
209
+ /* pointers */
210
+ static __forceinline void *ac_load_ptr (void * volatile *p) { return InterlockedCompareExchangePointer(p, NULL, NULL); }
211
+ static __forceinline void ac_store_ptr(void * volatile *p, void *v) { InterlockedExchangePointer(p, v); }
212
+ static __forceinline void *ac_xchg_ptr (void * volatile *p, void *v) { return InterlockedExchangePointer(p, v); }
213
+ static __forceinline int ac_cas_ptr (void * volatile *p, void **e, void *d) {
214
+ void *orig = InterlockedCompareExchangePointer(p, d, *e);
215
+ if (orig == *e) return 1;
216
+ *e = orig; return 0;
217
+ }
218
+
219
+ /* --------------------------------------------------------------------- */
220
+ /* 4) GNU-style, type-directed macros via _Generic (C mode on MSVC 2022).*/
221
+ /* These work on *plain* volatile T* (no _Atomic required). */
222
+ /* --------------------------------------------------------------------- */
223
+
224
+ /* Load */
225
+ #define atomic_compat_load(ptr) \
226
+ _Generic((ptr), \
227
+ /* signed */ volatile int32_t *: ac_load_i32((volatile int32_t*)(ptr)), \
228
+ int32_t *: ac_load_i32((volatile int32_t*)(ptr)), \
229
+ /* unsigned */ volatile uint32_t *: ac_load_u32((volatile uint32_t*)(ptr)), \
230
+ uint32_t *: ac_load_u32((volatile uint32_t*)(ptr)), \
231
+ /* size_t */ volatile size_t *: ac_load_size((volatile size_t*)(ptr)), \
232
+ size_t *: ac_load_size((volatile size_t*)(ptr)), \
233
+ /* pointer */ default: ac_load_ptr((void * volatile *)(ptr)) \
234
+ )
235
+
236
+ /* Store */
237
+ #define atomic_compat_store(ptr, value) \
238
+ _Generic((ptr), \
239
+ /* signed */ volatile int32_t *: ac_store_i32((volatile int32_t*)(ptr), (int32_t)(value)), \
240
+ int32_t *: ac_store_i32((volatile int32_t*)(ptr), (int32_t)(value)), \
241
+ /* unsigned */ volatile uint32_t *: ac_store_u32((volatile uint32_t*)(ptr), (uint32_t)(value)), \
242
+ uint32_t *: ac_store_u32((volatile uint32_t*)(ptr), (uint32_t)(value)), \
243
+ /* size_t */ volatile size_t *: ac_store_size((volatile size_t*)(ptr), (size_t)(value)), \
244
+ size_t *: ac_store_size((volatile size_t*)(ptr), (size_t)(value)), \
245
+ /* pointer */ default: ac_store_ptr((void * volatile *)(ptr), (void*)(value)) \
246
+ )
247
+
248
+ /* Exchange */
249
+ #define atomic_compat_exchange(ptr, value) \
250
+ _Generic((ptr), \
251
+ /* signed */ volatile int32_t *: (int32_t) ac_xchg_i32((volatile int32_t*)(ptr), (int32_t)(value)), \
252
+ int32_t *: (int32_t) ac_xchg_i32((volatile int32_t*)(ptr), (int32_t)(value)), \
253
+ /* unsigned */ volatile uint32_t *: (uint32_t)ac_xchg_u32((volatile uint32_t*)(ptr), (uint32_t)(value)), \
254
+ uint32_t *: (uint32_t)ac_xchg_u32((volatile uint32_t*)(ptr), (uint32_t)(value)), \
255
+ /* pointer */ default: ac_xchg_ptr((void * volatile *)(ptr), (void*)(value)) \
256
+ )
257
+
258
+ /* Fetch add / sub (integers only) */
259
+ #define atomic_compat_fetch_add(ptr, value) \
260
+ _Generic((ptr), \
261
+ volatile int32_t *: (int32_t) ac_fadd_i32((volatile int32_t*)(ptr), (int32_t)(value)), \
262
+ int32_t *: (int32_t) ac_fadd_i32((volatile int32_t*)(ptr), (int32_t)(value)), \
263
+ volatile uint32_t *: (uint32_t)ac_fadd_u32((volatile uint32_t*)(ptr), (uint32_t)(value)), \
264
+ uint32_t *: (uint32_t)ac_fadd_u32((volatile uint32_t*)(ptr), (uint32_t)(value)) \
265
+ )
266
+
267
+ #define atomic_compat_fetch_sub(ptr, value) \
268
+ _Generic((ptr), \
269
+ volatile int32_t *: (int32_t) ac_fadd_i32((volatile int32_t*)(ptr), (int32_t)-(value)), \
270
+ int32_t *: (int32_t) ac_fadd_i32((volatile int32_t*)(ptr), (int32_t)-(value)), \
271
+ volatile uint32_t *: (uint32_t)ac_fadd_u32((volatile uint32_t*)(ptr), (uint32_t)-(value)), \
272
+ uint32_t *: (uint32_t)ac_fadd_u32((volatile uint32_t*)(ptr), (uint32_t)-(value)) \
273
+ )
274
+
275
+ /* Compare-exchange (C11 rules: update *expected on failure) */
276
+ #define atomic_compat_compare_exchange(ptr, expected, desired) \
277
+ _Generic((ptr), \
278
+ volatile int32_t *: ac_cas_i32((volatile int32_t*)(ptr), (int32_t*)(expected), (int32_t)(desired)), \
279
+ int32_t *: ac_cas_i32((volatile int32_t*)(ptr), (int32_t*)(expected), (int32_t)(desired)), \
280
+ volatile uint32_t *: ac_cas_u32((volatile uint32_t*)(ptr), (uint32_t*)(expected), (uint32_t)(desired)), \
281
+ uint32_t *: ac_cas_u32((volatile uint32_t*)(ptr), (uint32_t*)(expected), (uint32_t)(desired)), \
282
+ default: ac_cas_ptr((void * volatile *)(ptr), (void**)(expected), (void*)(desired)) \
283
+ )
284
+
285
+ /* --------------------------------------------------------------------- */
286
+ /* 5) Public C11-like API (explicit + default seq_cst variants). */
287
+ /* These *do not* require _Atomic-qualified objects on MSVC. */
288
+ /* --------------------------------------------------------------------- */
289
+
290
+ #define atomic_init(obj, value) \
291
+ atomic_compat_store((obj), (value))
292
+
293
+ #define atomic_load_explicit(ptr, order) \
294
+ ( (void)(order), atomic_compat_load(ptr) )
295
+
296
+ #define atomic_store_explicit(ptr, value, order) \
297
+ do { (void)(order); atomic_compat_store((ptr), (value)); } while (0)
298
+
299
+ #define atomic_exchange_explicit(ptr, value, order) \
300
+ ( (void)(order), atomic_compat_exchange((ptr), (value)) )
301
+
302
+ #define atomic_fetch_add_explicit(ptr, value, order) \
303
+ ( (void)(order), atomic_compat_fetch_add((ptr), (value)) )
304
+
305
+ #define atomic_fetch_sub_explicit(ptr, value, order) \
306
+ ( (void)(order), atomic_compat_fetch_sub((ptr), (value)) )
307
+
308
+ #define atomic_compare_exchange_strong_explicit(ptr, expected, desired, success_order, failure_order) \
309
+ ( (void)(success_order), (void)(failure_order), atomic_compat_compare_exchange((ptr), (expected), (desired)) )
310
+
311
+ #define atomic_compare_exchange_weak_explicit(ptr, expected, desired, success_order, failure_order) \
312
+ atomic_compare_exchange_strong_explicit(ptr, expected, desired, success_order, failure_order)
313
+
314
+ /* seq_cst defaults per C11 */
315
+ #define atomic_load(ptr) atomic_load_explicit((ptr), memory_order_seq_cst)
316
+ #define atomic_store(ptr, value) atomic_store_explicit((ptr), (value), memory_order_seq_cst)
317
+ #define atomic_exchange(ptr, value) atomic_exchange_explicit((ptr), (value), memory_order_seq_cst)
318
+ #define atomic_fetch_add(ptr, value) atomic_fetch_add_explicit((ptr), (value), memory_order_seq_cst)
319
+ #define atomic_fetch_sub(ptr, value) atomic_fetch_sub_explicit((ptr), (value), memory_order_seq_cst)
320
+ #define atomic_compare_exchange_strong(ptr,e,d) atomic_compare_exchange_strong_explicit((ptr),(e),(d), memory_order_acq_rel, memory_order_acquire)
321
+ #define atomic_compare_exchange_weak(ptr,e,d) atomic_compare_exchange_weak_explicit((ptr),(e),(d), memory_order_acq_rel, memory_order_acquire)
322
+
323
+ /* atomic_flag support:
324
+ - If vcruntime already typedefs atomic_flag, we only provide the API macros.
325
+ - If not, we provide a minimal struct + API. */
326
+ #ifndef ATOMIC_FLAG_INIT
327
+ # define ATOMIC_FLAG_INIT { 0 }
328
+ #endif
329
+
330
+ /* Minimal atomic_flag replacement for the compatibility path. */
331
+ typedef struct {
332
+ volatile LONG _v;
333
+ } atomic_flag;
334
+
335
+ static __forceinline int atomic_flag_test_and_set_explicit(atomic_flag *obj, memory_order order) {
336
+ (void)order;
337
+ /* Returns previous value (true if already set). */
338
+ LONG prev = InterlockedExchange(&obj->_v, 1);
339
+ return prev != 0;
340
+ }
341
+ static __forceinline void atomic_flag_clear_explicit(atomic_flag *obj, memory_order order) {
342
+ (void)order;
343
+ InterlockedExchange(&obj->_v, 0);
344
+ }
345
+ #define atomic_flag_test_and_set(obj) atomic_flag_test_and_set_explicit((obj), memory_order_seq_cst)
346
+ #define atomic_flag_clear(obj) atomic_flag_clear_explicit((obj), memory_order_seq_cst)
347
+
348
+ #endif /* ATOMIC_COMPAT_USE_NATIVE_ATOMICS */
349
+
350
+ /* ===================================================================== */
351
+ /* NON-MSVC (use real C11) */
352
+ /* ===================================================================== */
353
+ #else /* !_MSC_VER */
354
+
355
+ # include <stdatomic.h>
356
+ # define ATOMIC_COMPAT_HAVE_ATOMICS 1
357
+ # define ATOMIC_VAR(type) _Atomic(type)
358
+
359
+ #endif /* _MSC_VER */
360
+
361
+ #ifdef __cplusplus
362
+ } /* extern "C" */
363
+ #endif
364
+
365
+ #endif /* ATOMIC_COMPAT_H */