/***
This file is part of systemd.
Copyright 2012 Kay Sievers <kay@vrfy.org>
under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2.1 of the License, or
(at your option) any later version.
systemd is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with systemd; If not, see <http://www.gnu.org/licenses/>.
***/
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include "alloc-util.h"
#include "strbuf.h"
/*
* Strbuf stores given strings in a single continuous allocated memory
* area. Identical strings are de-duplicated and return the same offset
* as the first string stored. If the tail of a string already exists
* in the buffer, the tail is returned.
*
* A trie (http://en.wikipedia.org/wiki/Trie) is used to maintain the
* information about the stored strings.
*
* Example of udev rules:
* $ ./udevadm test .
* ...
* rules contain 196608 bytes tokens (16384 * 12 bytes), 39742 bytes strings
* 23939 strings (207859 bytes), 20404 de-duplicated (171653 bytes), 3536 trie nodes used
* ...
*/
if (!str)
return NULL;
goto err;
goto err;
return str;
err:
return NULL;
}
size_t i;
for (i = 0; i < node->children_count; i++)
}
/* clean up trie data, leave only the string buffer */
if (!str)
return;
}
/* clean up everything */
if (!str)
return;
}
const struct strbuf_child_entry *n2) {
}
uint8_t c,
struct strbuf_node *node_child) {
.c = c,
.child = node_child,
};
else
}
node->children_count ++;
}
uint8_t c;
char *buf_new;
return -EINVAL;
/* search string; start from last character to find possibly matching tails */
if (len == 0)
return 0;
c = s[len-1];
/* match against current node */
str->dedup_count++;
return off;
}
/* lookup child node */
search.c = c;
sizeof(struct strbuf_child_entry),
if (!child)
break;
}
/* add new string */
if (!buf_new)
return -ENOMEM;
/* new node */
if (!node_child)
return -ENOMEM;
/* extend array, add new entry, sort for bisection */
if (!child) {
return -ENOMEM;
}
str->nodes_count++;
return off;
}