コード例 #1
0
ファイル: edge.c プロジェクト: czchen/r3
/**
 * branch the edge pattern at "dl" offset,
 * insert a dummy child between the edges.
 *
 *
 * A -> [prefix..suffix] -> B
 * A -> [prefix] -> B -> [suffix] -> New Child (Copy Data, Edges from B)
 *
 */
node * r3_edge_branch(edge *e, int dl) {
    node *new_child;
    edge *e1;
    char * s1 = e->pattern + dl;
    int s1_len = 0;

    edge **tmp_edges = e->child->edges;
    int   tmp_edge_len = e->child->edge_len;

    // the suffix edge of the leaf
    new_child = r3_tree_create(3);
    s1_len = e->pattern_len - dl;
    e1 = r3_edge_create(zstrndup(s1, s1_len), s1_len, new_child);

    // Migrate the child edges to the new edge we just created.
    for ( int i = 0 ; i < tmp_edge_len ; i++ ) {
        r3_node_append_edge(new_child, tmp_edges[i]);
        e->child->edges[i] = NULL;
    }
    e->child->edge_len = 0;
    new_child->endpoint = e->child->endpoint;
    e->child->endpoint = 0; // reset endpoint

    r3_node_append_edge(e->child, e1);
    new_child->data = e->child->data; // copy data pointer
    e->child->data = NULL;

    // truncate the original edge pattern
    char *op = e->pattern;
    e->pattern = zstrndup(e->pattern, dl);
    e->pattern_len = dl;

    return new_child;
}
コード例 #2
0
ファイル: check_tree.c プロジェクト: CindyLinz/r3
END_TEST



START_TEST (test_find_common_prefix_middle)
{
    node * n = r3_tree_create(10);
    edge * e = r3_edge_createl(zstrdup("/foo/{slug}/hate"), sizeof("/foo/{slug}/hate")-1, NULL);
    r3_node_append_edge(n,e);

    int prefix_len;
    edge *ret_edge = NULL;
    char *errstr = NULL;

    errstr = NULL;
    ret_edge = r3_node_find_common_prefix(n, "/foo/{slug}/bar", sizeof("/foo/{slug}/bar")-1, &prefix_len, &errstr);
    ck_assert(ret_edge);
    ck_assert_int_eq(prefix_len, 12);
    SAFE_FREE(errstr);

    errstr = NULL;
    ret_edge = r3_node_find_common_prefix(n, "/fo/{slug}/bar", sizeof("/fo/{slug}/bar")-1, &prefix_len, &errstr);
    ck_assert(ret_edge);
    ck_assert_int_eq(prefix_len, 3);
    SAFE_FREE(errstr);

    r3_tree_free(n);
}
コード例 #3
0
ファイル: node.c プロジェクト: lucemia/r3
edge * r3_node_connectl(node * n, const char * pat, int len, int dupl, node *child) {
    // find the same sub-pattern, if it does not exist, create one
    edge * e;

    e = r3_node_find_edge(n, pat);
    if (e) {
        return e;
    }

    if (dupl) {
        pat = zstrndup(pat, len);
    }
    e = r3_edge_create(pat, len, child);
    r3_node_append_edge(n, e);
    return e;
}
コード例 #4
0
ファイル: node.c プロジェクト: SciTeX/r3
/* parent node, edge pattern, child */
edge * r3_node_add_child(node * n, char * pat , node *child) {
    // find the same sub-pattern, if it does not exist, create one

    edge * e;

    e = r3_node_find_edge(n, pat);
    if (e) {
        return e;
    }

    e = r3_edge_create( pat, strlen(pat), child);
    r3_node_append_edge(n, e);
    // str_array_append(n->edge_patterns, pat);
    // assert( str_array_len(n->edge_patterns) == n->edge_len );
    return e;
}
コード例 #5
0
ファイル: check_tree.c プロジェクト: CindyLinz/r3
END_TEST

START_TEST (test_find_common_prefix_same_pattern2)
{
    node * n = r3_tree_create(10);
    edge * e = r3_edge_createl(zstrdup("{slug:xxx}/hate"), sizeof("{slug:xxx}/hate")-1, NULL);
    r3_node_append_edge(n,e);

    int prefix_len;
    edge *ret_edge = NULL;

    prefix_len = 0;
    ret_edge = r3_node_find_common_prefix(n, "{slug:yyy}/hate", sizeof("{slug:yyy}/hate")-1, &prefix_len, NULL);
    ck_assert(ret_edge);
    ck_assert_int_eq(prefix_len, 0);

    r3_tree_free(n);
}
コード例 #6
0
ファイル: edge.c プロジェクト: karantin2020/r3
/**
 * r3_edge_branch splits the edge and append the rest part as the child of the
 * first level child
 *
 * branch the edge pattern at "dl" offset,
 * and insert a dummy child between the edges.
 *
 * A -> [EDGE: abcdefg] -> B -> [EDGE:branch1], [EDGE:branch2]
 * A -> [EDGE: abcd] -> B1 -> [efg] -> B2 (new child with copied data from B)
 *
 */
R3Node * r3_edge_branch(R3Edge *e, int dl) {
    R3Node * new_child;
    R3Edge * new_edge;

    // the rest string
    char * s1 = e->pattern.base + dl;
    int s1_len = e->pattern.len - dl;

    // the suffix edge of the leaf
    new_child = r3_tree_create(3);

    new_edge = r3_node_append_edge(new_child);
    r3_edge_initl(new_edge, s1, s1_len, e->child);
    e->child = new_child;
    
    // truncate the original edge pattern
    e->pattern.len = dl;
    return new_child;
}
コード例 #7
0
ファイル: node.c プロジェクト: arpanlepcha/r3
/**
 * Return the last inserted node.
 */
node * r3_tree_insert_pathl(node *tree, char *path, int path_len, route * route, void * data)
{
    node * n = tree;
    edge * e = NULL;

    /* length of common prefix */
    int offset = 0;
    for( int i = 0 ; i < n->edge_len ; i++ ) {
        offset = strndiff(path, n->edges[i]->pattern, n->edges[i]->pattern_len);

        // printf("offset: %d   %s vs %s\n", offset, path, n->edges[i]->pattern );

        // no common, consider insert a new edge
        if ( offset > 0 ) {
            e = n->edges[i];
            break;
        }
    }

    // branch the edge at correct position (avoid broken slugs)
    char *slug_s = strchr(path, '{');
    char *slug_e = strchr(path, '}');
    if ( slug_s && slug_e ) {
        if ( offset > (slug_s - path) && offset < (slug_e - path) ) {
            // break before '{'
            offset = slug_s - path;
        }
    }

    if ( offset == 0 ) {
        // not found, we should just insert a whole new edge
        node * child = r3_tree_create(3);
        r3_node_add_child(n, strndup(path, path_len) , child);
        info("edge not found, insert one: %s\n", path);
        child->data = data;
        child->endpoint++;

        if (route) {
            route->data = data;
            r3_node_append_route(child, route);
        }
        return child;
    } else if ( offset == e->pattern_len ) {    // fully-equal to the pattern of the edge

        char * subpath = path + offset;
        int    subpath_len = path_len - offset;

        // there are something more we can insert
        if ( subpath_len > 0 ) {
            return r3_tree_insert_pathl(e->child, subpath, subpath_len, route, data);
        } else {
            // no more path to insert
            e->child->endpoint++; // make it as an endpoint
            e->child->data = data;
            if (route) {
                route->data = data;
                r3_node_append_route(e->child, route);
            }
            return e->child;
        }

    } else if ( offset < e->pattern_len ) {
        // printf("branch the edge offset: %d\n", offset);


        /* it's partially matched with the pattern,
         * we should split the end point and make a branch here...
         */
        node *c2; // child 1, child 2
        edge *e2; // edge 1, edge 2
        char * s2 = path + offset;
        int s2_len = 0;

        r3_edge_branch(e, offset);

        // here is the new edge from.
        c2 = r3_tree_create(3);
        s2_len = path_len - offset;
        e2 = r3_edge_create(strndup(s2, s2_len), s2_len, c2);
        // printf("edge right: %s\n", e2->pattern);
        r3_node_append_edge(e->child, e2);


        char *op = e->pattern;
        // truncate the original edge pattern 
        e->pattern = strndup(e->pattern, offset);
        e->pattern_len = offset;
        free(op);

        // move n->edges to c1
        c2->endpoint++;
        c2->data = data;

        if (route) {
            route->data = data;
            r3_node_append_route(c2, route);
        }
        return c2;
    } else {
        printf("unexpected route.");
        return NULL;
    }
    return n;
}