summaryrefslogtreecommitdiff
path: root/src/nspsl.c
diff options
context:
space:
mode:
authorVincent Sanders <vince@kyllikki.org>2016-09-23 23:40:30 +0100
committerVincent Sanders <vince@kyllikki.org>2016-09-23 23:40:30 +0100
commit503c59aed669ebed4b8a38a4594815a730e5b59a (patch)
tree3bf4f5e1c06551a367c43e603242bd21944bec12 /src/nspsl.c
parent3b12cf2109b43ccc825ab2498128a7c6e4c9a5d0 (diff)
downloadlibnspsl-503c59aed669ebed4b8a38a4594815a730e5b59a.tar.gz
libnspsl-503c59aed669ebed4b8a38a4594815a730e5b59a.tar.bz2
huffman encode string table
By huffman encoding the string table we can save 20% (15KB) size
Diffstat (limited to 'src/nspsl.c')
-rw-r--r--src/nspsl.c70
1 files changed, 69 insertions, 1 deletions
diff --git a/src/nspsl.c b/src/nspsl.c
index 83e0f4e..b103bc7 100644
--- a/src/nspsl.c
+++ b/src/nspsl.c
@@ -17,6 +17,74 @@
#define DOMSEP '.'
/**
+ * Test whether a character is upper-case alphabetical.
+ *
+ * \param[in] c Character to test.
+ * \return true iff `c` is upper-case alphabetical, else false.
+ */
+static inline int ascii_is_alpha_upper(char c)
+{
+ return (c >= 'A' && c <= 'Z');
+}
+
+/**
+ * Convert an upper case character to lower case.
+ *
+ * If the given character is not upper case alphabetical, it is returned
+ * unchanged.
+ *
+ * \param[in] c Character to convert.
+ * \return lower case conversion of `c` else `c`.
+ */
+static inline char ascii_to_lower(char c)
+{
+ return (ascii_is_alpha_upper(c)) ? (c + 'a' - 'A') : c;
+}
+
+static int huffcasecmp(unsigned int labelidx, const char *str, unsigned int len)
+{
+ const uint8_t *stabidx; /* string table byte index */
+ unsigned int bitidx; /* amount of current byte used */
+ unsigned int cnt; /* current character being compared */
+ uint8_t curc; /* current label table byte */
+ unsigned int curh; /* current huffman tree node */
+ int res;
+ int term;
+
+ /* get address of byte */
+ stabidx = &stab[labelidx >> 3];
+ /* offset of first bit */
+ bitidx = labelidx & 7;
+
+ curc = *stabidx; stabidx++;
+ curc = curc >> bitidx;
+
+ for (cnt = 0; cnt < len; cnt++) {
+ /* walk huffman code table to get value */
+ curh = 0;
+ term = 0;
+ while (term == 0) {
+ term = htable[curh + (curc & 1)].term;
+ curh = htable[curh + (curc & 1)].value;
+ bitidx++;
+ if (bitidx < 8) {
+ curc = curc >> 1;
+ } else {
+ curc = *stabidx; stabidx++;
+ bitidx = 0;
+ }
+ }
+
+ res = ascii_to_lower(str[cnt]) - curh;
+ if (res != 0) {
+ return res;
+ }
+ }
+
+ return 0;
+}
+
+/**
* match the label element of the domain from a point in the tree
*/
static int matchlabel(int parent, const char *start, int len)
@@ -38,7 +106,7 @@ static int matchlabel(int parent, const char *start, int len)
ridx = cidx;
} else {
if ((pnodes[cidx].label.len == len) &&
- (strncasecmp(&stab[pnodes[cidx].label.idx],
+ (huffcasecmp(pnodes[cidx].label.idx,
start,
len) == 0)) {
/* label match */