int aws_cryptosdk_enc_ctx_clone()

in source/enc_ctx.c [202:257]


int aws_cryptosdk_enc_ctx_clone(
    struct aws_allocator *alloc, struct aws_hash_table *dest, const struct aws_hash_table *src) {
    AWS_PRECONDITION(aws_allocator_is_valid(alloc));
    AWS_PRECONDITION(aws_hash_table_is_valid(dest));
    AWS_PRECONDITION(aws_hash_table_is_valid(src));

    /* First, scan the destination for keys that don't belong, and remove them */
    for (struct aws_hash_iter iter = aws_hash_iter_begin(dest); !aws_hash_iter_done(&iter); aws_hash_iter_next(&iter)) {
        struct aws_hash_element *src_elem = NULL;

        /* We don't need to check for an error return as we can just look at src_elem */
        aws_hash_table_find(src, iter.element.key, &src_elem);

        if (src_elem == NULL) {
            aws_hash_iter_delete(&iter, true);
        }
    }

    /* Next, iterate src and ensure that the destination is consistent */
    for (struct aws_hash_iter iter = aws_hash_iter_begin(src); !aws_hash_iter_done(&iter); aws_hash_iter_next(&iter)) {
        struct aws_hash_element *dest_elem = NULL;

        /*
         * We don't use _create here as we might not be able to reuse the key as-is, and want to avoid duping it
         * if it's already in the destination hash table.
         */
        aws_hash_table_find(dest, iter.element.key, &dest_elem);

        if (dest_elem && !aws_string_eq(dest_elem->value, iter.element.value)) {
            /* The key was present; only the value needs to be updated */
            struct aws_string *value = clone_or_reuse_string(alloc, iter.element.value);

            if (!value) {
                return AWS_OP_ERR;
            }

            aws_string_destroy(dest_elem->value);
            dest_elem->value = value;
        } else if (!dest_elem) {
            /* A new element needs to be created, with a copy of the key and value */
            struct aws_string *key   = clone_or_reuse_string(alloc, iter.element.key);
            struct aws_string *value = clone_or_reuse_string(alloc, iter.element.value);

            if (!key || !value || aws_hash_table_put(dest, key, value, NULL)) {
                aws_string_destroy(key);
                aws_string_destroy(value);

                return AWS_OP_ERR;
            }
        } else {
            /* Key and value matched; no change needed */
        }
    }

    return AWS_OP_SUCCESS;
}