Kodi Development 22.0
for Binary and Script based Add-Ons
 
All Classes Functions Variables Typedefs Enumerations Enumerator Modules Pages
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//==============================================================================
456
457//------------------------------------------------------------------------------
458
459//==============================================================================
472{
473public:
474 //============================================================================
478 static const std::string Empty;
479 //----------------------------------------------------------------------------
480
481 //----------------------------------------------------------------------------
487
488
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
851
852 //----------------------------------------------------------------------------
858
859
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) { StringUtils::TrimRight(strLine, "\n\r"); }
1457 //----------------------------------------------------------------------------
1458
1459 //============================================================================
1477 inline static void WordToDigits(std::string& word)
1478 {
1479 static const char word_to_letter[] = "22233344455566677778889999";
1481 for (unsigned int i = 0; i < word.size(); ++i)
1482 { // NB: This assumes ascii, which probably needs extending at some point.
1483 char letter = word[i];
1484 if ((letter >= 'a' && letter <= 'z')) // assume contiguous letter range
1485 {
1486 word[i] = word_to_letter[letter - 'a'];
1487 }
1488 else if (letter < '0' || letter > '9') // We want to keep 0-9!
1489 {
1490 word[i] = ' '; // replace everything else with a space
1491 }
1492 }
1493 }
1494 //----------------------------------------------------------------------------
1495
1496 //============================================================================
1516 inline static std::string Paramify(const std::string& param)
1517 {
1518 std::string result = param;
1519 // escape backspaces
1520 StringUtils::Replace(result, "\\", "\\\\");
1521 // escape double quotes
1522 StringUtils::Replace(result, "\"", "\\\"");
1523
1524 // add double quotes around the whole string
1525 return "\"" + result + "\"";
1526 }
1527 //----------------------------------------------------------------------------
1528
1530
1531 //----------------------------------------------------------------------------
1538
1539
1540 //============================================================================
1559 inline static bool EqualsNoCase(const std::string& str1, const std::string& str2)
1560 {
1561 // before we do the char-by-char comparison, first compare sizes of both strings.
1562 // This led to a 33% improvement in benchmarking on average. (size() just returns a member of std::string)
1563 if (str1.size() != str2.size())
1564 return false;
1565 return EqualsNoCase(str1.c_str(), str2.c_str());
1566 }
1567 //----------------------------------------------------------------------------
1568
1569 //============================================================================
1576 inline static bool EqualsNoCase(const std::string& str1, const char* s2)
1577 {
1578 return EqualsNoCase(str1.c_str(), s2);
1579 }
1580 //----------------------------------------------------------------------------
1581
1582 //============================================================================
1589 inline static bool EqualsNoCase(const char* s1, const char* s2)
1590 {
1591 char c2; // we need only one char outside the loop
1592 do
1593 {
1594 const char c1 = *s1++; // const local variable should help compiler to optimize
1595 c2 = *s2++;
1596 // This includes the possibility that one of the characters is the null-terminator,
1597 // which implies a string mismatch.
1598 if (c1 != c2 && ::tolower(c1) != ::tolower(c2))
1599 return false;
1600 } while (c2 != '\0'); // At this point, we know c1 == c2, so there's no need to test them both.
1601 return true;
1602 }
1603 //----------------------------------------------------------------------------
1604
1605 //============================================================================
1618 inline static int CompareNoCase(const std::string& str1, const std::string& str2, size_t n = 0)
1619 {
1620 return CompareNoCase(str1.c_str(), str2.c_str(), n);
1621 }
1622 //----------------------------------------------------------------------------
1623
1624 //============================================================================
1637 inline static int CompareNoCase(const char* s1, const char* s2, size_t n = 0)
1638 {
1639 char c2; // we need only one char outside the loop
1640 size_t index = 0;
1641 do
1642 {
1643 const char c1 = *s1++; // const local variable should help compiler to optimize
1644 c2 = *s2++;
1645 index++;
1646 // This includes the possibility that one of the characters is the null-terminator,
1647 // which implies a string mismatch.
1648 if (c1 != c2 && ::tolower(c1) != ::tolower(c2))
1649 return ::tolower(c1) - ::tolower(c2);
1650 } while (c2 != '\0' &&
1651 index != n); // At this point, we know c1 == c2, so there's no need to test them both.
1652 return 0;
1653 }
1654 //----------------------------------------------------------------------------
1655
1656 //============================================================================
1680 inline static bool StartsWith(const std::string& str1, const std::string& str2)
1681 {
1682 return str1.compare(0, str2.size(), str2) == 0;
1683 }
1684 //----------------------------------------------------------------------------
1685
1686 //============================================================================
1694 inline static bool StartsWith(const std::string& str1, const char* s2)
1695 {
1696 return StartsWith(str1.c_str(), s2);
1697 }
1698 //----------------------------------------------------------------------------
1699
1700 //============================================================================
1708 inline static bool StartsWith(const char* s1, const char* s2)
1709 {
1710 while (*s2 != '\0')
1711 {
1712 if (*s1 != *s2)
1713 return false;
1714 s1++;
1715 s2++;
1716 }
1717 return true;
1718 }
1719 //----------------------------------------------------------------------------
1720
1721 //============================================================================
1749 inline static bool StartsWithNoCase(const std::string& str1, const std::string& str2)
1750 {
1751 return StartsWithNoCase(str1.c_str(), str2.c_str());
1752 }
1753 //----------------------------------------------------------------------------
1754
1755 //============================================================================
1764 inline static bool StartsWithNoCase(const std::string& str1, const char* s2)
1765 {
1766 return StartsWithNoCase(str1.c_str(), s2);
1767 }
1768 //----------------------------------------------------------------------------
1769
1770 //============================================================================
1779 inline static bool StartsWithNoCase(const char* s1, const char* s2)
1780 {
1781 while (*s2 != '\0')
1782 {
1783 if (::tolower(*s1) != ::tolower(*s2))
1784 return false;
1785 s1++;
1786 s2++;
1787 }
1788 return true;
1789 }
1790 //----------------------------------------------------------------------------
1791
1792 //============================================================================
1816 inline static bool EndsWith(const std::string& str1, const std::string& str2)
1817 {
1818 if (str1.size() < str2.size())
1819 return false;
1820 return str1.compare(str1.size() - str2.size(), str2.size(), str2) == 0;
1821 }
1822 //----------------------------------------------------------------------------
1823
1824 //============================================================================
1832 inline static bool EndsWith(const std::string& str1, const char* s2)
1833 {
1834 size_t len2 = strlen(s2);
1835 if (str1.size() < len2)
1836 return false;
1837 return str1.compare(str1.size() - len2, len2, s2) == 0;
1838 }
1839 //----------------------------------------------------------------------------
1840
1841 //============================================================================
1866 inline static bool EndsWithNoCase(const std::string& str1, const std::string& str2)
1867 {
1868 if (str1.size() < str2.size())
1869 return false;
1870 const char* s1 = str1.c_str() + str1.size() - str2.size();
1871 const char* s2 = str2.c_str();
1872 while (*s2 != '\0')
1873 {
1874 if (::tolower(*s1) != ::tolower(*s2))
1875 return false;
1876 s1++;
1877 s2++;
1878 }
1879 return true;
1880 }
1881 //----------------------------------------------------------------------------
1882
1883 //============================================================================
1892 inline static bool EndsWithNoCase(const std::string& str1, const char* s2)
1893 {
1894 size_t len2 = strlen(s2);
1895 if (str1.size() < len2)
1896 return false;
1897 const char* s1 = str1.c_str() + str1.size() - len2;
1898 while (*s2 != '\0')
1899 {
1900 if (::tolower(*s1) != ::tolower(*s2))
1901 return false;
1902 s1++;
1903 s2++;
1904 }
1905 return true;
1906 }
1907 //----------------------------------------------------------------------------
1908
1909 //============================================================================
1934 inline static int64_t AlphaNumericCompare(const wchar_t* left, const wchar_t* right)
1935 {
1936 const wchar_t* l = left;
1937 const wchar_t* r = right;
1938 const wchar_t *ld, *rd;
1939 wchar_t lc, rc;
1940 int64_t lnum, rnum;
1941 const std::collate<wchar_t>& coll = std::use_facet<std::collate<wchar_t>>(std::locale());
1942 int cmp_res = 0;
1943 while (*l != 0 && *r != 0)
1944 {
1945 // check if we have a numerical value
1946 if (*l >= L'0' && *l <= L'9' && *r >= L'0' && *r <= L'9')
1947 {
1948 ld = l;
1949 lnum = 0;
1950 while (*ld >= L'0' && *ld <= L'9' && ld < l + 15)
1951 { // compare only up to 15 digits
1952 lnum *= 10;
1953 lnum += *ld++ - '0';
1954 }
1955 rd = r;
1956 rnum = 0;
1957 while (*rd >= L'0' && *rd <= L'9' && rd < r + 15)
1958 { // compare only up to 15 digits
1959 rnum *= 10;
1960 rnum += *rd++ - L'0';
1961 }
1962 // do we have numbers?
1963 if (lnum != rnum)
1964 { // yes - and they're different!
1965 return lnum - rnum;
1966 }
1967 l = ld;
1968 r = rd;
1969 continue;
1970 }
1971 // do case less comparison
1972 lc = *l;
1973 if (lc >= L'A' && lc <= L'Z')
1974 lc += L'a' - L'A';
1975 rc = *r;
1976 if (rc >= L'A' && rc <= L'Z')
1977 rc += L'a' - L'A';
1978
1979 // ok, do a normal comparison, taking current locale into account. Add special case stuff (eg '(' characters)) in here later
1980 if ((cmp_res = coll.compare(&lc, &lc + 1, &rc, &rc + 1)) != 0)
1981 {
1982 return cmp_res;
1983 }
1984 l++;
1985 r++;
1986 }
1987 if (*r)
1988 { // r is longer
1989 return -1;
1990 }
1991 else if (*l)
1992 { // l is longer
1993 return 1;
1994 }
1995 return 0; // files are the same
1996 }
1997 //----------------------------------------------------------------------------
1998
1999 //============================================================================
2008 inline static size_t Utf8StringLength(const char* s)
2009 {
2010 size_t length = 0;
2011 while (*s)
2012 {
2013 if ((*s++ & 0xC0) != 0x80)
2014 length++;
2015 }
2016 return length;
2017 }
2018 //----------------------------------------------------------------------------
2019
2020 //============================================================================
2029 inline static int IsSpace(char c) { return (c & 0x80) == 0 && ::isspace(c); }
2030 //----------------------------------------------------------------------------
2031
2032 //============================================================================
2038 inline static int IsUTF8Letter(const unsigned char* str)
2039 {
2040 // reference:
2041 // unicode -> utf8 table: http://www.utf8-chartable.de/
2042 // latin characters in unicode: http://en.wikipedia.org/wiki/Latin_characters_in_Unicode
2043 unsigned char ch = str[0];
2044 if (!ch)
2045 return -1;
2046 if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))
2047 return 1;
2048 if (!(ch & 0x80))
2049 return -1;
2050 unsigned char ch2 = str[1];
2051 if (!ch2)
2052 return -1;
2053 // check latin 1 letter table: http://en.wikipedia.org/wiki/C1_Controls_and_Latin-1_Supplement
2054 if (ch == 0xC3 && ch2 >= 0x80 && ch2 <= 0xBF && ch2 != 0x97 && ch2 != 0xB7)
2055 return 2;
2056 // check latin extended A table: http://en.wikipedia.org/wiki/Latin_Extended-A
2057 if (ch >= 0xC4 && ch <= 0xC7 && ch2 >= 0x80 && ch2 <= 0xBF)
2058 return 2;
2059 // check latin extended B table: http://en.wikipedia.org/wiki/Latin_Extended-B
2060 // and International Phonetic Alphabet: http://en.wikipedia.org/wiki/IPA_Extensions_(Unicode_block)
2061 if (((ch == 0xC8 || ch == 0xC9) && ch2 >= 0x80 && ch2 <= 0xBF) ||
2062 (ch == 0xCA && ch2 >= 0x80 && ch2 <= 0xAF))
2063 return 2;
2064 return -1;
2065 }
2066 //----------------------------------------------------------------------------
2067
2068 //============================================================================
2095 inline static bool IsNaturalNumber(const std::string& str)
2096 {
2097 size_t i = 0, n = 0;
2098 // allow whitespace,digits,whitespace
2099 while (i < str.size() && isspace((unsigned char)str[i]))
2100 i++;
2101 while (i < str.size() && isdigit((unsigned char)str[i]))
2102 {
2103 i++;
2104 n++;
2105 }
2106 while (i < str.size() && isspace((unsigned char)str[i]))
2107 i++;
2108 return i == str.size() && n > 0;
2109 }
2110 //----------------------------------------------------------------------------
2111
2112 //============================================================================
2139 inline static bool IsInteger(const std::string& str)
2140 {
2141 size_t i = 0, n = 0;
2142 // allow whitespace,-,digits,whitespace
2143 while (i < str.size() && isspace((unsigned char)str[i]))
2144 i++;
2145 if (i < str.size() && str[i] == '-')
2146 i++;
2147 while (i < str.size() && isdigit((unsigned char)str[i]))
2148 {
2149 i++;
2150 n++;
2151 }
2152 while (i < str.size() && isspace((unsigned char)str[i]))
2153 i++;
2154 return i == str.size() && n > 0;
2155 }
2156 //----------------------------------------------------------------------------
2157
2158 //============================================================================
2164 inline static bool IsAasciiDigit(char chr) // locale independent
2165 {
2166 return chr >= '0' && chr <= '9';
2167 }
2168 //----------------------------------------------------------------------------
2169
2170 //============================================================================
2176 inline static bool IsAsciiXDigit(char chr) // locale independent
2177 {
2178 return (chr >= '0' && chr <= '9') || (chr >= 'a' && chr <= 'f') || (chr >= 'A' && chr <= 'F');
2179 }
2180 //----------------------------------------------------------------------------
2181
2182 //============================================================================
2189 inline static int AsciiDigitValue(char chr) // locale independent
2190 {
2191 if (!IsAasciiDigit(chr))
2192 return -1;
2193
2194 return chr - '0';
2195 }
2196 //----------------------------------------------------------------------------
2197
2198 //============================================================================
2206 inline static int AsciiXDigitValue(char chr) // locale independent
2207 {
2208 int v = AsciiDigitValue(chr);
2209 if (v >= 0)
2210 return v;
2211 if (chr >= 'a' && chr <= 'f')
2212 return chr - 'a' + 10;
2213 if (chr >= 'A' && chr <= 'F')
2214 return chr - 'A' + 10;
2215
2216 return -1;
2217 }
2218 //----------------------------------------------------------------------------
2219
2220 //============================================================================
2226 inline static bool IsAsciiUppercaseLetter(char chr) // locale independent
2227 {
2228 return (chr >= 'A' && chr <= 'Z');
2229 }
2230 //----------------------------------------------------------------------------
2231
2232 //============================================================================
2238 inline static bool IsAsciiLowercaseLetter(char chr) // locale independent
2239 {
2240 return (chr >= 'a' && chr <= 'z');
2241 }
2242 //----------------------------------------------------------------------------
2243
2244 //============================================================================
2250 inline static bool IsAsciiAlphaNum(char chr) // locale independent
2251 {
2253 }
2254 //----------------------------------------------------------------------------
2255
2256 //============================================================================
2263 inline static bool ContainsKeyword(const std::string& str,
2264 const std::vector<std::string>& keywords)
2265 {
2266 for (const auto& it : keywords)
2267 {
2268 if (str.find(it) != str.npos)
2269 return true;
2270 }
2271 return false;
2272 }
2273 //----------------------------------------------------------------------------
2274
2276
2277 //----------------------------------------------------------------------------
2284
2285
2286 //============================================================================
2313 inline static size_t FindWords(const char* str, const char* wordLowerCase)
2314 {
2315 // NOTE: This assumes word is lowercase!
2316 const unsigned char* s = (const unsigned char*)str;
2317 do
2318 {
2319 // start with a compare
2320 const unsigned char* c = s;
2321 const unsigned char* w = (const unsigned char*)wordLowerCase;
2322 bool same = true;
2323 while (same && *c && *w)
2324 {
2325 unsigned char lc = *c++;
2326 if (lc >= 'A' && lc <= 'Z')
2327 lc += 'a' - 'A';
2328
2329 if (lc != *w++) // different
2330 same = false;
2331 }
2332 if (same && *w == 0) // only the same if word has been exhausted
2333 return (const char*)s - str;
2334
2335 // otherwise, skip current word (composed by latin letters) or number
2336 int l;
2337 if (*s >= '0' && *s <= '9')
2338 {
2339 ++s;
2340 while (*s >= '0' && *s <= '9')
2341 ++s;
2342 }
2343 else if ((l = IsUTF8Letter(s)) > 0)
2344 {
2345 s += l;
2346 while ((l = IsUTF8Letter(s)) > 0)
2347 s += l;
2348 }
2349 else
2350 ++s;
2351 while (*s && *s == ' ')
2352 s++;
2353
2354 // and repeat until we're done
2355 } while (*s);
2356
2357 return std::string::npos;
2358 }
2359 //----------------------------------------------------------------------------
2360
2361 //============================================================================
2384 inline static size_t FindEndBracket(const std::string& str,
2385 char opener,
2386 char closer,
2387 size_t startPos = 0)
2388 {
2389 size_t blocks = 1;
2390 for (size_t i = startPos; i < str.size(); i++)
2391 {
2392 if (str[i] == opener)
2393 blocks++;
2394 else if (str[i] == closer)
2395 {
2396 blocks--;
2397 if (!blocks)
2398 return i;
2399 }
2400 }
2401
2402 return std::string::npos;
2403 }
2404 //----------------------------------------------------------------------------
2405
2406 //============================================================================
2423 inline static int FindNumber(const std::string& strInput, const std::string& strFind)
2424 {
2425 size_t pos = strInput.find(strFind, 0);
2426 int numfound = 0;
2427 while (pos != std::string::npos)
2428 {
2429 numfound++;
2430 pos = strInput.find(strFind, pos + 1);
2431 }
2432 return numfound;
2433 }
2434 //----------------------------------------------------------------------------
2435
2437
2438 //----------------------------------------------------------------------------
2445
2446
2447 //============================================================================
2479 template<typename CONTAINER>
2480 inline static std::string Join(const CONTAINER& strings, const std::string& delimiter)
2481 {
2482 std::string result;
2483 for (const auto& str : strings)
2484 result += str + delimiter;
2485
2486 if (!result.empty())
2487 result.erase(result.size() - delimiter.size());
2488 return result;
2489 }
2490 //----------------------------------------------------------------------------
2491
2492 //============================================================================
2522 inline static std::vector<std::string> Split(const std::string& input,
2523 const std::string& delimiter,
2524 unsigned int iMaxStrings = 0)
2525 {
2526 std::vector<std::string> result;
2527 SplitTo(std::back_inserter(result), input, delimiter, iMaxStrings);
2528 return result;
2529 }
2530 //----------------------------------------------------------------------------
2531
2532 //============================================================================
2544 inline static std::vector<std::string> Split(const std::string& input,
2545 const char delimiter,
2546 int iMaxStrings = 0)
2547 {
2548 std::vector<std::string> result;
2549 SplitTo(std::back_inserter(result), input, delimiter, iMaxStrings);
2550 return result;
2551 }
2552 //----------------------------------------------------------------------------
2553
2554 //============================================================================
2566 inline static std::vector<std::string> Split(const std::string& input,
2567 const std::vector<std::string>& delimiters)
2568 {
2569 std::vector<std::string> result;
2570 SplitTo(std::back_inserter(result), input, delimiters);
2571 return result;
2572 }
2573 //----------------------------------------------------------------------------
2574
2575 //============================================================================
2589 template<typename OutputIt>
2590 inline static OutputIt SplitTo(OutputIt d_first,
2591 const std::string& input,
2592 const std::string& delimiter,
2593 unsigned int iMaxStrings = 0)
2594 {
2595 OutputIt dest = d_first;
2596
2597 if (input.empty())
2598 return dest;
2599 if (delimiter.empty())
2600 {
2601 *d_first++ = input;
2602 return dest;
2603 }
2604
2605 const size_t delimLen = delimiter.length();
2606 size_t nextDelim;
2607 size_t textPos = 0;
2608 do
2609 {
2610 if (--iMaxStrings == 0)
2611 {
2612 *dest++ = input.substr(textPos);
2613 break;
2614 }
2615 nextDelim = input.find(delimiter, textPos);
2616 *dest++ = input.substr(textPos, nextDelim - textPos);
2617 textPos = nextDelim + delimLen;
2618 } while (nextDelim != std::string::npos);
2619
2620 return dest;
2621 }
2622 //----------------------------------------------------------------------------
2623
2624 //============================================================================
2638 template<typename OutputIt>
2639 inline static OutputIt SplitTo(OutputIt d_first,
2640 const std::string& input,
2641 const char delimiter,
2642 int iMaxStrings = 0)
2643 {
2644 return SplitTo(d_first, input, std::string(1, delimiter), iMaxStrings);
2645 }
2646 //----------------------------------------------------------------------------
2647
2648 //============================================================================
2662 template<typename OutputIt>
2663 inline static OutputIt SplitTo(OutputIt d_first,
2664 const std::string& input,
2665 const std::vector<std::string>& delimiters)
2666 {
2667 OutputIt dest = d_first;
2668 if (input.empty())
2669 return dest;
2670
2671 if (delimiters.empty())
2672 {
2673 *dest++ = input;
2674 return dest;
2675 }
2676 std::string str = input;
2677 for (size_t di = 1; di < delimiters.size(); di++)
2678 StringUtils::Replace(str, delimiters[di], delimiters[0]);
2679 return SplitTo(dest, str, delimiters[0]);
2680 }
2681 //----------------------------------------------------------------------------
2682
2683 //============================================================================
2701 inline static std::vector<std::string> SplitMulti(const std::vector<std::string>& input,
2702 const std::vector<std::string>& delimiters,
2703 unsigned int iMaxStrings = 0)
2704 {
2705 if (input.empty())
2706 return std::vector<std::string>();
2707
2708 std::vector<std::string> results(input);
2709
2710 if (delimiters.empty() || (iMaxStrings > 0 && iMaxStrings <= input.size()))
2711 return results;
2712
2713 std::vector<std::string> strings1;
2714 if (iMaxStrings == 0)
2715 {
2716 for (size_t di = 0; di < delimiters.size(); di++)
2717 {
2718 for (size_t i = 0; i < results.size(); i++)
2719 {
2720 std::vector<std::string> substrings = StringUtils::Split(results[i], delimiters[di]);
2721 for (size_t j = 0; j < substrings.size(); j++)
2722 strings1.push_back(substrings[j]);
2723 }
2724 results = strings1;
2725 strings1.clear();
2726 }
2727 return results;
2728 }
2729
2730 // Control the number of strings input is split into, keeping the original strings.
2731 // Note iMaxStrings > input.size()
2732 size_t iNew = iMaxStrings - results.size();
2733 for (size_t di = 0; di < delimiters.size(); di++)
2734 {
2735 for (size_t i = 0; i < results.size(); i++)
2736 {
2737 if (iNew > 0)
2738 {
2739 std::vector<std::string> substrings =
2740 StringUtils::Split(results[i], delimiters[di], static_cast<int>(iNew + 1));
2741 iNew = iNew - substrings.size() + 1;
2742 for (size_t j = 0; j < substrings.size(); j++)
2743 strings1.push_back(substrings[j]);
2744 }
2745 else
2746 strings1.push_back(results[i]);
2747 }
2748 results = strings1;
2749 iNew = iMaxStrings - results.size();
2750 strings1.clear();
2751 if ((iNew <= 0))
2752 break; //Stop trying any more delimiters
2753 }
2754 return results;
2755 }
2756 //----------------------------------------------------------------------------
2757
2758 //============================================================================
2773 inline static std::vector<std::string> Tokenize(const std::string& input,
2774 const std::string& delimiters)
2775 {
2776 std::vector<std::string> tokens;
2777 Tokenize(input, tokens, delimiters);
2778 return tokens;
2779 }
2780 //----------------------------------------------------------------------------
2781
2782 //============================================================================
2790 inline static void Tokenize(const std::string& input,
2791 std::vector<std::string>& tokens,
2792 const std::string& delimiters)
2793 {
2794 tokens.clear();
2795 // Skip delimiters at beginning.
2796 std::string::size_type dataPos = input.find_first_not_of(delimiters);
2797 while (dataPos != std::string::npos)
2798 {
2799 // Find next delimiter
2800 const std::string::size_type nextDelimPos = input.find_first_of(delimiters, dataPos);
2801 // Found a token, add it to the vector.
2802 tokens.push_back(input.substr(dataPos, nextDelimPos - dataPos));
2803 // Skip delimiters. Note the "not_of"
2804 dataPos = input.find_first_not_of(delimiters, nextDelimPos);
2805 }
2806 }
2807 //----------------------------------------------------------------------------
2808
2809 //============================================================================
2817 inline static std::vector<std::string> Tokenize(const std::string& input, const char delimiter)
2818 {
2819 std::vector<std::string> tokens;
2820 Tokenize(input, tokens, delimiter);
2821 return tokens;
2822 }
2823 //----------------------------------------------------------------------------
2824
2825 //============================================================================
2833 inline static void Tokenize(const std::string& input,
2834 std::vector<std::string>& tokens,
2835 const char delimiter)
2836 {
2837 tokens.clear();
2838 // Skip delimiters at beginning.
2839 std::string::size_type dataPos = input.find_first_not_of(delimiter);
2840 while (dataPos != std::string::npos)
2841 {
2842 // Find next delimiter
2843 const std::string::size_type nextDelimPos = input.find(delimiter, dataPos);
2844 // Found a token, add it to the vector.
2845 tokens.push_back(input.substr(dataPos, nextDelimPos - dataPos));
2846 // Skip delimiters. Note the "not_of"
2847 dataPos = input.find_first_not_of(delimiter, nextDelimPos);
2848 }
2849 }
2850 //----------------------------------------------------------------------------
2851
2853
2854 //----------------------------------------------------------------------------
2859
2860
2861 //============================================================================
2890 inline static long TimeStringToSeconds(const std::string& timeString)
2891 {
2892 std::string strCopy(timeString);
2893 StringUtils::Trim(strCopy);
2894 if (StringUtils::EndsWithNoCase(strCopy, " min"))
2895 {
2896 // this is imdb format of "XXX min"
2897 return 60 * atoi(strCopy.c_str());
2898 }
2899 else
2900 {
2901 std::vector<std::string> secs = StringUtils::Split(strCopy, ':');
2902 int timeInSecs = 0;
2903 for (unsigned int i = 0; i < 3 && i < secs.size(); i++)
2904 {
2905 timeInSecs *= 60;
2906 timeInSecs += atoi(secs[i].c_str());
2907 }
2908 return timeInSecs;
2909 }
2910 }
2911 //----------------------------------------------------------------------------
2912
2913 //============================================================================
2937 inline static std::string SecondsToTimeString(long seconds,
2939 {
2940 const bool isNegative = seconds < 0;
2941 seconds = std::abs(seconds);
2942
2943 std::string strHMS;
2944 if (format == TIME_FORMAT_SECS)
2945 strHMS = std::to_string(seconds);
2946 else if (format == TIME_FORMAT_MINS)
2947 strHMS = std::to_string(std::lrintf(static_cast<float>(seconds) / 60.0f));
2948 else if (format == TIME_FORMAT_HOURS)
2949 strHMS = std::to_string(std::lrintf(static_cast<float>(seconds) / 3600.0f));
2950 else if (format & TIME_FORMAT_M)
2951 strHMS += std::to_string(seconds % 3600 / 60);
2952 else
2953 {
2954 const long hh = seconds / 3600;
2955 seconds = seconds % 3600;
2956 const long mm = seconds / 60;
2957 unsigned int ss = seconds % 60;
2958
2959 if (format == TIME_FORMAT_GUESS)
2960 format = (hh >= 1) ? TIME_FORMAT_HH_MM_SS : TIME_FORMAT_MM_SS;
2961 if (format & TIME_FORMAT_HH)
2962 strHMS += StringUtils::Format("{:02}", hh);
2963 else if (format & TIME_FORMAT_H)
2964 strHMS += std::to_string(hh);
2965 if (format & TIME_FORMAT_MM)
2966 strHMS += StringUtils::Format(strHMS.empty() ? "{:02}" : ":{:02}", mm);
2967 if (format & TIME_FORMAT_SS)
2968 strHMS += StringUtils::Format(strHMS.empty() ? "{:02}" : ":{:02}", ss);
2969 }
2970
2971 if (isNegative)
2972 strHMS = "-" + strHMS;
2973
2974 return strHMS;
2975 }
2976 //----------------------------------------------------------------------------
2977
2978 //============================================================================
3003 inline static int DateStringToYYYYMMDD(const std::string& dateString)
3004 {
3005 std::vector<std::string> days = StringUtils::Split(dateString, '-');
3006 if (days.size() == 1)
3007 return atoi(days[0].c_str());
3008 else if (days.size() == 2)
3009 return atoi(days[0].c_str()) * 100 + atoi(days[1].c_str());
3010 else if (days.size() == 3)
3011 return atoi(days[0].c_str()) * 10000 + atoi(days[1].c_str()) * 100 + atoi(days[2].c_str());
3012 else
3013 return -1;
3014 }
3015 //----------------------------------------------------------------------------
3016
3018
3019private:
3020 inline static int compareWchar(const void* a, const void* b)
3021 {
3022 if (*static_cast<const wchar_t*>(a) < *static_cast<const wchar_t*>(b))
3023 return -1;
3024 else if (*static_cast<const wchar_t*>(a) > *static_cast<const wchar_t*>(b))
3025 return 1;
3026 return 0;
3027 }
3028
3029 inline static wchar_t tolowerUnicode(const wchar_t& c)
3030 {
3031 wchar_t* p =
3032 static_cast<wchar_t*>(bsearch(&c, unicode_uppers, sizeof(unicode_uppers) / sizeof(wchar_t),
3033 sizeof(wchar_t), compareWchar));
3034 if (p)
3035 return *(unicode_lowers + (p - unicode_uppers));
3036
3037 return c;
3038 }
3039
3040 inline static wchar_t toupperUnicode(const wchar_t& c)
3041 {
3042 wchar_t* p =
3043 static_cast<wchar_t*>(bsearch(&c, unicode_lowers, sizeof(unicode_lowers) / sizeof(wchar_t),
3044 sizeof(wchar_t), compareWchar));
3045 if (p)
3046 return *(unicode_uppers + (p - unicode_lowers));
3047
3048 return c;
3049 }
3050
3051 static uint32_t UTF8ToUnicode(const unsigned char* z, int nKey, unsigned char& bytes)
3052 {
3053 // Lookup table used decode the first byte of a multi-byte UTF8 character
3054 // clang-format off
3055 static const unsigned char utf8Trans1[] = {
3056 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
3057 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
3058 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
3059 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
3060 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
3061 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
3062 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
3063 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x00, 0x00,
3064 };
3065 // clang-format on
3066
3067 uint32_t c;
3068 bytes = 0;
3069 c = z[0];
3070 if (c >= 0xc0)
3071 {
3072 c = utf8Trans1[c - 0xc0];
3073 int index = 1;
3074 while (index < nKey && (z[index] & 0xc0) == 0x80)
3075 {
3076 c = (c << 6) + (0x3f & z[index]);
3077 index++;
3078 }
3079 if (c < 0x80 || (c & 0xFFFFF800) == 0xD800 || (c & 0xFFFFFFFE) == 0xFFFE)
3080 c = 0xFFFD;
3081 bytes = static_cast<unsigned char>(index - 1);
3082 }
3083 return c;
3084 }
3085};
3086
3087//------------------------------------------------------------------------------
3088
3089} /* namespace tools */
3090} /* namespace kodi */
3091
3092#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:1832
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:1637
static bool IsAsciiUppercaseLetter(char chr)
Checks a character is ascii alphabetic lowercase.
Definition StringUtils.h:2226
static bool ContainsKeyword(const std::string &str, const std::vector< std::string > &keywords)
Check a string for another text.
Definition StringUtils.h:2263
static int AsciiDigitValue(char chr)
Translate a character where defined as a numerical value (0-9) string to right integer.
Definition StringUtils.h:2189
static int IsSpace(char c)
Check given character is a space.
Definition StringUtils.h:2029
static bool IsAsciiAlphaNum(char chr)
Checks a character is within ascii alphabetic and numerical fields.
Definition StringUtils.h:2250
static bool IsAsciiXDigit(char chr)
Checks a character is ascii hexadecimal number.
Definition StringUtils.h:2176
static int AsciiXDigitValue(char chr)
Translate a character where defined as a hexadecimal value string to right integer.
Definition StringUtils.h:2206
static size_t Utf8StringLength(const char *s)
UTF8 version of strlen.
Definition StringUtils.h:2008
static bool StartsWith(const std::string &str1, const char *s2)
Checks a string for the begin of another string.
Definition StringUtils.h:1694
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:1779
static int IsUTF8Letter(const unsigned char *str)
Checks given pointer in string is a UTF8 letter.
Definition StringUtils.h:2038
static bool EqualsNoCase(const char *s1, const char *s2)
Compare two strings with ignore of lower-/uppercase.
Definition StringUtils.h:1589
static bool IsInteger(const std::string &str)
Check whether a string is an integer.
Definition StringUtils.h:2139
static bool EqualsNoCase(const std::string &str1, const char *s2)
Compare two strings with ignore of lower-/uppercase.
Definition StringUtils.h:1576
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:1749
static bool IsAsciiLowercaseLetter(char chr)
Checks a character is ascii alphabetic lowercase.
Definition StringUtils.h:2238
static bool StartsWith(const char *s1, const char *s2)
Checks a string for the begin of another string.
Definition StringUtils.h:1708
static bool IsNaturalNumber(const std::string &str)
Check whether a string is a natural number.
Definition StringUtils.h:2095
static bool StartsWith(const std::string &str1, const std::string &str2)
Checks a string for the begin of another string.
Definition StringUtils.h:1680
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:1618
static bool EndsWith(const std::string &str1, const std::string &str2)
Checks a string for the ending of another string.
Definition StringUtils.h:1816
static bool EqualsNoCase(const std::string &str1, const std::string &str2)
Compare two strings with ignore of lower-/uppercase.
Definition StringUtils.h:1559
static int64_t AlphaNumericCompare(const wchar_t *left, const wchar_t *right)
Compare two strings by his calculated alpha numeric values.
Definition StringUtils.h:1934
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:1764
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:1892
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:1866
static bool IsAasciiDigit(char chr)
Checks a character is ascii number.
Definition StringUtils.h:2164
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:1516
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:1477
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:2773
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:2833
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:2522
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:2663
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:2544
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:2817
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:2701
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:2590
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:2480
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:2790
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:2566
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:2639
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:2423
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:2384
static size_t FindWords(const char *str, const char *wordLowerCase)
Search for a single word within a text.
Definition StringUtils.h:2313
static long TimeStringToSeconds(const std::string &timeString)
Converts a time string to the respective integer value.
Definition StringUtils.h:2890
static int DateStringToYYYYMMDD(const std::string &dateString)
Converts a string in the format YYYYMMDD to the corresponding integer value.
Definition StringUtils.h:3003
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:2937