Merge branch 'release/1.1.0'

Conflicts:
	evhtp.c
diff --git a/ChangeLog b/ChangeLog
index 70a991a..79fd9f2 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,8 @@
+v1.1.0
+ o Add ability for rules to be ordered. (ad8c468 Mark Ellzey)
+ o Cleanup the old rule code. (fbfda73 Mark Ellzey)
+ o Fixed missing variable in callback_find (4eb5e87 Mark Ellzey)
+
 v1.0.1
  o Fixes to make coverity happy. (6776d85 Mark Ellzey)
  o Add support for empty header values. (7ec160f Mark Ellzey)
diff --git a/evhtp.c b/evhtp.c
index 0704e31..66a149c 100644
--- a/evhtp.c
+++ b/evhtp.c
@@ -494,41 +494,6 @@
 }
 
 /**
- * @brief attempts to find a callback via hashing the path
- *
- * @param callbacks a evhtp_callbacks_t * structure
- * @param path a null terminated string to be hashed and searched
- *
- * @return evhtp_callback_t * if found, NULL if not found.
- */
-static evhtp_callback_t *
-_evhtp_callback_hash_find(evhtp_callbacks_t * callbacks, const char * path) {
-    evhtp_callback_t * callback;
-    unsigned int       hash;
-    unsigned int       shash;
-
-    if (path == NULL) {
-        return NULL;
-    }
-
-    hash     = _evhtp_quick_hash(path);
-    shash    = (hash & (callbacks->buckets - 1));
-    callback = callbacks->callbacks[shash];
-
-    while (callback != NULL) {
-        if (callback->hash == hash &&
-            callback->type == evhtp_callback_type_hash &&
-            strcmp(callback->val.path, path) == 0) {
-            return callback;
-        }
-
-        callback = callback->next;
-    }
-
-    return NULL;
-}
-
-/**
  * @brief glob/wildcard type pattern matching.
  *
  * Note: This code was derived from redis's (v2.6) stringmatchlen() function.
@@ -599,126 +564,53 @@
     return 0;
 } /* _evhtp_glob_match */
 
-/**
- * @brief iterate through a list of glob/wildcard defined callbacks.
- *
- * @param callbacks
- * @param path
- *
- * @return
- */
 static evhtp_callback_t *
-_evhtp_callback_glob_find(evhtp_callbacks_t * callbacks, const char * path) {
-    evhtp_callback_t * callback;
-
-    if (!callbacks || !path) {
-        return NULL;
-    }
-
-    callback = callbacks->glob_callbacks;
-
-    while (callback != NULL) {
-        if (callback->type == evhtp_callback_type_glob) {
-            if (_evhtp_glob_match(callback->val.glob, path) == 1) {
-                return callback;
-            }
-        }
-
-        callback = callback->next;
-    }
-
-    return NULL;
-}
-
-/**
- * @brief iterate through a tailq of callback hooks defined as a regex until a
- *        match is found.
- *
- * @param callbacks a evhtp_callbacks_t structure
- * @param path a string containing a path to be matched against
- * @param soff a pointer to an integer which will be filled with the start
- *             offset in the string if matched.
- * @param eoff a pointer to an integer which will be filled with the end
- *             offset in the string if matched
- *
- * @return an evhtp_callback_t function on success, otherwise NULL
- */
-#ifndef EVHTP_DISABLE_REGEX
-static evhtp_callback_t *
-_evhtp_callback_regex_find(evhtp_callbacks_t * callbacks, const char * path,
-                           unsigned int * soff, unsigned int * eoff) {
-    evhtp_callback_t * callback = callbacks->regex_callbacks;
-
-    if (path == NULL) {
-        return NULL;
-    }
-
-    while (callback != NULL) {
-        regmatch_t pmatch[28];
-
-        if (callback->type == evhtp_callback_type_regex) {
-            if (regexec(callback->val.regex, path, callback->val.regex->re_nsub + 1, pmatch, 0) == 0) {
-                *soff = (unsigned int)pmatch[callback->val.regex->re_nsub].rm_so;
-                *eoff = (unsigned int)pmatch[callback->val.regex->re_nsub].rm_eo;
-
-                return callback;
-            }
-        }
-
-        callback = callback->next;
-    }
-
-    return NULL;
-}
-
-#endif
-
-/**
- * @brief A wrapper around hash, glob, and regex hook lookups
- *        Search is done in this order:
- *          hash
- *          glob
- *          regex
- *
- * @param callbacks
- * @param path
- * @param start_offset
- * @param end_offset
- *
- * @return evhtp_callback_t on success, otherwise NULL
- */
-static evhtp_callback_t *
-_evhtp_callback_find(evhtp_callbacks_t * callbacks,
+_evhtp_callback_find(evhtp_callbacks_t * cbs,
                      const char        * path,
                      unsigned int      * start_offset,
                      unsigned int      * end_offset) {
+#ifndef EVHTP_DISABLE_REGEX
+    regmatch_t         pmatch[28];
+#endif
     evhtp_callback_t * callback;
 
-    if (callbacks == NULL) {
+    if (cbs == NULL) {
         return NULL;
     }
 
-    if ((callback = _evhtp_callback_hash_find(callbacks, path)) != NULL) {
-        *start_offset = 0;
-        *end_offset   = (unsigned int)strlen(path);
-        return callback;
-    }
-
-    if ((callback = _evhtp_callback_glob_find(callbacks, path)) != NULL) {
-        *start_offset = 0;
-        *end_offset   = (unsigned int)strlen(path);
-        return callback;
-    }
-
+    TAILQ_FOREACH(callback, cbs, next) {
+        switch (callback->type) {
+            case evhtp_callback_type_hash:
+                if (strcmp(callback->val.path, path) == 0) {
+                    *start_offset = 0;
+                    *end_offset   = (unsigned int)strlen(path);
+                    return callback;
+                }
+                break;
 #ifndef EVHTP_DISABLE_REGEX
-    if ((callback = _evhtp_callback_regex_find(callbacks, path,
-                                               start_offset, end_offset)) != NULL) {
-        return callback;
-    }
+            case evhtp_callback_type_regex:
+                if (regexec(callback->val.regex, path, callback->val.regex->re_nsub + 1, pmatch, 0) == 0) {
+                    *start_offset = pmatch[callback->val.regex->re_nsub].rm_so;
+                    *end_offset   = pmatch[callback->val.regex->re_nsub].rm_eo;
+
+                    return callback;
+                }
+
+                break;
 #endif
+            case evhtp_callback_type_glob:
+                if (_evhtp_glob_match(callback->val.glob, path) == 1) {
+                    *start_offset = 0;
+                    *end_offset   = (unsigned int)strlen(path);
+                    return callback;
+                }
+            default:
+                break;
+        } /* switch */
+    }
 
     return NULL;
-}
+}         /* _evhtp_callback_find */
 
 /**
  * @brief Creates a new evhtp_request_t
@@ -2632,63 +2524,9 @@
     evconnlistener_free(htp->server);
 }
 
-evhtp_callbacks_t *
-evhtp_callbacks_new(unsigned int buckets) {
-    evhtp_callbacks_t * cbs;
-
-    if (!(cbs = calloc(sizeof(evhtp_callbacks_t), 1))) {
-        return NULL;
-    }
-
-    if (!(cbs->callbacks = calloc(sizeof(evhtp_callback_t *), buckets))) {
-        free(cbs);
-        return NULL;
-    }
-
-    cbs->buckets = buckets;
-    cbs->count   = 0;
-
-    return cbs;
-}
-
 void
 evhtp_callbacks_free(evhtp_callbacks_t * callbacks) {
-    evhtp_callback_t * callback;
-    evhtp_callback_t * next;
-    unsigned int       idx;
-
-    if (callbacks == NULL) {
-        return;
-    }
-
-    if (callbacks->callbacks) {
-        for (idx = 0; idx < callbacks->buckets; idx++) {
-            if (callbacks->callbacks[idx] == NULL) {
-                continue;
-            }
-
-            callback = callbacks->callbacks[idx];
-
-            while (callback != NULL) {
-                next     = callback->next;
-                evhtp_callback_free(callback);
-                callback = next;
-            }
-        }
-        free(callbacks->callbacks);
-    }
-
-#ifndef EVHTP_DISABLE_REGEX
-    callback = callbacks->regex_callbacks;
-
-    while (callback != NULL) {
-        next     = callback->next;
-        evhtp_callback_free(callback);
-        callback = next;
-    }
-#endif
-
-    free(callbacks);
+    /* XXX TODO */
 }
 
 evhtp_callback_t *
@@ -2757,32 +2595,7 @@
 
 int
 evhtp_callbacks_add_callback(evhtp_callbacks_t * cbs, evhtp_callback_t * cb) {
-    unsigned int hkey;
-
-    switch (cb->type) {
-        case evhtp_callback_type_hash:
-            hkey = cb->hash & (cbs->buckets - 1);
-
-            if (cbs->callbacks[hkey] == NULL) {
-                cbs->callbacks[hkey] = cb;
-            } else {
-                cb->next = cbs->callbacks[hkey];
-                cbs->callbacks[hkey] = cb;
-            }
-            break;
-#ifndef EVHTP_DISABLE_REGEX
-        case evhtp_callback_type_regex:
-            cb->next = cbs->regex_callbacks;
-            cbs->regex_callbacks = cb;
-            break;
-#endif
-        case evhtp_callback_type_glob:
-            cb->next = cbs->glob_callbacks;
-            cbs->glob_callbacks = cb;
-            break;
-        default:
-            return -1;
-    } /* switch */
+    TAILQ_INSERT_TAIL(cbs, cb, next);
 
     return 0;
 }
@@ -2918,10 +2731,12 @@
     _evhtp_lock(htp);
 
     if (htp->callbacks == NULL) {
-        if (!(htp->callbacks = evhtp_callbacks_new(1024))) {
+        if (!(htp->callbacks = calloc(sizeof(evhtp_callbacks_t), sizeof(char)))) {
             _evhtp_unlock(htp);
             return NULL;
         }
+
+        TAILQ_INIT(htp->callbacks);
     }
 
     if (!(hcb = evhtp_callback_new(path, evhtp_callback_type_hash, cb, arg))) {
@@ -2992,10 +2807,12 @@
     _evhtp_lock(htp);
 
     if (htp->callbacks == NULL) {
-        if (!(htp->callbacks = evhtp_callbacks_new(1024))) {
+        if (!(htp->callbacks = calloc(sizeof(evhtp_callbacks_t), sizeof(char)))) {
             _evhtp_unlock(htp);
             return NULL;
         }
+
+        TAILQ_INIT(htp->callbacks);
     }
 
     if (!(hcb = evhtp_callback_new(pattern, evhtp_callback_type_regex, cb, arg))) {
@@ -3022,10 +2839,12 @@
     _evhtp_lock(htp);
 
     if (htp->callbacks == NULL) {
-        if (!(htp->callbacks = evhtp_callbacks_new(1024))) {
+        if (!(htp->callbacks = calloc(sizeof(evhtp_callbacks_t), sizeof(char)))) {
             _evhtp_unlock(htp);
             return NULL;
         }
+
+        TAILQ_INIT(htp->callbacks);
     }
 
     if (!(hcb = evhtp_callback_new(pattern, evhtp_callback_type_glob, cb, arg))) {
diff --git a/evhtp.h b/evhtp.h
index f242ca4..e826a4a 100644
--- a/evhtp.h
+++ b/evhtp.h
@@ -155,10 +155,10 @@
 typedef evhtp_ssl_sess_t * (*evhtp_ssl_scache_get)(evhtp_connection_t * connection, unsigned char * sid, int sid_len);
 typedef void * (*evhtp_ssl_scache_init)(evhtp_t *);
 
-#define EVHTP_VERSION          "1.0.1"
+#define EVHTP_VERSION          "1.1.0"
 #define EVHTP_VERSION_MAJOR    1
-#define EVHTP_VERSION_MINOR    0
-#define EVHTP_VERSION_PATCH    1
+#define EVHTP_VERSION_MINOR    1
+#define EVHTP_VERSION_PATCH    0
 
 #define evhtp_headers_iterator evhtp_kvs_iterator
 
@@ -276,23 +276,6 @@
 };
 
 /**
- * @brief structure containing all registered evhtp_callbacks_t
- *
- * This structure holds information which correlates either
- * a path string (via a hash) or a regular expression callback.
- *
- */
-struct evhtp_callbacks_s {
-    evhtp_callback_t ** callbacks;      /**< hash of path callbacks */
-#ifndef EVHTP_DISABLE_REGEX
-    evhtp_callback_t * regex_callbacks; /**< list of regex callbacks */
-#endif
-    evhtp_callback_t * glob_callbacks;  /**< list of wildcard callbacks */
-    unsigned int       count;           /**< number of callbacks defined */
-    unsigned int       buckets;         /**< buckets allocated for hash */
-};
-
-/**
  * @brief structure containing a single callback and configuration
  *
  * The definition structure which is used within the evhtp_callbacks_t
@@ -321,9 +304,10 @@
 #endif
     } val;
 
-    evhtp_callback_t * next;
+    TAILQ_ENTRY(evhtp_callback_s) next;
 };
 
+TAILQ_HEAD(evhtp_callbacks_s, evhtp_callback_s);
 
 /**
  * @brief a generic key/value structure
@@ -711,22 +695,6 @@
  */
 void evhtp_send_reply_chunk_end(evhtp_request_t * request);
 
-
-/**
- * @brief creates a new evhtp_callbacks_t structure
- *
- * this structure is used to store all known
- * callbacks for a request.
- *
- * @param buckets the number of buckets to allocate for the
- *        path type hash.
- *
- * @return an evhtp_callbacks_t structure
- */
-evhtp_callbacks_t * evhtp_callbacks_new(unsigned int buckets);
-void                evhtp_callbacks_free(evhtp_callbacks_t * callbacks);
-
-
 /**
  * @brief creates a new evhtp_callback_t structure.
  *