Steppable 0.0.1
A CAS project written from scratch in C++
Loading...
Searching...
No Matches
util.hpp
1/**************************************************************************************************
2 * Copyright (c) 2023-2025 NWSOFT *
3 * *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy *
5 * of this software and associated documentation files (the "Software"), to deal *
6 * in the Software without restriction, including without limitation the rights *
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell *
8 * copies of the Software, and to permit persons to whom the Software is *
9 * furnished to do so, subject to the following conditions: *
10 * *
11 * The above copyright notice and this permission notice shall be included in all *
12 * copies or substantial portions of the Software. *
13 * *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE *
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, *
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE *
20 * SOFTWARE. *
21 **************************************************************************************************/
22
34
35#pragma once
36
37#include "colors.hpp"
38#include "output.hpp"
39#include "platform.hpp"
40
41#include <algorithm>
42#include <array>
43#include <chrono>
44#include <clocale>
45#include <cstddef>
46#include <iomanip>
47#include <iostream>
48#include <sstream>
49#include <string>
50#include <vector>
51
52using namespace std::literals;
53
54#ifndef TIC
59 #define TIC(...) \
60 { \
61 const char* nameSection = #__VA_ARGS__; \
62 std::cout << colors::brightBlue << std::setw(80) << std::setfill('-') << reset << '\n'; \
63 std::cout << colors::brightBlue << "[Profiling: " << nameSection << ']' << reset << '\n'; \
64 auto start = std::chrono::high_resolution_clock::now();
65#endif
66
67#ifndef TOC
69 #define TOC() \
70 auto duration = \
71 std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now() - start) \
72 .count(); \
73 std::cout << colors::brightBlue << '[' << nameSection << " took " << duration << "(microseconds) to execute]" \
74 << reset << '\n'; \
75 std::cout << colors::brightBlue << std::setw(80) << std::setfill('-'); \
76 std::cout << reset << '\n'; \
77 }
78#endif
79
80#ifndef MAX_DECIMALS
82 #define MAX_DECIMALS 50
83#endif
84
86{
87#ifndef MS_STDLIB_BUGS
88 #if (_MSC_VER || __MINGW32__ || __MSVCRT__)
89 #define MS_STDLIB_BUGS 1
90 #else
91 #define MS_STDLIB_BUGS 0 // NOLINT(cppcoreguidelines-macro-usage)
92 #endif
93#endif
94
95#if MS_STDLIB_BUGS
96 #include <fcntl.h>
97 #include <io.h>
98#endif
99
100#ifdef WINDOWS
101 #include <fcntl.h>
102 #include <windows.h>
103
109 inline DWORD enableVtMode()
110 {
111 // Set output mode to handle virtual terminal sequences
112 const HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
113 if (hOut == INVALID_HANDLE_VALUE)
114 return -1;
115
116 DWORD dwMode = 0;
117 if (!GetConsoleMode(hOut, &dwMode))
118 return -1;
119 const DWORD dwModeOrig = dwMode;
120
121 dwMode |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
122 if (!SetConsoleMode(hOut, dwMode))
123 return -1;
124 return dwModeOrig;
125 }
126
133 inline bool restoreVtMode(const DWORD dwModeOrig)
134 {
135 const HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
136 if (hOut == INVALID_HANDLE_VALUE)
137 return false;
138
139 if (!SetConsoleMode(hOut, dwModeOrig))
140 return false;
141 return true;
142 }
143
151 class Utf8CodePage
152 {
153 public:
160 Utf8CodePage() : oldCodePage(GetConsoleOutputCP())
161 {
162 SetConsoleOutputCP(CP_UTF8);
163 dwModeOrig = enableVtMode();
164 }
165
172 {
173 SetConsoleOutputCP(oldCodePage);
174 restoreVtMode(dwModeOrig);
175 }
176
177 private:
178 UINT oldCodePage;
179 DWORD dwModeOrig;
180 };
181#else
182
191 {
192 public:
194 };
195#endif
196
205 template<typename NumberT>
206 void checkDecimalArg(const NumberT* decimal)
207 {
208 if (*decimal > MAX_DECIMALS)
209 {
210 output::error("checkDecimalArg"s,
211 "The number of decimals ({0}) is more than the accepted {1} digits."s,
212 { std::to_string(*decimal), std::to_string(MAX_DECIMALS) });
214 }
215 }
216
221 template<size_t N>
223 {
228 constexpr StringLiteral(const char (&str)[N]) // NOLINT(*-pro-type-member-init, *-explicit-constructor)
229 { // NOLINT(*-avoid-c-arrays)
230 std::copy_n(str, N, value);
231 }
232
236 char value[N]; // NOLINT(*-avoid-c-arrays)
237 };
238} // namespace steppable::__internals::utils
239
245{
254 {
255 std::array<std::string, 4> splitNumberArray;
256 bool aIsNegative = false, bIsNegative = false;
257 };
258
268 std::string simplifyZeroPolarity(const std::string& string);
269
275 std::string simplifyPolarity(const std::string& _string);
276
283 std::string standardizeNumber(const std::string& _number);
284
294 constexpr bool isZeroString(const std::string& string)
295 {
296 return std::ranges::all_of(string, [](const char c) { return c == '0' or c == '.' or c == '-'; });
297 }
298
305 bool isNumber(const std::string& s);
306
319 SplitNumberResult splitNumber(const std::string& a,
320 const std::string& b,
321 bool padInteger = true,
322 bool padDecimal = true,
323 bool properlyFormat = true,
324 bool preserveNegative = false);
325
332 auto replaceLeadingZeros(const std::vector<int>& vector) -> std::decay_t<decltype(vector)>;
333
340 auto removeLeadingZeros(const std::vector<int>& vector) -> std::decay_t<decltype(vector)>;
341
348 auto removeLeadingZeros(const std::string& string) -> std::decay_t<decltype(string)>;
349
356 auto removeTrailingZeros(const std::vector<int>& _vector) -> std::decay_t<decltype(_vector)>;
357
364 auto removeTrailingZeros(const std::string& numStr) -> std::decay_t<decltype(numStr)>;
365
372 long long determineScale(const std::string& number);
373
380 bool isInteger(const std::string& number);
381
388 bool isDecimal(const std::string& number);
389
396 bool isPowerOfTen(const std::string& number);
397
404 bool isOdd(const std::string& number);
405
412 bool isEven(const std::string& number);
413} // namespace steppable::__internals::numUtils
414
420{
428 template<typename CharT>
429 auto split(std::basic_string<CharT> s, const CharT separator)
430 {
431 std::vector<decltype(s)> substrings;
432 std::basic_stringstream<CharT> ss(s);
433 decltype(s) token;
434
435 while (getline(ss, token, separator))
436 substrings.push_back(token);
437
438 return substrings;
439 }
440
448 template<typename CharT>
449 auto split(std::basic_string_view<CharT> s, const CharT separator)
450 {
451 std::vector<decltype(s)> result;
452 auto left = s.begin();
453 for (auto it = left; it != s.end(); ++it)
454 {
455 if (*it == separator)
456 {
457 result.emplace_back(&*left, it - left);
458 left = it + 1;
459 }
460 }
461 if (left != s.end())
462 result.emplace_back(&*left, s.end() - left);
463 return result;
464 }
465
480 template<typename CharT>
481 auto rReplace(const std::basic_string<CharT> s, const CharT t, const CharT replacement = '\0')
482 {
483 std::basic_string<CharT> out = s;
484 typename std::basic_string<CharT>::size_type count = 0;
485 while (out.back() == t)
486 {
487 out.pop_back();
488 ++count;
489 }
490 if (replacement != '\0')
491 out += std::basic_string<CharT>(count, replacement);
492 return out;
493 }
494
506 template<typename CharT>
507 auto lReplace(const std::basic_string<CharT> s, const CharT t, const CharT replacement = '\0')
508 {
509 std::basic_string<CharT> out = s;
510 typename std::basic_string<CharT>::size_type count = 0;
511 while (out[0] == t)
512 {
513 out.erase(out.begin());
514 ++count;
515 }
516 if (replacement != '\0')
517 out = std::basic_string<CharT>(count, replacement) + out;
518 return out;
519 }
520
535 template<typename CharT>
536 auto bothEndsReplace(const std::basic_string<CharT> s, const CharT t, const CharT replacement = '\0')
537 {
538 return lReplace(rReplace(s, t, replacement), t, replacement);
539 }
540
549 template<typename T>
550 auto join(const std::vector<T>& vector, const std::string& delimiter)
551 {
552 std::stringstream result;
553 for (const auto& item : vector)
554 result << item << delimiter;
555 return result.str();
556 }
557
564 std::string makeWider(const std::string& orig);
565
572 [[maybe_unused]] int utf8ToUnicode(const std::string& utf8_code);
573
583 std::string unicodeToUtf8(int unicode);
584
590 std::vector<std::string> duplicates(const std::vector<std::string>& vector);
591
592 template<typename ValueType>
593 std::string vectorToString(const std::vector<ValueType>& vector)
594 {
595 std::ostringstream out;
596 out << "[";
597 for (size_t i = 0; i < vector.size(); ++i)
598 {
599 out << vector[i];
600 if (i != vector.size() - 1)
601 out << ", ";
602 }
603 return out.str();
604 }
605} // namespace steppable::__internals::stringUtils
A class that sets the console output code page to UTF-8 and enables VT mode.
Definition util.hpp:191
Utilities to operate numbers.
Definition factors.cpp:35
bool isEven(const std::string &number)
Checks if a number is even.
Definition util.cpp:300
auto removeLeadingZeros(const std::vector< int > &vector) -> std::decay_t< decltype(vector)>
Definition util.cpp:191
std::string simplifyPolarity(const std::string &_string)
Simplifies a string with non-standard polarity (e.g., –1, —1, etc.).
Definition util.cpp:77
std::string simplifyZeroPolarity(const std::string &string)
Simplifies a string that represents a number with non-standard polarity.
Definition util.cpp:69
auto removeTrailingZeros(const std::vector< int > &_vector) -> std::decay_t< decltype(_vector)>
Definition util.cpp:220
constexpr bool isZeroString(const std::string &string)
Checks if a given string is a zero string.
Definition util.hpp:294
bool isOdd(const std::string &number)
Checks if a number is odd.
Definition util.cpp:289
bool isPowerOfTen(const std::string &_number)
Determines whether the number is a power of 10.
Definition util.cpp:273
long long determineScale(const std::string &number)
Determines the scale of a number, i.e., the power of 10 when it is expressed in scientific notation.
Definition util.cpp:244
bool isInteger(const std::string &number)
Determines whether the number is an integer or not.
Definition util.cpp:264
bool isNumber(const std::string &s)
Checks if a given string is a valid number.
Definition util.cpp:42
auto replaceLeadingZeros(const std::vector< int > &vector) -> std::decay_t< decltype(vector)>
Definition util.cpp:177
std::string standardizeNumber(const std::string &_number)
Standardizes a number string.
Definition util.cpp:85
SplitNumberResult splitNumber(const std::string &_a, const std::string &_b, const bool padInteger, const bool padDecimal, bool properlyFormat, bool preserveNegative)
Definition util.cpp:103
bool isDecimal(const std::string &number)
Determines whether the number is a decimal or not.
Definition util.cpp:271
Utilities to operate strings.
Definition util.cpp:312
auto split(std::basic_string< CharT > s, const CharT separator)
Splits a string into substrings based on a separator.
Definition util.hpp:429
std::string vectorToString(const std::vector< ValueType > &vector)
Definition util.hpp:593
std::string unicodeToUtf8(const int unicode)
Converts a Unicode character to UTF-8 encoding.
Definition util.cpp:342
auto join(const std::vector< T > &vector, const std::string &delimiter)
Joins a vector of elements into a single string using a delimiter.
Definition util.hpp:550
auto lReplace(const std::basic_string< CharT > s, const CharT t, const CharT replacement='\0')
Replaces the leading occurrences of a character in a string with a replacement character.
Definition util.hpp:507
auto rReplace(const std::basic_string< CharT > s, const CharT t, const CharT replacement='\0')
Replaces the trailing occurrences of a character in a string with another character.
Definition util.hpp:481
std::string makeWider(const std::string &orig)
Makes the given string wider by adding 2 spaces between each character.
Definition util.cpp:313
std::vector< std::string > duplicates(const std::vector< std::string > &vector)
Gets the duplicates in a vector of strings.
auto bothEndsReplace(const std::basic_string< CharT > s, const CharT t, const CharT replacement='\0')
Replaces the leading and trailing occurrences of a character in a string with a replacement character...
Definition util.hpp:536
int utf8ToUnicode(const std::string &utf8_code)
Converts a UTF-8 encoded string to a Unicode string.
Definition util.cpp:325
The namespace containing utility functions for the Steppable library.
Definition argParse.cpp:40
void programSafeExit(const int status)
Exit the program safely.
Definition platform.hpp:59
void checkDecimalArg(const NumberT *decimal)
Checks whether the decimal number is correctly specified.
Definition util.hpp:206
void error(const std::string &name, const std::basic_string< T > &msg, const std::vector< std::string > &args={})
Prints an error message.
Definition output.hpp:80
A structure for storing split numbers.
Definition util.hpp:254
std::array< std::string, 4 > splitNumberArray
Definition util.hpp:255
char value[N]
The value of the wrapper class. Stores the string object.
Definition util.hpp:236
constexpr StringLiteral(const char(&str)[N])
Initializes the wrapper class.
Definition util.hpp:228
Untitled