as_val * blob_to_asval(const as_particle *p) { blob_mem *p_blob_mem = (blob_mem *)p; uint8_t *value = cf_malloc(p_blob_mem->sz); if (! value) { return NULL; } memcpy(value, p_blob_mem->data, p_blob_mem->sz); return (as_val *)as_bytes_new_wrap(value, p_blob_mem->sz, true); }
static void as_command_parse_value(uint8_t* p, uint8_t type, uint32_t value_size, as_val** value) { // Allocate values on heap. switch (type) { case AS_BYTES_UNDEF: { *value = (as_val*)&as_nil; break; } case AS_BYTES_INTEGER: { int64_t v = 0; as_command_bytes_to_int(p, value_size, &v); *value = (as_val*)as_integer_new(v); break; } case AS_BYTES_DOUBLE: { double v = cf_swap_from_big_float64(*(double*)p); *value = (as_val*)as_double_new(v); break; } case AS_BYTES_STRING: { char* v = malloc(value_size + 1); memcpy(v, p, value_size); v[value_size] = 0; *value = (as_val*)as_string_new_wlen(v, value_size, true); break; } case AS_BYTES_LIST: case AS_BYTES_MAP: { as_buffer buffer; buffer.data = p; buffer.size = value_size; as_serializer ser; as_msgpack_init(&ser); as_serializer_deserialize(&ser, &buffer, value); as_serializer_destroy(&ser); break; } default: { void* v = malloc(value_size); memcpy(v, p, value_size); *value = (as_val*)as_bytes_new_wrap(v, value_size, true); break; } } }
static as_bytes * udf_record_digest(const as_rec *rec) { int ret = udf_record_param_check(rec, UDF_BIN_NONAME, __FILE__, __LINE__); if (ret) { return NULL; } udf_record *urecord = (udf_record *)as_rec_source(rec); if (urecord && urecord->flag & UDF_RECORD_FLAG_OPEN) { cf_digest *keyd = cf_malloc(sizeof(cf_digest)); if (!keyd) { return NULL; } memcpy(keyd, &urecord->keyd, CF_DIGEST_KEY_SZ); as_bytes *b = as_bytes_new_wrap(keyd->digest, CF_DIGEST_KEY_SZ, true); return b; } return NULL; }
// Local utility. static as_val * as_val_from_flat_key(uint8_t * flat_key, uint32_t size) { uint8_t type = *flat_key; uint8_t * key = flat_key + 1; switch ( type ) { case AS_PARTICLE_TYPE_INTEGER: // TODO - verify size is (1 + 8) ??? // Flat integer keys are in big-endian order. return (as_val *) as_integer_new(cf_swap_from_be64(*(int64_t *)key)); case AS_PARTICLE_TYPE_STRING: { // Key length is size - 1, then +1 for null-termination. char * buf = cf_malloc(size); if (! buf) { return NULL; } uint32_t len = size - 1; memcpy(buf, key, len); buf[len] = '\0'; return (as_val *) as_string_new(buf, true); } case AS_PARTICLE_TYPE_BLOB: { uint32_t blob_size = size - 1; uint8_t *buf = cf_malloc(blob_size); if (! buf) { return NULL; } memcpy(buf, key, blob_size); return (as_val *) as_bytes_new_wrap(buf, blob_size, true); } default: return NULL; } }
static as_bytes * as_record_rec_digest(const as_rec * r) { return r ? as_bytes_new_wrap(((as_record *) r)->key.digest.value, AS_DIGEST_VALUE_SIZE, false) : NULL; }
static void as_command_parse_value(uint8_t* p, uint8_t type, uint32_t value_size, as_val** value) { // Allocate values on heap. switch (type) { case AS_BYTES_UNDEF: { *value = (as_val*)&as_nil; break; } case AS_BYTES_INTEGER: { int64_t v = 0; as_command_bytes_to_int(p, value_size, &v); *value = (as_val*)as_integer_new(v); break; } case AS_BYTES_DOUBLE: { double v = cf_swap_from_big_float64(*(double*)p); *value = (as_val*)as_double_new(v); break; } case AS_BYTES_STRING: { char* v = cf_malloc(value_size + 1); memcpy(v, p, value_size); v[value_size] = 0; *value = (as_val*)as_string_new_wlen(v, value_size, true); break; } case AS_BYTES_GEOJSON: { uint8_t * ptr = p; // skip flags ptr++; // ncells uint16_t ncells = cf_swap_from_be16(* (uint16_t *) ptr); ptr += sizeof(uint16_t); // skip any cells ptr += sizeof(uint64_t) * ncells; // Use the json bytes. size_t jsonsz = value_size - 1 - 2 - (ncells * sizeof(uint64_t)); char* v = cf_malloc(jsonsz + 1); memcpy(v, ptr, jsonsz); v[jsonsz] = 0; *value = (as_val*) as_geojson_new_wlen(v, jsonsz, true); break; } case AS_BYTES_LIST: case AS_BYTES_MAP: { as_buffer buffer; buffer.data = p; buffer.size = value_size; as_serializer ser; as_msgpack_init(&ser); as_serializer_deserialize(&ser, &buffer, value); as_serializer_destroy(&ser); break; } default: { void* v = cf_malloc(value_size); memcpy(v, p, value_size); *value = (as_val*)as_bytes_new_wrap(v, value_size, true); break; } } }
static bool unpack_blob(serial_context *ser_cont, uint32_t size, as_val **value) { int32_t type = READ_CHAR(ser_cont->fd, ser_cont->line_no, ser_cont->col_no, ser_cont->bytes); if (type == EOF) { err("Error while reading BLOB type"); return false; } --size; if (VERBOSE) { ver("%sBLOB, %u byte(s), type 0x%02x", indent(ser_cont), size, type); } // Waste one byte... void *buffer = safe_malloc(size + 1); // ... so that we can NUL-terminate all strings for as_string_val_hashcode(). char *chars = buffer; chars[size] = 0; if (!READ_BLOCK(ser_cont->fd, ser_cont->line_no, ser_cont->col_no, ser_cont->bytes, buffer, size)) { err("Error while reading BLOB data"); cf_free(buffer); return false; } if (type == AS_BYTES_STRING) { if (VERBOSE) { ver("%s -> string BLOB: \"%s\"", indent(ser_cont), chars); } as_string *string = as_string_new_wlen(buffer, size, true); if (string == NULL) { err("Error while allocating string"); cf_free(buffer); return false; } *value = (as_val *)string; return true; } if (type == AS_BYTES_GEOJSON) { if (VERBOSE) { ver("%s -> geo BLOB: \"%s\"", indent(ser_cont), chars); } as_geojson *geo = as_geojson_new_wlen(buffer, size, true); if (geo == NULL) { err("Error while allocating geo value"); cf_free(buffer); return false; } *value = (as_val *)geo; return true; } as_bytes *blob = as_bytes_new_wrap(buffer, size, true); if (blob == NULL) { err("Error while allocating BLOB"); return false; } blob->type = (as_bytes_type)type; *value = (as_val *)blob; return true; }
void clbin_to_asval(cl_bin * bin, as_serializer * ser, as_val ** val) { if ( val == NULL ) return; switch( bin->object.type ) { case CL_NULL :{ *val = (as_val *) &as_nil; break; } case CL_INT : { *val = (as_val *) as_integer_new(bin->object.u.i64); break; } case CL_STR : { // steal the pointer from the object into the val *val = (as_val *) as_string_new(strdup(bin->object.u.str), true /*ismalloc*/); // TODO: re-evaluate the follow zero-copy for strings from cl_bins // *val = (as_val *) as_string_new(bin->object.u.str, true /*ismalloc*/); // bin->object.free = NULL; break; } case CL_LIST : case CL_MAP : { // use a temporary buffer, which doesn't need to be destroyed as_buffer buf = { .capacity = (uint32_t) bin->object.sz, .size = (uint32_t) bin->object.sz, .data = (uint8_t *) bin->object.u.blob }; // print_buffer(&buf); as_serializer_deserialize(ser, &buf, val); break; } case CL_BLOB: case CL_JAVA_BLOB: case CL_CSHARP_BLOB: case CL_PYTHON_BLOB: case CL_RUBY_BLOB: case CL_ERLANG_BLOB: default : { *val = NULL; uint8_t * raw = malloc(sizeof(bin->object.sz)); memcpy(raw, bin->object.u.blob, bin->object.sz); as_bytes * b = as_bytes_new_wrap(raw, (uint32_t)bin->object.sz, true /*ismalloc*/); b->type = (as_bytes_type)bin->object.type; *val = (as_val *) b; break; } } } void clbin_to_asrecord(cl_bin * bin, as_record * r) { switch(bin->object.type) { case CL_NULL: { as_record_set_nil(r, bin->bin_name); break; } case CL_INT: { as_record_set_int64(r, bin->bin_name, bin->object.u.i64); break; } case CL_STR: { as_record_set_strp(r, bin->bin_name, bin->object.u.str, true); // the following completes the handoff of the value. bin->object.free = NULL; break; } case CL_LIST: case CL_MAP: { as_val * val = NULL; as_buffer buffer; buffer.data = (uint8_t *) bin->object.u.blob; buffer.size = (uint32_t)bin->object.sz; as_serializer ser; as_msgpack_init(&ser); as_serializer_deserialize(&ser, &buffer, &val); as_serializer_destroy(&ser); as_record_set(r, bin->bin_name, (as_bin_value *) val); break; } default: { as_record_set_rawp(r, bin->bin_name, bin->object.u.blob, (uint32_t)bin->object.sz, true); // the following completes the handoff of the value. bin->object.free = NULL; break; } } } void clbins_to_asrecord(cl_bin * bins, uint32_t nbins, as_record * r) { uint32_t n = nbins < r->bins.capacity ? nbins : r->bins.capacity; for ( int i = 0; i < n; i++ ) { clbin_to_asrecord(&bins[i], r); } }