Electroneum
Loading...
Searching...
No Matches
string_tools.h
Go to the documentation of this file.
1// Copyright (c) 2006-2013, Andrey N. Sabelnikov, www.sabelnikov.net
2// All rights reserved.
3//
4// Redistribution and use in source and binary forms, with or without
5// modification, are permitted provided that the following conditions are met:
6// * Redistributions of source code must retain the above copyright
7// notice, this list of conditions and the following disclaimer.
8// * Redistributions in binary form must reproduce the above copyright
9// notice, this list of conditions and the following disclaimer in the
10// documentation and/or other materials provided with the distribution.
11// * Neither the name of the Andrey N. Sabelnikov nor the
12// names of its contributors may be used to endorse or promote products
13// derived from this software without specific prior written permission.
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 BE LIABLE FOR ANY
19// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25//
26
27
28
29#ifndef _STRING_TOOLS_H_
30#define _STRING_TOOLS_H_
31
32// Previously pulled in by ASIO, further cleanup still required ...
33#ifdef _WIN32
34# include <winsock2.h>
35# include <windows.h>
36#endif
37
38#include <string.h>
39#include <locale>
40#include <cstdlib>
41#include <string>
42#include <type_traits>
43#include <boost/lexical_cast.hpp>
44#include <boost/algorithm/string/predicate.hpp>
45#include "misc_log_ex.h"
47#include "hex.h"
48#include "memwipe.h"
49#include "mlocker.h"
50#include "span.h"
51#include "warnings.h"
52
53
54#ifndef OUT
55 #define OUT
56#endif
57
58#ifdef WINDOWS_PLATFORM
59#pragma comment (lib, "Rpcrt4.lib")
60#endif
61
62static const constexpr unsigned char isx[256] =
63{
64 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
65 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
66 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
67 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
68 0xff, 10, 11, 12, 13, 14, 15, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
69 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
70 0xff, 10, 11, 12, 13, 14, 15, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
71 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
72 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
73 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
74 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
75 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
76 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
77 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
78 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
79 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
80};
81
82namespace epee
83{
84namespace string_tools
85{
86 //----------------------------------------------------------------------------
87 inline std::string buff_to_hex_nodelimer(const std::string& src)
88 {
90 }
91 //----------------------------------------------------------------------------
93 {
94 if (s.size() != res.size() * 2)
95 return false;
96
97 unsigned char *dst = (unsigned char *)&res[0];
98 const unsigned char *src = (const unsigned char *)s.data();
99 for(size_t i = 0; i < s.size(); i += 2)
100 {
101 int tmp = *src++;
102 tmp = isx[tmp];
103 if (tmp == 0xff) return false;
104 int t2 = *src++;
105 t2 = isx[t2];
106 if (t2 == 0xff) return false;
107 *dst++ = (tmp << 4) | t2;
108 }
109
110 return true;
111 }
112 //----------------------------------------------------------------------------
113 inline bool parse_hexstr_to_binbuff(const std::string& s, std::string& res)
114 {
115 if (s.size() & 1)
116 return false;
117 res.resize(s.size() / 2);
118 epee::span<char> rspan((char*)&res[0], res.size());
119 return parse_hexstr_to_binbuff(epee::to_span(s), rspan);
120 }
121 //----------------------------------------------------------------------------
123DISABLE_GCC_WARNING(maybe-uninitialized)
124 template<class XType>
125 inline bool get_xtype_from_string(OUT XType& val, const std::string& str_id)
126 {
127 if (std::is_integral<XType>::value && !std::numeric_limits<XType>::is_signed && !std::is_same<XType, bool>::value)
128 {
129 for (char c : str_id)
130 {
132 return false;
133 }
134 }
135
136 try
137 {
138 val = boost::lexical_cast<XType>(str_id);
139 return true;
140 }
141 catch(const std::exception& /*e*/)
142 {
143 //const char* pmsg = e.what();
144 return false;
145 }
146 catch(...)
147 {
148 return false;
149 }
150
151 return true;
152 }
154 //----------------------------------------------------------------------------
155 template<class XType>
156 inline bool xtype_to_string(const XType& val, std::string& str)
157 {
158 try
159 {
160 str = boost::lexical_cast<std::string>(val);
161 }
162 catch(...)
163 {
164 return false;
165 }
166
167 return true;
168 }
169 //----------------------------------------------------------------------------
170 std::string get_ip_string_from_int32(uint32_t ip);
171 //----------------------------------------------------------------------------
172 bool get_ip_int32_from_string(uint32_t& ip, const std::string& ip_str);
173 //----------------------------------------------------------------------------
174 inline bool parse_peer_from_string(uint32_t& ip, uint16_t& port, const std::string& addres)
175 {
176 //parse ip and address
177 std::string::size_type p = addres.find(':');
178 std::string ip_str, port_str;
179 if(p == std::string::npos)
180 {
181 port = 0;
182 ip_str = addres;
183 }
184 else
185 {
186 ip_str = addres.substr(0, p);
187 port_str = addres.substr(p+1, addres.size());
188 }
189
190 if(!get_ip_int32_from_string(ip, ip_str))
191 {
192 return false;
193 }
194
195 if(p != std::string::npos && !get_xtype_from_string(port, port_str))
196 {
197 return false;
198 }
199 return true;
200 }
201
202 inline std::string num_to_string_fast(int64_t val)
203 {
204 /*
205 char buff[30] = {0};
206 i64toa_s(val, buff, sizeof(buff)-1, 10);
207 return buff;*/
208 return boost::lexical_cast<std::string>(val);
209 }
210 //----------------------------------------------------------------------------
211 inline std::string to_string_hex(uint32_t val)
212 {
213 std::stringstream ss;
214 ss << std::hex << val;
215 std::string s;
216 ss >> s;
217 return s;
218 }
219 //----------------------------------------------------------------------------
220
221 inline bool compare_no_case(const std::string& str1, const std::string& str2)
222 {
223
224 return !boost::iequals(str1, str2);
225 }
226 //----------------------------------------------------------------------------
227 inline std::string& get_current_module_name()
228 {
229 static std::string module_name;
230 return module_name;
231 }
232 //----------------------------------------------------------------------------
233 inline std::string& get_current_module_folder()
234 {
235 static std::string module_folder;
236 return module_folder;
237 }
238 //----------------------------------------------------------------------------
239#ifdef _WIN32
240 inline std::string get_current_module_path()
241 {
242 char pname [5000] = {0};
243 GetModuleFileNameA( NULL, pname, sizeof(pname));
244 pname[sizeof(pname)-1] = 0; //be happy ;)
245 return pname;
246 }
247#endif
248 //----------------------------------------------------------------------------
249 inline bool set_module_name_and_folder(const std::string& path_to_process_)
250 {
251 std::string path_to_process = path_to_process_;
252#ifdef _WIN32
253 path_to_process = get_current_module_path();
254#endif
255 std::string::size_type a = path_to_process.rfind( '\\' );
256 if(a == std::string::npos )
257 {
258 a = path_to_process.rfind( '/' );
259 }
260 if ( a != std::string::npos )
261 {
262 get_current_module_name() = path_to_process.substr(a+1, path_to_process.size());
263 get_current_module_folder() = path_to_process.substr(0, a);
264 return true;
265 }else
266 return false;
267
268 }
269
270 //----------------------------------------------------------------------------
271 inline bool trim_left(std::string& str)
272 {
273 for(std::string::iterator it = str.begin(); it!= str.end() && isspace(static_cast<unsigned char>(*it));)
274 str.erase(str.begin());
275
276 return true;
277 }
278 //----------------------------------------------------------------------------
279 inline bool trim_right(std::string& str)
280 {
281
282 for(std::string::reverse_iterator it = str.rbegin(); it!= str.rend() && isspace(static_cast<unsigned char>(*it));)
283 str.erase( --((it++).base()));
284
285 return true;
286 }
287 //----------------------------------------------------------------------------
288 inline std::string& trim(std::string& str)
289 {
290
291 trim_left(str);
292 trim_right(str);
293 return str;
294 }
295 //----------------------------------------------------------------------------
296 inline std::string trim(const std::string& str_)
297 {
298 std::string str = str_;
299 trim_left(str);
300 trim_right(str);
301 return str;
302 }
303 //----------------------------------------------------------------------------
304 inline std::string pad_string(std::string s, size_t n, char c = ' ', bool prepend = false)
305 {
306 if (s.size() < n)
307 {
308 if (prepend)
309 s = std::string(n - s.size(), c) + s;
310 else
311 s.append(n - s.size(), c);
312 }
313 return s;
314 }
315 //----------------------------------------------------------------------------
316 template<class t_pod_type>
317 std::string pod_to_hex(const t_pod_type& s)
318 {
319 static_assert(std::is_standard_layout<t_pod_type>(), "expected standard layout type");
320 return to_hex::string(as_byte_span(s));
321 }
322 //----------------------------------------------------------------------------
323 template<class t_pod_type>
324 bool hex_to_pod(const std::string& hex_str, t_pod_type& s)
325 {
326 static_assert(std::is_pod<t_pod_type>::value, "expected pod type");
327 if(sizeof(s)*2 != hex_str.size())
328 return false;
329 epee::span<char> rspan((char*)&s, sizeof(s));
330 return parse_hexstr_to_binbuff(epee::to_span(hex_str), rspan);
331 }
332 //----------------------------------------------------------------------------
333 template<class t_pod_type>
334 bool hex_to_pod(const std::string& hex_str, tools::scrubbed<t_pod_type>& s)
335 {
336 return hex_to_pod(hex_str, unwrap(s));
337 }
338 //----------------------------------------------------------------------------
339 template<class t_pod_type>
340 bool hex_to_pod(const std::string& hex_str, epee::mlocked<t_pod_type>& s)
341 {
342 return hex_to_pod(hex_str, unwrap(s));
343 }
344 //----------------------------------------------------------------------------
345 bool validate_hex(uint64_t length, const std::string& str);
346 //----------------------------------------------------------------------------
347 inline std::string get_extension(const std::string& str)
348 {
349 std::string res;
350 std::string::size_type pos = str.rfind('.');
351 if(std::string::npos == pos)
352 return res;
353
354 res = str.substr(pos+1, str.size()-pos);
355 return res;
356 }
357 //----------------------------------------------------------------------------
358 inline std::string cut_off_extension(const std::string& str)
359 {
360 std::string res;
361 std::string::size_type pos = str.rfind('.');
362 if(std::string::npos == pos)
363 return str;
364
365 res = str.substr(0, pos);
366 return res;
367 }
368 //----------------------------------------------------------------------------
369#ifdef _WIN32
370 inline std::wstring utf8_to_utf16(const std::string& str)
371 {
372 if (str.empty())
373 return {};
374 int wstr_size = MultiByteToWideChar(CP_UTF8, 0, &str[0], str.size(), NULL, 0);
375 if (wstr_size == 0)
376 {
377 throw std::runtime_error(std::error_code(GetLastError(), std::system_category()).message());
378 }
379 std::wstring wstr(wstr_size, wchar_t{});
380 if (!MultiByteToWideChar(CP_UTF8, 0, &str[0], str.size(), &wstr[0], wstr_size))
381 {
382 throw std::runtime_error(std::error_code(GetLastError(), std::system_category()).message());
383 }
384 return wstr;
385 }
386 inline std::string utf16_to_utf8(const std::wstring& wstr)
387 {
388 if (wstr.empty())
389 return {};
390 int str_size = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], wstr.size(), NULL, 0, NULL, NULL);
391 if (str_size == 0)
392 {
393 throw std::runtime_error(std::error_code(GetLastError(), std::system_category()).message());
394 }
395 std::string str(str_size, char{});
396 if (!WideCharToMultiByte(CP_UTF8, 0, &wstr[0], wstr.size(), &str[0], str_size, NULL, NULL))
397 {
398 throw std::runtime_error(std::error_code(GetLastError(), std::system_category()).message());
399 }
400 return str;
401 }
402#endif
403}
404}
405#endif //_STRING_TOOLS_H_
Non-owning sequence of data. Does not deep copy.
Definition span.h:57
constexpr std::size_t size() const noexcept
Definition span.h:111
constexpr pointer data() const noexcept
Definition span.h:110
std::string message("Message requiring signing")
const char * res
bool set_module_name_and_folder(const std::string &path_to_process_)
bool parse_hexstr_to_binbuff(const epee::span< const char > s, epee::span< char > &res)
std::string cut_off_extension(const std::string &str)
std::string pod_to_hex(const t_pod_type &s)
std::string get_extension(const std::string &str)
bool hex_to_pod(const std::string &hex_str, t_pod_type &s)
std::string & get_current_module_name()
POP_WARNINGS bool xtype_to_string(const XType &val, std::string &str)
std::string get_ip_string_from_int32(uint32_t ip)
PUSH_WARNINGS bool get_xtype_from_string(OUT XType &val, const std::string &str_id)
bool trim_left(std::string &str)
bool get_ip_int32_from_string(uint32_t &ip, const std::string &ip_str)
std::string pad_string(std::string s, size_t n, char c=' ', bool prepend=false)
std::string & get_current_module_folder()
std::string to_string_hex(uint32_t val)
bool validate_hex(uint64_t length, const std::string &str)
bool compare_no_case(const std::string &str1, const std::string &str2)
std::string buff_to_hex_nodelimer(const std::string &src)
std::string num_to_string_fast(int64_t val)
bool parse_peer_from_string(uint32_t &ip, uint16_t &port, const std::string &addres)
std::string & trim(std::string &str)
bool trim_right(std::string &str)
span< const std::uint8_t > to_byte_span(const span< const T > src) noexcept
Definition span.h:145
T & unwrap(mlocked< T > &src)
Definition mlocker.h:80
constexpr span< const typename T::value_type > to_span(const T &src)
Definition span.h:123
span< const std::uint8_t > as_byte_span(const T &src) noexcept
Definition span.h:153
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition pointer.h:1124
t2
Definition pow22523.h:103
unsigned short uint16_t
Definition stdint.h:125
signed __int64 int64_t
Definition stdint.h:135
unsigned int uint32_t
Definition stdint.h:126
unsigned __int64 uint64_t
Definition stdint.h:136
#define OUT
static std::string string(const span< const std::uint8_t > src)
Definition hex.cpp:68
#define DISABLE_GCC_WARNING
Definition warnings.h:24
#define POP_WARNINGS
Definition warnings.h:17
#define PUSH_WARNINGS
Definition warnings.h:16