Skip to content

Commit 848bff2

Browse files
committed
OrcLib: Utils: add ComparisonOperator
1 parent 7f9e656 commit 848bff2

File tree

4 files changed

+270
-0
lines changed

4 files changed

+270
-0
lines changed

src/OrcLib/CMakeLists.txt

+3
Original file line numberDiff line numberDiff line change
@@ -655,6 +655,8 @@ source_group(Stream
655655
set(SRC_TEXT
656656
"Text/ByteQuantity.h"
657657
"Text/ByteQuantity.cpp"
658+
"Text/ComparisonOperator.h"
659+
"Text/ComparisonOperator.cpp"
658660
"Text/Encoding.h"
659661
"Text/Encoding.cpp"
660662
"Text/Iconv.h"
@@ -828,6 +830,7 @@ set(SRC_UTILITIES
828830
"Flags.h"
829831
"Utils/BufferView.h"
830832
"Utils/BufferSpan.h"
833+
"Utils/ComparisonOperator.h"
831834
"Utils/Dump.h"
832835
"Utils/EnumFlags.h"
833836
"Utils/Guard.h"
+215
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
//
2+
// SPDX-License-Identifier: LGPL-2.1-or-later
3+
//
4+
// Copyright © 2025 ANSSI. All Rights Reserved.
5+
//
6+
// Author(s): fabienfl (ANSSI)
7+
//
8+
9+
#include "ComparisonOperator.h"
10+
11+
using namespace Orc::Text;
12+
using namespace Orc;
13+
14+
using namespace std::literals::string_view_literals;
15+
16+
namespace {
17+
18+
static_assert(
19+
std::underlying_type_t<ComparisonOperator>(ComparisonOperator::Undefined) == 0,
20+
"Check enum values so they are ordered for 'kStringViewArray'");
21+
22+
constexpr auto enum_count = static_cast<std::underlying_type_t<ComparisonOperator>>(ComparisonOperator::EnumCount);
23+
24+
constexpr std::array<std::tuple<ComparisonOperator, std::string_view>, enum_count + 1> kStringViewArray = {
25+
std::make_tuple(ComparisonOperator::Undefined, "<Undefined>"sv),
26+
std::make_tuple(ComparisonOperator::LessThan, "<"sv),
27+
std::make_tuple(ComparisonOperator::LessThanOrEqual, "<="sv),
28+
std::make_tuple(ComparisonOperator::Equal, "=="sv),
29+
std::make_tuple(ComparisonOperator::GreaterThan, ">"sv),
30+
std::make_tuple(ComparisonOperator::GreaterThanOrEqual, ">="sv),
31+
std::make_tuple(ComparisonOperator::NotEqual, "!="sv),
32+
std::make_tuple(ComparisonOperator::EnumCount, "<Unknown>"sv)};
33+
34+
// cpp17 limitation ?
35+
constexpr std::array<std::tuple<ComparisonOperator, std::wstring_view>, enum_count + 1> kWStringViewArray = {
36+
std::make_tuple(ComparisonOperator::Undefined, L"<Undefined>"sv),
37+
std::make_tuple(ComparisonOperator::LessThan, L"<"sv),
38+
std::make_tuple(ComparisonOperator::LessThanOrEqual, L"<="sv),
39+
std::make_tuple(ComparisonOperator::Equal, L"=="sv),
40+
std::make_tuple(ComparisonOperator::GreaterThan, L">"sv),
41+
std::make_tuple(ComparisonOperator::GreaterThanOrEqual, L">="sv),
42+
std::make_tuple(ComparisonOperator::NotEqual, L"!="sv),
43+
std::make_tuple(ComparisonOperator::EnumCount, L"<Unknown>"sv)};
44+
45+
template <typename T>
46+
Result<std::pair<ComparisonOperator, std::basic_string_view<T>>>
47+
ComparisonOperatorFromString(std::basic_string_view<T> expression, std::optional<ComparisonOperator> defaultOperator)
48+
{
49+
size_t start = 0;
50+
while (start < expression.size() && std::isspace(expression[start]))
51+
{
52+
++start;
53+
}
54+
55+
expression = expression.substr(start);
56+
if (expression.empty())
57+
{
58+
return std::errc::invalid_argument;
59+
}
60+
61+
ComparisonOperator op;
62+
uint8_t opLength;
63+
64+
// Symbol based operators
65+
if (expression[0] == '<')
66+
{
67+
if (expression.size() > 1 && expression[1] == '=')
68+
{
69+
op = ComparisonOperator::LessThanOrEqual;
70+
opLength = 2;
71+
}
72+
else
73+
{
74+
op = ComparisonOperator::LessThan;
75+
opLength = 1;
76+
}
77+
}
78+
else if (expression[0] == '=')
79+
{
80+
op = ComparisonOperator::Equal;
81+
opLength = expression.size() > 1 && expression[1] == '=' ? 2 : 1;
82+
}
83+
else if (expression[0] == '>')
84+
{
85+
if (expression.size() > 1 && expression[1] == '=')
86+
{
87+
op = ComparisonOperator::GreaterThanOrEqual;
88+
opLength = 2;
89+
}
90+
else
91+
{
92+
op = ComparisonOperator::GreaterThan;
93+
opLength = 1;
94+
}
95+
}
96+
else if (expression.size() > 1 && expression[0] == '!' && expression[1] == '=')
97+
{
98+
op = ComparisonOperator::NotEqual;
99+
opLength = 2;
100+
}
101+
// Text based operators
102+
else if (
103+
expression.size() >= 2 && (expression[0] == 'l' || expression[0] == 'L')
104+
&& (expression[1] == 't' || expression[1] == 'T'))
105+
{
106+
if (expression.size() >= 3 && (expression[2] == 'e' || expression[2] == 'E'))
107+
{
108+
op = ComparisonOperator::LessThanOrEqual;
109+
opLength = 3;
110+
}
111+
else
112+
{
113+
op = ComparisonOperator::LessThan;
114+
opLength = 2;
115+
}
116+
}
117+
else if (
118+
expression.size() >= 2 && (expression[0] == 'g' || expression[0] == 'G')
119+
&& (expression[1] == 't' || expression[1] == 'T'))
120+
{
121+
if (expression.size() >= 3 && (expression[2] == 'e' || expression[2] == 'E'))
122+
{
123+
op = ComparisonOperator::GreaterThanOrEqual;
124+
opLength = 3;
125+
}
126+
else
127+
{
128+
op = ComparisonOperator::GreaterThan;
129+
opLength = 2;
130+
}
131+
}
132+
else if (
133+
expression.size() >= 2 && (expression[0] == 'e' || expression[0] == 'E')
134+
&& (expression[1] == 'q' || expression[1] == 'Q'))
135+
{
136+
op = ComparisonOperator::Equal;
137+
opLength = 2;
138+
}
139+
else if (
140+
expression.size() >= 3 && (expression[0] == 'n' || expression[0] == 'N')
141+
&& (expression[1] == 'e' || expression[1] == 'E') && (expression[2] == 'q' || expression[2] == 'Q'))
142+
{
143+
op = ComparisonOperator::NotEqual;
144+
opLength = 3;
145+
}
146+
else if (defaultOperator.has_value())
147+
{
148+
op = *defaultOperator;
149+
opLength = 0;
150+
}
151+
else
152+
{
153+
return std::errc::invalid_argument;
154+
}
155+
156+
return std::make_pair(op, expression.substr(opLength));
157+
}
158+
159+
} // namespace
160+
161+
namespace Orc {
162+
namespace Text {
163+
164+
Result<std::pair<ComparisonOperator, std::string_view>>
165+
ComparisonOperatorFromString(std::string_view expression, std::optional<ComparisonOperator> defaultOperator)
166+
{
167+
return ::ComparisonOperatorFromString<char>(expression, defaultOperator);
168+
}
169+
170+
Result<std::pair<ComparisonOperator, std::wstring_view>>
171+
ComparisonOperatorFromString(std::wstring_view expression, std::optional<ComparisonOperator> defaultOperator)
172+
{
173+
return ::ComparisonOperatorFromString<wchar_t>(expression, defaultOperator);
174+
}
175+
176+
std::string_view ToStringView(const ComparisonOperator type, bool displayEqual)
177+
{
178+
using underlying_type = std::underlying_type_t<ComparisonOperator>;
179+
constexpr auto enum_count = static_cast<underlying_type>(ComparisonOperator::EnumCount);
180+
181+
auto id = static_cast<underlying_type>(type);
182+
if (id >= enum_count)
183+
{
184+
id = static_cast<underlying_type>(ComparisonOperator::EnumCount);
185+
}
186+
187+
if (type == ComparisonOperator::Equal && !displayEqual)
188+
{
189+
return {};
190+
}
191+
192+
return std::get<1>(kStringViewArray[id]);
193+
}
194+
195+
std::wstring_view ToWStringView(const ComparisonOperator type, bool displayEqual)
196+
{
197+
using underlying_type = std::underlying_type_t<ComparisonOperator>;
198+
constexpr auto enum_count = static_cast<underlying_type>(ComparisonOperator::EnumCount);
199+
200+
auto id = static_cast<underlying_type>(type);
201+
if (id >= enum_count)
202+
{
203+
id = static_cast<underlying_type>(ComparisonOperator::EnumCount);
204+
}
205+
206+
if (type == ComparisonOperator::Equal && !displayEqual)
207+
{
208+
return {};
209+
}
210+
211+
return std::get<1>(kWStringViewArray[id]);
212+
}
213+
214+
} // namespace Text
215+
} // namespace Orc

src/OrcLib/Text/ComparisonOperator.h

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
//
2+
// SPDX-License-Identifier: LGPL-2.1-or-later
3+
//
4+
// Copyright © 2025 ANSSI. All Rights Reserved.
5+
//
6+
// Author(s): fabienfl (ANSSI)
7+
//
8+
9+
#pragma once
10+
11+
#include "Utils/Result.h"
12+
#include "Utils/ComparisonOperator.h"
13+
14+
namespace Orc {
15+
namespace Text {
16+
17+
Result<std::pair<ComparisonOperator, std::string_view>>
18+
ComparisonOperatorFromString(std::string_view expression, std::optional<ComparisonOperator> defaultOperator = {});
19+
20+
Result<std::pair<ComparisonOperator, std::wstring_view>>
21+
ComparisonOperatorFromString(std::wstring_view expression, std::optional<ComparisonOperator> defaultOperator = {});
22+
23+
std::string_view ToStringView(ComparisonOperator op, bool displayEqual = true);
24+
std::wstring_view ToWStringView(ComparisonOperator op, bool displayEqual = true);
25+
26+
} // namespace Text
27+
} // namespace Orc

src/OrcLib/Utils/ComparisonOperator.h

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
//
2+
// SPDX-License-Identifier: LGPL-2.1-or-later
3+
//
4+
// Copyright © 2025 ANSSI. All Rights Reserved.
5+
//
6+
// Author(s): fabienfl (ANSSI)
7+
//
8+
9+
#pragma once
10+
11+
namespace Orc {
12+
13+
enum class ComparisonOperator
14+
{
15+
Undefined,
16+
LessThan,
17+
LessThanOrEqual,
18+
Equal,
19+
GreaterThanOrEqual,
20+
GreaterThan,
21+
NotEqual,
22+
EnumCount
23+
};
24+
25+
} // namespace Orc

0 commit comments

Comments
 (0)