/src/spotify-json/include/spotify/json/detail/field_registry.hpp
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2018 Spotify AB |
3 | | * |
4 | | * Licensed under the Apache License, Version 2.0 (the "License"); you may not |
5 | | * use this file except in compliance with the License. You may obtain a copy of |
6 | | * the License at |
7 | | * |
8 | | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | | * |
10 | | * Unless required by applicable law or agreed to in writing, software |
11 | | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
12 | | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the |
13 | | * License for the specific language governing permissions and limitations under |
14 | | * the License. |
15 | | */ |
16 | | |
17 | | #pragma once |
18 | | |
19 | | #include <cstddef> |
20 | | #include <memory> |
21 | | #include <string> |
22 | | #include <unordered_map> |
23 | | #include <utility> |
24 | | #include <vector> |
25 | | |
26 | | #include <spotify/json/decode_context.hpp> |
27 | | #include <spotify/json/encode_context.hpp> |
28 | | |
29 | | namespace spotify { |
30 | | namespace json { |
31 | | namespace detail { |
32 | | |
33 | | // This is a non-templated base class for field types to reduce binary size by |
34 | | // avoiding template instantiation explosion of shared_ptr<field_type> in |
35 | | // object_t. It needs a virtual destructor so the shared_ptr<detail::field> |
36 | | // deleter does the right thing. |
37 | | struct field { |
38 | | field(bool required, size_t required_field_idx) |
39 | 2.34k | : _data(required ? required_field_idx : json_size_t_max) {} |
40 | 2.34k | virtual ~field() = default; |
41 | | |
42 | | virtual void decode(decode_context &context, void *object) const = 0; |
43 | | virtual void encode( |
44 | | encode_context &context, |
45 | | const std::string &escaped_key, |
46 | | const void *object) const = 0; |
47 | | |
48 | 903 | json_force_inline bool is_required() const { return (_data != json_size_t_max); } |
49 | 903 | json_force_inline size_t required_field_idx() const { return _data; } |
50 | | |
51 | | private: |
52 | | size_t _data; |
53 | | }; |
54 | | |
55 | | // Non-templated class to reduce code bloat. |
56 | | class field_registry final { |
57 | | public: |
58 | | using field_vec = std::vector<std::pair<std::string, std::shared_ptr<const field>>>; |
59 | | using field_map = std::unordered_map<std::string, std::shared_ptr<const field>>; |
60 | | using const_iterator = typename field_vec::const_iterator; |
61 | | |
62 | | field_registry(); |
63 | | ~field_registry(); |
64 | | field_registry(const field_registry &); |
65 | | field_registry(field_registry &&); |
66 | | |
67 | | // Forward the iterator implementation so range based for works. |
68 | 0 | inline const_iterator begin() const noexcept { return _field_list.begin(); } |
69 | 0 | inline const_iterator end() const noexcept { return _field_list.end(); } |
70 | | |
71 | | void save(const std::string &name, bool required, const std::shared_ptr<field> &f); |
72 | | const field *find(const std::string &name) const noexcept; |
73 | 4.69k | size_t num_required_fields() const noexcept { return _num_required_fields; } |
74 | | |
75 | | private: |
76 | | field_vec _field_list; |
77 | | field_map _fields; |
78 | | size_t _num_required_fields = 0; |
79 | | }; |
80 | | |
81 | | } // namespace detail |
82 | | } // namespace json |
83 | | } // namespace spotify |