2010-11-20 12:29:18 +02:00
|
|
|
/*
|
|
|
|
* id.c - Registry of unique and alphabetically sorted identifiers
|
|
|
|
*
|
|
|
|
* Written 2010 by Werner Almesberger
|
|
|
|
* Copyright 2010 Werner Almesberger
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
2010-11-19 19:00:15 +02:00
|
|
|
#include <string.h>
|
2010-11-22 02:14:04 +02:00
|
|
|
#include <ctype.h>
|
2010-11-19 19:00:15 +02:00
|
|
|
|
2010-11-20 12:29:18 +02:00
|
|
|
#include "jrb.h"
|
|
|
|
|
2010-11-19 19:00:15 +02:00
|
|
|
#include "util.h"
|
|
|
|
#include "id.h"
|
|
|
|
|
|
|
|
|
|
|
|
static struct id *free_id = NULL;
|
|
|
|
|
|
|
|
|
2010-11-22 02:14:04 +02:00
|
|
|
/* ----- ID comparison (regular string compare) ---------------------------- */
|
|
|
|
|
|
|
|
|
2010-11-20 02:48:48 +02:00
|
|
|
static int do_comp_id(const struct id *a, const struct id *b)
|
2010-11-19 19:00:15 +02:00
|
|
|
{
|
|
|
|
int len = a->len < b->len ? a->len : b->len;
|
|
|
|
int cmp;
|
|
|
|
|
|
|
|
cmp = memcmp(a->s, b->s, len);
|
|
|
|
if (cmp)
|
|
|
|
return cmp;
|
|
|
|
return a->len < b->len ? -1 : a->len > b->len;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-11-20 02:48:48 +02:00
|
|
|
int comp_id(const void *a, const void *b)
|
|
|
|
{
|
|
|
|
return do_comp_id(a, b);
|
|
|
|
}
|
|
|
|
|
2010-11-22 02:14:04 +02:00
|
|
|
|
|
|
|
/* ----- Version comparison ------------------------------------------------ */
|
|
|
|
|
|
|
|
|
|
|
|
static int epoch(const char **s, const struct id *id)
|
|
|
|
{
|
|
|
|
const char *end = id->s+id->len;
|
|
|
|
int n = 0;
|
|
|
|
|
|
|
|
while (*s != end && isdigit(**s)) {
|
|
|
|
n = 10*n+**s-'0';
|
|
|
|
(*s)++;
|
|
|
|
}
|
|
|
|
if (*s == id->s || (*s != end && **s == ':'))
|
|
|
|
return n;
|
|
|
|
*s = id->s;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int comp_versions(const struct id *va, const struct id *vb)
|
|
|
|
{
|
|
|
|
int epoch_a = 0, epoch_b = 0;
|
|
|
|
const char *a = va->s;
|
|
|
|
const char *b = vb->s;
|
|
|
|
const char *ea = a+va->len;
|
|
|
|
const char *eb = b+vb->len;
|
|
|
|
|
|
|
|
epoch_a = epoch(&a, va);
|
|
|
|
epoch_b = epoch(&b, vb);
|
|
|
|
if (epoch_a != epoch_b)
|
|
|
|
return epoch_a-epoch_b;
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
if (a == ea || b == eb)
|
|
|
|
return (a != ea)-(b != eb);
|
|
|
|
if (isdigit(*a) && isdigit(*b)) {
|
|
|
|
int na = 0, nb = 0;
|
|
|
|
|
|
|
|
while (a != ea && isdigit(*a)) {
|
|
|
|
na = na*10+*a-'0';
|
|
|
|
a++;
|
|
|
|
}
|
|
|
|
while (b != eb && isdigit(*b)) {
|
|
|
|
nb = nb*10+*b-'0';
|
|
|
|
b++;
|
|
|
|
}
|
|
|
|
if (na == nb)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
return na-nb;
|
|
|
|
}
|
|
|
|
if (*a > *b)
|
|
|
|
return 1;
|
|
|
|
if (*a < *b)
|
|
|
|
return 1;
|
|
|
|
a++;
|
|
|
|
b++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* ----- Tree maintenance -------------------------------------------------- */
|
|
|
|
|
|
|
|
|
2010-11-20 02:48:48 +02:00
|
|
|
struct tree *make_tree(int (*comp)(const void *a, const void *b))
|
2010-11-19 19:00:15 +02:00
|
|
|
{
|
|
|
|
struct tree *tree;
|
|
|
|
|
|
|
|
tree = alloc_type(struct tree);
|
|
|
|
tree->comp = comp;
|
2010-11-20 02:17:08 +02:00
|
|
|
tree->root = make_jrb();
|
2010-11-19 19:00:15 +02:00
|
|
|
return tree;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-11-21 08:07:48 +02:00
|
|
|
struct jrb *make_id(struct tree *tree, const char *s, size_t len)
|
2010-11-19 19:00:15 +02:00
|
|
|
{
|
|
|
|
struct id *id;
|
|
|
|
|
|
|
|
if (!free_id)
|
|
|
|
free_id = alloc_type(struct id);
|
|
|
|
id = free_id;
|
|
|
|
id->s = s;
|
|
|
|
id->len = len;
|
2010-11-20 03:20:15 +02:00
|
|
|
id->jrb = jrb_find_or_insert(tree->root, id, NULL, tree->comp);
|
2010-11-21 08:07:48 +02:00
|
|
|
if (id->jrb->key == id)
|
|
|
|
free_id = NULL;
|
|
|
|
return id->jrb;
|
2010-11-19 19:00:15 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-11-20 18:11:41 +02:00
|
|
|
const struct jrb *find_id(const struct tree *tree, const char *s, size_t len)
|
2010-11-19 19:00:15 +02:00
|
|
|
{
|
|
|
|
struct id id = {
|
|
|
|
.s = s,
|
|
|
|
.len = len
|
|
|
|
};
|
|
|
|
|
2010-11-20 18:11:41 +02:00
|
|
|
return jrb_find(tree->root, &id, tree->comp);
|
2010-11-19 19:00:15 +02:00
|
|
|
}
|