L'octidi 18 fructidor, an CCXXIII, Kevin Wheatley a écrit :
> as part of adding support for non-string data types to .mov metadata,
> I wondered about adding the following helper functions for storing
> numeric types into an AVDictionary.
>
> upfront I'll say I'm not 100% happy with the float32 and float64 named
> variants (vs float and double) as there is no clear preference in
> other areas of the code that I could see.
These function deal with CPU-ready values, not with the values serialized as
octets in memory; therefore, I am in favour of using the type names: float /
double. There is no guarantee that float is 32 bits and double 64. On
x86_32, double is sometimes 64 sometimes 80 depending on the FPU used.
> From 34fedb67d58402b519a7c91bff7623469802c4c4 Mon Sep 17 00:00:00 2001
> From: Kevin Wheatley
> Date: Fri, 4 Sep 2015 14:26:49 +0100
> Subject: [PATCH] libavutil/dict: extend the list of convienience functions
> for storing different data types
>
>
> Signed-off-by: Kevin Wheatley
> ---
> libavutil/dict.c| 81 +-
> libavutil/dict.h| 24 +++
> tests/ref/fate/dict | 17 +++
> 3 files changed, 120 insertions(+), 2 deletions(-)
>
> diff --git a/libavutil/dict.c b/libavutil/dict.c
> index 6ff1af5..4eaaf83 100644
> --- a/libavutil/dict.c
> +++ b/libavutil/dict.c
> @@ -149,6 +149,33 @@ int av_dict_set_int(AVDictionary **pm, const char *key,
> int64_t value,
> return av_dict_set(pm, key, valuestr, flags);
> }
>
> +int av_dict_set_uint(AVDictionary **pm, const char *key, uint64_t value,
> +int flags)
> +{
> +char valuestr[22];
> +snprintf(valuestr, sizeof(valuestr), "%"PRIu64, value);
> +flags &= ~AV_DICT_DONT_STRDUP_VAL;
I do not like that, it feels like defensive programming. API users should
not give random flags to functions and expect them to work. Therefore, I
would rather have the documentation state "AV_DICT_DONT_STRDUP_VAL must not
be set", implying that setting it is an undefined behaviour.
(And just to be nice, av_assert0() that it is not set: failing an assert is
the epitome of undefined behaviour, but nicer to debug than memory
corruption.)
> +return av_dict_set(pm, key, valuestr, flags);
> +}
> +
> +int av_dict_set_float32(AVDictionary **pm, const char *key, float value,
> +int flags)
> +{
> +char valuestr[17]; // sign + 1 + point + 8 + e + sign + 3 + term
> +snprintf(valuestr, sizeof(valuestr), "%.9g", value);
> +flags &= ~AV_DICT_DONT_STRDUP_VAL;
> +return av_dict_set(pm, key, valuestr, flags);
> +}
> +
> +int av_dict_set_float64(AVDictionary **pm, const char *key, double value,
> +int flags)
> +{
> +char valuestr[26]; // sign + 1 + point + 16 + e + sign + 4 + term
> +snprintf(valuestr, sizeof(valuestr), "%.17g", value);
> +flags &= ~AV_DICT_DONT_STRDUP_VAL;
> +return av_dict_set(pm, key, valuestr, flags);
> +}
> +
> static int parse_key_value_pair(AVDictionary **pm, const char **buf,
> const char *key_val_sep, const char
> *pairs_sep,
> int flags)
> @@ -276,9 +303,13 @@ static void test_separators(const AVDictionary *m, const
> char pair, const char v
> int main(void)
> {
> AVDictionary *dict = NULL;
> -AVDictionaryEntry *e;
> +AVDictionaryEntry *e, *e2;
> char *buffer = NULL;
> -
> +float f32 = 0.0f;
> +double f64 = 0.0f;
> +union { uint32_t i; float f; } intfloat;
> +union { uint64_t ui; int64_t i; } un_signed_int;
What you are doing with these unions is highly non-portable and should be
avoided in the current code IMHO.
> +
> printf("Testing av_dict_get_string() and av_dict_parse_string()\n");
> av_dict_get_string(dict, &buffer, '=', ',');
> printf("%s\n", buffer);
> @@ -356,6 +387,52 @@ int main(void)
> printf("%s\n", e->value);
> av_dict_free(&dict);
>
> +printf("\nTesting av_dict_set_int()\n");
> +un_signed_int.ui = 0U;
> +av_dict_set_int(&dict, "0", un_signed_int.i, 0);
> +un_signed_int.ui = 0x8000UL;
> +av_dict_set_int(&dict, "-max", un_signed_int.i, 0);
> +un_signed_int.ui = 0x7fffUL;
> +av_dict_set_int(&dict, "max", un_signed_int.i, 0);
> +e = NULL;
> +while ((e = av_dict_get(dict, "", e, AV_DICT_IGNORE_SUFFIX)))
> +printf("%s %s\n", e->key, e->value);
> +av_dict_free(&dict);
> +
> +printf("\nTesting av_dict_set_uint()\n");
> +av_dict_set_uint(&dict, "0", 0, 0);
> +av_dict_set_uint(&dict, "max", 0xUL, 0);
> +e = NULL;
> +while ((e = av_dict_get(dict, "", e, AV_DICT_IGNORE_SUFFIX)))
> +printf("%s %s\n", e->key, e->value);
> +av_dict_free(&dict);
> +
> +printf("\nTesting av_dict_set_float*()\n");
> +// float and double representation of a given number should give the
> same value
> +f32 = -1.20786635e-05f;
> +f64 =