@@ -44,14 +44,15 @@ typedef union _npy_static_string_u {
44
44
#define NPY_STRING_SHORT 0x40 // 0100 0000
45
45
#define NPY_STRING_ARENA_FREED 0x20 // 0010 0000
46
46
#define NPY_STRING_ON_HEAP 0x10 // 0001 0000
47
+ #define NPY_STRING_MEDIUM 0x08 // 0000 1000
48
+ #define NPY_STRING_FLAG_MASK 0xF8 // 1111 1000
47
49
48
50
// short string sizes fit in a 4-bit integer
49
51
#define NPY_SHORT_STRING_SIZE_MASK 0x0F // 0000 1111
50
52
#define NPY_SHORT_STRING_MAX_SIZE \
51
53
(sizeof(npy_static_string) - 1) // 15 or 7 depending on arch
52
54
// one bit is used to signal a medium string
53
- #define NPY_MEDIUM_STRING_MAX_SIZE 0x7F // 0111 1111 or 127
54
- #define NPY_MEDIUM_STRING_FLAG 0x80 // 1000 0000
55
+ #define NPY_MEDIUM_STRING_MAX_SIZE 0xFF // 256
55
56
56
57
// Since this has no flags set, technically this is a heap-allocated string
57
58
// with size zero. Practically, that doesn't matter because we always do size
@@ -89,8 +90,7 @@ struct npy_string_allocator {
89
90
void
90
91
set_vstring_size (_npy_static_string_u * str , size_t size )
91
92
{
92
- unsigned char * flags = & str -> direct_buffer .flags_and_size ;
93
- unsigned char current_flags = * flags & ~NPY_SHORT_STRING_SIZE_MASK ;
93
+ unsigned char current_flags = str -> direct_buffer .flags_and_size ;
94
94
str -> vstring .size = size ;
95
95
str -> direct_buffer .flags_and_size = current_flags ;
96
96
}
@@ -115,7 +115,7 @@ npy_string_arena_malloc(npy_string_arena *arena, npy_string_realloc_func r,
115
115
// one extra size_t to store the size of the allocation
116
116
size_t string_storage_size ;
117
117
if (size <= NPY_MEDIUM_STRING_MAX_SIZE ) {
118
- string_storage_size = size + sizeof (char );
118
+ string_storage_size = size + sizeof (unsigned char );
119
119
}
120
120
else {
121
121
string_storage_size = size + sizeof (size_t );
@@ -148,12 +148,13 @@ npy_string_arena_malloc(npy_string_arena *arena, npy_string_realloc_func r,
148
148
}
149
149
char * ret ;
150
150
if (size <= NPY_MEDIUM_STRING_MAX_SIZE ) {
151
- char * size_loc = (char * )& arena -> buffer [arena -> cursor ];
152
- * size_loc = size | NPY_MEDIUM_STRING_FLAG ;
151
+ unsigned char * size_loc =
152
+ (unsigned char * )& arena -> buffer [arena -> cursor ];
153
+ * size_loc = size ;
153
154
ret = & arena -> buffer [arena -> cursor + sizeof (char )];
154
155
}
155
156
else {
156
- size_t * size_ptr = (size_t * )& arena -> buffer [arena -> cursor ];
157
+ char * size_ptr = (char * )& arena -> buffer [arena -> cursor ];
157
158
memcpy (size_ptr , & size , sizeof (size_t ));
158
159
ret = & arena -> buffer [arena -> cursor + sizeof (size_t )];
159
160
}
@@ -223,9 +224,12 @@ is_short_string(const npy_packed_static_string *s)
223
224
}
224
225
225
226
int
226
- is_medium_string (const char * buf )
227
+ is_medium_string (const _npy_static_string_u * s )
227
228
{
228
- return ((buf [0 ] & NPY_MEDIUM_STRING_FLAG ) != 0 );
229
+ unsigned char high_byte = s -> direct_buffer .flags_and_size ;
230
+ int has_short_flag = (high_byte & NPY_STRING_SHORT );
231
+ int has_medium_flag = (high_byte & NPY_STRING_MEDIUM );
232
+ return (!has_short_flag && has_medium_flag );
229
233
}
230
234
231
235
int
@@ -308,18 +312,18 @@ heap_or_arena_allocate(npy_string_allocator *allocator,
308
312
return NULL ;
309
313
}
310
314
size_t alloc_size ;
311
- if (is_medium_string (buf )) {
315
+ if (is_medium_string (to_init_u )) {
312
316
// stored in a char so direct access is OK
313
- alloc_size = (size_t ) * (buf - 1 ) & ~ NPY_MEDIUM_STRING_FLAG ;
317
+ alloc_size = (size_t ) * (buf - 1 );
314
318
}
315
319
else {
316
320
// not necessarily memory-aligned, so need to use memcpy
317
- char * size_loc = (char * )((uintptr_t )buf - sizeof (size_t ));
321
+ size_t * size_loc = (size_t * )((uintptr_t )buf - sizeof (size_t ));
318
322
memcpy (& alloc_size , size_loc , sizeof (size_t ));
319
323
}
320
324
if (size <= alloc_size ) {
321
325
// we have room!
322
- * flags = NPY_STRING_ARENA_FREED ;
326
+ * flags &= ~ NPY_STRING_ARENA_FREED ;
323
327
return buf ;
324
328
}
325
329
else {
@@ -346,8 +350,12 @@ heap_or_arena_allocate(npy_string_allocator *allocator,
346
350
if (arena == NULL ) {
347
351
return NULL ;
348
352
}
349
- return npy_string_arena_malloc (arena , allocator -> realloc ,
350
- sizeof (char ) * size );
353
+ char * ret = npy_string_arena_malloc (arena , allocator -> realloc ,
354
+ sizeof (char ) * size );
355
+ if (size < NPY_MEDIUM_STRING_MAX_SIZE ) {
356
+ * flags |= NPY_STRING_MEDIUM ;
357
+ }
358
+ return ret ;
351
359
}
352
360
353
361
int
0 commit comments