/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */


#include "parse_tree.h"
#include <qpid/dispatch/log.h>
#include <qpid/dispatch/alloc.h>
#include <qpid/dispatch/hash.h>

#include <stdio.h>
#include <inttypes.h>


// token parsing
// parse a string of tokens separated by a boundary character.
//
// The format of a pattern string is a series of tokens. A token can contain
// any characters but those reserved for wildcards or the boundary character.
//
// TODO(kgiusti): really should create a token parsing qd_iterator_t view.
// Then all this token/token_iterator stuff can be removed...
//
typedef struct token {
    const char *begin;
    const char *end;
} token_t;
#define TOKEN_LEN(t) ((t).end - (t).begin)

// for iterating over a string of tokens:
typedef struct token_iterator {
    const char *separators;
    const char *terminator;  // end of entire string
    token_t token;           // token at head of string
    char match_1;            // match any 1 token
    char match_glob;         // match 0 or more tokens
} token_iterator_t;


static void token_iterator_init(token_iterator_t *t,
                                qd_parse_tree_type_t type,
                                const char *str)
{
    switch (type) {
    default:  // See DISPATCH-1567: shuts up some bogus compiler warnings
        assert(false);
        // fall through
    case QD_PARSE_TREE_ADDRESS:
        t->separators = "./";   // accept either for backward compatibility
        t->match_1 = '*';
        t->match_glob = '#';
        break;
    case QD_PARSE_TREE_AMQP_0_10:
        t->separators = ".";
        t->match_1 = '*';
        t->match_glob = '#';
        break;
    case QD_PARSE_TREE_MQTT:
        t->separators = "/";
        t->match_1 = '+';
        t->match_glob = '#';
        break;
    }

    while (*str && strchr(t->separators, *str))
        str++;  // skip any leading separators
    const char *tend = strpbrk(str, t->separators);
    t->terminator = str + strlen(str);
    t->token.begin = str;
    t->token.end = (tend) ? tend : t->terminator;
}


static void token_iterator_next(token_iterator_t *t)
{
    if (t->token.end == t->terminator) {
        t->token.begin = t->terminator;
    } else {
        const char *tend;
        t->token.begin = t->token.end + 1;
        tend = strpbrk(t->token.begin, t->separators);
        t->token.end = (tend) ? tend : t->terminator;
    }
}


const char address_token_sep[] = "./";
const char *qd_parse_address_token_sep()
{
    return address_token_sep;
}

static bool token_iterator_done(const token_iterator_t *t)
{
    return t->token.begin == t->terminator;
}


static void token_iterator_pop(token_iterator_t *t, token_t *head)
{
    if (head) *head = t->token;
    token_iterator_next(t);
}


static bool token_match_str(const token_t *t, const char *str)
{
    return (TOKEN_LEN(*t) == strlen(str) && !strncmp(t->begin, str, TOKEN_LEN(*t)));
}

// True if current token is the match one wildcard
static bool token_iterator_is_match_1(const token_iterator_t *t)
{
    return TOKEN_LEN(t->token) == 1 &&
        *t->token.begin == t->match_1;
}

// True if current token is the match zero or more wildcard
static bool token_iterator_is_match_glob(const token_iterator_t *t)
{
    return TOKEN_LEN(t->token) == 1 &&
        *t->token.begin == t->match_glob;
}


// Optimize the pattern match code by performing the following
// transformations to the pattern:
// #.* ---> *.#
// #.# ---> #
// This only applies to non-MQTT patterns since in MQTT it is illegal for the #
// to appear anywhere but the last token.
// Returns true if pattern was rewritten.
//
static bool normalize_pattern(qd_parse_tree_type_t type, char *pattern)
{
    token_iterator_t t;
    bool modified = false;
    char *original = NULL;

    if (type == QD_PARSE_TREE_MQTT) return false;

    token_iterator_init(&t, type, pattern);
    while (!token_iterator_done(&t)) {
        if (token_iterator_is_match_glob(&t)) {
            token_t last_token;
            token_iterator_pop(&t, &last_token);
            if (token_iterator_done(&t)) break;
            if (token_iterator_is_match_glob(&t)) {  // #.# --> #
                if (!modified) original = strdup(pattern);
                modified = true;
                char *src = (char *)t.token.begin;
                char *dest = (char *)last_token.begin;
                // note: overlapping strings, can't strcpy
                while (*src)
                    *dest++ = *src++;
                *dest = (char)0;
                t.terminator = dest;
                t.token = last_token;
            } else if (token_iterator_is_match_1(&t)) { // #.* --> *.#
                if (!modified) original = strdup(pattern);
                modified = true;
                *(char *)t.token.begin = t.match_glob;
                *(char *)last_token.begin = t.match_1;
            } else {
                token_iterator_next(&t);
            }
        } else {
            token_iterator_next(&t);
        }
    }

    if (original) {
        qd_log(qd_log_source("DEFAULT"), QD_LOG_NOTICE,
               "configured pattern '%s' optimized and re-written to '%s'",
               original, pattern);
        free(original);
    }

    return modified;
}


// Parse Tree
//
// The pattern is broken up into tokens delimited by a separation character and
// stored in a directed tree graph.  Common pattern prefixes are merged.  This
// allows the lookup alogrithm to quickly isolate those sub-trees that match a
// given input string.
// For example, given the patterns:
//     a.b.c.<...>
//     a.b.d.<...>
//     a.x.y.<...>
// The resulting parse tree would be:
//    a-->b-->c-->...
//    |   +-->d-->...
//    +-->x-->y-->...
//


typedef struct qd_parse_node qd_parse_node_t;

struct qd_parse_tree {
    qd_parse_node_t      *root;
    qd_log_source_t      *log_source;
    qd_hash_t            *hash;
    qd_parse_tree_type_t  type;
    uint32_t              next_hkey_prefix;  // next # for hash key prefix
};
ALLOC_DECLARE(qd_parse_tree_t);
ALLOC_DEFINE(qd_parse_tree_t);


typedef enum {
    QD_PARSE_NODE_ROOT,
    QD_PARSE_NODE_TOKEN,
    QD_PARSE_NODE_MATCH_ONE,
    QD_PARSE_NODE_MATCH_GLOB,
} qd_parse_node_type_t;

DEQ_DECLARE(qd_parse_node_t, qd_parse_node_list_t);
struct qd_parse_node {
    DEQ_LINKS(qd_parse_node_t); // siblings
    char *token;                // portion of pattern represented by this node
    char *pattern;              // entire normalized pattern matching this node

    // sub-trees of this node:
    qd_parse_node_t     *match_1_child;     // starts with a match 1 wildcard
    qd_parse_node_t     *match_glob_child;  // starts with 0 or more wildcard
    qd_parse_node_list_t children;          // all that start with a non-wildcard token

    qd_parse_node_t  *parent;         // NULL if root node
    qd_hash_handle_t *handle;
    void             *payload;

    // prefix for hash keys of this node's children
    uint32_t             hkey_prefix;
    qd_parse_node_type_t match_type;
};
ALLOC_DECLARE(qd_parse_node_t);
ALLOC_DEFINE(qd_parse_node_t);


// Hash key for a token node is in the following format:
//  "<parent node hkey-prefix in hex>/<token>
//
#define HKEY_PREFIX_LEN (8 + 1)  // 8 hex chars (32 bit integer) + '/'
static inline void generate_hkey(char *hkey, size_t buf_len, uint32_t pprefix, const token_t *t)
{
    int rc = snprintf(hkey, buf_len, "%"PRIX32"/%.*s", pprefix, (int)TOKEN_LEN(*t), t->begin);
    assert(rc > 0 && rc < buf_len);
    (void)rc;  // prevent warnings for unused var
}


// return count of child nodes
static int parse_node_child_count(const qd_parse_node_t *n)
{
    return DEQ_SIZE(n->children)
        + (n->match_1_child ? 1 : 0)
        + (n->match_glob_child ? 1 : 0);
}


// Free a parse node
static void free_parse_node(qd_parse_tree_t *tree, qd_parse_node_t *n)
{
    if (n) {
        assert(parse_node_child_count(n) == 0);
        free(n->token);
        free(n->pattern);
        if (n->handle) {
            qd_hash_remove_by_handle(tree->hash, n->handle);
            qd_hash_handle_free(n->handle);
        }
        free_qd_parse_node_t(n);
    }
}


// Allocate a new parse tree node.
//
// Allocate a new hash node. If a token is given the hash key for this node is
// generated by concatenating the parent prefix with the token.
//
static qd_parse_node_t *new_parse_node(qd_parse_tree_t *tree,
                                       qd_parse_node_type_t match_type,
                                       const token_t *t,
                                       qd_parse_node_t *parent)
{
    qd_parse_node_t *n = new_qd_parse_node_t();
    if (n) {
        ZERO(n);
        DEQ_ITEM_INIT(n);
        DEQ_INIT(n->children);
        n->match_type = match_type;
        // generate a new hash key prefix for this node's children
        n->hkey_prefix = tree->next_hkey_prefix++;

        if (match_type == QD_PARSE_NODE_TOKEN) {
            assert(t);
            assert(parent);
            const size_t tlen = TOKEN_LEN(*t);
            n->token = malloc(tlen + 1);
            if (!n->token) {
                free_qd_parse_node_t(n);
                return 0;
            }
            strncpy(n->token, t->begin, tlen);
            n->token[tlen] = 0;
            {
                const size_t hkey_size = HKEY_PREFIX_LEN + tlen + 1;
                char hkey[hkey_size];
                generate_hkey(hkey, hkey_size, parent->hkey_prefix, t);

                if (qd_hash_insert_str(tree->hash, (unsigned char *)hkey, (void *)n, &n->handle) != QD_ERROR_NONE) {
                    free_parse_node(tree, n);
                    return 0;
                }

                n->parent = parent;
            }
        }
    }

    return n;
}


// find immediate child node matching token
static qd_parse_node_t *parse_node_find_child(qd_parse_tree_t *tree, const qd_parse_node_t *node, const token_t *token)
{
    qd_parse_node_t *child = 0;
    const size_t tlen = TOKEN_LEN(*token);
    const size_t hkey_size = HKEY_PREFIX_LEN + tlen + 1;
    char hkey[hkey_size];

    generate_hkey(hkey, hkey_size, node->hkey_prefix, token);
    qd_hash_retrieve_str(tree->hash, (const unsigned char *)hkey, (void **)&child);
    if (child) {
        assert(child->parent == node);
    }
    return child;
}


// Add a new pattern and associated data to the tree.
// Return QD_ERROR_ALREADY_EXISTS if the pattern is already in the tree.
// caller transfers ownership of "pattern"
//
static qd_error_t parse_node_add_pattern(qd_parse_tree_t *tree, char *pattern, void *payload)
{
    qd_parse_node_t *node = tree->root;
    qd_error_t result = QD_ERROR_NONE;
    token_iterator_t iterator;

    normalize_pattern(tree->type, pattern);

    // worst case maximum for hash key if pattern is a single token
    const size_t buf_size = HKEY_PREFIX_LEN + strlen(pattern) + 1;
    char *hkey = malloc(buf_size);
    if (!hkey) {
        result = qd_error(QD_ERROR_ALLOC, "Pattern '%s' not added to parse tree", pattern);
        free(pattern);
        return result;
    }

    token_iterator_init(&iterator, tree->type, pattern);

    //
    // walk the iterator through the tree adding nodes for each token/wildcard as needed
    //
    while (!token_iterator_done(&iterator)) {

        if (token_iterator_is_match_1(&iterator)) {
            if (!node->match_1_child) {
                node->match_1_child = new_parse_node(tree, QD_PARSE_NODE_MATCH_ONE, 0, node);
                if (!node->match_1_child) {
                    result = qd_error(QD_ERROR_ALLOC, "Pattern '%s' not added to parse tree", pattern);
                    break;
                }
                node->match_1_child->parent = node;
            }
            node = node->match_1_child;
            token_iterator_next(&iterator);

        } else if (token_iterator_is_match_glob(&iterator)) {
            if (!node->match_glob_child) {
                node->match_glob_child = new_parse_node(tree, QD_PARSE_NODE_MATCH_GLOB, 0, node);
                if (!node->match_glob_child) {
                    result = qd_error(QD_ERROR_ALLOC, "Pattern '%s' not added to parse tree", pattern);
                    break;
                }
                node->match_glob_child->parent = node;
            }
            node = node->match_glob_child;
            token_iterator_next(&iterator);

        } else { // non-wildcard token
            token_t new_token;
            token_iterator_pop(&iterator, &new_token);
            generate_hkey(hkey, buf_size, node->hkey_prefix, &new_token);

            qd_parse_node_t *child = 0;
            qd_hash_retrieve_str(tree->hash, (const unsigned char *)hkey, (void **)&child);

            if (child) {
                assert(child->parent == node);
                node = child;
            } else {
                // add new node for new_token
                child = new_parse_node(tree, QD_PARSE_NODE_TOKEN, &new_token, node);
                if (!child) {
                    result = qd_error(QD_ERROR_ALLOC, "Pattern '%s' not added to parse tree", pattern);
                    break;
                }
                DEQ_INSERT_TAIL(node->children, child);
                node = child;
            }
        }
    }

    // done iterating over pattern.

    if (result == QD_ERROR_NONE) {
        if (node == tree->root) {
            result = qd_error(QD_ERROR_VALUE, "Invalid pattern '%s' not added to parse tree", pattern);
        } else if (node->pattern) {
            result = qd_error(QD_ERROR_ALREADY_EXISTS, "Duplicate pattern '%s' not added to parse tree", pattern);
        } else {
            node->pattern = pattern;
            pattern = 0;
            node->payload = payload;
            qd_log(tree->log_source, QD_LOG_TRACE, "Parse tree add pattern '%s'", node->pattern);
        }
    }

    free(pattern);
    free(hkey);

    return result;
}


// Find the leaf node matching the pattern.  Returns 0 if pattern is not in the tree
//
static qd_parse_node_t *parse_node_get_pattern(qd_parse_tree_t *tree, char *pattern)
{
    qd_parse_node_t *node = tree->root;
    token_iterator_t iterator;

    normalize_pattern(tree->type, pattern);

    // worst case maximum for hash key if pattern is a single token
    const size_t buf_size = HKEY_PREFIX_LEN + strlen(pattern) + 1;
    char *hkey = malloc(buf_size);
    if (!hkey) {
        return 0;
    }

    token_iterator_init(&iterator, tree->type, pattern);

    while (node && !token_iterator_done(&iterator)) {

        if (token_iterator_is_match_1(&iterator)) {
            node = node->match_1_child;
            token_iterator_next(&iterator);

        } else if (token_iterator_is_match_glob(&iterator)) {
            node = node->match_glob_child;
            token_iterator_next(&iterator);

        } else {
            token_t new_token;
            token_iterator_pop(&iterator, &new_token);

            // search for new_token child
            assert(node->hkey_prefix);
            generate_hkey(hkey, buf_size, node->hkey_prefix, &new_token);

            qd_parse_node_t *child = 0;
            qd_hash_retrieve_str(tree->hash, (const unsigned char *)hkey, (void **)&child);

            assert(!child || child->parent == node);
            node = child;
        }
    }

    free(hkey);

    if (node && node->pattern) {
        assert(strcmp(node->pattern, pattern) == 0);
        return node;
    }

    return 0;
}


static bool parse_node_find(qd_parse_tree_t *, qd_parse_node_t *, token_iterator_t *,
                            qd_parse_tree_visit_t *, void *);


// search the sub-trees of this node.
// This function returns false to stop the search
static bool parse_node_find_children(qd_parse_tree_t *tree, qd_parse_node_t *node, token_iterator_t *value,
                                     qd_parse_tree_visit_t *callback, void *handle)
{
    if (!token_iterator_done(value)) {

        // check exact match first (precedence)
        if (DEQ_SIZE(node->children) > 0) {
            token_iterator_t tmp = *value;
            token_t child_token;
            token_iterator_pop(&tmp, &child_token);

            qd_parse_node_t *child = parse_node_find_child(tree, node, &child_token);
            if (child) {
                if (!parse_node_find(tree, child, &tmp, callback, handle))
                    return false;
            }
        }

        if (node->match_1_child) {
            token_iterator_t tmp = *value;
            if (!parse_node_find(tree, node->match_1_child, &tmp, callback, handle))
                return false;
        }
    }

    // always try glob - even if empty (it can match empty keys)
    if (node->match_glob_child) {
        token_iterator_t tmp = *value;
        if (!parse_node_find(tree, node->match_glob_child, &tmp, callback, handle))
            return false;
    }

    return true; // continue search
}


// This node matched the last token.
// This function returns false to stop the search
static bool parse_node_find_token(qd_parse_tree_t *tree, qd_parse_node_t *node, token_iterator_t *value,
                                  qd_parse_tree_visit_t *callback, void *handle)
{
    if (token_iterator_done(value) && node->pattern) {
        // exact match current node
        if (!callback(handle, node->pattern, node->payload))
            return false;
    }

    // no payload or more tokens.  Continue to lower sub-trees. Even if no more
    // tokens (may have a # match)
    return parse_node_find_children(tree, node, value, callback, handle);
}


// this node matches any one token
// returns false to stop the search
static bool parse_node_match_1(qd_parse_tree_t *tree, qd_parse_node_t *node, token_iterator_t *value,
                               qd_parse_tree_visit_t *callback, void *handle)
{
    // must match exactly one token:
    if (token_iterator_done(value))
        return true;  // no match here, but continue searching

    // pop the topmost token (matched)
    token_iterator_next(value);

    if (token_iterator_done(value) && node->pattern) {
        // exact match current node
        if (!callback(handle, node->pattern, node->payload))
            return false;
    }

    // no payload or more tokens: continue to lower sub-trees
    return parse_node_find_children(tree, node, value, callback, handle);
}


// current node is hash, match the remainder of the string
// return false to stop search
static bool parse_node_match_glob(qd_parse_tree_t *tree, qd_parse_node_t *node, token_iterator_t *value,
                                  qd_parse_tree_visit_t *callback, void *handle)
{
    // consume each token and look for a match on the
    // remaining key.
    while (!token_iterator_done(value)) {
        if (!parse_node_find_children(tree, node, value, callback, handle))
            return false;
        token_iterator_next(value);
    }

    // this node matches
    if (node->pattern)
        return callback(handle, node->pattern, node->payload);

    return true;
}


// find the payload associated with the input string 'value'
static bool parse_node_find(qd_parse_tree_t *tree, qd_parse_node_t *node, token_iterator_t *value,
                            qd_parse_tree_visit_t *callback, void *handle)
{
    switch (node->match_type) {
    case QD_PARSE_NODE_MATCH_ONE:
        return parse_node_match_1(tree, node, value, callback, handle);
    case QD_PARSE_NODE_MATCH_GLOB:
        return parse_node_match_glob(tree, node, value, callback, handle);
    case QD_PARSE_NODE_TOKEN:
        return parse_node_find_token(tree, node, value, callback, handle);
    case QD_PARSE_NODE_ROOT:
        return parse_node_find_children(tree, node, value, callback, handle);
    }
    return true;
}


static void parse_node_free(qd_parse_tree_t *tree, qd_parse_node_t *node)
{
    if (node) {
        if (node->match_1_child) parse_node_free(tree, node->match_1_child);
        if (node->match_glob_child) parse_node_free(tree, node->match_glob_child);
        node->match_1_child = node->match_glob_child = NULL;
        while (!DEQ_IS_EMPTY(node->children)) {
            qd_parse_node_t *child = DEQ_HEAD(node->children);
            DEQ_REMOVE_HEAD(node->children);
            parse_node_free(tree, child);
        }

        free_parse_node(tree, node);
    }
}


qd_parse_tree_t *qd_parse_tree_new(qd_parse_tree_type_t type)
{

    qd_parse_tree_t *tree = new_qd_parse_tree_t();
    if (tree) {
        ZERO(tree);
        tree->type = type;
        tree->log_source = qd_log_source("DEFAULT");
        tree->next_hkey_prefix = 1;
        tree->root = new_parse_node(tree, QD_PARSE_NODE_ROOT, 0, 0);
        if (!tree->root) {
            free_qd_parse_tree_t(tree);
            return 0;
        }
        tree->hash = qd_hash(10, 32, false);
        if (!tree->hash) {
            parse_node_free(tree, tree->root);
            free_qd_parse_tree_t(tree);
            return 0;
        }
    }

    return tree;
}


// find best match for value
//
static bool get_first(void *handle, const char *pattern, void *payload)
{
    *(void **)handle = payload;
    return false;
}

bool qd_parse_tree_retrieve_match(qd_parse_tree_t *tree,
                                  const qd_iterator_t *value,
                                  void **payload)
{
    *payload = NULL;
    qd_parse_tree_search(tree, value, get_first, payload);
    if (*payload == NULL)
        qd_log(tree->log_source, QD_LOG_TRACE, "Parse tree match not found");
    return *payload != NULL;
}


// Invoke callback for each pattern that matches 'value'
void qd_parse_tree_search(qd_parse_tree_t *tree,
                          const qd_iterator_t *value,
                          qd_parse_tree_visit_t *callback, void *handle)
{
    token_iterator_t t_iter;
    char *str = (char *)qd_iterator_copy_const(value);
    qd_log(tree->log_source, QD_LOG_TRACE, "Parse tree search for '%s'", str);

    token_iterator_init(&t_iter, tree->type, str);
    parse_node_find(tree, tree->root, &t_iter, callback, handle);

    free(str);
}


qd_error_t qd_parse_tree_add_pattern(qd_parse_tree_t *tree,
                                     const qd_iterator_t *pattern,
                                     void *payload)
{
    char *str = (char *)qd_iterator_copy_const(pattern);
    if (!str)
        return QD_ERROR_ALLOC;

    return parse_node_add_pattern(tree, str, payload);
}


// returns true if pattern exists in tree
bool qd_parse_tree_get_pattern(qd_parse_tree_t *tree,
                               const qd_iterator_t *pattern,
                               void **payload)
{
    char *str = (char *)qd_iterator_copy_const(pattern);
    if (!str)
        return false;

    qd_parse_node_t *found = parse_node_get_pattern(tree, str);
    free(str);
    *payload = found ? found->payload : NULL;
    return !!found;
}


// returns the payload void *
void *qd_parse_tree_remove_pattern(qd_parse_tree_t *tree,
                                   const qd_iterator_t *pattern)
{
    char *str = (char *)qd_iterator_copy_const(pattern);
    if (!str)
        return 0;

    qd_parse_node_t *node = parse_node_get_pattern(tree, str);
    if (!node) {
        free(str);
        return 0;
    }

    assert(strcmp(node->pattern, str) == 0);
    free(str);

    void *value = node->payload;

    // now clean up this node.  Be aware we can only free the entire node if it does not have children.
    // If it has children just zero out the pattern field indicates it is no longer a terminal node.
    // The fun happens if it has no children: in this case free the node then
    // see if the parent node is now childless and NOT a terminal node. If so
    // clean it up as well.  Repeat.

    free(node->pattern);
    node->pattern = 0;
    node->payload = 0;
    qd_parse_node_t *parent = node->parent;

    while (node && node->pattern == 0 && parse_node_child_count(node) == 0 && parent) {

        switch (node->match_type) {
        case QD_PARSE_NODE_MATCH_ONE:
            assert(parent->match_1_child == node);
            parent->match_1_child = 0;
            break;
        case QD_PARSE_NODE_MATCH_GLOB:
            assert(parent->match_glob_child == node);
            parent->match_glob_child = 0;
            break;
        case QD_PARSE_NODE_TOKEN:
            DEQ_REMOVE(parent->children, node);
            break;
        case QD_PARSE_NODE_ROOT:
        default:
            // cannot get here
            assert(false);
            break;
        }
        free_parse_node(tree, node);
        node = parent;
        parent = node->parent;
    }

    return value;
}


static bool parse_tree_walk(qd_parse_node_t *node, qd_parse_tree_visit_t *callback, void *handle)
{
    if (node->pattern) {  // terminal node for pattern
        if (!callback(handle, node->pattern, node->payload))
            return false;
    }

    qd_parse_node_t *child = DEQ_HEAD(node->children);
    while (child) {
        if (!parse_tree_walk(child, callback, handle))
            return false;
        child = DEQ_NEXT(child);
    }

    if (node->match_1_child)
        if (!parse_tree_walk(node->match_1_child, callback, handle))
            return false;

    if (node->match_glob_child)
        if (!parse_tree_walk(node->match_glob_child, callback, handle))
            return false;

    return true;
}


bool qd_parse_tree_walk(qd_parse_tree_t *tree, qd_parse_tree_visit_t *callback, void *handle)
{
    return parse_tree_walk(tree->root, callback, handle);
}


bool qd_parse_tree_validate_pattern(const qd_parse_tree_t *tree,
                                    const qd_iterator_t *pattern)
{
    char *str = (char *)qd_iterator_copy_const(pattern);
    if (!str)
        return false;

    token_iterator_t ti;
    token_iterator_init(&ti, tree->type, str);
    if (token_iterator_done(&ti)) {
        // empty iterator
        free(str);
        return false;
    }

    if (tree->type == QD_PARSE_TREE_MQTT) {
        // simply ensure that if a '#' is present it is the last token in the
        // pattern
        bool valid = true;
        while (!token_iterator_done(&ti)) {
            token_t head;
            token_iterator_pop(&ti, &head);
            if (token_match_str(&head, "#")) {
                valid = token_iterator_done(&ti);
                break;
            }
        }
        free(str);
        return valid;
    }

    free(str);
    return true;
}


qd_parse_tree_type_t qd_parse_tree_type(const qd_parse_tree_t *tree)
{
    return tree->type;
}


static void _parse_tree_free(qd_parse_tree_t *tree)
{
    if (tree) {
        parse_node_free(tree, tree->root);
        qd_hash_free(tree->hash);
        free_qd_parse_tree_t(tree);
    }
}

#if 0

static void _node_dump(const qd_parse_node_t *node, const int depth)
{
    for (int i = 0; i < depth; i++)
        fprintf(stdout, "  ");
    char *type = (node->match_type == QD_PARSE_NODE_ROOT
                  ? "ROOT"
                  : (node->match_type == QD_PARSE_NODE_TOKEN
                     ? "TOKEN"
                     : (node->match_type == QD_PARSE_NODE_MATCH_ONE
                        ? "STAR"
                        : "GLOB")));
    fprintf(stdout, "token: %s pattern: %s type: %s # childs: %d hkey: %s hprefix %"PRIX32" payload: %p\n",
            node->token ? node->token : "*NONE*",
            node->pattern ? node->pattern: "*NONE*",
            type,
            parse_node_child_count(node),
            (node->handle ? (const char *)qd_hash_key_by_handle(node->handle) : "*NONE*"),
            node->hkey_prefix,
            node->payload);

    if (node->match_1_child) _node_dump(node->match_1_child, depth + 1);
    if (node->match_glob_child) _node_dump(node->match_glob_child, depth + 1);
    qd_parse_node_t *child = DEQ_HEAD(node->children);
    while (child) {
        _node_dump(child, depth + 1);
        child = DEQ_NEXT(child);
    }
}

void qd_parse_tree_dump(const qd_parse_tree_t *tree)
{
    if (tree && tree->root) {
        _node_dump(tree->root, 0);
        fflush(stdout);
    }
}

void qd_parse_tree_free(qd_parse_tree_t *tree)
{
    fprintf(stdout, "PARSE TREE DUMP\n");
    fprintf(stdout, "===============\n");
    qd_parse_tree_dump(tree);
    _parse_tree_free(tree);
}

#else

void qd_parse_tree_free(qd_parse_tree_t *tree)
{
    _parse_tree_free(tree);
}
#endif

//
// parse tree functions using string interface
//

qd_error_t qd_parse_tree_add_pattern_str(qd_parse_tree_t *tree,
                                         const char *pattern,
                                         void *payload)
{
    char *str = strdup(pattern);
    if (!str)
        return QD_ERROR_ALLOC;

    return parse_node_add_pattern(tree, str, payload);
}


// visit each matching pattern that matches value in the order based on the
// precedence rules
void qd_parse_tree_search_str(qd_parse_tree_t *tree,
                              const char *value,
                              qd_parse_tree_visit_t *callback, void *handle)
{
    token_iterator_t t_iter;
    // @TODO(kgiusti) for now:
    char *str = strdup(value);
    qd_log(tree->log_source, QD_LOG_TRACE, "Parse tree(str) search for '%s'", str);

    token_iterator_init(&t_iter, tree->type, str);
    parse_node_find(tree, tree->root, &t_iter, callback, handle);

    free(str);
}


// returns true on match and sets *payload
bool qd_parse_tree_retrieve_match_str(qd_parse_tree_t *tree,
                                      const char *value,
                                      void **payload)
{
    *payload = NULL;
    qd_parse_tree_search_str(tree, value, get_first, payload);
    if (*payload == NULL)
        qd_log(tree->log_source, QD_LOG_TRACE, "Parse tree(str) match not found");
    return *payload != NULL;
}

// returns old payload or NULL if not present
void *qd_parse_tree_remove_pattern_str(qd_parse_tree_t *tree,
                                       const char *pattern)
{
    qd_iterator_t *piter = qd_iterator_string(pattern, ITER_VIEW_ALL);
    void *result = qd_parse_tree_remove_pattern(tree, piter);
    qd_iterator_free(piter);
    return result;
}
