/*
* Sherlock Library -- Object Functions
*
- * (c) 1997--2001 Martin Mares <mj@ucw.cz>
+ * (c) 1997--2004 Martin Mares <mj@ucw.cz>
+ * (c) 2004 Robert Spalek <robert@ucw.cz>
+ *
+ * This software may be freely distributed and used according to the terms
+ * of the GNU Lesser General Public License.
*/
#include "lib/lib.h"
-#include "lib/pools.h"
+#include "lib/mempool.h"
#include "lib/fastbuf.h"
+#include "lib/object.h"
#include <string.h>
#include <stdio.h>
-
-#define OBJ_POOL_SIZE 4096
+#include <stdlib.h>
void
obj_dump(struct odes *o)
{
- struct oattr *a, *b;
-
- for(a=o->attrs; a; a=a->next)
- for(b=a; b; b=b->same)
+ for(struct oattr *a=o->attrs; a; a=a->next)
+ for(struct oattr *b=a; b; b=b->same)
printf("%c%s\n", (a==b ? a->attr : ' '), b->val);
}
static struct oattr *
oa_new(struct odes *o, uns x, byte *v)
{
- struct oattr *a = mp_alloc(o->pool, sizeof(struct oattr) + strlen(v));
+ struct oattr *a = mp_alloc(o->pool, sizeof(struct oattr) + strlen(v)+1);
a->next = a->same = NULL;
- a->last_same = a;
a->attr = x;
+ a->val = (byte*) (a+1);
strcpy(a->val, v);
return a;
}
-struct odes *
-obj_new(struct mempool *pool)
+static struct oattr *
+oa_new_ref(struct odes *o, uns x, byte *v)
{
- struct mempool *lp = pool;
- struct odes *o;
+ struct oattr *a = mp_alloc(o->pool, sizeof(struct oattr));
- if (!lp)
- lp = mp_new(OBJ_POOL_SIZE);
- o = mp_alloc(lp, sizeof(struct odes));
- o->pool = lp;
- o->local_pool = (pool == lp) ? NULL : lp;
- o->attrs = NULL;
- return o;
-}
-
-void
-obj_free(struct odes *o)
-{
- if (o->local_pool)
- mp_delete(o->local_pool);
+ a->next = a->same = NULL;
+ a->attr = x;
+ a->val = v;
+ return a;
}
-int
-obj_read(struct fastbuf *f, struct odes *o)
+struct odes *
+obj_new(struct mempool *pool)
{
- byte buf[1024];
- struct oattr **last = &o->attrs;
- struct oattr *a, *la;
-
- la = NULL;
- *last = NULL;
- while (bgets(f, buf, sizeof(buf)))
- {
- if (!buf[0])
- return 1;
- a = oa_new(o, buf[0], buf+1);
- if (!la || la->attr != a->attr)
- for(la=o->attrs; la && la->attr != a->attr; la=la->next)
- ;
- if (la)
- {
- la->last_same->same = a;
- la->last_same = a;
- }
- else
- {
- *last = a;
- last = &a->next;
- la = a;
- }
- }
- return 0;
-}
-
-void
-obj_write(struct fastbuf *f, struct odes *d)
-{
- struct oattr *a, *b;
- byte *z;
-
- for(a=d->attrs; a; a=a->next)
- for(b=a; b; b=b->same)
- {
- bputc(f, a->attr);
- for(z = b->val; *z; z++)
- if (*z >= ' ')
- bputc(f, *z);
- else
- {
- bputc(f, '?');
- log(L_ERROR, "obj_dump: Found non-ASCII characters (URL might be %s)", obj_find_aval(d, 'U'));
- }
- bputc(f, '\n');
- }
+ struct odes *o = mp_alloc(pool, sizeof(struct odes));
+ o->pool = pool;
+ o->attrs = NULL;
+ o->cached_attr = NULL;
+ return o;
}
struct oattr *
obj_find_attr(struct odes *o, uns x)
{
struct oattr *a;
-
for(a=o->attrs; a && a->attr != x; a=a->next)
;
return a;
{
struct oattr *a = obj_find_attr(o, x);
- return a ? a->last_same : NULL;
+ if (a)
+ {
+ while (a->same)
+ a = a->same;
+ }
+ return a;
}
uns
struct oattr *x, **p, *y, *l;
byte aa = a->attr;
+ o->cached_attr = NULL;
p = &o->attrs;
while (x = *p)
{
if (x == a)
{
*p = x->same;
- if (y->last_same == x)
- y->last_same = l;
return 1;
}
p = &x->same;
obj_find_aval(struct odes *o, uns x)
{
struct oattr *a = obj_find_attr(o, x);
-
return a ? a->val : NULL;
}
+uns
+obj_find_anum(struct odes *o, uns x, uns def)
+{
+ struct oattr *a = obj_find_attr(o, x);
+ return a ? (uns)atol(a->val) : def;
+}
+
struct oattr *
obj_set_attr(struct odes *o, uns x, byte *v)
{
}
else
a = NULL;
+ o->cached_attr = a;
return a;
}
return obj_set_attr(o, a, x);
}
-struct oattr *
-obj_add_attr(struct odes *o, struct oattr *a, uns x, byte *v)
+static inline struct oattr *
+obj_add_attr_internal(struct odes *o, struct oattr *b)
{
- struct oattr *b;
+ struct oattr *a, **z;
- if (!a)
+ if (!(a = o->cached_attr) || a->attr != b->attr)
{
- a = obj_find_attr(o, x);
+ z = &o->attrs;
+ while ((a = *z) && a->attr != b->attr)
+ z = &a->next;
if (!a)
- return obj_set_attr(o, x, v);
+ {
+ *z = b;
+ /* b->next is NULL */
+ goto done;
+ }
}
+ while (a->same)
+ a = a->same;
+ a->same = b;
+ done:
+ o->cached_attr = b;
+ return b;
+}
+
+struct oattr *
+obj_add_attr(struct odes *o, uns x, byte *v)
+{
+ return obj_add_attr_internal(o, oa_new(o, x, v));
+}
+
+struct oattr *
+obj_add_attr_ref(struct odes *o, uns x, byte *v)
+{
+ return obj_add_attr_internal(o, oa_new_ref(o, x, v));
+}
+
+struct oattr *
+obj_prepend_attr(struct odes *o, uns x, byte *v)
+{
+ struct oattr *a, *b, **z;
+
b = oa_new(o, x, v);
- a->last_same->same = b;
- a->last_same = b;
- return a;
+ z = &o->attrs;
+ while (a = *z)
+ {
+ if (a->attr == x)
+ {
+ b->same = a;
+ b->next = a->next;
+ a->next = NULL;
+ *z = b;
+ return b;
+ }
+ z = &a->next;
+ }
+ b->next = o->attrs;
+ o->attrs = b;
+ return b;
+}
+
+struct oattr *
+obj_insert_attr(struct odes *o, struct oattr *first, struct oattr *after, byte *v)
+{
+ struct oattr *b = oa_new(o, first->attr, v);
+ b->same = after->same;
+ after->same = b;
+ return b;
+}
+
+void
+obj_move_attr_to_head(struct odes *o, uns x)
+{
+ struct oattr *a, **z;
+
+ z = &o->attrs;
+ while (a = *z)
+ {
+ if (a->attr == x)
+ {
+ *z = a->next;
+ a->next = o->attrs;
+ o->attrs = a;
+ break;
+ }
+ z = &a->next;
+ }
+}
+
+void
+obj_move_attr_to_tail(struct odes *o, uns x)
+{
+ struct oattr *a, **z;
+
+ z = &o->attrs;
+ while (a = *z)
+ {
+ if (a->attr == x)
+ {
+ *z = a->next;
+ while (*z)
+ z = &(*z)->next;
+ *z = a;
+ a->next = NULL;
+ break;
+ }
+ z = &a->next;
+ }
}