celix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From pnol...@apache.org
Subject [01/46] celix git commit: CELIX-417: Initial refactoring for CMake usage
Date Mon, 20 Nov 2017 20:32:58 GMT
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:dev@celix.apache.org">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:dev@celix.apache.org">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:dev@celix.apache.org">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:dev@celix.apache.org">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:dev@celix.apache.org">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:dev@celix.apache.org">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:dev@celix.apache.org">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:dev@celix.apache.org">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_ */


Mime
View raw message