add single instance mode
[uwplayer.git] / ucx / list.c
index ebfff65..cc96710 100644 (file)
@@ -32,7 +32,7 @@
 
 // <editor-fold desc="Store Pointers Functionality">
 
-static _Thread_local CxListComparator cx_pl_cmpfunc_impl;
+static _Thread_local cx_compare_func cx_pl_cmpfunc_impl;
 
 static int cx_pl_cmpfunc(
         void const *l,
@@ -115,12 +115,12 @@ static void *cx_pl_at(
     return ptr == NULL ? NULL : *ptr;
 }
 
-static size_t cx_pl_find(
+static ssize_t cx_pl_find(
         struct cx_list_s const *list,
         void const *elem
 ) {
     cx_pl_hack_cmpfunc(list);
-    size_t ret = list->climpl->find(list, &elem);
+    ssize_t ret = list->climpl->find(list, &elem);
     cx_pl_unhack_cmpfunc(list);
     return ret;
 }
@@ -179,6 +179,7 @@ static cx_list_class cx_pointer_list_class = {
 };
 
 void cxListStoreObjects(CxList *list) {
+    list->store_pointer = false;
     if (list->climpl != NULL) {
         list->cl = list->climpl;
         list->climpl = NULL;
@@ -186,90 +187,111 @@ void cxListStoreObjects(CxList *list) {
 }
 
 void cxListStorePointers(CxList *list) {
-    list->itemsize = sizeof(void *);
+    list->item_size = sizeof(void *);
+    list->store_pointer = true;
     list->climpl = list->cl;
     list->cl = &cx_pointer_list_class;
 }
 
-bool cxListIsStoringPointers(CxList const *list) {
-    return list->climpl != NULL;
+// </editor-fold>
+
+// <editor-fold desc="empty list implementation">
+
+static void cx_emptyl_noop(__attribute__((__unused__)) CxList *list) {
+    // this is a noop, but MUST be implemented
 }
 
-// </editor-fold>
+static void *cx_emptyl_at(
+        __attribute__((__unused__)) struct cx_list_s const *list,
+        __attribute__((__unused__)) size_t index
+) {
+    return NULL;
+}
 
-void cx_list_invoke_destructor(
-        CxList const *list,
-        void *elem
+static ssize_t cx_emptyl_find(
+        __attribute__((__unused__)) struct cx_list_s const *list,
+        __attribute__((__unused__)) void const *elem
 ) {
-    switch (list->content_destructor_type) {
-        case CX_DESTRUCTOR_SIMPLE: {
-            cx_list_invoke_simple_destructor(list, elem);
-            break;
-        }
-        case CX_DESTRUCTOR_ADVANCED: {
-            cx_list_invoke_advanced_destructor(list, elem);
-            break;
-        }
-        case CX_DESTRUCTOR_NONE:
-            break; // nothing
-    }
+    return -1;
 }
 
-void cx_list_invoke_simple_destructor(
-        CxList const *list,
-        void *elem
+static int cx_emptyl_compare(
+        __attribute__((__unused__)) struct cx_list_s const *list,
+        struct cx_list_s const *other
 ) {
-    if (cxListIsStoringPointers(list)) {
-        elem = *((void **) elem);
-    }
-    list->simple_destructor(elem);
+    if (other->size == 0) return 0;
+    return -1;
 }
 
-void cx_list_invoke_advanced_destructor(
-        CxList const *list,
-        void *elem
+static bool cx_emptyl_iter_valid(__attribute__((__unused__)) void const *iter) {
+    return false;
+}
+
+static CxIterator cx_emptyl_iterator(
+        struct cx_list_s const *list,
+        size_t index,
+        __attribute__((__unused__)) bool backwards
 ) {
-    if (cxListIsStoringPointers(list)) {
-        elem = *((void **) elem);
-    }
-    list->advanced_destructor.func(list->advanced_destructor.data, elem);
+    CxIterator iter = {0};
+    iter.src_handle = list;
+    iter.index = index;
+    iter.base.valid = cx_emptyl_iter_valid;
+    return iter;
 }
 
-void cxListDestroy(CxList *list) {
-    switch (list->content_destructor_type) {
-        case CX_DESTRUCTOR_SIMPLE: {
-            CxIterator iter = cxListIterator(list);
-            cx_foreach(void*, elem, iter) {
-                // already correctly resolved pointer - immediately invoke dtor
-                list->simple_destructor(elem);
-            }
-            break;
-        }
-        case CX_DESTRUCTOR_ADVANCED: {
-            CxIterator iter = cxListIterator(list);
-            cx_foreach(void*, elem, iter) {
-                // already correctly resolved pointer - immediately invoke dtor
-                list->advanced_destructor.func(list->advanced_destructor.data, elem);
-            }
-            break;
-        }
-        case CX_DESTRUCTOR_NONE:
-            break; // nothing
-    }
+static cx_list_class cx_empty_list_class = {
+        cx_emptyl_noop,
+        NULL,
+        NULL,
+        NULL,
+        NULL,
+        cx_emptyl_noop,
+        NULL,
+        cx_emptyl_at,
+        cx_emptyl_find,
+        cx_emptyl_noop,
+        cx_emptyl_compare,
+        cx_emptyl_noop,
+        cx_emptyl_iterator,
+};
+
+CxList cx_empty_list = {
+        NULL,
+        NULL,
+        0,
+        0,
+        NULL,
+        NULL,
+        NULL,
+        false,
+        &cx_empty_list_class,
+        NULL
+};
+
+CxList *const cxEmptyList = &cx_empty_list;
 
+// </editor-fold>
+
+void cxListDestroy(CxList *list) {
     list->cl->destructor(list);
-    cxFree(list->allocator, list);
 }
 
 int cxListCompare(
         CxList const *list,
         CxList const *other
 ) {
-    if (list->cl->compare == other->cl->compare) {
-        // same compare function, lists are compatible
-        return list->cl->compare(list, other);
-    } else {
-        // different compare functions, use iterator
+    if (
+        // if one is storing pointers but the other is not
+        (list->store_pointer ^ other->store_pointer) ||
+
+        // if one class is wrapped but the other is not
+        ((list->climpl == NULL) ^ (other->climpl == NULL)) ||
+
+        // if the resolved compare functions are not the same
+        ((list->climpl != NULL ? list->climpl->compare : list->cl->compare) !=
+         (other->climpl != NULL ? other->climpl->compare : other->cl->compare))
+    ) {
+        // lists are definitely different - cannot use internal compare function
         if (list->size == other->size) {
             CxIterator left = cxListIterator(list);
             CxIterator right = cxListIterator(other);
@@ -287,6 +309,9 @@ int cxListCompare(
         } else {
             return list->size < other->size ? -1 : 1;
         }
+    } else {
+        // lists are compatible
+        return list->cl->compare(list, other);
     }
 }