Skip to content

Commit 114f54d

Browse files
committed
Add min/max & clamp functions
1 parent 211d314 commit 114f54d

File tree

4 files changed

+93
-13
lines changed

4 files changed

+93
-13
lines changed

libraries/libim/content/text/impl/text_resource_writer.cpp

+7-9
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "../text_resource_writer.h"
22
#include "text_resource_literals.h"
3+
#include <libim/math/math.h>
34

45
using namespace libim;
56
using namespace libim::text;
@@ -26,11 +27,8 @@ TextResourceWriter& TextResourceWriter::writeRowIdx(std::size_t idx, std::size_t
2627
const auto strIdx = utils::to_string(idx);
2728
if(indent > 0)
2829
{
29-
const auto strIdxLen = strIdx.size(); // Note: Do not change this!
30-
// clang7 and gcc 8 try to optimize out strIdx.size()
31-
// in std::minmax which then returns garbage
32-
indent = indent - std::min(strIdxLen, indent);
33-
this->indent(indent);
30+
auto[min, max] = minmax(indent, strIdx.size());
31+
this->indent(max - min);
3432
}
3533

3634
ostream_ << strIdx << kResLabelPunc;
@@ -47,15 +45,15 @@ TextResourceWriter& TextResourceWriter::write(std::string_view text, std::size_t
4745
{
4846
write(text);
4947

50-
auto[min, max] = std::minmax(fieldWidth, std::clamp(text.size(), minSep, fieldWidth));
51-
auto indw = std::max(minSep, max - min);
48+
auto[min, max] = minmax(fieldWidth, clamp(text.size(), minSep, fieldWidth));
49+
auto indw = ::max(minSep, max - min);
5250
indent(indw, indentChar);
5351
return *this;
5452
}
5553

5654
TextResourceWriter& TextResourceWriter::writeCommentLine(std::string_view comment)
5755
{
58-
if(!comment.empty())
56+
if (!comment.empty())
5957
{
6058
ostream_ << ChComment << ChSpace << comment;
6159
writeEol();
@@ -92,7 +90,7 @@ TextResourceWriter& TextResourceWriter::writeLine(std::string_view line)
9290

9391
TextResourceWriter& TextResourceWriter::writeSection(std::string_view section, bool overline)
9492
{
95-
if(overline) {
93+
if (overline) {
9694
writeLine(kResSectionHeader);
9795
}
9896
return writeLabel(kResName_Section, section);

libraries/libim/math/box.h

+4-3
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@
55
#include <vector>
66
#include <tuple>
77

8-
#include "vector.h"
8+
#include "math.h"
99
#include "size.h"
10+
#include "vector.h"
1011

1112
namespace libim {
1213
template <typename T, std::size_t N> class Box
@@ -80,8 +81,8 @@ namespace libim {
8081

8182
for(; v0_it != v0.end(); ++v0_it, ++v1_it, ++b0_it, ++b1_it, ++nv0_it, ++nv1_it)
8283
{
83-
*nv0_it = std::max(*v0_it, *b0_it);
84-
*nv1_it = std::min(*v1_it, *b1_it);
84+
*nv0_it = max(*v0_it, *b0_it);
85+
*nv1_it = min(*v1_it, *b1_it);
8586
}
8687

8788
return Box(nv0, nv1);

libraries/libim/math/math.h

+79
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
#ifndef LIBIM_MATH_H
22
#define LIBIM_MATH_H
3+
#include <algorithm>
34
#include <cmath>
45
#include <cfloat>
56
#include <type_traits>
7+
#include <utility>
68

79
namespace libim {
810

@@ -31,6 +33,83 @@ namespace libim {
3133
}
3234
}
3335

36+
/** clamp overload for arithmetic types (numbers) for std::clamp because r-value references can cause UB */
37+
template<class T, typename = std::enable_if_t<std::is_arithmetic_v<std::remove_reference_t<T>>>>
38+
[[nodiscard]] constexpr inline T clamp(T v, T lo, T hi) {
39+
return std::clamp(v, lo, hi);
40+
}
41+
42+
template<class T, typename = std::enable_if_t<!std::is_arithmetic_v<std::remove_reference_t<T>>>>
43+
[[nodiscard]] constexpr inline const T& clamp(const T& v, const T& lo, const T& hi) {
44+
return std::clamp(v, lo, hi);
45+
}
46+
47+
template<class T, typename = std::enable_if_t<!std::is_arithmetic_v<std::remove_reference_t<T>>>>
48+
[[nodiscard]] constexpr inline T& clamp(T& v, T& lo, T& hi) {
49+
return const_cast<T&>(std::clamp(v, lo, hi));
50+
}
51+
52+
template<class T, typename = std::enable_if_t<!std::is_arithmetic_v<std::remove_reference_t<T>>>>
53+
T&& clamp(T&&, T&&, T&&) = delete;
54+
55+
/** min overload for arithmetic types (numbers) for std::min because r-value references can cause UB */
56+
template<typename T, typename = std::enable_if_t<std::is_arithmetic_v<std::remove_reference_t<T>>>>
57+
[[nodiscard]] constexpr inline T min(T a, T b) {
58+
return std::min({ a, b });
59+
}
60+
61+
template<typename T, typename = std::enable_if_t<!std::is_arithmetic_v<std::remove_reference_t<T>>>>
62+
[[nodiscard]] constexpr inline const T& min(const T& a, const T& b ) {
63+
return std::min(a, b);
64+
}
65+
66+
template<typename T, typename = std::enable_if_t<!std::is_arithmetic_v<std::remove_reference_t<T>>>>
67+
[[nodiscard]] constexpr inline T& min(T& a, T& b ) {
68+
return const_cast<T&>(std::min(a, b));
69+
}
70+
71+
template<typename T, typename = std::enable_if_t<!std::is_arithmetic_v<std::remove_reference_t<T>>>>
72+
[[nodiscard]] constexpr inline T&& min(T&&, T&&) = delete;
73+
74+
/** max overload for arithmetic types (numbers) for std::max because r-value references can cause UB */
75+
template<typename T, typename = std::enable_if_t<std::is_arithmetic_v<std::remove_reference_t<T>>>>
76+
[[nodiscard]] constexpr inline T max(T a, T b) {
77+
return std::max({ a, b });
78+
}
79+
80+
template<typename T, typename = std::enable_if_t<!std::is_arithmetic_v<std::remove_reference_t<T>>>>
81+
[[nodiscard]] constexpr inline const T& max(const T& a, const T& b ) {
82+
return std::max(a, b);
83+
}
84+
85+
template<typename T, typename = std::enable_if_t<!std::is_arithmetic_v<std::remove_reference_t<T>>>>
86+
[[nodiscard]] constexpr inline T& max(T& a, T& b ) {
87+
return const_cast<T&>(std::max(a, b));
88+
}
89+
90+
template<typename T, typename = std::enable_if_t<!std::is_arithmetic_v<std::remove_reference_t<T>>>>
91+
T&& max(T&&, T&&) = delete;
92+
93+
/** minmax overload for arithmetic types (numbers) for std::minmax because r-value references can cause UB */
94+
template<typename T, typename = std::enable_if_t<std::is_arithmetic_v<std::remove_reference_t<T>>>>
95+
[[nodiscard]] constexpr inline std::pair<T, T> minmax(T a, T b) {
96+
return std::minmax({ a, b });
97+
}
98+
99+
template<typename T, typename = std::enable_if_t<!std::is_arithmetic_v<std::remove_reference_t<T>>>>
100+
[[nodiscard]] constexpr inline std::pair<const T&,const T&> minmax(const T& a, const T& b ) {
101+
return std::minmax(a, b);
102+
}
103+
104+
template<typename T, typename = std::enable_if_t<!std::is_arithmetic_v<std::remove_reference_t<T>>>>
105+
[[nodiscard]] constexpr inline std::pair<T&,T&> minmax(T& a, T& b) {
106+
auto p = std::minmax(a, b);
107+
return { const_cast<T&>(p.first), const_cast<T&>(p.second) };
108+
}
109+
110+
template<typename T, typename = std::enable_if_t<!std::is_arithmetic_v<std::remove_reference_t<T>>>>
111+
std::pair<T&&, T&&> minmax(T&&, T&&) = delete;
112+
34113

35114
template<typename T, typename = std::enable_if<std::is_floating_point_v<T>>>
36115
static constexpr T epsilon = std::numeric_limits<T>::epsilon();

libraries/libim/text/impl/tokenizer_p.h

+3-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
#include "../diagnostic_location.h"
88
#include "../../io/stream.h"
99

10+
#include <libim/math/math.h>
11+
1012
#include <array>
1113
#include <cctype>
1214
#include <functional>
@@ -35,7 +37,7 @@ namespace libim::text {
3537
}
3638
else
3739
{
38-
auto[p, q] = std::minmax(istream_.tell() - position, end_);
40+
auto[p, q] = minmax(istream_.tell() - position, end_);
3941
pos_ = q - p;
4042
}
4143
}

0 commit comments

Comments
 (0)