Skip to content

Commit cd582ce

Browse files
author
vagrant
committed
add compile, insert_path, match method to pyr3
1 parent 7a7f822 commit cd582ce

File tree

5 files changed

+290
-0
lines changed

5 files changed

+290
-0
lines changed

.gitmodules

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "r3"]
2+
path = r3
3+
url = https://github.com/c9s/r3

pyr3.c

+237
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,237 @@
1+
#include <Python.h>
2+
#include "structmember.h"
3+
#include "r3.h"
4+
#include "r3_str.h"
5+
#include "str_array.h"
6+
7+
typedef struct link_data{
8+
PyObject* data;
9+
struct link_data* link;
10+
} LINK_NODE;
11+
12+
typedef struct {
13+
PyObject_HEAD
14+
node *root;
15+
LINK_NODE* datas;
16+
} R3Tree;
17+
18+
19+
LINK_NODE *new_node(PyObject* data){
20+
LINK_NODE *node;
21+
node=(LINK_NODE *) malloc(sizeof(LINK_NODE));/*<stdlib.h>*/
22+
23+
// 記憶體不足
24+
if(node == NULL){ return NULL;}
25+
26+
node->data=data;
27+
node->link=NULL;
28+
return node;
29+
}
30+
31+
/* 加入新的資料於最後 */
32+
LINK_NODE *push_node(LINK_NODE *list, PyObject* data){
33+
/*產生新節點*/
34+
LINK_NODE *node=new_node(data);
35+
36+
// 加入第一個新節點
37+
if(list==NULL){
38+
list=node;
39+
} else{
40+
LINK_NODE *p=list;
41+
// 取得最後一個節點
42+
while(p->link!=NULL){p=p->link;}
43+
p->link=node;
44+
}
45+
return list;
46+
}
47+
48+
49+
static void clean_data(R3Tree* tree) {
50+
LINK_NODE *node = tree->datas, *next_node=NULL;
51+
52+
while (node!=NULL) {
53+
Py_XDECREF(node->data);
54+
next_node = node->link;
55+
free(node);
56+
node = next_node;
57+
}
58+
tree->datas = NULL;
59+
}
60+
61+
static void
62+
R3Tree_dealloc(R3Tree* self)
63+
{
64+
int i=0;
65+
if(self->root != NULL) {
66+
clean_data(self);
67+
r3_tree_free(self->root);
68+
}
69+
self->root = NULL;
70+
self->datas = NULL;
71+
self->ob_type->tp_free((PyObject*)self);
72+
}
73+
74+
static PyObject *
75+
R3Tree_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
76+
{
77+
R3Tree *self;
78+
79+
self = (R3Tree *)type->tp_alloc(type, 0);
80+
if (self != NULL) {
81+
self->root = r3_tree_create(255);
82+
self->datas = new_node(NULL);
83+
}
84+
85+
return (PyObject *)self;
86+
}
87+
88+
89+
static int
90+
R3Tree_init(R3Tree *self, PyObject *args, PyObject *kwds)
91+
{
92+
// TODO: may need to add init here
93+
return 0;
94+
}
95+
96+
static PyObject *
97+
R3Tree_insert_path(R3Tree* self, PyObject *args, PyObject *kwds)
98+
{
99+
//http://stackoverflow.com/questions/9896032/how-to-get-a-char-from-a-pyobject-which-points-to-a-string
100+
PyObject* path = NULL, *data = NULL;
101+
102+
static char *kwlist[] = {"path", "data", NULL};
103+
104+
if (! PyArg_ParseTupleAndKeywords(args, kwds, "|OO", kwlist,
105+
&path, &data))
106+
return NULL ;
107+
108+
if (path == NULL) {
109+
PyErr_SetString(PyExc_AttributeError, "path");
110+
return NULL;
111+
}
112+
if (data == NULL) {
113+
PyErr_SetString(PyExc_AttributeError, "data");
114+
return NULL;
115+
}
116+
117+
Py_XINCREF(data);
118+
push_node(self->datas, data);
119+
PyObject* objectsRepresentation = PyObject_Repr(path);
120+
const char* s = PyString_AsString(objectsRepresentation);
121+
122+
r3_tree_insert_path(self->root, s, data);
123+
124+
// return None
125+
// http://code.activestate.com/recipes/52309-to-return-none-from-your-python-callable-c-functio/
126+
return Py_None;
127+
}
128+
129+
static PyObject*
130+
R3Tree_compile(R3Tree* self) {
131+
char *errstr = NULL;
132+
int err = r3_tree_compile(self->root, &errstr);
133+
return Py_None;
134+
}
135+
136+
static PyObject*
137+
R3Tree_match(R3Tree* self, PyObject *args, PyObject *kwds)
138+
{
139+
PyObject* path = NULL;
140+
141+
static char *kwlist[] = {"path", NULL};
142+
143+
if (! PyArg_ParseTupleAndKeywords(args, kwds, "|O", kwlist,
144+
&path))
145+
return NULL ;
146+
147+
if(path == NULL) {
148+
PyErr_SetString(PyExc_AttributeError, "path");
149+
return NULL;
150+
}
151+
152+
PyObject* objectsRepresentation = PyObject_Repr(path);
153+
const char* s = PyString_AsString(objectsRepresentation);
154+
155+
156+
node* match_node = r3_tree_match(self->root, s, NULL);
157+
if(match_node != NULL) {
158+
return match_node->data;
159+
}
160+
161+
return Py_None;
162+
}
163+
164+
// https://docs.python.org/2/c-api/structures.html#PyMethodDef
165+
static PyMethodDef R3Tree_methods[] = {
166+
{"insert_path", (PyCFunction)R3Tree_insert_path, METH_KEYWORDS,
167+
"Return the name, combining the first and last name"},
168+
{"compile", (PyCFunction)R3Tree_compile, METH_NOARGS,
169+
"compile"},
170+
{"match", (PyCFunction)R3Tree_match, METH_KEYWORDS,
171+
"match"},
172+
{NULL} /* Sentinel */
173+
};
174+
175+
176+
static PyTypeObject r3_TreeType = {
177+
PyObject_HEAD_INIT(NULL)
178+
0, /*ob_size*/
179+
"pyr3.R3Tree", /*tp_name*/
180+
sizeof(R3Tree), /*tp_basicsize*/
181+
0, /*tp_itemsize*/
182+
(destructor)R3Tree_dealloc,/*tp_dealloc*/
183+
0, /*tp_print*/
184+
0, /*tp_getattr*/
185+
0, /*tp_setattr*/
186+
0, /*tp_compare*/
187+
0, /*tp_repr*/
188+
0, /*tp_as_number*/
189+
0, /*tp_as_sequence*/
190+
0, /*tp_as_mapping*/
191+
0, /*tp_hash */
192+
0, /*tp_call*/
193+
0, /*tp_str*/
194+
0, /*tp_getattro*/
195+
0, /*tp_setattro*/
196+
0, /*tp_as_buffer*/
197+
Py_TPFLAGS_DEFAULT, /*tp_flags*/
198+
"R3 objects", /* tp_doc */
199+
0, /* tp_traverse */
200+
0, /* tp_clear */
201+
0, /* tp_richcompare */
202+
0, /* tp_weaklistoffset */
203+
0, /* tp_iter */
204+
0, /* tp_iternext */
205+
R3Tree_methods, /* tp_methods */
206+
0, /* tp_members */
207+
0, /* tp_getset */
208+
0, /* tp_base */
209+
0, /* tp_dict */
210+
0, /* tp_descr_get */
211+
0, /* tp_descr_set */
212+
0, /* tp_dictoffset */
213+
(initproc)R3Tree_init, /* tp_init */
214+
0, /* tp_alloc */
215+
R3Tree_new, /* tp_new */
216+
};
217+
218+
static PyMethodDef r3_methods[] = {
219+
{NULL} /* Sentinel */
220+
};
221+
222+
#ifndef PyMODINIT_FUNC /* declarations for DLL import/export */
223+
#define PyMODINIT_FUNC void
224+
#endif
225+
PyMODINIT_FUNC
226+
initpyr3(void)
227+
{
228+
PyObject* m;
229+
if (PyType_Ready(&r3_TreeType) < 0)
230+
return;
231+
232+
m = Py_InitModule3("pyr3", r3_methods,
233+
"Python wrapper for r3");
234+
235+
Py_INCREF(&r3_TreeType);
236+
PyModule_AddObject(m, "R3Tree", (PyObject *)&r3_TreeType);
237+
}

r3

Submodule r3 added at 8e3a35b

setup.py

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
from distutils.core import setup, Extension
2+
setup(name="pyr3", version="1.0",
3+
ext_modules=[Extension(
4+
"pyr3",
5+
["pyr3.c"],
6+
libraries=["pcre","r3"],
7+
include_dirs=['./r3/include', './r3'],
8+
library_dirs=['/usr/local/lib'],
9+
runtime_library_dirs=['/usr/local/lib']
10+
)])
11+
12+
try:
13+
import pyr3
14+
r = pyr3.R3Tree()
15+
print r
16+
print dir(r)
17+
r.insert_path(path="/bar", data=0)
18+
r.insert_path(path="/zoo", data=1)
19+
r.insert_path(path="/foo/bar", data='123')
20+
r.compile()
21+
22+
print r.match('/foo/bar')
23+
except:
24+
raise
25+
finally:
26+
import os
27+
os.remove('pyr3.so')

test.py

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
def setup():
2+
import noddy
3+
r = noddy.R3Tree()
4+
print r
5+
print dir(r)
6+
r.insert_path(path="/bar", data='4')
7+
r.insert_path(path="/zoo", data='5')
8+
r.insert_path(path="/foo/bar", data='123')
9+
r.compile()
10+
return r
11+
12+
def run(r):
13+
return r.match('/foo/bar')
14+
15+
# if __name__ == "__main__":
16+
# import timeit
17+
# t = timeit.Timer('run(r)', setup='from __main__ import setup, run; r = setup()')
18+
# print t.timeit()
19+
20+
r = setup()
21+
for i in xrange(10000):
22+
run(r)

0 commit comments

Comments
 (0)