Browse Source

Backport from xs (new xs_set() API).

default 2 years ago
parent
commit
b487b41be6
3 changed files with 55 additions and 33 deletions
  1. 5 3
      html.c
  2. 49 29
      xs_set.h
  3. 1 1
      xs_version.h

+ 5 - 3
html.c

@@ -773,11 +773,13 @@ d_char *html_timeline(snac *snac, char *list, int local)
 /* returns the HTML for the timeline */
 {
     d_char *s = xs_str_new(NULL);
-    xs_set *seen = xs_set_new(4096);
+    xs_set seen;
     char *v;
     double t = ftime();
     int num = 0;
 
+    xs_set_init(&seen);
+
     s = html_user_header(snac, s, local);
 
     if (!local)
@@ -789,7 +791,7 @@ d_char *html_timeline(snac *snac, char *list, int local)
     while (xs_list_iter(&list, &v)) {
         xs *msg = timeline_get(snac, v);
 
-        s = html_entry(snac, s, msg, seen, local, 0, &num);
+        s = html_entry(snac, s, msg, &seen, local, 0, &num);
     }
 
     s = xs_str_cat(s, "</div>\n");
@@ -828,7 +830,7 @@ d_char *html_timeline(snac *snac, char *list, int local)
 
     s = xs_str_cat(s, "</body>\n</html>\n");
 
-    xs_set_free(seen);
+    xs_set_free(&seen);
 
     return s;
 }

+ 49 - 29
xs_set.h

@@ -7,42 +7,40 @@
 typedef struct _xs_set {
     int elems;              /* number of hash entries */
     int used;               /* number of used hash entries */
+    int *hash;              /* hashed offsets */
     d_char *list;           /* list of stored data */
-    int hash[];             /* hashed offsets */
 } xs_set;
 
-xs_set *xs_set_new(int elems);
+void xs_set_init(xs_set *s);
 void xs_set_free(xs_set *s);
 int xs_set_add(xs_set *s, const char *data);
 
 
 #ifdef XS_IMPLEMENTATION
 
-xs_set *xs_set_new(int elems)
-/* creates a new set with a maximum of size hashed data */
-{
-    int sz = sizeof(struct _xs_set) + sizeof(int) * elems;
-    xs_set *s = xs_realloc(NULL, sz);
-
-    memset(s, '\0', sz);
 
-    /* initialize */
-    s->elems  = elems;
-    s->list   = xs_list_new();
+void xs_set_init(xs_set *s)
+/* initializes a set */
+{
+    /* arbitrary default */
+    s->elems = 256;
+    s->used  = 0;
+    s->hash  = xs_realloc(NULL, s->elems * sizeof(int));
+    s->list  = xs_list_new();
 
-    return s;
+    memset(s->hash, '\0', s->elems * sizeof(int));
 }
 
 
 void xs_set_free(xs_set *s)
 /* frees a set */
 {
-    xs_free(s->list);
-    xs_free(s);
+    s->hash = xs_free(s->hash);
+    s->list = xs_free(s->list);
 }
 
 
-unsigned int _xs_set_hash(const char *data, int size)
+static unsigned int _calc_hash(const char *data, int size)
 {
     unsigned int hash = 0x666;
     int n;
@@ -56,14 +54,12 @@ unsigned int _xs_set_hash(const char *data, int size)
 }
 
 
-int xs_set_add(xs_set *s, const char *data)
-/* adds the data to the set */
-/* returns: 1 if added, 0 if already there, -1 if it's full */
+static int _store_hash(xs_set *s, const char *data, int value)
 {
     unsigned int hash, i;
     int sz = xs_size(data);
 
-    hash = _xs_set_hash(data, sz);
+    hash = _calc_hash(data, sz);
 
     while (s->hash[(i = hash % s->elems)]) {
         /* get the pointer to the stored data */
@@ -77,21 +73,45 @@ int xs_set_add(xs_set *s, const char *data)
         hash++;
     }
 
-    /* is it full? fail */
-    if (s->used == s->elems / 2)
-        return -1;
-
-    /* store the position */
-    s->hash[i] = xs_size(s->list);
-
-    /* add the data */
-    s->list = xs_list_append_m(s->list, data, sz);
+    /* store the new value */
+    s->hash[i] = value;
 
     s->used++;
 
     return 1;
 }
 
+
+int xs_set_add(xs_set *s, const char *data)
+/* adds the data to the set */
+/* returns: 1 if added, 0 if already there */
+{
+    /* is it 'full'? */
+    if (s->used >= s->elems / 2) {
+        char *p, *v;
+
+        /* expand! */
+        s->elems *= 2;
+        s->used  = 0;
+        s->hash  = xs_realloc(s->hash, s->elems * sizeof(int));
+
+        memset(s->hash, '\0', s->elems * sizeof(int));
+
+        /* add the list elements back */
+        p = s->list;
+        while (xs_list_iter(&p, &v))
+            _store_hash(s, v, v - s->list);
+    }
+
+    int ret = _store_hash(s, data, xs_size(s->list));
+
+    /* if it's new, add the data */
+    if (ret)
+        s->list = xs_list_append_m(s->list, data, xs_size(data));
+
+    return ret;
+}
+
 #endif /* XS_IMPLEMENTATION */
 
 #endif /* XS_SET_H */

+ 1 - 1
xs_version.h

@@ -1 +1 @@
-/* 1cde797082a259158b181f9c1e4bda4c5204109d */
+/* a78beb97d364ff31cbaa504e275118afeaea7a59 */