1 /*
2 * module.c - optimizations for various parts of py-postgresql
3 *
4 * This module.c file ties together other classified C source.
5 * Each filename describing the part of the protocol package that it
6 * covers. It merely uses CPP includes to bring them into this
7 * file and then uses some CPP macros to expand the definitions
8 * in each file.
9 */
10 #include <Python.h>
11 #include <structmember.h>
12 /*
13 * If Python didn't find it, it won't include it.
14 * However, it's quite necessary.
15 */
16 #ifndef HAVE_STDINT_H
17 #include <stdint.h>
18 #endif
19
20 #define USHORT_MAX ((1<<16)-1)
21 #define SHORT_MAX ((1<<15)-1)
22 #define SHORT_MIN (-(1<<15))
23
24 #define PyObject_TypeName(ob) \
25 (((PyTypeObject *) (ob->ob_type))->tp_name)
26
27 /*
28 * buffer.c needs the message_types object from .protocol.message_types.
29 * Initialized in PyInit_optimized.
30 */
31 static PyObject *message_types = NULL;
32 static PyObject *serialize_strob = NULL;
33 static PyObject *msgtype_strob = NULL;
34
35 static int32_t (*local_ntohl)(int32_t) = NULL;
36 static short (*local_ntohs)(short) = NULL;
37
38 /*
39 * optimized module contents
40 */
41 #include "structlib.c"
42 #include "functools.c"
43 #include "buffer.c"
44 #include "wirestate.c"
45 #include "element3.c"
46
47
48 /* cpp abuse, read up on X-Macros if you don't understand */
49 #define mFUNC(name, typ, doc) \
50 {#name, (PyCFunction) name, typ, PyDoc_STR(doc)},
51 static PyMethodDef optimized_methods[] = {
52 include_element3_functions
53 include_structlib_functions
54 include_functools_functions
55 {NULL}
56 };
57 #undef mFUNC
58
59 static struct PyModuleDef optimized_module = {
60 PyModuleDef_HEAD_INIT,
61 "optimized", /* name of module */
62 NULL, /* module documentation, may be NULL */
63 -1, /* size of per-interpreter state of the module,
64 or -1 if the module keeps state in global variables. */
65 optimized_methods,
66 };
67
68 PyMODINIT_FUNC
PyInit_optimized(void)69 PyInit_optimized(void)
70 {
71 PyObject *mod;
72 PyObject *msgtypes;
73 PyObject *fromlist, *fromstr;
74 long l;
75
76 /* make some constants */
77 if (serialize_strob == NULL)
78 {
79 serialize_strob = PyUnicode_FromString("serialize");
80 if (serialize_strob == NULL)
81 return(NULL);
82 }
83 if (msgtype_strob == NULL)
84 {
85 msgtype_strob = PyUnicode_FromString("type");
86 if (msgtype_strob == NULL)
87 return(NULL);
88 }
89
90 mod = PyModule_Create(&optimized_module);
91 if (mod == NULL)
92 return(NULL);
93
94 /* cpp abuse; ready types */
95 #define mTYPE(name) \
96 if (PyType_Ready(&name##_Type) < 0) \
97 goto cleanup; \
98 if (PyModule_AddObject(mod, #name, \
99 (PyObject *) &name##_Type) < 0) \
100 goto cleanup;
101
102 /* buffer.c */
103 include_buffer_types
104 /* wirestate.c */
105 include_wirestate_types
106 #undef mTYPE
107
108 l = 1;
109 if (((char *) &l)[0] == 1)
110 {
111 /* little */
112 local_ntohl = swap_int4;
113 local_ntohs = swap_short;
114 }
115 else
116 {
117 /* big */
118 local_ntohl = return_int4;
119 local_ntohs = return_short;
120 }
121
122 /*
123 * Get the message_types tuple to type "instantiation".
124 */
125 fromlist = PyList_New(1);
126 fromstr = PyUnicode_FromString("message_types");
127 PyList_SetItem(fromlist, 0, fromstr);
128 msgtypes = PyImport_ImportModuleLevel(
129 "protocol.message_types",
130 PyModule_GetDict(mod),
131 PyModule_GetDict(mod),
132 fromlist, 2
133 );
134 Py_DECREF(fromlist);
135 if (msgtypes == NULL)
136 goto cleanup;
137 message_types = PyObject_GetAttrString(msgtypes, "message_types");
138 Py_DECREF(msgtypes);
139
140 if (!PyObject_IsInstance(message_types, (PyObject *) (&PyTuple_Type)))
141 {
142 PyErr_SetString(PyExc_RuntimeError,
143 "local protocol.message_types.message_types is not a tuple object");
144 goto cleanup;
145 }
146
147 return(mod);
148 cleanup:
149 Py_DECREF(mod);
150 return(NULL);
151 }
152 /*
153 * vim: ts=3:sw=3:noet:
154 */
155