source: trunk/pymigemo/pymigemo.c @ 38

Revision 38, 11.2 KB checked in by atzm, 13 years ago (diff)
  • fix copyright year
  • Property svn:keywords set to Id
RevLine 
[21]1/*
[37]2 * pymigemo.c - C/Migemo Python binding
[38]3 * Copyright(C) 2005-2010, Atzm WATANABE <atzm@atzm.org>
[21]4 *
5 * $Id$
6 */
7
8#include <Python.h>
[30]9#include <structmember.h>
10#include <migemo.h>
[34]11#include <stdbool.h>
[30]12#include <string.h>
[36]13#include <errno.h>
14#include <sys/types.h>
15#include <sys/stat.h>
16#include <fcntl.h>
17#include <unistd.h>
[21]18
[34]19#define PYMIGEMO_VERSION "0.3"
[21]20
21/* for dereference migemo object members */
[30]22struct _migemo {
23    int   enable;
24    void *mtree;
25    int   charset;
26    void *roma2hira;
27    void *hira2kata;
28    void *han2zen;
29    void *zen2han;
30    void *rx;
31    void *addword;
32    void *char2int;
[21]33};
34
35typedef struct {
[30]36    PyObject_HEAD
37    migemo *migemo_obj;
[21]38} Migemo;
39
[34]40static bool
41get_encoding(char *encoding, size_t size, int charset)
42{
43    char *enc;
44
45    switch(charset) {
46    case 1:
47        enc = "cp932";
48        break;
49    case 2:
50        enc = "euc_jp";
51        break;
52    case 3:
53        enc = "utf_8";
54        break;
55    default:
56        enc = "ascii";
57    }
58
59    if (strlen(enc) < size) {
60        strcpy(encoding, enc);
61        return true;
62    }
63
64    return false;
65}
66
[36]67static int
68isloadable(const char *path)
69{
70    struct stat st;
71    int ret = 0;
72    int fd  = open(path, O_RDONLY);
73
74    if (fd < 0) {
75        return errno;
76    }
77
78    if (fstat(fd, &st) < 0) {
79        ret = errno;
80        goto isloadable_end;
81    }
82    if (S_ISDIR(st.st_mode)) {
83        ret = EISDIR;
84        goto isloadable_end;
85    }
86
87  isloadable_end:
88    if (close(fd) < 0) {
89        ret = errno;
90    }
91    return ret;
92}
93
[21]94static void
95Migemo_dealloc(Migemo *self)
96{
[30]97    if (self->migemo_obj) {
98        migemo_close(self->migemo_obj);
99    }
[21]100
[30]101    self->ob_type->tp_free((PyObject *)self);
[21]102}
103
104static PyObject *
105Migemo_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
106{
[30]107    Migemo *self;
[21]108
[30]109    self = (Migemo *)type->tp_alloc(type, 0);
[21]110
[30]111    if (self != NULL) {
112        self->migemo_obj = NULL;
113    }
114
115    return (PyObject *)self;
[21]116}
117
118static int
119Migemo_init(Migemo *self, PyObject *args, PyObject *kwds)
120{
[30]121    migemo *migemo_obj;
122    char   *dictionary;
[21]123
[30]124    static char *kwlist[] = {"dictionary", NULL};
[21]125
[30]126    if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", kwlist, &dictionary)) {
127        return -1;
128    }
[21]129
[30]130    if (dictionary) {
[36]131        int ret = isloadable(dictionary);
132
133        if (ret != 0) {
134            PyErr_SetString(PyExc_ValueError, strerror(ret));
135            return -1;
136        }
137
[30]138        if (self->migemo_obj) {
139            migemo_close(self->migemo_obj);
140        }
[21]141
[30]142        migemo_obj = migemo_open(dictionary);
[21]143
[30]144        if (migemo_obj) {
145            self->migemo_obj = migemo_obj;
146        }
147        else {
[34]148            PyErr_SetString(PyExc_AssertionError, "migemo_open() failed");
[30]149            return -1;
150        }
151    }
152
153    return 0;
[21]154}
155
156static PyObject *
157Migemo_get_encoding(Migemo *self)
158{
[30]159    char encoding[7];
160
161    if (!get_encoding(encoding, sizeof(encoding), self->migemo_obj->charset)) {
[34]162        PyErr_SetString(PyExc_AssertionError, "get_encoding() failed");
[30]163        return NULL;
164    }
165
166    return PyString_FromString(encoding);
[21]167}
168
169static PyObject *
170Migemo_query(Migemo *self, PyObject *args, PyObject *kwds)
171{
[34]172    PyObject      *result, *pyquery, *pyrestr;
[30]173    char          *query, encoding[7];
174    unsigned char *regex;
[21]175
[30]176    static char *kwlist[] = {"query", NULL};
[21]177
[34]178    if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &pyquery)) {
[30]179        return NULL;
180    }
[21]181
[30]182    if (!get_encoding(encoding, sizeof(encoding), self->migemo_obj->charset)) {
[34]183        PyErr_SetString(PyExc_AssertionError, "get_encoding() failed");
[30]184        return NULL;
185    }
[21]186
[34]187    if (PyUnicode_Check(pyquery)) {
188        PyObject *q = PyUnicode_AsEncodedString(pyquery, encoding, "strict");
189
190        if (q == NULL) {
191            return NULL;
192        }
193
194        query = PyString_AS_STRING(q);
195        Py_DECREF(q);
[30]196    }
[34]197    else if (PyString_Check(pyquery)) {
198        query = PyString_AS_STRING(pyquery);
[30]199    }
200    else {
[34]201        PyErr_SetString(PyExc_ValueError, "argument must be string");
[30]202        return NULL;
203    }
[34]204    if (query == NULL) {
205        return NULL;
206    }
[21]207
[34]208    regex = migemo_query(self->migemo_obj, query);
209    if (regex == NULL) {
210        PyErr_SetString(PyExc_AssertionError, "migemo_query() failed");
211        return NULL;
[21]212    }
213
[34]214    pyrestr = PyString_FromString(regex);
215    migemo_release(self->migemo_obj, regex);
216    if (pyrestr == NULL) {
[30]217        return NULL;
218    }
[21]219
[34]220    result = PyUnicode_FromEncodedObject(pyrestr, encoding, "strict");
221    Py_DECREF(pyrestr);
[30]222    return result;
[21]223}
224
225static PyObject *
226Migemo_set_operator(Migemo *self, PyObject *args, PyObject *kwds)
227{
[35]228    PyObject *result = NULL;
[30]229    char     *op;
230    int       index;
[21]231 
[30]232    static char *kwlist[] = {"index", "op", NULL};
[21]233
[30]234    if (!PyArg_ParseTupleAndKeywords(args, kwds, "is", kwlist, &index, &op)) {
235        return NULL;
236    }
[21]237
[30]238    if (op) {
[34]239        result = PyBool_FromLong((long)migemo_set_operator(self->migemo_obj, index, op));
[30]240    }
[21]241
[30]242    return result;
[21]243}
244
245static PyObject *
246Migemo_get_operator(Migemo *self, PyObject *args, PyObject *kwds)
247{
[35]248    PyObject            *result = NULL;
[34]249    const unsigned char *op;
250    int                  index;
[21]251 
[30]252    static char *kwlist[] = {"index", NULL};
[21]253
[30]254    if (!PyArg_ParseTupleAndKeywords(args, kwds, "i", kwlist, &index)) {
255        return NULL;
256    }
[21]257
[30]258    if (op = migemo_get_operator(self->migemo_obj, index)) {
259        result = PyString_FromString(op);
260    }
[35]261    else {
262        PyErr_SetString(PyExc_ValueError, "invalid opindex");
[30]263    }
264
265    return result;
[21]266}
267
268static PyObject *
269Migemo_load(Migemo *self, PyObject *args, PyObject *kwds)
270{
[35]271    PyObject *result = NULL;
[30]272    char     *dict_file;
273    int       dict_id;
[21]274 
[30]275    static char *kwlist[] = {"dict_id", "dict_file", NULL};
[21]276
[30]277    if (!PyArg_ParseTupleAndKeywords(args, kwds, "is", kwlist, &dict_id, &dict_file)) {
278        return NULL;
279    }
[21]280
[30]281    if (dict_file) {
[36]282        int ret = isloadable(dict_file);
283
284        if (ret != 0) {
285            PyErr_SetString(PyExc_ValueError, strerror(ret));
286            return NULL;
287        }
288
[30]289        result = PyInt_FromLong((long)migemo_load(self->migemo_obj, dict_id, dict_file));
290    }
[21]291
[30]292    return result;
[21]293}
294
295static PyObject *
296Migemo_is_enable(Migemo *self)
297{
[34]298    return PyBool_FromLong((long)migemo_is_enable(self->migemo_obj));
[21]299}
300
301static PyMethodDef Migemo_methods[] = {
[30]302    {"query", (PyCFunction)Migemo_query, METH_KEYWORDS,
303     "return regex from romaji string\n\
[21]304\n\
305def query(query)\n\
306  query: romaji string (str or unicode)\n\
307\n\
308  returns: regex string as Unicode object"},
[30]309    {"set_operator", (PyCFunction)Migemo_set_operator, METH_KEYWORDS,
310     "set operator string as the meta character of regex\n\
[21]311\n\
312def set_operator(index, op):\n\
313  index: (OPINDEX_NEST_IN|OPINDEX_NEST_OUT|OPINDEX_NEWLINE|\n\
314          OPINDEX_OR|OPINDEX_SELECT_IN|OPINDEX_SELECT_OUT)\n\
315  op: operator string (str)\n\
316\n\
317  returns: boolean value"},
[30]318    {"get_operator", (PyCFunction)Migemo_get_operator, METH_KEYWORDS,
319     "get operator string as the meta character of regex\n\
[21]320\n\
321def get_operator(index)\n\
322  index: (OPINDEX_NEST_IN|OPINDEX_NEST_OUT|OPINDEX_NEWLINE|\n\
323          OPINDEX_OR|OPINDEX_SELECT_IN|OPINDEX_SELECT_OUT)\n\
324\n\
325  returns: operator string (str)"},
[30]326    {"load", (PyCFunction)Migemo_load, METH_KEYWORDS,
327     "add dictionary to Migemo object\n\
[21]328\n\
329def load(dict_id, dict_file)\n\
330  dict_id: (DICTID_HAN2ZEN|DICTID_HIRA2KATA|DICTID_MIGEMO|\n\
331            DICTID_ROMA2HIRA|DICTID_ZEN2HAN)\n\
332  dict_file: path to dictionary file (str)\n\
333\n\
[37]334  returns: ID of loaded dictionary"},
[30]335    {"is_enable", (PyCFunction)Migemo_is_enable, METH_NOARGS,
336     "check internal migemo_dict\n\
[21]337\n\
338def is_enable()\n\
339  returns: boolean value"},
[30]340    {"get_encoding", (PyCFunction)Migemo_get_encoding, METH_NOARGS,
341     "get dictionary encoding\n\
[21]342\n\
343def get_encoding()\n\
344  returns: encoding string (str)"},
[30]345    {NULL} /* Sentinel */
[21]346};
347
348static PyMemberDef Migemo_members[] = {
[30]349    {NULL} /* Sentinel */
[21]350};
351
352static PyTypeObject MigemoType = {
[30]353    PyObject_HEAD_INIT(NULL)
354    0,                          /*ob_size*/
355    "migemo.Migemo",            /*tp_name*/
356    sizeof(Migemo),             /*tp_basicsize*/
357    0,                          /*tp_itemsize*/
358    (destructor)Migemo_dealloc, /*tp_dealloc*/
359    0,                          /*tp_print*/
360    0,                          /*tp_getattr*/
361    0,                          /*tp_setattr*/
362    0,                          /*tp_compare*/
363    0,                          /*tp_repr*/
364    0,                          /*tp_as_number*/
365    0,                          /*tp_as_sequence*/
366    0,                          /*tp_as_mapping*/
367    0,                          /*tp_hash */
368    0,                          /*tp_call*/
369    0,                          /*tp_str*/
370    0,                          /*tp_getattro*/
371    0,                          /*tp_setattro*/
372    0,                          /*tp_as_buffer*/
373    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
[37]374    "",                         /* tp_doc */
[30]375    0,                          /* tp_traverse */
376    0,                          /* tp_clear */
377    0,                          /* tp_richcompare */
378    0,                          /* tp_weaklistoffset */
379    0,                          /* tp_iter */
380    0,                          /* tp_iternext */
381    Migemo_methods,             /* tp_methods */
382    Migemo_members,             /* tp_members */
383    0,                          /* tp_getset */
384    0,                          /* tp_base */
385    0,                          /* tp_dict */
386    0,                          /* tp_descr_get */
387    0,                          /* tp_descr_set */
388    0,                          /* tp_dictoffset */
389    (initproc)Migemo_init,      /* tp_init */
390    0,                          /* tp_alloc */
391    Migemo_new,                 /* tp_new */
[21]392};
393
394static PyMethodDef module_methods[] = {
[30]395    {NULL} /* Sentinel */
[21]396};
397
398#ifndef PyMODINIT_FUNC
399#define PyMODINIT_FUNC void
400#endif
401PyMODINIT_FUNC
402initmigemo(void) 
403{
[30]404    PyObject* m;
[21]405
[30]406    if (PyType_Ready(&MigemoType) < 0)
407        return;
[21]408
[37]409    m = Py_InitModule3("migemo", module_methods, "C/Migemo Python binding");
[21]410
[30]411    Py_INCREF(&MigemoType);
412    PyModule_AddObject(m, "Migemo", (PyObject *)&MigemoType);
413    PyModule_AddObject(m, "PYMIGEMO_VERSION", Py_BuildValue("s", PYMIGEMO_VERSION));
[21]414
[30]415    PyModule_AddObject(m, "MIGEMO_VERSION", Py_BuildValue("s", MIGEMO_VERSION));
[21]416
[30]417    PyModule_AddObject(m, "DICTID_INVALID", Py_BuildValue("i", MIGEMO_DICTID_INVALID));
418    PyModule_AddObject(m, "DICTID_MIGEMO", Py_BuildValue("i", MIGEMO_DICTID_MIGEMO));
419    PyModule_AddObject(m, "DICTID_ROMA2HIRA", Py_BuildValue("i", MIGEMO_DICTID_ROMA2HIRA));
420    PyModule_AddObject(m, "DICTID_HIRA2KATA", Py_BuildValue("i", MIGEMO_DICTID_HIRA2KATA));
421    PyModule_AddObject(m, "DICTID_HAN2ZEN", Py_BuildValue("i", MIGEMO_DICTID_HAN2ZEN));
422    PyModule_AddObject(m, "DICTID_ZEN2HAN", Py_BuildValue("i", MIGEMO_DICTID_ZEN2HAN));
[21]423
[30]424    PyModule_AddObject(m, "OPINDEX_OR", Py_BuildValue("i", MIGEMO_OPINDEX_OR));
425    PyModule_AddObject(m, "OPINDEX_NEST_IN", Py_BuildValue("i", MIGEMO_OPINDEX_NEST_IN));
426    PyModule_AddObject(m, "OPINDEX_NEST_OUT", Py_BuildValue("i", MIGEMO_OPINDEX_NEST_OUT));
427    PyModule_AddObject(m, "OPINDEX_SELECT_IN", Py_BuildValue("i", MIGEMO_OPINDEX_SELECT_IN));
428    PyModule_AddObject(m, "OPINDEX_SELECT_OUT", Py_BuildValue("i", MIGEMO_OPINDEX_SELECT_OUT));
429    PyModule_AddObject(m, "OPINDEX_NEWLINE", Py_BuildValue("i", MIGEMO_OPINDEX_NEWLINE));
[21]430}
Note: See TracBrowser for help on using the repository browser.