2 * Licensed to the Apache Software Foundation (ASF) under one
3 * or more contributor license agreements. See the NOTICE file
4 * distributed with this work for additional information
5 * regarding copyright ownership. The ASF licenses this file
6 * to you under the Apache License, Version 2.0 (the
7 * "License"); you may not use this file except in compliance
8 * with the License. You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing,
13 * software distributed under the License is distributed on an
14 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15 * KIND, either express or implied. See the License for the
16 * specific language governing permissions and limitations
27 // TODO(dreiss): defval appears to be unused. Look into removing it.
28 // TODO(dreiss): Make parse_spec_args recursive, and cache the output
29 // permanently in the object. (Malloc and orphan.)
30 // TODO(dreiss): Why do we need cStringIO for reading, why not just char*?
31 // Can cStringIO let us work with a BufferedTransport?
32 // TODO(dreiss): Don't ignore the rv from cwrite (maybe).
34 // Doing a benchmark shows that interning actually makes a difference, amazingly.
36 /** Pointer to interned string to speed up attribute lookup. */
37 PyObject
* INTERN_STRING(TFrozenDict
);
38 PyObject
* INTERN_STRING(cstringio_buf
);
39 PyObject
* INTERN_STRING(cstringio_refill
);
40 static PyObject
* INTERN_STRING(string_length_limit
);
41 static PyObject
* INTERN_STRING(container_length_limit
);
42 static PyObject
* INTERN_STRING(trans
);
49 static PyObject
* encode_impl(PyObject
* args
) {
53 PyObject
* enc_obj
= NULL
;
54 PyObject
* type_args
= NULL
;
55 if (!PyArg_ParseTuple(args
, "OO", &enc_obj
, &type_args
)) {
58 if (!enc_obj
|| !type_args
) {
63 if (!protocol
.prepareEncodeBuffer() || !protocol
.encodeValue(enc_obj
, T_STRUCT
, type_args
)) {
67 return protocol
.getEncodedValue();
70 static inline long as_long_then_delete(PyObject
* value
, long default_value
) {
71 ScopedPyObject
scope(value
);
72 long v
= PyInt_AsLong(value
);
73 if (INT_CONV_ERROR_OCCURRED(v
)) {
81 static PyObject
* decode_impl(PyObject
* args
) {
82 PyObject
* output_obj
= NULL
;
83 PyObject
* oprot
= NULL
;
84 PyObject
* typeargs
= NULL
;
85 if (!PyArg_ParseTuple(args
, "OOO", &output_obj
, &oprot
, &typeargs
)) {
90 int32_t default_limit
= (std::numeric_limits
<int32_t>::max
)();
91 protocol
.setStringLengthLimit(
92 as_long_then_delete(PyObject_GetAttr(oprot
, INTERN_STRING(string_length_limit
)),
94 protocol
.setContainerLengthLimit(
95 as_long_then_delete(PyObject_GetAttr(oprot
, INTERN_STRING(container_length_limit
)),
97 ScopedPyObject
transport(PyObject_GetAttr(oprot
, INTERN_STRING(trans
)));
102 StructTypeArgs parsedargs
;
103 if (!parse_struct_args(&parsedargs
, typeargs
)) {
107 if (!protocol
.prepareDecodeBufferFromTransport(transport
.get())) {
111 return protocol
.readStruct(output_obj
, parsedargs
.klass
, parsedargs
.spec
);
117 using namespace apache::thrift::py
;
119 /* -- PYTHON MODULE SETUP STUFF --- */
123 static PyObject
* encode_binary(PyObject
*, PyObject
* args
) {
124 return encode_impl
<BinaryProtocol
>(args
);
127 static PyObject
* decode_binary(PyObject
*, PyObject
* args
) {
128 return decode_impl
<BinaryProtocol
>(args
);
131 static PyObject
* encode_compact(PyObject
*, PyObject
* args
) {
132 return encode_impl
<CompactProtocol
>(args
);
135 static PyObject
* decode_compact(PyObject
*, PyObject
* args
) {
136 return decode_impl
<CompactProtocol
>(args
);
139 static PyMethodDef ThriftFastBinaryMethods
[] = {
140 {"encode_binary", encode_binary
, METH_VARARGS
, ""},
141 {"decode_binary", decode_binary
, METH_VARARGS
, ""},
142 {"encode_compact", encode_compact
, METH_VARARGS
, ""},
143 {"decode_compact", decode_compact
, METH_VARARGS
, ""},
144 {NULL
, NULL
, 0, NULL
} /* Sentinel */
147 #if PY_MAJOR_VERSION >= 3
149 static struct PyModuleDef ThriftFastBinaryDef
= {PyModuleDef_HEAD_INIT
,
150 "thrift.protocol.fastbinary",
153 ThriftFastBinaryMethods
,
159 #define INITERROR return NULL;
161 PyObject
* PyInit_fastbinary() {
165 #define INITERROR return;
167 void initfastbinary() {
170 if (PycStringIO
== NULL
)
175 #define INIT_INTERN_STRING(value) \
177 INTERN_STRING(value) = PyString_InternFromString(#value); \
178 if (!INTERN_STRING(value)) \
182 INIT_INTERN_STRING(TFrozenDict
);
183 INIT_INTERN_STRING(cstringio_buf
);
184 INIT_INTERN_STRING(cstringio_refill
);
185 INIT_INTERN_STRING(string_length_limit
);
186 INIT_INTERN_STRING(container_length_limit
);
187 INIT_INTERN_STRING(trans
);
188 #undef INIT_INTERN_STRING
191 #if PY_MAJOR_VERSION >= 3
192 PyModule_Create(&ThriftFastBinaryDef
);
194 Py_InitModule("thrift.protocol.fastbinary", ThriftFastBinaryMethods
);
199 #if PY_MAJOR_VERSION >= 3