[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