The new flags allow specifying the case sensitivity of key and value 
independently
The are shorter
0 now represents key never keyvalue reducing the risk for accidential overread

Signed-off-by: Michael Niedermayer <mich...@niedermayer.cc>
---
 libavutil/map.c       | 60 +++++++++++++++++++++++++------------------
 libavutil/map.h       | 30 +++++++++++++++-------
 libavutil/tests/map.c | 22 ++++++++--------
 3 files changed, 67 insertions(+), 45 deletions(-)

diff --git a/libavutil/map.c b/libavutil/map.c
index af1ca61054e..795a8ba24d8 100644
--- a/libavutil/map.c
+++ b/libavutil/map.c
@@ -36,7 +36,7 @@ typedef struct{
 
 struct AVMap{
 #define CMP_MASK 31
-    AVMapCompareFunc cmp[27];
+    AVMapCompareFunc cmp[36];
     AVMapCopyFunc copy;
     AVMapFreeFunc freef;
     size_t count;
@@ -101,29 +101,34 @@ int av_map_supercmp_keyvalue(const char *a, const char *b)
 
 int av_map_add_cmp_func(AVMap *m, AVMapCompareFunc cmp, int cmp_flags)
 {
-    if (cmp_flags >= 27U)
+    if (cmp_flags >= 36U)
         return AVERROR(EINVAL);
 
-    static const uint8_t sensitivity[27][3] = {
-        {0,0, 0},{1,0, 0},{2,0, 0}, {0,3, 0},{1,3, 0},{2,3, 0}, {0,6, 0},{1,6, 
0},{2,6, 0},
-        {0,0, 9},{1,0, 9},{2,0, 9}, {0,3, 9},{1,3, 9},{2,3, 9}, {0,6, 9},{1,6, 
9},{2,6, 9},
-        {0,0,18},{1,0,18},{2,0,18}, {0,3,18},{1,3,18},{2,3,18}, 
{0,6,18},{1,6,18},{2,6,18},};
-    int case_sensitive       =  sensitivity[cmp_flags][0];
-    int keyvalue_sensitive   =  sensitivity[cmp_flags][1];
+    static const uint8_t sensitivity[36][3] = {
+        {0,0, 0},{1,0, 0},{2,0, 0}, {0,3, 0},{1,3, 0},{2,3, 0}, {0,6, 0},{1,6, 
0},{2,6, 0}, {0,9, 0},{1,9, 0},{2,9, 0},
+        {0,0,12},{1,0,12},{2,0,12}, {0,3,12},{1,3,12},{2,3,12}, 
{0,6,12},{1,6,12},{2,6,12}, {0,9,12},{1,9,12},{2,9,12},
+        {0,0,24},{1,0,24},{2,0,24}, {0,3,24},{1,3,24},{2,3,24}, 
{0,6,24},{1,6,24},{2,6,24}, {0,9,24},{1,9,24},{2,9,24},
+    };
+
+    int key_case_sensitive   =  sensitivity[cmp_flags][0];
+    int value_case_sensitive =  sensitivity[cmp_flags][1];
     int truncated_sensitive  =  sensitivity[cmp_flags][2];
 
-    if (!keyvalue_sensitive)
-        return AVERROR(EINVAL);
+    av_assert1(key_case_sensitive + value_case_sensitive + truncated_sensitive 
== cmp_flags);
 
-    av_assert1(case_sensitive + keyvalue_sensitive + truncated_sensitive == 
cmp_flags);
     if (!truncated_sensitive)
         truncated_sensitive = AV_MAP_CMP_NON_TRUNCATED;
 
-    if (     case_sensitive == AV_MAP_CMP_CASE_SENSITIVE && 
m->cmp[keyvalue_sensitive + AV_MAP_CMP_CASE_INSENSITIVE])
+    if (key_case_sensitive == AV_MAP_CMP_KEY_S && m->cmp[value_case_sensitive 
+ AV_MAP_CMP_KEY_I])
         return AVERROR(EINVAL);
-    if ( keyvalue_sensitive == AV_MAP_CMP_KEYVALUE       && 
m->cmp[AV_MAP_CMP_KEY])
+
+    if (value_case_sensitive == AV_MAP_CMP_KEYVALUE__S && 
m->cmp[key_case_sensitive + AV_MAP_CMP_KEYVALUE__I])
         return AVERROR(EINVAL);
-    if (truncated_sensitive == AV_MAP_CMP_NON_TRUNCATED  && 
m->cmp[keyvalue_sensitive + AV_MAP_CMP_TRUNCATED])
+
+    if (value_case_sensitive && m->cmp[key_case_sensitive])
+        return AVERROR(EINVAL);
+
+    if (truncated_sensitive == AV_MAP_CMP_NON_TRUNCATED  && 
m->cmp[key_case_sensitive + value_case_sensitive + AV_MAP_CMP_TRUNCATED])
         return AVERROR(EINVAL);
 
     //max functions is KV NT CS -> KV NT CI -> KV T CI (CI/T is about value 
only) -> K NT CS -> K NT CI -> K T CI
@@ -131,8 +136,13 @@ int av_map_add_cmp_func(AVMap *m, AVMapCompareFunc cmp, 
int cmp_flags)
 
     for (int i=0; i<8; i++) {
         int flags = 0;
-        if (i&1) flags += case_sensitive;
-        if (i&2) flags += keyvalue_sensitive;
+
+        if (i&1) flags += key_case_sensitive;
+
+        if (i&2) flags += AV_MAP_CMP_KEYVALUE; // key compare is always usable 
as keyvalue compare
+        else if (value_case_sensitive) {
+            flags += value_case_sensitive;
+        }
         if (i&4) flags += truncated_sensitive;
 
         if (!m->cmp[flags])
@@ -143,7 +153,7 @@ int av_map_add_cmp_func(AVMap *m, AVMapCompareFunc cmp, int 
cmp_flags)
 
 int av_map_is_cmp_flags_supported(AVMap *m, int cmp_flags)
 {
-    if (cmp_flags >= 27U)
+    if (cmp_flags >= 36U)
         return AVERROR(EINVAL);
     return !!m->cmp[cmp_flags];
 }
@@ -184,7 +194,7 @@ const AVMapEntry *av_map_get_multiple(const AVMap *s, const 
AVMapEntry *prev, co
 
     if (prev) {
         void *next_node[2] = { NULL, NULL };
-        void *prev_keyvalue = av_tree_find2(s->tree_root, prev->key, 
s->cmp[0], next_node, 2);
+        void *prev_keyvalue = av_tree_find2(s->tree_root, prev->key, 
s->cmp[AV_MAP_CMP_KEYVALUE], next_node, 2);
         av_assert2(prev_keyvalue);
         if (!next_node[1] || cmp(next_node[1], keyvalue))
             return NULL;
@@ -270,15 +280,15 @@ int av_map_add(AVMap *s, const char *key, size_t keylen, 
const char *value, size
     memcpy(entry->key  , key  , keylen);
     memcpy(entry->value, value, valuelen);
 
-    void *elem = av_tree_insert(&s->tree_root, entry->key, s->cmp[0], &next);
+    void *elem = av_tree_insert(&s->tree_root, entry->key, 
s->cmp[AV_MAP_CMP_KEYVALUE], &next);
     int ret = 1;
     if (elem != entry->key && elem) {
         av_assert2(next);
         //we assume that new entries are more common than replacements
         if (flags & AV_MAP_REPLACE) {
-            ret = av_map_del(s, entry->key, flags & ~CMP_MASK);
+            ret = av_map_del(s, entry->key, (flags & ~CMP_MASK) + 
AV_MAP_CMP_KEYVALUE);
             av_assert2(ret == 1);
-            elem = av_tree_insert(&s->tree_root, entry->key, s->cmp[0], &next);
+            elem = av_tree_insert(&s->tree_root, entry->key, 
s->cmp[AV_MAP_CMP_KEYVALUE], &next);
             av_assert2(elem == entry->key || !elem);
             ret = 2;
         } else
@@ -303,7 +313,7 @@ int av_map_del(AVMap *s, const char *keyvalue, int flags)
     AVTreeNode *next = NULL;
     AVMapCompareFunc cmp = s->cmp[flags & CMP_MASK];
 
-    if (cmp != s->cmp[0]) {
+    if (cmp != s->cmp[AV_MAP_CMP_KEYVALUE]) {
         // The user asks us to remove a entry with a compare function 
different from the one used to build the map
         // we need to do 2 calls here, first with the users compare to find 
the entry she wants to remove
         // and then to remove it while maintaining the correct order within 
the map
@@ -311,10 +321,10 @@ int av_map_del(AVMap *s, const char *keyvalue, int flags)
         if (!old_keyvalue)
             return 0;
 
-        av_tree_insert(&s->tree_root, old_keyvalue, s->cmp[0], &next);
+        av_tree_insert(&s->tree_root, old_keyvalue, 
s->cmp[AV_MAP_CMP_KEYVALUE], &next);
         av_assert2(next);
     } else {
-        av_tree_insert(&s->tree_root, (char*)keyvalue, s->cmp[0], &next);
+        av_tree_insert(&s->tree_root, (char*)keyvalue, 
s->cmp[AV_MAP_CMP_KEYVALUE], &next);
         if (!next)
             return 0;
         old_keyvalue = next->elem; //TODO add a API to av_tree() to return the 
elem of a AVTreeNode
@@ -327,7 +337,7 @@ int av_map_del(AVMap *s, const char *keyvalue, int flags)
     s->deleted++;
 
     if ((flags & AV_MAP_ALLOW_REBUILD) && s->deleted > s->count) {
-        AVMap *news = av_map_alloc(s->cmp[0], AV_MAP_CMP_KEYVALUE + 
AV_MAP_CMP_NON_TRUNCATED, s->copy, s->freef);
+        AVMap *news = av_map_alloc(s->cmp[AV_MAP_CMP_KEYVALUE], 
AV_MAP_CMP_KEYVALUE + AV_MAP_CMP_NON_TRUNCATED, s->copy, s->freef);
         if(news) {
             memcpy(news->cmp, s->cmp, sizeof(news->cmp));
             int ret = av_map_copy(news, s);
diff --git a/libavutil/map.h b/libavutil/map.h
index 2784bde0ae0..61c64900ace 100644
--- a/libavutil/map.h
+++ b/libavutil/map.h
@@ -37,13 +37,13 @@
  *
  * ---------- Creating AVMaps ------------------
  *
- * AVMap *map = av_map_alloc(strcmp, AV_MAP_CMP_CASE_SENSITIVE + 
AV_MAP_CMP_KEY, NULL, NULL);
+ * AVMap *map = av_map_alloc(strcmp, AV_MAP_CMP_KEY_S, NULL, NULL);
  *
  * This creates a case sensitve string based map using strcmp(). It will not 
allow
  * multiple entries with the same key.
  * or
  *
- * AVMap *map = av_map_alloc(av_map_strcmp_keyvalue, AV_MAP_CMP_CASE_SENSITIVE 
+ AV_MAP_CMP_KEYVALUE, NULL, NULL);
+ * AVMap *map = av_map_alloc(av_map_strcmp_keyvalue, AV_MAP_CMP_KEYVALUE_SS, 
NULL, NULL);
  *
  * This is like the previous, but it will allow multiple entries with the same 
key
  * the difference here is that the compare function compares the value too when
@@ -78,7 +78,7 @@
  *
  * AVMapEntry *e = av_map_get(map, "cat", AV_MAP_CMP_KEY); //Find an entry 
with the key = "cat"
  *
- * AVMapEntry *e = av_map_get(map, "cat", 
AV_MAP_CMP_KEY+AV_MAP_CMP_CASE_INSENSITIVE); //Find an entry with the key = 
"cat", "Cat", "cAt", ...
+ * AVMapEntry *e = av_map_get(map, "cat", AV_MAP_CMP_KEY_I); //Find an entry 
with the key = "cat", "Cat", "cAt", ...
  * // this will only work if one of the set compare functions is case 
insensitive
  *
  *
@@ -133,12 +133,24 @@
 
 enum {
 //use + not | to combine these flags
-    AV_MAP_CMP_CASE_SENSITIVE   = 1,
-    AV_MAP_CMP_CASE_INSENSITIVE = 2,
-    AV_MAP_CMP_KEY              = 3,
-    AV_MAP_CMP_KEYVALUE         = 6,
-    AV_MAP_CMP_TRUNCATED        = 9,
-    AV_MAP_CMP_NON_TRUNCATED    = 18,
+    AV_MAP_CMP_KEY              = 0,    ///< key compare
+    AV_MAP_CMP_KEY_I            = 1,    ///< case insensitive key compare
+    AV_MAP_CMP_KEY_S            = 2,    ///< case   sensitive key compare
+
+    AV_MAP_CMP_KEYVALUE         = 3,    ///< key and value compare
+    AV_MAP_CMP_KEYVALUE_I_      = 3+1,  ///< case insensitive key and value 
compare
+    AV_MAP_CMP_KEYVALUE_S_      = 3+2,  ///< case   sensitive key and value 
compare
+
+    AV_MAP_CMP_KEYVALUE__I      = 6,    ///< key and case insensitive value 
compare
+    AV_MAP_CMP_KEYVALUE_II      = 6+1,  ///< case insensitive key and case 
insensitive value compare
+    AV_MAP_CMP_KEYVALUE_SI      = 6+2,  ///< case   sensitive key and case 
insensitive value compare
+
+    AV_MAP_CMP_KEYVALUE__S      = 9,    ///< key and case sensitive value 
compare
+    AV_MAP_CMP_KEYVALUE_IS      = 9+1,  ///< case insensitive key and case 
sensitive value compare
+    AV_MAP_CMP_KEYVALUE_SS      = 9+2,  ///< case   sensitive key and case 
sensitive value compare
+
+    AV_MAP_CMP_TRUNCATED        = 12,
+    AV_MAP_CMP_NON_TRUNCATED    = 24,
 
     AV_MAP_ALLOW_REBUILD        = 256,   ///< when removing entries rebuild 
the map to reduce memory consumption, note, this invalidates previously 
retrieved elements and iterate state.
     AV_MAP_REPLACE              = 512,   ///< replace keyvalue if already in 
the map
diff --git a/libavutil/tests/map.c b/libavutil/tests/map.c
index e43f0f05db4..e1412e0dfc8 100644
--- a/libavutil/tests/map.c
+++ b/libavutil/tests/map.c
@@ -48,11 +48,11 @@ int main(void)
         av_map_supercmp_keyvalue,
     };
     int our_flags[] = {
-        AV_MAP_CMP_NON_TRUNCATED + AV_MAP_CMP_CASE_SENSITIVE   + 
AV_MAP_CMP_KEY,
-        AV_MAP_CMP_NON_TRUNCATED + AV_MAP_CMP_CASE_SENSITIVE   + 
AV_MAP_CMP_KEYVALUE,
-        AV_MAP_CMP_NON_TRUNCATED + AV_MAP_CMP_CASE_INSENSITIVE + 
AV_MAP_CMP_KEY,
-        AV_MAP_CMP_NON_TRUNCATED + AV_MAP_CMP_CASE_SENSITIVE   + 
AV_MAP_CMP_KEYVALUE,
-        AV_MAP_CMP_NON_TRUNCATED + AV_MAP_CMP_CASE_SENSITIVE   + 
AV_MAP_CMP_KEYVALUE,
+        AV_MAP_CMP_NON_TRUNCATED + AV_MAP_CMP_KEY_S,
+        AV_MAP_CMP_NON_TRUNCATED + AV_MAP_CMP_KEYVALUE_SS,
+        AV_MAP_CMP_NON_TRUNCATED + AV_MAP_CMP_KEY_I,
+        AV_MAP_CMP_NON_TRUNCATED + AV_MAP_CMP_KEYVALUE_SS,
+        AV_MAP_CMP_NON_TRUNCATED + AV_MAP_CMP_KEYVALUE_SS,
     };
     void *our_subcmp[] = {
         strcmp,
@@ -62,11 +62,11 @@ int main(void)
         av_strcasecmp,
     };
     int our_subflags[] = {
-        AV_MAP_CMP_NON_TRUNCATED + AV_MAP_CMP_CASE_SENSITIVE   + 
AV_MAP_CMP_KEY,
-        AV_MAP_CMP_NON_TRUNCATED + AV_MAP_CMP_CASE_SENSITIVE   + 
AV_MAP_CMP_KEY,
-        AV_MAP_CMP_NON_TRUNCATED + AV_MAP_CMP_CASE_INSENSITIVE + 
AV_MAP_CMP_KEY,
-        AV_MAP_CMP_NON_TRUNCATED + AV_MAP_CMP_CASE_SENSITIVE   + 
AV_MAP_CMP_KEY,
-        AV_MAP_CMP_NON_TRUNCATED + AV_MAP_CMP_CASE_INSENSITIVE + 
AV_MAP_CMP_KEY,
+        AV_MAP_CMP_NON_TRUNCATED + AV_MAP_CMP_KEY_S,
+        AV_MAP_CMP_NON_TRUNCATED + AV_MAP_CMP_KEY_S,
+        AV_MAP_CMP_NON_TRUNCATED + AV_MAP_CMP_KEY_I,
+        AV_MAP_CMP_NON_TRUNCATED + AV_MAP_CMP_KEY_S,
+        AV_MAP_CMP_NON_TRUNCATED + AV_MAP_CMP_KEY_I,
     };
 
     for (int settype=0; settype<3; settype++) {
@@ -224,7 +224,7 @@ int main(void)
 #define P 4
     fprintf(stderr, "%d entries variable bytes at location %d-%d\n", 
N_ENTRIES, P, P+1);
     for (int runs = 0; runs < 1000; runs++) {
-        AVMap *map = av_map_alloc(av_strcasecmp, 
AV_MAP_CMP_CASE_INSENSITIVE+AV_MAP_CMP_KEYVALUE+AV_MAP_CMP_NON_TRUNCATED, NULL, 
NULL);
+        AVMap *map = av_map_alloc(av_strcasecmp, 
AV_MAP_CMP_KEY_I+AV_MAP_CMP_NON_TRUNCATED, NULL, NULL);
         for(int pass = 0; pass < 2; pass++) {
             START_TIMER
             unsigned r = 5;
-- 
2.49.0

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-requ...@ffmpeg.org with subject "unsubscribe".

Reply via email to