A HEADER FILE project with useful macros and template functions for C/C++. 一个只有头文件的,有许多实用宏和函数的 C/C++ 轮子库
Homepage: https://github.com/BH2WFR/cutil Author: BH2WFR LICENSE: MIT License (except extern codes)
Reference of Ansi Escape Codes:
- https://en.wikipedia.org/wiki/ANSI_escape_code
- https://zh.wikipedia.org/wiki/ANSI%E8%BD%AC%E4%B9%89%E5%BA%8F%E5%88%97
| name | author | link | path | license |
|---|---|---|---|---|
| scope_guard | ricab | https://github.com/ricab/scope_guard | External/ScopeGuard.hpp |
Unlicense |
| xorstr | JustasMasiulis | https://github.com/JustasMasiulis/xorstr | External/XorStr.hpp |
Apache 2.0 |
| span | tcbrindle | https://github.com/tcbrindle/span | External/Span.hpp |
BSL 1.0 |
| strutil | Shot511 | https://github.com/Shot511/strutil | External/StrUtil.h |
MIT |
| magic_enum | Neargye | https://github.com/Neargye/magic_enum | External/MaginEnum/*.h |
MIT |
-
namespace of this library is
cutil::, and it has a shorter aliascu::. if you want to disable shorter alias namespacecu::, add#define CUTIL_PARAM_USE_SHORTEN_NAMESPACE = 1before including headers, then you can only use bycutil::. 本库的命名空间为cutil::,且有一个叫cu::的简称。在引用本库头文件前,加入#define CUTIL_PARAM_USE_SHORTEN_NAMESPACE = 1,可以停止使用cu::简称,只能用cutil::访问本库。 -
features using ANSI Escape code (like color customizing, or cursor moving macros in this header file) DO NOT SUPPORT Windows version lower than Windows 10 1511, otherwise it can't display properly in windows cmd. ANSI Escape Code 不支持 Windows 10 1511 以下的 Windows 版本,否则无法在 CMD 中正常显示。
- If you are using these operating systems, pls
#define CONSOLE_UTIL_ANSI_ESCAPE_UNSUPPORTED 1before#include <cutil/console_utils.h>to disable features by printing Ansi Escape Code.
- If you are using these operating systems, pls
-
C language version
≥ C99, C++ language≥ C++14(≥C++17 recommended) , with##__VA_ARGS__extension support. C 语言标准最低 C99, C++ 标准最低 C++14 (推荐 ≥C++17), 且有##__VA_ARGS__编译器扩展 (VS2015 Update 3 后支持此扩展)(MSVC supports
##__VA_ARGS__since VS2015 Update 3. if your MSVC or VS version is older, pls delete "##", MSVC eats trailing comma before__VA_ARGS__by default without/Zc::preprocessorcommand) -
UTF-8 encoding REQUIRED for C++ compiler. pls add
/utf-8compiler argument for MSVC. 如果使用 C++, 强制要求编译器使用 UTF-8 编码. 如果使用的是 MSVC 编译器, 请加入/utf-8编译参数 -
Pls #include this header after other header files, especially those from libraries such as Qt/fmtlib, or OS API headers like
<windows.h>/<unistd.h>. DO NOT #include <cutil/console_utils.h> in header files. -
#define CUTIL_ANSI_ESCAPE_UNSUPPORTED 1BEFORE include of this header may turn off all the features with ANSI Escape Code. -
#define CUTIL_FORCE_FUNCTION_STATIC 1BEFORE include ofCppUtil.hppmay let all the inline functions to bestatic inline -
#define CUTIL_FORCE_UTF8 0BEFORE include may turn off UTF-8 literal encoding checking (C++ Only). By Default, if you are using MSVC,/UTF-8compiler param is REQUIRED.
-
cutil::equal_any(...):
(compared == arg1 || compared == arg2 || compared == arg3 || ...)cutil::equal_all(...):(compared == arg1 && compared == arg2 && compared == arg3 && ...)cutil::unequal_all(...):(compared != arg1 || compared != arg2 || compared != arg3 || ...)cutil::uniqual_any(...):(compared != arg1 && compared != arg2 && compared != arg3 && ...)后续参数与第一个参数,有相等的?全部相等?有不等的?全部不等(不是互不相等)?
int var = 10; if(cutil::equal_any(var, 2, 4, 6, 8, 10)){ // equivalent to `if(var == 2 || var == 4 || var == 6 || var == 8 || var == 10)` // equivalent to `if(!CUTIL_UNEQUAL_ALL(var, 2, 4, 6, 8, 10))` } if(cutil::equal_all(var, 2, 4, 6, 8, 10)){ // equivalent to `if(var == 2 && var == 4 && var == 6 && var == 8 && var == 10)` // equivalent to `if(cutil::equal_mutually(var, 2, 4, 6, 8, 10))` // equivalent to `if(!cutil::unequal_any(var, 2, 4, 6, 8, 10))` } if(cutil::unequal_all(var, 2, 4, 6, 8, 10)){ // equivalent to `if(var != 2 && var != 4 && var != 6 && var != 8 && var != 10)` // equivalent to `if(! cutil::equal_any(var, 2, 4, 6, 8, 10))` } if(cutil::unequal_any(var, 2, 4, 6, 8, 10)){ // equivalent to `if(var != 2 || var != 4 || var != 6 || var != 8 || var != 10)` // equivalent to `if(! cutil::equal_all(var, 2, 4, 6, 8, 10))` }
-
cutil::unequal_mutually(...): check if variables are mutually different. 互不相等
If's recommended to use std::set<> if number of arguments is more than 5. 参数在 5 以上,推荐使用 std::set<>
cutil::equal_mutually(...): equivalent to
cutil::equal_all(a1, a2, a3, a4, a5)互相相等if(cutil::unequal_mutually(a1, a2, a3, a4);){ // is `a1`, `a2`, `a3`, `a4` mutually different? // ( ((a1) != (a2) && (a1) != (a3) && (a1) != (a4)) // && ((a2) != (a3) && (a2) != (a4)) // && ((a3) != (a4)) ) } if(cutil::equal_mutually(a1, a2, a3, a4, a5)){ // ((a1) == (a2) && (a1) == (a3) && (a1) == (a4) && (a1) == (a5)) // equivalent to `if(cutil::equal_all(a1, a2, a3, a4, a5))` }
-
cutil::increasing(...):
(a1 < a2 && a2 < a3 && ...)递增序列 cutil::decreasing(...):(a1 > a2 && a2 > a3 && ...)递减序列 cutil::increasing_equal(...):(a1 <= a2 && a2 <= a3 && ...)递增(可相等)序列 cutil::decreasing_equal(...):(a1 >= a2 && a2 >= a3 && ...)递减(可相等)序列constexpr bool b1 = cutil::increasing(1, 2, 3, 4, 5); // true constexpr bool b2 = cutil::increasing(1, 2, 3, 3, 5); // false constexpr bool b3 = cutil::decreasing(5, 4, 3, 2, 1); // true constexpr bool b4 = cutil::decreasing(5, 4, 3, 3, 1); // false constexpr bool b5 = cutil::increasing_equal(1, 2, 3, 3, 5); // true constexpr bool b6 = cutil::decreasing_equal(5, 4, 3, 3, 1); // true
-
cutil::enum_int(enum_value)
convert enum type to underlying integer type: 将枚举值 转化为 该枚举类型对应的底层整型
enum class MyEnum : uint8_t { None = 0, Flag1 = 1 << 0, // 0b00000001 Flag2 = 1 << 1, // 0b00000010 Flag3 = 1 << 2, // 0b00000100 Flag4 = 1 << 3, // 0b00001000 }; // convert enum to its underlying integer type uint8_t value = cutil::enum_int(MyEnum::Flag1); // uint8_t, 0b00000011
-
namespace cutil::enum_bitwise
bitwise operations overloading for enum class: 针对 enum class 的位运算重载:
using namespace cutil::enum_bitwise; // you must include this namespace to use bitwise operators auto flag = MyEnum::Flag1 | MyEnum::Flag2; auto flag2 = MyEnum::Flag1 & MyEnum::Flag2; auto flag3 = MyEnum::Flag1 ^ MyEnum::Flag2; auto flag4 = ~MyEnum::Flag1; flag |= MyEnum::Flag2; flag &= MyEnum::Flag3; flag ^= MyEnum::Flag4;
-
cutil::overload<...>(&function)
for non-member functions, static member functions or member functions without const overload 非成员函数、静态成员函数、没有 const 重载的成员函数
referenced from qOverload<>() | 借鉴自 qOverload<>()
class ConvertTestClass{ public: int func() {return 0;} int func(int i) {return 1;} int func(double i) {return 2;} int func(int i, double d) {return 3;} int func() const {return 4;} // with const/non-const overload int func(int i) const {return 5;} int func(double i) const {return 6;} int func(int i, double d) const {return 7;} static int static_func() {return 8;} // non-member function static int static_func(int i) {return 9;} static int static_func(double i) {return 10;} static int static_func(int i, double d) {return 11;} int func2() {return 12;} // without const/non-const overload int func2(int i) {return 13;} int func2(double i) {return 14;} int func2(int i, double d) {return 15;} }; ConvertTestClass c; const ConvertTestClass cc; // gtest codes, it means to check if right expression equals to left expresson EXPECT_EQ(8, cutil::overload<>(&ConvertTestClass::static_func)()); EXPECT_EQ(9, cutil::overload<int>(&ConvertTestClass::static_func)(1)); EXPECT_EQ(10, cutil::overload<double>(&ConvertTestClass::static_func)(1.0)); EXPECT_EQ(11, (cutil::overload<int, double>(&ConvertTestClass::static_func)(1, 1.0))); EXPECT_EQ(12, (c.*cutil::overload<>(&ConvertTestClass::func2))()); EXPECT_EQ(13, (c.*cutil::overload<int>(&ConvertTestClass::func2))(1)); EXPECT_EQ(14, (c.*cutil::overload<double>(&ConvertTestClass::func2))(1.0)); EXPECT_EQ(15, (c.*cutil::overload<int, double>(&ConvertTestClass::func2))(1, 1.0));
-
cutil::const_overload<...>(&function) cutil::non_const_overload<...>(&function)
for member functions with const overload 有 const 重载的成员函数
EXPECT_EQ(0, (c.*cutil::non_const_overload<>(&ConvertTestClass::func))()); EXPECT_EQ(1, (c.*cutil::non_const_overload<int>(&ConvertTestClass::func))(1)); EXPECT_EQ(4, (cc.*cutil::const_overload<>(&ConvertTestClass::func))()); EXPECT_EQ(5, (cc.*cutil::const_overload<int>(&ConvertTestClass::func))(1));
-
cutil::bit_cast<T>(var): bit_cast for C++14/17 | 针对 C++14/17 的 bit_cast (按位转换)
redirects to std::bit_cast<> since C++20, and it's constexpr | C++20 起重定向到 constexpr 的 std::bit_cast uses memcpy in C++14/17, so not constexpr | C++14/17 中, 利用 memcpy 来实现转换, 不是 constexpr
-
cutil::bitwise_memcpy<Out, In>(out, in):
cutil::bitwise_memcpy(f, i) // i -> f, bitwise memcpy f = bit_cast<float>(i); // equivalent f = *reinterpret_cast<volatile float*>(&i); // equivalent std::memcpy(&f, &i, sizeof(f)); // equivalent f = std::bit_cast<float>(i) // C++20
-
cutil::safe_cast<T>(base): do
dynamic_castin DEBUG, ; dostatic_castin RELEASE, used for conversion from base class ptr to derived class ptr在 DEBUG 模式下映射到 dymanic_cast, 而在 RELEASE 模式下映射到 static_cast, 用于基类指针向派生类的转换
-
cutil::midpoint(ptr1, ptr2): get midpoint of two pointers. | 两个指针之间的中点地址
-
cutil::get_ptr_offset(ptr1, ptr2) : offset of two member variables | 两个成员指针之间的差值
-
cutil::get_member_offset(ptr) : offset of the member variable in struct/class | 成员距离其所在结构体/类的偏移量
struct S { int a; int b; }; ptrdiff_t offset = cutil::memory::get_member_offset(&A::b); // offset of b in struct S S s; ptrdiff_t offset = cutil::memory::get_ptr_offset(&s.a, &s.b); // offset of two pointers
-
cutil::read_memory<T>(ptr) cutil::write_memory<T>(ptr, val)
-
cutil::memcpy_type cutil::memmove_type cutil::memset_type cutil::memcmp_type cutil::malloc_type cutil::calloc_type cutil::realloc_type
-
cutil::free_ptr : free()/delete/delete[] a pointer and set to nullptr cutil::delete_ptr cutil::delete_array
-
Iterator Expression Generator
#define CUTIL_IT_RANGE(_container) (_container).begin(), (_container).end() #define CUTIL_CTI_RANGE(_container) (_container).cbegin(), (_container).cend() #define CUTIL_RIT_RANGE(_container) (_container).rbegin(), (_container).rend() #define CUTIL_CRIT_RANGE(_container) (_container).crbegin(), (_container).crend() std::vector<int> vec(10); std::iota(CUTIL_IT_RANGE(vec), 0); // fill vec with 0 to 9
-
cutil::contains(container, value): wrapper of std::find and std::find_if, without typing
.begin()and.end()cutil::contains_if(container, pred)std::vector<int> vec = {1, 2, 3, 4, 5}; if(cutil::contains(vec, 3)){} if(cutil::contains(std::execution::par_seq, vec, 3)){} // C++17 if(cutil::contains_if(vec, [](int i){return i == 3;})){} if(cutil::contains_if((std::execution::par_seq, vec, [](int i){return i == 3;})){} // C++17
-
cutil::erase_vector(container, value): combination of std::remove and .erase() for std::vector and std::deque, to erase a value
std::vector<int> e1 = {1, 2, 2, 4, 2, 5, 4}; size_t removed = cutil::erase_vector(e1, 2); // 3 removed = cutil::erase_if_vector(e1, [](int i){return i == 4;}); // 2 e1.clear(); removed = cutil::erase_vector(e1, 6); // 0
-
cutil::num::___ / cutil::numbers::___ cutil::Num<T>::___ / cutil::Numbers<T>::___
Mathematical Constants** like
pifor C++14/17, similar asstd::numbersin C++20 针对 C++14/17 的数学常量, 与 C++20 中的 std::numbers 类似float pi = cutil::num::pi_f; double pi = cutil::num::pi; long double pi_ld = cutil::num::pi_ld float pi = cutil::Num<float>::pi; double pi = cutil::Num<double>::pi; long double pi_ld = cutil::Num<long double>::pi float var; var = cutil::Num<float>::inf; // redirects to std::numeric_limits<float>::infinity() var = cutil::Num<float>::neg_inf; var = cutil::Num<float>::nan; // redirectes to std::numeric_limits<float>::quiet_NaN()
-
cutil::fequal_eps(a, b, eps) cutil::fequal_ulp(a, b, ulp) cutil::fequal_zero(a)
compare if two floating numbers could be regarded as equal by epsilon or ULP 基于 epsilon 或 ULP 方法比较两个浮点数是否可被认作相等
available to use
fequal_epsorfequal_zeroif compared number is near zero, otherwise recommended to usefequal_ulp当被比较浮点数接近 0 时, 可用fequal_eps或fequal_zero, 否则建议使用fequal_ulp.fequal_ulpforlong doubleis not tested for Linux, BE CAREFUL BEFORE USING. (long double is 8 bytes in windows, and 16 bytes in Linux) 针对long double的fequal_ulp尚未在 Linux 中测试, 使用前请注意 (long double 在 windows 中为 8 字节, 在 linux 中为 16 字节)fequal_ulpis not constexpr. -
cutil::pow<exp_int>(num)
>= C++17cutil::pow(num, exp_int)
C++14power of a number, with integer exponent, unwrap to multiply itself for times. 指数为整数的乘方, 展开为多次自身相乘
exponent number could be template argument since C++17, and it is recommended 指数从 C++ 17 起可作为模板参数, 且推荐这样的写法
std::powis for floating number exponents, sometimes it is inefficient if exponent is an integer and not too large 标准库的std::pow是针对浮点数指数, 当指数为较小的整数时并不高效 referenced fromint ret = cutil::pow(2, 3); // generates `2*2*2`, 2^3 = 8 int ret = cutil::pow<3>(2); // generates `2*2*2`, 2^3 = 8, >=C++17
-
cutil::deg2rad(deg) cutil::rad2deg(rad)
convert an angle between deg and rad | 角度弧度互转
double a = cutil::deg2rad(30.0); EXPECT_EQ(true, cutil::fequal_ulp(a, cutil::numbers::pi / 6.0));
-
cutil::git_digit<digit>(num)
>= C++17cutil::get_digit(num, digit)C++14get any digit of a decimal number | 获取十进制数的任意一位数
cutil::get_digit<0>(12345) == 5; // get the last digit cutil::get_digit<1>(12345) == 4; // get the second last digit cutil::get_digit<2>(12345) == 3; // get the third last digit cutil::get_digit<-1>(12345) == 0; // get the first digit after the decimal point cutil::get_digit<-1>(123.456,) == 6; // get the first digit after the decimal point cutil::get_digit<-2>(123.456) == 5; // get the second digit after the decimal point
-
cutil::lerp(a, b, t)
Linear Interpolation
(a + (b-a) * t)for C++14/17 | 针对 C++14/17 的线性插值(redirects to
std::lerpsince C++20). t should be in the range [0, 1]. if t = 0, returns a; if t == 1, returns b. if t is out of range [0, 1], the behavior is undefined.EXPECT_EQ(true, (cutil::fequal_ulp(17.5, cutil::math::lerp(10, 20, 0.75))) ); EXPECT_EQ(true, (cutil::fequal_ulp(20.0, cutil::math::lerp(10, 20, 1.0))) ); EXPECT_EQ(true, (cutil::fequal_eps(10.0, cutil::math::lerp(10, 20, 0.0), 1e-14))) );
-
cutil::cmp_equal(a, b) cutil::cmp_not_equal(a, b) cutil::cmp_less(a, b) cutil::cmp_less_equal(a, b) cutil::cmp_greater(a, b) cutil::cmp_greater_equal(a, b)
SAFE signed/unsigned interger comparison for C++14/17 安全的有符号/无符号整数比较函数 (C++14/17)
redirects to std::cmp_equal, std::cmp_less, ... since C++20.
bool cmp; cmp = cutil::cmp_less(-1, 1U); // true cmp = cutil::cmp_less_equal(-1, 1u); // false cmp = cutil::cmp_greater(-1, 1u); // false cmp = cutil::cmp_not_equal(-1, 0xFFFFFFFFu); // true
-
cutil::in_range<T>(a)
check if a value is within the range of a integer type for C++14/17 检查某个数值是否在某个整数型的可表示范围内 (C++14/17)
will be redirected to std::in_range since C++20.
bool a = cutil::in_range<size_t>(-1); // false bool b = cutil::in_range<int>(-1); // true bool c = cutil::in_range<unsigned int>(-1); // false static_assert(cutil::in_range<size_t>(999), "999 is in range of size_t");
-
cutil::midpoint(a, b)
midpoint of two integer or floating point numbers for C++14/17 获取两个整数或浮点数的中间值 (针对 C++14/17)
redirects to
std::midpointsince C++20.EXPECT_EQ(cutil::math::midpoint(6.0, 9.0), 7.5); EXPECT_EQ(cutil::math::midpoint(6, 9), 7);
-
cutil::gcd(a, b) cutil::lcm(a, b)
Greatest Common Divisor (GCD), and Lease Common Multiple (LCM) for C++14 针对 C++14 的最大公因数, 最小公倍数
(redirects to
std::gcdandstd::lcmsince C++17). -
cutil::clamp(var, min, max, comp)
clamp the value between a range for C++14 将一个值 "夹" 在上下范围之间, 针对 C++14
redirects to
std::clamp()since C++17int a = 35, b = 26, c = 19, d = 35; d = std::clamp(d, 20, 30); // C++17, equivalent to above d = cutil::math::clamp(d, 20, 30); // C++14, equivalent to above d = cutil::math::clamp(d, 20, 30, std::less<int>()); // equivalent to above
-
cutil::factorial(num) :
factorial of an integer | 整数的阶乘
int ret = cutil::factorial(3); // 3! = 6
-
increase or decrease the number within a range (limit), or increase or decrease rolling within a range
[namespace modified to cutil::]
-
execute any lambda expression while the object destructs (RAII defer lock) 创建一个 RAII 对象, 并在析构时执行任意 lambda
-
useful for automatic resource cleaning while operating some object without RAII 在调用没有 RAII 机制的对象时, 可用此模块进行自动资源释放
-
use
auto xxxx = cutil::make_scope_guard([&yyy](){yyy->close();});to create a RAII object. -
use
.dismiss()to dismiss it (will not execute while distructing) -
use
.execute_and_dismiss()to excute beforehand, and dismiss it (will not execute while distructing)void someFunction() { MyDevice* pDevice = Manager::getDevice(); pDevice->open(); auto closeDevice = cutil::make_scope_guard([&pDevice] { if(pDevice->isOpen()){ pDevice->close(); } }); // do something with pDevice if(...){ return ; // if something goes wrong, the device will be closed automatically } // do something else with pDevice pDevice->close(); // if everything is ok, close the device manually } void someFunction2() { MyDevice* pDevice = Manager::getDevice(); pDevice->open(); auto closeDevice = cutil::make_scope_guard([&pDevice] { if(pDevice->isOpen()){ pDevice->close(); } }); //... closeDevice.dismiss(); // if you want to dismiss the scope guard, call dismiss() before leaving the scope // pDevice will not be closed automatically } void someFunction3() { MyDevice* pDevice = Manager::getDevice(); pDevice->open(); auto closeDevice = cutil::make_scope_guard([&pDevice] { if(pDevice->isOpen()){ pDevice->close(); } }); //... // if you want to execute the callback and dismiss the scope guard, call execute_and_dismiss() before leaving the scope closeDevice.execute_and_dismiss(); // pDevice will not be closed automatically }
-
cutil::get_bit_by_mask(num, bit_mask) cutil::set_bit_by_mask(num, bit_mask) cutil::clear_bit_by_mask(num, bit_mask) cutil::flip_bit_by_mask(num, bit_mask) cutil::check_bit_by_mask(num, bit_mask) -> bool
operate bit for unsigned integer by mask 用 遮罩 进行 无符号整数类型的位操作
uint16_t num {0}; num = cutil::bit::set_bit_by_mask(num, 0x2B00); // equals to {num = num | 0x2B00;} num = cutil::bit::clear_bit_by_mask(num, 0x2B00); // equals to {num = num & ~0x2B00;} num = cutil::bit::flip_bit_by_mask(num, 0x1100); // equals to {num = num ^ 0x1100;} if(cutil::bit::get_bit_by_mask(num, 0x0022) != 0x0000) {} if(cutil::bit::check_bit_by_mask(num, 0x0022) == true){} // reading bit, if bit is 1, returns `true`
-
cutil::get_bit_by_idx(num, bit_idx) cutil::set_bit_by_idx(num, bit_idx) cutil::clear_bit_by_idx(num, bit_idx) cutil::flip_bit_by_idx(num, bit_idx) cutil::check_bit_by_idx(num, bit_idx) -> bool
operate bit for unsigned integer by idx, supports setting bits by once using
std::initializer_list<>用 位序号 进行 无符号整数类型的位操作, 支持使用std::initializer_list<>批量设置uint16_t num {0}; num = cutil::bit::set_bit_by_idx(num, 1); // equals to {num = num | (1u << 0));} num = cutil::bit::clear_bit_by_idx(num, 2); // equals to {num = num & ~(1u << 2));} num = cutil::bit::flip_bit_by_idx(num, 3); // equals to {num = num ^ (1u << 3));} num = cutil::bit::set_bit_by_idx(num, {0, 1, 3}); // initializer_list available num = cutil::bit::clear_bit_by_idx(num, {0, 1, 3}); // initializer_list available num = cutil::bit::flip_bit_by_idx(num, {0, 1, 3}); // initializer_list available if(cutil::bit::get_bit_by_idx(num, 0) != 0x0000){} // reading bit, if bit is 1, returns `(1<<bitIdx)`, NOT `1` if(cutil::bit::check_bit_by_idx(num, 0) == true){} // reading bit, if bit is 1, returns `true`
-
cutil::insert_bit_left(num, inserted:bool) cutil::insert_bit_right(num, inserted:bool)
insert bit to the left, then shift others to right.
(bit >> 1) | (inserted << (bitSize - 1))insert bit to the right, then shift others to left.(bit << 1) | inserteduint16_t var2 {0b0001'0010'0011'0100}; var2 = cutil::bit::insert_bit_left(var2, true); -> 0b1000'1001'0001'1010 var2 = cutil::bit::insert_bit_right(var2, false); -> 0b0001'0010'0011'0100
-
cutil::get_msb(num) cutil::get_lsb(num)
get msb (most significant bit, the leftmost bit) get lsb (least significant bit, the rightmost bit)
-
cutil::rotl(num) cutil::rotr(num)
rotate bit left/right by step for C++14/17 | 循环位移, 针对 C++14/17 redirects to
std::rotlandstd::rotrsince C++20.uint16_t var {0b0001'0010'0011'0100}; var = cutil::bit::rotate_bit_left(var, 1); -> 0b0010'0100'0110'1000 var = cutil::bit::rotate_bit_right(var, 1); -> 0b0001'0010'0011'0100 var = cutil::bit::rotate_bit_left(var, 4); -> 0b0010'0100'0110'1000 fmt::println("var={:#016b}", var);
-
cutil::has_single_bit(num) cutil::is_power_of_2(num)
check if the lowest bit is 1, that is, check if the number is power of 2 ({1, 2, 4, 8...}), (
== num != 0 && (num & (num - 1)) == 0) 检测最低位是否为 1, 也就是检查是否为 2 的整数次方 redirects tostd::has_single_bitsince C++20.
C macro version of above features
Useful ANSI Escape code macros, and some functions for console output.
-
Set Front Color, Back Color, and font style for messages to print by printf/cout.
Forecolors:
FBlack,FRed,FGreen,FYellow,FBlue,FMagenta,FCyan,FWhite,FDefault,FRgb(66, 66, 66)Bright Forecolors:
FGray(=FGrey,FLBlack),FLRed,FLGreen,FLYellow,FLBlue,FLMagenta,FLCyan,FLWhite;Backcolors:
BBlack,BRed,BGreen,BYellow,BBlue,BMagenta,BCyan,BWhite,BDefault,BRgb(66, 66, 66);Bright Backcolors:
BGray(=BGrey,BLBlack),BLRed,BLGreen,BLYellow,BLBlue,BLMagenta,BLCyan,BLWhite;Font Styles:
CBold,CWeak,CItalic,CUnderLine,CFlash,CQFlash,CInvert(swap fg and bg colors),CHide;Reset to Default:
CRstorCReset, you must append this to the end of the string literal to revert console style back to default.printf(BRed FLGreen CQFlash "test" CReset "\n"); // Red Background, Light Green Text Forecolor, and flashing quickly std::cout << CCyan "test" CReset << "\n"; // Text forecolor: cyan fmt::println(CYellow "test" CReset); // Text forecolor: yellow
-
Control text cursor location in console, or erase text.
Move cursor:
CUp(2),CDown(3),CFwd(4),CBack(5),CNextLn(1),CPrevLn(1),CHorzPos(12)(column X, absolute),CPos(44, 55)(move the cursor to row 44, column 55) Just print them, use individual or append to string literals.printf(CForward(2)); // move thr cursor 2 characters right, equals to `CRight(2)` or `CFwd(2)`. printf(CCursorPos(15, 20)); // move the text cursor to (15, 20) position CUTIL_CONSOLE_CURSOR_POS(15, 20); // equivalent, calls SetConsoleCursorPosition() in win32.
-
set console encoding, console window size (in windows), or console title, also with pause program and force abort the program.
CUTIL_CHCP_ENCODING_UTF8(); // switch console encoding to UTF-8 (windows) cutil::console::set_chcp_encoding(cutil::console::Encodings::UTF8); // C++ version cutil::console::set_chcp_encoding_utf8(); CUTIL_CONSOLE_TITLE("MyProject"); // set console window title (calls SetConsoleTitleA() or SetConsoleTitleW() for windows, and print ansi escape code "\033]0;%s\007" for linux) cutil::console::set_title("MyProject"); // CUTIL_CONSOLE_TITLE(_TEXT("MyProgram")); // CUTIL_CONSOLE_TITLE_A("MyProgram"); // CUTIL_CONSOLE_TITLE_W(L"MyProgram"); CUTIL_CONSOLE_SIZE(100, 30); // set console window size to with of 30 chars and height of 30 lines (only available in windows) cutil::console::set_size(100, 30); CUTIL_CONSOLE_CLEAR(); // clear console (calls system("cls") ) cutil::console::clear(); printf("中文한글\n"); // you can correctly display this when the code saved in UTF-8 Encoding, especially in MSVC Compiler.
// available encodings: CUTIL_CHCP_ENCODING_UTF8(); CUTIL_CHCP_ENCODING_GB2312(); CUTIL_CHCP_ENCODING_BIG5(); CUTIL_CHCP_ENCODING_KOR(); CUTIL_CHCP_ENCODING_JIS(); CUTIL_CHCP_ENCODING_LATIN1(); CUTIL_CHCP_ENCODING_LATIN2(); CUTIL_CHCP_ENCODING_CYR(); CUTIL_CHCP_ENCODING_WIN1250(); CUTIL_CHCP_ENCODING_WIN1251(); CUTIL_CHCP_ENCODING_WIN1252();
- set program locale to
UTF-8
CUTIL_LOCALE_UTF8(); // setlocale(LC_ALL, ".UTF-8") CUTIL_LOCALE_DEFAULT(); // setlocale(LC_ALL, "") CUTIL_LOCALE_UTF8_PRINT(); // print if succeed or not
- set program locale to
-
Print Text only in Debug Build, and do Not Print in Release Build.
pls make sure that macro "
_DEBUG" is defined in Debug Build, or macro "NDEBUG" is defined in Release Build.int a{1}; CUTIL_DEBUG_PRINTLN("debug text {}", a); // calls fmt::println()(fmtlib) or std::println()(C++23) CUTIL_DEBUG_COUT("debug text " << a << '\n'); // calls std::cout << CUTIL_DEBUG_PRINTF("debug text %d", a); // calls printf() // these function-like macros will DO NOTHING IN RELEASE BUILD. CUTIL_DEBUG_PRINTLN_ERR("debug stderr text {}", a); // print to stderr CUTIL_DEBUG_CERR("debug stderr text " << a << '\n'); CUTIL_DEBUG_PRINTF_ERR("debug stderr text %d", a);
-
Flush the input buffer to ensure that subsequent "scanf()" or "cin" calls receive valid input.
(吸收输入缓存区内的其余字符, 以便下次 scanf 或 cin 时能够获取到正确的输入内容)
// #define CUTIL_FLUSH_INPUT_BUFFER() {char ch; while((ch = getchar()) != '\n') continue;} int num1, num2; scanf("%d", &num1); // you inputed "123ss", then still remains characters "ss" in the input buffer CUTIL_CONSOLE_FLUSH_INPUTBUFFER(); // flush input buffer (clear) scanf("%d", &num2); // you can normally input other contents. // C++ version: std::cin >> num1; cutil::console::flush_input_buffer(); // C++ Version std::cin >> num2;
-
print argc and argv arguments of main(int argc, char* argv[]) function in sequence.
int main(int argc, char* argv[]){ CUTIL_PRINT_ARGV(argc, argv); // print all argc and argv[n] of main() function cutil::console::print_argv(argc, argv); // C++ version return 0; }
-
Print custom Error Message with filename, line number and function name
打印错误信息,并输出当前文件名、行号、函数名
-
EXAMPLES for C:
#include <locale.h> #include <stdio.h> #include <windows.h> // include other headers first #include <fmt/core.h> // include other headers first #include <cutil/console_utils.h> // include this header at last int main(int argc, char* argv[]){ CUTIL_CHCP_ENCODING_UTF8(); // switch console encoding to UTF-8 (windows) CUTIL_LOCALE_UTF8_PRINT(); // set locale to UTF-8, and print the current locale CUTIL_ENABLE_VIRTUAL_TERMINAL(); // enable virtual terminal processing in Windows console, so that ANSI escape codes can be used. CUTIL_CONSOLE_TITLE(_TEXT("MyProject")); // set console window title CUTIL_CONSOLE_SIZE(100, 30); // set console window size to with of 30 chars and height of 30 lines. CUTIL_CONSOLE_CLEAR(); // clear console (system("cls")) CUTIL_PRINT_ARGV(argc, argv); // print all argc and argv[n] of main() function printf(FLGreen "Hello World!\n" CRst); // print "Hello World" with light yellow console color formatting you should put "CRst" at the end of string to RESET console font color to DEFAULT printf(CStyle(FLGreen, "Hello World!\n")); // Equivalent fprintf(stderr, FLRed "ERROR\n" CRst); // print "ERROR" with font color light red, "CRst" is also needed to revert font color to default fprintf(stderr, CStyle(FLRed, "ERROR\n")); // Equivalent printf(BRed FGreen CQFlash "test\n" CRst); // Print text with green font and red background, and quickly flashing printf(CStyle(BRed FGreen CQFlash, "test\n"));// Equivalent printf(CForward(2)); // move thr cursor 2 characters right, equals to `CRight(2)` or `CFwd(2)`. CUTIL_ERROR_MESSAGE("error occurred!"); // print an error message with filename, function name and line number ATTACHED. CUTIL_CONSOLE_PAUSE(); // system("pause"); return 0; }
-
EXAMPLES for C++:
#include <clocale> #include <iostream> #include <fmt/core.h> // optional #include <windows.h> // windows only #include <cutil/console_utils.h> // include this header at last int main(int argc, char* argv[]){ cutil::console::set_locale_utf8(); // set locale to UTF-8 cutil::console::set_chcp_encoding(cutil::console::Encodings::UTF8); // set console encoding to UTF-8, you can also use `set_chcp_encoding_utf8()` cutil::console::enable_virtual_terminal(); // enable virtual terminal processing in Windows console, so that ANSI escape codes can be used. cutil::console::set_title("MyProject"); // set console window title cutil::console::set_size(100, 30); // set console window size to with of 30 chars and height of 30 lines. cutil::console::clear(); // clear console (system("cls")) cutil::console::print_argv(argc, argv); // print all argc and argv[n] of main() function fmt::println(FLGreen "Hello World!" CRst); // print "Hello World" with light green console color formatting fmt::println(stderr, FLRed "ERROR" CRst); // print "ERROR" with font color light red fmt::println(BRed FGreen CQFlash "test" CRst); // Print text with green font and red background, and quickly flashing cutil::console::pause(); // system("pause"); return 0; }
-
Console Effects 控制台效果 :
refers to: https://github.com/Shot511/strutil
[namespace modified to cutil::str::]
additional functions added:
- Sanitize Filename
- convert std::string to numbers
this header is included by all other headers
-
Get compiler type and version:
#ifdef CUTIL_COMPILER_MSVC #ifdef CUTIL_COMPILER_GCC #ifdef CUTIL_COMPILER_CLANG #ifdef CUTIL_COMPILER_MSVC_2022
-
Get CPU architecture, bit width, features and endian type:
#ifdef CUTIL_CPU_ARCH_X86 // x86 and x86_64 #ifdef CUTIL_CPU_ARCH_X86_64 #ifdef CUTIL_CPU_ARCH_X86_32 #ifdef CUTIL_CPU_ARCH_ARM #ifdef CUTIL_CPU_ARCH_ARM_64 #ifdef CUTIL_CPU_ARCH_ARM_32 #ifdef CUTIL_CPU_ARCH_64BIT #ifdef CUTIL_CPU_ARCH_32BIT #if CUTIL_PTR_SIZE == 8 #if CUTIL_PTR_SIZE == 4 #ifdef CUTIL_ENDIAN_LITTLE #ifdef CUTIL_ENDIAN_BIG
-
Get OS Type:
#ifdef CUTIL_OS_WINDOWS #ifdef CUTIL_OS_WINDOWS_64 #ifdef CUTIL_OS_WINDOWS_32 #ifdef CUTIL_OS_CYGWIN #ifdef CUTIL_OS_LINUX #ifdef CUTIL_OS_MACOS
-
Get C and C++ Language standard:
#ifdef CUTIL_C99_SUPPORTED #ifdef CUTIL_C11_SUPPORTED #ifdef CUTIL_C17_SUPPORTED #ifdef CUTIL_C23_SUPPORTED #ifdef CUTIL_CPP14_SUPPORTED #ifdef CUTIL_CPP17_SUPPORTED #ifdef CUTIL_CPP20_SUPPORTED #ifdef CUTIL_CPP23_SUPPORTED
-
Get if build mode is Debug or Release (
NDEBUGshould be defined):#ifdef CUTIL_DEBUG_BUILD fmt::println("debug message"); #endif // equivalents to CUTIL_DEBUG_PRINTLN("debug message");
-
IF statement using macros:
CUTIL_IF(1, a, b) // -> a CUTIL_IF(0, a, b) // -> b CUTIL_IF(666, a, b) // -> a
-
count amount of arguments of a function-like macro
int a = CUTIL_VA_CNT(); // -> 0 int b = CUTIL_VA_CNT(b1); // -> 1 int c = CUTIL_VA_CNT(c1, c2); // -> 2 int d = CUTIL_VA_CNT(c1, c2, c3); // -> 3 ... int a = CUTIL_VA_EXISTS(); // -> 0 int b = CUTIL_VA_EXISTS(b1); // -> 1 int c = CUTIL_VA_EXISTS(c1, c2); // -> 1 int d = CUTIL_VA_EXISTS(c1, c2, c3); // -> 1
-
Overload C macros by amount of arguments of function-like macro:
#define CUTIL_EQUAL_ANY(_var, ...) \ (CUTIL_EXPAND(CUTIL_OVERLOAD_AMOUNT(_CUTIL_EQUAL_ANY_, __VA_ARGS__)(_var, __VA_ARGS__))) #define _CUTIL_EQUAL_ANY_1(_var, _1) (_var) == (_1) #define _CUTIL_EQUAL_ANY_2(_var, _1, _2) (_var) == (_1) || _CUTIL_EQUAL_ANY_1(_var, _2) #define _CUTIL_EQUAL_ANY_3(_var, _1, ...) CUTIL_EXPAND((_var) == (_1) || _CUTIL_EQUAL_ANY_2(_var, __VA_ARGS__)) #define _CUTIL_EQUAL_ANY_4(_var, _1, ...) CUTIL_EXPAND((_var) == (_1) || _CUTIL_EQUAL_ANY_3(_var, __VA_ARGS__)) #define _CUTIL_EQUAL_ANY_5(_var, _1, ...) CUTIL_EXPAND((_var) == (_1) || _CUTIL_EQUAL_ANY_4(_var, __VA_ARGS__)) // usage: if(CUTIL_EQUAL_ANY(a, 1, 2)) {} // if(a == 1 || a == 2) if(CUTIL_EQUAL_ANY(a, 1, 2, 3, 4)) // if(a == 1 || a == 2 || a == 3 || a == 4)
refers to: https://github.com/tcbrindle/span
[namespace modified to cutil::]
refers to: https://github.com/qis/xorstr
≥ C++17 REQUIRED. only supports intel x86 and ARM architectures
[namespace modified to cutil::xorstr::]
refers to: https://github.com/Neargye/magic_enum
≥ C++17 REQUIRED.
[namespace remained magic_enum::]
provides static reflection for enums by special macros provided by MSVC/G++/Clang
