@@ -11,21 +11,18 @@ PyTypeObject *StringScalar_Type = NULL;
11
11
PyObject *
12
12
new_stringdtype_instance (PyObject * na_object , int coerce )
13
13
{
14
- npy_string_allocator * allocator = NULL ;
15
- PyThread_type_lock * allocator_lock = NULL ;
16
- npy_packed_static_string packed_na_name = * NPY_EMPTY_STRING ;
17
- npy_packed_static_string packed_default_string = * NPY_EMPTY_STRING ;
18
-
19
14
PyObject * new =
20
15
PyArrayDescr_Type .tp_new ((PyTypeObject * )& StringDType , NULL , NULL );
21
16
22
17
if (new == NULL ) {
23
18
return NULL ;
24
19
}
25
20
21
+ npy_string_allocator * allocator = NULL ;
22
+ PyThread_type_lock * allocator_lock = NULL ;
23
+
26
24
allocator = NpyString_new_allocator (PyMem_RawMalloc , PyMem_RawFree ,
27
25
PyMem_RawRealloc );
28
-
29
26
if (allocator == NULL ) {
30
27
PyErr_SetString (PyExc_MemoryError ,
31
28
"Failed to create string allocator" );
@@ -38,6 +35,13 @@ new_stringdtype_instance(PyObject *na_object, int coerce)
38
35
goto fail ;
39
36
}
40
37
38
+ char packed_na_name [SIZEOF_NPY_PACKED_STATIC_STRING ] = {0 };
39
+ NpyString_pack (allocator , (npy_packed_static_string * )& packed_na_name , "" ,
40
+ 0 );
41
+ char packed_default_string [SIZEOF_NPY_PACKED_STATIC_STRING ] = {0 };
42
+ NpyString_pack (allocator ,
43
+ (npy_packed_static_string * )& packed_default_string , "" , 0 );
44
+
41
45
Py_XINCREF (na_object );
42
46
((StringDTypeObject * )new )-> na_object = na_object ;
43
47
int hasnull = na_object != NULL ;
@@ -49,8 +53,10 @@ new_stringdtype_instance(PyObject *na_object, int coerce)
49
53
has_string_na = 1 ;
50
54
Py_ssize_t size = 0 ;
51
55
const char * buf = PyUnicode_AsUTF8AndSize (na_object , & size );
52
- if (NpyString_newsize (buf , (size_t )size , & packed_default_string ,
53
- allocator ) < 0 ) {
56
+ if (NpyString_newsize (
57
+ buf , (size_t )size ,
58
+ (npy_packed_static_string * )& packed_default_string ,
59
+ allocator ) < 0 ) {
54
60
PyErr_SetString (PyExc_MemoryError ,
55
61
"Failed to allocate string while creating "
56
62
"StringDType instance." );
@@ -86,7 +92,8 @@ new_stringdtype_instance(PyObject *na_object, int coerce)
86
92
Py_DECREF (na_pystr );
87
93
goto fail ;
88
94
}
89
- if (NpyString_newsize (utf8_ptr , (size_t )size , & packed_na_name ,
95
+ if (NpyString_newsize (utf8_ptr , (size_t )size ,
96
+ (npy_packed_static_string * )& packed_na_name ,
90
97
allocator ) < 0 ) {
91
98
PyErr_SetString (PyExc_MemoryError ,
92
99
"Failed to allocate string while creating "
@@ -101,16 +108,20 @@ new_stringdtype_instance(PyObject *na_object, int coerce)
101
108
102
109
snew -> has_nan_na = has_nan_na ;
103
110
snew -> has_string_na = has_string_na ;
104
- snew -> packed_default_string = packed_default_string ;
105
- snew -> packed_na_name = packed_na_name ;
111
+ memcpy (snew -> packed_default_string , packed_default_string ,
112
+ SIZEOF_NPY_PACKED_STATIC_STRING );
113
+ memcpy (snew -> packed_na_name , packed_na_name ,
114
+ SIZEOF_NPY_PACKED_STATIC_STRING );
106
115
snew -> coerce = coerce ;
107
116
snew -> allocator_lock = allocator_lock ;
108
117
snew -> allocator = allocator ;
109
118
snew -> array_owned = 0 ;
110
119
111
120
npy_static_string default_string = {0 , NULL };
112
- if (NpyString_load (allocator , & snew -> packed_default_string ,
113
- & default_string ) == -1 ) {
121
+ if (NpyString_load (
122
+ allocator ,
123
+ (npy_packed_static_string * )& snew -> packed_default_string ,
124
+ & default_string ) == -1 ) {
114
125
PyErr_SetString (PyExc_MemoryError ,
115
126
"Failed to load packed string while "
116
127
"creating StringDType instance." );
@@ -119,7 +130,9 @@ new_stringdtype_instance(PyObject *na_object, int coerce)
119
130
}
120
131
121
132
npy_static_string na_name = {0 , NULL };
122
- if (NpyString_load (allocator , & snew -> packed_na_name , & na_name ) == -1 ) {
133
+ if (NpyString_load (allocator ,
134
+ (npy_packed_static_string * )& snew -> packed_na_name ,
135
+ & na_name ) == -1 ) {
123
136
PyErr_SetString (PyExc_MemoryError ,
124
137
"Failed to load packed string while "
125
138
"creating StringDType instance." );
@@ -132,8 +145,8 @@ new_stringdtype_instance(PyObject *na_object, int coerce)
132
145
snew -> default_string = default_string ;
133
146
134
147
PyArray_Descr * base = (PyArray_Descr * )new ;
135
- base -> elsize = sizeof ( npy_static_string ) ;
136
- base -> alignment = _Alignof( npy_static_string ) ;
148
+ base -> elsize = SIZEOF_NPY_PACKED_STATIC_STRING ;
149
+ base -> alignment = ALIGNOF_NPY_PACKED_STATIC_STRING ;
137
150
base -> flags |= NPY_NEEDS_INIT ;
138
151
base -> flags |= NPY_LIST_PICKLE ;
139
152
base -> flags |= NPY_ITEM_REFCOUNT ;
@@ -150,8 +163,9 @@ new_stringdtype_instance(PyObject *na_object, int coerce)
150
163
// this only makes sense if the allocator isn't attached to new yet
151
164
Py_DECREF (new );
152
165
if (allocator != NULL ) {
153
- NpyString_free (& packed_na_name , allocator );
154
- NpyString_free (& packed_default_string , allocator );
166
+ NpyString_free ((npy_packed_static_string * )& packed_na_name , allocator );
167
+ NpyString_free ((npy_packed_static_string * )& packed_default_string ,
168
+ allocator );
155
169
NpyString_free_allocator (allocator );
156
170
}
157
171
if (allocator_lock != NULL ) {
@@ -289,21 +303,18 @@ stringdtype_setitem(StringDTypeObject *descr, PyObject *obj, char **dataptr)
289
303
290
304
NPY_STRING_ACQUIRE_ALLOCATOR (descr );
291
305
292
- // free if dataptr holds preexisting string data,
293
- // npy_string_free does a NULL check and checks for small strings
294
- if (NpyString_free (sdata , descr -> allocator ) < 0 ) {
295
- PyErr_SetString (PyExc_MemoryError ,
296
- "String deallocation failed in StringDType setitem" );
297
- goto fail ;
298
- }
299
-
300
306
// borrow reference
301
307
PyObject * na_object = descr -> na_object ;
302
308
303
309
// setting NA *must* check pointer equality since NA types might not
304
310
// allow equality
305
311
if (na_object != NULL && obj == na_object ) {
306
- * sdata = * NPY_NULL_STRING ;
312
+ if (NpyString_pack_null (descr -> allocator , sdata ) < 0 ) {
313
+ PyErr_SetString (PyExc_MemoryError ,
314
+ "Failed to pack null string during StringDType "
315
+ "setitem" );
316
+ goto fail ;
317
+ }
307
318
}
308
319
else {
309
320
PyObject * val_obj = get_value (obj , descr -> coerce );
@@ -319,9 +330,9 @@ stringdtype_setitem(StringDTypeObject *descr, PyObject *obj, char **dataptr)
319
330
goto fail ;
320
331
}
321
332
322
- if (NpyString_newsize ( val , length , sdata , descr -> allocator ) < 0 ) {
333
+ if (NpyString_pack ( descr -> allocator , sdata , val , length ) < 0 ) {
323
334
PyErr_SetString (PyExc_MemoryError ,
324
- "Failed to allocate string during StringDType "
335
+ "Failed to pack string during StringDType "
325
336
"setitem" );
326
337
Py_DECREF (val_obj );
327
338
goto fail ;
@@ -482,12 +493,13 @@ _compare(void *a, void *b, StringDTypeObject *descr_a,
482
493
// PyArray_ArgFunc
483
494
// The max element is the one with the highest unicode code point.
484
495
int
485
- argmax (void * data , npy_intp n , npy_intp * max_ind , void * arr )
496
+ argmax (char * data , npy_intp n , npy_intp * max_ind , void * arr )
486
497
{
487
- npy_packed_static_string * dptr = (npy_packed_static_string * )data ;
498
+ PyArray_Descr * descr = PyArray_DESCR (arr );
499
+ npy_intp elsize = descr -> elsize ;
488
500
* max_ind = 0 ;
489
501
for (int i = 1 ; i < n ; i ++ ) {
490
- if (compare (& dptr [ i ], & dptr [ * max_ind ] , arr ) > 0 ) {
502
+ if (compare (data + i * elsize , data + ( * max_ind ) * elsize , arr ) > 0 ) {
491
503
* max_ind = i ;
492
504
}
493
505
}
@@ -497,12 +509,13 @@ argmax(void *data, npy_intp n, npy_intp *max_ind, void *arr)
497
509
// PyArray_ArgFunc
498
510
// The min element is the one with the lowest unicode code point.
499
511
int
500
- argmin (void * data , npy_intp n , npy_intp * min_ind , void * arr )
512
+ argmin (char * data , npy_intp n , npy_intp * min_ind , void * arr )
501
513
{
502
- npy_packed_static_string * dptr = (npy_packed_static_string * )data ;
514
+ PyArray_Descr * descr = PyArray_DESCR (arr );
515
+ npy_intp elsize = descr -> elsize ;
503
516
* min_ind = 0 ;
504
517
for (int i = 1 ; i < n ; i ++ ) {
505
- if (compare (& dptr [ i ], & dptr [ * min_ind ] , arr ) < 0 ) {
518
+ if (compare (data + i * elsize , data + ( * min_ind ) * elsize , arr ) < 0 ) {
506
519
* min_ind = i ;
507
520
}
508
521
}
@@ -525,13 +538,10 @@ stringdtype_clear_loop(void *NPY_UNUSED(traverse_context),
525
538
NPY_STRING_ACQUIRE_ALLOCATOR (sdescr );
526
539
while (size -- ) {
527
540
npy_packed_static_string * sdata = (npy_packed_static_string * )data ;
528
- if (data != NULL ) {
529
- if (NpyString_free (sdata , sdescr -> allocator ) < 0 ) {
530
- gil_error (PyExc_MemoryError ,
531
- "String deallocation failed in clear loop" );
532
- goto fail ;
533
- }
534
- memset (data , 0 , sizeof (npy_packed_static_string ));
541
+ if (data != NULL && NpyString_free (sdata , sdescr -> allocator ) < 0 ) {
542
+ gil_error (PyExc_MemoryError ,
543
+ "String deallocation failed in clear loop" );
544
+ goto fail ;
535
545
}
536
546
data += stride ;
537
547
}
@@ -703,8 +713,11 @@ stringdtype_dealloc(StringDTypeObject *self)
703
713
if (self -> allocator != NULL ) {
704
714
// can we assume the destructor for an instance will only get called
705
715
// inside of one C thread?
706
- NpyString_free (& self -> packed_default_string , self -> allocator );
707
- NpyString_free (& self -> packed_na_name , self -> allocator );
716
+ NpyString_free (
717
+ (npy_packed_static_string * )& self -> packed_default_string ,
718
+ self -> allocator );
719
+ NpyString_free ((npy_packed_static_string * )& self -> packed_na_name ,
720
+ self -> allocator );
708
721
NpyString_free_allocator (self -> allocator );
709
722
PyThread_free_lock (self -> allocator_lock );
710
723
}
0 commit comments