UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
string_view_utils.hpp
Go to the documentation of this file.
1
5/*
6 * Copyright (c) 2022 CESNET z.s.p.o.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, is permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 *
20 * 3. Neither the name of CESNET nor the names of its contributors may be
21 * used to endorse or promote products derived from this software without
22 * specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS
25 * "AS IS" AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING,
26 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
27 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
28 * EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
29 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
30 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
34 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
35 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 */
37
38#ifndef STRING_VIEW_UTILS_183e2da27fe9
39#define STRING_VIEW_UTILS_183e2da27fe9
40
41#include <string>
42#include <string_view>
43#include <type_traits>
44#include <utility>
45#include <stdlib.h>
46#include <ctype.h>
47
66std::string_view tokenize(std::string_view& str, char delim, char quot = '\0');
67
68inline bool sv_contains(std::string_view haystack, std::string_view needle){
69 return haystack.find(needle) != std::string_view::npos;
70}
71
72inline bool sv_is_prefix(std::string_view haystack, std::string_view needle){
73 return haystack.compare(0, needle.length(), needle) == 0;
74}
75
76inline std::string_view sv_trim_whitespace_front(std::string_view sv){
77 size_t i = 0;
78 while(i < sv.size() && isspace(sv[i])) i++;
79
80 return sv.substr(i);
81}
82
83inline std::string_view sv_trim_whitespace_back(std::string_view sv){
84 size_t i = sv.size();
85 while(i > 0 && isspace(sv[i - 1])) i--;
86
87 return sv.substr(0, i);
88}
89
90inline std::string_view sv_trim_whitespace(std::string_view sv){
92}
93
94/* std::from_chars is c++17, but on major compilers the feature was missing or
95 * partial (no floating point support). This header provides safe fallbacks
96 * if the particular implementation lacks std::from_chars for a given type.
97 *
98 * std::from_chars support:
99 * GCC - partial since v8, floating since v11
100 * Clang - partial since 7
101 */
102#if __has_include(<charconv>)
103#include <charconv>
104
105template<typename T, typename = void>
106struct from_chars_available : std::false_type { };
107
108template<typename T>
109struct from_chars_available<T,
110 std::void_t<decltype(std::from_chars(std::declval<const char *>(), std::declval<const char *>(), std::declval<T&>()))>>
111 : std::true_type { };
112
113template<typename T>
114inline constexpr bool from_chars_available_v = from_chars_available<T>::value;
115
116template<typename T, std::enable_if_t<from_chars_available_v<T>, bool> = true,
117 std::enable_if_t<!std::is_floating_point_v<T>, bool> = true>
118bool parse_num(std::string_view sv, T& res, int base = 10){
119 return !sv.empty() && std::from_chars(sv.begin(), sv.end(), res, base).ec == std::errc();
120}
121
122template<typename T, std::enable_if_t<from_chars_available_v<T>, bool> = true,
123 std::enable_if_t<std::is_floating_point_v<T>, bool> = true>
124bool parse_num(std::string_view sv, T& res){
125 return !sv.empty() && std::from_chars(sv.begin(), sv.end(), res).ec == std::errc();
126}
127
128#else
129
130template<typename T>
131inline constexpr bool from_chars_available_v = false;
132
133#endif // has_include(<charconv>)
134
135template<typename T, auto convert, typename... Args>
136bool parse_num_fallback_impl(std::string_view sv, T& res, Args... args){
137 if(sv.empty())
138 return false;
139
140 std::string tmp(sv);
141 const char *c_str_ptr = tmp.c_str();
142 char *endptr = nullptr;
143 T num;
144
145 num = convert(c_str_ptr, &endptr, args...);
146
147 if(c_str_ptr == endptr)
148 return false;
149
150 res = num;
151 return true;
152}
153
154template<typename T,
155 std::enable_if_t<!from_chars_available_v<T>, bool> = true,
156 std::enable_if_t<std::is_integral_v<T>, bool> = true>
157bool parse_num(std::string_view sv, T& res, int base = 10){
158 return parse_num_fallback_impl<T, strtol>(sv, res, base);
159}
160
161template<typename T,
162 std::enable_if_t<!from_chars_available_v<T>, bool> = true,
163 std::enable_if_t<std::is_same_v<T, double>, bool> = true>
164bool parse_num(std::string_view sv, T& res){
166}
167
168template<typename T,
169 std::enable_if_t<!from_chars_available_v<T>, bool> = true,
170 std::enable_if_t<std::is_same_v<T, float>, bool> = true>
171bool parse_num(std::string_view sv, T& res){
173}
174
175#endif
convert_t convert
bool parse_num_fallback_impl(std::string_view sv, T &res, Args... args)
std::string_view sv_trim_whitespace(std::string_view sv)
bool sv_contains(std::string_view haystack, std::string_view needle)
std::string_view tokenize(std::string_view &str, char delim, char quot='\0')
Tokenizer for string_view.
bool parse_num(std::string_view sv, T &res, int base=10)
constexpr bool from_chars_available_v
bool sv_is_prefix(std::string_view haystack, std::string_view needle)
std::string_view sv_trim_whitespace_back(std::string_view sv)
std::string_view sv_trim_whitespace_front(std::string_view sv)