Chromium Code Reviews| 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..c985c63b11c4f7c8e930e7afa484fbddbc7cdac6 |
| --- /dev/null |
| +++ b/src/shared/serialization/serialization.cc |
| @@ -0,0 +1,316 @@ |
| +/* -*- 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); |
| + for (size_t ix = 0; ix < nbytes_; ++ix) { |
| + buffer_[ix] = data_buffer[ix]; |
| + } |
|
sehr
2013/02/26 00:57:58
memcpy?
bsy
2013/02/26 01:05:01
Done.
|
| +} |
| + |
| +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 |