Etterna 0.74.4
Loading...
Searching...
No Matches
RageUtil.h
1
3#ifndef RAGE_UTIL_H
4#define RAGE_UTIL_H
5
6#include <map>
7#include <sstream>
8#include <cstring>
9#include <vector>
10#include <memory>
11#include <cmath>
12
13class RageFileDriver;
14
16#define SAFE_DELETE(p) \
17 do { \
18 delete (p); \
19 (p) = nullptr; \
20 } while (false)
22#define SAFE_DELETE_ARRAY(p) \
23 do { \
24 delete[](p); \
25 (p) = nullptr; \
26 } while (false)
27
29#define ZERO(x) memset(&(x), 0, sizeof(x))
30
32#define ARRAYLEN(a) (sizeof(a) / sizeof((a)[0]))
33
42#define SCALE(x, l1, h1, l2, h2) \
43 (((x) - (l1)) * ((h2) - (l2)) / ((h1) - (l1)) + (l2))
44
45template<typename T, typename U>
46auto
47lerp(T x, U l, U h) -> U
48{
49 return static_cast<U>(x * (h - l) + l);
50}
51
52template<typename T, typename U, typename V>
53auto
54CLAMP(T& x, U l, V h) -> bool
55{
56 if (x > static_cast<T>(h)) {
57 x = static_cast<T>(h);
58 return true;
59 }
60 if (x < static_cast<T>(l)) {
61 x = static_cast<T>(l);
62 return true;
63 }
64 return false;
65}
66
67template<class T>
68auto
69ENUM_CLAMP(T& x, T l, T h) -> bool
70{
71 if (x > h) {
72 x = h;
73 return true;
74 } else if (x < l) {
75 x = l;
76 return true;
77 }
78 return false;
79}
80
81inline auto
82wife2(float maxms, float ts) -> float
83{
84 maxms = maxms * 1000.F;
85 float avedeviation = 95.F * ts;
86 float y = 1 - static_cast<float>(
87 pow(2, -1 * maxms * maxms / (avedeviation * avedeviation)));
88 y = static_cast<float>(pow(y, 2));
89 return (2 - -8) * (1 - y) + -8;
90}
91
92static const float wife3_mine_hit_weight = -7.F;
93static const float wife3_hold_drop_weight = -4.5F;
94static const float wife3_miss_weight = -5.5F;
95
96// erf approximation A&S formula 7.1.26
97inline auto
98werwerwerwerf(float x) -> float
99{
100 static const float a1 = 0.254829592F;
101 static const float a2 = -0.284496736F;
102 static const float a3 = 1.421413741F;
103 static const float a4 = -1.453152027F;
104 static const float a5 = 1.061405429F;
105 static const float p = 0.3275911F;
106
107 int sign = 1;
108 if (x < 0.F) {
109 sign = -1;
110 }
111 x = std::abs(x);
112
113 auto t = 1.F / (1.F + p * x);
114 auto y =
115 1.F - (((((a5 * t + a4) * t) + a3) * t + a2) * t + a1) * t * exp(-x * x);
116
117 return sign * y;
118}
119
120inline auto
121wife3(float maxms, float ts) -> float
122{
123 // so judge scaling isn't so extreme
124 static const float j_pow = 0.75F;
125 // min/max points
126 static const float max_points = 2.F;
127 // offset at which points starts decreasing(ms)
128 float ridic = 5.F * ts;
129
130 // technically the max boo is always 180ms above j4 however this is
131 // immaterial to the end purpose of the scoring curve - assignment of point
132 // values
133 float max_boo_weight = 180.F * ts;
134
135 // need positive values for this
136 maxms = std::abs(maxms * 1000.F);
137
138 // case optimizations
139 if (maxms <= ridic) {
140 return max_points;
141 }
142
143 // piecewise inflection
144 float zero = 65.F * pow(ts, j_pow);
145 float dev = 22.7F * pow(ts, j_pow);
146
147 if (maxms <= zero) {
148 return max_points * werwerwerwerf((zero - maxms) / dev);
149 }
150 if (maxms <= max_boo_weight) {
151 return (maxms - zero) * wife3_miss_weight / (max_boo_weight - zero);
152 }
153 return wife3_miss_weight;
154}
155
156inline void
157wrap(int& x, int n)
158{
159 if (x < 0) {
160 x += ((-x / n) + 1) * n;
161 }
162 x %= n;
163}
164inline void
165wrap(unsigned& x, unsigned n)
166{
167 x %= n;
168}
169inline void
170wrap(float& x, float n)
171{
172 if (x < 0) {
173 x += truncf(((-x / n) + 1)) * n;
174 }
175 x = fmodf(x, n);
176}
177
178inline auto
179fracf(float f) -> float
180{
181 return f - truncf(f);
182}
183
184template<class T>
185void
186CircularShift(std::vector<T>& v, int dist)
187{
188 for (int i = std::abs(dist); i > 0; i--) {
189 if (v.size() == 0)
190 break;
191 if (dist > 0) {
192 T t = v[0];
193 v.erase(v.begin());
194 v.push_back(t);
195 } else {
196 T t = v.back();
197 v.erase(v.end() - 1);
198 v.insert(v.begin(), t);
199 }
200 }
201}
202
203inline auto
204sstolower(char ch) -> char
205{
206 return (ch >= 'A' && ch <= 'Z') ? static_cast<char>(ch + 'a' - 'A') : ch;
207}
208
209template<typename CT>
210inline auto
211ssicmp(const CT* pA1, const CT* pA2) -> int
212{
213 CT f;
214 CT l;
215
216 do {
217 f = sstolower(*(pA1++));
218 l = sstolower(*(pA2++));
219 } while ((f) && (f == l));
220
221 return static_cast<int>(f - l);
222}
223
224inline auto
225CompareNoCase(const std::string& a, const std::string& b) -> int
226{
227 return ssicmp(a.c_str(), b.c_str());
228}
229
230inline auto
231EqualsNoCase(const std::string& a, const std::string& b) -> bool
232{
233 return CompareNoCase(a, b) == 0;
234}
235
236void
237s_replace(std::string& target, std::string const& from, std::string const& to);
238
239inline void
240ensure_slash_at_end(std::string& s)
241{
242 if (s.back() != '/') {
243 s += "/";
244 }
245}
246
248auto
249starts_with(std::string const& source, std::string const& target) -> bool;
250
252auto
253ends_with(std::string const& source, std::string const& target) -> bool;
254
256auto
257make_upper(std::string const& source) -> std::string;
258
260auto
261make_lower(std::string const& source) -> std::string;
262
263template<typename Type, typename Ret>
264static auto
265CreateClass() -> Ret*
266{
267 return new Type;
268}
269
270/* Helper for ConvertValue(). */
271template<typename TO, typename FROM>
273{
274 explicit ConvertValueHelper(FROM* pVal)
275 : m_pFromValue(pVal)
276 {
277 m_ToValue = static_cast<TO>(*m_pFromValue);
278 }
279
280 ~ConvertValueHelper() { *m_pFromValue = static_cast<FROM>(m_ToValue); }
281
282 auto operator*() -> TO& { return m_ToValue; }
283 operator TO*() { return &m_ToValue; }
284
285 private:
286 FROM* m_pFromValue;
287 TO m_ToValue;
288};
289
290/* Safely temporarily convert between types. For example,
291 *
292 * float f = 10.5;
293 * *ConvertValue<int>(&f) = 12;
294 */
295template<typename TO, typename FROM>
296auto
297ConvertValue(FROM* pValue) -> ConvertValueHelper<TO, FROM>
298{
299 return ConvertValueHelper<TO, FROM>(pValue);
300}
301
302/* Safely add an integer to an enum.
303 *
304 * This is illegal:
305 *
306 * ((int&)val) += iAmt;
307 *
308 * It breaks aliasing rules; the compiler is allowed to assume that "val"
309 * doesn't change (unless it's declared volatile), and in some cases, you'll end
310 * up getting old values for "val" following the add. (What's probably really
311 * happening is that the memory location is being added to, but the value is
312 * stored in a register, and breaking aliasing rules means the compiler doesn't
313 * know that the register value is invalid.)
314 */
315template<typename T>
316static void
317enum_add(T& val, int iAmt)
318{
319 val = static_cast<T>(val + iAmt);
320}
321
322template<typename T>
323static auto
324enum_add2(T val, int iAmt) -> T
325{
326 return static_cast<T>(val + iAmt);
327}
328
329template<typename T>
330static auto
331enum_cycle(T val, int iMax, int iAmt = 1) -> T
332{
333 int iVal = val + iAmt;
334 iVal %= iMax;
335 return static_cast<T>(iVal);
336}
337
338/* We only have unsigned swaps; byte swapping a signed value doesn't make sense.
339 *
340 * Platform-specific, optimized versions are defined in arch_setup, with the
341 * names ArchSwap32, ArchSwap24, and ArchSwap16; we define them to their real
342 * names here, to force inclusion of this file when swaps are in use (to prevent
343 * different dependencies on different systems).
344 */
345#ifdef HAVE_BYTE_SWAPS
346#define Swap32 ArchSwap32
347#define Swap24 ArchSwap24
348#define Swap16 ArchSwap16
349#else
350inline auto
351Swap32(uint32_t n) -> uint32_t
352{
353 return (n >> 24) | ((n >> 8) & 0x0000FF00) | ((n << 8) & 0x00FF0000) |
354 (n << 24);
355}
356
357inline auto
358Swap24(uint32_t n) -> uint32_t
359{
360 return Swap32(n) >> 8; // xx223344 -> 443322xx -> 00443322
361}
362
363inline auto
364Swap16(uint16_t n) -> uint16_t
365{
366 return (n >> 8) | (n << 8);
367}
368#endif
369
370inline auto
371Swap32LE(uint32_t n) -> uint32_t
372{
373 return n;
374}
375inline auto
376Swap24LE(uint32_t n) -> uint32_t
377{
378 return n;
379}
380inline auto
381Swap16LE(uint16_t n) -> uint16_t
382{
383 return n;
384}
385inline auto
386Swap32BE(uint32_t n) -> uint32_t
387{
388 return Swap32(n);
389}
390inline auto
391Swap24BE(uint32_t n) -> uint32_t
392{
393 return Swap24(n);
394}
395inline auto
396Swap16BE(uint16_t n) -> uint16_t
397{
398 return Swap16(n);
399}
400
401/* return f rounded to the nearest multiple of fRoundInterval */
402inline auto
403Quantize(const float f, const float fRoundInterval) -> float
404{
405 return static_cast<int>((f + fRoundInterval / 2) / fRoundInterval) *
406 fRoundInterval;
407}
408
409inline auto
410Quantize(const int i, const int iRoundInterval) -> int
411{
412 return static_cast<int>((i + iRoundInterval / 2) / iRoundInterval) *
413 iRoundInterval;
414}
415
416/* return f truncated to the nearest multiple of fTruncInterval */
417inline auto
418ftruncf(const float f, const float fTruncInterval) -> float
419{
420 return static_cast<int>((f) / fTruncInterval) * fTruncInterval;
421}
422
423/* Return i rounded up to the nearest multiple of iInterval. */
424inline auto
425QuantizeUp(int i, int iInterval) -> int
426{
427 return static_cast<int>((i + iInterval - 1) / iInterval) * iInterval;
428}
429
430inline auto
431QuantizeUp(float i, float iInterval) -> float
432{
433 return ceilf(i / iInterval) * iInterval;
434}
435
436/* Return i rounded down to the nearest multiple of iInterval. */
437inline auto
438QuantizeDown(int i, int iInterval) -> int
439{
440 return static_cast<int>((i - iInterval + 1) / iInterval) * iInterval;
441}
442
443inline auto
444QuantizeDown(float i, float iInterval) -> float
445{
446 return floorf(i / iInterval) * iInterval;
447}
448
449// Move val toward other_val by to_move.
450void
451fapproach(float& val, float other_val, float to_move);
452
453/* Return a positive x mod y. */
454inline auto
455fmodfp(float x, float y) -> float
456{
457 x = fmodf(x, y); /* x is [-y,y] */
458 x += y; /* x is [0,y*2] */
459 x = fmodf(x, y); /* x is [0,y] */
460 return x;
461}
462
463inline auto
464power_of_two(int input) -> int
465{
466 auto exp = 31;
467 auto i = input;
468 if (i >> 16 != 0) {
469 i >>= 16;
470 } else {
471 exp -= 16;
472 }
473 if (i >> 8 != 0) {
474 i >>= 8;
475 } else {
476 exp -= 8;
477 }
478 if (i >> 4 != 0) {
479 i >>= 4;
480 } else {
481 exp -= 4;
482 }
483 if (i >> 2 != 0) {
484 i >>= 2;
485 } else {
486 exp -= 2;
487 }
488 if (i >> 1 == 0) {
489 exp -= 1;
490 }
491 const auto value = 1 << exp;
492 return input == value ? value : value << 1;
493}
494inline auto
495IsAnInt(const std::string& s) -> bool
496{
497 if (s.empty()) {
498 return false;
499 }
500
501 for (auto i : s) {
502 if (i < '0' || i > '9') {
503 return false;
504 }
505 }
506
507 return true;
508}
509auto
510IsHexVal(const std::string& s) -> bool;
511auto
512BinaryToHex(const void* pData_, int iNumBytes) -> std::string;
513auto
514BinaryToHex(const std::string& sString) -> std::string;
515auto
516HHMMSSToSeconds(const std::string& sHMS) -> float;
517auto
518SecondsToHHMMSS(float fSecs) -> std::string;
519auto
520SecondsToMSSMsMs(float fSecs) -> std::string;
521auto
522SecondsToMMSSMsMs(float fSecs) -> std::string;
523auto
524SecondsToMMSSMsMsMs(float fSecs) -> std::string;
525auto
526SecondsToMSS(float fSecs) -> std::string;
527auto
528SecondsToMMSS(float fSecs) -> std::string;
529auto
530PrettyPercent(float fNumerator, float fDenominator) -> std::string;
531inline auto
532PrettyPercent(int fNumerator, int fDenominator) -> std::string
533{
534 return PrettyPercent(float(fNumerator), float(fDenominator));
535}
536auto
537Commify(int iNum) -> std::string;
538auto
539Commify(const std::string& num,
540 const std::string& sep = ",",
541 const std::string& dot = ".") -> std::string;
542auto
543FormatNumberAndSuffix(int i) -> std::string;
544
545auto
546GetLocalTime() -> struct tm;
547
548// Supress warnings about format strings not being string literals
549#if defined(__clang__)
550#pragma clang diagnostic push
551#pragma clang diagnostic ignored "-Wformat-security"
552#elif defined(__GNUC__)
553#pragma GCC diagnostic push
554#pragma GCC diagnostic ignored "-Wformat-security"
555#elif defined(_MSC_VER)
556// TODO: Suppress warnings for Windows
557#endif
558template<typename... Args>
559auto
560ssprintf(const char* format, Args... args) -> std::string
561{
562 // Extra space for '\0'
563 size_t size = snprintf(nullptr, 0, format, args...) + 1;
564 std::unique_ptr<char[]> buf(new char[size]);
565 snprintf(buf.get(), size, format, args...);
566 // Don't want the '\0' inside
567 return std::string(buf.get(), buf.get() + size - 1);
568}
569#if defined(__clang__)
570#pragma clang diagnostic pop
571#elif defined(__GNUC__)
572#pragma GCC pop
573#elif defined(_MSC_VER)
574// TODO: Suppress warnings for Windows
575#endif
576
577template<typename... Args>
578auto
579ssprintf(const std::string& format, Args... args) -> std::string
580{
581 return ssprintf(format.c_str(), args...);
582}
583
584auto
585vssprintf(const char* fmt, va_list argList) -> std::string;
586auto
587ConvertI64FormatString(const std::string& sStr) -> std::string;
588
589/*
590 * Splits a Path into 4 parts (Directory, Drive, Filename, Extention).
591 * Supports UNC path names. If Path is a directory (eg.
592 * c:\games\stepmania"), append a slash so the last element will end up in
593 * Dir, not FName: "c:\games\stepmania\".
594 * */
595void
596splitpath(const std::string& Path,
597 std::string& Dir,
598 std::string& Filename,
599 std::string& Ext);
600
601auto
602SetExtension(const std::string& path, const std::string& ext) -> std::string;
603auto
604GetExtension(const std::string& sPath) -> std::string;
605auto
606GetFileNameWithoutExtension(const std::string& sPath) -> std::string;
607void
608MakeValidFilename(std::string& sName);
609
610auto
611FindFirstFilenameContaining(const std::vector<std::string>& filenames,
612 std::string& out,
613 const std::vector<std::string>& starts_with,
614 const std::vector<std::string>& contains,
615 const std::vector<std::string>& ends_with) -> bool;
616
617extern const wchar_t INVALID_CHAR;
618
619auto
620utf8_get_char_len(char p) -> int;
621auto
622utf8_to_wchar(const char* s, size_t iLength, unsigned& start, wchar_t& ch)
623 -> bool;
624auto
625utf8_to_wchar_ec(const std::string& s, unsigned& start, wchar_t& ch) -> bool;
626void
627wchar_to_utf8(wchar_t ch, std::string& out);
628auto
629utf8_get_char(const std::string& s) -> wchar_t;
630auto
631utf8_is_valid(const std::string& s) -> bool;
632void
633utf8_remove_bom(std::string& s);
634void
635MakeUpper(char* p, size_t iLen);
636void
637MakeLower(char* p, size_t iLen);
638void
639MakeLower(std::string& data);
640void
641MakeUpper(wchar_t* p, size_t iLen);
642void
643MakeLower(wchar_t* p, size_t iLen);
648auto
649StringToInt(const std::string& sString) -> int;
654auto
655IntToString(const int& iNum) -> std::string;
656auto
657StringToFloat(const std::string& sString) -> float;
658auto
659FloatToString(const float& num) -> std::string;
660auto
661StringToFloat(const std::string& sString, float& fOut) -> bool;
662// Better than IntToString because you can check for success.
663template<class T>
664auto
665operator>>(const std::string& lhs, T& rhs) -> bool
666{
667 return !!(std::istringstream(lhs) >> rhs);
668}
669
670auto
671WStringToString(const std::wstring& sString) -> std::string;
672auto
673WcharToUTF8(wchar_t c) -> std::string;
674auto
675StringToWString(const std::string& sString) -> std::wstring;
676
678{
679 const char* szIsoCode;
680 const char* szEnglishName;
681};
682void
683GetLanguageInfos(std::vector<const LanguageInfo*>& vAddTo);
684auto
685GetLanguageInfo(const std::string& sIsoCode) -> const LanguageInfo*;
686
687// Splits a std::string into an std::vector<std::string> according the
688// Delimitor.
689void
690split(const std::string& sSource,
691 const std::string& sDelimitor,
692 std::vector<std::string>& asAddIt,
693 bool bIgnoreEmpty = true);
694void
695split(const std::wstring& sSource,
696 const std::wstring& sDelimitor,
697 std::vector<std::wstring>& asAddIt,
698 bool bIgnoreEmpty = true);
699
700/* In-place split. */
701void
702split(const std::string& sSource,
703 const std::string& sDelimitor,
704 int& iBegin,
705 int& iSize,
706 bool bIgnoreEmpty = true);
707void
708split(const std::wstring& sSource,
709 const std::wstring& sDelimitor,
710 int& iBegin,
711 int& iSize,
712 bool bIgnoreEmpty = true);
713
714/* In-place split of partial string. */
715void
716split(const std::string& sSource,
717 const std::string& sDelimitor,
718 int& iBegin,
719 int& iSize,
720 int iLen,
721 bool bIgnoreEmpty); /* no default to avoid ambiguity */
722void
723split(const std::wstring& sSource,
724 const std::wstring& sDelimitor,
725 int& iBegin,
726 int& iSize,
727 int iLen,
728 bool bIgnoreEmpty);
729
730// Joins a std::vector<std::string> to create a std::string according the
731// Deliminator.
732auto
733join(const std::string& sDelimitor, const std::vector<std::string>& sSource)
734 -> std::string;
735auto
736join(const std::string& sDelimitor,
737 std::vector<std::string>::const_iterator begin,
738 std::vector<std::string>::const_iterator end) -> std::string;
739
740auto
741luajoin(const std::string& sDelimitor, const std::vector<std::string>& sSource)
742 -> std::string;
743auto
744luajoin(const std::string& sDelimitor,
745 std::vector<std::string>::const_iterator begin,
746 std::vector<std::string>::const_iterator end) -> std::string;
747
748// These methods escapes a string for saving in a .sm or .crs file
749auto
750SmEscape(const std::string& sUnescaped) -> std::string;
751auto
752SmEscape(const char* cUnescaped, int len) -> std::string;
753
754// These methods "escape" a string for .dwi by turning = into -, ] into I,
755// etc. That is "lossy".
756auto
757DwiEscape(const std::string& sUnescaped) -> std::string;
758auto
759DwiEscape(const char* cUnescaped, int len) -> std::string;
760
761auto
762GetCwd() -> std::string;
763
764void
765SetCommandlineArguments(int argc, char** argv);
766void
767GetCommandLineArguments(int& argc, char**& argv);
768auto
769GetCommandlineArgument(const std::string& option,
770 std::string* argument = nullptr,
771 int iIndex = 0) -> bool;
772extern int g_argc;
773extern char** g_argv;
774
775void
776CRC32(unsigned int& iCRC, const void* pBuffer, size_t iSize);
777auto
778GetHashForString(const std::string& s) -> unsigned int;
779auto
780GetHashForFile(const std::string& sPath) -> unsigned int;
781auto
782GetHashForDirectory(const std::string& sDir)
783 -> unsigned int; // a hash value that remains the
784 // same as long as nothing in the
785 // directory has changed
786auto
787DirectoryIsEmpty(const std::string& sPath) -> bool;
788
789auto
790CompareStringsAsc(const std::string& sStr1, const std::string& sStr2) -> bool;
791void
792SortStringArray(std::vector<std::string>& asAddTo, bool bSortAscending = true);
793
794/* Find the mean and standard deviation of all numbers in [start,end). */
795auto
796calc_mean(const float* pStart, const float* pEnd) -> float;
797/* When bSample is true, it calculates the square root of an unbiased
798 * estimator for the population variance. Note that this is not an unbiased
799 * estimator for the population standard deviation but it is close and an
800 * unbiased estimator is complicated (apparently). When the entire
801 * population is known, bSample should be false to calculate the exact
802 * standard deviation. */
803auto
804calc_stddev(const float* pStart, const float* pEnd, bool bSample = false)
805 -> float;
806
807/* Useful for objects with no operator-, eg. std::map::iterator (more
808 * convenient than advance). */
809template<class T>
810inline auto
811Increment(T a) -> T
812{
813 ++a;
814 return a;
815}
816template<class T>
817inline auto
818Decrement(T a) -> T
819{
820 --a;
821 return a;
822}
823auto
824compress_string(const std::string& str, int compressionLevel = 9) -> std::string;
825auto
826decompress_string(const std::string& str) -> std::string;
827std::string
828base64_encode(const ::std::string& bindata);
829std::string
830base64_decode(const std::string& ascdata);
831void
832TrimLeft(std::string& sStr, const char* szTrim = "\r\n\t ");
833void
834TrimRight(std::string& sStr, const char* szTrim = "\r\n\t ");
835void
836Trim(std::string& sStr, const char* szTrim = "\r\n\t ");
837void
838StripCrnl(std::string& sStr);
839auto
840BeginsWith(const std::string& sTestThis, const std::string& sBeginning) -> bool;
841auto
842EndsWith(const std::string& sTestThis, const std::string& sEnding) -> bool;
843auto
844URLEncode(const std::string& sStr) -> std::string;
845
846auto
847DerefRedir(const std::string& sPath) -> std::string;
848auto
849GetFileContents(const std::string& sPath,
850 std::string& sOut,
851 bool bOneLine = false) -> bool;
852auto
853GetFileContents(const std::string& sFile, std::vector<std::string>& asOut)
854 -> bool;
855
856class Regex
857{
858 public:
859 Regex(const std::string& sPat = "");
860 Regex(const Regex& rhs);
861 auto operator=(const Regex& rhs) -> Regex&;
862 auto operator=(Regex&& rhs) noexcept -> Regex&;
863 ~Regex();
864 [[nodiscard]] auto IsSet() const -> bool { return !m_sPattern.empty(); }
865 void Set(const std::string& str);
866 auto Compare(const std::string& sStr) -> bool;
867 auto Compare(const std::string& sStr, std::vector<std::string>& asMatches)
868 -> bool;
869 auto Replace(const std::string& sReplacement,
870 const std::string& sSubject,
871 std::string& sOut) -> bool;
872
873 private:
874 void Compile();
875 void Release();
876
877 void* m_pReg;
878 unsigned m_iBackrefs;
879 std::string m_sPattern;
880};
881
882void
883ReplaceEntityText(std::string& sText,
884 const std::map<std::string, std::string>& m);
885void
886ReplaceEntityText(std::string& sText, const std::map<char, std::string>& m);
887void
888Replace_Unicode_Markers(std::string& Text);
889auto
890WcharDisplayText(wchar_t c) -> std::string;
891
892auto
893Basename(const std::string& dir) -> std::string;
894auto
895Dirname(const std::string& dir) -> std::string;
896auto
897Capitalize(const std::string& s) -> std::string;
898
899#if defined(HAVE_UNISTD_H)
900#include <unistd.h> /* correct place with correct definitions */
901#endif
902
903extern unsigned char g_UpperCase[256];
904extern unsigned char g_LowerCase[256];
905
906/* ASCII-only case insensitivity. */
907struct char_traits_char_nocase : public std::char_traits<char>
908{
909 static auto eq(char c1, char c2) -> bool
910 {
911 return g_UpperCase[static_cast<unsigned char>(c1)] ==
912 g_UpperCase[static_cast<unsigned char>(c2)];
913 }
914
915 static auto ne(char c1, char c2) -> bool
916 {
917 return g_UpperCase[static_cast<unsigned char>(c1)] !=
918 g_UpperCase[static_cast<unsigned char>(c2)];
919 }
920
921 static auto lt(char c1, char c2) -> bool
922 {
923 return g_UpperCase[static_cast<unsigned char>(c1)] <
924 g_UpperCase[static_cast<unsigned char>(c2)];
925 }
926
927 static auto compare(const char* s1, const char* s2, size_t n) -> int
928 {
929 int ret = 0;
930 while ((n--) != 0U) {
931 ret = fasttoupper(*s1++) - fasttoupper(*s2++);
932 if (ret != 0) {
933 break;
934 }
935 }
936 return ret;
937 }
938
939 static auto fasttoupper(char a) -> char
940 {
941 return g_UpperCase[static_cast<unsigned char>(a)];
942 }
943
944 static auto find(const char* s, int n, char a) -> const char*
945 {
946 a = fasttoupper(a);
947 while (n-- > 0 && fasttoupper(*s) != a) {
948 ++s;
949 }
950
951 if (fasttoupper(*s) == a) {
952 return s;
953 }
954 return nullptr;
955 }
956};
957using istring = std::basic_string<char, char_traits_char_nocase>;
958
959/* Compatibility/convenience shortcuts. These are actually defined in
960 * RageFileManager.h, but declared here since they're used in many places.
961 */
962void
963GetDirListing(const std::string& sPath,
964 std::vector<std::string>& addTo,
965 bool onlydir,
966 bool returnPathToo);
967
968void
969GetDirListingRecursive(const std::string& sDir,
970 const std::string& sMatch,
971 std::vector<std::string>& AddTo); /* returns path too */
972void
973GetDirListingRecursive(RageFileDriver* prfd,
974 const std::string& sDir,
975 const std::string& sMatch,
976 std::vector<std::string>& AddTo); /* returns path too */
977auto
978DoesFileExist(const std::string& sPath) -> bool;
979auto
980IsAFile(const std::string& sPath) -> bool;
981auto
982IsADirectory(const std::string& sPath) -> bool;
983auto
984GetFileSizeInBytes(const std::string& sFilePath) -> int;
985
990auto
991head(std::string const& source, int32_t length) -> std::string;
992
997auto
998tail(std::string const& source, int32_t length) -> std::string;
999
1000// call FixSlashesInPlace on any path that came from the user
1001void
1002FixSlashesInPlace(std::string& sPath);
1003void
1004CollapsePath(std::string& sPath, bool bRemoveLeadingDot = false);
1005
1007namespace StringConversion {
1008template<typename T>
1009auto
1010FromString(const std::string& sValue, T& out) -> bool;
1011
1012template<typename T>
1013auto
1014ToString(const T& value) -> std::string;
1015
1016template<>
1017inline auto
1018FromString<std::string>(const std::string& sValue, std::string& out) -> bool
1019{
1020 out = sValue;
1021 return true;
1022}
1023template<>
1024inline auto
1025ToString<std::string>(const std::string& value) -> std::string
1026{
1027 return value;
1028}
1029} // namespace StringConversion
1030
1031class RageFileBasic;
1032auto
1033FileCopy(const std::string& sSrcFile, const std::string& sDstFile) -> bool;
1034auto
1035FileCopy(RageFileBasic& in,
1036 RageFileBasic& out,
1037 std::string& sError,
1038 bool* bReadError = nullptr) -> bool;
1039
1040template<class T>
1041void
1042GetAsNotInBs(const std::vector<T>& as,
1043 const std::vector<T>& bs,
1044 std::vector<T>& difference)
1045{
1046 std::vector<T> bsUnmatched = bs;
1047 // Cannot use FOREACH_CONST here because std::vector<T>::const_iterator
1048 // is an implicit type.
1049 for (typename std::vector<T>::const_iterator a = as.begin(); a != as.end();
1050 ++a) {
1051 typename std::vector<T>::iterator iter =
1052 find(bsUnmatched.begin(), bsUnmatched.end(), *a);
1053 if (iter != bsUnmatched.end())
1054 bsUnmatched.erase(iter);
1055 else
1056 difference.push_back(*a);
1057 }
1058}
1059
1060template<class T>
1061void
1062GetConnectsDisconnects(const std::vector<T>& before,
1063 const std::vector<T>& after,
1064 std::vector<T>& disconnects,
1065 std::vector<T>& connects)
1066{
1067 GetAsNotInBs(before, after, disconnects);
1068 GetAsNotInBs(after, before, connects);
1069}
1070
1071#endif
Definition RageFileBasic.h:10
Definition RageFileDriver.h:12
Definition RageUtil.h:857
Utilities for converting the Strings.
Definition GameConstantsAndTypes.cpp:49
Definition RageUtil.h:273
Definition RageUtil.h:678
Definition RageUtil.h:908