Skip to content

Commit

Permalink
Define detail namespace
Browse files Browse the repository at this point in the history
  • Loading branch information
alandefreitas committed Apr 17, 2022
1 parent 7553c03 commit 919d5bd
Show file tree
Hide file tree
Showing 45 changed files with 6,792 additions and 7,054 deletions.
2 changes: 1 addition & 1 deletion examples/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,7 @@ int main() {
template <class R>
void print(R&& v) {
for (const auto& x : v) {
constexpr bool x_is_pair = small::is_pair_v<std::decay_t<decltype(x)>>;
constexpr bool x_is_pair = small::detail::is_pair_v<std::decay_t<decltype(x)>>;
if constexpr (not x_is_pair) {
std::cout << x << ' ';
} else {
Expand Down
125 changes: 63 additions & 62 deletions source/small/detail/algorithm/console_unicode_guard.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
// https://www.boost.org/LICENSE_1_0.txt
//


#ifndef SMALL_DETAIL_ALGORITHM_CONSOLE_UNICODE_GUARD_H
#define SMALL_DETAIL_ALGORITHM_CONSOLE_UNICODE_GUARD_H

Expand All @@ -18,80 +17,82 @@

#include <iostream>

#if defined(_WIN32) && __has_include(<Windows.h>)
#if defined(_WIN32) && __has_include(<Windows.h>)
#include <Windows.h>
#undef small
#endif

namespace small {
class console_unicode_guard {
public:
inline console_unicode_guard(std::ostream &os, size_t size, size_t codepoints, bool above_10000 = true) {
#if defined(_WIN32) && __has_include(<Windows.h>)
const bool is_console = &os == reinterpret_cast<std::ostream*>(&std::cout) || &os == reinterpret_cast<std::ostream*>(&std::wcout);
const bool requires_unicode = size != codepoints;
prev_console_output_cp = GetConsoleOutputCP();
requires_another_console_cp = is_console && requires_unicode && prev_console_output_cp != CP_UTF8;
if (requires_another_console_cp) {
SetConsoleOutputCP(CP_UTF8);
}
// If the highest codepoint is above U+10000, we also need to change the default console font
// to one that supports these characters if the current one can't support them yet.
// Unfortunately, cmd.exe won't support high codepoints even if the corresponding fonts
// support them. But this solves the problem for the terminals, like most IDE terminals,
// and future versions of cmd.exe.
if (requires_unicode && above_10000) {
// Console handle
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
// Get current font
ZeroMemory(&prev_console_font, sizeof(prev_console_font));
prev_console_font.cbSize = sizeof(prev_console_font);
if (GetCurrentConsoleFontEx(hStdOut, false, &prev_console_font)) {
// Check if current font supports unicode above 10000
// There's no simple heuristic to do that, be we do know 1) the default console font (consolas)
// do not support unicode above 10000 and 2) the user probably doesn't want another
// font if they explicitly chose that font.
requires_another_font = std::wcscmp(prev_console_font.FaceName, L"Consolas");
if (requires_another_font) {
CONSOLE_FONT_INFOEX new_font;
ZeroMemory(&new_font, sizeof(new_font));
new_font.cbSize = sizeof(new_font);
lstrcpyW(new_font.FaceName, L"Lucida Console");
SetCurrentConsoleFontEx(hStdOut, false, &new_font);
namespace detail {
class console_unicode_guard {
public:
inline console_unicode_guard(std::ostream &os, size_t size, size_t codepoints, bool above_10000 = true) {
#if defined(_WIN32) && __has_include(<Windows.h>)
const bool is_console = &os == reinterpret_cast<std::ostream *>(&std::cout) ||
&os == reinterpret_cast<std::ostream *>(&std::wcout);
const bool requires_unicode = size != codepoints;
prev_console_output_cp = GetConsoleOutputCP();
requires_another_console_cp = is_console && requires_unicode && prev_console_output_cp != CP_UTF8;
if (requires_another_console_cp) {
SetConsoleOutputCP(CP_UTF8);
}
// If the highest codepoint is above U+10000, we also need to change the default console font
// to one that supports these characters if the current one can't support them yet.
// Unfortunately, cmd.exe won't support high codepoints even if the corresponding fonts
// support them. But this solves the problem for the terminals, like most IDE terminals,
// and future versions of cmd.exe.
if (requires_unicode && above_10000) {
// Console handle
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
// Get current font
ZeroMemory(&prev_console_font, sizeof(prev_console_font));
prev_console_font.cbSize = sizeof(prev_console_font);
if (GetCurrentConsoleFontEx(hStdOut, false, &prev_console_font)) {
// Check if current font supports unicode above 10000
// There's no simple heuristic to do that, be we do know 1) the default console font (consolas)
// do not support unicode above 10000 and 2) the user probably doesn't want another
// font if they explicitly chose that font.
requires_another_font = std::wcscmp(prev_console_font.FaceName, L"Consolas");
if (requires_another_font) {
CONSOLE_FONT_INFOEX new_font;
ZeroMemory(&new_font, sizeof(new_font));
new_font.cbSize = sizeof(new_font);
lstrcpyW(new_font.FaceName, L"Lucida Console");
SetCurrentConsoleFontEx(hStdOut, false, &new_font);
}
}
}
}
#else
// Discard values
(void) os;
(void) size;
(void) codepoints;
(void) above_10000;
// Discard values
(void)os;
(void)size;
(void)codepoints;
(void)above_10000;
#endif
}


inline ~console_unicode_guard() {
#if defined(_WIN32) && __has_include(<Windows.h>)
if (requires_another_console_cp) {
SetConsoleOutputCP(prev_console_output_cp);
}
if (requires_another_font) {
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
SetCurrentConsoleFontEx(hStdOut, false, &prev_console_font);
}

inline ~console_unicode_guard() {
#if defined(_WIN32) && __has_include(<Windows.h>)
if (requires_another_console_cp) {
SetConsoleOutputCP(prev_console_output_cp);
}
if (requires_another_font) {
HANDLE hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);
SetCurrentConsoleFontEx(hStdOut, false, &prev_console_font);
}
#endif
}
}

private:
#if defined(_WIN32) && __has_include(<Windows.h>)
bool requires_another_console_cp{false};
UINT prev_console_output_cp{0};
bool requires_another_font{false};
CONSOLE_FONT_INFOEX prev_console_font{};
private:
#if defined(_WIN32) && __has_include(<Windows.h>)
bool requires_another_console_cp{false};
UINT prev_console_output_cp{0};
bool requires_another_font{false};
CONSOLE_FONT_INFOEX prev_console_font{};
#endif
};
};

}
} // namespace detail
} // namespace small

#endif // SMALL_DETAIL_ALGORITHM_CONSOLE_UNICODE_GUARD_H
154 changes: 78 additions & 76 deletions source/small/detail/algorithm/intcmp.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,118 +5,120 @@
// https://www.boost.org/LICENSE_1_0.txt
//


#ifndef SMALL_DETAIL_ALGORITHM_INTCMP_H
#define SMALL_DETAIL_ALGORITHM_INTCMP_H

#include <type_traits>
#include <cstddef>
#include <type_traits>

#include "../traits/cpp_version.h"

/// \headerfile Compare numbers of different types

namespace small {
namespace detail {

template <class T, class U> constexpr bool cmp_equal(T t, U u) noexcept {
using UT = std::make_unsigned_t<T>;
using UU = std::make_unsigned_t<U>;
if constexpr (std::is_signed_v<T> == std::is_signed_v<U>)
return t == u;
else if constexpr (std::is_signed_v<T>)
return t < 0 ? false : UT(t) == u;
else
return u < 0 ? false : t == UU(u);
}

template <class T, class U> constexpr bool cmp_not_equal(T t, U u) noexcept { return !cmp_equal(t, u); }
template <class T, class U> constexpr bool cmp_equal(T t, U u) noexcept {
using UT = std::make_unsigned_t<T>;
using UU = std::make_unsigned_t<U>;
if constexpr (std::is_signed_v<T> == std::is_signed_v<U>)
return t == u;
else if constexpr (std::is_signed_v<T>)
return t < 0 ? false : UT(t) == u;
else
return u < 0 ? false : t == UU(u);
}

template <class T, class U> constexpr bool cmp_less(T t, U u) noexcept {
using UT = std::make_unsigned_t<T>;
using UU = std::make_unsigned_t<U>;
if constexpr (std::is_signed_v<T> == std::is_signed_v<U>)
return t < u;
else if constexpr (std::is_signed_v<T>)
return t < 0 ? true : UT(t) < u;
else
return u < 0 ? false : t < UU(u);
}
template <class T, class U> constexpr bool cmp_not_equal(T t, U u) noexcept { return !cmp_equal(t, u); }

template <class T, class U> constexpr bool cmp_less(T t, U u) noexcept {
using UT = std::make_unsigned_t<T>;
using UU = std::make_unsigned_t<U>;
if constexpr (std::is_signed_v<T> == std::is_signed_v<U>)
return t < u;
else if constexpr (std::is_signed_v<T>)
return t < 0 ? true : UT(t) < u;
else
return u < 0 ? false : t < UU(u);
}

template <class T, class U> constexpr bool cmp_greater(T t, U u) noexcept { return cmp_less(u, t); }
template <class T, class U> constexpr bool cmp_greater(T t, U u) noexcept { return cmp_less(u, t); }

template <class T, class U> constexpr bool cmp_less_equal(T t, U u) noexcept { return !cmp_greater(t, u); }
template <class T, class U> constexpr bool cmp_less_equal(T t, U u) noexcept { return !cmp_greater(t, u); }

template <class T, class U> constexpr bool cmp_greater_equal(T t, U u) noexcept { return !cmp_less(t, u); }
template <class T, class U> constexpr bool cmp_greater_equal(T t, U u) noexcept { return !cmp_less(t, u); }

namespace detail {
/// \section Traits to promote integer types
namespace detail {
/// \section Traits to promote integer types

/// \struct Get the integer type for the given parameters
template <size_t N, bool IsSigned> struct custom_int;
/// \struct Get the integer type for the given parameters
template <size_t N, bool IsSigned> struct custom_int;

template <> struct custom_int<8, true> { typedef int8_t type; };
template <> struct custom_int<8, true> { typedef int8_t type; };

template <> struct custom_int<16, true> { typedef int16_t type; };
template <> struct custom_int<16, true> { typedef int16_t type; };

template <> struct custom_int<32, true> { typedef int32_t type; };
template <> struct custom_int<32, true> { typedef int32_t type; };

template <> struct custom_int<64, true> { typedef int64_t type; };
template <> struct custom_int<64, true> { typedef int64_t type; };

template <> struct custom_int<8, false> { typedef uint8_t type; };
template <> struct custom_int<8, false> { typedef uint8_t type; };

template <> struct custom_int<16, false> { typedef uint16_t type; };
template <> struct custom_int<16, false> { typedef uint16_t type; };

template <> struct custom_int<32, false> { typedef uint32_t type; };
template <> struct custom_int<32, false> { typedef uint32_t type; };

template <> struct custom_int<64, false> { typedef uint64_t type; };
template <> struct custom_int<64, false> { typedef uint64_t type; };

template <size_t N, bool IsSigned> using custom_int_t = typename custom_int<N, IsSigned>::type;
template <size_t N, bool IsSigned> using custom_int_t = typename custom_int<N, IsSigned>::type;

template <class T, class U> struct promoted_size {
static constexpr std::size_t first_size = sizeof(T);
static constexpr std::size_t second_size = sizeof(U);
static constexpr bool first_is_signed = std::is_signed_v<T>;
static constexpr bool second_is_signed = std::is_signed_v<U>;
static constexpr std::size_t largest_size = std::max(first_size, second_size);
static constexpr std::size_t smallest_size = std::min(first_size, second_size);
static constexpr bool largest_is_signed = first_size < second_size ? second_is_signed : first_is_signed;
static constexpr bool smallest_is_signed = first_size < second_size ? first_is_signed : second_is_signed;
static constexpr bool largest_needs_double =
largest_size == smallest_size && largest_size != 64 / 8 && not largest_is_signed && smallest_is_signed;
static constexpr size_t value = largest_size * (largest_needs_double ? 2 : 1);
};
template <class T, class U> struct promoted_size {
static constexpr std::size_t first_size = sizeof(T);
static constexpr std::size_t second_size = sizeof(U);
static constexpr bool first_is_signed = std::is_signed_v<T>;
static constexpr bool second_is_signed = std::is_signed_v<U>;
static constexpr std::size_t largest_size = std::max(first_size, second_size);
static constexpr std::size_t smallest_size = std::min(first_size, second_size);
static constexpr bool largest_is_signed = first_size < second_size ? second_is_signed : first_is_signed;
static constexpr bool smallest_is_signed =
first_size < second_size ? first_is_signed : second_is_signed;
static constexpr bool largest_needs_double = largest_size == smallest_size && largest_size != 64 / 8 &&
not largest_is_signed && smallest_is_signed;
static constexpr size_t value = largest_size * (largest_needs_double ? 2 : 1);
};

template <class T, class U> constexpr std::size_t promoted_size_v = promoted_size<T, U>::value;
template <class T, class U> constexpr std::size_t promoted_size_v = promoted_size<T, U>::value;

/// \struct Promote an integer to the proper type capable of representing both integers
template <class T, class U>
using promoted = custom_int<promoted_size_v<T, U> * 8, std::is_signed_v<T> || std::is_signed_v<U>>;
/// \struct Promote an integer to the proper type capable of representing both integers
template <class T, class U>
using promoted = custom_int<promoted_size_v<T, U> * 8, std::is_signed_v<T> || std::is_signed_v<U>>;

template <class T, class U> using promoted_t = typename promoted<T, U>::type;
} // namespace detail
template <class T, class U> using promoted_t = typename promoted<T, U>::type;
} // namespace detail

/// \brief Minimum number of two types. This returns a value rather than
template <class T, class U> constexpr detail::promoted_t<T, U> min_value(T t, U u) noexcept {
if (cmp_less(t, u)) {
return static_cast<detail::promoted_t<T, U>>(t);
} else {
return static_cast<detail::promoted_t<T, U>>(u);
/// \brief Minimum number of two types. This returns a value rather than
template <class T, class U> constexpr detail::promoted_t<T, U> min_value(T t, U u) noexcept {
if (cmp_less(t, u)) {
return static_cast<detail::promoted_t<T, U>>(t);
} else {
return static_cast<detail::promoted_t<T, U>>(u);
}
}
}

template <class T, class U> constexpr detail::promoted_t<T, U> max_value(T t, U u) noexcept {
if (cmp_less(t, u)) {
return static_cast<detail::promoted_t<T, U>>(u);
} else {
return static_cast<detail::promoted_t<T, U>>(t);
template <class T, class U> constexpr detail::promoted_t<T, U> max_value(T t, U u) noexcept {
if (cmp_less(t, u)) {
return static_cast<detail::promoted_t<T, U>>(u);
} else {
return static_cast<detail::promoted_t<T, U>>(t);
}
}
}

inline long long int div_ceil(long long int numerator, long long int denominator) {
lldiv_t res = std::div(numerator, denominator);
return res.rem ? (res.quot + 1) : res.quot;
}
inline long long int div_ceil(long long int numerator, long long int denominator) {
lldiv_t res = std::div(numerator, denominator);
return res.rem ? (res.quot + 1) : res.quot;
}

} // namespace detail
} // namespace small

#endif // SMALL_DETAIL_ALGORITHM_INTCMP_H
Loading

0 comments on commit 919d5bd

Please sign in to comment.