1 /* 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 9 * 10 * http://www.apache.org/licenses/LICENSE-2.0 11 * 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 17 * under the License. 18 */ 19 20 #ifndef THRIFT_PY_TYPES_H 21 #define THRIFT_PY_TYPES_H 22 23 #include <Python.h> 24 25 #ifdef _MSC_VER 26 #define __STDC_FORMAT_MACROS 27 #define __STDC_LIMIT_MACROS 28 #endif 29 #include <stdint.h> 30 31 #if PY_MAJOR_VERSION >= 3 32 33 #include <vector> 34 35 // TODO: better macros 36 #define PyInt_AsLong(v) PyLong_AsLong(v) 37 #define PyInt_FromLong(v) PyLong_FromLong(v) 38 39 #define PyString_InternFromString(v) PyUnicode_InternFromString(v) 40 41 #endif 42 43 #define INTERN_STRING(value) _intern_##value 44 45 #define INT_CONV_ERROR_OCCURRED(v) (((v) == -1) && PyErr_Occurred()) 46 47 extern "C" { 48 extern PyObject* INTERN_STRING(TFrozenDict); 49 extern PyObject* INTERN_STRING(cstringio_buf); 50 extern PyObject* INTERN_STRING(cstringio_refill); 51 } 52 53 namespace apache { 54 namespace thrift { 55 namespace py { 56 57 extern PyObject* ThriftModule; 58 59 // Stolen out of TProtocol.h. 60 // It would be a huge pain to have both get this from one place. 61 enum TType { 62 T_INVALID = -1, 63 T_STOP = 0, 64 T_VOID = 1, 65 T_BOOL = 2, 66 T_BYTE = 3, 67 T_I08 = 3, 68 T_I16 = 6, 69 T_I32 = 8, 70 T_U64 = 9, 71 T_I64 = 10, 72 T_DOUBLE = 4, 73 T_STRING = 11, 74 T_UTF7 = 11, 75 T_STRUCT = 12, 76 T_MAP = 13, 77 T_SET = 14, 78 T_LIST = 15, 79 T_UTF8 = 16, 80 T_UTF16 = 17 81 }; 82 83 // replace with unique_ptr when we're OK with C++11 84 class ScopedPyObject { 85 public: ScopedPyObject()86 ScopedPyObject() : obj_(nullptr) {} ScopedPyObject(PyObject * py_object)87 explicit ScopedPyObject(PyObject* py_object) : obj_(py_object) {} ~ScopedPyObject()88 ~ScopedPyObject() { 89 if (obj_) 90 Py_DECREF(obj_); 91 } get()92 PyObject* get() throw() { return obj_; } 93 operator bool() { return obj_; } reset(PyObject * py_object)94 void reset(PyObject* py_object) throw() { 95 if (obj_) 96 Py_DECREF(obj_); 97 obj_ = py_object; 98 } release()99 PyObject* release() throw() { 100 PyObject* tmp = obj_; 101 obj_ = nullptr; 102 return tmp; 103 } swap(ScopedPyObject & other)104 void swap(ScopedPyObject& other) throw() { 105 ScopedPyObject tmp(other.release()); 106 other.reset(release()); 107 reset(tmp.release()); 108 } 109 110 private: ScopedPyObject(const ScopedPyObject &)111 ScopedPyObject(const ScopedPyObject&) {} 112 ScopedPyObject& operator=(const ScopedPyObject&) { return *this; } 113 114 PyObject* obj_; 115 }; 116 117 /** 118 * A cache of the two key attributes of a CReadableTransport, 119 * so we don't have to keep calling PyObject_GetAttr. 120 */ 121 struct DecodeBuffer { 122 ScopedPyObject stringiobuf; 123 ScopedPyObject refill_callable; 124 }; 125 126 #if PY_MAJOR_VERSION < 3 127 extern char refill_signature[3]; 128 typedef PyObject EncodeBuffer; 129 #else 130 extern const char* refill_signature; 131 struct EncodeBuffer { 132 std::vector<char> buf; 133 size_t pos; 134 }; 135 #endif 136 137 /** 138 * A cache of the spec_args for a set or list, 139 * so we don't have to keep calling PyTuple_GET_ITEM. 140 */ 141 struct SetListTypeArgs { 142 TType element_type; 143 PyObject* typeargs; 144 bool immutable; 145 }; 146 147 /** 148 * A cache of the spec_args for a map, 149 * so we don't have to keep calling PyTuple_GET_ITEM. 150 */ 151 struct MapTypeArgs { 152 TType ktag; 153 TType vtag; 154 PyObject* ktypeargs; 155 PyObject* vtypeargs; 156 bool immutable; 157 }; 158 159 /** 160 * A cache of the spec_args for a struct, 161 * so we don't have to keep calling PyTuple_GET_ITEM. 162 */ 163 struct StructTypeArgs { 164 PyObject* klass; 165 PyObject* spec; 166 bool immutable; 167 }; 168 169 /** 170 * A cache of the item spec from a struct specification, 171 * so we don't have to keep calling PyTuple_GET_ITEM. 172 */ 173 struct StructItemSpec { 174 int tag; 175 TType type; 176 PyObject* attrname; 177 PyObject* typeargs; 178 PyObject* defval; 179 }; 180 181 bool parse_set_list_args(SetListTypeArgs* dest, PyObject* typeargs); 182 183 bool parse_map_args(MapTypeArgs* dest, PyObject* typeargs); 184 185 bool parse_struct_args(StructTypeArgs* dest, PyObject* typeargs); 186 187 bool parse_struct_item_spec(StructItemSpec* dest, PyObject* spec_tuple); 188 } 189 } 190 } 191 192 #endif // THRIFT_PY_TYPES_H 193