[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