hessian2/basic_codec/number_codec.cc (279 lines of code) (raw):

#include "hessian2/basic_codec/number_codec.hpp" namespace Hessian2 { namespace { void writeBEDouble(WriterPtr &writer, const double &value) { uint64_t out; std::memcpy(&out, &value, 8); writer->writeBE<uint64_t>(out); } } // namespace template <> std::unique_ptr<double> Decoder::decode() { auto out = std::make_unique<double>(); uint8_t code = reader_->readBE<uint8_t>().second; switch (code) { // ::= x5b # 0.0 case 0x5b: *out.get() = 0.0; return out; // ::= x5c # 1.0 case 0x5c: *out.get() = 1.0; return out; // ::= x5d b0 # byte cast to double (-128.0 to 127.0) case 0x5d: if (reader_->byteAvailable() < 1) { return nullptr; } *out.get() = static_cast<double>(reader_->readBE<int8_t>().second); return out; // ::= x5e b1 b0 # short cast to double case 0x5e: if (reader_->byteAvailable() < 2) { return nullptr; } *out.get() = static_cast<double>(reader_->readBE<int16_t>().second); return out; // ::= x5f b3 b2 b1 b0 # 32-bit float cast to double case 0x5f: if (reader_->byteAvailable() < 4) { return nullptr; } *out.get() = readBE<double, 4>(reader_); return out; // ::= 'D' b7 b6 b5 b4 b3 b2 b1 b0 case 'D': if (reader_->byteAvailable() < 8) { return nullptr; } *out.get() = readBE<double, 8>(reader_); return out; } return nullptr; } template <> bool Encoder::encode(const double &value) { int32_t int_value = static_cast<int32_t>(value); if (int_value == value) { if (int_value == 0) { writer_->writeByte(0x5b); return true; } if (int_value == 1) { writer_->writeByte(0x5c); return true; } if (int_value >= -0x80 && int_value < 0x80) { writer_->writeByte(0x5d); writer_->writeBE<int8_t>(int_value); return true; } if (int_value >= -0x8000 && int_value < 0x8000) { writer_->writeByte(0x5e); writer_->writeBE<int8_t>(int_value >> 8); writer_->writeBE<uint8_t>(int_value); return true; } } writer_->writeByte(0x44); writeBEDouble(writer_, value); return true; } // # 32-bit signed integer // ::= 'I' b3 b2 b1 b0 // ::= [x80-xbf] # -x10 to x3f // ::= [xc0-xcf] b0 # -x800 to x7ff // ::= [xd0-xd7] b1 b0 # -x40000 to x3ffff template <> std::unique_ptr<int32_t> Decoder::decode() { auto out = std::make_unique<int32_t>(); uint8_t code = reader_->readBE<uint8_t>().second; // ::= [x80-xbf] # -x10 to x3f if (code >= 0x80 && code <= 0xbf) { *out.get() = (code - 0x90); return out; } switch (code) { // ::= [xc0-xcf] b0 # -x800 to x7ff case 0xc0: case 0xc1: case 0xc2: case 0xc3: case 0xc4: case 0xc5: case 0xc6: case 0xc7: case 0xc8: case 0xc9: case 0xca: case 0xcb: case 0xcc: case 0xcd: case 0xce: case 0xcf: if (reader_->byteAvailable() < 1) { return nullptr; } *out.get() = LeftShift<int16_t>(code - 0xc8, 8) + reader_->readBE<uint8_t>().second; return out; // ::= [xd0-xd7] b1 b0 # -x40000 to x3ffff case 0xd0: case 0xd1: case 0xd2: case 0xd3: case 0xd4: case 0xd5: case 0xd6: case 0xd7: if (reader_->byteAvailable() < 2) { return nullptr; } *out.get() = LeftShift<int32_t>(code - 0xd4, 16) + reader_->readBE<uint16_t>().second; return out; // ::= 'I' b3 b2 b1 b0 case 0x49: if (reader_->byteAvailable() < 4) { return nullptr; } *out.get() = reader_->readBE<int32_t>().second; return out; } return nullptr; } // # 32-bit signed integer // ::= 'I' b3 b2 b1 b0 // ::= [x80-xbf] # -x10 to x3f // ::= [xc0-xcf] b0 # -x800 to x7ff // ::= [xd0-xd7] b1 b0 # -x40000 to x3ffff template <> bool Encoder::encode(const int32_t &data) { if (data >= -0x10 && data <= 0x2f) { writer_->writeByte(data + 0x90); return true; } if (data >= -0x800 && data <= 0x7ff) { writer_->writeByte(0xc8 + (data >> 8)); writer_->writeByte(data); return true; } if (data >= -0x40000 && data <= 0x3ffff) { writer_->writeByte(0xd4 + (data >> 16)); writer_->writeByte(data >> 8); writer_->writeByte(data); return true; } writer_->writeByte(0x49); writer_->writeBE<uint32_t>(data); return true; } // # 64-bit signed long integer // ::= 'L' b7 b6 b5 b4 b3 b2 b1 b0 // ::= [xd8-xef] # -x08 to x0f // ::= [xf0-xff] b0 # -x800 to x7ff // ::= [x38-x3f] b1 b0 # -x40000 to x3ffff // ::= x59 b3 b2 b1 b0 # 32-bit integer cast to long template <> std::unique_ptr<int64_t> Decoder::decode() { auto out = std::make_unique<int64_t>(); uint8_t code = reader_->readBE<uint8_t>().second; switch (code) { // ::= [xd8-xef] # -x08 to x0f case 0xd8: case 0xd9: case 0xda: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf: case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4: case 0xe5: case 0xe6: case 0xe7: case 0xe8: case 0xe9: case 0xea: case 0xeb: case 0xec: case 0xed: case 0xee: case 0xef: *out.get() = (code - 0xe0); return out; // ::= [xf0-xff] b0 # -x800 to x7ff case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: case 0xf6: case 0xf7: case 0xf8: case 0xf9: case 0xfa: case 0xfb: case 0xfc: case 0xfd: case 0xfe: case 0xff: if (reader_->byteAvailable() < 1) { return nullptr; } *out.get() = LeftShift<int16_t>(code - 0xf8, 8) + reader_->readBE<uint8_t>().second; return out; // ::= [x38-x3f] b1 b0 # -x40000 to x3ffff case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: case 0x3e: case 0x3f: if (reader_->byteAvailable() < 2) { return nullptr; } *out.get() = LeftShift<int32_t>(code - 0x3c, 16) + reader_->readBE<uint16_t>().second; return out; // ::= x59 b3 b2 b1 b0 # 32-bit integer cast to long case 0x59: if (reader_->byteAvailable() < 4) { return nullptr; } *out.get() = reader_->readBE<int32_t>().second; return out; // ::= 'L' b7 b6 b5 b4 b3 b2 b1 b0 case 0x4c: if (reader_->byteAvailable() < 8) { return nullptr; } *out.get() = reader_->readBE<int64_t>().second; return out; } return nullptr; } // # 64-bit signed long integer // ::= 'L' b7 b6 b5 b4 b3 b2 b1 b0 // ::= [xd8-xef] # -x08 to x0f // ::= [xf0-xff] b0 # -x800 to x7ff // ::= [x38-x3f] b1 b0 # -x40000 to x3ffff // ::= x59 b3 b2 b1 b0 # 32-bit integer cast to long template <> bool Encoder::encode(const int64_t &data) { if (data >= -0x08 && data <= 0x0f) { writer_->writeByte(data + 0xe0); return true; } if (data >= -0x800 && data <= 0x7ff) { writer_->writeByte(0xf8 + (data >> 8)); writer_->writeByte(data); return true; } if (data >= -0x40000 && data <= 0x3ffff) { writer_->writeByte(0x3c + (data >> 16)); writer_->writeByte(data >> 8); writer_->writeByte(data); return true; } if (data >= -0x80000000L && data <= 0x7fffffffL) { writer_->writeByte(0x59); writer_->writeBE<int32_t>(data); return true; } writer_->writeByte(0x4c); writer_->writeBE<int64_t>(data); return true; } template <> bool Encoder::encode(const int8_t &data) { return encode<int32_t>(data); } template <> bool Encoder::encode(const int16_t &data) { return encode<int32_t>(data); } template <> bool Encoder::encode(const uint8_t &data) { return encode<int32_t>(data); } template <> bool Encoder::encode(const uint16_t &data) { return encode<int32_t>(data); } template <> bool Encoder::encode(const uint32_t &data) { return encode<int64_t>(data); } // Encoding and decoding of uint64_t is not supported because Java 64-bit // integers are signed. } // namespace Hessian2