As_record : C client: How can I clone it?

At certain part of the code, I want to simply make a deep copy of the as_record object.

Is there any API or sample code?

thank you -Vikrant

Most users copy as_record data into their own data structures before processing. There are other cases where incrementing the ref count (as_val_reserve()) on record, bin, list or map values is optimal because copied record is not modified or the original record state is no longer needed.

In the rare case where both source and target records need to be completely independent of each other (zero shared ref values), I suggest using something like this:

#include <aerospike/as_arraylist.h>
#include <aerospike/as_bin.h>
#include <aerospike/as_geojson.h>
#include <aerospike/as_hashmap.h>
#include <aerospike/as_hashmap_iterator.h>
#include <aerospike/as_nil.h>
#include <aerospike/as_record.h>

// Deep copy as_val to either local or heap depending on type.
static void
as_val_copy(as_val* src, as_val* trg, as_val** trgp)
{
	if (! src) {
		*trgp = (as_val*)&as_nil;
		return;
	}

	switch (src->type) {
		case AS_NIL: {
			*trgp = (as_val*)&as_nil;
			break;
		}
		case AS_INTEGER: {
			as_integer* s = (as_integer*)src;

			if (trg) {
				as_integer_init((as_integer*)trg, s->value);
				*trgp = trg;
			}
			else {
				*trgp = (as_val*)as_integer_new(s->value);
			}
			break;
		}
		case AS_DOUBLE: {
			as_double* s = (as_double*)src;

			if (trg) {
				as_double_init((as_double*)trg, s->value);
				*trgp = trg;
			}
			else {
				*trgp = (as_val*)as_double_new(s->value);
			}
			break;
		}
		case AS_STRING: {
			as_string* s = (as_string*)src;
			size_t len = as_string_len(s);
			char* sc = cf_malloc(len + 1);
			memcpy(sc, s->value, len);
			sc[len] = 0;

			if (trg) {
				as_string_init_wlen((as_string*)trg, sc, len, true);
				*trgp = trg;
			}
			else {
				*trgp = (as_val*)as_string_new_wlen(sc, len, true);
			}
			break;
		}
		case AS_BYTES: {
			as_bytes* s = (as_bytes*)src;
			uint8_t* sb = cf_malloc(s->size);
			memcpy(sb, s->value, s->size);

			if (trg) {
				as_bytes* t = (as_bytes*)trg;
				as_bytes_init_wrap(t, sb, s->size, true);
				t->type = s->type;
				*trgp = trg;
			}
			else {
				as_bytes* t = as_bytes_new_wrap(sb, s->size, true);
				t->type = s->type;
				*trgp = (as_val*)t;
			}
			break;
		}
		case AS_GEOJSON: {
			as_geojson* s = (as_geojson*)src;
			size_t len = as_geojson_len(s);
			char* sc = cf_malloc(len + 1);
			memcpy(sc, s->value, len);
			sc[len] = 0;

			as_geojson* t = as_geojson_new_wlen(sc, len, true);
			*trgp = (as_val*)t;
			break;
		}
		case AS_LIST: {
			as_list* slist = (as_list*)src;
			uint32_t size = as_list_size(slist);

			as_arraylist* tlist = as_arraylist_new(size, 0);

			for (uint32_t i = 0; i < size; i++) {
				as_val* sv = as_list_get(slist, i);
				as_val* tv;
				as_val_copy(sv, NULL, &tv);
				as_arraylist_append(tlist, tv);
			}
			*trgp = (as_val*)tlist;
			break;
		}
		case AS_MAP: {
			as_map* smap = (as_map*)src;
			uint32_t size = as_map_size(smap);

			as_hashmap* tmap = as_hashmap_new(size);

			as_hashmap_iterator it;
			as_hashmap_iterator_init(&it, (const as_hashmap*)smap);

			while (as_hashmap_iterator_has_next(&it)) {
				as_pair* pair = (as_pair*)as_hashmap_iterator_next(&it);

				as_val* sk = as_pair_1(pair);
				as_val* tk;
				as_val_copy(sk, NULL, &tk);

				as_val* sv = as_pair_2(pair);
				as_val* tv;
				as_val_copy(sv, NULL, &tv);

				as_hashmap_set(tmap, tk, tv);
			}
			as_hashmap_iterator_destroy(&it);
			*trgp = (as_val*)tmap;
			break;
		}
		default: {
			// Type invalid. Set value to nil.
			*trgp = (as_val*)&as_nil;
			break;
		}
	}
}

static void
as_key_copy(as_key* src, as_key* trg)
{
	trg->_free = false;
	strcpy(trg->ns, src->ns);
	strcpy(trg->set, src->set);
	memcpy(&trg->digest, &src->digest, sizeof(as_digest));
	as_val_copy((as_val*)src->valuep, (as_val*)&trg->value, (as_val**)&trg->valuep);
}

static void
as_bin_copy(as_bin* src, as_bin* trg)
{
	strcpy(trg->name, src->name);
	as_val_copy((as_val*)src->valuep, (as_val*)&trg->value, (as_val**)&trg->valuep);
}

void
as_record_copy(as_record* src, as_record* trg)
{
	uint16_t size = src->bins.size;
	as_record_init(trg, size);

	as_key_copy(&src->key, &trg->key);
	trg->gen = src->gen;
	trg->ttl = src->ttl;
	trg->bins.size = size;

	as_bin* sb = src->bins.entries;
	as_bin* tb = trg->bins.entries;

	for (uint16_t i = 0; i < size; i++) {
		as_bin_copy(sb++, tb++);
	}
}

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.