305 lines
8.8 KiB
C++
305 lines
8.8 KiB
C++
// Licensed to the Apache Software Foundation (ASF) under one
|
|
// or more contributor license agreements. See the NOTICE file
|
|
// distributed with this work for additional information
|
|
// regarding copyright ownership. The ASF licenses this file
|
|
// to you under the Apache License, Version 2.0 (the
|
|
// "License"); you may not use this file except in compliance
|
|
// with the License. You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing,
|
|
// software distributed under the License is distributed on an
|
|
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
// KIND, either express or implied. See the License for the
|
|
// specific language governing permissions and limitations
|
|
// under the License.
|
|
|
|
// mcpack2pb - Make protobuf be front-end of mcpack/compack
|
|
|
|
// Date: Mon Oct 19 17:17:36 CST 2015
|
|
|
|
#ifndef MCPACK2PB_MCPACK_SERIALIZER_INL_H
|
|
#define MCPACK2PB_MCPACK_SERIALIZER_INL_H
|
|
|
|
void* fast_memcpy(void *__restrict dest, const void *__restrict src, size_t n);
|
|
|
|
namespace mcpack2pb {
|
|
|
|
inline OutputStream::Area::Area(const Area& rhs)
|
|
: _addr1(rhs._addr1)
|
|
, _addr2(rhs._addr2)
|
|
, _size1(rhs._size1)
|
|
, _size2(rhs._size2)
|
|
, _addional_area(NULL) {
|
|
|
|
if (rhs._addional_area) {
|
|
_addional_area = new std::vector<butil::StringPiece>(*rhs._addional_area);
|
|
}
|
|
}
|
|
|
|
inline OutputStream::Area::~Area() {
|
|
if (_addional_area) {
|
|
delete _addional_area;
|
|
_addional_area = NULL;
|
|
}
|
|
}
|
|
|
|
inline OutputStream::Area& OutputStream::Area::operator=(const OutputStream::Area& rhs) {
|
|
if (this == &rhs) {
|
|
return *this;
|
|
}
|
|
this->~Area();
|
|
new (this) Area(rhs);
|
|
return *this;
|
|
}
|
|
|
|
inline void OutputStream::Area::add(void* data, size_t n) {
|
|
if (!data) {
|
|
return;
|
|
}
|
|
if (_addr1 == NULL) {
|
|
_addr1 = data;
|
|
_size1 = n;
|
|
} else if (_addr2 == NULL) {
|
|
_addr2 = data;
|
|
_size2 = n;
|
|
} else {
|
|
if (_addional_area == NULL) {
|
|
_addional_area = new std::vector<butil::StringPiece>;
|
|
}
|
|
_addional_area->push_back(butil::StringPiece((const char*)data, n));
|
|
}
|
|
}
|
|
|
|
inline void OutputStream::Area::assign(const void* data) const {
|
|
if (_addr1) {
|
|
fast_memcpy(_addr1, data, _size1);
|
|
if (!_addr2) {
|
|
return;
|
|
}
|
|
fast_memcpy(_addr2, (const char*)data + _size1, _size2);
|
|
if (!_addional_area) {
|
|
return;
|
|
}
|
|
size_t offset = _size1 + _size2;
|
|
for (std::vector<butil::StringPiece>::const_iterator iter =
|
|
_addional_area->begin(); iter != _addional_area->end(); ++iter) {
|
|
fast_memcpy((void*)iter->data(), (const char*)data + offset, iter->size());
|
|
offset += iter->size();
|
|
}
|
|
}
|
|
}
|
|
|
|
inline void OutputStream::done() {
|
|
if (_good && _size) {
|
|
_zc_stream->BackUp(_size);
|
|
_size = 0;
|
|
_fullsize = 0;
|
|
}
|
|
}
|
|
|
|
inline void OutputStream::append(const void* data, int n) {
|
|
const int saved_n = n;
|
|
do {
|
|
if (n <= _size) {
|
|
fast_memcpy(_data, data, n);
|
|
_data = (char*)_data + n;
|
|
_size -= n;
|
|
_pushed_bytes += saved_n;
|
|
return;
|
|
}
|
|
fast_memcpy(_data, data, _size);
|
|
data = (const char*)data + _size;
|
|
n -= _size;
|
|
if (!_zc_stream->Next(&_data, &_size)) {
|
|
break;
|
|
}
|
|
_fullsize = _size;
|
|
} while (1);
|
|
_data = NULL;
|
|
_size = 0;
|
|
_fullsize = 0;
|
|
_pushed_bytes += (saved_n - n);
|
|
if (n) {
|
|
set_bad();
|
|
}
|
|
}
|
|
|
|
template <typename T>
|
|
inline void OutputStream::append_packed_pod(const T& packed_pod) {
|
|
// if (sizeof(T) <= _size) {
|
|
// *(T*)_data = packed_pod;
|
|
// _data = (char*)_data + sizeof(T);
|
|
// _size -= sizeof(T);
|
|
// _pushed_bytes += sizeof(T);
|
|
// return;
|
|
// }
|
|
return append(&packed_pod, sizeof(T));
|
|
}
|
|
|
|
inline void OutputStream::push_back(char c) {
|
|
do {
|
|
if (_size > 0) {
|
|
*(char*)_data = c;
|
|
_data = (char*)_data + 1;
|
|
--_size;
|
|
++_pushed_bytes;
|
|
return;
|
|
}
|
|
if (!_zc_stream->Next(&_data, &_size)) {
|
|
break;
|
|
}
|
|
_fullsize = _size;
|
|
} while (1);
|
|
_data = NULL;
|
|
_size = 0;
|
|
_fullsize = 0;
|
|
set_bad();
|
|
}
|
|
|
|
inline void* OutputStream::skip_continuous(int n) {
|
|
if (_size >= n) {
|
|
void* ret = _data;
|
|
_data = (char*)_data + n;
|
|
_size -= n;
|
|
_pushed_bytes += n;
|
|
return ret;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
inline OutputStream::Area OutputStream::reserve(int n) {
|
|
Area area;
|
|
const int saved_n = n;
|
|
do {
|
|
if (n <= _size) {
|
|
area.add(_data, n);
|
|
_data = (char*)_data + n;
|
|
_size -= n;
|
|
_pushed_bytes += saved_n;
|
|
return area;
|
|
}
|
|
area.add(_data, _size);
|
|
n -= _size;
|
|
if (!_zc_stream->Next(&_data, &_size)) {
|
|
break;
|
|
}
|
|
_fullsize = _size;
|
|
} while (1);
|
|
_data = NULL;
|
|
_size = 0;
|
|
_fullsize = 0;
|
|
_pushed_bytes += (saved_n - n);
|
|
if (n) {
|
|
set_bad();
|
|
}
|
|
return area;
|
|
}
|
|
|
|
inline void OutputStream::assign(const Area& area, const void* data) {
|
|
area.assign(data);
|
|
}
|
|
|
|
inline void OutputStream::backup(int n) {
|
|
if (_fullsize >= _size + n) {
|
|
_size += n;
|
|
_data = (char*)_data - n;
|
|
_pushed_bytes -= n;
|
|
return;
|
|
}
|
|
const int64_t saved_bytecount = _zc_stream->ByteCount();
|
|
// Backup the remaining size + what user requests. The implementation
|
|
// <= r33563 backups n + _size - _fullsize which is wrong.
|
|
_zc_stream->BackUp(n + _size);
|
|
const int64_t nbackup = saved_bytecount - _zc_stream->ByteCount();
|
|
if (nbackup != n + _size) {
|
|
CHECK(false) << "Expect output stream backward for " << n + _size
|
|
<< " bytes, actually " << nbackup << " bytes";
|
|
}
|
|
_size = 0;
|
|
_fullsize = 0;
|
|
_data = NULL;
|
|
_pushed_bytes -= n;
|
|
}
|
|
|
|
inline Serializer::GroupInfo* Serializer::push_group_info() {
|
|
if (_ndepth + 1 < (int)arraysize(_group_info_fast)) {
|
|
return &_group_info_fast[++_ndepth];
|
|
}
|
|
if (_ndepth >= MAX_DEPTH) {
|
|
return NULL;
|
|
}
|
|
if (_group_info_more == NULL) {
|
|
_group_info_more =
|
|
(GroupInfo*)malloc((MAX_DEPTH + 1 - arraysize(_group_info_fast))
|
|
* sizeof(GroupInfo));
|
|
if (_group_info_more == NULL) {
|
|
return NULL;
|
|
}
|
|
}
|
|
return &_group_info_more[++_ndepth - arraysize(_group_info_fast)];
|
|
}
|
|
|
|
inline Serializer::GroupInfo& Serializer::peek_group_info() {
|
|
if (_ndepth < (int)arraysize(_group_info_fast)) {
|
|
return _group_info_fast[_ndepth];
|
|
} else {
|
|
return _group_info_more[_ndepth - arraysize(_group_info_fast)];
|
|
}
|
|
}
|
|
|
|
inline void Serializer::add_multiple_int8(const uint8_t* values, size_t count) {
|
|
return add_multiple_int8((const int8_t*)values, count);
|
|
}
|
|
inline void Serializer::add_multiple_int16(const uint16_t* values, size_t count) {
|
|
return add_multiple_int16((const int16_t*)values, count);
|
|
}
|
|
inline void Serializer::add_multiple_int32(const uint32_t* values, size_t count) {
|
|
return add_multiple_int32((const int32_t*)values, count);
|
|
}
|
|
inline void Serializer::add_multiple_int64(const uint64_t* values, size_t count) {
|
|
return add_multiple_int64((const int64_t*)values, count);
|
|
}
|
|
|
|
inline void Serializer::add_multiple_uint8(const int8_t* values, size_t count) {
|
|
return add_multiple_uint8((const uint8_t*)values, count);
|
|
}
|
|
inline void Serializer::add_multiple_uint16(const int16_t* values, size_t count) {
|
|
return add_multiple_uint16((const uint16_t*)values, count);
|
|
}
|
|
inline void Serializer::add_multiple_uint32(const int32_t* values, size_t count) {
|
|
return add_multiple_uint32((const uint32_t*)values, count);
|
|
}
|
|
inline void Serializer::add_multiple_uint64(const int64_t* values, size_t count) {
|
|
return add_multiple_uint64((const uint64_t*)values, count);
|
|
}
|
|
|
|
inline void Serializer::begin_mcpack_array(const StringWrapper& name, FieldType item_type)
|
|
{ begin_array_internal(name, item_type, false); }
|
|
|
|
inline void Serializer::begin_mcpack_array(FieldType item_type)
|
|
{ begin_array_internal(item_type, false); }
|
|
|
|
inline void Serializer::begin_compack_array(const StringWrapper& name, FieldType item_type)
|
|
{ begin_array_internal(name, item_type, true); }
|
|
|
|
inline void Serializer::begin_compack_array(FieldType item_type)
|
|
{ begin_array_internal(item_type, true); }
|
|
|
|
inline void Serializer::begin_object(const StringWrapper& name)
|
|
{ begin_object_internal(name); }
|
|
|
|
inline void Serializer::begin_object()
|
|
{ begin_object_internal(); }
|
|
|
|
inline void Serializer::end_object()
|
|
{ end_object_internal(false); }
|
|
|
|
inline void Serializer::end_object_iso()
|
|
{ end_object_internal(true); }
|
|
|
|
} // namespace mcpack2pb
|
|
|
|
#endif // MCPACK2PB_MCPACK_SERIALIZER_INL_H
|