[FFmpeg-devel] AVWriter again (was: v2 1/2] avformat/url: check double dot is not to parent directory)

Nicolas George george at nsup.org
Sat Jul 25 14:03:40 EEST 2020


Marton Balint (12020-07-25):
> And I also would like to point out that using static strings with
> MAX_URL_SIZE is not OK. This function supports an arbitrary buffer size, so
> limiting it to MAX_URL_SIZE is a bug.

Excellent point. That would require changing the prototype of a few
functions, but they are internal, we can do it.

For this, I would like to pitch the AVWriter API once again, because it
is made precisely for these cases: when you need to return a string of
arbitrary length, but would like to avoid, as much a possible, the
overhead of dynamically allocating it and the many error tests that come
with it. It is like AVBPrint, but better.

Let me elaborate without polluting the discussion by showing the actual
implementation.

So, let us say that function A calls function B, and function B needs to
return a string of arbitrary length but often small (I say string, but
the API can deal with binary data).

Likely use cases: rewriting an URL like here; escaping special
characters; serialization to key=value string; serialization to JSON or
XML; character encoding conversion, zlib-style unpacking, etc.


First, from the point of view of B, the function that needs to return
the string:

Instead of either:

	int B(char *buf, size_t buf_size, other arguments);
	int B(char **buf, other arguments);

request an AVWriter as argument:

	void B(AVWriter wr, other arguments);

Then, just write in it with the various API functions:
av_writer_write(), av_writer_printf(), etc.

And that's all. Everything is taken care of: the string will grow as
needed, the size will be tracked, error checks are made. Nothing to
worry about at all.


Now, from the point of view of A, the function that calls B and gets a
string in return:

Instead of declaring a buffer, or a pointer to a buffer, declare:

	AVWriter wr = av_dynbuf_writer();

and call B with it: B(wr, ...).

Then, extract the string, check for error (of course: dynamic allocation
can happen and fail; but this error check is the only one necessary),
use the string and free it:

	char *msg = av_dynbuf_writer_get_data(wr, NULL);
	if (!msg)
	    return AVERROR(ENOMEM);
	do something with msg
	av_dynbuf_writer_reset(wr);

I concede, for this example, av_dynbuf_writer_get_data() is one more
step than using the pointer directly. But as soon as the code becomes
more complex, in particular as soon as it uses the same writer twice to
put two strings together, this extra step is balanced by the fewer error
checks necessary.


All said, it makes one more API to learn, but IMHO, it is very simple to
learn: seven line of sample code. And the benefits are immediate.

Plus: there are many wonderful features that I have not told you about
yet.

So, Steven, Marton and the others: presented like that, does it look
appealing? Shall I elaborate?

Regards,

-- 
  Nicolas George
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <https://ffmpeg.org/pipermail/ffmpeg-devel/attachments/20200725/a99b448d/attachment.sig>


More information about the ffmpeg-devel mailing list