[Spice-devel] [PATCH libcacard 07/45] simpletlv: Allow clonning of the SimpleTLV structures with test

Jonathon Jongsma jjongsma at redhat.com
Wed Aug 1 14:52:27 UTC 2018


just a minor typo in the summary: clonning -> cloning


On Tue, 2018-07-31 at 16:50 +0200, Jakub Jelen wrote:
>  * This function creates a deep copy of the whole structure.
>  * The new structure is dynamically allocated and needs to be freed.
> 
> Signed-off-by: Jakub Jelen <jjelen at redhat.com>
> Reviewed-by: Robert Relyea <rrelyea at redhat.com>
> ---
>  src/simpletlv.c   | 42 ++++++++++++++++++++++++++++++++++++++++++
>  src/simpletlv.h   |  9 +++++++++
>  tests/simpletlv.c | 28 ++++++++++++++++++++++++++++
>  3 files changed, 79 insertions(+)
> 
> diff --git a/src/simpletlv.c b/src/simpletlv.c
> index 5cea04b..2a9a6a7 100644
> --- a/src/simpletlv.c
> +++ b/src/simpletlv.c
> @@ -278,4 +278,46 @@ simpletlv_free(struct simpletlv_member *tlv,
> size_t tlvlen)
>      }
>      free(tlv);
>  }
> +
> +struct simpletlv_member *
> +simpletlv_clone(struct simpletlv_member *tlv, size_t tlvlen)
> +{
> +    size_t i = 0, j;
> +    struct simpletlv_member *new = NULL;
> +
> +    new = malloc(sizeof(struct simpletlv_member)*tlvlen);
> +    if (!new)
> +        goto failure;
> +
> +    for (i = 0; i < tlvlen; i++) {
> +        new[i].type = tlv[i].type;
> +        new[i].tag = tlv[i].tag;
> +        new[i].length = tlv[i].length;
> +        if (tlv[i].type == SIMPLETLV_TYPE_COMPOUND) {
> +            new[i].value.child = simpletlv_clone(
> +                tlv[i].value.child, tlv[i].length);
> +            if (new[i].value.child == NULL)
> +                goto failure;
> +        } else {
> +            new[i].value.value = malloc(
> +                sizeof(unsigned char)*tlv[i].length);
> +            if (new[i].value.value == NULL)
> +                goto failure;
> +            memcpy(new[i].value.value, tlv[i].value.value,
> +                tlv[i].length);
> +        }
> +    }
> +    return new;
> +
> +failure:
> +    for (j = 0; j < i; i++) {
> +        if (tlv[i].type == SIMPLETLV_TYPE_COMPOUND) {
> +            simpletlv_free(new[i].value.child, new[i].length);
> +        } else {
> +            free(new[i].value.value);
> +        }
> +    }
> +    free(new);
> +    return NULL;
> +}
>  /* vim: set ts=4 sw=4 tw=0 noet expandtab: */
> diff --git a/src/simpletlv.h b/src/simpletlv.h
> index dcb795b..e1cb5a2 100644
> --- a/src/simpletlv.h
> +++ b/src/simpletlv.h
> @@ -115,4 +115,13 @@ int
>  simpletlv_read_tag(unsigned char **buf, size_t buflen,
>                     unsigned char *tag_out, size_t *taglen);
>  
> +
> +/* create a deep copy of the SimpleTLV structure
> + *
> + * The calling function is responsible for freeing the structure and
> + * all its children by calling simpletlv_free().
> + */
> +struct simpletlv_member *
> +simpletlv_clone(struct simpletlv_member *tlv, size_t tlvlen);
> +
>  #endif
> diff --git a/tests/simpletlv.c b/tests/simpletlv.c
> index 3bd22ae..2be78db 100644
> --- a/tests/simpletlv.c
> +++ b/tests/simpletlv.c
> @@ -220,6 +220,7 @@ static void test_encode_skipped(void)
>        {0x30, 2, {/*.value = simple_value2*/}, SIMPLETLV_TYPE_NONE}
>      };
>      unsigned char encoded[] = "\x25\x02\x12\x14";
> +
>      simple[0].value.value = simple_value;
>      simple[1].value.value = simple_value2;
>  
> @@ -242,6 +243,32 @@ static void test_encode_skipped(void)
>      g_free(result);
>  }
>  
> +static void test_clone_simple(void)
> +{
> +    unsigned char *result = NULL;
> +    size_t result_len = 0;
> +    unsigned char simple_value[] = "\x14\x18";
> +    unsigned char simple_value2[] = "\x64\x24\x44";
> +    static struct simpletlv_member simple[2] = {
> +      {0x13, 2, {/*.value = simple_value*/}, SIMPLETLV_TYPE_LEAF},
> +      {0xDD, 3, {/*.value = simple_value2*/}, SIMPLETLV_TYPE_LEAF}
> +    };
> +    unsigned char encoded[] =
> "\x13\x02\x14\x18\xDD\x03\x64\x24\x44";
> +    struct simpletlv_member *clone;
> +
> +    simple[0].value.value = simple_value;
> +    simple[1].value.value = simple_value2;
> +
> +    clone = simpletlv_clone(simple, 2);
> +    g_assert_nonnull(clone);
> +
> +    result = NULL;
> +    result_len = simpletlv_encode(clone, 2, &result, 0, NULL);
> +    g_assert_cmpmem(result, result_len, encoded, 9);
> +    g_free(result);
> +    simpletlv_free(clone, 2);
> +}
> +
>  int main(int argc, char *argv[])
>  {
>      int ret;
> @@ -256,6 +283,7 @@ int main(int argc, char *argv[])
>      g_test_add_func("/simpletlv/encode/simple", test_encode_simple);
>      g_test_add_func("/simpletlv/encode/nested", test_encode_nested);
>      g_test_add_func("/simpletlv/encode/skipped",
> test_encode_skipped);
> +    g_test_add_func("/simpletlv/clone/simple", test_clone_simple);
>  
>      ret = g_test_run();
>  


More information about the Spice-devel mailing list