CELIX-281: Moved fmemopen/open_memstream to utils. Added usage of 
open_memstream to bonjour shell for OSX.


Project: http://git-wip-us.apache.org/repos/asf/celix/repo
Commit: http://git-wip-us.apache.org/repos/asf/celix/commit/2c74cc35
Tree: http://git-wip-us.apache.org/repos/asf/celix/tree/2c74cc35
Diff: http://git-wip-us.apache.org/repos/asf/celix/diff/2c74cc35

Branch: refs/heads/release/celix-2.0.0
Commit: 2c74cc35b573eb2e0b587065808181286f830362
Parents: 652741c
Author: Pepijn Noltes <pepijnnol...@gmail.com>
Authored: Fri Oct 14 21:10:15 2016 +0200
Committer: Pepijn Noltes <pepijnnol...@gmail.com>
Committed: Fri Oct 14 21:10:15 2016 +0200

----------------------------------------------------------------------
 dfi/CMakeLists.txt                              |   8 +-
 dfi/private/src/memstream/fmemopen.c            |  78 -----------
 dfi/private/src/memstream/open_memstream.c      | 130 -------------------
 dfi/public/include/memstream/README.md          |  49 -------
 dfi/public/include/memstream/fmemopen.h         |  52 --------
 dfi/public/include/memstream/open_memstream.h   |  15 ---
 shell_bonjour/CMakeLists.txt                    |   8 +-
 shell_bonjour/private/src/activator.c           |   2 +-
 shell_bonjour/private/src/bonjour_shell.c       |  15 ++-
 utils/private/src/memstream/fmemopen.c          |  78 +++++++++++
 utils/private/src/memstream/open_memstream.c    | 130 +++++++++++++++++++
 utils/public/include/memstream/README.md        |  49 +++++++
 utils/public/include/memstream/fmemopen.h       |  52 ++++++++
 utils/public/include/memstream/open_memstream.h |  15 +++
 14 files changed, 348 insertions(+), 333 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/celix/blob/2c74cc35/dfi/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/dfi/CMakeLists.txt b/dfi/CMakeLists.txt
index 6fe7071..c672f94 100644
--- a/dfi/CMakeLists.txt
+++ b/dfi/CMakeLists.txt
@@ -28,10 +28,10 @@ include_directories(
 
 set(MEMSTREAM_SOURCES )
 set(MEMSTREAM_INCLUDES )
-if (${CMAKE_SYSTEM_NAME} STREQUAL "Darwin" OR ANDROID) 
-       set(MEMSTREAM_SOURCES private/src/memstream/open_memstream.c 
private/src/memstream/fmemopen.c)
-       set(MEMSTREAM_INCLUDES public/include/memstream/open_memstream.h 
public/include/memstream/fmemopen.h)
-    include_directories(public/include/memstream)
+if (APPLE OR ANDROID)
+       set(MEMSTREAM_SOURCES 
${PROJECT_SOURCE_DIR}/utils/private/src/memstream/open_memstream.c  
${PROJECT_SOURCE_DIR}/utils/private/src/memstream/fmemopen.c)
+       set(MEMSTREAM_INCLUDES 
${PROJECT_SOURCE_DIR}/utils/public/include/memstream/open_memstream.h 
${PROJECT_SOURCE_DIR}/utils/public/include/memstream/fmemopen.h)
+    include_directories(${PROJECT_SOURCE_DIR}/utils/public/include/memstream)
 endif()
 
 add_library(celix_dfi SHARED

http://git-wip-us.apache.org/repos/asf/celix/blob/2c74cc35/dfi/private/src/memstream/fmemopen.c
----------------------------------------------------------------------
diff --git a/dfi/private/src/memstream/fmemopen.c 
b/dfi/private/src/memstream/fmemopen.c
deleted file mode 100644
index 66fc9c5..0000000
--- a/dfi/private/src/memstream/fmemopen.c
+++ /dev/null
@@ -1,78 +0,0 @@
-
-/*
- * fmem.c : fmemopen() on top of BSD's funopen()
- * 20081017 AF
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#ifndef linux
-struct fmem {
-    size_t pos;
-    size_t size;
-    char *buffer;
-};
-typedef struct fmem fmem_t;
-
-static int readfn(void *handler, char *buf, int size)
-{
-    int count = 0;
-    fmem_t *mem = handler;
-    size_t available = mem->size - mem->pos;
-
-    if(size > available) size = available;
-    for(count=0; count < size; mem->pos++, count++)
-        buf[count] = mem->buffer[mem->pos];
-
-    return count;
-}
-
-static int writefn(void *handler, const char *buf, int size)
-{
-    int count = 0;
-    fmem_t *mem = handler;
-    size_t available = mem->size - mem->pos;
-
-    if(size > available) size = available;
-    for(count=0; count < size; mem->pos++, count++)
-        mem->buffer[mem->pos] = buf[count];
-
-    return count; // ? count : size;
-}
-
-static fpos_t seekfn(void *handler, fpos_t offset, int whence)
-{
-    size_t pos;
-    fmem_t *mem = handler;
-
-    switch(whence) {
-        case SEEK_SET: pos = offset; break;
-        case SEEK_CUR: pos = mem->pos + offset; break;
-        case SEEK_END: pos = mem->size + offset; break;
-        default: return -1;
-    }
-
-    if(pos > mem->size) return -1;
-
-    mem->pos = pos;
-    return (fpos_t) pos;
-}
-
-static int closefn(void *handler)
-{
-    free(handler);
-    return 0;
-}
-
-/* simple, but portable version of fmemopen for OS X / BSD */
-FILE *fmemopen(void *buf, size_t size, const char *mode)
-{
-    fmem_t *mem = (fmem_t *) malloc(sizeof(fmem_t));
-
-    memset(mem, 0, sizeof(fmem_t));
-    mem->size = size, mem->buffer = buf;
-    return funopen(mem, readfn, writefn, seekfn, closefn);
-}
-#endif

http://git-wip-us.apache.org/repos/asf/celix/blob/2c74cc35/dfi/private/src/memstream/open_memstream.c
----------------------------------------------------------------------
diff --git a/dfi/private/src/memstream/open_memstream.c 
b/dfi/private/src/memstream/open_memstream.c
deleted file mode 100644
index 6bc4f01..0000000
--- a/dfi/private/src/memstream/open_memstream.c
+++ /dev/null
@@ -1,130 +0,0 @@
-/* Use funopen(3) to provide open_memstream(3) like functionality. */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
-struct memstream {
-       char **cp;
-       size_t *lenp;
-       size_t offset;
-};
-
-static void
-memstream_grow(struct memstream *ms, size_t newsize)
-{
-       char *buf;
-
-       if (newsize > *ms->lenp) {
-               buf = realloc(*ms->cp, newsize + 1);
-               if (buf != NULL) {
-#ifdef DEBUG
-                       fprintf(stderr, "MS: %p growing from %zd to %zd\n",
-                           ms, *ms->lenp, newsize);
-#endif
-                       memset(buf + *ms->lenp + 1, 0, newsize - *ms->lenp);
-                       *ms->cp = buf;
-                       *ms->lenp = newsize;
-               }
-       }
-}
-
-static int
-memstream_read(void *cookie, char *buf, int len)
-{
-       struct memstream *ms;
-       int tocopy;
-
-       ms = cookie;
-       memstream_grow(ms, ms->offset + len);
-       tocopy = *ms->lenp - ms->offset;
-       if (len < tocopy)
-               tocopy = len;
-       memcpy(buf, *ms->cp + ms->offset, tocopy);
-       ms->offset += tocopy;
-#ifdef DEBUG
-       fprintf(stderr, "MS: read(%p, %d) = %d\n", ms, len, tocopy);
-#endif
-       return (tocopy);
-}
-
-static int
-memstream_write(void *cookie, const char *buf, int len)
-{
-       struct memstream *ms;
-       int tocopy;
-
-       ms = cookie;
-       memstream_grow(ms, ms->offset + len);
-       tocopy = *ms->lenp - ms->offset;
-       if (len < tocopy)
-               tocopy = len;
-       memcpy(*ms->cp + ms->offset, buf, tocopy);
-       ms->offset += tocopy;
-#ifdef DEBUG
-       fprintf(stderr, "MS: write(%p, %d) = %d\n", ms, len, tocopy);
-#endif
-       return (tocopy);
-}
-
-static fpos_t
-memstream_seek(void *cookie, fpos_t pos, int whence)
-{
-       struct memstream *ms;
-#ifdef DEBUG
-       size_t old;
-#endif
-
-       ms = cookie;
-#ifdef DEBUG
-       old = ms->offset;
-#endif
-       switch (whence) {
-       case SEEK_SET:
-               ms->offset = pos;
-               break;
-       case SEEK_CUR:
-               ms->offset += pos;
-               break;
-       case SEEK_END:
-               ms->offset = *ms->lenp + pos;
-               break;
-       }
-#ifdef DEBUG
-       fprintf(stderr, "MS: seek(%p, %zd, %d) %zd -> %zd\n", ms, pos, whence,
-           old, ms->offset);
-#endif
-       return (ms->offset);
-}
-
-static int
-memstream_close(void *cookie)
-{
-
-       free(cookie);
-       return (0);
-}
-
-FILE *
-open_memstream(char **cp, size_t *lenp)
-{
-       struct memstream *ms;
-       int save_errno;
-       FILE *fp;
-
-       *cp = NULL;
-       *lenp = 0;
-       ms = malloc(sizeof(*ms));
-       ms->cp = cp;
-       ms->lenp = lenp;
-       ms->offset = 0;
-       fp = funopen(ms, memstream_read, memstream_write, memstream_seek,
-           memstream_close);
-       if (fp == NULL) {
-               save_errno = errno;
-               free(ms);
-               errno = save_errno;
-       }
-       return (fp);
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/celix/blob/2c74cc35/dfi/public/include/memstream/README.md
----------------------------------------------------------------------
diff --git a/dfi/public/include/memstream/README.md 
b/dfi/public/include/memstream/README.md
deleted file mode 100644
index 476810e..0000000
--- a/dfi/public/include/memstream/README.md
+++ /dev/null
@@ -1,49 +0,0 @@
-fmemopen for Mac OS and iOS
-===========================
-
-Originally ported from [ingenuitas 
python-tesseract](https://github.com/ingenuitas/python-tesseract/blob/master/fmemopen.c).
 Ported by Jeff Verkoeyen under the Apache 2.0 License.
-
-From the fmemopen man page:
-
-> FILE *fmemopen(void *buf, size_t size, const char *mode);
->
-> The fmemopen() function opens a stream that permits the access specified by 
mode. The stream
-> allows I/O to be performed on the string or memory buffer pointed to by buf. 
This buffer must be
-> at least size bytes long.
-
-Alas, this method does not exist on BSD operating systems (specifically Mac OS 
X and iOS). It is
-possible to recreate this functionality using a BSD-specific method called 
`funopen`.
-
-From the funopen man page:
-
-> FILE * funopen(const void *cookie, int (*readfn)(void *, char *, int),
->                int (*writefn)(void *, const char *, int), fpos_t 
(*seekfn)(void *, fpos_t, int),
->                int (*closefn)(void *));
->
-> The funopen() function associates a stream with up to four ``I/O 
functions''.  Either readfn or
-> writefn must be specified; the others can be given as an appropriately-typed 
NULL pointer.  These
-> I/O functions will be used to read, write, seek and close the new stream.
-
-fmemopen.c provides a simple implementation of fmemopen using funopen so that 
you can create FILE
-pointers to blocks of memory.
-
-Adding it to your Project
-=========================
-
-Drag fmemopen.h and fmemopen.c to your project and add them to your target. 
`#include "fmemopen.h"`
-wherever you need to use `fmemopen`.
-
-Examples
-========
-
-```obj-c
-#import "fmemopen.h"
-
-NSString* string = @"fmemopen in Objective-C";
-const char* cstr = [string UTF8String];
-FILE* file = fmemopen((void *)cstr, sizeof(char) * (string.length + 1), "r");
-
-// fread on file will now read the contents of the NSString
-
-fclose(file);
-```

http://git-wip-us.apache.org/repos/asf/celix/blob/2c74cc35/dfi/public/include/memstream/fmemopen.h
----------------------------------------------------------------------
diff --git a/dfi/public/include/memstream/fmemopen.h 
b/dfi/public/include/memstream/fmemopen.h
deleted file mode 100644
index 3d06b20..0000000
--- a/dfi/public/include/memstream/fmemopen.h
+++ /dev/null
@@ -1,52 +0,0 @@
-//
-// Copyright 2012 Jeff Verkoeyen
-// Originally ported from 
https://github.com/ingenuitas/python-tesseract/blob/master/fmemopen.c
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//    http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-//
-
-#ifndef FMEMOPEN_H_
-#define FMEMOPEN_H_
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-/**
- * A BSD port of the fmemopen Linux method using funopen.
- *
- * man docs for fmemopen:
- * http://linux.die.net/man/3/fmemopen
- *
- * man docs for funopen:
- * 
https://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man3/funopen.3.html
- *
- * This method is ported from ingenuitas' python-tesseract project.
- *
- * You must call fclose on the returned file pointer or memory will be leaked.
- *
- *      @param buf The data that will be used to back the FILE* methods. Must 
be at least
- *                 @c size bytes.
- *      @param size The size of the @c buf data.
- *      @param mode The permitted stream operation modes.
- *      @returns A pointer that can be used in the fread/fwrite/fseek/fclose 
family of methods.
- *               If a failure occurred NULL will be returned.
- */
-FILE *fmemopen(void *buf, size_t size, const char *mode);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // #ifndef FMEMOPEN_H_

http://git-wip-us.apache.org/repos/asf/celix/blob/2c74cc35/dfi/public/include/memstream/open_memstream.h
----------------------------------------------------------------------
diff --git a/dfi/public/include/memstream/open_memstream.h 
b/dfi/public/include/memstream/open_memstream.h
deleted file mode 100644
index e87bb0a..0000000
--- a/dfi/public/include/memstream/open_memstream.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef OPEN_MEMSTREAM_H_
-#define OPEN_MEMSTREAM_H_
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-FILE *open_memstream(char **cp, size_t *lenp);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // #ifndef FMEMOPEN_H_

http://git-wip-us.apache.org/repos/asf/celix/blob/2c74cc35/shell_bonjour/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/shell_bonjour/CMakeLists.txt b/shell_bonjour/CMakeLists.txt
index 38ef9a1..300fef0 100644
--- a/shell_bonjour/CMakeLists.txt
+++ b/shell_bonjour/CMakeLists.txt
@@ -30,12 +30,18 @@ if (SHELL_BONJOUR)
        include_directories("${PROJECT_SOURCE_DIR}/shell/public/include")
        include_directories("${LIBXML2_INCLUDE_DIR}")
        include_directories("private/include")
-       
+
+       set(MEMSTREAM_SOURCES )
+       if (APPLE OR ANDROID)
+               set(MEMSTREAM_SOURCES 
${PROJECT_SOURCE_DIR}/utils/private/src/memstream/open_memstream.c  
${PROJECT_SOURCE_DIR}/utils/private/src/memstream/fmemopen.c)
+               
include_directories(${PROJECT_SOURCE_DIR}/utils/public/include/memstream)
+       endif()
        add_bundle(bonjour_shell
                 VERSION "1.0.0"
                SOURCES
                        private/src/activator.c
                        private/src/bonjour_shell.c
+                       ${MEMSTREAM_SOURCES}
        )
        
        target_link_libraries(bonjour_shell celix_framework celix_utils 
${LIBXML2_LIBRARIES} ${DNS_SD_LIB})

http://git-wip-us.apache.org/repos/asf/celix/blob/2c74cc35/shell_bonjour/private/src/activator.c
----------------------------------------------------------------------
diff --git a/shell_bonjour/private/src/activator.c 
b/shell_bonjour/private/src/activator.c
index 75340b2..e05211d 100644
--- a/shell_bonjour/private/src/activator.c
+++ b/shell_bonjour/private/src/activator.c
@@ -73,7 +73,7 @@ celix_status_t bundleActivator_start(void * userData, 
bundle_context_pt context)
 
         char id[128];
         if (bonjourShellId != NULL) {
-                snprintf(id, 128, bonjourShellId);
+                snprintf(id, 128, "%s", bonjourShellId);
         } else if (hostname != NULL) {
                 snprintf(id, 128, "Celix-%.8s@%s", uuid, hostname);
         } else {

http://git-wip-us.apache.org/repos/asf/celix/blob/2c74cc35/shell_bonjour/private/src/bonjour_shell.c
----------------------------------------------------------------------
diff --git a/shell_bonjour/private/src/bonjour_shell.c 
b/shell_bonjour/private/src/bonjour_shell.c
index a93d3e1..59ee18a 100644
--- a/shell_bonjour/private/src/bonjour_shell.c
+++ b/shell_bonjour/private/src/bonjour_shell.c
@@ -40,6 +40,11 @@
 #include <celixbool.h>
 #include <shell.h>
 
+#if defined(BSD) || defined(__APPLE__)  || defined(ANDROID)
+#include "open_memstream.h"
+#include "fmemopen.h"
+#endif
+
 #define MAX_BUFFER_SIZE 5120
 
 //static xmlBufferPtr buf; //FOR DEBUG
@@ -358,9 +363,13 @@ static void bonjourShell_parseCommand(bonjour_shell_pt 
shell, struct connection_
 
 static void bonjourShell_addDataToCurrentContext(const char* out, const char* 
err) {
        pthread_mutex_lock(&currentContext->mutex);
-       arrayList_add(currentContext->dataList, strdup(out));
-       arrayList_add(currentContext->dataList, strdup(err));
-        gettimeofday(&currentContext->lastUpdated, NULL);
+    if (out != NULL) {
+           arrayList_add(currentContext->dataList, strdup(out));
+    }
+       if (err != NULL) {
+        arrayList_add(currentContext->dataList, strdup(err));
+    }
+    gettimeofday(&currentContext->lastUpdated, NULL);
        pthread_mutex_unlock(&currentContext->mutex);
        pthread_cond_signal(&currentContext->dataAvailCond);
 }

http://git-wip-us.apache.org/repos/asf/celix/blob/2c74cc35/utils/private/src/memstream/fmemopen.c
----------------------------------------------------------------------
diff --git a/utils/private/src/memstream/fmemopen.c 
b/utils/private/src/memstream/fmemopen.c
new file mode 100644
index 0000000..66fc9c5
--- /dev/null
+++ b/utils/private/src/memstream/fmemopen.c
@@ -0,0 +1,78 @@
+
+/*
+ * fmem.c : fmemopen() on top of BSD's funopen()
+ * 20081017 AF
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef linux
+struct fmem {
+    size_t pos;
+    size_t size;
+    char *buffer;
+};
+typedef struct fmem fmem_t;
+
+static int readfn(void *handler, char *buf, int size)
+{
+    int count = 0;
+    fmem_t *mem = handler;
+    size_t available = mem->size - mem->pos;
+
+    if(size > available) size = available;
+    for(count=0; count < size; mem->pos++, count++)
+        buf[count] = mem->buffer[mem->pos];
+
+    return count;
+}
+
+static int writefn(void *handler, const char *buf, int size)
+{
+    int count = 0;
+    fmem_t *mem = handler;
+    size_t available = mem->size - mem->pos;
+
+    if(size > available) size = available;
+    for(count=0; count < size; mem->pos++, count++)
+        mem->buffer[mem->pos] = buf[count];
+
+    return count; // ? count : size;
+}
+
+static fpos_t seekfn(void *handler, fpos_t offset, int whence)
+{
+    size_t pos;
+    fmem_t *mem = handler;
+
+    switch(whence) {
+        case SEEK_SET: pos = offset; break;
+        case SEEK_CUR: pos = mem->pos + offset; break;
+        case SEEK_END: pos = mem->size + offset; break;
+        default: return -1;
+    }
+
+    if(pos > mem->size) return -1;
+
+    mem->pos = pos;
+    return (fpos_t) pos;
+}
+
+static int closefn(void *handler)
+{
+    free(handler);
+    return 0;
+}
+
+/* simple, but portable version of fmemopen for OS X / BSD */
+FILE *fmemopen(void *buf, size_t size, const char *mode)
+{
+    fmem_t *mem = (fmem_t *) malloc(sizeof(fmem_t));
+
+    memset(mem, 0, sizeof(fmem_t));
+    mem->size = size, mem->buffer = buf;
+    return funopen(mem, readfn, writefn, seekfn, closefn);
+}
+#endif

http://git-wip-us.apache.org/repos/asf/celix/blob/2c74cc35/utils/private/src/memstream/open_memstream.c
----------------------------------------------------------------------
diff --git a/utils/private/src/memstream/open_memstream.c 
b/utils/private/src/memstream/open_memstream.c
new file mode 100644
index 0000000..6bc4f01
--- /dev/null
+++ b/utils/private/src/memstream/open_memstream.c
@@ -0,0 +1,130 @@
+/* Use funopen(3) to provide open_memstream(3) like functionality. */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+struct memstream {
+       char **cp;
+       size_t *lenp;
+       size_t offset;
+};
+
+static void
+memstream_grow(struct memstream *ms, size_t newsize)
+{
+       char *buf;
+
+       if (newsize > *ms->lenp) {
+               buf = realloc(*ms->cp, newsize + 1);
+               if (buf != NULL) {
+#ifdef DEBUG
+                       fprintf(stderr, "MS: %p growing from %zd to %zd\n",
+                           ms, *ms->lenp, newsize);
+#endif
+                       memset(buf + *ms->lenp + 1, 0, newsize - *ms->lenp);
+                       *ms->cp = buf;
+                       *ms->lenp = newsize;
+               }
+       }
+}
+
+static int
+memstream_read(void *cookie, char *buf, int len)
+{
+       struct memstream *ms;
+       int tocopy;
+
+       ms = cookie;
+       memstream_grow(ms, ms->offset + len);
+       tocopy = *ms->lenp - ms->offset;
+       if (len < tocopy)
+               tocopy = len;
+       memcpy(buf, *ms->cp + ms->offset, tocopy);
+       ms->offset += tocopy;
+#ifdef DEBUG
+       fprintf(stderr, "MS: read(%p, %d) = %d\n", ms, len, tocopy);
+#endif
+       return (tocopy);
+}
+
+static int
+memstream_write(void *cookie, const char *buf, int len)
+{
+       struct memstream *ms;
+       int tocopy;
+
+       ms = cookie;
+       memstream_grow(ms, ms->offset + len);
+       tocopy = *ms->lenp - ms->offset;
+       if (len < tocopy)
+               tocopy = len;
+       memcpy(*ms->cp + ms->offset, buf, tocopy);
+       ms->offset += tocopy;
+#ifdef DEBUG
+       fprintf(stderr, "MS: write(%p, %d) = %d\n", ms, len, tocopy);
+#endif
+       return (tocopy);
+}
+
+static fpos_t
+memstream_seek(void *cookie, fpos_t pos, int whence)
+{
+       struct memstream *ms;
+#ifdef DEBUG
+       size_t old;
+#endif
+
+       ms = cookie;
+#ifdef DEBUG
+       old = ms->offset;
+#endif
+       switch (whence) {
+       case SEEK_SET:
+               ms->offset = pos;
+               break;
+       case SEEK_CUR:
+               ms->offset += pos;
+               break;
+       case SEEK_END:
+               ms->offset = *ms->lenp + pos;
+               break;
+       }
+#ifdef DEBUG
+       fprintf(stderr, "MS: seek(%p, %zd, %d) %zd -> %zd\n", ms, pos, whence,
+           old, ms->offset);
+#endif
+       return (ms->offset);
+}
+
+static int
+memstream_close(void *cookie)
+{
+
+       free(cookie);
+       return (0);
+}
+
+FILE *
+open_memstream(char **cp, size_t *lenp)
+{
+       struct memstream *ms;
+       int save_errno;
+       FILE *fp;
+
+       *cp = NULL;
+       *lenp = 0;
+       ms = malloc(sizeof(*ms));
+       ms->cp = cp;
+       ms->lenp = lenp;
+       ms->offset = 0;
+       fp = funopen(ms, memstream_read, memstream_write, memstream_seek,
+           memstream_close);
+       if (fp == NULL) {
+               save_errno = errno;
+               free(ms);
+               errno = save_errno;
+       }
+       return (fp);
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/celix/blob/2c74cc35/utils/public/include/memstream/README.md
----------------------------------------------------------------------
diff --git a/utils/public/include/memstream/README.md 
b/utils/public/include/memstream/README.md
new file mode 100644
index 0000000..476810e
--- /dev/null
+++ b/utils/public/include/memstream/README.md
@@ -0,0 +1,49 @@
+fmemopen for Mac OS and iOS
+===========================
+
+Originally ported from [ingenuitas 
python-tesseract](https://github.com/ingenuitas/python-tesseract/blob/master/fmemopen.c).
 Ported by Jeff Verkoeyen under the Apache 2.0 License.
+
+From the fmemopen man page:
+
+> FILE *fmemopen(void *buf, size_t size, const char *mode);
+>
+> The fmemopen() function opens a stream that permits the access specified by 
mode. The stream
+> allows I/O to be performed on the string or memory buffer pointed to by buf. 
This buffer must be
+> at least size bytes long.
+
+Alas, this method does not exist on BSD operating systems (specifically Mac OS 
X and iOS). It is
+possible to recreate this functionality using a BSD-specific method called 
`funopen`.
+
+From the funopen man page:
+
+> FILE * funopen(const void *cookie, int (*readfn)(void *, char *, int),
+>                int (*writefn)(void *, const char *, int), fpos_t 
(*seekfn)(void *, fpos_t, int),
+>                int (*closefn)(void *));
+>
+> The funopen() function associates a stream with up to four ``I/O 
functions''.  Either readfn or
+> writefn must be specified; the others can be given as an appropriately-typed 
NULL pointer.  These
+> I/O functions will be used to read, write, seek and close the new stream.
+
+fmemopen.c provides a simple implementation of fmemopen using funopen so that 
you can create FILE
+pointers to blocks of memory.
+
+Adding it to your Project
+=========================
+
+Drag fmemopen.h and fmemopen.c to your project and add them to your target. 
`#include "fmemopen.h"`
+wherever you need to use `fmemopen`.
+
+Examples
+========
+
+```obj-c
+#import "fmemopen.h"
+
+NSString* string = @"fmemopen in Objective-C";
+const char* cstr = [string UTF8String];
+FILE* file = fmemopen((void *)cstr, sizeof(char) * (string.length + 1), "r");
+
+// fread on file will now read the contents of the NSString
+
+fclose(file);
+```

http://git-wip-us.apache.org/repos/asf/celix/blob/2c74cc35/utils/public/include/memstream/fmemopen.h
----------------------------------------------------------------------
diff --git a/utils/public/include/memstream/fmemopen.h 
b/utils/public/include/memstream/fmemopen.h
new file mode 100644
index 0000000..3d06b20
--- /dev/null
+++ b/utils/public/include/memstream/fmemopen.h
@@ -0,0 +1,52 @@
+//
+// Copyright 2012 Jeff Verkoeyen
+// Originally ported from 
https://github.com/ingenuitas/python-tesseract/blob/master/fmemopen.c
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//    http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+#ifndef FMEMOPEN_H_
+#define FMEMOPEN_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * A BSD port of the fmemopen Linux method using funopen.
+ *
+ * man docs for fmemopen:
+ * http://linux.die.net/man/3/fmemopen
+ *
+ * man docs for funopen:
+ * 
https://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man3/funopen.3.html
+ *
+ * This method is ported from ingenuitas' python-tesseract project.
+ *
+ * You must call fclose on the returned file pointer or memory will be leaked.
+ *
+ *      @param buf The data that will be used to back the FILE* methods. Must 
be at least
+ *                 @c size bytes.
+ *      @param size The size of the @c buf data.
+ *      @param mode The permitted stream operation modes.
+ *      @returns A pointer that can be used in the fread/fwrite/fseek/fclose 
family of methods.
+ *               If a failure occurred NULL will be returned.
+ */
+FILE *fmemopen(void *buf, size_t size, const char *mode);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // #ifndef FMEMOPEN_H_

http://git-wip-us.apache.org/repos/asf/celix/blob/2c74cc35/utils/public/include/memstream/open_memstream.h
----------------------------------------------------------------------
diff --git a/utils/public/include/memstream/open_memstream.h 
b/utils/public/include/memstream/open_memstream.h
new file mode 100644
index 0000000..e87bb0a
--- /dev/null
+++ b/utils/public/include/memstream/open_memstream.h
@@ -0,0 +1,15 @@
+#ifndef OPEN_MEMSTREAM_H_
+#define OPEN_MEMSTREAM_H_
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+FILE *open_memstream(char **cp, size_t *lenp);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // #ifndef FMEMOPEN_H_

Reply via email to