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