move slug related functions to slug.c and slug.h
This commit is contained in:
parent
2a75861741
commit
6dfd37d43d
7 changed files with 177 additions and 127 deletions
38
include/r3.h
38
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 };
|
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
|
#ifdef ENABLE_JSON
|
||||||
json_object * r3_edge_to_json_object(const edge * e);
|
json_object * r3_edge_to_json_object(const edge * e);
|
||||||
json_object * r3_node_to_json_object(const node * n);
|
json_object * r3_node_to_json_object(const node * n);
|
||||||
|
|
|
@ -3,7 +3,7 @@ AM_LDFLAGS=$(DEPS_LIBS) $(GVC_DEPS_LIBS) $(JSONC_LIBS)
|
||||||
|
|
||||||
noinst_LTLIBRARIES = libr3core.la
|
noinst_LTLIBRARIES = libr3core.la
|
||||||
# lib_LIBRARIES = libr3.a
|
# 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
|
if ENABLE_JSON
|
||||||
libr3core_la_SOURCES += json.c
|
libr3core_la_SOURCES += json.c
|
||||||
|
|
119
src/slug.c
Normal file
119
src/slug.c
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
/*
|
||||||
|
* slug.c
|
||||||
|
* Copyright (C) 2014 c9s <c9s@c9smba.local>
|
||||||
|
*
|
||||||
|
* Distributed under terms of the MIT license.
|
||||||
|
*/
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#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;
|
||||||
|
}
|
52
src/slug.h
Normal file
52
src/slug.h
Normal file
|
@ -0,0 +1,52 @@
|
||||||
|
/*
|
||||||
|
* slug.h
|
||||||
|
* Copyright (C) 2014 c9s <c9s@c9smba.local>
|
||||||
|
*
|
||||||
|
* 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 */
|
84
src/str.c
84
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 '{'
|
* provide a quick way to count slugs, simply search for '{'
|
||||||
|
|
|
@ -6,8 +6,8 @@
|
||||||
# endif
|
# endif
|
||||||
TESTS =
|
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_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) -lr3 -lcheck @CHECK_LIBS@
|
AM_LDFLAGS=$(DEPS_LIBS) $(GVC_DEPS_LIBS) $(JSONC_LIBS) -L$(top_builddir) -lcheck @CHECK_LIBS@ $(top_builddir)/libr3.la
|
||||||
|
|
||||||
if USE_JEMALLOC
|
if USE_JEMALLOC
|
||||||
AM_CFLAGS += -ljemalloc
|
AM_CFLAGS += -ljemalloc
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include "r3.h"
|
#include "r3.h"
|
||||||
#include "r3_str.h"
|
#include "r3_str.h"
|
||||||
#include "zmalloc.h"
|
#include "zmalloc.h"
|
||||||
|
#include "slug.h"
|
||||||
|
|
||||||
START_TEST (test_pattern_to_opcode)
|
START_TEST (test_pattern_to_opcode)
|
||||||
{
|
{
|
||||||
|
@ -99,7 +100,7 @@ START_TEST (test_slug_parse_with_pattern)
|
||||||
{
|
{
|
||||||
char * pattern = "/user/{name:\\d{3}}";
|
char * pattern = "/user/{name:\\d{3}}";
|
||||||
char * errstr = NULL;
|
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);
|
char * out = r3_slug_to_str(s);
|
||||||
printf("%s\n",out);
|
printf("%s\n",out);
|
||||||
|
@ -114,7 +115,7 @@ START_TEST (test_slug_parse_without_pattern)
|
||||||
{
|
{
|
||||||
char * pattern = "/user/{name}";
|
char * pattern = "/user/{name}";
|
||||||
char * errstr = NULL;
|
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);
|
char * out = r3_slug_to_str(s);
|
||||||
printf("%s\n",out);
|
printf("%s\n",out);
|
||||||
|
|
Loading…
Reference in a new issue