[vlc-devel] [PATCH] Add open_memstream replacement
Rémi Denis-Courmont
remi at remlab.net
Wed Aug 24 16:40:04 CEST 2016
Le keskiviikkona 24. elokuuta 2016, 15.57.50 EEST Felix Paul Kühne a écrit :
> ---
> compat/open_memstream.c | 153
> ++++++++++++++++++++++++++++++++++++++++++++++++ configure.ac |
> 2 +-
> include/vlc_fixups.h | 5 ++
> 3 files changed, 159 insertions(+), 1 deletion(-)
> create mode 100644 compat/open_memstream.c
>
> diff --git a/compat/open_memstream.c b/compat/open_memstream.c
> new file mode 100644
> index 0000000..42938ba
> --- /dev/null
> +++ b/compat/open_memstream.c
> @@ -0,0 +1,153 @@
> +/*
> + * Copyright (c) 2013 Ian Piumarta <ian at vpri.org>
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> copy + * of this software and associated documentation files (the
> "Software"), to + * deal in the Software without restriction, including
> without limitation the + * rights to use, copy, modify, merge, publish,
> distribute, sublicense, and/or + * sell copies of the Software, and to
> permit persons to whom the Software is + * furnished to do so, subject to
> the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included
> in + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
> OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
> MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
> IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
> CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
> TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE
> SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE.
> + */
> +
> +#ifdef HAVE_CONFIG_H
> +# include <config.h>
> +#endif
> +
> +#include <stdio.h>
> +
> +#include <stddef.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <errno.h>
> +#include <assert.h>
> +
> +#define min(X, Y) (((X) < (Y)) ? (X) : (Y))
> +
> +struct memstream
> +{
> + int position;
> + int size;
> + int capacity;
> + char *contents;
> + char **ptr;
> + size_t *sizeloc;
> +};
> +
> +#ifdef MEMSTREAM_DEBUG
> + static void memstream_print(struct memstream *ms)
> + {
> + printf("memstream %p {", ms);
I suspect missing void * cast. Also below.
> + printf(" %i", ms->position);
> + printf(" %i", ms->size);
> + printf(" %i", ms->capacity);
> + printf(" %p", ms->contents);
> + printf(" }\n");
> + }
> +# define memstream_info(ARGS) printf ARGS
> +#else
> +# define memstream_print(ms)
> +# define memstream_info(ARGS)
> +#endif
> +
> +#define memstream_check(MS) if (!(MS)->contents) { errno= ENOMEM; return
> -1; } +
> +static int memstream_grow(struct memstream *ms, int minsize)
> +{
> + int newcap= ms->capacity * 2; memstream_check(ms);
> + while (newcap <= minsize) newcap *= 2; memstream_info(("grow %p
to
> %i\n", ms, newcap)); + ms->contents= realloc(ms->contents, newcap);
> + if (!ms->contents) return -1; /* errno == ENOMEM */
> + memset(ms->contents + ms->capacity, 0, newcap - ms->capacity);
> + ms->capacity= newcap;
> + *ms->ptr= ms->contents; /* size has not changed */
> + return 0;
> +}
> +
> +static int memstream_read(void *cookie, char *buf, int count)
> +{
> + struct memstream *ms= (struct memstream
> *)cookie;
Redundant cast. Ditto below.
> memstream_check(ms);
> + int n= min(ms->size - ms->position,
> count); memstream_info(("memstream_read %p %i\n", ms, count)); +
if
> (n < 1) return 0;
> + memcpy(buf, ms->contents, n);
> + ms->position += n; memstream_print(ms);
> + return n;
> +}
> +
> +static int memstream_write(void *cookie, const char *buf, int count)
> +{
> + struct memstream *ms= (struct memstream
> *)cookie; memstream_check(ms); + if (ms->capacity <= ms->position +
> count)
> + if (memstream_grow(ms, ms->position + count) < 0) /* errno == ENOMEM
*/
> + return -1;
> + memcpy(ms->contents + ms->position, buf,
> count); memstream_info(("memstream_write %p %i\n", ms, count)); +
> ms->position += count;
> + if (ms->size < ms->position) *ms->sizeloc= ms->size=
> ms->position; memstream_print(ms); + assert(ms->size
<
> ms->capacity);
> + assert(ms->contents[ms->size] == 0);
> + return count;
> +}
> +
> +static fpos_t memstream_seek(void *cookie, fpos_t offset, int whence)
> +{
> + struct memstream *ms= (struct memstream *)cookie;
> + fpos_t pos= 0; memstream_check(ms);
fpos_t is an opaque type. Might this file be BSD-specific?
> + memstream_info(("memstream_seek %p %i %i\n", ms,
(int)offset,
> whence)); + switch (whence) {
> + case SEEK_SET: pos= offset; break;
> + case SEEK_CUR: pos= ms->position + offset; break;
> + case SEEK_END: pos= ms->size + offset; break;
> + default: errno= EINVAL; return -1;
> + }
> + if (pos >= ms->capacity) memstream_grow(ms, pos);
> + ms->position= pos;
> + if (ms->size < ms->position) *ms->sizeloc= ms->size=
> ms->position; memstream_print(ms); memstream_info(("=> %i\n", (int)pos));
> + assert(ms->size < ms->capacity && ms->contents[ms-
>size] == 0); +
> return pos;
> +}
> +
> +static int memstream_close(void *cookie)
> +{
> + struct memstream *ms= (struct memstream *)cookie; if (!ms-
>contents)
> { free(ms); errno= ENOMEM; return -1; } + ms->size= min(ms->size,
> ms->position);
> + *ms->ptr= ms->contents;
> + *ms->sizeloc= ms->size; assert(ms->size < ms-
>capacity);
> + ms->contents[ms->size]= 0;
> + free(ms);
> + return 0;
> +}
> +
> +FILE *open_memstream(char **ptr, size_t *sizeloc)
> +{
> + if (ptr && sizeloc) {
> + struct memstream *ms= calloc(1, sizeof(struct memstream));
> + FILE *fp= 0; if (!ms) return 0; /* errno == ENOMEM */
0 as NULL...
> + ms->position= ms->size= 0;
> + ms->capacity= 4096;
> + ms->contents= calloc(ms->capacity, 1); if (!ms->contents) {
free(ms);
> return 0; } /* errno == ENOMEM */ + ms->ptr= ptr;
> + ms->sizeloc= sizeloc;
> + memstream_print(ms);
> + fp= funopen(ms, memstream_read, memstream_write, memstream_seek,
> memstream_close); + if (!fp) {
> + free(ms->contents);
> + free(ms);
> + return 0; /* errno set by funopen */
> + }
> + *ptr= ms->contents;
> + *sizeloc= ms->size;
> + return fp;
> + }
> + errno= EINVAL;
> + return 0;
> +}
> diff --git a/configure.ac b/configure.ac
> index ee8f524..feae621 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -598,7 +598,7 @@ need_libc=false
> dnl Check for usual libc functions
> AC_CHECK_DECLS([nanosleep],,,[#include <time.h>])
> AC_CHECK_FUNCS([daemon fcntl flock fstatvfs fork getenv getpwuid_r isatty
> lstat memalign mkostemp mmap open_memstream openat pread posix_fadvise
> posix_madvise setlocale stricmp strnicmp strptime uselocale
> pthread_cond_timedwait_monotonic_np pthread_condattr_setclock])
> -AC_REPLACE_FUNCS([atof atoll dirfd fdopendir ffsll flockfile fsync
> getdelim getpid lldiv memrchr nrand48 poll posix_memalign recvmsg rewind
> sendmsg setenv strcasecmp strcasestr strdup strlcpy strndup strnlen strnstr
> strsep strtof strtok_r strtoll swab tdestroy timegm timespec_get
> strverscmp]) +AC_REPLACE_FUNCS([atof atoll dirfd fdopendir ffsll flockfile
> fsync getdelim getpid lldiv memrchr nrand48 open_memstream poll
> posix_memalign recvmsg rewind sendmsg setenv strcasecmp strcasestr strdup
> strlcpy strndup strnlen strnstr strsep strtof strtok_r strtoll swab
> tdestroy timegm timespec_get strverscmp]) AC_REPLACE_FUNCS([gettimeofday])
> AC_CHECK_FUNCS(fdatasync,,
> [AC_DEFINE(fdatasync, fsync, [Alias fdatasync() to fsync() if missing.])
> diff --git a/include/vlc_fixups.h b/include/vlc_fixups.h
> index a14764f..0ae090d 100644
> --- a/include/vlc_fixups.h
> +++ b/include/vlc_fixups.h
> @@ -209,6 +209,11 @@ float strtof (const char *, char **);
> long long int strtoll (const char *, char **, int);
> #endif
>
> +#ifndef HAVE_OPEN_MEMSTREAM
> +#include <stdio.h>
> +FILE *open_memstream(char **ptr, size_t *sizeloc);
> +#endif
> +
Probably not the right place witihn the file.
> /* time.h */
> #ifndef HAVE_GMTIME_R
> struct tm *gmtime_r (const time_t *, struct tm *);
--
Rémi Denis-Courmont
http://www.remlab.net/
More information about the vlc-devel
mailing list