Skip to content

Instantly share code, notes, and snippets.

@meangrape
Last active March 16, 2024 18:02
Show Gist options
  • Save meangrape/2ac0f4842912d6e564f015890cab656f to your computer and use it in GitHub Desktop.
Save meangrape/2ac0f4842912d6e564f015890cab656f to your computer and use it in GitHub Desktop.
cython cbor add()
def add(self, cnp.ndarray ts,
cnp.ndarray durations,
cnp.ndarray cols,
cnp.ndarray values
) -> bool:
# since cols is strings of indeterminate length we can't use a memoryview
# since values is dtype=object using a memoryview doesn't get us perforamce benefits
cdef unsigned char[:] ts_view = ts
cdef uint64_t[:] dur_view = durations
cdef char* c_str
cdef uint8_t max_len = 31
cdef cbor_item_t* root = cbor_new_indefinite_array()
cdef cbor_item_t* array
cdef cbor_item_t* map
cdef Buffer* buffer = self.get_buffer()
cdef cbor_pair ts_p
cdef cbor_pair duration_p
cdef cbor_pair value_p
cdef cbor_item_t* ts_k = self.cbor_string("ts")
cdef cbor_item_t* ts_v = cbor_new_null()
cdef cbor_item_t* duration_k = self.cbor_string("duration")
cdef cbor_item_t* duration_v = cbor_new_null()
cdef cbor_item_t* value_k = self.cbor_string("value")
cdef cbor_item_t* value_v = cbor_new_null()
cdef cbor_item_t* col = cbor_new_null()
cdef object val
cdef object p_buffer
cdef bool res
cdef char* t
cdef uint8_t length = 0
cdef uint64_t dur_value
cdef uint8_t i, idx
for i in range(len(ts_view)):
# can't impliciltly cast dur_view[i] to uint64_t inside the gil
dur_value = <uint64_t>dur_view[i]
# can't do &ts_view[i * max_len] inside the gil for some reason
length = i * max_len
with nogil:
array = cbor_new_indefinite_array()
map = cbor_new_definite_map(3)
c_str = <char*>&ts_view[length]
ts_p.key = cbor_move(ts_k)
ts_p.value = cbor_move(cbor_build_string(c_str))
cbor_map_add(map, ts_p)
# cbor_decref(&ts_v)
duration_p.key = cbor_move(duration_k)
duration_p.value = cbor_move(cbor_build_uint64(dur_value))
cbor_map_add(map, duration_p)
# cbor_decref(&duration_v)
for idx, name in enumerate(cols):
col = self.cbor_string(name)
val = values[i, idx]
if isinstance(val, str):
value_v = self.cbor_string(val)
elif isinstance(val, (float, np.floating)):
value_v = cbor_build_float8(float(val))
# why we subtract 1 from negative ints -- https://libcbor.readthedocs.io/en/latest/api/type_0_1_integers.html
elif isinstance(val, (int, np.integer)):
if val < 0:
# negint expects the positive value of an int so we flip the sign of a negative integer
value_v = cbor_build_negint64(-val - 1)
else:
value_v = cbor_build_uint64(val)
else:
t = self.c_string(type(val))
printf("unhandled type %s", t)
# with nogil:
value_p.key = cbor_move(col)
value_p.value = cbor_move(value_v)
cbor_map_add(map, value_p)
# cbor_decref(&col)
# cbor_decref(&value_v)
cbor_array_push(array, map)
cbor_array_push(root, array)
# cbor_decref(&map)
# cbor_decref(&array)
print(f"added row {i}")
print("done adding rows")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment