Kodi Development 22.0
for Binary and Script based Add-Ons
 
Loading...
Searching...
No Matches
StringUtils.h
1/*
2 * Copyright (C) 2005-2020 Team Kodi
3 * This file is part of Kodi - https://kodi.tv
4 *
5 * SPDX-License-Identifier: GPL-2.0-or-later
6 * See LICENSES/README.md for more information.
7 */
8
9#pragma once
10
11#ifdef __cplusplus
12
13#if !defined(NOMINMAX)
14#define NOMINMAX
15#endif
16
17#include <algorithm>
18#include <array>
19#include <cassert>
20#include <cinttypes>
21#include <cmath>
22#include <cstdarg>
23#include <cstring>
24#include <iomanip>
25#include <regex>
26#include <sstream>
27#include <string>
28#include <vector>
29
30// # of bytes for initial allocation for printf
31#define FORMAT_BLOCK_SIZE 512
32
33// macros for gcc, clang & others
34#ifndef PARAM1_PRINTF_FORMAT
35#ifdef __GNUC__
36// for use in functions that take printf format string as first parameter and additional printf parameters as second parameter
37// for example: int myprintf(const char* format, ...) PARAM1_PRINTF_FORMAT;
38#define PARAM1_PRINTF_FORMAT __attribute__((format(printf, 1, 2)))
39
40// for use in functions that take printf format string as second parameter and additional printf parameters as third parameter
41// for example: bool log_string(int logLevel, const char* format, ...) PARAM2_PRINTF_FORMAT;
42// note: all non-static class member functions take pointer to class object as hidden first parameter
43#define PARAM2_PRINTF_FORMAT __attribute__((format(printf, 2, 3)))
44
45// for use in functions that take printf format string as third parameter and additional printf parameters as fourth parameter
46// note: all non-static class member functions take pointer to class object as hidden first parameter
47// for example: class A { bool log_string(int logLevel, const char* functionName, const char* format, ...) PARAM3_PRINTF_FORMAT; };
48#define PARAM3_PRINTF_FORMAT __attribute__((format(printf, 3, 4)))
49
50// for use in functions that take printf format string as fourth parameter and additional printf parameters as fifth parameter
51// note: all non-static class member functions take pointer to class object as hidden first parameter
52// for example: class A { bool log_string(int logLevel, const char* functionName, int component, const char* format, ...) PARAM4_PRINTF_FORMAT; };
53#define PARAM4_PRINTF_FORMAT __attribute__((format(printf, 4, 5)))
54#else // ! __GNUC__
55#define PARAM1_PRINTF_FORMAT
56#define PARAM2_PRINTF_FORMAT
57#define PARAM3_PRINTF_FORMAT
58#define PARAM4_PRINTF_FORMAT
59#endif // ! __GNUC__
60#endif // PARAM1_PRINTF_FORMAT
61
62// macros for VC
63// VC check parameters only when "Code Analysis" is called
64#ifndef PRINTF_FORMAT_STRING
65#ifdef _MSC_VER
66#include <sal.h>
67
68// for use in any function that take printf format string and parameters
69// for example: bool log_string(int logLevel, PRINTF_FORMAT_STRING const char* format, ...);
70#define PRINTF_FORMAT_STRING _In_z_ _Printf_format_string_
71
72// specify that parameter must be zero-terminated string
73// for example: void SetName(IN_STRING const char* newName);
74#define IN_STRING _In_z_
75
76// specify that parameter must be zero-terminated string or NULL
77// for example: bool SetAdditionalName(IN_OPT_STRING const char* addName);
78#define IN_OPT_STRING _In_opt_z_
79#else // ! _MSC_VER
80#define PRINTF_FORMAT_STRING
81#define IN_STRING
82#define IN_OPT_STRING
83#endif // ! _MSC_VER
84#endif // PRINTF_FORMAT_STRING
85
86static constexpr wchar_t unicode_lowers[] = {
87 (wchar_t)0x0061, (wchar_t)0x0062, (wchar_t)0x0063, (wchar_t)0x0064, (wchar_t)0x0065,
88 (wchar_t)0x0066, (wchar_t)0x0067, (wchar_t)0x0068, (wchar_t)0x0069, (wchar_t)0x006A,
89 (wchar_t)0x006B, (wchar_t)0x006C, (wchar_t)0x006D, (wchar_t)0x006E, (wchar_t)0x006F,
90 (wchar_t)0x0070, (wchar_t)0x0071, (wchar_t)0x0072, (wchar_t)0x0073, (wchar_t)0x0074,
91 (wchar_t)0x0075, (wchar_t)0x0076, (wchar_t)0x0077, (wchar_t)0x0078, (wchar_t)0x0079,
92 (wchar_t)0x007A, (wchar_t)0x00E0, (wchar_t)0x00E1, (wchar_t)0x00E2, (wchar_t)0x00E3,
93 (wchar_t)0x00E4, (wchar_t)0x00E5, (wchar_t)0x00E6, (wchar_t)0x00E7, (wchar_t)0x00E8,
94 (wchar_t)0x00E9, (wchar_t)0x00EA, (wchar_t)0x00EB, (wchar_t)0x00EC, (wchar_t)0x00ED,
95 (wchar_t)0x00EE, (wchar_t)0x00EF, (wchar_t)0x00F0, (wchar_t)0x00F1, (wchar_t)0x00F2,
96 (wchar_t)0x00F3, (wchar_t)0x00F4, (wchar_t)0x00F5, (wchar_t)0x00F6, (wchar_t)0x00F8,
97 (wchar_t)0x00F9, (wchar_t)0x00FA, (wchar_t)0x00FB, (wchar_t)0x00FC, (wchar_t)0x00FD,
98 (wchar_t)0x00FE, (wchar_t)0x00FF, (wchar_t)0x0101, (wchar_t)0x0103, (wchar_t)0x0105,
99 (wchar_t)0x0107, (wchar_t)0x0109, (wchar_t)0x010B, (wchar_t)0x010D, (wchar_t)0x010F,
100 (wchar_t)0x0111, (wchar_t)0x0113, (wchar_t)0x0115, (wchar_t)0x0117, (wchar_t)0x0119,
101 (wchar_t)0x011B, (wchar_t)0x011D, (wchar_t)0x011F, (wchar_t)0x0121, (wchar_t)0x0123,
102 (wchar_t)0x0125, (wchar_t)0x0127, (wchar_t)0x0129, (wchar_t)0x012B, (wchar_t)0x012D,
103 (wchar_t)0x012F, (wchar_t)0x0131, (wchar_t)0x0133, (wchar_t)0x0135, (wchar_t)0x0137,
104 (wchar_t)0x013A, (wchar_t)0x013C, (wchar_t)0x013E, (wchar_t)0x0140, (wchar_t)0x0142,
105 (wchar_t)0x0144, (wchar_t)0x0146, (wchar_t)0x0148, (wchar_t)0x014B, (wchar_t)0x014D,
106 (wchar_t)0x014F, (wchar_t)0x0151, (wchar_t)0x0153, (wchar_t)0x0155, (wchar_t)0x0157,
107 (wchar_t)0x0159, (wchar_t)0x015B, (wchar_t)0x015D, (wchar_t)0x015F, (wchar_t)0x0161,
108 (wchar_t)0x0163, (wchar_t)0x0165, (wchar_t)0x0167, (wchar_t)0x0169, (wchar_t)0x016B,
109 (wchar_t)0x016D, (wchar_t)0x016F, (wchar_t)0x0171, (wchar_t)0x0173, (wchar_t)0x0175,
110 (wchar_t)0x0177, (wchar_t)0x017A, (wchar_t)0x017C, (wchar_t)0x017E, (wchar_t)0x0183,
111 (wchar_t)0x0185, (wchar_t)0x0188, (wchar_t)0x018C, (wchar_t)0x0192, (wchar_t)0x0199,
112 (wchar_t)0x01A1, (wchar_t)0x01A3, (wchar_t)0x01A5, (wchar_t)0x01A8, (wchar_t)0x01AD,
113 (wchar_t)0x01B0, (wchar_t)0x01B4, (wchar_t)0x01B6, (wchar_t)0x01B9, (wchar_t)0x01BD,
114 (wchar_t)0x01C6, (wchar_t)0x01C9, (wchar_t)0x01CC, (wchar_t)0x01CE, (wchar_t)0x01D0,
115 (wchar_t)0x01D2, (wchar_t)0x01D4, (wchar_t)0x01D6, (wchar_t)0x01D8, (wchar_t)0x01DA,
116 (wchar_t)0x01DC, (wchar_t)0x01DF, (wchar_t)0x01E1, (wchar_t)0x01E3, (wchar_t)0x01E5,
117 (wchar_t)0x01E7, (wchar_t)0x01E9, (wchar_t)0x01EB, (wchar_t)0x01ED, (wchar_t)0x01EF,
118 (wchar_t)0x01F3, (wchar_t)0x01F5, (wchar_t)0x01FB, (wchar_t)0x01FD, (wchar_t)0x01FF,
119 (wchar_t)0x0201, (wchar_t)0x0203, (wchar_t)0x0205, (wchar_t)0x0207, (wchar_t)0x0209,
120 (wchar_t)0x020B, (wchar_t)0x020D, (wchar_t)0x020F, (wchar_t)0x0211, (wchar_t)0x0213,
121 (wchar_t)0x0215, (wchar_t)0x0217, (wchar_t)0x0253, (wchar_t)0x0254, (wchar_t)0x0257,
122 (wchar_t)0x0258, (wchar_t)0x0259, (wchar_t)0x025B, (wchar_t)0x0260, (wchar_t)0x0263,
123 (wchar_t)0x0268, (wchar_t)0x0269, (wchar_t)0x026F, (wchar_t)0x0272, (wchar_t)0x0275,
124 (wchar_t)0x0283, (wchar_t)0x0288, (wchar_t)0x028A, (wchar_t)0x028B, (wchar_t)0x0292,
125 (wchar_t)0x03AC, (wchar_t)0x03AD, (wchar_t)0x03AE, (wchar_t)0x03AF, (wchar_t)0x03B1,
126 (wchar_t)0x03B2, (wchar_t)0x03B3, (wchar_t)0x03B4, (wchar_t)0x03B5, (wchar_t)0x03B6,
127 (wchar_t)0x03B7, (wchar_t)0x03B8, (wchar_t)0x03B9, (wchar_t)0x03BA, (wchar_t)0x03BB,
128 (wchar_t)0x03BC, (wchar_t)0x03BD, (wchar_t)0x03BE, (wchar_t)0x03BF, (wchar_t)0x03C0,
129 (wchar_t)0x03C1, (wchar_t)0x03C3, (wchar_t)0x03C4, (wchar_t)0x03C5, (wchar_t)0x03C6,
130 (wchar_t)0x03C7, (wchar_t)0x03C8, (wchar_t)0x03C9, (wchar_t)0x03CA, (wchar_t)0x03CB,
131 (wchar_t)0x03CC, (wchar_t)0x03CD, (wchar_t)0x03CE, (wchar_t)0x03E3, (wchar_t)0x03E5,
132 (wchar_t)0x03E7, (wchar_t)0x03E9, (wchar_t)0x03EB, (wchar_t)0x03ED, (wchar_t)0x03EF,
133 (wchar_t)0x0430, (wchar_t)0x0431, (wchar_t)0x0432, (wchar_t)0x0433, (wchar_t)0x0434,
134 (wchar_t)0x0435, (wchar_t)0x0436, (wchar_t)0x0437, (wchar_t)0x0438, (wchar_t)0x0439,
135 (wchar_t)0x043A, (wchar_t)0x043B, (wchar_t)0x043C, (wchar_t)0x043D, (wchar_t)0x043E,
136 (wchar_t)0x043F, (wchar_t)0x0440, (wchar_t)0x0441, (wchar_t)0x0442, (wchar_t)0x0443,
137 (wchar_t)0x0444, (wchar_t)0x0445, (wchar_t)0x0446, (wchar_t)0x0447, (wchar_t)0x0448,
138 (wchar_t)0x0449, (wchar_t)0x044A, (wchar_t)0x044B, (wchar_t)0x044C, (wchar_t)0x044D,
139 (wchar_t)0x044E, (wchar_t)0x044F, (wchar_t)0x0451, (wchar_t)0x0452, (wchar_t)0x0453,
140 (wchar_t)0x0454, (wchar_t)0x0455, (wchar_t)0x0456, (wchar_t)0x0457, (wchar_t)0x0458,
141 (wchar_t)0x0459, (wchar_t)0x045A, (wchar_t)0x045B, (wchar_t)0x045C, (wchar_t)0x045E,
142 (wchar_t)0x045F, (wchar_t)0x0461, (wchar_t)0x0463, (wchar_t)0x0465, (wchar_t)0x0467,
143 (wchar_t)0x0469, (wchar_t)0x046B, (wchar_t)0x046D, (wchar_t)0x046F, (wchar_t)0x0471,
144 (wchar_t)0x0473, (wchar_t)0x0475, (wchar_t)0x0477, (wchar_t)0x0479, (wchar_t)0x047B,
145 (wchar_t)0x047D, (wchar_t)0x047F, (wchar_t)0x0481, (wchar_t)0x0491, (wchar_t)0x0493,
146 (wchar_t)0x0495, (wchar_t)0x0497, (wchar_t)0x0499, (wchar_t)0x049B, (wchar_t)0x049D,
147 (wchar_t)0x049F, (wchar_t)0x04A1, (wchar_t)0x04A3, (wchar_t)0x04A5, (wchar_t)0x04A7,
148 (wchar_t)0x04A9, (wchar_t)0x04AB, (wchar_t)0x04AD, (wchar_t)0x04AF, (wchar_t)0x04B1,
149 (wchar_t)0x04B3, (wchar_t)0x04B5, (wchar_t)0x04B7, (wchar_t)0x04B9, (wchar_t)0x04BB,
150 (wchar_t)0x04BD, (wchar_t)0x04BF, (wchar_t)0x04C2, (wchar_t)0x04C4, (wchar_t)0x04C8,
151 (wchar_t)0x04CC, (wchar_t)0x04D1, (wchar_t)0x04D3, (wchar_t)0x04D5, (wchar_t)0x04D7,
152 (wchar_t)0x04D9, (wchar_t)0x04DB, (wchar_t)0x04DD, (wchar_t)0x04DF, (wchar_t)0x04E1,
153 (wchar_t)0x04E3, (wchar_t)0x04E5, (wchar_t)0x04E7, (wchar_t)0x04E9, (wchar_t)0x04EB,
154 (wchar_t)0x04EF, (wchar_t)0x04F1, (wchar_t)0x04F3, (wchar_t)0x04F5, (wchar_t)0x04F9,
155 (wchar_t)0x0561, (wchar_t)0x0562, (wchar_t)0x0563, (wchar_t)0x0564, (wchar_t)0x0565,
156 (wchar_t)0x0566, (wchar_t)0x0567, (wchar_t)0x0568, (wchar_t)0x0569, (wchar_t)0x056A,
157 (wchar_t)0x056B, (wchar_t)0x056C, (wchar_t)0x056D, (wchar_t)0x056E, (wchar_t)0x056F,
158 (wchar_t)0x0570, (wchar_t)0x0571, (wchar_t)0x0572, (wchar_t)0x0573, (wchar_t)0x0574,
159 (wchar_t)0x0575, (wchar_t)0x0576, (wchar_t)0x0577, (wchar_t)0x0578, (wchar_t)0x0579,
160 (wchar_t)0x057A, (wchar_t)0x057B, (wchar_t)0x057C, (wchar_t)0x057D, (wchar_t)0x057E,
161 (wchar_t)0x057F, (wchar_t)0x0580, (wchar_t)0x0581, (wchar_t)0x0582, (wchar_t)0x0583,
162 (wchar_t)0x0584, (wchar_t)0x0585, (wchar_t)0x0586, (wchar_t)0x10D0, (wchar_t)0x10D1,
163 (wchar_t)0x10D2, (wchar_t)0x10D3, (wchar_t)0x10D4, (wchar_t)0x10D5, (wchar_t)0x10D6,
164 (wchar_t)0x10D7, (wchar_t)0x10D8, (wchar_t)0x10D9, (wchar_t)0x10DA, (wchar_t)0x10DB,
165 (wchar_t)0x10DC, (wchar_t)0x10DD, (wchar_t)0x10DE, (wchar_t)0x10DF, (wchar_t)0x10E0,
166 (wchar_t)0x10E1, (wchar_t)0x10E2, (wchar_t)0x10E3, (wchar_t)0x10E4, (wchar_t)0x10E5,
167 (wchar_t)0x10E6, (wchar_t)0x10E7, (wchar_t)0x10E8, (wchar_t)0x10E9, (wchar_t)0x10EA,
168 (wchar_t)0x10EB, (wchar_t)0x10EC, (wchar_t)0x10ED, (wchar_t)0x10EE, (wchar_t)0x10EF,
169 (wchar_t)0x10F0, (wchar_t)0x10F1, (wchar_t)0x10F2, (wchar_t)0x10F3, (wchar_t)0x10F4,
170 (wchar_t)0x10F5, (wchar_t)0x1E01, (wchar_t)0x1E03, (wchar_t)0x1E05, (wchar_t)0x1E07,
171 (wchar_t)0x1E09, (wchar_t)0x1E0B, (wchar_t)0x1E0D, (wchar_t)0x1E0F, (wchar_t)0x1E11,
172 (wchar_t)0x1E13, (wchar_t)0x1E15, (wchar_t)0x1E17, (wchar_t)0x1E19, (wchar_t)0x1E1B,
173 (wchar_t)0x1E1D, (wchar_t)0x1E1F, (wchar_t)0x1E21, (wchar_t)0x1E23, (wchar_t)0x1E25,
174 (wchar_t)0x1E27, (wchar_t)0x1E29, (wchar_t)0x1E2B, (wchar_t)0x1E2D, (wchar_t)0x1E2F,
175 (wchar_t)0x1E31, (wchar_t)0x1E33, (wchar_t)0x1E35, (wchar_t)0x1E37, (wchar_t)0x1E39,
176 (wchar_t)0x1E3B, (wchar_t)0x1E3D, (wchar_t)0x1E3F, (wchar_t)0x1E41, (wchar_t)0x1E43,
177 (wchar_t)0x1E45, (wchar_t)0x1E47, (wchar_t)0x1E49, (wchar_t)0x1E4B, (wchar_t)0x1E4D,
178 (wchar_t)0x1E4F, (wchar_t)0x1E51, (wchar_t)0x1E53, (wchar_t)0x1E55, (wchar_t)0x1E57,
179 (wchar_t)0x1E59, (wchar_t)0x1E5B, (wchar_t)0x1E5D, (wchar_t)0x1E5F, (wchar_t)0x1E61,
180 (wchar_t)0x1E63, (wchar_t)0x1E65, (wchar_t)0x1E67, (wchar_t)0x1E69, (wchar_t)0x1E6B,
181 (wchar_t)0x1E6D, (wchar_t)0x1E6F, (wchar_t)0x1E71, (wchar_t)0x1E73, (wchar_t)0x1E75,
182 (wchar_t)0x1E77, (wchar_t)0x1E79, (wchar_t)0x1E7B, (wchar_t)0x1E7D, (wchar_t)0x1E7F,
183 (wchar_t)0x1E81, (wchar_t)0x1E83, (wchar_t)0x1E85, (wchar_t)0x1E87, (wchar_t)0x1E89,
184 (wchar_t)0x1E8B, (wchar_t)0x1E8D, (wchar_t)0x1E8F, (wchar_t)0x1E91, (wchar_t)0x1E93,
185 (wchar_t)0x1E95, (wchar_t)0x1EA1, (wchar_t)0x1EA3, (wchar_t)0x1EA5, (wchar_t)0x1EA7,
186 (wchar_t)0x1EA9, (wchar_t)0x1EAB, (wchar_t)0x1EAD, (wchar_t)0x1EAF, (wchar_t)0x1EB1,
187 (wchar_t)0x1EB3, (wchar_t)0x1EB5, (wchar_t)0x1EB7, (wchar_t)0x1EB9, (wchar_t)0x1EBB,
188 (wchar_t)0x1EBD, (wchar_t)0x1EBF, (wchar_t)0x1EC1, (wchar_t)0x1EC3, (wchar_t)0x1EC5,
189 (wchar_t)0x1EC7, (wchar_t)0x1EC9, (wchar_t)0x1ECB, (wchar_t)0x1ECD, (wchar_t)0x1ECF,
190 (wchar_t)0x1ED1, (wchar_t)0x1ED3, (wchar_t)0x1ED5, (wchar_t)0x1ED7, (wchar_t)0x1ED9,
191 (wchar_t)0x1EDB, (wchar_t)0x1EDD, (wchar_t)0x1EDF, (wchar_t)0x1EE1, (wchar_t)0x1EE3,
192 (wchar_t)0x1EE5, (wchar_t)0x1EE7, (wchar_t)0x1EE9, (wchar_t)0x1EEB, (wchar_t)0x1EED,
193 (wchar_t)0x1EEF, (wchar_t)0x1EF1, (wchar_t)0x1EF3, (wchar_t)0x1EF5, (wchar_t)0x1EF7,
194 (wchar_t)0x1EF9, (wchar_t)0x1F00, (wchar_t)0x1F01, (wchar_t)0x1F02, (wchar_t)0x1F03,
195 (wchar_t)0x1F04, (wchar_t)0x1F05, (wchar_t)0x1F06, (wchar_t)0x1F07, (wchar_t)0x1F10,
196 (wchar_t)0x1F11, (wchar_t)0x1F12, (wchar_t)0x1F13, (wchar_t)0x1F14, (wchar_t)0x1F15,
197 (wchar_t)0x1F20, (wchar_t)0x1F21, (wchar_t)0x1F22, (wchar_t)0x1F23, (wchar_t)0x1F24,
198 (wchar_t)0x1F25, (wchar_t)0x1F26, (wchar_t)0x1F27, (wchar_t)0x1F30, (wchar_t)0x1F31,
199 (wchar_t)0x1F32, (wchar_t)0x1F33, (wchar_t)0x1F34, (wchar_t)0x1F35, (wchar_t)0x1F36,
200 (wchar_t)0x1F37, (wchar_t)0x1F40, (wchar_t)0x1F41, (wchar_t)0x1F42, (wchar_t)0x1F43,
201 (wchar_t)0x1F44, (wchar_t)0x1F45, (wchar_t)0x1F51, (wchar_t)0x1F53, (wchar_t)0x1F55,
202 (wchar_t)0x1F57, (wchar_t)0x1F60, (wchar_t)0x1F61, (wchar_t)0x1F62, (wchar_t)0x1F63,
203 (wchar_t)0x1F64, (wchar_t)0x1F65, (wchar_t)0x1F66, (wchar_t)0x1F67, (wchar_t)0x1F80,
204 (wchar_t)0x1F81, (wchar_t)0x1F82, (wchar_t)0x1F83, (wchar_t)0x1F84, (wchar_t)0x1F85,
205 (wchar_t)0x1F86, (wchar_t)0x1F87, (wchar_t)0x1F90, (wchar_t)0x1F91, (wchar_t)0x1F92,
206 (wchar_t)0x1F93, (wchar_t)0x1F94, (wchar_t)0x1F95, (wchar_t)0x1F96, (wchar_t)0x1F97,
207 (wchar_t)0x1FA0, (wchar_t)0x1FA1, (wchar_t)0x1FA2, (wchar_t)0x1FA3, (wchar_t)0x1FA4,
208 (wchar_t)0x1FA5, (wchar_t)0x1FA6, (wchar_t)0x1FA7, (wchar_t)0x1FB0, (wchar_t)0x1FB1,
209 (wchar_t)0x1FD0, (wchar_t)0x1FD1, (wchar_t)0x1FE0, (wchar_t)0x1FE1, (wchar_t)0x24D0,
210 (wchar_t)0x24D1, (wchar_t)0x24D2, (wchar_t)0x24D3, (wchar_t)0x24D4, (wchar_t)0x24D5,
211 (wchar_t)0x24D6, (wchar_t)0x24D7, (wchar_t)0x24D8, (wchar_t)0x24D9, (wchar_t)0x24DA,
212 (wchar_t)0x24DB, (wchar_t)0x24DC, (wchar_t)0x24DD, (wchar_t)0x24DE, (wchar_t)0x24DF,
213 (wchar_t)0x24E0, (wchar_t)0x24E1, (wchar_t)0x24E2, (wchar_t)0x24E3, (wchar_t)0x24E4,
214 (wchar_t)0x24E5, (wchar_t)0x24E6, (wchar_t)0x24E7, (wchar_t)0x24E8, (wchar_t)0x24E9,
215 (wchar_t)0xFF41, (wchar_t)0xFF42, (wchar_t)0xFF43, (wchar_t)0xFF44, (wchar_t)0xFF45,
216 (wchar_t)0xFF46, (wchar_t)0xFF47, (wchar_t)0xFF48, (wchar_t)0xFF49, (wchar_t)0xFF4A,
217 (wchar_t)0xFF4B, (wchar_t)0xFF4C, (wchar_t)0xFF4D, (wchar_t)0xFF4E, (wchar_t)0xFF4F,
218 (wchar_t)0xFF50, (wchar_t)0xFF51, (wchar_t)0xFF52, (wchar_t)0xFF53, (wchar_t)0xFF54,
219 (wchar_t)0xFF55, (wchar_t)0xFF56, (wchar_t)0xFF57, (wchar_t)0xFF58, (wchar_t)0xFF59,
220 (wchar_t)0xFF5A};
221
222static const wchar_t unicode_uppers[] = {
223 (wchar_t)0x0041, (wchar_t)0x0042, (wchar_t)0x0043, (wchar_t)0x0044, (wchar_t)0x0045,
224 (wchar_t)0x0046, (wchar_t)0x0047, (wchar_t)0x0048, (wchar_t)0x0049, (wchar_t)0x004A,
225 (wchar_t)0x004B, (wchar_t)0x004C, (wchar_t)0x004D, (wchar_t)0x004E, (wchar_t)0x004F,
226 (wchar_t)0x0050, (wchar_t)0x0051, (wchar_t)0x0052, (wchar_t)0x0053, (wchar_t)0x0054,
227 (wchar_t)0x0055, (wchar_t)0x0056, (wchar_t)0x0057, (wchar_t)0x0058, (wchar_t)0x0059,
228 (wchar_t)0x005A, (wchar_t)0x00C0, (wchar_t)0x00C1, (wchar_t)0x00C2, (wchar_t)0x00C3,
229 (wchar_t)0x00C4, (wchar_t)0x00C5, (wchar_t)0x00C6, (wchar_t)0x00C7, (wchar_t)0x00C8,
230 (wchar_t)0x00C9, (wchar_t)0x00CA, (wchar_t)0x00CB, (wchar_t)0x00CC, (wchar_t)0x00CD,
231 (wchar_t)0x00CE, (wchar_t)0x00CF, (wchar_t)0x00D0, (wchar_t)0x00D1, (wchar_t)0x00D2,
232 (wchar_t)0x00D3, (wchar_t)0x00D4, (wchar_t)0x00D5, (wchar_t)0x00D6, (wchar_t)0x00D8,
233 (wchar_t)0x00D9, (wchar_t)0x00DA, (wchar_t)0x00DB, (wchar_t)0x00DC, (wchar_t)0x00DD,
234 (wchar_t)0x00DE, (wchar_t)0x0178, (wchar_t)0x0100, (wchar_t)0x0102, (wchar_t)0x0104,
235 (wchar_t)0x0106, (wchar_t)0x0108, (wchar_t)0x010A, (wchar_t)0x010C, (wchar_t)0x010E,
236 (wchar_t)0x0110, (wchar_t)0x0112, (wchar_t)0x0114, (wchar_t)0x0116, (wchar_t)0x0118,
237 (wchar_t)0x011A, (wchar_t)0x011C, (wchar_t)0x011E, (wchar_t)0x0120, (wchar_t)0x0122,
238 (wchar_t)0x0124, (wchar_t)0x0126, (wchar_t)0x0128, (wchar_t)0x012A, (wchar_t)0x012C,
239 (wchar_t)0x012E, (wchar_t)0x0049, (wchar_t)0x0132, (wchar_t)0x0134, (wchar_t)0x0136,
240 (wchar_t)0x0139, (wchar_t)0x013B, (wchar_t)0x013D, (wchar_t)0x013F, (wchar_t)0x0141,
241 (wchar_t)0x0143, (wchar_t)0x0145, (wchar_t)0x0147, (wchar_t)0x014A, (wchar_t)0x014C,
242 (wchar_t)0x014E, (wchar_t)0x0150, (wchar_t)0x0152, (wchar_t)0x0154, (wchar_t)0x0156,
243 (wchar_t)0x0158, (wchar_t)0x015A, (wchar_t)0x015C, (wchar_t)0x015E, (wchar_t)0x0160,
244 (wchar_t)0x0162, (wchar_t)0x0164, (wchar_t)0x0166, (wchar_t)0x0168, (wchar_t)0x016A,
245 (wchar_t)0x016C, (wchar_t)0x016E, (wchar_t)0x0170, (wchar_t)0x0172, (wchar_t)0x0174,
246 (wchar_t)0x0176, (wchar_t)0x0179, (wchar_t)0x017B, (wchar_t)0x017D, (wchar_t)0x0182,
247 (wchar_t)0x0184, (wchar_t)0x0187, (wchar_t)0x018B, (wchar_t)0x0191, (wchar_t)0x0198,
248 (wchar_t)0x01A0, (wchar_t)0x01A2, (wchar_t)0x01A4, (wchar_t)0x01A7, (wchar_t)0x01AC,
249 (wchar_t)0x01AF, (wchar_t)0x01B3, (wchar_t)0x01B5, (wchar_t)0x01B8, (wchar_t)0x01BC,
250 (wchar_t)0x01C4, (wchar_t)0x01C7, (wchar_t)0x01CA, (wchar_t)0x01CD, (wchar_t)0x01CF,
251 (wchar_t)0x01D1, (wchar_t)0x01D3, (wchar_t)0x01D5, (wchar_t)0x01D7, (wchar_t)0x01D9,
252 (wchar_t)0x01DB, (wchar_t)0x01DE, (wchar_t)0x01E0, (wchar_t)0x01E2, (wchar_t)0x01E4,
253 (wchar_t)0x01E6, (wchar_t)0x01E8, (wchar_t)0x01EA, (wchar_t)0x01EC, (wchar_t)0x01EE,
254 (wchar_t)0x01F1, (wchar_t)0x01F4, (wchar_t)0x01FA, (wchar_t)0x01FC, (wchar_t)0x01FE,
255 (wchar_t)0x0200, (wchar_t)0x0202, (wchar_t)0x0204, (wchar_t)0x0206, (wchar_t)0x0208,
256 (wchar_t)0x020A, (wchar_t)0x020C, (wchar_t)0x020E, (wchar_t)0x0210, (wchar_t)0x0212,
257 (wchar_t)0x0214, (wchar_t)0x0216, (wchar_t)0x0181, (wchar_t)0x0186, (wchar_t)0x018A,
258 (wchar_t)0x018E, (wchar_t)0x018F, (wchar_t)0x0190, (wchar_t)0x0193, (wchar_t)0x0194,
259 (wchar_t)0x0197, (wchar_t)0x0196, (wchar_t)0x019C, (wchar_t)0x019D, (wchar_t)0x019F,
260 (wchar_t)0x01A9, (wchar_t)0x01AE, (wchar_t)0x01B1, (wchar_t)0x01B2, (wchar_t)0x01B7,
261 (wchar_t)0x0386, (wchar_t)0x0388, (wchar_t)0x0389, (wchar_t)0x038A, (wchar_t)0x0391,
262 (wchar_t)0x0392, (wchar_t)0x0393, (wchar_t)0x0394, (wchar_t)0x0395, (wchar_t)0x0396,
263 (wchar_t)0x0397, (wchar_t)0x0398, (wchar_t)0x0399, (wchar_t)0x039A, (wchar_t)0x039B,
264 (wchar_t)0x039C, (wchar_t)0x039D, (wchar_t)0x039E, (wchar_t)0x039F, (wchar_t)0x03A0,
265 (wchar_t)0x03A1, (wchar_t)0x03A3, (wchar_t)0x03A4, (wchar_t)0x03A5, (wchar_t)0x03A6,
266 (wchar_t)0x03A7, (wchar_t)0x03A8, (wchar_t)0x03A9, (wchar_t)0x03AA, (wchar_t)0x03AB,
267 (wchar_t)0x038C, (wchar_t)0x038E, (wchar_t)0x038F, (wchar_t)0x03E2, (wchar_t)0x03E4,
268 (wchar_t)0x03E6, (wchar_t)0x03E8, (wchar_t)0x03EA, (wchar_t)0x03EC, (wchar_t)0x03EE,
269 (wchar_t)0x0410, (wchar_t)0x0411, (wchar_t)0x0412, (wchar_t)0x0413, (wchar_t)0x0414,
270 (wchar_t)0x0415, (wchar_t)0x0416, (wchar_t)0x0417, (wchar_t)0x0418, (wchar_t)0x0419,
271 (wchar_t)0x041A, (wchar_t)0x041B, (wchar_t)0x041C, (wchar_t)0x041D, (wchar_t)0x041E,
272 (wchar_t)0x041F, (wchar_t)0x0420, (wchar_t)0x0421, (wchar_t)0x0422, (wchar_t)0x0423,
273 (wchar_t)0x0424, (wchar_t)0x0425, (wchar_t)0x0426, (wchar_t)0x0427, (wchar_t)0x0428,
274 (wchar_t)0x0429, (wchar_t)0x042A, (wchar_t)0x042B, (wchar_t)0x042C, (wchar_t)0x042D,
275 (wchar_t)0x042E, (wchar_t)0x042F, (wchar_t)0x0401, (wchar_t)0x0402, (wchar_t)0x0403,
276 (wchar_t)0x0404, (wchar_t)0x0405, (wchar_t)0x0406, (wchar_t)0x0407, (wchar_t)0x0408,
277 (wchar_t)0x0409, (wchar_t)0x040A, (wchar_t)0x040B, (wchar_t)0x040C, (wchar_t)0x040E,
278 (wchar_t)0x040F, (wchar_t)0x0460, (wchar_t)0x0462, (wchar_t)0x0464, (wchar_t)0x0466,
279 (wchar_t)0x0468, (wchar_t)0x046A, (wchar_t)0x046C, (wchar_t)0x046E, (wchar_t)0x0470,
280 (wchar_t)0x0472, (wchar_t)0x0474, (wchar_t)0x0476, (wchar_t)0x0478, (wchar_t)0x047A,
281 (wchar_t)0x047C, (wchar_t)0x047E, (wchar_t)0x0480, (wchar_t)0x0490, (wchar_t)0x0492,
282 (wchar_t)0x0494, (wchar_t)0x0496, (wchar_t)0x0498, (wchar_t)0x049A, (wchar_t)0x049C,
283 (wchar_t)0x049E, (wchar_t)0x04A0, (wchar_t)0x04A2, (wchar_t)0x04A4, (wchar_t)0x04A6,
284 (wchar_t)0x04A8, (wchar_t)0x04AA, (wchar_t)0x04AC, (wchar_t)0x04AE, (wchar_t)0x04B0,
285 (wchar_t)0x04B2, (wchar_t)0x04B4, (wchar_t)0x04B6, (wchar_t)0x04B8, (wchar_t)0x04BA,
286 (wchar_t)0x04BC, (wchar_t)0x04BE, (wchar_t)0x04C1, (wchar_t)0x04C3, (wchar_t)0x04C7,
287 (wchar_t)0x04CB, (wchar_t)0x04D0, (wchar_t)0x04D2, (wchar_t)0x04D4, (wchar_t)0x04D6,
288 (wchar_t)0x04D8, (wchar_t)0x04DA, (wchar_t)0x04DC, (wchar_t)0x04DE, (wchar_t)0x04E0,
289 (wchar_t)0x04E2, (wchar_t)0x04E4, (wchar_t)0x04E6, (wchar_t)0x04E8, (wchar_t)0x04EA,
290 (wchar_t)0x04EE, (wchar_t)0x04F0, (wchar_t)0x04F2, (wchar_t)0x04F4, (wchar_t)0x04F8,
291 (wchar_t)0x0531, (wchar_t)0x0532, (wchar_t)0x0533, (wchar_t)0x0534, (wchar_t)0x0535,
292 (wchar_t)0x0536, (wchar_t)0x0537, (wchar_t)0x0538, (wchar_t)0x0539, (wchar_t)0x053A,
293 (wchar_t)0x053B, (wchar_t)0x053C, (wchar_t)0x053D, (wchar_t)0x053E, (wchar_t)0x053F,
294 (wchar_t)0x0540, (wchar_t)0x0541, (wchar_t)0x0542, (wchar_t)0x0543, (wchar_t)0x0544,
295 (wchar_t)0x0545, (wchar_t)0x0546, (wchar_t)0x0547, (wchar_t)0x0548, (wchar_t)0x0549,
296 (wchar_t)0x054A, (wchar_t)0x054B, (wchar_t)0x054C, (wchar_t)0x054D, (wchar_t)0x054E,
297 (wchar_t)0x054F, (wchar_t)0x0550, (wchar_t)0x0551, (wchar_t)0x0552, (wchar_t)0x0553,
298 (wchar_t)0x0554, (wchar_t)0x0555, (wchar_t)0x0556, (wchar_t)0x10A0, (wchar_t)0x10A1,
299 (wchar_t)0x10A2, (wchar_t)0x10A3, (wchar_t)0x10A4, (wchar_t)0x10A5, (wchar_t)0x10A6,
300 (wchar_t)0x10A7, (wchar_t)0x10A8, (wchar_t)0x10A9, (wchar_t)0x10AA, (wchar_t)0x10AB,
301 (wchar_t)0x10AC, (wchar_t)0x10AD, (wchar_t)0x10AE, (wchar_t)0x10AF, (wchar_t)0x10B0,
302 (wchar_t)0x10B1, (wchar_t)0x10B2, (wchar_t)0x10B3, (wchar_t)0x10B4, (wchar_t)0x10B5,
303 (wchar_t)0x10B6, (wchar_t)0x10B7, (wchar_t)0x10B8, (wchar_t)0x10B9, (wchar_t)0x10BA,
304 (wchar_t)0x10BB, (wchar_t)0x10BC, (wchar_t)0x10BD, (wchar_t)0x10BE, (wchar_t)0x10BF,
305 (wchar_t)0x10C0, (wchar_t)0x10C1, (wchar_t)0x10C2, (wchar_t)0x10C3, (wchar_t)0x10C4,
306 (wchar_t)0x10C5, (wchar_t)0x1E00, (wchar_t)0x1E02, (wchar_t)0x1E04, (wchar_t)0x1E06,
307 (wchar_t)0x1E08, (wchar_t)0x1E0A, (wchar_t)0x1E0C, (wchar_t)0x1E0E, (wchar_t)0x1E10,
308 (wchar_t)0x1E12, (wchar_t)0x1E14, (wchar_t)0x1E16, (wchar_t)0x1E18, (wchar_t)0x1E1A,
309 (wchar_t)0x1E1C, (wchar_t)0x1E1E, (wchar_t)0x1E20, (wchar_t)0x1E22, (wchar_t)0x1E24,
310 (wchar_t)0x1E26, (wchar_t)0x1E28, (wchar_t)0x1E2A, (wchar_t)0x1E2C, (wchar_t)0x1E2E,
311 (wchar_t)0x1E30, (wchar_t)0x1E32, (wchar_t)0x1E34, (wchar_t)0x1E36, (wchar_t)0x1E38,
312 (wchar_t)0x1E3A, (wchar_t)0x1E3C, (wchar_t)0x1E3E, (wchar_t)0x1E40, (wchar_t)0x1E42,
313 (wchar_t)0x1E44, (wchar_t)0x1E46, (wchar_t)0x1E48, (wchar_t)0x1E4A, (wchar_t)0x1E4C,
314 (wchar_t)0x1E4E, (wchar_t)0x1E50, (wchar_t)0x1E52, (wchar_t)0x1E54, (wchar_t)0x1E56,
315 (wchar_t)0x1E58, (wchar_t)0x1E5A, (wchar_t)0x1E5C, (wchar_t)0x1E5E, (wchar_t)0x1E60,
316 (wchar_t)0x1E62, (wchar_t)0x1E64, (wchar_t)0x1E66, (wchar_t)0x1E68, (wchar_t)0x1E6A,
317 (wchar_t)0x1E6C, (wchar_t)0x1E6E, (wchar_t)0x1E70, (wchar_t)0x1E72, (wchar_t)0x1E74,
318 (wchar_t)0x1E76, (wchar_t)0x1E78, (wchar_t)0x1E7A, (wchar_t)0x1E7C, (wchar_t)0x1E7E,
319 (wchar_t)0x1E80, (wchar_t)0x1E82, (wchar_t)0x1E84, (wchar_t)0x1E86, (wchar_t)0x1E88,
320 (wchar_t)0x1E8A, (wchar_t)0x1E8C, (wchar_t)0x1E8E, (wchar_t)0x1E90, (wchar_t)0x1E92,
321 (wchar_t)0x1E94, (wchar_t)0x1EA0, (wchar_t)0x1EA2, (wchar_t)0x1EA4, (wchar_t)0x1EA6,
322 (wchar_t)0x1EA8, (wchar_t)0x1EAA, (wchar_t)0x1EAC, (wchar_t)0x1EAE, (wchar_t)0x1EB0,
323 (wchar_t)0x1EB2, (wchar_t)0x1EB4, (wchar_t)0x1EB6, (wchar_t)0x1EB8, (wchar_t)0x1EBA,
324 (wchar_t)0x1EBC, (wchar_t)0x1EBE, (wchar_t)0x1EC0, (wchar_t)0x1EC2, (wchar_t)0x1EC4,
325 (wchar_t)0x1EC6, (wchar_t)0x1EC8, (wchar_t)0x1ECA, (wchar_t)0x1ECC, (wchar_t)0x1ECE,
326 (wchar_t)0x1ED0, (wchar_t)0x1ED2, (wchar_t)0x1ED4, (wchar_t)0x1ED6, (wchar_t)0x1ED8,
327 (wchar_t)0x1EDA, (wchar_t)0x1EDC, (wchar_t)0x1EDE, (wchar_t)0x1EE0, (wchar_t)0x1EE2,
328 (wchar_t)0x1EE4, (wchar_t)0x1EE6, (wchar_t)0x1EE8, (wchar_t)0x1EEA, (wchar_t)0x1EEC,
329 (wchar_t)0x1EEE, (wchar_t)0x1EF0, (wchar_t)0x1EF2, (wchar_t)0x1EF4, (wchar_t)0x1EF6,
330 (wchar_t)0x1EF8, (wchar_t)0x1F08, (wchar_t)0x1F09, (wchar_t)0x1F0A, (wchar_t)0x1F0B,
331 (wchar_t)0x1F0C, (wchar_t)0x1F0D, (wchar_t)0x1F0E, (wchar_t)0x1F0F, (wchar_t)0x1F18,
332 (wchar_t)0x1F19, (wchar_t)0x1F1A, (wchar_t)0x1F1B, (wchar_t)0x1F1C, (wchar_t)0x1F1D,
333 (wchar_t)0x1F28, (wchar_t)0x1F29, (wchar_t)0x1F2A, (wchar_t)0x1F2B, (wchar_t)0x1F2C,
334 (wchar_t)0x1F2D, (wchar_t)0x1F2E, (wchar_t)0x1F2F, (wchar_t)0x1F38, (wchar_t)0x1F39,
335 (wchar_t)0x1F3A, (wchar_t)0x1F3B, (wchar_t)0x1F3C, (wchar_t)0x1F3D, (wchar_t)0x1F3E,
336 (wchar_t)0x1F3F, (wchar_t)0x1F48, (wchar_t)0x1F49, (wchar_t)0x1F4A, (wchar_t)0x1F4B,
337 (wchar_t)0x1F4C, (wchar_t)0x1F4D, (wchar_t)0x1F59, (wchar_t)0x1F5B, (wchar_t)0x1F5D,
338 (wchar_t)0x1F5F, (wchar_t)0x1F68, (wchar_t)0x1F69, (wchar_t)0x1F6A, (wchar_t)0x1F6B,
339 (wchar_t)0x1F6C, (wchar_t)0x1F6D, (wchar_t)0x1F6E, (wchar_t)0x1F6F, (wchar_t)0x1F88,
340 (wchar_t)0x1F89, (wchar_t)0x1F8A, (wchar_t)0x1F8B, (wchar_t)0x1F8C, (wchar_t)0x1F8D,
341 (wchar_t)0x1F8E, (wchar_t)0x1F8F, (wchar_t)0x1F98, (wchar_t)0x1F99, (wchar_t)0x1F9A,
342 (wchar_t)0x1F9B, (wchar_t)0x1F9C, (wchar_t)0x1F9D, (wchar_t)0x1F9E, (wchar_t)0x1F9F,
343 (wchar_t)0x1FA8, (wchar_t)0x1FA9, (wchar_t)0x1FAA, (wchar_t)0x1FAB, (wchar_t)0x1FAC,
344 (wchar_t)0x1FAD, (wchar_t)0x1FAE, (wchar_t)0x1FAF, (wchar_t)0x1FB8, (wchar_t)0x1FB9,
345 (wchar_t)0x1FD8, (wchar_t)0x1FD9, (wchar_t)0x1FE8, (wchar_t)0x1FE9, (wchar_t)0x24B6,
346 (wchar_t)0x24B7, (wchar_t)0x24B8, (wchar_t)0x24B9, (wchar_t)0x24BA, (wchar_t)0x24BB,
347 (wchar_t)0x24BC, (wchar_t)0x24BD, (wchar_t)0x24BE, (wchar_t)0x24BF, (wchar_t)0x24C0,
348 (wchar_t)0x24C1, (wchar_t)0x24C2, (wchar_t)0x24C3, (wchar_t)0x24C4, (wchar_t)0x24C5,
349 (wchar_t)0x24C6, (wchar_t)0x24C7, (wchar_t)0x24C8, (wchar_t)0x24C9, (wchar_t)0x24CA,
350 (wchar_t)0x24CB, (wchar_t)0x24CC, (wchar_t)0x24CD, (wchar_t)0x24CE, (wchar_t)0x24CF,
351 (wchar_t)0xFF21, (wchar_t)0xFF22, (wchar_t)0xFF23, (wchar_t)0xFF24, (wchar_t)0xFF25,
352 (wchar_t)0xFF26, (wchar_t)0xFF27, (wchar_t)0xFF28, (wchar_t)0xFF29, (wchar_t)0xFF2A,
353 (wchar_t)0xFF2B, (wchar_t)0xFF2C, (wchar_t)0xFF2D, (wchar_t)0xFF2E, (wchar_t)0xFF2F,
354 (wchar_t)0xFF30, (wchar_t)0xFF31, (wchar_t)0xFF32, (wchar_t)0xFF33, (wchar_t)0xFF34,
355 (wchar_t)0xFF35, (wchar_t)0xFF36, (wchar_t)0xFF37, (wchar_t)0xFF38, (wchar_t)0xFF39,
356 (wchar_t)0xFF3A};
357
358namespace kodi
359{
360namespace tools
361{
362
363template<typename T, std::enable_if_t<!std::is_enum<T>::value, int> = 0>
364constexpr auto&& EnumToInt(T&& arg) noexcept
365{
366 return arg;
367}
368template<typename T, std::enable_if_t<std::is_enum<T>::value, int> = 0>
369constexpr auto EnumToInt(T&& arg) noexcept
370{
371 return static_cast<int>(arg);
372}
373
374//==============================================================================
385
386//==============================================================================
457//------------------------------------------------------------------------------
458
459//==============================================================================
472{
473public:
474 //============================================================================
478 static const std::string Empty;
479 //----------------------------------------------------------------------------
480
481 //----------------------------------------------------------------------------
487
489 //============================================================================
558 inline static std::string Format(const char* fmt, ...)
559 {
560 va_list args;
561 va_start(args, fmt);
562 std::string str = FormatV(fmt, args);
563 va_end(args);
564
565 return str;
566 }
567 //----------------------------------------------------------------------------
568
569 //============================================================================
584 inline static std::wstring Format(const wchar_t* fmt, ...)
585 {
586 va_list args;
587 va_start(args, fmt);
588 std::wstring str = FormatV(fmt, args);
589 va_end(args);
590
591 return str;
592 }
593 //----------------------------------------------------------------------------
594
595 //============================================================================
604 inline static std::string FormatV(PRINTF_FORMAT_STRING const char* fmt, va_list args)
605 {
606 if (!fmt || !fmt[0])
607 return "";
608
609 int size = FORMAT_BLOCK_SIZE;
610 va_list argCopy;
611
612 while (true)
613 {
614 char* cstr = reinterpret_cast<char*>(malloc(sizeof(char) * size));
615 if (!cstr)
616 return "";
617
618 va_copy(argCopy, args);
619 int nActual = vsnprintf(cstr, size, fmt, argCopy);
620 va_end(argCopy);
621
622 if (nActual > -1 && nActual < size) // We got a valid result
623 {
624 std::string str(cstr, nActual);
625 free(cstr);
626 return str;
627 }
628 free(cstr);
629#ifndef TARGET_WINDOWS
630 if (nActual > -1) // Exactly what we will need (glibc 2.1)
631 size = nActual + 1;
632 else // Let's try to double the size (glibc 2.0)
633 size *= 2;
634#else // TARGET_WINDOWS
635 va_copy(argCopy, args);
636 size = _vscprintf(fmt, argCopy);
637 va_end(argCopy);
638 if (size < 0)
639 return "";
640 else
641 size++; // increment for null-termination
642#endif // TARGET_WINDOWS
643 }
644
645 return ""; // unreachable
646 }
647 //----------------------------------------------------------------------------
648
649 //============================================================================
658 inline static std::wstring FormatV(PRINTF_FORMAT_STRING const wchar_t* fmt, va_list args)
659 {
660 if (!fmt || !fmt[0])
661 return L"";
662
663 int size = FORMAT_BLOCK_SIZE;
664 va_list argCopy;
665
666 while (true)
667 {
668 wchar_t* cstr = reinterpret_cast<wchar_t*>(malloc(sizeof(wchar_t) * size));
669 if (!cstr)
670 return L"";
671
672 va_copy(argCopy, args);
673 int nActual = vswprintf(cstr, size, fmt, argCopy);
674 va_end(argCopy);
675
676 if (nActual > -1 && nActual < size) // We got a valid result
677 {
678 std::wstring str(cstr, nActual);
679 free(cstr);
680 return str;
681 }
682 free(cstr);
683
684#ifndef TARGET_WINDOWS
685 if (nActual > -1) // Exactly what we will need (glibc 2.1)
686 size = nActual + 1;
687 else // Let's try to double the size (glibc 2.0)
688 size *= 2;
689#else // TARGET_WINDOWS
690 va_copy(argCopy, args);
691 size = _vscwprintf(fmt, argCopy);
692 va_end(argCopy);
693 if (size < 0)
694 return L"";
695 else
696 size++; // increment for null-termination
697#endif // TARGET_WINDOWS
698 }
699
700 return L"";
701 }
702 //----------------------------------------------------------------------------
703
704 //============================================================================
756 inline static std::string FormatFileSize(uint64_t bytes)
757 {
758 const std::array<std::string, 9> units{{"B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"}};
759 if (bytes < 1000)
760 return Format("%" PRIu64 "B", bytes);
761
762 size_t i = 0;
763 double value = static_cast<double>(bytes);
764 while (i + 1 < units.size() && value >= 999.5)
765 {
766 ++i;
767 value /= 1024.0;
768 }
769 unsigned int decimals = value < 9.995 ? 2 : (value < 99.95 ? 1 : 0);
770 auto frmt = "%." + Format("%u", decimals) + "f%s";
771 return Format(frmt.c_str(), value, units[i].c_str());
772 }
773 //----------------------------------------------------------------------------
774
775 //============================================================================
785 inline static std::string BinaryStringToString(const std::string& in)
786 {
787 std::string out;
788 out.reserve(in.size() / 2);
789 for (const char *cur = in.c_str(), *end = cur + in.size(); cur != end; ++cur)
790 {
791 if (*cur == '\\')
792 {
793 ++cur;
794 if (cur == end)
795 {
796 break;
797 }
798 if (isdigit(*cur))
799 {
800 char* end;
801 unsigned long num = strtol(cur, &end, 10);
802 cur = end - 1;
803 out.push_back(static_cast<char>(num));
804 continue;
805 }
806 }
807 out.push_back(*cur);
808 }
809 return out;
810 }
811 //----------------------------------------------------------------------------
812
813 //============================================================================
838 inline static std::string ToHexadecimal(const std::string& in)
839 {
840 std::ostringstream ss;
841 ss << std::hex;
842 for (unsigned char ch : in)
843 {
844 ss << std::setw(2) << std::setfill('0') << static_cast<unsigned long>(ch);
845 }
846 return ss.str();
847 }
848 //----------------------------------------------------------------------------
849
852 //----------------------------------------------------------------------------
858
860 //============================================================================
878 inline static void ToUpper(std::string& str)
879 {
880 std::transform(str.begin(), str.end(), str.begin(), ::toupper);
881 }
882 //----------------------------------------------------------------------------
883
884 //============================================================================
889 inline static void ToUpper(std::wstring& str)
890 {
891 transform(str.begin(), str.end(), str.begin(), toupperUnicode);
892 }
893 //----------------------------------------------------------------------------
894
895 //============================================================================
913 inline static void ToLower(std::string& str)
914 {
915 transform(str.begin(), str.end(), str.begin(), ::tolower);
916 }
917 //----------------------------------------------------------------------------
918
919 //============================================================================
924 inline static void ToLower(std::wstring& str)
925 {
926 transform(str.begin(), str.end(), str.begin(), tolowerUnicode);
927 }
928 //----------------------------------------------------------------------------
929
930 //============================================================================
936 inline static int ReturnDigits(const std::string& str)
937 {
938 std::stringstream ss;
939 for (const auto& character : str)
940 {
941 if (isdigit(character))
942 ss << character;
943 }
944 return atoi(ss.str().c_str());
945 }
946 //----------------------------------------------------------------------------
947
948 //============================================================================
978 inline static std::string Left(const std::string& str, size_t count)
979 {
980 count = std::max((size_t)0, std::min(count, str.size()));
981 return str.substr(0, count);
982 }
983 //----------------------------------------------------------------------------
984
985 //============================================================================
1028 inline static std::string Mid(const std::string& str,
1029 size_t first,
1030 size_t count = std::string::npos)
1031 {
1032 if (first + count > str.size())
1033 count = str.size() - first;
1034
1035 if (first > str.size())
1036 return std::string();
1037
1038 assert(first + count <= str.size());
1039
1040 return str.substr(first, count);
1041 }
1042 //----------------------------------------------------------------------------
1043
1044 //============================================================================
1074 inline static std::string Right(const std::string& str, size_t count)
1075 {
1076 count = std::max((size_t)0, std::min(count, str.size()));
1077 return str.substr(str.size() - count);
1078 }
1079 //----------------------------------------------------------------------------
1080
1081 //============================================================================
1102 inline static std::string& Trim(std::string& str)
1103 {
1104 TrimLeft(str);
1105 return TrimRight(str);
1106 }
1107 //----------------------------------------------------------------------------
1108
1109 //============================================================================
1118 inline static std::string& Trim(std::string& str, const char* const chars)
1119 {
1120 TrimLeft(str, chars);
1121 return TrimRight(str, chars);
1122 }
1123 //----------------------------------------------------------------------------
1124
1125 //============================================================================
1145 inline static std::string& TrimLeft(std::string& str)
1146 {
1147 str.erase(str.begin(),
1148 std::find_if(str.begin(), str.end(), [](char s) { return IsSpace(s) == 0; }));
1149 return str;
1150 }
1151 //----------------------------------------------------------------------------
1152
1153 //============================================================================
1162 inline static std::string& TrimLeft(std::string& str, const char* const chars)
1163 {
1164 size_t nidx = str.find_first_not_of(chars);
1165 str.erase(0, nidx);
1166 return str;
1167 }
1168 //----------------------------------------------------------------------------
1169
1170 //============================================================================
1190 inline static std::string& TrimRight(std::string& str)
1191 {
1192 str.erase(std::find_if(str.rbegin(), str.rend(), [](char s) { return IsSpace(s) == 0; }).base(),
1193 str.end());
1194 return str;
1195 }
1196 //----------------------------------------------------------------------------
1197
1198 //============================================================================
1207 inline static std::string& TrimRight(std::string& str, const char* const chars)
1208 {
1209 size_t nidx = str.find_last_not_of(chars);
1210 str.erase(str.npos == nidx ? 0 : ++nidx);
1211 return str;
1212 }
1213 //----------------------------------------------------------------------------
1214
1215 //============================================================================
1222 inline static std::string& RemoveDuplicatedSpacesAndTabs(std::string& str)
1223 {
1224 std::string::iterator it = str.begin();
1225 bool onSpace = false;
1226 while (it != str.end())
1227 {
1228 if (*it == '\t')
1229 *it = ' ';
1230
1231 if (*it == ' ')
1232 {
1233 if (onSpace)
1234 {
1235 it = str.erase(it);
1236 continue;
1237 }
1238 else
1239 onSpace = true;
1240 }
1241 else
1242 onSpace = false;
1243
1244 ++it;
1245 }
1246 return str;
1247 }
1248 //----------------------------------------------------------------------------
1249
1250 //============================================================================
1274 inline static int Replace(std::string& str, char oldChar, char newChar)
1275 {
1276 int replacedChars = 0;
1277 for (std::string::iterator it = str.begin(); it != str.end(); ++it)
1278 {
1279 if (*it == oldChar)
1280 {
1281 *it = newChar;
1282 replacedChars++;
1283 }
1284 }
1285
1286 return replacedChars;
1287 }
1288 //----------------------------------------------------------------------------
1289
1290 //============================================================================
1314 inline static int Replace(std::string& str, const std::string& oldStr, const std::string& newStr)
1315 {
1316 if (oldStr.empty())
1317 return 0;
1318
1319 int replacedChars = 0;
1320 size_t index = 0;
1321
1322 while (index < str.size() && (index = str.find(oldStr, index)) != std::string::npos)
1323 {
1324 str.replace(index, oldStr.size(), newStr);
1325 index += newStr.size();
1326 replacedChars++;
1327 }
1328
1329 return replacedChars;
1330 }
1331 //----------------------------------------------------------------------------
1332
1333 //============================================================================
1341 inline static int Replace(std::wstring& str,
1342 const std::wstring& oldStr,
1343 const std::wstring& newStr)
1344 {
1345 if (oldStr.empty())
1346 return 0;
1347
1348 int replacedChars = 0;
1349 size_t index = 0;
1350
1351 while (index < str.size() && (index = str.find(oldStr, index)) != std::string::npos)
1352 {
1353 str.replace(index, oldStr.size(), newStr);
1354 index += newStr.size();
1355 replacedChars++;
1356 }
1357
1358 return replacedChars;
1359 }
1360 //----------------------------------------------------------------------------
1361
1362 //============================================================================
1375 inline static std::string MakeSafeUrl(const std::string& str)
1376 {
1377 std::string safeUrl;
1378
1379 safeUrl.reserve(str.size());
1380
1381 std::transform(str.begin(), str.end(), std::back_inserter(safeUrl),
1382 [](char c)
1383 {
1384 if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') ||
1385 ('0' <= c && c <= '9') || c == '-' || c == '.' || c == '_' || c == '~')
1386 {
1387 return c;
1388 }
1389 return '_';
1390 });
1391
1392 return safeUrl;
1393 }
1394 //----------------------------------------------------------------------------
1395
1396 //============================================================================
1405 inline static std::string MakeSafeString(const std::string& str)
1406 {
1407 std::string safeString;
1408
1409 safeString.reserve(str.size());
1410
1411 std::transform(str.begin(), str.end(), std::back_inserter(safeString),
1412 [](char c)
1413 {
1414 if (c < 0x20)
1415 return ' ';
1416
1417 return c;
1418 });
1419
1420 return safeString;
1421 }
1422 //----------------------------------------------------------------------------
1423
1424 //============================================================================
1430 inline static std::string RemoveMACAddress(const std::string& str)
1431 {
1432 std::regex re(R"mac([\‍(\[]?([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})[\)\]]?)mac");
1433 return std::regex_replace(str, re, "", std::regex_constants::format_default);
1434 }
1435 //----------------------------------------------------------------------------
1436
1437 //============================================================================
1456 inline static void RemoveCRLF(std::string& strLine)
1457 {
1458 StringUtils::TrimRight(strLine, "\n\r");
1459 }
1460 //----------------------------------------------------------------------------
1461
1462 //============================================================================
1479 inline static void WordToDigits(std::string& word)
1480 {
1481 static const char word_to_letter[] = "22233344455566677778889999";
1483 for (unsigned int i = 0; i < word.size(); ++i)
1484 { // NB: This assumes ascii, which probably needs extending at some point.
1485 char letter = word[i];
1486 if ((letter >= 'a' && letter <= 'z')) // assume contiguous letter range
1487 {
1488 word[i] = word_to_letter[letter - 'a'];
1489 }
1490 else if (letter < '0' || letter > '9') // We want to keep 0-9!
1491 {
1492 word[i] = ' '; // replace everything else with a space
1493 }
1494 }
1495 }
1496 //----------------------------------------------------------------------------
1497
1498 //============================================================================
1518 inline static std::string Paramify(const std::string& param)
1519 {
1520 std::string result = param;
1521 // escape backspaces
1522 StringUtils::Replace(result, "\\", "\\\\");
1523 // escape double quotes
1524 StringUtils::Replace(result, "\"", "\\\"");
1525
1526 // add double quotes around the whole string
1527 return "\"" + result + "\"";
1528 }
1529 //----------------------------------------------------------------------------
1530
1533 //----------------------------------------------------------------------------
1540
1542 //============================================================================
1561 inline static bool EqualsNoCase(const std::string& str1, const std::string& str2)
1562 {
1563 // before we do the char-by-char comparison, first compare sizes of both strings.
1564 // This led to a 33% improvement in benchmarking on average. (size() just returns a member of std::string)
1565 if (str1.size() != str2.size())
1566 return false;
1567 return EqualsNoCase(str1.c_str(), str2.c_str());
1568 }
1569 //----------------------------------------------------------------------------
1570
1571 //============================================================================
1578 inline static bool EqualsNoCase(const std::string& str1, const char* s2)
1579 {
1580 return EqualsNoCase(str1.c_str(), s2);
1581 }
1582 //----------------------------------------------------------------------------
1583
1584 //============================================================================
1591 inline static bool EqualsNoCase(const char* s1, const char* s2)
1592 {
1593 char c2; // we need only one char outside the loop
1594 do
1595 {
1596 const char c1 = *s1++; // const local variable should help compiler to optimize
1597 c2 = *s2++;
1598 // This includes the possibility that one of the characters is the null-terminator,
1599 // which implies a string mismatch.
1600 if (c1 != c2 && ::tolower(c1) != ::tolower(c2))
1601 return false;
1602 } while (c2 != '\0'); // At this point, we know c1 == c2, so there's no need to test them both.
1603 return true;
1604 }
1605 //----------------------------------------------------------------------------
1606
1607 //============================================================================
1620 inline static int CompareNoCase(const std::string& str1, const std::string& str2, size_t n = 0)
1621 {
1622 return CompareNoCase(str1.c_str(), str2.c_str(), n);
1623 }
1624 //----------------------------------------------------------------------------
1625
1626 //============================================================================
1639 inline static int CompareNoCase(const char* s1, const char* s2, size_t n = 0)
1640 {
1641 char c2; // we need only one char outside the loop
1642 size_t index = 0;
1643 do
1644 {
1645 const char c1 = *s1++; // const local variable should help compiler to optimize
1646 c2 = *s2++;
1647 index++;
1648 // This includes the possibility that one of the characters is the null-terminator,
1649 // which implies a string mismatch.
1650 if (c1 != c2 && ::tolower(c1) != ::tolower(c2))
1651 return ::tolower(c1) - ::tolower(c2);
1652 } while (c2 != '\0' &&
1653 index != n); // At this point, we know c1 == c2, so there's no need to test them both.
1654 return 0;
1655 }
1656 //----------------------------------------------------------------------------
1657
1658 //============================================================================
1682 inline static bool StartsWith(const std::string& str1, const std::string& str2)
1683 {
1684 return str1.compare(0, str2.size(), str2) == 0;
1685 }
1686 //----------------------------------------------------------------------------
1687
1688 //============================================================================
1696 inline static bool StartsWith(const std::string& str1, const char* s2)
1697 {
1698 return StartsWith(str1.c_str(), s2);
1699 }
1700 //----------------------------------------------------------------------------
1701
1702 //============================================================================
1710 inline static bool StartsWith(const char* s1, const char* s2)
1711 {
1712 while (*s2 != '\0')
1713 {
1714 if (*s1 != *s2)
1715 return false;
1716 s1++;
1717 s2++;
1718 }
1719 return true;
1720 }
1721 //----------------------------------------------------------------------------
1722
1723 //============================================================================
1751 inline static bool StartsWithNoCase(const std::string& str1, const std::string& str2)
1752 {
1753 return StartsWithNoCase(str1.c_str(), str2.c_str());
1754 }
1755 //----------------------------------------------------------------------------
1756
1757 //============================================================================
1766 inline static bool StartsWithNoCase(const std::string& str1, const char* s2)
1767 {
1768 return StartsWithNoCase(str1.c_str(), s2);
1769 }
1770 //----------------------------------------------------------------------------
1771
1772 //============================================================================
1781 inline static bool StartsWithNoCase(const char* s1, const char* s2)
1782 {
1783 while (*s2 != '\0')
1784 {
1785 if (::tolower(*s1) != ::tolower(*s2))
1786 return false;
1787 s1++;
1788 s2++;
1789 }
1790 return true;
1791 }
1792 //----------------------------------------------------------------------------
1793
1794 //============================================================================
1818 inline static bool EndsWith(const std::string& str1, const std::string& str2)
1819 {
1820 if (str1.size() < str2.size())
1821 return false;
1822 return str1.compare(str1.size() - str2.size(), str2.size(), str2) == 0;
1823 }
1824 //----------------------------------------------------------------------------
1825
1826 //============================================================================
1834 inline static bool EndsWith(const std::string& str1, const char* s2)
1835 {
1836 size_t len2 = strlen(s2);
1837 if (str1.size() < len2)
1838 return false;
1839 return str1.compare(str1.size() - len2, len2, s2) == 0;
1840 }
1841 //----------------------------------------------------------------------------
1842
1843 //============================================================================
1868 inline static bool EndsWithNoCase(const std::string& str1, const std::string& str2)
1869 {
1870 if (str1.size() < str2.size())
1871 return false;
1872 const char* s1 = str1.c_str() + str1.size() - str2.size();
1873 const char* s2 = str2.c_str();
1874 while (*s2 != '\0')
1875 {
1876 if (::tolower(*s1) != ::tolower(*s2))
1877 return false;
1878 s1++;
1879 s2++;
1880 }
1881 return true;
1882 }
1883 //----------------------------------------------------------------------------
1884
1885 //============================================================================
1894 inline static bool EndsWithNoCase(const std::string& str1, const char* s2)
1895 {
1896 size_t len2 = strlen(s2);
1897 if (str1.size() < len2)
1898 return false;
1899 const char* s1 = str1.c_str() + str1.size() - len2;
1900 while (*s2 != '\0')
1901 {
1902 if (::tolower(*s1) != ::tolower(*s2))
1903 return false;
1904 s1++;
1905 s2++;
1906 }
1907 return true;
1908 }
1909 //----------------------------------------------------------------------------
1910
1911 //============================================================================
1936 inline static int64_t AlphaNumericCompare(const wchar_t* left, const wchar_t* right)
1937 {
1938 const wchar_t* l = left;
1939 const wchar_t* r = right;
1940 const wchar_t *ld, *rd;
1941 wchar_t lc, rc;
1942 int64_t lnum, rnum;
1943 const std::collate<wchar_t>& coll = std::use_facet<std::collate<wchar_t>>(std::locale());
1944 int cmp_res = 0;
1945 while (*l != 0 && *r != 0)
1946 {
1947 // check if we have a numerical value
1948 if (*l >= L'0' && *l <= L'9' && *r >= L'0' && *r <= L'9')
1949 {
1950 ld = l;
1951 lnum = 0;
1952 while (*ld >= L'0' && *ld <= L'9' && ld < l + 15)
1953 { // compare only up to 15 digits
1954 lnum *= 10;
1955 lnum += *ld++ - '0';
1956 }
1957 rd = r;
1958 rnum = 0;
1959 while (*rd >= L'0' && *rd <= L'9' && rd < r + 15)
1960 { // compare only up to 15 digits
1961 rnum *= 10;
1962 rnum += *rd++ - L'0';
1963 }
1964 // do we have numbers?
1965 if (lnum != rnum)
1966 { // yes - and they're different!
1967 return lnum - rnum;
1968 }
1969 l = ld;
1970 r = rd;
1971 continue;
1972 }
1973 // do case less comparison
1974 lc = *l;
1975 if (lc >= L'A' && lc <= L'Z')
1976 lc += L'a' - L'A';
1977 rc = *r;
1978 if (rc >= L'A' && rc <= L'Z')
1979 rc += L'a' - L'A';
1980
1981 // ok, do a normal comparison, taking current locale into account. Add special case stuff (eg '(' characters)) in here later
1982 if ((cmp_res = coll.compare(&lc, &lc + 1, &rc, &rc + 1)) != 0)
1983 {
1984 return cmp_res;
1985 }
1986 l++;
1987 r++;
1988 }
1989 if (*r)
1990 { // r is longer
1991 return -1;
1992 }
1993 else if (*l)
1994 { // l is longer
1995 return 1;
1996 }
1997 return 0; // files are the same
1998 }
1999 //----------------------------------------------------------------------------
2000
2001 //============================================================================
2010 inline static size_t Utf8StringLength(const char* s)
2011 {
2012 size_t length = 0;
2013 while (*s)
2014 {
2015 if ((*s++ & 0xC0) != 0x80)
2016 length++;
2017 }
2018 return length;
2019 }
2020 //----------------------------------------------------------------------------
2021
2022 //============================================================================
2031 inline static int IsSpace(char c)
2032 {
2033 return (c & 0x80) == 0 && ::isspace(c);
2034 }
2035 //----------------------------------------------------------------------------
2036
2037 //============================================================================
2043 inline static int IsUTF8Letter(const unsigned char* str)
2044 {
2045 // reference:
2046 // unicode -> utf8 table: http://www.utf8-chartable.de/
2047 // latin characters in unicode: http://en.wikipedia.org/wiki/Latin_characters_in_Unicode
2048 unsigned char ch = str[0];
2049 if (!ch)
2050 return -1;
2051 if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))
2052 return 1;
2053 if (!(ch & 0x80))
2054 return -1;
2055 unsigned char ch2 = str[1];
2056 if (!ch2)
2057 return -1;
2058 // check latin 1 letter table: http://en.wikipedia.org/wiki/C1_Controls_and_Latin-1_Supplement
2059 if (ch == 0xC3 && ch2 >= 0x80 && ch2 <= 0xBF && ch2 != 0x97 && ch2 != 0xB7)
2060 return 2;
2061 // check latin extended A table: http://en.wikipedia.org/wiki/Latin_Extended-A
2062 if (ch >= 0xC4 && ch <= 0xC7 && ch2 >= 0x80 && ch2 <= 0xBF)
2063 return 2;
2064 // check latin extended B table: http://en.wikipedia.org/wiki/Latin_Extended-B
2065 // and International Phonetic Alphabet: http://en.wikipedia.org/wiki/IPA_Extensions_(Unicode_block)
2066 if (((ch == 0xC8 || ch == 0xC9) && ch2 >= 0x80 && ch2 <= 0xBF) ||
2067 (ch == 0xCA && ch2 >= 0x80 && ch2 <= 0xAF))
2068 return 2;
2069 return -1;
2070 }
2071 //----------------------------------------------------------------------------
2072
2073 //============================================================================
2100 inline static bool IsNaturalNumber(const std::string& str)
2101 {
2102 size_t i = 0, n = 0;
2103 // allow whitespace,digits,whitespace
2104 while (i < str.size() && isspace((unsigned char)str[i]))
2105 i++;
2106 while (i < str.size() && isdigit((unsigned char)str[i]))
2107 {
2108 i++;
2109 n++;
2110 }
2111 while (i < str.size() && isspace((unsigned char)str[i]))
2112 i++;
2113 return i == str.size() && n > 0;
2114 }
2115 //----------------------------------------------------------------------------
2116
2117 //============================================================================
2144 inline static bool IsInteger(const std::string& str)
2145 {
2146 size_t i = 0, n = 0;
2147 // allow whitespace,-,digits,whitespace
2148 while (i < str.size() && isspace((unsigned char)str[i]))
2149 i++;
2150 if (i < str.size() && str[i] == '-')
2151 i++;
2152 while (i < str.size() && isdigit((unsigned char)str[i]))
2153 {
2154 i++;
2155 n++;
2156 }
2157 while (i < str.size() && isspace((unsigned char)str[i]))
2158 i++;
2159 return i == str.size() && n > 0;
2160 }
2161 //----------------------------------------------------------------------------
2162
2163 //============================================================================
2169 inline static bool IsAasciiDigit(char chr) // locale independent
2170 {
2171 return chr >= '0' && chr <= '9';
2172 }
2173 //----------------------------------------------------------------------------
2174
2175 //============================================================================
2181 inline static bool IsAsciiXDigit(char chr) // locale independent
2182 {
2183 return (chr >= '0' && chr <= '9') || (chr >= 'a' && chr <= 'f') || (chr >= 'A' && chr <= 'F');
2184 }
2185 //----------------------------------------------------------------------------
2186
2187 //============================================================================
2194 inline static int AsciiDigitValue(char chr) // locale independent
2195 {
2196 if (!IsAasciiDigit(chr))
2197 return -1;
2198
2199 return chr - '0';
2200 }
2201 //----------------------------------------------------------------------------
2202
2203 //============================================================================
2211 inline static int AsciiXDigitValue(char chr) // locale independent
2212 {
2213 int v = AsciiDigitValue(chr);
2214 if (v >= 0)
2215 return v;
2216 if (chr >= 'a' && chr <= 'f')
2217 return chr - 'a' + 10;
2218 if (chr >= 'A' && chr <= 'F')
2219 return chr - 'A' + 10;
2220
2221 return -1;
2222 }
2223 //----------------------------------------------------------------------------
2224
2225 //============================================================================
2231 inline static bool IsAsciiUppercaseLetter(char chr) // locale independent
2232 {
2233 return (chr >= 'A' && chr <= 'Z');
2234 }
2235 //----------------------------------------------------------------------------
2236
2237 //============================================================================
2243 inline static bool IsAsciiLowercaseLetter(char chr) // locale independent
2244 {
2245 return (chr >= 'a' && chr <= 'z');
2246 }
2247 //----------------------------------------------------------------------------
2248
2249 //============================================================================
2255 inline static bool IsAsciiAlphaNum(char chr) // locale independent
2256 {
2257 return IsAsciiUppercaseLetter(chr) || IsAsciiLowercaseLetter(chr) || IsAasciiDigit(chr);
2258 }
2259 //----------------------------------------------------------------------------
2260
2261 //============================================================================
2268 inline static bool ContainsKeyword(const std::string& str,
2269 const std::vector<std::string>& keywords)
2270 {
2271 for (const auto& it : keywords)
2272 {
2273 if (str.find(it) != str.npos)
2274 return true;
2275 }
2276 return false;
2277 }
2278 //----------------------------------------------------------------------------
2279
2282 //----------------------------------------------------------------------------
2289
2291 //============================================================================
2318 inline static size_t FindWords(const char* str, const char* wordLowerCase)
2319 {
2320 // NOTE: This assumes word is lowercase!
2321 const unsigned char* s = (const unsigned char*)str;
2322 do
2323 {
2324 // start with a compare
2325 const unsigned char* c = s;
2326 const unsigned char* w = (const unsigned char*)wordLowerCase;
2327 bool same = true;
2328 while (same && *c && *w)
2329 {
2330 unsigned char lc = *c++;
2331 if (lc >= 'A' && lc <= 'Z')
2332 lc += 'a' - 'A';
2333
2334 if (lc != *w++) // different
2335 same = false;
2336 }
2337 if (same && *w == 0) // only the same if word has been exhausted
2338 return (const char*)s - str;
2339
2340 // otherwise, skip current word (composed by latin letters) or number
2341 int l;
2342 if (*s >= '0' && *s <= '9')
2343 {
2344 ++s;
2345 while (*s >= '0' && *s <= '9')
2346 ++s;
2347 }
2348 else if ((l = IsUTF8Letter(s)) > 0)
2349 {
2350 s += l;
2351 while ((l = IsUTF8Letter(s)) > 0)
2352 s += l;
2353 }
2354 else
2355 ++s;
2356 while (*s && *s == ' ')
2357 s++;
2358
2359 // and repeat until we're done
2360 } while (*s);
2361
2362 return std::string::npos;
2363 }
2364 //----------------------------------------------------------------------------
2365
2366 //============================================================================
2389 inline static size_t FindEndBracket(const std::string& str,
2390 char opener,
2391 char closer,
2392 size_t startPos = 0)
2393 {
2394 size_t blocks = 1;
2395 for (size_t i = startPos; i < str.size(); i++)
2396 {
2397 if (str[i] == opener)
2398 blocks++;
2399 else if (str[i] == closer)
2400 {
2401 blocks--;
2402 if (!blocks)
2403 return i;
2404 }
2405 }
2406
2407 return std::string::npos;
2408 }
2409 //----------------------------------------------------------------------------
2410
2411 //============================================================================
2428 inline static int FindNumber(const std::string& strInput, const std::string& strFind)
2429 {
2430 size_t pos = strInput.find(strFind, 0);
2431 int numfound = 0;
2432 while (pos != std::string::npos)
2433 {
2434 numfound++;
2435 pos = strInput.find(strFind, pos + 1);
2436 }
2437 return numfound;
2438 }
2439 //----------------------------------------------------------------------------
2440
2443 //----------------------------------------------------------------------------
2450
2452 //============================================================================
2484 template<typename CONTAINER>
2485 inline static std::string Join(const CONTAINER& strings, const std::string& delimiter)
2486 {
2487 std::string result;
2488 for (const auto& str : strings)
2489 result += str + delimiter;
2490
2491 if (!result.empty())
2492 result.erase(result.size() - delimiter.size());
2493 return result;
2494 }
2495 //----------------------------------------------------------------------------
2496
2497 //============================================================================
2527 inline static std::vector<std::string> Split(const std::string& input,
2528 const std::string& delimiter,
2529 unsigned int iMaxStrings = 0)
2530 {
2531 std::vector<std::string> result;
2532 SplitTo(std::back_inserter(result), input, delimiter, iMaxStrings);
2533 return result;
2534 }
2535 //----------------------------------------------------------------------------
2536
2537 //============================================================================
2549 inline static std::vector<std::string> Split(const std::string& input,
2550 const char delimiter,
2551 int iMaxStrings = 0)
2552 {
2553 std::vector<std::string> result;
2554 SplitTo(std::back_inserter(result), input, delimiter, iMaxStrings);
2555 return result;
2556 }
2557 //----------------------------------------------------------------------------
2558
2559 //============================================================================
2571 inline static std::vector<std::string> Split(const std::string& input,
2572 const std::vector<std::string>& delimiters)
2573 {
2574 std::vector<std::string> result;
2575 SplitTo(std::back_inserter(result), input, delimiters);
2576 return result;
2577 }
2578 //----------------------------------------------------------------------------
2579
2580 //============================================================================
2594 template<typename OutputIt>
2595 inline static OutputIt SplitTo(OutputIt d_first,
2596 const std::string& input,
2597 const std::string& delimiter,
2598 unsigned int iMaxStrings = 0)
2599 {
2600 OutputIt dest = d_first;
2601
2602 if (input.empty())
2603 return dest;
2604 if (delimiter.empty())
2605 {
2606 *d_first++ = input;
2607 return dest;
2608 }
2609
2610 const size_t delimLen = delimiter.length();
2611 size_t nextDelim;
2612 size_t textPos = 0;
2613 do
2614 {
2615 if (--iMaxStrings == 0)
2616 {
2617 *dest++ = input.substr(textPos);
2618 break;
2619 }
2620 nextDelim = input.find(delimiter, textPos);
2621 *dest++ = input.substr(textPos, nextDelim - textPos);
2622 textPos = nextDelim + delimLen;
2623 } while (nextDelim != std::string::npos);
2624
2625 return dest;
2626 }
2627 //----------------------------------------------------------------------------
2628
2629 //============================================================================
2643 template<typename OutputIt>
2644 inline static OutputIt SplitTo(OutputIt d_first,
2645 const std::string& input,
2646 const char delimiter,
2647 int iMaxStrings = 0)
2648 {
2649 return SplitTo(d_first, input, std::string(1, delimiter), iMaxStrings);
2650 }
2651 //----------------------------------------------------------------------------
2652
2653 //============================================================================
2667 template<typename OutputIt>
2668 inline static OutputIt SplitTo(OutputIt d_first,
2669 const std::string& input,
2670 const std::vector<std::string>& delimiters)
2671 {
2672 OutputIt dest = d_first;
2673 if (input.empty())
2674 return dest;
2675
2676 if (delimiters.empty())
2677 {
2678 *dest++ = input;
2679 return dest;
2680 }
2681 std::string str = input;
2682 for (size_t di = 1; di < delimiters.size(); di++)
2683 StringUtils::Replace(str, delimiters[di], delimiters[0]);
2684 return SplitTo(dest, str, delimiters[0]);
2685 }
2686 //----------------------------------------------------------------------------
2687
2688 //============================================================================
2706 inline static std::vector<std::string> SplitMulti(const std::vector<std::string>& input,
2707 const std::vector<std::string>& delimiters,
2708 unsigned int iMaxStrings = 0)
2709 {
2710 if (input.empty())
2711 return std::vector<std::string>();
2712
2713 std::vector<std::string> results(input);
2714
2715 if (delimiters.empty() || (iMaxStrings > 0 && iMaxStrings <= input.size()))
2716 return results;
2717
2718 std::vector<std::string> strings1;
2719 if (iMaxStrings == 0)
2720 {
2721 for (size_t di = 0; di < delimiters.size(); di++)
2722 {
2723 for (size_t i = 0; i < results.size(); i++)
2724 {
2725 std::vector<std::string> substrings = StringUtils::Split(results[i], delimiters[di]);
2726 for (size_t j = 0; j < substrings.size(); j++)
2727 strings1.push_back(substrings[j]);
2728 }
2729 results = strings1;
2730 strings1.clear();
2731 }
2732 return results;
2733 }
2734
2735 // Control the number of strings input is split into, keeping the original strings.
2736 // Note iMaxStrings > input.size()
2737 size_t iNew = iMaxStrings - results.size();
2738 for (size_t di = 0; di < delimiters.size(); di++)
2739 {
2740 for (size_t i = 0; i < results.size(); i++)
2741 {
2742 if (iNew > 0)
2743 {
2744 std::vector<std::string> substrings =
2745 StringUtils::Split(results[i], delimiters[di], static_cast<int>(iNew + 1));
2746 iNew = iNew - substrings.size() + 1;
2747 for (size_t j = 0; j < substrings.size(); j++)
2748 strings1.push_back(substrings[j]);
2749 }
2750 else
2751 strings1.push_back(results[i]);
2752 }
2753 results = strings1;
2754 iNew = iMaxStrings - results.size();
2755 strings1.clear();
2756 if ((iNew <= 0))
2757 break; //Stop trying any more delimiters
2758 }
2759 return results;
2760 }
2761 //----------------------------------------------------------------------------
2762
2763 //============================================================================
2778 inline static std::vector<std::string> Tokenize(const std::string& input,
2779 const std::string& delimiters)
2780 {
2781 std::vector<std::string> tokens;
2782 Tokenize(input, tokens, delimiters);
2783 return tokens;
2784 }
2785 //----------------------------------------------------------------------------
2786
2787 //============================================================================
2795 inline static void Tokenize(const std::string& input,
2796 std::vector<std::string>& tokens,
2797 const std::string& delimiters)
2798 {
2799 tokens.clear();
2800 // Skip delimiters at beginning.
2801 std::string::size_type dataPos = input.find_first_not_of(delimiters);
2802 while (dataPos != std::string::npos)
2803 {
2804 // Find next delimiter
2805 const std::string::size_type nextDelimPos = input.find_first_of(delimiters, dataPos);
2806 // Found a token, add it to the vector.
2807 tokens.push_back(input.substr(dataPos, nextDelimPos - dataPos));
2808 // Skip delimiters. Note the "not_of"
2809 dataPos = input.find_first_not_of(delimiters, nextDelimPos);
2810 }
2811 }
2812 //----------------------------------------------------------------------------
2813
2814 //============================================================================
2822 inline static std::vector<std::string> Tokenize(const std::string& input, const char delimiter)
2823 {
2824 std::vector<std::string> tokens;
2825 Tokenize(input, tokens, delimiter);
2826 return tokens;
2827 }
2828 //----------------------------------------------------------------------------
2829
2830 //============================================================================
2838 inline static void Tokenize(const std::string& input,
2839 std::vector<std::string>& tokens,
2840 const char delimiter)
2841 {
2842 tokens.clear();
2843 // Skip delimiters at beginning.
2844 std::string::size_type dataPos = input.find_first_not_of(delimiter);
2845 while (dataPos != std::string::npos)
2846 {
2847 // Find next delimiter
2848 const std::string::size_type nextDelimPos = input.find(delimiter, dataPos);
2849 // Found a token, add it to the vector.
2850 tokens.push_back(input.substr(dataPos, nextDelimPos - dataPos));
2851 // Skip delimiters. Note the "not_of"
2852 dataPos = input.find_first_not_of(delimiter, nextDelimPos);
2853 }
2854 }
2855 //----------------------------------------------------------------------------
2856
2859 //----------------------------------------------------------------------------
2864
2866 //============================================================================
2895 inline static long TimeStringToSeconds(const std::string& timeString)
2896 {
2897 std::string strCopy(timeString);
2898 StringUtils::Trim(strCopy);
2899 if (StringUtils::EndsWithNoCase(strCopy, " min"))
2900 {
2901 // this is imdb format of "XXX min"
2902 return 60 * atoi(strCopy.c_str());
2903 }
2904 else
2905 {
2906 std::vector<std::string> secs = StringUtils::Split(strCopy, ':');
2907 int timeInSecs = 0;
2908 for (unsigned int i = 0; i < 3 && i < secs.size(); i++)
2909 {
2910 timeInSecs *= 60;
2911 timeInSecs += atoi(secs[i].c_str());
2912 }
2913 return timeInSecs;
2914 }
2915 }
2916 //----------------------------------------------------------------------------
2917
2918 //============================================================================
2941 inline static std::string SecondsToTimeString(long seconds,
2943 {
2944 bool isNegative = seconds < 0;
2945 seconds = std::abs(seconds);
2946
2947 std::string strHMS;
2948 if (format == TIME_FORMAT_SECS)
2949 strHMS = std::to_string(seconds);
2950 else if (format == TIME_FORMAT_MINS)
2951 strHMS = std::to_string(lrintf(static_cast<float>(seconds) / 60.0f));
2952 else if (format == TIME_FORMAT_HOURS)
2953 strHMS = std::to_string(lrintf(static_cast<float>(seconds) / 3600.0f));
2954 else if (format & TIME_FORMAT_M)
2955 strHMS += std::to_string(seconds % 3600 / 60);
2956 else
2957 {
2958 int hh = seconds / 3600;
2959 seconds = seconds % 3600;
2960 int mm = seconds / 60;
2961 int ss = seconds % 60;
2962
2963 if (format == TIME_FORMAT_GUESS)
2964 format = (hh >= 1) ? TIME_FORMAT_HH_MM_SS : TIME_FORMAT_MM_SS;
2965 if (format & TIME_FORMAT_HH)
2966 strHMS += StringUtils::Format("{:02}", hh);
2967 else if (format & TIME_FORMAT_H)
2968 strHMS += std::to_string(hh);
2969 if (format & TIME_FORMAT_MM)
2970 strHMS += StringUtils::Format(strHMS.empty() ? "{:02}" : ":{:02}", mm);
2971 if (format & TIME_FORMAT_SS)
2972 strHMS += StringUtils::Format(strHMS.empty() ? "{:02}" : ":{:02}", ss);
2973 }
2974
2975 if (isNegative)
2976 strHMS = "-" + strHMS;
2977
2978 return strHMS;
2979 }
2980 //----------------------------------------------------------------------------
2981
2982 //============================================================================
3007 inline static int DateStringToYYYYMMDD(const std::string& dateString)
3008 {
3009 std::vector<std::string> days = StringUtils::Split(dateString, '-');
3010 if (days.size() == 1)
3011 return atoi(days[0].c_str());
3012 else if (days.size() == 2)
3013 return atoi(days[0].c_str()) * 100 + atoi(days[1].c_str());
3014 else if (days.size() == 3)
3015 return atoi(days[0].c_str()) * 10000 + atoi(days[1].c_str()) * 100 + atoi(days[2].c_str());
3016 else
3017 return -1;
3018 }
3019 //----------------------------------------------------------------------------
3020
3023private:
3024 inline static int compareWchar(const void* a, const void* b)
3025 {
3026 if (*static_cast<const wchar_t*>(a) < *static_cast<const wchar_t*>(b))
3027 return -1;
3028 else if (*static_cast<const wchar_t*>(a) > *static_cast<const wchar_t*>(b))
3029 return 1;
3030 return 0;
3031 }
3032
3033 inline static wchar_t tolowerUnicode(const wchar_t& c)
3034 {
3035 wchar_t* p =
3036 static_cast<wchar_t*>(bsearch(&c, unicode_uppers, sizeof(unicode_uppers) / sizeof(wchar_t),
3037 sizeof(wchar_t), compareWchar));
3038 if (p)
3039 return *(unicode_lowers + (p - unicode_uppers));
3040
3041 return c;
3042 }
3043
3044 inline static wchar_t toupperUnicode(const wchar_t& c)
3045 {
3046 wchar_t* p =
3047 static_cast<wchar_t*>(bsearch(&c, unicode_lowers, sizeof(unicode_lowers) / sizeof(wchar_t),
3048 sizeof(wchar_t), compareWchar));
3049 if (p)
3050 return *(unicode_uppers + (p - unicode_lowers));
3051
3052 return c;
3053 }
3054
3055 static uint32_t UTF8ToUnicode(const unsigned char* z, int nKey, unsigned char& bytes)
3056 {
3057 // Lookup table used decode the first byte of a multi-byte UTF8 character
3058 // clang-format off
3059 static const unsigned char utf8Trans1[] = {
3060 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
3061 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
3062 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
3063 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
3064 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
3065 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
3066 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
3067 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x00, 0x00,
3068 };
3069 // clang-format on
3070
3071 uint32_t c;
3072 bytes = 0;
3073 c = z[0];
3074 if (c >= 0xc0)
3075 {
3076 c = utf8Trans1[c - 0xc0];
3077 int index = 1;
3078 while (index < nKey && (z[index] & 0xc0) == 0x80)
3079 {
3080 c = (c << 6) + (0x3f & z[index]);
3081 index++;
3082 }
3083 if (c < 0x80 || (c & 0xFFFFF800) == 0xD800 || (c & 0xFFFFFFFE) == 0xFFFE)
3084 c = 0xFFFD;
3085 bytes = static_cast<unsigned char>(index - 1);
3086 }
3087 return c;
3088 }
3089};
3091//------------------------------------------------------------------------------
3092
3093} /* namespace tools */
3094} /* namespace kodi */
3095
3096#endif /* __cplusplus */
Definition StringUtils.h:472
static bool EndsWith(const std::string &str1, const char *s2)
Checks a string for the ending of another string.
Definition StringUtils.h:1834
static int CompareNoCase(const char *s1, const char *s2, size_t n=0)
Compare two strings with ignore of lower-/uppercase with given size.
Definition StringUtils.h:1639
static bool IsAsciiUppercaseLetter(char chr)
Checks a character is ascii alphabetic lowercase.
Definition StringUtils.h:2231
static bool ContainsKeyword(const std::string &str, const std::vector< std::string > &keywords)
Check a string for another text.
Definition StringUtils.h:2268
static int AsciiDigitValue(char chr)
Translate a character where defined as a numerical value (0-9) string to right integer.
Definition StringUtils.h:2194
static int IsSpace(char c)
Check given character is a space.
Definition StringUtils.h:2031
static bool IsAsciiAlphaNum(char chr)
Checks a character is within ascii alphabetic and numerical fields.
Definition StringUtils.h:2255
static bool IsAsciiXDigit(char chr)
Checks a character is ascii hexadecimal number.
Definition StringUtils.h:2181
static int AsciiXDigitValue(char chr)
Translate a character where defined as a hexadecimal value string to right integer.
Definition StringUtils.h:2211
static size_t Utf8StringLength(const char *s)
UTF8 version of strlen.
Definition StringUtils.h:2010
static bool StartsWith(const std::string &str1, const char *s2)
Checks a string for the begin of another string.
Definition StringUtils.h:1696
static bool StartsWithNoCase(const char *s1, const char *s2)
Checks a string for the begin of another string by ignore of upper-/lowercase.
Definition StringUtils.h:1781
static int IsUTF8Letter(const unsigned char *str)
Checks given pointer in string is a UTF8 letter.
Definition StringUtils.h:2043
static bool EqualsNoCase(const char *s1, const char *s2)
Compare two strings with ignore of lower-/uppercase.
Definition StringUtils.h:1591
static bool IsInteger(const std::string &str)
Check whether a string is an integer.
Definition StringUtils.h:2144
static bool EqualsNoCase(const std::string &str1, const char *s2)
Compare two strings with ignore of lower-/uppercase.
Definition StringUtils.h:1578
static bool StartsWithNoCase(const std::string &str1, const std::string &str2)
Checks a string for the begin of another string by ignore of upper-/lowercase.
Definition StringUtils.h:1751
static bool IsAsciiLowercaseLetter(char chr)
Checks a character is ascii alphabetic lowercase.
Definition StringUtils.h:2243
static bool StartsWith(const char *s1, const char *s2)
Checks a string for the begin of another string.
Definition StringUtils.h:1710
static bool IsNaturalNumber(const std::string &str)
Check whether a string is a natural number.
Definition StringUtils.h:2100
static bool StartsWith(const std::string &str1, const std::string &str2)
Checks a string for the begin of another string.
Definition StringUtils.h:1682
static int CompareNoCase(const std::string &str1, const std::string &str2, size_t n=0)
Compare two strings with ignore of lower-/uppercase with given size.
Definition StringUtils.h:1620
static bool EndsWith(const std::string &str1, const std::string &str2)
Checks a string for the ending of another string.
Definition StringUtils.h:1818
static bool EqualsNoCase(const std::string &str1, const std::string &str2)
Compare two strings with ignore of lower-/uppercase.
Definition StringUtils.h:1561
static int64_t AlphaNumericCompare(const wchar_t *left, const wchar_t *right)
Compare two strings by his calculated alpha numeric values.
Definition StringUtils.h:1936
static bool StartsWithNoCase(const std::string &str1, const char *s2)
Checks a string for the begin of another string by ignore of upper-/lowercase.
Definition StringUtils.h:1766
static bool EndsWithNoCase(const std::string &str1, const char *s2)
Checks a string for the ending of another string by ignore of upper-/lowercase.
Definition StringUtils.h:1894
static bool EndsWithNoCase(const std::string &str1, const std::string &str2)
Checks a string for the ending of another string by ignore of upper-/lowercase.
Definition StringUtils.h:1868
static bool IsAasciiDigit(char chr)
Checks a character is ascii number.
Definition StringUtils.h:2169
TIME_FORMAT
Definition StringUtils.h:401
@ TIME_FORMAT_SS
ss - seconds only
Definition StringUtils.h:406
@ TIME_FORMAT_H_MM_SS_XX
hh:mm:ss xx - returns hours (1-digit), minutes and seconds in a 12-hour clock format (AM/PM)
Definition StringUtils.h:442
@ TIME_FORMAT_GUESS
Usually used as the fallback value if the format value is empty.
Definition StringUtils.h:403
@ TIME_FORMAT_HH_MM_SS
hh:mm:ss - hours, minutes and seconds
Definition StringUtils.h:424
@ TIME_FORMAT_M
m - minutes only (1-digit)
Definition StringUtils.h:454
@ TIME_FORMAT_MINS
mins - total time in minutes
Definition StringUtils.h:448
@ TIME_FORMAT_HOURS
hours - total time in hours
Definition StringUtils.h:451
@ TIME_FORMAT_MM_SS
mm:ss - minutes and seconds
Definition StringUtils.h:412
@ TIME_FORMAT_HH_MM_XX
hh:mm xx - returns hours and minutes in a 12-hour clock format (AM/PM)
Definition StringUtils.h:430
@ TIME_FORMAT_XX
xx - returns AM/PM for a 12-hour clock
Definition StringUtils.h:427
@ TIME_FORMAT_H
h - hours only (1-digit)
Definition StringUtils.h:436
@ TIME_FORMAT_HH_MM_SS_XX
hh:mm:ss xx - returns hours (2-digit), minutes and seconds in a 12-hour clock format (AM/PM)
Definition StringUtils.h:433
@ TIME_FORMAT_H_MM_SS
hh:mm:ss - hours, minutes and seconds
Definition StringUtils.h:439
@ TIME_FORMAT_HH_MM
hh:mm - hours and minutes
Definition StringUtils.h:421
@ TIME_FORMAT_MM
mm - minutes only (2-digit)
Definition StringUtils.h:409
@ TIME_FORMAT_SECS
secs - total time in seconds
Definition StringUtils.h:445
@ TIME_FORMAT_HH_SS
hh:ss - hours and seconds (this is not particularly useful)
Definition StringUtils.h:418
@ TIME_FORMAT_HH
hh - hours only (2-digit)
Definition StringUtils.h:415
static const std::string Empty
Defines a static empty std::string.
Definition StringUtils.h:478
static std::string & TrimLeft(std::string &str)
Trim a string with remove of not wanted spaces at begin of string.
Definition StringUtils.h:1145
static int Replace(std::string &str, char oldChar, char newChar)
Replace a character with another inside text string.
Definition StringUtils.h:1274
static void ToLower(std::wstring &str)
Convert a 16bit wide string to lowercase.
Definition StringUtils.h:924
static std::string & TrimLeft(std::string &str, const char *const chars)
Trim a string with remove of not wanted characters at begin of string.
Definition StringUtils.h:1162
static void ToUpper(std::wstring &str)
Convert a 16bit wide string to uppercase.
Definition StringUtils.h:889
static int Replace(std::wstring &str, const std::wstring &oldStr, const std::wstring &newStr)
Replace a complete text with another inside 16bit wide text string.
Definition StringUtils.h:1341
static std::string & Trim(std::string &str)
Trim a string with remove of not wanted spaces at begin and end of string.
Definition StringUtils.h:1102
static void RemoveCRLF(std::string &strLine)
Remove carriage return and line feeds on string ends.
Definition StringUtils.h:1456
static std::string MakeSafeString(const std::string &str)
Transform characters to create a safe, printable string.
Definition StringUtils.h:1405
static std::string RemoveMACAddress(const std::string &str)
Removes a MAC address from a given string.
Definition StringUtils.h:1430
static void ToUpper(std::string &str)
Convert a string to uppercase.
Definition StringUtils.h:878
static std::string Left(const std::string &str, size_t count)
Returns a string from start with givent count.
Definition StringUtils.h:978
static std::string & TrimRight(std::string &str, const char *const chars)
Trim a string with remove of not wanted characters at end of string.
Definition StringUtils.h:1207
static std::string Right(const std::string &str, size_t count)
Returns a string from end with givent count.
Definition StringUtils.h:1074
static int Replace(std::string &str, const std::string &oldStr, const std::string &newStr)
Replace a complete text with another inside text string.
Definition StringUtils.h:1314
static void ToLower(std::string &str)
Convert a string to lowercase.
Definition StringUtils.h:913
static std::string MakeSafeUrl(const std::string &str)
Transform characters to create a safe URL.
Definition StringUtils.h:1375
static std::string Paramify(const std::string &param)
Escapes the given string to be able to be used as a parameter.
Definition StringUtils.h:1518
static std::string Mid(const std::string &str, size_t first, size_t count=std::string::npos)
Get substring from mid of given string.
Definition StringUtils.h:1028
static void WordToDigits(std::string &word)
Convert a word to a digit numerical string.
Definition StringUtils.h:1479
static std::string & TrimRight(std::string &str)
Trim a string with remove of not wanted spaces at end of string.
Definition StringUtils.h:1190
static std::string & RemoveDuplicatedSpacesAndTabs(std::string &str)
Cleanup string by remove of duplicates of spaces and tabs.
Definition StringUtils.h:1222
static std::string & Trim(std::string &str, const char *const chars)
Trim a string with remove of not wanted characters at begin and end of string.
Definition StringUtils.h:1118
static int ReturnDigits(const std::string &str)
Combine all numerical digits and give it as integer value.
Definition StringUtils.h:936
static std::string FormatV(PRINTF_FORMAT_STRING const char *fmt, va_list args)
Returns the C++ string pointed by given format list.
Definition StringUtils.h:604
static std::wstring Format(const wchar_t *fmt,...)
Returns the C++ wide string pointed by given format.
Definition StringUtils.h:584
static std::wstring FormatV(PRINTF_FORMAT_STRING const wchar_t *fmt, va_list args)
Returns the C++ wide string pointed by given format list.
Definition StringUtils.h:658
static std::string BinaryStringToString(const std::string &in)
Convert the string of binary chars to the actual string.
Definition StringUtils.h:785
static std::string ToHexadecimal(const std::string &in)
Convert each character in the string to its hexadecimal representation and return the concatenated re...
Definition StringUtils.h:838
static std::string FormatFileSize(uint64_t bytes)
Returns bytes in a human readable format using the smallest unit that will fit bytes in at most three...
Definition StringUtils.h:756
static std::string Format(const char *fmt,...)
Returns the C++ string pointed by given format. If format includes format specifiers (subsequences be...
Definition StringUtils.h:558
static std::vector< std::string > Tokenize(const std::string &input, const std::string &delimiters)
Split a string by the specified delimiters.
Definition StringUtils.h:2778
static void Tokenize(const std::string &input, std::vector< std::string > &tokens, const char delimiter)
Tokenizing a string denotes splitting a string with respect to a delimiter.
Definition StringUtils.h:2838
static std::vector< std::string > Split(const std::string &input, const std::string &delimiter, unsigned int iMaxStrings=0)
Splits the given input string using the given delimiter into separate strings.
Definition StringUtils.h:2527
static OutputIt SplitTo(OutputIt d_first, const std::string &input, const std::vector< std::string > &delimiters)
Splits the given input string using the given delimiter into separate strings.
Definition StringUtils.h:2668
static std::vector< std::string > Split(const std::string &input, const char delimiter, int iMaxStrings=0)
Splits the given input string using the given delimiter into separate strings.
Definition StringUtils.h:2549
static std::vector< std::string > Tokenize(const std::string &input, const char delimiter)
Tokenizing a string denotes splitting a string with respect to a delimiter.
Definition StringUtils.h:2822
static std::vector< std::string > SplitMulti(const std::vector< std::string > &input, const std::vector< std::string > &delimiters, unsigned int iMaxStrings=0)
Splits the given input strings using the given delimiters into further separate strings.
Definition StringUtils.h:2706
static OutputIt SplitTo(OutputIt d_first, const std::string &input, const std::string &delimiter, unsigned int iMaxStrings=0)
Splits the given input string using the given delimiter into separate strings.
Definition StringUtils.h:2595
static std::string Join(const CONTAINER &strings, const std::string &delimiter)
Concatenates the elements of a specified array or the members of a collection and uses the specified ...
Definition StringUtils.h:2485
static void Tokenize(const std::string &input, std::vector< std::string > &tokens, const std::string &delimiters)
Tokenizing a string denotes splitting a string with respect to a delimiter.
Definition StringUtils.h:2795
static std::vector< std::string > Split(const std::string &input, const std::vector< std::string > &delimiters)
Splits the given input string using the given delimiter into separate strings.
Definition StringUtils.h:2571
static OutputIt SplitTo(OutputIt d_first, const std::string &input, const char delimiter, int iMaxStrings=0)
Splits the given input string using the given delimiter into separate strings.
Definition StringUtils.h:2644
static int FindNumber(const std::string &strInput, const std::string &strFind)
Search a text and return the number of parts found as a number.
Definition StringUtils.h:2428
static size_t FindEndBracket(const std::string &str, char opener, char closer, size_t startPos=0)
Search a string for a given bracket and give its end position.
Definition StringUtils.h:2389
static size_t FindWords(const char *str, const char *wordLowerCase)
Search for a single word within a text.
Definition StringUtils.h:2318
static long TimeStringToSeconds(const std::string &timeString)
Converts a time string to the respective integer value.
Definition StringUtils.h:2895
static int DateStringToYYYYMMDD(const std::string &dateString)
Converts a string in the format YYYYMMDD to the corresponding integer value.
Definition StringUtils.h:3007
static std::string SecondsToTimeString(long seconds, TIME_FORMAT format=TIME_FORMAT_GUESS)
Convert a time in seconds to a string based on the given time format.
Definition StringUtils.h:2941