@@ -11,21 +11,18 @@ PyTypeObject *StringScalar_Type = NULL;
1111PyObject *
1212new_stringdtype_instance (PyObject * na_object , int coerce )
1313{
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-
1914 PyObject * new =
2015 PyArrayDescr_Type .tp_new ((PyTypeObject * )& StringDType , NULL , NULL );
2116
2217 if (new == NULL ) {
2318 return NULL ;
2419 }
2520
21+ npy_string_allocator * allocator = NULL ;
22+ PyThread_type_lock * allocator_lock = NULL ;
23+
2624 allocator = NpyString_new_allocator (PyMem_RawMalloc , PyMem_RawFree ,
2725 PyMem_RawRealloc );
28-
2926 if (allocator == NULL ) {
3027 PyErr_SetString (PyExc_MemoryError ,
3128 "Failed to create string allocator" );
@@ -38,6 +35,13 @@ new_stringdtype_instance(PyObject *na_object, int coerce)
3835 goto fail ;
3936 }
4037
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+
4145 Py_XINCREF (na_object );
4246 ((StringDTypeObject * )new )-> na_object = na_object ;
4347 int hasnull = na_object != NULL ;
@@ -49,8 +53,10 @@ new_stringdtype_instance(PyObject *na_object, int coerce)
4953 has_string_na = 1 ;
5054 Py_ssize_t size = 0 ;
5155 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 ) {
5460 PyErr_SetString (PyExc_MemoryError ,
5561 "Failed to allocate string while creating "
5662 "StringDType instance." );
@@ -86,7 +92,8 @@ new_stringdtype_instance(PyObject *na_object, int coerce)
8692 Py_DECREF (na_pystr );
8793 goto fail ;
8894 }
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 ,
9097 allocator ) < 0 ) {
9198 PyErr_SetString (PyExc_MemoryError ,
9299 "Failed to allocate string while creating "
@@ -101,16 +108,20 @@ new_stringdtype_instance(PyObject *na_object, int coerce)
101108
102109 snew -> has_nan_na = has_nan_na ;
103110 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 );
106115 snew -> coerce = coerce ;
107116 snew -> allocator_lock = allocator_lock ;
108117 snew -> allocator = allocator ;
109118 snew -> array_owned = 0 ;
110119
111120 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 ) {
114125 PyErr_SetString (PyExc_MemoryError ,
115126 "Failed to load packed string while "
116127 "creating StringDType instance." );
@@ -119,7 +130,9 @@ new_stringdtype_instance(PyObject *na_object, int coerce)
119130 }
120131
121132 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 ) {
123136 PyErr_SetString (PyExc_MemoryError ,
124137 "Failed to load packed string while "
125138 "creating StringDType instance." );
@@ -132,8 +145,8 @@ new_stringdtype_instance(PyObject *na_object, int coerce)
132145 snew -> default_string = default_string ;
133146
134147 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 ;
137150 base -> flags |= NPY_NEEDS_INIT ;
138151 base -> flags |= NPY_LIST_PICKLE ;
139152 base -> flags |= NPY_ITEM_REFCOUNT ;
@@ -150,8 +163,9 @@ new_stringdtype_instance(PyObject *na_object, int coerce)
150163 // this only makes sense if the allocator isn't attached to new yet
151164 Py_DECREF (new );
152165 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 );
155169 NpyString_free_allocator (allocator );
156170 }
157171 if (allocator_lock != NULL ) {
@@ -289,21 +303,18 @@ stringdtype_setitem(StringDTypeObject *descr, PyObject *obj, char **dataptr)
289303
290304 NPY_STRING_ACQUIRE_ALLOCATOR (descr );
291305
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-
300306 // borrow reference
301307 PyObject * na_object = descr -> na_object ;
302308
303309 // setting NA *must* check pointer equality since NA types might not
304310 // allow equality
305311 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+ }
307318 }
308319 else {
309320 PyObject * val_obj = get_value (obj , descr -> coerce );
@@ -319,9 +330,9 @@ stringdtype_setitem(StringDTypeObject *descr, PyObject *obj, char **dataptr)
319330 goto fail ;
320331 }
321332
322- if (NpyString_newsize ( val , length , sdata , descr -> allocator ) < 0 ) {
333+ if (NpyString_pack ( descr -> allocator , sdata , val , length ) < 0 ) {
323334 PyErr_SetString (PyExc_MemoryError ,
324- "Failed to allocate string during StringDType "
335+ "Failed to pack string during StringDType "
325336 "setitem" );
326337 Py_DECREF (val_obj );
327338 goto fail ;
@@ -482,12 +493,13 @@ _compare(void *a, void *b, StringDTypeObject *descr_a,
482493// PyArray_ArgFunc
483494// The max element is the one with the highest unicode code point.
484495int
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 )
486497{
487- npy_packed_static_string * dptr = (npy_packed_static_string * )data ;
498+ PyArray_Descr * descr = PyArray_DESCR (arr );
499+ npy_intp elsize = descr -> elsize ;
488500 * max_ind = 0 ;
489501 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 ) {
491503 * max_ind = i ;
492504 }
493505 }
@@ -497,12 +509,13 @@ argmax(void *data, npy_intp n, npy_intp *max_ind, void *arr)
497509// PyArray_ArgFunc
498510// The min element is the one with the lowest unicode code point.
499511int
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 )
501513{
502- npy_packed_static_string * dptr = (npy_packed_static_string * )data ;
514+ PyArray_Descr * descr = PyArray_DESCR (arr );
515+ npy_intp elsize = descr -> elsize ;
503516 * min_ind = 0 ;
504517 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 ) {
506519 * min_ind = i ;
507520 }
508521 }
@@ -525,13 +538,10 @@ stringdtype_clear_loop(void *NPY_UNUSED(traverse_context),
525538 NPY_STRING_ACQUIRE_ALLOCATOR (sdescr );
526539 while (size -- ) {
527540 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 ;
535545 }
536546 data += stride ;
537547 }
@@ -703,8 +713,11 @@ stringdtype_dealloc(StringDTypeObject *self)
703713 if (self -> allocator != NULL ) {
704714 // can we assume the destructor for an instance will only get called
705715 // 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 );
708721 NpyString_free_allocator (self -> allocator );
709722 PyThread_free_lock (self -> allocator_lock );
710723 }
0 commit comments