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

STEllAR-GROUP / hpx / #882

31 Aug 2023 07:44PM UTC coverage: 41.798% (-44.7%) from 86.546%
#882

push

19442 of 46514 relevant lines covered (41.8%)

126375.38 hits per line

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

94.38
/libs/core/logging/src/format/named_write.cpp
1
// named_write.cpp
2

3
// Boost Logging library
4
//
5
// Author: John Torjo, www.torjo.com
6
//
7
// Copyright (C) 2007 John Torjo (see www.torjo.com for email)
8
//
9
//  SPDX-License-Identifier: BSL-1.0
10
// Distributed under the Boost Software License, Version 1.0.
11
//    (See accompanying file LICENSE_1_0.txt or copy at
12
//          http://www.boost.org/LICENSE_1_0.txt)
13
//
14
// See http://www.boost.org for updates, documentation, and revision history.
15
// See http://www.torjo.com/log2/ for more details
16

17
#include <hpx/config.hpp>
18
#include <hpx/assert.hpp>
19
#include <hpx/logging/format/destinations.hpp>
20
#include <hpx/logging/format/formatters.hpp>
21
#include <hpx/logging/format/named_write.hpp>
22

23
#include <cstddef>
24
#include <memory>
25
#include <sstream>
26
#include <string>
27

28
namespace hpx::util::logging::detail {
29

30
    static std::string unescape(std::string escaped)
31
    {
12,736✔
32
        using size_type = std::size_t;
33

34
        size_type idx_start = 0;
35
        while (true)
36
        {
37
            size_type const found = escaped.find("%%", idx_start);
38
            if (found != std::string::npos)
39
            {
12,736✔
40
                escaped.erase(
41
                    escaped.begin() + static_cast<std::ptrdiff_t>(found));
42
                ++idx_start;
43
            }
×
44
            else
45
                break;
46
        }
47
        return escaped;
×
48
    }
12,736✔
49

50
    void named_formatters::compute_write_steps()
51
    {
3,712✔
52
        typedef std::size_t size_type;
53

54
        write_steps.clear();
55
        std::string remaining = format_string;
3,712✔
56
        size_type start_search_idx = 0;
57
        while (!remaining.empty())
58
        {
16,448✔
59
            size_type idx = remaining.find_first_of("%|", start_search_idx);
60
            switch (idx != std::string::npos ? remaining[idx] : '\0')
61
            {
12,736✔
62
            case '|':
63
            {
1,216✔
64
                // up to here, this is a spacer string
65
                start_search_idx = 0;
66
                std::string spacer = detail::unescape(remaining.substr(0, idx));
67
                remaining.erase(0, idx + 1);
1,216✔
68

1,216✔
69
                auto* fmt = reinterpret_cast<formatter::manipulator*>(-1);
70
                write_steps.emplace_back(spacer, fmt);
1,216✔
71
                break;
1,216✔
72
            }
73
            case '%':
74
            {
75
                // see if just escaped
76
                if ((idx < remaining.size() - 1) && remaining[idx + 1] == '%')
77
                {
10,368✔
78
                    // we found an escaped char
79
                    start_search_idx = idx + 2;
80
                    continue;
×
81
                }
×
82

83
                // up to here, this is a spacer string
84
                start_search_idx = 0;
85
                std::string spacer = detail::unescape(remaining.substr(0, idx));
86
                remaining.erase(0, idx + 1);
10,368✔
87
                // find end of formatter name
10,368✔
88
                idx = remaining.find('%');
89
                formatter::manipulator* fmt = nullptr;
10,368✔
90
                if (idx != std::string::npos)
10,368✔
91
                {
10,368✔
92
                    std::string name = remaining.substr(0, idx);
93
                    remaining.erase(0, idx + 1);
10,368✔
94
                    auto iter = find_named(formatters, name);
10,368✔
95
                    if (iter != formatters.end())
10,368✔
96
                        fmt = iter->value.get();
10,368✔
97
                }
5,888✔
98
                // note: fmt could be null, in case
99
                write_steps.emplace_back(spacer, fmt);
100
                break;
10,368✔
101
            }
102
            case '\0':
103
            {
1,152✔
104
                // last part
105
                write_steps.emplace_back(detail::unescape(remaining), nullptr);
106
                remaining.clear();
3,456✔
107
                break;
108
            }
109
            default:
110
                break;
111
            }
112
        }
113
    }
114

3,712✔
115
    void named_destinations::compute_write_steps()
116
    {
3,648✔
117
        write_steps.clear();
118

3,648✔
119
        std::istringstream in(format_string);
120
        std::string word;
3,648✔
121
        while (in >> word)
122
        {
3,904✔
123
            if (word[0] == '+')
124
                word.erase(word.begin());
256✔
125
            else if (word[0] == '-')
126
                // ignore this word
256✔
127
                continue;
128

129
            auto iter = find_named(destinations, word);
130
            if (iter != destinations.cend())
256✔
131
                write_steps.push_back(iter->value.get());
256✔
132
        }
256✔
133
    }
134

3,648✔
135
    namespace {
136
        struct parse_formatter
137
        {
192✔
138
            // formatter starts and ends with %
139
            [[nodiscard]] bool has_manipulator_name() const
140
            {
141
                if (m_manipulator.empty())
142
                    return false;
16,704✔
143
                if (m_manipulator.size() > 1)
144
                    if (m_manipulator[0] == '%' &&
14,336✔
145
                        (*m_manipulator.rbegin() == '%'))
12,032✔
146
                        return true;
12,032✔
147

148
                return false;
149
            }
150

151
            [[nodiscard]] std::string get_manipulator_name() const
152
            {
153
                HPX_ASSERT(has_manipulator_name());
154
                // ignore starting and ending %
155
                return m_manipulator.substr(1, m_manipulator.size() - 2);
156
            }
128✔
157

158
            void clear()
159
            {
160
                m_manipulator.clear();
161
            }
162

1,024✔
163
            void add(char c)
164
            {
14,144✔
165
                if (has_manipulator_name())
166
                    // was a manipulator until now
167
                    clear();
168

169
                if (c == '%')
170
                {
14,144✔
171
                    m_manipulator += c;
172
                    if (!has_manipulator_name())
2,304✔
173
                        // it could be the start of a formatter
174
                        m_manipulator = '%';
175
                }
176
                else if (m_manipulator.empty())
177
                {
11,840✔
178
                    // ignore this char - not from a manipulator
179
                }
180
                else if (m_manipulator[0] == '%')
181
                {
9,728✔
182
                    m_manipulator += c;
183
                }
9,728✔
184
                else
185
                {
186
                    // manipulator should always start with %
187
                    HPX_ASSERT(false);
188
                }
189
            }
190

14,144✔
191
        private:
192
            std::string m_manipulator;
193
        };
194

195
        struct parse_destination
196
        {
192✔
197
            [[nodiscard]] bool has_manipulator_name() const
198
            {
199
                return !m_manipulator.empty();
200
            }
201

202
            [[nodiscard]] std::string get_manipulator_name() const
203
            {
64✔
204
                HPX_ASSERT(has_manipulator_name());
205
                if (m_manipulator[0] == '-' || m_manipulator[0] == '+')
206
                    // + or - -> turning on or off a destination
64✔
207
                    return m_manipulator.substr(1);
208
                else
×
209
                    return m_manipulator;
210
            }
211

212
            void clear()
213
            {
214
                m_manipulator.clear();
215
            }
216

64✔
217
            void add(char c)
218
            {
219
                // destination always follows ' '
220
                if (c == ' ')
221
                    clear();
1,472✔
222
                else
223
                    m_manipulator += c;
224
            }
1,408✔
225

226
        private:
227
            std::string m_manipulator;
228
        };
229

230
        template <typename Named, typename ParserType>
231
        void configure(
232
            Named& named, std::string const& format, ParserType parser)
192✔
233
        {
234
            // need to parse string
235
            bool parsing_params = false;
236
            std::string params;
237
            std::string stripped_str;
238
            for (char c : format)
239
            {
16,768✔
240
                if ((c == '(') && !parsing_params)
241
                {
16,576✔
242
                    if (parser.has_manipulator_name())
243
                    {
64✔
244
                        parsing_params = true;
245
                        params.clear();
246
                    }
247
                    else
248
                    {
249
                        stripped_str += c;
250
                        parser.add(c);
251
                    }
128✔
252
                }
253
                else if (c == ')' && parsing_params)
254
                {
16,320✔
255
                    HPX_ASSERT(parser.has_manipulator_name());
256
                    named.configure(parser.get_manipulator_name(), params);
257
                    parser.clear();
256✔
258
                    parsing_params = false;
259
                }
260
                else
261
                {
262
                    if (parsing_params)
263
                        params += c;
16,192✔
264
                    else
2,176✔
265
                    {
266
                        stripped_str += c;
267
                        parser.add(c);
14,016✔
268
                    }
14,016✔
269
                }
270
            }
271
            named.string(stripped_str);
272
        }
273
    }    // namespace
192✔
274
}    // namespace hpx::util::logging::detail
275

276
namespace hpx::util::logging::writer {
277

278
    named_write::named_write()
279
    {
832✔
280
        set_formatter<formatter::idx>("idx");
281
        set_formatter<formatter::high_precision_time>("time", "$hh:$mm:$ss");
832✔
282
        set_formatter<formatter::thread_id>("thread_id");
832✔
283

832✔
284
        set_destination<destination::file>("file", "");
285
        set_destination<destination::cout>("cout");
832✔
286
        set_destination<destination::cerr>("cerr");
832✔
287
        set_destination<destination::dbg_window>("debug");
832✔
288
    }
832✔
289

832✔
290
    void named_write::configure_formatter(std::string const& format)
291
    {
192✔
292
        detail::configure(m_format, format, detail::parse_formatter{});
293
    }
192✔
294

192✔
295
    void named_write::configure_destination(std::string const& format)
296
    {
192✔
297
        detail::configure(m_destination, format, detail::parse_destination{});
298
    }
192✔
299
}    // namespace hpx::util::logging::writer
192✔
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