diff --git a/include/r3.h b/include/r3.h index c68559b..b2562c9 100644 --- a/include/r3.h +++ b/include/r3.h @@ -180,44 +180,6 @@ enum { NODE_COMPARE_STR, NODE_COMPARE_PCRE, NODE_COMPARE_OPCODE }; enum { OP_EXPECT_MORE_DIGITS = 1, OP_EXPECT_MORE_WORDS, OP_EXPECT_NOSLASH, OP_EXPECT_NODASH, OP_EXPECT_MORE_ALPHA }; -typedef struct { - /** - * source path - */ - char * path; - - int path_len; - - /** - * slug start pointer - */ - char * begin; - - /** - * slug end pointer - */ - char * end; - - /** - * slug length - */ - int len; - - // slug pattern pointer if we have one - char * pattern; - - // the length of custom pattern, if the pattern is found. - int pattern_len; - -} r3_slug_t; - - -r3_slug_t * r3_slug_parse(const char *needle, int needle_len, char **errstr); - -char * r3_slug_to_str(r3_slug_t *s); - -void r3_slug_free(r3_slug_t * s); - #ifdef ENABLE_JSON json_object * r3_edge_to_json_object(const edge * e); json_object * r3_node_to_json_object(const node * n); diff --git a/src/Makefile.am b/src/Makefile.am index e154d2a..d43514d 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -3,7 +3,7 @@ AM_LDFLAGS=$(DEPS_LIBS) $(GVC_DEPS_LIBS) $(JSONC_LIBS) noinst_LTLIBRARIES = libr3core.la # lib_LIBRARIES = libr3.a -libr3core_la_SOURCES = node.c edge.c str.c token.c match_entry.c +libr3core_la_SOURCES = node.c edge.c str.c token.c match_entry.c slug.c if ENABLE_JSON libr3core_la_SOURCES += json.c diff --git a/src/slug.c b/src/slug.c new file mode 100644 index 0000000..1ed197c --- /dev/null +++ b/src/slug.c @@ -0,0 +1,119 @@ +/* + * slug.c + * Copyright (C) 2014 c9s + * + * Distributed under terms of the MIT license. + */ +#include +#include +#include "config.h" +#include "r3.h" +#include "r3_str.h" +#include "slug.h" +#include "zmalloc.h" + +r3_slug_t * r3_slug_new(char * path, int path_len) { + r3_slug_t * s = zmalloc(sizeof(r3_slug_t)); + s->path = path; + s->path_len = path_len; + + s->begin = NULL; + s->end = NULL; + s->len = 0; + + s->pattern = NULL; + s->pattern_len = 0; + return s; +} + +void r3_slug_free(r3_slug_t * s) { + zfree(s); +} + + +/** + * Return 1 means OK + * Return 0 means Empty + * Return -1 means Error + */ +int r3_slug_check(r3_slug_t *s, char **errstr) { + // if it's empty + if (s->begin == NULL && s->len == 0) { + return 0; + } + if (s->begin && s->begin == s->end && s->len == 0) { + return 0; + } + + // if the head is defined, we should also have end pointer + if (s->begin && s->end == NULL) { + return -1; + } + return 0; +} + + +char * r3_slug_to_str(r3_slug_t *s) { + char *str = NULL; + asprintf(&str, "slug: '%.*s', pattern: '%.*s', path: '%.*s'", s->len, s->begin, s->pattern_len, s->pattern, s->path_len, s->path); + return str; +} + + +/* +r3_slug_t * r3_slug_parse_next(r3_slug_t *s, char **errstr) { + return r3_slug_parse(s->end, s->path_len - (s->end - s->begin), errstr); +} +*/ + +r3_slug_t * r3_slug_parse(const char *needle, int needle_len, char *offset, char **errstr) { + r3_slug_t * s = r3_slug_new(needle, needle_len); + + int cnt = 0; + int state = 0; + char * p = offset; + + while( (p-needle) < needle_len) { + + if (*p == '\\' ) { + p++; p++; + } + if (state == 0 && *p == '{') { + s->begin = p+1; + } + + if (state == 1 && *p == ':') { + // start from next + s->pattern = p+1; + } + + // closing slug + if (state == 1 && *p == '}') { + s->end = p; + s->len = s->end - s->begin; + if (s->pattern) { + s->pattern_len = p - s->pattern; + } + + cnt++; + state--; + break; + } + + if ( *p == '{' ) { + state++; + } else if ( *p == '}' ) { + state--; + } + p++; + }; + + if (state > 0) { + if (errstr) { + asprintf(errstr, "incomplete slug pattern. PATH (%d): '%s', OFFSET: %ld, STATE: %d", needle_len, needle, p - needle, state); + } + return NULL; + } + + return s; +} diff --git a/src/slug.h b/src/slug.h new file mode 100644 index 0000000..afde660 --- /dev/null +++ b/src/slug.h @@ -0,0 +1,52 @@ +/* + * slug.h + * Copyright (C) 2014 c9s + * + * Distributed under terms of the MIT license. + */ +#ifndef R3_SLUG_H +#define R3_SLUG_H + +typedef struct { + /** + * source path + */ + char * path; + + int path_len; + + /** + * slug start pointer + */ + char * begin; + + /** + * slug end pointer + */ + char * end; + + /** + * slug length + */ + int len; + + // slug pattern pointer if we have one + char * pattern; + + // the length of custom pattern, if the pattern is found. + int pattern_len; + +} r3_slug_t; + + +r3_slug_t * r3_slug_new(char * path, int path_len); + +int r3_slug_check(r3_slug_t *s, char **errstr); + +r3_slug_t * r3_slug_parse(const char *needle, int needle_len, char *offset, char **errstr); + +char * r3_slug_to_str(r3_slug_t *s); + +void r3_slug_free(r3_slug_t * s); + +#endif /* !SLUG_H */ diff --git a/src/str.c b/src/str.c index 3219f73..5e708c4 100644 --- a/src/str.c +++ b/src/str.c @@ -38,90 +38,6 @@ int r3_pattern_to_opcode(const char * pattern, int len) { } -r3_slug_t * r3_slug_new(char * path, int path_len) { - r3_slug_t * s = zmalloc(sizeof(r3_slug_t)); - s->path = path; - s->path_len = path_len; - - s->begin = NULL; - s->end = NULL; - s->len = 0; - - s->pattern = NULL; - s->pattern_len = 0; - return s; -} - -void r3_slug_free(r3_slug_t * s) { - zfree(s); -} - -int r3_slug_check(r3_slug_t *s, char **errstr) { - if (s->begin == NULL) { - return 1; - } - if (s->end == NULL) { - return 1; - } - return 0; -} - - -char * r3_slug_to_str(r3_slug_t *s) { - char *str = NULL; - asprintf(&str, "slug: '%.*s', pattern: '%.*s', path: '%.*s'", s->len, s->begin, s->pattern_len, s->pattern, s->path_len, s->path); - return str; -} - - -/* -r3_slug_t * r3_slug_parse_next(r3_slug_t *s) { - r3_slug_parse(s->end, s->path_len - (s->end - s->begin), s->end; -} -*/ - - -r3_slug_t * r3_slug_parse(const char *needle, int needle_len, char **errstr) { - r3_slug_t * s = r3_slug_new(needle, needle_len); - - int cnt = 0; - int state = 0; - char * p = (char*) needle; - - while( (p-needle) < needle_len) { - - if (*p == '\\' ) { - p++; p++; - } - if (state == 0 && *p == '{') { - s->begin = p+1; - } - - if (state == 1 && *p == ':') { - // start from next - s->pattern = p+1; - } - - // closing slug - if (state == 1 && *p == '}') { - s->end = p; - s->len = s->end - s->begin; - if (s->pattern) { - s->pattern_len = p - s->pattern; - } - cnt++; - break; - } - - if ( *p == '{' ) { - state++; - } else if ( *p == '}' ) { - state--; - } - p++; - }; - return s; -} /** * provide a quick way to count slugs, simply search for '{' diff --git a/tests/Makefile.am b/tests/Makefile.am index 98334ed..fb15e51 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -6,8 +6,8 @@ # endif TESTS = -AM_CFLAGS=$(DEPS_CFLAGS) $(GVC_DEPS_CFLAGS) $(JSONC_CFLAGS) -I$(top_builddir) -I$(top_builddir)/include -I$(top_builddir)/3rdparty -Wall -std=c99 -ggdb -Wall -AM_LDFLAGS=$(DEPS_LIBS) $(GVC_DEPS_LIBS) $(JSONC_LIBS) -L$(top_builddir) -lr3 -lcheck @CHECK_LIBS@ +AM_CFLAGS=$(DEPS_CFLAGS) $(GVC_DEPS_CFLAGS) $(JSONC_CFLAGS) -I$(top_builddir) -I$(top_builddir)/include -I$(top_builddir)/src -I$(top_builddir)/3rdparty -Wall -std=c99 -ggdb -Wall +AM_LDFLAGS=$(DEPS_LIBS) $(GVC_DEPS_LIBS) $(JSONC_LIBS) -L$(top_builddir) -lcheck @CHECK_LIBS@ $(top_builddir)/libr3.la if USE_JEMALLOC AM_CFLAGS += -ljemalloc diff --git a/tests/check_slug.c b/tests/check_slug.c index e943b94..bae4d42 100644 --- a/tests/check_slug.c +++ b/tests/check_slug.c @@ -11,6 +11,7 @@ #include "r3.h" #include "r3_str.h" #include "zmalloc.h" +#include "slug.h" START_TEST (test_pattern_to_opcode) { @@ -99,7 +100,7 @@ START_TEST (test_slug_parse_with_pattern) { char * pattern = "/user/{name:\\d{3}}"; char * errstr = NULL; - r3_slug_t *s = r3_slug_parse(pattern, strlen(pattern), &errstr); + r3_slug_t *s = r3_slug_parse(pattern, strlen(pattern), pattern, &errstr); char * out = r3_slug_to_str(s); printf("%s\n",out); @@ -114,7 +115,7 @@ START_TEST (test_slug_parse_without_pattern) { char * pattern = "/user/{name}"; char * errstr = NULL; - r3_slug_t *s = r3_slug_parse(pattern, strlen(pattern), &errstr); + r3_slug_t *s = r3_slug_parse(pattern, strlen(pattern), pattern, &errstr); char * out = r3_slug_to_str(s); printf("%s\n",out);