quasardb 3.14.2.dev1__cp312-cp312-win_amd64.whl → 3.14.2.dev4__cp312-cp312-win_amd64.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.

Potentially problematic release.


This version of quasardb might be problematic. Click here for more details.

Files changed (96) hide show
  1. quasardb/INSTALL.vcxproj +10 -5
  2. quasardb/__init__.py +33 -4
  3. quasardb/cmake_install.cmake +6 -0
  4. quasardb/date/ALL_BUILD.vcxproj +10 -9
  5. quasardb/date/CMakeFiles/Export/df49adab93b9e0c10c64f72458b31971/dateTargets.cmake +13 -13
  6. quasardb/date/CMakeFiles/generate.stamp.depend +4 -4
  7. quasardb/date/INSTALL.vcxproj +10 -5
  8. quasardb/date/cmake_install.cmake +6 -0
  9. quasardb/date/dateConfigVersion.cmake +0 -5
  10. quasardb/date/dateTargets.cmake +4 -8
  11. quasardb/numpy/__init__.py +58 -10
  12. quasardb/pandas/__init__.py +58 -102
  13. quasardb/pybind11/ALL_BUILD.vcxproj +10 -9
  14. quasardb/pybind11/CMakeFiles/generate.stamp.depend +14 -14
  15. quasardb/pybind11/INSTALL.vcxproj +10 -5
  16. quasardb/pybind11/cmake_install.cmake +6 -0
  17. quasardb/qdb_api.dll +0 -0
  18. quasardb/quasardb.cp312-win_amd64.pyd +0 -0
  19. quasardb/range-v3/ALL_BUILD.vcxproj +10 -9
  20. quasardb/range-v3/CMakeFiles/Export/d94ef200eca10a819b5858b33e808f5b/range-v3-targets.cmake +13 -13
  21. quasardb/range-v3/CMakeFiles/generate.stamp.depend +11 -11
  22. quasardb/range-v3/INSTALL.vcxproj +10 -5
  23. quasardb/range-v3/cmake_install.cmake +42 -0
  24. quasardb/range-v3/range-v3-config-version.cmake +0 -5
  25. quasardb/range-v3/range-v3-config.cmake +4 -8
  26. quasardb/range-v3/range.v3.headers.vcxproj +10 -9
  27. {quasardb-3.14.2.dev1.dist-info → quasardb-3.14.2.dev4.dist-info}/METADATA +15 -10
  28. quasardb-3.14.2.dev4.dist-info/RECORD +54 -0
  29. {quasardb-3.14.2.dev1.dist-info → quasardb-3.14.2.dev4.dist-info}/WHEEL +1 -1
  30. quasardb/CMakeLists.txt +0 -510
  31. quasardb/batch_column.hpp +0 -80
  32. quasardb/batch_inserter.hpp +0 -248
  33. quasardb/blob.hpp +0 -150
  34. quasardb/cluster.cpp +0 -89
  35. quasardb/cluster.hpp +0 -551
  36. quasardb/concepts.hpp +0 -278
  37. quasardb/continuous.cpp +0 -149
  38. quasardb/continuous.hpp +0 -106
  39. quasardb/convert/array.hpp +0 -282
  40. quasardb/convert/point.hpp +0 -330
  41. quasardb/convert/range.hpp +0 -282
  42. quasardb/convert/unicode.hpp +0 -598
  43. quasardb/convert/util.hpp +0 -22
  44. quasardb/convert/value.hpp +0 -711
  45. quasardb/convert.hpp +0 -38
  46. quasardb/detail/qdb_resource.hpp +0 -129
  47. quasardb/detail/ts_column.hpp +0 -224
  48. quasardb/direct_blob.hpp +0 -108
  49. quasardb/direct_handle.hpp +0 -83
  50. quasardb/direct_integer.hpp +0 -94
  51. quasardb/dispatch.hpp +0 -157
  52. quasardb/double.hpp +0 -87
  53. quasardb/entry.hpp +0 -273
  54. quasardb/error.hpp +0 -318
  55. quasardb/handle.cpp +0 -29
  56. quasardb/handle.hpp +0 -98
  57. quasardb/integer.hpp +0 -88
  58. quasardb/logger.cpp +0 -106
  59. quasardb/logger.hpp +0 -228
  60. quasardb/masked_array.hpp +0 -651
  61. quasardb/metrics.cpp +0 -103
  62. quasardb/metrics.hpp +0 -112
  63. quasardb/module.cpp +0 -76
  64. quasardb/module.hpp +0 -24
  65. quasardb/node.hpp +0 -123
  66. quasardb/numpy.cpp +0 -6
  67. quasardb/numpy.hpp +0 -489
  68. quasardb/object_tracker.hpp +0 -283
  69. quasardb/options.hpp +0 -244
  70. quasardb/perf.hpp +0 -336
  71. quasardb/pytypes.hpp +0 -221
  72. quasardb/query.cpp +0 -420
  73. quasardb/query.hpp +0 -92
  74. quasardb/reader/ts_row.hpp +0 -281
  75. quasardb/reader/ts_value.hpp +0 -245
  76. quasardb/remove_cvref.hpp +0 -31
  77. quasardb/string.hpp +0 -160
  78. quasardb/table.cpp +0 -289
  79. quasardb/table.hpp +0 -325
  80. quasardb/table_reader.hpp +0 -220
  81. quasardb/tag.hpp +0 -77
  82. quasardb/timestamp.hpp +0 -97
  83. quasardb/traits.hpp +0 -619
  84. quasardb/ts_iterator.hpp +0 -193
  85. quasardb/utils/blob_deque.hpp +0 -96
  86. quasardb/utils/ostream.hpp +0 -17
  87. quasardb/utils/permutation.hpp +0 -50
  88. quasardb/utils/stable_sort.hpp +0 -25
  89. quasardb/utils/unzip_view.hpp +0 -89
  90. quasardb/utils.cpp +0 -28
  91. quasardb/utils.hpp +0 -174
  92. quasardb/writer.cpp +0 -534
  93. quasardb/writer.hpp +0 -396
  94. quasardb-3.14.2.dev1.dist-info/RECORD +0 -118
  95. {quasardb-3.14.2.dev1.dist-info → quasardb-3.14.2.dev4.dist-info}/LICENSE.md +0 -0
  96. {quasardb-3.14.2.dev1.dist-info → quasardb-3.14.2.dev4.dist-info}/top_level.txt +0 -0
@@ -1,711 +0,0 @@
1
- /*
2
- *
3
- * Official Python API
4
- *
5
- * Copyright (c) 2009-2024, quasardb SAS. All rights reserved.
6
- * All rights reserved.
7
- *
8
- * Redistribution and use in source and binary forms, with or without
9
- * modification, are permitted provided that the following conditions are met:
10
- *
11
- * * Redistributions of source code must retain the above copyright
12
- * notice, this list of conditions and the following disclaimer.
13
- * * Redistributions in binary form must reproduce the above copyright
14
- * notice, this list of conditions and the following disclaimer in the
15
- * documentation and/or other materials provided with the distribution.
16
- * * Neither the name of quasardb nor the names of its contributors may
17
- * be used to endorse or promote products derived from this software
18
- * without specific prior written permission.
19
- *
20
- * THIS SOFTWARE IS PROVIDED BY QUASARDB AND CONTRIBUTORS ``AS IS'' AND ANY
21
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
- * DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
24
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
27
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
29
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
- */
31
- #pragma once
32
-
33
- #include "../concepts.hpp"
34
- #include "../error.hpp"
35
- #include "../object_tracker.hpp"
36
- #include "../pytypes.hpp"
37
- #include "../traits.hpp"
38
- #include "unicode.hpp"
39
- #include <qdb/ts.h>
40
- #include <date/date.h> // We cannot use <chrono> until we upgrade to at least GCC11 (ARM).
41
- #include <pybind11/pybind11.h>
42
- #include <range/v3/algorithm/copy.hpp>
43
- #include <range/v3/algorithm/for_each.hpp>
44
- #include <range/v3/range/concepts.hpp>
45
- #include <range/v3/view/counted.hpp>
46
- #include <chrono>
47
- #include <cstring>
48
-
49
- namespace qdb::convert::detail
50
- {
51
-
52
- namespace py = pybind11;
53
- typedef std::remove_cvref<decltype(qdb_string_t::data[0])>::type qdb_char_type;
54
-
55
- ////////////////////////////////////////////////////////////////////////////////
56
- //
57
- // VALUE CONVERTERS
58
- //
59
- ///////////////////
60
- //
61
- // These converters operate on individual values, with various degrees of
62
- // complexity.
63
- //
64
- ////////////////////////////////////////////////////////////////////////////////
65
-
66
- template <typename From, typename To>
67
- struct value_converter;
68
-
69
- template <typename From, typename To>
70
- requires(std::is_same_v<From, To>)
71
- struct value_converter<From, To>
72
- {
73
- inline To operator()(From const & x) const
74
- {
75
- static_assert(sizeof(To) >= sizeof(From));
76
- // Default implementation for "simple" conversions allowed by the compiler,
77
- // e.g. int32 to int64.
78
- return x;
79
- }
80
- };
81
-
82
- template <typename To>
83
- struct value_converter<traits::int64_dtype, To> : public value_converter<std::int64_t, To>
84
- {};
85
-
86
- template <typename To>
87
- struct value_converter<traits::int32_dtype, To> : public value_converter<std::int32_t, To>
88
- {};
89
-
90
- template <typename To>
91
- struct value_converter<traits::int16_dtype, To> : public value_converter<std::int16_t, To>
92
- {};
93
-
94
- template <typename From>
95
- struct value_converter<From, traits::int64_dtype> : public value_converter<From, std::int64_t>
96
- {};
97
-
98
- template <typename From>
99
- struct value_converter<From, traits::int32_dtype> : public value_converter<From, std::int32_t>
100
- {};
101
-
102
- template <typename From>
103
- struct value_converter<From, traits::int16_dtype> : public value_converter<From, std::int16_t>
104
- {};
105
-
106
- template <typename To>
107
- struct value_converter<traits::float64_dtype, To> : public value_converter<double, To>
108
- {};
109
-
110
- template <typename To>
111
- struct value_converter<traits::float32_dtype, To> : public value_converter<float, To>
112
- {};
113
-
114
- template <typename From>
115
- struct value_converter<From, traits::float64_dtype> : public value_converter<From, double>
116
- {};
117
-
118
- template <typename From>
119
- struct value_converter<From, traits::float32_dtype> : public value_converter<From, float>
120
- {};
121
-
122
- template <typename From>
123
- struct value_converter<From, traits::pyobject_dtype> : public value_converter<From, py::object>
124
- {};
125
-
126
- ////////////////////////////////////////////////////////////////////////////////
127
- //
128
- // qdb_timespec_t converters
129
- //
130
- ///////////////////
131
- //
132
- // These converters focus on converting qdb_timespec_t to/from other types.
133
- //
134
- /////
135
-
136
- using clock_t = std::chrono::system_clock;
137
-
138
- // Explicitly specifying the durations here, rather than relying on type
139
- // inference of the integer type, avoids pitfalls like Python using an
140
- // `int` to represent seconds which isn't enough for chrono.
141
- using nanoseconds_t = std::chrono::duration<std::int64_t, std::nano>;
142
- using microseconds_t = std::chrono::duration<std::int64_t, std::micro>;
143
- using milliseconds_t = std::chrono::duration<std::int64_t, std::milli>;
144
- using seconds_t = std::chrono::duration<std::int64_t>;
145
- using minutes_t = std::chrono::duration<std::int32_t, std::ratio<60>>;
146
- using hours_t = std::chrono::duration<std::int32_t, std::ratio<3600>>;
147
- using days_t = std::chrono::duration<std::int32_t, std::ratio<86400>>;
148
- using weeks_t = std::chrono::duration<std::int32_t, std::ratio<604800>>;
149
- using months_t = std::chrono::duration<std::int32_t, std::ratio<2629746>>;
150
- using years_t = std::chrono::duration<std::int32_t, std::ratio<31556952>>;
151
-
152
- /**
153
- * datetime.timedelta -> std::chrono::duration
154
- *
155
- * Useful for converting a datetime timezone offset to a chrono duration, among others.
156
- */
157
- template <>
158
- struct value_converter<qdb::pytimedelta, clock_t::duration>
159
- {
160
- inline std::chrono::system_clock::duration operator()(pytimedelta const & x) const
161
- {
162
- assert(x.is_none() == false);
163
-
164
- static_assert(sizeof(decltype(x.days())) <= sizeof(days_t::rep));
165
- static_assert(sizeof(decltype(x.seconds())) <= sizeof(seconds_t::rep));
166
- static_assert(sizeof(decltype(x.microseconds())) <= sizeof(microseconds_t::rep));
167
-
168
- return days_t{x.days()} + seconds_t{x.seconds()} + microseconds_t{x.microseconds()};
169
- }
170
- };
171
-
172
- /**
173
- * datetime.datetime -> std::chrono::time_point
174
- *
175
- * Takes the input datetime, and converts it to a time point. ensures that the timezone
176
- * offset of datetime is taken into account, and output time_point is in UTC.
177
- */
178
-
179
- template <>
180
- struct value_converter<qdb::pydatetime, clock_t::time_point>
181
- {
182
- value_converter<qdb::pytimedelta, clock_t::duration> offset_convert_{};
183
-
184
- inline clock_t::time_point operator()(qdb::pydatetime const & x) const
185
-
186
- {
187
- // Construct the date
188
- date::year_month_day ymd{
189
- date::year{x.year()}, date::month{(unsigned)x.month()}, date::day{(unsigned)x.day()}};
190
-
191
- // Calculate the number of days since epoch
192
- date::sys_days days_since_epoch{ymd};
193
-
194
- static_assert(sizeof(decltype(x.hour())) <= sizeof(hours_t::rep));
195
- static_assert(sizeof(decltype(x.second())) <= sizeof(seconds_t::rep));
196
- static_assert(sizeof(decltype(x.microsecond())) <= sizeof(microseconds_t::rep));
197
-
198
- // Calculate the time of day as a duration
199
- clock_t::duration time_of_day{hours_t{x.hour()} + minutes_t{x.minute()} + seconds_t{x.second()}
200
- + microseconds_t{x.microsecond()}};
201
-
202
- // Adjust for UTC
203
- clock_t::duration tz_offset = offset_convert_(x.utcoffset());
204
-
205
- // Compose the whole thing together
206
- return clock_t::time_point(days_since_epoch) + time_of_day - tz_offset;
207
- }
208
- };
209
-
210
- template <>
211
- struct value_converter<std::int64_t, qdb_timespec_t>
212
- {
213
- inline constexpr qdb_timespec_t operator()(std::int64_t const & x) const
214
- {
215
- if (x < 0) [[unlikely]]
216
- {
217
- return qdb_timespec_t{qdb_min_time, qdb_min_time};
218
- }
219
-
220
- constexpr std::int64_t ns = 1'000'000'000ull;
221
- std::int64_t tv_nsec = x % ns;
222
- std::int64_t tv_sec = (x - tv_nsec) / ns;
223
-
224
- return qdb_timespec_t{tv_sec, tv_nsec};
225
- }
226
- };
227
-
228
- /**
229
- * chrono time_point -> qdb_timespec_t
230
- *
231
- * First converts timepoint to nanos since epoch, then delegates to another converter.
232
- */
233
- template <>
234
- struct value_converter<clock_t::time_point, qdb_timespec_t>
235
- {
236
- value_converter<std::int64_t, qdb_timespec_t> delegate_{};
237
-
238
- inline constexpr qdb_timespec_t operator()(clock_t::time_point const & x) const
239
- {
240
- auto nanos = std::chrono::duration_cast<nanoseconds_t>(x.time_since_epoch());
241
-
242
- return delegate_(nanos.count());
243
- }
244
- };
245
-
246
- /**
247
- * clock_t::time_point -> qdb_time_t
248
- *
249
- * Returns the qdb_time_t representation of a time_point; qdb_time_t is assumed
250
- * to be using milliseconds.
251
- */
252
- template <>
253
- struct value_converter<clock_t::time_point, qdb_time_t>
254
- {
255
- inline qdb_time_t operator()(clock_t::time_point const & x) const
256
- {
257
- auto time_since_epoch = x.time_since_epoch();
258
-
259
- return static_cast<qdb_time_t>(
260
- std::chrono::duration_cast<milliseconds_t>(time_since_epoch).count());
261
- }
262
- };
263
-
264
- /**
265
- * datetime.datetime -> qdb_time_t
266
- */
267
- template <>
268
- struct value_converter<qdb::pydatetime, qdb_time_t>
269
- {
270
- value_converter<qdb::pydatetime, clock_t::time_point> dt_to_tp_{};
271
- value_converter<clock_t::time_point, qdb_time_t> tp_to_qt_{};
272
-
273
- inline qdb_time_t operator()(pydatetime const & x) const
274
- {
275
- if (x.is_none())
276
- {
277
-
278
- return qdb_time_t{0};
279
- }
280
- else
281
- {
282
- return tp_to_qt_(dt_to_tp_(x));
283
- }
284
- }
285
- };
286
-
287
- /**
288
- * qdb_timespec_t -> std::chrono::time_point
289
- */
290
-
291
- template <>
292
- struct value_converter<qdb_timespec_t, clock_t::time_point>
293
- {
294
- inline clock_t::time_point operator()(qdb_timespec_t const & x) const
295
- {
296
- // We *could* feed chrono the nanoseconds_t directly, but:
297
- // - python is not able to represent nanoseconds;
298
- // - some architectures are unable to represent the system_clock with
299
- // nanosecond precision; it requires some pretty big integers.
300
- //
301
- // As such, let's first truncate things to milliseconds
302
- milliseconds_t millis{x.tv_nsec / 1'000'000};
303
- seconds_t seconds{x.tv_sec};
304
-
305
- return clock_t::time_point(millis + seconds);
306
- }
307
- };
308
-
309
- /**
310
- * std::chrono::time_point -> datetime.datetime
311
- *
312
- * time point is assumed to be UTC.
313
- */
314
- template <>
315
- struct value_converter<clock_t::time_point, qdb::pydatetime>
316
- {
317
- inline qdb::pydatetime operator()(clock_t::time_point const & tp) const
318
- {
319
- date::sys_days dp = date::floor<days_t>(tp);
320
- date::year_month_day ymd{dp};
321
- date::hh_mm_ss hms{date::floor<seconds_t>(tp - dp)};
322
-
323
- // We get the 'microseconds' part by simply calculating the total amount of seconds since
324
- // epoch, and then substracting that from the time point; whatever is left, is guaranteed
325
- // to be the fraction after the second.
326
- //
327
- // Similar appproach as here: https://stackoverflow.com/a/27137475
328
-
329
- auto since_epoch = tp.time_since_epoch();
330
- auto seconds = std::chrono::duration_cast<seconds_t>(since_epoch);
331
- since_epoch -= seconds;
332
-
333
- // Round it to microseconds, because that's what pydatetime uses as max precision
334
- auto micros = std::chrono::duration_cast<microseconds_t>(since_epoch);
335
-
336
- return qdb::pydatetime::from_date_and_time(static_cast<int>(ymd.year()),
337
- static_cast<unsigned>(ymd.month()), static_cast<unsigned>(ymd.day()), static_cast<int>(hms.hours().count()),
338
- static_cast<int>(hms.minutes().count()), static_cast<int>(hms.seconds().count()), static_cast<int>(micros.count()));
339
- }
340
- };
341
-
342
- /**
343
- * qdb_timespec_t -> datetime.datetime
344
- *
345
- * composes two converters to convert a timespec into a datetime.datetime object in one
346
- * swoop:
347
- *
348
- * - first convert the qdb_timespec_t to a (utc) time point;
349
- * - use the utc time point to create a datetime object
350
- */
351
- template <>
352
- struct value_converter<qdb_timespec_t, qdb::pydatetime>
353
- {
354
- value_converter<qdb_timespec_t, clock_t::time_point> ts_to_tp_{};
355
- value_converter<clock_t::time_point, qdb::pydatetime> tp_to_dt_{};
356
-
357
- inline qdb::pydatetime operator()(qdb_timespec_t const & x) const
358
- {
359
- return tp_to_dt_(ts_to_tp_(x));
360
- }
361
- };
362
-
363
- /**
364
- * datetime.datetime -> qdb_timespec_t
365
- *
366
- * composes two converters to convert a datetime.datetime into a timespec in one
367
- * swoop.
368
- */
369
- template <>
370
- struct value_converter<qdb::pydatetime, qdb_timespec_t>
371
- {
372
- value_converter<qdb::pydatetime, clock_t::time_point> dt_to_tp_{};
373
- value_converter<clock_t::time_point, qdb_timespec_t> tp_to_ts_{};
374
-
375
- inline qdb_timespec_t operator()(qdb::pydatetime const & x) const
376
- {
377
- return tp_to_ts_(dt_to_tp_(x));
378
- }
379
- };
380
-
381
- template <>
382
- struct value_converter<qdb_timespec_t, std::int64_t>
383
- {
384
- inline std::int64_t operator()(qdb_timespec_t const & x) const
385
- {
386
- // XXX(leon): potential overflow
387
- return x.tv_nsec + x.tv_sec * 1'000'000'000ull;
388
- }
389
- };
390
-
391
- template <>
392
- struct value_converter<qdb_timespec_t, traits::datetime64_ns_dtype>
393
- : public value_converter<qdb_timespec_t, std::int64_t>
394
- {};
395
-
396
- template <>
397
- struct value_converter<traits::datetime64_ns_dtype, qdb_timespec_t>
398
- : public value_converter<std::int64_t, qdb_timespec_t>
399
- {};
400
-
401
- ////////////////////////////////////////////////////////////////////////////////
402
- //
403
- // qdb_blob_t/qdb_string_t converters
404
- //
405
- ///////////////////
406
- //
407
- // These converters focus on converting qdb_blob_t or qdb_string_t to/from
408
- // other types. They *may* allocate free pointers on the heap, in which case
409
- // those are tracked using the qdb::object_tracker
410
- //
411
- /////
412
-
413
- template <>
414
- struct value_converter<traits::bytestring_dtype, qdb_string_t>
415
- {
416
- using char_t = std::string::value_type;
417
-
418
- template <concepts::input_range_t<char_t> R>
419
- requires(ranges::sized_range<R> && ranges::contiguous_range<R>)
420
- inline qdb_string_t operator()(R && x) const
421
- {
422
- std::size_t n = (ranges::size(x) + 1) * sizeof(char_t);
423
- char_t const * x_ = ranges::data(x);
424
- char_t * tmp = qdb::object_tracker::alloc<char_t>(n);
425
-
426
- std::memcpy((void *)(tmp), x_, ranges::size(x) + 1);
427
- return qdb_string_t{tmp, ranges::size(x)};
428
- }
429
- };
430
-
431
- template <>
432
- struct value_converter<traits::unicode_dtype, qdb_string_t>
433
- {
434
- typedef std::u32string::value_type in_char_type;
435
- typedef qdb_char_type out_char_type;
436
-
437
- template <concepts::input_range_t<in_char_type> R>
438
- requires(ranges::sized_range<R> && ranges::contiguous_range<R>)
439
- inline qdb_string_t operator()(R && x) const
440
- {
441
- // std::cout << "+ input" << std::endl;
442
- // ranges::for_each(x, [](auto && x) { printf("%08X\n", x); });
443
- // std::cout << "- /input" << std::endl;
444
-
445
- // Calculate total size of output buffer; we *could* do it more
446
- // accurately by first scanning everything and then filling it,
447
- // but trades memory efficiency for performance.
448
- //
449
- // As such, we just allocate the maximum amount of theoretical bytes.
450
- std::size_t n_codepoints = ranges::size(x);
451
- std::size_t max_bytes_out = n_codepoints * sizeof(in_char_type);
452
-
453
- // std::cout << "input size, n_codepoints = " << n_codepoints << std::endl;
454
- // std::cout << "input size, max_bytes_out = " << max_bytes_out << std::endl;
455
-
456
- // Note: we allocate the buffer on our object_tracker heap!
457
- out_char_type * out = qdb::object_tracker::alloc<out_char_type>(max_bytes_out);
458
-
459
- // Get some range representation for this output buffer
460
- auto out_ = ranges::views::counted(out, max_bytes_out);
461
- auto out_begin = ranges::begin(out_);
462
-
463
- // Project our input data (in UTF32 / code points) to UTF8
464
- auto codepoints = unicode::utf32::decode_view(std::move(x));
465
- auto encoded = unicode::utf8::encode_view(std::move(codepoints));
466
-
467
- // std::cout << "encoded size = " << ranges::size(encoded) << std::endl;
468
-
469
- // Copy everything and keep track of the end
470
- auto [in_end, out_end] = ranges::copy(encoded, out_begin);
471
-
472
- // We can use the position of the output iterator to calculate
473
- // the length of the generated string.
474
- qdb_size_t n = static_cast<qdb_size_t>(std::distance(out_begin, out_end));
475
- // std::cout << "n = " << n << std::endl;
476
- // std::cout << "ranges::size(encoded) = " << ranges::size(encoded) << std::endl;
477
-
478
- // std::cout << "+ output: " << std::endl;
479
- // ranges::for_each(encoded, [](auto && x) { printf("%02X\n", x); });
480
- // std::cout << "- /output " << std::endl;
481
-
482
- // Sanity check: we expect to have written exactly as many bytes as our range claims it is
483
- assert(n == ranges::size(encoded));
484
-
485
- // UTF32->UTF8 we always expect at least as many items
486
- // assert(n >= n_codepoints);
487
-
488
- return qdb_string_t{out, n};
489
- }
490
- };
491
-
492
- template <>
493
- struct value_converter<py::bytes, qdb_blob_t>
494
- {
495
- using dtype = traits::object_dtype<py::bytes>;
496
-
497
- inline qdb_blob_t operator()(py::bytes const & x) const
498
- {
499
- assert(dtype::is_null(x) == false);
500
- assert(dtype::is_null(x) == x.is_none());
501
-
502
- qdb_blob_t ret{nullptr, 0};
503
-
504
- if (PYBIND11_BYTES_AS_STRING_AND_SIZE(
505
- x.ptr(), (char **)(&ret.content), (Py_ssize_t *)(&ret.content_length))) [[unlikely]]
506
- {
507
- throw qdb::incompatible_type_exception{"Unable to interpret object as bytes and size: "};
508
- }
509
-
510
- return ret;
511
- }
512
- };
513
-
514
- template <>
515
- struct value_converter<traits::pyobject_dtype, qdb_blob_t>
516
- : public value_converter<py::bytes, qdb_blob_t>
517
- {};
518
-
519
- template <>
520
- struct value_converter<qdb_blob_t, py::bytes>
521
- {
522
- inline py::bytes operator()(qdb_blob_t const & x) const
523
- {
524
- // Again, if we're already at the point that we're sure we can cast it to py::bytes,
525
- // it implies it is guaranteed not to be null.
526
- assert(traits::is_null(x) == false);
527
-
528
- return py::bytes(static_cast<char const *>(x.content), x.content_length);
529
- }
530
- };
531
-
532
- template <>
533
- struct value_converter<qdb_blob_t, py::object>
534
- {
535
- using dtype = traits::pyobject_dtype;
536
-
537
- value_converter<qdb_blob_t, py::bytes> delegate_{};
538
-
539
- inline py::object operator()(qdb_blob_t const & x) const
540
- {
541
- if (traits::is_null(x))
542
- {
543
- return dtype::null_value();
544
- }
545
-
546
- return delegate_(x);
547
- }
548
- };
549
-
550
- template <>
551
- struct value_converter<qdb_string_t, py::str>
552
- {
553
- inline py::str operator()(qdb_string_t const & x) const
554
- {
555
- // Again, if we're already at the point that we're sure we can cast it to py::bytes,
556
- // it implies it is guaranteed not to be null.
557
- assert(traits::is_null(x) == false);
558
-
559
- return py::str(x.data, x.length);
560
- }
561
- };
562
-
563
- template <>
564
- struct value_converter<qdb_string_t, py::object>
565
- {
566
- using dtype = traits::pyobject_dtype;
567
-
568
- value_converter<qdb_string_t, py::str> delegate_{};
569
-
570
- inline py::object operator()(qdb_string_t const & x) const
571
- {
572
- if (traits::is_null(x))
573
- {
574
- return dtype::null_value();
575
- }
576
-
577
- return delegate_(x);
578
- }
579
- };
580
-
581
- using qdb_string_view = ranges::counted_view<qdb_char_type const *>;
582
-
583
- template <>
584
- struct value_converter<qdb_string_t, qdb_string_view>
585
- {
586
- inline qdb_string_view operator()(qdb_string_t const & x) const
587
- {
588
- return qdb_string_view(x.data, static_cast<std::size_t>(x.length));
589
- }
590
- };
591
-
592
- template <>
593
- struct value_converter<qdb_string_t, traits::unicode_dtype>
594
- {
595
- value_converter<qdb_string_t, qdb_string_view> delegate_{};
596
-
597
- inline auto operator()(qdb_string_t const & x) const
598
- {
599
- return unicode::utf32::encode_view(unicode::utf8::decode_view(delegate_(x)));
600
- }
601
- };
602
-
603
- template <>
604
- struct value_converter<py::object, qdb_blob_t>
605
- {
606
- using dtype = traits::object_dtype<py::object>;
607
-
608
- value_converter<py::bytes, qdb_blob_t> delegate_{};
609
-
610
- inline qdb_blob_t operator()(py::object const & x) const
611
- {
612
- if (dtype::is_null(x))
613
- {
614
- return traits::null_value<qdb_blob_t>();
615
- }
616
-
617
- return delegate_(x);
618
- }
619
- };
620
-
621
- template <>
622
- struct value_converter<py::object, qdb_timespec_t>
623
- {
624
- using dtype = traits::object_dtype<py::object>;
625
-
626
- value_converter<std::int64_t, qdb_timespec_t> delegate_{};
627
-
628
- inline qdb_timespec_t operator()(py::object const & x) const
629
- {
630
- if (dtype::is_null(x))
631
- {
632
- return traits::null_value<qdb_timespec_t>();
633
- }
634
-
635
- try
636
- {
637
- return delegate_(x.cast<std::int64_t>());
638
- }
639
- catch (py::cast_error const & /* e */)
640
- {
641
- throw qdb::invalid_datetime_exception{x};
642
- }
643
- }
644
- };
645
-
646
- template <>
647
- struct value_converter<py::tuple, qdb_ts_range_t>
648
- {
649
- using dtype = traits::object_dtype<py::object>;
650
-
651
- value_converter<py::object, qdb_timespec_t> delegate_{};
652
-
653
- inline qdb_ts_range_t operator()(py::tuple const & x) const
654
- {
655
- if (x.is_none()) [[unlikely]]
656
- {
657
- throw qdb::invalid_argument_exception{
658
- std::string{"Expected a Tuple of datetime, got None"}};
659
- }
660
- else if (x.size() != 2) [[unlikely]]
661
- {
662
- throw qdb::invalid_argument_exception{
663
- std::string{"A time range should be a Tuple with 2 datetimes, got "
664
- + std::to_string(x.size()) + " items in tuple"}};
665
- }
666
-
667
- qdb_timespec_t begin = delegate_(x[0]);
668
- qdb_timespec_t end = delegate_(x[1]);
669
-
670
- return qdb_ts_range_t{begin, end};
671
- }
672
- };
673
-
674
- template <>
675
- struct value_converter<traits::bytestring_dtype, qdb_blob_t>
676
- {
677
- value_converter<traits::bytestring_dtype, qdb_string_t> delegate_{};
678
-
679
- template <ranges::input_range R>
680
- inline qdb_blob_t operator()(R && x) const
681
- {
682
- qdb_string_t s = delegate_(std::forward<R &&>(x));
683
-
684
- return qdb_blob_t{static_cast<void const *>(s.data), s.length};
685
- }
686
- };
687
- } // namespace qdb::convert::detail
688
-
689
- namespace qdb::convert
690
- {
691
-
692
- ////////////////////////////////////////////////////////////////////////////////
693
- //
694
- // PUBLIC API
695
- //
696
- ///////////////////
697
- //
698
- // Functions below define the public API. Their intent to handle boilerplate and
699
- // and easier-to-use interface than the lower-level converters defined above.
700
- //
701
- ////////////////////////////////////////////////////////////////////////////////
702
-
703
- // any -> any
704
- template <typename From, typename To>
705
- static inline constexpr To value(From const & x)
706
- {
707
- detail::value_converter<From, To> c{};
708
- return c(x);
709
- }
710
-
711
- } // namespace qdb::convert