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