X-Git-Url: https://git.cworth.org/git?a=blobdiff_plain;f=common%2Fpickle.hpp;h=60694fa83d92d8da1e9891e6865574d13d7e0ea2;hb=5f2245e7500f9024ba90e631fd865c9ffac172c2;hp=c8f90ae12bc1ee5eb1a6915be8ce9ac4b4f39ed3;hpb=299a1b3adc806ef33234683bae4b9477ba5cc378;p=apitrace diff --git a/common/pickle.hpp b/common/pickle.hpp index c8f90ae..60694fa 100644 --- a/common/pickle.hpp +++ b/common/pickle.hpp @@ -32,6 +32,7 @@ #include #include +#include #include #include @@ -89,29 +90,31 @@ private: SETITEMS = 'u', BINFLOAT = 'G', - PROTO = 0x80, - NEWOBJ = 0x81, - EXT1 = 0x82, - EXT2 = 0x83, - EXT4 = 0x84, - TUPLE1 = 0x85, - TUPLE2 = 0x86, - TUPLE3 = 0x87, - NEWTRUE = 0x88, - NEWFALSE = 0x89, - LONG1 = 0x8a, - LONG4 = 0x8b, + PROTO = '\x80', + NEWOBJ = '\x81', + EXT1 = '\x82', + EXT2 = '\x83', + EXT4 = '\x84', + TUPLE1 = '\x85', + TUPLE2 = '\x86', + TUPLE3 = '\x87', + NEWTRUE = '\x88', + NEWFALSE = '\x89', + LONG1 = '\x8a', + LONG4 = '\x8b', }; public: - PickleWriter(std::ostream &_os) : - os(_os) - { + PickleWriter(std::ostream &_os) : + os(_os) { + } + + inline void begin() { os.put(PROTO); os.put(2); } - ~PickleWriter() { + inline void end() { os.put(STOP); } @@ -158,13 +161,6 @@ public: os.put(TUPLE); } - inline void putInt(int i) { - os.put( i & 0xff); - os.put((i >> 8) & 0xff); - os.put((i >> 16) & 0xff); - os.put((i >> 24) & 0xff); - } - inline void writeString(const char *s, size_t length) { if (!s) { writeNone(); @@ -176,7 +172,7 @@ public: os.put(length); } else { os.put(BINSTRING); - putInt(length); + putInt32(length); } os.write(s, length); @@ -205,16 +201,121 @@ public: os.put(b ? NEWTRUE : NEWFALSE); } - inline void writeInt(long i) { - // TODO: binary - os.put(INT); - os << i << '\n'; + inline void writeInt(uint8_t i) { + os.put(BININT1); + os.put(i); } - inline void writeFloat(float f) { - // TODO: binary - os.put(FLOAT); - os << f << '\n'; + inline void writeInt(uint16_t i) { + if (i < 0x100) { + writeInt((uint8_t)i); + } else { + os.put(BININT2); + putInt16(i); + } + } + + inline void writeInt(int32_t i) { + if (0 <= i && i < 0x10000) { + writeInt((uint16_t)i); + } else { + os.put(BININT); + putInt32(i); + } + } + + inline void writeInt(uint32_t i) { + if (i < 0x8000000) { + writeInt((int32_t)i); + } else { + writeLong(i); + } + } + + inline void writeInt(long long i) { + if (-0x8000000 <= i && i < 0x8000000) { + writeInt((int32_t)i); + } else { + writeLong(i); + } + } + + inline void writeInt(unsigned long long i) { + if (i < 0x8000000) { + writeInt((int32_t)i); + } else { + writeLong(i); + } + } + + inline void writeFloat(double f) { + union { + double f; + char c[8]; + } u; + + assert(sizeof u.f == sizeof u.c); + u.f = f; + + os.put(BINFLOAT); + os.put(u.c[7]); + os.put(u.c[6]); + os.put(u.c[5]); + os.put(u.c[4]); + os.put(u.c[3]); + os.put(u.c[2]); + os.put(u.c[1]); + os.put(u.c[0]); + } + + inline void writeByteArray(const void *buf, size_t length) { + os.put(GLOBAL); + os << "__builtin__\nbytearray\n"; + os.put(BINPUT); + os.put(1); + writeString(static_cast(buf), length); + os.put(TUPLE1); + os.put(REDUCE); + } + +protected: + inline void putInt16(uint16_t i) { + os.put( i & 0xff); + os.put( i >> 8 ); + } + + inline void putInt32(uint32_t i) { + os.put( i & 0xff); + os.put((i >> 8) & 0xff); + os.put((i >> 16) & 0xff); + os.put( i >> 24 ); + } + + template< class T > + inline void writeLong(T l) { + os.put(LONG1); + + if (l == 0) { + os.put(0); + return; + } + + unsigned c = 1; + // Same as l >> (8 * sizeof l), but without the warnings + T sign = l < 0 ? ~0 : 0; + while ((l >> (8 * c)) != sign) { + ++c; + } + // Add an extra byte if sign bit doesn't match + if (((l >> (8 * c - 1)) & 1) != ((l >> (8 * sizeof l - 1)) & 1)) { + ++c; + } + os.put(c); + + for (unsigned i = 0; i < c; ++ i) { + os.put(l & 0xff); + l >>= 8; + } } };