Coverage Report

Created: 2026-06-15 06:43

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/rnp/src/common/str-utils.cpp
Line
Count
Source
1
/*
2
 * Copyright (c) 2017 [Ribose Inc](https://www.ribose.com).
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without modification,
6
 * are permitted provided that the following conditions are met:
7
 *
8
 * 1.  Redistributions of source code must retain the above copyright notice,
9
 *     this list of conditions and the following disclaimer.
10
 *
11
 * 2.  Redistributions in binary form must reproduce the above copyright notice,
12
 *     this list of conditions and the following disclaimer in the documentation
13
 *     and/or other materials provided with the distribution.
14
 *
15
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
19
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25
 */
26
/** String utilities
27
 *  @file
28
 */
29
30
#include <cstddef>
31
#include <cstring>
32
#include <cctype>
33
#include <stdexcept>
34
#include "str-utils.h"
35
#ifdef _WIN32
36
#include <locale>
37
#include <codecvt>
38
#endif
39
40
using std::size_t;
41
using std::strlen;
42
43
namespace rnp {
44
char *
45
strip_eol(char *s)
46
0
{
47
0
    size_t len = strlen(s);
48
49
0
    while ((len > 0) && ((s[len - 1] == '\n') || (s[len - 1] == '\r'))) {
50
0
        s[--len] = '\0';
51
0
    }
52
53
0
    return s;
54
0
}
55
56
bool
57
strip_eol(std::string &s)
58
0
{
59
0
    size_t len = s.size();
60
0
    while (len && ((s[len - 1] == '\n') || (s[len - 1] == '\r'))) {
61
0
        len--;
62
0
    }
63
0
    if (len == s.size()) {
64
0
        return false;
65
0
    }
66
0
    s.resize(len);
67
0
    return true;
68
0
}
69
70
bool
71
is_blank_line(const char *line, size_t len)
72
274k
{
73
291k
    for (size_t i = 0; i < len && line[i]; i++) {
74
291k
        if (line[i] != ' ' && line[i] != '\t' && line[i] != '\r') {
75
274k
            return false;
76
274k
        }
77
291k
    }
78
26
    return true;
79
274k
}
80
81
bool
82
str_case_eq(const char *s1, const char *s2)
83
302k
{
84
592k
    while (*s1 && *s2) {
85
556k
        if (std::tolower(*s1) != std::tolower(*s2)) {
86
266k
            return false;
87
266k
        }
88
289k
        s1++;
89
289k
        s2++;
90
289k
    }
91
36.2k
    return !*s1 && !*s2;
92
302k
}
93
94
bool
95
str_case_eq(const std::string &s1, const std::string &s2)
96
0
{
97
0
    if (s1.size() != s2.size()) {
98
0
        return false;
99
0
    }
100
0
    return str_case_eq(s1.c_str(), s2.c_str());
101
0
}
102
103
static size_t
104
hex_prefix_len(const std::string &str)
105
540k
{
106
540k
    if ((str.length() >= 2) && (str[0] == '0') && ((str[1] == 'x') || (str[1] == 'X'))) {
107
540k
        return 2;
108
540k
    }
109
0
    return 0;
110
540k
}
111
112
bool
113
is_hex(const std::string &s)
114
540k
{
115
39.3M
    for (size_t i = hex_prefix_len(s); i < s.length(); i++) {
116
38.8M
        auto &ch = s[i];
117
38.8M
        if ((ch >= '0') && (ch <= '9')) {
118
20.3M
            continue;
119
20.3M
        }
120
18.4M
        if ((ch >= 'a') && (ch <= 'f')) {
121
17.8M
            continue;
122
17.8M
        }
123
581k
        if ((ch >= 'A') && (ch <= 'F')) {
124
581k
            continue;
125
581k
        }
126
0
        if ((ch == ' ') || (ch == '\t')) {
127
0
            continue;
128
0
        }
129
0
        return false;
130
0
    }
131
540k
    return true;
132
540k
}
133
134
std::string
135
strip_hex(const std::string &s)
136
0
{
137
0
    std::string res = "";
138
0
    for (size_t idx = hex_prefix_len(s); idx < s.length(); idx++) {
139
0
        auto ch = s[idx];
140
0
        if ((ch == ' ') || (ch == '\t')) {
141
0
            continue;
142
0
        }
143
0
        res.push_back(ch);
144
0
    }
145
0
    return res;
146
0
}
147
148
char *
149
lowercase(char *s)
150
0
{
151
0
    if (!s) {
152
0
        return s;
153
0
    }
154
0
    for (char *ptr = s; *ptr; ++ptr) {
155
0
        *ptr = tolower(*ptr);
156
0
    }
157
0
    return s;
158
0
}
159
160
bool
161
str_to_int(const std::string &s, int &val)
162
0
{
163
0
    for (const char &ch : s) {
164
0
        if ((ch < '0') || (ch > '9')) {
165
0
            return false;
166
0
        }
167
0
    }
168
0
    try {
169
0
        val = std::stoi(s);
170
0
    } catch (std::out_of_range const &ex) {
171
0
        return false;
172
0
    }
173
0
    return true;
174
0
}
175
176
bool
177
is_slash(char c)
178
0
{
179
0
    return (c == '/') || (c == '\\');
180
0
}
181
182
} // namespace rnp
183
184
#ifdef _WIN32
185
std::wstring
186
wstr_from_utf8(const char *s)
187
{
188
    std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> utf8conv;
189
    return utf8conv.from_bytes(s);
190
}
191
192
std::wstring
193
wstr_from_utf8(const char *first, const char *last)
194
{
195
    std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> utf8conv;
196
    return utf8conv.from_bytes(first, last);
197
}
198
199
std::wstring
200
wstr_from_utf8(const std::string &s)
201
{
202
    return wstr_from_utf8(s.c_str());
203
}
204
205
std::string
206
wstr_to_utf8(const wchar_t *ws)
207
{
208
    std::wstring_convert<std::codecvt_utf8_utf16<wchar_t>> utf8conv;
209
    return utf8conv.to_bytes(ws);
210
}
211
212
std::string
213
wstr_to_utf8(const std::wstring &ws)
214
{
215
    return wstr_to_utf8(ws.c_str());
216
}
217
#endif