[vlc-devel] [PATCH] Add open_memstream replacement

Felix Paul Kühne fkuehne at videolan.org
Wed Aug 24 15:57:50 CEST 2016


---
 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);
+      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;			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);
+									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 */
+	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
+
 /* time.h */
 #ifndef HAVE_GMTIME_R
 struct tm *gmtime_r (const time_t *, struct tm *);
-- 
2.9.3



More information about the vlc-devel mailing list