Kodi Development 19.0
for Binary and Script based Add-Ons
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 fith 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//==============================================================================
401{
404
407
410
413
416
419
422
425
428
431
434
437
440
443
446
449
452
454 TIME_FORMAT_M = 256
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), [](char c) {
1382 if (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || ('0' <= c && c <= '9') || c == '-' ||
1383 c == '.' || c == '_' || c == '~')
1384 {
1385 return c;
1386 }
1387 return '_';
1388 });
1389
1390 return safeUrl;
1391 }
1392 //----------------------------------------------------------------------------
1393
1394 //============================================================================
1403 inline static std::string MakeSafeString(const std::string& str)
1404 {
1405 std::string safeString;
1406
1407 safeString.reserve(str.size());
1408
1409 std::transform(str.begin(), str.end(), std::back_inserter(safeString), [](char c) {
1410 if (c < 0x20)
1411 return ' ';
1412
1413 return c;
1414 });
1415
1416 return safeString;
1417 }
1418 //----------------------------------------------------------------------------
1419
1420 //============================================================================
1426 inline static std::string RemoveMACAddress(const std::string& str)
1427 {
1428 std::regex re(R"mac([\‍(\[]?([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})[\)\]]?)mac");
1429 return std::regex_replace(str, re, "", std::regex_constants::format_default);
1430 }
1431 //----------------------------------------------------------------------------
1432
1433 //============================================================================
1452 inline static void RemoveCRLF(std::string& strLine) { StringUtils::TrimRight(strLine, "\n\r"); }
1453 //----------------------------------------------------------------------------
1454
1455 //============================================================================
1472 inline static void WordToDigits(std::string& word)
1473 {
1474 static const char word_to_letter[] = "22233344455566677778889999";
1476 for (unsigned int i = 0; i < word.size(); ++i)
1477 { // NB: This assumes ascii, which probably needs extending at some point.
1478 char letter = word[i];
1479 if ((letter >= 'a' && letter <= 'z')) // assume contiguous letter range
1480 {
1481 word[i] = word_to_letter[letter - 'a'];
1482 }
1483 else if (letter < '0' || letter > '9') // We want to keep 0-9!
1484 {
1485 word[i] = ' '; // replace everything else with a space
1486 }
1487 }
1488 }
1489 //----------------------------------------------------------------------------
1490
1491 //============================================================================
1511 inline static std::string Paramify(const std::string& param)
1512 {
1513 std::string result = param;
1514 // escape backspaces
1515 StringUtils::Replace(result, "\\", "\\\\");
1516 // escape double quotes
1517 StringUtils::Replace(result, "\"", "\\\"");
1518
1519 // add double quotes around the whole string
1520 return "\"" + result + "\"";
1521 }
1522 //----------------------------------------------------------------------------
1523
1526 //----------------------------------------------------------------------------
1533
1535 //============================================================================
1554 inline static bool EqualsNoCase(const std::string& str1, const std::string& str2)
1555 {
1556 // before we do the char-by-char comparison, first compare sizes of both strings.
1557 // This led to a 33% improvement in benchmarking on average. (size() just returns a member of std::string)
1558 if (str1.size() != str2.size())
1559 return false;
1560 return EqualsNoCase(str1.c_str(), str2.c_str());
1561 }
1562 //----------------------------------------------------------------------------
1563
1564 //============================================================================
1571 inline static bool EqualsNoCase(const std::string& str1, const char* s2)
1572 {
1573 return EqualsNoCase(str1.c_str(), s2);
1574 }
1575 //----------------------------------------------------------------------------
1576
1577 //============================================================================
1584 inline static bool EqualsNoCase(const char* s1, const char* s2)
1585 {
1586 char c2; // we need only one char outside the loop
1587 do
1588 {
1589 const char c1 = *s1++; // const local variable should help compiler to optimize
1590 c2 = *s2++;
1591 // This includes the possibility that one of the characters is the null-terminator,
1592 // which implies a string mismatch.
1593 if (c1 != c2 && ::tolower(c1) != ::tolower(c2))
1594 return false;
1595 } while (c2 != '\0'); // At this point, we know c1 == c2, so there's no need to test them both.
1596 return true;
1597 }
1598 //----------------------------------------------------------------------------
1599
1600 //============================================================================
1613 inline static int CompareNoCase(const std::string& str1, const std::string& str2, size_t n = 0)
1614 {
1615 return CompareNoCase(str1.c_str(), str2.c_str(), n);
1616 }
1617 //----------------------------------------------------------------------------
1618
1619 //============================================================================
1632 inline static int CompareNoCase(const char* s1, const char* s2, size_t n = 0)
1633 {
1634 char c2; // we need only one char outside the loop
1635 size_t index = 0;
1636 do
1637 {
1638 const char c1 = *s1++; // const local variable should help compiler to optimize
1639 c2 = *s2++;
1640 index++;
1641 // This includes the possibility that one of the characters is the null-terminator,
1642 // which implies a string mismatch.
1643 if (c1 != c2 && ::tolower(c1) != ::tolower(c2))
1644 return ::tolower(c1) - ::tolower(c2);
1645 } while (c2 != '\0' &&
1646 index != n); // At this point, we know c1 == c2, so there's no need to test them both.
1647 return 0;
1648 }
1649 //----------------------------------------------------------------------------
1650
1651 //============================================================================
1675 inline static bool StartsWith(const std::string& str1, const std::string& str2)
1676 {
1677 return str1.compare(0, str2.size(), str2) == 0;
1678 }
1679 //----------------------------------------------------------------------------
1680
1681 //============================================================================
1689 inline static bool StartsWith(const std::string& str1, const char* s2)
1690 {
1691 return StartsWith(str1.c_str(), s2);
1692 }
1693 //----------------------------------------------------------------------------
1694
1695 //============================================================================
1703 inline static bool StartsWith(const char* s1, const char* s2)
1704 {
1705 while (*s2 != '\0')
1706 {
1707 if (*s1 != *s2)
1708 return false;
1709 s1++;
1710 s2++;
1711 }
1712 return true;
1713 }
1714 //----------------------------------------------------------------------------
1715
1716 //============================================================================
1744 inline static bool StartsWithNoCase(const std::string& str1, const std::string& str2)
1745 {
1746 return StartsWithNoCase(str1.c_str(), str2.c_str());
1747 }
1748 //----------------------------------------------------------------------------
1749
1750 //============================================================================
1759 inline static bool StartsWithNoCase(const std::string& str1, const char* s2)
1760 {
1761 return StartsWithNoCase(str1.c_str(), s2);
1762 }
1763 //----------------------------------------------------------------------------
1764
1765 //============================================================================
1774 inline static bool StartsWithNoCase(const char* s1, const char* s2)
1775 {
1776 while (*s2 != '\0')
1777 {
1778 if (::tolower(*s1) != ::tolower(*s2))
1779 return false;
1780 s1++;
1781 s2++;
1782 }
1783 return true;
1784 }
1785 //----------------------------------------------------------------------------
1786
1787 //============================================================================
1811 inline static bool EndsWith(const std::string& str1, const std::string& str2)
1812 {
1813 if (str1.size() < str2.size())
1814 return false;
1815 return str1.compare(str1.size() - str2.size(), str2.size(), str2) == 0;
1816 }
1817 //----------------------------------------------------------------------------
1818
1819 //============================================================================
1827 inline static bool EndsWith(const std::string& str1, const char* s2)
1828 {
1829 size_t len2 = strlen(s2);
1830 if (str1.size() < len2)
1831 return false;
1832 return str1.compare(str1.size() - len2, len2, s2) == 0;
1833 }
1834 //----------------------------------------------------------------------------
1835
1836 //============================================================================
1861 inline static bool EndsWithNoCase(const std::string& str1, const std::string& str2)
1862 {
1863 if (str1.size() < str2.size())
1864 return false;
1865 const char* s1 = str1.c_str() + str1.size() - str2.size();
1866 const char* s2 = str2.c_str();
1867 while (*s2 != '\0')
1868 {
1869 if (::tolower(*s1) != ::tolower(*s2))
1870 return false;
1871 s1++;
1872 s2++;
1873 }
1874 return true;
1875 }
1876 //----------------------------------------------------------------------------
1877
1878 //============================================================================
1887 inline static bool EndsWithNoCase(const std::string& str1, const char* s2)
1888 {
1889 size_t len2 = strlen(s2);
1890 if (str1.size() < len2)
1891 return false;
1892 const char* s1 = str1.c_str() + str1.size() - len2;
1893 while (*s2 != '\0')
1894 {
1895 if (::tolower(*s1) != ::tolower(*s2))
1896 return false;
1897 s1++;
1898 s2++;
1899 }
1900 return true;
1901 }
1902 //----------------------------------------------------------------------------
1903
1904 //============================================================================
1929 inline static int64_t AlphaNumericCompare(const wchar_t* left, const wchar_t* right)
1930 {
1931 const wchar_t* l = left;
1932 const wchar_t* r = right;
1933 const wchar_t *ld, *rd;
1934 wchar_t lc, rc;
1935 int64_t lnum, rnum;
1936 const std::collate<wchar_t>& coll = std::use_facet<std::collate<wchar_t>>(std::locale());
1937 int cmp_res = 0;
1938 while (*l != 0 && *r != 0)
1939 {
1940 // check if we have a numerical value
1941 if (*l >= L'0' && *l <= L'9' && *r >= L'0' && *r <= L'9')
1942 {
1943 ld = l;
1944 lnum = 0;
1945 while (*ld >= L'0' && *ld <= L'9' && ld < l + 15)
1946 { // compare only up to 15 digits
1947 lnum *= 10;
1948 lnum += *ld++ - '0';
1949 }
1950 rd = r;
1951 rnum = 0;
1952 while (*rd >= L'0' && *rd <= L'9' && rd < r + 15)
1953 { // compare only up to 15 digits
1954 rnum *= 10;
1955 rnum += *rd++ - L'0';
1956 }
1957 // do we have numbers?
1958 if (lnum != rnum)
1959 { // yes - and they're different!
1960 return lnum - rnum;
1961 }
1962 l = ld;
1963 r = rd;
1964 continue;
1965 }
1966 // do case less comparison
1967 lc = *l;
1968 if (lc >= L'A' && lc <= L'Z')
1969 lc += L'a' - L'A';
1970 rc = *r;
1971 if (rc >= L'A' && rc <= L'Z')
1972 rc += L'a' - L'A';
1973
1974 // ok, do a normal comparison, taking current locale into account. Add special case stuff (eg '(' characters)) in here later
1975 if ((cmp_res = coll.compare(&lc, &lc + 1, &rc, &rc + 1)) != 0)
1976 {
1977 return cmp_res;
1978 }
1979 l++;
1980 r++;
1981 }
1982 if (*r)
1983 { // r is longer
1984 return -1;
1985 }
1986 else if (*l)
1987 { // l is longer
1988 return 1;
1989 }
1990 return 0; // files are the same
1991 }
1992 //----------------------------------------------------------------------------
1993
1994 //============================================================================
2003 inline static size_t Utf8StringLength(const char* s)
2004 {
2005 size_t length = 0;
2006 while (*s)
2007 {
2008 if ((*s++ & 0xC0) != 0x80)
2009 length++;
2010 }
2011 return length;
2012 }
2013 //----------------------------------------------------------------------------
2014
2015 //============================================================================
2024 inline static int IsSpace(char c) { return (c & 0x80) == 0 && ::isspace(c); }
2025 //----------------------------------------------------------------------------
2026
2027 //============================================================================
2033 inline static int IsUTF8Letter(const unsigned char* str)
2034 {
2035 // reference:
2036 // unicode -> utf8 table: http://www.utf8-chartable.de/
2037 // latin characters in unicode: http://en.wikipedia.org/wiki/Latin_characters_in_Unicode
2038 unsigned char ch = str[0];
2039 if (!ch)
2040 return -1;
2041 if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))
2042 return 1;
2043 if (!(ch & 0x80))
2044 return -1;
2045 unsigned char ch2 = str[1];
2046 if (!ch2)
2047 return -1;
2048 // check latin 1 letter table: http://en.wikipedia.org/wiki/C1_Controls_and_Latin-1_Supplement
2049 if (ch == 0xC3 && ch2 >= 0x80 && ch2 <= 0xBF && ch2 != 0x97 && ch2 != 0xB7)
2050 return 2;
2051 // check latin extended A table: http://en.wikipedia.org/wiki/Latin_Extended-A
2052 if (ch >= 0xC4 && ch <= 0xC7 && ch2 >= 0x80 && ch2 <= 0xBF)
2053 return 2;
2054 // check latin extended B table: http://en.wikipedia.org/wiki/Latin_Extended-B
2055 // and International Phonetic Alphabet: http://en.wikipedia.org/wiki/IPA_Extensions_(Unicode_block)
2056 if (((ch == 0xC8 || ch == 0xC9) && ch2 >= 0x80 && ch2 <= 0xBF) ||
2057 (ch == 0xCA && ch2 >= 0x80 && ch2 <= 0xAF))
2058 return 2;
2059 return -1;
2060 }
2061 //----------------------------------------------------------------------------
2062
2063 //============================================================================
2090 inline static bool IsNaturalNumber(const std::string& str)
2091 {
2092 size_t i = 0, n = 0;
2093 // allow whitespace,digits,whitespace
2094 while (i < str.size() && isspace((unsigned char)str[i]))
2095 i++;
2096 while (i < str.size() && isdigit((unsigned char)str[i]))
2097 {
2098 i++;
2099 n++;
2100 }
2101 while (i < str.size() && isspace((unsigned char)str[i]))
2102 i++;
2103 return i == str.size() && n > 0;
2104 }
2105 //----------------------------------------------------------------------------
2106
2107 //============================================================================
2134 inline static bool IsInteger(const std::string& str)
2135 {
2136 size_t i = 0, n = 0;
2137 // allow whitespace,-,digits,whitespace
2138 while (i < str.size() && isspace((unsigned char)str[i]))
2139 i++;
2140 if (i < str.size() && str[i] == '-')
2141 i++;
2142 while (i < str.size() && isdigit((unsigned char)str[i]))
2143 {
2144 i++;
2145 n++;
2146 }
2147 while (i < str.size() && isspace((unsigned char)str[i]))
2148 i++;
2149 return i == str.size() && n > 0;
2150 }
2151 //----------------------------------------------------------------------------
2152
2153 //============================================================================
2159 inline static bool IsAasciiDigit(char chr) // locale independent
2160 {
2161 return chr >= '0' && chr <= '9';
2162 }
2163 //----------------------------------------------------------------------------
2164
2165 //============================================================================
2171 inline static bool IsAsciiXDigit(char chr) // locale independent
2172 {
2173 return (chr >= '0' && chr <= '9') || (chr >= 'a' && chr <= 'f') || (chr >= 'A' && chr <= 'F');
2174 }
2175 //----------------------------------------------------------------------------
2176
2177 //============================================================================
2184 inline static int AsciiDigitValue(char chr) // locale independent
2185 {
2186 if (!IsAasciiDigit(chr))
2187 return -1;
2188
2189 return chr - '0';
2190 }
2191 //----------------------------------------------------------------------------
2192
2193 //============================================================================
2201 inline static int AsciiXDigitValue(char chr) // locale independent
2202 {
2203 int v = AsciiDigitValue(chr);
2204 if (v >= 0)
2205 return v;
2206 if (chr >= 'a' && chr <= 'f')
2207 return chr - 'a' + 10;
2208 if (chr >= 'A' && chr <= 'F')
2209 return chr - 'A' + 10;
2210
2211 return -1;
2212 }
2213 //----------------------------------------------------------------------------
2214
2215 //============================================================================
2221 inline static bool IsAsciiUppercaseLetter(char chr) // locale independent
2222 {
2223 return (chr >= 'A' && chr <= 'Z');
2224 }
2225 //----------------------------------------------------------------------------
2226
2227 //============================================================================
2233 inline static bool IsAsciiLowercaseLetter(char chr) // locale independent
2234 {
2235 return (chr >= 'a' && chr <= 'z');
2236 }
2237 //----------------------------------------------------------------------------
2238
2239 //============================================================================
2245 inline static bool IsAsciiAlphaNum(char chr) // locale independent
2246 {
2247 return IsAsciiUppercaseLetter(chr) || IsAsciiLowercaseLetter(chr) || IsAasciiDigit(chr);
2248 }
2249 //----------------------------------------------------------------------------
2250
2251 //============================================================================
2258 inline static bool ContainsKeyword(const std::string& str,
2259 const std::vector<std::string>& keywords)
2260 {
2261 for (const auto& it : keywords)
2262 {
2263 if (str.find(it) != str.npos)
2264 return true;
2265 }
2266 return false;
2267 }
2268 //----------------------------------------------------------------------------
2269
2272 //----------------------------------------------------------------------------
2279
2281 //============================================================================
2308 inline static size_t FindWords(const char* str, const char* wordLowerCase)
2309 {
2310 // NOTE: This assumes word is lowercase!
2311 const unsigned char* s = (const unsigned char*)str;
2312 do
2313 {
2314 // start with a compare
2315 const unsigned char* c = s;
2316 const unsigned char* w = (const unsigned char*)wordLowerCase;
2317 bool same = true;
2318 while (same && *c && *w)
2319 {
2320 unsigned char lc = *c++;
2321 if (lc >= 'A' && lc <= 'Z')
2322 lc += 'a' - 'A';
2323
2324 if (lc != *w++) // different
2325 same = false;
2326 }
2327 if (same && *w == 0) // only the same if word has been exhausted
2328 return (const char*)s - str;
2329
2330 // otherwise, skip current word (composed by latin letters) or number
2331 int l;
2332 if (*s >= '0' && *s <= '9')
2333 {
2334 ++s;
2335 while (*s >= '0' && *s <= '9')
2336 ++s;
2337 }
2338 else if ((l = IsUTF8Letter(s)) > 0)
2339 {
2340 s += l;
2341 while ((l = IsUTF8Letter(s)) > 0)
2342 s += l;
2343 }
2344 else
2345 ++s;
2346 while (*s && *s == ' ')
2347 s++;
2348
2349 // and repeat until we're done
2350 } while (*s);
2351
2352 return std::string::npos;
2353 }
2354 //----------------------------------------------------------------------------
2355
2356 //============================================================================
2379 inline static size_t FindEndBracket(const std::string& str,
2380 char opener,
2381 char closer,
2382 size_t startPos = 0)
2383 {
2384 size_t blocks = 1;
2385 for (size_t i = startPos; i < str.size(); i++)
2386 {
2387 if (str[i] == opener)
2388 blocks++;
2389 else if (str[i] == closer)
2390 {
2391 blocks--;
2392 if (!blocks)
2393 return i;
2394 }
2395 }
2396
2397 return std::string::npos;
2398 }
2399 //----------------------------------------------------------------------------
2400
2401 //============================================================================
2418 inline static int FindNumber(const std::string& strInput, const std::string& strFind)
2419 {
2420 size_t pos = strInput.find(strFind, 0);
2421 int numfound = 0;
2422 while (pos != std::string::npos)
2423 {
2424 numfound++;
2425 pos = strInput.find(strFind, pos + 1);
2426 }
2427 return numfound;
2428 }
2429 //----------------------------------------------------------------------------
2430
2433 //----------------------------------------------------------------------------
2440
2442 //============================================================================
2474 template<typename CONTAINER>
2475 inline static std::string Join(const CONTAINER& strings, const std::string& delimiter)
2476 {
2477 std::string result;
2478 for (const auto& str : strings)
2479 result += str + delimiter;
2480
2481 if (!result.empty())
2482 result.erase(result.size() - delimiter.size());
2483 return result;
2484 }
2485 //----------------------------------------------------------------------------
2486
2487 //============================================================================
2517 inline static std::vector<std::string> Split(const std::string& input,
2518 const std::string& delimiter,
2519 unsigned int iMaxStrings = 0)
2520 {
2521 std::vector<std::string> result;
2522 SplitTo(std::back_inserter(result), input, delimiter, iMaxStrings);
2523 return result;
2524 }
2525 //----------------------------------------------------------------------------
2526
2527 //============================================================================
2539 inline static std::vector<std::string> Split(const std::string& input,
2540 const char delimiter,
2541 int iMaxStrings = 0)
2542 {
2543 std::vector<std::string> result;
2544 SplitTo(std::back_inserter(result), input, delimiter, iMaxStrings);
2545 return result;
2546 }
2547 //----------------------------------------------------------------------------
2548
2549 //============================================================================
2561 inline static std::vector<std::string> Split(const std::string& input,
2562 const std::vector<std::string>& delimiters)
2563 {
2564 std::vector<std::string> result;
2565 SplitTo(std::back_inserter(result), input, delimiters);
2566 return result;
2567 }
2568 //----------------------------------------------------------------------------
2569
2570 //============================================================================
2584 template<typename OutputIt>
2585 inline static OutputIt SplitTo(OutputIt d_first,
2586 const std::string& input,
2587 const std::string& delimiter,
2588 unsigned int iMaxStrings = 0)
2589 {
2590 OutputIt dest = d_first;
2591
2592 if (input.empty())
2593 return dest;
2594 if (delimiter.empty())
2595 {
2596 *d_first++ = input;
2597 return dest;
2598 }
2599
2600 const size_t delimLen = delimiter.length();
2601 size_t nextDelim;
2602 size_t textPos = 0;
2603 do
2604 {
2605 if (--iMaxStrings == 0)
2606 {
2607 *dest++ = input.substr(textPos);
2608 break;
2609 }
2610 nextDelim = input.find(delimiter, textPos);
2611 *dest++ = input.substr(textPos, nextDelim - textPos);
2612 textPos = nextDelim + delimLen;
2613 } while (nextDelim != std::string::npos);
2614
2615 return dest;
2616 }
2617 //----------------------------------------------------------------------------
2618
2619 //============================================================================
2633 template<typename OutputIt>
2634 inline static OutputIt SplitTo(OutputIt d_first,
2635 const std::string& input,
2636 const char delimiter,
2637 int iMaxStrings = 0)
2638 {
2639 return SplitTo(d_first, input, std::string(1, delimiter), iMaxStrings);
2640 }
2641 //----------------------------------------------------------------------------
2642
2643 //============================================================================
2657 template<typename OutputIt>
2658 inline static OutputIt SplitTo(OutputIt d_first,
2659 const std::string& input,
2660 const std::vector<std::string>& delimiters)
2661 {
2662 OutputIt dest = d_first;
2663 if (input.empty())
2664 return dest;
2665
2666 if (delimiters.empty())
2667 {
2668 *dest++ = input;
2669 return dest;
2670 }
2671 std::string str = input;
2672 for (size_t di = 1; di < delimiters.size(); di++)
2673 StringUtils::Replace(str, delimiters[di], delimiters[0]);
2674 return SplitTo(dest, str, delimiters[0]);
2675 }
2676 //----------------------------------------------------------------------------
2677
2678 //============================================================================
2696 inline static std::vector<std::string> SplitMulti(const std::vector<std::string>& input,
2697 const std::vector<std::string>& delimiters,
2698 unsigned int iMaxStrings = 0)
2699 {
2700 if (input.empty())
2701 return std::vector<std::string>();
2702
2703 std::vector<std::string> results(input);
2704
2705 if (delimiters.empty() || (iMaxStrings > 0 && iMaxStrings <= input.size()))
2706 return results;
2707
2708 std::vector<std::string> strings1;
2709 if (iMaxStrings == 0)
2710 {
2711 for (size_t di = 0; di < delimiters.size(); di++)
2712 {
2713 for (size_t i = 0; i < results.size(); i++)
2714 {
2715 std::vector<std::string> substrings = StringUtils::Split(results[i], delimiters[di]);
2716 for (size_t j = 0; j < substrings.size(); j++)
2717 strings1.push_back(substrings[j]);
2718 }
2719 results = strings1;
2720 strings1.clear();
2721 }
2722 return results;
2723 }
2724
2725 // Control the number of strings input is split into, keeping the original strings.
2726 // Note iMaxStrings > input.size()
2727 size_t iNew = iMaxStrings - results.size();
2728 for (size_t di = 0; di < delimiters.size(); di++)
2729 {
2730 for (size_t i = 0; i < results.size(); i++)
2731 {
2732 if (iNew > 0)
2733 {
2734 std::vector<std::string> substrings =
2735 StringUtils::Split(results[i], delimiters[di], static_cast<int>(iNew + 1));
2736 iNew = iNew - substrings.size() + 1;
2737 for (size_t j = 0; j < substrings.size(); j++)
2738 strings1.push_back(substrings[j]);
2739 }
2740 else
2741 strings1.push_back(results[i]);
2742 }
2743 results = strings1;
2744 iNew = iMaxStrings - results.size();
2745 strings1.clear();
2746 if ((iNew <= 0))
2747 break; //Stop trying any more delimiters
2748 }
2749 return results;
2750 }
2751 //----------------------------------------------------------------------------
2752
2753 //============================================================================
2768 inline static std::vector<std::string> Tokenize(const std::string& input,
2769 const std::string& delimiters)
2770 {
2771 std::vector<std::string> tokens;
2772 Tokenize(input, tokens, delimiters);
2773 return tokens;
2774 }
2775 //----------------------------------------------------------------------------
2776
2777 //============================================================================
2785 inline static void Tokenize(const std::string& input,
2786 std::vector<std::string>& tokens,
2787 const std::string& delimiters)
2788 {
2789 tokens.clear();
2790 // Skip delimiters at beginning.
2791 std::string::size_type dataPos = input.find_first_not_of(delimiters);
2792 while (dataPos != std::string::npos)
2793 {
2794 // Find next delimiter
2795 const std::string::size_type nextDelimPos = input.find_first_of(delimiters, dataPos);
2796 // Found a token, add it to the vector.
2797 tokens.push_back(input.substr(dataPos, nextDelimPos - dataPos));
2798 // Skip delimiters. Note the "not_of"
2799 dataPos = input.find_first_not_of(delimiters, nextDelimPos);
2800 }
2801 }
2802 //----------------------------------------------------------------------------
2803
2804 //============================================================================
2812 inline static std::vector<std::string> Tokenize(const std::string& input, const char delimiter)
2813 {
2814 std::vector<std::string> tokens;
2815 Tokenize(input, tokens, delimiter);
2816 return tokens;
2817 }
2818 //----------------------------------------------------------------------------
2819
2820 //============================================================================
2828 inline static void Tokenize(const std::string& input,
2829 std::vector<std::string>& tokens,
2830 const char delimiter)
2831 {
2832 tokens.clear();
2833 // Skip delimiters at beginning.
2834 std::string::size_type dataPos = input.find_first_not_of(delimiter);
2835 while (dataPos != std::string::npos)
2836 {
2837 // Find next delimiter
2838 const std::string::size_type nextDelimPos = input.find(delimiter, dataPos);
2839 // Found a token, add it to the vector.
2840 tokens.push_back(input.substr(dataPos, nextDelimPos - dataPos));
2841 // Skip delimiters. Note the "not_of"
2842 dataPos = input.find_first_not_of(delimiter, nextDelimPos);
2843 }
2844 }
2845 //----------------------------------------------------------------------------
2846
2849 //----------------------------------------------------------------------------
2854
2856 //============================================================================
2885 inline static long TimeStringToSeconds(const std::string& timeString)
2886 {
2887 std::string strCopy(timeString);
2888 StringUtils::Trim(strCopy);
2889 if (StringUtils::EndsWithNoCase(strCopy, " min"))
2890 {
2891 // this is imdb format of "XXX min"
2892 return 60 * atoi(strCopy.c_str());
2893 }
2894 else
2895 {
2896 std::vector<std::string> secs = StringUtils::Split(strCopy, ':');
2897 int timeInSecs = 0;
2898 for (unsigned int i = 0; i < 3 && i < secs.size(); i++)
2899 {
2900 timeInSecs *= 60;
2901 timeInSecs += atoi(secs[i].c_str());
2902 }
2903 return timeInSecs;
2904 }
2905 }
2906 //----------------------------------------------------------------------------
2907
2908 //============================================================================
2931 inline static std::string SecondsToTimeString(long seconds,
2933 {
2934 bool isNegative = seconds < 0;
2935 seconds = std::abs(seconds);
2936
2937 std::string strHMS;
2938 if (format == TIME_FORMAT_SECS)
2939 strHMS = StringUtils::Format("%i", seconds);
2940 else if (format == TIME_FORMAT_MINS)
2941 strHMS = StringUtils::Format("%i", lrintf(static_cast<float>(seconds) / 60.0f));
2942 else if (format == TIME_FORMAT_HOURS)
2943 strHMS = StringUtils::Format("%i", lrintf(static_cast<float>(seconds) / 3600.0f));
2944 else if (format & TIME_FORMAT_M)
2945 strHMS += StringUtils::Format("%i", seconds % 3600 / 60);
2946 else
2947 {
2948 int hh = seconds / 3600;
2949 seconds = seconds % 3600;
2950 int mm = seconds / 60;
2951 int ss = seconds % 60;
2952
2953 if (format == TIME_FORMAT_GUESS)
2954 format = (hh >= 1) ? TIME_FORMAT_HH_MM_SS : TIME_FORMAT_MM_SS;
2955 if (format & TIME_FORMAT_HH)
2956 strHMS += StringUtils::Format("%2.2i", hh);
2957 else if (format & TIME_FORMAT_H)
2958 strHMS += StringUtils::Format("%i", hh);
2959 if (format & TIME_FORMAT_MM)
2960 strHMS += StringUtils::Format(strHMS.empty() ? "%2.2i" : ":%2.2i", mm);
2961 if (format & TIME_FORMAT_SS)
2962 strHMS += StringUtils::Format(strHMS.empty() ? "%2.2i" : ":%2.2i", ss);
2963 }
2964
2965 if (isNegative)
2966 strHMS = "-" + strHMS;
2967
2968 return strHMS;
2969 }
2970 //----------------------------------------------------------------------------
2971
2972 //============================================================================
2997 inline static int DateStringToYYYYMMDD(const std::string& dateString)
2998 {
2999 std::vector<std::string> days = StringUtils::Split(dateString, '-');
3000 if (days.size() == 1)
3001 return atoi(days[0].c_str());
3002 else if (days.size() == 2)
3003 return atoi(days[0].c_str()) * 100 + atoi(days[1].c_str());
3004 else if (days.size() == 3)
3005 return atoi(days[0].c_str()) * 10000 + atoi(days[1].c_str()) * 100 + atoi(days[2].c_str());
3006 else
3007 return -1;
3008 }
3009 //----------------------------------------------------------------------------
3010
3013private:
3014 inline static int compareWchar(const void* a, const void* b)
3015 {
3016 if (*static_cast<const wchar_t*>(a) < *static_cast<const wchar_t*>(b))
3017 return -1;
3018 else if (*static_cast<const wchar_t*>(a) > *static_cast<const wchar_t*>(b))
3019 return 1;
3020 return 0;
3021 }
3022
3023 inline static wchar_t tolowerUnicode(const wchar_t& c)
3024 {
3025 wchar_t* p =
3026 static_cast<wchar_t*>(bsearch(&c, unicode_uppers, sizeof(unicode_uppers) / sizeof(wchar_t),
3027 sizeof(wchar_t), compareWchar));
3028 if (p)
3029 return *(unicode_lowers + (p - unicode_uppers));
3030
3031 return c;
3032 }
3033
3034 inline static wchar_t toupperUnicode(const wchar_t& c)
3035 {
3036 wchar_t* p =
3037 static_cast<wchar_t*>(bsearch(&c, unicode_lowers, sizeof(unicode_lowers) / sizeof(wchar_t),
3038 sizeof(wchar_t), compareWchar));
3039 if (p)
3040 return *(unicode_uppers + (p - unicode_lowers));
3041
3042 return c;
3043 }
3044
3045 static uint32_t UTF8ToUnicode(const unsigned char* z, int nKey, unsigned char& bytes)
3046 {
3047 // Lookup table used decode the first byte of a multi-byte UTF8 character
3048 // clang-format off
3049 static const unsigned char utf8Trans1[] = {
3050 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
3051 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
3052 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
3053 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
3054 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
3055 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
3056 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
3057 0x00, 0x01, 0x02, 0x03, 0x00, 0x01, 0x00, 0x00,
3058 };
3059 // clang-format on
3060
3061 uint32_t c;
3062 bytes = 0;
3063 c = z[0];
3064 if (c >= 0xc0)
3065 {
3066 c = utf8Trans1[c - 0xc0];
3067 int index = 1;
3068 while (index < nKey && (z[index] & 0xc0) == 0x80)
3069 {
3070 c = (c << 6) + (0x3f & z[index]);
3071 index++;
3072 }
3073 if (c < 0x80 || (c & 0xFFFFF800) == 0xD800 || (c & 0xFFFFFFFE) == 0xFFFE)
3074 c = 0xFFFD;
3075 bytes = static_cast<unsigned char>(index - 1);
3076 }
3077 return c;
3078 }
3079};
3081//------------------------------------------------------------------------------
3082
3083} /* namespace tools */
3084} /* namespace kodi */
3085
3086#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:1827
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:1632
static bool IsAsciiUppercaseLetter(char chr)
Checks a character is ascii alphabetic lowercase.
Definition: StringUtils.h:2221
static bool ContainsKeyword(const std::string &str, const std::vector< std::string > &keywords)
Check a string for another text.
Definition: StringUtils.h:2258
static int AsciiDigitValue(char chr)
Translate a character where defined as a numerical value (0-9) string to right integer.
Definition: StringUtils.h:2184
static int IsSpace(char c)
Check given character is a space.
Definition: StringUtils.h:2024
static bool IsAsciiAlphaNum(char chr)
Checks a character is within ascii alphabetic and numerical fields.
Definition: StringUtils.h:2245
static bool IsAsciiXDigit(char chr)
Checks a character is ascii hexadecimal number.
Definition: StringUtils.h:2171
static int AsciiXDigitValue(char chr)
Translate a character where defined as a hexadecimal value string to right integer.
Definition: StringUtils.h:2201
static size_t Utf8StringLength(const char *s)
UTF8 version of strlen.
Definition: StringUtils.h:2003
static bool StartsWith(const std::string &str1, const char *s2)
Checks a string for the begin of another string.
Definition: StringUtils.h:1689
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:1774
static int IsUTF8Letter(const unsigned char *str)
Checks given pointer in string is a UTF8 letter.
Definition: StringUtils.h:2033
static bool EqualsNoCase(const char *s1, const char *s2)
Compare two strings with ignore of lower-/uppercase.
Definition: StringUtils.h:1584
static bool IsInteger(const std::string &str)
Check whether a string is an integer.
Definition: StringUtils.h:2134
static bool EqualsNoCase(const std::string &str1, const char *s2)
Compare two strings with ignore of lower-/uppercase.
Definition: StringUtils.h:1571
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:1744
static bool IsAsciiLowercaseLetter(char chr)
Checks a character is ascii alphabetic lowercase.
Definition: StringUtils.h:2233
static bool StartsWith(const char *s1, const char *s2)
Checks a string for the begin of another string.
Definition: StringUtils.h:1703
static bool IsNaturalNumber(const std::string &str)
Check whether a string is a natural number.
Definition: StringUtils.h:2090
static bool StartsWith(const std::string &str1, const std::string &str2)
Checks a string for the begin of another string.
Definition: StringUtils.h:1675
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:1613
static bool EndsWith(const std::string &str1, const std::string &str2)
Checks a string for the ending of another string.
Definition: StringUtils.h:1811
static bool EqualsNoCase(const std::string &str1, const std::string &str2)
Compare two strings with ignore of lower-/uppercase.
Definition: StringUtils.h:1554
static int64_t AlphaNumericCompare(const wchar_t *left, const wchar_t *right)
Compare two strings by his calculated alpha numeric values.
Definition: StringUtils.h:1929
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:1759
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:1887
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:1861
static bool IsAasciiDigit(char chr)
Checks a character is ascii number.
Definition: StringUtils.h:2159
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:1452
static std::string MakeSafeString(const std::string &str)
Transform characters to create a safe, printable string.
Definition: StringUtils.h:1403
static std::string RemoveMACAddress(const std::string &str)
Removes a MAC address from a given string.
Definition: StringUtils.h:1426
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:1511
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:1472
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:2768
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:2828
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:2517
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:2658
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:2539
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:2812
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:2696
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:2585
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:2475
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:2785
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:2561
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:2634
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:2418
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:2379
static size_t FindWords(const char *str, const char *wordLowerCase)
Search for a single word within a text.
Definition: StringUtils.h:2308
static long TimeStringToSeconds(const std::string &timeString)
Converts a time string to the respective integer value.
Definition: StringUtils.h:2885
static int DateStringToYYYYMMDD(const std::string &dateString)
Converts a string in the format YYYYMMDD to the corresponding integer value.
Definition: StringUtils.h:2997
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:2931