Revert "init: Assign set value to avoid ambiguity"
[platform/core/system/tizen-platform-wrapper.git] / src / scratch.c
index dc3c918..6f25b54 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2013 Intel Corporation.
+ * Copyright (C) 2013-2014 Intel Corporation.
  * 
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -28,6 +28,7 @@
 #endif
 
 #include <stdlib.h>
+#include <memory.h>
 
 #ifndef INITIAL_SCRATCH_CAPACITY
 #define INITIAL_SCRATCH_CAPACITY  240
 #error "bad value for INITIAL_SCRATCH_CAPACITY"
 #endif
 
+#define INSTANCIATE 1
+#if INSTANCIATE
+#define SET_CAPACITY        97
+#define HASHCODE_INIT       5381
+#define HASHCODE_NEXT(H,C)  (((H) << 5) + (H) + (C))
+#endif
+
 #ifndef NOT_MULTI_THREAD_SAFE
 #include <pthread.h>
-static pthread_key_t tlskey;
-static int key_initialized = 0;
+#endif
+
+#if !(defined(NOT_MULTI_THREAD_SAFE) || INSTANCIATE)
+static __thread void *global_scratch = NULL;
 #else
 static void *global_scratch = NULL;
 #endif
+#if INSTANCIATE && !defined(NOT_MULTI_THREAD_SAFE)
+static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
+#endif
+
+#if INSTANCIATE
+/* structure for recording items in the hash map */
+struct set_item {
+    struct set_item *next;        /* chain to next item */
+    size_t hashcode;                /* hash of the string */
+    size_t length;                /* length of the string including null */
+};
+
+/* the array of recorded strings */
+static struct set_item *global_path_set[SET_CAPACITY]; /* initialized to  zeros */
+
+/* instanciate (or retrieve an instance) of the 'string' that
+is granted to have the 'length' including terminating null and a
+hash code 'hashcode' */
+static const char *instantiate(const char *string, size_t length, size_t hashcode)
+{
+    struct set_item **pp, *item;
+    char *result;
+
+    /* get first item in the table */
+    pp = &global_path_set[hashcode % SET_CAPACITY];
+    result = 0;
+    do {
+        /* inspect the item */
+        item = *pp;
+        if (!item) {
+            /* no item: create it */
+            item = malloc(length + sizeof * item);
+            if (!item)
+                return NULL;
+            /* init it */
+            item->next = 0;
+            item->hashcode = hashcode;
+            item->length = length;
+            result = (char *)(item + 1);
+            memcpy(result, string, length);
+            /* record it */
+            *pp = item;
+        } else if (item->hashcode == hashcode
+                && item->length == length
+                && 0 == strcmp(string, (const char *)(item + 1))) {
+            /* item found */
+            result = (char *)(item + 1);
+        } else {
+            /* try the next */
+            pp = &item->next;
+        }
+    } while (!result);
+
+    return result;
+}
+#endif
 
 /* CAUTION: in a multitheaded context, it is expected that
 =========== the function scratchcat is call under a mutex. 
 If it is not the case please check for initializing 'tlskey' 
 only one time before use of it. */
 
+#if INSTANCIATE && !defined(NOT_MULTI_THREAD_SAFE)
+static const char *_scratchcat( int ispath, const char **strings);
+
 const char *scratchcat( int ispath, const char **strings)
 {
+    const char *result;
+    pthread_mutex_lock(&mutex);
+    result = _scratchcat( ispath, strings);
+    pthread_mutex_unlock(&mutex);
+    return result;
+}
+
+static const char *_scratchcat( int ispath, const char **strings)
+#else
+const char *scratchcat( int ispath, const char **strings)
+#endif
+{
     void *scratch, *p;
     char *result;
     size_t length, capacity;
     const char *instr;
     char c, pc;
+#if INSTANCIATE
+    size_t hashcode = HASHCODE_INIT;
+#endif
 
     /* get the recorded pointer on scrtch area */
-#ifndef NOT_MULTI_THREAD_SAFE
-    if (!key_initialized) {
-        key_initialized = 1;
-        pthread_key_create( &tlskey, (void(*)(void*))free);
-    }
-    scratch = pthread_getspecific( tlskey);
-#else
     scratch = global_scratch;
-#endif
 
     /* create the scratch area if needed */
     if (scratch == NULL) {
@@ -77,11 +153,7 @@ const char *scratchcat( int ispath, const char **strings)
             return NULL;
         *((size_t*)p) = capacity;
         scratch = p;
-#ifndef NOT_MULTI_THREAD_SAFE
-        pthread_setspecific( tlskey, p);
-#else
         global_scratch = p;
-#endif
     }
 
     /* set local data for scratch area */
@@ -128,30 +200,39 @@ const char *scratchcat( int ispath, const char **strings)
             *((size_t*)p) = capacity;
             if (p != scratch) {
                 scratch = p;
-#ifndef NOT_MULTI_THREAD_SAFE
-                pthread_setspecific( tlskey, p);
-#else
                 global_scratch = p;
-#endif
                 result = (char*)(1+((size_t*)p));
             }
         }
 
         /* append the char */
         pc = result[length++] = c;
+#if INSTANCIATE
+        hashcode = HASHCODE_NEXT(hashcode, (size_t)c);
+#endif
     }
 
+#if INSTANCIATE
+    return instantiate(result, length, hashcode);
+#else
     return result;
+#endif
 }
 
 
 #ifdef TEST_SCRATCH
 #include <stdio.h>
 int main(int argc, const char**argv) {
-    int ispath;
+    int ispath, iter, i;
     argv++;
     ispath = argv[0] && argv[0][0] == '-' && argv[0][1] == 'p';
-    printf("%s\n",scratchcat(ispath,argv+ispath));
+    for (i = 0 ; i < 2 ; i++) {
+        iter = ispath;
+        while (iter < argc) {
+            const char *p = scratchcat(ispath,argv+iter++);
+            printf("%p: %s\n",p,p);
+        }
+    }
     return 0;
 }
 #endif