new dav_query function

Sat, 17 Aug 2013 12:04:04 +0200

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sat, 17 Aug 2013 12:04:04 +0200
changeset 17
11dffb40cd91
parent 16
5dbef9e07376
child 18
651989681053

new dav_query function

dav/Makefile file | annotate | diff | comparison | revisions
dav/davql.c file | annotate | diff | comparison | revisions
dav/davql.h file | annotate | diff | comparison | revisions
dav/main.c file | annotate | diff | comparison | revisions
dav/methods.c file | annotate | diff | comparison | revisions
dav/methods.h file | annotate | diff | comparison | revisions
dav/utils.c file | annotate | diff | comparison | revisions
dav/utils.h file | annotate | diff | comparison | revisions
dav/webdav.c file | annotate | diff | comparison | revisions
dav/webdav.h file | annotate | diff | comparison | revisions
ucx/allocator.h file | annotate | diff | comparison | revisions
ucx/buffer.c file | annotate | diff | comparison | revisions
ucx/buffer.h file | annotate | diff | comparison | revisions
ucx/list.h file | annotate | diff | comparison | revisions
ucx/logging.c file | annotate | diff | comparison | revisions
ucx/logging.h file | annotate | diff | comparison | revisions
ucx/map.c file | annotate | diff | comparison | revisions
ucx/map.h file | annotate | diff | comparison | revisions
ucx/mempool.c file | annotate | diff | comparison | revisions
ucx/mempool.h file | annotate | diff | comparison | revisions
ucx/properties.h file | annotate | diff | comparison | revisions
ucx/string.c file | annotate | diff | comparison | revisions
ucx/string.h file | annotate | diff | comparison | revisions
ucx/test.c file | annotate | diff | comparison | revisions
ucx/test.h file | annotate | diff | comparison | revisions
ucx/utils.c file | annotate | diff | comparison | revisions
ucx/utils.h file | annotate | diff | comparison | revisions
--- a/dav/Makefile	Fri Aug 16 12:41:30 2013 +0200
+++ b/dav/Makefile	Sat Aug 17 12:04:04 2013 +0200
@@ -35,6 +35,7 @@
 SRC += utils.c
 SRC += webdav.c
 SRC += methods.c
+SRC += davql.c
 SRC += config.c
 SRC += crypto.c
 SRC += optparser.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dav/davql.c	Sat Aug 17 12:04:04 2013 +0200
@@ -0,0 +1,139 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2013 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "davql.h"
+#include "methods.h"
+#include "webdav.h"
+#include "utils.h"
+
+DavQuery dav_ql_parse(char *query, va_list ap) {
+    DavQuery davquery;
+    davquery.command = DAV_QUERY_ERROR;
+    davquery.command_data = NULL;
+    sstr_t q = sstr(query);
+    q = sstrtrim(q);
+    
+    // get query command
+    sstr_t cmd;
+    cmd.ptr = NULL;
+    int i;
+    for(i=0;i<q.length;i++) {
+        if(q.ptr[i] == ' ') {
+            cmd = sstrsubsl(q, 0, i);
+            break;
+        }
+    }
+    if(!cmd.ptr) {
+        fprintf(stderr, "DQL syntax error\n");
+        return davquery;
+    }
+    
+    cmd = sstrtrim(cmd);
+    q = sstrtrim(sstrsubs(q, i));
+    if(!sstrcmp(cmd, S("get"))) {
+        davquery.command = DAV_QUERY_GET;
+        davquery.command_data = dav_ql_parse_get(q, ap);
+    }
+    
+    return davquery;
+}
+
+DavGetQuery* dav_ql_parse_get(sstr_t q, va_list ap) {  
+    sstr_t property_query = q;
+    q = util_getsubstr_until_token(q, S("from"), &property_query);
+    
+    sstr_t from_query = q;
+    sstr_t cond = util_getsubstr_until_token(q, S("where"), &from_query);
+    
+    // insert variable values
+    UcxBuffer *fbuf = ucx_buffer_new(NULL, 128, UCX_BUFFER_AUTOEXTEND);
+    int var = 0;
+    for(int i=0;i<from_query.length;i++) {
+        char c = from_query.ptr[i];
+        if(c == '%') {
+            if(var) {
+                ucx_buffer_putc(fbuf, '%'); // previous '%'
+            } else {
+                var = 1;
+            }
+        } else if(var) {
+            switch(c) {
+                case 's': {
+                    char *arg = va_arg(ap, char*);
+                    ucx_buffer_puts(fbuf, arg);
+                    break;
+                }
+                default: {
+                    ucx_buffer_putc(fbuf, '%');
+                    ucx_buffer_putc(fbuf, c);
+                }
+            }
+            var = 0;
+        } else {
+            ucx_buffer_putc(fbuf, c);
+        }
+    }
+    
+    DavGetQuery *getquery = malloc(sizeof(DavGetQuery));
+    getquery->properties = sstrdup(property_query);
+    getquery->from = sstrn(fbuf->space, fbuf->pos);
+    // TODO: condition
+    return getquery;
+}
+
+void free_get_query(DavGetQuery *q) {
+    free(q->from.ptr);
+    free(q->properties.ptr);
+    free(q);
+}
+
+int parse_path_query(sstr_t query, char **path, int *depth) {
+    if(query.length == 1) {
+        if(query.ptr[0] == '/') {
+            *path = sstrdup(query).ptr;
+            *depth = 1;
+            return 0;
+        } else {
+            *path = NULL;
+            return 1;
+        }
+    }
+    
+    if(query.ptr[query.length-1] == '*') {
+        *depth = -1;
+        *path = sstrdup(sstrsubsl(query, 0, query.length-1)).ptr;
+    } else {
+        *path = sstrdup(query).ptr;
+        *depth = 1;
+    }
+    
+    return 0;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/dav/davql.h	Sat Aug 17 12:04:04 2013 +0200
@@ -0,0 +1,68 @@
+/*
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
+ *
+ * Copyright 2013 Olaf Wintermann. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ *   1. Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *
+ *   2. Redistributions in binary form must reproduce the above copyright
+ *      notice, this list of conditions and the following disclaimer in the
+ *      documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef DAVQL_H
+#define	DAVQL_H
+
+#include <ucx/string.h>
+#include <stdarg.h>
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+enum DavQueryType {
+    DAV_QUERY_ERROR = 0,
+    DAV_QUERY_GET
+};
+typedef enum DavQueryType DavQueryType;
+    
+typedef struct {
+    DavQueryType command;
+    void         *command_data;
+} DavQuery;
+
+typedef struct {
+    sstr_t properties;
+    sstr_t from;
+    // TODO: condition
+} DavGetQuery;
+    
+DavQuery dav_ql_parse(char *query, va_list ap);
+DavGetQuery* dav_ql_parse_get(sstr_t q, va_list ap);
+void free_get_query(DavGetQuery *q);
+
+int parse_path_query(sstr_t query, char **path, int *depth);
+
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* DAVQL_H */
+
--- a/dav/main.c	Fri Aug 16 12:41:30 2013 +0200
+++ b/dav/main.c	Sat Aug 17 12:04:04 2013 +0200
@@ -42,6 +42,8 @@
 #include "crypto.h"
 #include "main.h"
 
+#include "davql.h"
+
 static DavContext *ctx;
 
 void xmlerrorfnc(void * c, const char * msg, ... ) {
@@ -202,7 +204,8 @@
     
     //printf("baseurl: %s\n", sn->base_url);
     
-    DavResource *ls = dav_get(sn, path, "U:crypto-key");
+    //DavResource *ls = dav_get(sn, path, "U:crypto-key");
+    DavResource *ls = dav_query(sn, "get U:crypto-key from %s", path);
     if(!ls) {
         print_resource_error(sn, path);
         return -1;
--- a/dav/methods.c	Fri Aug 16 12:41:30 2013 +0200
+++ b/dav/methods.c	Sat Aug 17 12:04:04 2013 +0200
@@ -150,10 +150,12 @@
     return buf;
 }
 
-DavResource* parse_propfind_response(DavSession *sn, UcxBuffer *response) {
+DavResource* parse_propfind_response(DavSession *sn, DavResource *root, UcxBuffer *response) {
     char *url = NULL;
     curl_easy_getinfo(sn->handle, CURLINFO_EFFECTIVE_URL, &url);
-    DavResource *root = resource_new_href(sn, util_url_path(url));
+    if(!root) {
+        root = resource_new_href(sn, util_url_path(url));
+    }
     
     xmlDoc *doc = xmlReadMemory(response->space, response->size, url, NULL, 0);
     if(!doc) {
--- a/dav/methods.h	Fri Aug 16 12:41:30 2013 +0200
+++ b/dav/methods.h	Sat Aug 17 12:04:04 2013 +0200
@@ -53,7 +53,7 @@
 
 UcxBuffer* create_allprop_propfind_request();
 UcxBuffer* create_propfind_request(UcxList *properties);
-DavResource* parse_propfind_response(DavSession *sn, UcxBuffer *response);
+DavResource* parse_propfind_response(DavSession *sn, DavResource *root, UcxBuffer *response);
 int parse_response_tag(DavResource *resource, xmlNode *node);
 void set_davprops(DavResource *res);
 
--- a/dav/utils.c	Fri Aug 16 12:41:30 2013 +0200
+++ b/dav/utils.c	Sat Aug 17 12:04:04 2013 +0200
@@ -191,3 +191,48 @@
     
     return out;
 }
+
+/*
+ * gets a substring from 0 to the appearance of the token
+ * tokens are separated by space
+ * sets sub to the substring and returns the remaining string
+ */
+sstr_t util_getsubstr_until_token(sstr_t str, sstr_t token, sstr_t *sub) {  
+    int i;
+    int token_start = -1;
+    int token_end = -1;
+    for(i=0;i<=str.length;i++) {
+        int c;
+        if(i == str.length) {
+            c = ' ';
+        } else {
+            c = str.ptr[i];
+        }
+        if(c < 33) {
+            if(token_start != -1) {
+                token_end = i;
+                size_t len = token_end - token_start;
+                sstr_t tk = sstrsubsl(str, token_start, len);
+                //printf("token: {%.*s}\n", token.length, token.ptr);
+                if(!sstrcmp(tk, token)) {
+                    *sub = sstrtrim(sstrsubsl(str, 0, token_start));
+                    break;
+                }
+                token_start = -1;
+                token_end = -1;
+            }
+        } else {
+            if(token_start == -1) {
+                token_start = i;
+            }
+        }
+    }
+    
+    if(i < str.length) {
+        return sstrtrim(sstrsubs(str, i));
+    } else {
+        str.ptr = NULL;
+        str.length = 0;
+        return str;
+    }
+}
--- a/dav/utils.h	Fri Aug 16 12:41:30 2013 +0200
+++ b/dav/utils.h	Sat Aug 17 12:04:04 2013 +0200
@@ -31,6 +31,7 @@
 
 #include <sys/types.h>
 #include <libxml/tree.h>
+#include <ucx/string.h>
 
 #ifdef	__cplusplus
 extern "C" {
@@ -50,6 +51,8 @@
 
 char* util_base64decode(char* in);
 
+sstr_t util_getsubstr_until_token(sstr_t str, sstr_t token, sstr_t *sub);
+
 #ifdef	__cplusplus
 }
 #endif
--- a/dav/webdav.c	Fri Aug 16 12:41:30 2013 +0200
+++ b/dav/webdav.c	Sat Aug 17 12:04:04 2013 +0200
@@ -34,6 +34,7 @@
 #include "utils.h"
 #include "webdav.h"
 #include "methods.h"
+#include "davql.h"
 #include "ucx/buffer.h"
 #include "ucx/utils.h"
 
@@ -209,10 +210,87 @@
     curl_easy_getinfo (handle, CURLINFO_RESPONSE_CODE, &status);
     if(ret == CURLE_OK && status == 207) {
         //printf("response\n%s\n", rpbuf->space); 
-        resource = parse_propfind_response(sn, rpbuf);
+        resource = parse_propfind_response(sn, NULL, rpbuf);
+        sn->error = DAV_OK;
+    } else  {
+        session_set_error(sn, ret, status);
+    }
+    return resource;
+}
+
+DavResource* dav_propfind(DavSession *sn, DavResource *root, UcxBuffer *rqbuf, char *path) {
+    char *url = util_concat_path(sn->base_url, path);  
+    CURL *handle = sn->handle;
+    curl_easy_setopt(handle, CURLOPT_URL, url);
+    free(url);
+    
+    UcxBuffer *rpbuf = ucx_buffer_new(NULL, 4096, UCX_BUFFER_AUTOEXTEND);
+    DavResource *resource = root;
+    CURLcode ret = do_propfind_request(handle, rqbuf, rpbuf);
+    int status = 0;
+    curl_easy_getinfo (handle, CURLINFO_RESPONSE_CODE, &status);
+    if(ret == CURLE_OK && status == 207) {
+        //printf("response\n%s\n", rpbuf->space); 
+        resource = parse_propfind_response(sn, resource, rpbuf);
         sn->error = DAV_OK;
     } else  {
         session_set_error(sn, ret, status);
+        resource = NULL;
+    }
+    ucx_buffer_free(rpbuf);
+    return resource;
+}
+
+UcxList* propfind_stack_push(UcxList *stack, DavResource *children) {
+    while(children) {
+        if(children->iscollection) {
+            stack = ucx_list_prepend(stack, children);
+        }
+        children = children->next;
+    }
+    return stack;
+}
+
+DavResource* dav_get2(DavSession *sn, DavGetQuery *query) {
+    char *path;
+    int depth = 0;
+    if(parse_path_query(query->from, &path, &depth)) {
+        sn->error = DAV_ERROR;
+        return NULL;
+    }
+    
+    sstr_t ps = query->properties;
+    UcxBuffer *rqbuf;
+    if(!sstrcmp(ps, S("*"))) {
+        rqbuf = create_allprop_propfind_request();
+    } else if(!sstrcmp(ps, S("-"))) {
+        rqbuf = create_propfind_request(NULL);
+    } else {
+        UcxList *proplist = parse_properties_string(sn->context, ps);
+        rqbuf = create_propfind_request(proplist);
+    }
+    
+    //fwrite(rqbuf->space, 1, rqbuf->size, stdout);
+    //printf("\n");
+    
+    DavResource *resource = dav_propfind(sn, NULL, rqbuf, path);
+    free(path);
+    int error = 0;
+    if(resource && depth == -1) {
+        UcxList *stack = NULL; // stack with davResource* elements
+        stack = propfind_stack_push(stack, resource->children);
+        while(stack) {
+            DavResource *sr = stack->data; // get first element from the stack
+            stack = ucx_list_remove(stack, stack); // remove first element
+            // do propfind request for sr
+            sr = dav_propfind(sn, sr, rqbuf, sr->path);
+            if(!sr) {
+                error = 1;
+                printf("subrequest failed\n");
+                break;
+            }
+            stack = propfind_stack_push(stack, sr->children); // add children
+        }
     }
     return resource;
 }
@@ -247,6 +325,21 @@
     return proplist;
 }
 
+DavResource* dav_query(DavSession *sn, char *query, ...) {
+    va_list ap;
+    va_start(ap, query);
+    DavQuery q = dav_ql_parse(query, ap);
+    va_end(ap);
+    DavResource *res = NULL;
+    switch(q.command) {
+        case DAV_QUERY_GET: {
+            res = dav_get2(sn, q.command_data);
+            free_get_query(q.command_data);
+            break;
+        }
+    }
+    return res;
+}
 
 
 
--- a/dav/webdav.h	Fri Aug 16 12:41:30 2013 +0200
+++ b/dav/webdav.h	Sat Aug 17 12:04:04 2013 +0200
@@ -36,6 +36,7 @@
 #include <ucx/buffer.h>
 #include <curl/curl.h>
 #include <libxml/tree.h>
+#include "davql.h"
 
 #ifdef	__cplusplus
 extern "C" {
@@ -149,9 +150,11 @@
 void dav_session_destroy(DavSession *sn);
 
 DavResource* dav_get(DavSession *sn, char *path, char *properties);
+DavResource* dav_get2(DavSession *sn, DavGetQuery *query);
 
 UcxList* parse_properties_string(DavContext *context, sstr_t str);
 
+DavResource* dav_query(DavSession *sn, char *query, ...);
 
 DavResource* dav_resource_new(DavSession *sn, char *path);
 DavResource* resource_new_href(DavSession *sn, char *href);
--- a/ucx/allocator.h	Fri Aug 16 12:41:30 2013 +0200
+++ b/ucx/allocator.h	Sat Aug 17 12:04:04 2013 +0200
@@ -63,16 +63,19 @@
  * @see UcxAllocator
  */
 typedef void*(*ucx_allocator_malloc)(void *pool, size_t n);
+
 /**
  * A function pointer to the allocators <code>calloc()</code> function.
  * @see UcxAllocator
  */
 typedef void*(*ucx_allocator_calloc)(void *pool, size_t n, size_t size);
+
 /**
  * A function pointer to the allocators <code>realloc()</code> function.
  * @see UcxAllocator
  */
 typedef void*(*ucx_allocator_realloc)(void *pool, void *data, size_t n);
+
 /**
  * A function pointer to the allocators <code>free()</code> function.
  * @see UcxAllocator
--- a/ucx/buffer.c	Fri Aug 16 12:41:30 2013 +0200
+++ b/ucx/buffer.c	Sat Aug 17 12:04:04 2013 +0200
@@ -91,17 +91,16 @@
 }
 
 int ucx_buffer_seek(UcxBuffer *buffer, off_t offset, int whence) {
-    size_t npos = 0;
+    size_t npos;
     switch (whence) {
-    case SEEK_SET:
-        npos = 0;
-        break;
     case SEEK_CUR:
         npos = buffer->pos;
         break;
     case SEEK_END:
         npos = buffer->size;
         break;
+    default:
+        npos = 0;
     }
 
     npos += offset;
@@ -210,51 +209,6 @@
     }
 }
 
-size_t ucx_buffer_generic_copy(void *s1, void *s2,
-        read_func readfnc, write_func writefnc, size_t bufsize) {
-    size_t ncp = 0;
-    char *buf = (char*)malloc(bufsize);
-    if(buf == NULL) {
-        return 0;
-    }
-    
-    size_t r;
-    while((r = readfnc(buf, 1, bufsize, s1)) != 0) {
-        r = writefnc(buf, 1, r, s2);
-        ncp += r;
-        if(r == 0) {
-            break;
-        }
-    }
-    
-    free(buf);
-    return ncp;
+size_t ucx_buffer_puts(UcxBuffer *buffer, char *str) {
+    return ucx_buffer_write((const void*)str, 1, strlen(str), buffer);
 }
-
-size_t ucx_buffer_generic_ncopy(void *s1, void *s2,
-        read_func readfnc, write_func writefnc, size_t bufsize, size_t n) {
-    if(n == 0) {
-        return 0;
-    }
-    
-    size_t ncp = 0;
-    char *buf = (char*)malloc(bufsize);
-    if(buf == NULL) {
-        return 0;
-    }
-    
-    size_t r;
-    size_t rn = bufsize > n ? n : bufsize;
-    while((r = readfnc(buf, 1, rn, s1)) != 0) {
-        r = writefnc(buf, 1, r, s2);
-        ncp += r;
-        n -= r;
-        rn = bufsize > n ? n : bufsize;
-        if(r == 0 || n == 0) {
-            break;
-        }
-    }
-    
-    free(buf);
-    return ncp;
-}
--- a/ucx/buffer.h	Fri Aug 16 12:41:30 2013 +0200
+++ b/ucx/buffer.h	Sat Aug 17 12:04:04 2013 +0200
@@ -26,6 +26,23 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 
+/**
+ * @file buffer.h
+ * 
+ * Advanced buffer implementation.
+ * 
+ * Instances of UcxBuffer can be used to read from or to write to like one
+ * would do with a stream. This allows the use of ucx_stream_copy() to copy
+ * contents from one buffer to another.
+ * 
+ * Some features for convenient use of the buffer
+ * can be enabled. See the documentation of the macro constants for more
+ * information.
+ * 
+ * @author Mike Becker
+ * @author Olaf Wintermann
+ */
+
 #ifndef UCX_BUFFER_H
 #define	UCX_BUFFER_H
 
@@ -37,94 +54,210 @@
 extern "C" {
 #endif
 
-/* no autoextend or autofree behaviour */
+/**
+ * No buffer features enabled (all flags cleared).
+ */
 #define UCX_BUFFER_DEFAULT      0x00
-/* the buffer shall free the occupied memory space */
+
+/**
+ * If this flag is enabled, the buffer will automatically free its contents.
+ */
 #define UCX_BUFFER_AUTOFREE     0x01
-/* the buffer may automatically double its size on write operations */
+
+/**
+ * If this flag is enabled, the buffer will automatically extends its capacity.
+ */
 #define UCX_BUFFER_AUTOEXTEND   0x02
 
-/* the user shall not modify values, but may get the latest pointer */
+/** UCX Buffer. */
 typedef struct {
+    /** A pointer to the buffer contents. */
     char *space;
+    /** Current position of the buffer. */
     size_t pos;
+    /** Current capacity (i.e. maximum size) of the buffer. */
     size_t capacity;
+    /** Current size of the buffer content. */
     size_t size;
+    /**
+     * Flag register for buffer features.
+     * @see #UCX_BUFFER_DEFAULT
+     * @see #UCX_BUFFER_AUTOFREE
+     * @see #UCX_BUFFER_AUTOEXTEND
+     */
     int flags;
 } UcxBuffer;
 
-/* if space is NULL, new space is allocated and the autofree flag is enforced */
+/**
+ * Creates a new buffer.
+ * 
+ * <b>Note:</b> you may provide <code>NULL</code> as argument for
+ * <code>space</code>. Then this function will allocate the space and enforce
+ * the #UCX_BUFFER_AUTOFREE flag.
+ * 
+ * @param space pointer to the memory area, or <code>NULL</code> to allocate
+ * new memory
+ * @param size the size of the buffer
+ * @param flags buffer features (see UcxBuffer.flags)
+ * @return the new buffer
+ */
 UcxBuffer *ucx_buffer_new(void *space, size_t size, int flags);
+
+/**
+ * Destroys a buffer.
+ * 
+ * If the #UCX_BUFFER_AUTOFREE feature is enabled, the contents of the buffer
+ * are also freed.
+ * 
+ * @param buffer the buffer to destroy
+ */
 void ucx_buffer_free(UcxBuffer* buffer);
 
-/*
- * the autofree flag is enforced for the new buffer
- * if length is zero, the whole remaining buffer shall be extracted
- * the position of the new buffer is set to zero
+/**
+ * Creates a new buffer and fills it with extracted content from another buffer.
+ * 
+ * <b>Note:</b> the #UCX_BUFFER_AUTOFREE feature is enforced for the new buffer.
+ * 
+ * @param src the source buffer
+ * @param start the start position of extraction
+ * @param length the count of bytes to extract or 0 if all of the remaining
+ * bytes shall be extracted
+ * @param flags feature mask for the new buffer
+ * @return 
  */
 UcxBuffer* ucx_buffer_extract(UcxBuffer *src,
         size_t start, size_t length, int flags);
+
+/**
+ * A shorthand macro for the full extraction of the buffer.
+ * 
+ * @param src the source buffer
+ * @param flags feature mask for the new buffer
+ * @return a new buffer with the extracted content
+ */
 #define ucx_buffer_clone(src,flags) \
     ucx_buffer_extract(src, 0, 0, flags)
 
-/*
- * Moves the position of the buffer to a new position relative to whence.
+/**
+ * Moves the position of the buffer.
+ * 
+ * The new position is relative to the <code>whence</code> argument.
  *
- * SEEK_SET marks the start of the buffer
- * SEEK_CUR marks the current position
- * SEEK_END marks the first 0-byte in the buffer
- *
- * ucx_buffer_seek returns 0 on success and -1 if the new position is beyond the
- * bounds of the allocated buffer. In that case the position of the buffer
- * remains unchanged.
+ * SEEK_SET marks the start of the buffer.
+ * SEEK_CUR marks the current position.
+ * SEEK_END marks the first 0-byte in the buffer.
+ * 
+ * @param buffer
+ * @param offset position offset relative to <code>whence</code>
+ * @param whence one of SEEK_SET, SEEK_CUR or SEEK_END
+ * @return 0 on success, non-zero if the position is invalid
  *
  */
 int ucx_buffer_seek(UcxBuffer *buffer, off_t offset, int whence);
 
-#define ucx_buffer_clear(buffer)    memset(buffer->space, 0, buffer->size); \
-                                    buffer->size = 0; buffer->pos = 0;
+/**
+ * Clears the buffer by resetting the position and deleting the data.
+ * 
+ * The data is deleted by a zeroing it with call to <code>memset()</code>.
+ * 
+ * @param buffer the buffer to be cleared
+ */
+#define ucx_buffer_clear(buffer) memset(buffer->space, 0, buffer->size); \
+        buffer->size = 0; buffer->pos = 0;
 
-/*
- * returns non-zero, if the current buffer position has exceeded the last
- * available byte of the underlying buffer
- *
+/**
+ * Tests, if the buffer position has exceeded the buffer capacity.
+ * 
+ * @param buffer the buffer to test
+ * @return non-zero, if the current buffer position has exceeded the last
+ * available byte of the buffer.
  */
 int ucx_buffer_eof(UcxBuffer *buffer);
 
 
-int ucx_buffere_extend(UcxBuffer *buffer, size_t len);
+/**
+ * Extends the capacity of the buffer.
+ * 
+ * <b>Note:</b> The buffer capacity increased by a power of two. I.e.
+ * the buffer capacity is doubled, as long as it would not hold the current
+ * content plus the additional required bytes.
+ * 
+ * <b>Attention:</b> the argument provided is the count of <i>additional</i>
+ * bytes the buffer shall hold. It is <b>NOT</b> the total count of bytes the
+ * buffer shall hold.
+ * 
+ * @param buffer the buffer to extend
+ * @param additional_bytes the count of additional bytes the buffer shall
+ * <i>at least</i> hold
+ * @return 0 on success or a non-zero value on failure
+ */
+int ucx_buffer_extend(UcxBuffer *buffer, size_t additional_bytes);
 
+/**
+ * Writes data to an UcxBuffer.
+ * 
+ * The position of the buffer is increased by the number of bytes read.
+ * 
+ * @param ptr a pointer to the memory area containing the bytes to be written
+ * @param size the length of one element
+ * @param nitems the element count
+ * @param buffer the UcxBuffer to write to
+ * @return the total count of bytes written
+ */
 size_t ucx_buffer_write(const void *ptr, size_t size, size_t nitems,
         UcxBuffer *buffer);
 
+/**
+ * Reads data from an UcxBuffer.
+ * 
+ * The position of the buffer is increased by the number of bytes read.
+ * 
+ * @param ptr a pointer to the memory area where to store the read data
+ * @param size the length of one element
+ * @param nitems the element count
+ * @param buffer the UcxBuffer to read from
+ * @return the total count of bytes read
+ */
 size_t ucx_buffer_read(void *ptr, size_t size, size_t nitems,
         UcxBuffer *buffer);
 
-int ucx_buffer_putc(UcxBuffer *b, int c);
-int ucx_buffer_getc(UcxBuffer *b);
-
-
-/*
- * copies all bytes from s1 to s2
- * uses the read function r to read from s1 und writes the data using the
- * write function w to s2
- * returns the number of bytes copied
+/**
+ * Writes a character to a buffer.
+ * 
+ * The least significant byte of the argument is written to the buffer. If the
+ * end of the buffer is reached and #UCX_BUFFER_AUTOEXTEND feature is enabled,
+ * the buffer capacity is extended by ucx_buffer_extend(). If the feature is
+ * disabled or buffer extension fails, <code>EOF</code> is returned.
+ * 
+ * On successful write the position of the buffer is increased.
+ * 
+ * @param buffer the buffer to write to
+ * @param c the character to write as <code>int</code> value
+ * @return the byte that has bean written as <code>int</code> value or
+ * <code>EOF</code> when the end of the stream is reached and automatic
+ * extension is not enabled or not possible
  */
-size_t ucx_buffer_generic_copy(void *s1, void *s2, read_func r, write_func w,
-        size_t bufsize);
+int ucx_buffer_putc(UcxBuffer *buffer, int c);
 
-size_t ucx_buffer_generic_ncopy(void *s1, void *s2, read_func r, write_func w,
-        size_t bufsize, size_t n);
-
-#define UCX_DEFAULT_BUFFER_SIZE 0x1000
+/**
+ * Gets a character from a buffer.
+ * 
+ * The current position of the buffer is increased after a successful read.
+ * 
+ * @param buffer the buffer to read from
+ * @return the character as <code>int</code> value or <code>EOF</code>, if the
+ * end of the buffer is reached
+ */
+int ucx_buffer_getc(UcxBuffer *buffer);
 
-#define ucx_buffer_copy(s1,s2,r,w) \
-    ucx_buffer_generic_copy(s1, s2, (read_func)r, (write_func)w, \
-    UCX_DEFAULT_BUFFER_SIZE)
-
-#define ucx_buffer_ncopy(s1,s2,r,w, n) \
-    ucx_buffer_generic_ncopy(s1, s2, (read_func)r, (write_func)w, \
-    UCX_DEFAULT_BUFFER_SIZE, n)
+/**
+ * Writes a string to a buffer.
+ * 
+ * @param buffer the buffer
+ * @param str the string
+ * @return the number of bytes written
+ */
+size_t ucx_buffer_puts(UcxBuffer *buffer, char *str);
 
 #ifdef	__cplusplus
 }
--- a/ucx/list.h	Fri Aug 16 12:41:30 2013 +0200
+++ b/ucx/list.h	Sat Aug 17 12:04:04 2013 +0200
@@ -64,6 +64,7 @@
  * @see UcxList
  */
 typedef struct UcxList UcxList;
+
 /**
  * UCX list structure.
  */
@@ -99,6 +100,7 @@
  * @return a pointer to the copy
  */
 UcxList *ucx_list_clone(UcxList *list, copy_func cpyfnc, void* data);
+
 /**
  * Creates an element-wise copy of a list using an UcxAllocator.
  * 
@@ -152,6 +154,7 @@
  * @param list the list to free
  */
 void ucx_list_free(UcxList *list);
+
 /**
  * Destroys the entire list using an UcxAllocator.
  * 
@@ -162,6 +165,7 @@
  * @see ucx_list_free()
  */
 void ucx_list_free_a(UcxAllocator *allocator, UcxList *list);
+
 /**
  * Inserts an element at the end of the list.
  * 
@@ -175,6 +179,7 @@
  * the newly created list otherwise
  */
 UcxList *ucx_list_append(UcxList *list, void *data);
+
 /**
  * Inserts an element at the end of the list using an UcxAllocator.
  * 
@@ -189,6 +194,7 @@
  * @see ucx_list_append()
  */
 UcxList *ucx_list_append_a(UcxAllocator *allocator, UcxList *list, void *data);
+
 /**
  * Inserts an element at the beginning of the list.
  * 
@@ -204,6 +210,7 @@
  * @return a pointer to the new list head
  */
 UcxList *ucx_list_prepend(UcxList *list, void *data);
+
 /**
  * Inserts an element at the beginning of the list using an UcxAllocator.
  * 
@@ -217,6 +224,7 @@
  * @see ucx_list_prepend()
  */
 UcxList *ucx_list_prepend_a(UcxAllocator *allocator, UcxList *list, void *data);
+
 /**
  * Concatenates two lists.
  * 
@@ -232,6 +240,7 @@
  * returned, otherwise <code>list1</code> is returned
  */
 UcxList *ucx_list_concat(UcxList *list1, UcxList *list2);
+
 /**
  * Returns the first element of a list.
  * 
@@ -243,6 +252,7 @@
  * @return the first element of the list, the specified element is a member of
  */
 UcxList *ucx_list_first(const UcxList *elem);
+
 /**
  * Returns the last element of a list.
  * 
@@ -254,6 +264,7 @@
  * @return the last element of the list, the specified element is a member of
  */
 UcxList *ucx_list_last(const UcxList *elem);
+
 /**
  * Returns the list element at the specified index.
  * 
@@ -263,6 +274,7 @@
  * index is greater than the list size
  */
 UcxList *ucx_list_get(const UcxList *list, int index);
+
 /**
  * Returns the index of an element.
  * 
@@ -272,6 +284,7 @@
  * element
  */
 ssize_t ucx_list_indexof(const UcxList *list, const UcxList *elem);
+
 /**
  * Returns the element count of the list.
  * 
@@ -279,6 +292,7 @@
  * @return the element count
  */
 size_t ucx_list_size(const UcxList *list);
+
 /**
  * Returns the index of an element containing the specified data.
  *
@@ -297,6 +311,7 @@
  * data is not found in this list
  */
 ssize_t ucx_list_find(UcxList *list, void *elem, cmp_func cmpfnc, void *data);
+
 /**
  * Checks, if a list contains a specific element.
  * 
@@ -340,6 +355,7 @@
  * is now empty
  */
 UcxList *ucx_list_remove(UcxList *list, UcxList *element);
+
 /**
  * Removes an element from the list using an UcxAllocator.
  * 
--- a/ucx/logging.c	Fri Aug 16 12:41:30 2013 +0200
+++ b/ucx/logging.c	Sat Aug 17 12:04:04 2013 +0200
@@ -64,7 +64,7 @@
 void ucx_logger_logf(UcxLogger *logger, unsigned int level, const char* file,
         const unsigned int line, const char *format, ...) {
     if (level <= logger->level) {
-        const size_t max = 4096; // estimated maximum message length
+        const size_t max = 4096; // estimated max. message length (documented)
         char msg[max];
         char *text;
         size_t k = 0;
--- a/ucx/logging.h	Fri Aug 16 12:41:30 2013 +0200
+++ b/ucx/logging.h	Sat Aug 17 12:04:04 2013 +0200
@@ -44,14 +44,19 @@
 #endif
 
 /* leave enough space for custom log levels */
+
 /** Log level for error messages. */
 #define UCX_LOGGER_ERROR        0x00
+    
 /** Log level for warning messages. */
 #define UCX_LOGGER_WARN         0x10
+
 /** Log level for information messages. */
 #define UCX_LOGGER_INFO         0x20
+
 /** Log level for debug messages. */
 #define UCX_LOGGER_DEBUG        0x30
+
 /** Log level for trace messages. */
 #define UCX_LOGGER_TRACE        0x40
 
@@ -61,12 +66,14 @@
  * @see UcxLogger.mask
  */
 #define UCX_LOGGER_LEVEL        0x01
+
 /**
  * Output flag for the timestmap.
  * If this flag is set, the log message will contain the timestmap.
  * @see UcxLogger.mask
  */
 #define UCX_LOGGER_TIMESTAMP    0x02
+
 /**
  * Output flag for the source.
  * If this flag is set, the log message will contain the source file and line
@@ -81,24 +88,28 @@
 typedef struct {
     /** The stream this logger writes its messages to.*/
     void *stream;
+
     /**
      * The write function that shall be used.
      * For standard file or stdout loggers this might be standard fwrite
      * (default).
      */
     write_func writer;
+
     /**
      * The date format for timestamp outputs
      * (default: <code>"%F %T %z "</code>).
      * @see UCX_LOGGER_TIMESTAMP
      */
     char *dateformat;
+
     /**
      * The level, this logger operates on.
      * If a log command is issued, the message will only be logged, if the log
      * level of the message is less or equal than the log level of the logger.
      */
     unsigned int level;
+
     /**
      * A configuration mask for automatic output. 
      * For each flag that is set, the logger automatically outputs some extra
@@ -106,6 +117,7 @@
      * See the documentation for the flags for details.
      */
     unsigned int mask;
+
     /**
      * A map of valid log levels for this logger.
      * 
@@ -128,6 +140,7 @@
  * @return a new logger object
  */
 UcxLogger *ucx_logger_new(void *stream, unsigned int level, unsigned int mask);
+
 /**
  * Destroys the logger.
  * 
@@ -148,6 +161,9 @@
  * 
  * <code>[LEVEL] [TIMESTAMP] [SOURCEFILE]:[LINENO] message</code>
  * 
+ * <b>Attention:</b> the message (including automatically generated information)
+ * <b>MUST NOT</b> exceed the size of 4 KB.
+ * 
  * @param logger the logger to use
  * @param level the level to log on
  * @param file information about the source file
@@ -177,6 +193,7 @@
  */
 #define ucx_logger_error(logger, ...) \
     ucx_logger_log(logger, UCX_LOGGER_ERROR, __VA_ARGS__)
+
 /**
  * Shortcut for logging an information message.
  * @param logger the logger to use
@@ -185,6 +202,7 @@
  */
 #define ucx_logger_info(logger, ...) \
     ucx_logger_log(logger, UCX_LOGGER_INFO, __VA_ARGS__)
+
 /**
  * Shortcut for logging a warning message.
  * @param logger the logger to use
@@ -193,6 +211,7 @@
  */
 #define ucx_logger_warn(logger, ...) \
     ucx_logger_log(logger, UCX_LOGGER_WARN, __VA_ARGS__)
+
 /**
  * Shortcut for logging a debug message.
  * @param logger the logger to use
@@ -201,6 +220,7 @@
  */
 #define ucx_logger_debug(logger, ...) \
     ucx_logger_log(logger, UCX_LOGGER_DEBUG, __VA_ARGS__)
+
 /**
  * Shortcut for logging a trace message.
  * @param logger the logger to use
--- a/ucx/map.c	Fri Aug 16 12:41:30 2013 +0200
+++ b/ucx/map.c	Sat Aug 17 12:04:04 2013 +0200
@@ -45,7 +45,7 @@
     }
     
     UcxMap *map = (UcxMap*)allocator->malloc(allocator->pool, sizeof(UcxMap));
-    if(map == NULL) {
+    if (!map) {
         return NULL;
     }
     
@@ -89,8 +89,7 @@
     UcxMapIterator i = ucx_map_iterator(from);
     void *value;
     UCX_MAP_FOREACH(key, value, i) {
-        int ret = ucx_map_put(to, i.cur->key, fnc ? fnc(value, data) : value);
-        if(ret != 0) {
+        if (ucx_map_put(to, key, fnc ? fnc(value, data) : value)) {
             return 1;
         }
     }
@@ -100,7 +99,7 @@
 UcxMap *ucx_map_clone(UcxMap *map, copy_func fnc, void *data) {
     size_t bs = (map->count * 5) >> 1;
     UcxMap *newmap = ucx_map_new(bs > map->size ? bs : map->size);
-    if(newmap == NULL) {
+    if (!newmap) {
         return NULL;
     }
     ucx_map_copy(map, newmap, fnc, data);
@@ -121,7 +120,7 @@
                 map->allocator->pool,
                 map->size,
                 sizeof(UcxMapElement*));
-        if(map->map == NULL) {
+        if (!map->map) {
             *map = oldmap;
             return 1;
         }
@@ -137,7 +136,7 @@
 int ucx_map_put(UcxMap *map, UcxKey key, void *data) {
     UcxAllocator *allocator = map->allocator;
     
-    if(key.hash == 0) {
+    if (key.hash == 0) {
         key.hash = ucx_hash((char*)key.data, key.len);
     }
 
@@ -145,16 +144,16 @@
     UcxMapElement *restrict elm = map->map[slot];
     UcxMapElement *restrict prev = NULL;
 
-    while (elm != NULL && elm->key.hash < key.hash) {
+    while (elm && elm->key.hash < key.hash) {
         prev = elm;
         elm = elm->next;
     }
     
-    if (elm == NULL || elm->key.hash != key.hash) {
+    if (!elm || elm->key.hash != key.hash) {
         UcxMapElement *e = (UcxMapElement*)allocator->malloc(
                 allocator->pool,
                 sizeof(UcxMapElement));
-        if(e == NULL) {
+        if (!e) {
             return -1;
         }
         e->key.data = NULL;
@@ -167,9 +166,9 @@
         elm = e;
     }
     
-    if(elm->key.data == NULL) {
+    if (!elm->key.data) {
         void *kd = allocator->malloc(allocator->pool, key.len);
-        if (kd == NULL) {
+        if (!kd) {
             return -1;
         }
         memcpy(kd, key.data, key.len);
@@ -201,6 +200,7 @@
                     } else {
                         map->map[slot] = elm->next;
                     }
+                    map->allocator->free(map->allocator->pool, elm->key.data);
                     map->allocator->free(map->allocator->pool, elm);
                     map->count--;
                 }
@@ -285,31 +285,31 @@
 int ucx_map_iter_next(UcxMapIterator *i, UcxKey *key, void **elm) {
     UcxMapElement *e = i->cur;
     
-    if(e == NULL) {
+    if (e) {
+        e = e->next;
+    } else {
         e = i->map->map[0];
-    } else {
-        e = e->next;
     }
     
-    while(i->index < i->map->size) {
-        if(e != NULL) {
-            if(e->data != NULL) {
+    while (i->index < i->map->size) {
+        if (e) {
+            if (e->data) {
                 i->cur = e;
                 *elm = e->data;
                 *key = e->key;
-                return 0;
+                return 1;
             }
 
             e = e->next;
         } else {
             i->index++;
             
-            if(i->index < i->map->size) {
+            if (i->index < i->map->size) {
                 e = i->map->map[i->index];
             }
         }
     }
     
-    return 1;
+    return 0;
 }
 
--- a/ucx/map.h	Fri Aug 16 12:41:30 2013 +0200
+++ b/ucx/map.h	Sat Aug 17 12:04:04 2013 +0200
@@ -50,36 +50,81 @@
 extern "C" {
 #endif
 
-#define UCX_MAP_FOREACH(key,elm,iter) \
-        for(UcxKey key;ucx_map_iter_next(&iter,&key, (void**)&elm)==0;)
+/**
+ * Loop statement for UCX maps.
+ * 
+ * The <code>key</code> variable is implicitly defined, but the
+ * <code>value</code> variable must be already declared as type information
+ * cannot be inferred.
+ * 
+ * @param key the variable name for the key
+ * @param value the variable name for the value
+ * @param iter an UcxMapIterator
+ * @see ucx_map_iterator()
+ */
+#define UCX_MAP_FOREACH(key,value,iter) \
+        for(UcxKey key;ucx_map_iter_next(&iter,&key, (void**)&value);)
 
+/** Type for the UCX map. @see UcxMap */
 typedef struct UcxMap          UcxMap;
+
+/** Type for a key of an UcxMap. @see UcxKey */
 typedef struct UcxKey          UcxKey;
+
+/** Type for an element of an UcxMap. @see UcxMapElement */
 typedef struct UcxMapElement   UcxMapElement;
+
+/** Type for an iterator over an UcxMap. @see UcxMapIterator */
 typedef struct UcxMapIterator  UcxMapIterator;
 
+/** Structure for the UCX map. */
 struct UcxMap {
+    /** An allocator that is used for the map elements. */
     UcxAllocator  *allocator;
+    /** The array of map element lists. */
     UcxMapElement **map;
+    /** The size of the map is the length of the element list array. */
     size_t        size;
+    /** The count of elements currently stored in this map. */
     size_t        count;
 };
 
+/** Structure for a key of an UcxMap. */
 struct UcxKey {
+    /** The key data. */
     void   *data;
+    /** The length of the key data. */
     size_t len;
+    /** The hash value of the key data. */
     int    hash;
 };
 
+/** Structure for an element of an UcxMap. */
 struct UcxMapElement {
+    /** The value data. */
     void          *data;
+    
+    /** A pointer to the next element in the current list. */
     UcxMapElement *next;
+    
+    /** The corresponding key. */
     UcxKey        key;
 };
 
+/** Structure for an iterator over an UcxMap. */
 struct UcxMapIterator {
+    /** The map to iterate over. */
     UcxMap        *map;
+    
+    /** The current map element. */
     UcxMapElement *cur;
+    
+    /**
+     * The current index of the element list array.
+     * <b>Attention: </b> this is <b>NOT</b> the element index! Do <b>NOT</b>
+     * manually iterate over the map by increasing this index. Use
+     * ucx_map_iter_next().
+     * @see UcxMap.map*/
     size_t        index;
 };
 
@@ -108,14 +153,83 @@
  */
 void ucx_map_free(UcxMap *map);
 
-/* you cannot clone maps with more than 390 mio entries */
+/**
+ * Copies contents from a map to another map using a copy function.
+ * 
+ * <b>Note:</b> The destination map does not need to be empty. However, if it
+ * contains data with keys that are also present in the source map, the contents
+ * are overwritten.
+ * 
+ * @param from the source map
+ * @param to the destination map
+ * @param fnc the copy function or <code>NULL</code> if the pointer address
+ * shall be copied
+ * @param data additional data for the copy function
+ * @return 0 on success or a non-zero value on memory allocation errors
+ */
 int ucx_map_copy(UcxMap *restrict from, UcxMap *restrict to,
         copy_func fnc, void *data);
+
+/**
+ * Clones the map and rehashes if necessary.
+ * 
+ * <b>Note:</b> In contrast to ucx_map_rehash() the load factor is irrelevant.
+ * This function <i>always</i> ensures a new UcxMap.size of at least
+ * 2.5*UcxMap.count.
+ * 
+ * @param map the map to clone
+ * @param fnc the copy function to use or <code>NULL</code> if the new and
+ * the old map shall share the data pointers
+ * @param data additional data for the copy function
+ * @return the cloned map
+ * @see ucx_map_copy()
+ */
 UcxMap *ucx_map_clone(UcxMap *map, copy_func fnc, void *data);
+
+/**
+ * Increases size of the hash map, if necessary.
+ * 
+ * The load value is 0.75*UcxMap.size. If the element count exceeds the load
+ * value, the map needs to be rehashed. Otherwise no action is performed and
+ * this function simply returns 0.
+ * 
+ * The rehashing process ensures, that the UcxMap.size is at least
+ * 2.5*UcxMap.count. So there is enough room for additional elements without
+ * the need of another soon rehashing.
+ * 
+ * You can use this function to dramatically increase access performance.
+ * 
+ * @param map the map to rehash
+ * @return 1, if a memory allocation error occurred, 0 otherwise
+ */
 int ucx_map_rehash(UcxMap *map);
 
-int ucx_map_put(UcxMap *map, UcxKey key, void *data);
+/**
+ * Puts a key/value-pair into the map.
+ * 
+ * @param map the map
+ * @param key the key
+ * @param value the value
+ * @return 0 on success, non-zero value on failure
+ */
+int ucx_map_put(UcxMap *map, UcxKey key, void *value);
+
+/**
+ * Retrieves a value by using a key.
+ * 
+ * @param map the map
+ * @param key the key
+ * @return the value
+ */
 void* ucx_map_get(UcxMap *map, UcxKey key);
+
+/**
+ * Removes a key/value-pair from the map by using the key.
+ * 
+ * @param map the map
+ * @param key the key
+ * @return the removed value
+ */
 void* ucx_map_remove(UcxMap *map, UcxKey key);
 
 /**
@@ -123,84 +237,151 @@
  * @param map the map
  * @param key the key
  * @param value the value
+ * @return 0 on success, non-zero value on failure
  * @see ucx_map_put()
  */
 #define ucx_map_sstr_put(map, key, value) \
     ucx_map_put(map, ucx_key(key.ptr, key.length), (void*)value)
+
 /**
  * Shorthand for putting data with a C string key into the map.
  * @param map the map
  * @param key the key
  * @param value the value
+ * @return 0 on success, non-zero value on failure
  * @see ucx_map_put()
  */
 #define ucx_map_cstr_put(map, key, value) \
     ucx_map_put(map, ucx_key((void*)key, strlen(key)), (void*)value)
+
 /**
  * Shorthand for putting data with an integer key into the map.
  * @param map the map
  * @param key the key
  * @param value the value
+ * @return 0 on success, non-zero value on failure
  * @see ucx_map_put()
  */
 #define ucx_map_int_put(map, key, value) \
     ucx_map_put(map, ucx_key((void*)&key, sizeof(key)), (void*)value)
 
-
 /**
  * Shorthand for getting data from the map with a sstr_t key.
  * @param map the map
  * @param key the key
+ * @return the value
  * @see ucx_map_get()
  */
 #define ucx_map_sstr_get(map, key) \
     ucx_map_get(map, ucx_key(key.ptr, key.length))
+
 /**
  * Shorthand for getting data from the map with a C string key.
+ * @param map the map
+ * @param key the key
+ * @return the value
  * @see ucx_map_get()
  */
 #define ucx_map_cstr_get(map, key) \
     ucx_map_get(map, ucx_key((void*)key, strlen(key)))
+
 /**
  * Shorthand for getting data from the map with an integer key.
  * @param map the map
  * @param key the key
+ * @return the value
  * @see ucx_map_get()
  */
 #define ucx_map_int_get(map, key) \
     ucx_map_get(map, ucx_key((void*)&key, sizeof(int)))
+
 /**
  * Shorthand for removing data from the map with a sstr_t key.
  * @param map the map
  * @param key the key
+ * @return the removed value
  * @see ucx_map_remove()
  */
 #define ucx_map_sstr_remove(map, key) \
     ucx_map_remove(map, ucx_key(key.ptr, key.length))
+
 /**
  * Shorthand for removing data from the map with a C string key.
  * @param map the map
  * @param key the key
+ * @return the removed value
  * @see ucx_map_remove()
  */
 #define ucx_map_cstr_remove(map, key) \
     ucx_map_remove(map, ucx_key((void*)key, strlen(key)))
+
 /**
  * Shorthand for removing data from the map with an integer key.
  * @param map the map
  * @param key the key
+ * @return the removed value
  * @see ucx_map_remove()
  */
 #define ucx_map_int_remove(map, key) \
     ucx_map_remove(map, ucx_key((void*)&key, sizeof(key)))
 
+/**
+ * Creates an UcxKey based on the given data.
+ * 
+ * This function implicitly computes the hash.
+ * 
+ * @param data the data for the key
+ * @param len the length of the data
+ * @return an UcxKey with implicitly computed hash
+ * @see ucx_hash()
+ */
 UcxKey ucx_key(void *data, size_t len);
 
+/**
+ * Computes a murmur hash-2.
+ * 
+ * @param data the data to hash
+ * @param len the length of the data
+ * @return the murmur hash-2 of the data
+ */
 int ucx_hash(const char *data, size_t len);
 
+/**
+ * Creates an iterator for a map.
+ * 
+ * <b>Note:</b> An UcxMapIterator iterates over all elements in all element
+ * lists successively. Therefore the order highly depends on the key hashes and
+ * may vary under different map sizes. So generally you may <b>NOT</b> rely on
+ * the iteration order.
+ * 
+ * <b>Note:</b> The iterator is <b>NOT</b> initialized. You need to call
+ * ucx_map_iter_next() at least once before accessing any information. However,
+ * it is not recommended to access the fields of an UcxMapIterator directly.
+ * 
+ * @param map the map to create the iterator for
+ * @return an iterator initialized on the first element of the
+ * first element list
+ * @see ucx_map_iter_next()
+ */
 UcxMapIterator ucx_map_iterator(UcxMap *map);
 
-int ucx_map_iter_next(UcxMapIterator *i, UcxKey *key, void **elm);
+/**
+ * Proceeds to the next element of the map (if any).
+ * 
+ * Subsequent calls on the same iterator proceed to the next element and
+ * store the key/value-pair into the memory specified as arguments of this
+ * function.
+ * 
+ * If no further elements are found, this function returns zero and leaves the
+ * last found key/value-pair in memory.
+ * 
+ * @param iterator the iterator to use
+ * @param key a pointer to the memory where to store the key
+ * @param value a pointer to the memory where to store the value
+ * @return 1, if another element was found, 0 if all elements has been processed
+ * @see ucx_map_iterator()
+ */
+int ucx_map_iter_next(UcxMapIterator *iterator, UcxKey *key, void **value);
 
 
 #ifdef	__cplusplus
--- a/ucx/mempool.c	Fri Aug 16 12:41:30 2013 +0200
+++ b/ucx/mempool.c	Sat Aug 17 12:04:04 2013 +0200
@@ -36,13 +36,23 @@
 
 #include "mempool.h"
 
+/** Capsule for destructible memory chunks. */
 typedef struct {
+    /** The destructor for the memory chunk. */
     ucx_destructor destructor;
+    /**
+     * First byte of the memory chunk.
+     * Note, that the address <code>&amp;c</code> is also the address
+     * of the whole memory chunk.
+     */
     char c;
 } ucx_memchunk;
 
+/** Capsule for data and its destructor. */
 typedef struct {
+    /** The destructor for the data. */
     ucx_destructor destructor;
+    /** A pointer to the data. */
     void           *ptr;
 } ucx_regdestr;
 
@@ -80,16 +90,18 @@
 }
 
 void *ucx_mempool_malloc(UcxMempool *pool, size_t n) {
+    if (pool->ndata >= pool->size) {
+        // The hard coded 16 is documented for this function and ucx_mempool_new
+        if (ucx_mempool_chcap(pool, pool->size + 16) == EXIT_FAILURE) {
+            return NULL;
+        }
+    }
+
     ucx_memchunk *mem = (ucx_memchunk*)malloc(sizeof(ucx_destructor) + n);
     if (!mem) {
         return NULL;
     }
 
-    if (pool->ndata >= pool->size) {
-        // The hard coded 16 is documented for this function and ucx_mempool_new
-        ucx_mempool_chcap(pool, pool->size + 16);
-     }
-
     mem->destructor = NULL;
     pool->data[pool->ndata] = mem;
     pool->ndata++;
@@ -121,7 +133,7 @@
         }
         fprintf(stderr, "FATAL: 0x%08" PRIxPTR" not in mpool 0x%08" PRIxPTR"\n",
           (intptr_t)ptr, (intptr_t)pool);
-        exit(1);
+        exit(EXIT_FAILURE);
     } else {
         return newm + sizeof(ucx_destructor);
     }
@@ -132,12 +144,13 @@
     for(size_t i=0 ; i<pool->ndata ; i++) {
         if(chunk == pool->data[i]) {
             if(chunk->destructor != NULL) {
-                chunk->destructor(&chunk->c);
+                chunk->destructor(&(chunk->c));
             }
             free(chunk);
             size_t last_index = pool->ndata - 1;
             if(i != last_index) {
                 pool->data[i] = pool->data[last_index];
+                pool->data[last_index] = NULL;
             }
             pool->ndata--;
             return;
--- a/ucx/mempool.h	Fri Aug 16 12:41:30 2013 +0200
+++ b/ucx/mempool.h	Sat Aug 17 12:04:04 2013 +0200
@@ -59,8 +59,10 @@
 typedef struct {
     /** List of pointers to pooled memory. */
     void   **data;
+    
     /** Count of pooled memory items. */
     size_t ndata;
+    
     /** Memory pool size. */
     size_t size;
 } UcxMempool;
@@ -92,6 +94,19 @@
 int ucx_mempool_chcap(UcxMempool *pool, size_t newcap);
 
 /**
+ * Changes the pool size to the next smallest multiple of 16.
+ * 
+ * You may use this macro, to reduce the pool size after freeing
+ * many pooled memory items.
+ * 
+ * @param pool the pool to clamp
+ * @return <code>EXIT_SUCCESS</code> on success or
+ * <code>EXIT_FAILURE</code> on failure
+ */
+#define ucx_mempool_clamp(pool) ucx_mempool_chcap(pool, \
+        (pool->ndata & ~0xF)+0x10)
+
+/**
  * Allocates pooled memory.
  * 
  * @param pool the memory pool
@@ -112,9 +127,15 @@
  * @see ucx_allocator_calloc()
  */
 void *ucx_mempool_calloc(UcxMempool *pool, size_t nelem, size_t elsize);
+
 /**
  * Reallocates pooled memory.
  * 
+ * If the memory to be reallocated is not contained by the specified pool, this
+ * function will possibly fail. In case the memory had to be moved to another
+ * location, this function will print out a message to <code>stderr</code>
+ * and exit the program with error code <code>EXIT_FAILURE</code>.
+ * 
  * @param pool the memory pool
  * @param ptr a pointer to the memory that shall be reallocated
  * @param n the new size of the memory
@@ -122,6 +143,7 @@
  * @see ucx_allocator_realloc()
  */
 void *ucx_mempool_realloc(UcxMempool *pool, void *ptr, size_t n);
+
 /**
  * Frees pooled memory.
  * 
--- a/ucx/properties.h	Fri Aug 16 12:41:30 2013 +0200
+++ b/ucx/properties.h	Sat Aug 17 12:04:04 2013 +0200
@@ -56,52 +56,62 @@
      * Automatically set by calls to ucx_properties_fill().
      */
     char   *buffer;
+    
     /**
      * Length of the input buffer (don't set manually).
      * Automatically set by calls to ucx_properties_fill().
      */
     size_t buflen;
+    
     /**
      * Current buffer position (don't set manually).
      * Used by ucx_properties_next().
      */
     size_t pos;
+    
     /**
      * Internal temporary buffer (don't set manually).
      * Used by ucx_properties_next().
      */
     char   *tmp;
+    
     /**
      * Internal temporary buffer length (don't set manually).
      * Used by ucx_properties_next().
      */
     size_t tmplen;
+    
     /**
      * Internal temporary buffer capacity (don't set manually).
      * Used by ucx_properties_next().
      */
     size_t tmpcap;
+    
     /**
      * Parser error code.
      * This is always 0 on success and a nonzero value on syntax errors.
      * The value is set by ucx_properties_next().
      */
     int    error;
+    
     /**
      * The delimiter that shall be used.
      * This is '=' by default.
      */
     char   delimiter;
+    
     /**
      * The first comment character.
      * This is '#' by default.
      */
     char   comment1;
+    
     /**
      * The second comment character.
      * This is not set by default.
      */
     char   comment2;
+    
     /**
      * The third comment character.
      * This is not set by default.
@@ -115,11 +125,13 @@
  * @return a pointer to the new UcxProperties object
  */
 UcxProperties *ucx_properties_new();
+
 /**
  * Destroys an UcxProperties object.
  * @param prop the UcxProperties object to destroy
  */
 void ucx_properties_free(UcxProperties *prop);
+
 /**
  * Sets the input buffer for the properties parser.
  * 
@@ -136,6 +148,7 @@
  * @see ucx_properties2map()
  */
 void ucx_properties_fill(UcxProperties *prop, char *buf, size_t len);
+
 /**
  * Retrieves the next key/value-pair.
  * 
@@ -155,6 +168,7 @@
  * @see ucx_properties_fill()
  */
 int ucx_properties_next(UcxProperties *prop, sstr_t *name, sstr_t *value);
+
 /**
  * Retrieves all available key/value-pairs and puts them into an UcxMap.
  * 
@@ -184,6 +198,7 @@
  * @see ucx_properties2map()
  */
 int ucx_properties_load(UcxMap *map, FILE *file);
+
 /**
  * Stores an UcxMap to a file.
  * 
--- a/ucx/string.c	Fri Aug 16 12:41:30 2013 +0200
+++ b/ucx/string.c	Sat Aug 17 12:04:04 2013 +0200
@@ -252,3 +252,34 @@
     
     return newstr;
 }
+
+int sstrprefix(sstr_t string, sstr_t prefix) {
+    if (string.length == 0) {
+        return prefix.length == 0;
+    }
+    if (prefix.length == 0) {
+        return 1;
+    }
+    
+    if (prefix.length > string.length) {
+        return 0;
+    } else {
+        return memcmp(string.ptr, prefix.ptr, prefix.length) == 0;
+    }
+}
+
+int sstrsuffix(sstr_t string, sstr_t suffix) {
+    if (string.length == 0) {
+        return suffix.length == 0;
+    }
+    if (suffix.length == 0) {
+        return 1;
+    }
+    
+    if (suffix.length > string.length) {
+        return 0;
+    } else {
+        return memcmp(string.ptr+string.length-suffix.length,
+            suffix.ptr, suffix.length) == 0;
+    }
+}
--- a/ucx/string.h	Fri Aug 16 12:41:30 2013 +0200
+++ b/ucx/string.h	Sat Aug 17 12:04:04 2013 +0200
@@ -54,6 +54,7 @@
 
 /** Shortcut for a <code>sstr_t struct</code> literal. */
 #define ST(s) { (char*)s, sizeof(s)-1 }
+
 /** Shortcut for the conversion of a C string to a <code>sstr_t</code>. */
 #define S(s) sstrn((char*)s, sizeof(s)-1)
 
@@ -338,6 +339,22 @@
  */
 sstr_t sstrtrim(sstr_t string);
 
+/**
+ * Checks, if a string has a specific prefix.
+ * @param string the string to check
+ * @param prefix the prefix the string should have
+ * @return 1, if and only if the string has the specified prefix, 0 otherwise
+ */
+int sstrprefix(sstr_t string, sstr_t prefix);
+
+/**
+ * Checks, if a string has a specific suffix.
+ * @param string the string to check
+ * @param suffix the suffix the string should have
+ * @return 1, if and only if the string has the specified suffix, 0 otherwise
+ */
+int sstrsuffix(sstr_t string, sstr_t suffix);
+
 #ifdef	__cplusplus
 }
 #endif
--- a/ucx/test.c	Fri Aug 16 12:41:30 2013 +0200
+++ b/ucx/test.c	Sat Aug 17 12:04:04 2013 +0200
@@ -28,12 +28,6 @@
 
 #include "test.h"
 
-    
-struct UcxTestList{
-    UcxTest test;
-    UcxTestList *next;
-};
-
 UcxTestSuite* ucx_test_suite_new() {
     UcxTestSuite* suite = (UcxTestSuite*) malloc(sizeof(UcxTestSuite));
     if (suite != NULL) {
--- a/ucx/test.h	Fri Aug 16 12:41:30 2013 +0200
+++ b/ucx/test.h	Sat Aug 17 12:04:04 2013 +0200
@@ -81,6 +81,7 @@
 #endif
 
 #ifndef __FUNCTION__
+
 /**
  * Alias for the <code>__func__</code> preprocessor macro.
  * Some compilers use <code>__func__</code> and others use __FUNC__.
@@ -90,21 +91,36 @@
 #define __FUNCTION__ __func__
 #endif
 
+/** Type for the UcxTestSuite. */
+typedef struct UcxTestSuite UcxTestSuite;
+
+/** Pointer to a test function. */
+typedef void(*UcxTest)(UcxTestSuite*,FILE*);
+
 /** Type for the internal list of test cases. */
 typedef struct UcxTestList UcxTestList;
-/** Type for the UcxTestSuite. */
-typedef struct UcxTestSuite UcxTestSuite;
-/** Pointer to a test function. */
-typedef void(*UcxTest)(UcxTestSuite*,FILE*);
+
+/** Structure for the internal list of test cases. */
+struct UcxTestList {
+    
+    /** Test case. */
+    UcxTest test;
+    
+    /** Pointer to the next list element. */
+    UcxTestList *next;
+};
 
 /**
  * A test suite containing multiple test cases.
  */
 struct UcxTestSuite {
+    
     /** The number of successful tests after the suite has been run. */
     unsigned int success;
+    
     /** The number of failed tests after the suite has been run. */
     unsigned int failure;
+    
     /**
      * Internal list of test cases.
      * Use ucx_test_register() to add tests to this list.
@@ -117,9 +133,10 @@
  * @return a new test suite
  */
 UcxTestSuite* ucx_test_suite_new();
+
 /**
  * Destroys a test suite.
- * @param the test suite to destroy
+ * @param suite the test suite to destroy
  */
 void ucx_test_suite_free(UcxTestSuite* suite);
 
@@ -132,6 +149,7 @@
  * <code>EXIT_FAILURE</code> on failure
  */
 int ucx_test_register(UcxTestSuite* suite, UcxTest test);
+
 /**
  * Runs a test suite and writes the test log to the specified stream.
  * @param suite the test suite to run
--- a/ucx/utils.c	Fri Aug 16 12:41:30 2013 +0200
+++ b/ucx/utils.c	Sat Aug 17 12:04:04 2013 +0200
@@ -27,7 +27,10 @@
  */
 
 #include "utils.h"
-#include "math.h"
+#include <math.h>
+#include <stdio.h>
+#include <limits.h>
+#include <errno.h>
 
 /* COPY FUCNTIONS */
 void* ucx_strcpy(void* s, void* data) {
@@ -45,7 +48,37 @@
     return cpy;
 }
 
-/* COMPARE FUNCTION */
+size_t ucx_stream_copy(void *src, void *dest, read_func readfnc,
+        write_func writefnc, char* buf, size_t bufsize, size_t n) {
+    if(n == 0 || bufsize == 0) {
+        return 0;
+    }
+    
+    size_t ncp = 0;
+    if (!buf) {
+        buf = (char*)malloc(bufsize);
+        if(buf == NULL) {
+            return 0;
+        }
+    }
+    
+    size_t r;
+    size_t rn = bufsize > n ? n : bufsize;
+    while((r = readfnc(buf, 1, rn, src)) != 0) {
+        r = writefnc(buf, 1, r, dest);
+        ncp += r;
+        n -= r;
+        rn = bufsize > n ? n : bufsize;
+        if(r == 0 || n == 0) {
+            break;
+        }
+    }
+    
+    free(buf);
+    return ncp;
+}
+
+/* COMPARE FUNCTIONS */
 
 int ucx_strcmp(void *s1, void *s2, void *data) {
     return strcmp((char*)s1, (char*)s2);
@@ -98,3 +131,86 @@
 int ucx_memcmp(void *ptr1, void *ptr2, void *n) {
     return memcmp(ptr1, ptr2, *((size_t*)n));
 }
+
+/* PRINTF FUNCTIONS */
+
+#define UCX_PRINTF_BUFSIZE 256
+
+int ucx_fprintf(void *stream, write_func wfc, const char *fmt, ...) {
+    va_list ap;
+    int ret;
+    va_start(ap, fmt);
+    ret = ucx_vfprintf(stream, wfc, fmt, ap);
+    va_end(ap);
+    return ret;
+}
+
+int ucx_vfprintf(void *stream, write_func wfc, const char *fmt, va_list ap) {
+    char buf[UCX_PRINTF_BUFSIZE];
+    va_list ap2;
+    va_copy(ap2, ap);
+    int ret = vsnprintf(buf, UCX_PRINTF_BUFSIZE, fmt, ap);
+    if (ret < 0) {
+        return ret;
+    } else if (ret < UCX_PRINTF_BUFSIZE) {
+        return (int)wfc(buf, 1, ret, stream);
+    } else {
+        if (ret == INT_MAX) {
+            errno = ENOMEM;
+            return -1;
+        }
+        
+        int len = ret + 1;
+        char *newbuf = (char*)malloc(len);
+        if (!newbuf) {
+            return -1;
+        }
+        
+        ret = vsnprintf(newbuf, len, fmt, ap2);
+        va_end(ap2);
+        if (ret > 0) {
+            ret = (int)wfc(newbuf, 1, ret, stream);
+        }
+        free(newbuf);
+    }
+    return ret;
+}
+
+sstr_t ucx_asprintf(UcxAllocator *allocator, const char *fmt, ...) {
+    va_list ap;
+    sstr_t ret;
+    va_start(ap, fmt);
+    ret = ucx_vasprintf(allocator, fmt, ap);
+    va_end(ap);
+    return ret;
+}
+
+sstr_t ucx_vasprintf(UcxAllocator *a, const char *fmt, va_list ap) {
+    sstr_t s;
+    s.ptr = NULL;
+    s.length = 0;
+    va_list ap2;
+    va_copy(ap2, ap);
+    char buf[UCX_PRINTF_BUFSIZE];
+    int ret = vsnprintf(buf, UCX_PRINTF_BUFSIZE, fmt, ap);
+    if (ret > 0 && ret < UCX_PRINTF_BUFSIZE) {
+        s.ptr = (char*)a->malloc(a->pool, ret + 1);
+        s.length = (size_t)ret;
+        memcpy(s.ptr, buf, ret);
+        s.ptr[s.length] = '\0';
+    } else if (ret == INT_MAX) {
+        errno = ENOMEM;
+    } else  {
+        int len = ret + 1;
+        s.ptr = (char*)a->malloc(a->pool, len);
+        ret = vsnprintf(s.ptr, len, fmt, ap2);
+        va_end(ap2);
+        if (ret < 0) {
+            free(s.ptr);
+            s.ptr = NULL;
+        } else {
+            s.length = (size_t)ret;
+        }
+    }
+    return s;
+}
--- a/ucx/utils.h	Fri Aug 16 12:41:30 2013 +0200
+++ b/ucx/utils.h	Sat Aug 17 12:04:04 2013 +0200
@@ -29,7 +29,7 @@
 /**
  * @file utils.h
  * 
- * Common utilities like compare and copy functions.
+ * Compare, copy and printf functions.
  * 
  * @author Mike Becker
  * @author Olaf Wintermann
@@ -43,7 +43,11 @@
 #endif
 
 #include "ucx.h"
+#include "string.h"
+#include "allocator.h"
+#include <stdint.h>
 #include <string.h>
+#include <stdarg.h>
 
 /**
  * Copies a string.
@@ -62,6 +66,50 @@
  */
 void *ucx_memcpy(void *m, void *n);
 
+
+/**
+ * Reads data from a stream and writes it to another stream.
+ * 
+ * @param src the source stream
+ * @param dest the destination stream
+ * @param rfnc the read function
+ * @param wfnc the write function
+ * @param buf a pointer to the copy buffer or <code>NULL</code> if a buffer
+ * shall be implicitly created on the heap
+ * @param bufsize the size of the copy buffer - if <code>NULL</code> was
+ * provided for <code>buf</code>, this is the size of the buffer that shall be
+ * implicitly created
+ * @param n the maximum number of bytes that shall be copied
+ * @return the total number of bytes copied
+  */
+size_t ucx_stream_copy(void *src, void *dest, read_func rfnc, write_func wfnc,
+        char* buf, size_t bufsize, size_t n);
+
+/**
+ * Shorthand for ucx_stream_copy using the default copy buffer.
+ * 
+ * @param src the source stream
+ * @param dest the destination stream
+ * @param rfnc the read function
+ * @param wfnc the write function
+ * @return total number of bytes copied
+ */
+#define ucx_stream_hcopy(src,dest,rfnc,wfnc) ucx_stream_copy(\
+        src, dest, (read_func)rfnc, (write_func)wfnc, NULL, 0x100, SIZE_MAX)
+
+/**
+ * Shorthand for ucx_stream_copy using the default copy buffer and a copy limit.
+ * 
+ * @param src the source stream
+ * @param dest the destination stream
+ * @param rfnc the read function
+ * @param wfnc the write function
+ * @param n maximum number of bytes that shall be copied
+ * @return total number of bytes copied
+ */
+#define ucx_stream_ncopy(src,dest,rfnc,wfnc, n) ucx_stream_copy(\
+        src, dest, (read_func)rfnc, (write_func)wfnc, NULL, 0x100, n)
+
 /**
  * Wraps the strcmp function.
  * @param s1 string one
@@ -88,14 +136,13 @@
  * @return -1, if *i1 is less than *i2, 0 if both are equal,
  * 1 if *i1 is greater than *i2
  */
-
 int ucx_intcmp(void *i1, void *i2, void *data);
 
 /**
  * Compares two real numbers of type float.
  * @param f1 pointer to float one
  * @param f2 pointer to float two
- * @param if provided: a pointer to precision (default: 1e-6f)
+ * @param data if provided: a pointer to precision (default: 1e-6f)
  * @return -1, if *f1 is less than *f2, 0 if both are equal,
  * 1 if *f1 is greater than *f2
  */
@@ -104,13 +151,12 @@
 
 /**
  * Compares two real numbers of type double.
- * @param f1 pointer to double one
- * @param f2 pointer to double two
-* @param if provided: a pointer to precision (default: 1e-14)
+ * @param d1 pointer to double one
+ * @param d2 pointer to double two
+ * @param data if provided: a pointer to precision (default: 1e-14)
  * @return -1, if *d1 is less than *d2, 0 if both are equal,
  * 1 if *d1 is greater than *d2
  */
-
 int ucx_doublecmp(void *d1, void *d2, void *data);
 
 /**
@@ -132,6 +178,70 @@
  */
 int ucx_memcmp(void *ptr1, void *ptr2, void *n);
 
+/**
+ * A <code>printf()</code> like function which writes the output to a stream by
+ * using a write_func().
+ * @param stream the stream the data is written to
+ * @param wfc the write function
+ * @param fmt format string
+ * @param ... additional arguments
+ * @return the total number of bytes written
+ */
+int ucx_fprintf(void *stream, write_func wfc, const char *fmt, ...);
+
+/**
+ * <code>va_list</code> version of ucx_fprintf().
+ * @param stream the stream the data is written to
+ * @param wfc the write function
+ * @param fmt format string
+ * @param ap argument list
+ * @return the total number of bytes written
+ * @see ucx_fprintf()
+ */
+int ucx_vfprintf(void *stream, write_func wfc, const char *fmt, va_list ap);
+
+/**
+ * A <code>printf()</code> like function which allocates space for a sstr_t
+ * the result is written to.
+ * 
+ * <b>Attention</b>: The sstr_t data is allocated with the allocators
+ * ucx_allocator_malloc() function. So it is implementation dependent, if
+ * the returned sstr_t.ptr pointer must be passed to the allocators
+ * ucx_allocator_free() function manually.
+ * 
+ * <b>Note</b>: The sstr_t.ptr of the return value will <i>always</i> be
+ * <code>NULL</code>-terminated.
+ * 
+ * @param allocator the UcxAllocator used for allocating the result sstr_t
+ * @param fmt format string
+ * @param ... additional arguments
+ * @return a sstr_t containing the formatted string
+ */
+sstr_t ucx_asprintf(UcxAllocator *allocator, const char *fmt, ...);
+
+/**
+ * <code>va_list</code> version of ucx_asprintf().
+ * 
+ * @param allocator the UcxAllocator used for allocating the result sstr_t
+ * @param fmt format string
+ * @param ap argument list
+ * @return a sstr_t containing the formatted string
+ * @see ucx_asprintf()
+ */
+sstr_t ucx_vasprintf(UcxAllocator *allocator, const char *fmt, va_list ap);
+
+/**
+ * A <code>printf()</code> like function which writes the output to an
+ * UcxBuffer.
+ * 
+ * @param buffer the buffer the data is written to
+ * @param ... format string and additional arguments
+ * @return the total number of bytes written
+ * @see ucx_fprintf()
+ */
+#define ucx_bprintf(buffer, ...) ucx_fprintf((UcxBuffer*)buffer, \
+        (write_func)ucx_buffer_write, __VA_ARGS__)
+
 #ifdef	__cplusplus
 }
 #endif

mercurial