Skip to content

set, unordered_set, and deque support #28

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion docs/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,10 @@ This interface supports the following types:
* enum and enum classes.
* std::string.
* C-style arrays with elements of any supported type.
* std::array, std::pair, std::tuple, and std::vector with elements of any
* std::array, std::pair, std::tuple, std::vector, and std::deque with elements of any
supported type.
* std::map and std::unordered_map with keys and values of any supported type.
* std::set and std::unordered_set with keys of any supported type.
* std::reference_wrapper<T> with T of any supported type.
* nop::Optional<T> with T of any supported type.
* nop::Result<ErrorEnum, T> with T of any supported type.
Expand Down
101 changes: 101 additions & 0 deletions include/nop/base/deque.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
/*
* Copyright 2017 The Native Object Protocols Authors
*
* Licensed 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.
*/

#ifndef LIBNOP_INCLUDE_NOP_BASE_DEQUE_H_
#define LIBNOP_INCLUDE_NOP_BASE_DEQUE_H_

#include <nop/base/encoding.h>
#include <nop/base/utility.h>

#include <deque>
#include <numeric>

namespace nop {

//
// std::deque<T> encoding format:
//
// +-------+---------+-----//-----+
// | DEQUE | INT64:N | N ELEMENTS |
// +-------+---------+-----//-----+
//
// Elements must be valid encodings of type T.
//

template <typename T, typename Allocator>
struct Encoding<std::deque<T, Allocator>>
: EncodingIO<std::deque<T, Allocator>> {
using Type = std::deque<T, Allocator>;

static constexpr EncodingByte Prefix(const Type& /*value*/) {
return EncodingByte::Array;
}

static constexpr std::size_t Size(const Type& value) {
return BaseEncodingSize(Prefix(value)) +
Encoding<SizeType>::Size(value.size()) +
std::accumulate(value.cbegin(), value.cend(), 0U,
[](const std::size_t& sum, const T& element) {
return sum + Encoding<T>::Size(element);
});
}

static constexpr bool Match(EncodingByte prefix) {
return prefix == EncodingByte::Array;
}

template <typename Writer>
static constexpr Status<void> WritePayload(EncodingByte /*prefix*/,
const Type& value,
Writer* writer) {
auto status = Encoding<SizeType>::Write(value.size(), writer);
if (!status)
return status;

for (const T& element : value) {
status = Encoding<T>::Write(element, writer);
if (!status)
return status;
}

return {};
}

template <typename Reader>
static constexpr Status<void> ReadPayload(EncodingByte /*prefix*/,
Type* value, Reader* reader) {
SizeType size = 0;
auto status = Encoding<SizeType>::Read(&size, reader);
if (!status)
return status;

value->clear();
for (SizeType i = 0; i < size; i++) {
T element;
status = Encoding<T>::Read(&element, reader);
if (!status)
return status;

value->push_back(std::move(element));
}

return {};
}
};

} // namespace nop

#endif // LIBNOP_INCLUDE_NOP_BASE_DEQUE_H_
162 changes: 162 additions & 0 deletions include/nop/base/set.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
/*
* Copyright 2017 The Native Object Protocols Authors
*
* Licensed 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.
*/

#ifndef LIBNOP_INCLUDE_NOP_BASE_SET_H_
#define LIBNOP_INCLUDE_NOP_BASE_SET_H_

#include <nop/base/encoding.h>

#include <numeric>
#include <set>
#include <unordered_set>

namespace nop {

//
// std::set<Key> and std::unordered_set<Key> encoding format:
//
// +-----+---------+---//---+
// | SET | INT64:N | N KEYS |
// +-----+---------+---//---+
//
// Elements must be valid encodings of type T.
//

template <typename Key, typename Compare, typename Allocator>
struct Encoding<std::set<Key, Compare, Allocator>>
: EncodingIO<std::set<Key, Compare, Allocator>> {
using Type = std::set<Key, Compare, Allocator>;

static constexpr EncodingByte Prefix(const Type& /*value*/) {
return EncodingByte::Array;
}

static constexpr std::size_t Size(const Type& value) {
return BaseEncodingSize(Prefix(value)) +
Encoding<SizeType>::Size(value.size()) +
std::accumulate(value.cbegin(), value.cend(), 0U,
[](const std::size_t& sum, const Key& element) {
return sum + Encoding<Key>::Size(element);
});
}

static constexpr bool Match(EncodingByte prefix) {
return prefix == EncodingByte::Array;
}

template <typename Writer>
static constexpr Status<void> WritePayload(EncodingByte /*prefix*/,
const Type& value,
Writer* writer) {
auto status = Encoding<SizeType>::Write(value.size(), writer);
if (!status)
return status;

for (const Key& element : value) {
status = Encoding<Key>::Write(element, writer);
if (!status)
return status;
}

return {};
}

template <typename Reader>
static constexpr Status<void> ReadPayload(EncodingByte /*prefix*/,
Type* value, Reader* reader) {
SizeType size = 0;
auto status = Encoding<SizeType>::Read(&size, reader);
if (!status)
return status;

value->clear();
for (SizeType i = 0; i < size; i++) {
Key element;
status = Encoding<Key>::Read(&element, reader);
if (!status)
return status;

value->insert(std::move(element));
}

return {};
}
};

template <typename Key, typename Hash, typename KeyEqual, typename Allocator>
struct Encoding<std::unordered_set<Key, Hash, KeyEqual, Allocator>>
: EncodingIO<std::unordered_set<Key, Hash, KeyEqual, Allocator>> {
using Type = std::unordered_set<Key, Hash, KeyEqual, Allocator>;

static constexpr EncodingByte Prefix(const Type& /*value*/) {
return EncodingByte::Array;
}

static constexpr std::size_t Size(const Type& value) {
return BaseEncodingSize(Prefix(value)) +
Encoding<SizeType>::Size(value.size()) +
std::accumulate(value.cbegin(), value.cend(), 0U,
[](const std::size_t& sum, const Key& element) {
return sum + Encoding<Key>::Size(element);
});
}

static constexpr bool Match(EncodingByte prefix) {
return prefix == EncodingByte::Array;
}

template <typename Writer>
static constexpr Status<void> WritePayload(EncodingByte /*prefix*/,
const Type& value,
Writer* writer) {
auto status = Encoding<SizeType>::Write(value.size(), writer);
if (!status)
return status;

for (const Key& element : value) {
status = Encoding<Key>::Write(element, writer);
if (!status)
return status;
}

return {};
}

template <typename Reader>
static constexpr Status<void> ReadPayload(EncodingByte /*prefix*/,
Type* value, Reader* reader) {
SizeType size = 0;
auto status = Encoding<SizeType>::Read(&size, reader);
if (!status)
return status;

value->clear();
for (SizeType i = 0; i < size; i++) {
Key element;
status = Encoding<Key>::Read(&element, reader);
if (!status)
return status;

value->insert(std::move(element));
}

return {};
}
};

} // namespace nop

#endif // LIBNOP_INCLUDE_NOP_BASE_SET_H_
2 changes: 2 additions & 0 deletions include/nop/serializer.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#define LIBNOP_INCLUDE_NOP_SERIALIZER_H_

#include <nop/base/array.h>
#include <nop/base/deque.h>
#include <nop/base/encoding.h>
#include <nop/base/enum.h>
#include <nop/base/handle.h>
Expand All @@ -28,6 +29,7 @@
#include <nop/base/reference_wrapper.h>
#include <nop/base/result.h>
#include <nop/base/serializer.h>
#include <nop/base/set.h>
#include <nop/base/string.h>
#include <nop/base/table.h>
#include <nop/base/tuple.h>
Expand Down