summaryrefslogtreecommitdiffstats
path: root/tinySAK/src
diff options
context:
space:
mode:
Diffstat (limited to 'tinySAK/src')
-rw-r--r--tinySAK/src/Makefile.am38
-rw-r--r--tinySAK/src/tinysak_config.h105
-rw-r--r--tinySAK/src/tsk.c285
-rw-r--r--tinySAK/src/tsk.h70
-rw-r--r--tinySAK/src/tsk_base64.c236
-rw-r--r--tinySAK/src/tsk_base64.h53
-rw-r--r--tinySAK/src/tsk_binaryutils.c33
-rw-r--r--tinySAK/src/tsk_binaryutils.h157
-rw-r--r--tinySAK/src/tsk_buffer.c363
-rw-r--r--tinySAK/src/tsk_buffer.h102
-rw-r--r--tinySAK/src/tsk_common.h70
-rw-r--r--tinySAK/src/tsk_condwait.c303
-rw-r--r--tinySAK/src/tsk_condwait.h53
-rw-r--r--tinySAK/src/tsk_debug.c76
-rw-r--r--tinySAK/src/tsk_debug.h125
-rw-r--r--tinySAK/src/tsk_errno.h93
-rw-r--r--tinySAK/src/tsk_fsm.c311
-rw-r--r--tinySAK/src/tsk_fsm.h178
-rw-r--r--tinySAK/src/tsk_hmac.c226
-rw-r--r--tinySAK/src/tsk_hmac.h49
-rw-r--r--tinySAK/src/tsk_list.c604
-rw-r--r--tinySAK/src/tsk_list.h135
-rw-r--r--tinySAK/src/tsk_md5.c276
-rw-r--r--tinySAK/src/tsk_md5.h94
-rw-r--r--tinySAK/src/tsk_memory.c124
-rw-r--r--tinySAK/src/tsk_memory.h59
-rw-r--r--tinySAK/src/tsk_mutex.c167
-rw-r--r--tinySAK/src/tsk_mutex.h50
-rw-r--r--tinySAK/src/tsk_object.c224
-rw-r--r--tinySAK/src/tsk_object.h173
-rw-r--r--tinySAK/src/tsk_options.c242
-rw-r--r--tinySAK/src/tsk_options.h77
-rw-r--r--tinySAK/src/tsk_params.c378
-rw-r--r--tinySAK/src/tsk_params.h83
-rw-r--r--tinySAK/src/tsk_ppfcs16.c82
-rw-r--r--tinySAK/src/tsk_ppfcs16.h45
-rw-r--r--tinySAK/src/tsk_ppfcs32.c115
-rw-r--r--tinySAK/src/tsk_ppfcs32.h45
-rw-r--r--tinySAK/src/tsk_ragel_state.c51
-rw-r--r--tinySAK/src/tsk_ragel_state.h184
-rw-r--r--tinySAK/src/tsk_runnable.c236
-rw-r--r--tinySAK/src/tsk_runnable.h167
-rw-r--r--tinySAK/src/tsk_safeobj.c33
-rw-r--r--tinySAK/src/tsk_safeobj.h81
-rw-r--r--tinySAK/src/tsk_semaphore.c198
-rw-r--r--tinySAK/src/tsk_semaphore.h47
-rw-r--r--tinySAK/src/tsk_sha1.c455
-rw-r--r--tinySAK/src/tsk_sha1.h122
-rw-r--r--tinySAK/src/tsk_string.c619
-rw-r--r--tinySAK/src/tsk_string.h127
-rw-r--r--tinySAK/src/tsk_thread.c109
-rw-r--r--tinySAK/src/tsk_thread.h45
-rw-r--r--tinySAK/src/tsk_time.c154
-rw-r--r--tinySAK/src/tsk_time.h73
-rw-r--r--tinySAK/src/tsk_timer.c531
-rw-r--r--tinySAK/src/tsk_timer.h94
-rw-r--r--tinySAK/src/tsk_url.c92
-rw-r--r--tinySAK/src/tsk_url.h43
-rw-r--r--tinySAK/src/tsk_uuid.c92
-rw-r--r--tinySAK/src/tsk_uuid.h48
-rw-r--r--tinySAK/src/tsk_xml.c296
-rw-r--r--tinySAK/src/tsk_xml.h175
62 files changed, 9971 insertions, 0 deletions
diff --git a/tinySAK/src/Makefile.am b/tinySAK/src/Makefile.am
new file mode 100644
index 0000000..d7ea30b
--- /dev/null
+++ b/tinySAK/src/Makefile.am
@@ -0,0 +1,38 @@
+lib_LTLIBRARIES = libtinySAK.la
+
+libtinySAK_la_SOURCES = tsk.c\
+ tsk_base64.c\
+ tsk_binaryutils.c\
+ tsk_buffer.c\
+ tsk_condwait.c\
+ tsk_debug.c\
+ tsk_fsm.c\
+ tsk_hmac.c\
+ tsk_list.c\
+ tsk_md5.c\
+ tsk_memory.c\
+ tsk_mutex.c\
+ tsk_object.c\
+ tsk_options.c\
+ tsk_params.c\
+ tsk_ppfcs16.c\
+ tsk_ppfcs32.c\
+ tsk_ragel_state.c\
+ tsk_runnable.c\
+ tsk_safeobj.c\
+ tsk_semaphore.c\
+ tsk_sha1.c\
+ tsk_string.c\
+ tsk_thread.c\
+ tsk_time.c\
+ tsk_timer.c\
+ tsk_url.c\
+ tsk_uuid.c\
+ tsk_xml.c
+
+# LDFLAGS
+libtinySAK_la_LDFLAGS = $LDFLAGS -no-undefined
+
+# Headers file to install
+libtinySAK_la_HEADERS = *.h
+libtinySAK_ladir = $(includedir)/tinySAK
diff --git a/tinySAK/src/tinysak_config.h b/tinySAK/src/tinysak_config.h
new file mode 100644
index 0000000..85352e8
--- /dev/null
+++ b/tinySAK/src/tinysak_config.h
@@ -0,0 +1,105 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tinysak_config.h
+ * @brief Global configuration file.
+ *
+ * This file incude all your preferences or configuration. All specific configuration
+ * must be defined in this file. You must include this file in all your header files.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+
+#ifndef _TINYSAK_H_
+#define _TINYSAK_H_
+
+#ifdef __SYMBIAN32__
+#undef _WIN32 /* Because of WINSCW */
+#endif
+
+/* Windows (XP/Vista/7/CE and Windows Mobile) macro definition.
+*/
+#if defined(WIN32)|| defined(_WIN32) || defined(_WIN32_WCE)
+# define TSK_UNDER_WINDOWS 1
+#endif
+
+/* Used on Windows and Symbian systems to export/import public functions and global variables.
+*/
+#if !defined(__GNUC__) && defined(TINYSAK_EXPORTS)
+# define TINYSAK_API __declspec(dllexport)
+# define TINYSAK_GEXTERN __declspec(dllexport)
+#elif !defined(__GNUC__) /*&& defined(TINYSAK_IMPORTS)*/
+# define TINYSAK_API __declspec(dllimport)
+# define TINYSAK_GEXTERN __declspec(dllimport)
+#else
+# define TINYSAK_API
+# define TINYSAK_GEXTERN extern
+#endif
+
+/* Guards against C++ name mangling */
+#ifdef __cplusplus
+# define TSK_BEGIN_DECLS extern "C" {
+# define TSK_END_DECLS }
+#else
+# define TSK_BEGIN_DECLS
+# define TSK_END_DECLS
+#endif
+
+#if defined(_MSC_VER)
+# define TSK_INLINE __forceinline
+#elif defined(__GNUC__) && !defined(__APPLE__)
+# define TSK_INLINE __inline
+#else
+# define TSK_INLINE
+#endif
+
+
+/* Disable some well-known warnings for M$ Visual Studio*/
+#ifdef _MSC_VER
+# define _CRT_SECURE_NO_WARNINGS
+# pragma warning( disable : 4996 )
+#endif
+
+/* Features */
+#if TSK_UNDER_WINDOWS
+# define HAVE_GETTIMEOFDAY 0
+#else
+# define HAVE_GETTIMEOFDAY 1
+#endif
+
+#if defined(ANDROID)
+# define HAVE_CLOCK_GETTIME 1
+#endif
+
+#include <stdint.h>
+#include <stddef.h>
+#include "tsk_common.h"
+
+
+#if HAVE_CONFIG_H
+# include "../config.h"
+#endif
+
+#endif /* _TINYSAK_H_ */
+
diff --git a/tinySAK/src/tsk.c b/tinySAK/src/tsk.c
new file mode 100644
index 0000000..93fc8e6
--- /dev/null
+++ b/tinySAK/src/tsk.c
@@ -0,0 +1,285 @@
+/**
+* @file tsk.c
+* @author Mamadou Diop <diopmamadou(at)doubango.org>
+* @version 1.0
+*
+* @section LICENSE
+*
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+#include "tsk.h"
+
+/** @mainpage tinySAK API Overview
+*
+* This file is an overview of <b>tinySAK</b> API.
+*
+* <b>tinySAK</b> (a.k.a <b>T</b>iny <b>S</b>wiss <b>A</b>rmy <b>K</b>nife) is a tiny but fully featured utility API.
+* This API is designed to efficiently work on embedded systems with limited memory and low computing power.<br>
+* This library provide a base object class to ease Object Oriented Programming in C. There are many other
+* features like multi-threading, time management, encoding, encryption or content management.
+* <h1>6 ANSI-C Object Programming</h1>
+* As you probably know, C is not an object oriented language.<br>
+* Today, OOP (Object-Oriented Programing) is the best way to program well designed softwares.<br>
+* In this chapter a “well-defined object” is a special C structure. All functions shown in this chapter are part of tinySAK project.<br>
+* To explain how well-defined objects are implemented and used, I will give an example based on “Person” object.<br>
+* The person object is declared like this:<br>
+* @code
+* typedef struct person_s
+{
+ TSK_DECLARE_OBJECT; // Mandatory
+
+ char* name;
+ struct person_s* girlfriend;
+}
+person_t;
+* @endcode
+<h2>6.1 Object Definition</h2>
+* An object definition could be considered as a class definition. The definition holds the object’s mandatory functions, size and a reference counter.<br>
+* The mandatory functions are the constructor, the destructor and the comparator.<br>
+* A C structure is defined as an object by using @ref TSK_DECLARE_OBJECT macro in its body.<br>
+* A pointer to an object definition shall point to a struct @ref tsk_object_def_s.<br>
+* @code
+typedef struct tsk_object_def_s
+{
+ //! The size of the object.
+ tsk_size_t size;
+ //! Pointer to the constructor.
+ tsk_object_t* (* constructor) (tsk_object_t *, va_list *);
+ //! Pointer to the destructor.
+ tsk_object_t* (* destructor) (tsk_object_t *);
+ //! Pointer to the comparator.
+ int (*comparator) (const tsk_object_t *, const tsk_object_t *);
+}
+tsk_object_def_t;
+* @endcode
+*
+* <p>
+* An object is created in two phases. The first phase consists of dynamically allocating the object on the heap; this is why its size is mandatory in the object definition structure. When a new object is allocated on the heap, all its members (char*, void*, int, long …) will be zeroed. In the second phase, the newly created object will be initialized by calling the supplied constructor. To perform these two phases, you should call @ref tsk_object_new() or @ref tsk_object_new_2().
+* </p>
+* <p>
+* An object is destroyed in two phases. The first phase consists of freeing its members (void*, char* …). It’s the destructor which is responsible of this task. In the second phase, the object itself is destroyed. As the object cannot destroy itself, you should use @ref tsk_object_unref() or @ref tsk_object_delete() to perform these two phases. The difference between these two functions is explained in the coming sections.
+* </p>
+* A well-defined object must never be freed using free() standard C function.<br>
+* Below, an example of how to declare an object definition:<br>
+* @code
+* //(Object defnition)
+ static const tsk_object_def_t person_def_t =
+ {
+ sizeof(person_t),
+ person_ctor,
+ person_dtor,
+ person_cmp
+ };
+* @endcode
+* <h2>6.2 Constructor</h2>
+* The constructor is only responsible for the initialization and won’t allocate the object. When passed to the constructor, the object is already allocated.<br>
+* Here is an example:<br>
+* @code
+// (constructor)
+static tsk_object_t* person_ctor(tsk_object_t * self, va_list * app)
+{
+ person_t *person = self;
+ if(person){
+ person->name = tsk_strdup(va_arg(*app, const char *));
+ }
+ return self;
+ }
+* @endcode
+* <h2>6.3 Destructor</h2>
+* The destructor will free the object’s members and won’t destroy the object itself (Phase 1). The destructor function must return a pointer to itself to allow the caller to perform the second phase.<br>
+* Here is an example:<br>
+* @code
+// (destructor)
+ static tsk_object_t * person_dtor(tsk_object_t * self)
+ {
+ person_t *person = self;
+ if(person){
+ TSK_FREE(person->name);
+ tsk_object_unref(person->girlfriend);
+ }
+ return self;
+ }
+* @endcode
+* <h2>6.4 Comparator</h2>
+* The comparator function is used to compare two well-defined objects. The objects to compare shall have the same definition (or type). <br>
+* Here is an example:<br>
+* @code
+// (comparator)
+static int person_cmp(const tsk_object_t *_p1, const tsk_object_t *_p2)
+ {
+ const person_t *p1 = _p1;
+ const person_t *p1 = _p2;
+ int ret;
+
+ // do they have the same name?
+ if((ret = tsk_stricmp(p1->name, p2->name))){
+ return ret;
+ }
+ // do they have the same girlfriend?
+ if((ret = tsk_object_cmp(p1->girlfriend, p2->girlfriend))){
+ return ret;
+ }
+
+ // they are the same
+ return 0;
+ }
+* @endcode
+<h2>6.5 Reference counting</h2>
+* Reference counting is used to emulate garbage collection. Each well-defined object contains a reference counter field which indicates how many object have a reference to the actual object.<br>
+* When an object is created (see below) the counter value is initialized to 1; this is automatically done and you have nothing to do. The counter is incremented by 1 when you call @ref tsk_object_ref() and decremented (by 1) when you call @ref tsk_object_unref().<br>
+* When the counter value reaches zero, then the object is garbaged (freed).<br>
+*
+* <h2>6.6 Inheritence</h2>
+* As you expect, inheritance is not supported in ANSI-C. <br>
+* As any C Structure could be casted to a pointer to its first element, inheritance could be achieved like this:<br>
+* @code
+#include "tsk.h"
+// (a student is a person)
+typedef struct student_s
+{
+ person_t* person; // Must be the first element
+ char* school;
+}
+student_t;
+
+// (as a student is a person you can do)
+student_t* s = tsk_null;
+//....
+((person_t*)s)->name = tsk_strdup("bob");
+* @endcode
+*
+* As @code person_t is a well-defined object, then @code student_t is also well-defined.<br>
+* <h2>6.7 Usage</h2>
+* Once the object’s definition is declared and all its mandatory functions implemented, it is used like this:<br>
+* @code
+// creates a person: will call the constructor
+person_t* bob = tsk_object_new(&person_def_t, "bob");
+// creates bob's girlfriend
+bob->girlfriend = tsk_object_new(&person_def_t, "alice");
+// deletes bob: will delete both bob and bob's girlfriend field by calling their destructors
+tsk_object_unref(bob);
+* @endcode
+* As it’s hard to guest which parameters the construct expects, it’s common to use macro (or function) helpers. In our example the macro will look like this:
+* @code
+// create a person
+#define PERSON_CREATE(name) tsk_object_new(&person_def_t, (const char*)name)
+* @endcode
+*
+* As the destructor has fixed parameters, there is a common macro to destroy all kind of well-defined objects. <br>
+* TSK_OBJECT_SAFE_FREE() is used to destroy any object. <br>
+* The object will be freed only if; when decremented by 1 the reference count of the object is equal to zero. In all case (freed or not) the pointer value will be set to NULL.<br>
+* The above example can be rewritten like this:<br>
+* @code
+#include "tsk.h"
+
+// create a person: will call the constructor
+person_t* bob = PERSON_CREATE("bob");
+// create bob's girlfriend
+bob->girlfriend = PERSON_CREATE("alice");
+// delete bob: will delete both bob and bob's girlfriend field by calling their destructors
+TSK_OBJECT_SAFE_FREE(bob);
+* @endcode
+*
+* <h2>6.8 Lists</h2>
+*
+* <h2>7 Threading</h2>
+* The framework provides an operating system agnostic threading functions for both WIN32 and Unix-like systems.<br>
+*
+* <h2>7.1 Threads</h2>
+* You don’t need thousands of functions to manage threads. In the Framework we only need to create, pause and destroy threads.<br>
+* Threads can be created using @ref tsk_thread_create() and joined using @ref tsk_thread_join().<br>
+* You can temporary cease the executing of a thread by calling @ref tsk_thread_sleep().<br>
+* @code
+#include "tsk.h"
+
+void* MyThreadFunction(void *arg)
+{
+ printf("arg=%d", *((int*)arg));
+ return tsk_null;
+}
+
+void test_threads()
+{
+ void* tid[1] = {tsk_null}; // thread id
+ int arg = 112; // arg to pass to the function
+
+ // creates the thread
+ tsk_thread_create(&tid[0], MyThreadFunction, &arg);
+
+ // joins the thread
+ tsk_thread_join(&(tid[0]));
+}
+* @endcode
+*
+* <h2>7.2 Mutexes</h2>
+* Mutexes (Mutual exclusion) are used to protect a portion of code or function against concurrent access. Concurrent access happens when two or several threads try to execute the same portion of code at nearly the same time.<br>
+* @code
+#include "tsk.h"
+
+// create the mutext
+tsk_mutex_handle_t *mutex = tsk_mutex_create();
+
+tsk_mutex_lock(mutex);
+// ...portion of code to protect
+tsk_mutex_unlock(mutex);
+
+// destroy the mutex
+tsk_mutex_destroy(&mutex);
+* @endcode
+* Mutexes are not well-defined objects; you should use @ref tsk_mutex_destroy instead of TSK_OBJECT_SAFE_FREE() to destroy them.<br>
+*
+* <h2>7.3 Thread-Safe Objects</h2>
+*
+* Any C Structure could be declared as thread-safe using @ref TSK_DECLARE_SAFEOBJ macro. It’s not mandatory for the object to be well-defined.<br>
+* A thread-safe object is initialized using @ref tsk_safeobj_init() and deinitilized using @ref tsk_safeobj_deinit(). To lock and unlock a portion of code which accesses the object you should use @ref tsk_safeobj_lock() and @ref tsk_safeobj_unlock() respectively.<br>
+*
+* <h2>7.4 Semaphores</h2>
+* Only counting semaphores are supported by the framework.
+* Counting semaphores are used to control the access to a portion of code which might be executed by multiple threads. A thread will have rights to execute the portion of code only if the semaphore’s internal counter value is different than zero. Before executing the code to control, a thread should decrement the counter to check if it has permit.<br>
+* @code
+#include "tsk.h"
+
+// (create the semaphore)
+tsk_semaphore_handle_t *sem = tsk_semaphore_create();
+// (increment the counter)
+tsk_semaphore_increment(sem);
+// (decrement the counter)
+tsk_semaphore_decrement(sem);
+// (destoy the semaphore)
+tsk_semaphore_destroy(&sem);
+* @endcode
+* Semaphores are not well-defined objects; you should use @ref tsk_semaphore_destroy instead of TSK_OBJECT_SAFE_FREE() to destroy them.<br>
+* Mutexes are binary semaphores (counter value is always equals to 1 or 0).<br>
+*
+* <h2>7.5 Condition Variables</h2>
+* Condition variables are used to control the access to a portion of code which might be executed by multiple threads. Each thread will block until a certain condition is signaled or ms milliseconds have passed.<br>
+* @ref tsk_condwait_create is used to create a condition variable, @ref tsk_condwait_wait() to wait indefinitely until the condition is signaled and @ref tsk_condwait_timedwait() to wait until the condition is signaled or ms milliseconds have passed.<br>
+* @ref tsk_condwait_signal() is used to alert the first waiting thread that the condition is now true and @ref tsk_condwait_broadcast() is used to alert all waiting threads.<br>
+* Condition variables are not well-defined objects; you should use @ref tsk_condwait_destroy() instead of TSK_OBJECT_SAFE_FREE() to destroy them.<br>
+*
+* <h2>7.6 Runnable</h2>
+* A <i>runnable</i> object is a well-defined object and is declared using @ref TSK_DECLARE_RUNNABLE() macro.<br>
+* A <i>runnable</i> object must be explicitly started using @ref tsk_runnable_start() and is implicitly stopped when destroyed. You can explicitly stop the object by calling @ref tsk_runnable_stop().<br>
+*
+* <h2>8 Final Sate Machine</h2>
+*
+* <h2>9 Timer Manager</h2>
+*
+*/
+
+
diff --git a/tinySAK/src/tsk.h b/tinySAK/src/tsk.h
new file mode 100644
index 0000000..2fa06ed
--- /dev/null
+++ b/tinySAK/src/tsk.h
@@ -0,0 +1,70 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk.h
+ * @brief This file contains all headers needed to export public API functions.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+
+#ifndef _TINYSAK_SAK_H_
+#define _TINYSAK_SAK_H_
+
+#include "tinysak_config.h"
+
+TSK_BEGIN_DECLS
+
+#include "tsk_list.h"
+#include "tsk_string.h"
+#include "tsk_buffer.h"
+#include "tsk_memory.h"
+#include "tsk_url.h"
+#include "tsk_params.h"
+#include "tsk_options.h"
+#include "tsk_fsm.h"
+
+#include "tsk_time.h"
+#include "tsk_timer.h"
+#include "tsk_condwait.h"
+#include "tsk_mutex.h"
+#include "tsk_semaphore.h"
+#include "tsk_thread.h"
+#include "tsk_runnable.h"
+#include "tsk_safeobj.h"
+#include "tsk_object.h"
+
+#include "tsk_debug.h"
+
+#include "tsk_ppfcs16.h"
+#include "tsk_sha1.h"
+#include "tsk_md5.h"
+#include "tsk_hmac.h"
+#include "tsk_base64.h"
+#include "tsk_uuid.h"
+#include "tsk_ragel_state.h"
+
+TSK_END_DECLS
+
+#endif /* _TINYSAK_SAK_H_ */
+
diff --git a/tinySAK/src/tsk_base64.c b/tinySAK/src/tsk_base64.c
new file mode 100644
index 0000000..d94ef5c
--- /dev/null
+++ b/tinySAK/src/tsk_base64.c
@@ -0,0 +1,236 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_base64.c
+ * @brief Base64 encoder and decoder as per RFC 4648.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tsk_base64.h"
+
+#include "tsk_memory.h"
+
+/**@defgroup tsk_base64_group Base64 encoder/decoder as per RFC 4648.
+* @brief Provides base64 encoder and decoder functions.
+*/
+
+/** Pad char.*/
+#define TSK_BASE64_PAD '='
+
+/** Encoding block size. */
+#define TSK_BASE64_ENCODE_BLOCK_SIZE 3 /* 24-bit input group */
+/** Decoding block size. */
+#define TSK_BASE64_DECODE_BLOCK_SIZE 4
+
+/*==================================================================
+ Value Encoding Value Encoding Value Encoding Value Encoding
+ 0 A 17 R 34 i 51 z
+ 1 B 18 S 35 j 52 0
+ 2 C 19 T 36 k 53 1
+ 3 D 20 U 37 l 54 2
+ 4 E 21 V 38 m 55 3
+ 5 F 22 W 39 n 56 4
+ 6 G 23 X 40 o 57 5
+ 7 H 24 Y 41 p 58 6
+ 8 I 25 Z 42 q 59 7
+ 9 J 26 a 43 r 60 8
+ 10 K 27 b 44 s 61 9
+ 11 L 28 c 45 t 62 +
+ 12 M 29 d 46 u 63 /
+ 13 N 30 e 47 v
+ 14 O 31 f 48 w (pad) =
+ 15 P 32 g 49 x
+ 16 Q 33 h 50 y
+
+ RFC 4548 - Table 1: The Base 64 Alphabet
+*/
+
+/**@ingroup tsk_base64_group
+* Encodes arbitrary data into base64 format.
+* @param input The input data to encode in base64 format.
+* @param input_size The size of the @a input data.
+* @param output A pointer where to copy the encoded data.
+* If you don't know what will be the size of the output result then set the pointer value to NULL to let the function allocate it of you.
+* In all case it is up to you to free the @a ouput.
+* You can also use @ref TSK_BASE64_ENCODE_LEN to allocate the buffer before calling this method.
+*
+* @retval The size of the encoded data (sizeof(@a output))
+*/
+tsk_size_t tsk_base64_encode(const uint8_t* input, tsk_size_t input_size, char **output)
+{
+ static const char* TSK_BASE64_ENCODE_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+ /*=================================================================================
+ content T S K
+ ASCII 0x54 0x53 0x4B
+ Binary 0101 0100 0101 0011 0100 1011
+ ------------------------------------------------------------------------------
+ ------------------------------------------------------------------------------
+ Packs of 6bits 010101 000101 001101 001011
+ Indexes 21 5 13 11
+ Base64 encoded V F N L <=== HERE IS THE RESULT OF tsk_base64_encode("TSK")
+ */
+
+ tsk_size_t i = 0;
+ tsk_size_t output_size = 0;
+
+ /* Caller provided his own buffer? */
+ if(!*output){
+ *output = tsk_calloc(1, (TSK_BASE64_ENCODE_LEN(input_size)+1));
+ }
+
+ /* Too short? */
+ if(input_size < TSK_BASE64_ENCODE_BLOCK_SIZE){
+ goto quantum;
+ }
+
+ do{
+ *(*output + output_size++) = TSK_BASE64_ENCODE_ALPHABET [ input[i]>> 2 ];
+ *(*output + output_size++) = TSK_BASE64_ENCODE_ALPHABET [ (input[i]<<4 | input[i+1]>>4) & 0x3F ];
+ *(*output + output_size++) = TSK_BASE64_ENCODE_ALPHABET [ (input[i+1]<<2 | input[i+2]>>6) & 0x3F ];
+ *(*output + output_size++) = TSK_BASE64_ENCODE_ALPHABET [ input[i+2] & 0x3F ];
+
+ i += TSK_BASE64_ENCODE_BLOCK_SIZE;
+ }
+ while(( i+ TSK_BASE64_ENCODE_BLOCK_SIZE) <= input_size);
+
+quantum:
+
+ if((input_size - i) == 1){
+ /* The final quantum of encoding input is exactly 8 bits; here, the
+ final unit of encoded output will be two characters followed by
+ two "=" padding characters.
+ */
+ *(*output + output_size++) = TSK_BASE64_ENCODE_ALPHABET [ input[i]>> 2 ];
+ *(*output + output_size++) = TSK_BASE64_ENCODE_ALPHABET [ input[i]<<4 & 0x3F ];
+ *(*output + output_size++) = TSK_BASE64_PAD, *(*output + output_size++) = TSK_BASE64_PAD;
+ }
+ else if((input_size-i) == 2){
+ /* The final quantum of encoding input is exactly 16 bits; here, the
+ final unit of encoded output will be three characters followed by
+ one "=" padding character.
+ */
+ *(*output + output_size++) = TSK_BASE64_ENCODE_ALPHABET [ input[i]>> 2 ];
+ *(*output + output_size++) = TSK_BASE64_ENCODE_ALPHABET [ (input[i]<<4 | input[i+1]>>4) & 0x3F ];
+ *(*output + output_size++) = TSK_BASE64_ENCODE_ALPHABET [ (input[i+1]<<2 | input[i+2]>>6) & 0x3F ];
+ *(*output + output_size++) = TSK_BASE64_PAD;
+ }
+
+ return output_size;
+}
+
+/**@ingroup tsk_base64_group
+* Decodes arbitrary base64 data.
+* @param input The input base64 data to decode.
+* @param input_size The size of the @a input data.
+* @param output A pointer where to copy the decoded data.
+* If you don't know what will be the size of the output result then set the pointer value to NULL to let the function allocate it of you.
+* In all case it is up to you to free the @a ouput.
+* You can also use @ref TSK_BASE64_DECODE_LEN to allocate the buffer before calling this method.
+*
+* @retval The size of the decoded data (sizeof(@a output))
+*/
+tsk_size_t tsk_base64_decode(const uint8_t* input, tsk_size_t input_size, char **output)
+{
+ static const uint8_t TSK_BASE64_DECODE_ALPHABET[256] =
+ {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1,
+ 62,
+ -1, -1, -1,
+ 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61,
+ -1, -1, -1, -1, -1, -1, -1,
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,
+ -1, -1, -1, -1, -1, -1,
+ 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1,
+ };
+
+ tsk_size_t i, pay_size;
+ tsk_size_t output_size = 0;
+
+ /* Caller provided his own buffer? */
+ if(!*output){
+ *output = tsk_calloc(1, (TSK_BASE64_DECODE_LEN(input_size)+1));
+ }
+
+ /* Count pads and remove them from the base64 string */
+ for(i = input_size, pay_size = input_size; i > 0; i--){
+ if(input[i-1] == TSK_BASE64_PAD) {
+ pay_size--;
+ }
+ else{
+ break;
+ }
+ }
+
+ /* Reset i */
+ i = 0;
+
+ if(pay_size < TSK_BASE64_DECODE_BLOCK_SIZE){
+ goto quantum;
+ }
+
+ do{
+ *(*output + output_size++) = (TSK_BASE64_DECODE_ALPHABET [ input[i] ]<< 2
+ | TSK_BASE64_DECODE_ALPHABET [ input[i+1] ]>>4);
+ *(*output + output_size++) = (TSK_BASE64_DECODE_ALPHABET [ input[i+1] ]<< 4
+ | TSK_BASE64_DECODE_ALPHABET [ input[i+2] ]>>2);
+ *(*output + output_size++) = (TSK_BASE64_DECODE_ALPHABET [ input[i+2] ]<<6
+ | TSK_BASE64_DECODE_ALPHABET [ input[i+3] ]);
+
+ i += TSK_BASE64_DECODE_BLOCK_SIZE;
+ }
+ while(( i+ TSK_BASE64_DECODE_BLOCK_SIZE) <= pay_size);
+
+quantum:
+
+ if((input_size - pay_size) == 1){
+ *(*output + output_size++) = (TSK_BASE64_DECODE_ALPHABET [ input[i] ]<< 2
+ | TSK_BASE64_DECODE_ALPHABET [ input[i+1] ]>>4);
+ *(*output + output_size++) = (TSK_BASE64_DECODE_ALPHABET [ input[i+1] ]<< 4
+ | TSK_BASE64_DECODE_ALPHABET [ input[i+2] ]>>2);
+ }
+ else if((input_size-pay_size) == 2){
+ *(*output + output_size++) = (TSK_BASE64_DECODE_ALPHABET [ input[i] ]<< 2
+ | TSK_BASE64_DECODE_ALPHABET [ input[i+1] ]>>4);
+ }
+
+ return output_size;
+}
diff --git a/tinySAK/src/tsk_base64.h b/tinySAK/src/tsk_base64.h
new file mode 100644
index 0000000..369688c
--- /dev/null
+++ b/tinySAK/src/tsk_base64.h
@@ -0,0 +1,53 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_base64.h
+ * @brief Base64 encoder and decoder as per RFC 4648.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef TINYSAK_BASE64_H
+#define TINYSAK_BASE64_H
+
+#include "tinysak_config.h"
+
+TSK_BEGIN_DECLS
+
+/**@ingroup tsk_base64_group
+* Guess the output(encoded) size.
+* @param IN_LEN The input size.
+*/
+#define TSK_BASE64_ENCODE_LEN(IN_LEN) ((2 + (IN_LEN) - (((IN_LEN) + 2) % 3)) * 4 / 3)
+/**@ingroup tsk_base64_group
+* Guess the output(decoded) size.
+* @param IN_LEN The input size.
+*/
+#define TSK_BASE64_DECODE_LEN(IN_LEN) (((IN_LEN * 3)/4) + 2)
+
+TINYSAK_API tsk_size_t tsk_base64_encode(const uint8_t* input, tsk_size_t input_size, char **output);
+TINYSAK_API tsk_size_t tsk_base64_decode(const uint8_t* input, tsk_size_t input_size, char **output);
+
+TSK_END_DECLS
+
+#endif /* TINYSAK_BASE64_H */
diff --git a/tinySAK/src/tsk_binaryutils.c b/tinySAK/src/tsk_binaryutils.c
new file mode 100644
index 0000000..6702e20
--- /dev/null
+++ b/tinySAK/src/tsk_binaryutils.c
@@ -0,0 +1,33 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_binaryutils.c
+ * @brief Utility functions for binary manipulation.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tsk_binaryutils.h"
+
+/**@defgroup tsk_binaryutils_group Binary utility functions.
+*/
diff --git a/tinySAK/src/tsk_binaryutils.h b/tinySAK/src/tsk_binaryutils.h
new file mode 100644
index 0000000..79943ba
--- /dev/null
+++ b/tinySAK/src/tsk_binaryutils.h
@@ -0,0 +1,157 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_binaryutils.h
+ * @brief Binary utils.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef _TINYSAK_BINARYUTILS_H_
+#define _TINYSAK_BINARYUTILS_H_
+
+#include "tinysak_config.h"
+
+#include <stdio.h>
+
+TSK_BEGIN_DECLS
+
+/**@ingroup tsk_binaryutils_group
+* Reverse (bit per bit) a 2-byte value.
+* @param value The 2-byte value to reverse.
+*/
+#define TSK_BINARY_REVERSE_2BYTE(value) ((Tsk_BitReverseTable256[value & 0xff] << 8) | (Tsk_BitReverseTable256[(value >> 8)]))
+
+/**@ingroup tsk_binaryutils_group
+* Converts to uint8_t pointer.
+*/
+#define TSK_TO_U8(buffer) ((uint8_t*)buffer)
+/**@ingroup tsk_binaryutils_group
+* Gets the value of the fist byte.
+*/
+#define TSK_BINARY_GET_1BYTE(buffer) *TSK_TO_U8(buffer)// 1-byte
+
+/**@ingroup tsk_binaryutils_group
+* Converts from Little to Big endian.
+*/
+static uint16_t TSK_LSB_2_MSB( void const * buffer )
+{
+ const uint8_t* dummy = (const uint8_t*)buffer;
+ return ( ((uint16_t)dummy[0] << 8) | dummy[1] );
+}
+
+/**@ingroup tsk_binaryutils_group
+* @def TSK_BINARY_GET_2BYTES
+* Gets the first 2-bytes value.
+*/
+/**@ingroup tsk_binaryutils_group
+* @def TSK_BINARY_SET_2BYTES
+* Sets the first 2-bytes value.
+*/
+
+#if 0 /*BIG_ENDIAN*/// Do not change this (it's for my own tests)
+# define TSK_BINARY_GET_2BYTES(buffer) *((uint16_t*)buffer)
+# define TSK_BINARY_SET_2BYTES(buffer, value) *((uint16_t*)buffer)=value
+#else
+# define TSK_BINARY_GET_2BYTES(buffer) TSK_LSB_2_MSB(buffer)
+# define TSK_BINARY_SET_2BYTES(buffer, value) \
+ {uint16_t __value__ = value; \
+ uint8_t*__buffer__ = buffer; \
+ (__buffer__[0]) = (__value__ >> 8); \
+ (__buffer__[1]) = (__value__ & 0xff);}
+#endif
+
+/////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////
+
+// RFC 3320 - 7.3. Uploading UDVM bytecode
+static const uint16_t sigcomp_encoding_destination[]
+= { 0, 128, 192, 256, 320, 384, 448, 512, 576, 640, 704, 768, 832, 896, 960, 1024 };
+
+// RFC 3320 - 7.2. Accessing Stored State
+static const uint8_t sigcomp_encoding_partial_id_length[]
+= { 0, 6, 9, 12 };
+
+// RFC 3320 - 3.3.1. Memory Size and UDVM Cycles
+static const uint8_t sigcomp_encoding_cycles_per_bit[]
+= { 16, 32, 64, 128 };
+static const uint32_t sigcomp_encoding_state_memory_size[]
+= { 0, 2048, 4096, 8192, 16384, 32768, 65536, 131072 };
+static const uint32_t sigcomp_encoding_decompression_memory_size[]
+= { 0, 2048, 4096, 8192, 16384, 32768, 65536, 131072 }; // the bit pattern 000 cannot be used.
+
+// 3.3.1. Memory Size and UDVM Cycles
+// 3.3. SigComp Parameters
+static const uint8_t sigcomp_encoding_cpb[]
+= { 16, 32, 64, 128 };
+static const uint32_t sigcomp_encoding_sms[]
+= { 0, 2048, 4096, 8192, 16384, 32768, 65536, 131072 };
+static const uint32_t sigcomp_encoding_dms[]
+= { 0, 2048, 4096, 8192, 16384, 32768, 65536, 131072 }; // the bit pattern 000 cannot be used.
+
+
+// RFC 3320: Figure 10: Bytecode for a multitype (%) operand
+static const int8_t operand_multitype_indexes [256] =
+{
+1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+9,
+10,
+-1, -1, -1, -1,
+3, 3,
+4, 4, 4, 4, 4, 4, 4, 4,
+6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
+7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
+5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5
+};
+
+// Used LSB<->MSB bits reverse/swap
+/**@ingroup tsk_binaryutils_group
+* Lookup table for bit reversing.
+*/
+static const unsigned char Tsk_BitReverseTable256[] =
+{
+ 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
+ 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
+ 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
+ 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
+ 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
+ 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
+ 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
+ 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
+ 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
+ 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
+ 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
+ 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
+ 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
+ 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
+ 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
+ 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
+};
+
+TSK_END_DECLS
+
+#endif /* _TINYSAK_BINARYUTILS_H_ */
+
diff --git a/tinySAK/src/tsk_buffer.c b/tinySAK/src/tsk_buffer.c
new file mode 100644
index 0000000..4ae1f4c
--- /dev/null
+++ b/tinySAK/src/tsk_buffer.c
@@ -0,0 +1,363 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_buffer.c
+ * @brief Buffer manager.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tsk_buffer.h"
+
+#include "tsk_memory.h"
+#include "tsk_debug.h"
+
+#if defined(_WIN32_WCE)
+# include "tsk_string.h" /* tsk_strlen() */
+#endif
+
+
+#include <stdio.h>
+#include <string.h>
+
+/**@defgroup tsk_buffer_group Buffer management.
+*/
+
+#if defined(_MSC_VER) || TSK_UNDER_WINDOWS
+# define vsnprintf _vsnprintf
+#endif
+
+/**@ingroup tsk_buffer_group
+* Creates new buffer.
+* @param data A pointer to the data to copy into the newly created buffer.
+* @param size The size of the data to copy.
+* @retval A new buffer object.
+* @sa @ref tsk_buffer_create_null
+*/
+tsk_buffer_t* tsk_buffer_create(const void* data, tsk_size_t size)
+{
+ return tsk_object_new(tsk_buffer_def_t, data, size);
+}
+
+/**@ingroup tsk_buffer_group
+* Creates a new empty buffer.
+* @retval A new empty buffer object.
+* @sa tsk_buffer_create.
+*/
+tsk_buffer_t* tsk_buffer_create_null()
+{
+ return tsk_buffer_create(tsk_null, 0);
+}
+
+/**@ingroup tsk_buffer_group
+* Appends new data to the buffer.
+* @param self The buffer to append to. The buffer should be created using @ref tsk_buffer_create or @ref tsk_buffer_create_null.
+* @param format A string with embedded tag to be substituted.
+* @param ... List of parameters.
+* @retval Zero if succeed and non-zero error code otherwise.
+* @sa @ref tsk_buffer_append.
+*
+* @code
+* tsk_buffer_t* buffer = tsk_buffer_create_null();
+* tsk_buffer_append_2(buffer, "str1=%s, c1=%c and val1=%x", "str1", 'c', 0x2554);
+* printf(TSK_BUFFER_TO_STRING(buffer));
+* TSK_OBJECT_SAFE_FREE(buffer);
+* @endcode
+*/
+int tsk_buffer_append_2(tsk_buffer_t* self, const char* format, ...)
+{
+ /*
+ * I suppose that sizeof(char) = 1-byte
+ */
+ int len = 0;
+ va_list ap;
+ char *buffer;
+ tsk_size_t oldsize;
+ va_list ap2;
+
+ if(!self){
+ return -1;
+ }
+
+ oldsize = self->size;
+ buffer = (char*)TSK_BUFFER_DATA(self);
+
+ /* initialize variable arguments (needed for 64bit platforms where vsnprintf will change the va_list) */
+ va_start(ap, format);
+ va_start(ap2, format);
+
+ /* compute destination len for windows mobile
+ */
+#if defined(_WIN32_WCE)
+ {
+ int n;
+ len = (tsk_strlen(format)*2);
+ buffer = tsk_realloc(buffer, (oldsize+len));
+ for(;;){
+ if( (n = vsnprintf((char*)(buffer + oldsize), len, format, ap)) >= 0 && (n<=len) ){
+ len = n;
+ break;
+ }
+ else{
+ len += 10;
+ buffer = tsk_realloc(buffer, (oldsize+len));
+ }
+ }
+ }
+#else
+ len = vsnprintf(tsk_null, 0, format, ap);
+ buffer = tsk_realloc(buffer, oldsize+len+1);
+ vsnprintf((buffer + oldsize), len
+#if !defined(_MSC_VER) || defined(__GNUC__)
+ +1
+#endif
+ , format, ap2);
+#endif
+
+ /* reset variable arguments */
+ va_end(ap);
+ va_end(ap2);
+
+ self->data = buffer;
+ self->size = (oldsize+len);
+
+ return 0;
+}
+
+/**@ingroup tsk_buffer_group
+* Appends data to the buffer.
+* @param self The buffer to append to. The buffer should be created using @ref tsk_buffer_create or @ref tsk_buffer_create_null.
+* @param data The data to append to the buffer.
+* @param size The size of the @a data to append.
+* @retval Zero if succeed and non-zero error code otherwise.
+* @sa @ref tsk_buffer_append_2.
+*
+* @code
+* tsk_buffer_t* buffer = tsk_buffer_create_null();
+* tsk_buffer_append(buffer, "doubango", tsk_strlen("doubango"));
+* printf(TSK_BUFFER_TO_STRING(buffer));
+* TSK_OBJECT_SAFE_FREE(buffer);
+* @endcode
+*/
+int tsk_buffer_append(tsk_buffer_t* self, const void* data, tsk_size_t size)
+{
+ if(self && data && size){
+ tsk_size_t oldsize = self->size;
+ tsk_size_t newsize = oldsize + size;
+
+ if(oldsize){
+ self->data = tsk_realloc(self->data, newsize);
+ }
+ else{
+ self->data = tsk_calloc(size, sizeof(uint8_t));
+ }
+
+ if(self->data){
+ memcpy((void*)(TSK_BUFFER_TO_U8(self) + oldsize), data, size);
+ self->size = newsize;
+ return 0;
+ }
+ }
+ else{
+ TSK_DEBUG_ERROR("Invalid parameter");
+ }
+ return -1;
+}
+
+/**@ingroup tsk_buffer_group
+* Reallocates the buffer.
+* @param self The buffer to realloc.
+* @param size The new size.
+* @retval Zero if succeed and non-zero error code otherwise.
+*/
+int tsk_buffer_realloc(tsk_buffer_t* self, tsk_size_t size)
+{
+ if(self)
+ {
+ if(size == 0){
+ return tsk_buffer_cleanup(self);
+ }
+
+ if(self->size == 0){
+ self->data = tsk_calloc(size, sizeof(uint8_t));
+ }
+ else{
+ self->data = tsk_realloc(self->data, size);
+ }
+
+ self->size = size;
+ return 0;
+ }
+ return -1;
+}
+
+/**@ingroup tsk_buffer_group
+* Removes a chunck of data from the buffer.
+* @param self The buffer from which to remove the chunck.
+* @param position The chunck start position.
+* @param size The size of the chunck.
+* @retval Zero if succeed and non-zero error code otherwise.
+*/
+int tsk_buffer_remove(tsk_buffer_t* self, tsk_size_t position, tsk_size_t size)
+{
+ if(self && self->data && size){
+ if((position == 0) && ((position + size) >= self->size)){ /* Very common case. */
+ return tsk_buffer_cleanup(self);
+ }
+ else if((position + size) < self->size){
+ memcpy(((uint8_t*)self->data) + position, ((uint8_t*)self->data) + position + size,
+ self->size-(position+size));
+ return tsk_buffer_realloc(self, (self->size-size));
+ }
+ }
+ return -1;
+}
+
+/**@ingroup tsk_buffer_group
+* Inserts a chunck of data into the buffer.
+* @param self The buffer to insert to.
+* @param position The starting position to insert to.
+* @param data A pointer to the chunck to insert.
+* @param size The size of the chunck.
+* @retval Zero if succeed and non-zero error code otherwise.
+*/
+int tsk_buffer_insert(tsk_buffer_t* self, tsk_size_t position, const void* data, tsk_size_t size)
+{
+ if(self && size)
+ {
+ int ret;
+ tsk_size_t tomove;
+
+ if(position > self->size){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -2;
+ }
+
+ tomove = (self->size - position);
+
+ if((ret = tsk_buffer_realloc(self, (self->size + size)))){
+ return ret;
+ }
+ memmove(((uint8_t*)self->data) + position + size, ((uint8_t*)self->data) + position,
+ tomove/*self->size - (position + size)*/);
+
+
+ if(data){
+ memcpy(((uint8_t*)self->data) + position, data, size);
+ }
+ else{
+ memset(((uint8_t*)self->data) + position, 0, size);
+ }
+
+ return 0;
+ }
+ return -1;
+}
+
+/**@ingroup tsk_buffer_group
+* Cleanups the internal data and reset the size.
+* @param self The buffer holding the internal data to free.
+* @retval Zero if succeed and non-zero error code otherwise.
+*/
+int tsk_buffer_cleanup(tsk_buffer_t* self)
+{
+ if(self && self->data){
+ tsk_free(&(self->data));
+ self->size = 0;
+ }
+ return 0;
+}
+
+/**@ingroup tsk_buffer_group
+* Takes the ownership of the @a data. If the destination buffer had data, then it will
+* be cleaned up.
+* @param self The buffer
+* @param data
+* @param size
+* @retval Zero if succeed and non-zero error code otherwise.
+*/
+int tsk_buffer_takeownership(tsk_buffer_t* self, void** data, tsk_size_t size)
+{
+ if(!self || !data || !*data || !size){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ if(self->data){
+ tsk_free(&(self->data));
+ }
+ self->data = *data;
+ self->size = size;
+ *data = tsk_null;
+
+ return 0;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+//=================================================================================================
+// Buffer object definition
+//
+static tsk_object_t* tsk_buffer_ctor(tsk_object_t * self, va_list * app)
+{
+ tsk_buffer_t *buffer = self;
+ const void *data = va_arg(*app, const void *);
+ tsk_size_t size = va_arg(*app, tsk_size_t);
+
+ if(data && size){
+ buffer->data = tsk_calloc((size+1), sizeof(uint8_t));
+ memcpy(buffer->data, data, size);
+ buffer->size = size;
+ }
+ return self;
+}
+
+static tsk_object_t* tsk_buffer_dtor(tsk_object_t * self)
+{
+ tsk_buffer_t *buffer = self;
+ if(buffer){
+ TSK_FREE(buffer->data);
+ buffer->size = 0;
+ }
+
+ return self;
+}
+
+static const tsk_object_def_t tsk_buffer_def_s =
+{
+ sizeof(tsk_buffer_t),
+ tsk_buffer_ctor,
+ tsk_buffer_dtor,
+ tsk_null,
+};
+const tsk_object_def_t *tsk_buffer_def_t = &tsk_buffer_def_s;
+
diff --git a/tinySAK/src/tsk_buffer.h b/tinySAK/src/tsk_buffer.h
new file mode 100644
index 0000000..b5df8aa
--- /dev/null
+++ b/tinySAK/src/tsk_buffer.h
@@ -0,0 +1,102 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_buffer.h
+ * @brief Buffer manager.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef _TINYSAK_BUFFER_H_
+#define _TINYSAK_BUFFER_H_
+
+#include "tinysak_config.h"
+#include "tsk_list.h"
+
+/**@ingroup tsk_buffer_group
+* @def TSK_BUFFER
+* Converts to @ref tsk_buffer_t object.
+* @param self @ref tsk_buffer_t object.
+*/
+/**@ingroup tsk_buffer_group
+* @def TSK_BUFFER_DATA
+* Gets the internal buffer.
+* @param self @ref tsk_buffer_t object.
+*/
+/**@ingroup tsk_buffer_group
+* @def TSK_BUFFER_SIZE
+* Gets the size of the internal buffer.
+* @param self @ref tsk_buffer_t object.
+*/
+
+TSK_BEGIN_DECLS
+
+
+#define TSK_BUFFER(self) ((tsk_buffer_t*)self)
+#define TSK_BUFFER_DATA(self) (self ? TSK_BUFFER(self)->data : tsk_null)
+#define TSK_BUFFER_SIZE(self) (self ? TSK_BUFFER(self)->size : 0)
+
+/**@ingroup tsk_buffer_group
+* @def TSK_BUFFER_TO_STRING
+* Gets a the internal buffer as a pointer to a string (const char*).
+* @param self @ref tsk_buffer_t object.
+*/
+/**@ingroup tsk_buffer_group
+* @def TSK_BUFFER_TO_U8
+* Gets a the internal buffer as a pointer to an unsigned string (uint8_t*).
+* @param self @ref tsk_buffer_t object.
+*/
+#define TSK_BUFFER_TO_STRING(self) (self ? (const char*)TSK_BUFFER_DATA(self) : tsk_null)
+#define TSK_BUFFER_TO_U8(self) (self ? (uint8_t*)TSK_BUFFER_DATA(self) : tsk_null)
+
+/**@ingroup tsk_buffer_group
+* Buffer object.
+*/
+typedef struct tsk_buffer_s
+{
+ TSK_DECLARE_OBJECT;
+
+ void *data; /**< Interanl data. */
+ tsk_size_t size; /**< The size of the internal data. */
+}
+tsk_buffer_t;
+
+typedef tsk_list_t tsk_buffers_L_t; /**<@ingroup tsk_buffer_group List of @ref tsk_buffer_t elements. */
+
+TINYSAK_API tsk_buffer_t* tsk_buffer_create(const void* data, tsk_size_t size);
+TINYSAK_API tsk_buffer_t* tsk_buffer_create_null();
+
+TINYSAK_API int tsk_buffer_append_2(tsk_buffer_t* self, const char* format, ...);
+TINYSAK_API int tsk_buffer_append(tsk_buffer_t* self, const void* data, tsk_size_t size);
+TINYSAK_API int tsk_buffer_realloc(tsk_buffer_t* self, tsk_size_t size);
+TINYSAK_API int tsk_buffer_remove(tsk_buffer_t* self, tsk_size_t position, tsk_size_t size);
+TINYSAK_API int tsk_buffer_insert(tsk_buffer_t* self, tsk_size_t position, const void*data, tsk_size_t size);
+TINYSAK_API int tsk_buffer_cleanup(tsk_buffer_t* self);
+TINYSAK_API int tsk_buffer_takeownership(tsk_buffer_t* self, void** data, tsk_size_t size);
+
+TINYSAK_GEXTERN const tsk_object_def_t *tsk_buffer_def_t;
+
+TSK_END_DECLS
+
+#endif /* _TINYSAK_BUFFER_H_ */
+
diff --git a/tinySAK/src/tsk_common.h b/tinySAK/src/tsk_common.h
new file mode 100644
index 0000000..2383f4d
--- /dev/null
+++ b/tinySAK/src/tsk_common.h
@@ -0,0 +1,70 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_common.h
+ * Commons.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+
+#ifndef _TINYSAK_COMMON_H_
+#define _TINYSAK_COMMON_H_
+
+typedef int tsk_boolean_t;
+#define tsk_bool_t tsk_boolean_t
+
+/**@def tsk_true
+* True (1).
+*/
+/**@def tsk_false
+* False (0).
+*/
+#define tsk_true 1
+#define tsk_false 0
+
+#define TSK_MIN(a,b) (((a) < (b)) ? (a) : (b))
+#define TSK_MAX(a,b) (((a) > (b)) ? (a) : (b))
+#define TSK_ABS(a) (((a)< 0) ? -(a) : (a))
+
+// used to avoid doing *((uint32_t*)ptr) which don't respect memory alignment on
+// some embedded platforms
+#define TSK_TO_UINT32(u8_ptr) (((uint32_t)(u8_ptr)[0]) | ((uint32_t)(u8_ptr)[1])<<8 | ((uint32_t)(u8_ptr)[2])<<16 | ((uint32_t)(u8_ptr)[3])<<24)
+#define TSK_TO_UINT16(u8_ptr) (((uint16_t)(u8_ptr)[0]) | ((uint16_t)(u8_ptr)[1])<<8)
+
+typedef int tsk_ssize_t; /**< Signed size */
+typedef unsigned int tsk_size_t; /**< Unsigned size */
+
+#if !defined(va_copy)
+# define tsk_va_copy(D, S) ((D) = (S))
+#else
+# define tsk_va_copy(D, S) va_copy((D), (S))
+#endif
+
+#ifdef NULL
+#define tsk_null NULL /**< Null pointer */
+#else
+#define tsk_null 0 /**< Null pointer */
+#endif
+
+#endif /* _TINYSAK_COMMON_H_ */
diff --git a/tinySAK/src/tsk_condwait.c b/tinySAK/src/tsk_condwait.c
new file mode 100644
index 0000000..08f9c89
--- /dev/null
+++ b/tinySAK/src/tsk_condwait.c
@@ -0,0 +1,303 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_condwait.c
+ * @brief Pthread/Windows functions for waiting an signaling on condition variables.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+
+#include "tsk_condwait.h"
+#include "tsk_memory.h"
+#include "tsk_debug.h"
+#include "tsk_time.h"
+#include <time.h>
+
+#if TSK_UNDER_WINDOWS
+# include <windows.h>
+# include "tsk_errno.h"
+# define CONDWAIT_S void
+ typedef HANDLE CONDWAIT_T;
+# define TIMED_OUT WAIT_TIMEOUT
+#else
+# include <sys/time.h>
+# include <pthread.h>
+# define CONDWAIT_S pthread_cond_t
+ typedef CONDWAIT_S* CONDWAIT_T;
+# define TIMED_OUT ETIMEDOUT
+#endif
+
+#if defined(__GNUC__) || defined (__SYMBIAN32__)
+# include <errno.h>
+#endif
+
+/**@defgroup tsk_condwait_group Pthread/Windows functions for waiting and signaling on condition variables (conwait).
+* @code
+* tsk_condwait_handle_t *condwait = tsk_condwait_create();
+* @endcode
+*
+* In thread-1:
+* @code
+* // Bock the current thread until the condition is opened or until 1000ms have passed.
+* int ret = tsk_condwait_timedwait(condwait, 1000);
+* @endcode
+*
+* In thread-2:
+* @code
+* // Wakes up
+* int ret = tsk_condwait_signal(condwait);
+* // or tsk_condwait_broadcast(condwait)
+* @endcode
+*
+* To free the condwait object:
+* @code
+* tsk_condwait_destroy(&condwait);
+* @endcode
+*/
+
+/**@ingroup tsk_condwait_group
+* Represents both PThread an Windows condwait object.
+*/
+typedef struct tsk_condwait_s
+{
+ CONDWAIT_T pcond; /**< Pthread handle pointing to the internal condwait object. */
+#if !TSK_UNDER_WINDOWS
+ tsk_mutex_handle_t* mutex; /**< Locker. */
+#endif
+}
+tsk_condwait_t;
+
+/**@ingroup tsk_condwait_group
+* Creates new conwait handle. You MUST call @ref tsk_condwait_destroy to free the handle.
+* @retval New condwait handle.
+* @sa @ref tsk_condwait_destroy.
+*/
+tsk_condwait_handle_t* tsk_condwait_create()
+{
+ tsk_condwait_t *condwait = tsk_calloc(1, sizeof(tsk_condwait_t));
+
+ if(condwait)
+ {
+#if TSK_UNDER_WINDOWS
+ condwait->pcond = CreateEvent(NULL, TRUE, FALSE, NULL);
+ if(!condwait->pcond)
+ {
+ TSK_FREE(condwait);
+ }
+#else
+ condwait->pcond = (CONDWAIT_T)tsk_calloc(1, sizeof(CONDWAIT_S));
+ if(pthread_cond_init(condwait->pcond, 0))
+ {
+ TSK_DEBUG_ERROR("Failed to initialize the new conwait.");
+ }
+
+ if(!(condwait->mutex = tsk_mutex_create()))
+ {
+ pthread_cond_destroy(condwait->pcond);
+
+ TSK_FREE(condwait);
+ TSK_DEBUG_ERROR("Failed to initialize the internal mutex.");
+ }
+#endif
+ }
+
+ if(!condwait)
+ {
+ TSK_DEBUG_ERROR("Failed to create new conwait.");
+ }
+ return condwait;
+}
+
+/**@ingroup tsk_condwait_group
+* Block the current thread until the condition is opened.
+* @param handle CondWait handle created using @ref tsk_condwait_create.
+* @retval Zero if succeed and non-zero otherwise.
+* @sa @ref tsk_condwait_timedwait.
+*/
+int tsk_condwait_wait(tsk_condwait_handle_t* handle)
+{
+ int ret = EINVAL;
+ tsk_condwait_t *condwait = (tsk_condwait_t*)handle;
+
+#if TSK_UNDER_WINDOWS
+ if((ret = (WaitForSingleObject(condwait->pcond, INFINITE) == WAIT_FAILED) ? -1 : 0)){
+ TSK_DEBUG_ERROR("WaitForSingleObject function failed: %d", ret);
+ }
+#else
+ if(condwait && condwait->mutex){
+ tsk_mutex_lock(condwait->mutex);
+ if(ret = pthread_cond_wait(condwait->pcond, (pthread_mutex_t*)condwait->mutex))
+ {
+ TSK_DEBUG_ERROR("pthread_cond_wait function failed: %d", ret);
+ }
+ tsk_mutex_unlock(condwait->mutex);
+ }
+#endif
+ return ret;
+}
+
+/**@ingroup tsk_condwait_group
+* Block the current thread until the condition is opened or until @a ms milliseconds have passed.
+* @param handle condwait handle created using @ref tsk_condwait_create.
+* @param ms The number of milliseconds to wait for a given condition.
+* @retval Zero if succeed and non-zero error code otherwise.
+* @sa @ref tsk_condwait_wait.
+*/
+int tsk_condwait_timedwait(tsk_condwait_handle_t* handle, uint64_t ms)
+{
+#if TSK_UNDER_WINDOWS
+ DWORD ret = WAIT_FAILED;
+#else
+ int ret = EINVAL;
+#endif
+ tsk_condwait_t *condwait = (tsk_condwait_t*)handle;
+
+#if TSK_UNDER_WINDOWS
+ if((ret = WaitForSingleObject(condwait->pcond, (DWORD)ms)) != WAIT_OBJECT_0)
+ {
+ if(ret == TIMED_OUT){
+ /* TSK_DEBUG_INFO("WaitForSingleObject function timedout: %d", ret); */
+ }
+ else{
+ TSK_DEBUG_ERROR("WaitForSingleObject function failed: %d", ret);
+ }
+ return ((ret == TIMED_OUT) ? 0 : ret);
+ }
+#else
+ if(condwait && condwait->mutex)
+ {
+ struct timespec ts = {0, 0};
+ struct timeval tv = {0, 0};
+ /*int rc =*/ tsk_gettimeofday(&tv, 0);
+
+ ts.tv_sec = ( tv.tv_sec + ((long)ms/1000) );
+ ts.tv_nsec += ( (tv.tv_usec * 1000) + ((long)ms % 1000 * 1000000) );
+ if(ts.tv_nsec > 999999999) ts.tv_sec+=1, ts.tv_nsec = ts.tv_nsec % 1000000000;
+
+ tsk_mutex_lock(condwait->mutex);
+ if(ret = pthread_cond_timedwait(condwait->pcond, (pthread_mutex_t*)condwait->mutex, &ts)){
+ if(ret == TIMED_OUT){
+ /* TSK_DEBUG_INFO("pthread_cond_timedwait function timedout: %d", ret); */
+ }
+ else{
+ TSK_DEBUG_ERROR("pthread_cond_timedwait function failed: %d", ret);
+ }
+ }
+
+ tsk_mutex_unlock(condwait->mutex);
+
+ return ((ret == TIMED_OUT) ? 0 : ret);
+ }
+#endif
+
+ return ret;
+}
+
+/**@ingroup tsk_condwait_group
+* Wakes up at least one thread that is currently waiting.
+* @param handle CondWait handle created using @ref tsk_condwait_create.
+* @retval Zero if succeed and non-zero otherwise.
+* @sa @ref tsk_condwait_broadcast.
+*/
+int tsk_condwait_signal(tsk_condwait_handle_t* handle)
+{
+ int ret = EINVAL;
+ tsk_condwait_t *condwait = (tsk_condwait_t*)handle;
+
+#if TSK_UNDER_WINDOWS
+ if(ret = ((SetEvent(condwait->pcond) && ResetEvent(condwait->pcond)) ? 0 : -1)){
+ ret = GetLastError();
+ TSK_DEBUG_ERROR("SetEvent/ResetEvent function failed: %d", ret);
+ }
+#else
+ if(condwait && condwait->mutex){
+ tsk_mutex_lock(condwait->mutex);
+
+ if(ret = pthread_cond_signal(condwait->pcond))
+ {
+ TSK_DEBUG_ERROR("pthread_cond_signal function failed: %d", ret);
+ }
+ tsk_mutex_unlock(condwait->mutex);
+ }
+#endif
+ return ret;
+}
+
+
+/**@ingroup tsk_condwait_group
+* Wakes up all threads that are currently waiting for the condition.
+* @param handle CondWait handle created using @ref tsk_condwait_create.
+* @retval Zero if succeed and non-zero otherwise.
+* @sa @ref tsk_condwait_signal.
+*/
+int tsk_condwait_broadcast(tsk_condwait_handle_t* handle)
+{
+ int ret = EINVAL;
+ tsk_condwait_t *condwait = (tsk_condwait_t*)handle;
+
+#if TSK_UNDER_WINDOWS
+ if(ret = ((SetEvent(condwait->pcond) && ResetEvent(condwait->pcond)) ? 0 : -1))
+ {
+ ret = GetLastError();
+ TSK_DEBUG_ERROR("SetEvent function failed: %d", ret);
+ }
+#else
+ if(condwait && condwait->mutex)
+ {
+ tsk_mutex_lock(condwait->mutex);
+ if(ret = pthread_cond_broadcast(condwait->pcond))
+ {
+ TSK_DEBUG_ERROR("pthread_cond_broadcast function failed: %d", ret);
+ }
+ tsk_mutex_unlock(condwait->mutex);
+ }
+#endif
+
+ return ret;
+}
+
+/**@ingroup tsk_condwait_group
+* Safely free a condwait variable previously created using @ref tsk_condwait_create.
+* @param handle The condwait handle to free.
+* @sa @ref tsk_condwait_create
+*/
+void tsk_condwait_destroy(tsk_condwait_handle_t** handle)
+{
+ tsk_condwait_t **condwait = (tsk_condwait_t**)handle;
+
+ if(condwait && *condwait){
+#if TSK_UNDER_WINDOWS
+ CloseHandle((*condwait)->pcond);
+#else
+ tsk_mutex_destroy(&((*condwait)->mutex));
+ pthread_cond_destroy((*condwait)->pcond);
+ TSK_FREE((*condwait)->pcond);
+#endif
+ tsk_free((void**)condwait);
+ }
+ else{
+ TSK_DEBUG_WARN("Cannot free an uninitialized condwait object");
+ }
+}
+
diff --git a/tinySAK/src/tsk_condwait.h b/tinySAK/src/tsk_condwait.h
new file mode 100644
index 0000000..b35b45c
--- /dev/null
+++ b/tinySAK/src/tsk_condwait.h
@@ -0,0 +1,53 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_condwait.h
+ * @brief Pthread CondWait
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef _TINYSAK_CONDWAIT_H_
+#define _TINYSAK_CONDWAIT_H_
+
+#include "tinysak_config.h"
+#include "tsk_mutex.h"
+
+TSK_BEGIN_DECLS
+
+/**@ingroup tsk_condwait_group
+* An opaque handle to a condwait object.
+*/
+typedef void tsk_condwait_handle_t;
+
+TINYSAK_API tsk_condwait_handle_t* tsk_condwait_create();
+TINYSAK_API int tsk_condwait_wait(tsk_condwait_handle_t* handle);
+TINYSAK_API int tsk_condwait_timedwait(tsk_condwait_handle_t* handle, uint64_t ms);
+TINYSAK_API int tsk_condwait_signal(tsk_condwait_handle_t* handle);
+TINYSAK_API int tsk_condwait_broadcast(tsk_condwait_handle_t* handle);
+TINYSAK_API void tsk_condwait_destroy(tsk_condwait_handle_t** handle);
+
+TSK_END_DECLS
+
+#endif /* _TINYSAK_CONDWAIT_H_ */
+
diff --git a/tinySAK/src/tsk_debug.c b/tinySAK/src/tsk_debug.c
new file mode 100644
index 0000000..6ff1bcf
--- /dev/null
+++ b/tinySAK/src/tsk_debug.c
@@ -0,0 +1,76 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_debug.c
+ * @brief Utility functions for debugging purpose.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tsk_debug.h"
+
+/**@defgroup tsk_debug_group Utility functions for debugging purpose.
+*/
+
+#if TSK_HAVE_DEBUG_H
+// Nothing to do --> all is up to the end-user application
+#else
+
+const void* tsk_debug_arg_data = tsk_null;
+tsk_debug_f tsk_debug_info_cb = tsk_null;
+tsk_debug_f tsk_debug_warn_cb = tsk_null;
+tsk_debug_f tsk_debug_error_cb = tsk_null;
+tsk_debug_f tsk_debug_fatal_cb = tsk_null;
+
+void tsk_debug_set_arg_data(const void* arg_data){
+ tsk_debug_arg_data = arg_data;
+}
+const void* tsk_debug_get_arg_data(){
+ return tsk_debug_arg_data;
+}
+void tsk_debug_set_info_cb(tsk_debug_f cb){
+ tsk_debug_info_cb = cb;
+}
+tsk_debug_f tsk_debug_get_info_cb(){
+ return tsk_debug_info_cb;
+}
+void tsk_debug_set_warn_cb(tsk_debug_f cb){
+ tsk_debug_warn_cb = cb;
+}
+tsk_debug_f tsk_debug_get_warn_cb(){
+ return tsk_debug_warn_cb;
+}
+void tsk_debug_set_error_cb(tsk_debug_f cb){
+ tsk_debug_error_cb = cb;
+}
+tsk_debug_f tsk_debug_get_error_cb(){
+ return tsk_debug_error_cb;
+}
+void tsk_debug_set_fatal_cb(tsk_debug_f cb){
+ tsk_debug_fatal_cb = cb;
+}
+tsk_debug_f tsk_debug_get_fatal_cb(){
+ return tsk_debug_fatal_cb;
+}
+
+#endif /* TSK_HAVE_DEBUG_H */
diff --git a/tinySAK/src/tsk_debug.h b/tinySAK/src/tsk_debug.h
new file mode 100644
index 0000000..90b9618
--- /dev/null
+++ b/tinySAK/src/tsk_debug.h
@@ -0,0 +1,125 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_debug.h
+ * @brief Useful functions for debugging purpose.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef _TINYSAK_DEBUG_H_
+#define _TINYSAK_DEBUG_H_
+
+#include "tinysak_config.h"
+#include <stdio.h>
+
+TSK_BEGIN_DECLS
+
+#if !defined(DEBUG_LEVEL)
+# define DEBUG_LEVEL DEBUG_LEVEL_ERROR
+#endif
+
+/**@ingroup tsk_debug_group
+* @def DEBUG_LEVEL_INFO
+* @a INFO level (4). This is the lowest possible level and will turn on all logging.
+*/
+/**@ingroup tsk_debug_group
+* @def DEBUG_LEVEL_WARN
+* @a WARN level (3). Warning are error which could change the normal process without blocking the application.
+*/
+/**@ingroup tsk_debug_group
+* @def DEBUG_LEVEL_ERROR
+* @a ERROR level (2). This level log error which might change the application behavior.
+*/
+/**@ingroup tsk_debug_group
+* @def DEBUG_LEVEL_FATAL
+* @a FATAL level (1). This level log fatal errors which might abort the application.
+*/
+#define DEBUG_LEVEL_INFO 4
+#define DEBUG_LEVEL_WARN 3
+#define DEBUG_LEVEL_ERROR 2
+#define DEBUG_LEVEL_FATAL 1
+
+#if TSK_HAVE_DEBUG_H
+# include <my_debug.h>
+#else
+ typedef int (*tsk_debug_f)(const void* arg, const char* fmt, ...);
+
+ /* INFO */
+# if (DEBUG_LEVEL >= DEBUG_LEVEL_INFO)
+# define TSK_DEBUG_INFO(FMT, ...) \
+ if(tsk_debug_get_info_cb()) \
+ tsk_debug_get_info_cb()(tsk_debug_get_arg_data(), "*INFO: " FMT "\n", ##__VA_ARGS__); \
+ else \
+ fprintf(stderr, "*INFO: " FMT "\n", ##__VA_ARGS__);
+# else
+# define TSK_DEBUG_INFO(FMT, ...) ((void)0)
+# endif
+ /* WARN */
+# if (DEBUG_LEVEL >= DEBUG_LEVEL_WARN)
+# define TSK_DEBUG_WARN(FMT, ...) \
+ if(tsk_debug_get_warn_cb()) \
+ tsk_debug_get_warn_cb()(tsk_debug_get_arg_data(), "**WARN: function: \"%s()\" \nfile: \"%s\" \nline: \"%u\" \nMSG: " FMT "\n", __FUNCTION__, __FILE__, __LINE__, ##__VA_ARGS__); \
+ else \
+ fprintf(stderr, "**WARN: function: \"%s()\" \nfile: \"%s\" \nline: \"%u\" \nMSG: " FMT "\n", __FUNCTION__, __FILE__, __LINE__, ##__VA_ARGS__);
+# else
+# define TSK_DEBUG_WARN(FMT, ...) ((void)0)
+# endif
+ /* ERROR */
+# if (DEBUG_LEVEL >= DEBUG_LEVEL_ERROR)
+# define TSK_DEBUG_ERROR(FMT, ...) \
+ if(tsk_debug_get_error_cb()) \
+ tsk_debug_get_error_cb()(tsk_debug_get_arg_data(), "***ERROR: function: \"%s()\" \nfile: \"%s\" \nline: \"%u\" \nMSG: " FMT "\n", __FUNCTION__, __FILE__, __LINE__, ##__VA_ARGS__); \
+ else \
+ fprintf(stderr, "***ERROR: function: \"%s()\" \nfile: \"%s\" \nline: \"%u\" \nMSG: " FMT "\n", __FUNCTION__, __FILE__, __LINE__, ##__VA_ARGS__);
+# else
+# define TSK_DEBUG_ERROR(FMT, ...) ((void)0)
+# endif
+ /* FATAL */
+# if (DEBUG_LEVEL >= DEBUG_LEVEL_FATAL)
+# define TSK_DEBUG_FATAL(FMT, ...) \
+ if(tsk_debug_get_fatal_cb()) \
+ tsk_debug_get_fatal_cb()(tsk_debug_get_arg_data(), "****FATAL: function: \"%s()\" \nfile: \"%s\" \nline: \"%u\" \nMSG: " FMT "\n", __FUNCTION__, __FILE__, __LINE__, ##__VA_ARGS__); \
+ else \
+ fprintf(stderr, "****FATAL: function: \"%s()\" \nfile: \"%s\" \nline: \"%u\" \nMSG: " FMT "\n", __FUNCTION__, __FILE__, __LINE__, ##__VA_ARGS__);
+# else
+# define TSK_DEBUG_FATAL(FMT, ...) ((void)0)
+# endif
+TINYSAK_API void tsk_debug_set_arg_data(const void*);
+TINYSAK_API const void* tsk_debug_get_arg_data();
+TINYSAK_API void tsk_debug_set_info_cb(tsk_debug_f );
+TINYSAK_API tsk_debug_f tsk_debug_get_info_cb();
+TINYSAK_API void tsk_debug_set_warn_cb(tsk_debug_f );
+TINYSAK_API tsk_debug_f tsk_debug_get_warn_cb();
+TINYSAK_API void tsk_debug_set_error_cb(tsk_debug_f );
+TINYSAK_API tsk_debug_f tsk_debug_get_error_cb( );
+TINYSAK_API void tsk_debug_set_fatal_cb(tsk_debug_f );
+TINYSAK_API tsk_debug_f tsk_debug_get_fatal_cb( );
+
+#endif /* TSK_HAVE_DEBUG_H */
+
+
+TSK_END_DECLS
+
+#endif /* _TINYSAK_DEBUG_H_ */
+
diff --git a/tinySAK/src/tsk_errno.h b/tinySAK/src/tsk_errno.h
new file mode 100644
index 0000000..22c4fb4
--- /dev/null
+++ b/tinySAK/src/tsk_errno.h
@@ -0,0 +1,93 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_mutex.h
+ * @brief ERRNO.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef _TINYSAK_ERRNO_H_
+#define _TINYSAK_ERRNO_H_
+
+#include "tinysak_config.h"
+
+TSK_BEGIN_DECLS
+
+#ifndef _WIN32_WCE
+# include <errno.h>
+#else
+#define EPERM 1
+#define ENOENT 2
+#define ESRCH 3
+#define EINTR 4
+#define EIO 5
+#define ENXIO 6
+#define E2BIG 7
+#define ENOEXEC 8
+#define EBADF 9
+#define ECHILD 10
+#define EAGAIN 11
+#define ENOMEM 12
+#define EACCES 13
+#define EFAULT 14
+#define EBUSY 16
+#define EEXIST 17
+#define EXDEV 18
+#define ENODEV 19
+#define ENOTDIR 20
+#define EISDIR 21
+#define ENFILE 23
+#define EMFILE 24
+#define ENOTTY 25
+#define EFBIG 27
+#define ENOSPC 28
+#define ESPIPE 29
+#define EROFS 30
+#define EMLINK 31
+#define EPIPE 32
+#define EDOM 33
+#define EDEADLK 36
+#define ENAMETOOLONG 38
+#define ENOLCK 39
+#define ENOSYS 40
+#define ENOTEMPTY 41
+
+/* Error codes used in the Secure CRT functions */
+
+#ifndef RC_INVOKED
+#if !defined(_SECURECRT_ERRCODE_VALUES_DEFINED)
+#define _SECURECRT_ERRCODE_VALUES_DEFINED
+#define EINVAL 22
+#define ERANGE 34
+#define EILSEQ 42
+#define STRUNCATE 80
+#endif
+#endif
+
+#endif
+
+TSK_END_DECLS
+
+#endif
+
diff --git a/tinySAK/src/tsk_fsm.c b/tinySAK/src/tsk_fsm.c
new file mode 100644
index 0000000..8acd511
--- /dev/null
+++ b/tinySAK/src/tsk_fsm.c
@@ -0,0 +1,311 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_fsm.c
+ * @brief Finite-state machine (FSM) implementation.
+ * @sa http://en.wikipedia.org/wiki/Finite-state_machine.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tsk_fsm.h"
+#include "tsk_memory.h"
+#include "tsk_debug.h"
+
+/**@defgroup tsk_fsm_group Finite-state machine (FSM) implementation.
+*/
+
+int tsk_fsm_exec_nothing(va_list *app){ return 0/*success*/; }
+tsk_bool_t tsk_fsm_cond_always(const void* data1, const void* data2) { return tsk_true; }
+
+/**@ingroup tsk_fsm_group
+*/
+tsk_fsm_t* tsk_fsm_create(tsk_fsm_state_id state_curr, tsk_fsm_state_id state_term)
+{
+ return tsk_object_new(tsk_fsm_def_t, state_curr, state_term);
+}
+
+/**@ingroup tsk_fsm_group
+*/
+tsk_fsm_entry_t* tsk_fsm_entry_create()
+{
+ return tsk_object_new(tsk_fsm_entry_def_t);
+}
+
+/**@ingroup tsk_fsm_group
+* Add entries (states) to the FSM.
+* @param self The FSM.
+* @param ... One of these helper macros: @b TSK_FSM_ADD_*. MUST end with
+* @b TSK_FSM_ADD_NULL.
+* @retval Zero if succeed and non-zero error code otherwise.
+*/
+int tsk_fsm_set(tsk_fsm_t* self, ...)
+{
+ va_list args;
+ int guard;
+
+ if(!self){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ va_start(args, self);
+ while((guard = va_arg(args, int))){
+ tsk_fsm_entry_t* entry;
+ if((entry = tsk_fsm_entry_create())){
+ entry->from = va_arg(args, tsk_fsm_state_id);
+ entry->action = va_arg(args, tsk_fsm_action_id);
+ entry->cond = va_arg(args, tsk_fsm_cond);
+ entry->to = va_arg(args, tsk_fsm_state_id);
+ entry->exec = va_arg(args, tsk_fsm_exec);
+ entry->desc = va_arg(args, const char*);
+
+ tsk_list_push_descending_data(self->entries, (void**)&entry);
+ }
+ }
+ va_end(args);
+
+ return 0;
+}
+
+/**@ingroup tsk_fsm_group
+* Sets the @a callback function to call when the FSM enter in the final state.
+* @param self The FSM.
+* @param callback The callback function to call.
+* @param callbackdata Opaque data (user-data) to pass to the callback function.
+* @retval Zero if succeed and non-zero error code otherwise.
+*/
+int tsk_fsm_set_callback_terminated(tsk_fsm_t* self, tsk_fsm_onterminated_f callback, const void* callbackdata)
+{
+ if(self){
+ self->callback_term = callback;
+ self->callback_data = callbackdata;
+ return 0;
+ }
+ else{
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+}
+
+/**@ingroup tsk_fsm_group
+* Execute an @a action. This action will probably change the current state of the FSM.
+* @param self The FSM.
+* @param action The id of the action to execute.
+* @param cond_data1 The first opaque data to pass to the @a condition function.
+* @param cond_data2 The first opaque data to pass to the @a condition function.
+* @param ... Variable parameters to pass to the @a exec function.
+* @retval Zero if succeed and non-zero error code otherwise.
+*/
+int tsk_fsm_act(tsk_fsm_t* self, tsk_fsm_action_id action, const void* cond_data1, const void* cond_data2, ...)
+{
+ tsk_list_item_t *item;
+ va_list ap;
+ tsk_bool_t found = tsk_false;
+ tsk_bool_t terminates = tsk_false; /* thread-safeness -> DO NOT REMOVE THIS VARIABLE */
+ int ret_exec = 0; /* success */
+
+ if(!self){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ if(tsk_fsm_terminated(self)){
+ TSK_DEBUG_WARN("The FSM is in the final state.");
+ return -2;
+ }
+
+ // lock
+ tsk_safeobj_lock(self);
+
+ va_start(ap, cond_data2);
+ tsk_list_foreach(item, self->entries)
+ {
+ tsk_fsm_entry_t* entry = item->data;
+ if((entry->from != tsk_fsm_state_any) && (entry->from != self->current)){
+ continue;
+ }
+
+ if((entry->action != tsk_fsm_action_any) && (entry->action != action)){
+ continue;
+ }
+
+ // check condition
+ if(entry->cond(cond_data1, cond_data2)){
+ // For debug information
+ if(self->debug){
+ TSK_DEBUG_INFO("State machine: %s", entry->desc);
+ }
+
+ if(entry->to != tsk_fsm_action_any){ /* Stay at the current state if dest. state is Any */
+ self->current = entry->to;
+ }
+
+ if(entry->exec){
+ if((ret_exec = entry->exec(&ap))){
+ TSK_DEBUG_INFO("State machine: Exec function failed. Moving to terminal state.");
+ }
+ }
+ else{ /* Nothing to execute */
+ ret_exec = 0;
+ }
+
+ terminates = (ret_exec || (self->current == self->term));
+ found = tsk_true;
+ break;
+ }
+ }
+ va_end(ap);
+
+ // unlock
+ tsk_safeobj_unlock(self);
+
+ /* Only call the callback function after unlock. */
+ if(terminates){
+ self->current = self->term;
+ if(self->callback_term){
+ self->callback_term(self->callback_data);
+ }
+ }
+ if(!found){
+ TSK_DEBUG_WARN("State machine: No matching state found.");
+ }
+
+ return ret_exec;
+}
+
+tsk_bool_t tsk_fsm_terminated(tsk_fsm_t* self)
+{
+ if(self){
+ return (self->current == self->term);
+ }
+ else{
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return tsk_true;
+ }
+}
+
+
+//=================================================================================================
+// fsm object definition
+//
+static tsk_object_t* tsk_fsm_ctor(tsk_object_t * self, va_list * app)
+{
+ tsk_fsm_t *fsm = self;
+ if(fsm){
+ fsm->current = va_arg(*app, tsk_fsm_state_id);
+ fsm->term = va_arg(*app, tsk_fsm_state_id);
+
+ fsm->entries = tsk_list_create();
+
+#if defined(DEBUG) || defined(_DEBUG)
+ fsm->debug = 1; /* default value, could be changed at any time */
+#endif
+ tsk_safeobj_init(fsm);
+ }
+
+ return self;
+}
+
+static tsk_object_t* tsk_fsm_dtor(tsk_object_t * self)
+{
+ tsk_fsm_t *fsm = self;
+ if(fsm){
+ /* If not in the terminal state ==>do it */
+ /*if(fsm->current != fsm->term){
+ tsk_safeobj_lock(fsm);
+ if(fsm->callback_term){
+ fsm->callback_term(fsm->callback_data);
+ }
+ tsk_safeobj_unlock(fsm);
+ }*/
+ tsk_safeobj_deinit(fsm);
+
+ TSK_OBJECT_SAFE_FREE(fsm->entries);
+ }
+
+ return self;
+}
+
+static const tsk_object_def_t tsk_fsm_def_s =
+{
+ sizeof(tsk_fsm_t),
+ tsk_fsm_ctor,
+ tsk_fsm_dtor,
+ tsk_null,
+};
+const tsk_object_def_t *tsk_fsm_def_t = &tsk_fsm_def_s;
+
+//=================================================================================================
+// fsm entry object definition
+//
+static tsk_object_t* tsk_fsm_entry_ctor(tsk_object_t * self, va_list * app)
+{
+ tsk_fsm_entry_t *fsm_entry = self;
+ if(fsm_entry){
+ }
+
+ return self;
+}
+
+static tsk_object_t* tsk_fsm_entry_dtor(tsk_object_t * self)
+{
+ tsk_fsm_entry_t *fsm_entry = self;
+ if(fsm_entry){
+ /* desc is "const char*" => should not be deleted */
+ /* TSK_FREE(fsm_entry->desc); */
+ }
+
+ return self;
+}
+static int tsk_fsm_entry_cmp(const tsk_object_t *_entry1, const tsk_object_t *_entry2)
+{
+ const tsk_fsm_entry_t* entry1 = _entry1;
+ const tsk_fsm_entry_t* entry2 = _entry2;
+ if(entry1 && entry2){
+ /* Put "Any" states at the bottom. (Strong)*/
+ if(entry1->from == tsk_fsm_state_any){
+ return -20;
+ }
+ else if(entry2->from == tsk_fsm_state_any){
+ return +20;
+ }
+
+ /* Put "Any" actions at the bottom. (Weak)*/
+ if(entry1->action == tsk_fsm_action_any){
+ return -10;
+ }
+ else if(entry1->action == tsk_fsm_action_any){
+ return +10;
+ }
+ }
+ return 0;
+}
+
+static const tsk_object_def_t tsk_fsm_entry_def_s =
+{
+ sizeof(tsk_fsm_entry_t),
+ tsk_fsm_entry_ctor,
+ tsk_fsm_entry_dtor,
+ tsk_fsm_entry_cmp,
+};
+const tsk_object_def_t *tsk_fsm_entry_def_t = &tsk_fsm_entry_def_s;
diff --git a/tinySAK/src/tsk_fsm.h b/tinySAK/src/tsk_fsm.h
new file mode 100644
index 0000000..b7639aa
--- /dev/null
+++ b/tinySAK/src/tsk_fsm.h
@@ -0,0 +1,178 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_fsm.h
+ * @brief Finite-state machine (FSM) implementation.
+ * @sa http://en.wikipedia.org/wiki/Finite-state_machine.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef _TINYSAK_FSM_H_
+#define _TINYSAK_FSM_H_
+
+#include "tinysak_config.h"
+#include "tsk_list.h"
+#include "tsk_safeobj.h"
+
+/**@ingroup tsk_fsm_group
+* @def TSK_FSM_ONTERMINATED
+*/
+
+TSK_BEGIN_DECLS
+
+#define TSK_FSM_ONTERMINATED_F(self) (tsk_fsm_onterminated_f)(self)
+
+/**@ingroup tsk_fsm_group
+* @def tsk_fsm_state_any
+*/
+/**@ingroup tsk_fsm_group
+* @def tsk_fsm_state_default
+*/
+/**@ingroup tsk_fsm_group
+* @def tsk_fsm_state_none
+*/
+/**@ingroup tsk_fsm_group
+* @def tsk_fsm_state_final
+*/
+#define tsk_fsm_state_any -0xFFFF
+#define tsk_fsm_state_default -0xFFF0
+#define tsk_fsm_state_none -0xFF00
+#define tsk_fsm_state_final -0xF000
+
+/**@ingroup tsk_fsm_group
+* @def tsk_fsm_action_any
+*/
+#define tsk_fsm_action_any -0xFFFF
+
+/**@ingroup tsk_fsm_group
+* @def tsk_fsm_state_id_t
+*/
+/**@ingroup tsk_fsm_group
+* @def tsk_fsm_action_id_t
+*/
+/**@ingroup tsk_fsm_group
+* @def tsk_fsm_cond
+*/
+/**@ingroup tsk_fsm_group
+* @def tsk_fsm_exec
+*/
+/**@ingroup tsk_fsm_group
+* @def tsk_fsm_onterminated
+*/
+
+typedef int tsk_fsm_state_id;
+typedef int tsk_fsm_action_id;
+typedef tsk_bool_t (*tsk_fsm_cond)(const void*, const void*);
+typedef int (*tsk_fsm_exec)(va_list *app);
+typedef int (*tsk_fsm_onterminated_f)(const void*);
+
+
+/**@ingroup tsk_fsm_group
+* @def TSK_FSM_ADD
+*/
+/**@ingroup tsk_fsm_group
+* @def TSK_FSM_ADD_ALWAYS
+*/
+/**@ingroup tsk_fsm_group
+* @def TSK_FSM_ADD_NOTHING
+*/
+/**@ingroup tsk_fsm_group
+* @def TSK_FSM_ADD_ALWAYS_NOTHING
+*/
+/**@ingroup tsk_fsm_group
+* @def TSK_FSM_ADD_DEFAULT
+*/
+/**@ingroup tsk_fsm_group
+* @def TSK_FSM_ADD_NULL
+*/
+#define TSK_FSM_ADD(from, action, cond, to, exec, desc)\
+ 1,\
+ (tsk_fsm_state_id)from, \
+ (tsk_fsm_action_id)action, \
+ (tsk_fsm_cond)cond, \
+ (tsk_fsm_state_id)to, \
+ (tsk_fsm_exec)exec, \
+ (const char*)desc
+#define TSK_FSM_ADD_ALWAYS(from, action, to, exec, desc) TSK_FSM_ADD(from, action, tsk_fsm_cond_always, to, exec, desc)
+#define TSK_FSM_ADD_NOTHING(from, action, cond, desc) TSK_FSM_ADD(from, action, cond, from, tsk_fsm_exec_nothing, desc)
+#define TSK_FSM_ADD_ALWAYS_NOTHING(from, desc) TSK_FSM_ADD(from, tsk_fsm_action_any, tsk_fsm_cond_always, from, tsk_fsm_exec_nothing, desc)
+#define TSK_FSM_ADD_DEFAULT()
+#define TSK_FSM_ADD_NULL()\
+ tsk_null
+
+/**@ingroup tsk_fsm_group
+* FSM entry.
+*/
+typedef struct tsk_fsm_entry_s
+{
+ TSK_DECLARE_OBJECT;
+
+ tsk_fsm_state_id from;
+ tsk_fsm_action_id action;
+ tsk_fsm_cond cond;
+ tsk_fsm_state_id to;
+ tsk_fsm_exec exec;
+ const char* desc;
+}
+tsk_fsm_entry_t;
+
+/**@ingroup tsk_fsm_group
+* List of @ref tsk_fsm_entry_t elements.
+*/
+typedef tsk_list_t tsk_fsm_entries_L_t;
+
+/**@ingroup tsk_fsm_group
+* FSM.
+*/
+typedef struct tsk_fsm_s
+{
+ TSK_DECLARE_OBJECT;
+
+ unsigned debug:1;
+ tsk_fsm_state_id current;
+ tsk_fsm_state_id term;
+ tsk_fsm_entries_L_t* entries;
+
+ tsk_fsm_onterminated_f callback_term;
+ const void* callback_data;
+
+ TSK_DECLARE_SAFEOBJ;
+}
+tsk_fsm_t;
+
+TINYSAK_API tsk_fsm_t* tsk_fsm_create(tsk_fsm_state_id state_curr, tsk_fsm_state_id state_term);
+
+TINYSAK_API int tsk_fsm_exec_nothing(va_list *app);
+TINYSAK_API tsk_bool_t tsk_fsm_cond_always(const void*, const void*);
+TINYSAK_API int tsk_fsm_set(tsk_fsm_t* self, ...);
+TINYSAK_API int tsk_fsm_set_callback_terminated(tsk_fsm_t* self, tsk_fsm_onterminated_f callback, const void* callbackdata);
+TINYSAK_API int tsk_fsm_act(tsk_fsm_t* self, tsk_fsm_action_id action, const void* cond_data1, const void* cond_data2, ...);
+TINYSAK_API tsk_bool_t tsk_fsm_terminated(tsk_fsm_t* self);
+
+TINYSAK_GEXTERN const tsk_object_def_t *tsk_fsm_def_t;
+TINYSAK_GEXTERN const tsk_object_def_t *tsk_fsm_entry_def_t;
+
+TSK_END_DECLS
+
+#endif /* _TINYSAK_FSM_H_ */
diff --git a/tinySAK/src/tsk_hmac.c b/tinySAK/src/tsk_hmac.c
new file mode 100644
index 0000000..5e30d21
--- /dev/null
+++ b/tinySAK/src/tsk_hmac.c
@@ -0,0 +1,226 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_hmac.c
+ * @brief HMAC: Keyed-Hashing for Message Authentication (RFC 2104) / FIPS-198-1.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tsk_hmac.h"
+
+#include "tsk_string.h"
+#include "tsk_buffer.h"
+
+#include <string.h>
+
+/**@defgroup tsk_hmac_group Keyed-Hashing for Message Authentication (RFC 2104/ FIPS-198-1).
+*/
+
+/**@ingroup tsk_hmac_group
+*/
+typedef enum tsk_hash_type_e { md5, sha1 } tsk_hash_type_t;
+
+int tsk_hmac_xxxcompute(const uint8_t* input, tsk_size_t input_size, const char* key, tsk_size_t key_size, tsk_hash_type_t type, uint8_t* digest)
+{
+#define TSK_MAX_BLOCK_SIZE TSK_SHA1_BLOCK_SIZE
+
+ tsk_size_t i, newkey_size;
+
+ tsk_size_t block_size = type == md5 ? TSK_MD5_BLOCK_SIZE : TSK_SHA1_BLOCK_SIZE; // Only SHA-1 and MD5 are supported for now
+ tsk_size_t digest_size = type == md5 ? TSK_MD5_DIGEST_SIZE : TSK_SHA1_DIGEST_SIZE;
+ char hkey [TSK_MAX_BLOCK_SIZE];
+
+ uint8_t ipad [TSK_MAX_BLOCK_SIZE];
+ uint8_t opad [TSK_MAX_BLOCK_SIZE];
+
+
+ memset(ipad, 0, sizeof(ipad));
+ memset(opad, 0, sizeof(ipad));
+
+ /*
+ * H(K XOR opad, H(K XOR ipad, input))
+ */
+
+ // Check key len
+ if (key_size > block_size){
+ if(type == md5){
+ TSK_MD5_DIGEST_CALC(key, key_size, (uint8_t*)hkey);
+ }
+ else if(type == sha1){
+ TSK_SHA1_DIGEST_CALC((uint8_t*)key, key_size, hkey);
+ }
+ else return -3;
+
+ newkey_size = digest_size;
+ }
+ else{
+ memcpy(hkey, key, key_size);
+ newkey_size = key_size;
+ }
+
+ memcpy(ipad, hkey, newkey_size);
+ memcpy(opad, hkey, newkey_size);
+
+ /* [K XOR ipad] and [K XOR opad]*/
+ for (i=0; i<block_size; i++){
+ ipad[i] ^= 0x36;
+ opad[i] ^= 0x5c;
+ }
+
+
+ {
+ tsk_buffer_t *passx; // pass1 or pass2
+ int pass1_done = 0;
+
+ passx = tsk_buffer_create(ipad, block_size); // pass1
+ tsk_buffer_append(passx, input, input_size);
+
+digest_compute:
+ if(type == md5){
+ TSK_MD5_DIGEST_CALC(TSK_BUFFER_TO_U8(passx), TSK_BUFFER_SIZE(passx), digest);
+ }
+ else{
+ TSK_SHA1_DIGEST_CALC(TSK_BUFFER_TO_U8(passx), TSK_BUFFER_SIZE(passx), (char*)digest);
+ }
+
+ if(pass1_done){
+ TSK_OBJECT_SAFE_FREE(passx);
+ goto pass1_and_pass2_done;
+ }
+ else{
+ pass1_done = 1;
+ }
+
+ tsk_buffer_cleanup(passx);
+ tsk_buffer_append(passx, opad, block_size); // pass2
+ tsk_buffer_append(passx, digest, digest_size);
+
+ goto digest_compute;
+ }
+
+pass1_and_pass2_done:
+
+ return 0;
+}
+
+
+/**@ingroup tsk_hmac_group
+ *
+ * Calculate HMAC-MD5 hash (hexa-string) as per RFC 2104.
+ *
+ * @author Mamadou
+ * @date 12/29/2009
+ *
+ * @param [in,out] input The input data.
+ * @param input_size The size of the input.
+ * @param [in,out] key The input key.
+ * @param key_size The size of the input key.
+ * @param [out] result Pointer to the result.
+ *
+ * @return Zero if succeed and non-zero error code otherwise.
+**/
+int hmac_md5_compute(const uint8_t* input, tsk_size_t input_size, const char* key, tsk_size_t key_size, tsk_md5string_t *result)
+{
+ tsk_md5digest_t digest;
+ int ret;
+
+ if((ret = hmac_md5digest_compute(input, input_size, key, key_size, digest))){
+ return ret;
+ }
+ tsk_str_from_hex(digest, TSK_MD5_DIGEST_SIZE, *result);
+ (*result)[TSK_MD5_STRING_SIZE] = '\0';
+
+ return 0;
+}
+
+
+/**@ingroup tsk_hmac_group
+ *
+ * Calculate HMAC-MD5 hash (bytes) as per RFC 2104.
+ *
+ * @author Mamadou
+ * @date 12/29/2009
+ *
+ * @param [in,out] input The input data.
+ * @param input_size The Size of the input.
+ * @param [in,out] key The input key.
+ * @param key_size The size of the input key.
+ * @param result Pointer to the result.
+ *
+ * @return Zero if succeed and non-zero error code otherwise.
+**/
+int hmac_md5digest_compute(const uint8_t* input, tsk_size_t input_size, const char* key, tsk_size_t key_size, tsk_md5digest_t result)
+{
+ return tsk_hmac_xxxcompute(input, input_size, key, key_size, md5, result);
+}
+
+/**@ingroup tsk_hmac_group
+ *
+ * Calculate HMAC-SHA-1 hash (hexa-string) as per RFC 2104.
+ *
+ * @author Mamadou
+ * @date 12/29/2009
+ *
+ * @param [in,out] input The input data.
+ * @param input_size The Size of the input.
+ * @param [in,out] key The input key.
+ * @param key_size The size of the input key.
+ * @param [out] result Pointer to the result.
+ *
+ * @return Zero if succeed and non-zero error code otherwise.
+**/
+int hmac_sha1_compute(const uint8_t* input, tsk_size_t input_size, const char* key, tsk_size_t key_size, tsk_sha1string_t *result)
+{
+ tsk_sha1digest_t digest;
+ int ret;
+
+ if((ret = hmac_sha1digest_compute(input, input_size, key, key_size, digest))){
+ return ret;
+ }
+ tsk_str_from_hex((uint8_t*)digest, TSK_SHA1_DIGEST_SIZE, *result);
+ (*result)[TSK_SHA1_STRING_SIZE] = '\0';
+
+ return 0;
+}
+
+/**@ingroup tsk_hmac_group
+ *
+ * Calculate HMAC-SHA-1 hash (bytes) as per RFC 2104.
+ *
+ * @author Mamadou
+ * @date 12/29/2009
+ *
+ * @param [in,out] input If non-null, the input.
+ * @param input_size The size of the input.
+ * @param [in,out] key The input key.
+ * @param key_size The size of the input key.
+ * @param result Pointer to the result.
+ *
+ * @return Zero if succeed and non-zero error code otherwise.
+**/
+int hmac_sha1digest_compute(const uint8_t* input, tsk_size_t input_size, const char* key, tsk_size_t key_size, tsk_sha1digest_t result)
+{
+ return tsk_hmac_xxxcompute(input, input_size, key, key_size, sha1, (uint8_t*)result);
+}
+
diff --git a/tinySAK/src/tsk_hmac.h b/tinySAK/src/tsk_hmac.h
new file mode 100644
index 0000000..e680ee6
--- /dev/null
+++ b/tinySAK/src/tsk_hmac.h
@@ -0,0 +1,49 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_hmac.h
+ * @brief HMAC: Keyed-Hashing for Message Authentication (RFC 2104) / FIPS-198-1.
+ * HMAC-MD5 and HMAC-SHA-1 are also implemented.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef _TINYSAK_HMAC_H_
+#define _TINYSAK_HMAC_H_
+
+#include "tinysak_config.h"
+
+#include "tsk_sha1.h"
+#include "tsk_md5.h"
+
+TSK_BEGIN_DECLS
+
+TINYSAK_API int hmac_md5_compute(const uint8_t* input, tsk_size_t input_size, const char* key, tsk_size_t key_size, tsk_md5string_t *result);
+TINYSAK_API int hmac_md5digest_compute(const uint8_t* input, tsk_size_t input_size, const char* key, tsk_size_t key_size, tsk_md5digest_t result);
+
+TINYSAK_API int hmac_sha1_compute(const uint8_t* input, tsk_size_t input_size, const char* key, tsk_size_t key_size, tsk_sha1string_t *result);
+TINYSAK_API int hmac_sha1digest_compute(const uint8_t* input, tsk_size_t input_size, const char* key, tsk_size_t key_size, tsk_sha1digest_t result);
+
+TSK_END_DECLS
+
+#endif /* _TINYSAK_HMAC_H_ */
diff --git a/tinySAK/src/tsk_list.c b/tinySAK/src/tsk_list.c
new file mode 100644
index 0000000..d441bfc
--- /dev/null
+++ b/tinySAK/src/tsk_list.c
@@ -0,0 +1,604 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_list.c
+ * @brief Linked list.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tsk_list.h"
+#include "tsk_memory.h"
+#include "tsk_debug.h"
+
+//#include <assert.h>
+#include <string.h>
+
+// FIXME: remove asserts
+
+/**@defgroup tsk_list_group Linked list.
+* For more information about linked list you can visit http://en.wikipedia.org/wiki/Linked_list.
+*/
+
+/** tsk_list_find_by_item
+*/
+static int tsk_list_find_by_item(const tsk_list_item_t* item, const void* _item)
+{
+ return (item == (const tsk_list_item_t*)_item) ? 0 : -1;
+}
+
+/**@ingroup tsk_list_group
+* Creates a linked list object.
+* You MUST use @ref TSK_OBJECT_SAFE_FREE() to safely free the object.
+*/
+tsk_list_t* tsk_list_create()
+{
+ return tsk_object_new(tsk_list_def_t);
+}
+
+/**@ingroup tsk_list_group
+* Create and initialize an item to be added to a linked list.
+* You MUST use @ref TSK_OBJECT_SAFE_FREE() to safely free the object.
+*/
+tsk_list_item_t* tsk_list_item_create()
+{
+ return tsk_object_new(tsk_list_item_def_t);
+}
+
+/**@ingroup tsk_list_group
+* Locks the list to avoid concurrent access. The list should be unlocked using
+* @ref tsk_list_unlock.
+* @param list The list to lock.
+* @retval zero if succeed and non-zero error code otherwise.
+* @sa @ref tsk_list_unlock
+*/
+int tsk_list_lock(tsk_list_t* list)
+{
+ if(list){
+ if(!list->mutex){
+ list->mutex = tsk_mutex_create();
+ }
+ return tsk_mutex_lock(list->mutex);
+ }
+ else{
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+}
+
+/**@ingroup tsk_list_group
+* UnLocks a previously locked list.
+* @param list The list to unlock.
+* @retval zero if succeed and non-zero error code otherwise.
+* @sa @ref tsk_list_lock
+*/
+int tsk_list_unlock(tsk_list_t* list)
+{
+ if(list && list->mutex){
+ return tsk_mutex_unlock(list->mutex);
+ }
+ else{
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+}
+
+/**@ingroup tsk_list_group
+* Remove an free an item from the @a list.
+* @param list the list from which to remove the @a item.
+* @param item the item to remove (and free) from the @a list.
+*/
+void tsk_list_remove_item(tsk_list_t* list, tsk_list_item_t* item)
+{
+ tsk_list_remove_item_by_pred(list, tsk_list_find_by_item, (const void*)item);
+}
+
+/**@ingroup tsk_list_group
+* Pops an object from the @a list.
+* @param list The list from which to pop the object.
+* @param tskobj Any valid object(declared using @ref TSK_DECLARE_OBJECT) to remove.
+* @retval The item.
+*/
+tsk_list_item_t* tsk_list_pop_item_by_data(tsk_list_t* list, const tsk_object_t * tskobj)
+{
+ if(list){
+ tsk_list_item_t *prev = tsk_null;
+ tsk_list_item_t *curr = prev = list->head;
+
+ while(curr){
+ if(!tsk_object_cmp(curr->data, tskobj)){
+ if(prev == curr){
+ /* Found at first position. */
+ if(list->head == list->tail){
+ /* There was only one item */
+ list->head = list->tail = tsk_null;
+ }
+ else{
+ list->head = curr->next;
+ }
+ }
+ else {
+ if(curr == list->tail){
+ /* Found at last position */
+ list->tail = prev;
+ list->tail->next = tsk_null;
+ }
+ else{
+ prev->next = curr->next;
+ }
+ }
+
+ return curr;
+ }
+
+ prev = curr;
+ curr = curr->next;
+ }
+ }
+
+ return 0;
+}
+
+/**@ingroup tsk_list_group
+* Removes an object from the @a list.
+* @param list The list from which to remove the object.
+* @param tskobj Any valid object(declared using @ref TSK_DECLARE_OBJECT) to remove.
+*/
+void tsk_list_remove_item_by_data(tsk_list_t* list, const tsk_object_t * tskobj)
+{
+ tsk_list_item_t* item;
+ if((item = tsk_list_pop_item_by_data(list, tskobj))){
+ tsk_object_unref(item);
+ }
+}
+
+/**@ingroup tsk_list_group
+* Pops an item from the @a list using a predicate function.
+* @param list The list from which to pop the item.
+* @param predicate The predicate function used to match the item.
+* @param data Arbitrary data to pass to the predicate function.
+* @retval The item
+*/
+tsk_list_item_t* tsk_list_pop_item_by_pred(tsk_list_t* list, tsk_list_func_predicate predicate, const void * data)
+{
+ if(list){
+ tsk_list_item_t *prev = tsk_null;
+ tsk_list_item_t *curr = prev = list->head;
+
+ while(curr){
+ if(!predicate(curr, data)){
+ if(prev == curr){
+ /* Found at first position. */
+ if(list->head == list->tail){
+ /* There was only one item */
+ list->head = list->tail = tsk_null;
+ }
+ else{
+ list->head = curr->next;
+ }
+ }
+ else {
+ if(curr == list->tail){
+ /* Found at last position */
+ list->tail = prev;
+ list->tail->next = tsk_null;
+ }
+ else{
+ prev->next = curr->next;
+ }
+ }
+
+ return curr;
+ }
+
+ prev = curr;
+ curr = curr->next;
+ }
+ }
+
+ return 0;
+}
+
+/**@ingroup tsk_list_group
+* Removes an item from the @a list using a predicate function.
+* @param list The list from which to remove the item.
+* @param predicate The predicate function used to match the item.
+* @param data Arbitrary data to pass to the predicate function.
+*/
+void tsk_list_remove_item_by_pred(tsk_list_t* list, tsk_list_func_predicate predicate, const void * data)
+{
+ tsk_list_item_t* item;
+ if((item = tsk_list_pop_item_by_pred(list, predicate, data))){
+ tsk_object_unref(item);
+ }
+}
+
+/**@ingroup tsk_list_group
+* Clean up and remove all items from the @a list.
+* @param list The list ro clean up.
+*/
+void tsk_list_clear_items(tsk_list_t* list)
+{
+ if(list){
+ tsk_list_item_t* next = tsk_null;
+ tsk_list_item_t* curr = list->head;
+
+ while(curr){
+ next = curr->next;
+ tsk_object_unref(curr);
+ curr = next;
+ }
+ list->head = tsk_null;
+ list->tail = tsk_null;
+ }
+}
+
+/**@ingroup tsk_list_group
+* Pops first item from the @a list. The item will be definitely removed from the list.
+* @param list The list from which to pop the item.
+* @retval The first item. It is up to you to free the returned item (@ref TSK_OBJECT_SAFE_FREE(item)).
+*/
+tsk_list_item_t* tsk_list_pop_first_item(tsk_list_t* list)
+{
+ tsk_list_item_t* item = tsk_null;
+ if(list){
+ item = list->head;
+ if(list->head){
+ if(list->head->next){
+ list->head = list->head->next;
+ }
+ else{
+ list->head = list->tail = tsk_null;
+ }
+ }
+ }
+
+ return item;
+}
+
+/**@ingroup tsk_list_group
+* Add an item to the @a list.
+* @param list The destination @a list.
+* @param item The @a item to add.
+* @param back Indicates whether to put the item back or not.
+*/
+void tsk_list_push_item(tsk_list_t* list, tsk_list_item_t** item, tsk_bool_t back)
+{
+ // do not test
+ tsk_bool_t first = !list->head;
+
+ if(back && list->tail){
+ list->tail->next = *item, list->tail = *item, (*item)->next = tsk_null;
+ }
+ else {
+ (*item)->next = list->head, list->head = *item;
+ }
+
+ if(first){
+ list->tail = list->head = *item, list->tail->next = tsk_null;
+ }
+ (*item) = tsk_null;
+}
+
+/**@ingroup tsk_list_group
+* Add an item to the list in ascending or descending order.
+* @param list The destination @a list.
+* @param item The @a item to add.
+* @param ascending Indicates whether to put the @a item in ascending order or not.
+*/
+void tsk_list_push_filtered_item(tsk_list_t* list, tsk_list_item_t** item, tsk_bool_t ascending)
+{
+ if(list)
+ {
+ tsk_list_item_t *prev = tsk_null;
+ tsk_list_item_t *curr = prev = list->head;
+
+ while(curr)
+ {
+ int diff = tsk_object_cmp((*item), curr);
+ if((diff </*=*/ 0 && ascending) || (diff >/*=*/0 && !ascending)){
+ if(curr == list->head){
+ tsk_list_push_front_item(list, item);
+ }
+ else{
+ (*item)->next = curr;
+ prev->next = (*item);
+ }
+
+ return;
+ }
+
+ prev = curr;
+ curr = curr->next;
+ }
+
+ tsk_list_push_back_item(list, item);
+ }
+}
+
+/**@ingroup tsk_list_group
+* Add all items in @a src into @a dest.
+* @param dest The destination list.
+* @param src The source list.
+* @param back Indicates whether to put the list back or not.
+**/
+int tsk_list_push_list(tsk_list_t* dest, const tsk_list_t* src, tsk_bool_t back)
+{
+ const tsk_list_item_t* curr = (src)->head;
+ tsk_object_t* copy;
+
+ if(!dest || !src){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ while(curr){
+ copy = tsk_object_ref(curr->data);
+ tsk_list_push_data(dest, (void**)&copy, back);
+
+ curr = curr->next;
+ }
+ return 0;
+}
+
+/**@ingroup tsk_list_group
+* Add an opaque data to the @a list.
+* @param list The destination @a list.
+* @param data The @a data to add.
+* @param back Indicates whether to put the item back or not.
+*/
+int tsk_list_push_data(tsk_list_t* list, void** data, tsk_bool_t back)
+{
+ if(list && data && *data){
+ tsk_list_item_t *item = tsk_list_item_create();
+ item->data = *data;
+
+ tsk_list_push_item(list, &item, back);
+ (*data) = tsk_null;
+
+ return 0;
+ }
+ else{
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+}
+
+/**@ingroup tsk_list_group
+* Add an opaque data to the list in ascending or descending order.
+* @param list The destination @a list.
+* @param data The @a data to add.
+* @param ascending Indicates whether to put the @a data in ascending order or not.
+*/
+int tsk_list_push_filtered_data(tsk_list_t* list, void** data, tsk_bool_t ascending)
+{
+ if(list && data && *data){
+ tsk_list_item_t *item = tsk_list_item_create();
+ item->data = *data;
+
+ tsk_list_push_filtered_item(list, &item, ascending);
+ (*data) = tsk_null;
+
+ return 0;
+ }
+ else{
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+}
+
+/**@ingroup tsk_list_group
+* Find an item from a list.
+* @param list The @a list holding the item.
+* @param tskobj The @a object to find.
+* @retval A @ref tsk_list_item_t item if found and NULL otherwize.
+*/
+const tsk_list_item_t* tsk_list_find_item_by_data(const tsk_list_t* list, const tsk_object_t* tskobj)
+{
+ if(list && tskobj){
+ tsk_list_item_t *item;
+ tsk_list_foreach(item, list){
+ if(!tsk_object_cmp(item->data, tskobj)){
+ return item;
+ }
+ }
+ }
+
+ return 0;
+}
+
+/**@ingroup tsk_list_group
+* Find first item matching criteria defined by the @a predicate.
+* @param list the list to query
+* @param predicate the predicate against which to test each item
+* @param data data passed to the predicate function for comparaison
+* @retval the item which match the criteria and NULL otherwise
+* @sa @ref tsk_list_find_item_by_data
+*/
+const tsk_list_item_t* tsk_list_find_item_by_pred(const tsk_list_t* list, tsk_list_func_predicate predicate, const void* data)
+{
+ if(predicate){
+ const tsk_list_item_t *item;
+ tsk_list_foreach(item, list){
+ if(!predicate(item, data)){
+ return item;
+ }
+ }
+ }
+ else{
+ TSK_DEBUG_WARN("Cannot use an uninitialized predicate function");
+ }
+ return tsk_null;
+}
+
+/**@ingroup tsk_list_group
+* Find first item matching criteria defined by the @a predicate.
+* @param list the list to query
+* @param predicate the predicate against which to test each item
+* @param data data passed to the predicate function for comparaison
+* @retval the data holded by the item which match the criteria and NULL otherwise
+* @sa @ref tsk_list_find_item_by_pred
+*/
+const tsk_object_t* tsk_list_find_object_by_pred(const tsk_list_t* list, tsk_list_func_predicate predicate, const void* data)
+{
+ const tsk_list_item_t *item;
+ if((item = tsk_list_find_item_by_pred(list, predicate, data))){
+ return item->data;
+ }
+ else{
+ return tsk_null;
+ }
+}
+
+/**@ingroup tsk_list_group
+* Counts the number of item matching the predicate.
+* @param list The list containing the items to count
+* @param predicate The predicate to use to match the items
+* @param data Data passed to the predicate function for comparaison
+* @retval The number of item matching the predicate
+*/
+tsk_size_t tsk_list_count(const tsk_list_t* list, tsk_list_func_predicate predicate, const void* data)
+{
+ tsk_size_t count = 0;
+ if(predicate && list){
+ const tsk_list_item_t *item;
+ tsk_list_foreach(item, list){
+ if(!predicate(item, data)){
+ ++count;
+ }
+ }
+ }
+ else{
+ TSK_DEBUG_ERROR("Invalid parameter");
+ }
+
+ return count;
+}
+
+
+
+
+
+
+
+
+
+
+
+//=================================================================================================
+// Item object definition
+//
+static tsk_object_t* tsk_list_item_ctor(tsk_object_t * self, va_list * app)
+{
+ tsk_list_item_t *item = self;
+ if(item){
+ }
+ return self;
+}
+
+static tsk_object_t* tsk_list_item_dtor(tsk_object_t *self)
+{
+ tsk_list_item_t *item = self;
+ if(item){
+ item->data = tsk_object_unref(item->data);
+ }
+ else{
+ TSK_DEBUG_WARN("Cannot free an uninitialized item");
+ }
+ return item;
+}
+
+static int tsk_list_item_cmp(const tsk_object_t *_item1, const tsk_object_t *_item2)
+{
+ const tsk_list_item_t* item1 = _item1;
+ const tsk_list_item_t* item2 = _item2;
+
+ if(item1 && item2){
+ return tsk_object_cmp(item1->data, item2->data);
+ }
+ else return -1;
+}
+
+static const tsk_object_def_t tsk_list_item_def_s =
+{
+ sizeof(tsk_list_item_t),
+ tsk_list_item_ctor,
+ tsk_list_item_dtor,
+ tsk_list_item_cmp,
+};
+const tsk_object_def_t *tsk_list_item_def_t = &tsk_list_item_def_s;
+
+//=================================================================================================
+// List object definition
+//
+static tsk_object_t* tsk_list_ctor(tsk_object_t *self, va_list *app)
+{
+ tsk_list_t *list = self;
+ if(list){
+ }
+
+ return self;
+}
+
+static tsk_object_t* tsk_list_dtor(tsk_object_t *self)
+{
+ tsk_list_t *list = self;
+ if(list){
+#if 0
+ /* Not thread-safe */
+ tsk_list_item_t* next = tsk_null;
+ tsk_list_item_t* curr = list->head;
+
+ while(curr){
+ next = curr->next;
+ /*curr =*/ tsk_object_unref(curr);
+ curr = next;
+ }
+#else
+ /* Thread-safe method */
+ tsk_list_item_t* item;
+ while((item = tsk_list_pop_first_item(list))){
+ tsk_object_unref(item);
+ }
+#endif
+
+ /* destroy the on-demand mutex */
+ if(list->mutex){
+ tsk_mutex_destroy(&list->mutex);
+ }
+ }
+ else{
+ TSK_DEBUG_WARN("Cannot free an uninitialized list");
+ }
+ return list;
+}
+
+static const tsk_object_def_t tsk_list_def_s =
+{
+ sizeof(tsk_list_t),
+ tsk_list_ctor,
+ tsk_list_dtor,
+ tsk_null,
+};
+const tsk_object_def_t *tsk_list_def_t = &tsk_list_def_s;
+
diff --git a/tinySAK/src/tsk_list.h b/tinySAK/src/tsk_list.h
new file mode 100644
index 0000000..9e2c5b8
--- /dev/null
+++ b/tinySAK/src/tsk_list.h
@@ -0,0 +1,135 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_list.h
+ * @brief Linked list. For more information about linked list you can visit http://en.wikipedia.org/wiki/Linked_list.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef _TINYSAK_LIST_H_
+#define _TINYSAK_LIST_H_
+
+#include "tinysak_config.h"
+#include "tsk_mutex.h"
+#include "tsk_object.h"
+
+TSK_BEGIN_DECLS
+
+/**@ingroup tsk_list_group
+* Check if the the linked list is empty or not.
+* This function will fail if the list is NULL.
+*/
+#define TSK_LIST_IS_EMPTY(self) ((self) ? (!(self)->head) : tsk_true)
+
+#define TSK_LIST_IS_FIRST(self, item) ((self) ? ((self)->head == item) : tsk_false)
+#define TSK_LIST_IS_LAST(self, item) ((self) ? ((self)->tail == item) : tsk_false)
+
+#define TSK_LIST_FIRST_DATA(self) (((self) && (self)->head) ? (self)->head->data : tsk_null)
+
+/**@ingroup tsk_list_group
+* Item for linked list.
+*/
+typedef struct tsk_list_item_s
+{
+ TSK_DECLARE_OBJECT;
+ void* data; /**< Opaque data. */
+ struct tsk_list_item_s* next; /**< Next item. */
+}
+tsk_list_item_t;
+
+/**@ingroup tsk_list_group
+* Linked list.
+*/
+typedef struct tsk_list_s
+{
+ TSK_DECLARE_OBJECT;
+
+ tsk_list_item_t* head; /**< The head of the linked list. */
+ tsk_list_item_t* tail; /**< The tail of the linked list. */
+ tsk_mutex_handle_t* mutex; /**< on-demand mutex. */
+}
+tsk_list_t;
+
+/**@ingroup tsk_list_group
+* Function predicate used to match an item.
+* @param item The current item to match.
+* @param data Arbitrary data holding the object to compare.
+* @retval 0 if match and <0 if first<second and >0 otherwise
+*/
+typedef int (*tsk_list_func_predicate)(const tsk_list_item_t* item, const void* data);
+
+
+/**@ingroup tsk_list_group
+* Loop through the linked list.
+* @param item The current item.
+* @param list Pointer to the list for which we want to get items.
+*
+*/
+#define tsk_list_foreach(item, list) for(item = list ? list->head : tsk_null; item; item = item->next)
+
+TINYSAK_API tsk_list_t* tsk_list_create();
+TINYSAK_API tsk_list_item_t* tsk_list_item_create();
+
+TINYSAK_API int tsk_list_lock(tsk_list_t* list);
+TINYSAK_API int tsk_list_unlock(tsk_list_t* list);
+
+TINYSAK_API void tsk_list_remove_item(tsk_list_t* list, tsk_list_item_t* item);
+TINYSAK_API tsk_list_item_t* tsk_list_pop_item_by_data(tsk_list_t* list, const tsk_object_t * tskobj);
+TINYSAK_API void tsk_list_remove_item_by_data(tsk_list_t* list, const tsk_object_t * tskobj);
+TINYSAK_API void tsk_list_remove_item_by_pred(tsk_list_t* list, tsk_list_func_predicate predicate, const void * data);
+TINYSAK_API tsk_list_item_t* tsk_list_pop_item_by_pred(tsk_list_t* list, tsk_list_func_predicate predicate, const void * data);
+TINYSAK_API void tsk_list_clear_items(tsk_list_t* list);
+
+TINYSAK_API tsk_list_item_t* tsk_list_pop_first_item(tsk_list_t* list);
+TINYSAK_API void tsk_list_push_item(tsk_list_t* list, tsk_list_item_t** item, tsk_bool_t back);
+#define tsk_list_push_back_item(list, item) tsk_list_push_item(list, item, tsk_true)
+#define tsk_list_push_front_item(list, item) tsk_list_push_item(list, item, tsk_false)
+TINYSAK_API void tsk_list_push_filtered_item(tsk_list_t* list, tsk_list_item_t** item, tsk_bool_t ascending);
+#define tsk_list_push_ascending_item(list, item) tsk_list_pushfiltered_item(list, item, tsk_true)
+#define tsk_list_push_descending_item(list, item) tsk_list_pushfiltered_item(list, item, tsk_false)
+
+TINYSAK_API int tsk_list_push_list(tsk_list_t* destination, const tsk_list_t* source, tsk_bool_t back);
+#define tsk_list_pushback_list(destination, source) tsk_list_push_list(destination, source, tsk_true)
+#define tsk_list_pushfront_list(destination, source) tsk_list_push_list(destination, source, tsk_false)
+
+TINYSAK_API int tsk_list_push_data(tsk_list_t* list, void** data, tsk_bool_t back);
+#define tsk_list_push_back_data(list, data) tsk_list_push_data(list, data, tsk_true)
+#define tsk_list_push_front_data(list, data) tsk_list_push_data(list, data, tsk_false)
+TINYSAK_API int tsk_list_push_filtered_data(tsk_list_t* list, void** data, tsk_bool_t ascending);
+#define tsk_list_push_ascending_data(list, data) tsk_list_push_filtered_data(list, data, tsk_true)
+#define tsk_list_push_descending_data(list, data) tsk_list_push_filtered_data(list, data, tsk_false)
+
+TINYSAK_API const tsk_list_item_t* tsk_list_find_item_by_data(const tsk_list_t* list, const tsk_object_t * tskobj);
+TINYSAK_API const tsk_list_item_t* tsk_list_find_item_by_pred(const tsk_list_t* list, tsk_list_func_predicate predicate, const void* data);
+TINYSAK_API const tsk_object_t* tsk_list_find_object_by_pred(const tsk_list_t* list, tsk_list_func_predicate predicate, const void* data);
+TINYSAK_API tsk_size_t tsk_list_count(const tsk_list_t* list, tsk_list_func_predicate predicate, const void* data);
+
+TINYSAK_GEXTERN const tsk_object_def_t *tsk_list_def_t;
+TINYSAK_GEXTERN const tsk_object_def_t *tsk_list_item_def_t;
+
+
+TSK_END_DECLS
+
+#endif /* _TINYSAK_LIST_H_ */
+
diff --git a/tinySAK/src/tsk_md5.c b/tinySAK/src/tsk_md5.c
new file mode 100644
index 0000000..111cc3c
--- /dev/null
+++ b/tinySAK/src/tsk_md5.c
@@ -0,0 +1,276 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_md5.c
+ * @brief Implements Message-Digest algorithm 5 (RFC 1321).
+ *
+ * @author Colin Plumb
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tsk_md5.h"
+
+#include "tsk_string.h"
+
+#include <string.h>
+
+/**@defgroup tsk_md5_group MD5 (RFC 1321) utility functions.
+ * The code in this file is a modified version of an implementation placed in the public domain by the following persons:
+ * @author Colin Plumb
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+*/
+
+/**@ingroup tsk_md5_group
+*/
+#if defined(_BIG_ENDIAN)
+void tsk_byteReverse(uint32_t *buf, unsigned words)
+{
+ uint8_t *p = (uint8_t *)buf;
+
+ do{
+ *buf++ = (uint32_t)((unsigned)p[3] << 8 | p[2]) << 16 |
+ ((unsigned)p[1] << 8 | p[0]);
+ p += 4;
+ }
+ while (--words);
+}
+#else
+#define tsk_byteReverse(buf,words) /* do nothing*/
+#endif
+
+/**@ingroup tsk_md5_group
+ * Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
+ * initialization constants.
+ */
+void tsk_md5init(tsk_md5context_t *ctx)
+{
+ ctx->buf[0] = 0x67452301;
+ ctx->buf[1] = 0xefcdab89;
+ ctx->buf[2] = 0x98badcfe;
+ ctx->buf[3] = 0x10325476;
+
+ ctx->bytes[0] = 0;
+ ctx->bytes[1] = 0;
+}
+
+/**@ingroup tsk_md5_group
+ * Update context to reflect the concatenation of another buffer full
+ * of bytes.
+ */
+void tsk_md5update(tsk_md5context_t *ctx, uint8_t const *buf, tsk_size_t len)
+{
+ uint32_t t;
+
+ /* Update byte count */
+
+ t = ctx->bytes[0];
+ if ((ctx->bytes[0] = t + len) < t)
+ ctx->bytes[1]++; /* Carry from low to high */
+
+ t = 64 - (t & 0x3f); /* Space available in ctx->in (at least 1) */
+ if (t > len)
+ {
+ memcpy((uint8_t *)ctx->in + 64 - t, buf, len);
+ return ;
+ }
+ /* First chunk is an odd size */
+ memcpy((uint8_t *)ctx->in + 64 - t, buf, t);
+ tsk_byteReverse(ctx->in, 16);
+ tsk_md5transform(ctx->buf, ctx->in);
+ buf += t;
+ len -= t;
+
+ /* Process data in 64-byte chunks */
+ while (len >= 64)
+ {
+ memcpy(ctx->in, buf, 64);
+ tsk_byteReverse(ctx->in, 16);
+ tsk_md5transform(ctx->buf, ctx->in);
+ buf += 64;
+ len -= 64;
+ }
+
+ /* Handle any remaining bytes of data. */
+ memcpy(ctx->in, buf, len);
+}
+
+/**@ingroup tsk_md5_group
+ * Final wrapup - pad to 64-byte boundary with the bit pattern
+ * 1 0* (64-bit count of bits processed, MSB-first)
+ */
+void tsk_md5final(tsk_md5digest_t digest, tsk_md5context_t *ctx)
+{
+ int count = ctx->bytes[0] & 0x3f; /* Number of bytes in ctx->in */
+ uint8_t *p = (uint8_t *)ctx->in + count;
+
+ /* Set the first char of padding to 0x80. There is always room. */
+ *p++ = 0x80;
+
+ /* Bytes of padding needed to make 56 bytes (-8..55) */
+ count = 56 - 1 - count;
+
+ if (count < 0)
+ { /* Padding forces an extra block */
+ memset(p, 0, count + 8);
+ tsk_byteReverse(ctx->in, 16);
+ tsk_md5transform(ctx->buf, ctx->in);
+ p = (uint8_t *)ctx->in;
+ count = 56;
+ }
+ memset(p, 0, count);
+ tsk_byteReverse(ctx->in, 14);
+
+ /* Append length in bits and transform */
+ ctx->in[14] = ctx->bytes[0] << 3;
+ ctx->in[15] = ctx->bytes[1] << 3 | ctx->bytes[0] >> 29;
+ tsk_md5transform(ctx->buf, ctx->in);
+
+ tsk_byteReverse(ctx->buf, 4);
+ memcpy(digest, ctx->buf, 16);
+ memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */
+}
+
+/* The four core functions - F1 is optimized somewhat */
+
+/* #define F1(x, y, z) (x & y | ~x & z) */
+#define F1(x, y, z) (z ^ (x & (y ^ z)))
+#define F2(x, y, z) F1(z, x, y)
+#define F3(x, y, z) (x ^ y ^ z)
+#define F4(x, y, z) (y ^ (x | ~z))
+
+/* This is the central step in the MD5 algorithm. */
+#define MD5STEP(f,w,x,y,z,in,s) \
+(w += f(x,y,z) + in, w = (w<<s | w>>(32-s)) + x)
+
+/**@ingroup tsk_md5_group
+ * The core of the MD5 algorithm, this alters an existing MD5 hash to
+ * reflect the addition of 16 longwords of new data. MD5Update blocks
+ * the data and converts bytes into longwords for this routine.
+ */
+void tsk_md5transform(uint32_t buf[4], uint32_t const in[TSK_MD5_DIGEST_SIZE])
+{
+ register uint32_t a, b, c, d;
+
+ a = buf[0];
+ b = buf[1];
+ c = buf[2];
+ d = buf[3];
+
+ MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
+ MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
+ MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
+ MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
+ MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
+ MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
+ MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
+ MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
+ MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
+ MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
+ MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
+ MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
+ MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
+ MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
+ MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
+ MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
+
+ MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
+ MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
+ MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
+ MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
+ MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
+ MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
+ MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
+ MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
+ MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
+ MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
+ MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
+ MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
+ MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
+ MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
+ MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
+ MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
+
+ MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
+ MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
+ MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
+ MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
+ MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
+ MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
+ MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
+ MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
+ MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
+ MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
+ MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
+ MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
+ MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
+ MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
+ MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
+ MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
+
+ MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
+ MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
+ MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
+ MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
+ MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
+ MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
+ MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
+ MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
+ MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
+ MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
+ MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
+ MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
+ MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
+ MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
+ MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
+ MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
+
+ buf[0] += a;
+ buf[1] += b;
+ buf[2] += c;
+ buf[3] += d;
+}
+
+
+/**@ingroup tsk_md5_group
+ *
+ * @brief Calculate MD5 HASH for @a input data.
+ *
+ * @param input The input data.
+ * @param size The size of the input data.
+ * @param result MD5 hash result as Hexadecimal string.
+ *
+ * @return Zero if succeed and non-zero error code otherwise.
+**/
+int tsk_md5compute(const char* input, tsk_size_t size, tsk_md5string_t *result)
+{
+ tsk_md5digest_t digest;
+
+ if(!result | !*result) return -1;
+
+ (*result)[TSK_MD5_STRING_SIZE] = '\0';
+
+ TSK_MD5_DIGEST_CALC(input, size, digest);
+ tsk_str_from_hex(digest, TSK_MD5_DIGEST_SIZE, *result);
+
+ return 0;
+}
diff --git a/tinySAK/src/tsk_md5.h b/tinySAK/src/tsk_md5.h
new file mode 100644
index 0000000..4bcd209
--- /dev/null
+++ b/tinySAK/src/tsk_md5.h
@@ -0,0 +1,94 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_md5.h
+ * @brief Implements Message-Digest algorithm 5 (RFC 1321).
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef _TINYSAK_MD5_H_
+#define _TINYSAK_MD5_H_
+
+#include "tinysak_config.h"
+
+TSK_BEGIN_DECLS
+
+/**@ingroup tsk_md5_group
+* @def TSK_MD5_DIGEST_SIZE
+*/
+/**@ingroup tsk_md5_group
+* @def TSK_MD5_BLOCK_SIZE
+*/
+/**@ingroup tsk_md5_group
+* @def TSK_MD5_EMPTY
+*/
+/**@ingroup tsk_md5_group
+* @def TSK_MD5_STRING_SIZE
+*/
+/**@ingroup tsk_md5_group
+* @def tsk_md5string_t
+*/
+/**@ingroup tsk_md5_group
+* @def tsk_md5digest_t
+*/
+/**@ingroup TSK_MD5_DIGEST_CALC
+* @def tsk_md5digest_t
+*/
+
+
+#define TSK_MD5_DIGEST_SIZE 16
+#define TSK_MD5_BLOCK_SIZE 64
+
+#define TSK_MD5_EMPTY "d41d8cd98f00b204e9800998ecf8427e"
+
+#define TSK_MD5_STRING_SIZE (TSK_MD5_DIGEST_SIZE*2)
+typedef char tsk_md5string_t[TSK_MD5_STRING_SIZE+1]; /**< Hexadecimal MD5 string. */
+typedef uint8_t tsk_md5digest_t[TSK_MD5_DIGEST_SIZE]; /**< MD5 digest bytes. */
+
+#define TSK_MD5_DIGEST_CALC(input, input_size, digest) \
+ { \
+ tsk_md5context_t ctx; \
+ tsk_md5init(&ctx); \
+ tsk_md5update(&ctx, (const uint8_t*)(input), (input_size)); \
+ tsk_md5final((digest), &ctx); \
+ }
+
+typedef struct tsk_md5context_s
+{
+ uint32_t buf[4];
+ uint32_t bytes[2];
+ uint32_t in[16];
+}
+tsk_md5context_t;
+
+TINYSAK_API void tsk_md5init(tsk_md5context_t *context);
+TINYSAK_API void tsk_md5update(tsk_md5context_t *context, uint8_t const *buf, tsk_size_t len);
+TINYSAK_API void tsk_md5final(tsk_md5digest_t digest, tsk_md5context_t *context);
+TINYSAK_API void tsk_md5transform(uint32_t buf[4], uint32_t const in[TSK_MD5_DIGEST_SIZE]);
+TINYSAK_API int tsk_md5compute(const char* input, tsk_size_t size, tsk_md5string_t *result);
+
+TSK_END_DECLS
+
+#endif /* _TINYSAK_MD5_H_ */
+
diff --git a/tinySAK/src/tsk_memory.c b/tinySAK/src/tsk_memory.c
new file mode 100644
index 0000000..4a5d29f
--- /dev/null
+++ b/tinySAK/src/tsk_memory.c
@@ -0,0 +1,124 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_memory.c
+ * @brief Useful memory management functions to handle memory.
+ * As I'm a lazy man, some definition come from <ahref="http://www.cplusplus.com">this website</a>
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tsk_memory.h"
+#include "tsk_debug.h"
+
+#include <stdarg.h>
+#include <ctype.h>
+#include <stdio.h>
+
+/**@defgroup tsk_memory_group Utility functions for memory management.
+*/
+
+/**@ingroup tsk_memory_group
+* Allocates a block of size bytes of memory, returning a pointer to the beginning of the block.
+* The content of the newly allocated block of memory is not initialized, remaining with indeterminate values.
+* @param size Size of the memory block, in bytes.
+* @retval On success, a pointer to the memory block allocated by the function.
+* It is up to you to free the returned pointer.
+*/
+void* tsk_malloc(tsk_size_t size)
+{
+ void *ret = malloc(size);
+ if(!ret){
+ TSK_DEBUG_ERROR("Memory allocation failed");
+ }
+
+ return ret;
+}
+
+/**@ingroup tsk_memory_group
+* Reallocate memory block.
+* In case that ptr is NULL, the function behaves exactly as @a tsk_malloc, assigning a new block of size bytes and returning a pointer to the beginning of it.
+* The function may move the memory block to a new location, in which case the new location is returned. The content of the memory block is preserved up to the lesser of the
+* new and old sizes, even if the block is moved. If the new size is larger, the value of the newly allocated portion is indeterminate.
+* In case that the size is 0, the memory previously allocated in ptr is deallocated as if a call to free was made, and a NULL pointer is returned.
+* @param ptr Pointer to a memory block previously allocated with malloc, calloc or realloc to be reallocated.
+* If this is NULL, a new block is allocated and a pointer to it is returned by the function.
+* @param size New size for the memory block, in bytes.
+* If it is 0 and ptr points to an existing block of memory, the memory block pointed by ptr is deallocated and a NULL pointer is returned.
+* @retval A pointer to the reallocated memory block, which may be either the same as the ptr argument or a new location.
+* The type of this pointer is void*, which can be cast to the desired type of data pointer in order to be dereferenceable.
+* If the function failed to allocate the requested block of memory, a NULL pointer is returned.
+* It is up to you to free the returned pointer.
+*/
+void* tsk_realloc (void* ptr, tsk_size_t size)
+{
+ void *ret = tsk_null;
+
+ if(ptr){
+ if(!(ret = realloc(ptr, size))){
+ TSK_DEBUG_ERROR("Memory reallocation failed");
+ }
+ }
+ else{
+ if(!(ret = calloc(size, 1))){
+ TSK_DEBUG_ERROR("Memory allocation failed");
+ }
+ }
+
+ return ret;
+}
+
+/**@ingroup tsk_memory_group
+* Deallocate space in memory.
+* @param ptr Pointer to a memory block previously allocated with @a tsk_malloc, @a tsk_calloc or @a tsk_realloc to be deallocated.
+* If a null pointer is passed as argument, no action occurs.
+*/
+void tsk_free(void** ptr)
+{
+ if(ptr && *ptr){
+ free(*ptr);
+ *ptr = tsk_null;
+ }
+}
+
+/**@ingroup tsk_memory_group
+* Allocates a block of memory for an array of num elements, each of them size bytes long, and initializes all its bits to zero.
+* The effective result is the allocation of an zero-initialized memory block of (num * size) bytes.
+* @param num Number of elements to be allocated
+* @param size Size of elements
+* @retval A pointer to the memory block allocated by the function. The type of this pointer is always void*, which can be cast to the desired type of data pointer in order to be dereferenceable.
+* If the function failed to allocate the requested block of memory, a NULL pointer is returned.
+* It is up to you to free the returned pointer.
+*/
+void* tsk_calloc(tsk_size_t num, tsk_size_t size)
+{
+ void* ret = 0;
+ if(num && size){
+ ret = calloc(num, size);
+ if(!ret){
+ TSK_DEBUG_ERROR("Memory allocation failed. num=%u and size=%u", num, size);
+ }
+ }
+
+ return ret;
+}
diff --git a/tinySAK/src/tsk_memory.h b/tinySAK/src/tsk_memory.h
new file mode 100644
index 0000000..49b67b8
--- /dev/null
+++ b/tinySAK/src/tsk_memory.h
@@ -0,0 +1,59 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_memory.h
+ * @brief Useful memory management functions to handle memory.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef _TINYSAK_MEMORY_H_
+#define _TINYSAK_MEMORY_H_
+
+#include "tinysak_config.h"
+
+#include <stdlib.h> /* tsk_size_t */
+
+/**@ingroup tsk_memory_group
+* @def TSK_SAFE_FREE
+* Safely free the memory pointed by @a ptr.
+*/
+/**@ingroup tsk_memory_group
+* @def TSK_FREE
+* Safely free the memory pointed by @a ptr.
+*/
+
+TSK_BEGIN_DECLS
+
+#define TSK_SAFE_FREE(ptr) (void)tsk_free((void**)(&ptr));
+#define TSK_FREE(ptr) TSK_SAFE_FREE(ptr)
+
+TINYSAK_API void* tsk_malloc(tsk_size_t size);
+TINYSAK_API void* tsk_realloc (void * ptr, tsk_size_t size);
+TINYSAK_API void tsk_free(void** ptr);
+TINYSAK_API void* tsk_calloc(tsk_size_t num, tsk_size_t size);
+
+TSK_END_DECLS
+
+#endif /* _TINYSAK_MEMORY_H_ */
+
diff --git a/tinySAK/src/tsk_mutex.c b/tinySAK/src/tsk_mutex.c
new file mode 100644
index 0000000..6e417db
--- /dev/null
+++ b/tinySAK/src/tsk_mutex.c
@@ -0,0 +1,167 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_mutex.c
+ * @brief Pthread/Windows Mutex utility functions.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tsk_mutex.h"
+#include "tsk_memory.h"
+#include "tsk_debug.h"
+
+#if TSK_UNDER_WINDOWS
+# include <windows.h>
+# include "tsk_errno.h"
+ typedef HANDLE MUTEX_T;
+# define MUTEX_S void
+# define TSK_ERROR_NOT_OWNER ERROR_NOT_OWNER
+#else
+# include <pthread.h>
+# define MUTEX_S pthread_mutex_t
+ typedef MUTEX_S* MUTEX_T;
+# define TSK_ERROR_NOT_OWNER EPERM
+#endif
+
+#if defined(__GNUC__) || defined(__SYMBIAN32__)
+# include <errno.h>
+#endif
+
+// FIXME: Momory leaks in mutex
+
+/**@defgroup tsk_mutex_group Pthread/Windows Mutex utility functions.
+*/
+
+/**@ingroup tsk_mutex_group
+* Creates new recursive mutex handle.
+* @retval New mutex handle. It is up to you free the returned handle using @ref tsk_mutex_destroy.
+* @sa @ref tsk_mutex_destroy.
+*/
+tsk_mutex_handle_t* tsk_mutex_create()
+{
+ MUTEX_T handle = tsk_null;
+
+#if TSK_UNDER_WINDOWS
+ handle = CreateMutex(NULL, FALSE, NULL);
+#else
+ int ret;
+ pthread_mutexattr_t mta;
+
+ if((ret = pthread_mutexattr_init(&mta))){
+ TSK_DEBUG_ERROR("pthread_mutexattr_init failed with error code %d", ret);
+ return tsk_null;
+ }
+ if((ret = pthread_mutexattr_settype(&mta, PTHREAD_MUTEX_RECURSIVE))){
+ TSK_DEBUG_ERROR("pthread_mutexattr_settype failed with error code %d", ret);
+ pthread_mutexattr_destroy(&mta);
+ return tsk_null;
+ }
+
+ /* if we are here: all is ok */
+ handle = tsk_calloc(1, sizeof(MUTEX_S));
+ if(pthread_mutex_init((MUTEX_T)handle, &mta)){
+ TSK_FREE(handle);
+ }
+ pthread_mutexattr_destroy(&mta);
+#endif
+
+ if(!handle){
+ TSK_DEBUG_ERROR("Failed to create new mutex.");
+ }
+ return handle;
+}
+
+/**@ingroup tsk_mutex_group
+* Lock a mutex. You must use @ref tsk_mutex_unlock to unlock the mutex.
+* @param handle The handle of the mutex to lock.
+* @retval Zero if succeed and non-zero error code otherwise.
+* @sa @ref tsk_mutex_unlock.
+*/
+int tsk_mutex_lock(tsk_mutex_handle_t* handle)
+{
+ int ret = EINVAL;
+ if(handle)
+ {
+#if TSK_UNDER_WINDOWS
+ if((ret = WaitForSingleObject((MUTEX_T)handle , INFINITE)) == WAIT_FAILED)
+#else
+ if(ret = pthread_mutex_lock((MUTEX_T)handle))
+#endif
+ {
+ TSK_DEBUG_ERROR("Failed to lock the mutex: %d", ret);
+ }
+ }
+ return ret;
+}
+
+/**@ingroup tsk_mutex_group
+* Unlock a mutex previously locked using @ref tsk_mutex_lock.
+* @param handle The handle of the mutex to unlock.
+* @retval Zero if succeed and non-zero otherwise.
+* @sa @ref tsk_mutex_lock.
+*/
+int tsk_mutex_unlock(tsk_mutex_handle_t* handle)
+{
+ int ret = EINVAL;
+ if(handle)
+ {
+#if TSK_UNDER_WINDOWS
+ if((ret = ReleaseMutex((MUTEX_T)handle) ? 0 : -1)){
+ ret = GetLastError();
+#else
+ if(ret = pthread_mutex_unlock((MUTEX_T)handle))
+ {
+#endif
+ if(ret == TSK_ERROR_NOT_OWNER){
+ TSK_DEBUG_WARN("The calling thread does not own the mutex: %d", ret);
+ }
+ else{
+ TSK_DEBUG_ERROR("Failed to unlock the mutex: %d", ret);
+ }
+ }
+ }
+ return ret;
+}
+
+/**@ingroup tsk_mutex_group
+* Free/destroy a mutex.
+* @param handle The mutex to free.
+* @sa @ref tsk_mutex_create.
+*/
+void tsk_mutex_destroy(tsk_mutex_handle_t** handle)
+{
+ if(handle && *handle){
+#if TSK_UNDER_WINDOWS
+ CloseHandle((MUTEX_T)*handle);
+ *handle = 0;
+#else
+ pthread_mutex_destroy((MUTEX_T)*handle);
+ tsk_free(handle);
+#endif
+ }
+ else{
+ TSK_DEBUG_WARN("Cannot free an uninitialized mutex");
+ }
+}
+
diff --git a/tinySAK/src/tsk_mutex.h b/tinySAK/src/tsk_mutex.h
new file mode 100644
index 0000000..f37387c
--- /dev/null
+++ b/tinySAK/src/tsk_mutex.h
@@ -0,0 +1,50 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_mutex.h
+ * @brief Pthread Mutex.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef _TINYSAK_MUTEX_H_
+#define _TINYSAK_MUTEX_H_
+
+#include "tinysak_config.h"
+
+TSK_BEGIN_DECLS
+
+/**@ingroup tsk_mutex_group
+* Mutex handle.
+*/
+typedef void tsk_mutex_handle_t;
+
+TINYSAK_API tsk_mutex_handle_t* tsk_mutex_create();
+TINYSAK_API int tsk_mutex_lock(tsk_mutex_handle_t* handle);
+TINYSAK_API int tsk_mutex_unlock(tsk_mutex_handle_t* handle);
+TINYSAK_API void tsk_mutex_destroy(tsk_mutex_handle_t** handle);
+
+TSK_END_DECLS
+
+#endif /* _TINYSAK_MUTEX_H_ */
+
diff --git a/tinySAK/src/tsk_object.c b/tinySAK/src/tsk_object.c
new file mode 100644
index 0000000..36984bf
--- /dev/null
+++ b/tinySAK/src/tsk_object.c
@@ -0,0 +1,224 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_object.c
+ * @brief Base object implementation.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tsk_object.h"
+#include "tsk_memory.h"
+#include "tsk_debug.h"
+#include "tsk_common.h"
+
+/**@defgroup tsk_object_group Base object implementation.
+* @brief Provides utility functions to ease Object Oriented Programming in C.
+*/
+
+#if defined (_DEBUG) || defined (DEBUG)
+# define TSK_DEBUG_OBJECTS 0
+static int tsk_objects_count = 0;
+#else
+# define TSK_DEBUG_OBJECTS 0
+#endif
+
+/** Object meta-data (definition).
+*/
+typedef struct tsk_object_header_s{
+ const void* base; /**< Opaque data holding a pointer to the actual meta-data(size, constructor, destructor and comparator) */
+ int refCount; /**< Reference counter. */
+}
+tsk_object_header_t;
+#define TSK_OBJECT_HEADER(object) ((tsk_object_header_t*)object)
+
+/**@ingroup tsk_object_group
+* Creates new object. The object MUST be declared using @ref TSK_DECLARE_OBJECT macro.
+* @param objdef The object meta-data (definition). For more infomation see @ref tsk_object_def_t.
+* @param ... List of parameters to pass to the constructor(defined in the meta-data).
+* @retval @ref tsk_object_t object with a reference counter equal to 1.
+* @sa @ref tsk_object_new_2.
+*/
+tsk_object_t* tsk_object_new(const tsk_object_def_t *objdef, ...)
+{
+ // Do not check "objdef", let the application die if it's null
+ tsk_object_t *newobj = tsk_calloc(1, objdef->size);
+ if(newobj){
+ (*(const tsk_object_def_t **) newobj) = objdef;
+ TSK_OBJECT_HEADER(newobj)->refCount = 1;
+ if(objdef->constructor){
+ va_list ap;
+ va_start(ap, objdef);
+ newobj = objdef->constructor(newobj, &ap);
+ va_end(ap);
+
+#if TSK_DEBUG_OBJECTS
+ TSK_DEBUG_INFO("N∞ objects:%d", ++tsk_objects_count);
+#endif
+ }
+ else{
+ TSK_DEBUG_WARN("No constructor found.");
+ }
+ }
+ else{
+ TSK_DEBUG_ERROR("Failed to create new tsk_object.");
+ }
+
+ return newobj;
+}
+
+/**@ingroup tsk_object_group
+* Creates new object. The object MUST be declared using @ref TSK_DECLARE_OBJECT macro.
+* @param objdef The object meta-data (definition). For more infomation see @ref tsk_object_def_t.
+* @param ap Variable argument list to pass to the constructor(defined in the meta-data).
+* @retval @ref tsk_object_t object with a reference counter equal to 1.
+* @sa @ref tsk_object_new.
+*/
+tsk_object_t* tsk_object_new_2(const tsk_object_def_t *objdef, va_list* ap)
+{
+ tsk_object_t *newobj = tsk_calloc(1, objdef->size);
+ if(newobj){
+ (*(const tsk_object_def_t **) newobj) = objdef;
+ TSK_OBJECT_HEADER(newobj)->refCount = 1;
+ if(objdef->constructor){
+ newobj = objdef->constructor(newobj, ap);
+
+#if TSK_DEBUG_OBJECTS
+ TSK_DEBUG_INFO("N∞ objects:%d", ++tsk_objects_count);
+#endif
+ }
+ else{
+ TSK_DEBUG_WARN("No constructor found.");
+ }
+ }
+ else{
+ TSK_DEBUG_ERROR("Failed to create new tsk_object.");
+ }
+
+ return newobj;
+}
+
+/**@ingroup tsk_object_group
+* Gets the size of an opaque object.
+* @param self The object for which we want to get the size.
+* The object MUST be declared using @ref TSK_DECLARE_OBJECT macro and created using @ref tsk_object_new or @ref tsk_object_new_2.
+* @retval The size of the object.
+*/
+tsk_size_t tsk_object_sizeof(const tsk_object_t *self)
+{
+ const tsk_object_def_t **objdef = (const tsk_object_def_t **)self;
+ if(objdef && *objdef){
+ return (*objdef)->size;
+ }
+ else{
+ TSK_DEBUG_ERROR("NULL object definition.");
+ return 0;
+ }
+}
+
+/**@ingroup tsk_object_group
+* Compares two well-defined objects.
+* If the meta-data (definition) of the first object (@a object1) do not include a function comparator then this method will amlways return -1.
+* @param object1 The first object to compare.
+* @param object2 The second object to compare.
+* @retval Zero if the two object are equal.
+* Positive value if @a object1 is greater than @a object2 and a negative value otherwise.
+*/
+int tsk_object_cmp(const tsk_object_t *object1, const tsk_object_t *object2)
+{
+ const tsk_object_def_t **objdef = (const tsk_object_def_t **)object1;
+
+ if(objdef && *objdef && (*objdef)->comparator){
+ return (*objdef)->comparator(object1, object2);
+ }
+ return -1;
+}
+
+/**@ingroup tsk_object_group
+* Increment the refrence counting of the object.<br>
+* Refernce counting: http://en.wikipedia.org/wiki/Reference_counting.<br>
+* The object MUST be declared using @ref TSK_DECLARE_OBJECT macro and created using @ref tsk_object_new or @ref tsk_object_new_2.
+* @param self The object holding the counter to increment.
+* @retval The new object (incremented).
+* @sa tsk_object_unref.
+*/
+tsk_object_t* tsk_object_ref(tsk_object_t *self)
+{
+ tsk_object_header_t* objhdr = TSK_OBJECT_HEADER(self);
+ if(objhdr && objhdr->refCount){
+ objhdr->refCount++;
+ return self;
+ }
+ return tsk_null;
+}
+
+/**@ingroup tsk_object_group
+* Decrement the refrence counting of the object.<br>
+* Refernce counting: http://en.wikipedia.org/wiki/Reference_counting.<br>
+* The object MUST be declared using @ref TSK_DECLARE_OBJECT macro and created using @ref tsk_object_new or @ref tsk_object_new_2.
+* @param self The object holding the counter to decrement.
+* @retval If the refernce counter is equal to zero then NULL is returned otherwise a new object (decremented) is returned.
+* @sa ref tsk_object_ref.
+* @sa ref TSK_OBJECT_SAFE_FREE.
+*/
+tsk_object_t* tsk_object_unref(tsk_object_t *self)
+{
+ if(self){
+ tsk_object_header_t* objhdr = TSK_OBJECT_HEADER(self);
+ if(objhdr->refCount){ // If refCount is == 0 then, nothing should happen.
+ if(!--objhdr->refCount){
+ tsk_object_delete(self);
+ return tsk_null;
+ }
+ }
+ else{
+ return tsk_null;
+ }
+ }
+ return self;
+}
+
+/**@ingroup tsk_object_group
+* Delete an object. This function will delete the object even if it's reference counter is greater than 1.
+* This mean that this function is not safe. You should use @ref TSK_OBJECT_SAFE_FREE to safely delete an object.
+* The object MUST be declared using @ref TSK_DECLARE_OBJECT macro and created using @ref tsk_object_new or @ref tsk_object_new_2.
+* @param self The object to delete.
+* @sa @ref TSK_OBJECT_SAFE_FREE.
+*/
+void tsk_object_delete(tsk_object_t *self)
+{
+ const tsk_object_def_t ** objdef = self;
+ if(self && *objdef){
+ if((*objdef)->destructor){
+ self = (*objdef)->destructor(self);
+#if TSK_DEBUG_OBJECTS
+ TSK_DEBUG_INFO("N∞ objects:%d", --tsk_objects_count);
+#endif
+ }
+ else{
+ TSK_DEBUG_WARN("No destructor found.");
+ }
+ free(self);
+ }
+}
+
diff --git a/tinySAK/src/tsk_object.h b/tinySAK/src/tsk_object.h
new file mode 100644
index 0000000..00ac3e7
--- /dev/null
+++ b/tinySAK/src/tsk_object.h
@@ -0,0 +1,173 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_object.h
+ * @brief Base object implementation.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef TSK_OBJECT_H
+#define TSK_OBJECT_H
+
+#include "tinysak_config.h"
+
+#include <stdarg.h>
+#include <stdio.h>
+
+TSK_BEGIN_DECLS
+
+/**@ingroup tsk_object_group
+* Plain object.
+*/
+typedef void tsk_object_t;
+
+/**@ingroup tsk_object_group
+* @def TSK_OBJECT_SAFE_FREE
+* Safely free any well-defined object. If the reference count of the object was equal to 1 then this
+ * object will be freed otherwise the refrence counter will be decremented.
+ * In all case this operation will set the pointer (the object itself) to NULL.<br>
+ * <b>Very Important</b>: Mutexes, Semaphores and CondVars are not well-defined objects. You should never use this macro to destroy them.
+ * @param self The object to free or unref.
+**/
+#define TSK_OBJECT_SAFE_FREE(self) if(self) tsk_object_unref(self), self = tsk_null
+
+/**@ingroup tsk_object_group
+* tag a structure as an object. If this macro is used then you MUST
+* provide a constructor and a destructor functions into an object definition (or meta-data).
+* @ref tsk_object_new or @ref tsk_object_new_2 are used to create the object and @ref tsk_object_unref or @ref tsk_object_delete to destroy it.
+* @code
+* typedef struct person_s{
+* TSK_DECLARE_OBJECT;
+* int id;
+* char* firstName;
+* char* lastName;
+* } person_t;
+* @endcode
+* To create the object:
+* @code
+* // person_def_t: See bellow to understand how to create an object definition.
+* person_t* person = tsk_object_new(person_def_t, "My First Name", "My last Name");
+* @endcode
+* To safely free the object:
+* @code
+* TSK_OBJECT_SAFE_FREE(person);
+* @endcode
+*/
+#define TSK_DECLARE_OBJECT \
+ const void* __base__; \
+ tsk_size_t refCount
+
+/**@ingroup tsk_object_group
+* Internal macro to get the definition of the object.
+*/
+#define TSK_OBJECT_DEF(self) ((const tsk_object_def_t*)self)
+
+/**@ingroup tsk_object_group
+* Meta-data used of define an object.
+* You MUST provide at least a constructor and a destructor. The comparator should
+* be provided if you would like to compare opaque object or sort linked lists.
+* @code
+*
+* // constructor
+* static void* person_create(tsk_object_t * self, va_list * app)
+* {
+* static int unique_id = 0;
+* person_t *person = self;
+* if(person){
+* person->id = ++unique_id;
+* person->firstName = tsk_strdup(va_arg(*app, const char *));
+* person->lastName = tsk_strdup(va_arg(*app, const char *));
+* }
+* return self;
+* }
+*
+* // destructor
+* static void* person_destroy(tsk_object_t * self)
+* {
+* person_t *person = self;
+* if(person){
+* TSK_FREE(person->firstName);
+* TSK_FREE(person->lastName);
+* }
+* return self;
+* }
+*
+* // comparator
+* static int person_cmp(const tsk_object_t *object1, const tsk_object_t *object1)
+* {
+* const person_t *person1 = object1;
+* const person_t *person2 = object2;
+*
+* return (person1 && person2) ? (person1->id - person2->id) : -1;
+* }
+*
+* // Meta-data (Object defnition)
+* static const tsk_object_def_t person_def_s =
+* {
+* sizeof(person_t),
+* person_create,
+* person_destroy,
+* person_cmp,
+* }person_def_t;
+*
+* @endcode
+* Now, to create your object:
+* @code
+* person_t* person = tsk_object_new(person_def_t, "My First Name", "My last Name"); // Will call "person_create" function.
+* @endcode
+* Or
+* @code
+* #define PERSON_CREATE(firstName, lastName) tsk_object_new(person_def_t, firstName, lastName)
+* person_t* person = PERSON_CREATE("My First Name", "My last Name") // For clarity, this form will be used in all projects declared using @ref TSK_DECLARE_OBJECT.
+* @endcode
+* To safely free your object:
+* @code
+* TSK_OBJECT_SAFE_FREE(person); // Will call "person_destroy" function.
+* @endcode
+*/
+typedef struct tsk_object_def_s
+{
+ //! The size of the object.
+ tsk_size_t size;
+ //! Pointer to the constructor.
+ tsk_object_t* (* constructor) (tsk_object_t *, va_list *);
+ //! Pointer to the destructor.
+ tsk_object_t* (* destructor) (tsk_object_t *);
+ //! Pointer to the comparator.
+ int (* comparator) (const tsk_object_t *, const tsk_object_t *);
+}
+tsk_object_def_t;
+
+TINYSAK_API tsk_object_t* tsk_object_new(const tsk_object_def_t *objdef, ...);
+TINYSAK_API tsk_object_t* tsk_object_new_2(const tsk_object_def_t *objdef, va_list* ap);
+TINYSAK_API tsk_size_t tsk_object_sizeof(const tsk_object_t *);
+TINYSAK_API int tsk_object_cmp(const void *self, const tsk_object_t *object);
+TINYSAK_API tsk_object_t* tsk_object_ref(tsk_object_t *self);
+TINYSAK_API tsk_object_t* tsk_object_unref(tsk_object_t *self);
+TINYSAK_API void tsk_object_delete(tsk_object_t *self);
+
+TSK_END_DECLS
+
+#endif /* TSK_OBJECT_H */
+
diff --git a/tinySAK/src/tsk_options.c b/tinySAK/src/tsk_options.c
new file mode 100644
index 0000000..7372427
--- /dev/null
+++ b/tinySAK/src/tsk_options.c
@@ -0,0 +1,242 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_options.c
+ * @brief Options.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tsk_options.h"
+#include "tsk_memory.h"
+#include "tsk_string.h"
+#include "tsk_common.h"
+
+#include <string.h>
+
+/**@defgroup tsk_options_group Options.
+*/
+
+/** Predicate function used to find an option by id.
+*/
+static int pred_find_option_by_id(const tsk_list_item_t *item, const void *id)
+{
+ if(item && item->data){
+ tsk_option_t *option = item->data;
+ return (option->id - *((int*)id));
+ }
+ return -1;
+}
+
+/**@ingroup tsk_options_group
+*/
+tsk_option_t* tsk_option_create(int id, const char* value)
+{
+ return tsk_object_new(TSK_OPTION_VA_ARGS(id, value));
+}
+
+/**@ingroup tsk_options_group
+*/
+tsk_option_t* tsk_option_create_null()
+{
+ return tsk_option_create(0, tsk_null);
+}
+
+
+/**@ingroup tsk_options_group
+* Checks if the supplied list of options contains an option with this @a id.
+* @param self The list of options into which to search.
+* @param id The id of the option to search.
+* @retval @ref tsk_true if the parameter exist and @ref tsk_false otherwise.
+*/
+tsk_bool_t tsk_options_have_option(const tsk_options_L_t *self, int id)
+{
+ if(self){
+ if(tsk_list_find_item_by_pred(self, pred_find_option_by_id, &id)){
+ return tsk_true;
+ }
+ }
+ return tsk_false;
+}
+
+/**@ingroup tsk_options_group
+* Adds an option to the list of options. If the option already exist(same id), then it's value will be updated.
+* @param self The destination list.
+* @param id The id of the option to add.
+* @param value The value of the option to add.
+* @retval Zero if succeed and -1 otherwise.
+*/
+int tsk_options_add_option(tsk_options_L_t **self, int id, const char* value)
+{
+ tsk_option_t *option;
+
+ if(!self) {
+ return -1;
+ }
+
+ if(!*self){
+ *self = tsk_list_create();
+ }
+
+ if((option = (tsk_option_t*)tsk_options_get_option_by_id(*self, id))){
+ tsk_strupdate(&option->value, value); /* Already exist ==> update the value. */
+ }
+ else{
+ option = tsk_option_create(id, value);
+ tsk_list_push_back_data(*self, (void**)&option);
+ }
+
+ return 0;
+}
+
+int tsk_options_add_option_2(tsk_options_L_t **self, const tsk_option_t* option)
+{
+ int ret = -1;
+ if(!self || !option || !option){
+ return ret;
+ }
+
+ ret = tsk_options_add_option(self, option->id, option->value);
+ return ret;
+}
+
+/**@ingroup tsk_options_group
+* Removes an option from the list of options.
+* @param self The source list.
+* @param id The id of the option to remove.
+* @retval Zero if succeed and -1 otherwise.
+*/
+int tsk_options_remove_option(tsk_options_L_t *self, int id)
+{
+ if(self){
+ tsk_list_remove_item_by_pred(self, pred_find_option_by_id, &id);
+ return 0;
+ }
+ return -1;
+}
+
+/**@ingroup tsk_options_group
+* Gets an option from the list of options by id.
+* @param self The source list.
+* @param id The id of the option to retrieve.
+* @retval @ref tsk_option_t if succeed and NULL otherwise.
+*/
+const tsk_option_t *tsk_options_get_option_by_id(const tsk_options_L_t *self, int id)
+{
+ if(self){
+ const tsk_list_item_t *item_const = tsk_list_find_item_by_pred(self, pred_find_option_by_id, &id);
+ if(item_const){
+ return item_const->data;
+ }
+ }
+ return 0;
+}
+
+/**@ingroup tsk_options_group
+* Gets the value of a option.
+* @param self The source list.
+* @param id The id of the option to retrieve.
+* @retval The value of the option if succeed and @ref tsk_null otherwise.
+*/
+const char *tsk_options_get_option_value(const tsk_options_L_t *self, int id)
+{
+ if(self){
+ const tsk_list_item_t *item_const = tsk_list_find_item_by_pred(self, pred_find_option_by_id, &id);
+ if(item_const && item_const->data){
+ return ((const tsk_option_t *)item_const->data)->value;
+ }
+ }
+ return tsk_null;
+}
+
+/**@ingroup tsk_options_group
+* Gets the value of a option.
+* @param self The source list.
+* @param id The id of the option to retrieve.
+* @retval The value of the option if succeed and -1 otherwise.
+*/
+int tsk_options_get_option_value_as_int(const tsk_options_L_t *self, int id)
+{
+ const char *value = tsk_options_get_option_value(self, id);
+ return value ? atoi(value) : -1;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+//=================================================================================================
+// option object definition
+//
+static tsk_object_t* tsk_option_ctor(tsk_object_t * self, va_list * app)
+{
+ tsk_option_t *option = self;
+ if(option){
+ int id = va_arg(*app, int);
+ const char* value = va_arg(*app, const char *);
+
+ option->id = id;
+ if(!tsk_strnullORempty(value)) {
+ option->value = tsk_strdup(value);
+ }
+ }
+
+ return self;
+}
+
+static tsk_object_t* tsk_option_dtor(tsk_object_t * self)
+{
+ tsk_option_t *option = self;
+ if(option){
+ TSK_FREE(option->value);
+ }
+
+ return self;
+}
+
+static const tsk_object_def_t tsk_option_def_s =
+{
+ sizeof(tsk_option_t),
+ tsk_option_ctor,
+ tsk_option_dtor,
+ tsk_null,
+};
+const tsk_object_def_t* tsk_option_def_t = &tsk_option_def_s;
+
diff --git a/tinySAK/src/tsk_options.h b/tinySAK/src/tsk_options.h
new file mode 100644
index 0000000..221b2d1
--- /dev/null
+++ b/tinySAK/src/tsk_options.h
@@ -0,0 +1,77 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_options.h
+ * @brief Options.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef _TINYSAK_OPTIONS_H_
+#define _TINYSAK_OPTIONS_H_
+
+#include "tinysak_config.h"
+#include "tsk_object.h"
+#include "tsk_list.h"
+#include "tsk_buffer.h"
+
+
+TSK_BEGIN_DECLS
+
+#define TSK_OPTION_VA_ARGS(id, value) tsk_option_def_t, (int)id, (const char*)value
+
+#define TSK_OPTION(self) ((tsk_option_t*)(self))
+
+/**@ingroup tsk_options_group
+* Parameter.
+*/
+typedef struct tsk_option_s
+{
+ TSK_DECLARE_OBJECT;
+
+ int id;
+ char* value;
+
+ tsk_bool_t tag;
+}
+tsk_option_t;
+
+typedef tsk_list_t tsk_options_L_t; /**< List of @ref tsk_option_t elements. */
+
+TINYSAK_API tsk_option_t* tsk_option_create(int id, const char* value);
+TINYSAK_API tsk_option_t* tsk_option_create_null();
+
+TINYSAK_API int tsk_options_have_option(const tsk_options_L_t *self, int id);
+TINYSAK_API int tsk_options_add_option(tsk_options_L_t **self, int id, const char* value);
+TINYSAK_API int tsk_options_add_option_2(tsk_options_L_t **self, const tsk_option_t* option);
+TINYSAK_API int tsk_options_remove_option(tsk_options_L_t *self, int id);
+TINYSAK_API const tsk_option_t *tsk_options_get_option_by_id(const tsk_options_L_t *self, int id);
+TINYSAK_API const char *tsk_options_get_option_value(const tsk_options_L_t *self, int id);
+TINYSAK_API int tsk_options_get_option_value_as_int(const tsk_options_L_t *self, int id);
+
+TINYSAK_GEXTERN const tsk_object_def_t *tsk_option_def_t;
+
+TSK_END_DECLS
+
+#endif /* _TINYSAK_OPTIONS_H_ */
+
diff --git a/tinySAK/src/tsk_params.c b/tinySAK/src/tsk_params.c
new file mode 100644
index 0000000..5fa15fd
--- /dev/null
+++ b/tinySAK/src/tsk_params.c
@@ -0,0 +1,378 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_params.c
+ * @brief SIP/MSRP/XCAP Parameters parser.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tsk_params.h"
+#include "tsk_memory.h"
+#include "tsk_string.h"
+#include "tsk_common.h"
+#include "tsk_debug.h"
+
+#include <string.h>
+
+/**@defgroup tsk_params_group SIP/MSRP/XCAP Parameters parser.
+*/
+
+/* Predicate function used to find a parameter by name (case-insensitive).
+*/
+static int pred_find_param_by_name(const tsk_list_item_t *item, const void *name)
+{
+ if(item && item->data){
+ tsk_param_t *param = item->data;
+ return tsk_stricmp(param->name, name);
+ }
+ return -1;
+}
+
+/**@ingroup tsk_params_group
+*/
+tsk_param_t* tsk_param_create(const char* name, const char* value)
+{
+ return tsk_object_new(TSK_PARAM_VA_ARGS(name, value));
+}
+
+/**@ingroup tsk_params_group
+*/
+tsk_param_t* tsk_param_create_null()
+{
+ return tsk_param_create(tsk_null, tsk_null);
+}
+
+/**@ingroup tsk_params_group
+* Converts a key-value-pair string (kvp) to @ref tsk_param_t object.
+* @param line The kvp (e.g. 'branch=z9hG4bK652hsge') string to parse.
+* @param size The size (length) of the kvp string.
+* @retval @ref tsk_param_t object.
+*/
+tsk_param_t *tsk_params_parse_param(const char* line, tsk_size_t size)
+{
+ if(line && size){
+ const char* start = line;
+ const char* end = (line + size);
+ const char* equal = strstr(line, "=");
+ tsk_param_t *param = tsk_param_create_null();
+
+ if(param && equal && equal<end){
+ if((param->name = tsk_calloc((equal-start)+1, sizeof(const char)))){
+ memcpy(param->name, start, (equal-start));
+ }
+
+ if((param->value = tsk_calloc((end-equal-1)+1, sizeof(const char)))){
+ memcpy(param->value, equal+1, (end-equal-1));
+ }
+ }
+ else if(param){
+ if((param->name = tsk_calloc((end-start)+1, sizeof(const char)))){
+ memcpy(param->name, start, (end-start));
+ }
+ }
+
+ return param;
+ }
+ return tsk_null;
+}
+/**@ingroup tsk_params_group
+* Checks if the supplied list of parameters contains a parameter named @a name (case-insensitive).
+* @param self The list of parameters into which to search.
+* @param name The name of the parameter to search.
+* @retval @ref tsk_true if the parameter exist and @ref tsk_false otherwise.
+*/
+tsk_bool_t tsk_params_have_param(const tsk_params_L_t *self, const char* name)
+{
+ if(self){
+ if(tsk_list_find_item_by_pred(self, pred_find_param_by_name, name)){
+ return tsk_true;
+ }
+ }
+ else{
+ TSK_DEBUG_ERROR("Invalid parameter");
+ }
+ return tsk_false;
+}
+
+/**@ingroup tsk_params_group
+* Adds a parameter to the list of parameters. If the parameter already exist(case-insensitive), then it's value will be updated.
+* @param self The destination list.
+* @param name The name of the parameter to add.
+* @param value The value of the parameter to add.
+* @retval Zero if succeed and -1 otherwise.
+*/
+int tsk_params_add_param(tsk_params_L_t **self, const char* name, const char* value)
+{
+ tsk_param_t *param;
+
+ if(!self || !name) {
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ if(!*self){
+ *self = tsk_list_create();
+ }
+
+ if((param = (tsk_param_t*)tsk_params_get_param_by_name(*self, name))){
+ tsk_strupdate(&param->value, value); /* Already exist ==> update the value. */
+ }
+ else{
+ param = tsk_param_create(name, value);
+ tsk_list_push_back_data(*self, (void**)&param);
+ }
+
+ return 0;
+}
+
+int tsk_params_add_param_2(tsk_params_L_t **self, const tsk_param_t* param)
+{
+ if(!self || !param || !param){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+
+ return tsk_params_add_param(self, param->name, param->value);
+}
+
+/**@ingroup tsk_params_group
+* Removes a parameter from the list of parameters.
+* @param self The list from which to remove the parameter.
+* @param name The name(case-insensitive) of the parameter to remove.
+* @retval Zero if succeed and -1 otherwise.
+*/
+int tsk_params_remove_param(tsk_params_L_t *self, const char* name)
+{
+ if(self){
+ tsk_list_remove_item_by_pred(self, pred_find_param_by_name, name);
+ return 0;
+ }
+ else{
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+}
+
+/**@ingroup tsk_params_group
+* Gets a parameter from the list of parameters by name.
+* @param self The source list.
+* @param name The name(case-insensitive) of the parameter to retrieve.
+* @retval @ref tsk_param_t if succeed and @ref tsk_null otherwise.
+*/
+const tsk_param_t *tsk_params_get_param_by_name(const tsk_params_L_t *self, const char* name)
+{
+ if(self){
+ const tsk_list_item_t *item_const = tsk_list_find_item_by_pred(self, pred_find_param_by_name, name);
+ if(item_const){
+ return item_const->data;
+ }
+ }
+ else{
+ TSK_DEBUG_ERROR("Invalid parameter");
+ }
+ return tsk_null;
+}
+
+/**@ingroup tsk_params_group
+* Gets the value of a parameter.
+* @param self The source list.
+* @param name The name(case-insensitive) of the parameter to retrieve.
+* @retval The value of the parameter if succeed and NULL otherwise.
+*/
+const char *tsk_params_get_param_value(const tsk_params_L_t *self, const char* name)
+{
+ if(self && name){
+ const tsk_list_item_t *item_const = tsk_list_find_item_by_pred(self, pred_find_param_by_name, name);
+ if(item_const && item_const->data){
+ return ((const tsk_param_t *)item_const->data)->value;
+ }
+ }
+ else{
+ TSK_DEBUG_ERROR("Invalid parameter");
+ }
+ return tsk_null;
+}
+
+/**@ingroup tsk_params_group
+* Gets the value of a parameter.
+* @param self The source list.
+* @param name The name(case-insensitive) of the parameter to retrieve.
+* @retval The value of the parameter if succeed and -1 otherwise.
+*/
+int tsk_params_get_param_value_as_int(const tsk_params_L_t *self, const char* name)
+{
+ const char *value = tsk_params_get_param_value(self, name);
+ return value ? atoi(value) : -1;
+}
+
+/**@ingroup tsk_params_group
+* Serializes a @ref tsk_param_t object.
+* @param param The parameter to serialize.
+* @param output The output buffer.
+* @retval Zero if succeed and -1 otherwise.
+*/
+int tsk_params_param_tostring(const tsk_param_t *param, tsk_buffer_t* output)
+{
+ if(param){
+ return tsk_buffer_append_2(output, param->value?"%s=%s":"%s", param->name, param->value);
+ }
+ return -1;
+}
+
+/**@ingroup tsk_params_group
+* Serializes a @ref tsk_params_L_t object.
+* @param self The list of parameters to serialize.
+* @param separator The character to use as separator between params.
+* @param output The output buffer.
+* @retval Zero if succeed and non-zero error code otherwise.
+*/
+int tsk_params_tostring(const tsk_params_L_t *self, const char separator, tsk_buffer_t* output)
+{
+ int ret = -1;
+
+ if(self){
+ tsk_list_item_t *item;
+ ret = 0; // for empty lists
+ tsk_list_foreach(item, self){
+ tsk_param_t* param = item->data;
+ //tsk_params_param_tostring(param, output);
+ if(TSK_LIST_IS_FIRST(self, item)){
+ if(ret = tsk_buffer_append_2(output, param->value?"%s=%s":"%s", param->name, param->value)){
+ goto bail;
+ }
+ }
+ else{
+ if(ret = tsk_buffer_append_2(output, param->value?"%c%s=%s":"%c%s", separator, param->name, param->value)){
+ goto bail;
+ }
+ }
+ }
+ }
+
+bail:
+ return ret;
+}
+
+/**@ingroup tsk_params_group
+*/
+tsk_params_L_t* tsk_params_fromstring(const char* string, const char* separator, tsk_bool_t trim)
+{
+ tsk_params_L_t* params = tsk_null;
+ tsk_param_t* param;
+
+ int i = 0, index;
+ tsk_size_t size = tsk_strlen(string);
+
+#define PUSH_PARAM() \
+ if(!params){ \
+ params = tsk_list_create(); \
+ } \
+ if(trim){ \
+ if(param->name){ \
+ tsk_strtrim(&param->name); \
+ } \
+ if(param->value){ \
+ tsk_strtrim(&param->value); \
+ } \
+ } \
+ tsk_list_push_back_data(params, (void**)&param);
+
+ while((index = tsk_strindexOf((string + i), (size - i), separator)) != -1){
+ if((param = tsk_params_parse_param((string + i), index))){
+ PUSH_PARAM();
+ }
+ i += (index + 1);
+ }
+
+ // last one
+ if(i<(int)size){
+ if((param = tsk_params_parse_param((string + i), (size - i)))){
+ PUSH_PARAM();
+ }
+ }
+
+ return params;
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+//=================================================================================================
+// param object definition
+//
+static tsk_object_t* tsk_param_ctor(tsk_object_t* self, va_list * app)
+{
+ tsk_param_t *param = self;
+ if(param){
+ const char* name = va_arg(*app, const char *);
+ const char* value = va_arg(*app, const char *);
+
+ if(!tsk_strnullORempty(name)) {
+ param->name = tsk_strdup(name);
+ if(!tsk_strnullORempty(value)) {
+ param->value = tsk_strdup(value);
+ }
+ }
+ }
+
+ return self;
+}
+
+static tsk_object_t* tsk_param_dtor(tsk_object_t* self)
+{
+ tsk_param_t *param = self;
+ if(param){
+ TSK_FREE(param->name);
+ TSK_FREE(param->value);
+ }
+
+ return self;
+}
+
+static const tsk_object_def_t tsk_param_def_s =
+{
+ sizeof(tsk_param_t),
+ tsk_param_ctor,
+ tsk_param_dtor,
+ tsk_null,
+};
+const tsk_object_def_t *tsk_param_def_t = &tsk_param_def_s;
+
diff --git a/tinySAK/src/tsk_params.h b/tinySAK/src/tsk_params.h
new file mode 100644
index 0000000..2c4a5de
--- /dev/null
+++ b/tinySAK/src/tsk_params.h
@@ -0,0 +1,83 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_params.h
+ * @brief SIP/MSRP/XCAP Parameters parser.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef _TINYSAK_PARAMS_H_
+#define _TINYSAK_PARAMS_H_
+
+#include "tinysak_config.h"
+#include "tsk_object.h"
+#include "tsk_list.h"
+#include "tsk_buffer.h"
+
+
+TSK_BEGIN_DECLS
+
+#define TSK_PARAM_VA_ARGS(name, value) tsk_param_def_t, (const char*)name, (const char*)value
+
+#define TSK_PARAM(self) ((tsk_param_t*)(self))
+
+/**@ingroup tsk_params_group
+* Parameter.
+*/
+typedef struct tsk_param_s
+{
+ TSK_DECLARE_OBJECT;
+
+ char *name;/**< The name of the parameter. */
+ char *value;/**< The value of the parameter. */
+
+ tsk_bool_t tag;/**< tag to be used for any use case (e.g. validity of the parameter, whether to ignore the param., ...). Default value: @ref tsk_false.*/
+}
+tsk_param_t;
+
+typedef tsk_list_t tsk_params_L_t; /**< List of @ref tsk_param_t elements. */
+
+TINYSAK_API tsk_param_t* tsk_param_create(const char* name, const char* value);
+TINYSAK_API tsk_param_t* tsk_param_create_null();
+
+TINYSAK_API tsk_param_t *tsk_params_parse_param(const char* line, tsk_size_t size);
+
+TINYSAK_API tsk_bool_t tsk_params_have_param(const tsk_params_L_t *self, const char* name);
+TINYSAK_API int tsk_params_add_param(tsk_params_L_t **self, const char* name, const char* value);
+TINYSAK_API int tsk_params_add_param_2(tsk_params_L_t **self, const tsk_param_t* param);
+TINYSAK_API int tsk_params_remove_param(tsk_params_L_t *self, const char* name);
+TINYSAK_API const tsk_param_t *tsk_params_get_param_by_name(const tsk_params_L_t *self, const char* name);
+TINYSAK_API const char *tsk_params_get_param_value(const tsk_params_L_t *self, const char* name);
+TINYSAK_API int tsk_params_get_param_value_as_int(const tsk_params_L_t *self, const char* name);
+
+TINYSAK_API int tsk_params_param_tostring(const tsk_param_t *param, tsk_buffer_t* output);
+TINYSAK_API int tsk_params_tostring(const tsk_params_L_t *self, const char separator, tsk_buffer_t* output);
+TINYSAK_API tsk_params_L_t* tsk_params_fromstring(const char* string, const char* separator, tsk_bool_t trim);
+
+TINYSAK_GEXTERN const tsk_object_def_t *tsk_param_def_t;
+
+TSK_END_DECLS
+
+#endif /* _TINYSAK_PARAMS_H_ */
+
diff --git a/tinySAK/src/tsk_ppfcs16.c b/tinySAK/src/tsk_ppfcs16.c
new file mode 100644
index 0000000..6fa8066
--- /dev/null
+++ b/tinySAK/src/tsk_ppfcs16.c
@@ -0,0 +1,82 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_ppfcs16.c
+ * @brief PPP in HDLC-like Framing (RFC 1662).
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+
+#include "tsk_ppfcs16.h"
+
+/**@defgroup tsk_ppfcs16_group PPP in HDLC-like Framing (RFC 1662).
+*/
+
+static uint16_t fcstab[256] =
+{
+ 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
+ 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
+ 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
+ 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
+ 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
+ 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
+ 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
+ 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
+ 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
+ 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
+ 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
+ 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
+ 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
+ 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
+ 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
+ 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
+ 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
+ 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
+ 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
+ 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
+ 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
+ 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
+ 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
+ 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
+ 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
+ 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
+ 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
+ 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
+ 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
+ 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
+ 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
+ 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
+};
+
+/**@ingroup tsk_ppfcs16_group
+* Calculates a new fcs given the current fcs and the new data.
+*/
+uint16_t tsk_pppfcs16(register uint16_t fcs, register const uint8_t* cp, register int32_t len)
+{
+ while (len--){
+ fcs = (fcs >> 8) ^ fcstab[(fcs ^ *cp++) & 0xff];
+ }
+ return (fcs);
+}
+
diff --git a/tinySAK/src/tsk_ppfcs16.h b/tinySAK/src/tsk_ppfcs16.h
new file mode 100644
index 0000000..ae62968
--- /dev/null
+++ b/tinySAK/src/tsk_ppfcs16.h
@@ -0,0 +1,45 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_ppfcs16.h
+ * @brief PPP in HDLC-like Framing (RFC 1662).
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef _TINYSAK_PPFCS16_H_
+#define _TINYSAK_PPFCS16_H_
+
+#include "tinysak_config.h"
+
+TSK_BEGIN_DECLS
+
+#define TSK_PPPINITFCS16 0xffff /* Initial FCS value */
+#define TSK_PPPGOODFCS16 0xf0b8 /* Good final FCS value */
+
+TINYSAK_API uint16_t tsk_pppfcs16(register uint16_t fcs, register const uint8_t* cp, register int32_t len);
+
+TSK_END_DECLS
+
+#endif /* _TINYSAK_PPFCS16_H_ */
+
diff --git a/tinySAK/src/tsk_ppfcs32.c b/tinySAK/src/tsk_ppfcs32.c
new file mode 100644
index 0000000..2514648
--- /dev/null
+++ b/tinySAK/src/tsk_ppfcs32.c
@@ -0,0 +1,115 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_ppfcs32.c
+ * @brief PPP in HDLC-like Framing (RFC 1662).
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+
+#include "tsk_ppfcs32.h"
+
+/**@defgroup tsk_ppfcs32_group PPP in HDLC-like Framing (RFC 1662).
+*/
+
+static uint32_t fcstab_32[256] =
+{
+ 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
+ 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
+ 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+ 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
+ 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+ 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+ 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
+ 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
+ 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+ 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+ 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
+ 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+ 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
+ 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
+ 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+ 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
+ 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
+ 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+ 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
+ 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+ 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+ 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
+ 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
+ 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+ 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+ 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
+ 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+ 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
+ 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
+ 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+ 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
+ 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
+ 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+ 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
+ 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+ 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+ 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
+ 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
+ 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+ 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+ 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
+ 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+ 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
+ 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
+ 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+ 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
+ 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
+ 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+ 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
+ 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+ 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+ 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
+ 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
+ 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+ 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+ 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
+ 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+ 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
+ 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
+ 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+ 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
+ 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
+ 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+ 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
+};
+
+/**@ingroup tsk_ppfcs32_group
+* Calculates a new fcs given the current fcs and the new data.
+*/
+uint32_t tsk_pppfcs32(register uint32_t fcs, register const uint8_t* cp, register int32_t len)
+{
+ while (len--){
+ fcs = (((fcs) >> 8) ^ fcstab_32[((fcs) ^ (*cp++)) & 0xff]);
+ }
+
+ return (fcs);
+}
+
diff --git a/tinySAK/src/tsk_ppfcs32.h b/tinySAK/src/tsk_ppfcs32.h
new file mode 100644
index 0000000..2499e47
--- /dev/null
+++ b/tinySAK/src/tsk_ppfcs32.h
@@ -0,0 +1,45 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_ppfcs32.h
+ * @brief PPP in HDLC-like Framing (RFC 1662).
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef _TINYSAK_PPFCS32_H_
+#define _TINYSAK_PPFCS32_H_
+
+#include "tinysak_config.h"
+
+TSK_BEGIN_DECLS
+
+#define TSK_PPPINITFCS32 0xffffffff /* Initial FCS value */
+#define TSK_PPPGOODFCS32 0xdebb20e3 /* Good final FCS value */
+
+TINYSAK_API uint32_t tsk_pppfcs32(register uint32_t fcs, register const uint8_t* cp, register int32_t len);
+
+TSK_END_DECLS
+
+#endif /* _TINYSAK_PPFCS32_H_ */
+
diff --git a/tinySAK/src/tsk_ragel_state.c b/tinySAK/src/tsk_ragel_state.c
new file mode 100644
index 0000000..37ddaee
--- /dev/null
+++ b/tinySAK/src/tsk_ragel_state.c
@@ -0,0 +1,51 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_ragel_state.c
+ * @brief Ragel state for SIP, HTTP and MSRP parsing.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tsk_ragel_state.h"
+
+/**@defgroup tsk_ragel_state_group Ragel state for SIP, HTTP and MSRP parsing.
+*/
+
+/**@ingroup tsk_ragel_state_group
+* Initialize/Reset the ragel state with default values.
+* @param state The ragel @a state to initialize.
+* @param data The @a data to parse.
+* @param size The @a size of the data.
+*/
+void tsk_ragel_state_init(tsk_ragel_state_t *state, const char *data, tsk_size_t size)
+{
+ state->cs = 0;
+ state->p = data;
+ state->pe = state->p + size;
+ state->eof = 0;
+
+ state->tag_start = 0;
+ state->tag_end = 0;
+}
+
diff --git a/tinySAK/src/tsk_ragel_state.h b/tinySAK/src/tsk_ragel_state.h
new file mode 100644
index 0000000..6adb571
--- /dev/null
+++ b/tinySAK/src/tsk_ragel_state.h
@@ -0,0 +1,184 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_ragel_state.h
+ * @brief Ragel state for SIP, HTTP and MSRP parsing.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef TINYSAK_RAGEL_STATE_H
+#define TINYSAK_RAGEL_STATE_H
+
+#include "tinysak_config.h"
+#include "tsk_params.h"
+
+#include <string.h>
+
+TSK_BEGIN_DECLS
+
+
+#if defined(_MSC_VER)
+# define atoi64 _atoi64
+#else
+# define atoi64 atoll
+#endif
+
+/**@ingroup tsk_ragel_state_group
+*/
+#define TSK_SCANNER_SET_STRING(string) \
+ if(!string) \
+ { \
+ int len = (int)(te - ts); \
+ if(len >0) \
+ { \
+ string = tsk_calloc(len+1, sizeof(char)), memcpy(string, ts, len); \
+ } \
+ }
+
+/**@ingroup tsk_ragel_state_group
+*/
+#define TSK_PARSER_SET_STRING(string) \
+ { \
+ int len = (int)(p - tag_start); \
+ if(len && tag_start){ \
+ if(string){ \
+ TSK_FREE(string); \
+ } \
+ string = tsk_calloc(len+1, sizeof(char)), memcpy(string, tag_start, len); \
+ } \
+ }
+
+/**@ingroup tsk_ragel_state_group
+*/
+#define TSK_SCANNER_SET_INTEGER(integer) \
+ { \
+ int len = (int)(te - ts); \
+ if(len>=0) \
+ { \
+ char* tmp = tsk_calloc(len+1, sizeof(char)); \
+ memcpy(tmp, ts, len); \
+ integer = atoi(tmp); \
+ free(tmp); \
+ } \
+ }
+
+/**@ingroup tsk_ragel_state_group
+*/
+#define TSK_PARSER_SET_INTEGER_EX(retval, type, func) \
+ { \
+ int len = (int)(p - tag_start); \
+ if(len>=0) \
+ { \
+ char* tmp = tsk_calloc(len+1, sizeof(char)); \
+ memcpy(tmp, tag_start, len); \
+ retval = (type) func(tmp); \
+ free(tmp); \
+ } \
+ }
+/**@ingroup tsk_ragel_state_group
+* @def TSK_PARSER_SET_INTEGER
+*/
+/**@ingroup tsk_ragel_state_group
+* @def TSK_PARSER_SET_INT
+*/
+/**@ingroup tsk_ragel_state_group
+* @def TSK_PARSER_SET_UINT
+*/
+/**@ingroup tsk_ragel_state_group
+* @def TSK_PARSER_SET_FLOAT
+*/
+/**@ingroup tsk_ragel_state_group
+* @def TSK_PARSER_SET_DOUBLE
+*/
+#define TSK_PARSER_SET_INTEGER(retval) TSK_PARSER_SET_INTEGER_EX(retval, int, atoi)
+#define TSK_PARSER_SET_INT(retval) TSK_PARSER_SET_INTEGER(retval)
+#define TSK_PARSER_SET_UINT(retval) TSK_PARSER_SET_INTEGER_EX(retval, uint32_t, atoi64)
+#define TSK_PARSER_SET_FLOAT(retval) TSK_PARSER_SET_INTEGER_EX(retval, float, atof)
+#define TSK_PARSER_SET_DOUBLE(retval) TSK_PARSER_SET_INTEGER_EX(retval, double, atof)
+
+/**@ingroup tsk_ragel_state_group
+*/
+#define TSK_PARSER_ADD_PARAM(dest) \
+ { \
+ tsk_size_t len = (tsk_size_t)(p - tag_start); \
+ tsk_param_t *param = tsk_params_parse_param(tag_start, len); \
+ if(param) \
+ { \
+ if(!dest) dest = tsk_list_create(); \
+ tsk_list_push_back_data(dest, ((void**) &param)); \
+ } \
+ }
+
+/**@ingroup tsk_ragel_state_group
+*/
+#define TSK_SACANNER_ADD_PARAM(dest) \
+ { \
+ int len = (int)(te - ts); \
+ if(len >0) \
+ { \
+ tsk_param_t *param = tsk_params_parse_param(ts, len); \
+ if(param) \
+ { \
+ if(!dest) dest = tsk_list_create(); \
+ tsk_list_push_back_data(dest, ((void**) &param)); \
+ } \
+ } \
+ }
+
+/**@ingroup tsk_ragel_state_group
+*/
+#define TSK_PARSER_ADD_STRING(dest) \
+ { \
+ tsk_size_t len = (tsk_size_t)(p - tag_start); \
+ tsk_string_t *string = tsk_string_create(tsk_null); \
+ string->value = tsk_calloc(len+1, sizeof(char)), memcpy(string->value, tag_start, len); \
+ if(!dest) \
+ { \
+ dest = tsk_list_create(); \
+ } \
+ tsk_list_push_back_data(dest, ((void**) &string)); \
+ }
+
+/**@ingroup tsk_ragel_state_group
+* Ragel state.
+*/
+typedef struct tsk_ragel_state_s
+{
+ int cs; /**< Ragel current state. */
+ const char *p; /**< Data pointing to the buffer to parse. */
+ const char *pe; /**< Data end pointer. */
+ const char *eof; /**< End of the file (in our cas data) pointer. */
+
+ const char* tag_start; /**< Last tag start position set by ragel machine. */
+ const char* tag_end; /**< The end of the ragel tag. */
+}
+tsk_ragel_state_t;
+
+
+TINYSAK_API void tsk_ragel_state_init(tsk_ragel_state_t *state, const char *data, tsk_size_t size);
+
+TSK_END_DECLS
+
+#endif /* TINYSAK_RAGEL_STATE_H */
+
diff --git a/tinySAK/src/tsk_runnable.c b/tinySAK/src/tsk_runnable.c
new file mode 100644
index 0000000..7125b1e
--- /dev/null
+++ b/tinySAK/src/tsk_runnable.c
@@ -0,0 +1,236 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_runnable.c
+ * @brief Base class for runnable object.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tsk_runnable.h"
+#include "tsk_thread.h"
+#include "tsk_debug.h"
+
+/**@defgroup tsk_runnable_group Base class for runnable object.
+*/
+
+/**@ingroup tsk_runnable_group
+* Creates new Runnable object.
+* @retval @ref tsk_runnable_t.
+*/
+tsk_runnable_t* tsk_runnable_create()
+{
+ return tsk_object_new(tsk_runnable_def_t);
+}
+
+/**@ingroup tsk_runnable_group
+* Initializes a runnable object and allocate it's internal fields.
+* @param self The runnable object to initialize.
+* @param objdef Internal objects definition class.
+* @retval Zero if succeed and nonzero error code otherwise.
+* @sa tsk_runnable_deinit.
+*/
+static int tsk_runnable_init(tsk_runnable_t *self, const tsk_object_def_t *objdef)
+{
+ if(self && objdef){
+ if(self->initialized){
+ TSK_DEBUG_ERROR("Already initialized");
+ return -2;
+ }
+
+ self->semaphore = tsk_semaphore_create();
+ self->objdef = objdef;
+ self->objects = tsk_list_create();
+
+ self->initialized = tsk_true;
+ return 0;
+ }
+ TSK_DEBUG_ERROR("Invalid Parameter");
+ return -1;
+}
+
+/**@ingroup tsk_runnable_group
+* DeInitializes a runnable object.
+* @param self The runnable object to deinitialize.
+* @retval Zero if succeed and nonzero error code otherwise.
+* @sa tsk_runnable_init.
+*/
+static int tsk_runnable_deinit(tsk_runnable_t *self)
+{
+ if(self){
+ if(!self->initialized){
+ return 0; /* Already deinitialized */
+ }
+ else if(self->running){
+ TSK_DEBUG_ERROR("Cannot deinit a runnable object while running.");
+ return -3;
+ }
+
+ tsk_semaphore_destroy(&self->semaphore);
+ TSK_OBJECT_SAFE_FREE(self->objects);
+
+ self->initialized = tsk_false;
+
+ return 0;
+ }
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+}
+
+/**@ingroup tsk_runnable_group
+* Starts a runnable object.
+* @param self The runnable object to start.
+* @param objdef Internal objects definition (meta-data) class.
+* @retval Zero if succeed and nonzero error code otherwise.
+* @sa tsk_runnable_stop.
+*/
+int tsk_runnable_start(tsk_runnable_t *self, const tsk_object_def_t *objdef)
+{
+ if(self){
+ int ret = -1;
+ if(self->running) return -2;
+ else if(!self->run) return -3;
+ else if(tsk_runnable_init(self, objdef)) return -4;
+
+ /* call run() function in new thread. */
+ if((ret = tsk_thread_create(&(self->tid[0]), self->run, self))){
+ TSK_DEBUG_ERROR("Failed to start new thread.");
+ return ret;
+ }
+ // Do not set "running" to true here
+ // Problem: When you try to stop the thread before it start
+ // Will be done by "TSK_RUNNABLE_RUN_BEGIN" which is called into the thread
+ //self->running = tsk_true;
+
+ self->started = tsk_true;
+ return 0;
+ }
+ else{
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+}
+
+/**@ingroup tsk_runnable_group
+* To indicate whether the enqueued data is important or not.
+* @param self The runnable object
+* @param important @a tsk_true or @a tsk_false. If set to @a tsk_true, the thread will not be joined
+* until all data in the queue have been consumed.
+*/
+int tsk_runnable_set_important(tsk_runnable_t *self, tsk_bool_t important)
+{
+ if(self){
+ self->important = important;
+ return 0;
+ }
+ else{
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+}
+
+/**@ingroup tsk_runnable_group
+* Stops a runnable object.
+* @param self The runnable object to stop.
+* @retval Zero if succeed and nonzero error code otherwise.
+* @sa tsk_runnable_start.
+*/
+int tsk_runnable_stop(tsk_runnable_t *self)
+{
+ int ret = -1;
+ if(self){
+ if(!self->initialized) {
+ if(!self->running){
+ /* already deinitialized */
+ return 0;
+ }
+ else{
+ /* should never happen */
+ TSK_DEBUG_ERROR("Not initialized.");
+ return -2;
+ }
+ }
+ else if(!self->running) {
+
+ if(self->started){
+ tsk_size_t count = 0;
+ /* Thread is started but not running ==> Give it time.*/
+ while(++count <= 5){
+ tsk_thread_sleep(count * 200);
+ if(self->running){
+ goto stop;
+ }
+ }
+ }
+ else{
+ return 0; /* already stopped */
+ }
+ return -3;
+ }
+
+stop:
+ self->running = tsk_false;
+ tsk_semaphore_increment(self->semaphore);
+
+ if((ret = tsk_thread_join(&(self->tid[0])))){
+ self->running = tsk_true;
+ TSK_DEBUG_ERROR("Failed to join the thread.");
+ return ret;
+ }
+ tsk_runnable_deinit(self);
+
+ self->started = tsk_false;
+ }
+ return ret;
+}
+
+//=================================================================================================
+// Runnable object definition
+//
+static tsk_object_t* tsk_runnable_ctor(tsk_object_t * self, va_list * app)
+{
+ tsk_runnable_t* runnable = self;
+ if(runnable){
+ }
+ return self;
+}
+
+static tsk_object_t* tsk_runnable_dtor(tsk_object_t * self)
+{
+ tsk_runnable_t* runnable = self;
+ if(runnable){
+ /* stops runnable object (if running or started) */
+ tsk_runnable_stop(runnable);
+ }
+ return self;
+}
+
+static const tsk_object_def_t tsk_runnable_def_s =
+{
+ sizeof(tsk_runnable_t),
+ tsk_runnable_ctor,
+ tsk_runnable_dtor,
+ tsk_null,
+};
+const tsk_object_def_t *tsk_runnable_def_t = &tsk_runnable_def_s;
+
diff --git a/tinySAK/src/tsk_runnable.h b/tinySAK/src/tsk_runnable.h
new file mode 100644
index 0000000..d182dcd
--- /dev/null
+++ b/tinySAK/src/tsk_runnable.h
@@ -0,0 +1,167 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_runnable.h
+ * @brief Base class for runnable object.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef _TINYSAK_RUNNABLE_H_
+#define _TINYSAK_RUNNABLE_H_
+
+#include "tinysak_config.h"
+
+#include "tsk_object.h"
+#include "tsk_semaphore.h"
+#include "tsk_list.h"
+
+TSK_BEGIN_DECLS
+
+/**@ingroup tsk_runnable_group
+*/
+typedef void * (*tsk_runnable_func_run)(void* self);
+
+/**@ingroup tsk_runnable_group
+*/
+#define TSK_RUNNABLE(self) ((tsk_runnable_t*)(self))
+
+/**@ingroup tsk_runnable_group
+* Runnable.
+*/
+typedef struct tsk_runnable_s
+{
+ TSK_DECLARE_OBJECT;
+
+ const tsk_object_def_t *objdef;
+
+ void* tid[1];
+ tsk_runnable_func_run run;
+ tsk_semaphore_handle_t *semaphore;
+
+ tsk_bool_t running;
+ tsk_bool_t started;
+ tsk_bool_t initialized;
+ /** whether the enqueued data are important or not.
+ * if yes, the thread will not be joined until all data in the queue have been consumed.
+ * default value: tsk_false
+ */
+ tsk_bool_t important;
+
+ tsk_list_t *objects;
+}
+tsk_runnable_t;
+
+/**@ingroup tsk_runnable_group
+*/
+#define TSK_DECLARE_RUNNABLE tsk_runnable_t __runnable__
+
+TINYSAK_API tsk_runnable_t* tsk_runnable_create();
+
+TINYSAK_API int tsk_runnable_start(tsk_runnable_t *self, const tsk_object_def_t *objdef);
+TINYSAK_API int tsk_runnable_set_important(tsk_runnable_t *self, tsk_bool_t important);
+TINYSAK_API int tsk_runnable_enqueue(tsk_runnable_t *self, ...);
+TINYSAK_API int tsk_runnable_stop(tsk_runnable_t *self);
+
+TINYSAK_GEXTERN const tsk_object_def_t *tsk_runnable_def_t;
+
+
+/**@ingroup tsk_runnable_group
+* @def TSK_RUNNABLE_RUN_BEGIN
+*/
+/**@ingroup tsk_runnable_group
+* @def TSK_RUNNABLE_RUN_END
+*/
+#define TSK_RUNNABLE_RUN_BEGIN(self) \
+ TSK_RUNNABLE(self)->running = tsk_true; \
+ for(;;) { \
+ tsk_semaphore_decrement(TSK_RUNNABLE(self)->semaphore); \
+ if(!TSK_RUNNABLE(self)->running && \
+ (!TSK_RUNNABLE(self)->important || (TSK_RUNNABLE(self)->important && TSK_LIST_IS_EMPTY(TSK_RUNNABLE(self)->objects)))) \
+ break;
+
+
+#define TSK_RUNNABLE_RUN_END(self) \
+ } \
+ TSK_RUNNABLE(self)->running = tsk_false;
+
+/**@ingroup tsk_runnable_group
+* @def TSK_RUNNABLE_ENQUEUE
+*/
+/**@ingroup tsk_runnable_group
+* @def TSK_RUNNABLE_ENQUEUE_OBJECT
+*/
+#define TSK_RUNNABLE_ENQUEUE(self, ...) \
+{ \
+ if((self) && TSK_RUNNABLE(self)->initialized){ \
+ tsk_object_t *object = tsk_object_new(TSK_RUNNABLE(self)->objdef, ##__VA_ARGS__); \
+ tsk_list_push_back_data(TSK_RUNNABLE(self)->objects, (void**)&object); \
+ tsk_semaphore_increment(TSK_RUNNABLE(self)->semaphore); \
+ } \
+ else{ \
+ TSK_DEBUG_WARN("Invalid/uninitialized runnable object."); \
+ } \
+}
+
+#define TSK_RUNNABLE_ENQUEUE_OBJECT(self, object) \
+{ \
+ if((self) && TSK_RUNNABLE(self)->initialized){ \
+ tsk_list_push_back_data(TSK_RUNNABLE(self)->objects, (void**)&object); \
+ tsk_semaphore_increment(TSK_RUNNABLE(self)->semaphore); \
+ } \
+ else{ \
+ TSK_DEBUG_WARN("Invalid/uninitialized runnable object."); \
+ TSK_OBJECT_SAFE_FREE(object); \
+ } \
+}
+
+#define TSK_RUNNABLE_ENQUEUE_OBJECT_SAFE(self, object) \
+{ \
+ if((self) && TSK_RUNNABLE(self)->initialized){ \
+ tsk_list_lock(TSK_RUNNABLE(self)->objects); \
+ tsk_list_push_back_data(TSK_RUNNABLE(self)->objects, (void**)&object); \
+ tsk_list_unlock(TSK_RUNNABLE(self)->objects); \
+ tsk_semaphore_increment(TSK_RUNNABLE(self)->semaphore); \
+ } \
+ else{ \
+ TSK_DEBUG_WARN("Invalid/uninitialized runnable object."); \
+ TSK_OBJECT_SAFE_FREE(object); \
+ } \
+}
+
+/**@ingroup tsk_runnable_group
+*/
+#define TSK_RUNNABLE_POP_FIRST(self) \
+ tsk_list_pop_first_item(TSK_RUNNABLE(self)->objects)
+static tsk_list_item_t* TSK_RUNNABLE_POP_FIRST_SAFE(tsk_runnable_t* self){
+ tsk_list_item_t* item;
+ tsk_list_lock(self->objects);
+ item= tsk_list_pop_first_item(self->objects);
+ tsk_list_unlock(self->objects);
+ return item;
+}
+
+TSK_END_DECLS
+
+#endif /* _TINYSAK_RUNNABLE_H_ */
+
diff --git a/tinySAK/src/tsk_safeobj.c b/tinySAK/src/tsk_safeobj.c
new file mode 100644
index 0000000..d32a527
--- /dev/null
+++ b/tinySAK/src/tsk_safeobj.c
@@ -0,0 +1,33 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_safeobj.c
+ * @brief Thread-Safe object.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tsk_safeobj.h"
+
+/**@defgroup tsk_safeobj_group Helper macros to declare thread-safe objects.
+*/
diff --git a/tinySAK/src/tsk_safeobj.h b/tinySAK/src/tsk_safeobj.h
new file mode 100644
index 0000000..f3190f5
--- /dev/null
+++ b/tinySAK/src/tsk_safeobj.h
@@ -0,0 +1,81 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_safeobj.h
+ * @brief Thread-Safe object.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef _TINYSAK_SAFEOBJ_H_
+#define _TINYSAK_SAFEOBJ_H_
+
+#include "tinysak_config.h"
+#include "tsk_mutex.h"
+
+TSK_BEGIN_DECLS
+
+//#define TSK_DECLARE_SAFEOBJ\
+// union{ \
+// tsk_mutex_handle_t *mutex; \
+// }
+
+/**@ingroup tsk_safeobj_group
+* Macro helper to declare an object as thread-safe.
+*/
+#define TSK_DECLARE_SAFEOBJ tsk_mutex_handle_t *mutex
+
+#define TSK_SAFEOBJ_MUTEX(safeobj) ((safeobj)->mutex)
+
+/**@ingroup tsk_safeobj_group
+* @def tsk_safeobj_init
+* You MUST call this method before using @ref tsk_safeobj_lock or @ref tsk_safeobj_unlock to initilize the internal mutex.
+* Before freeing your safeobject you MUST call @ref tsk_safeobj_deinit to deinitialize the internal mutex.
+* @param safeobj The thread-safe object to initialize.
+* @sa @ref tsk_safeobj_deinit.
+*/
+/**@ingroup tsk_safeobj_group
+*@def tsk_safeobj_lock
+* Locks a previously initialized safeobject.
+* @param safeobj The thread-safe object to lock.
+*/
+/**@ingroup tsk_safeobj_group
+*@def tsk_safeobj_unlock
+* Unlocks a previously locked safeobject.
+* @param safeobj The thread-safe object to unlock.
+*/
+/**@ingroup tsk_safeobj_group
+*@def tsk_safeobj_deinit
+* Deinitialize a previously initialize safeobject.
+* @param safeobj The thread-safe object to deinitialize.
+* @sa @ref tsk_safeobj_init.
+*/
+#define tsk_safeobj_init(safeobj) TSK_SAFEOBJ_MUTEX(safeobj) = (TSK_SAFEOBJ_MUTEX(safeobj) ? TSK_SAFEOBJ_MUTEX(safeobj) : tsk_mutex_create())
+#define tsk_safeobj_lock(safeobj) tsk_mutex_lock(TSK_SAFEOBJ_MUTEX(safeobj))
+#define tsk_safeobj_unlock(safeobj) tsk_mutex_unlock(TSK_SAFEOBJ_MUTEX(safeobj))
+#define tsk_safeobj_deinit(safeobj) tsk_mutex_destroy(&TSK_SAFEOBJ_MUTEX(safeobj))
+
+TSK_END_DECLS
+
+#endif /* _TINYSAK_SAFEOBJ_H_ */
+
diff --git a/tinySAK/src/tsk_semaphore.c b/tinySAK/src/tsk_semaphore.c
new file mode 100644
index 0000000..649c4a8
--- /dev/null
+++ b/tinySAK/src/tsk_semaphore.c
@@ -0,0 +1,198 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_semaphore.c
+* @brief Pthread/Windows Semaphore utility functions.
+*
+* @author Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* @date Created: Sat Nov 8 16:54:58 2009 mdiop
+*/
+#include "tsk_semaphore.h"
+#include "tsk_memory.h"
+#include "tsk_debug.h"
+#include "tsk_string.h"
+
+/* Apple claims that they fully support POSIX semaphore but ...
+ */
+#if defined(__APPLE__) /* Mac OSX/Darwin/Iphone/Ipod Touch */
+# define TSK_USE_NAMED_SEM 1
+#else
+# define TSK_USE_NAMED_SEM 0
+#endif
+
+#if TSK_UNDER_WINDOWS /* Windows XP/Vista/7/CE */
+
+# include <windows.h>
+# include "tsk_errno.h"
+# define SEMAPHORE_S void
+ typedef HANDLE SEMAPHORE_T;
+//#else if define(__APPLE__) /* Mac OSX/Darwin/Iphone/Ipod Touch */
+//# include <march/semaphore.h>
+//# include <march/task.h>
+#else /* All *nix */
+
+# include <pthread.h>
+# include <semaphore.h>
+# if TSK_USE_NAMED_SEM
+# include <fcntl.h> /* O_CREAT */
+# include <sys/stat.h> /* S_IRUSR, S_IWUSR*/
+
+ static int sem_count = 0;
+ typedef struct named_sem_s
+ {
+ sem_t* sem;
+ char* name;
+ } named_sem_t;
+# define SEMAPHORE_S named_sem_t
+# define GET_SEM(PSEM) (((named_sem_t*)(PSEM))->sem)
+# else
+# define SEMAPHORE_S sem_t
+# define GET_SEM(PSEM) ((PSEM))
+# endif /* TSK_USE_NAMED_SEM */
+ typedef sem_t* SEMAPHORE_T;
+
+#endif
+
+#if defined(__GNUC__) || defined(__SYMBIAN32__)
+# include <errno.h>
+#endif
+
+
+
+/**@defgroup tsk_semaphore_group Pthread/Windows Semaphore functions.
+*/
+
+/**@ingroup tsk_semaphore_group
+* Creates new semaphore handle.
+* @retval A New semaphore handle.
+* You MUST call @ref tsk_semaphore_destroy to free the semaphore.
+* @sa @ref tsk_semaphore_destroy
+*/
+tsk_semaphore_handle_t* tsk_semaphore_create()
+{
+ SEMAPHORE_T handle = 0;
+
+#if TSK_UNDER_WINDOWS
+ handle = CreateSemaphore(NULL, 0, 0x7FFFFFFF, NULL);
+#else
+ handle = tsk_calloc(1, sizeof(SEMAPHORE_S));
+
+#if TSK_USE_NAMED_SEM
+ named_sem_t * nsem = (named_sem_t*)handle;
+ tsk_sprintf(&(nsem->name), "/sem-%d", sem_count++);
+ if((nsem->sem = sem_open(nsem->name, O_CREAT /*| O_EXCL*/, S_IRUSR | S_IWUSR, 0)) == SEM_FAILED)
+ {
+ TSK_FREE(nsem->name);
+#else
+ if(sem_init((SEMAPHORE_T)handle, 0, 0))
+ {
+#endif
+ TSK_FREE(handle);
+ TSK_DEBUG_ERROR("Failed to initialize the new semaphore (errno=%d).", errno);
+ }
+#endif
+
+ if(!handle){
+ TSK_DEBUG_ERROR("Failed to create new mutex.");
+ }
+ return handle;
+}
+
+/**@ingroup tsk_semaphore_group
+* Increments a semaphore.
+* @param handle The semaphore to increment.
+* @retval Zero if succeed and otherwise the function returns -1 and sets errno to indicate the error.
+* @sa @ref tsk_semaphore_decrement.
+*/
+int tsk_semaphore_increment(tsk_semaphore_handle_t* handle)
+{
+ int ret = EINVAL;
+ if(handle)
+ {
+#if TSK_UNDER_WINDOWS
+ if((ret = ReleaseSemaphore((SEMAPHORE_T)handle, 1L, 0L) ? 0 : -1))
+#else
+ if(ret = sem_post((SEMAPHORE_T)GET_SEM(handle)))
+#endif
+ {
+ TSK_DEBUG_ERROR("sem_post function failed: %d", ret);
+ }
+ }
+ return ret;
+}
+
+/**@ingroup tsk_semaphore_group
+* Decrements a semaphore.
+* @param handle The semaphore to decrement.
+* @retval Zero if succeed and otherwise the function returns -1 and sets errno to indicate the error.
+* @sa @ref tsk_semaphore_increment.
+*/
+int tsk_semaphore_decrement(tsk_semaphore_handle_t* handle)
+{
+ int ret = EINVAL;
+ if(handle)
+ {
+#if TSK_UNDER_WINDOWS
+ ret = (WaitForSingleObject((SEMAPHORE_T)handle, INFINITE) == WAIT_OBJECT_0 ? 0 : -1);
+ if(ret) TSK_DEBUG_ERROR("sem_wait function failed: %d", ret);
+#else
+ do
+ {
+ ret = sem_wait((SEMAPHORE_T)GET_SEM(handle));
+ }
+ while ( errno == EINTR );
+ if(ret) TSK_DEBUG_ERROR("sem_wait function failed: %d", errno);
+#endif
+ }
+
+ return ret;
+}
+
+/**@ingroup tsk_semaphore_group
+* Destroy a semaphore previously created using @ref tsk_semaphore_create.
+* @param handle The semaphore to free.
+* @sa @ref tsk_semaphore_create
+*/
+void tsk_semaphore_destroy(tsk_semaphore_handle_t** handle)
+{
+ if(handle && *handle)
+ {
+#if TSK_UNDER_WINDOWS
+ CloseHandle((SEMAPHORE_T)*handle);
+ *handle = 0;
+#else
+# if TSK_USE_NAMED_SEM
+ named_sem_t * nsem = ((named_sem_t*)*handle);
+ sem_close(nsem->sem);
+ TSK_FREE(nsem->name);
+#else
+ sem_destroy((SEMAPHORE_T)GET_SEM(*handle));
+#endif /* TSK_USE_NAMED_SEM */
+ tsk_free(handle);
+#endif
+ }
+ else{
+ TSK_DEBUG_WARN("Cannot free an uninitialized semaphore object");
+ }
+}
+
diff --git a/tinySAK/src/tsk_semaphore.h b/tinySAK/src/tsk_semaphore.h
new file mode 100644
index 0000000..abb94d0
--- /dev/null
+++ b/tinySAK/src/tsk_semaphore.h
@@ -0,0 +1,47 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_semaphore.h
+ * @brief Pthread Semaphore.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef _TINYSAK_SEMAPHORE_H_
+#define _TINYSAK_SEMAPHORE_H_
+
+#include "tinysak_config.h"
+
+TSK_BEGIN_DECLS
+
+typedef void tsk_semaphore_handle_t;
+
+TINYSAK_API tsk_semaphore_handle_t* tsk_semaphore_create();
+TINYSAK_API int tsk_semaphore_increment(tsk_semaphore_handle_t* handle);
+TINYSAK_API int tsk_semaphore_decrement(tsk_semaphore_handle_t* handle);
+TINYSAK_API void tsk_semaphore_destroy(tsk_semaphore_handle_t** handle);
+
+TSK_END_DECLS
+
+#endif /* _TINYSAK_SEMAPHORE_H_ */
+
diff --git a/tinySAK/src/tsk_sha1.c b/tinySAK/src/tsk_sha1.c
new file mode 100644
index 0000000..5828874
--- /dev/null
+++ b/tinySAK/src/tsk_sha1.c
@@ -0,0 +1,455 @@
+/*
+ *
+ * Based on the RFC 3174
+ *
+ * Full Copyright Statement
+ *
+ * Copyright (C) The Internet Society (2001). All Rights Reserved.
+ * Copyright (C) Mamadou Diop (2009)
+ *
+ * This document and translations of it may be copied and furnished to
+ * others, and derivative works that comment on or otherwise explain it
+ * or assist in its implementation may be prepared, copied, published
+ * and distributed, in whole or in part, without restriction of any
+ * kind, provided that the above copyright notice and this paragraph are
+ * included on all such copies and derivative works. However, this
+ * document itself may not be modified in any way, such as by removing
+ * the copyright notice or references to the Internet Society or other
+ * Internet organizations, except as needed for the purpose of
+ * developing Internet standards in which case the procedures for
+ * copyrights defined in the Internet Standards process must be
+ * followed, or as required to translate it into languages other than
+ * English.
+ *
+ * The limited permissions granted above are perpetual and will not be
+ * revoked by the Internet Society or its successors or assigns.
+
+ * This document and the information contained herein is provided on an
+ * "AS IS" basis and THE INTERNET SOCIETY AND THE INTERNET ENGINEERING
+ * TASK FORCE DISCLAIMS ALL WARRANTIES, EXPRESS OR IMPLIED, INCLUDING
+ * BUT NOT LIMITED TO ANY WARRANTY THAT THE USE OF THE INFORMATION
+ * HEREIN WILL NOT INFRINGE ANY RIGHTS OR ANY IMPLIED WARRANTIES OF
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ *
+ *
+ * Description:
+ * This file implements the Secure Hashing Algorithm 1 as
+ * defined in FIPS PUB 180-1 published April 17, 1995.
+ *
+ * The SHA-1, produces a 160-bit message digest for a given
+ * data stream. It should take about 2**n steps to find a
+ * message with the same digest as a given message and
+ * 2**(n/2) to find any two messages with the same digest,
+ * when n is the digest size in bits. Therefore, this
+ * algorithm can serve as a means of providing a
+ * "fingerprint" for a message.
+ *
+ * Portability Issues:
+ * SHA-1 is defined in terms of 32-bit "words". This code
+ * uses <stdint.h> (included via "sha1.h" to define 32 and 8
+ * bit unsigned integer types. If your C compiler does not
+ * support 32 bit unsigned integers, this code is not
+ * appropriate.
+ *
+ * Caveats:
+ * SHA-1 is designed to work with messages less than 2^64 bits
+ * long. Although SHA-1 allows a message digest to be generated
+ * for messages of any number of bits less than 2^64, this
+ * implementation only works with messages with a length that is
+ * a multiple of the size of an 8-bit character.
+ *
+ */
+
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_sha1.c
+ * @brief US Secure Hash Algorithm 1 (RFC 3174)
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tsk_sha1.h"
+
+#include "tsk_string.h"
+
+/**@defgroup tsk_sha1_group SHA1 (RFC 3174) utility functions.
+ * Copyright (C) The Internet Society (2001). All Rights Reserved.<br>
+ * Copyright (C) Mamadou Diop (2009)<br>
+ *
+ * This file implements the Secure Hashing Algorithm 1 as
+ * defined in FIPS PUB 180-1 published April 17, 1995.
+ *
+ * The SHA-1, produces a 160-bit message digest for a given
+ * data stream. It should take about 2**n steps to find a
+ * message with the same digest as a given message and
+ * 2**(n/2) to find any two messages with the same digest,
+ * when n is the digest size in bits. Therefore, this
+ * algorithm can serve as a means of providing a
+ * "fingerprint" for a message.
+ *
+*/
+
+/**@ingroup tsk_sha1_group
+ * Define the SHA1 circular left shift macro
+ */
+#define SHA1CircularShift(bits,word) \
+ (((word) << (bits)) | ((word) >> (32-(bits))))
+
+/* Local Function Prototyptes */
+void SHA1PadMessage(tsk_sha1context_t *);
+void SHA1ProcessMessageBlock(tsk_sha1context_t *);
+
+/**@ingroup tsk_sha1_group
+ *
+ * This function will initialize the @a context in preparation
+ * for computing a new SHA1 message digest.
+ *
+ *@param context The context to reset.
+ *
+ *@retval @ref tsk_sha1_errcode_t code.
+ */
+tsk_sha1_errcode_t tsk_sha1reset(tsk_sha1context_t *context)
+{
+ if (!context){
+ return shaNull;
+ }
+
+ context->Length_Low = 0;
+ context->Length_High = 0;
+ context->Message_Block_Index = 0;
+
+ context->Intermediate_Hash[0] = 0x67452301;
+ context->Intermediate_Hash[1] = 0xEFCDAB89;
+ context->Intermediate_Hash[2] = 0x98BADCFE;
+ context->Intermediate_Hash[3] = 0x10325476;
+ context->Intermediate_Hash[4] = 0xC3D2E1F0;
+
+ context->Computed = 0;
+ context->Corrupted = 0;
+
+ return shaSuccess;
+}
+
+/**@ingroup tsk_sha1_group
+ * This function will return the 160-bit message digest into the
+ * Message_Digest array provided by the caller.
+ * NOTE: The first octet of hash is stored in the 0th element,
+ * the last octet of hash in the 19th element.
+ * @param context The @a context to use to calculate the SHA-1 hash.
+ * @param Message_Digest A pointer the the sha1 digest result.
+ * @retval @ref tsk_sha1_errcode_t code.
+ */
+tsk_sha1_errcode_t tsk_sha1result( tsk_sha1context_t *context, tsk_sha1digest_t Message_Digest)
+{
+ int32_t i;
+
+ if (!context || !Message_Digest){
+ return shaNull;
+ }
+
+ if (context->Corrupted){
+ return context->Corrupted;
+ }
+
+ if (!context->Computed){
+ SHA1PadMessage(context);
+ for(i=0; i<64; ++i){
+ /* message may be sensitive, clear it out */
+ context->Message_Block[i] = 0;
+ }
+ context->Length_Low = 0; /* and clear length */
+ context->Length_High = 0;
+ context->Computed = 1;
+
+ }
+
+ for(i = 0; i < TSK_SHA1_DIGEST_SIZE; ++i){
+ Message_Digest[i] = context->Intermediate_Hash[i>>2]
+ >> 8 * ( 3 - ( i & 0x03 ) );
+ }
+
+ return shaSuccess;
+}
+
+/**@ingroup tsk_sha1_group
+ *
+ * This function accepts an array of octets as the next portion of the message.
+ *
+ * @param context The sha1 context.
+ * @param message_array An array of characters representing the next portion of the message.
+ * @param length The @a length of the message in message_array
+ * @retval @ref tsk_sha1_errcode_t code.
+ */
+tsk_sha1_errcode_t tsk_sha1input(tsk_sha1context_t *context,
+ const uint8_t *message_array,
+ unsigned length)
+{
+ if (!length){
+ return shaSuccess;
+ }
+
+ if (!context || !message_array){
+ return shaNull;
+ }
+
+ if (context->Computed){
+ context->Corrupted = shaStateError;
+
+ return shaStateError;
+ }
+
+ if (context->Corrupted){
+ return context->Corrupted;
+ }
+ while(length-- && !context->Corrupted)
+ {
+ context->Message_Block[context->Message_Block_Index++] =
+ (*message_array & 0xFF);
+
+ context->Length_Low += 8;
+ if (context->Length_Low == 0){
+ context->Length_High++;
+ if (context->Length_High == 0)
+ {
+ /* Message is too long */
+ context->Corrupted = 1;
+ }
+ }
+
+ if (context->Message_Block_Index == 64){
+ SHA1ProcessMessageBlock(context);
+ }
+
+ message_array++;
+ }
+
+ return shaSuccess;
+}
+
+/**@ingroup tsk_sha1_group
+ *
+ * This function will process the next 512 bits of the message
+ * stored in the Message_Block array.
+ *
+ * @param context The sha1 context.
+ *
+ */
+void SHA1ProcessMessageBlock(tsk_sha1context_t *context)
+{
+ /*
+ * Many of the variable names in this code, especially the
+ * single character names, were used because those were the
+ * names used in the publication.
+ */
+ const uint32_t K[] = { /* Constants defined in SHA-1 */
+ 0x5A827999,
+ 0x6ED9EBA1,
+ 0x8F1BBCDC,
+ 0xCA62C1D6
+ };
+ int32_t t; /* Loop counter */
+ uint32_t temp; /* Temporary word value */
+ uint32_t W[80]; /* Word sequence */
+ uint32_t A, B, C, D, E; /* Word buffers */
+
+ /*
+ * Initialize the first 16 words in the array W
+ */
+ for(t = 0; t < 16; t++){
+ W[t] = context->Message_Block[t * 4] << 24;
+ W[t] |= context->Message_Block[t * 4 + 1] << 16;
+ W[t] |= context->Message_Block[t * 4 + 2] << 8;
+ W[t] |= context->Message_Block[t * 4 + 3];
+ }
+
+ for(t = 16; t < 80; t++){
+ W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
+ }
+
+ A = context->Intermediate_Hash[0];
+ B = context->Intermediate_Hash[1];
+ C = context->Intermediate_Hash[2];
+ D = context->Intermediate_Hash[3];
+ E = context->Intermediate_Hash[4];
+
+ for(t = 0; t < 20; t++){
+ temp = SHA1CircularShift(5,A) +
+ ((B & C) | ((~B) & D)) + E + W[t] + K[0];
+ E = D;
+ D = C;
+ C = SHA1CircularShift(30,B);
+
+ B = A;
+ A = temp;
+ }
+
+ for(t = 20; t < 40; t++){
+ temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];
+ E = D;
+ D = C;
+ C = SHA1CircularShift(30,B);
+ B = A;
+ A = temp;
+ }
+
+ for(t = 40; t < 60; t++){
+ temp = SHA1CircularShift(5,A) +
+ ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];
+ E = D;
+ D = C;
+ C = SHA1CircularShift(30,B);
+ B = A;
+ A = temp;
+ }
+
+ for(t = 60; t < 80; t++){
+ temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];
+ E = D;
+ D = C;
+ C = SHA1CircularShift(30,B);
+ B = A;
+ A = temp;
+ }
+
+ context->Intermediate_Hash[0] += A;
+ context->Intermediate_Hash[1] += B;
+ context->Intermediate_Hash[2] += C;
+ context->Intermediate_Hash[3] += D;
+ context->Intermediate_Hash[4] += E;
+
+ context->Message_Block_Index = 0;
+}
+
+/**@ingroup tsk_sha1_group
+ *
+ * According to the standard, the message must be padded to an even
+ * 512 bits. The first padding bit must be a '1'. The last 64
+ * bits represent the length of the original message. All bits in
+ * between should be 0. This function will pad the message
+ * according to those rules by filling the Message_Block array
+ * accordingly. It will also call the ProcessMessageBlock function
+ * provided appropriately. When it returns, it can be assumed that
+ * the message digest has been computed.
+ *
+ * @param context The sha1 context.
+ *
+ */
+
+void SHA1PadMessage(tsk_sha1context_t *context)
+{
+ /*
+ * Check to see if the current message block is too small to hold
+ * the initial padding bits and length. If so, we will pad the
+ * block, process it, and then continue padding into a second
+ * block.
+ */
+ if (context->Message_Block_Index > 55){
+ context->Message_Block[context->Message_Block_Index++] = 0x80;
+ while(context->Message_Block_Index < 64){
+ context->Message_Block[context->Message_Block_Index++] = 0;
+ }
+
+ SHA1ProcessMessageBlock(context);
+
+ while(context->Message_Block_Index < 56){
+ context->Message_Block[context->Message_Block_Index++] = 0;
+ }
+ }
+ else{
+ context->Message_Block[context->Message_Block_Index++] = 0x80;
+ while(context->Message_Block_Index < 56){
+ context->Message_Block[context->Message_Block_Index++] = 0;
+ }
+ }
+
+ /*
+ * Store the message length as the last 8 octets
+ */
+ context->Message_Block[56] = context->Length_High >> 24;
+ context->Message_Block[57] = context->Length_High >> 16;
+ context->Message_Block[58] = context->Length_High >> 8;
+ context->Message_Block[59] = context->Length_High;
+ context->Message_Block[60] = context->Length_Low >> 24;
+ context->Message_Block[61] = context->Length_Low >> 16;
+ context->Message_Block[62] = context->Length_Low >> 8;
+ context->Message_Block[63] = context->Length_Low;
+
+ SHA1ProcessMessageBlock(context);
+}
+
+/**@ingroup tsk_sha1_group
+* Computes the sha1 digest result.
+* @param Message_Digest A pointer to the sha1 digest result.
+* @param context The sha1 context.
+*/
+void tsk_sha1final(uint8_t *Message_Digest, tsk_sha1context_t *context)
+{
+ int32_t i;
+
+ SHA1PadMessage(context);
+ for(i = 0; i<64; ++i) {
+ context->Message_Block[i] = 0;
+ }
+ context->Length_Low = 0; /* and clear length */
+ context->Length_High = 0;
+
+ for(i = 0; i < TSK_SHA1_DIGEST_SIZE; ++i) {
+ Message_Digest[i] = context->Intermediate_Hash[i>>2] >> 8*(3-(i&0x03));
+ }
+}
+
+
+/**@ingroup tsk_sha1_group
+ * Calculates sha1 digest result (hexadecimal string).
+ *
+ * @param input The input data for which to calculate the SHA-1 hash.
+ * @param size The size of the input data.
+ * @param result SHA-1 hash result as a hexadecimal string.
+ *
+ * @retval @ref tsk_sha1_errcode_t code.
+ * @sa @ref TSK_SHA1_DIGEST_CALC
+**/
+tsk_sha1_errcode_t tsk_sha1compute(const char* input, tsk_size_t size, tsk_sha1string_t *result)
+{
+ tsk_sha1_errcode_t ret;
+ tsk_sha1context_t sha;
+ uint8_t digest[TSK_SHA1_DIGEST_SIZE];
+
+ (*result)[TSK_SHA1_STRING_SIZE] = '\0';
+
+ if( (ret = tsk_sha1reset(&sha)) != shaSuccess ){
+ return ret;
+ }
+ else if ( (ret = tsk_sha1input(&sha, (uint8_t*)input, size)) != shaSuccess ){
+ return ret;
+ }
+ else if( (ret = tsk_sha1result(&sha, (char*)digest)) != shaSuccess ){
+ return ret;
+ }
+
+ tsk_str_from_hex(digest, TSK_SHA1_DIGEST_SIZE, *result);
+
+ return shaSuccess;
+}
diff --git a/tinySAK/src/tsk_sha1.h b/tinySAK/src/tsk_sha1.h
new file mode 100644
index 0000000..6d78a94
--- /dev/null
+++ b/tinySAK/src/tsk_sha1.h
@@ -0,0 +1,122 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_sha1.h
+ * @brief US Secure Hash Algorithm 1 (RFC 3174)
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef _TINYSAK_SHA1_H_
+#define _TINYSAK_SHA1_H_
+
+#include "tinysak_config.h"
+
+TSK_BEGIN_DECLS
+
+/**@ingroup tsk_sha1_group
+* SHA-1 error codes.
+*/
+typedef enum tsk_sha1_errcode_e
+{
+ shaSuccess = 0, /**< Success */
+ shaNull, /**< Null pointer parameter */
+ shaInputTooLong, /**< input data too long */
+ shaStateError /**< called Input after Result */
+}
+tsk_sha1_errcode_t;
+
+/**@ingroup tsk_sha1_group
+*@def TSK_SHA1_DIGEST_SIZE
+*/
+/**@ingroup tsk_sha1_group
+*@def TSK_SHA1_BLOCK_SIZE
+*/
+/**@ingroup tsk_sha1_group
+*@def TSK_SHA1_STRING_SIZE
+*/
+/**@ingroup tsk_sha1_group
+*@def tsk_sha1string_t
+* Hexadecimal SHA-1 digest string.
+*/
+/**@ingroup tsk_sha1_group
+*@def tsk_sha1digest_t
+* SHA-1 digest bytes.
+*/
+
+#define TSK_SHA1_DIGEST_SIZE 20
+#define TSK_SHA1_BLOCK_SIZE 64
+
+#define TSK_SHA1_STRING_SIZE (TSK_SHA1_DIGEST_SIZE*2)
+typedef char tsk_sha1string_t[TSK_SHA1_STRING_SIZE+1];
+typedef char tsk_sha1digest_t[TSK_SHA1_DIGEST_SIZE]; /**< SHA-1 digest bytes. */
+
+/**@ingroup tsk_sha1_group
+* Computes SHA-1 digest.
+* @param input The input data.
+* @param input_size The size of the input data.
+* @param digest @ref tsk_sha1digest_t object conaining the sha1 digest result.
+* @sa @ref tsk_sha1compute.
+*/
+#define TSK_SHA1_DIGEST_CALC(input, input_size, digest) \
+ { \
+ tsk_sha1context_t ctx; \
+ tsk_sha1reset(&ctx); \
+ tsk_sha1input(&ctx, (input), (input_size)); \
+ tsk_sha1result(&ctx, (digest)); \
+ }
+
+/**@ingroup tsk_sha1_group
+ * This structure will hold context information for the SHA-1
+ * hashing SSESSION
+ */
+typedef struct tsk_sha1context_s
+{
+ uint32_t Intermediate_Hash[TSK_SHA1_DIGEST_SIZE/4]; /* Message Digest */
+
+ uint32_t Length_Low; /**< Message length in bits */
+ uint32_t Length_High; /**< Message length in bits */
+
+
+ int_least16_t Message_Block_Index;/**< Index into message block array */
+ uint8_t Message_Block[64]; /**< 512-bit message blocks */
+
+ int32_t Computed; /**< Is the digest computed? */
+ int32_t Corrupted; /**< Is the message digest corrupted? */
+}
+tsk_sha1context_t;
+
+/*
+ * Function Prototypes
+ */
+
+TINYSAK_API tsk_sha1_errcode_t tsk_sha1reset(tsk_sha1context_t *);
+TINYSAK_API tsk_sha1_errcode_t tsk_sha1input(tsk_sha1context_t *, const uint8_t *, unsigned length);
+TINYSAK_API tsk_sha1_errcode_t tsk_sha1result(tsk_sha1context_t *, tsk_sha1digest_t Message_Digest);
+TINYSAK_API void tsk_sha1final(uint8_t *Message_Digest, tsk_sha1context_t *context);
+TINYSAK_API tsk_sha1_errcode_t tsk_sha1compute(const char* input, tsk_size_t size, tsk_sha1string_t *result);
+
+TSK_END_DECLS
+
+#endif /* _TINYSAK_SHA1_H_ */
+
diff --git a/tinySAK/src/tsk_string.c b/tinySAK/src/tsk_string.c
new file mode 100644
index 0000000..abb4831
--- /dev/null
+++ b/tinySAK/src/tsk_string.c
@@ -0,0 +1,619 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_string.c
+ * @brief Useful string functions to manipulate strings.
+ * As I'm a lazy man, some comments come from <ahref="http://www.cplusplus.com">this website</a>
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tsk_string.h"
+#include "tsk_memory.h"
+#include "tsk_time.h"
+#include "tsk_debug.h"
+#include "tsk_common.h"
+
+#include <stdarg.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#if defined(_MSC_VER)
+# define snprintf _snprintf
+# define vsnprintf _vsnprintf
+# define strdup _strdup
+# define stricmp _stricmp
+# define strnicmp _strnicmp
+#else
+# if !HAVE_STRNICMP && !HAVE_STRICMP
+# define stricmp strcasecmp
+# define strnicmp strncasecmp
+# endif
+#endif
+
+/**@defgroup tsk_string_group String utillity functions.
+*/
+
+static char HEX[] = "0123456789abcdef";
+
+/**@ingroup tsk_string_group
+*/
+tsk_string_t* tsk_string_create(const char* str)
+{
+ return tsk_object_new(tsk_string_def_t, str);
+}
+
+/**@ingroup tsk_string_group
+* From base 10 to base 16
+* @param c the base 10 char to convert to base 16
+* @retval The base 16 value
+*/
+char tsk_b10tob16(char c)
+{
+ return HEX[c & 15];
+}
+
+/**@ingroup tsk_string_group
+* From base 16 to base 10
+* @param c The base 16 char to convert to base 10
+* @retval The base 10 value
+*/
+char tsk_b16tob10(char c)
+{
+ return isdigit(c) ? c - '0' : tolower(c) - 'a' + 10;
+}
+
+/**@ingroup tsk_string_group
+* Compare two Null-terminated strings (case insensitive)
+* Compares the C string str1 to the C string str2.
+* This function starts comparing the first character of each string. If they are equal to each other, it continues with the following pairs
+* until the characters differ or until a terminanting null-character is reached.
+* @param str1 First C string to be compared.
+* @param str2 Second C string to be compared.
+* @retval Returns an integral value indicating the relationship between the strings:
+* <0 : str1 less than str2.<br>
+* 0 : str1 identical to str2.<br>
+* >0 : str1 greater than str2.<br>
+*/
+int tsk_stricmp(const char * str1, const char * str2)
+{
+ return (str1 && str2) ?
+ ( (tolower(*str1) == tolower(*str2)) ? stricmp(str1, str2) : (*str1-*str2) ) /* Compare first charaters before doing complete comparison */
+ :
+ ( (!str1 && !str2) ? 0 : -1 );
+}
+
+/**@ingroup tsk_string_group
+* Compare two Null-terminated strings (case insensitive)
+* Compares the C string str1 to the C string str2.
+* This function starts comparing the first character of each string. If they are equal to each other, it continues with the following pairs
+* until the characters differ or until a terminanting null-character is reached or @a n characters passed.
+* @param str1 First C string to be compared.
+* @param str2 Second C string to be compared.
+* @param n The maximum number of characters to compare.
+* @retval Returns an integral value indicating the relationship between the strings:
+* <0 : str1 less than str2.<br>
+* 0 : str1 identical to str2.<br>
+* >0 : str1 greater than str2.<br>
+*/
+int tsk_strnicmp(const char * str1, const char * str2, tsk_size_t n)
+{
+ return (str1 && str2 && n) ?
+ ( (tolower(*str1) == tolower(*str2)) ? strnicmp(str1, str2, n) : (*str1-*str2) ) /* Compare first charaters before doing complete comparison */
+ :
+ ( (!str1 && !str2) ? 0 : -1 );
+}
+
+/**@ingroup tsk_string_group
+*/
+int tsk_strcmp(const char * str1, const char * str2)
+{
+ return (str1 && str2) ?
+ ( (*str1 == *str2) ? stricmp(str1, str2) : (*str1-*str2) ) /* Compare first charaters before doing complete comparison */
+ :
+ ( (!str1 && !str2) ? 0 : -1 );
+}
+
+/**@ingroup tsk_string_group
+* Compare two Null-terminated strings (case sensitive)
+* Compares the C string str1 to the C string str2.
+* This function starts comparing the first character of each string. If they are equal to each other, it continues with the following pairs
+* until the characters differ or until a terminanting null-character is reached.
+* @param str1 First C string to be compared.
+* @param str2 Second C string to be compared.
+* @param n The maximum number of characters to compare.
+* @retval Returns an integral value indicating the relationship between the strings:
+* <0 : str1 less than str2.<br>
+* 0 : str1 identical to str2.<br>
+* >0 : str1 greater than str2.<br>
+*/
+int tsk_strncmp(const char * str1, const char * str2, tsk_size_t n)
+{
+ return (str1 && str2) ? ((*str1 != *str2) ? -1 : strncmp(str1, str2, n)) : ((!str1 && !str2) ? 0 : -1);
+}
+
+/**@ingroup tsk_string_group
+* Duplicate a Null-terminated string.
+* @param s1 The string to duplicate.
+* @retval The duplicated string. It's up to you to free the returned string.
+*/
+char* tsk_strdup(const char *s1)
+{
+ if(s1){
+ return strdup(s1);
+ }
+ return tsk_null;
+}
+
+/** Duplicates the first @a n chars of @a s1.
+ * @param s1 The string to duplicate.
+ * @param n The number of characters to copy to the new string.
+ * @retval null A copy of @a s1.
+**/
+char* tsk_strndup(const char *s1, tsk_size_t n)
+{
+ char *ret = tsk_null;
+
+ if(s1 && n){
+ tsk_size_t len = tsk_strlen(s1);
+ tsk_size_t nret = (n > len) ? (len) : (n);
+
+ ret = tsk_calloc((nret+1), sizeof(uint8_t));
+ memcpy(ret, s1, nret);
+ }
+
+ return ret;
+}
+
+/**@ingroup tsk_string_group
+* Checks if @a str contains @a substring.
+* @param str The master string.
+* @param size The size of the master string.
+* @param substring the substring.
+* @retval @a tsk_true if @a str contains at least one occurence of @a substring and @a tsk_false othewise.
+*/
+tsk_bool_t tsk_strcontains(const char * str, tsk_size_t size, const char * substring)
+{
+ return (tsk_strindexOf(str, size, substring) >= 0);
+}
+
+/**@ingroup tsk_string_group
+* Gets the first occurrence of @a substring within @a str.
+* @param str The master string.
+* @param size The size of the master string.
+* @param substring The substring that is to be searched for within @a str.
+* @retval The index of the first ocurrence of @a substring in @a str.
+* If no occurrence of @a substring is found, then -1 is returned.
+*/
+int tsk_strindexOf(const char * str, tsk_size_t size, const char * substring)
+{
+ if(str && substring){
+ const char* sub_start = strstr(str, substring);
+ if(sub_start && (sub_start < (str + size))){
+ return (sub_start - str);
+ }
+ }
+ return -1;
+}
+
+/**@ingroup tsk_string_group
+*/
+int tsk_strLastIndexOf(const char * str, tsk_size_t size, const char * substring)
+{
+ if(str && substring){
+ tsk_size_t sub_size = tsk_strlen(substring);
+ const char* last_sub_start = tsk_null;
+ const char* sub_start = strstr(str, substring);
+ const char* end = (str + size);
+ while(sub_start && (sub_start < end)){
+ last_sub_start = sub_start;
+ if((sub_start + sub_size)<end){
+ sub_start = strstr((sub_start + sub_size), substring);
+ }
+ else{
+ break;
+ }
+ }
+ if(last_sub_start){
+ return (last_sub_start - str);
+ }
+ }
+ return -1;
+}
+
+/**@ingroup tsk_string_group
+* Appends a copy of the source string to the destination string. The terminating null character in destination is overwritten by the first character of source,
+* and a new null-character is appended at the end of the new string formed by the concatenation of both in destination. If the destination is NULL then new
+* memory will allocated and filled with source value.
+* @param destination Pointer de the destination array containing the new string.
+* @param source C string to be appended. This should not overlap destination. If NULL then nothing is done.
+*/
+void tsk_strcat(char** destination, const char* source)
+{
+ tsk_strncat(destination, source, tsk_strlen(source));
+}
+
+/**@ingroup tsk_string_group
+*/
+void tsk_strcat_2(char** destination, const char* format, ...)
+{
+ char* temp = tsk_null;
+ int len;
+ va_list ap;
+
+ /* initialize variable arguments */
+ va_start(ap, format);
+ /* compute */
+ if((len = tsk_sprintf_2(&temp, format, &ap))){
+ tsk_strncat(destination, temp, len);
+ }
+ /* reset variable arguments */
+ va_end(ap);
+ TSK_FREE(temp);
+}
+
+/**@ingroup tsk_string_group
+*/
+void tsk_strncat(char** destination, const char* source, tsk_size_t n)
+{
+ tsk_size_t index = 0;
+ tsk_size_t tsk_size_to_cat = (n > tsk_strlen(source)) ? tsk_strlen(source) : n;
+
+ if(!source || !n){
+ return;
+ }
+
+ if(!*destination){
+ *destination = (char*)tsk_malloc(tsk_size_to_cat+1);
+ strncpy(*destination, source, tsk_size_to_cat+1);
+ }else{
+ index = tsk_strlen(*destination);
+ *destination = tsk_realloc(*destination, index + tsk_size_to_cat+1);
+ strncpy(((*destination)+index), source, tsk_size_to_cat+1);
+ }
+ (*destination)[index + tsk_size_to_cat] = '\0';
+}
+
+/**@ingroup tsk_string_group
+* Writes into the array pointed by str a C string consisting on a sequence of data formatted as the format argument specifies. After the format parameter,
+* the function expects at least as many additional arguments as specified in format.
+* This function behaves exactly as printf does, but writing its results to a string instead of stdout. The size of the array passed as str should be enough to
+* contain the entire formatted string.
+* @param str Pointer to an array of char elements where the resulting C string is stored.
+* MUST be NULL.
+* @param format C string that contains the text to be written to the buffer. For more information see definiton of C function @a sprintf
+* @retval On success, the total number of characters written is returned. This count does not include the additional null-character automatically appended
+* at the end of the string.
+* On failure, a negative number is returned.
+*/
+int tsk_sprintf(char** str, const char* format, ...)
+{
+ int len;
+ va_list ap;
+
+ /* initialize variable arguments */
+ va_start(ap, format);
+ /* compute */
+ len = tsk_sprintf_2(str, format, &ap);
+ /* reset variable arguments */
+ va_end(ap);
+
+ return len;
+}
+
+/**@ingroup tsk_string_group
+*/
+int tsk_sprintf_2(char** str, const char* format, va_list* ap)
+{
+ int len = 0;
+ va_list ap2;
+
+ /* free previous value */
+ if(*str){
+ tsk_free((void**)str);
+ }
+
+ /* needed for 64bit platforms where vsnprintf will change the va_list */
+ tsk_va_copy(ap2, *ap);
+
+ /* compute destination len for windows mobile
+ */
+#if defined(_WIN32_WCE)
+ {
+ int n;
+ len = (tsk_strlen(format)*2);
+ *str = (char*)tsk_calloc(1, len+1);
+ for(;;){
+ if( (n = vsnprintf(*str, len, format, *ap)) >= 0 && (n<len) ){
+ len = n;
+ goto done;
+ }
+ else{
+ len += 10;
+ *str = tsk_realloc(*str, len+1);
+ }
+ }
+done:
+ (*str)[len] = '\0';
+ }
+#else
+ len = vsnprintf(0, 0, format, *ap);
+ *str = (char*)tsk_calloc(1, len+1);
+ vsnprintf(*str, len
+#if !defined(_MSC_VER) || defined(__GNUC__)
+ +1
+#endif
+ , format, ap2);
+#endif
+
+ va_end(ap2);
+
+ return len;
+}
+
+/**@ingroup tsk_string_group
+* Updates the value of @a str.
+* @param str The string to update.
+* @param newval The new value of @a str.
+*/
+void tsk_strupdate(char** str, const char* newval)
+{
+ tsk_free((void**)str);
+ *str = tsk_strdup(newval);
+}
+
+
+/**@ingroup tsk_string_group
+* Removes all occurrences of white space characters from the beginning of this @a str.
+* @param str The string to trim.
+*/
+void tsk_strtrim_left(char **str)
+{
+ if(str && *str){
+ tsk_size_t count = 0;
+ while(isspace(*((*str)+count))) count++;
+ if(count){
+ strcpy((*str), (*str)+count);
+ }
+ }
+}
+
+/**@ingroup tsk_string_group
+* Removes all occurrences of white space characters from the end of @a str.
+* @param str The string to trim.
+*/
+void tsk_strtrim_right(char **str)
+{
+ if(str && *str){
+ tsk_size_t size;
+ if((size = tsk_strlen(*str))){
+ while(isspace(*((*str)+size-1))) size--;
+ *(*str + size) = '\0';
+ }
+ }
+}
+/**@ingroup tsk_string_group
+* Removes all occurrences of white space characters from the beginning and end of @a str.
+* @param str The string to trim.
+*/
+void tsk_strtrim(char **str)
+{
+ // left
+ tsk_strtrim_left(str);
+ // right
+ tsk_strtrim_right(str);
+}
+
+/**@ingroup tsk_string_group
+* Adds quotes ("") to the beginning and end of @a str.<br>
+* @param str The string to quote.
+* Example: tsk_strquote("doubango") = ""doubango\"".
+*/
+void tsk_strquote(char **str)
+{
+ tsk_strquote_2(str, '"', '"');
+}
+
+/**@ingroup tsk_string_group
+* Adds quotes to the beginning and end of @a str.
+* @param str The string to quote.
+* @param lquote Quote to add to the begining of @a str.
+* @param rquote Quote to add to the end of @a str.
+*/
+void tsk_strquote_2(char **str, char lquote, char rquote)
+{
+ if(str && *str){
+ char *result = tsk_null;
+ tsk_sprintf(&result, "%c%s%c", lquote, *str, rquote);
+ tsk_free((void**)str);
+ *str = result;
+ }
+}
+
+/**@ingroup tsk_string_group
+* Removes quotes ("") from the beginning and end of @a str.<br>
+* @param str The string to unquote.
+* Example: tsk_strunquote(""doubango"") = "doubango".
+*/
+void tsk_strunquote(char **str)
+{
+ tsk_strunquote_2(str, '"', '"');
+}
+
+/**@ingroup tsk_string_group
+* Removes quotes from the beginning and end of @a str. The string must starts with @a lquote
+* and end with @a rquote.
+* @param str The string to unquote.
+* @param lquote Quote to remove from the begining of @a str.
+* @param rquote Quote to remove from the end of @a str.
+*/
+void tsk_strunquote_2(char **str, char lquote, char rquote)
+{
+ if(str && *str){
+ tsk_size_t size = tsk_strlen(*str);
+ if(size>=2 && **str == lquote && *((*str)+size-1) == rquote){
+ strcpy((*str), (*str)+1);
+ *((*str)+size-2) = '\0';
+ }
+ }
+}
+
+/**@ingroup tsk_string_group
+* Conversts an integer to string.
+* @param i The integer number to convert to a string.
+* @param result Pointer to the string where to copy the result.
+*/
+void tsk_itoa(int64_t i, tsk_istr_t *result)
+{
+ memset(result, 0, sizeof(*result));
+ sprintf(*result,"%lld",i);
+}
+
+/**@ingroup tsk_string_group
+*/
+int64_t tsk_atoll(const char* str)
+{
+ // FIXME: use HAVE_ATOLL and use macro instead of function
+ if(str){
+#if defined(_MSC_VER)
+ return _atoi64(str);
+#elif defined(__GNUC__)
+ return atoll(str);
+#else
+ return atol(str);
+#endif
+ }
+ return 0;
+}
+
+/**@ingroup tsk_string_group
+*/
+long tsk_atox(const char* str)
+{
+ long ret = 0;
+ if(str){
+ sscanf(str, "%lx", &ret);
+ }
+ return ret;
+}
+
+/**@ingroup tsk_string_group
+ * Generates a random string.
+ *
+ * @param result A pointer to the result.
+**/
+void tsk_strrandom(tsk_istr_t *result)
+{
+ static uint64_t __counter = 1;
+ tsk_itoa((tsk_time_epoch() ^ (rand())) ^ ++__counter, result);
+}
+
+/**@ingroup tsk_string_group
+ *
+ * Converts hexadecimal bytes into string representation.
+ *
+ * @param hex The hexadecimal bytes to convert.
+ * @param size The size of the hexadecimal bytes.
+ * @param str The pointer to the result. MUST be enought large to hold the result.
+ * It is up to you to add the final '\\0'.
+ * @sa @ref tsk_str_to_hex
+**/
+void tsk_str_from_hex(const uint8_t *hex, tsk_size_t size, char* str)
+{
+ static const char *TSK_HEXA_VALUES = {"0123456789abcdef"};
+ tsk_size_t i;
+
+ for (i = 0 ; i<size; i++){
+ str[2*i] = TSK_HEXA_VALUES [ (*(hex+i) & 0xf0) >> 4 ];
+ str[(2*i)+1] = TSK_HEXA_VALUES [ (*(hex+i) & 0x0f) ];
+ }
+}
+
+/**@ingroup tsk_string_group
+ * Converts string chars into hexadecimal bytes.
+ *
+ * @param str If non-null, the string.
+ * @param size The size.
+ * @param hex If non-null, the hexadecimal.
+**/
+void tsk_str_to_hex(const char *str, tsk_size_t size, uint8_t* hex)
+{
+ // to avoid SIGBUS error when memory is misaligned do not use sscanf("%2x")
+ TSK_DEBUG_FATAL("Not implemented.");
+}
+
+
+
+
+
+
+
+
+
+
+//=================================================================================================
+// String object definition
+//
+static tsk_object_t* tsk_string_ctor(tsk_object_t * self, va_list * app)
+{
+ tsk_string_t *string = self;
+ const char *value = va_arg(*app, const char *);
+ if(value){
+ string->value = tsk_strdup(value);
+ }
+ return self;
+}
+
+static tsk_object_t* tsk_string_dtor(tsk_object_t * self)
+{
+ tsk_string_t *string = self;
+ if(string){
+ TSK_FREE(string->value);
+ }
+
+ return self;
+}
+
+static int tsk_string_cmp(const tsk_object_t *_s1, const tsk_object_t *_s2)
+{
+ const tsk_string_t *s1 = _s1;
+ const tsk_string_t *s2 = _s2;
+
+ if(s1 && s2){
+ return tsk_stricmp(s1->value, s2->value);
+ }
+ else if(!s1 && !s2) return 0;
+ else return -1;
+}
+
+static const tsk_object_def_t tsk_string_def_s =
+{
+ sizeof(tsk_string_t),
+ tsk_string_ctor,
+ tsk_string_dtor,
+ tsk_string_cmp,
+};
+const tsk_object_def_t *tsk_string_def_t = &tsk_string_def_s;
+
diff --git a/tinySAK/src/tsk_string.h b/tinySAK/src/tsk_string.h
new file mode 100644
index 0000000..f064fc1
--- /dev/null
+++ b/tinySAK/src/tsk_string.h
@@ -0,0 +1,127 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_string.h
+ * @brief Useful string functions to manipulate strings.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef _TINYSAK_STRING_H_
+#define _TINYSAK_STRING_H_
+
+#include "tinysak_config.h"
+
+#include "tsk_object.h"
+#include "tsk_list.h"
+
+/**@ingroup tsk_string_group
+* @def TSK_STRING_STR
+* Gets the internal string pointer.
+*/
+TSK_BEGIN_DECLS
+
+#define TSK_STRING_STR(self) ((tsk_string_t*)self)->value
+
+typedef char tsk_istr_t[21]; /**< Integer number as string value. */
+
+TINYSAK_API char tsk_b10tob16(char c);
+TINYSAK_API char tsk_b16tob10(char c);
+
+TINYSAK_API int tsk_stricmp(const char * str1, const char * str2);
+TINYSAK_API int tsk_strnicmp(const char * str1, const char * str2, tsk_size_t n);
+TINYSAK_API int tsk_strcmp(const char * str1, const char * str2);
+TINYSAK_API int tsk_strncmp(const char * str1, const char * str2, tsk_size_t n);
+TINYSAK_API char* tsk_strdup(const char *s1);
+TINYSAK_API char* tsk_strndup(const char *s1, tsk_size_t n);
+TINYSAK_API tsk_bool_t tsk_strcontains(const char * str, tsk_size_t size, const char * substring);
+TINYSAK_API int tsk_strindexOf(const char * str, tsk_size_t size, const char * substring);
+TINYSAK_API int tsk_strLastIndexOf(const char * str, tsk_size_t size, const char * substring);
+TINYSAK_API void tsk_strcat(char** destination, const char* source);
+TINYSAK_API void tsk_strcat_2(char** destination, const char* format, ...);
+TINYSAK_API void tsk_strncat(char** destination, const char* source, tsk_size_t n);
+TINYSAK_API int tsk_sprintf(char** str, const char* format, ...);
+TINYSAK_API int tsk_sprintf_2(char** str, const char* format, va_list* ap);
+TINYSAK_API void tsk_strupdate(char** str, const char* newval);
+TINYSAK_API void tsk_strtrim_left(char **str);
+TINYSAK_API void tsk_strtrim_right(char **str);
+TINYSAK_API void tsk_strtrim(char **str);
+TINYSAK_API void tsk_strquote(char **str);
+TINYSAK_API void tsk_strquote_2(char **str, char lquote, char rquote);
+TINYSAK_API void tsk_strunquote(char **str);
+TINYSAK_API void tsk_strunquote_2(char **str, char lquote, char rquote);
+TINYSAK_API void tsk_itoa(int64_t i, tsk_istr_t *result);
+TINYSAK_API int64_t tsk_atoll(const char*);
+TINYSAK_API long tsk_atox(const char*);
+TINYSAK_API void tsk_strrandom(tsk_istr_t *result);
+TINYSAK_API void tsk_str_from_hex(const uint8_t *hex, tsk_size_t size, char* str);
+TINYSAK_API void tsk_str_to_hex(const char *str, tsk_size_t size, uint8_t* hex);
+
+/**@ingroup tsk_string_group
+* @def tsk_strtrim_both
+*/
+/**@ingroup tsk_string_group
+* @def tsk_strempty
+*/
+/**@ingroup tsk_string_group
+* @def tsk_striequals
+*/
+/**@ingroup tsk_string_group
+* @def tsk_strniequals
+*/
+/**@ingroup tsk_string_group
+* @def tsk_strequals
+*/
+/**@ingroup tsk_string_group
+* @def tsk_strnequals
+*/
+#define tsk_strtrim_both(str) tsk_strtrim_left(str), tsk_strtrim_right(str);
+#define tsk_strempty(s) (*(s) == '\0')
+#define tsk_strnullORempty(s) (!(s) || tsk_strempty((s)))
+#define tsk_striequals(s1, s2) (tsk_stricmp((const char*)(s1), (const char*)(s2)) ? tsk_false : tsk_true)
+#define tsk_strniequals(s1, s2, n) (tsk_strnicmp((const char*)(s1), (const char*)(s2), n) ? tsk_false : tsk_true)
+#define tsk_strequals(s1, s2) (tsk_strcmp((const char*)(s1), (const char*)(s2)) ? tsk_false : tsk_true)
+#define tsk_strnequals(s1, s2, n) (tsk_strncmp((const char*)(s1), (const char*)(s2), n) ? tsk_false : tsk_true)
+#define tsk_strlen(s) ((s) ? strlen((s)) : 0)
+
+/**@ingroup tsk_string_group
+* String object.
+*/
+typedef struct tsk_string_s
+{
+ TSK_DECLARE_OBJECT;
+
+ char *value; /**< The value of the string object. */
+}
+tsk_string_t;
+
+typedef tsk_list_t tsk_strings_L_t;
+
+TINYSAK_API tsk_string_t* tsk_string_create(const char* str);
+
+TINYSAK_GEXTERN const tsk_object_def_t *tsk_string_def_t;
+
+TSK_END_DECLS
+
+#endif /* _TINYSAK_STRING_H_ */
+
diff --git a/tinySAK/src/tsk_thread.c b/tinySAK/src/tsk_thread.c
new file mode 100644
index 0000000..c8339e5
--- /dev/null
+++ b/tinySAK/src/tsk_thread.c
@@ -0,0 +1,109 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_thread.c
+ * @brief Utility functions for threading.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tsk_thread.h"
+#include "tsk_debug.h"
+#include "tsk_memory.h"
+
+#if TSK_UNDER_WINDOWS
+# include <windows.h>
+#else
+# include <pthread.h>
+#endif
+
+/**@defgroup tsk_thread_group Utility functions for threading.
+*/
+
+/**@ingroup tsk_thread_group
+*/
+void tsk_thread_sleep(uint64_t ms)
+{
+#if TSK_UNDER_WINDOWS
+ Sleep((DWORD)ms);
+#else
+ struct timespec interval;
+
+ interval.tv_sec = (long)(ms/1000);
+ interval.tv_nsec = (long)(ms%1000) * 1000000;
+ nanosleep(&interval, 0);
+#endif
+}
+
+/**@ingroup tsk_thread_group
+* Creates a new thread.
+* @param tid Handle id of the newly created thread. The returned handle should be destroyed using @ref tsk_thread_join()
+* @param start The function to be run as the new thread's start routine
+* @param arg An address for the argument for the thread's start routine
+* @retval If successful, returns zero. Otherwise, an error number is returned to indicate the error
+*/
+int tsk_thread_create(void** tid, void *(*start) (void *), void *arg)
+{
+#if TSK_UNDER_WINDOWS
+ DWORD ThreadId;
+ *((HANDLE*)tid) = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)start, arg, 0, &ThreadId);
+ return *((HANDLE*)tid) ? 0 : -1;
+#else
+ *tid = tsk_calloc(1, sizeof(pthread_t));
+ return pthread_create((pthread_t*)*tid, 0, start, arg);
+#endif
+}
+
+/**@ingroup tsk_thread_group
+* Join a thread.
+* @param tid Pthread handle to the target thread.
+* @retval If successful, returns zero. Otherwise, an error number is returned to indicate the error.
+*/
+int tsk_thread_join(void** tid)
+{
+ int ret;
+
+ if(!tid){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return -1;
+ }
+ if(!*tid){
+ TSK_DEBUG_WARN("Cannot join NULL tid");
+ return 0;
+ }
+
+#if TSK_UNDER_WINDOWS
+ ret = (WaitForSingleObject(*((HANDLE*)tid), INFINITE) == WAIT_FAILED) ? -1 : 0;
+ if(ret == 0){
+ CloseHandle(*((HANDLE*)tid));
+ *tid = tsk_null;
+ }
+#else
+ if((ret = pthread_join(*((pthread_t*)*tid), 0)) == 0){
+ tsk_free(tid);
+ }
+#endif
+
+ return ret;
+}
+
diff --git a/tinySAK/src/tsk_thread.h b/tinySAK/src/tsk_thread.h
new file mode 100644
index 0000000..4ebe56c
--- /dev/null
+++ b/tinySAK/src/tsk_thread.h
@@ -0,0 +1,45 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_thread.h
+ * @brief Utility functions for threading.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef _TINYSAK_THREAD_H_
+#define _TINYSAK_THREAD_H_
+
+#include "tinysak_config.h"
+
+TSK_BEGIN_DECLS
+
+TINYSAK_API void tsk_thread_sleep(uint64_t ms);
+TINYSAK_API int tsk_thread_create(void** tid, void *(*start) (void *), void *arg);
+TINYSAK_API int tsk_thread_join(void** tid);
+
+TSK_END_DECLS
+
+#endif
+
+
diff --git a/tinySAK/src/tsk_time.c b/tinySAK/src/tsk_time.c
new file mode 100644
index 0000000..5d2d66b
--- /dev/null
+++ b/tinySAK/src/tsk_time.c
@@ -0,0 +1,154 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_time.c
+* @brief Datetime functions.
+*
+* @author Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* @date Created: Sat Nov 8 16:54:58 2009 mdiop
+*/
+#include "tsk_time.h"
+
+#include "tsk_debug.h"
+
+#if TSK_UNDER_WINDOWS
+//# ifdef _WIN32_WCE
+# include <Winsock2.h> // timeval
+//# endif
+# include <windows.h>
+#elif defined(__SYMBIAN32__)
+# include <_timeval.h>
+#else
+# include <sys/time.h>
+#endif
+
+#include <time.h>
+
+/**@defgroup tsk_time_group Datetime functions.
+*/
+
+#if !HAVE_GETTIMEOFDAY
+#if TSK_UNDER_WINDOWS
+
+/* Thanks to "http://www.cpp-programming.net/c-tidbits/gettimeofday-function-for-windows" */
+#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
+#define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
+#else
+#define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
+#endif
+
+struct timezone
+{
+ int tz_minuteswest; /* minutes W of Greenwich */
+ int tz_dsttime; /* type of dst correction */
+};
+
+int gettimeofday(struct timeval *tv, struct timezone *tz)
+{
+ FILETIME ft;
+ uint64_t tmpres = 0;
+ static int tzflag = 0;
+
+ if(tv)
+ {
+#ifdef _WIN32_WCE
+ SYSTEMTIME st;
+ GetSystemTime(&st);
+ SystemTimeToFileTime(&st, &ft);
+#else
+ GetSystemTimeAsFileTime(&ft);
+#endif
+
+ tmpres |= ft.dwHighDateTime;
+ tmpres <<= 32;
+ tmpres |= ft.dwLowDateTime;
+
+ /*converting file time to unix epoch*/
+ tmpres /= 10; /*convert into microseconds*/
+ tmpres -= DELTA_EPOCH_IN_MICROSECS;
+ tv->tv_sec = (long)(tmpres / 1000000UL);
+ tv->tv_usec = (long)(tmpres % 1000000UL);
+ }
+
+ if (tz){
+ if (!tzflag){
+ _tzset();
+ tzflag++;
+ }
+ tz->tz_minuteswest = _timezone / 60;
+ tz->tz_dsttime = _daylight;
+ }
+
+ return 0;
+}
+
+#else
+#pragma error "You MUST provide an implement for 'gettimeofday'"
+#endif /* WIN32 */
+
+#endif /* !HAVE_GETTIMEOFDAY */
+
+/**@ingroup tsk_time_group
+* The tsk_gettimeofday() function shall obtain the current time, expressed as seconds and microseconds since EPOCH (00:00:00 UTC on 1 January 1970).
+* The resolution of the system clock is unspecified.
+* @param tv The current time, expressed as seconds and microseconds since EPOCH(00:00:00 UTC on 1 January 1970).
+* @param tz The timezone.
+* @retval The tsk_gettimeofday() function shall return 0 and no value shall be reserved to indicate an error.
+*/
+int tsk_gettimeofday(struct timeval *tv, struct timezone *tz)
+{
+ return gettimeofday(tv, tz);
+}
+
+/**@ingroup tsk_time_group
+* Gets the number of milliseconds in @a tv
+* @retval The number of milliseconds
+*/
+uint64_t tsk_time_get_ms(struct timeval* tv)
+{
+ if(!tv){
+ TSK_DEBUG_ERROR("Invalid parameter");
+ return 0;
+ }
+ return (((uint64_t)tv->tv_sec)*(uint64_t)1000) + (((uint64_t)tv->tv_usec)/(uint64_t)1000);
+}
+
+/**@ingroup tsk_time_group
+* Gets the number of milliseconds since the EPOCH.
+* @retval The number of milliseconds since EPOCH.
+*/
+uint64_t tsk_time_epoch()
+{
+#if TSK_UNDER_WINDOWS
+ return (uint64_t)timeGetTime();
+#elif HAVE_CLOCK_GETTIME
+ struct timespec ts;
+ clock_gettime(CLOCK_MONOTONIC, &ts);
+ return (((uint64_t)ts.tv_sec)*(uint64_t)1000) + (((uint64_t)ts.tv_nsec)/(uint64_t)1000000);
+#else
+ struct timeval tv;
+ gettimeofday(&tv, 0);
+ return (((uint64_t)tv.tv_sec)*(uint64_t)1000) + (((uint64_t)tv.tv_usec)/(uint64_t)1000);
+#endif
+}
+
diff --git a/tinySAK/src/tsk_time.h b/tinySAK/src/tsk_time.h
new file mode 100644
index 0000000..e351389
--- /dev/null
+++ b/tinySAK/src/tsk_time.h
@@ -0,0 +1,73 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_time.h
+ * @brief Datetime functions.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef _TINYSAK_TIME_H_
+#define _TINYSAK_TIME_H_
+
+#include "tinysak_config.h"
+
+TSK_BEGIN_DECLS
+
+//#if defined(__SYMBIAN32__) || ANDROID /* Forward declaration */
+struct timeval;
+struct timezone;
+//#endif
+
+/**@ingroup tsk_time_group
+*/
+#define TSK_TIME_S_2_MS(S) ((S)*1000)
+#define TSK_TIME_MS_2_S(MS) ((MS)/1000)
+
+TINYSAK_API int tsk_gettimeofday(struct timeval *tv, struct timezone *tz);
+TINYSAK_API uint64_t tsk_time_get_ms(struct timeval *tv);
+TINYSAK_API uint64_t tsk_time_epoch();
+
+/**@ingroup tsk_time_group
+* Gets the number of milliseconds since the EPOCH.
+*/
+#define tsk_time_now() tsk_time_epoch()
+
+//#ifdef _WIN32_WCE
+//
+//#ifndef TIMEVAL
+///* On wince timeval struct is defined in "Winsock2.h" but I don't want to add it */
+//struct timeval
+//{
+// long tv_sec;
+// long tv_usec;
+//};
+//#define TIMEVAL
+//#endif TIMEVAL
+//
+//#endif
+
+TSK_END_DECLS
+
+#endif /* _TINYSAK_TIME_H_ */
+
diff --git a/tinySAK/src/tsk_timer.c b/tinySAK/src/tsk_timer.c
new file mode 100644
index 0000000..0cb4ba0
--- /dev/null
+++ b/tinySAK/src/tsk_timer.c
@@ -0,0 +1,531 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_timer.c
+* @brief Timer Manager.
+*
+* @author Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* @date Created: Sat Nov 8 16:54:58 2009 mdiop
+*/
+#include "tsk_timer.h"
+#include "tsk_debug.h"
+#include "tsk_list.h"
+#include "tsk_thread.h"
+#include "tsk_runnable.h"
+#include "tsk_condwait.h"
+#include "tsk_semaphore.h"
+#include "tsk_time.h"
+
+
+/**@defgroup tsk_timer_group Timers Management
+*/
+
+#define TSK_TIMER_CREATE(timeout, callback, arg) tsk_object_new(tsk_timer_def_t, timeout, callback, arg)
+#define TSK_TIMER_TIMEOUT(self) ((tsk_timer_t*)self)->timeout
+#define TSK_TIMER_GET_FIRST() (manager->timers && manager->timers->head) ? (tsk_timer_t*)(((tsk_list_item_t*)(manager->timers->head))->data) : 0
+
+/**
+ * @struct tsk_timer_s
+ * @brief Timer.
+**/
+typedef struct tsk_timer_s
+{
+ TSK_DECLARE_OBJECT;
+
+ tsk_timer_id_t id; /**< Unique timer identifier. */
+ const void *arg; /**< Opaque data to return with the callback function. */
+ uint64_t timeout; /**< When the timer will timeout(as EPOCH time). */
+ tsk_timer_callback_f callback; /**< The callback function to call after @ref timeout milliseconds. */
+
+ unsigned canceled:1;
+}
+tsk_timer_t;
+typedef tsk_list_t tsk_timers_L_t; /**< List of @ref tsk_timer_t elements. */
+
+/**
+ * @struct tsk_timer_manager_s
+ *
+ * @brief Timer manager.
+**/
+typedef struct tsk_timer_manager_s
+{
+ TSK_DECLARE_RUNNABLE;
+
+ void* mainThreadId[1];
+ tsk_condwait_handle_t *condwait;
+ tsk_mutex_handle_t *mutex;
+ tsk_semaphore_handle_t *sem;
+
+ tsk_timers_L_t *timers;
+}
+tsk_timer_manager_t;
+typedef tsk_list_t tsk_timer_manager_L_t; /**< List of @ref tsk_timer_manager_t elements. */
+
+/*== Definitions */
+static void *__tsk_timer_manager_mainthread(void *param);
+static int __tsk_pred_find_timer_by_id(const tsk_list_item_t *item, const void *id);
+static void __tsk_timer_manager_raise(tsk_timer_t *timer);
+static void *run(void* self);
+
+/**@ingroup tsk_timer_group
+*/
+tsk_timer_manager_handle_t* tsk_timer_manager_create()
+{
+ return tsk_object_new(tsk_timer_manager_def_t);
+}
+
+/**@ingroup tsk_timer_group
+* Starts the timer manager.
+*/
+int tsk_timer_manager_start(tsk_timer_manager_handle_t *self)
+{
+ int err = -1;
+ tsk_timer_manager_t *manager = self;
+
+ TSK_DEBUG_INFO("tsk_timer_manager_start");
+
+ if(!manager){
+ return -1;
+ }
+
+ tsk_mutex_lock(manager->mutex);
+
+ if(!TSK_RUNNABLE(manager)->running && !TSK_RUNNABLE(manager)->started){
+ TSK_RUNNABLE(manager)->run = run;
+ if(err = tsk_runnable_start(TSK_RUNNABLE(manager), tsk_timer_def_t)){
+ //TSK_OBJECT_SAFE_FREE(manager);
+ goto bail;
+ }
+ }
+ else{
+ TSK_DEBUG_WARN("Timer manager already running");
+ }
+
+bail:
+ tsk_mutex_unlock(manager->mutex);
+
+ return err;
+}
+
+#if defined(DEBUG) || defined(_DEBUG) || !defined(NDEBUG)
+/**@ingroup tsk_timer_group
+*/
+void tsk_timer_manager_debug(tsk_timer_manager_handle_t *self)
+{
+ tsk_timer_manager_t *manager = self;
+ if(manager){
+ //int index = 0;
+ tsk_list_item_t *item = tsk_null;
+
+ tsk_mutex_lock(manager->mutex);
+
+ tsk_list_foreach(item, manager->timers){
+ tsk_timer_t* timer = item->data;
+ TSK_DEBUG_INFO("timer [%llu]- %llu, %llu", timer->id, timer->timeout, tsk_time_epoch());
+ }
+
+ tsk_mutex_unlock(manager->mutex);
+ }
+}
+#endif
+
+/**@ingroup tsk_timer_group
+*/
+int tsk_timer_manager_stop(tsk_timer_manager_handle_t *self)
+{
+ int ret = -1;
+ tsk_timer_manager_t *manager = self;
+
+ if(!manager){
+ TSK_DEBUG_ERROR("Invalid paramater");
+ return -1;
+ }
+
+ // all functions called below are thread-safe ==> do not lock
+ // "mainthread" uses manager->mutex and runs in a separate thread ==> deadlock
+
+ if(TSK_RUNNABLE(manager)->running){
+ if(ret = tsk_runnable_stop(TSK_RUNNABLE(manager))){
+ goto bail;
+ }
+
+ tsk_semaphore_increment(manager->sem);
+ tsk_condwait_signal(manager->condwait);
+
+ ret = tsk_thread_join(manager->mainThreadId);
+ goto bail;
+ }
+ else{
+ ret = 0; /* already running. */
+ goto bail;
+ }
+
+bail:
+ return ret;
+}
+
+/**@ingroup tsk_timer_group
+*/
+tsk_timer_id_t tsk_timer_manager_schedule(tsk_timer_manager_handle_t *self, uint64_t timeout, tsk_timer_callback_f callback, const void *arg)
+{
+ tsk_timer_id_t timer_id = TSK_INVALID_TIMER_ID;
+ tsk_timer_manager_t *manager = self;
+
+ if(manager && (TSK_RUNNABLE(manager)->running || TSK_RUNNABLE(manager)->started)){
+ tsk_timer_t *timer;
+
+ timer = TSK_TIMER_CREATE(timeout, callback, arg);
+ timer_id = timer->id;
+ tsk_mutex_lock(manager->mutex);
+ tsk_list_push_ascending_data(manager->timers, ((void**) &timer));
+ tsk_mutex_unlock(manager->mutex);
+
+ //tsk_timer_manager_debug(self);
+
+ tsk_condwait_signal(manager->condwait);
+ tsk_semaphore_increment(manager->sem);
+ }
+
+ return timer_id;
+}
+
+/**@ingroup tsk_timer_group
+*/
+int tsk_timer_manager_cancel(tsk_timer_manager_handle_t *self, tsk_timer_id_t id)
+{
+ int ret = -1;
+ tsk_timer_manager_t *manager = self;
+
+ /* Check validity. */
+ if(!TSK_TIMER_ID_IS_VALID(id)){ /* Very common. */
+ return 0;
+ }
+
+ if(!TSK_LIST_IS_EMPTY(manager->timers) && TSK_RUNNABLE(manager)->running){
+ const tsk_list_item_t *item;
+ tsk_mutex_lock(manager->mutex);
+ item = tsk_list_find_item_by_pred(manager->timers, __tsk_pred_find_timer_by_id, &id);
+ if(item && item->data){
+ tsk_timer_t *timer = item->data;
+ timer->canceled = 1;
+
+ if(item == manager->timers->head){
+ /* The timer we are waiting on ? ==> remove it now. */
+ tsk_condwait_signal(manager->condwait);
+ }
+
+ ret = 0;
+ }
+ tsk_mutex_unlock(manager->mutex);
+ }
+ return ret;
+}
+
+static void *run(void* self)
+{
+ int ret;
+ tsk_list_item_t *curr;
+ tsk_timer_manager_t *manager = self;
+
+ TSK_RUNNABLE(manager)->running = tsk_true; // VERY IMPORTANT --> needed by the main thread
+
+ /* create main thread */
+ if((ret = tsk_thread_create(&(manager->mainThreadId[0]), __tsk_timer_manager_mainthread, manager))){
+ TSK_DEBUG_FATAL("Failed to create mainthread: %d\n", ret);
+ return tsk_null;
+ }
+
+ TSK_DEBUG_INFO("Timer manager run()::enter");
+
+ TSK_RUNNABLE_RUN_BEGIN(manager);
+
+ if(curr = TSK_RUNNABLE_POP_FIRST(manager)){
+ tsk_timer_t *timer = (tsk_timer_t *)curr->data;
+ if(timer->callback){
+ timer->callback(timer->arg, timer->id);
+ }
+ tsk_object_unref(curr);
+ }
+
+ TSK_RUNNABLE_RUN_END(manager);
+
+ TSK_DEBUG_INFO("Timer manager run()::exit");
+
+ return tsk_null;
+}
+
+static int __tsk_pred_find_timer_by_id(const tsk_list_item_t *item, const void *id)
+{
+ tsk_timer_t *timer;
+ if(item && item->data){
+ timer = item->data;
+ return (int)(timer->id - *((tsk_timer_id_t*)id));
+ }
+ return -1;
+}
+
+static void *__tsk_timer_manager_mainthread(void *param)
+{
+ int ret;
+ tsk_timer_t *curr;
+ uint64_t epoch;
+ tsk_timer_manager_t *manager = param;
+
+ TSK_DEBUG_INFO("TIMER MANAGER -- START");
+
+ while(TSK_RUNNABLE(manager)->running){
+ tsk_semaphore_decrement(manager->sem);
+
+peek_first:
+ if(!TSK_RUNNABLE(manager)->running){
+ break;
+ }
+
+ tsk_mutex_lock(manager->mutex);
+ curr = TSK_TIMER_GET_FIRST();
+ tsk_mutex_unlock(manager->mutex);
+
+ if(curr && !curr->canceled) {
+ epoch = tsk_time_epoch();
+ if(epoch >= curr->timeout){
+ tsk_timer_t *timer = tsk_object_ref(curr);
+ //TSK_DEBUG_INFO("Timer raise %llu", timer->id);
+
+ tsk_mutex_lock(manager->mutex);
+ TSK_RUNNABLE_ENQUEUE_OBJECT(TSK_RUNNABLE(manager), timer);
+ tsk_list_remove_item_by_data(manager->timers, curr);
+ tsk_mutex_unlock(manager->mutex);
+ }
+ else{
+ if((ret = tsk_condwait_timedwait(manager->condwait, (curr->timeout - epoch)))){
+ TSK_DEBUG_ERROR("CONWAIT for timer manager failed [%d]", ret);
+ break;
+ }
+ else{
+ goto peek_first;
+ }
+ }
+ }
+ else if(curr){
+ tsk_mutex_lock(manager->mutex);
+ /* TSK_DEBUG_INFO("Timer canceled %llu", curr->id); */
+ tsk_list_remove_item_by_data(manager->timers, curr);
+ tsk_mutex_unlock(manager->mutex);
+ }
+ } /* while() */
+
+ TSK_DEBUG_INFO("TIMER MANAGER -- STOP");
+
+ return 0;
+}
+
+
+
+
+
+/* ================= Global Timer Manager ================= */
+
+static tsk_timer_manager_t* __timer_mgr = tsk_null;
+static int __timer_mgr_start_count = 0;
+
+int tsk_timer_mgr_global_ref()
+{
+ if(!__timer_mgr){
+ __timer_mgr = tsk_timer_manager_create();
+ }
+ else{
+ __timer_mgr = tsk_object_ref(__timer_mgr);
+ }
+ return 0;
+}
+
+int tsk_timer_mgr_global_start()
+{
+ int ret = 0;
+ if(!__timer_mgr){
+ TSK_DEBUG_ERROR("No global Timer manager could be found");
+ return -1;
+ }
+ if(!TSK_RUNNABLE(__timer_mgr)->running && !TSK_RUNNABLE(__timer_mgr)->started){
+ if((ret = tsk_timer_manager_start(__timer_mgr))){
+ return ret;
+ }
+ }
+ __timer_mgr_start_count++;
+ return ret;
+}
+
+tsk_timer_id_t tsk_timer_mgr_global_schedule(uint64_t timeout, tsk_timer_callback_f callback, const void *arg)
+{
+ if(!__timer_mgr){
+ TSK_DEBUG_ERROR("No global Timer manager could be found");
+ return TSK_INVALID_TIMER_ID;
+ }
+ return tsk_timer_manager_schedule(__timer_mgr, timeout, callback, arg);
+}
+
+int tsk_timer_mgr_global_cancel(tsk_timer_id_t id)
+{
+ if(!__timer_mgr){
+ TSK_DEBUG_ERROR("No global Timer manager could be found");
+ return -1;
+ }
+ return tsk_timer_manager_cancel(__timer_mgr, id);
+}
+
+int tsk_timer_mgr_global_stop()
+{
+ int ret = 0;
+ if(!__timer_mgr){
+ TSK_DEBUG_ERROR("No global Timer manager could be found");
+ return -1;
+ }
+
+ if(__timer_mgr_start_count <= 0){
+ TSK_DEBUG_ERROR("Global Timer is in an invalid state");
+ return -2;
+ }
+
+ if(TSK_RUNNABLE(__timer_mgr)->running){
+ if(__timer_mgr_start_count == 1){
+ if((ret = tsk_timer_manager_stop(__timer_mgr))){
+ return ret;
+ }
+ }
+ __timer_mgr_start_count--;
+ }
+ return 0;
+}
+
+int tsk_timer_mgr_global_unref()
+{
+ if(!__timer_mgr){
+ TSK_DEBUG_ERROR("No global Timer manager could be found");
+ return -1;
+ }
+
+ __timer_mgr = tsk_object_unref(__timer_mgr);
+
+ return 0;
+}
+
+
+
+
+
+
+
+//=================================================================================================
+// Timer manager object definition
+//
+static tsk_object_t* tsk_timer_manager_ctor(tsk_object_t * self, va_list * app)
+{
+ tsk_timer_manager_t *manager = self;
+ if(manager){
+ manager->timers = tsk_list_create();
+ manager->sem = tsk_semaphore_create();
+ manager->condwait = tsk_condwait_create();
+ manager->mutex = tsk_mutex_create();
+ }
+ return self;
+}
+
+static tsk_object_t* tsk_timer_manager_dtor(tsk_object_t * self)
+{
+ tsk_timer_manager_t *manager = self;
+
+ if(manager){
+ tsk_timer_manager_stop(manager);
+
+ tsk_semaphore_destroy(&manager->sem);
+ tsk_condwait_destroy(&manager->condwait);
+ tsk_mutex_destroy(&manager->mutex);
+ tsk_object_unref(manager->timers);
+ }
+
+ return self;
+}
+
+static const tsk_object_def_t tsk_timer_manager_def_s =
+{
+ sizeof(tsk_timer_manager_t),
+ tsk_timer_manager_ctor,
+ tsk_timer_manager_dtor,
+ tsk_null,
+};
+const tsk_object_def_t * tsk_timer_manager_def_t = &tsk_timer_manager_def_s;
+
+
+
+
+
+
+//=================================================================================================
+// Timer object definition
+//
+static tsk_object_t* tsk_timer_ctor(tsk_object_t * self, va_list * app)
+{
+ static tsk_timer_id_t tsk_unique_timer_id = 1;
+ tsk_timer_t *timer = self;
+ if(timer){
+ timer->id = tsk_unique_timer_id++;
+ timer->timeout = va_arg(*app, uint64_t);
+ timer->callback = va_arg(*app, tsk_timer_callback_f);
+ timer->arg = va_arg(*app, const void *);
+
+ timer->timeout += tsk_time_epoch();
+ }
+ return self;
+}
+
+static tsk_object_t* tsk_timer_dtor(tsk_object_t * self)
+{
+ tsk_timer_t *timer = self;
+ if(timer){
+ }
+
+ return self;
+}
+
+static int tsk_timer_cmp(const tsk_object_t *obj1, const tsk_object_t *obj2)
+{
+ const tsk_timer_t *t1 = obj1;
+ const tsk_timer_t *t2 = obj2;
+
+ if(t1 && t2){
+ return (int)(t1->timeout - t2->timeout);
+ }
+ else if(!t1 && !t2) return 0;
+ else return -1;
+}
+
+static const tsk_object_def_t tsk_timer_def_s =
+{
+ sizeof(tsk_timer_t),
+ tsk_timer_ctor,
+ tsk_timer_dtor,
+ tsk_timer_cmp,
+};
+const tsk_object_def_t * tsk_timer_def_t = &tsk_timer_def_s;
+
+
diff --git a/tinySAK/src/tsk_timer.h b/tinySAK/src/tsk_timer.h
new file mode 100644
index 0000000..efe6743
--- /dev/null
+++ b/tinySAK/src/tsk_timer.h
@@ -0,0 +1,94 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_timer.h
+ * @brief Timer Manager.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef _TINYSAK_TIMER_H_
+#define _TINYSAK_TIMER_H_
+
+#include "tinysak_config.h"
+
+#include "tsk_object.h"
+
+TSK_BEGIN_DECLS
+
+
+/**@ingroup tsk_timer_group
+* @def TSK_TIMER_CALLBACK
+*/
+#define TSK_TIMER_CALLBACK_F(callback) ((tsk_timer_callback_f)callback)
+
+/**@ingroup tsk_timer_group
+* @def TSK_INVALID_TIMER_ID
+*/
+/**@ingroup tsk_timer_group
+* @def TSK_TIMER_ID_IS_VALID
+*/
+#define TSK_INVALID_TIMER_ID 0
+#define TSK_TIMER_ID_IS_VALID(id) ((id) != TSK_INVALID_TIMER_ID)
+
+/**@ingroup tsk_timer_group
+* @def tsk_timer_manager_handle_t
+*/
+/**@ingroup tsk_timer_group
+* @def tsk_timer_id_t
+*/
+/**@ingroup tsk_timer_group
+* @def tsk_timer_callback
+*/
+typedef void tsk_timer_manager_handle_t;
+typedef uint64_t tsk_timer_id_t;
+typedef int (*tsk_timer_callback_f)(const void* arg, tsk_timer_id_t timer_id);
+
+TINYSAK_API tsk_timer_manager_handle_t* tsk_timer_manager_create();
+
+TINYSAK_API int tsk_timer_manager_start(tsk_timer_manager_handle_t *self);
+TINYSAK_API int tsk_timer_manager_stop(tsk_timer_manager_handle_t *self);
+#if defined(DEBUG) || defined(_DEBUG)
+TINYSAK_API void tsk_timer_manager_debug(tsk_timer_manager_handle_t *self);
+#endif
+
+TINYSAK_API tsk_timer_id_t tsk_timer_manager_schedule(tsk_timer_manager_handle_t *self, uint64_t timeout, tsk_timer_callback_f callback, const void *arg);
+TINYSAK_API int tsk_timer_manager_cancel(tsk_timer_manager_handle_t *self, tsk_timer_id_t id);
+
+
+// Global Timer manager
+TINYSAK_API int tsk_timer_mgr_global_ref();
+TINYSAK_API int tsk_timer_mgr_global_start();
+TINYSAK_API tsk_timer_id_t tsk_timer_mgr_global_schedule(uint64_t timeout, tsk_timer_callback_f callback, const void *arg);
+TINYSAK_API int tsk_timer_mgr_global_cancel(tsk_timer_id_t id);
+TINYSAK_API int tsk_timer_mgr_global_stop();
+TINYSAK_API int tsk_timer_mgr_global_unref();
+
+
+TINYSAK_GEXTERN const tsk_object_def_t *tsk_timer_def_t;
+TINYSAK_GEXTERN const tsk_object_def_t *tsk_timer_manager_def_t;
+
+TSK_END_DECLS
+
+#endif /* _TINYSAK_TIMER_H_ */
+
diff --git a/tinySAK/src/tsk_url.c b/tinySAK/src/tsk_url.c
new file mode 100644
index 0000000..68a9915
--- /dev/null
+++ b/tinySAK/src/tsk_url.c
@@ -0,0 +1,92 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_url.c
+ * @brief Utility functions to encode/decode urls.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tsk_url.h"
+#include "tsk_memory.h"
+#include "tsk_string.h"
+
+#include <ctype.h>
+#include <string.h>
+
+/**@defgroup tsk_url_group Utility functions to encode/decode urls.
+*/
+
+
+/**@ingroup tsk_url_group
+* Encode an url.
+* @param url The url to encode
+* @retval The encoded url. It is up to you to free the returned string.
+*
+* @sa tsk_url_decode
+*
+*/
+char* tsk_url_encode(const char* url) {
+ char *purl = (char*)url, *buf = tsk_malloc(tsk_strlen(url) * 3 + 1), *pbuf = buf;
+ while (*purl) {
+ if (isalnum(*purl) || *purl == '-' || *purl == '_' || *purl == '.' || *purl == '~'){
+ *pbuf++ = *purl;
+ }
+ else if (*purl == ' '){
+ *pbuf++ = '+';
+ }
+ else{
+ *pbuf++ = '%', *pbuf++ = tsk_b10tob16(*purl >> 4), *pbuf++ = tsk_b10tob16(*purl & 15);
+ }
+ purl++;
+ }
+ *pbuf = '\0';
+ return buf;
+}
+
+/**@ingroup tsk_url_group
+* Decode an url.
+* @param url The url to encode
+* @retval The decoded url. It is up to you to free the returned string.
+*
+* @sa tsk_url_encode
+*/
+char* tsk_url_decode(const char* url) {
+ char *purl = (char*)url, *buf = tsk_malloc(tsk_strlen(url) + 1), *pbuf = buf;
+ while (*purl) {
+ if (*purl == '%') {
+ if (purl[1] && purl[2]) {
+ *pbuf++ = tsk_b16tob10(purl[1]) << 4 | tsk_b16tob10(purl[2]);
+ purl += 2;
+ }
+ } else if (*purl == '+') {
+ *pbuf++ = ' ';
+ } else {
+ *pbuf++ = *purl;
+ }
+ purl++;
+ }
+ *pbuf = '\0';
+ return buf;
+}
+
diff --git a/tinySAK/src/tsk_url.h b/tinySAK/src/tsk_url.h
new file mode 100644
index 0000000..5b213be
--- /dev/null
+++ b/tinySAK/src/tsk_url.h
@@ -0,0 +1,43 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_url.h
+ * @brief Useful string functions to manipulate strings.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef _TINYSAK_URL_H_
+#define _TINYSAK_URL_H_
+
+#include "tinysak_config.h"
+
+TSK_BEGIN_DECLS
+
+TINYSAK_API char* tsk_url_encode(const char* url);
+TINYSAK_API char* tsk_url_decode(const char* url);
+
+TSK_END_DECLS
+
+#endif /* _TINYSAK_URL_H_ */
+
diff --git a/tinySAK/src/tsk_uuid.c b/tinySAK/src/tsk_uuid.c
new file mode 100644
index 0000000..18c04f3
--- /dev/null
+++ b/tinySAK/src/tsk_uuid.c
@@ -0,0 +1,92 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_uuid.c
+ * @brief Universally Unique Identifier (UUID version 5) implementation (RFC 4122).
+ * This implementation is not fully conform to RFC 4122 but could be safely used to generate random UUIDs.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tsk_uuid.h"
+
+#include "tsk_sha1.h"
+#include "tsk_string.h"
+#include "tsk_time.h"
+
+#include <stdlib.h>
+#include <string.h>
+
+/**@defgroup tsk_uuid_group niversally Unique Identifier (UUID version 5) implementation (RFC 4122).
+*/
+
+/**@ingroup tsk_uuid_group
+*/
+int tsk_uuidgenerate(tsk_uuidstring_t *result)
+{
+ /* From wikipedia
+ * Version 5 UUIDs use a scheme with SHA-1 hashing, otherwise it is the same idea as in version 3.
+ * RFC 4122 states that version 5 is preferred over version 3 name based UUIDs.
+ * Note that the 160 bit SHA-1 hash is truncated to 128 bits to make the length work out.
+ */
+ tsk_sha1string_t sha1result;
+ tsk_istr_t epoch;
+ unsigned i, k;
+ static char HEX[] = "0123456789abcdef";
+
+ tsk_itoa(tsk_time_epoch(), &epoch);
+ tsk_sha1compute(epoch, sizeof(epoch), &sha1result);
+
+ /* XOR the SHA-1 result with random numbers. */
+ for(i=0; i<(TSK_UUID_DIGEST_SIZE*2); i+=4){
+#if 0
+ *((uint32_t*)&sha1result[i]) ^= rand();
+#else
+ k = rand();
+ sha1result[i] ^= k, sha1result[i + 1] ^= k,
+ sha1result[i + 2] ^= k, sha1result[i + 3] ^= k;
+#endif
+
+ for(k=0; k<sizeof(uint32_t); k++){
+ sha1result[i+k] = HEX[sha1result[i+k] & 0x0F]; /* To hexa. */
+ }
+ }
+
+ /* f47ac10b-58cc-4372-a567-0e02b2c3d479 */
+ memcpy(&(*result)[0], &sha1result[0], 8);
+ (*result)[8] = '-';
+
+ memcpy(&(*result)[9], &sha1result[8], 4);
+ (*result)[13] = '-';
+
+ memcpy(&(*result)[14], &sha1result[12], 4);
+ (*result)[18] = '-';
+
+ memcpy(&(*result)[19], &sha1result[16], 4);
+ (*result)[23] = '-';
+
+ memcpy(&(*result)[24], &sha1result[20], 12);
+ (*result)[36] = '\0';
+
+ return 0;
+}
diff --git a/tinySAK/src/tsk_uuid.h b/tinySAK/src/tsk_uuid.h
new file mode 100644
index 0000000..fff47ba
--- /dev/null
+++ b/tinySAK/src/tsk_uuid.h
@@ -0,0 +1,48 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_uuid.h
+ * @brief Universally Unique Identifier (UUID version 5) implementation (RFC 4122).
+ * This implementation is not fully conform to RFC 4122 but could be safely used to generate random UUIDs.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef _TINYSAK_UUID_H_
+#define _TINYSAK_UUID_H_
+
+#include "tinysak_config.h"
+
+TSK_BEGIN_DECLS
+
+#define TSK_UUID_DIGEST_SIZE 16
+#define TSK_UUID_STRING_SIZE ((TSK_UUID_DIGEST_SIZE*2)+4/*-*/)
+
+typedef char tsk_uuidstring_t[TSK_UUID_STRING_SIZE+1]; /**< Hexadecimal UUID digest string. */
+typedef char tsk_uuiddigest_t[TSK_UUID_DIGEST_SIZE]; /**< UUID digest bytes. */
+
+TINYSAK_API int tsk_uuidgenerate(tsk_uuidstring_t *result);
+
+TSK_END_DECLS
+
+#endif /* _TINYSAK_UUID_H_ */
diff --git a/tinySAK/src/tsk_xml.c b/tinySAK/src/tsk_xml.c
new file mode 100644
index 0000000..0c1c56b
--- /dev/null
+++ b/tinySAK/src/tsk_xml.c
@@ -0,0 +1,296 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_xml.c
+ * @brief Useful functions to manipulate xml documents.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#include "tsk_xml.h"
+
+#if HAVE_LIBXML2_H
+
+#include "tsk_string.h"
+#include "tsk_memory.h"
+#include "tsk_macros.h"
+
+#include <string.h>
+
+/**@defgroup tsk_xml_group XML
+*/
+
+/**@page tsk_xml_page XML Tutorial
+*/
+
+
+/**@ingroup tsk_xml_group
+* Initialize an XML namespace
+* @param namespace The XML namespace to initialize.
+*/
+/*void tsk_xml_namespace_init(tsk_xml_namespace_t* namespace)
+{
+}*/
+
+/**@ingroup tsk_xml_group
+* Free an XML namespace
+* @param namespace The namespace to free
+*/
+/*void tsk_xml_namespace_free(tsk_xml_namespace_t** namespace)
+{
+ TSK_FREE((*namespace)->prefix);
+ TSK_FREE((*namespace)->value);
+ TSK_FREE(namespace);
+}*/
+
+/**@ingroup tsk_xml_group
+* Initialize an XML element
+* @param element The XML element to initialize
+*/
+/*void tsk_xml_element_init(tsk_xml_element_t* element)
+{
+}*/
+
+/**@ingroup tsk_xml_group
+* Initialize an XML element and set values
+* @param element The XML element to initialize
+* @param name The element name
+* @param value The element value
+* @param type The element type
+*/
+void tsk_xml_element_init_set(tsk_xml_element_t** element, const char* name, const char* value, tsk_xml_type_t type)
+{
+ TSK_XML_ELEMENT_CREATE((*element));
+ (*element)->elements = TSK_LIST_CREATE();
+ (*element)->attributes = TSK_LIST_CREATE();
+ (*element)->namespaces = TSK_LIST_CREATE();
+ (*element)->name = tsk_strdup(name);
+ (*element)->value = tsk_strdup(value);
+ (*element)->type = type;
+}
+
+/**@ingroup tsk_xml_group
+* Free an XML element
+* @param _element The XML element to free
+*/
+/*void tsk_xml_element_free(void** _element)
+{
+ tsk_xml_element_t** element = (tsk_xml_element_t**)_element;
+
+ TSK_FREE((*element)->name);
+ TSK_FREE((*element)->value);
+ TSK_OBJECT_SAFE_FREE((*element)->elements);
+ TSK_OBJECT_SAFE_FREE((*element)->attributes);
+ TSK_OBJECT_SAFE_FREE((*element)->namespaces);
+
+ TSK_FREE(element);
+}*/
+
+/**@ingroup tsk_xml_group
+* Initialize an XML attribute
+* @param attribute The XML attribute to initialize
+*/
+/*void tsk_xml_attribute_init(tsk_xml_attribute_t* attribute)
+{
+}*/
+
+/**@ingroup tsk_xml_group
+* Free an XML attribute
+* @param attribute The XML attribute to free
+*/
+/*void tsk_xml_attribute_free(tsk_xml_attribute_t** attribute)
+{
+ TSK_FREE((*attribute)->name);
+ TSK_FREE((*attribute)->value);
+
+ TSK_FREE(attribute);
+}*/
+
+/**@ingroup tsk_xml_group
+* Get an XML namespace from an XML document
+* @param docPtr A pointer to the XML document
+* @param node The XML node from which to extract the namespace
+* @param href The namespace href
+* @retval The Namespace value matching our criteria (href)
+*/
+xmlNsPtr tsk_xml_get_namespace(xmlDocPtr docPtr, xmlNodePtr node, const char *href)
+{
+ xmlNs *ns = *xmlGetNsList(docPtr, node);
+ while (ns)
+ {
+ if (tsk_striequals(ns->href, href)) return ns;
+ else ns = ns->next;
+ }
+
+ return 0;
+}
+
+/**@ingroup tsk_xml_group
+* Find an XML node by name
+* @param curr The XML node from which to start
+* @param name The name of the XML node to find
+* @param ftype The find type
+* @retval Returns the node which match our criteria. If none match, this method returns NULL.
+*/
+xmlNodePtr tsk_xml_find_node(const xmlNodePtr curr, const char* name, tsk_xml_node_find_type_t ftype)
+{
+ xmlNodePtr node = curr;
+
+ while(node)
+ {
+ switch(ftype)
+ {
+ case nft_none: return (tsk_striequals(node->name, name))? node : 0;
+ case nft_children: node = node->children; break;
+ case nft_parent: node = node->parent; break;
+ case nft_next: node = node->next; break;
+ case nft_prev: node = node->prev; break;
+ default: return 0;
+ } /* switch */
+
+ /* check and return value if match */
+ if( node && (!name || tsk_striequals(node->name, name)) )
+ //if( node && (name == 0 || !tsk_stricmp((const char*)node->name, name)) )
+ {
+ return node;
+ }
+ }
+
+ return 0;
+}
+
+/**@ingroup tsk_xml_group
+* Select an XML node
+* @retval Returns the pointer to the node which match our criteria. If none match, this method returns NULL.
+*/
+xmlNodePtr tsk_xml_select_node(const xmlNodePtr root, ...)
+{
+ va_list list;
+ int step;
+ char* root_name = 0;
+ xmlNodePtr node = root;
+
+ if(!node || !(node->name)) return 0;
+
+ /* initialize variable arguments */
+ va_start(list, root);
+
+ while( node && (step=va_arg(list, tsk_xml_node_select_type_t)) != nst_end)
+ {
+ switch(step)
+ {
+ case nst_by_name:
+ { /* name */
+ const char* qname = va_arg(list, const char*);
+ if(tsk_striequals(root->name, qname)){
+ node = tsk_xml_find_node(node, 0, nft_children);
+ }
+ else{
+ if(!tsk_striequals(node->name, qname))
+ { /* do not match */
+ node = tsk_xml_find_node(node, qname, nft_next);
+ }
+ else
+ { /* already match */
+ node = node->children;
+ }
+ }
+ break;
+ }
+
+ case nst_content:
+ { /**/
+ node = tsk_xml_find_node(node, 0, nft_children);
+ break;
+ }
+
+ case nst_att_value:
+ { /* qname, att_name */
+ xmlAttrPtr attrPtr = 0;
+ int found = 0;
+ const char* qname = va_arg(list, const char*);
+ const char* att_name = va_arg(list, const char*);
+ node = tsk_xml_find_node(node, qname, nft_none);
+ while( node && !found )
+ {
+ attrPtr = node->properties;
+ while(attrPtr)
+ {
+ if(attrPtr->type == XML_ATTRIBUTE_NODE && attrPtr->children)
+ {
+ if( tsk_striequals(attrPtr->name, att_name) ){
+ node = attrPtr->children;
+ found = 1;
+ }
+ }
+ attrPtr = attrPtr->next;
+ }
+ if(!found) node = tsk_xml_find_node(node, 0, nft_next);
+ }
+ break;
+ }
+
+ case nst_by_att:
+ { /* qname att_name att_value */
+ xmlAttrPtr attrPtr = 0;
+ int found = 0;
+ const char* qname = va_arg(list, const char*);
+ const char* att_name = va_arg(list, const char*);
+ const char* att_value = va_arg(list, const char*);
+ node = tsk_xml_find_node(node, qname, nft_none);
+ while( node && !found )
+ {
+ attrPtr = node->properties;
+ while(attrPtr)
+ {
+ if(attrPtr->type == XML_ATTRIBUTE_NODE && attrPtr->children)
+ {
+ if( tsk_striequals(attrPtr->name, att_name)
+ && ( (attrPtr->children->content && tsk_striequals(attrPtr->children->content, att_value)) || !att_value )
+ ){
+ found = 1;
+ }
+ }
+ attrPtr = attrPtr->next;
+ }
+ if(!found) node = tsk_xml_find_node(node, 0, nft_next);
+ }
+
+ if(found && node) break;
+ else return 0;
+
+ break;
+ }
+ default: return 0;
+ } /* switch */
+
+ /* skip all comments */
+ TSK_XML_NODE_SKIP_COMMENTS(node);
+
+ } /* while*/
+
+ return node;
+}
+
+#endif /* HAVE_LIBXML2_H */
+
diff --git a/tinySAK/src/tsk_xml.h b/tinySAK/src/tsk_xml.h
new file mode 100644
index 0000000..9dc9e63
--- /dev/null
+++ b/tinySAK/src/tsk_xml.h
@@ -0,0 +1,175 @@
+/*
+* Copyright (C) 2009-2010 Mamadou Diop.
+*
+* Contact: Mamadou Diop <diopmamadou(at)doubango.org>
+*
+* This file is part of Open Source Doubango Framework.
+*
+* DOUBANGO is free software: you can redistribute it and/or modify
+* it under the terms of the GNU General Public License as published by
+* the Free Software Foundation, either version 3 of the License, or
+* (at your option) any later version.
+*
+* DOUBANGO is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+* GNU General Public License for more details.
+*
+* You should have received a copy of the GNU General Public License
+* along with DOUBANGO.
+*
+*/
+
+/**@file tsk_xml.h
+ * @brief Useful functions to manipulate xml document.
+ *
+ * @author Mamadou Diop <diopmamadou(at)doubango.org>
+ *
+ * @date Created: Sat Nov 8 16:54:58 2009 mdiop
+ */
+#ifndef _TINYSAK_XML_H_
+#define _TINYSAK_XML_H_
+
+#include "tinysak_config.h"
+#include "tsk_list.h"
+
+#if HAVE_LIBXML2_H
+#include <libxml/tree.h>
+
+#define TSK_XML_NODE_IS_TEXTVALUE(node) (node && node->type==XML_TEXT_NODE)
+#define TSK_XML_NODE_SAFE_GET_TEXTVALUE(node) (const char*)(TSK_XML_NODE_IS_TEXTVALUE(node)?(node->content):0)
+#define TSK_XML_NODE_SKIP_COMMENTS(node) while(node && (node->type==XML_COMMENT_NODE)) node = tsk_xml_find_node(node, 0, nft_next);
+
+
+#define TSK_XML_NODE_SELECT_BY_NAME(qname) nst_by_name, qname
+#define TSK_XML_NODE_SELECT_BY_ATT(qname, att_name, att_value) nst_by_att, qname, att_name, att_value
+#define TSK_XML_NODE_SELECT_ATT_VALUE(qname, att_name) nst_att_value, qname, att_name
+#define TSK_XML_NODE_SELECT_CONTENT() nst_content
+#define TSK_XML_NODE_SELECT_END() nst_end
+
+#define TSK_XML_NAMESPACE_CREATE() tsk_object_new(tsk_xml_namespace_def_t)
+#define TSK_XML_NAMESPACE_FREE(self) tsk_object_unref(self), self = 0
+
+#define TSK_XML_ELEMENT_CREATE(element) tsk_object_new(tsk_xml_element_def_t)
+#define TSK_XML_ELEMENT_FREE(self) tsk_object_unref(self), self = 0
+
+#define TSK_XML_ATTRIBUTE_CREATE(attribute) tsk_object_new(tsk_xml_attribute_def_t)
+#define TSK_XML_ATTRIBUTE_FREE(self) tsk_object_unref(self), self = 0
+
+#define TSK_XML_SERIALIZE(result, element, strValue)\
+ if(strValue) tsk_sprintf(&result, "<"##element##">%s</"##element##">", strValue); \
+ else tsk_strupdate(&result, "");
+
+/** C and XML Schema mapping */
+typedef enum tsk_xml_type_e
+{
+ xt_none,
+ xt_string, /* xsd:string */
+ xt_byte, /* xsd:byte */
+ xt_unsignedByte, /* xsd:unsignedByte */
+ xt_short, /* xsd:short */
+ xt_unsignedShort, /* xsd:unsignedShort */
+ xt_int, /* xsd:int */
+ xt_unsignedInt, /* xsd:unsignedInt */
+ xt_long, /* xsd:long */
+ xt_boolean, /* xsd:boolean */
+ xt_float, /* xsd:float */
+ xt_double /* xsd:double */
+}
+tsk_xml_type_t;
+
+/** Node finding types */
+typedef enum tsk_xml_node_find_type_s
+{
+ nft_none,
+ nft_children,
+ nft_parent,
+ nft_next,
+ nft_prev
+}
+tsk_xml_node_find_type_t;
+
+/** Element selection types */
+typedef enum tsk_xml_node_select_type_s
+{
+ nst_by_name,
+ nst_by_att,
+ nst_att_value,
+ nst_content,
+ nst_end
+}
+tsk_xml_node_select_type_t;
+
+/** XML namespace */
+typedef struct tsk_xml_namespace_s
+{
+ TSK_DECLARE_OBJECT;
+
+ char* prefix;
+ char* value;
+}
+tsk_xml_namespace_t;
+
+/** XML attribute */
+typedef struct tsk_xml_attribute_s
+{
+ TSK_DECLARE_OBJECT;
+
+ char* name;
+ void* value;
+ tsk_xml_type_t type;
+}
+tsk_xml_attribute_t;
+
+/** XML element */
+typedef struct tsk_xml_element_s
+{
+ TSK_DECLARE_OBJECT;
+
+ char* name;
+ void* value;
+ tsk_list_t* elements;
+ tsk_list_t* attributes;
+ tsk_list_t* namespaces;
+ tsk_xml_type_t type;
+}
+tsk_xml_element_t;
+
+typedef tsk_list_t tsk_xml_elements_t;
+typedef tsk_list_t tsk_xml_attributes_t;
+typedef tsk_list_t tsk_xml_namespaces_t;
+
+#define tsk_xml_elements_init tsk_list_init
+#define tsk_xml_attributes_init tsk_list_init
+#define tsk_xml_namespaces_init tsk_list_init
+
+#define tsk_xml_elements_add tsk_list_add_data
+#define tsk_xml_attributes_add tsk_list_add_data
+#define tsk_xml_namespaces_add tsk_list_add_data
+
+#define tsk_xml_elements_free tsk_list_free
+#define tsk_xml_attributes_free tsk_list_free
+#define tsk_xml_namespaces_free tsk_list_free
+
+//TINYSAK_API void tsk_xml_namespace_init(tsk_xml_namespace_t* _namespace);
+//TINYSAK_API void tsk_xml_namespace_free(tsk_xml_namespace_t** _namespace);
+
+//TINYSAK_API void tsk_xml_element_init(tsk_xml_element_t* element);
+TINYSAK_API void tsk_xml_element_init_set(tsk_xml_element_t** element, const char* name, const char* value, tsk_xml_type_t type);
+//TINYSAK_API void tsk_xml_element_free(void** element);
+
+//TINYSAK_API void tsk_xml_attribute_init(tsk_xml_attribute_t* attribute);
+//TINYSAK_API void tsk_xml_attribute_free(tsk_xml_attribute_t** attribute);
+
+TINYSAK_API xmlNsPtr tsk_xml_get_namespace(xmlDocPtr docPtr, xmlNodePtr node, const char *href);
+TINYSAK_API xmlNodePtr tsk_xml_find_node(const xmlNodePtr curr, const char* name, tsk_xml_node_find_type_t ftype);
+TINYSAK_API xmlNodePtr tsk_xml_select_node(const xmlNodePtr root, ...);
+
+TINYSAK_GEXTERN const void *tsk_xml_namespace_def_t;
+TINYSAK_GEXTERN const void *tsk_xml_attribute_def_t;
+TINYSAK_GEXTERN const void *tsk_xml_element_def_t;
+
+#endif /* HAVE_LIBXML2_H */
+
+#endif /* _TINYSAK_XML_H_ */
+
OpenPOWER on IntegriCloud