• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

mendersoftware / mender / 950534094

pending completion
950534094

push

gitlab-ci

kacf
chore: Add `StartsWith` and `EndsWith` generic utility functions.

Also use the latter in `states.cpp`.

Signed-off-by: Kristian Amlie <kristian.amlie@northern.tech>

1 of 1 new or added line in 1 file covered. (100.0%)

4931 of 6276 relevant lines covered (78.57%)

196.18 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

72.73
/common/json/json.cpp
1
// Copyright 2023 Northern.tech AS
2
//
3
//    Licensed under the Apache License, Version 2.0 (the "License");
4
//    you may not use this file except in compliance with the License.
5
//    You may obtain a copy of the License at
6
//
7
//        http://www.apache.org/licenses/LICENSE-2.0
8
//
9
//    Unless required by applicable law or agreed to in writing, software
10
//    distributed under the License is distributed on an "AS IS" BASIS,
11
//    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
//    See the License for the specific language governing permissions and
13
//    limitations under the License.
14

15
#include <common/json.hpp>
16

17
#include <string>
18
#include <unordered_map>
19
#include <vector>
20

21
namespace mender {
22
namespace common {
23
namespace json {
24

25
const JsonErrorCategoryClass JsonErrorCategory;
26

27
const char *JsonErrorCategoryClass::name() const noexcept {
×
28
        return "JsonErrorCategory";
×
29
}
30

31
string JsonErrorCategoryClass::message(int code) const {
×
32
        switch (code) {
×
33
        case NoError:
×
34
                return "Success";
×
35
        case ParseError:
×
36
                return "Parse error";
×
37
        case KeyError:
×
38
                return "Key error";
×
39
        case IndexError:
×
40
                return "Index error";
×
41
        case TypeError:
×
42
                return "Type error";
×
43
        default:
×
44
                return "Unknown";
×
45
        }
46
}
47

48
error::Error MakeError(JsonErrorCode code, const string &msg) {
557✔
49
        return error::Error(error_condition(code, JsonErrorCategory), msg);
1,114✔
50
}
51

52
template <>
53
expected::expected<KeyValueMap, error::Error> Json::Get<KeyValueMap>() const {
8✔
54
        return ToKeyValuesMap(*this);
8✔
55
}
56

57
template <>
58
expected::expected<vector<string>, error::Error> Json::Get<vector<string>>() const {
16✔
59
        return ToStringVector(*this);
16✔
60
}
61

62
template <>
63
expected::expected<string, error::Error> Json::Get<string>() const {
17✔
64
        return GetString();
17✔
65
}
66

67
template <>
68
expected::expected<int64_t, error::Error> Json::Get<int64_t>() const {
9✔
69
        return GetInt();
9✔
70
}
71

72
template <>
73
expected::expected<double, error::Error> Json::Get<double>() const {
1✔
74
        return GetDouble();
1✔
75
}
76

77
template <>
78
expected::expected<bool, error::Error> Json::Get<bool>() const {
1✔
79
        return GetBool();
1✔
80
}
81

82
inline void StringReplaceAll(string &str, const string &what, const string &with) {
19,663✔
83
        for (string::size_type pos {}; str.npos != (pos = str.find(what.data(), pos, what.length()));
19,676✔
84
                 pos += with.length()) {
13✔
85
                str.replace(pos, what.length(), with);
13✔
86
        }
87
}
19,663✔
88

89
string EscapeString(const string &str) {
2,809✔
90
        string ret {str};
2,809✔
91

92
        // see https://www.json.org/json-en.html
93
        StringReplaceAll(ret, "\\", "\\\\");
2,809✔
94
        StringReplaceAll(ret, "\"", "\\\"");
2,809✔
95
        StringReplaceAll(ret, "\n", "\\n");
2,809✔
96
        StringReplaceAll(ret, "\t", "\\t");
2,809✔
97
        StringReplaceAll(ret, "\r", "\\r");
2,809✔
98
        StringReplaceAll(ret, "\f", "\\f");
2,809✔
99
        StringReplaceAll(ret, "\b", "\\b");
2,809✔
100

101
        return ret;
2,809✔
102
}
103

104
ExpectedString ToString(const json::Json &j) {
582✔
105
        return j.GetString();
582✔
106
}
107

108
ExpectedStringVector ToStringVector(const json::Json &j) {
248✔
109
        if (!j.IsArray()) {
248✔
110
                return expected::unexpected(
×
111
                        MakeError(JsonErrorCode::ParseError, "The JSON object is not an array"));
×
112
        }
113
        vector<string> vector_elements {};
496✔
114
        size_t vector_size {j.GetArraySize().value()};
248✔
115
        for (size_t i = 0; i < vector_size; ++i) {
586✔
116
                auto element = j.Get(i).and_then(ToString);
338✔
117
                if (!element) {
338✔
118
                        return expected::unexpected(element.error());
×
119
                }
120
                vector_elements.push_back(element.value());
338✔
121
        }
122
        return vector_elements;
248✔
123
}
124

125
ExpectedKeyValueMap ToKeyValuesMap(const json::Json &j) {
109✔
126
        if (!j.IsObject()) {
109✔
127
                return expected::unexpected(
×
128
                        MakeError(JsonErrorCode::ParseError, "The JSON is not an object"));
×
129
        }
130

131
        auto expected_children = j.GetChildren();
218✔
132
        if (!expected_children) {
109✔
133
                return expected::unexpected(expected_children.error());
×
134
        }
135

136
        unordered_map<string, string> kv_map {};
218✔
137

138
        for (const auto &kv : expected_children.value()) {
264✔
139
                string key = kv.first;
155✔
140
                auto expected_value = kv.second.GetString();
155✔
141
                if (!expected_value) {
155✔
142
                        return expected::unexpected(expected_value.error());
×
143
                }
144
                kv_map[key] = expected_value.value();
155✔
145
        }
146

147
        return kv_map;
109✔
148
}
149

150
ExpectedInt64 ToInt(const json::Json &j) {
26✔
151
        return j.GetInt();
26✔
152
}
153

154
ExpectedBool ToBool(const json::Json &j) {
26✔
155
        return j.GetBool();
26✔
156
}
157

158
template <typename T>
159
expected::expected<T, error::Error> Get(
8✔
160
        const json::Json &json, const string &key, MissingOk missing_ok) {
161
        auto exp_value = json.Get(key);
16✔
162
        if (!exp_value) {
8✔
163
                if (missing_ok == MissingOk::Yes
1✔
164
                        && exp_value.error().code != json::MakeError(json::KeyError, "").code) {
1✔
165
                        return T();
×
166
                } else {
167
                        auto err = exp_value.error();
1✔
168
                        err.message += ": Could not get `" + key + "` from state data";
1✔
169
                        return expected::unexpected(err);
2✔
170
                }
171
        }
172
        return exp_value.value().Get<T>();
7✔
173
}
174
// The number of instantiations is pretty much set in stone since it depends on the number of JSON
175
// types, which isn't going to change. So use explicit instantiation for compile time efficiency.
176
template expected::expected<KeyValueMap, error::Error> Get(
177
        const json::Json &json, const string &key, MissingOk missing_ok);
178
template expected::expected<vector<string>, error::Error> Get(
179
        const json::Json &json, const string &key, MissingOk missing_ok);
180
template expected::expected<string, error::Error> Get(
181
        const json::Json &json, const string &key, MissingOk missing_ok);
182
template expected::expected<int64_t, error::Error> Get(
183
        const json::Json &json, const string &key, MissingOk missing_ok);
184
template expected::expected<double, error::Error> Get(
185
        const json::Json &json, const string &key, MissingOk missing_ok);
186
template expected::expected<bool, error::Error> Get(
187
        const json::Json &json, const string &key, MissingOk missing_ok);
188

189
} // namespace json
190
} // namespace common
191
} // namespace mender
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc