self->link = (struct node *) 0;
}
-static void node_dbg(const struct node *self, const struct node *root, size_t indent, const uint8_t *str, size_t len)
+void node_dbg(const struct node *self, const struct node *root, size_t indent, const uint8_t *str, size_t len)
{
const struct node *node;
size_t i;
{
struct node *node;
- printf("calling node_edge_inv\n");
-
if (record_seen) {
for (node = self->son; node; node = node->brother) {
if (!seen[str[node->from]]) {
break;
}
--*code;
- printf("decrementing code to %d\n", *code);
}
}
if (!node) {
size_t n;
bool present;
bool seen[256];
+ uint8_t code;
nodes = (struct node *) malloc(sizeof(struct node) * stree_max_size(len));
if (!nodes) return -1;
prev = (struct node *) 0;
++rem;
memset(seen, 0, sizeof seen);
- out[i] = 0;
- active_edge = node_edge(active_node, in[i-active_len], in, &brother, seen, out + i, active_len == 0);
+ code = 0;
+ active_edge = node_edge(active_node, in[i-active_len], in, &brother, seen, &code, active_len == 0);
do {
present = active_edge && in[active_edge->from+active_len] == in[i];
if (present) {
new_leaf = nodes + n;
++n, --rem;
} else {
- printf("seen? %d\n", seen[in[active_edge->from+active_len]]);
if (!seen[in[active_edge->from+active_len]]) {
seen[in[active_edge->from+active_len]] = true;
- ++out[i];
+ ++code;
}
node_init(nodes + n + 1, i);
node_split_son(active_node, active_edge, brother, nodes + n, nodes + n + 1, active_len);
new_leaf = (struct node *) 0;
}
active_node = active_node->link ? active_node->link : (active_len = rem - 1, root);
- active_edge = node_edge(active_node, in[i-active_len], in, &brother, seen, out + i, active_len == 0 && active_node->son != new_leaf);
+ if (active_len == 0 && active_node->son == new_leaf)
+ brother = active_edge = (struct node *) 0;
+ else
+ active_edge = node_edge(active_node, in[i-active_len], in, &brother, seen, &code, active_len == 0 && active_node->son != new_leaf);
}
while (active_edge && active_edge->from + active_len >= active_edge->to) {
active_node = active_edge;
active_len -= active_node->to - active_node->from;
- active_edge = node_edge(active_node, in[i-active_len], in, &brother, seen, out + i, active_len == 0 && !present);
+ if (active_len == 0 && present)
+ brother = active_edge = (struct node *) 0;
+ else
+ active_edge = node_edge(active_node, in[i-active_len], in, &brother, seen, &code, active_len == 0 && !present);
}
} while (rem > 0 && !present);
if (!present)
for (int a = 0; a < in[i]; ++a)
if (!seen[a])
- ++out[i];
+ ++code;
+ out[i] = code;
}
#ifndef NDEBUG
++rem;
memset(seen, 0, sizeof seen);
code = in[i];
- printf("i = %d - decoding %d\n", (int) i, code);
active_edge = node_edge_inv(active_node, out[i-active_len], out, &brother, seen, &code, active_len == 0);
do {
- printf("loop iteration: active_node = %d, active_edge = %d, active_len = %d\n", (int) (active_node - root), (int) (active_edge - root), (int) active_len);
- present = active_edge && code == 0;
+ present = active_edge && code == 0 && (active_len == 0 || !seen[out[active_edge->from+active_len]]);
if (present) {
out[i] = out[active_edge->from+active_len];
- printf("setting out[%d] = %c\n", (int) i, (char) out[active_edge->from+active_len]);
++active_len;
} else {
if (!active_edge) {
new_leaf = nodes + n;
++n, --rem;
} else {
- printf("seen? %d\n", seen[out[active_edge->from+active_len]]);
if (!seen[out[active_edge->from+active_len]]) {
seen[out[active_edge->from+active_len]] = true;
--code;
new_leaf = (struct node *) 0;
}
active_node = active_node->link ? active_node->link : (active_len = rem - 1, root);
- active_edge = node_edge_inv(active_node, out[i-active_len], out, &brother, seen, &code, active_len == 0 && active_node->son != new_leaf);
- printf("!setting active_edge = %d, active_len = %d\n", (int) (active_edge - root), (int) active_len);
+ if (active_len == 0 && active_node->son == new_leaf)
+ brother = active_edge = (struct node *) 0;
+ else
+ active_edge = node_edge_inv(active_node, out[i-active_len], out, &brother, seen, &code, active_len == 0);
}
while (active_edge && active_edge->from + active_len >= active_edge->to) {
active_node = active_edge;
active_len -= active_node->to - active_node->from;
- active_edge = node_edge_inv(active_node, out[i-active_len], out, &brother, seen, &code, active_len == 0 && !present);
+ if (active_len == 0 && present)
+ brother = active_edge = (struct node *) 0;
+ else
+ active_edge = node_edge_inv(active_node, out[i-active_len], out, &brother, seen, &code, active_len == 0);
}
} while (rem > 0 && !present);
if (!present)
return -1;
}
- node_dbg(root, root, 0, out, len);
+ //node_dbg(root, root, 0, out, len);
#endif
free(nodes);
return TEST_SUCCESS;
}
+static enum test_result test_stree_minimal_6(void)
+{
+ const uint8_t *in = (const uint8_t *) "ccdebdaabddaeeadeeccacbecdddaaddcccdebbddaeccbdaeebbdcaaeaadadda";
+ uint8_t enc[64];
+ uint8_t dec[64];
+ size_t aux1[64];
+ size_t aux2[64];
+ size_t i;
+
+ ASSERT_EQ(0, stree_encode(44, in, enc, aux1));
+ ASSERT_EQ(0, stree_decode(44, enc, dec, aux2));
+
+ for (i = 0; i < 44; ++i) {
+ ASSERT_EQ(in[i], dec[i]);
+ ASSERT_EQ(aux1[i], aux2[i]);
+ }
+
+ return TEST_SUCCESS;
+}
+
static enum test_result test_stree_repeating(void)
{
const uint8_t *in = (const uint8_t *) "abcabcabcabcabcdabcabcabcabcabcdababababab";
ASSERT_EQ(0, stree_encode(65536, in, enc, aux1));
ASSERT_EQ(0, stree_decode(65536, enc, dec, aux2));
+ for (i = 0; i < 65536; ++i) {
+ ASSERT_EQ(in[i], dec[i]);
+ ASSERT_EQ(aux1[i], aux2[i]);
+ }
+
return TEST_SUCCESS;
}
static enum test_result test_stree_roundtrip_so_example(void)
{
- int i;
const uint8_t *in = (const uint8_t *) "abcabxabcd";
uint8_t enc[10];
uint8_t dec[10];
ASSERT_EQ(0, stree_encode(10, in, enc, aux1));
ASSERT_EQ(0, stree_decode(10, enc, dec, aux2));
- for (i = 0; i < 10; ++i)
- printf("%d ", enc[i]);
- printf("\n");
-
ASSERT_EQ(in[0], dec[0]);
ASSERT_EQ(in[1], dec[1]);
ASSERT_EQ(in[2], dec[2]);
RUN_TEST(test_stree_minimal_3);
RUN_TEST(test_stree_minimal_4);
RUN_TEST(test_stree_minimal_5);
+ RUN_TEST(test_stree_minimal_6);
RUN_TEST(test_stree_repeating);
RUN_TEST(test_stree_long);
RUN_TEST(test_stree_very_long);