| Index: src/shared/serialization/serialization.cc
|
| diff --git a/src/shared/serialization/serialization.cc b/src/shared/serialization/serialization.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..26a23ee3e51cec2fe8ceeaaf1d4a4c7f15dae189
|
| --- /dev/null
|
| +++ b/src/shared/serialization/serialization.cc
|
| @@ -0,0 +1,314 @@
|
| +/* -*- c++ -*- */
|
| +/*
|
| + * Copyright (c) 2013 The Native Client Authors. All rights reserved.
|
| + * Use of this source code is governed by a BSD-style license that can be
|
| + * found in the LICENSE file.
|
| + */
|
| +
|
| +#include "native_client/src/shared/serialization/serialization.h"
|
| +
|
| +#include <stdio.h>
|
| +#include <string.h>
|
| +
|
| +#include "native_client/src/shared/platform/nacl_check.h"
|
| +
|
| +namespace nacl {
|
| +
|
| +int const kInitialBufferSize = 256;
|
| +
|
| +SerializationBuffer::SerializationBuffer()
|
| + : nbytes_(0)
|
| + , in_use_(0)
|
| + , read_ix_(0) {}
|
| +
|
| +
|
| +SerializationBuffer::SerializationBuffer(uint8_t const *data_buffer,
|
| + size_t nbytes)
|
| + : nbytes_(0) // EnsureTotalSize will update
|
| + , in_use_(nbytes)
|
| + , read_ix_(0) {
|
| + EnsureTotalSize(nbytes);
|
| + memcpy(&buffer_[0], data_buffer, nbytes);
|
| +}
|
| +
|
| +bool SerializationBuffer::Serialize(char const *cstr, size_t char_count) {
|
| + if (char_count > ~(uint32_t) 0) {
|
| + return false;
|
| + }
|
| + AddTag<char *>();
|
| + AddVal(static_cast<uint32_t>(char_count));
|
| + for (size_t ix = 0; ix < char_count; ++ix) {
|
| + AddVal<uint8_t>(cstr[ix]);
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +bool SerializationBuffer::Serialize(char const *cstr) {
|
| + size_t len = strlen(cstr) + 1; // The ASCII character NUL is included
|
| + return Serialize(cstr, len);
|
| +}
|
| +
|
| +bool SerializationBuffer::Serialize(std::string str) {
|
| + size_t bytes = str.size();
|
| + if (bytes > ~(uint32_t) 0) {
|
| + return false;
|
| + }
|
| + AddTag<std::string>();
|
| + AddVal(static_cast<uint32_t>(bytes));
|
| + for (size_t ix = 0; ix < bytes; ++ix) {
|
| + AddVal<uint8_t>(str[ix]);
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +bool SerializationBuffer::Deserialize(char *cstr, size_t *buffer_size) {
|
| + size_t orig = cur_read_pos();
|
| + if (bytes_unread() < kTagBytes + SerializationTraits<uint32_t>::kBytes) {
|
| + return false;
|
| + }
|
| + if (ReadTag() != SerializationTraits<char *>::kTag) {
|
| + reset_read_pos(orig);
|
| + return false;
|
| + }
|
| + uint32_t char_count;
|
| + if (!GetUint32(&char_count)) {
|
| + reset_read_pos(orig);
|
| + return false;
|
| + }
|
| + if (char_count > *buffer_size) {
|
| + *buffer_size = char_count;
|
| + reset_read_pos(orig);
|
| + return true; // true means check buffer_size!
|
| + }
|
| + for (size_t ix = 0; ix < char_count; ++ix) {
|
| + uint8_t byte;
|
| + if (!GetVal(&byte)) {
|
| + reset_read_pos(orig);
|
| + return false; // encoded data is garbled!
|
| + }
|
| + cstr[ix] = byte;
|
| + }
|
| + *buffer_size = char_count;
|
| + return true;
|
| +}
|
| +
|
| +bool SerializationBuffer::Deserialize(char **cstr_out) {
|
| + size_t nbytes = 256;
|
| + char *buffer = new char[nbytes];
|
| +
|
| + size_t used = nbytes;
|
| + if (!Deserialize(buffer, &used)) {
|
| + return false;
|
| + }
|
| + if (used > nbytes) {
|
| + delete[] buffer;
|
| + buffer = new char[used];
|
| + CHECK(Deserialize(buffer, &used));
|
| + }
|
| + *cstr_out = buffer;
|
| + return true;
|
| +}
|
| +
|
| +bool SerializationBuffer::Deserialize(std::string *str) {
|
| + size_t orig = cur_read_pos();
|
| + if (bytes_unread() < kTagBytes + SerializationTraits<uint32_t>::kBytes) {
|
| + return false;
|
| + }
|
| + if (ReadTag() != SerializationTraits<std::string>::kTag) {
|
| + reset_read_pos(orig);
|
| + return false;
|
| + }
|
| + uint32_t bytes;
|
| + if (!GetUint32(&bytes)) {
|
| + reset_read_pos(orig);
|
| + return false;
|
| + }
|
| + for (size_t ix = 0; ix < bytes; ++ix) {
|
| + uint8_t b;
|
| + if (!GetUint8(&b)) {
|
| + reset_read_pos(orig);
|
| + return false;
|
| + }
|
| + str->push_back(b);
|
| + }
|
| + return true;
|
| +}
|
| +
|
| +void SerializationBuffer::AddUint8(uint8_t value) {
|
| + EnsureAvailableSpace(sizeof value);
|
| + buffer_[in_use_] = value;
|
| + in_use_ += sizeof value;
|
| +}
|
| +
|
| +void SerializationBuffer::AddUint16(uint16_t value) {
|
| + EnsureAvailableSpace(sizeof value);
|
| + buffer_[in_use_ + 0] = static_cast<uint8_t>(value >> 0);
|
| + buffer_[in_use_ + 1] = static_cast<uint8_t>(value >> 8);
|
| + in_use_ += sizeof value;
|
| +}
|
| +
|
| +void SerializationBuffer::AddUint32(uint32_t value) {
|
| + EnsureAvailableSpace(sizeof value);
|
| + buffer_[in_use_ + 0] = static_cast<uint8_t>(value >> 0);
|
| + buffer_[in_use_ + 1] = static_cast<uint8_t>(value >> 8);
|
| + buffer_[in_use_ + 2] = static_cast<uint8_t>(value >> 16);
|
| + buffer_[in_use_ + 3] = static_cast<uint8_t>(value >> 24);
|
| + in_use_ += sizeof value;
|
| +}
|
| +
|
| +void SerializationBuffer::AddUint64(uint64_t value) {
|
| + EnsureAvailableSpace(sizeof value);
|
| + buffer_[in_use_ + 0] = static_cast<uint8_t>(value >> 0);
|
| + buffer_[in_use_ + 1] = static_cast<uint8_t>(value >> 8);
|
| + buffer_[in_use_ + 2] = static_cast<uint8_t>(value >> 16);
|
| + buffer_[in_use_ + 3] = static_cast<uint8_t>(value >> 24);
|
| + buffer_[in_use_ + 4] = static_cast<uint8_t>(value >> 32);
|
| + buffer_[in_use_ + 5] = static_cast<uint8_t>(value >> 40);
|
| + buffer_[in_use_ + 6] = static_cast<uint8_t>(value >> 48);
|
| + buffer_[in_use_ + 7] = static_cast<uint8_t>(value >> 56);
|
| + in_use_ += sizeof value;
|
| +}
|
| +
|
| +#if defined(NACL_HAS_IEEE_754)
|
| +void SerializationBuffer::AddFloat(float value) {
|
| + union ieee754_float v;
|
| + v.f = value;
|
| + AddUint32((static_cast<uint32_t>(v.ieee.negative) << 31) |
|
| + (static_cast<uint32_t>(v.ieee.exponent) << 23) |
|
| + (static_cast<uint32_t>(v.ieee.mantissa) << 0));
|
| +}
|
| +
|
| +void SerializationBuffer::AddDouble(double value) {
|
| + union ieee754_double v;
|
| + v.d = value;
|
| + AddUint64((static_cast<uint64_t>(v.ieee.negative) << 63) |
|
| + (static_cast<uint64_t>(v.ieee.exponent) << 52) |
|
| + (static_cast<uint64_t>(v.ieee.mantissa0) << 32) |
|
| + (static_cast<uint64_t>(v.ieee.mantissa1) << 0));
|
| +}
|
| +
|
| +void SerializationBuffer::AddLongDouble(long double value) {
|
| + union ieee854_long_double v;
|
| + v.d = value;
|
| + AddUint16((static_cast<uint16_t>(v.ieee.negative) << 15) |
|
| + (static_cast<uint16_t>(v.ieee.exponent) << 0));
|
| + AddUint64((static_cast<uint64_t>(v.ieee.mantissa0) << 32) |
|
| + (static_cast<uint64_t>(v.ieee.mantissa1) << 0));
|
| +}
|
| +#endif
|
| +
|
| +bool SerializationBuffer::GetUint8(uint8_t *value) {
|
| + if (bytes_unread() < sizeof *value) {
|
| + return false;
|
| + }
|
| + *value = static_cast<uint8_t>(buffer_[read_ix_]);
|
| + read_ix_ += sizeof *value;
|
| + return true;
|
| +}
|
| +
|
| +bool SerializationBuffer::GetUint16(uint16_t *value) {
|
| + if (bytes_unread() < sizeof *value) {
|
| + return false;
|
| + }
|
| + *value = ((static_cast<uint16_t>(buffer_[read_ix_ + 0]) << 0) |
|
| + (static_cast<uint16_t>(buffer_[read_ix_ + 1]) << 8));
|
| + read_ix_ += sizeof *value;
|
| + return true;
|
| +}
|
| +
|
| +bool SerializationBuffer::GetUint32(uint32_t *value) {
|
| + if (bytes_unread() < sizeof *value) {
|
| + return false;
|
| + }
|
| + *value = ((static_cast<uint32_t>(buffer_[read_ix_ + 0]) << 0) |
|
| + (static_cast<uint32_t>(buffer_[read_ix_ + 1]) << 8) |
|
| + (static_cast<uint32_t>(buffer_[read_ix_ + 2]) << 16) |
|
| + (static_cast<uint32_t>(buffer_[read_ix_ + 3]) << 24));
|
| + read_ix_ += sizeof *value;
|
| + return true;
|
| +}
|
| +
|
| +bool SerializationBuffer::GetUint64(uint64_t *value) {
|
| + if (bytes_unread() < sizeof *value) {
|
| + return false;
|
| + }
|
| + *value = ((static_cast<uint64_t>(buffer_[read_ix_ + 0]) << 0) |
|
| + (static_cast<uint64_t>(buffer_[read_ix_ + 1]) << 8) |
|
| + (static_cast<uint64_t>(buffer_[read_ix_ + 2]) << 16) |
|
| + (static_cast<uint64_t>(buffer_[read_ix_ + 3]) << 24) |
|
| + (static_cast<uint64_t>(buffer_[read_ix_ + 4]) << 32) |
|
| + (static_cast<uint64_t>(buffer_[read_ix_ + 5]) << 40) |
|
| + (static_cast<uint64_t>(buffer_[read_ix_ + 6]) << 48) |
|
| + (static_cast<uint64_t>(buffer_[read_ix_ + 7]) << 56));
|
| + read_ix_ += sizeof *value;
|
| + return true;
|
| +}
|
| +
|
| +#if defined(NACL_HAS_IEEE_754)
|
| +bool SerializationBuffer::GetFloat(float *value) {
|
| + union ieee754_float v;
|
| + uint32_t encoded = 0;
|
| + if (!GetUint32(&encoded)) {
|
| + return false;
|
| + }
|
| + v.ieee.negative = encoded >> 31;
|
| + v.ieee.exponent = encoded >> 23;
|
| + v.ieee.mantissa = encoded;
|
| + *value = v.f;
|
| + return true;
|
| +}
|
| +
|
| +bool SerializationBuffer::GetDouble(double *value) {
|
| + union ieee754_double v;
|
| + uint64_t encoded;
|
| + if (!GetUint64(&encoded)) {
|
| + return false;
|
| + }
|
| + v.ieee.negative = encoded >> 63;
|
| + v.ieee.exponent = encoded >> 52;
|
| + v.ieee.mantissa0 = encoded >> 32;
|
| + v.ieee.mantissa1 = encoded;
|
| + *value = v.d;
|
| + return true;
|
| +}
|
| +
|
| +bool SerializationBuffer::GetLongDouble(long double *value) {
|
| + union ieee854_long_double v;
|
| + uint16_t encoded1;
|
| + uint64_t encoded2;
|
| + if (in_use_ < read_ix_ + 10) {
|
| + return false;
|
| + }
|
| + if (!GetUint16(&encoded1) || !GetUint64(&encoded2)) {
|
| + return false;
|
| + }
|
| + v.ieee.negative = (encoded1 >> 15) & 1;
|
| + v.ieee.exponent = encoded1;
|
| + v.ieee.mantissa0 = encoded2 >> 32;
|
| + v.ieee.mantissa1 = encoded2;
|
| + *value = v.d;
|
| + return true;
|
| +}
|
| +#endif
|
| +
|
| +void SerializationBuffer::EnsureTotalSize(size_t req_size) {
|
| + if (nbytes_ >= req_size) {
|
| + return;
|
| + }
|
| + size_t new_size = (0 == nbytes_) ? kInitialBufferSize : 2 * nbytes_;
|
| + CHECK(new_size > nbytes_); // no arithmetic overflow
|
| + if (new_size < req_size) {
|
| + new_size = req_size;
|
| + }
|
| + buffer_.resize(new_size);
|
| + nbytes_ = new_size;
|
| +}
|
| +
|
| +void SerializationBuffer::EnsureAvailableSpace(size_t req_space) {
|
| + CHECK(nbytes_ >= in_use_);
|
| + CHECK((~(size_t) 0) - in_use_ >= req_space);
|
| + size_t new_size = in_use_ + req_space;
|
| + EnsureTotalSize(new_size);
|
| +}
|
| +
|
| +} // namespace nacl
|
|
|