summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Sanders <vince@kyllikki.org>2018-04-22 13:47:54 +0100
committerVincent Sanders <vince@kyllikki.org>2018-04-22 14:03:18 +0100
commit43582c50552021bbced0ea11f0ff6c4b2b618529 (patch)
tree0a01a92961c354369fa23fd28476aefc45c23dff
parentd196ea7795ada760dbc243fe640769eb9bc65dff (diff)
downloadnetsurf-43582c50552021bbced0ea11f0ff6c4b2b618529.tar.gz
netsurf-43582c50552021bbced0ea11f0ff6c4b2b618529.tar.bz2
allow hash table add inline to be uncompressed
-rw-r--r--utils/hashtable.c294
1 files changed, 175 insertions, 119 deletions
diff --git a/utils/hashtable.c b/utils/hashtable.c
index 0de6f83d2..4935d6b3f 100644
--- a/utils/hashtable.c
+++ b/utils/hashtable.c
@@ -81,6 +81,175 @@ static inline unsigned int hash_string_fnv(const char *datum, unsigned int *len)
}
+
+/**
+ * process a line of input.
+ *
+ * \param hash The hash table to add the line to
+ * \param ln The line to process
+ * \param lnlen The length of \ln
+ * \return NSERROR_OK on success else NSERROR_INVALID
+ */
+static nserror
+process_line(struct hash_table *hash, uint8_t *ln, int lnlen)
+{
+ uint8_t *key;
+ uint8_t *value;
+ uint8_t *colon;
+
+ key = ln; /* set key to start of line */
+ value = ln + lnlen; /* set value to end of line */
+
+ /* skip leading whitespace */
+ while ((key < value) &&
+ ((*key == ' ') || (*key == '\t'))) {
+ key++;
+ }
+
+ /* empty or comment lines */
+ if ((*key == 0) || (*key == '#')) {
+ return NSERROR_OK;
+ }
+
+ /* find first colon as key/value separator */
+ for (colon = key; colon < value; colon++) {
+ if (*colon == ':') {
+ break;
+ }
+ }
+ if (colon == value) {
+ /* no colon found */
+ return NSERROR_INVALID;
+ }
+
+ *colon = 0; /* terminate key */
+ value = colon + 1;
+
+ if (hash_add(hash, (char *)key, (char *)value) == false) {
+ NSLOG(netsurf, INFO,
+ "Unable to add %s:%s to hash table", ln, value);
+ return NSERROR_INVALID;
+ }
+ return NSERROR_OK;
+}
+
+
+/**
+ * adds key/value pairs to a hash from a memory area
+ */
+static nserror
+hash_add_inline_plain(struct hash_table *ht, const uint8_t *data, size_t size)
+{
+ uint8_t s[LINE_BUFFER_SIZE]; /* line buffer */
+ unsigned int slen = 0;
+ nserror res = NSERROR_OK;
+
+ while (size > 0) {
+ s[slen] = *data;
+
+ if (s[slen] == '\n') {
+ s[slen] = 0; /* replace newline with null termination */
+ res = process_line(ht, s, slen);
+ slen = 0;
+ if (res != NSERROR_OK) {
+ break;
+ }
+ } else {
+ slen++;
+ if (slen > sizeof s) {
+ NSLOG(netsurf, INFO, "Overlength line\n");
+ slen = 0;
+ }
+ }
+
+ size--;
+ data++;
+ }
+ if (slen > 0) {
+ s[slen] = 0;
+ res = process_line(ht, s, slen);
+ }
+
+ return res;
+}
+
+/**
+ * adds key/value pairs to a hash from a compressed memory area
+ */
+static nserror
+hash_add_inline_gzip(struct hash_table *ht, const uint8_t *data, size_t size)
+{
+ nserror res;
+ int ret; /* zlib return value */
+ z_stream strm;
+ uint8_t s[LINE_BUFFER_SIZE]; /* line buffer */
+ size_t used = 0; /* number of bytes in buffer in use */
+ uint8_t *nl;
+
+ strm.zalloc = Z_NULL;
+ strm.zfree = Z_NULL;
+ strm.opaque = Z_NULL;
+
+ strm.next_in = (uint8_t *)data;
+ strm.avail_in = size;
+
+ ret = inflateInit2(&strm, 32 + MAX_WBITS);
+ if (ret != Z_OK) {
+ NSLOG(netsurf, INFO, "inflateInit returned %d", ret);
+ return NSERROR_INVALID;
+ }
+
+ do {
+ strm.next_out = s + used;
+ strm.avail_out = sizeof(s) - used;
+
+ ret = inflate(&strm, Z_NO_FLUSH);
+ if ((ret != Z_OK) && (ret != Z_STREAM_END)) {
+ break;
+ }
+
+ used = sizeof(s) - strm.avail_out;
+ while (used > 0) {
+ /* find nl */
+ for (nl = &s[0]; nl < &s[used]; nl++) {
+ if (*nl == '\n') {
+ break;
+ }
+ }
+ if (nl == &s[used]) {
+ /* no nl found */
+ break;
+ }
+ /* found newline */
+ *nl = 0; /* null terminate line */
+ res = process_line(ht, &s[0], nl - &s[0]);
+ if (res != NSERROR_OK) {
+ inflateEnd(&strm);
+ return res;
+ }
+
+ /* move data down */
+ memmove(&s[0], nl + 1, used - ((nl + 1) - &s[0]) );
+ used -= ((nl +1) - &s[0]);
+ }
+ if (used == sizeof(s)) {
+ /* entire buffer used and no newline */
+ NSLOG(netsurf, INFO, "Overlength line");
+ used = 0;
+ }
+ } while (ret != Z_STREAM_END);
+
+ inflateEnd(&strm);
+
+ if (ret != Z_STREAM_END) {
+ NSLOG(netsurf, INFO, "inflate returned %d", ret);
+ return NSERROR_INVALID;
+ }
+ return NSERROR_OK;
+
+}
+
+
/* exported interface documented in utils/hashtable.h */
struct hash_table *hash_create(unsigned int chains)
{
@@ -187,57 +356,6 @@ const char *hash_get(struct hash_table *ht, const char *key)
}
-/**
- * process a line of input.
- *
- * \param hash The hash table to add the line to
- * \param ln The line to process
- * \param lnlen The length of \ln
- * \return NSERROR_OK on success else NSERROR_INVALID
- */
-static nserror
-process_line(struct hash_table *hash, uint8_t *ln, int lnlen)
-{
- uint8_t *key;
- uint8_t *value;
- uint8_t *colon;
-
- key = ln; /* set key to start of line */
- value = ln + lnlen; /* set value to end of line */
-
- /* skip leading whitespace */
- while ((key < value) &&
- ((*key == ' ') || (*key == '\t'))) {
- key++;
- }
-
- /* empty or comment lines */
- if ((*key == 0) || (*key == '#')) {
- return NSERROR_OK;
- }
-
- /* find first colon as key/value separator */
- for (colon = key; colon < value; colon++) {
- if (*colon == ':') {
- break;
- }
- }
- if (colon == value) {
- /* no colon found */
- return NSERROR_INVALID;
- }
-
- *colon = 0; /* terminate key */
- value = colon + 1;
-
- if (hash_add(hash, (char *)key, (char *)value) == false) {
- NSLOG(netsurf, INFO,
- "Unable to add %s:%s to hash table", ln, value);
- return NSERROR_INVALID;
- }
- return NSERROR_OK;
-}
-
/* exported interface documented in utils/hashtable.h */
nserror hash_add_file(struct hash_table *ht, const char *path)
@@ -262,7 +380,7 @@ nserror hash_add_file(struct hash_table *ht, const char *path)
while (gzgets(fp, s, sizeof s)) {
int slen = strlen(s);
s[--slen] = 0; /* remove \n at end */
-
+
res = process_line(ht, (uint8_t *)s, slen);
if (res != NSERROR_OK) {
break;
@@ -274,75 +392,13 @@ nserror hash_add_file(struct hash_table *ht, const char *path)
return res;
}
+
/* exported interface documented in utils/hashtable.h */
nserror hash_add_inline(struct hash_table *ht, const uint8_t *data, size_t size)
{
- nserror res;
- int ret; /* zlib return value */
- z_stream strm;
- uint8_t s[LINE_BUFFER_SIZE]; /* line buffer */
- size_t used = 0; /* number of bytes in buffer in use */
- uint8_t *nl;
-
- strm.zalloc = Z_NULL;
- strm.zfree = Z_NULL;
- strm.opaque = Z_NULL;
-
- strm.next_in = (uint8_t *)data;
- strm.avail_in = size;
-
- ret = inflateInit2(&strm, 32 + MAX_WBITS);
- if (ret != Z_OK) {
- NSLOG(netsurf, INFO, "inflateInit returned %d", ret);
- return NSERROR_INVALID;
- }
-
- do {
- strm.next_out = s + used;
- strm.avail_out = sizeof(s) - used;
-
- ret = inflate(&strm, Z_NO_FLUSH);
- if ((ret != Z_OK) && (ret != Z_STREAM_END)) {
- break;
- }
-
- used = sizeof(s) - strm.avail_out;
- while (used > 0) {
- /* find nl */
- for (nl = &s[0]; nl < &s[used]; nl++) {
- if (*nl == '\n') {
- break;
- }
- }
- if (nl == &s[used]) {
- /* no nl found */
- break;
- }
- /* found newline */
- *nl = 0; /* null terminate line */
- res = process_line(ht, &s[0], nl - &s[0]);
- if (res != NSERROR_OK) {
- inflateEnd(&strm);
- return res;
- }
-
- /* move data down */
- memmove(&s[0], nl + 1, used - ((nl + 1) - &s[0]) );
- used -= ((nl +1) - &s[0]);
- }
- if (used == sizeof(s)) {
- /* entire buffer used and no newline */
- NSLOG(netsurf, INFO, "Overlength line");
- used = 0;
- }
- } while (ret != Z_STREAM_END);
-
- inflateEnd(&strm);
-
- if (ret != Z_STREAM_END) {
- NSLOG(netsurf, INFO, "inflate returned %d", ret);
- return NSERROR_INVALID;
+ if ((data[0]==0x1f) && (data[1] == 0x8b)) {
+ /* gzip header detected */
+ return hash_add_inline_gzip(ht, data, size);
}
- return NSERROR_OK;
-
+ return hash_add_inline_plain(ht, data, size);
}