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;
}
Exemple #8
0
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);
	}
}