├── pyorient_native ├── orientc.h ├── parse_exception.cpp ├── parse_exception.h ├── helpers.h ├── encoder.h ├── pendian.h ├── listener.h ├── version_compare.h ├── pyorient_native.cpp ├── helpers.cpp ├── orientc_writer.h ├── orientc_reader.h ├── encoder.cpp ├── listener.cpp ├── orientc_reader.cpp └── orientc_writer.cpp ├── .gitignore ├── README.md ├── setup.py ├── tests └── test_version_compare.cpp └── LICENSE /pyorient_native/orientc.h: -------------------------------------------------------------------------------- 1 | /* 2 | * orientc.h 3 | * 4 | * Created on: 22 Jul 2015 5 | * Author: tglman 6 | */ 7 | 8 | #ifndef SRC_ORIENTC_H_ 9 | #define SRC_ORIENTC_H_ 10 | 11 | #include "orientc_reader.h" 12 | #include "orientc_writer.h" 13 | 14 | #endif /* SRC_ORIENTC_H_ */ 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Compiled Dynamic libraries 12 | *.so 13 | *.dylib 14 | *.dll 15 | 16 | # Fortran module files 17 | *.mod 18 | *.smod 19 | 20 | # Compiled Static libraries 21 | *.lai 22 | *.la 23 | *.a 24 | *.lib 25 | 26 | # Executables 27 | *.exe 28 | *.out 29 | *.app 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # pyorient_native 2 | This package provides python interface for OrientDB binary Serialization. It provides much faster serialization support for pyorient () as compared to the CSV protocol, especially for Embedded Lists, Maps etc. 3 | 4 | pyorient_native is based on the OrientDB C driver () 5 | 6 | # Installation 7 | pip install pyorient_native 8 | 9 | -------------------------------------------------------------------------------- /pyorient_native/parse_exception.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * ParseException.cpp 3 | * 4 | * Created on: 5 Aug 2015 5 | * Author: tglman 6 | */ 7 | 8 | #include "parse_exception.h" 9 | 10 | namespace Orient { 11 | 12 | parse_exception::parse_exception(const std::string message) : 13 | message(message) { 14 | 15 | } 16 | 17 | const char* parse_exception::what() const throw () { 18 | return message.c_str(); 19 | } 20 | 21 | parse_exception::~parse_exception() throw () { 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /pyorient_native/parse_exception.h: -------------------------------------------------------------------------------- 1 | /* 2 | * ParseException.h 3 | * 4 | * Created on: 5 Aug 2015 5 | * Author: tglman 6 | */ 7 | 8 | #ifndef SRC_PARSE_EXCEPTION_H_ 9 | #define SRC_PARSE_EXCEPTION_H_ 10 | 11 | #include 12 | #include 13 | namespace Orient { 14 | 15 | class parse_exception : public std::exception { 16 | public: 17 | parse_exception(const std::string message); 18 | virtual const char* what() const throw(); 19 | virtual ~parse_exception() throw(); 20 | private: 21 | std::string message; 22 | }; 23 | 24 | } 25 | #endif /* SRC_PARSE_EXCEPTION_H_ */ 26 | -------------------------------------------------------------------------------- /pyorient_native/helpers.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | namespace Orient { 4 | 5 | class ContentBuffer { 6 | public: 7 | ContentBuffer(); 8 | ContentBuffer(const unsigned char * content, const int content_size); 9 | void prepare(int next); 10 | void force_cursor(int position); 11 | unsigned char *content; 12 | int cursor; 13 | int prepared; 14 | int size; 15 | ~ContentBuffer(); 16 | private: 17 | bool writing; 18 | }; 19 | 20 | int64_t readVarint(ContentBuffer &reader); 21 | 22 | void writeVarint(ContentBuffer &reader,int64_t value); 23 | 24 | 25 | } // namespace Orient 26 | -------------------------------------------------------------------------------- /pyorient_native/encoder.h: -------------------------------------------------------------------------------- 1 | #ifndef ENCODER_H 2 | #define ENCODER_H 3 | #include "Python.h" 4 | #include "orientc.h" 5 | 6 | using namespace Orient; 7 | using namespace std; 8 | 9 | class PyRecWriter{ 10 | public: 11 | const unsigned char* serialize(PyObject* pyrec, int *size); 12 | 13 | PyRecWriter() ; 14 | ~PyRecWriter() ; 15 | private: 16 | RecordWriter* writer; 17 | void write_record(PyObject *pyrec); 18 | void write_value(PyObject *pyval); 19 | void write_list(PyObject* pylist); 20 | void write_dict(PyObject* pydict); 21 | void write_int(PyObject* pyval); 22 | void write_long(PyObject* pyval); 23 | void write_float(PyObject* pyval); 24 | void write_binary(PyObject* pyval); 25 | void write_date(PyObject* pyval); 26 | void write_datetime(PyObject* pyval); 27 | void write_link(PyObject* pylink); 28 | void write_ridbagtreekey(); 29 | }; 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /pyorient_native/pendian.h: -------------------------------------------------------------------------------- 1 | #ifndef PORTABLE_ENDIAN_H__ 2 | #define PORTABLE_ENDIAN_H__ 3 | 4 | #if (defined(_WIN16) || defined(_WIN32) || defined(_WIN64)) && !defined(__WINDOWS__) 5 | 6 | # define __WINDOWS__ 7 | 8 | #endif 9 | 10 | #if defined(__linux__) || defined(__CYGWIN__) 11 | 12 | # include 13 | # include 14 | # define ntohll(x) be64toh(x) 15 | # define htonll(x) htobe64(x) 16 | 17 | #elif defined(__APPLE__) 18 | 19 | # include 20 | # include 21 | 22 | # define ntohll(x) OSSwapBigToHostInt64(x) 23 | # define htonll(x) OSSwapHostToBigInt64(x) 24 | 25 | #elif defined(__OpenBSD__) 26 | 27 | # include 28 | # include 29 | # define ntohll(x) be64toh(x) 30 | # define htonll(x) htobe64(x) 31 | 32 | #elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) 33 | 34 | # include 35 | # include 36 | 37 | # define be64toh(x) betoh64(x) 38 | 39 | # define ntohll(x) be64toh(x) 40 | # define htonll(x) htobe64(x) 41 | 42 | #elif defined(__WINDOWS__) 43 | 44 | # include 45 | #else 46 | 47 | # error platform not supported 48 | 49 | #endif 50 | 51 | #endif -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import find_packages, setup, Extension 2 | 3 | h_files = [ 4 | "pyorient_native/orientc_reader.h", 5 | "pyorient_native/orientc_writer.h", 6 | "pyorient_native/orientc.h", 7 | "pyorient_native/helpers.h", 8 | "pyorient_native/parse_exception.h", 9 | "pyorient_native/listener.h", 10 | "pyorient_native/encoder.h", 11 | "pyorient_native/pendian.h" 12 | ] 13 | pyorient_native = Extension( 14 | "pyorient_native", 15 | sources=[ 16 | "pyorient_native/orientc_reader.cpp", 17 | "pyorient_native/orientc_writer.cpp", 18 | "pyorient_native/helpers.cpp", 19 | "pyorient_native/parse_exception.cpp", 20 | "pyorient_native/listener.cpp", 21 | "pyorient_native/encoder.cpp", 22 | "pyorient_native/pyorient_native.cpp"], 23 | depends=h_files, 24 | library_dirs=[], 25 | include_dirs=["./pyorient_native"], 26 | language="c++", 27 | libraries=["stdc++"] 28 | ) 29 | setup( 30 | name="pyorient_native", 31 | version="1.2.3", 32 | description="OrientDB Binary Serialization package for python", 33 | author="Nikul Ukani", 34 | author_email="nhu2001@columbia.edu", 35 | ext_modules=[pyorient_native], 36 | packages=find_packages(), 37 | url="https://github.com/nikulukani/pyorient_native", 38 | download_url="https://github.com/nikulukani/pyorient_native/" 39 | "archive/1.2.3.tar.gz" 40 | ) 41 | -------------------------------------------------------------------------------- /pyorient_native/listener.h: -------------------------------------------------------------------------------- 1 | #ifndef LISTENER_H 2 | #define LISTENER_H 3 | #include "Python.h" 4 | #include "orientc_reader.h" 5 | #include 6 | 7 | using namespace Orient; 8 | using namespace std; 9 | 10 | class TrackerListener: public RecordParseListener { 11 | public: 12 | PyObject *obj; 13 | string *cur_field; 14 | stack types_stack; 15 | stack obj_stack; 16 | bool legacy_link; 17 | 18 | virtual void startDocument(const char * name,size_t name_length) ; 19 | virtual void endDocument() ; 20 | virtual void startField(const char * name,size_t name_length, OType type) ; 21 | virtual void endField(const char * name,size_t name_length) ; 22 | virtual void stringValue(const char * value,size_t value_length) ; 23 | virtual void intValue(long value) ; 24 | virtual void longValue(long long value) ; 25 | virtual void shortValue(short value); 26 | virtual void byteValue(char value) ; 27 | virtual void booleanValue(bool value); 28 | virtual void floatValue(float value) ; 29 | virtual void doubleValue(double value) ; 30 | virtual void binaryValue(const char * value, int length) ; 31 | virtual void dateValue(long long value) ; 32 | virtual void dateTimeValue(long long value) ; 33 | virtual void linkValue(struct Link &value) ; 34 | virtual void startCollection(int size,OType type); 35 | virtual void startMap(int size,OType type) ; 36 | virtual void mapKey(const char *key,size_t key_length); 37 | virtual void ridBagTreeKey(long long fileId,long long pageIndex,long pageOffset); 38 | virtual void nullValue(); 39 | virtual void endMap(OType type); 40 | virtual void endCollection(OType type); 41 | virtual void decimalValue(int scale , const char * bytes, int bytes_length); 42 | 43 | TrackerListener(PyObject* props) ; 44 | ~TrackerListener() ; 45 | 46 | }; 47 | 48 | #endif 49 | -------------------------------------------------------------------------------- /pyorient_native/version_compare.h: -------------------------------------------------------------------------------- 1 | /* Sam Caldwell (released public domain to the project where this code resides). 2 | * Version Comparison Class. 3 | * 4 | * Given a version string in the form xxx.yyy.zzz.aaa, this class will parse the string 5 | * and allow version comparison operators to test equivalence, etc. Expected behavior is 6 | * defined in test_version_compare.cpp (in tests/ directory). 7 | * 8 | */ 9 | #ifndef VERSION_COMPARE_H 10 | #define VERSION_COMPARE_H 11 | #endif 12 | #include 13 | #include 14 | 15 | using namespace std; 16 | 17 | class Version { 18 | public: 19 | Version(const char *c){ 20 | string version(c); 21 | this->major = 0; 22 | this->minor = 0; 23 | this->revision = 0; 24 | this->build = 0; 25 | std::sscanf(version.c_str(), "%d.%d.%d.%d", &this->major, &this->minor, &this->revision, &this->build); 26 | } 27 | 28 | bool operator<(const Version rhs){ 29 | if (this->major < rhs.major) 30 | return true; 31 | if (this->minor < rhs.minor) 32 | return true; 33 | if (this->revision < rhs.revision) 34 | return true; 35 | if (this->build < rhs.build) 36 | return true; 37 | return false; 38 | } 39 | 40 | bool operator>(const Version rhs){ 41 | if (this->major > rhs.major) 42 | return true; 43 | if (this->minor > rhs.minor) 44 | return true; 45 | if (this->revision > rhs.revision) 46 | return true; 47 | if (this->build > rhs.build) 48 | return true; 49 | return false; 50 | } 51 | 52 | bool operator==(const Version rhs){ 53 | return this->major == rhs.major 54 | && this->minor == rhs.minor 55 | && this->revision == rhs.revision 56 | && this->build == rhs.build; 57 | } 58 | 59 | bool operator!=(const Version rhs){ 60 | return this->major != rhs.major 61 | && this->minor != rhs.minor 62 | && this->revision != rhs.revision 63 | && this->build != rhs.build; 64 | } 65 | 66 | public: 67 | int major = 0; 68 | int minor = 0; 69 | int revision = 0; 70 | int build = 0; 71 | }; -------------------------------------------------------------------------------- /pyorient_native/pyorient_native.cpp: -------------------------------------------------------------------------------- 1 | #include "Python.h" 2 | #include "orientc.h" 3 | #include "listener.h" 4 | #include "encoder.h" 5 | 6 | #include 7 | using namespace Orient; 8 | using namespace std; 9 | 10 | 11 | static PyObject* 12 | native_deserialize(PyObject *self, PyObject *args){ 13 | PyObject * pycontent; 14 | int len; 15 | PyObject * props = NULL; 16 | PyArg_ParseTuple(args, "|SiO", &pycontent, &len, &props); 17 | 18 | RecordParser reader("onet_ser_v0"); 19 | TrackerListener* listener; 20 | 21 | listener = new TrackerListener(props); 22 | #if PY_MAJOR_VERSION >= 3 23 | reader.parse((unsigned char*)PyBytes_AsString(pycontent), len, *listener); 24 | #else 25 | reader.parse((unsigned char*)PyString_AsString(pycontent), len, *listener); 26 | #endif 27 | PyObject *ret = listener->obj; 28 | delete listener; 29 | //Py_XDECREF(pycontent); 30 | return ret; 31 | } 32 | 33 | static PyObject* native_serialize(PyObject* self, PyObject *args){ 34 | PyObject *pyrec; 35 | int size; 36 | const char *content; 37 | PyArg_ParseTuple(args, "O", &pyrec); 38 | 39 | PyRecWriter writer; 40 | content = (const char *) writer.serialize(pyrec, &size); 41 | 42 | #if PY_MAJOR_VERSION >= 3 43 | return PyBytes_FromStringAndSize(content, size); 44 | #else 45 | return PyString_FromStringAndSize(content, size); 46 | #endif 47 | 48 | } 49 | 50 | 51 | 52 | static PyMethodDef native_methods[] = { 53 | {"deserialize", native_deserialize, METH_VARARGS, ""}, 54 | {"serialize", native_serialize, METH_VARARGS, ""}, 55 | {NULL, NULL,0, NULL} 56 | }; 57 | 58 | 59 | #if PY_MAJOR_VERSION >= 3 60 | #define MOD_DEF(ob, name, doc, methods) \ 61 | static struct PyModuleDef moduledef = { \ 62 | PyModuleDef_HEAD_INIT, name, doc, -1, methods, }; \ 63 | ob = PyModule_Create(&moduledef); 64 | #else 65 | #define MOD_DEF(ob, name, doc, methods) \ 66 | ob = Py_InitModule3(name, methods, doc); 67 | #endif 68 | 69 | 70 | static PyObject * 71 | moduleinit(void) 72 | { 73 | PyObject *m; 74 | MOD_DEF(m, "pyorient_native", 75 | "This is the module docstring", 76 | native_methods) 77 | 78 | if (m == NULL) 79 | return NULL; 80 | 81 | 82 | return m; 83 | } 84 | 85 | #if PY_MAJOR_VERSION < 3 86 | PyMODINIT_FUNC initpyorient_native(void) 87 | { 88 | moduleinit(); 89 | } 90 | #else 91 | PyMODINIT_FUNC PyInit_pyorient_native(void) 92 | { 93 | return moduleinit(); 94 | } 95 | #endif 96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /pyorient_native/helpers.cpp: -------------------------------------------------------------------------------- 1 | #include "helpers.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "parse_exception.h" 9 | namespace Orient { 10 | 11 | ContentBuffer::ContentBuffer() : 12 | content(0), cursor(0), prepared(0), size(0), writing(true) { 13 | content = new unsigned char[2048]; 14 | size = 2048; 15 | } 16 | 17 | ContentBuffer::ContentBuffer(const unsigned char * content, const int content_size) : 18 | content((unsigned char*) content), cursor(0), prepared(0), size(content_size), writing(false) { 19 | } 20 | 21 | void ContentBuffer::prepare(int next) { 22 | assert(next > 0); 23 | if (prepared + next > this->size) { 24 | if (writing) { 25 | int newSize = size; 26 | while (prepared + next > newSize) 27 | newSize *= 2; 28 | unsigned char * new_content = new unsigned char[newSize]; 29 | std::copy(content, content + size, new_content); 30 | delete[] content; 31 | content = new_content; 32 | size = newSize; 33 | } else { 34 | std::stringstream ss; 35 | ss << "out of content size:" << this->size << " nextCursor:" << prepared + next; 36 | throw parse_exception(ss.str()); 37 | } 38 | } 39 | cursor = prepared; 40 | prepared += next; 41 | } 42 | 43 | ContentBuffer::~ContentBuffer() { 44 | if (writing) 45 | delete[] content; 46 | } 47 | 48 | void ContentBuffer::force_cursor(int position) { 49 | if (position > this->size) 50 | throw parse_exception(" out of content size"); 51 | cursor = position; 52 | prepared = position; 53 | } 54 | 55 | int64_t readVarint(ContentBuffer &reader) { 56 | int64_t value = 0; 57 | int32_t i = 0; 58 | uint64_t b; 59 | do { 60 | reader.prepare(1); 61 | b = (uint64_t) reader.content[reader.cursor]; 62 | if ((b & 0x80) != 0) { 63 | value |= ((b & 0x7F) << i); 64 | i += 7; 65 | if (i > 63) { 66 | throw "Variable length quantity is too long (must be <= 63)"; 67 | } 68 | } 69 | } while ((b & 0x80) != 0); 70 | value |= b << i; 71 | int64_t temp = ((((int64_t) value << 63) >> 63) ^ (int64_t) value) >> 1; 72 | return temp ^ (value & ((int64_t) 1 << 63)); 73 | } 74 | 75 | void writeVarint(ContentBuffer &reader, int64_t value) { 76 | uint64_t realValue = (value << (int64_t) 1) ^ (value >> (int64_t) 63); 77 | while ((realValue & 0xFFFFFFFFFFFFFF80) != 0) { 78 | reader.prepare(1); 79 | reader.content[reader.cursor] = (unsigned char) ((realValue & 0x7F) | 0x80); 80 | realValue >>= 7; 81 | } 82 | reader.prepare(1); 83 | reader.content[reader.cursor] = (unsigned char) ((realValue & 0x7F)); 84 | } 85 | 86 | } 87 | -------------------------------------------------------------------------------- /tests/test_version_compare.cpp: -------------------------------------------------------------------------------- 1 | /* Sam Caldwell (released public domain to the project where this code resides). 2 | * This file contains the tests for the version_compare.h source file. 3 | */ 4 | #include "../pyorient_native/version_compare.h" 5 | #include 6 | #include 7 | 8 | /*void show_values(Version v1, Version v2){ 9 | cout << "show_values():\n"; 10 | cout << "\tv1: " << v1.major << "." << v1.minor << "." << v1.revision << "." << v1.build << "\n"; 11 | cout << "\tv2: " << v2.major << "." << v2.minor << "." << v2.revision << "." << v2.build << "\n"; 12 | cout << "\t---\n"; 13 | }*/ 14 | 15 | bool test_equivalence_operator_happy(){ 16 | cout << "test: test_equivalence_operator_happy() starting\n"; 17 | const char *version_string = "1.0.0"; 18 | 19 | Version v1(version_string); 20 | Version v2(version_string); 21 | 22 | return (v1 == v2); 23 | } 24 | 25 | bool test_equivalence_operator_sad(){ 26 | cout << "test: test_equivalence_operator_sad(): starting\n"; 27 | const char *version_string1 = "1.0.0"; 28 | const char *version_string2 = "2.0.0"; 29 | 30 | Version v1(version_string1); 31 | Version v2(version_string2); 32 | 33 | return !(v1 == v2); 34 | } 35 | 36 | bool test_less_than_operator_happy(){ 37 | cout << "test: test_less_than_operator_happy(): starting\n"; 38 | const char *version_string1 = "1.0.0"; 39 | const char *version_string2 = "1.0.1"; 40 | 41 | Version v1(version_string1); 42 | Version v2(version_string2); 43 | 44 | return (v1 < v2); 45 | } 46 | 47 | bool test_less_than_operator_sad_if_equal(){ 48 | cout << "test: test_less_than_operator_sad_if_equal(): starting\n"; 49 | const char *version_string1 = "1.0.0"; 50 | const char *version_string2 = "1.0.0"; 51 | 52 | Version v1(version_string1); 53 | Version v2(version_string2); 54 | 55 | return !(v1 < v2); 56 | } 57 | 58 | bool test_less_than_operator_sad_if_greater(){ 59 | cout << "test: test_less_than_operator_sad_if_greater(): starting\n"; 60 | const char *version_string1 = "2.0.0"; 61 | const char *version_string2 = "1.0.0"; 62 | 63 | Version v1(version_string1); 64 | Version v2(version_string2); 65 | 66 | return !(v1 < v2); 67 | } 68 | 69 | bool test_inequal_operator_happy(){ 70 | cout << "test: test_less_than_operator_sad_if_greater(): starting\n"; 71 | const char *version_string1 = "2.0.0"; 72 | const char *version_string2 = "1.0.0"; 73 | 74 | Version v1(version_string1); 75 | Version v2(version_string2); 76 | 77 | return (v1 != v2); 78 | } 79 | 80 | bool test_inequal_operator_sad(){ 81 | cout << "test: test_less_than_operator_sad_if_greater(): starting\n"; 82 | const char *version_string1 = "1.0.0"; 83 | const char *version_string2 = "1.0.0"; 84 | 85 | Version v1(version_string1); 86 | Version v2(version_string2); 87 | 88 | return !(v1 != v2); 89 | } 90 | 91 | bool test_casted_comparison_happy(){ 92 | cout << "test: test_casted_comparison_happy(): starting\n"; 93 | return (Version)("1.0") == (Version)("1.0"); 94 | } 95 | bool test_casted_comparison_sad(){ 96 | cout << "test: test_casted_comparison_sad(): starting\n"; 97 | return (Version)("1.0") == (Version)("1.0"); 98 | } 99 | 100 | int main(){ 101 | cout << "\n\nStarting tests.\n"; 102 | 103 | assert (test_equivalence_operator_happy()); 104 | assert (test_equivalence_operator_sad()); 105 | assert (test_less_than_operator_happy()); 106 | assert (test_less_than_operator_sad_if_equal()); 107 | assert (test_less_than_operator_sad_if_greater()); 108 | assert (test_casted_comparison_happy()); 109 | assert (test_casted_comparison_sad()); 110 | } 111 | -------------------------------------------------------------------------------- /pyorient_native/orientc_writer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * orientc_writer.h 3 | * 4 | * Created on: 22 Jul 2015 5 | * Author: tglman 6 | */ 7 | 8 | #ifndef SRC_ORIENTC_WRITER_H_ 9 | #define SRC_ORIENTC_WRITER_H_ 10 | #include 11 | #include "orientc_reader.h" 12 | namespace Orient{ 13 | 14 | class InternalWriter; 15 | 16 | 17 | /** Sax style writer for generate serialised version of orientdb formats. 18 | * 19 | * This implementation it's not thread safe and cannot be reused. 20 | * 21 | */ 22 | class RecordWriter { 23 | 24 | public: 25 | /** Create a new instance of the writer with a specific format. 26 | * 27 | * @param format the name of the format, supported formats are "onet_ser_v0" 28 | * 29 | */ 30 | RecordWriter(std::string format); 31 | 32 | /** Start a new document with a specified class. 33 | * 34 | * need to be call for the root and for each embedded document start. 35 | * 36 | * @param className the name of the class of the document or "" in case of missed class. 37 | */ 38 | void startDocument(const char * className); 39 | 40 | /** Start a new collection with a specific size and of a specific type. 41 | * 42 | * @param size the size of the collection. 43 | * @param type is the type of the collection, allowed types are EMBEDDEDSET,EMBEDDEDLIST,LINKSET,LINKLIST,LINKBAG 44 | * 45 | */ 46 | void startCollection(int size,OType type); 47 | 48 | /**Start a new map wiht a specific size and of a specific type 49 | * 50 | * balanced with 51 | * 52 | * @param size the size of the map. 53 | * @param type the type of the map, EMBEDDEDMAP, LINKMAP 54 | * 55 | */ 56 | void startMap(int size,OType type); 57 | 58 | /** Provide the key of a value, should be call before a *Value call. 59 | * 60 | * @param mapKey the key of the map entry. 61 | * 62 | */ 63 | void mapKey(const char * mapKey); 64 | 65 | /** Start a new field, Should be call before a *Value call. 66 | * 67 | * Balanced with endField(const char * name). 68 | * 69 | * @param name the name of the field. 70 | * 71 | */ 72 | void startField(const char* name); 73 | 74 | /** End a field. 75 | * 76 | * Balanced with startField(const char* name) 77 | * 78 | * @param name the name of the field. 79 | * 80 | */ 81 | void endField(const char * name); 82 | 83 | /** Write a string value. 84 | * 85 | * @param value Value to write. 86 | * 87 | */ 88 | void stringValue(const char * value); 89 | 90 | /** Write a int value. 91 | * 92 | * @param value Value to write. 93 | * 94 | */ 95 | void intValue(long value); 96 | 97 | /** Write a long value. 98 | * 99 | * @param value Value to write. 100 | * 101 | */ 102 | void longValue(long long value); 103 | 104 | /** Write a short value. 105 | * 106 | * @param value Value to write. 107 | * 108 | */ 109 | void shortValue(short value); 110 | 111 | /** Write a byte value. 112 | * 113 | * @param value Value to write. 114 | * 115 | */ 116 | void byteValue(char value); 117 | 118 | /** Write a boolean value. 119 | * 120 | * @param value Value to write. 121 | * 122 | */ 123 | void booleanValue(bool value); 124 | 125 | /** Write a float value. 126 | * 127 | * @param value Value to write. 128 | * 129 | */ 130 | void floatValue(float value); 131 | 132 | /** Write a double value. 133 | * 134 | * @param value Value to write. 135 | * 136 | */ 137 | void doubleValue(double value); 138 | 139 | /** Write a binary value. 140 | * 141 | * @param value Value to write.. 142 | * @param length the length of the value. 143 | * 144 | */ 145 | void binaryValue(const char * value, int length); 146 | 147 | /** Write a date value . 148 | * 149 | * @param value Value to write. 150 | * 151 | */ 152 | void dateValue(long long value); 153 | 154 | /** Write a datetime value. 155 | * 156 | * @param value Value to write. 157 | * 158 | */ 159 | void dateTimeValue(long long value); 160 | 161 | /** Write a link value. 162 | * 163 | * @param value Value to write. 164 | * 165 | */ 166 | void linkValue(struct Link & value); 167 | 168 | /** Write a ridbag tree key. 169 | * 170 | * @param value ridbag tree key. 171 | * 172 | */ 173 | void ridBagTreeKey(long long fileId,long long pageIndex,long pageOffset); 174 | 175 | /** Write a decima value. 176 | * 177 | * @param scale the scale of the decimal value. 178 | * @param bytes the bytes that rapresent the decimal value. 179 | * @param bytes_length the length ofthe bytes that represent the decimal. 180 | * 181 | */ 182 | void decimalValue(int scale, const char * bytes, int bytes_length); 183 | 184 | /** Write a null value. 185 | * 186 | */ 187 | void nullValue(); 188 | 189 | /** End a map 190 | * 191 | * Balanced with startMap(int size,OType type); 192 | * 193 | * @param type the type of the map, EMBEDDEDMAP, LINKMAP 194 | */ 195 | void endMap(OType type); 196 | 197 | /** End a collection 198 | * 199 | * Balanced with startCollection(int size,OType type); 200 | * 201 | * @param type is the type of the collection, allowed types are EMBEDDEDSET,EMBEDDEDLIST,LINKSET,LINKLIST,LINKBAG 202 | * 203 | */ 204 | void endCollection(OType type); 205 | /** End an embedded document or the root document. 206 | * 207 | */ 208 | void endDocument(); 209 | 210 | /** 211 | * Return the written content, can be call just after the last endDocument call. 212 | * 213 | * @param size filled with the size of the record. 214 | * @return the bytes result of the write operation. 215 | * 216 | */ 217 | const unsigned char * writtenContent(int *size); 218 | 219 | /** 220 | * free all internal structures. 221 | * 222 | */ 223 | ~RecordWriter(); 224 | private: 225 | InternalWriter *writer; 226 | }; 227 | 228 | 229 | } 230 | #endif /* SRC_ORIENTC_WRITER_H_ */ 231 | -------------------------------------------------------------------------------- /pyorient_native/orientc_reader.h: -------------------------------------------------------------------------------- 1 | /* 2 | * orientc_reader.h 3 | * 4 | * Created on: 22 Jul 2015 5 | * Author: tglman 6 | */ 7 | 8 | #ifndef SRC_ORIENTC_READER_H_ 9 | #define SRC_ORIENTC_READER_H_ 10 | #include 11 | #include "Python.h" 12 | #include 13 | 14 | #if PY_MAJOR_VERSION >= 3 15 | #define PyInt_FromLong PyLong_FromLong 16 | #define PyInt_AsLong PyLong_AsLong 17 | #define PyInt_Check(val) PyLong_Check(val) && ((int) PyInt_AsLong(val)) == ((long) PyInt_AsLong(val)) 18 | #define PyString_Check PyUnicode_Check 19 | char* PyString_AsString(PyObject* obj); 20 | #endif 21 | 22 | 23 | namespace Orient { 24 | 25 | enum OType { 26 | BOOLEAN =0, 27 | INTEGER =1, 28 | SHORT =2, 29 | LONG =3, 30 | FLOAT =4, 31 | DOUBLE =5, 32 | DATETIME=6, 33 | STRING=7, 34 | BINARY=8, 35 | EMBEDDED=9, 36 | EMBEDDEDLIST=10, 37 | EMBEDDEDSET=11, 38 | EMBEDDEDMAP=12, 39 | LINK =13, 40 | LINKLIST=14, 41 | LINKSET =15, 42 | LINKMAP =16, 43 | BYTE = 17, 44 | TRANSIENT = 18, 45 | DATE =19, 46 | CUSTOM = 20, 47 | DECIMAL = 21, 48 | LINKBAG = 22, 49 | ANY = 23 50 | }; 51 | struct Link { 52 | long cluster; 53 | long long position; 54 | }; 55 | /** Sax style record parse listener, extends this class for get the result of the parse operations. 56 | * 57 | */ 58 | class RecordParseListener { 59 | public: 60 | 61 | PyObject* props; 62 | /** Called at the start of a document in any case of root and embedded document. 63 | * 64 | * Balanced with endDocument(); 65 | * 66 | * @param class_name the name of the class 67 | * @param class_name_length the number of bytes to consider in the class_name. 68 | * 69 | */ 70 | virtual void startDocument(const char * class_name, size_t class_name_length)=0; 71 | 72 | /** 73 | * Called each time a collection start. 74 | * 75 | * Balanced with endCollection(OType type); 76 | * 77 | * @param size the number of element present in the collection. 78 | * @param type the type of collection can have as value EMBEDDEDSET,EMBEDDEDLIST,LINKSET,LINKLIST,LINKBAG 79 | * 80 | */ 81 | virtual void startCollection(int size,OType type)=0; 82 | 83 | /** Called each time a map start. 84 | * 85 | * Balanced with endMap(OType type); 86 | * 87 | * @param size the number of values in the map. 88 | * @param the type of the map can have as value EMBEDDEDMAP, LINKMAP 89 | * 90 | */ 91 | virtual void startMap(int size,OType type)=0; 92 | 93 | /** Called for each entry of a map defining the key of the map, before a corresponding *Value() method is called for the value. 94 | * 95 | * @param key the name of the key 96 | * @param key_length the number of bytes to consider as key. 97 | * 98 | */ 99 | virtual void mapKey(const char * key,size_t key_length)=0; 100 | 101 | /** Called at the start of each fiend found in a document. 102 | * 103 | * Balanced with endField(const char * name,size_t name_length); 104 | * 105 | * @param name the name of the filed 106 | * @param name_length the number of bytes to consider in the name. 107 | * @param type the type of the field can be any OType. 108 | * 109 | */ 110 | virtual void startField(const char * name,size_t name_length,OType type)=0; 111 | 112 | /** Called after at the end of a field parse. 113 | * 114 | * Balance with startField(const char * name,size_t name_length,OType type) 115 | * 116 | * @param name the name of the field. 117 | * @param name_length the number of bytes to consider as name. 118 | * 119 | */ 120 | virtual void endField(const char * name,size_t name_length)=0; 121 | 122 | /** Called each time is found a string value. 123 | * 124 | * @param value the value. 125 | * @param value_length the number of bytes to consider as value. 126 | * 127 | */ 128 | virtual void stringValue(const char * value ,size_t value_length)=0; 129 | 130 | /** Called each time is found a int value. 131 | * 132 | * @param value the value. 133 | */ 134 | virtual void intValue(long value)=0; 135 | 136 | /** Called each time is found a long value. 137 | * 138 | * @param value the value. 139 | */ 140 | virtual void longValue(long long value)=0; 141 | 142 | /** Called each time is found a short value. 143 | * 144 | * @param value the value. 145 | */ 146 | virtual void shortValue(short value)=0; 147 | 148 | /** Called each time is found a bye value. 149 | * 150 | * @param value the value. 151 | */ 152 | virtual void byteValue(char value)=0; 153 | 154 | /** Called each time is found a boolean value. 155 | * 156 | * @param value the value. 157 | */ 158 | virtual void booleanValue(bool value)=0; 159 | 160 | /** Called each time is found a float value. 161 | * 162 | * @param value the value. 163 | */ 164 | virtual void floatValue(float value)=0; 165 | 166 | /** Called each time is found a double value. 167 | * 168 | * @param value the value. 169 | */ 170 | virtual void doubleValue(double value)=0; 171 | 172 | /** Called each time is found a binary value. 173 | * 174 | * @param value the value. 175 | * @param value_length the number of bytes to consider as value. 176 | * 177 | */ 178 | virtual void binaryValue(const char * value, int length)=0; 179 | 180 | /** Called each time is found a date value. 181 | * 182 | * @param value the value as UTC. 183 | */ 184 | virtual void dateValue(long long value)=0; 185 | 186 | /** Called each time is found a date time value. 187 | * 188 | * @param value the value as UTC. 189 | */ 190 | virtual void dateTimeValue(long long value)=0; 191 | 192 | /** Called each time is found a link value. 193 | * 194 | * @param value a link structure that contains cluster and position. 195 | */ 196 | virtual void linkValue(struct Link & value)=0; 197 | 198 | /** 199 | * Called each time is found a decimal value. 200 | * 201 | * 202 | * @param scale the scale of the decimal value. 203 | * @param bytes that rapresent the decimal value 204 | * @param bytes_length the length of the bytes that represent the value. 205 | * 206 | */ 207 | virtual void decimalValue(int scale , const char * bytes, int bytes_length)=0; 208 | 209 | /** Called each time is found a ridbag tree value. 210 | * 211 | * @param fileId the tree fileId. 212 | * @param pageIndex the tree pageIndex. 213 | * @param pageOffset the tree pageOffeset. 214 | */ 215 | virtual void ridBagTreeKey(long long fileId,long long pageIndex,long pageOffset)=0; 216 | 217 | /** Called each time if found a null value. 218 | * 219 | */ 220 | virtual void nullValue()=0; 221 | 222 | /** Called at the end of a map parse. 223 | * 224 | * Balance with startMap(int size,OType type); 225 | * 226 | * @param type the type of the map can have as value EMBEDDEDMAP, LINKMAP 227 | * 228 | */ 229 | virtual void endMap(OType type)=0; 230 | 231 | /** Called at the edn of a collection parse 232 | * 233 | * Balance with startCollection(int size,OType type); 234 | * 235 | * @param type he type of collection can have as value EMBEDDEDSET,EMBEDDEDLIST,LINKSET,LINKLIST,LINKBAG 236 | * 237 | */ 238 | virtual void endCollection(OType type)=0; 239 | 240 | /** Called at the end of a document for root and embedded documents. 241 | * 242 | */ 243 | virtual void endDocument()=0; 244 | 245 | /**/ 246 | virtual ~RecordParseListener() {} 247 | }; 248 | 249 | 250 | /** Sax style perser for parse record in orientdb serialization formats 251 | * 252 | * this instance can be reused. 253 | * 254 | */ 255 | class RecordParser { 256 | public: 257 | 258 | /** create the instance of the parser with the format 259 | * 260 | * 261 | * @param format the name of the format supported formats are "onet_ser_v0" 262 | */ 263 | RecordParser(std::string format); 264 | 265 | 266 | /** 267 | * Synchronous call for parse a record, the values are passed to the listener as collbacks. 268 | * 269 | * @param content the raw stream of the record. 270 | * @param content_size the number of bytes to read from the content. 271 | * @param listener will receive the call for each value found in the record. 272 | * 273 | */ 274 | void parse(const unsigned char * content,int content_size, RecordParseListener & listener); 275 | 276 | 277 | }; 278 | 279 | } 280 | #endif /* SRC_ORIENTC_READER_H_ */ 281 | -------------------------------------------------------------------------------- /pyorient_native/encoder.cpp: -------------------------------------------------------------------------------- 1 | #include "Python.h" 2 | #include "encoder.h" 3 | #include "orientc.h" 4 | #include "string.h" 5 | #include "time.h" 6 | #include "stdlib.h" 7 | #include "datetime.h" 8 | #include 9 | 10 | using namespace Orient; 11 | using namespace std; 12 | 13 | 14 | const unsigned char* PyRecWriter::serialize(PyObject* pyrec, int *size){ 15 | write_record(pyrec); 16 | return this->writer->writtenContent(size); 17 | } 18 | 19 | PyRecWriter::PyRecWriter(){ 20 | this->writer = new RecordWriter("onet_ser_v0"); 21 | PyDateTime_IMPORT; 22 | } 23 | 24 | PyRecWriter::~PyRecWriter() { 25 | delete this->writer; 26 | } 27 | 28 | void PyRecWriter::write_record(PyObject *pyrec){ 29 | PyObject *reccls = PyObject_GetAttrString(pyrec,"_class"); // new ref 30 | if(reccls!=Py_None){ 31 | this->writer->startDocument(PyString_AsString(reccls)); 32 | } 33 | else{ 34 | this->writer->startDocument(""); 35 | } 36 | PyObject* rec_data = PyObject_GetAttrString(pyrec,"oRecordData"); // new ref 37 | int size = PyDict_Size(rec_data); 38 | PyObject *keys = PyDict_Keys(rec_data); // new ref 39 | PyObject *key; 40 | PyObject *val; 41 | int i; 42 | for(i=0;iwriter->startField(PyString_AsString(key)); 48 | Py_XDECREF(key); 49 | } 50 | else{ 51 | this->writer->startField(PyString_AsString(key)); 52 | } 53 | write_value(val); 54 | this->writer->endField(PyString_AsString(key)); 55 | } 56 | this->writer->endDocument(); 57 | Py_XDECREF(reccls); 58 | Py_XDECREF(rec_data); 59 | Py_XDECREF(keys); 60 | } 61 | 62 | void PyRecWriter::write_link(PyObject *pylink){ 63 | Link link; 64 | PyObject *temp = PyObject_GetAttrString(pylink,"clusterID"); 65 | char* cluster = PyString_AsString(temp); 66 | PyObject *temp1 = PyObject_GetAttrString(pylink,"recordPosition"); 67 | char* position = PyString_AsString(temp1); 68 | link.cluster = atol(cluster); 69 | link.position = atoll(position); 70 | this->writer->linkValue(link); 71 | Py_XDECREF(temp); 72 | Py_XDECREF(temp1); 73 | } 74 | 75 | void PyRecWriter::write_list(PyObject* pylist){ 76 | int size = PyList_Size(pylist); 77 | OType type = EMBEDDEDLIST; 78 | if(!size){ 79 | this->writer->startCollection(0,type); 80 | this->writer->endCollection(type); 81 | return; 82 | } 83 | // See if it is a link list (list of links) 84 | 85 | PyObject *val0=PyList_GetItem(pylist, 0); // borrowed ref 86 | // new refs 87 | PyObject *temp = PyObject_GetAttrString(val0,"__class__"); 88 | PyObject *temp1 = PyObject_GetAttrString(temp,"__name__"); 89 | char* cls = PyString_AsString(temp1); 90 | if(strcmp(cls,"OrientRecordLink")==0) 91 | type = LINKLIST; 92 | this->writer->startCollection(size, type); 93 | int i; 94 | for(i=0;iwriter->endCollection(type); 98 | Py_XDECREF(temp); 99 | Py_XDECREF(temp1); 100 | } 101 | 102 | void PyRecWriter::write_dict(PyObject* pydict){ 103 | int size = PyDict_Size(pydict); 104 | OType type = EMBEDDEDMAP; 105 | this->writer->startMap(size, type); 106 | PyObject *keys = PyDict_Keys(pydict); // new ref 107 | PyObject *key; 108 | PyObject *val; 109 | int i; 110 | for(i=0;iwriter->mapKey(PyString_AsString(key)); 116 | Py_XDECREF(key); 117 | } 118 | else{ 119 | this->writer->mapKey(PyString_AsString(key)); 120 | } 121 | write_value(val); 122 | } 123 | this->writer->endMap(type); 124 | Py_XDECREF(keys); 125 | } 126 | 127 | void PyRecWriter::write_int(PyObject* pyval){ 128 | int val = (int) PyInt_AsLong(pyval); 129 | if (val == -1 && PyErr_Occurred()!=NULL){ 130 | PyObject *temp = PyObject_GetAttrString(pyval,"__class__"); 131 | PyObject *temp1 = PyObject_GetAttrString(temp,"__name__"); 132 | char* cls = PyString_AsString(temp1); 133 | cout << "Error while converting to int from python object of class" << 134 | cls << endl << flush; 135 | Py_XDECREF(temp); 136 | Py_XDECREF(temp1); 137 | return; 138 | } 139 | this->writer->intValue(val); 140 | } 141 | 142 | void PyRecWriter::write_long(PyObject* pyval){ 143 | long val = PyLong_AsLong(pyval); 144 | if (val == -1 && PyErr_Occurred()!=NULL){ 145 | PyObject *temp = PyObject_GetAttrString(pyval,"__class__"); 146 | PyObject *temp1 = PyObject_GetAttrString(temp,"__name__"); 147 | char* cls = PyString_AsString(temp1); 148 | cout << "Error while converting to long from python object of class" << 149 | cls << endl << flush; 150 | Py_XDECREF(temp); 151 | Py_XDECREF(temp1); 152 | return; 153 | } 154 | this->writer->longValue(val); 155 | } 156 | 157 | void PyRecWriter::write_float(PyObject* pyval){ 158 | double val = PyFloat_AsDouble(pyval); 159 | if (val == -1.0 && PyErr_Occurred()!=NULL){ 160 | PyObject *temp = PyObject_GetAttrString(pyval,"__class__"); 161 | PyObject *temp1 = PyObject_GetAttrString(temp,"__name__"); 162 | char* cls = PyString_AsString(temp1); 163 | cout << "Error while converting to float from python object of class" << 164 | cls << endl << flush; 165 | Py_XDECREF(temp); 166 | Py_XDECREF(temp1); 167 | return; 168 | } 169 | this->writer->doubleValue(val); 170 | } 171 | 172 | void PyRecWriter::write_binary(PyObject* pyval){ 173 | PyObject* obj = PyByteArray_FromObject(pyval); // new ref 174 | this->writer->binaryValue((const char *)PyByteArray_AsString(obj), 175 | (int) PyByteArray_Size(obj)); 176 | Py_XDECREF(obj); 177 | } 178 | 179 | void PyRecWriter::write_date(PyObject* pyval){ 180 | struct tm t = {0}; 181 | t.tm_year = PyDateTime_GET_YEAR(pyval)-1900; 182 | t.tm_mon = PyDateTime_GET_MONTH(pyval)-1; 183 | t.tm_mday = PyDateTime_GET_DAY(pyval); 184 | long long val = static_cast(mktime(&t)); 185 | this->writer->dateValue(val*1000); 186 | } 187 | 188 | void PyRecWriter::write_datetime(PyObject* pyval){ 189 | struct tm t = {0}; 190 | t.tm_year = PyDateTime_GET_YEAR(pyval)-1900; 191 | t.tm_mon = PyDateTime_GET_MONTH(pyval)-1; 192 | t.tm_mday = PyDateTime_GET_DAY(pyval); 193 | t.tm_hour = PyDateTime_DATE_GET_HOUR(pyval); 194 | t.tm_min = PyDateTime_DATE_GET_MINUTE(pyval); 195 | t.tm_sec = PyDateTime_DATE_GET_SECOND(pyval); 196 | t.tm_isdst = -1; 197 | time_t tt = mktime(&t); 198 | long long val = static_cast(tt); //Seconds since EPOCH 199 | val *= 1000; // Convert to ms since epoch 200 | // Add ms precision 201 | val = val + (long long) (PyDateTime_DATE_GET_MICROSECOND(pyval) / 1000); 202 | this->writer->dateTimeValue(val); 203 | } 204 | 205 | void PyRecWriter::write_ridbagtreekey(){ 206 | // Not Implemented 207 | return; 208 | } 209 | 210 | void PyRecWriter::write_value(PyObject *pyval){ 211 | PyObject *temp = PyObject_GetAttrString(pyval,"__class__"); 212 | PyObject *temp1 = PyObject_GetAttrString(temp,"__name__"); 213 | char* cls = PyString_AsString(temp1); 214 | if(PyString_Check(pyval)){ 215 | this->writer->stringValue(PyString_AsString(pyval)); 216 | } 217 | else if(PyFloat_Check(pyval)){ 218 | write_float(pyval); 219 | } 220 | else if(PyInt_Check(pyval)){ 221 | write_int(pyval); 222 | } 223 | else if(PyLong_Check(pyval)){ 224 | write_long(pyval); 225 | } 226 | // Convert sets to lists to address the fact that the current deserializatin 227 | // does not support deserializing to sets. 228 | else if(PyList_Check(pyval) || PyTuple_Check(pyval) || PySet_Check(pyval)){ 229 | write_list(pyval); 230 | } 231 | else if(PyDict_Check(pyval)){ 232 | write_dict(pyval); 233 | } 234 | else if(strcmp(cls, "OrientRecord")==0){ 235 | write_record(pyval); 236 | } 237 | else if(strcmp(cls, "OrientRecordLink")==0){ 238 | write_link(pyval); 239 | } 240 | else if(strcmp(cls, "datetime")==0){ 241 | write_datetime(pyval); 242 | } 243 | else if(strcmp(cls, "date")==0){ 244 | write_date(pyval); 245 | } 246 | else if(pyval == Py_None){ 247 | this->writer->nullValue(); 248 | } 249 | // Treat as binary object 250 | else{ 251 | write_binary(pyval); 252 | } 253 | Py_XDECREF(temp); 254 | Py_XDECREF(temp1); 255 | 256 | } 257 | 258 | 259 | -------------------------------------------------------------------------------- /pyorient_native/listener.cpp: -------------------------------------------------------------------------------- 1 | #include "Python.h" 2 | #include "orientc_reader.h" 3 | #include "listener.h" 4 | #include 5 | #include 6 | #include "stdio.h" 7 | #include "time.h" 8 | #include "math.h" 9 | #include "datetime.h" 10 | #include "string.h" 11 | #include "version_compare.h" 12 | 13 | using namespace Orient; 14 | using namespace std; 15 | 16 | #if PY_MAJOR_VERSION >= 3 17 | #define PyInt_FromLong PyLong_FromLong 18 | #define PyString_FromStringAndSize PyUnicode_FromStringAndSize 19 | #endif 20 | 21 | 22 | void TrackerListener::startDocument(const char * name,size_t name_length) { 23 | PyObject *cur = this->obj_stack.top(); 24 | OType cur_type = this->types_stack.top(); 25 | PyObject *nw = PyDict_New(); 26 | if (name_length > 0){ 27 | PyObject *temp = PyString_FromStringAndSize(name, name_length); 28 | PyList_Append(cur, temp); 29 | Py_XDECREF(temp); 30 | } 31 | else{ 32 | if (!PyList_Size(this->obj)){ 33 | PyList_Append(this->obj,Py_None); 34 | } 35 | } 36 | switch(cur_type){ 37 | case EMBEDDEDMAP: 38 | PyDict_SetItemString(cur, this->cur_field->c_str(), nw); 39 | Py_XDECREF(nw); 40 | break; 41 | default: 42 | PyList_Append(cur, nw); 43 | Py_XDECREF(nw); 44 | break; 45 | } 46 | this->types_stack.push(EMBEDDEDMAP); 47 | this->obj_stack.push(nw); 48 | } 49 | 50 | void TrackerListener::endDocument() { 51 | this->types_stack.pop(); 52 | this->obj_stack.pop(); 53 | } 54 | 55 | void TrackerListener::startField(const char * name,size_t name_length, OType type) { 56 | delete this->cur_field; 57 | this->cur_field = new string(name, name_length); 58 | } 59 | 60 | void TrackerListener::endField(const char * name,size_t name_length) { 61 | } 62 | 63 | void TrackerListener::stringValue(const char * value,size_t value_length) { 64 | PyObject* val = PyString_FromStringAndSize(value, value_length); 65 | switch(this->types_stack.top()){ 66 | case EMBEDDEDMAP: 67 | PyDict_SetItemString(this->obj_stack.top(), this->cur_field->c_str(), val); 68 | Py_XDECREF(val); 69 | break; 70 | default: 71 | PyList_Append(this->obj_stack.top(), val); 72 | Py_XDECREF(val); 73 | break; 74 | } 75 | } 76 | 77 | void TrackerListener::intValue(long value) { 78 | 79 | PyObject* val = PyInt_FromLong(value); 80 | switch(this->types_stack.top()){ 81 | case EMBEDDEDMAP: 82 | PyDict_SetItemString(this->obj_stack.top(), this->cur_field->c_str(), val); 83 | Py_XDECREF(val); 84 | break; 85 | default: 86 | PyList_Append(this->obj_stack.top(), val); 87 | Py_XDECREF(val); 88 | break; 89 | } 90 | 91 | } 92 | 93 | void TrackerListener::longValue(long long value) { 94 | PyObject* val = PyLong_FromLong(value); 95 | switch(this->types_stack.top()){ 96 | case EMBEDDEDMAP: 97 | PyDict_SetItemString(this->obj_stack.top(), this->cur_field->c_str(), val); 98 | Py_XDECREF(val); 99 | break; 100 | default: 101 | PyList_Append(this->obj_stack.top(), val); 102 | Py_XDECREF(val); 103 | break; 104 | } 105 | } 106 | 107 | void TrackerListener::shortValue(short value) { 108 | 109 | PyObject* val = PyInt_FromLong(value); 110 | switch(this->types_stack.top()){ 111 | case EMBEDDEDMAP: 112 | PyDict_SetItemString(this->obj_stack.top(), this->cur_field->c_str(), val); 113 | Py_XDECREF(val); 114 | break; 115 | default: 116 | PyList_Append(this->obj_stack.top(), val); 117 | Py_XDECREF(val); 118 | break; 119 | } 120 | 121 | } 122 | 123 | void TrackerListener::byteValue(char value) { 124 | 125 | #if PY_MAJOR_VERSION >= 3 126 | PyObject* val = PyBytes_FromFormat("%c",value); 127 | #else 128 | PyObject* val = PyString_FromFormat("%c",value); 129 | #endif 130 | switch(this->types_stack.top()){ 131 | case EMBEDDEDMAP: 132 | PyDict_SetItemString(this->obj_stack.top(), this->cur_field->c_str(), val); 133 | Py_XDECREF(val); 134 | break; 135 | default: 136 | PyList_Append(this->obj_stack.top(), val); 137 | Py_XDECREF(val); 138 | break; 139 | } 140 | 141 | } 142 | 143 | void TrackerListener::booleanValue(bool value) { 144 | PyObject* val = value? Py_True: Py_False; 145 | switch(this->types_stack.top()){ 146 | case EMBEDDEDMAP: 147 | PyDict_SetItemString(this->obj_stack.top(), this->cur_field->c_str(), val); 148 | break; 149 | default: 150 | PyList_Append(this->obj_stack.top(), val); 151 | break; 152 | } 153 | } 154 | 155 | void TrackerListener::floatValue(float value) { 156 | PyObject* val = PyFloat_FromDouble(value); 157 | switch(this->types_stack.top()){ 158 | case EMBEDDEDMAP: 159 | PyDict_SetItemString(this->obj_stack.top(), this->cur_field->c_str(), val); 160 | Py_XDECREF(val); 161 | break; 162 | default: 163 | PyList_Append(this->obj_stack.top(), val); 164 | Py_XDECREF(val); 165 | break; 166 | } 167 | } 168 | 169 | void TrackerListener::doubleValue(double value) { 170 | PyObject* val = PyFloat_FromDouble(value); 171 | switch(this->types_stack.top()){ 172 | case EMBEDDEDMAP: 173 | PyDict_SetItemString(this->obj_stack.top(), this->cur_field->c_str(), val); 174 | Py_XDECREF(val); 175 | break; 176 | default: 177 | PyList_Append(this->obj_stack.top(), val); 178 | Py_XDECREF(val); 179 | break; 180 | } 181 | } 182 | 183 | void TrackerListener::decimalValue(int scale , const char * bytes, int bytes_length){ 184 | long long v = 0; 185 | int i=bytes_length-1; 186 | do{ 187 | v |= ((long long) bytes[i]) << (i*8); 188 | i--; 189 | }while (i>=0); 190 | double vd = double(v); 191 | vd *= pow((double)10,-scale); 192 | PyObject* val = PyFloat_FromDouble(vd); 193 | switch(this->types_stack.top()){ 194 | case EMBEDDEDMAP: 195 | PyDict_SetItemString(this->obj_stack.top(), this->cur_field->c_str(), val); 196 | Py_XDECREF(val); 197 | break; 198 | default: 199 | PyList_Append(this->obj_stack.top(), val); 200 | Py_XDECREF(val); 201 | break; 202 | } 203 | } 204 | 205 | void TrackerListener::binaryValue(const char * value, int length) { 206 | #if PY_MAJOR_VERSION >= 3 207 | PyObject* val = PyBytes_FromStringAndSize(value, length); 208 | #else 209 | PyObject* val = PyString_FromStringAndSize(value, length); 210 | #endif 211 | switch(this->types_stack.top()){ 212 | case EMBEDDEDMAP: 213 | PyDict_SetItemString(this->obj_stack.top(), this->cur_field->c_str(), val); 214 | Py_XDECREF(val); 215 | break; 216 | default: 217 | PyList_Append(this->obj_stack.top(), val); 218 | Py_XDECREF(val); 219 | break; 220 | } 221 | } 222 | 223 | void TrackerListener::dateValue(long long value) { 224 | long long val_in_sec = (long long) (value/1000); 225 | struct tm* t = gmtime((time_t *) &val_in_sec); 226 | PyObject* val = PyDate_FromDate(t->tm_year+1900, t->tm_mon+1, t->tm_mday); 227 | switch(this->types_stack.top()){ 228 | case EMBEDDEDMAP: 229 | PyDict_SetItemString(this->obj_stack.top(), this->cur_field->c_str(), val); 230 | Py_XDECREF(val); 231 | break; 232 | default: 233 | PyList_Append(this->obj_stack.top(), val); 234 | Py_XDECREF(val); 235 | break; 236 | } 237 | } 238 | 239 | void TrackerListener::dateTimeValue(long long value) { 240 | long long val_in_sec = (long long) (value/1000); 241 | struct tm* t = localtime((time_t *) &val_in_sec); 242 | PyObject* val = PyDateTime_FromDateAndTime(t->tm_year+1900, t->tm_mon+1, t->tm_mday, 243 | t->tm_hour, t->tm_min, t->tm_sec, (int)(value % 1000)*1000); 244 | switch(this->types_stack.top()){ 245 | case EMBEDDEDMAP: 246 | PyDict_SetItemString(this->obj_stack.top(), this->cur_field->c_str(), val); 247 | Py_XDECREF(val); 248 | break; 249 | default: 250 | PyList_Append(this->obj_stack.top(), val); 251 | Py_XDECREF(val); 252 | break; 253 | } 254 | } 255 | 256 | void TrackerListener::linkValue(struct Link &value) { 257 | PyObject *val; 258 | if(this->legacy_link){ 259 | val = Py_BuildValue("(slL)", "OrientRecordLink",value.cluster, value.position); 260 | } 261 | else{ 262 | char recordLink[32]; 263 | sprintf(recordLink, "%ld:%lld", value.cluster, value.position); 264 | PyObject* module = PyImport_ImportModule("pyorient.otypes"); 265 | val = PyObject_CallMethod(module, "OrientRecordLink", "(s)",recordLink); 266 | } 267 | switch(this->types_stack.top()){ 268 | case EMBEDDEDMAP: 269 | PyDict_SetItemString(this->obj_stack.top(), this->cur_field->c_str(), val); 270 | Py_XDECREF(val); 271 | break; 272 | default: 273 | PyList_Append(this->obj_stack.top(), val); 274 | Py_XDECREF(val); 275 | break; 276 | } 277 | } 278 | 279 | void TrackerListener::startCollection(int size,OType type) { 280 | PyObject *cur = this->obj_stack.top(); 281 | PyObject *nw = PyList_New(0); 282 | switch(this->types_stack.top()){ 283 | case EMBEDDEDMAP: 284 | PyDict_SetItemString(cur, this->cur_field->c_str(), nw); 285 | Py_XDECREF(nw); 286 | break; 287 | default: 288 | PyList_Append(cur,nw); 289 | Py_XDECREF(nw); 290 | break; 291 | } 292 | this->types_stack.push(type); 293 | this->obj_stack.push(nw); 294 | } 295 | 296 | void TrackerListener::startMap(int size,OType type) { 297 | PyObject *cur = this->obj_stack.top(); 298 | OType cur_type = this->types_stack.top(); 299 | PyObject *nw = PyDict_New(); 300 | switch(cur_type){ 301 | case EMBEDDEDMAP: 302 | PyDict_SetItemString(cur, this->cur_field->c_str(), nw); 303 | Py_XDECREF(nw); 304 | break; 305 | default: 306 | PyList_Append(cur, nw); 307 | Py_XDECREF(nw); 308 | break; 309 | } 310 | this->types_stack.push(EMBEDDEDMAP); 311 | this->obj_stack.push(nw); 312 | 313 | } 314 | 315 | void TrackerListener::mapKey(const char *key,size_t key_size) { 316 | delete this->cur_field; 317 | this->cur_field = new string(key, key_size); 318 | } 319 | 320 | void TrackerListener::ridBagTreeKey(long long fileId,long long pageIndex,long pageOffset) { 321 | //cout << "Warning: ridBagTreeKey not Implemented " << endl; 322 | } 323 | 324 | void TrackerListener::nullValue() { 325 | switch(this->types_stack.top()){ 326 | case EMBEDDEDMAP: 327 | PyDict_SetItemString(this->obj_stack.top(), this->cur_field->c_str(), Py_None); 328 | break; 329 | default: 330 | PyList_Append(this->obj_stack.top(), Py_None); 331 | break; 332 | } 333 | } 334 | 335 | void TrackerListener::endMap(OType type) { 336 | this->types_stack.pop(); 337 | this->obj_stack.pop(); 338 | 339 | } 340 | 341 | void TrackerListener::endCollection(OType type) { 342 | this->types_stack.pop(); 343 | this->obj_stack.pop(); 344 | } 345 | 346 | 347 | TrackerListener::TrackerListener(PyObject* props) { 348 | this->cur_field = new string(); 349 | this->obj = PyList_New(0); 350 | this->types_stack.push(EMBEDDEDLIST); 351 | this->obj_stack.push(this->obj); 352 | this->props = props; 353 | 354 | /* If pyorient version is <= 1.5.5, set legacy_link and 355 | return links as tuples of form "OrientRecordLink, , ) 356 | else return instances of OrientRecordLink */ 357 | PyObject *pyorient_constants = PyImport_ImportModule("pyorient.constants"); 358 | PyObject *version_pystring = PyObject_GetAttrString(pyorient_constants, "VERSION"); 359 | char *version = PyString_AsString(version_pystring); 360 | Py_XDECREF(version_pystring); 361 | if((Version)(version) > (Version)("1.5.5")) 362 | this->legacy_link = false; 363 | else 364 | this->legacy_link = true; 365 | 366 | PyDateTime_IMPORT; 367 | } 368 | 369 | TrackerListener::~TrackerListener() { 370 | while ( !this->types_stack.empty() ) 371 | this->types_stack.pop(); 372 | while ( !this->obj_stack.empty() ){ 373 | this->obj_stack.pop(); 374 | } 375 | delete this->cur_field; 376 | } 377 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /pyorient_native/orientc_reader.cpp: -------------------------------------------------------------------------------- 1 | #include "orientc_reader.h" 2 | #include 3 | #include "helpers.h" 4 | #include "parse_exception.h" 5 | #include "pendian.h" 6 | #include 7 | 8 | 9 | #if PY_MAJOR_VERSION >= 3 10 | char* PyString_AsString(PyObject* obj){ 11 | if(obj==NULL) 12 | return (char *)(""); 13 | if (PyUnicode_Check(obj)) { 14 | char* rv; 15 | PyObject * byte_obj = PyUnicode_AsEncodedString(obj, "ASCII", "strict"); 16 | rv = PyBytes_AsString(byte_obj); 17 | Py_XDECREF(byte_obj); 18 | return rv; 19 | } else if (PyBytes_Check(obj)) { 20 | return PyBytes_AsString(obj); 21 | } else { 22 | char* rv; 23 | PyObject* byte_obj = PyObject_Str(obj); 24 | rv = PyString_AsString(byte_obj); 25 | Py_XDECREF(byte_obj); 26 | return rv; 27 | } 28 | } 29 | #endif 30 | 31 | using namespace std; 32 | 33 | namespace Orient { 34 | 35 | void readSimpleValue(ContentBuffer &reader, OType type, RecordParseListener & listener); 36 | inline void readValueString(ContentBuffer & reader, RecordParseListener & listener); 37 | void readValueLinkCollection(ContentBuffer & reader, RecordParseListener & listener, OType collType); 38 | void readValueEmbeddedCollection(ContentBuffer & reader, RecordParseListener & listener, OType collType); 39 | void readValueEmbeddedMap(ContentBuffer & reader, RecordParseListener & listener, OType collType); 40 | void readValueLinkMap(ContentBuffer & reader, RecordParseListener & listener, OType collType); 41 | inline void readValueLink(ContentBuffer & reader, RecordParseListener & listener); 42 | void readDocument(ContentBuffer &reader, RecordParseListener & listener); 43 | void readValueRidbag(ContentBuffer &reader, RecordParseListener & listener); 44 | int16_t readFlat16Integer(ContentBuffer & reader); 45 | int32_t readFlat32Integer(ContentBuffer & reader); 46 | int64_t readFlat64Integer(ContentBuffer & reader); 47 | RecordParser::RecordParser(std::string formatter) { 48 | if (formatter != "onet_ser_v0") 49 | throw parse_exception("Formatter not supported"); 50 | } 51 | 52 | void RecordParser::parse(const unsigned char * content, int content_size, 53 | RecordParseListener &listener) { 54 | ContentBuffer reader(content, content_size); 55 | reader.prepare(1); 56 | if (reader.content[reader.cursor] != 0) 57 | throw parse_exception("unsupported version"); 58 | readDocument(reader, listener); 59 | } 60 | 61 | void readDocument(ContentBuffer &reader, RecordParseListener & listener) { 62 | int64_t class_size = readVarint(reader); 63 | if (class_size > 0) { 64 | reader.prepare(class_size); 65 | char * class_name = (char *) reader.content + reader.cursor; 66 | listener.startDocument(class_name, class_size); 67 | } else 68 | listener.startDocument("", 0); 69 | int64_t size = 0; 70 | int32_t lastCursor = 0; 71 | while ((size = readVarint(reader)) != 0) { 72 | if (size > 0) { 73 | reader.prepare(size); 74 | char * field_name = (char *) reader.content + reader.cursor; 75 | int32_t position = readFlat32Integer(reader); 76 | 77 | reader.prepare(1); 78 | if (position == 0) { 79 | listener.startField(field_name, size, ANY); 80 | listener.nullValue(); 81 | } else { 82 | OType type = (OType) reader.content[reader.cursor]; 83 | listener.startField(field_name, size, type); 84 | int temp = reader.prepared; 85 | reader.force_cursor(position); 86 | readSimpleValue(reader, type, listener); 87 | lastCursor = reader.prepared; 88 | reader.force_cursor(temp); 89 | } 90 | listener.endField(field_name, size); 91 | } else { 92 | // Position from globalProperties 93 | int prop_ind = (size * -1) - 1; 94 | 95 | PyObject* pind = PyInt_FromLong(prop_ind); 96 | PyObject * name_type = PyDict_GetItem(listener.props, pind); 97 | Py_XDECREF(pind); 98 | if (name_type==NULL){ 99 | stringstream msg; 100 | msg << "Could not retrieve property from global properties for id " << prop_ind << endl; 101 | throw new parse_exception(msg.str()); 102 | } 103 | PyObject * pyname = PyList_GetItem(name_type, 0); 104 | char * name = PyString_AsString(pyname); 105 | int size = strlen(name); 106 | OType type = static_cast( PyInt_AsLong(PyList_GetItem(name_type, 1))); 107 | 108 | int32_t position = readFlat32Integer(reader); 109 | if (position == 0) { 110 | listener.startField((const char *)name, size, ANY); 111 | listener.nullValue(); 112 | } else { 113 | listener.startField((const char *) name, size, type); 114 | int temp = reader.prepared; 115 | reader.force_cursor(position); 116 | readSimpleValue(reader, type, listener); 117 | lastCursor = reader.prepared; 118 | reader.force_cursor(temp); 119 | } 120 | } 121 | } 122 | listener.endDocument(); 123 | if (lastCursor > reader.prepared) 124 | reader.force_cursor(lastCursor); 125 | } 126 | 127 | void readSimpleValue(ContentBuffer &reader, OType type, RecordParseListener & listener) { 128 | 129 | switch (type) { 130 | case STRING: 131 | readValueString(reader, listener); 132 | break; 133 | case INTEGER: { 134 | int64_t value = readVarint(reader); 135 | listener.intValue(value); 136 | } 137 | break; 138 | case LONG: { 139 | int64_t value = readVarint(reader); 140 | listener.longValue(value); 141 | } 142 | break; 143 | case SHORT: { 144 | int64_t value = readVarint(reader); 145 | listener.shortValue(value); 146 | } 147 | break; 148 | case BYTE: { 149 | reader.prepare(1); 150 | listener.byteValue(reader.content[reader.cursor]); 151 | } 152 | break; 153 | 154 | case BOOLEAN: { 155 | reader.prepare(1); 156 | listener.booleanValue(reader.content[reader.cursor] != 0); 157 | } 158 | break; 159 | case DATE: { 160 | int64_t read = readVarint(reader); 161 | read *= 86400000; 162 | listener.dateValue(read); 163 | } 164 | break; 165 | case FLOAT: { 166 | int32_t i_val = readFlat32Integer(reader); 167 | float fl; 168 | memcpy(&fl, &i_val, 4); 169 | listener.floatValue(fl); 170 | } 171 | break; 172 | case DOUBLE: { 173 | int64_t i_val; 174 | reader.prepare(8); 175 | memcpy(&i_val, reader.content + reader.cursor, 8); 176 | i_val = ntohll(i_val); 177 | double db; 178 | memcpy(&db, &i_val, 8); 179 | listener.doubleValue(db); 180 | } 181 | break; 182 | case DATETIME: { 183 | int64_t value = readVarint(reader); 184 | listener.dateTimeValue(value); 185 | } 186 | break; 187 | case LINK: { 188 | readValueLink(reader, listener); 189 | } 190 | break; 191 | case LINKSET: 192 | case LINKLIST: { 193 | readValueLinkCollection(reader, listener, type); 194 | } 195 | break; 196 | case BINARY: { 197 | int64_t value_size = readVarint(reader); 198 | 199 | if(value_size!=0){ 200 | reader.prepare(value_size); 201 | listener.binaryValue((char *) reader.content + reader.cursor, value_size); 202 | }else { 203 | listener.binaryValue("", 0); 204 | } 205 | } 206 | break; 207 | case EMBEDDEDLIST: 208 | case EMBEDDEDSET: { 209 | readValueEmbeddedCollection(reader, listener, type); 210 | } 211 | break; 212 | case EMBEDDEDMAP: { 213 | readValueEmbeddedMap(reader, listener, type); 214 | } 215 | break; 216 | case LINKMAP: { 217 | readValueLinkMap(reader, listener, type); 218 | } 219 | break; 220 | case EMBEDDED: { 221 | readDocument(reader, listener); 222 | } 223 | break; 224 | case LINKBAG: { 225 | readValueRidbag(reader, listener); 226 | } 227 | break; 228 | case DECIMAL : { 229 | int32_t scale = readFlat32Integer(reader); 230 | int32_t value_size = readFlat32Integer(reader); 231 | reader.prepare(value_size); 232 | listener.decimalValue(scale, (char *) reader.content + reader.cursor, value_size); 233 | } 234 | default: 235 | break; 236 | } 237 | 238 | } 239 | 240 | void readValueString(ContentBuffer & reader, RecordParseListener & listener) { 241 | int64_t value_size = readVarint(reader); 242 | if(value_size!=0){ 243 | reader.prepare(value_size); 244 | listener.stringValue((char *) reader.content + reader.cursor, value_size); 245 | }else { 246 | listener.stringValue("", 0); 247 | } 248 | } 249 | 250 | void readValueLink(ContentBuffer & reader, RecordParseListener & listener) { 251 | Link link; 252 | link.cluster = readVarint(reader); 253 | link.position = readVarint(reader); 254 | if (link.cluster == -2 && link.position == -1) 255 | listener.nullValue(); 256 | else 257 | listener.linkValue(link); 258 | } 259 | 260 | void readValueLinkCollection(ContentBuffer & reader, RecordParseListener & listener, OType type) { 261 | int size = readVarint(reader); 262 | listener.startCollection(size, type); 263 | while (size-- > 0) { 264 | //TODO: handle null 265 | readValueLink(reader, listener); 266 | } 267 | listener.endCollection(type); 268 | 269 | } 270 | void readValueEmbeddedCollection(ContentBuffer & reader, RecordParseListener & listener, OType collType) { 271 | int size = readVarint(reader); 272 | listener.startCollection(size, collType); 273 | reader.prepare(1); 274 | OType type = (OType) reader.content[reader.cursor]; 275 | if (ANY == type) { 276 | while (size-- > 0) { 277 | reader.prepare(1); 278 | OType entryType = (OType) reader.content[reader.cursor]; 279 | if (ANY == entryType) 280 | listener.nullValue(); 281 | else 282 | readSimpleValue(reader, entryType, listener); 283 | } 284 | } 285 | listener.endCollection(collType); 286 | //For now else is impossible 287 | } 288 | 289 | void readValueEmbeddedMap(ContentBuffer & reader, RecordParseListener & listener, OType mapType) { 290 | int64_t size = readVarint(reader); 291 | listener.startMap(size, mapType); 292 | int32_t lastCursor = 0; 293 | while (size-- > 0) { 294 | //Skipping because is everytime string 295 | reader.prepare(1); 296 | int key_size = readVarint(reader); 297 | reader.prepare(key_size); 298 | char * key_name = (char *) reader.content + reader.cursor; 299 | listener.mapKey(key_name, key_size); 300 | long position = readFlat32Integer(reader); 301 | reader.prepare(1); 302 | if (position == 0) { 303 | listener.nullValue(); 304 | } else { 305 | OType type = (OType) reader.content[reader.cursor]; 306 | int temp = reader.prepared; 307 | reader.force_cursor(position); 308 | readSimpleValue(reader, type, listener); 309 | lastCursor = reader.prepared; 310 | reader.force_cursor(temp); 311 | } 312 | } 313 | listener.endMap(mapType); 314 | if (lastCursor > reader.prepared) 315 | reader.force_cursor(lastCursor); 316 | } 317 | 318 | void readValueLinkMap(ContentBuffer & reader, RecordParseListener & listener, OType mapType) { 319 | int64_t size = readVarint(reader); 320 | listener.startMap(size, mapType); 321 | while (size-- > 0) { 322 | //Skipping because is everytime string 323 | reader.prepare(1); 324 | int key_size = readVarint(reader); 325 | reader.prepare(key_size); 326 | char * key_name = (char *) reader.content + reader.cursor; 327 | listener.mapKey(key_name, key_size); 328 | readValueLink(reader, listener); 329 | } 330 | listener.endMap(mapType); 331 | } 332 | 333 | void readValueRidbag(ContentBuffer & reader, RecordParseListener & listener) { 334 | reader.prepare(1); 335 | unsigned char c = reader.content[reader.cursor]; 336 | if ((c & 2) == 2) { 337 | //UUID 338 | //Skipping UUID 339 | readFlat64Integer(reader); 340 | readFlat64Integer(reader); 341 | } 342 | if ((c & 1) == 1) { 343 | int32_t size = readFlat32Integer(reader); 344 | listener.startCollection(size, LINKBAG); 345 | while (size-- > 0) { 346 | struct Link link; 347 | link.cluster = readFlat16Integer(reader); 348 | link.position = readFlat64Integer(reader); 349 | listener.linkValue(link); 350 | } 351 | listener.endCollection(LINKBAG); 352 | } else { 353 | long long fileId = readFlat64Integer(reader); 354 | long long pageIndex = readFlat64Integer(reader); 355 | long int pageOffset = readFlat32Integer(reader); 356 | // old data not needed anymore 357 | readFlat32Integer(reader); 358 | //changes client side should be everytime 0 359 | readFlat32Integer(reader); 360 | listener.ridBagTreeKey(fileId, pageIndex, pageOffset); 361 | } 362 | 363 | } 364 | 365 | int64_t readFlat64Integer(ContentBuffer & reader) { 366 | int64_t value; 367 | reader.prepare(8); 368 | memcpy(&value, reader.content + reader.cursor, 8); 369 | value = ntohll(value); 370 | return value; 371 | } 372 | 373 | int16_t readFlat16Integer(ContentBuffer & reader) { 374 | int16_t value; 375 | reader.prepare(2); 376 | memcpy(&value, reader.content + reader.cursor, 2); 377 | value = ntohs(value); 378 | return value; 379 | } 380 | 381 | int32_t readFlat32Integer(ContentBuffer & reader) { 382 | int32_t value; 383 | reader.prepare(4); 384 | memcpy(&value, reader.content + reader.cursor, 4); 385 | value = ntohl(value); 386 | return value; 387 | } 388 | 389 | } 390 | -------------------------------------------------------------------------------- /pyorient_native/orientc_writer.cpp: -------------------------------------------------------------------------------- 1 | #include "orientc_writer.h" 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "pendian.h" 8 | 9 | #include "helpers.h" 10 | 11 | namespace Orient { 12 | 13 | void writeString(ContentBuffer & buffer, const char *string); 14 | void writeFlat16Integer(ContentBuffer & buffer, int16_t value); 15 | void writeFlat32Integer(ContentBuffer & buffer, int32_t value); 16 | void writeFlat64Integer(ContentBuffer & buffer, int64_t value); 17 | 18 | class DocumentWriter { 19 | public: 20 | DocumentWriter(); 21 | ContentBuffer header; 22 | ContentBuffer data; 23 | std::list current; 24 | std::list > pointers; 25 | std::list > dataPointers; 26 | void writeRecordVersion(); 27 | void writeClass(const char * name); 28 | void startField(const char *name); 29 | void endField(const char *name); 30 | void writeTypeIfNeeded(OType type); 31 | void popType(); 32 | unsigned char * writtenContent(int *size, DocumentWriter * parent, int contentOffset); 33 | }; 34 | 35 | DocumentWriter::DocumentWriter() { 36 | } 37 | 38 | class InternalWriter { 39 | public: 40 | std::list nested; 41 | }; 42 | 43 | void DocumentWriter::popType() { 44 | current.pop_front(); 45 | } 46 | void DocumentWriter::writeTypeIfNeeded(OType type) { 47 | 48 | if (current.front() == EMBEDDED || current.front() == EMBEDDEDMAP) { 49 | header.prepare(4); 50 | std::pair toAdd(header.cursor, data.prepared); 51 | pointers.push_back(toAdd); 52 | header.prepare(1); 53 | header.content[header.cursor] = type; 54 | } else if (current.front() == EMBEDDEDLIST || current.front() == EMBEDDEDSET) { 55 | data.prepare(1); 56 | data.content[data.cursor] = type; 57 | } 58 | } 59 | 60 | void DocumentWriter::writeRecordVersion() { 61 | header.prepare(1); 62 | header.content[header.cursor] = 0; 63 | } 64 | 65 | void DocumentWriter::writeClass(const char * name) { 66 | writeString(header, name); 67 | } 68 | 69 | void DocumentWriter::startField(const char *name) { 70 | writeString(header, name); 71 | } 72 | 73 | void DocumentWriter::endField(const char *name) { 74 | } 75 | 76 | unsigned char * DocumentWriter::writtenContent(int * size, DocumentWriter * parent, int contentOffset) { 77 | writeVarint(header, 0); 78 | int headerSize = header.prepared; 79 | int dataSize = data.prepared; 80 | int wholeSize = headerSize + dataSize; 81 | std::list >::iterator i; 82 | for (i = pointers.begin(); i != pointers.end(); ++i) { 83 | std::pair & pair = *i; 84 | if (parent != 0) { 85 | parent->dataPointers.push_back(std::pair(pair.first + contentOffset, pair.second + headerSize + contentOffset)); 86 | } else { 87 | header.force_cursor(pair.first); 88 | writeFlat32Integer(header, pair.second + headerSize); 89 | } 90 | } 91 | for (i = dataPointers.begin(); i != dataPointers.end(); ++i) { 92 | std::pair & pair = *i; 93 | if (parent != 0) { 94 | parent->dataPointers.push_back(std::pair(pair.first + headerSize + contentOffset, pair.second + headerSize + contentOffset)); 95 | } else { 96 | data.force_cursor(pair.first); 97 | writeFlat32Integer(data, pair.second + headerSize); 98 | } 99 | } 100 | 101 | unsigned char * all = new unsigned char[wholeSize]; 102 | memcpy(all, header.content, headerSize); 103 | memcpy(all + headerSize, data.content, dataSize); 104 | 105 | *size = wholeSize; 106 | return all; 107 | } 108 | 109 | RecordWriter::RecordWriter(std::string formatter) : 110 | writer(new InternalWriter) { 111 | if (formatter != "onet_ser_v0") 112 | throw "Formatter not supported"; 113 | } 114 | RecordWriter::~RecordWriter() { 115 | delete writer->nested.front(); 116 | delete writer; 117 | } 118 | 119 | void RecordWriter::startDocument(const char * name) { 120 | DocumentWriter * doc = new DocumentWriter(); 121 | if (writer->nested.size() == 0) { 122 | writer->nested.push_front(doc); 123 | doc->writeRecordVersion(); 124 | } else { 125 | DocumentWriter * docFront = writer->nested.front(); 126 | docFront->writeTypeIfNeeded(EMBEDDED); 127 | writer->nested.push_front(doc); 128 | } 129 | doc->current.push_front(EMBEDDED); 130 | doc->writeClass(name); 131 | } 132 | 133 | void RecordWriter::startCollection(int size, OType type) { 134 | DocumentWriter * front = writer->nested.front(); 135 | front->writeTypeIfNeeded(type); 136 | front->current.push_front(type); 137 | if (type == LINKBAG) { 138 | front->data.prepare(1); 139 | front->data.content[front->data.cursor] = 0x1; 140 | writeFlat32Integer(front->data, size); 141 | } else { 142 | writeVarint(front->data, size); 143 | if (type == EMBEDDEDLIST || type == EMBEDDEDSET) { 144 | front->data.prepare(1); 145 | front->data.content[front->data.cursor] = ANY; 146 | } 147 | } 148 | } 149 | 150 | void RecordWriter::endCollection(OType type) { 151 | DocumentWriter * doc = writer->nested.front(); 152 | doc->current.pop_front(); 153 | } 154 | 155 | void RecordWriter::startMap(int size, OType type) { 156 | DocumentWriter *front = writer->nested.front(); 157 | front->writeTypeIfNeeded(type); 158 | writeVarint(front->data, size); 159 | if (type == EMBEDDEDMAP) { 160 | writer->nested.push_front(new DocumentWriter()); 161 | } 162 | writer->nested.front()->current.push_front(type); 163 | } 164 | 165 | void RecordWriter::mapKey(const char * mapKey) { 166 | DocumentWriter *front = writer->nested.front(); 167 | if (front->current.front() == EMBEDDEDMAP) { 168 | front->header.prepare(1); 169 | front->header.content[front->header.cursor] = STRING; 170 | front->startField(mapKey); 171 | } else { 172 | front->data.prepare(1); 173 | front->data.content[front->data.cursor] = STRING; 174 | writeString(front->data, mapKey); 175 | } 176 | } 177 | 178 | void RecordWriter::stringValue(const char * value) { 179 | DocumentWriter *front = writer->nested.front(); 180 | front->writeTypeIfNeeded(STRING); 181 | writeString(front->data, value); 182 | } 183 | 184 | void RecordWriter::intValue(long value) { 185 | DocumentWriter *front = writer->nested.front(); 186 | front->writeTypeIfNeeded(INTEGER); 187 | writeVarint(front->data, value); 188 | } 189 | 190 | void RecordWriter::shortValue(short value) { 191 | DocumentWriter *front = writer->nested.front(); 192 | front->writeTypeIfNeeded(SHORT); 193 | writeVarint(front->data, value); 194 | } 195 | 196 | void RecordWriter::longValue(long long value) { 197 | DocumentWriter *front = writer->nested.front(); 198 | front->writeTypeIfNeeded(LONG); 199 | writeVarint(front->data, value); 200 | } 201 | 202 | void RecordWriter::dateValue(long long value) { 203 | DocumentWriter *front = writer->nested.front(); 204 | front->writeTypeIfNeeded(DATE); 205 | value /= 86400000; 206 | writeVarint(front->data, value); 207 | } 208 | 209 | void RecordWriter::dateTimeValue(long long value) { 210 | DocumentWriter *front = writer->nested.front(); 211 | front->writeTypeIfNeeded(DATETIME); 212 | writeVarint(front->data, value); 213 | } 214 | 215 | void RecordWriter::byteValue(char value) { 216 | DocumentWriter *front = writer->nested.front(); 217 | front->writeTypeIfNeeded(BYTE); 218 | front->data.prepare(1); 219 | front->data.content[front->data.cursor] = value; 220 | } 221 | 222 | void RecordWriter::booleanValue(bool value) { 223 | DocumentWriter *front = writer->nested.front(); 224 | front->writeTypeIfNeeded(BOOLEAN); 225 | front->data.prepare(1); 226 | front->data.content[front->data.cursor] = value ? 1 : 0; 227 | } 228 | 229 | void RecordWriter::floatValue(float value) { 230 | DocumentWriter *front = writer->nested.front(); 231 | front->writeTypeIfNeeded(FLOAT); 232 | int32_t i_value; 233 | memcpy(&i_value, &value, 4); 234 | writeFlat32Integer(front->data, i_value); 235 | } 236 | 237 | void RecordWriter::doubleValue(double value) { 238 | DocumentWriter *front = writer->nested.front(); 239 | front->writeTypeIfNeeded(DOUBLE); 240 | front->data.prepare(8); 241 | int64_t i_val; 242 | memcpy(&i_val, &value, 8); 243 | i_val = htonll(i_val); 244 | memcpy(front->data.content + front->data.cursor, &i_val, 8); 245 | } 246 | 247 | void RecordWriter::binaryValue(const char * value, int size) { 248 | DocumentWriter *front = writer->nested.front(); 249 | front->writeTypeIfNeeded(BINARY); 250 | writeVarint(front->data, size); 251 | front->data.prepare(size); 252 | memcpy(front->data.content + front->data.cursor, value, size); 253 | } 254 | 255 | void RecordWriter::decimalValue(int scale, const char * bytes, int bytes_length) { 256 | DocumentWriter *front = writer->nested.front(); 257 | front->writeTypeIfNeeded(DECIMAL); 258 | writeFlat32Integer(front->data, scale); 259 | writeFlat32Integer(front->data, bytes_length); 260 | front->data.prepare(bytes_length); 261 | memcpy(front->data.content + front->data.cursor, bytes, bytes_length); 262 | } 263 | 264 | void RecordWriter::linkValue(struct Link &link) { 265 | DocumentWriter *front = writer->nested.front(); 266 | if (front->current.front() == LINKBAG) { 267 | writeFlat16Integer(front->data, link.cluster); 268 | writeFlat64Integer(front->data, link.position); 269 | } else { 270 | front->writeTypeIfNeeded(LINK); 271 | writeVarint(front->data, link.cluster); 272 | writeVarint(front->data, link.position); 273 | } 274 | } 275 | 276 | void RecordWriter::ridBagTreeKey(long long fileId, long long pageIndex, long pageOffset) { 277 | DocumentWriter *front = writer->nested.front(); 278 | front->writeTypeIfNeeded(LINKBAG); 279 | front->data.prepare(1); 280 | front->data.content[front->data.cursor] = 0; 281 | writeFlat64Integer(front->data, fileId); 282 | writeFlat64Integer(front->data, pageIndex); 283 | writeFlat32Integer(front->data, pageOffset); 284 | writeFlat32Integer(front->data, 0); 285 | writeFlat32Integer(front->data, 0); 286 | } 287 | 288 | void RecordWriter::startField(const char* name) { 289 | DocumentWriter* front = writer->nested.front(); 290 | front->startField(name); 291 | } 292 | 293 | void RecordWriter::endField(const char *name) { 294 | DocumentWriter *front = writer->nested.front(); 295 | front->endField(name); 296 | } 297 | 298 | void RecordWriter::endMap(OType type) { 299 | DocumentWriter *front = writer->nested.front(); 300 | if (front->current.front() == EMBEDDEDMAP) { 301 | writer->nested.pop_front(); 302 | DocumentWriter *front1 = writer->nested.front(); 303 | int size; 304 | unsigned char * content = front->writtenContent(&size, front1, front1->data.prepared); 305 | delete front; 306 | front1->data.prepare(size); 307 | memcpy(front1->data.content + front1->data.cursor, content, size); 308 | delete[] content; 309 | } else 310 | front->popType(); 311 | } 312 | 313 | void RecordWriter::nullValue() { 314 | DocumentWriter *front = writer->nested.front(); 315 | if (front->current.front() == EMBEDDEDMAP || front->current.front() == EMBEDDED) { 316 | writeFlat32Integer(front->header, 0); 317 | front->header.prepare(1); 318 | front->header.content[front->header.cursor] = ANY; 319 | } else if (front->current.front() == LINKLIST || front->current.front() == LINKMAP || front->current.front() == LINKSET) { 320 | writeVarint(front->data, -2); 321 | writeVarint(front->data, -1); 322 | } else if (front->current.front() == EMBEDDEDLIST || front->current.front() == EMBEDDEDSET) { 323 | front->data.prepare(1); 324 | front->data.content[front->data.cursor] = ANY; 325 | } 326 | } 327 | 328 | void RecordWriter::endDocument() { 329 | DocumentWriter *front = writer->nested.front(); 330 | front->popType(); 331 | if (writer->nested.size() > 1) { 332 | writer->nested.pop_front(); 333 | DocumentWriter *front1 = writer->nested.front(); 334 | int size; 335 | unsigned char * content = front->writtenContent(&size, front1, front1->data.prepared); 336 | delete front; 337 | front1->data.prepare(size); 338 | memcpy(front1->data.content + front1->data.cursor, content, size); 339 | delete[] content; 340 | } 341 | } 342 | 343 | const unsigned char * RecordWriter::writtenContent(int * size) { 344 | return writer->nested.front()->writtenContent(size, 0, 0); 345 | } 346 | 347 | void writeString(ContentBuffer & buffer, const char *string) { 348 | int size = strlen(string); 349 | writeVarint(buffer, size); 350 | if (size > 0) { 351 | buffer.prepare(size); 352 | memcpy(buffer.content + buffer.cursor, string, size); 353 | } 354 | } 355 | 356 | void writeFlat32Integer(ContentBuffer & buffer, int32_t value) { 357 | buffer.prepare(4); 358 | value = htonl(value); 359 | memcpy(buffer.content + buffer.cursor, &value, 4); 360 | } 361 | 362 | void writeFlat16Integer(ContentBuffer & buffer, int16_t value) { 363 | buffer.prepare(2); 364 | value = htons(value); 365 | memcpy(buffer.content + buffer.cursor, &value, 2); 366 | } 367 | 368 | void writeFlat64Integer(ContentBuffer & buffer, int64_t value) { 369 | buffer.prepare(8); 370 | value = htonll(value); 371 | memcpy(buffer.content + buffer.cursor, &value, 8); 372 | } 373 | 374 | } 375 | --------------------------------------------------------------------------------