From 4c117849b343109666c7a25b6fa815ce63d0175f Mon Sep 17 00:00:00 2001 From: Uoti Urpala Date: Fri, 25 Feb 2011 18:10:00 +0200 Subject: stream.[ch], ass_mp: new stream function for whole-file reads Add new stream_read_complete() function which reads the complete contents of file. Use that in ass_mp.c which had custom code to do the same. --- stream/stream.c | 34 ++++++++++++++++++++++++++++++++++ stream/stream.h | 10 ++++++++++ sub/ass_mp.c | 46 ++++++++++++---------------------------------- 3 files changed, 56 insertions(+), 34 deletions(-) diff --git a/stream/stream.c b/stream/stream.c index 6f35252e3d..86dd61389e 100644 --- a/stream/stream.c +++ b/stream/stream.c @@ -29,6 +29,8 @@ #include #include +#include "talloc.h" + #include "config.h" #if HAVE_WINSOCK2_H @@ -658,3 +660,35 @@ unsigned char* stream_read_line(stream_t *s,unsigned char* mem, int max, int utf if(s->eof && ptr == mem) return NULL; return mem; } + +struct bstr stream_read_complete(struct stream *s, void *talloc_ctx, + int max_size, int padding_bytes) +{ + if (max_size > 1000000000) + abort(); + + int bufsize; + int total_read = 0; + int padding = FFMAX(padding_bytes, 1); + char *buf = NULL; + if (s->end_pos > max_size) + return (struct bstr){NULL, 0}; + if (s->end_pos > 0) + bufsize = s->end_pos + padding; + else + bufsize = 1000; + while (1) { + buf = talloc_realloc_size(talloc_ctx, buf, bufsize); + int readsize = stream_read(s, buf + total_read, bufsize - total_read); + total_read += readsize; + if (total_read < bufsize) + break; + if (bufsize > max_size) { + talloc_free(buf); + return (struct bstr){NULL, 0}; + } + bufsize = FFMIN(bufsize + (bufsize >> 1), max_size + padding); + } + buf = talloc_realloc_size(talloc_ctx, buf, total_read + padding); + return (struct bstr){buf, total_read}; +} diff --git a/stream/stream.h b/stream/stream.h index 413e80ad91..94bfb0e343 100644 --- a/stream/stream.h +++ b/stream/stream.h @@ -28,6 +28,8 @@ #include #include +#include "bstr.h" + #ifndef O_BINARY #define O_BINARY 0 #endif @@ -331,6 +333,14 @@ inline static int stream_skip(stream_t *s,off_t len){ } struct MPOpts; +/* + * Return allocated buffer for all data until EOF. + * If amount of data would be more than max_size return NULL as data ptr. + * Make the allocated buffer padding_bytes larger than the data read. + * Write number of bytes read at *amount_read. + */ +struct bstr stream_read_complete(struct stream *s, void *talloc_ctx, + int max_size, int padding_bytes); void stream_reset(stream_t *s); int stream_control(stream_t *s, int cmd, void *arg); stream_t* new_stream(int fd,int type); diff --git a/sub/ass_mp.c b/sub/ass_mp.c index 98602ace03..78f607bc7a 100644 --- a/sub/ass_mp.c +++ b/sub/ass_mp.c @@ -233,50 +233,28 @@ ASS_Track *mp_ass_read_subdata(ASS_Library *library, sub_data *subdata, ASS_Track *mp_ass_read_stream(ASS_Library *library, const char *fname, char *charset) { - int i; - char *buf = NULL; ASS_Track *track; - size_t sz = 0; - size_t buf_alloc = 0; - stream_t *fd; - fd = open_stream(fname, NULL, NULL); - if (!fd) + struct stream *s = open_stream(fname, NULL, NULL); + if (!s) // Stream code should have printed an error already return NULL; - if (fd->end_pos > STREAM_BUFFER_SIZE) - /* read entire file if size is known */ - buf_alloc = fd->end_pos; - else - buf_alloc = 1000; - for (;;) { - if (sz > 100000000) { - mp_tmsg(MSGT_ASS, MSGL_ERR, "Refusing to load subtitle file " - "larger than 100 MB: %s\n", fname); - sz = 0; - break; - } - buf_alloc = FFMAX(buf_alloc, sz + (sz >> 1)); - buf_alloc = FFMIN(buf_alloc, 100000001); - buf = realloc(buf, buf_alloc + 1); - i = stream_read(fd, buf + sz, buf_alloc - sz); - if (i <= 0) - break; - sz += i; - } - free_stream(fd); - if (!sz) { - free(buf); + struct bstr content = stream_read_complete(s, NULL, 100000000, 1); + if (content.start == NULL) + mp_tmsg(MSGT_ASS, MSGL_ERR, "Refusing to load subtitle file " + "larger than 100 MB: %s\n", fname); + free_stream(s); + if (content.len == 0) { + talloc_free(content.start); return NULL; } - buf[sz] = 0; - buf = realloc(buf, sz + 1); - track = ass_read_memory(library, buf, sz, charset); + content.start[content.len] = 0; + track = ass_read_memory(library, content.start, content.len, charset); if (track) { free(track->name); track->name = strdup(fname); } - free(buf); + talloc_free(content.start); return track; } -- cgit v1.2.3