Coverage Report

Created: 2025-11-16 06:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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