From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: <ffmpeg-devel-bounces@ffmpeg.org> Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by master.gitmailbox.com (Postfix) with ESMTPS id E272D4D311 for <ffmpegdev@gitmailbox.com>; Wed, 16 Apr 2025 20:22:34 +0000 (UTC) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id C23B868A114; Wed, 16 Apr 2025 23:22:29 +0300 (EEST) Received: from NAM11-CO1-obe.outbound.protection.outlook.com (mail-co1nam11olkn2062.outbound.protection.outlook.com [40.92.18.62]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id 5B77A687D99 for <ffmpeg-devel@ffmpeg.org>; Wed, 16 Apr 2025 23:22:23 +0300 (EEST) ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=aSO9C4gok8dbdhuUAscvN9/e8oe0Bc82DLnPbAx1v/75ENuq1Mn/kB5+r4wjJKsMGGS8EqMaiBTZCkll0tORUACik1ioUJAtLWtJ+pTVnfNHE7vUHqYL+cL22L80pzWanyBe1kgTStLGxg152QWwu8NHptoWCT51YndxSGwQP93axDK6eOdgMHSxFRK0uaLRUP/sVLACXVBfc/d5TmIHLsWA9whQpZ00Xjt0l+h2h42L+ro7lnG8eIl5s33AWTJg8WnLGeDqra+68ZHaHHDTe+cnVO7Pz/6SfUrFbLZ7zq+3vkdR/nRQeVGwdIT+yIf3q8BQLHt6HQU8gQs/RhZIyg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=Rw0hDBxJ4FMaeMc511DjUpAheSHXViFNzEeKD8QOd6o=; b=s1VnzcO6qwawAuGnITCm4RfqxxA9mchWZzgtW7leDTWjzu2qExgu4F13tsDlbVfUsKBQHNVC+4xtceXU6JwmjhJVwNne+wry7o1xf2GaSP3YA/Y4oaaX8QPo03b6dMLT5ZacJ2GtZ42eS1BL4zPZ/x2qYI/iYFUNyGxdTGGwL2IC0LAtccsjj932En6TTBpmw2t61EBrcPFvUBKwZ+UgOPjCgQ7i88qLcZJ9KFHRJhw4yABL6EVUHHOZXTjnovyC61/jB5X9yDOj4o9a4Cu0Hjs+XeANBBvfUCyX7sd/O/aFYy1S5meAR+z4muEuXvEmw8617JjWJfcpeQHH5S8PXQ== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=none; dmarc=none; dkim=none; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=hotmail.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=Rw0hDBxJ4FMaeMc511DjUpAheSHXViFNzEeKD8QOd6o=; b=rtHAX7qf6qxOIRfVBtm0K3gYrROnEffSBAgbfhUgrDZTvA+tmXk7b4mdbXT0wGF7Zx6vzdoJIPPtY2fIIW4YztsCrxWWbhFBKM6AZp1Dt4bMC7MaGHsvxa5aivkjeyS5JdY+jhbR3aaQBy7RU6GGPPPsR1VsK1qs7OJaPaeYNZlnk2+YyedHEh11el2mRUIr0Jsj3zegf98RgoC7KvTUXXgmd+ePAWu3IFCdMcRnzC4lGkqD5Hwe/5+ZUvD4Phtk2wkrveMDG7XHt1B8+MCNF0Gs7i/QDSUxKlXxZHCNC6+VWvjNTPoG8mkwWXuNnx9/BghWMNJX1ZuGkMK0O3BMkw== Received: from DM8P223MB0365.NAMP223.PROD.OUTLOOK.COM (2603:10b6:8:b::20) by SA1P223MB0607.NAMP223.PROD.OUTLOOK.COM (2603:10b6:806:25a::8) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.8606.35; Wed, 16 Apr 2025 20:22:18 +0000 Received: from DM8P223MB0365.NAMP223.PROD.OUTLOOK.COM ([fe80::bf09:8e9:b07f:98a7]) by DM8P223MB0365.NAMP223.PROD.OUTLOOK.COM ([fe80::bf09:8e9:b07f:98a7%4]) with mapi id 15.20.8655.022; Wed, 16 Apr 2025 20:22:18 +0000 From: "softworkz ." <softworkz-at-hotmail.com@ffmpeg.org> To: FFmpeg development discussions and patches <ffmpeg-devel@ffmpeg.org> Thread-Topic: [FFmpeg-devel] [PATCH] avutil/map: replace passing Compare functions by flags Thread-Index: AQHbrwviSrnLYjDflUuPSEhfM2JrTbOmuh/Q Date: Wed, 16 Apr 2025 20:22:18 +0000 Message-ID: <DM8P223MB036559EBCB2C822F98D56A3FBABD2@DM8P223MB0365.NAMP223.PROD.OUTLOOK.COM> References: <20250416201208.2827641-1-michael@niedermayer.cc> In-Reply-To: <20250416201208.2827641-1-michael@niedermayer.cc> Accept-Language: en-US Content-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-ms-publictraffictype: Email x-ms-traffictypediagnostic: DM8P223MB0365:EE_|SA1P223MB0607:EE_ x-ms-office365-filtering-correlation-id: a33471db-0cd4-4074-b690-08dd7d246294 x-microsoft-antispam: BCL:0; ARA:14566002|8062599003|461199028|7092599003|8060799006|19110799003|15080799006|440099028|19061999003|3412199025|12091999003|41001999003|102099032; x-microsoft-antispam-message-info: =?us-ascii?Q?9Px1cgthQWiAPZAdy/Ey4/VZmNhloYgAE+sB2TZkDMiScJ26tnXnvzWiKJD1?= =?us-ascii?Q?IPxDr6CUfHTQFwdTEwqSKKsAUkqxLoBTQPjE3Nwzl6+OeX8hTEotgsQcdjJG?= =?us-ascii?Q?uYnhLDUwP3ox7S/HgjAxxcKyJJiuEoQFNJohOzelloP2COvvxcyx5H7Ifco8?= =?us-ascii?Q?8WLYjxD9+vmoDSfijp/hnHYClkhDQl2SlJq1Hswh8NRdqynPpLiG5ZHt7iyR?= =?us-ascii?Q?AwHC3br7ew/AdQtxhEmmAd496Mdf808undSHnx7bzt3Dg/cJBpS8QTumYEG5?= =?us-ascii?Q?YCN1hraf4QMIrTxBLr2io4dyn9BBLcoWZD4TyQR/cb2/X2NZ+X/ouUmUOoRT?= =?us-ascii?Q?voCVF8rmHSp3nxhkkV0VqaWIN9HQiUapZJQSYuaHsGtr4OmGZqcklupe0AiB?= =?us-ascii?Q?gSJbudqtUMdQ3fE1N/kEzDvTd3U1VydSpNdbWLXrH2jlJ+4zawX4KIzYLHGD?= =?us-ascii?Q?pCZTjuiUwvL8YVoE8fP8huJAkoFMJ2LIj2cml2VWynBYC7YFr8cRPYUW5WHV?= =?us-ascii?Q?9x6iCxv4UQLKER8lTCE6ZoEwy9ko9LrWSYGxwEPs+Nv6qlioiSjzx7YGdm0k?= =?us-ascii?Q?xBFmGA7zao4P30jDSnQ68G5pubejf6vaLRsepbxWPyNWkhf1o4Jw14UhHJM7?= =?us-ascii?Q?7NjG8bLjZUes+WO0D8irMIcVmXpHWh5crTmdtvSwK4soF+eQoHjeB/51+VeA?= =?us-ascii?Q?uOl5HpG0M92ul6FYtFoxbrYneZplhE+w0cmA9WiWuYP1VbLjgwybynrekw/k?= =?us-ascii?Q?/6lIUa7Wu3go4hFzlJdvy0EHl4UmLNNevdEF8ahgfnfB+SiOQJNlu5JD828m?= =?us-ascii?Q?f6DZsfYF30Oda5WSCWWn5NcpEqOKiSEH/WvRhKMnLLkbxvNP0GVd9RKrj2xk?= =?us-ascii?Q?8EfwQCFXf87Jx1afozupIc9y6w9xJuVbpxD4aYrakQ1RefQpMvZOkBK6GKZ+?= =?us-ascii?Q?8Mw3EBPwLvtE1+2ty4JgSpszOTvyxZOkru0bRDK5xpWsdl5K1nO001rONR/X?= =?us-ascii?Q?GimgMahzgPDgHYpo35uoobFBpw8jKAoMuF/YlNbQxTzFSlEeVEiYiWXSI8hF?= =?us-ascii?Q?+bNtVOGZC0sXZCZ7XWWiRdNSfU1rATCLqyXxOq9jhTu6LBcBu2TEu3cdcWjL?= =?us-ascii?Q?EetiSuTXsLhDPEbLvWc6lBjBxN3+ABfleKAVto2izBKZ1knU7vif6sU5/ODp?= =?us-ascii?Q?z24bOQISKF12e/CqmxvfMi4Nvvlw038PyIjczg=3D=3D?= x-ms-exchange-antispam-messagedata-chunkcount: 1 x-ms-exchange-antispam-messagedata-0: =?us-ascii?Q?rT3jfvw3JO0EEOQOx62lYZI7iY2g6QNhVImjZ2myIr25C6R51FP8k+f3cI73?= =?us-ascii?Q?qBUiqNV83DquiHCGLPb1erIa0GDkK+9t24KeBQHTUMaktDfeawgbaEaNUk1w?= =?us-ascii?Q?RJ2Dy8IhadnP7XYHYPabLN5pF4ycoE36DxNwzquoP72/wYrI8fbrv3ArbG+p?= =?us-ascii?Q?sX7gtzPT7/9Xpl2+QPc9k4a1umFYyJLQNLrOQ0hf44N1MLQz7ANBpNDGNKGW?= =?us-ascii?Q?BxyzX0HcXj2oouXu6xY3wIDZaIwUuVcGLATbRHfihaMzuTdnB6qtm+3aQv5h?= =?us-ascii?Q?lMnEpbtIy7+HszvTgLXYdi8NKNITj/bqu9YUXWL8034zK4cWONvHZd+eajfs?= =?us-ascii?Q?ktPnLeFUCtII/x4dE74sXeQnoF8pK+WI94LubT95wS9HuVKN2HsdQa/48mfU?= =?us-ascii?Q?B7y2GMfQZBXwZodjwqZZWH8tbwX7K1HZCTGBnmT3ZWkZj5l7VbQlcdLtufXv?= =?us-ascii?Q?saMb6YhXtK9qjr44VG+epNM6ZeLqRIkZynjleB+iLG8+aKmj0lXsEIfo34+M?= =?us-ascii?Q?v4Etj0ORdXrwaKqKN7CDR4finNuhEFscsq/TFNALEuVz01f4EI2cxOdMbZ0h?= =?us-ascii?Q?ciRmGFsPjwc0M9kxpyIFDNlGNeKVpBvPJaCmJkyvTzAXOYM1BNjmxawuRUkU?= =?us-ascii?Q?5TWcclzrZjeCtXnq8l1bVBcHsuK9kPJ3lXPlhdV29xwQp/h5iv0DMso4iYhv?= =?us-ascii?Q?c5uuj0QWDtDq2IlOWotf9BcJdfKO8hUosyDZ8Uqw64RSLhaTj1F6JMkT5uHY?= =?us-ascii?Q?yKFZr22xKHUCXEYFJnXIGgKdR2vrhY7E7xRx6YFRO5fnaVjB7TvvuCescpBe?= =?us-ascii?Q?RnPANYH2UmHMNWeg0DiXE9qEzDxG6Vr4c44JqyNWgiygovGbGX6GG0VSjZgx?= =?us-ascii?Q?nyjsP3UvD4xqRewehnmGCewacXm/wgvE6gJ3rIscbRTt/3su1S12V3xAaQ3K?= =?us-ascii?Q?DE6aLARMuLKeuBTfYj00m0ZvLyd/PYKQ/xJnNnglW4BN4O2qilgPtswQ4Nt/?= =?us-ascii?Q?nv4AfDew4M3R8ZaESyjmpIuq5moNdYiVLCjAP55HC7JSxsIVqEkA4p+84nP+?= =?us-ascii?Q?+I5oc+qp+tRzKus9GWRLnbx0oKiE3K2IkuuqgNrOobDX1Y6j+KuzeDj787WU?= =?us-ascii?Q?offx2OBLjn1galPjvbbyafPvWwY2g44zphXJLWlWlm07ss5fvDjerpiKeepm?= =?us-ascii?Q?i5/30xfIDz4ZeqX6qeFubWKmwMHNyZ9IRS0xKaChwNbDHNVLGq6WDpXtUlk?= =?us-ascii?Q?=3D?= MIME-Version: 1.0 X-OriginatorOrg: sct-15-20-7719-20-msonline-outlook-92255.templateTenant X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-AuthSource: DM8P223MB0365.NAMP223.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-RMS-PersistedConsumerOrg: 00000000-0000-0000-0000-000000000000 X-MS-Exchange-CrossTenant-Network-Message-Id: a33471db-0cd4-4074-b690-08dd7d246294 X-MS-Exchange-CrossTenant-originalarrivaltime: 16 Apr 2025 20:22:18.2087 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: 84df9e7f-e9f6-40af-b435-aaaaaaaaaaaa X-MS-Exchange-CrossTenant-rms-persistedconsumerorg: 00000000-0000-0000-0000-000000000000 X-MS-Exchange-Transport-CrossTenantHeadersStamped: SA1P223MB0607 Subject: Re: [FFmpeg-devel] [PATCH] avutil/map: replace passing Compare functions by flags X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: FFmpeg development discussions and patches <ffmpeg-devel.ffmpeg.org> List-Unsubscribe: <https://ffmpeg.org/mailman/options/ffmpeg-devel>, <mailto:ffmpeg-devel-request@ffmpeg.org?subject=unsubscribe> List-Archive: <https://ffmpeg.org/pipermail/ffmpeg-devel> List-Post: <mailto:ffmpeg-devel@ffmpeg.org> List-Help: <mailto:ffmpeg-devel-request@ffmpeg.org?subject=help> List-Subscribe: <https://ffmpeg.org/mailman/listinfo/ffmpeg-devel>, <mailto:ffmpeg-devel-request@ffmpeg.org?subject=subscribe> Reply-To: FFmpeg development discussions and patches <ffmpeg-devel@ffmpeg.org> Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" <ffmpeg-devel-bounces@ffmpeg.org> Archived-At: <https://master.gitmailbox.com/ffmpegdev/DM8P223MB036559EBCB2C822F98D56A3FBABD2@DM8P223MB0365.NAMP223.PROD.OUTLOOK.COM/> List-Archive: <https://master.gitmailbox.com/ffmpegdev/> List-Post: <mailto:ffmpegdev@gitmailbox.com> > -----Original Message----- > From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of > Michael Niedermayer > Sent: Mittwoch, 16. April 2025 22:12 > To: FFmpeg development discussions and patches <ffmpeg- > devel@ffmpeg.org> > Subject: [FFmpeg-devel] [PATCH] avutil/map: replace passing Compare > functions by flags > > This makes the API much more robust because if you receive a map > from some other module you no longer need to know which > compare function is correct for it > Instead you just specify what you need, like > AV_MAP_CMP_CASE_SENSITIVE or AV_MAP_CMP_CASE_INSENSITIVE or 0 if you > dont care > and the code will either do what you asked for or cleanly fail if its > unable to > previously it would just give you a wrong result sometimes > > Signed-off-by: Michael Niedermayer <michael@niedermayer.cc> > --- > libavutil/map.c | 80 +++++++++++++++++++++++++++++++++++------- > - > libavutil/map.h | 53 +++++++++++++++++++++------- > libavutil/tests/map.c | 45 ++++++++++++++++-------- > 3 files changed, 137 insertions(+), 41 deletions(-) > > diff --git a/libavutil/map.c b/libavutil/map.c > index 00dd5a1bd39..950473c2c45 100644 > --- a/libavutil/map.c > +++ b/libavutil/map.c > @@ -35,7 +35,8 @@ typedef struct{ > } AVMapInternalEntry; > > struct AVMap{ > - AVMapCompareFunc cmp_keyvalue; > +#define CMP_MASK 31 > + AVMapCompareFunc cmp[27]; > AVMapCopyFunc copy; > AVMapFreeFunc freef; > int count; > @@ -98,24 +99,71 @@ int av_map_supercmp_keyvalue(const char *a, const > char *b) > return v; > } > > -AVMap *av_map_new(AVMapCompareFunc cmp_keyvalue, AVMapCopyFunc copy, > AVMapFreeFunc freef) > +int av_map_add_cmp_func(AVMap *m, AVMapCompareFunc cmp, int > cmp_flags) > +{ > + 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]; > + int truncated_sensitive = sensitivity[cmp_flags][2]; > + > + if (!keyvalue_sensitive || !truncated_sensitive || cmp_flags >= > 27U) > + return AVERROR(EINVAL); > + > + av_assert1(case_sensitive + keyvalue_sensitive + > truncated_sensitive == cmp_flags); > + > + if ( case_sensitive == AV_MAP_CMP_CASE_SENSITIVE && m- > >cmp[keyvalue_sensitive + AV_MAP_CMP_CASE_INSENSITIVE]) > + return AVERROR(EINVAL); > + if ( keyvalue_sensitive == AV_MAP_CMP_KEYVALUE && m- > >cmp[AV_MAP_CMP_KEY]) > + return AVERROR(EINVAL); > + if (truncated_sensitive == AV_MAP_CMP_NON_TRUNCATED && m- > >cmp[keyvalue_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 > + //missing is KV T CS and K T CS, with them we can have KV NT CS - > > KV T CS -> K NT CS -> K T CS > + > + for (int i=0; i<8; i++) { > + int flags = 0; > + if (i&1) flags += case_sensitive; > + if (i&2) flags += keyvalue_sensitive; > + if (i&4) flags += truncated_sensitive; > + > + if (!m->cmp[flags]) > + m->cmp[flags] = cmp; > + } > + return 0; > +} > + > +int av_map_is_cmp_flags_supported(AVMap *m, int cmp_flags) > +{ > + if (cmp_flags >= 27U) > + return AVERROR(EINVAL); > + return !!m->cmp[cmp_flags]; > +} > + > +AVMap *av_map_new(AVMapCompareFunc cmp_keyvalue, int cmp_flags, > AVMapCopyFunc copy, AVMapFreeFunc freef) > { > AVMap *s = av_mallocz(sizeof(*s)); > if (!s) > return NULL; > > - s->cmp_keyvalue = cmp_keyvalue; > s->copy = copy; > s->freef = freef; > > + av_map_add_cmp_func(s, cmp_keyvalue, cmp_flags); > + > return s; > } > > -const AVMapEntry *av_map_get_multiple(const AVMap *s, const > AVMapEntry *prev, const char *keyvalue, int (*cmp)(const void > *keyvalue, const void *b)) > +const AVMapEntry *av_map_get_multiple(const AVMap *s, const > AVMapEntry *prev, const char *keyvalue, int flags) > { > + AVMapCompareFunc cmp = s->cmp[flags & CMP_MASK]; > + > if (prev) { > void *next_node[2] = { NULL, NULL }; > - void *prev_keyvalue = av_tree_find2(s->tree_root, prev->key, > s->cmp_keyvalue, next_node, 2); > + void *prev_keyvalue = av_tree_find2(s->tree_root, prev->key, > s->cmp[0], next_node, 2); > av_assert2(prev_keyvalue); > if (!next_node[1] || cmp(next_node[1], keyvalue)) > return NULL; > @@ -134,8 +182,10 @@ const AVMapEntry *av_map_get_multiple(const AVMap > *s, const AVMapEntry *prev, co > return &keyvalue2internal(keyvalue)->map_entry; > } > > -const AVMapEntry *av_map_get(const AVMap *s, const char *keyvalue, > int (*cmp)(const void *keyvalue, const void *b)) > +const AVMapEntry *av_map_get(const AVMap *s, const char *keyvalue, > int flags) > { > + AVMapCompareFunc cmp = s->cmp[flags & CMP_MASK]; > + > keyvalue = av_tree_find2(s->tree_root, keyvalue, cmp, NULL, 0); > > if (!keyvalue) > @@ -192,15 +242,15 @@ int av_map_add(AVMap *s, const char *key, int > keylen, const char *value, int val > memcpy(entry->key , key , keylen); > memcpy(entry->value, value, valuelen); > > - void *elem = av_tree_insert(&s->tree_root, entry->key, s- > >cmp_keyvalue, &next); > + void *elem = av_tree_insert(&s->tree_root, entry->key, s->cmp[0], > &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, s->cmp_keyvalue, flags); > + ret = av_map_del(s, entry->key, flags & ~CMP_MASK); > av_assert2(ret == 1); > - elem = av_tree_insert(&s->tree_root, entry->key, s- > >cmp_keyvalue, &next); > + elem = av_tree_insert(&s->tree_root, entry->key, s- > >cmp[0], &next); > av_assert2(elem == entry->key || !elem); > ret = 2; > } else > @@ -214,12 +264,13 @@ int av_map_add(AVMap *s, const char *key, int > keylen, const char *value, int val > return ret; > } > > -int av_map_del(AVMap *s, const char *keyvalue, int (*cmp)(const void > *keyvalue, const void *b), int flags) > +int av_map_del(AVMap *s, const char *keyvalue, int flags) > { > uint8_t *old_keyvalue; > AVTreeNode *next = NULL; > + AVMapCompareFunc cmp = s->cmp[flags & CMP_MASK]; > > - if (cmp != s->cmp_keyvalue) { > + if (cmp != s->cmp[0]) { > // 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 > @@ -227,10 +278,10 @@ int av_map_del(AVMap *s, const char *keyvalue, > int (*cmp)(const void *keyvalue, > if (!old_keyvalue) > return 0; > > - av_tree_insert(&s->tree_root, old_keyvalue, s->cmp_keyvalue, > &next); > + av_tree_insert(&s->tree_root, old_keyvalue, s->cmp[0], > &next); > av_assert2(next); > } else { > - av_tree_insert(&s->tree_root, (char*)keyvalue, s- > >cmp_keyvalue, &next); > + av_tree_insert(&s->tree_root, (char*)keyvalue, s->cmp[0], > &next); > if (!next) > return 0; > old_keyvalue = next->elem; //TODO add a API to av_tree() to > return the elem of a AVTreeNode > @@ -243,8 +294,9 @@ int av_map_del(AVMap *s, const char *keyvalue, int > (*cmp)(const void *keyvalue, > s->deleted++; > > if ((flags & AV_MAP_ALLOW_REBUILD) && s->deleted > s->count) { > - AVMap *news = av_map_new(s->cmp_keyvalue, s->copy, s->freef); > + AVMap *news = av_map_new(s->cmp[0], 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); > if (ret < 0) { > av_map_free(&news); > diff --git a/libavutil/map.h b/libavutil/map.h > index 0c660260017..10f541cc5ba 100644 > --- a/libavutil/map.h > +++ b/libavutil/map.h > @@ -46,8 +46,17 @@ > */ > > enum { > - AV_MAP_ALLOW_REBUILD = 1, ///< when removing entries rebuild > the map to reduce memory consumption, note, this invalidates > previously retrieved elements and iterate state. > - AV_MAP_REPLACE = 2, ///< replace keyvalue if already in > the map > +//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_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 > + > }; > > typedef struct AVMapEntry { > @@ -104,7 +113,33 @@ int av_map_supercmp_key(const char *a, const char > *b); > * > * > */ > -AVMap *av_map_new(AVMapCompareFunc keyvalue_cmp, AVMapCopyFunc clone, > AVMapFreeFunc freef); > +AVMap *av_map_new(AVMapCompareFunc keyvalue_cmp, int cmp_flags, > AVMapCopyFunc clone, AVMapFreeFunc freef); > + > + > +/** > + * Add a compatible compare function to the map. > + * The function will later be selected by using AV_MAP_CMP_* flags > + * > + * Functions must be added from most specific to least specific, that > is if a AVMap is build > + * with a case insensitive compare no case sensitive compare > functions can be added. This is > + * to avoid building non functional AVMaps. > + * > + * @see av_map_new > + * > + * @param cmp_flags a combination of AV_MAP_CMP_*, note key/keyvalue > and truncated vs non truncated > + * are mandatory to be specified > + * > + * @return a negative error code if the cmp_flags are illegal or > unsupported for this AVMap > + * If you know your flags are valid, then you dont need to > check the return > + */ > +int av_map_add_cmp_func(AVMap *m, AVMapCompareFunc keyvalue_cmp, int > cmp_flags); > + > +/** > + * > + * @return 1 if the provided AV_MAP_CMP_* flag combination is > supported by this map. > + * 0 otherwise > + */ > +int av_map_is_cmp_flags_supported(AVMap *m, int cmp_flags); > > /** > * realloc internal space to accomodate the specified new elements > @@ -136,13 +171,12 @@ int av_map_add(AVMap *s, const char *key, int > keylen, const char *value, int val > * > * @param s Pointer AVMap struct. > * @param keyvalue key or concatenated key+value > - * @param cmp compatible compare function that comapres key or > keyvalues > * @param flags AV_MAP_ALLOW_REBUILD or 0 > * > * @return 1 if the entry was deleted, 0 if it was not found > in the map > * otherwise an error code <0 > */ > -int av_map_del(AVMap *s, const char *keyvalue, int (*cmp)(const void > *keyvalue, const void *b), int flags); > +int av_map_del(AVMap *s, const char *keyvalue, int flags); > > /** > * Iterate over possibly multiple matching map entries. > @@ -153,22 +187,17 @@ int av_map_del(AVMap *s, const char *keyvalue, > int (*cmp)(const void *keyvalue, > * @param prev Set to the previous matching element to find the > next. > * If set to NULL the first matching element is > returned. > * @param keyvalue Matching key or key + value > - * @param cmp compare function, this will be passed keyvalue and > the concatenated key+value > - * it must form a total order on all elements, that is a > key can occur more than once. > - * But cmp2 must be a refinement of the cmp order, any > disagreement of the 2 compares > - * must be by cmp returning equal. If this only reads > the key part of keyvalue > - * then keyvalue can be just a key > * > * @return Found entry or NULL in case no matching entry was > found in the dictionary > */ > -const AVMapEntry *av_map_get_multiple(const AVMap *s, const > AVMapEntry *prev, const char *keyvalue, int (*cmp)(const void > *keyvalue, const void *b)); > +const AVMapEntry *av_map_get_multiple(const AVMap *s, const > AVMapEntry *prev, const char *keyvalue, int flags); > > /** > * Like av_map_get_multiple() but only returns one matching entry > * > * The returned entry cannot be used as initial prev entry for > av_map_get_multiple() > */ > -const AVMapEntry *av_map_get(const AVMap *s, const char *keyvalue, > int (*cmp)(const void *keyvalue, const void *b)); > +const AVMapEntry *av_map_get(const AVMap *s, const char *keyvalue, > int flags); > > /** > * Iterate over a map > diff --git a/libavutil/tests/map.c b/libavutil/tests/map.c > index 90950769f98..1e3f80a42af 100644 > --- a/libavutil/tests/map.c > +++ b/libavutil/tests/map.c > @@ -47,6 +47,13 @@ int main(void) > av_map_supercmp_keyvalue, > 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, > + }; > void *our_subcmp[] = { > strcmp, > strcmp, > @@ -54,19 +61,27 @@ int main(void) > av_map_supercmp_key, > 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, > + }; > > for (int settype=0; settype<3; settype++) { > - AVMap *set = av_map_new(our_cmp[settype], NULL, NULL); > + AVMap *set = av_map_new(our_cmp[settype], our_flags[settype], > NULL, NULL); > + av_map_add_cmp_func(set, our_subcmp[settype], > our_subflags[settype]); > > printf("testing empty set\n"); > > - const AVMapEntry *e = av_map_get(set, "foo", > our_subcmp[settype]); > + const AVMapEntry *e = av_map_get(set, "foo", > our_subflags[settype]); > av_assert0(e == NULL); > > - e = av_map_get(set, "foo", our_subcmp[settype]); > + e = av_map_get(set, "foo", our_subflags[settype]); > av_assert0(e == NULL); > > - int ret = av_map_del(set, "foo", our_subcmp[settype], 0); > + int ret = av_map_del(set, "foo", our_subflags[settype]); > av_assert0(ret == 0); > > print_set(set); > @@ -79,7 +94,7 @@ int main(void) > ret = av_map_add(set, "foo", 4, "bear", 5, 0); > av_assert0(ret == ((int[]){0,1,0})[settype]); > > - e = av_map_get(set, "foo", our_subcmp[settype]); > + e = av_map_get(set, "foo", our_subflags[settype]); > av_assert0(!strcmp(e->key, "foo")); > if (settype == 1) { > av_assert0(!strcmp(e->value, "bear") || !strcmp(e->value, > "bar")); > @@ -90,7 +105,7 @@ int main(void) > ret = av_map_add(set, "foo", 4, "bear", 5, AV_MAP_REPLACE); > av_assert0(ret == 2); > > - e = av_map_get(set, "foo", our_subcmp[settype]); > + e = av_map_get(set, "foo", our_subflags[settype]); > av_assert0(!strcmp(e->key, "foo")); > if (settype == 1) { > av_assert0(!strcmp(e->value, "bear") || !strcmp(e->value, > "bar")); > @@ -98,14 +113,14 @@ int main(void) > av_assert0(!strcmp(e->value, "bear")); > } > > - e = av_map_get_multiple(set, NULL, "foo", > our_subcmp[settype]); > + e = av_map_get_multiple(set, NULL, "foo", > our_subflags[settype]); > av_assert0(!strcmp(e->key, "foo")); > if (settype == 1) { > av_assert0(!strcmp(e->value, "bar")); > } else { > av_assert0(!strcmp(e->value, "bear")); > } > - e = av_map_get_multiple(set, e, "foo", our_subcmp[settype]); > + e = av_map_get_multiple(set, e, "foo", > our_subflags[settype]); > if (settype == 1) { > av_assert0(!strcmp(e->key, "foo")); > av_assert0(!strcmp(e->value, "bear")); > @@ -113,10 +128,10 @@ int main(void) > av_assert0(e == NULL); > } > > - ret = av_map_del(set, "foo", our_subcmp[settype], 0); > + ret = av_map_del(set, "foo", our_subflags[settype]); > av_assert0(ret == 1); > > - e = av_map_get(set, "foo", our_subcmp[settype]); > + e = av_map_get(set, "foo", our_subflags[settype]); > if (settype == 1) { > av_assert0(!strcmp(e->key, "foo")); > av_assert0(!strcmp(e->value, "bear") || !strcmp(e->value, > "bar")); > @@ -124,7 +139,7 @@ int main(void) > av_assert0(e == NULL); > } > > - ret = av_map_del(set, "foo", our_subcmp[settype], 0); > + ret = av_map_del(set, "foo", our_subflags[settype]); > av_assert0(ret == ((int[]){0,1,0})[settype]); > > > @@ -157,7 +172,7 @@ int main(void) > r = r*123 + 7; > char str[3] = {0}; > str[0] = r; > - e = av_map_get(set, str, our_subcmp[settype]); > + e = av_map_get(set, str, our_subflags[settype]); > if (settype != 2) { > av_assert0(!strcmp(e->key, str)); > av_assert0(!strcmp(e->value, str)); > @@ -165,7 +180,7 @@ int main(void) > av_assert0(!av_strcasecmp(e->key, str)); > av_assert0(!av_strcasecmp(e->value, str)); > } > - e = av_map_get_multiple(set, NULL, str, > our_subcmp[settype]); > + e = av_map_get_multiple(set, NULL, str, > our_subflags[settype]); > if (settype != 2) { > av_assert0(!strcmp(e->key, str)); > av_assert0(!strcmp(e->value, str)); > @@ -178,9 +193,9 @@ int main(void) > > str[1]='x'; > > - e = av_map_get(set, str, our_subcmp[settype]); > + e = av_map_get(set, str, our_subflags[settype]); > av_assert0(e == NULL); > - e = av_map_get_multiple(set, NULL, str, > our_subcmp[settype]); > + e = av_map_get_multiple(set, NULL, str, > our_subflags[settype]); > av_assert0(e == NULL); > } > print_set(set); > -- > 2.49.0 > > _______________________________________________ That's a good change, because it was in fact confusing. Another confusing part of the API is the need for specifying the lengths of key and value - and I finally figured out why it didn't retrieve any elements: those values need to be strlen + 1 I think the final API should not require any length params (or at least it should have a function that doesn't need it) Best, sw _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org https://ffmpeg.org/mailman/listinfo/ffmpeg-devel To unsubscribe, visit link above, or email ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".