free(container);
}
+/**
+ * Duplicates a contract block of a given type. Calls duplication
+ * method registered with the block.
+ *
+ * @param dest Where to store the copy
+ * @param source What to copy
+ *
+ * @return Zero on success, non-zero error code on error.
+ */
+int
+fres_block_duplicate(struct fres_block *dest,
+ const struct fres_block *source,
+ enum fres_block_type type)
+{
+ dest->state = FRES_BLOCK_EMPTY;
+ switch (source->state) {
+ case FRES_BLOCK_EMPTY:
+ /* nothing to do */
+ break;
+ case FRES_BLOCK_DATA: {
+ void *dup;
+ dup = block_registry[type]->duplicate(
+ type, source->u.data);
+ if (!dup) {
+ return FRES_ERR_BLOCK_DUP;
+ }
+ dest->u.data = dup;
+ dest->state = FRES_BLOCK_DATA;
+ break;
+ }
+ case FRES_BLOCK_STREAM:
+ dest->state = FRES_BLOCK_STREAM;
+ dest->u.stream = source->u.stream;
+ dest->u.stream.data = malloc(source->u.stream.length);
+ if (!dest->u.stream.data) {
+ return errno;
+ }
+ memcpy(dest->u.stream.data, source->u.stream.data,
+ source->u.stream.length);
+ break;
+ }
+ return 0;
+}
+
+
+
/**
* Duplicates a container
*
{
struct fres_container *dest;
enum fres_block_type type;
-
+ int ret;
if (!source) return NULL;
dest = fres_container_new();
if (!dest) return NULL;
for (type=0; type<FRES_NUM_BLOCKS; type++) {
- const struct fres_block *sb = &source->blocks[type];
- struct fres_block *db = &dest->blocks[type];
- db->state = FRES_BLOCK_EMPTY;
- switch (sb->state) {
- case FRES_BLOCK_EMPTY:
- /* nothing to do */
- break;
- case FRES_BLOCK_DATA: {
- void *dup;
- dup = block_registry[type]->duplicate(
- type, sb->u.data);
- if (!dup) goto free_dest_err;
- fres_container_add_block(dest, type, dup);
- break;
- case FRES_BLOCK_STREAM:
- db->state = FRES_BLOCK_STREAM;
- db->u.stream = sb->u.stream;
- db->u.stream.data = malloc(sb->u.stream.length);
- if (!db->u.stream.data) goto free_dest_err;
- memcpy(db->u.stream.data, sb->u.stream.data,
- sb->u.stream.length);
- break;
- }
- }
+ ret = fres_block_duplicate(&dest->blocks[type], &source->blocks[type], type);
+ if (ret) goto free_dest_err;
}
return dest;
free_dest_err:
err:
return ret;
}
+
+
+/**
+ * Returns the number of non-empty blocks in a container.
+ *
+ * @param c Container
+ *
+ * @return Number of non-empty blocks in container @a c.
+ */
+int
+fres_container_get_num_blocks(const struct fres_container *c)
+{
+ int num = 0;
+ enum fres_block_type type;
+
+ for (type=0; type<FRES_NUM_BLOCKS; type++) {
+ if (c->blocks[type].state != FRES_BLOCK_EMPTY) {
+ num++;
+ }
+ }
+ return num;
+}