Checking in vendor folder for ease of using go get.
This commit is contained in:
parent
7a1251853b
commit
cdb4b5a1d0
3554 changed files with 1270116 additions and 0 deletions
38
vendor/git.apache.org/thrift.git/lib/py/src/ext/binary.cpp
generated
vendored
Normal file
38
vendor/git.apache.org/thrift.git/lib/py/src/ext/binary.cpp
generated
vendored
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include "ext/binary.h"
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace py {
|
||||
|
||||
bool BinaryProtocol::readFieldBegin(TType& type, int16_t& tag) {
|
||||
uint8_t b = 0;
|
||||
if (!readByte(b)) {
|
||||
return false;
|
||||
}
|
||||
type = static_cast<TType>(b);
|
||||
if (type == T_STOP) {
|
||||
return true;
|
||||
}
|
||||
return readI16(tag);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
214
vendor/git.apache.org/thrift.git/lib/py/src/ext/binary.h
generated
vendored
Normal file
214
vendor/git.apache.org/thrift.git/lib/py/src/ext/binary.h
generated
vendored
Normal file
|
@ -0,0 +1,214 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef THRIFT_PY_BINARY_H
|
||||
#define THRIFT_PY_BINARY_H
|
||||
|
||||
#include <Python.h>
|
||||
#include "ext/protocol.h"
|
||||
#include "ext/endian.h"
|
||||
#include <stdint.h>
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace py {
|
||||
|
||||
class BinaryProtocol : public ProtocolBase<BinaryProtocol> {
|
||||
public:
|
||||
virtual ~BinaryProtocol() {}
|
||||
|
||||
void writeI8(int8_t val) { writeBuffer(reinterpret_cast<char*>(&val), sizeof(int8_t)); }
|
||||
|
||||
void writeI16(int16_t val) {
|
||||
int16_t net = static_cast<int16_t>(htons(val));
|
||||
writeBuffer(reinterpret_cast<char*>(&net), sizeof(int16_t));
|
||||
}
|
||||
|
||||
void writeI32(int32_t val) {
|
||||
int32_t net = static_cast<int32_t>(htonl(val));
|
||||
writeBuffer(reinterpret_cast<char*>(&net), sizeof(int32_t));
|
||||
}
|
||||
|
||||
void writeI64(int64_t val) {
|
||||
int64_t net = static_cast<int64_t>(htonll(val));
|
||||
writeBuffer(reinterpret_cast<char*>(&net), sizeof(int64_t));
|
||||
}
|
||||
|
||||
void writeDouble(double dub) {
|
||||
// Unfortunately, bitwise_cast doesn't work in C. Bad C!
|
||||
union {
|
||||
double f;
|
||||
int64_t t;
|
||||
} transfer;
|
||||
transfer.f = dub;
|
||||
writeI64(transfer.t);
|
||||
}
|
||||
|
||||
void writeBool(int v) { writeByte(static_cast<uint8_t>(v)); }
|
||||
|
||||
void writeString(PyObject* value, int32_t len) {
|
||||
writeI32(len);
|
||||
writeBuffer(PyBytes_AS_STRING(value), len);
|
||||
}
|
||||
|
||||
bool writeListBegin(PyObject* value, const SetListTypeArgs& parsedargs, int32_t len) {
|
||||
writeByte(parsedargs.element_type);
|
||||
writeI32(len);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool writeMapBegin(PyObject* value, const MapTypeArgs& parsedargs, int32_t len) {
|
||||
writeByte(parsedargs.ktag);
|
||||
writeByte(parsedargs.vtag);
|
||||
writeI32(len);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool writeStructBegin() { return true; }
|
||||
bool writeStructEnd() { return true; }
|
||||
bool writeField(PyObject* value, const StructItemSpec& parsedspec) {
|
||||
writeByte(static_cast<uint8_t>(parsedspec.type));
|
||||
writeI16(parsedspec.tag);
|
||||
return encodeValue(value, parsedspec.type, parsedspec.typeargs);
|
||||
}
|
||||
|
||||
void writeFieldStop() { writeByte(static_cast<uint8_t>(T_STOP)); }
|
||||
|
||||
bool readBool(bool& val) {
|
||||
char* buf;
|
||||
if (!readBytes(&buf, 1)) {
|
||||
return false;
|
||||
}
|
||||
val = buf[0] == 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool readI8(int8_t& val) {
|
||||
char* buf;
|
||||
if (!readBytes(&buf, 1)) {
|
||||
return false;
|
||||
}
|
||||
val = buf[0];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool readI16(int16_t& val) {
|
||||
char* buf;
|
||||
if (!readBytes(&buf, sizeof(int16_t))) {
|
||||
return false;
|
||||
}
|
||||
val = static_cast<int16_t>(ntohs(*reinterpret_cast<int16_t*>(buf)));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool readI32(int32_t& val) {
|
||||
char* buf;
|
||||
if (!readBytes(&buf, sizeof(int32_t))) {
|
||||
return false;
|
||||
}
|
||||
val = static_cast<int32_t>(ntohl(*reinterpret_cast<int32_t*>(buf)));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool readI64(int64_t& val) {
|
||||
char* buf;
|
||||
if (!readBytes(&buf, sizeof(int64_t))) {
|
||||
return false;
|
||||
}
|
||||
val = static_cast<int64_t>(ntohll(*reinterpret_cast<int64_t*>(buf)));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool readDouble(double& val) {
|
||||
union {
|
||||
int64_t f;
|
||||
double t;
|
||||
} transfer;
|
||||
|
||||
if (!readI64(transfer.f)) {
|
||||
return false;
|
||||
}
|
||||
val = transfer.t;
|
||||
return true;
|
||||
}
|
||||
|
||||
int32_t readString(char** buf) {
|
||||
int32_t len = 0;
|
||||
if (!readI32(len) || !checkLengthLimit(len, stringLimit()) || !readBytes(buf, len)) {
|
||||
return -1;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
int32_t readListBegin(TType& etype) {
|
||||
int32_t len;
|
||||
uint8_t b = 0;
|
||||
if (!readByte(b) || !readI32(len) || !checkLengthLimit(len, containerLimit())) {
|
||||
return -1;
|
||||
}
|
||||
etype = static_cast<TType>(b);
|
||||
return len;
|
||||
}
|
||||
|
||||
int32_t readMapBegin(TType& ktype, TType& vtype) {
|
||||
int32_t len;
|
||||
uint8_t k, v;
|
||||
if (!readByte(k) || !readByte(v) || !readI32(len) || !checkLengthLimit(len, containerLimit())) {
|
||||
return -1;
|
||||
}
|
||||
ktype = static_cast<TType>(k);
|
||||
vtype = static_cast<TType>(v);
|
||||
return len;
|
||||
}
|
||||
|
||||
bool readStructBegin() { return true; }
|
||||
bool readStructEnd() { return true; }
|
||||
|
||||
bool readFieldBegin(TType& type, int16_t& tag);
|
||||
|
||||
#define SKIPBYTES(n) \
|
||||
do { \
|
||||
if (!readBytes(&dummy_buf_, (n))) { \
|
||||
return false; \
|
||||
} \
|
||||
return true; \
|
||||
} while (0)
|
||||
|
||||
bool skipBool() { SKIPBYTES(1); }
|
||||
bool skipByte() { SKIPBYTES(1); }
|
||||
bool skipI16() { SKIPBYTES(2); }
|
||||
bool skipI32() { SKIPBYTES(4); }
|
||||
bool skipI64() { SKIPBYTES(8); }
|
||||
bool skipDouble() { SKIPBYTES(8); }
|
||||
bool skipString() {
|
||||
int32_t len;
|
||||
if (!readI32(len)) {
|
||||
return false;
|
||||
}
|
||||
SKIPBYTES(len);
|
||||
}
|
||||
#undef SKIPBYTES
|
||||
|
||||
private:
|
||||
char* dummy_buf_;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // THRIFT_PY_BINARY_H
|
107
vendor/git.apache.org/thrift.git/lib/py/src/ext/compact.cpp
generated
vendored
Normal file
107
vendor/git.apache.org/thrift.git/lib/py/src/ext/compact.cpp
generated
vendored
Normal file
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include "ext/compact.h"
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace py {
|
||||
|
||||
const uint8_t CompactProtocol::TTypeToCType[] = {
|
||||
CT_STOP, // T_STOP
|
||||
0, // unused
|
||||
CT_BOOLEAN_TRUE, // T_BOOL
|
||||
CT_BYTE, // T_BYTE
|
||||
CT_DOUBLE, // T_DOUBLE
|
||||
0, // unused
|
||||
CT_I16, // T_I16
|
||||
0, // unused
|
||||
CT_I32, // T_I32
|
||||
0, // unused
|
||||
CT_I64, // T_I64
|
||||
CT_BINARY, // T_STRING
|
||||
CT_STRUCT, // T_STRUCT
|
||||
CT_MAP, // T_MAP
|
||||
CT_SET, // T_SET
|
||||
CT_LIST, // T_LIST
|
||||
};
|
||||
|
||||
bool CompactProtocol::readFieldBegin(TType& type, int16_t& tag) {
|
||||
uint8_t b;
|
||||
if (!readByte(b)) {
|
||||
return false;
|
||||
}
|
||||
uint8_t ctype = b & 0xf;
|
||||
type = getTType(ctype);
|
||||
if (type == -1) {
|
||||
return false;
|
||||
} else if (type == T_STOP) {
|
||||
tag = 0;
|
||||
return true;
|
||||
}
|
||||
uint8_t diff = (b & 0xf0) >> 4;
|
||||
if (diff) {
|
||||
tag = readTags_.top() + diff;
|
||||
} else if (!readI16(tag)) {
|
||||
readTags_.top() = -1;
|
||||
return false;
|
||||
}
|
||||
if (ctype == CT_BOOLEAN_FALSE || ctype == CT_BOOLEAN_TRUE) {
|
||||
readBool_.exists = true;
|
||||
readBool_.value = ctype == CT_BOOLEAN_TRUE;
|
||||
}
|
||||
readTags_.top() = tag;
|
||||
return true;
|
||||
}
|
||||
|
||||
TType CompactProtocol::getTType(uint8_t type) {
|
||||
switch (type) {
|
||||
case T_STOP:
|
||||
return T_STOP;
|
||||
case CT_BOOLEAN_FALSE:
|
||||
case CT_BOOLEAN_TRUE:
|
||||
return T_BOOL;
|
||||
case CT_BYTE:
|
||||
return T_BYTE;
|
||||
case CT_I16:
|
||||
return T_I16;
|
||||
case CT_I32:
|
||||
return T_I32;
|
||||
case CT_I64:
|
||||
return T_I64;
|
||||
case CT_DOUBLE:
|
||||
return T_DOUBLE;
|
||||
case CT_BINARY:
|
||||
return T_STRING;
|
||||
case CT_LIST:
|
||||
return T_LIST;
|
||||
case CT_SET:
|
||||
return T_SET;
|
||||
case CT_MAP:
|
||||
return T_MAP;
|
||||
case CT_STRUCT:
|
||||
return T_STRUCT;
|
||||
default:
|
||||
PyErr_Format(PyExc_TypeError, "don't know what type: %d", type);
|
||||
return static_cast<TType>(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
367
vendor/git.apache.org/thrift.git/lib/py/src/ext/compact.h
generated
vendored
Normal file
367
vendor/git.apache.org/thrift.git/lib/py/src/ext/compact.h
generated
vendored
Normal file
|
@ -0,0 +1,367 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef THRIFT_PY_COMPACT_H
|
||||
#define THRIFT_PY_COMPACT_H
|
||||
|
||||
#include <Python.h>
|
||||
#include "ext/protocol.h"
|
||||
#include "ext/endian.h"
|
||||
#include <stdint.h>
|
||||
#include <stack>
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace py {
|
||||
|
||||
class CompactProtocol : public ProtocolBase<CompactProtocol> {
|
||||
public:
|
||||
CompactProtocol() { readBool_.exists = false; }
|
||||
|
||||
virtual ~CompactProtocol() {}
|
||||
|
||||
void writeI8(int8_t val) { writeBuffer(reinterpret_cast<char*>(&val), 1); }
|
||||
|
||||
void writeI16(int16_t val) { writeVarint(toZigZag(val)); }
|
||||
|
||||
int writeI32(int32_t val) { return writeVarint(toZigZag(val)); }
|
||||
|
||||
void writeI64(int64_t val) { writeVarint64(toZigZag64(val)); }
|
||||
|
||||
void writeDouble(double dub) {
|
||||
union {
|
||||
double f;
|
||||
int64_t t;
|
||||
} transfer;
|
||||
transfer.f = htolell(dub);
|
||||
writeBuffer(reinterpret_cast<char*>(&transfer.t), sizeof(int64_t));
|
||||
}
|
||||
|
||||
void writeBool(int v) { writeByte(static_cast<uint8_t>(v ? CT_BOOLEAN_TRUE : CT_BOOLEAN_FALSE)); }
|
||||
|
||||
void writeString(PyObject* value, int32_t len) {
|
||||
writeVarint(len);
|
||||
writeBuffer(PyBytes_AS_STRING(value), len);
|
||||
}
|
||||
|
||||
bool writeListBegin(PyObject* value, const SetListTypeArgs& args, int32_t len) {
|
||||
int ctype = toCompactType(args.element_type);
|
||||
if (len <= 14) {
|
||||
writeByte(static_cast<uint8_t>(len << 4 | ctype));
|
||||
} else {
|
||||
writeByte(0xf0 | ctype);
|
||||
writeVarint(len);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool writeMapBegin(PyObject* value, const MapTypeArgs& args, int32_t len) {
|
||||
if (len == 0) {
|
||||
writeByte(0);
|
||||
return true;
|
||||
}
|
||||
int ctype = toCompactType(args.ktag) << 4 | toCompactType(args.vtag);
|
||||
writeVarint(len);
|
||||
writeByte(ctype);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool writeStructBegin() {
|
||||
writeTags_.push(0);
|
||||
return true;
|
||||
}
|
||||
bool writeStructEnd() {
|
||||
writeTags_.pop();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool writeField(PyObject* value, const StructItemSpec& spec) {
|
||||
if (spec.type == T_BOOL) {
|
||||
doWriteFieldBegin(spec, PyObject_IsTrue(value) ? CT_BOOLEAN_TRUE : CT_BOOLEAN_FALSE);
|
||||
return true;
|
||||
} else {
|
||||
doWriteFieldBegin(spec, toCompactType(spec.type));
|
||||
return encodeValue(value, spec.type, spec.typeargs);
|
||||
}
|
||||
}
|
||||
|
||||
void writeFieldStop() { writeByte(0); }
|
||||
|
||||
bool readBool(bool& val) {
|
||||
if (readBool_.exists) {
|
||||
readBool_.exists = false;
|
||||
val = readBool_.value;
|
||||
return true;
|
||||
}
|
||||
char* buf;
|
||||
if (!readBytes(&buf, 1)) {
|
||||
return false;
|
||||
}
|
||||
val = buf[0] == CT_BOOLEAN_TRUE;
|
||||
return true;
|
||||
}
|
||||
bool readI8(int8_t& val) {
|
||||
char* buf;
|
||||
if (!readBytes(&buf, 1)) {
|
||||
return false;
|
||||
}
|
||||
val = buf[0];
|
||||
return true;
|
||||
}
|
||||
|
||||
bool readI16(int16_t& val) {
|
||||
uint16_t uval;
|
||||
if (readVarint<uint16_t, 3>(uval)) {
|
||||
val = fromZigZag<int16_t, uint16_t>(uval);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool readI32(int32_t& val) {
|
||||
uint32_t uval;
|
||||
if (readVarint<uint32_t, 5>(uval)) {
|
||||
val = fromZigZag<int32_t, uint32_t>(uval);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool readI64(int64_t& val) {
|
||||
uint64_t uval;
|
||||
if (readVarint<uint64_t, 10>(uval)) {
|
||||
val = fromZigZag<int64_t, uint64_t>(uval);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool readDouble(double& val) {
|
||||
union {
|
||||
int64_t f;
|
||||
double t;
|
||||
} transfer;
|
||||
|
||||
char* buf;
|
||||
if (!readBytes(&buf, 8)) {
|
||||
return false;
|
||||
}
|
||||
transfer.f = letohll(*reinterpret_cast<int64_t*>(buf));
|
||||
val = transfer.t;
|
||||
return true;
|
||||
}
|
||||
|
||||
int32_t readString(char** buf) {
|
||||
uint32_t len;
|
||||
if (!readVarint<uint32_t, 5>(len) || !checkLengthLimit(len, stringLimit())) {
|
||||
return -1;
|
||||
}
|
||||
if (len == 0) {
|
||||
return 0;
|
||||
}
|
||||
if (!readBytes(buf, len)) {
|
||||
return -1;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
int32_t readListBegin(TType& etype) {
|
||||
uint8_t b;
|
||||
if (!readByte(b)) {
|
||||
return -1;
|
||||
}
|
||||
etype = getTType(b & 0xf);
|
||||
if (etype == -1) {
|
||||
return -1;
|
||||
}
|
||||
uint32_t len = (b >> 4) & 0xf;
|
||||
if (len == 15 && !readVarint<uint32_t, 5>(len)) {
|
||||
return -1;
|
||||
}
|
||||
if (!checkLengthLimit(len, containerLimit())) {
|
||||
return -1;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
int32_t readMapBegin(TType& ktype, TType& vtype) {
|
||||
uint32_t len;
|
||||
if (!readVarint<uint32_t, 5>(len) || !checkLengthLimit(len, containerLimit())) {
|
||||
return -1;
|
||||
}
|
||||
if (len != 0) {
|
||||
uint8_t kvType;
|
||||
if (!readByte(kvType)) {
|
||||
return -1;
|
||||
}
|
||||
ktype = getTType(kvType >> 4);
|
||||
vtype = getTType(kvType & 0xf);
|
||||
if (ktype == -1 || vtype == -1) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
bool readStructBegin() {
|
||||
readTags_.push(0);
|
||||
return true;
|
||||
}
|
||||
bool readStructEnd() {
|
||||
readTags_.pop();
|
||||
return true;
|
||||
}
|
||||
bool readFieldBegin(TType& type, int16_t& tag);
|
||||
|
||||
bool skipBool() {
|
||||
bool val;
|
||||
return readBool(val);
|
||||
}
|
||||
#define SKIPBYTES(n) \
|
||||
do { \
|
||||
if (!readBytes(&dummy_buf_, (n))) { \
|
||||
return false; \
|
||||
} \
|
||||
return true; \
|
||||
} while (0)
|
||||
bool skipByte() { SKIPBYTES(1); }
|
||||
bool skipDouble() { SKIPBYTES(8); }
|
||||
bool skipI16() {
|
||||
int16_t val;
|
||||
return readI16(val);
|
||||
}
|
||||
bool skipI32() {
|
||||
int32_t val;
|
||||
return readI32(val);
|
||||
}
|
||||
bool skipI64() {
|
||||
int64_t val;
|
||||
return readI64(val);
|
||||
}
|
||||
bool skipString() {
|
||||
uint32_t len;
|
||||
if (!readVarint<uint32_t, 5>(len)) {
|
||||
return false;
|
||||
}
|
||||
SKIPBYTES(len);
|
||||
}
|
||||
#undef SKIPBYTES
|
||||
|
||||
private:
|
||||
enum Types {
|
||||
CT_STOP = 0x00,
|
||||
CT_BOOLEAN_TRUE = 0x01,
|
||||
CT_BOOLEAN_FALSE = 0x02,
|
||||
CT_BYTE = 0x03,
|
||||
CT_I16 = 0x04,
|
||||
CT_I32 = 0x05,
|
||||
CT_I64 = 0x06,
|
||||
CT_DOUBLE = 0x07,
|
||||
CT_BINARY = 0x08,
|
||||
CT_LIST = 0x09,
|
||||
CT_SET = 0x0A,
|
||||
CT_MAP = 0x0B,
|
||||
CT_STRUCT = 0x0C
|
||||
};
|
||||
|
||||
static const uint8_t TTypeToCType[];
|
||||
|
||||
TType getTType(uint8_t type);
|
||||
|
||||
int toCompactType(TType type) {
|
||||
int i = static_cast<int>(type);
|
||||
return i < 16 ? TTypeToCType[i] : -1;
|
||||
}
|
||||
|
||||
uint32_t toZigZag(int32_t val) { return (val >> 31) ^ (val << 1); }
|
||||
|
||||
uint64_t toZigZag64(int64_t val) { return (val >> 63) ^ (val << 1); }
|
||||
|
||||
int writeVarint(uint32_t val) {
|
||||
int cnt = 1;
|
||||
while (val & ~0x7fU) {
|
||||
writeByte(static_cast<char>((val & 0x7fU) | 0x80U));
|
||||
val >>= 7;
|
||||
++cnt;
|
||||
}
|
||||
writeByte(static_cast<char>(val));
|
||||
return cnt;
|
||||
}
|
||||
|
||||
int writeVarint64(uint64_t val) {
|
||||
int cnt = 1;
|
||||
while (val & ~0x7fULL) {
|
||||
writeByte(static_cast<char>((val & 0x7fULL) | 0x80ULL));
|
||||
val >>= 7;
|
||||
++cnt;
|
||||
}
|
||||
writeByte(static_cast<char>(val));
|
||||
return cnt;
|
||||
}
|
||||
|
||||
template <typename T, int Max>
|
||||
bool readVarint(T& result) {
|
||||
uint8_t b;
|
||||
T val = 0;
|
||||
int shift = 0;
|
||||
for (int i = 0; i < Max; ++i) {
|
||||
if (!readByte(b)) {
|
||||
return false;
|
||||
}
|
||||
if (b & 0x80) {
|
||||
val |= static_cast<T>(b & 0x7f) << shift;
|
||||
} else {
|
||||
val |= static_cast<T>(b) << shift;
|
||||
result = val;
|
||||
return true;
|
||||
}
|
||||
shift += 7;
|
||||
}
|
||||
PyErr_Format(PyExc_OverflowError, "varint exceeded %d bytes", Max);
|
||||
return false;
|
||||
}
|
||||
|
||||
template <typename S, typename U>
|
||||
S fromZigZag(U val) {
|
||||
return (val >> 1) ^ static_cast<U>(-static_cast<S>(val & 1));
|
||||
}
|
||||
|
||||
void doWriteFieldBegin(const StructItemSpec& spec, int ctype) {
|
||||
int diff = spec.tag - writeTags_.top();
|
||||
if (diff > 0 && diff <= 15) {
|
||||
writeByte(static_cast<uint8_t>(diff << 4 | ctype));
|
||||
} else {
|
||||
writeByte(static_cast<uint8_t>(ctype));
|
||||
writeI16(spec.tag);
|
||||
}
|
||||
writeTags_.top() = spec.tag;
|
||||
}
|
||||
|
||||
std::stack<int> writeTags_;
|
||||
std::stack<int> readTags_;
|
||||
struct {
|
||||
bool exists;
|
||||
bool value;
|
||||
} readBool_;
|
||||
char* dummy_buf_;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // THRIFT_PY_COMPACT_H
|
92
vendor/git.apache.org/thrift.git/lib/py/src/ext/endian.h
generated
vendored
Normal file
92
vendor/git.apache.org/thrift.git/lib/py/src/ext/endian.h
generated
vendored
Normal file
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef THRIFT_PY_ENDIAN_H
|
||||
#define THRIFT_PY_ENDIAN_H
|
||||
|
||||
#include <Python.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <netinet/in.h>
|
||||
#else
|
||||
#include <WinSock2.h>
|
||||
#pragma comment(lib, "ws2_32.lib")
|
||||
#define BIG_ENDIAN (4321)
|
||||
#define LITTLE_ENDIAN (1234)
|
||||
#define BYTE_ORDER LITTLE_ENDIAN
|
||||
#define inline __inline
|
||||
#endif
|
||||
|
||||
/* Fix endianness issues on Solaris */
|
||||
#if defined(__SVR4) && defined(__sun)
|
||||
#if defined(__i386) && !defined(__i386__)
|
||||
#define __i386__
|
||||
#endif
|
||||
|
||||
#ifndef BIG_ENDIAN
|
||||
#define BIG_ENDIAN (4321)
|
||||
#endif
|
||||
#ifndef LITTLE_ENDIAN
|
||||
#define LITTLE_ENDIAN (1234)
|
||||
#endif
|
||||
|
||||
/* I386 is LE, even on Solaris */
|
||||
#if !defined(BYTE_ORDER) && defined(__i386__)
|
||||
#define BYTE_ORDER LITTLE_ENDIAN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef __BYTE_ORDER
|
||||
#if defined(BYTE_ORDER) && defined(LITTLE_ENDIAN) && defined(BIG_ENDIAN)
|
||||
#define __BYTE_ORDER BYTE_ORDER
|
||||
#define __LITTLE_ENDIAN LITTLE_ENDIAN
|
||||
#define __BIG_ENDIAN BIG_ENDIAN
|
||||
#else
|
||||
#error "Cannot determine endianness"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// Same comment as the enum. Sorry.
|
||||
#if __BYTE_ORDER == __BIG_ENDIAN
|
||||
#define ntohll(n) (n)
|
||||
#define htonll(n) (n)
|
||||
#if defined(__GNUC__) && defined(__GLIBC__)
|
||||
#include <byteswap.h>
|
||||
#define letohll(n) bswap_64(n)
|
||||
#define htolell(n) bswap_64(n)
|
||||
#else /* GNUC & GLIBC */
|
||||
#define letohll(n) ((((unsigned long long)ntohl(n)) << 32) + ntohl(n >> 32))
|
||||
#define htolell(n) ((((unsigned long long)htonl(n)) << 32) + htonl(n >> 32))
|
||||
#endif
|
||||
#elif __BYTE_ORDER == __LITTLE_ENDIAN
|
||||
#if defined(__GNUC__) && defined(__GLIBC__)
|
||||
#include <byteswap.h>
|
||||
#define ntohll(n) bswap_64(n)
|
||||
#define htonll(n) bswap_64(n)
|
||||
#else /* GNUC & GLIBC */
|
||||
#define ntohll(n) ((((unsigned long long)ntohl(n)) << 32) + ntohl(n >> 32))
|
||||
#define htonll(n) ((((unsigned long long)htonl(n)) << 32) + htonl(n >> 32))
|
||||
#endif /* GNUC & GLIBC */
|
||||
#define letohll(n) (n)
|
||||
#define htolell(n) (n)
|
||||
#else /* __BYTE_ORDER */
|
||||
#error "Can't define htonll or ntohll!"
|
||||
#endif
|
||||
|
||||
#endif // THRIFT_PY_ENDIAN_H
|
208
vendor/git.apache.org/thrift.git/lib/py/src/ext/module.cpp
generated
vendored
Normal file
208
vendor/git.apache.org/thrift.git/lib/py/src/ext/module.cpp
generated
vendored
Normal file
|
@ -0,0 +1,208 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include <Python.h>
|
||||
#include "types.h"
|
||||
#include "binary.h"
|
||||
#include "compact.h"
|
||||
#include <limits>
|
||||
#include <stdint.h>
|
||||
|
||||
// TODO(dreiss): defval appears to be unused. Look into removing it.
|
||||
// TODO(dreiss): Make parse_spec_args recursive, and cache the output
|
||||
// permanently in the object. (Malloc and orphan.)
|
||||
// TODO(dreiss): Why do we need cStringIO for reading, why not just char*?
|
||||
// Can cStringIO let us work with a BufferedTransport?
|
||||
// TODO(dreiss): Don't ignore the rv from cwrite (maybe).
|
||||
|
||||
// Doing a benchmark shows that interning actually makes a difference, amazingly.
|
||||
|
||||
/** Pointer to interned string to speed up attribute lookup. */
|
||||
PyObject* INTERN_STRING(TFrozenDict);
|
||||
PyObject* INTERN_STRING(cstringio_buf);
|
||||
PyObject* INTERN_STRING(cstringio_refill);
|
||||
static PyObject* INTERN_STRING(string_length_limit);
|
||||
static PyObject* INTERN_STRING(container_length_limit);
|
||||
static PyObject* INTERN_STRING(trans);
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace py {
|
||||
|
||||
template <typename T>
|
||||
static PyObject* encode_impl(PyObject* args) {
|
||||
if (!args)
|
||||
return NULL;
|
||||
|
||||
PyObject* enc_obj = NULL;
|
||||
PyObject* type_args = NULL;
|
||||
if (!PyArg_ParseTuple(args, "OO", &enc_obj, &type_args)) {
|
||||
return NULL;
|
||||
}
|
||||
if (!enc_obj || !type_args) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
T protocol;
|
||||
if (!protocol.prepareEncodeBuffer() || !protocol.encodeValue(enc_obj, T_STRUCT, type_args)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return protocol.getEncodedValue();
|
||||
}
|
||||
|
||||
static inline long as_long_then_delete(PyObject* value, long default_value) {
|
||||
ScopedPyObject scope(value);
|
||||
long v = PyInt_AsLong(value);
|
||||
if (INT_CONV_ERROR_OCCURRED(v)) {
|
||||
PyErr_Clear();
|
||||
return default_value;
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static PyObject* decode_impl(PyObject* args) {
|
||||
PyObject* output_obj = NULL;
|
||||
PyObject* oprot = NULL;
|
||||
PyObject* typeargs = NULL;
|
||||
if (!PyArg_ParseTuple(args, "OOO", &output_obj, &oprot, &typeargs)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
T protocol;
|
||||
#ifdef _MSC_VER
|
||||
// workaround strange VC++ 2015 bug where #else path does not compile
|
||||
int32_t default_limit = INT32_MAX;
|
||||
#else
|
||||
int32_t default_limit = std::numeric_limits<int32_t>::max();
|
||||
#endif
|
||||
protocol.setStringLengthLimit(
|
||||
as_long_then_delete(PyObject_GetAttr(oprot, INTERN_STRING(string_length_limit)),
|
||||
default_limit));
|
||||
protocol.setContainerLengthLimit(
|
||||
as_long_then_delete(PyObject_GetAttr(oprot, INTERN_STRING(container_length_limit)),
|
||||
default_limit));
|
||||
ScopedPyObject transport(PyObject_GetAttr(oprot, INTERN_STRING(trans)));
|
||||
if (!transport) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
StructTypeArgs parsedargs;
|
||||
if (!parse_struct_args(&parsedargs, typeargs)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!protocol.prepareDecodeBufferFromTransport(transport.get())) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return protocol.readStruct(output_obj, parsedargs.klass, parsedargs.spec);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
using namespace apache::thrift::py;
|
||||
|
||||
/* -- PYTHON MODULE SETUP STUFF --- */
|
||||
|
||||
extern "C" {
|
||||
|
||||
static PyObject* encode_binary(PyObject*, PyObject* args) {
|
||||
return encode_impl<BinaryProtocol>(args);
|
||||
}
|
||||
|
||||
static PyObject* decode_binary(PyObject*, PyObject* args) {
|
||||
return decode_impl<BinaryProtocol>(args);
|
||||
}
|
||||
|
||||
static PyObject* encode_compact(PyObject*, PyObject* args) {
|
||||
return encode_impl<CompactProtocol>(args);
|
||||
}
|
||||
|
||||
static PyObject* decode_compact(PyObject*, PyObject* args) {
|
||||
return decode_impl<CompactProtocol>(args);
|
||||
}
|
||||
|
||||
static PyMethodDef ThriftFastBinaryMethods[] = {
|
||||
{"encode_binary", encode_binary, METH_VARARGS, ""},
|
||||
{"decode_binary", decode_binary, METH_VARARGS, ""},
|
||||
{"encode_compact", encode_compact, METH_VARARGS, ""},
|
||||
{"decode_compact", decode_compact, METH_VARARGS, ""},
|
||||
{NULL, NULL, 0, NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
|
||||
static struct PyModuleDef ThriftFastBinaryDef = {PyModuleDef_HEAD_INIT,
|
||||
"thrift.protocol.fastbinary",
|
||||
NULL,
|
||||
0,
|
||||
ThriftFastBinaryMethods,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL};
|
||||
|
||||
#define INITERROR return NULL;
|
||||
|
||||
PyObject* PyInit_fastbinary() {
|
||||
|
||||
#else
|
||||
|
||||
#define INITERROR return;
|
||||
|
||||
void initfastbinary() {
|
||||
|
||||
PycString_IMPORT;
|
||||
if (PycStringIO == NULL)
|
||||
INITERROR
|
||||
|
||||
#endif
|
||||
|
||||
#define INIT_INTERN_STRING(value) \
|
||||
do { \
|
||||
INTERN_STRING(value) = PyString_InternFromString(#value); \
|
||||
if (!INTERN_STRING(value)) \
|
||||
INITERROR \
|
||||
} while (0)
|
||||
|
||||
INIT_INTERN_STRING(TFrozenDict);
|
||||
INIT_INTERN_STRING(cstringio_buf);
|
||||
INIT_INTERN_STRING(cstringio_refill);
|
||||
INIT_INTERN_STRING(string_length_limit);
|
||||
INIT_INTERN_STRING(container_length_limit);
|
||||
INIT_INTERN_STRING(trans);
|
||||
#undef INIT_INTERN_STRING
|
||||
|
||||
PyObject* module =
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
PyModule_Create(&ThriftFastBinaryDef);
|
||||
#else
|
||||
Py_InitModule("thrift.protocol.fastbinary", ThriftFastBinaryMethods);
|
||||
#endif
|
||||
if (module == NULL)
|
||||
INITERROR;
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
return module;
|
||||
#endif
|
||||
}
|
||||
}
|
96
vendor/git.apache.org/thrift.git/lib/py/src/ext/protocol.h
generated
vendored
Normal file
96
vendor/git.apache.org/thrift.git/lib/py/src/ext/protocol.h
generated
vendored
Normal file
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef THRIFT_PY_PROTOCOL_H
|
||||
#define THRIFT_PY_PROTOCOL_H
|
||||
|
||||
#include "ext/types.h"
|
||||
#include <limits>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace py {
|
||||
|
||||
template <typename Impl>
|
||||
class ProtocolBase {
|
||||
|
||||
public:
|
||||
ProtocolBase()
|
||||
: stringLimit_(std::numeric_limits<int32_t>::max()),
|
||||
containerLimit_(std::numeric_limits<int32_t>::max()),
|
||||
output_(NULL) {}
|
||||
inline virtual ~ProtocolBase();
|
||||
|
||||
bool prepareDecodeBufferFromTransport(PyObject* trans);
|
||||
|
||||
PyObject* readStruct(PyObject* output, PyObject* klass, PyObject* spec_seq);
|
||||
|
||||
bool prepareEncodeBuffer();
|
||||
|
||||
bool encodeValue(PyObject* value, TType type, PyObject* typeargs);
|
||||
|
||||
PyObject* getEncodedValue();
|
||||
|
||||
long stringLimit() const { return stringLimit_; }
|
||||
void setStringLengthLimit(long limit) { stringLimit_ = limit; }
|
||||
|
||||
long containerLimit() const { return containerLimit_; }
|
||||
void setContainerLengthLimit(long limit) { containerLimit_ = limit; }
|
||||
|
||||
protected:
|
||||
bool readBytes(char** output, int len);
|
||||
|
||||
bool readByte(uint8_t& val) {
|
||||
char* buf;
|
||||
if (!readBytes(&buf, 1)) {
|
||||
return false;
|
||||
}
|
||||
val = static_cast<uint8_t>(buf[0]);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool writeBuffer(char* data, size_t len);
|
||||
|
||||
void writeByte(uint8_t val) { writeBuffer(reinterpret_cast<char*>(&val), 1); }
|
||||
|
||||
PyObject* decodeValue(TType type, PyObject* typeargs);
|
||||
|
||||
bool skip(TType type);
|
||||
|
||||
inline bool checkType(TType got, TType expected);
|
||||
inline bool checkLengthLimit(int32_t len, long limit);
|
||||
|
||||
inline bool isUtf8(PyObject* typeargs);
|
||||
|
||||
private:
|
||||
Impl* impl() { return static_cast<Impl*>(this); }
|
||||
|
||||
long stringLimit_;
|
||||
long containerLimit_;
|
||||
EncodeBuffer* output_;
|
||||
DecodeBuffer input_;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#include "ext/protocol.tcc"
|
||||
|
||||
#endif // THRIFT_PY_PROTOCOL_H
|
913
vendor/git.apache.org/thrift.git/lib/py/src/ext/protocol.tcc
generated
vendored
Normal file
913
vendor/git.apache.org/thrift.git/lib/py/src/ext/protocol.tcc
generated
vendored
Normal file
|
@ -0,0 +1,913 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef THRIFT_PY_PROTOCOL_TCC
|
||||
#define THRIFT_PY_PROTOCOL_TCC
|
||||
|
||||
#include <iterator>
|
||||
|
||||
#define CHECK_RANGE(v, min, max) (((v) <= (max)) && ((v) >= (min)))
|
||||
#define INIT_OUTBUF_SIZE 128
|
||||
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
#include <cStringIO.h>
|
||||
#else
|
||||
#include <algorithm>
|
||||
#endif
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace py {
|
||||
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
|
||||
namespace detail {
|
||||
|
||||
inline bool input_check(PyObject* input) {
|
||||
return PycStringIO_InputCheck(input);
|
||||
}
|
||||
|
||||
inline EncodeBuffer* new_encode_buffer(size_t size) {
|
||||
if (!PycStringIO) {
|
||||
PycString_IMPORT;
|
||||
}
|
||||
if (!PycStringIO) {
|
||||
return NULL;
|
||||
}
|
||||
return PycStringIO->NewOutput(size);
|
||||
}
|
||||
|
||||
inline int read_buffer(PyObject* buf, char** output, int len) {
|
||||
if (!PycStringIO) {
|
||||
PycString_IMPORT;
|
||||
}
|
||||
if (!PycStringIO) {
|
||||
PyErr_SetString(PyExc_ImportError, "failed to import native cStringIO");
|
||||
return -1;
|
||||
}
|
||||
return PycStringIO->cread(buf, output, len);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Impl>
|
||||
inline ProtocolBase<Impl>::~ProtocolBase() {
|
||||
if (output_) {
|
||||
Py_CLEAR(output_);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Impl>
|
||||
inline bool ProtocolBase<Impl>::isUtf8(PyObject* typeargs) {
|
||||
return PyString_Check(typeargs) && !strncmp(PyString_AS_STRING(typeargs), "UTF8", 4);
|
||||
}
|
||||
|
||||
template <typename Impl>
|
||||
PyObject* ProtocolBase<Impl>::getEncodedValue() {
|
||||
if (!PycStringIO) {
|
||||
PycString_IMPORT;
|
||||
}
|
||||
if (!PycStringIO) {
|
||||
return NULL;
|
||||
}
|
||||
return PycStringIO->cgetvalue(output_);
|
||||
}
|
||||
|
||||
template <typename Impl>
|
||||
inline bool ProtocolBase<Impl>::writeBuffer(char* data, size_t size) {
|
||||
if (!PycStringIO) {
|
||||
PycString_IMPORT;
|
||||
}
|
||||
if (!PycStringIO) {
|
||||
PyErr_SetString(PyExc_ImportError, "failed to import native cStringIO");
|
||||
return false;
|
||||
}
|
||||
int len = PycStringIO->cwrite(output_, data, size);
|
||||
if (len < 0) {
|
||||
PyErr_SetString(PyExc_IOError, "failed to write to cStringIO object");
|
||||
return false;
|
||||
}
|
||||
if (len != size) {
|
||||
PyErr_Format(PyExc_EOFError, "write length mismatch: expected %lu got %d", size, len);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
namespace detail {
|
||||
|
||||
inline bool input_check(PyObject* input) {
|
||||
// TODO: Check for BytesIO type
|
||||
return true;
|
||||
}
|
||||
|
||||
inline EncodeBuffer* new_encode_buffer(size_t size) {
|
||||
EncodeBuffer* buffer = new EncodeBuffer;
|
||||
buffer->buf.reserve(size);
|
||||
buffer->pos = 0;
|
||||
return buffer;
|
||||
}
|
||||
|
||||
struct bytesio {
|
||||
PyObject_HEAD
|
||||
#if PY_MINOR_VERSION < 5
|
||||
char* buf;
|
||||
#else
|
||||
PyObject* buf;
|
||||
#endif
|
||||
Py_ssize_t pos;
|
||||
Py_ssize_t string_size;
|
||||
};
|
||||
|
||||
inline int read_buffer(PyObject* buf, char** output, int len) {
|
||||
bytesio* buf2 = reinterpret_cast<bytesio*>(buf);
|
||||
#if PY_MINOR_VERSION < 5
|
||||
*output = buf2->buf + buf2->pos;
|
||||
#else
|
||||
*output = PyBytes_AS_STRING(buf2->buf) + buf2->pos;
|
||||
#endif
|
||||
Py_ssize_t pos0 = buf2->pos;
|
||||
buf2->pos = std::min(buf2->pos + static_cast<Py_ssize_t>(len), buf2->string_size);
|
||||
return static_cast<int>(buf2->pos - pos0);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Impl>
|
||||
inline ProtocolBase<Impl>::~ProtocolBase() {
|
||||
if (output_) {
|
||||
delete output_;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Impl>
|
||||
inline bool ProtocolBase<Impl>::isUtf8(PyObject* typeargs) {
|
||||
// while condition for py2 is "arg == 'UTF8'", it should be "arg != 'BINARY'" for py3.
|
||||
// HACK: check the length and don't bother reading the value
|
||||
return !PyUnicode_Check(typeargs) || PyUnicode_GET_LENGTH(typeargs) != 6;
|
||||
}
|
||||
|
||||
template <typename Impl>
|
||||
PyObject* ProtocolBase<Impl>::getEncodedValue() {
|
||||
return PyBytes_FromStringAndSize(output_->buf.data(), output_->buf.size());
|
||||
}
|
||||
|
||||
template <typename Impl>
|
||||
inline bool ProtocolBase<Impl>::writeBuffer(char* data, size_t size) {
|
||||
size_t need = size + output_->pos;
|
||||
if (output_->buf.capacity() < need) {
|
||||
try {
|
||||
output_->buf.reserve(need);
|
||||
} catch (std::bad_alloc& ex) {
|
||||
PyErr_SetString(PyExc_MemoryError, "Failed to allocate write buffer");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
std::copy(data, data + size, std::back_inserter(output_->buf));
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
namespace detail {
|
||||
|
||||
#define DECLARE_OP_SCOPE(name, op) \
|
||||
template <typename Impl> \
|
||||
struct name##Scope { \
|
||||
Impl* impl; \
|
||||
bool valid; \
|
||||
name##Scope(Impl* thiz) : impl(thiz), valid(impl->op##Begin()) {} \
|
||||
~name##Scope() { \
|
||||
if (valid) \
|
||||
impl->op##End(); \
|
||||
} \
|
||||
operator bool() { return valid; } \
|
||||
}; \
|
||||
template <typename Impl, template <typename> class T> \
|
||||
name##Scope<Impl> op##Scope(T<Impl>* thiz) { \
|
||||
return name##Scope<Impl>(static_cast<Impl*>(thiz)); \
|
||||
}
|
||||
DECLARE_OP_SCOPE(WriteStruct, writeStruct)
|
||||
DECLARE_OP_SCOPE(ReadStruct, readStruct)
|
||||
#undef DECLARE_OP_SCOPE
|
||||
|
||||
inline bool check_ssize_t_32(Py_ssize_t len) {
|
||||
// error from getting the int
|
||||
if (INT_CONV_ERROR_OCCURRED(len)) {
|
||||
return false;
|
||||
}
|
||||
if (!CHECK_RANGE(len, 0, std::numeric_limits<int32_t>::max())) {
|
||||
PyErr_SetString(PyExc_OverflowError, "size out of range: exceeded INT32_MAX");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool parse_pyint(PyObject* o, T* ret, int32_t min, int32_t max) {
|
||||
long val = PyInt_AsLong(o);
|
||||
|
||||
if (INT_CONV_ERROR_OCCURRED(val)) {
|
||||
return false;
|
||||
}
|
||||
if (!CHECK_RANGE(val, min, max)) {
|
||||
PyErr_SetString(PyExc_OverflowError, "int out of range");
|
||||
return false;
|
||||
}
|
||||
|
||||
*ret = static_cast<T>(val);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Impl>
|
||||
inline bool ProtocolBase<Impl>::checkType(TType got, TType expected) {
|
||||
if (expected != got) {
|
||||
PyErr_SetString(PyExc_TypeError, "got wrong ttype while reading field");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Impl>
|
||||
bool ProtocolBase<Impl>::checkLengthLimit(int32_t len, long limit) {
|
||||
if (len < 0) {
|
||||
PyErr_Format(PyExc_OverflowError, "negative length: %ld", limit);
|
||||
return false;
|
||||
}
|
||||
if (len > limit) {
|
||||
PyErr_Format(PyExc_OverflowError, "size exceeded specified limit: %ld", limit);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Impl>
|
||||
bool ProtocolBase<Impl>::readBytes(char** output, int len) {
|
||||
if (len < 0) {
|
||||
PyErr_Format(PyExc_ValueError, "attempted to read negative length: %d", len);
|
||||
return false;
|
||||
}
|
||||
// TODO(dreiss): Don't fear the malloc. Think about taking a copy of
|
||||
// the partial read instead of forcing the transport
|
||||
// to prepend it to its buffer.
|
||||
|
||||
int rlen = detail::read_buffer(input_.stringiobuf.get(), output, len);
|
||||
|
||||
if (rlen == len) {
|
||||
return true;
|
||||
} else if (rlen == -1) {
|
||||
return false;
|
||||
} else {
|
||||
// using building functions as this is a rare codepath
|
||||
ScopedPyObject newiobuf(PyObject_CallFunction(input_.refill_callable.get(), refill_signature,
|
||||
*output, rlen, len, NULL));
|
||||
if (!newiobuf) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// must do this *AFTER* the call so that we don't deref the io buffer
|
||||
input_.stringiobuf.reset(newiobuf.release());
|
||||
|
||||
rlen = detail::read_buffer(input_.stringiobuf.get(), output, len);
|
||||
|
||||
if (rlen == len) {
|
||||
return true;
|
||||
} else if (rlen == -1) {
|
||||
return false;
|
||||
} else {
|
||||
// TODO(dreiss): This could be a valid code path for big binary blobs.
|
||||
PyErr_SetString(PyExc_TypeError, "refill claimed to have refilled the buffer, but didn't!!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Impl>
|
||||
bool ProtocolBase<Impl>::prepareDecodeBufferFromTransport(PyObject* trans) {
|
||||
if (input_.stringiobuf) {
|
||||
PyErr_SetString(PyExc_ValueError, "decode buffer is already initialized");
|
||||
return false;
|
||||
}
|
||||
|
||||
ScopedPyObject stringiobuf(PyObject_GetAttr(trans, INTERN_STRING(cstringio_buf)));
|
||||
if (!stringiobuf) {
|
||||
return false;
|
||||
}
|
||||
if (!detail::input_check(stringiobuf.get())) {
|
||||
PyErr_SetString(PyExc_TypeError, "expecting stringio input_");
|
||||
return false;
|
||||
}
|
||||
|
||||
ScopedPyObject refill_callable(PyObject_GetAttr(trans, INTERN_STRING(cstringio_refill)));
|
||||
if (!refill_callable) {
|
||||
return false;
|
||||
}
|
||||
if (!PyCallable_Check(refill_callable.get())) {
|
||||
PyErr_SetString(PyExc_TypeError, "expecting callable");
|
||||
return false;
|
||||
}
|
||||
|
||||
input_.stringiobuf.swap(stringiobuf);
|
||||
input_.refill_callable.swap(refill_callable);
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Impl>
|
||||
bool ProtocolBase<Impl>::prepareEncodeBuffer() {
|
||||
output_ = detail::new_encode_buffer(INIT_OUTBUF_SIZE);
|
||||
return output_ != NULL;
|
||||
}
|
||||
|
||||
template <typename Impl>
|
||||
bool ProtocolBase<Impl>::encodeValue(PyObject* value, TType type, PyObject* typeargs) {
|
||||
/*
|
||||
* Refcounting Strategy:
|
||||
*
|
||||
* We assume that elements of the thrift_spec tuple are not going to be
|
||||
* mutated, so we don't ref count those at all. Other than that, we try to
|
||||
* keep a reference to all the user-created objects while we work with them.
|
||||
* encodeValue assumes that a reference is already held. The *caller* is
|
||||
* responsible for handling references
|
||||
*/
|
||||
|
||||
switch (type) {
|
||||
|
||||
case T_BOOL: {
|
||||
int v = PyObject_IsTrue(value);
|
||||
if (v == -1) {
|
||||
return false;
|
||||
}
|
||||
impl()->writeBool(v);
|
||||
return true;
|
||||
}
|
||||
case T_I08: {
|
||||
int8_t val;
|
||||
|
||||
if (!parse_pyint(value, &val, std::numeric_limits<int8_t>::min(),
|
||||
std::numeric_limits<int8_t>::max())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
impl()->writeI8(val);
|
||||
return true;
|
||||
}
|
||||
case T_I16: {
|
||||
int16_t val;
|
||||
|
||||
if (!parse_pyint(value, &val, std::numeric_limits<int16_t>::min(),
|
||||
std::numeric_limits<int16_t>::max())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
impl()->writeI16(val);
|
||||
return true;
|
||||
}
|
||||
case T_I32: {
|
||||
int32_t val;
|
||||
|
||||
if (!parse_pyint(value, &val, std::numeric_limits<int32_t>::min(),
|
||||
std::numeric_limits<int32_t>::max())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
impl()->writeI32(val);
|
||||
return true;
|
||||
}
|
||||
case T_I64: {
|
||||
int64_t nval = PyLong_AsLongLong(value);
|
||||
|
||||
if (INT_CONV_ERROR_OCCURRED(nval)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CHECK_RANGE(nval, std::numeric_limits<int64_t>::min(),
|
||||
std::numeric_limits<int64_t>::max())) {
|
||||
PyErr_SetString(PyExc_OverflowError, "int out of range");
|
||||
return false;
|
||||
}
|
||||
|
||||
impl()->writeI64(nval);
|
||||
return true;
|
||||
}
|
||||
|
||||
case T_DOUBLE: {
|
||||
double nval = PyFloat_AsDouble(value);
|
||||
if (nval == -1.0 && PyErr_Occurred()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
impl()->writeDouble(nval);
|
||||
return true;
|
||||
}
|
||||
|
||||
case T_STRING: {
|
||||
ScopedPyObject nval;
|
||||
|
||||
if (PyUnicode_Check(value)) {
|
||||
nval.reset(PyUnicode_AsUTF8String(value));
|
||||
if (!nval) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
Py_INCREF(value);
|
||||
nval.reset(value);
|
||||
}
|
||||
|
||||
Py_ssize_t len = PyBytes_Size(nval.get());
|
||||
if (!detail::check_ssize_t_32(len)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
impl()->writeString(nval.get(), static_cast<int32_t>(len));
|
||||
return true;
|
||||
}
|
||||
|
||||
case T_LIST:
|
||||
case T_SET: {
|
||||
SetListTypeArgs parsedargs;
|
||||
if (!parse_set_list_args(&parsedargs, typeargs)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Py_ssize_t len = PyObject_Length(value);
|
||||
if (!detail::check_ssize_t_32(len)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!impl()->writeListBegin(value, parsedargs, static_cast<int32_t>(len)) || PyErr_Occurred()) {
|
||||
return false;
|
||||
}
|
||||
ScopedPyObject iterator(PyObject_GetIter(value));
|
||||
if (!iterator) {
|
||||
return false;
|
||||
}
|
||||
|
||||
while (PyObject* rawItem = PyIter_Next(iterator.get())) {
|
||||
ScopedPyObject item(rawItem);
|
||||
if (!encodeValue(item.get(), parsedargs.element_type, parsedargs.typeargs)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
case T_MAP: {
|
||||
Py_ssize_t len = PyDict_Size(value);
|
||||
if (!detail::check_ssize_t_32(len)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
MapTypeArgs parsedargs;
|
||||
if (!parse_map_args(&parsedargs, typeargs)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!impl()->writeMapBegin(value, parsedargs, static_cast<int32_t>(len)) || PyErr_Occurred()) {
|
||||
return false;
|
||||
}
|
||||
Py_ssize_t pos = 0;
|
||||
PyObject* k = NULL;
|
||||
PyObject* v = NULL;
|
||||
// TODO(bmaurer): should support any mapping, not just dicts
|
||||
while (PyDict_Next(value, &pos, &k, &v)) {
|
||||
if (!encodeValue(k, parsedargs.ktag, parsedargs.ktypeargs)
|
||||
|| !encodeValue(v, parsedargs.vtag, parsedargs.vtypeargs)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
case T_STRUCT: {
|
||||
StructTypeArgs parsedargs;
|
||||
if (!parse_struct_args(&parsedargs, typeargs)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Py_ssize_t nspec = PyTuple_Size(parsedargs.spec);
|
||||
if (nspec == -1) {
|
||||
PyErr_SetString(PyExc_TypeError, "spec is not a tuple");
|
||||
return false;
|
||||
}
|
||||
|
||||
detail::WriteStructScope<Impl> scope = detail::writeStructScope(this);
|
||||
if (!scope) {
|
||||
return false;
|
||||
}
|
||||
for (Py_ssize_t i = 0; i < nspec; i++) {
|
||||
PyObject* spec_tuple = PyTuple_GET_ITEM(parsedargs.spec, i);
|
||||
if (spec_tuple == Py_None) {
|
||||
continue;
|
||||
}
|
||||
|
||||
StructItemSpec parsedspec;
|
||||
if (!parse_struct_item_spec(&parsedspec, spec_tuple)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ScopedPyObject instval(PyObject_GetAttr(value, parsedspec.attrname));
|
||||
|
||||
if (!instval) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (instval.get() == Py_None) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool res = impl()->writeField(instval.get(), parsedspec);
|
||||
if (!res) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
impl()->writeFieldStop();
|
||||
return true;
|
||||
}
|
||||
|
||||
case T_STOP:
|
||||
case T_VOID:
|
||||
case T_UTF16:
|
||||
case T_UTF8:
|
||||
case T_U64:
|
||||
default:
|
||||
PyErr_Format(PyExc_TypeError, "Unexpected TType for encodeValue: %d", type);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Impl>
|
||||
bool ProtocolBase<Impl>::skip(TType type) {
|
||||
switch (type) {
|
||||
case T_BOOL:
|
||||
return impl()->skipBool();
|
||||
case T_I08:
|
||||
return impl()->skipByte();
|
||||
case T_I16:
|
||||
return impl()->skipI16();
|
||||
case T_I32:
|
||||
return impl()->skipI32();
|
||||
case T_I64:
|
||||
return impl()->skipI64();
|
||||
case T_DOUBLE:
|
||||
return impl()->skipDouble();
|
||||
|
||||
case T_STRING: {
|
||||
return impl()->skipString();
|
||||
}
|
||||
|
||||
case T_LIST:
|
||||
case T_SET: {
|
||||
TType etype = T_STOP;
|
||||
int32_t len = impl()->readListBegin(etype);
|
||||
if (len < 0) {
|
||||
return false;
|
||||
}
|
||||
for (int32_t i = 0; i < len; i++) {
|
||||
if (!skip(etype)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
case T_MAP: {
|
||||
TType ktype = T_STOP;
|
||||
TType vtype = T_STOP;
|
||||
int32_t len = impl()->readMapBegin(ktype, vtype);
|
||||
if (len < 0) {
|
||||
return false;
|
||||
}
|
||||
for (int32_t i = 0; i < len; i++) {
|
||||
if (!skip(ktype) || !skip(vtype)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
case T_STRUCT: {
|
||||
detail::ReadStructScope<Impl> scope = detail::readStructScope(this);
|
||||
if (!scope) {
|
||||
return false;
|
||||
}
|
||||
while (true) {
|
||||
TType type = T_STOP;
|
||||
int16_t tag;
|
||||
if (!impl()->readFieldBegin(type, tag)) {
|
||||
return false;
|
||||
}
|
||||
if (type == T_STOP) {
|
||||
return true;
|
||||
}
|
||||
if (!skip(type)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
case T_STOP:
|
||||
case T_VOID:
|
||||
case T_UTF16:
|
||||
case T_UTF8:
|
||||
case T_U64:
|
||||
default:
|
||||
PyErr_Format(PyExc_TypeError, "Unexpected TType for skip: %d", type);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Returns a new reference.
|
||||
template <typename Impl>
|
||||
PyObject* ProtocolBase<Impl>::decodeValue(TType type, PyObject* typeargs) {
|
||||
switch (type) {
|
||||
|
||||
case T_BOOL: {
|
||||
bool v = 0;
|
||||
if (!impl()->readBool(v)) {
|
||||
return NULL;
|
||||
}
|
||||
if (v) {
|
||||
Py_RETURN_TRUE;
|
||||
} else {
|
||||
Py_RETURN_FALSE;
|
||||
}
|
||||
}
|
||||
case T_I08: {
|
||||
int8_t v = 0;
|
||||
if (!impl()->readI8(v)) {
|
||||
return NULL;
|
||||
}
|
||||
return PyInt_FromLong(v);
|
||||
}
|
||||
case T_I16: {
|
||||
int16_t v = 0;
|
||||
if (!impl()->readI16(v)) {
|
||||
return NULL;
|
||||
}
|
||||
return PyInt_FromLong(v);
|
||||
}
|
||||
case T_I32: {
|
||||
int32_t v = 0;
|
||||
if (!impl()->readI32(v)) {
|
||||
return NULL;
|
||||
}
|
||||
return PyInt_FromLong(v);
|
||||
}
|
||||
|
||||
case T_I64: {
|
||||
int64_t v = 0;
|
||||
if (!impl()->readI64(v)) {
|
||||
return NULL;
|
||||
}
|
||||
// TODO(dreiss): Find out if we can take this fastpath always when
|
||||
// sizeof(long) == sizeof(long long).
|
||||
if (CHECK_RANGE(v, LONG_MIN, LONG_MAX)) {
|
||||
return PyInt_FromLong((long)v);
|
||||
}
|
||||
return PyLong_FromLongLong(v);
|
||||
}
|
||||
|
||||
case T_DOUBLE: {
|
||||
double v = 0.0;
|
||||
if (!impl()->readDouble(v)) {
|
||||
return NULL;
|
||||
}
|
||||
return PyFloat_FromDouble(v);
|
||||
}
|
||||
|
||||
case T_STRING: {
|
||||
char* buf = NULL;
|
||||
int len = impl()->readString(&buf);
|
||||
if (len < 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (isUtf8(typeargs)) {
|
||||
return PyUnicode_DecodeUTF8(buf, len, 0);
|
||||
} else {
|
||||
return PyBytes_FromStringAndSize(buf, len);
|
||||
}
|
||||
}
|
||||
|
||||
case T_LIST:
|
||||
case T_SET: {
|
||||
SetListTypeArgs parsedargs;
|
||||
if (!parse_set_list_args(&parsedargs, typeargs)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TType etype = T_STOP;
|
||||
int32_t len = impl()->readListBegin(etype);
|
||||
if (len < 0) {
|
||||
return NULL;
|
||||
}
|
||||
if (len > 0 && !checkType(etype, parsedargs.element_type)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool use_tuple = type == T_LIST && parsedargs.immutable;
|
||||
ScopedPyObject ret(use_tuple ? PyTuple_New(len) : PyList_New(len));
|
||||
if (!ret) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
PyObject* item = decodeValue(etype, parsedargs.typeargs);
|
||||
if (!item) {
|
||||
return NULL;
|
||||
}
|
||||
if (use_tuple) {
|
||||
PyTuple_SET_ITEM(ret.get(), i, item);
|
||||
} else {
|
||||
PyList_SET_ITEM(ret.get(), i, item);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(dreiss): Consider biting the bullet and making two separate cases
|
||||
// for list and set, avoiding this post facto conversion.
|
||||
if (type == T_SET) {
|
||||
PyObject* setret;
|
||||
setret = parsedargs.immutable ? PyFrozenSet_New(ret.get()) : PySet_New(ret.get());
|
||||
return setret;
|
||||
}
|
||||
return ret.release();
|
||||
}
|
||||
|
||||
case T_MAP: {
|
||||
MapTypeArgs parsedargs;
|
||||
if (!parse_map_args(&parsedargs, typeargs)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
TType ktype = T_STOP;
|
||||
TType vtype = T_STOP;
|
||||
uint32_t len = impl()->readMapBegin(ktype, vtype);
|
||||
if (len > 0 && (!checkType(ktype, parsedargs.ktag) || !checkType(vtype, parsedargs.vtag))) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ScopedPyObject ret(PyDict_New());
|
||||
if (!ret) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < len; i++) {
|
||||
ScopedPyObject k(decodeValue(ktype, parsedargs.ktypeargs));
|
||||
if (!k) {
|
||||
return NULL;
|
||||
}
|
||||
ScopedPyObject v(decodeValue(vtype, parsedargs.vtypeargs));
|
||||
if (!v) {
|
||||
return NULL;
|
||||
}
|
||||
if (PyDict_SetItem(ret.get(), k.get(), v.get()) == -1) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (parsedargs.immutable) {
|
||||
if (!ThriftModule) {
|
||||
ThriftModule = PyImport_ImportModule("thrift.Thrift");
|
||||
}
|
||||
if (!ThriftModule) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ScopedPyObject cls(PyObject_GetAttr(ThriftModule, INTERN_STRING(TFrozenDict)));
|
||||
if (!cls) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ScopedPyObject arg(PyTuple_New(1));
|
||||
PyTuple_SET_ITEM(arg.get(), 0, ret.release());
|
||||
ret.reset(PyObject_CallObject(cls.get(), arg.get()));
|
||||
}
|
||||
|
||||
return ret.release();
|
||||
}
|
||||
|
||||
case T_STRUCT: {
|
||||
StructTypeArgs parsedargs;
|
||||
if (!parse_struct_args(&parsedargs, typeargs)) {
|
||||
return NULL;
|
||||
}
|
||||
return readStruct(Py_None, parsedargs.klass, parsedargs.spec);
|
||||
}
|
||||
|
||||
case T_STOP:
|
||||
case T_VOID:
|
||||
case T_UTF16:
|
||||
case T_UTF8:
|
||||
case T_U64:
|
||||
default:
|
||||
PyErr_Format(PyExc_TypeError, "Unexpected TType for decodeValue: %d", type);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Impl>
|
||||
PyObject* ProtocolBase<Impl>::readStruct(PyObject* output, PyObject* klass, PyObject* spec_seq) {
|
||||
int spec_seq_len = PyTuple_Size(spec_seq);
|
||||
bool immutable = output == Py_None;
|
||||
ScopedPyObject kwargs;
|
||||
if (spec_seq_len == -1) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (immutable) {
|
||||
kwargs.reset(PyDict_New());
|
||||
if (!kwargs) {
|
||||
PyErr_SetString(PyExc_TypeError, "failed to prepare kwargument storage");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
detail::ReadStructScope<Impl> scope = detail::readStructScope(this);
|
||||
if (!scope) {
|
||||
return NULL;
|
||||
}
|
||||
while (true) {
|
||||
TType type = T_STOP;
|
||||
int16_t tag;
|
||||
if (!impl()->readFieldBegin(type, tag)) {
|
||||
return NULL;
|
||||
}
|
||||
if (type == T_STOP) {
|
||||
break;
|
||||
}
|
||||
if (tag < 0 || tag >= spec_seq_len) {
|
||||
if (!skip(type)) {
|
||||
PyErr_SetString(PyExc_TypeError, "Error while skipping unknown field");
|
||||
return NULL;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
PyObject* item_spec = PyTuple_GET_ITEM(spec_seq, tag);
|
||||
if (item_spec == Py_None) {
|
||||
if (!skip(type)) {
|
||||
PyErr_SetString(PyExc_TypeError, "Error while skipping unknown field");
|
||||
return NULL;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
StructItemSpec parsedspec;
|
||||
if (!parse_struct_item_spec(&parsedspec, item_spec)) {
|
||||
return NULL;
|
||||
}
|
||||
if (parsedspec.type != type) {
|
||||
if (!skip(type)) {
|
||||
PyErr_Format(PyExc_TypeError, "struct field had wrong type: expected %d but got %d",
|
||||
parsedspec.type, type);
|
||||
return NULL;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
ScopedPyObject fieldval(decodeValue(parsedspec.type, parsedspec.typeargs));
|
||||
if (!fieldval) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((immutable && PyDict_SetItem(kwargs.get(), parsedspec.attrname, fieldval.get()) == -1)
|
||||
|| (!immutable && PyObject_SetAttr(output, parsedspec.attrname, fieldval.get()) == -1)) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
if (immutable) {
|
||||
ScopedPyObject args(PyTuple_New(0));
|
||||
if (!args) {
|
||||
PyErr_SetString(PyExc_TypeError, "failed to prepare argument storage");
|
||||
return NULL;
|
||||
}
|
||||
return PyObject_Call(klass, args.get(), kwargs.get());
|
||||
}
|
||||
Py_INCREF(output);
|
||||
return output;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // THRIFT_PY_PROTOCOL_H
|
113
vendor/git.apache.org/thrift.git/lib/py/src/ext/types.cpp
generated
vendored
Normal file
113
vendor/git.apache.org/thrift.git/lib/py/src/ext/types.cpp
generated
vendored
Normal file
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include "ext/types.h"
|
||||
#include "ext/protocol.h"
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace py {
|
||||
|
||||
PyObject* ThriftModule = NULL;
|
||||
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
char refill_signature[] = {'s', '#', 'i'};
|
||||
#else
|
||||
const char* refill_signature = "y#i";
|
||||
#endif
|
||||
|
||||
bool parse_struct_item_spec(StructItemSpec* dest, PyObject* spec_tuple) {
|
||||
// i'd like to use ParseArgs here, but it seems to be a bottleneck.
|
||||
if (PyTuple_Size(spec_tuple) != 5) {
|
||||
PyErr_Format(PyExc_TypeError, "expecting 5 arguments for spec tuple but got %d",
|
||||
static_cast<int>(PyTuple_Size(spec_tuple)));
|
||||
return false;
|
||||
}
|
||||
|
||||
dest->tag = static_cast<TType>(PyInt_AsLong(PyTuple_GET_ITEM(spec_tuple, 0)));
|
||||
if (INT_CONV_ERROR_OCCURRED(dest->tag)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
dest->type = static_cast<TType>(PyInt_AsLong(PyTuple_GET_ITEM(spec_tuple, 1)));
|
||||
if (INT_CONV_ERROR_OCCURRED(dest->type)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
dest->attrname = PyTuple_GET_ITEM(spec_tuple, 2);
|
||||
dest->typeargs = PyTuple_GET_ITEM(spec_tuple, 3);
|
||||
dest->defval = PyTuple_GET_ITEM(spec_tuple, 4);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool parse_set_list_args(SetListTypeArgs* dest, PyObject* typeargs) {
|
||||
if (PyTuple_Size(typeargs) != 3) {
|
||||
PyErr_SetString(PyExc_TypeError, "expecting tuple of size 3 for list/set type args");
|
||||
return false;
|
||||
}
|
||||
|
||||
dest->element_type = static_cast<TType>(PyInt_AsLong(PyTuple_GET_ITEM(typeargs, 0)));
|
||||
if (INT_CONV_ERROR_OCCURRED(dest->element_type)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
dest->typeargs = PyTuple_GET_ITEM(typeargs, 1);
|
||||
|
||||
dest->immutable = Py_True == PyTuple_GET_ITEM(typeargs, 2);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool parse_map_args(MapTypeArgs* dest, PyObject* typeargs) {
|
||||
if (PyTuple_Size(typeargs) != 5) {
|
||||
PyErr_SetString(PyExc_TypeError, "expecting 5 arguments for typeargs to map");
|
||||
return false;
|
||||
}
|
||||
|
||||
dest->ktag = static_cast<TType>(PyInt_AsLong(PyTuple_GET_ITEM(typeargs, 0)));
|
||||
if (INT_CONV_ERROR_OCCURRED(dest->ktag)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
dest->vtag = static_cast<TType>(PyInt_AsLong(PyTuple_GET_ITEM(typeargs, 2)));
|
||||
if (INT_CONV_ERROR_OCCURRED(dest->vtag)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
dest->ktypeargs = PyTuple_GET_ITEM(typeargs, 1);
|
||||
dest->vtypeargs = PyTuple_GET_ITEM(typeargs, 3);
|
||||
dest->immutable = Py_True == PyTuple_GET_ITEM(typeargs, 4);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool parse_struct_args(StructTypeArgs* dest, PyObject* typeargs) {
|
||||
if (PyTuple_Size(typeargs) != 2) {
|
||||
PyErr_SetString(PyExc_TypeError, "expecting tuple of size 2 for struct args");
|
||||
return false;
|
||||
}
|
||||
|
||||
dest->klass = PyTuple_GET_ITEM(typeargs, 0);
|
||||
dest->spec = PyTuple_GET_ITEM(typeargs, 1);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
191
vendor/git.apache.org/thrift.git/lib/py/src/ext/types.h
generated
vendored
Normal file
191
vendor/git.apache.org/thrift.git/lib/py/src/ext/types.h
generated
vendored
Normal file
|
@ -0,0 +1,191 @@
|
|||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef THRIFT_PY_TYPES_H
|
||||
#define THRIFT_PY_TYPES_H
|
||||
|
||||
#include <Python.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#define __STDC_LIMIT_MACROS
|
||||
#endif
|
||||
#include <stdint.h>
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
|
||||
#include <vector>
|
||||
|
||||
// TODO: better macros
|
||||
#define PyInt_AsLong(v) PyLong_AsLong(v)
|
||||
#define PyInt_FromLong(v) PyLong_FromLong(v)
|
||||
|
||||
#define PyString_InternFromString(v) PyUnicode_InternFromString(v)
|
||||
|
||||
#endif
|
||||
|
||||
#define INTERN_STRING(value) _intern_##value
|
||||
|
||||
#define INT_CONV_ERROR_OCCURRED(v) (((v) == -1) && PyErr_Occurred())
|
||||
|
||||
extern "C" {
|
||||
extern PyObject* INTERN_STRING(TFrozenDict);
|
||||
extern PyObject* INTERN_STRING(cstringio_buf);
|
||||
extern PyObject* INTERN_STRING(cstringio_refill);
|
||||
}
|
||||
|
||||
namespace apache {
|
||||
namespace thrift {
|
||||
namespace py {
|
||||
|
||||
extern PyObject* ThriftModule;
|
||||
|
||||
// Stolen out of TProtocol.h.
|
||||
// It would be a huge pain to have both get this from one place.
|
||||
enum TType {
|
||||
T_INVALID = -1,
|
||||
T_STOP = 0,
|
||||
T_VOID = 1,
|
||||
T_BOOL = 2,
|
||||
T_BYTE = 3,
|
||||
T_I08 = 3,
|
||||
T_I16 = 6,
|
||||
T_I32 = 8,
|
||||
T_U64 = 9,
|
||||
T_I64 = 10,
|
||||
T_DOUBLE = 4,
|
||||
T_STRING = 11,
|
||||
T_UTF7 = 11,
|
||||
T_STRUCT = 12,
|
||||
T_MAP = 13,
|
||||
T_SET = 14,
|
||||
T_LIST = 15,
|
||||
T_UTF8 = 16,
|
||||
T_UTF16 = 17
|
||||
};
|
||||
|
||||
// replace with unique_ptr when we're OK with C++11
|
||||
class ScopedPyObject {
|
||||
public:
|
||||
ScopedPyObject() : obj_(NULL) {}
|
||||
explicit ScopedPyObject(PyObject* py_object) : obj_(py_object) {}
|
||||
~ScopedPyObject() {
|
||||
if (obj_)
|
||||
Py_DECREF(obj_);
|
||||
}
|
||||
PyObject* get() throw() { return obj_; }
|
||||
operator bool() { return obj_; }
|
||||
void reset(PyObject* py_object) throw() {
|
||||
if (obj_)
|
||||
Py_DECREF(obj_);
|
||||
obj_ = py_object;
|
||||
}
|
||||
PyObject* release() throw() {
|
||||
PyObject* tmp = obj_;
|
||||
obj_ = NULL;
|
||||
return tmp;
|
||||
}
|
||||
void swap(ScopedPyObject& other) throw() {
|
||||
ScopedPyObject tmp(other.release());
|
||||
other.reset(release());
|
||||
reset(tmp.release());
|
||||
}
|
||||
|
||||
private:
|
||||
ScopedPyObject(const ScopedPyObject&) {}
|
||||
ScopedPyObject& operator=(const ScopedPyObject&) { return *this; }
|
||||
|
||||
PyObject* obj_;
|
||||
};
|
||||
|
||||
/**
|
||||
* A cache of the two key attributes of a CReadableTransport,
|
||||
* so we don't have to keep calling PyObject_GetAttr.
|
||||
*/
|
||||
struct DecodeBuffer {
|
||||
ScopedPyObject stringiobuf;
|
||||
ScopedPyObject refill_callable;
|
||||
};
|
||||
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
extern char refill_signature[3];
|
||||
typedef PyObject EncodeBuffer;
|
||||
#else
|
||||
extern const char* refill_signature;
|
||||
struct EncodeBuffer {
|
||||
std::vector<char> buf;
|
||||
size_t pos;
|
||||
};
|
||||
#endif
|
||||
|
||||
/**
|
||||
* A cache of the spec_args for a set or list,
|
||||
* so we don't have to keep calling PyTuple_GET_ITEM.
|
||||
*/
|
||||
struct SetListTypeArgs {
|
||||
TType element_type;
|
||||
PyObject* typeargs;
|
||||
bool immutable;
|
||||
};
|
||||
|
||||
/**
|
||||
* A cache of the spec_args for a map,
|
||||
* so we don't have to keep calling PyTuple_GET_ITEM.
|
||||
*/
|
||||
struct MapTypeArgs {
|
||||
TType ktag;
|
||||
TType vtag;
|
||||
PyObject* ktypeargs;
|
||||
PyObject* vtypeargs;
|
||||
bool immutable;
|
||||
};
|
||||
|
||||
/**
|
||||
* A cache of the spec_args for a struct,
|
||||
* so we don't have to keep calling PyTuple_GET_ITEM.
|
||||
*/
|
||||
struct StructTypeArgs {
|
||||
PyObject* klass;
|
||||
PyObject* spec;
|
||||
bool immutable;
|
||||
};
|
||||
|
||||
/**
|
||||
* A cache of the item spec from a struct specification,
|
||||
* so we don't have to keep calling PyTuple_GET_ITEM.
|
||||
*/
|
||||
struct StructItemSpec {
|
||||
int tag;
|
||||
TType type;
|
||||
PyObject* attrname;
|
||||
PyObject* typeargs;
|
||||
PyObject* defval;
|
||||
};
|
||||
|
||||
bool parse_set_list_args(SetListTypeArgs* dest, PyObject* typeargs);
|
||||
|
||||
bool parse_map_args(MapTypeArgs* dest, PyObject* typeargs);
|
||||
|
||||
bool parse_struct_args(StructTypeArgs* dest, PyObject* typeargs);
|
||||
|
||||
bool parse_struct_item_spec(StructItemSpec* dest, PyObject* spec_tuple);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif // THRIFT_PY_TYPES_H
|
Loading…
Add table
Add a link
Reference in a new issue