2014-05-16 08:38:14 -04:00
|
|
|
/*
|
|
|
|
* edge.c
|
2014-06-27 01:24:40 -04:00
|
|
|
* Copyright (C) 2014 c9s <yoanlin93@gmail.com>
|
2014-05-16 08:38:14 -04:00
|
|
|
*
|
|
|
|
* Distributed under terms of the MIT license.
|
|
|
|
*/
|
2014-06-03 09:47:52 -04:00
|
|
|
#include "config.h"
|
2014-05-16 08:38:14 -04:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <assert.h>
|
|
|
|
|
|
|
|
// Jemalloc memory management
|
2014-05-19 13:28:51 -04:00
|
|
|
// #include <jemalloc/jemalloc.h>
|
2014-05-16 08:38:14 -04:00
|
|
|
|
|
|
|
// PCRE
|
|
|
|
#include <pcre.h>
|
|
|
|
#include "r3.h"
|
2014-05-20 11:33:51 -04:00
|
|
|
#include "r3_str.h"
|
2014-06-01 20:04:57 -04:00
|
|
|
#include "slug.h"
|
2014-05-21 02:59:07 -04:00
|
|
|
#include "zmalloc.h"
|
2014-05-16 08:38:14 -04:00
|
|
|
|
2014-06-04 11:13:08 -04:00
|
|
|
|
|
|
|
#define CHECK_PTR(ptr) if (ptr == NULL) return NULL;
|
|
|
|
|
|
|
|
|
2014-06-01 21:48:00 -04:00
|
|
|
edge * r3_edge_createl(const char * pattern, int pattern_len, node * child) {
|
2014-05-20 13:50:15 -04:00
|
|
|
edge * e = (edge*) zmalloc( sizeof(edge) );
|
2014-06-04 11:13:08 -04:00
|
|
|
|
|
|
|
CHECK_PTR(e);
|
|
|
|
|
2014-05-26 13:08:31 -04:00
|
|
|
e->pattern = (char*) pattern;
|
2014-05-18 00:24:07 -04:00
|
|
|
e->pattern_len = pattern_len;
|
2014-05-22 23:47:44 -04:00
|
|
|
e->opcode = 0;
|
2014-05-18 00:24:07 -04:00
|
|
|
e->child = child;
|
2014-06-01 20:04:57 -04:00
|
|
|
e->has_slug = r3_path_contains_slug_char(e->pattern);
|
2014-05-18 00:24:07 -04:00
|
|
|
return e;
|
|
|
|
}
|
|
|
|
|
2014-05-16 08:38:14 -04:00
|
|
|
|
|
|
|
|
|
|
|
/**
|
2015-11-17 03:08:01 -05:00
|
|
|
* r3_edge_branch splits the edge and append the rest part as the child of the
|
|
|
|
* first level child
|
2014-05-18 06:58:31 -04:00
|
|
|
*
|
2015-11-17 03:08:01 -05:00
|
|
|
* branch the edge pattern at "dl" offset,
|
|
|
|
* and insert a dummy child between the edges.
|
2014-05-18 07:09:47 -04:00
|
|
|
*
|
2015-11-17 03:08:01 -05:00
|
|
|
* A -> [EDGE: abcdefg] -> B -> [EDGE:branch1], [EDGE:branch2]
|
|
|
|
* A -> [EDGE: abcd] -> B1 -> [efg] -> B2 (new child with copied data from B)
|
2014-05-16 08:38:14 -04:00
|
|
|
*
|
|
|
|
*/
|
2014-05-18 07:09:47 -04:00
|
|
|
node * r3_edge_branch(edge *e, int dl) {
|
2015-11-17 03:08:01 -05:00
|
|
|
node * new_child;
|
|
|
|
edge * new_edge;
|
|
|
|
|
|
|
|
// the rest string
|
2014-05-16 08:38:14 -04:00
|
|
|
char * s1 = e->pattern + dl;
|
2015-11-17 03:08:01 -05:00
|
|
|
int s1_len = e->pattern_len - dl;
|
2014-05-16 08:38:14 -04:00
|
|
|
|
|
|
|
// the suffix edge of the leaf
|
2014-05-18 07:09:47 -04:00
|
|
|
new_child = r3_tree_create(3);
|
2015-11-17 03:08:01 -05:00
|
|
|
new_edge = r3_edge_createl(zstrndup(s1, s1_len), s1_len, new_child);
|
2014-05-27 02:16:42 -04:00
|
|
|
|
2015-11-17 03:08:01 -05:00
|
|
|
// Move child node to the new edge
|
|
|
|
new_edge->child = e->child;
|
|
|
|
e->child = new_child;
|
2014-05-27 02:16:42 -04:00
|
|
|
|
2015-11-17 03:08:01 -05:00
|
|
|
r3_node_append_edge(new_child, new_edge);
|
2014-05-27 02:16:42 -04:00
|
|
|
|
2014-05-20 13:50:15 -04:00
|
|
|
// truncate the original edge pattern
|
2014-05-22 23:14:26 -04:00
|
|
|
char *oldpattern = e->pattern;
|
2014-05-21 04:18:12 -04:00
|
|
|
e->pattern = zstrndup(e->pattern, dl);
|
2014-05-18 06:58:31 -04:00
|
|
|
e->pattern_len = dl;
|
2014-05-22 23:14:26 -04:00
|
|
|
zfree(oldpattern);
|
2014-05-18 08:16:53 -04:00
|
|
|
return new_child;
|
2014-05-16 08:38:14 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void r3_edge_free(edge * e) {
|
2014-05-22 23:15:57 -04:00
|
|
|
zfree(e->pattern);
|
2014-05-16 08:38:14 -04:00
|
|
|
if ( e->child ) {
|
|
|
|
r3_tree_free(e->child);
|
|
|
|
}
|
2014-05-21 06:12:14 -04:00
|
|
|
// free itself
|
|
|
|
zfree(e);
|
2014-05-16 08:38:14 -04:00
|
|
|
}
|
|
|
|
|