Repository: celix
Updated Branches:
  refs/heads/feature/CELIX-417-cmake-refactor [created] a1c308879


http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/utils/src/linked_list_iterator.c
----------------------------------------------------------------------
diff --git a/utils/src/linked_list_iterator.c b/utils/src/linked_list_iterator.c
new file mode 100644
index 0000000..dc0e5c4
--- /dev/null
+++ b/utils/src/linked_list_iterator.c
@@ -0,0 +1,153 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you 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.
+ */
+/*
+ * linked_list_iterator.c
+ *
+ *  \date       Jul 16, 2010
+ *  \author            <a href="mailto:[email protected]";>Apache Celix 
Project Team</a>
+ *  \copyright Apache License, Version 2.0
+ */
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "linked_list_iterator.h"
+#include "linked_list_private.h"
+
+struct linkedListIterator {
+       linked_list_entry_pt lastReturned;
+       linked_list_entry_pt next;
+       int nextIndex;
+       linked_list_pt list;
+       int expectedModificationCount;
+};
+
+linked_list_iterator_pt linkedListIterator_create(linked_list_pt list, 
unsigned int index) {
+       linked_list_iterator_pt iterator;
+       if (index > list->size) {
+               return NULL;
+       }
+       iterator = (linked_list_iterator_pt) malloc(sizeof(*iterator));
+       iterator->lastReturned = list->header;
+       iterator->list = list;
+       iterator->expectedModificationCount = list->modificationCount;
+       if (index < (list->size >> 1)) {
+               iterator->next = iterator->list->header->next;
+               for (iterator->nextIndex = 0; iterator->nextIndex < index; 
iterator->nextIndex++) {
+                       iterator->next = iterator->next->next;
+               }
+       } else {
+               iterator->next = list->header;
+               for (iterator->nextIndex = list->size; iterator->nextIndex > 
index; iterator->nextIndex--) {
+                       iterator->next = iterator->next->previous;
+               }
+       }
+       return iterator;
+}
+
+void linkedListIterator_destroy(linked_list_iterator_pt iterator) {
+       iterator->expectedModificationCount = 0;
+       iterator->lastReturned = NULL;
+       iterator->list = NULL;
+       iterator->next = NULL;
+       iterator->nextIndex = 0;
+       free(iterator);
+}
+
+bool linkedListIterator_hasNext(linked_list_iterator_pt iterator) {
+       return iterator->nextIndex != iterator->list->size;
+}
+
+void * linkedListIterator_next(linked_list_iterator_pt iterator) {
+       if (iterator->list->modificationCount != 
iterator->expectedModificationCount) {
+               return NULL;
+       }
+       if (iterator->nextIndex == iterator->list->size) {
+               return NULL;
+       }
+       iterator->lastReturned = iterator->next;
+       iterator->next = iterator->next->next;
+       iterator->nextIndex++;
+       return iterator->lastReturned->element;
+}
+
+bool linkedListIterator_hasPrevious(linked_list_iterator_pt iterator) {
+       return iterator->nextIndex != 0;
+}
+
+void * linkedListIterator_previous(linked_list_iterator_pt iterator) {
+       if (iterator->nextIndex == 0) {
+               return NULL;
+       }
+
+       iterator->lastReturned = iterator->next = iterator->next->previous;
+       iterator->nextIndex--;
+
+       if (iterator->list->modificationCount != 
iterator->expectedModificationCount) {
+               return NULL;
+       }
+
+       return iterator->lastReturned->element;
+}
+
+int linkedListIterator_nextIndex(linked_list_iterator_pt iterator) {
+       return iterator->nextIndex;
+}
+
+int linkedListIterator_previousIndex(linked_list_iterator_pt iterator) {
+       return iterator->nextIndex-1;
+}
+
+void linkedListIterator_remove(linked_list_iterator_pt iterator) {
+       linked_list_entry_pt lastNext;
+       if (iterator->list->modificationCount != 
iterator->expectedModificationCount) {
+               return;
+       }
+       lastNext = iterator->lastReturned->next;
+       if (linkedList_removeEntry(iterator->list, iterator->lastReturned) == 
NULL) {
+               return;
+       }
+       if (iterator->next == iterator->lastReturned) {
+               iterator->next = lastNext;
+       } else {
+               iterator->nextIndex--;
+       }
+       iterator->lastReturned = iterator->list->header;
+       iterator->expectedModificationCount++;
+}
+
+void linkedListIterator_set(linked_list_iterator_pt iterator, void * element) {
+       if (iterator->lastReturned == iterator->list->header) {
+               return;
+       }
+       if (iterator->list->modificationCount != 
iterator->expectedModificationCount) {
+               return;
+       }
+       iterator->lastReturned->element = element;
+}
+
+void linkedListIterator_add(linked_list_iterator_pt iterator, void * element) {
+       if (iterator->list->modificationCount != 
iterator->expectedModificationCount) {
+               return;
+       }
+       iterator->lastReturned = iterator->list->header;
+       linkedList_addBefore(iterator->list, element, iterator->next);
+       iterator->nextIndex++;
+       iterator->expectedModificationCount++;
+}
+

http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/utils/src/linked_list_private.h
----------------------------------------------------------------------
diff --git a/utils/src/linked_list_private.h b/utils/src/linked_list_private.h
new file mode 100644
index 0000000..dcb0a46
--- /dev/null
+++ b/utils/src/linked_list_private.h
@@ -0,0 +1,44 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you 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.
+ */
+/*
+ * linked_list_private.h
+ *
+ *  \date       Jul 16, 2010
+ *  \author            <a href="mailto:[email protected]";>Apache Celix 
Project Team</a>
+ *  \copyright Apache License, Version 2.0
+ */
+
+#ifndef LINKED_LIST_PRIVATE_H_
+#define LINKED_LIST_PRIVATE_H_
+
+#include "linked_list.h"
+
+struct linked_list_entry {
+       void * element;
+       struct linked_list_entry * next;
+       struct linked_list_entry * previous;
+};
+
+struct linked_list {
+       linked_list_entry_pt header;
+       size_t size;
+       int modificationCount;
+};
+
+#endif /* LINKED_LIST_PRIVATE_H_ */

http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/utils/src/memstream/fmemopen.c
----------------------------------------------------------------------
diff --git a/utils/src/memstream/fmemopen.c b/utils/src/memstream/fmemopen.c
new file mode 100644
index 0000000..cb1b0c0
--- /dev/null
+++ b/utils/src/memstream/fmemopen.c
@@ -0,0 +1,76 @@
+
+/*
+ * fmem.c : fmemopen() on top of BSD's funopen()
+ * 20081017 AF
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+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);
+}

http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/utils/src/memstream/open_memstream.c
----------------------------------------------------------------------
diff --git a/utils/src/memstream/open_memstream.c 
b/utils/src/memstream/open_memstream.c
new file mode 100644
index 0000000..6bc4f01
--- /dev/null
+++ b/utils/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/a1c30887/utils/src/properties.c
----------------------------------------------------------------------
diff --git a/utils/src/properties.c b/utils/src/properties.c
new file mode 100644
index 0000000..0bd6dc3
--- /dev/null
+++ b/utils/src/properties.c
@@ -0,0 +1,302 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you 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.
+ */
+/*
+ * properties.c
+ *
+ *  \date       Apr 27, 2010
+ *  \author            <a href="mailto:[email protected]";>Apache Celix 
Project Team</a>
+ *  \copyright Apache License, Version 2.0
+ */
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include "celixbool.h"
+#include "properties.h"
+#include "utils.h"
+
+#define MALLOC_BLOCK_SIZE              5
+
+static void parseLine(const char* line, properties_pt props);
+
+properties_pt properties_create(void) {
+       return hashMap_create(utils_stringHash, utils_stringHash, 
utils_stringEquals, utils_stringEquals);
+}
+
+void properties_destroy(properties_pt properties) {
+       hash_map_iterator_pt iter = hashMapIterator_create(properties);
+       while (hashMapIterator_hasNext(iter)) {
+               hash_map_entry_pt entry = hashMapIterator_nextEntry(iter);
+               free(hashMapEntry_getKey(entry));
+               free(hashMapEntry_getValue(entry));
+       }
+       hashMapIterator_destroy(iter);
+       hashMap_destroy(properties, false, false);
+}
+
+properties_pt properties_load(const char* filename) {
+       FILE *file = fopen(filename, "r");
+       if(file==NULL){
+               return NULL;
+       }
+       properties_pt props = properties_loadWithStream(file);
+       fclose(file);
+       return props;
+}
+
+properties_pt properties_loadWithStream(FILE *file) {
+       properties_pt props = NULL;
+
+
+       if (file != NULL ) {
+               char *saveptr;
+               char *filebuffer = NULL;
+               char *line = NULL;
+               size_t file_size = 0;
+
+               props = properties_create();
+               fseek(file, 0, SEEK_END);
+               file_size = ftell(file);
+               fseek(file, 0, SEEK_SET);
+
+               if(file_size > 0){
+                       filebuffer = calloc(file_size + 1, sizeof(char));
+                       if(filebuffer) {
+                               size_t rs = fread(filebuffer, sizeof(char), 
file_size, file);
+                               if(rs != file_size){
+                                       fprintf(stderr,"fread read only %lu 
bytes out of %lu\n",rs,file_size);
+                               }
+                               filebuffer[file_size]='\0';
+                               line = strtok_r(filebuffer, "\n", &saveptr);
+                               while ( line != NULL ) {
+                                       parseLine(line, props);
+                                       line = strtok_r(NULL, "\n", &saveptr);
+                               }
+                               free(filebuffer);
+                       }
+               }
+       }
+
+       return props;
+}
+
+
+/**
+ * Header is ignored for now, cannot handle comments yet
+ */
+void properties_store(properties_pt properties, const char* filename, const 
char* header) {
+       FILE *file = fopen ( filename, "w+" );
+       char *str;
+
+       if (file != NULL) {
+               if (hashMap_size(properties) > 0) {
+                       hash_map_iterator_pt iterator = 
hashMapIterator_create(properties);
+                       while (hashMapIterator_hasNext(iterator)) {
+                               hash_map_entry_pt entry = 
hashMapIterator_nextEntry(iterator);
+                               str = hashMapEntry_getKey(entry);
+                               for (int i = 0; i < strlen(str); i += 1) {
+                                       if (str[i] == '#' || str[i] == '!' || 
str[i] == '=' || str[i] == ':') {
+                                               fputc('\\', file);
+                                       }
+                                       fputc(str[i], file);
+                               }
+
+                               fputc('=', file);
+
+                               str = hashMapEntry_getValue(entry);
+                               for (int i = 0; i < strlen(str); i += 1) {
+                                       if (str[i] == '#' || str[i] == '!' || 
str[i] == '=' || str[i] == ':') {
+                                               fputc('\\', file);
+                                       }
+                                       fputc(str[i], file);
+                               }
+
+                               fputc('\n', file);
+
+                       }
+                       hashMapIterator_destroy(iterator);
+               }
+               fclose(file);
+       } else {
+               perror("File is null");
+       }
+}
+
+celix_status_t properties_copy(properties_pt properties, properties_pt *out) {
+       celix_status_t status = CELIX_SUCCESS;
+       properties_pt copy = properties_create();
+
+       if (copy != NULL) {
+               hash_map_iterator_pt iter = hashMapIterator_create(properties);
+               while (hashMapIterator_hasNext(iter)) {
+                       hash_map_entry_pt entry = 
hashMapIterator_nextEntry(iter);
+                       char *key = hashMapEntry_getKey(entry);
+                       char *value = hashMapEntry_getValue(entry);
+                       properties_set(copy, key, value);
+               }
+               hashMapIterator_destroy(iter);
+       } else {
+               status = CELIX_ENOMEM;
+       }
+
+       if (status == CELIX_SUCCESS) {
+               *out = copy;
+       }
+
+       return status;
+}
+
+const char* properties_get(properties_pt properties, const char* key) {
+       return hashMap_get(properties, (void*)key);
+}
+
+const char* properties_getWithDefault(properties_pt properties, const char* 
key, const char* defaultValue) {
+       const char* value = properties_get(properties, key);
+       return value == NULL ? defaultValue : value;
+}
+
+void properties_set(properties_pt properties, const char* key, const char* 
value) {
+       hash_map_entry_pt entry = hashMap_getEntry(properties, key);
+       char* oldValue = NULL;
+       if (entry != NULL) {
+               char* oldKey = hashMapEntry_getKey(entry);
+               oldValue = hashMapEntry_getValue(entry);
+               hashMap_put(properties, oldKey, strndup(value, 1024*10));
+       } else {
+               hashMap_put(properties, strndup(key, 1024*10), strndup(value, 
1024*10));
+       }
+       free(oldValue);
+}
+
+static void updateBuffers(char **key, char ** value, char **output, int 
outputPos, int *key_len, int *value_len) {
+       if (*output == *key) {
+               if (outputPos == (*key_len) - 1) {
+                       (*key_len) += MALLOC_BLOCK_SIZE;
+                       *key = realloc(*key, *key_len);
+                       *output = *key;
+               }
+       }
+       else {
+               if (outputPos == (*value_len) - 1) {
+                       (*value_len) += MALLOC_BLOCK_SIZE;
+                       *value = realloc(*value, *value_len);
+                       *output = *value;
+               }
+       }
+}
+
+static void parseLine(const char* line, properties_pt props) {
+       int linePos = 0;
+       bool precedingCharIsBackslash = false;
+       bool isComment = false;
+       int outputPos = 0;
+       char *output = NULL;
+       int key_len = MALLOC_BLOCK_SIZE;
+       int value_len = MALLOC_BLOCK_SIZE;
+       linePos = 0;
+       precedingCharIsBackslash = false;
+       isComment = false;
+       output = NULL;
+       outputPos = 0;
+
+       //Ignore empty lines
+       if (line[0] == '\n' && line[1] == '\0') {
+               return;
+       }
+
+       char *key = calloc(1, key_len);
+       char *value = calloc(1, value_len);
+       key[0] = '\0';
+       value[0] = '\0';
+
+       while (line[linePos] != '\0') {
+               if (line[linePos] == ' ' || line[linePos] == '\t') {
+                       if (output == NULL) {
+                               //ignore
+                               linePos += 1;
+                               continue;
+                       }
+               }
+               else {
+                       if (output == NULL) {
+                               output = key;
+                       }
+               }
+               if (line[linePos] == '=' || line[linePos] == ':' || 
line[linePos] == '#' || line[linePos] == '!') {
+                       if (precedingCharIsBackslash) {
+                               //escaped special character
+                               output[outputPos++] = line[linePos];
+                               updateBuffers(&key, &value, &output, outputPos, 
&key_len, &value_len);
+                               precedingCharIsBackslash = false;
+                       }
+                       else {
+                               if (line[linePos] == '#' || line[linePos] == 
'!') {
+                                       if (outputPos == 0) {
+                                               isComment = true;
+                                               break;
+                                       }
+                                       else {
+                                               output[outputPos++] = 
line[linePos];
+                                               updateBuffers(&key, &value, 
&output, outputPos, &key_len, &value_len);
+                                       }
+                               }
+                               else { // = or :
+                                       if (output == value) { //already have a 
seperator
+                                               output[outputPos++] = 
line[linePos];
+                                               updateBuffers(&key, &value, 
&output, outputPos, &key_len, &value_len);
+                                       }
+                                       else {
+                                               output[outputPos++] = '\0';
+                                               updateBuffers(&key, &value, 
&output, outputPos, &key_len, &value_len);
+                                               output = value;
+                                               outputPos = 0;
+                                       }
+                               }
+                       }
+               }
+               else if (line[linePos] == '\\') {
+                       if (precedingCharIsBackslash) { //double backslash -> 
backslash
+                               output[outputPos++] = '\\';
+                               updateBuffers(&key, &value, &output, outputPos, 
&key_len, &value_len);
+                       }
+                       precedingCharIsBackslash = true;
+               }
+               else { //normal character
+                       precedingCharIsBackslash = false;
+                       output[outputPos++] = line[linePos];
+                       updateBuffers(&key, &value, &output, outputPos, 
&key_len, &value_len);
+               }
+               linePos += 1;
+       }
+       if (output != NULL) {
+               output[outputPos] = '\0';
+       }
+
+       if (!isComment) {
+               //printf("putting 'key'/'value' '%s'/'%s' in properties\n", 
utils_stringTrim(key), utils_stringTrim(value));
+               properties_set(props, utils_stringTrim(key), 
utils_stringTrim(value));
+       }
+       if(key) {
+               free(key);
+       }
+       if(value) {
+               free(value);
+       }
+
+}

http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/utils/src/thpool.c
----------------------------------------------------------------------
diff --git a/utils/src/thpool.c b/utils/src/thpool.c
new file mode 100644
index 0000000..5121fca
--- /dev/null
+++ b/utils/src/thpool.c
@@ -0,0 +1,535 @@
+/* ********************************
+ * Author:       Johan Hanssen Seferidis
+ * License:         MIT
+ * Description:  Library providing a threading pool where you can add
+ *               work. For usage, check the thpool.h file or README.md
+ *
+ *//** @file thpool.h *//*
+ * 
+ ********************************/
+
+
+#include <unistd.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <pthread.h>
+#include <errno.h>
+#include <time.h> 
+#include "thpool.h"
+
+#ifdef THPOOL_DEBUG
+#define THPOOL_DEBUG 1
+#else
+#define THPOOL_DEBUG 0
+#endif
+
+static volatile int threads_keepalive;
+static volatile int threads_on_hold;
+
+
+
+/* ========================== STRUCTURES ============================ */
+
+
+/* Binary semaphore */
+typedef struct bsem {
+       pthread_mutex_t mutex;
+       pthread_cond_t   cond;
+       int v;
+} bsem;
+
+
+/* Job */
+typedef struct job{
+       struct job*  prev;                   /* pointer to previous job   */
+       void*  (*function)(void* arg);       /* function pointer          */
+       void*  arg;                          /* function's argument       */
+} job;
+
+
+/* Job queue */
+typedef struct jobqueue{
+       pthread_mutex_t rwmutex;             /* used for queue r/w access */
+       job  *front;                         /* pointer to front of queue */
+       job  *rear;                          /* pointer to rear  of queue */
+       bsem *has_jobs;                      /* flag as binary semaphore  */
+       int   len;                           /* number of jobs in queue   */
+} jobqueue;
+
+
+/* Thread */
+typedef struct thread{
+       int       id;                        /* friendly id               */
+       pthread_t pthread;                   /* pointer to actual thread  */
+       struct thpool_* thpool_p;            /* access to thpool          */
+} thread;
+
+
+/* Threadpool */
+typedef struct thpool_{
+       thread**   threads;                  /* pointer to threads        */
+       volatile int num_threads_alive;      /* threads currently alive   */
+       volatile int num_threads_working;    /* threads currently working */
+       pthread_mutex_t  thcount_lock;       /* used for thread count etc */
+       pthread_cond_t  threads_all_idle;    /* signal to thpool_wait     */
+       jobqueue*  jobqueue_p;               /* pointer to the job queue  */    
+} thpool_;
+
+
+
+
+
+/* ========================== PROTOTYPES ============================ */
+
+
+static void  thread_init(thpool_* thpool_p, struct thread** thread_p, int id);
+static void* thread_do(struct thread* thread_p);
+static void  thread_hold();
+static void  thread_destroy(struct thread* thread_p);
+
+static int   jobqueue_init(thpool_* thpool_p);
+static void  jobqueue_clear(thpool_* thpool_p);
+static void  jobqueue_push(thpool_* thpool_p, struct job* newjob_p);
+static struct job* jobqueue_pull(thpool_* thpool_p);
+static void  jobqueue_destroy(thpool_* thpool_p);
+
+static void  bsem_init(struct bsem *bsem_p, int value);
+static void  bsem_reset(struct bsem *bsem_p);
+static void  bsem_post(struct bsem *bsem_p);
+static void  bsem_post_all(struct bsem *bsem_p);
+static void  bsem_wait(struct bsem *bsem_p);
+
+
+
+
+
+/* ========================== THREADPOOL ============================ */
+
+
+/* Initialise thread pool */
+struct thpool_* thpool_init(int num_threads){
+
+       threads_on_hold   = 0;
+       threads_keepalive = 1;
+
+       if ( num_threads < 0){
+               num_threads = 0;
+       }
+
+       /* Make new thread pool */
+       thpool_* thpool_p;
+       thpool_p = (struct thpool_*)malloc(sizeof(struct thpool_));
+       if (thpool_p == NULL){
+               fprintf(stderr, "thpool_init(): Could not allocate memory for 
thread pool\n");
+               return NULL;
+       }
+       thpool_p->num_threads_alive   = 0;
+       thpool_p->num_threads_working = 0;
+
+       /* Initialise the job queue */
+       if (jobqueue_init(thpool_p) == -1){
+               fprintf(stderr, "thpool_init(): Could not allocate memory for 
job queue\n");
+               free(thpool_p);
+               return NULL;
+       }
+
+       /* Make threads in pool */
+       thpool_p->threads = (struct thread**)malloc(num_threads * sizeof(struct 
thread*));
+       if (thpool_p->threads == NULL){
+               fprintf(stderr, "thpool_init(): Could not allocate memory for 
threads\n");
+               jobqueue_destroy(thpool_p);
+               free(thpool_p->jobqueue_p);
+               free(thpool_p);
+               return NULL;
+       }
+
+       pthread_mutex_init(&(thpool_p->thcount_lock), NULL);
+       pthread_cond_init(&thpool_p->threads_all_idle, NULL);
+       
+       /* Thread init */
+       int n;
+       for (n=0; n<num_threads; n++){
+               thread_init(thpool_p, &thpool_p->threads[n], n);
+               if (THPOOL_DEBUG)
+                       printf("THPOOL_DEBUG: Created thread %d in pool \n", n);
+       }
+       
+       /* Wait for threads to initialize */
+       while (thpool_p->num_threads_alive != num_threads) {}
+
+       return thpool_p;
+}
+
+
+/* Add work to the thread pool */
+int thpool_add_work(thpool_* thpool_p, void *(*function_p)(void*), void* 
arg_p){
+       job* newjob;
+
+       newjob=(struct job*)malloc(sizeof(struct job));
+       if (newjob==NULL){
+               fprintf(stderr, "thpool_add_work(): Could not allocate memory 
for new job\n");
+               return -1;
+       }
+
+       /* add function and argument */
+       newjob->function=function_p;
+       newjob->arg=arg_p;
+
+       /* add job to queue */
+       pthread_mutex_lock(&thpool_p->jobqueue_p->rwmutex);
+       jobqueue_push(thpool_p, newjob);
+       pthread_mutex_unlock(&thpool_p->jobqueue_p->rwmutex);
+
+       return 0;
+}
+
+
+/* Wait until all jobs have finished */
+void thpool_wait(thpool_* thpool_p){
+       pthread_mutex_lock(&thpool_p->thcount_lock);
+       while (thpool_p->jobqueue_p->len || thpool_p->num_threads_working) {
+               pthread_cond_wait(&thpool_p->threads_all_idle, 
&thpool_p->thcount_lock);
+       }
+       pthread_mutex_unlock(&thpool_p->thcount_lock);
+}
+
+
+/* Destroy the threadpool */
+void thpool_destroy(thpool_* thpool_p){
+       
+       volatile int threads_total = thpool_p->num_threads_alive;
+
+       /* End each thread 's infinite loop */
+       threads_keepalive = 0;
+       
+       /* Give one second to kill idle threads */
+       double TIMEOUT = 1.0;
+       time_t start, end;
+       double tpassed = 0.0;
+       time (&start);
+       while (tpassed < TIMEOUT && thpool_p->num_threads_alive){
+               bsem_post_all(thpool_p->jobqueue_p->has_jobs);
+               time (&end);
+               tpassed = difftime(end,start);
+       }
+       
+       /* Poll remaining threads */
+       while (thpool_p->num_threads_alive){
+               bsem_post_all(thpool_p->jobqueue_p->has_jobs);
+               sleep(1);
+       }
+
+       /* Job queue cleanup */
+       jobqueue_destroy(thpool_p);
+       free(thpool_p->jobqueue_p);
+       
+       /* Deallocs */
+       int n;
+       for (n=0; n < threads_total; n++){
+               thread_destroy(thpool_p->threads[n]);
+       }
+       free(thpool_p->threads);
+       free(thpool_p);
+}
+
+
+/* Pause all threads in threadpool */
+void thpool_pause(thpool_* thpool_p) {
+       int n;
+       for (n=0; n < thpool_p->num_threads_alive; n++){
+               pthread_kill(thpool_p->threads[n]->pthread, SIGUSR1);
+       }
+}
+
+
+/* Resume all threads in threadpool */
+void thpool_resume(thpool_* thpool_p) {
+       threads_on_hold = 0;
+}
+
+
+
+
+
+/* ============================ THREAD ============================== */
+
+
+/* Initialize a thread in the thread pool
+ * 
+ * @param thread        address to the pointer of the thread to be created
+ * @param id            id to be given to the thread
+ * 
+ */
+static void thread_init (thpool_* thpool_p, struct thread** thread_p, int id){
+       
+       *thread_p = (struct thread*)malloc(sizeof(struct thread));
+       if (*thread_p == NULL){
+               fprintf(stderr, "thpool_init(): Could not allocate memory for 
thread\n");
+               exit(1);
+       }
+
+       (*thread_p)->thpool_p = thpool_p;
+       (*thread_p)->id       = id;
+
+       pthread_create(&(*thread_p)->pthread, NULL, (void *)thread_do, 
(*thread_p));
+       pthread_detach((*thread_p)->pthread);
+       
+}
+
+
+/* Sets the calling thread on hold */
+static void thread_hold () {
+       threads_on_hold = 1;
+       while (threads_on_hold){
+               sleep(1);
+       }
+}
+
+
+/* What each thread is doing
+* 
+* In principle this is an endless loop. The only time this loop gets 
interuppted is once
+* thpool_destroy() is invoked or the program exits.
+* 
+* @param  thread        thread that will run this function
+* @return nothing
+*/
+static void* thread_do(struct thread* thread_p){
+
+       /* Set thread name for profiling and debuging */
+       char thread_name[128] = {0};
+       sprintf(thread_name, "thread-pool-%d", thread_p->id);
+
+#if defined(__linux__)
+       pthread_setname_np(thread_p->pthread, thread_name);
+#elif defined(__APPLE__) && defined(__MACH__)
+       pthread_setname_np(thread_name);
+#else
+       fprintf(stderr, "thread_do(): pthread_setname_np is not supported on 
this system");
+#endif
+
+       /* Assure all threads have been created before starting serving */
+       thpool_* thpool_p = thread_p->thpool_p;
+       
+       /* Register signal handler */
+       struct sigaction act;
+       sigemptyset(&act.sa_mask);
+       act.sa_flags = 0;
+       act.sa_handler = thread_hold;
+       if (sigaction(SIGUSR1, &act, NULL) == -1) {
+               fprintf(stderr, "thread_do(): cannot handle SIGUSR1");
+       }
+       
+       /* Mark thread as alive (initialized) */
+       pthread_mutex_lock(&thpool_p->thcount_lock);
+       thpool_p->num_threads_alive += 1;
+       pthread_mutex_unlock(&thpool_p->thcount_lock);
+
+       while(threads_keepalive){
+
+               bsem_wait(thpool_p->jobqueue_p->has_jobs);
+
+               if (threads_keepalive){
+                       
+                       pthread_mutex_lock(&thpool_p->thcount_lock);
+                       thpool_p->num_threads_working++;
+                       pthread_mutex_unlock(&thpool_p->thcount_lock);
+                       
+                       /* Read job from queue and execute it */
+                       void*(*func_buff)(void* arg);
+                       void*  arg_buff;
+                       job* job_p;
+                       pthread_mutex_lock(&thpool_p->jobqueue_p->rwmutex);
+                       job_p = jobqueue_pull(thpool_p);
+                       pthread_mutex_unlock(&thpool_p->jobqueue_p->rwmutex);
+                       if (job_p) {
+                               func_buff = job_p->function;
+                               arg_buff  = job_p->arg;
+                               func_buff(arg_buff);
+                               free(job_p);
+                       }
+                       
+                       pthread_mutex_lock(&thpool_p->thcount_lock);
+                       thpool_p->num_threads_working--;
+                       if (!thpool_p->num_threads_working) {
+                               
pthread_cond_signal(&thpool_p->threads_all_idle);
+                       }
+                       pthread_mutex_unlock(&thpool_p->thcount_lock);
+
+               }
+       }
+       pthread_mutex_lock(&thpool_p->thcount_lock);
+       thpool_p->num_threads_alive --;
+       pthread_mutex_unlock(&thpool_p->thcount_lock);
+
+       return NULL;
+}
+
+
+/* Frees a thread  */
+static void thread_destroy (thread* thread_p){
+       free(thread_p);
+}
+
+
+
+
+
+/* ============================ JOB QUEUE =========================== */
+
+
+/* Initialize queue */
+static int jobqueue_init(thpool_* thpool_p){
+       
+       thpool_p->jobqueue_p = (struct jobqueue*)malloc(sizeof(struct 
jobqueue));
+       if (thpool_p->jobqueue_p == NULL){
+               return -1;
+       }
+       thpool_p->jobqueue_p->len = 0;
+       thpool_p->jobqueue_p->front = NULL;
+       thpool_p->jobqueue_p->rear  = NULL;
+
+       thpool_p->jobqueue_p->has_jobs = (struct bsem*)malloc(sizeof(struct 
bsem));
+       if (thpool_p->jobqueue_p->has_jobs == NULL){
+               return -1;
+       }
+
+       pthread_mutex_init(&(thpool_p->jobqueue_p->rwmutex), NULL);
+       bsem_init(thpool_p->jobqueue_p->has_jobs, 0);
+
+       return 0;
+}
+
+
+/* Clear the queue */
+static void jobqueue_clear(thpool_* thpool_p){
+
+       while(thpool_p->jobqueue_p->len){
+               free(jobqueue_pull(thpool_p));
+       }
+
+       thpool_p->jobqueue_p->front = NULL;
+       thpool_p->jobqueue_p->rear  = NULL;
+       bsem_reset(thpool_p->jobqueue_p->has_jobs);
+       thpool_p->jobqueue_p->len = 0;
+
+}
+
+
+/* Add (allocated) job to queue
+ *
+ * Notice: Caller MUST hold a mutex
+ */
+static void jobqueue_push(thpool_* thpool_p, struct job* newjob){
+
+       newjob->prev = NULL;
+
+       switch(thpool_p->jobqueue_p->len){
+
+               case 0:  /* if no jobs in queue */
+                                       thpool_p->jobqueue_p->front = newjob;
+                                       thpool_p->jobqueue_p->rear  = newjob;
+                                       break;
+
+               default: /* if jobs in queue */
+                                       thpool_p->jobqueue_p->rear->prev = 
newjob;
+                                       thpool_p->jobqueue_p->rear = newjob;
+                                       
+       }
+       thpool_p->jobqueue_p->len++;
+       
+       bsem_post(thpool_p->jobqueue_p->has_jobs);
+}
+
+
+/* Get first job from queue(removes it from queue)
+ * 
+ * Notice: Caller MUST hold a mutex
+ */
+static struct job* jobqueue_pull(thpool_* thpool_p){
+
+       job* job_p;
+       job_p = thpool_p->jobqueue_p->front;
+
+       switch(thpool_p->jobqueue_p->len){
+               
+               case 0:  /* if no jobs in queue */
+                                       break;
+               
+               case 1:  /* if one job in queue */
+                                       thpool_p->jobqueue_p->front = NULL;
+                                       thpool_p->jobqueue_p->rear  = NULL;
+                                       thpool_p->jobqueue_p->len = 0;
+                                       break;
+               
+               default: /* if >1 jobs in queue */
+                                       thpool_p->jobqueue_p->front = 
job_p->prev;
+                                       thpool_p->jobqueue_p->len--;
+                                       /* more than one job in queue -> post 
it */
+                                       
bsem_post(thpool_p->jobqueue_p->has_jobs);
+                                       
+       }
+       
+       return job_p;
+}
+
+
+/* Free all queue resources back to the system */
+static void jobqueue_destroy(thpool_* thpool_p){
+       jobqueue_clear(thpool_p);
+       free(thpool_p->jobqueue_p->has_jobs);
+}
+
+
+
+
+
+/* ======================== SYNCHRONISATION ========================= */
+
+
+/* Init semaphore to 1 or 0 */
+static void bsem_init(bsem *bsem_p, int value) {
+       if (value < 0 || value > 1) {
+               fprintf(stderr, "bsem_init(): Binary semaphore can take only 
values 1 or 0");
+               exit(1);
+       }
+       pthread_mutex_init(&(bsem_p->mutex), NULL);
+       pthread_cond_init(&(bsem_p->cond), NULL);
+       bsem_p->v = value;
+}
+
+
+/* Reset semaphore to 0 */
+static void bsem_reset(bsem *bsem_p) {
+       bsem_init(bsem_p, 0);
+}
+
+
+/* Post to at least one thread */
+static void bsem_post(bsem *bsem_p) {
+       pthread_mutex_lock(&bsem_p->mutex);
+       bsem_p->v = 1;
+       pthread_cond_signal(&bsem_p->cond);
+       pthread_mutex_unlock(&bsem_p->mutex);
+}
+
+
+/* Post to all threads */
+static void bsem_post_all(bsem *bsem_p) {
+       pthread_mutex_lock(&bsem_p->mutex);
+       bsem_p->v = 1;
+       pthread_cond_broadcast(&bsem_p->cond);
+       pthread_mutex_unlock(&bsem_p->mutex);
+}
+
+
+/* Wait on semaphore until semaphore has value 0 */
+static void bsem_wait(bsem* bsem_p) {
+       pthread_mutex_lock(&bsem_p->mutex);
+       while (bsem_p->v != 1) {
+               pthread_cond_wait(&bsem_p->cond, &bsem_p->mutex);
+       }
+       bsem_p->v = 0;
+       pthread_mutex_unlock(&bsem_p->mutex);
+}

http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/utils/src/utils.c
----------------------------------------------------------------------
diff --git a/utils/src/utils.c b/utils/src/utils.c
new file mode 100644
index 0000000..fc4d538
--- /dev/null
+++ b/utils/src/utils.c
@@ -0,0 +1,141 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you 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.
+ */
+/*
+ * utils.c
+ *
+ *  \date       Jul 27, 2010
+ *  \author            <a href="mailto:[email protected]";>Apache Celix 
Project Team</a>
+ *  \copyright Apache License, Version 2.0
+ */
+#include <stdlib.h>
+#include <string.h>
+
+#include "utils.h"
+
+unsigned int utils_stringHash(const void* strPtr) {
+    const char* string = strPtr;
+    unsigned int hc = 5381;
+    char ch;
+    while((ch = *string++) != '\0'){
+        hc = (hc << 5) + hc + ch;
+    }
+
+    return hc;
+}
+
+int utils_stringEquals(const void* string, const void* toCompare) {
+       return strcmp((const char*)string, (const char*)toCompare) == 0;
+}
+
+char * string_ndup(const char *s, size_t n) {
+       size_t len = strlen(s);
+       char *ret;
+
+       if (len <= n) {
+               return strdup(s);
+       }
+
+       ret = malloc(n + 1);
+       strncpy(ret, s, n);
+       ret[n] = '\0';
+       return ret;
+}
+
+char * utils_stringTrim(char * string) {
+       char* copy = string;
+
+       char *end;
+       // Trim leading space
+       while (isspace(*copy)) {
+               copy++;
+       }
+
+       // Trim trailing space
+       end = copy + strlen(copy) - 1;
+       while(end > copy && isspace(*end)) {
+               *(end) = '\0';
+               end--;
+       }
+
+       if (copy != string) { 
+               //beginning whitespaces -> move char in copy to to begin string
+               //This to ensure free still works on the same pointer.
+               char* nstring = string;
+               while(*copy != '\0') {
+                       *(nstring++) = *(copy++);
+               }
+               (*nstring) = '\0';
+       }
+
+       return string;
+}
+
+bool utils_isStringEmptyOrNull(const char * const str) {
+       bool empty = true;
+       if (str != NULL) {
+               int i;
+               for (i = 0; i < strnlen(str, 1024 * 1024); i += 1) {
+                       if (!isspace(str[i])) {
+                               empty = false;
+                               break;
+                       }
+               }
+       }
+
+       return empty;
+}
+
+celix_status_t thread_equalsSelf(celix_thread_t thread, bool *equals) {
+       celix_status_t status = CELIX_SUCCESS;
+
+       celix_thread_t self = celixThread_self();
+       if (status == CELIX_SUCCESS) {
+               *equals = celixThread_equals(self, thread);
+       }
+
+       return status;
+}
+
+celix_status_t utils_isNumeric(const char *number, bool *ret) {
+       celix_status_t status = CELIX_SUCCESS;
+       *ret = true;
+       while(*number) {
+               if(!isdigit(*number) && *number != '.') {
+                       *ret = false;
+                       break;
+               }
+               number++;
+       }
+       return status;
+}
+
+
+int utils_compareServiceIdsAndRanking(unsigned long servId, long servRank, 
unsigned long otherServId, long otherServRank) {
+       int result;
+
+       if (servId == otherServId) {
+               result = 0;
+       } else if (servRank != otherServRank) {
+               result = servRank < otherServRank ? -1 : 1;
+       } else { //equal service rank, compare service ids
+               result = servId < otherServId ? 1 : -1;
+       }
+
+       return result;
+}

http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/utils/src/version.c
----------------------------------------------------------------------
diff --git a/utils/src/version.c b/utils/src/version.c
new file mode 100644
index 0000000..cb2703d
--- /dev/null
+++ b/utils/src/version.c
@@ -0,0 +1,264 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you 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.
+ */
+/*
+ * version.c
+ *
+ *  \date       Jul 12, 2010
+ *  \author            <a href="mailto:[email protected]";>Apache Celix 
Project Team</a>
+ *  \copyright Apache License, Version 2.0
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "celix_errno.h"
+#include "version_private.h"
+
+celix_status_t version_createVersion(int major, int minor, int micro, char * 
qualifier, version_pt *version) {
+       celix_status_t status = CELIX_SUCCESS;
+
+       if (*version != NULL) {
+               status = CELIX_ILLEGAL_ARGUMENT;
+       } else {
+               *version = (version_pt) malloc(sizeof(**version));
+               if (!*version) {
+                       status = CELIX_ENOMEM;
+               } else {
+                       unsigned int i;
+
+                       (*version)->major = major;
+                       (*version)->minor = minor;
+                       (*version)->micro = micro;
+                       if (qualifier == NULL) {
+                               qualifier = "";
+                       }
+                       (*version)->qualifier = strdup(qualifier);
+
+                       if (major < 0) {
+                               status = CELIX_ILLEGAL_ARGUMENT;
+                       }
+                       if (minor < 0) {
+                               status = CELIX_ILLEGAL_ARGUMENT;
+                       }
+                       if (micro < 0) {
+                               status = CELIX_ILLEGAL_ARGUMENT;
+                       }
+
+                       for (i = 0; i < strlen(qualifier); i++) {
+                               char ch = qualifier[i];
+                               if (('A' <= ch) && (ch <= 'Z')) {
+                                       continue;
+                               }
+                               if (('a' <= ch) && (ch <= 'z')) {
+                                       continue;
+                               }
+                               if (('0' <= ch) && (ch <= '9')) {
+                                       continue;
+                               }
+                               if ((ch == '_') || (ch == '-')) {
+                                       continue;
+                               }
+                               status = CELIX_ILLEGAL_ARGUMENT;
+                               break;
+                       }
+               }
+       }
+
+       return status;
+}
+
+celix_status_t version_clone(version_pt version, version_pt *clone) {
+       return version_createVersion(version->major, version->minor, 
version->micro, version->qualifier, clone);
+}
+
+celix_status_t version_destroy(version_pt version) {
+       version->major = 0;
+       version->minor = 0;
+       version->micro = 0;
+       free(version->qualifier);
+       version->qualifier = NULL;
+       free(version);
+       return CELIX_SUCCESS;
+}
+
+celix_status_t version_createVersionFromString(const char * versionStr, 
version_pt *version) {
+       celix_status_t status = CELIX_SUCCESS;
+
+       int major = 0;
+       int minor = 0;
+       int micro = 0;
+       char * qualifier = NULL;
+
+       char delims[] = ".";
+       char *token = NULL;
+       char *last = NULL;
+
+       int i = 0;
+
+       char* versionWrkStr = strdup(versionStr);
+
+       token = strtok_r(versionWrkStr, delims, &last);
+       if (token != NULL) {
+               for (i = 0; i < strlen(token); i++) {
+                       char ch = token[i];
+                       if (('0' <= ch) && (ch <= '9')) {
+                               continue;
+                       }
+                       status = CELIX_ILLEGAL_ARGUMENT;
+                       break;
+               }
+               major = atoi(token);
+               token = strtok_r(NULL, delims, &last);
+               if (token != NULL) {
+                       for (i = 0; i < strlen(token); i++) {
+                               char ch = token[i];
+                               if (('0' <= ch) && (ch <= '9')) {
+                                       continue;
+                               }
+                               status = CELIX_ILLEGAL_ARGUMENT;
+                               break;
+                       }
+                       minor = atoi(token);
+                       token = strtok_r(NULL, delims, &last);
+                       if (token != NULL) {
+                               for (i = 0; i < strlen(token); i++) {
+                                       char ch = token[i];
+                                       if (('0' <= ch) && (ch <= '9')) {
+                                               continue;
+                                       }
+                                       status = CELIX_ILLEGAL_ARGUMENT;
+                                       break;
+                               }
+                               micro = atoi(token);
+                               token = strtok_r(NULL, delims, &last);
+                               if (token != NULL) {
+                                       qualifier = strdup(token);
+                                       token = strtok_r(NULL, delims, &last);
+                                       if (token != NULL) {
+                                               *version = NULL;
+                                               status = CELIX_ILLEGAL_ARGUMENT;
+                                       }
+                               }
+                       }
+               }
+       }
+
+       free(versionWrkStr);
+
+       if (status == CELIX_SUCCESS) {
+               status = version_createVersion(major, minor, micro, qualifier, 
version);
+       }
+
+       if (qualifier != NULL) {
+           free(qualifier);
+       }
+
+       return status;
+}
+
+celix_status_t version_createEmptyVersion(version_pt *version) {
+       return version_createVersion(0, 0, 0, "", version);
+}
+
+celix_status_t version_getMajor(version_pt version, int *major) {
+       celix_status_t status = CELIX_SUCCESS;
+       *major = version->major;
+       return status;
+}
+
+celix_status_t version_getMinor(version_pt version, int *minor) {
+       celix_status_t status = CELIX_SUCCESS;
+       *minor = version->minor;
+       return status;
+}
+
+celix_status_t version_getMicro(version_pt version, int *micro) {
+       celix_status_t status = CELIX_SUCCESS;
+       *micro = version->micro;
+       return status;
+}
+
+celix_status_t version_getQualifier(version_pt version, const char 
**qualifier) {
+       celix_status_t status = CELIX_SUCCESS;
+       *qualifier = version->qualifier;
+       return status;
+}
+
+celix_status_t version_compareTo(version_pt version, version_pt compare, int 
*result) {
+       celix_status_t status = CELIX_SUCCESS;
+       if (compare == version) {
+               *result = 0;
+       } else {
+               int res = version->major - compare->major;
+               if (res != 0) {
+                       *result = res;
+               } else {
+                       res = version->minor - compare->minor;
+                       if (res != 0) {
+                               *result = res;
+                       } else {
+                               res = version->micro - compare->micro;
+                               if (res != 0) {
+                                       *result = res;
+                               } else {
+                                       *result = strcmp(version->qualifier, 
compare->qualifier);
+                               }
+                       }
+               }
+       }
+
+       return status;
+}
+
+celix_status_t version_toString(version_pt version, char **string) {
+    celix_status_t status = CELIX_SUCCESS;
+       if (strlen(version->qualifier) > 0) {
+           char str[512];
+           int written = snprintf(str, 512, "%d.%d.%d.%s", version->major, 
version->minor, version->micro, version->qualifier);
+           if (written >= 512 || written < 0) {
+               status = CELIX_BUNDLE_EXCEPTION;
+           }
+           *string = strdup(str);
+       } else {
+           char str[512];
+        int written = snprintf(str, 512, "%d.%d.%d", version->major, 
version->minor, version->micro);
+        if (written >= 512 || written < 0) {
+            status = CELIX_BUNDLE_EXCEPTION;
+        }
+        *string = strdup(str);
+       }
+       return status;
+}
+
+celix_status_t version_isCompatible(version_pt user, version_pt provider, 
bool* isCompatible) {
+    celix_status_t status = CELIX_SUCCESS;
+    bool result = false;
+
+    if (user == NULL || provider == NULL) {
+        return CELIX_ILLEGAL_ARGUMENT;
+    }
+
+    if (user->major == provider->major) {
+        result = (provider->minor >= user->minor);
+    }
+
+    *isCompatible = result;
+
+    return status;
+}

http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/utils/src/version_private.h
----------------------------------------------------------------------
diff --git a/utils/src/version_private.h b/utils/src/version_private.h
new file mode 100644
index 0000000..15e5c89
--- /dev/null
+++ b/utils/src/version_private.h
@@ -0,0 +1,41 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you 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.
+ */
+/*
+ * version_private.h
+ *
+ *  \date       Dec 18, 2012
+ *  \author     <a href="mailto:[email protected]";>Apache Celix Project 
Team</a>
+ *  \copyright  Apache License, Version 2.0
+ */
+
+
+#ifndef VERSION_PRIVATE_H_
+#define VERSION_PRIVATE_H_
+
+#include "version.h"
+
+struct version {
+       int major;
+       int minor;
+       int micro;
+       char *qualifier;
+};
+
+
+#endif /* VERSION_PRIVATE_H_ */

http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/utils/src/version_range.c
----------------------------------------------------------------------
diff --git a/utils/src/version_range.c b/utils/src/version_range.c
new file mode 100644
index 0000000..ed681fd
--- /dev/null
+++ b/utils/src/version_range.c
@@ -0,0 +1,233 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you 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.
+ */
+/*
+ * version_range.c
+ *
+ *  \date       Jul 12, 2010
+ *  \author            <a href="mailto:[email protected]";>Apache Celix 
Project Team</a>
+ *  \copyright Apache License, Version 2.0
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "version_range_private.h"
+
+celix_status_t versionRange_createVersionRange(version_pt low, bool 
isLowInclusive,
+                       version_pt high, bool isHighInclusive, version_range_pt 
*range) {
+       celix_status_t status = CELIX_SUCCESS;
+       *range = (version_range_pt) malloc(sizeof(**range));
+       if (!*range) {
+               status = CELIX_ENOMEM;
+       } else {
+               (*range)->low = low;
+               (*range)->isLowInclusive = isLowInclusive;
+               (*range)->high = high;
+               (*range)->isHighInclusive = isHighInclusive;
+       }
+
+       return status;
+}
+
+celix_status_t versionRange_destroy(version_range_pt range) {
+    if (range->high != NULL) {
+        version_destroy(range->high);
+    }
+    if (range->low != NULL) {
+        version_destroy(range->low);
+    }
+
+       range->high = NULL;
+       range->isHighInclusive = false;
+       range->low = NULL;
+       range->isLowInclusive = false;
+
+       free(range);
+
+       return CELIX_SUCCESS;
+}
+
+celix_status_t versionRange_createInfiniteVersionRange(version_range_pt 
*range) {
+       celix_status_t status;
+
+       version_pt version = NULL;
+       status = version_createEmptyVersion(&version);
+       if (status == CELIX_SUCCESS) {
+               status = versionRange_createVersionRange(version, true, NULL, 
true, range);
+       }
+
+       return status;
+}
+
+celix_status_t versionRange_isInRange(version_range_pt versionRange, 
version_pt version, bool *inRange) {
+       celix_status_t status;
+       if (versionRange->high == NULL) {
+               int cmp;
+               status = version_compareTo(version, versionRange->low, &cmp);
+               if (status == CELIX_SUCCESS) {
+                       *inRange = (cmp >= 0);
+               }
+       } else if (versionRange->isLowInclusive && 
versionRange->isHighInclusive) {
+               int low, high;
+               status = version_compareTo(version, versionRange->low, &low);
+               if (status == CELIX_SUCCESS) {
+                       status = version_compareTo(version, versionRange->high, 
&high);
+                       if (status == CELIX_SUCCESS) {
+                               *inRange = (low >= 0) && (high <= 0);
+                       }
+               }
+       } else if (versionRange->isHighInclusive) {
+               int low, high;
+               status = version_compareTo(version, versionRange->low, &low);
+               if (status == CELIX_SUCCESS) {
+                       status = version_compareTo(version, versionRange->high, 
&high);
+                       if (status == CELIX_SUCCESS) {
+                               *inRange = (low > 0) && (high <= 0);
+                       }
+               }
+       } else if (versionRange->isLowInclusive) {
+               int low, high;
+               status = version_compareTo(version, versionRange->low, &low);
+               if (status == CELIX_SUCCESS) {
+                       status = version_compareTo(version, versionRange->high, 
&high);
+                       if (status == CELIX_SUCCESS) {
+                               *inRange = (low >= 0) && (high < 0);
+                       }
+               }
+       } else {
+               int low, high;
+               status = version_compareTo(version, versionRange->low, &low);
+               if (status == CELIX_SUCCESS) {
+                       status = version_compareTo(version, versionRange->high, 
&high);
+                       if (status == CELIX_SUCCESS) {
+                               *inRange = (low > 0) && (high < 0);
+                       }
+               }
+       }
+
+       return status;
+}
+
+celix_status_t versionRange_getLowVersion(version_range_pt versionRange, 
version_pt *lowVersion) {
+    celix_status_t status = CELIX_SUCCESS;
+
+    if (versionRange == NULL) {
+        status = CELIX_ILLEGAL_ARGUMENT;
+    }
+    else {
+        *lowVersion = versionRange->low;
+    }
+
+    return status;
+}
+
+celix_status_t versionRange_isLowInclusive(version_range_pt versionRange, bool 
*isLowInclusive) {
+    celix_status_t status = CELIX_SUCCESS;
+
+    if (versionRange == NULL) {
+        status = CELIX_ILLEGAL_ARGUMENT;
+    }
+    else {
+        *isLowInclusive = versionRange->isLowInclusive;
+    }
+
+    return status;
+}
+
+celix_status_t versionRange_getHighVersion(version_range_pt versionRange, 
version_pt *highVersion) {
+    celix_status_t status = CELIX_SUCCESS;
+
+    if (versionRange == NULL) {
+        status = CELIX_ILLEGAL_ARGUMENT;
+    }
+    else {
+        *highVersion = versionRange->high;
+    }
+
+    return status;
+}
+
+celix_status_t versionRange_isHighInclusive(version_range_pt versionRange, 
bool *isHighInclusive) {
+    celix_status_t status = CELIX_SUCCESS;
+
+    if (versionRange == NULL) {
+        status = CELIX_ILLEGAL_ARGUMENT;
+    }
+    else {
+        *isHighInclusive = versionRange->isHighInclusive;
+    }
+
+    return status;
+}
+
+
+celix_status_t versionRange_parse(const char * rangeStr, version_range_pt 
*range) {
+       celix_status_t status;
+       if (strchr(rangeStr, ',') != NULL) {
+                       int vlowL = strcspn(rangeStr+1, ",");
+                       char * vlow = (char *) malloc(sizeof(char) * (vlowL + 
1));
+                       if (!vlow) {
+                               status = CELIX_ENOMEM;
+                       } else {
+                               int vhighL;
+                               char * vhigh;
+                               vlow = strncpy(vlow, rangeStr+1, vlowL);
+                               vlow[vlowL] = '\0';
+                               vhighL = strlen(rangeStr+1) - vlowL - 2;
+                               vhigh = (char *) malloc(sizeof(char) * 
(vhighL+1));
+                               if (!vhigh) {
+                                       status = CELIX_ENOMEM;
+                               } else {                                        
+                                       version_pt versionLow = NULL;
+                                       int rangeL = strlen(rangeStr);
+                                       char start = rangeStr[0];
+                                       char end = rangeStr[rangeL-1];
+
+                                       vhigh = strncpy(vhigh, 
rangeStr+vlowL+2, vhighL);
+                                       vhigh[vhighL] = '\0';
+                                       status = 
version_createVersionFromString(vlow, &versionLow);
+                                       if (status == CELIX_SUCCESS) {
+                                               version_pt versionHigh = NULL;
+                                               status = 
version_createVersionFromString(vhigh, &versionHigh);
+                                               if (status == CELIX_SUCCESS) {
+                                                       status = 
versionRange_createVersionRange(
+                                                                       
versionLow,
+                                                                       start 
== '[',
+                                                                       
versionHigh,
+                                                                       end 
==']',
+                                                                       range
+                                                               );
+                                               }
+                                       }
+                                       free(vhigh);
+                               }
+                               free(vlow);
+
+               }
+       } else {
+               version_pt version = NULL;
+               status = version_createVersionFromString(rangeStr, &version);
+               if (status == CELIX_SUCCESS) {
+                       status = versionRange_createVersionRange(version, true, 
NULL, false, range);
+               }
+       }
+
+       return status;
+}
+

http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/utils/src/version_range_private.h
----------------------------------------------------------------------
diff --git a/utils/src/version_range_private.h 
b/utils/src/version_range_private.h
new file mode 100644
index 0000000..dfccd59
--- /dev/null
+++ b/utils/src/version_range_private.h
@@ -0,0 +1,41 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you 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.
+ */
+/*
+ * version_range_private.h
+ *
+ *  \date       Dec 18, 2012
+ *  \author     <a href="mailto:[email protected]";>Apache Celix Project 
Team</a>
+ *  \copyright  Apache License, Version 2.0
+ */
+
+
+#ifndef VERSION_RANGE_PRIVATE_H_
+#define VERSION_RANGE_PRIVATE_H_
+
+#include "version_range.h"
+
+struct versionRange {
+       version_pt low;
+       bool isLowInclusive;
+       version_pt high;
+       bool isHighInclusive;
+
+};
+
+#endif /* VERSION_RANGE_PRIVATE_H_ */

Reply via email to