xnd 0.2.0dev3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. checksums.yaml +7 -0
  2. data/CONTRIBUTING.md +42 -0
  3. data/Gemfile +3 -0
  4. data/History.md +0 -0
  5. data/README.md +7 -0
  6. data/Rakefile +135 -0
  7. data/ext/ruby_xnd/extconf.rb +70 -0
  8. data/ext/ruby_xnd/float_pack_unpack.c +277 -0
  9. data/ext/ruby_xnd/float_pack_unpack.h +39 -0
  10. data/ext/ruby_xnd/gc_guard.c +36 -0
  11. data/ext/ruby_xnd/gc_guard.h +12 -0
  12. data/ext/ruby_xnd/include/xnd.h +449 -0
  13. data/ext/ruby_xnd/lib/libxnd.a +0 -0
  14. data/ext/ruby_xnd/lib/libxnd.so +1 -0
  15. data/ext/ruby_xnd/lib/libxnd.so.0 +1 -0
  16. data/ext/ruby_xnd/lib/libxnd.so.0.2.0dev3 +0 -0
  17. data/ext/ruby_xnd/memory_block_object.c +32 -0
  18. data/ext/ruby_xnd/memory_block_object.h +33 -0
  19. data/ext/ruby_xnd/ruby_xnd.c +1953 -0
  20. data/ext/ruby_xnd/ruby_xnd.h +61 -0
  21. data/ext/ruby_xnd/ruby_xnd_internal.h +85 -0
  22. data/ext/ruby_xnd/util.h +170 -0
  23. data/ext/ruby_xnd/xnd/AUTHORS.txt +5 -0
  24. data/ext/ruby_xnd/xnd/INSTALL.txt +134 -0
  25. data/ext/ruby_xnd/xnd/LICENSE.txt +29 -0
  26. data/ext/ruby_xnd/xnd/MANIFEST.in +3 -0
  27. data/ext/ruby_xnd/xnd/Makefile.in +80 -0
  28. data/ext/ruby_xnd/xnd/README.rst +44 -0
  29. data/ext/ruby_xnd/xnd/config.guess +1530 -0
  30. data/ext/ruby_xnd/xnd/config.h.in +22 -0
  31. data/ext/ruby_xnd/xnd/config.sub +1782 -0
  32. data/ext/ruby_xnd/xnd/configure +4867 -0
  33. data/ext/ruby_xnd/xnd/configure.ac +164 -0
  34. data/ext/ruby_xnd/xnd/doc/Makefile +14 -0
  35. data/ext/ruby_xnd/xnd/doc/_static/copybutton.js +66 -0
  36. data/ext/ruby_xnd/xnd/doc/conf.py +26 -0
  37. data/ext/ruby_xnd/xnd/doc/index.rst +44 -0
  38. data/ext/ruby_xnd/xnd/doc/libxnd/data-structures.rst +186 -0
  39. data/ext/ruby_xnd/xnd/doc/libxnd/functions.rst +148 -0
  40. data/ext/ruby_xnd/xnd/doc/libxnd/index.rst +25 -0
  41. data/ext/ruby_xnd/xnd/doc/releases/index.rst +34 -0
  42. data/ext/ruby_xnd/xnd/doc/xnd/align-pack.rst +96 -0
  43. data/ext/ruby_xnd/xnd/doc/xnd/buffer-protocol.rst +42 -0
  44. data/ext/ruby_xnd/xnd/doc/xnd/index.rst +30 -0
  45. data/ext/ruby_xnd/xnd/doc/xnd/quickstart.rst +62 -0
  46. data/ext/ruby_xnd/xnd/doc/xnd/types.rst +674 -0
  47. data/ext/ruby_xnd/xnd/install-sh +527 -0
  48. data/ext/ruby_xnd/xnd/libxnd/Makefile.in +102 -0
  49. data/ext/ruby_xnd/xnd/libxnd/Makefile.vc +112 -0
  50. data/ext/ruby_xnd/xnd/libxnd/bitmaps.c +345 -0
  51. data/ext/ruby_xnd/xnd/libxnd/contrib.h +313 -0
  52. data/ext/ruby_xnd/xnd/libxnd/copy.c +944 -0
  53. data/ext/ruby_xnd/xnd/libxnd/equal.c +1216 -0
  54. data/ext/ruby_xnd/xnd/libxnd/inline.h +154 -0
  55. data/ext/ruby_xnd/xnd/libxnd/overflow.h +147 -0
  56. data/ext/ruby_xnd/xnd/libxnd/split.c +286 -0
  57. data/ext/ruby_xnd/xnd/libxnd/tests/Makefile.in +39 -0
  58. data/ext/ruby_xnd/xnd/libxnd/tests/Makefile.vc +44 -0
  59. data/ext/ruby_xnd/xnd/libxnd/tests/README.txt +2 -0
  60. data/ext/ruby_xnd/xnd/libxnd/tests/runtest.c +101 -0
  61. data/ext/ruby_xnd/xnd/libxnd/tests/test.h +48 -0
  62. data/ext/ruby_xnd/xnd/libxnd/tests/test_fixed.c +108 -0
  63. data/ext/ruby_xnd/xnd/libxnd/xnd.c +1304 -0
  64. data/ext/ruby_xnd/xnd/libxnd/xnd.h +449 -0
  65. data/ext/ruby_xnd/xnd/python/test_xnd.py +3144 -0
  66. data/ext/ruby_xnd/xnd/python/xnd/__init__.py +290 -0
  67. data/ext/ruby_xnd/xnd/python/xnd/_xnd.c +2822 -0
  68. data/ext/ruby_xnd/xnd/python/xnd/contrib/pretty.py +850 -0
  69. data/ext/ruby_xnd/xnd/python/xnd/docstrings.h +129 -0
  70. data/ext/ruby_xnd/xnd/python/xnd/pyxnd.h +200 -0
  71. data/ext/ruby_xnd/xnd/python/xnd/util.h +182 -0
  72. data/ext/ruby_xnd/xnd/python/xnd_randvalue.py +1121 -0
  73. data/ext/ruby_xnd/xnd/python/xnd_support.py +106 -0
  74. data/ext/ruby_xnd/xnd/setup.py +303 -0
  75. data/ext/ruby_xnd/xnd/vcbuild/INSTALL.txt +42 -0
  76. data/ext/ruby_xnd/xnd/vcbuild/runtest32.bat +16 -0
  77. data/ext/ruby_xnd/xnd/vcbuild/runtest64.bat +14 -0
  78. data/ext/ruby_xnd/xnd/vcbuild/vcbuild32.bat +29 -0
  79. data/ext/ruby_xnd/xnd/vcbuild/vcbuild64.bat +29 -0
  80. data/ext/ruby_xnd/xnd/vcbuild/vcclean.bat +13 -0
  81. data/ext/ruby_xnd/xnd/vcbuild/vcdistclean.bat +14 -0
  82. data/lib/ruby_xnd.so +0 -0
  83. data/lib/xnd.rb +306 -0
  84. data/lib/xnd/monkeys.rb +29 -0
  85. data/lib/xnd/version.rb +6 -0
  86. data/spec/debug_spec.rb +9 -0
  87. data/spec/gc_guard_spec.rb +10 -0
  88. data/spec/leakcheck.rb +9 -0
  89. data/spec/spec_helper.rb +877 -0
  90. data/spec/type_inference_spec.rb +81 -0
  91. data/spec/xnd_spec.rb +2921 -0
  92. data/xnd.gemspec +47 -0
  93. metadata +215 -0
@@ -0,0 +1,129 @@
1
+ /*
2
+ * BSD 3-Clause License
3
+ *
4
+ * Copyright (c) 2017-2018, plures
5
+ * All rights reserved.
6
+ *
7
+ * Redistribution and use in source and binary forms, with or without
8
+ * modification, are permitted provided that the following conditions are met:
9
+ *
10
+ * 1. Redistributions of source code must retain the above copyright notice,
11
+ * this list of conditions and the following disclaimer.
12
+ *
13
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
14
+ * this list of conditions and the following disclaimer in the documentation
15
+ * and/or other materials provided with the distribution.
16
+ *
17
+ * 3. Neither the name of the copyright holder nor the names of its
18
+ * contributors may be used to endorse or promote products derived from
19
+ * this software without specific prior written permission.
20
+ *
21
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
+ */
32
+
33
+
34
+ #include "pymacro.h"
35
+
36
+
37
+ /******************************************************************************/
38
+ /* Module */
39
+ /******************************************************************************/
40
+
41
+
42
+ PyDoc_STRVAR(doc_module, "xnd module");
43
+
44
+
45
+
46
+ /******************************************************************************/
47
+ /* xnd properties */
48
+ /******************************************************************************/
49
+
50
+ PyDoc_STRVAR(doc_value,
51
+ "\n\
52
+ Convert the in-memory value to a Python value.\n\
53
+ \n\
54
+ >>> x = xnd([1, 2, 3, 4, 5])\n\
55
+ >>> x.value\n\
56
+ [1, 2, 3, 4, 5]\n\
57
+ \n");
58
+
59
+ PyDoc_STRVAR(doc_type,
60
+ "\n\
61
+ Return the type of the in-memory value.\n\
62
+ \n\
63
+ >>> x = xnd([[1, 2, 3], [4, 5]])\n\
64
+ >>> x.type\n\
65
+ ndt(\"var * var * int64\")\n\
66
+ \n");
67
+
68
+ PyDoc_STRVAR(doc_ndim,
69
+ "\n\
70
+ Return the number of dimensions of the in-memory value.\n\
71
+ \n\
72
+ >>> x = xnd([[(1, \"a\"), (2, \"b\")], [(3, \"x\"), (4, \"y\")]])\n\
73
+ >>> x.ndim\n\
74
+ 2\n\
75
+ \n");
76
+
77
+ PyDoc_STRVAR(doc_align,
78
+ "\n\
79
+ Return the alignment of the memory block.\n\
80
+ \n\
81
+ >>> t = \"2 * {a: uint8, b: float64, align=512}\"\n\
82
+ >>> x = xnd([{'a': 1, 'b': 2.0}, {'a': 2, 'b': 3.0}], type=t)\n\
83
+ >>> x.align\n\
84
+ 512\n\
85
+ \n");
86
+
87
+
88
+ /******************************************************************************/
89
+ /* xnd methods */
90
+ /******************************************************************************/
91
+
92
+ PyDoc_STRVAR(doc_short_value,
93
+ "short_value($self, /, maxshape=None)\n--\n\n\
94
+ Convert the in-memory value to an abbreviated Python value. Container types\n\
95
+ are converted to maxshape-1 actual values followed by an Ellipsis. If maxshape\n\
96
+ is None, the representation is not abbreviated.\n\
97
+ \n\
98
+ >>> x = xnd([1, 2, 3, 4, 5])\n\
99
+ >>> x.short_value(maxshape=3)\n\
100
+ [1, 2, ...]\n\
101
+ \n");
102
+
103
+ PyDoc_STRVAR(doc_empty,
104
+ "empty($type, type, /)\n--\n\n\
105
+ Class method that constructs a new xnd container according to the type\n\
106
+ argument. All values are initialized to zero.\n\
107
+ \n\
108
+ >>> xnd.empty(\"10 * 2 * (int64, string, complex128)\")\n\
109
+ xnd([[(0, '', 0j), (0, '', 0j)], [(0, '', 0j), (0, '', 0j)],\n\
110
+ [(0, '', 0j), (0, '', 0j)], [(0, '', 0j), (0, '', 0j)],\n\
111
+ [(0, '', 0j), (0, '', 0j)], [(0, '', 0j), (0, '', 0j)],\n\
112
+ [(0, '', 0j), (0, '', 0j)], [(0, '', 0j), (0, '', 0j)],\n\
113
+ [(0, '', 0j), (0, '', 0j)], ...], type=\"10 * 2 * (int64, string, complex128)\")\n\
114
+ \n");
115
+
116
+ PyDoc_STRVAR(doc_from_buffer,
117
+ "from_buffer($type, obj, /)\n--\n\n\
118
+ Class method that constructs a new xnd container from an object that supports\n\
119
+ the buffer protocol.\n\
120
+ \n\
121
+ >>> xnd.from_buffer(b\"123\")\n\
122
+ xnd([49, 50, 51], type=\"3 * uint8\")\n\
123
+ \n\
124
+ >>> import numpy as np\n\
125
+ >>> a = np.array([[1, 2, 3], [4, 5, 6]])\n\
126
+ >>> xnd.from_buffer(a)\n\
127
+ xnd([[1, 2, 3], [4, 5, 6]], type=\"2 * 3 * int64\")\n\
128
+ \n\
129
+ \n");
@@ -0,0 +1,200 @@
1
+ /*
2
+ * BSD 3-Clause License
3
+ *
4
+ * Copyright (c) 2017-2018, plures
5
+ * All rights reserved.
6
+ *
7
+ * Redistribution and use in source and binary forms, with or without
8
+ * modification, are permitted provided that the following conditions are met:
9
+ *
10
+ * 1. Redistributions of source code must retain the above copyright notice,
11
+ * this list of conditions and the following disclaimer.
12
+ *
13
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
14
+ * this list of conditions and the following disclaimer in the documentation
15
+ * and/or other materials provided with the distribution.
16
+ *
17
+ * 3. Neither the name of the copyright holder nor the names of its
18
+ * contributors may be used to endorse or promote products derived from
19
+ * this software without specific prior written permission.
20
+ *
21
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
+ */
32
+
33
+
34
+ #ifndef PYXND_H
35
+ #define PYXND_H
36
+ #ifdef __cplusplus
37
+ extern "C" {
38
+ #endif
39
+
40
+
41
+ #include <Python.h>
42
+ #include "ndtypes.h"
43
+ #include "xnd.h"
44
+
45
+
46
+ /****************************************************************************/
47
+ /* MemoryBlock Object */
48
+ /****************************************************************************/
49
+
50
+ /* This object owns the memory that is shared by several xnd objects. It is
51
+ never exposed to the Python level.
52
+
53
+ The memory block is created by the primary xnd object on initialization.
54
+ Sub-views, slices etc. share the memory block.
55
+
56
+ PEP-3118 imports are supported. At a later stage the mblock object will
57
+ potentially need to communicate with Arrow or other formats in order
58
+ to acquire and manage external memory blocks.
59
+ */
60
+
61
+ /* Exposed here for the benefit of Numba. The API should not be regarded
62
+ stable across versions. */
63
+
64
+ typedef struct {
65
+ PyObject_HEAD
66
+ PyObject *type; /* type owner */
67
+ xnd_master_t *xnd; /* memblock owner */
68
+ Py_buffer *view; /* PEP-3118 imports */
69
+ } MemoryBlockObject;
70
+
71
+
72
+ /****************************************************************************/
73
+ /* xnd object */
74
+ /****************************************************************************/
75
+
76
+ /* Exposed here for the benefit of Numba. The API should not be regarded
77
+ stable across versions. */
78
+
79
+ typedef struct {
80
+ PyObject_HEAD
81
+ MemoryBlockObject *mblock; /* owner of the primary type and memory block */
82
+ PyObject *type; /* owner of the current type */
83
+ xnd_t xnd; /* typed view, does not own anything */
84
+ } XndObject;
85
+
86
+ #define TYPE_OWNER(v) (((XndObject *)v)->type)
87
+ #define XND(v) (&(((XndObject *)v)->xnd))
88
+ #define XND_INDEX(v) (((XndObject *)v)->xnd.index)
89
+ #define XND_TYPE(v) (((XndObject *)v)->xnd.type)
90
+ #define XND_PTR(v) (((XndObject *)v)->xnd.ptr)
91
+
92
+
93
+ /****************************************************************************/
94
+ /* Capsule API */
95
+ /****************************************************************************/
96
+
97
+ #define Xnd_CheckExact_INDEX 0
98
+ #define Xnd_CheckExact_RETURN int
99
+ #define Xnd_CheckExact_ARGS (const PyObject *)
100
+
101
+ #define Xnd_Check_INDEX 1
102
+ #define Xnd_Check_RETURN int
103
+ #define Xnd_Check_ARGS (const PyObject *)
104
+
105
+ #define CONST_XND_INDEX 2
106
+ #define CONST_XND_RETURN const xnd_t *
107
+ #define CONST_XND_ARGS (const PyObject *)
108
+
109
+ #define Xnd_EmptyFromType_INDEX 3
110
+ #define Xnd_EmptyFromType_RETURN PyObject *
111
+ #define Xnd_EmptyFromType_ARGS (PyTypeObject *, ndt_t *t)
112
+
113
+ #define Xnd_ViewMoveNdt_INDEX 4
114
+ #define Xnd_ViewMoveNdt_RETURN PyObject *
115
+ #define Xnd_ViewMoveNdt_ARGS (const PyObject *, ndt_t *t)
116
+
117
+ #define Xnd_FromXnd_INDEX 5
118
+ #define Xnd_FromXnd_RETURN PyObject *
119
+ #define Xnd_FromXnd_ARGS (PyTypeObject *, xnd_t *x)
120
+
121
+ #define Xnd_Subscript_INDEX 6
122
+ #define Xnd_Subscript_RETURN PyObject *
123
+ #define Xnd_Subscript_ARGS (const PyObject *self, const PyObject *key)
124
+
125
+ #define Xnd_FromXndMoveType_INDEX 7
126
+ #define Xnd_FromXndMoveType_RETURN PyObject *
127
+ #define Xnd_FromXndMoveType_ARGS (const PyObject *xnd, xnd_t *x)
128
+
129
+ #define Xnd_FromXndView_INDEX 8
130
+ #define Xnd_FromXndView_RETURN PyObject *
131
+ #define Xnd_FromXndView_ARGS (xnd_view_t *x)
132
+
133
+ #define Xnd_GetType_INDEX 9
134
+ #define Xnd_GetType_RETURN PyTypeObject *
135
+ #define Xnd_GetType_ARGS (void)
136
+
137
+ #define XND_MAX_API 10
138
+
139
+
140
+ #ifdef XND_MODULE
141
+ static Xnd_CheckExact_RETURN Xnd_CheckExact Xnd_CheckExact_ARGS;
142
+ static Xnd_Check_RETURN Xnd_Check Xnd_Check_ARGS;
143
+ static CONST_XND_RETURN CONST_XND CONST_XND_ARGS;
144
+ static Xnd_EmptyFromType_RETURN Xnd_EmptyFromType Xnd_EmptyFromType_ARGS;
145
+ static Xnd_ViewMoveNdt_RETURN Xnd_ViewMoveNdt Xnd_ViewMoveNdt_ARGS;
146
+ static Xnd_FromXnd_RETURN Xnd_FromXnd Xnd_FromXnd_ARGS;
147
+ static Xnd_Subscript_RETURN Xnd_Subscript Xnd_Subscript_ARGS;
148
+ static Xnd_FromXndMoveType_RETURN Xnd_FromXndMoveType Xnd_FromXndMoveType_ARGS;
149
+ static Xnd_FromXndView_RETURN Xnd_FromXndView Xnd_FromXndView_ARGS;
150
+ static Xnd_GetType_RETURN Xnd_GetType Xnd_GetType_ARGS;
151
+ #else
152
+ static void **_xnd_api;
153
+
154
+ #define Xnd_CheckExact \
155
+ (*(Xnd_CheckExact_RETURN (*)Xnd_CheckExact_ARGS) _xnd_api[Xnd_CheckExact_INDEX])
156
+
157
+ #define Xnd_Check \
158
+ (*(Xnd_Check_RETURN (*)Xnd_Check_ARGS) _xnd_api[Xnd_Check_INDEX])
159
+
160
+ #define CONST_XND \
161
+ (*(CONST_XND_RETURN (*)CONST_XND_ARGS) _xnd_api[CONST_XND_INDEX])
162
+
163
+ #define Xnd_EmptyFromType \
164
+ (*(Xnd_EmptyFromType_RETURN (*)Xnd_EmptyFromType_ARGS) _xnd_api[Xnd_EmptyFromType_INDEX])
165
+
166
+ #define Xnd_ViewMoveNdt \
167
+ (*(Xnd_ViewMoveNdt_RETURN (*)Xnd_ViewMoveNdt_ARGS) _xnd_api[Xnd_ViewMoveNdt_INDEX])
168
+
169
+ #define Xnd_FromXnd \
170
+ (*(Xnd_FromXnd_RETURN (*)Xnd_FromXnd_ARGS) _xnd_api[Xnd_FromXnd_INDEX])
171
+
172
+ #define Xnd_Subscript \
173
+ (*(Xnd_Subscript_RETURN (*)Xnd_Subscript_ARGS) _xnd_api[Xnd_Subscript_INDEX])
174
+
175
+ #define Xnd_FromXndMoveType \
176
+ (*(Xnd_FromXndMoveType_RETURN (*)Xnd_FromXndMoveType_ARGS) _xnd_api[Xnd_FromXndMoveType_INDEX])
177
+
178
+ #define Xnd_FromXndView \
179
+ (*(Xnd_FromXndView_RETURN (*)Xnd_FromXndView_ARGS) _xnd_api[Xnd_FromXndView_INDEX])
180
+
181
+ #define Xnd_GetType \
182
+ (*(Xnd_GetType_RETURN (*)Xnd_GetType_ARGS) _xnd_api[Xnd_GetType_INDEX])
183
+
184
+ static int
185
+ import_xnd(void)
186
+ {
187
+ _xnd_api = (void **)PyCapsule_Import("xnd._xnd._API", 0);
188
+ if (_xnd_api == NULL) {
189
+ return -1;
190
+ }
191
+
192
+ return 0;
193
+ }
194
+ #endif
195
+
196
+ #ifdef __cplusplus
197
+ }
198
+ #endif
199
+
200
+ #endif /* PYXND_H */
@@ -0,0 +1,182 @@
1
+ /*
2
+ * BSD 3-Clause License
3
+ *
4
+ * Copyright (c) 2017-2018, plures
5
+ * All rights reserved.
6
+ *
7
+ * Redistribution and use in source and binary forms, with or without
8
+ * modification, are permitted provided that the following conditions are met:
9
+ *
10
+ * 1. Redistributions of source code must retain the above copyright notice,
11
+ * this list of conditions and the following disclaimer.
12
+ *
13
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
14
+ * this list of conditions and the following disclaimer in the documentation
15
+ * and/or other materials provided with the distribution.
16
+ *
17
+ * 3. Neither the name of the copyright holder nor the names of its
18
+ * contributors may be used to endorse or promote products derived from
19
+ * this software without specific prior written permission.
20
+ *
21
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
+ */
32
+
33
+
34
+ #ifndef UTIL_H
35
+ #define UTIL_H
36
+
37
+
38
+ #include <Python.h>
39
+ #include <stdlib.h>
40
+ #include <stdint.h>
41
+ #include <inttypes.h>
42
+ #include "ndtypes.h"
43
+
44
+
45
+ static inline Py_ssize_t
46
+ safe_downcast(int64_t size)
47
+ {
48
+ #if SIZE_MAX < INT64_MAX
49
+ if (size > INT32_MAX) {
50
+ PyErr_SetString(PyExc_ValueError,
51
+ "sizes should never exceed INT32_MAX on 32-bit platforms");
52
+ return -1;
53
+ }
54
+ #endif
55
+ return (Py_ssize_t)size;
56
+ }
57
+
58
+ static inline bool
59
+ check_invariants(const ndt_t *t)
60
+ {
61
+ #if SIZE_MAX < INT64_MAX
62
+ return safe_downcast(t->datasize) >= 0;
63
+ #else
64
+ (void)t;
65
+ return 1;
66
+ #endif
67
+ }
68
+
69
+ static inline PyObject *
70
+ list_new(int64_t size)
71
+ {
72
+ #if SIZE_MAX < INT64_MAX
73
+ Py_ssize_t n = safe_downcast(size);
74
+ return n < 0 ? NULL : PyList_New(n);
75
+ #else
76
+ return PyList_New(size);
77
+ #endif
78
+ }
79
+
80
+ static PyObject *
81
+ tuple_new(int64_t size)
82
+ {
83
+ #if SIZE_MAX < INT64_MAX
84
+ Py_ssize_t n = safe_downcast(size);
85
+ return n < 0 ? NULL : PyTuple_New(n);
86
+ #else
87
+ return PyTuple_New(size);
88
+ #endif
89
+ }
90
+
91
+ static inline PyObject *
92
+ unicode_from_kind_and_data(int kind, const void *buffer, int64_t size)
93
+ {
94
+ #if SIZE_MAX < INT64_MAX
95
+ Py_ssize_t n = safe_downcast(size);
96
+ return n < 0 ? NULL : PyUnicode_FromKindAndData(kind, buffer, n);
97
+ #else
98
+ return PyUnicode_FromKindAndData(kind, buffer, size);
99
+ #endif
100
+ }
101
+
102
+ static inline PyObject *
103
+ bytes_from_string_and_size(const char *str, int64_t size)
104
+ {
105
+ #if SIZE_MAX < INT64_MAX
106
+ Py_ssize_t n = safe_downcast(size);
107
+ return n < 0 ? NULL : PyBytes_FromStringAndSize(str, n);
108
+ #else
109
+ return PyBytes_FromStringAndSize(str, size);
110
+ #endif
111
+ }
112
+
113
+ static inline int
114
+ py_slice_get_indices_ex(PyObject *key, int64_t length,
115
+ int64_t *start, int64_t *stop, int64_t *step,
116
+ int64_t *slicelength)
117
+ {
118
+ Py_ssize_t n, _start, _stop, _step, _slicelength;
119
+ int ret;
120
+
121
+ n = safe_downcast(length);
122
+ if (n < 0) {
123
+ return -1;
124
+ }
125
+
126
+ ret = PySlice_GetIndicesEx(key, n, &_start, &_stop, &_step, &_slicelength);
127
+ *start = _start;
128
+ *stop = _stop;
129
+ *step = _step;
130
+ *slicelength = _slicelength;
131
+
132
+ return ret;
133
+ }
134
+
135
+ /* PSF copyright: Written by Jim Hugunin and Chris Chase. */
136
+ int
137
+ pyslice_unpack(PyObject *_r,
138
+ Py_ssize_t *start, Py_ssize_t *stop, Py_ssize_t *step)
139
+ {
140
+ PySliceObject *r = (PySliceObject*)_r;
141
+ /* this is harder to get right than you might think */
142
+
143
+ assert(PY_SSIZE_T_MIN + 1 <= -PY_SSIZE_T_MAX);
144
+
145
+ if (r->step == Py_None) {
146
+ *step = 1;
147
+ }
148
+ else {
149
+ if (!_PyEval_SliceIndex(r->step, step)) return -1;
150
+ if (*step == 0) {
151
+ PyErr_SetString(PyExc_ValueError,
152
+ "slice step cannot be zero");
153
+ return -1;
154
+ }
155
+ /* Here *step might be -PY_SSIZE_T_MAX-1; in this case we replace it
156
+ * with -PY_SSIZE_T_MAX. This doesn't affect the semantics, and it
157
+ * guards against later undefined behaviour resulting from code that
158
+ * does "step = -step" as part of a slice reversal.
159
+ */
160
+ if (*step < -PY_SSIZE_T_MAX)
161
+ *step = -PY_SSIZE_T_MAX;
162
+ }
163
+
164
+ if (r->start == Py_None) {
165
+ *start = *step < 0 ? PY_SSIZE_T_MAX : 0;
166
+ }
167
+ else {
168
+ if (!_PyEval_SliceIndex(r->start, start)) return -1;
169
+ }
170
+
171
+ if (r->stop == Py_None) {
172
+ *stop = *step < 0 ? PY_SSIZE_T_MIN : PY_SSIZE_T_MAX;
173
+ }
174
+ else {
175
+ if (!_PyEval_SliceIndex(r->stop, stop)) return -1;
176
+ }
177
+
178
+ return 0;
179
+ }
180
+
181
+
182
+ #endif /* UTIL_H */