Coverage Report

Created: 2025-07-18 06:30

/src/spotify-json/include/spotify/json/encode_context.hpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (c) 2016-2019 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 <cstdint>
21
#include <cstdlib>
22
#include <cstring>
23
#include <memory>
24
#include <spotify/json/detail/macros.hpp>
25
26
namespace spotify {
27
namespace json {
28
29
/**
30
 * An encode_context has the information that is kept while encoding JSON with
31
 * codecs. It keeps a buffer of data that can be expanded and written to.
32
 */
33
struct encode_context final {
34
  encode_context(const std::size_t capacity = 4096);
35
  ~encode_context();
36
37
9.61k
  json_force_inline char *reserve(const std::size_t reserved_bytes) {
38
9.61k
    const auto remaining_bytes = static_cast<std::size_t>(_end - _ptr);  // _end is always >= _ptr
39
9.61k
    if (json_likely(remaining_bytes >= reserved_bytes)) {
40
9.61k
      return _ptr;
41
9.61k
    } else {
42
0
      return grow_buffer(reserved_bytes);
43
0
    }
44
9.61k
  }
45
46
9.61k
  json_force_inline void advance(const std::size_t num_bytes) {
47
9.61k
    _ptr += num_bytes;
48
9.61k
  }
49
50
7.20k
  json_force_inline void append(const char c) {
51
7.20k
    reserve(1)[0] = c;
52
7.20k
    advance(1);
53
7.20k
  }
54
55
0
  json_force_inline void append_or_replace(const char replacing, const char with) {
56
0
    if (json_likely(!empty() && _ptr[-1] == replacing)) {
57
0
      _ptr[-1] = with;
58
0
    } else {
59
0
      append(with);
60
0
    }
61
0
  }
62
63
0
  json_force_inline void append(const void *data, const std::size_t size) {
64
0
    std::memcpy(reserve(size), data, size);
65
0
    advance(size);
66
0
  }
67
68
0
  json_never_inline void clear() {
69
0
    _ptr = _buf;
70
0
  }
71
72
2.40k
  json_force_inline const char *data() const {
73
2.40k
    return _buf;
74
2.40k
  }
75
76
2.40k
  json_force_inline std::size_t size() const {
77
2.40k
    return static_cast<std::size_t>(_ptr - _buf);
78
2.40k
  }
79
80
0
  json_force_inline std::size_t capacity() const {
81
0
    return _capacity;
82
0
  }
83
84
0
  json_force_inline bool empty() const {
85
0
    return (_ptr == _buf);
86
0
  }
87
88
  std::unique_ptr<void, decltype(std::free) *> steal_data();
89
90
  const bool has_sse42;
91
92
 private:
93
  char * grow_buffer(const std::size_t num_bytes);
94
95
  char *_buf;
96
  char *_ptr;
97
  const char *_end;
98
  std::size_t _capacity;
99
};
100
101
}  // namespace json
102
}  // namespace spotify