xnd 0.2.0dev3

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 (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 */