split logic into node_edge/node_edge_{en,de}code
authorGeoffrey Allott <geoffrey@allott.email>
Wed, 24 Aug 2022 22:10:31 +0000 (23:10 +0100)
committerGeoffrey Allott <geoffrey@allott.email>
Wed, 24 Aug 2022 22:10:31 +0000 (23:10 +0100)
src/stree.c

index 37ec431fe551c90236cd37df6e7adba5c856b8f8..950211708a238eec1657fbd17a5b6510349a1f97 100644 (file)
@@ -88,59 +88,58 @@ static void node_sort_sons(struct node *self)
     }
 }
 
-static struct node *node_edge_inv(struct node *self, uint8_t edge, const uint8_t *str, struct node **brother, bool seen[], uint8_t *code, bool record_seen)
+static struct node *node_edge_decode(struct node *self, const uint8_t *str, struct node **brother, bool seen[], uint8_t *code)
 {
     struct node *node;
 
-    if (record_seen) {
-        node_sort_sons(self);
+    node_sort_sons(self);
 
-        for (*brother = (struct node *) 0, node = self->son; node; *brother = node, node = node->brother) {
-            if (!seen[str[node->from]]) {
-                seen[str[node->from]] = true;
-                if (*code == 0) return node;
-                --*code;
-            }
+    for (*brother = (struct node *) 0, node = self->son; node; *brother = node, node = node->brother) {
+        if (!seen[str[node->from]]) {
+            seen[str[node->from]] = true;
+            if (*code == 0) return node;
+            --*code;
         }
-    } else {
-        for (*brother = (struct node *) 0, node = self->son; node; *brother = node, node = node->brother)
-            if (str[node->from] == edge)
-                return node;
     }
 
     return (struct node *) 0;
 }
 
-static struct node *node_edge(struct node *self, uint8_t edge, const uint8_t *str, struct node **brother, bool seen[], uint8_t *code, bool record_seen)
+static struct node *node_edge_encode(struct node *self, size_t i, const uint8_t *str, struct node **brother, bool seen[], uint8_t *code)
 {
     struct node *node;
 
-    if (record_seen) {
-        node_sort_sons(self);
+    node_sort_sons(self);
 
-        for (*brother = (struct node *) 0, node = self->son; node; *brother = node, node = node->brother) {
-            if (str[node->from] == edge) return node;
-            if (!seen[str[node->from]]) {
-                seen[str[node->from]] = true;
-                ++*code;
-            }
+    for (*brother = (struct node *) 0, node = self->son; node; *brother = node, node = node->brother) {
+        if (str[node->from] == str[i]) return node;
+        if (!seen[str[node->from]]) {
+            seen[str[node->from]] = true;
+            ++*code;
         }
-    } else {
-        for (*brother = (struct node *) 0, node = self->son; node; *brother = node, node = node->brother)
-            if (str[node->from] == edge)
-                return node;
     }
 
     return (struct node *) 0;
 }
 
+static struct node *node_edge(struct node *self, size_t i, const uint8_t *str, struct node **brother)
+{
+    struct node *node;
+
+    for (*brother = (struct node *) 0, node = self->son; node; *brother = node, node = node->brother)
+        if (str[node->from] == str[i])
+            return node;
+
+    return (struct node *) 0;
+}
+
 static bool node_validate_suffix(struct node *self, size_t len, const uint8_t *str, size_t i)
 {
     struct node *node, *brother;
     size_t j;
 
     if (len == 0) return true;
-    node = node_edge(self, str[i], str, &brother, (bool *) 0, (uint8_t *) 0, false);
+    node = node_edge(self, i, str, &brother);
     if (!node) return false;
     for (j = node->from; j < node->to && len > 0; --len, ++j, ++i) {
         if (str[j] != str[i]) return false;
@@ -203,7 +202,10 @@ int stree_encode(size_t len, const uint8_t *in, uint8_t *out, size_t *aux)
         ++rem;
         memset(seen, 0, sizeof seen);
         code = 0;
-        active_edge = node_edge(active_node, in[i-active_len], in, &brother, seen, &code, active_len == 0);
+        if (active_len == 0)
+            active_edge = node_edge_encode(active_node, i, in, &brother, seen, &code);
+        else
+            active_edge = node_edge(active_node, i - active_len, in, &brother);
         do {
             present = active_edge && in[active_edge->from+active_len] == in[i];
             if (present) {
@@ -227,16 +229,20 @@ int stree_encode(size_t len, const uint8_t *in, uint8_t *out, size_t *aux)
                 active_node = active_node->link ? active_node->link : (active_len = rem - 1, root);
                 if (active_len == 0 && active_node->son == nodes + n - 1)
                     brother = active_edge = (struct node *) 0;
+                else if (active_len == 0)
+                    active_edge = node_edge_encode(active_node, i, in, &brother, seen, &code);
                 else
-                    active_edge = node_edge(active_node, in[i-active_len], in, &brother, seen, &code, active_len == 0);
+                    active_edge = node_edge(active_node, i - active_len, in, &brother);
             }
             while (active_edge && active_edge->from + active_len >= active_edge->to) {
                 active_node = active_edge;
                 active_len -= active_node->to - active_node->from;
                 if (active_len == 0 && present)
                     brother = active_edge = (struct node *) 0;
+                else if (active_len == 0)
+                    active_edge = node_edge_encode(active_node, i, in, &brother, seen, &code);
                 else
-                    active_edge = node_edge(active_node, in[i-active_len], in, &brother, seen, &code, active_len == 0 && !present);
+                    active_edge = node_edge(active_node, i - active_len, in, &brother);
             }
         } while (rem > 0 && !present);
         if (!present)
@@ -289,7 +295,10 @@ int stree_decode(size_t len, const uint8_t *in, uint8_t *out, size_t *aux)
         memset(seen, 0, sizeof seen);
         code = in[i];
 
-        active_edge = node_edge_inv(active_node, out[i-active_len], out, &brother, seen, &code, active_len == 0);
+        if (active_len == 0)
+            active_edge = node_edge_decode(active_node, out, &brother, seen, &code);
+        else
+            active_edge = node_edge(active_node, i - active_len, out, &brother);
         do {
             present = active_edge && code == 0 && (active_len == 0 || !seen[out[active_edge->from+active_len]]);
             if (present) {
@@ -314,16 +323,20 @@ int stree_decode(size_t len, const uint8_t *in, uint8_t *out, size_t *aux)
                 active_node = active_node->link ? active_node->link : (active_len = rem - 1, root);
                 if (active_len == 0 && active_node->son == nodes + n - 1)
                     brother = active_edge = (struct node *) 0;
+                else if (active_len == 0)
+                    active_edge = node_edge_decode(active_node, out, &brother, seen, &code);
                 else
-                    active_edge = node_edge_inv(active_node, out[i-active_len], out, &brother, seen, &code, active_len == 0);
+                    active_edge = node_edge(active_node, i - active_len, out, &brother);
             }
             while (active_edge && active_edge->from + active_len >= active_edge->to) {
                 active_node = active_edge;
                 active_len -= active_node->to - active_node->from;
                 if (active_len == 0 && present)
                     brother = active_edge = (struct node *) 0;
+                else if (active_len == 0)
+                    active_edge = node_edge_decode(active_node, out, &brother, seen, &code);
                 else
-                    active_edge = node_edge_inv(active_node, out[i-active_len], out, &brother, seen, &code, active_len == 0);
+                    active_edge = node_edge(active_node, i - active_len, out, &brother);
             }
         } while (rem > 0 && !present);
         if (!present)