The function 'avio_enum_protocols()' iterates through the list of protocols, looking for a protocol that has a certain non-zero pointer-to-function; the exact pointer-to-function to use depends on the the argument passed through the parameter 'output'.
* Before this commit, the parameter 'output' was being checked on every iteration, despite the fact that its value does not change. * This commit explicitly separates out the different cases into their own loops (i.e., their own functions), so that 'output' need not be tested on each iteration. * To aid maintenance, these separate functions are the expansion of a single macro that provides a generic implementation: AVIO_ENUM_PROTOCOLS(METHOD) One of the benefits of using a macro is that it does not depend on a compiler being able to optimize the code. Before deciding to use a macro for this purpose, it was attempted to write a generic version in terms of pure C code that also would not rely on magical optimizations; this involved type conversions on pointer arithmetic around 'offsetof()', but it turns out that Standard C (not to be confused with Actual C) has no reliable way to recover the value of a pointer-to-function from an object, so that avenue was ultimately abandoned for the sake of pure pedantry. --- libavformat/protocols.c | 37 +++++++++++++++++++++++++++---------- 1 file changed, 27 insertions(+), 10 deletions(-) diff --git a/libavformat/protocols.c b/libavformat/protocols.c index 9ce98968fa..4cb8ae0b63 100644 --- a/libavformat/protocols.c +++ b/libavformat/protocols.c @@ -91,18 +91,35 @@ const AVClass *ff_urlcontext_child_class_iterate(void **iter) return ret; } -const char *avio_enum_protocols(void **const opaque, const int output) +#define AVIO_ENUM_PROTOCOLS(METHOD) \ + typedef const URLProtocol *const *Iterator; \ + for(Iterator p = *opaque ? (Iterator)(*opaque) + 1 : url_protocols; *p; ++p) { \ + if ((*p)->METHOD) { \ + *opaque = (void *)p; \ + return (*p)->name; \ + } \ + } \ + *opaque = NULL; \ + return NULL; + +static inline +const char *avio_enum_protocols_for_output(void **const opaque) { - typedef const URLProtocol *const *Iterator; - for(Iterator p = *opaque ? (Iterator)(*opaque) + 1 : url_protocols; *p; ++p) { - if ((output && (*p)->url_write) || (!output && (*p)->url_read)) { - *opaque = (void *)p; - return (*p)->name; - } - } + AVIO_ENUM_PROTOCOLS(url_write); +} - *opaque = NULL; - return NULL; +static inline +const char *avio_enum_protocols_for_input(void **const opaque) +{ + AVIO_ENUM_PROTOCOLS(url_read); +} + +const char *avio_enum_protocols(void **const opaque, const int output) +{ + if (output) + return avio_enum_protocols_for_output(opaque); + else + return avio_enum_protocols_for_input(opaque); } const AVClass *avio_protocol_get_class(const char *name) -- 2.22.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".