On Sat, Mar 7, 2015 at 8:30 AM, William A. Rowe Jr. <[email protected]> wrote:
> On Thu, 5 Mar 2015 11:19:40 -0500
> Jim Jagielski <[email protected]> wrote:
>
>> After doing some additional research, I think that the
>> current implementation of NOT allowing duplicates (in
>> APR 1.5/1.6) is BROKEN. In trunk this is determined by
>> a flag w/ the insert statement, but the default *should*
>> be to allow dups.
>>
>> As such, I'd like to adjust 1.5/1.6 to the correct and,
>> afaict, canonical behavior.
>
> I don't believe we can do this, it defies all rational API compatibility
> revisioning policies of any project, anywhere.

There is a possibility to both preserve/restore the addn semantic to
skiplist_insert() and still have the add semantic in 1.5.x.
It would be to give apr_skiplist_insert_compare(), which exists in
1.5.x, the add semantic when its compare function arg is NULL.

Eg. for trunk:

Index: tables/apr_skiplist.c
===================================================================
--- tables/apr_skiplist.c    (revision 1664776)
+++ tables/apr_skiplist.c    (working copy)
@@ -517,29 +517,39 @@ static apr_skiplistnode *insert_compare(apr_skipli
 APR_DECLARE(apr_skiplistnode *)
apr_skiplist_insert_compare(apr_skiplist *sl, void *data,
                                       apr_skiplist_compare comp)
 {
-    return insert_compare(sl, data, comp, 1);
+    if (comp) {
+        return insert_compare(sl, data, comp, 0);
+    }
+    else if (sl->compare) {
+        return insert_compare(sl, data, sl->compare, 1);
+    }
+    else {
+        return NULL;
+    }
 }

 APR_DECLARE(apr_skiplistnode *) apr_skiplist_insert(apr_skiplist *sl,
void *data)
 {
-    if (!sl->compare) {
-        return NULL;
-    }
-    return insert_compare(sl, data, sl->compare, 1);
+    return apr_skiplist_insert_compare(sl, data, sl->compare);
 }

-APR_DECLARE(apr_skiplistnode *)
apr_skiplist_addne_compare(apr_skiplist *sl, void *data,
+APR_DECLARE(apr_skiplistnode *) apr_skiplist_add_compare(apr_skiplist
*sl, void *data,
                                       apr_skiplist_compare comp)
 {
-    return insert_compare(sl, data, comp, 0);
+    if (comp) {
+        return insert_compare(sl, data, comp, 1);
+    }
+    else if (sl->compare) {
+        return insert_compare(sl, data, sl->compare, 1);
+    }
+    else {
+        return NULL;
+    }
 }

-APR_DECLARE(apr_skiplistnode *) apr_skiplist_addne(apr_skiplist *sl,
void *data)
+APR_DECLARE(apr_skiplistnode *) apr_skiplist_add(apr_skiplist *sl, void *data)
 {
-    if (!sl->compare) {
-        return NULL;
-    }
-    return insert_compare(sl, data, sl->compare, 0);
+    return apr_skiplist_add_compare(sl, data, sl->compare);
 }

 APR_DECLARE(int) apr_skiplist_remove(apr_skiplist *sl, void *data,
apr_skiplist_freefunc myfree)
--


And for 1.5.x:

Index: tables/apr_skiplist.c
===================================================================
--- tables/apr_skiplist.c    (revision 1664805)
+++ tables/apr_skiplist.c    (working copy)
@@ -394,8 +394,16 @@ APR_DECLARE(apr_skiplistnode *) apr_skiplist_inser
                                       apr_skiplist_compare comp)
 {
     apr_skiplistnode *m, *p, *tmp, *ret = NULL;
-    int nh = 1, ch;
+    int add = 0, nh = 1, ch;

+    if (!comp) {
+        if (!sl->compare) {
+            return NULL;
+        }
+        comp = sl->compare;
+        add = 1;
+    }
+
     if (sl->preheight) {
         while (nh < sl->preheight && get_b_rand()) {
             nh++;
@@ -423,6 +431,11 @@ APR_DECLARE(apr_skiplistnode *) apr_skiplist_inser
          */
         if (m->next) {
             int compared = comp(data, m->next->data);
+            if (compared == 0 && !add) {
+                /* Keep the existing element(s) */
+                skiplist_qclear(&sl->stack_q);
+                return NULL;
+            }
             if (compared > 0) {
                 m = m->next;
                 continue;
--

Reply via email to