Skip to content

Commit d10a921

Browse files
committed
feat: util specs
1 parent deaa47c commit d10a921

File tree

9 files changed

+212
-93
lines changed

9 files changed

+212
-93
lines changed

include/mrdox/Dom/Kind.hpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,12 @@ namespace dom {
2121
*/
2222
enum class Kind
2323
{
24+
Undefined,
2425
Null,
2526
Boolean,
2627
Integer,
2728
String,
29+
SafeString,
2830
Array,
2931
Object,
3032
Function

include/mrdox/Dom/Value.hpp

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -24,24 +24,17 @@
2424

2525
namespace clang {
2626
namespace mrdox {
27+
28+
dom::Value
29+
safeString(std::string_view str);
30+
2731
namespace dom {
2832

2933
/** A variant container for any kind of Dom value.
3034
*/
3135
class MRDOX_DECL
3236
Value
3337
{
34-
enum class Kind
35-
{
36-
Null,
37-
Boolean,
38-
Integer,
39-
String,
40-
Array,
41-
Object,
42-
Function
43-
};
44-
4538
Kind kind_;
4639

4740
union
@@ -56,6 +49,7 @@ class MRDOX_DECL
5649

5750
friend class Array;
5851
friend class Object;
52+
friend Value clang::mrdox::safeString(std::string_view s);
5953

6054
public:
6155
~Value();
@@ -65,13 +59,15 @@ class MRDOX_DECL
6559
Value& operator=(Value const&);
6660
Value& operator=(Value&&) noexcept;
6761

62+
Value(dom::Kind kind) noexcept;
6863
Value(std::nullptr_t) noexcept;
6964
Value(std::int64_t) noexcept;
7065
Value(String str) noexcept;
7166
Value(Array arr) noexcept;
7267
Value(Object obj) noexcept;
7368
Value(Function fn) noexcept;
7469

70+
7571
template <std::integral T>
7672
requires (!std::same_as<T, bool>)
7773
Value(T v) noexcept : Value(std::int64_t(v)) {}
@@ -85,7 +81,7 @@ class MRDOX_DECL
8581
}
8682

8783
template<class Enum>
88-
requires std::is_enum_v<Enum>
84+
requires std::is_enum_v<Enum> && (!std::same_as<Enum, dom::Kind>)
8985
Value(Enum v) noexcept
9086
: Value(static_cast<
9187
std::underlying_type_t<Enum>>(v))
@@ -99,16 +95,12 @@ class MRDOX_DECL
9995
}
10096

10197
// VFALCO Should this be a literal?
102-
#if 0
10398
Value(char const* s)
10499
: Value(String(s))
105100
{
106101
}
107-
#endif
108102

109-
template<class StringLike>
110-
requires std::convertible_to<
111-
StringLike, String>
103+
template <std::convertible_to<String> StringLike>
112104
Value(StringLike const& s)
113105
: Value(String(s))
114106
{
@@ -136,6 +128,13 @@ class MRDOX_DECL
136128
*/
137129
dom::Kind kind() const noexcept;
138130

131+
/** Return true if this is undefined.
132+
*/
133+
bool isUndefined() const noexcept
134+
{
135+
return kind_ == Kind::Undefined;
136+
}
137+
139138
/** Return true if this is null.
140139
*/
141140
bool isNull() const noexcept
@@ -164,6 +163,13 @@ class MRDOX_DECL
164163
return kind_ == Kind::String;
165164
}
166165

166+
/** Return true if this is a safe string.
167+
*/
168+
bool isSafeString() const noexcept
169+
{
170+
return kind_ == Kind::SafeString;
171+
}
172+
167173
/** Return true if this is an array.
168174
*/
169175
bool isArray() const noexcept
@@ -203,7 +209,7 @@ class MRDOX_DECL
203209
String const&
204210
getString() const noexcept
205211
{
206-
MRDOX_ASSERT(isString());
212+
MRDOX_ASSERT(isString() || isSafeString());
207213
return str_;
208214
}
209215

include/mrdox/Support/Error.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -524,8 +524,8 @@ Expected(
524524
U&& u)
525525
: has_error_(false)
526526
{
527-
static_assert(std::is_nothrow_convertible_v<U, T>);
528-
static_assert(! std::convertible_to<U, Error>);
527+
static_assert(std::is_convertible_v<U, T>);
528+
static_assert(!std::convertible_to<U, Error>);
529529

530530
std::construct_at(&v_, std::forward<U>(u));
531531
}

include/mrdox/Support/Handlebars.hpp

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -120,10 +120,6 @@ namespace detail {
120120
st.append( sv.data(), sv.data() + sv.size() );
121121
};
122122

123-
struct MRDOX_DECL safeStringWrapper {
124-
std::string v_;
125-
};
126-
127123
struct RenderState;
128124

129125
// Heterogeneous lookup support
@@ -1037,8 +1033,7 @@ class Handlebars {
10371033
using R = std::invoke_result_t<F, dom::Array const&, HandlebarsCallback const&>;
10381034
static_assert(
10391035
std::same_as<R, void> ||
1040-
std::convertible_to<R, dom::Value> ||
1041-
std::same_as<R, detail::safeStringWrapper>);
1036+
std::convertible_to<R, dom::Value>);
10421037
registerHelperImpl(name, helper_type([helper = std::forward<F>(helper)](
10431038
dom::Array const& args, HandlebarsCallback const& options)
10441039
-> std::pair<dom::Value, HelperBehavior> {
@@ -1051,10 +1046,6 @@ class Handlebars {
10511046
helper(args, options);
10521047
return {nullptr, HelperBehavior::NO_RENDER};
10531048
}
1054-
else if constexpr (std::same_as<R, detail::safeStringWrapper>)
1055-
{
1056-
return {helper(args, options).v_, HelperBehavior::RENDER_RESULT_NOESCAPE};
1057-
}
10581049
}));
10591050
}
10601051

@@ -1084,8 +1075,7 @@ class Handlebars {
10841075
using R = std::invoke_result_t<F, dom::Array const&>;
10851076
static_assert(
10861077
std::same_as<R, void> ||
1087-
std::convertible_to<R, dom::Value> ||
1088-
std::same_as<R, detail::safeStringWrapper>);
1078+
std::convertible_to<R, dom::Value>);
10891079
registerHelperImpl(name, helper_type([helper = std::forward<F>(helper)](
10901080
dom::Array const& args, HandlebarsCallback const&)
10911081
-> std::pair<dom::Value, HelperBehavior> {
@@ -1098,10 +1088,6 @@ class Handlebars {
10981088
helper(args);
10991089
return {nullptr, HelperBehavior::NO_RENDER};
11001090
}
1101-
else if constexpr (std::same_as<R, detail::safeStringWrapper>)
1102-
{
1103-
return {helper(args).v_, HelperBehavior::RENDER_RESULT_NOESCAPE};
1104-
}
11051091
}));
11061092
}
11071093

@@ -1134,8 +1120,7 @@ class Handlebars {
11341120
using R = std::invoke_result_t<F>;
11351121
static_assert(
11361122
std::same_as<R, void> ||
1137-
std::convertible_to<R, dom::Value> ||
1138-
std::same_as<R, detail::safeStringWrapper>);
1123+
std::convertible_to<R, dom::Value>);
11391124
registerHelperImpl(name, helper_type([helper = std::forward<F>(helper)](
11401125
dom::Array const&, HandlebarsCallback const&)
11411126
-> std::pair<dom::Value, HelperBehavior> {
@@ -1147,10 +1132,6 @@ class Handlebars {
11471132
{
11481133
helper();
11491134
return {nullptr, HelperBehavior::NO_RENDER};
1150-
}
1151-
else if constexpr (std::same_as<R, detail::safeStringWrapper>)
1152-
{
1153-
return {helper().v_, HelperBehavior::RENDER_RESULT_NOESCAPE};
11541135
}
11551136
}));
11561137
}
@@ -1354,7 +1335,7 @@ createFrame(dom::Object const& parent);
13541335
@see https://handlebarsjs.com/api-reference/utilities.html#handlebars-safestring-string
13551336
*/
13561337
MRDOX_DECL
1357-
detail::safeStringWrapper
1338+
dom::Value
13581339
safeString(std::string_view str);
13591340

13601341
/** HTML escapes the specified string
@@ -1388,6 +1369,32 @@ escapeExpression(
13881369
OutputRef out,
13891370
std::string_view str);
13901371

1372+
template <std::convertible_to<dom::Value> DomValue>
1373+
requires (!std::convertible_to<DomValue, std::string_view>)
1374+
std::string
1375+
escapeExpression(
1376+
DomValue const& val)
1377+
{
1378+
dom::Value v = val;
1379+
if (v.isString())
1380+
{
1381+
return escapeExpression(std::string_view(v.getString()));
1382+
}
1383+
if (v.isObject() && v.getObject().exists("toHTML"))
1384+
{
1385+
dom::Value fn = v.getObject().find("toHTML");
1386+
if (fn.isFunction()) {
1387+
return toString(fn.getFunction()());
1388+
}
1389+
}
1390+
if (v.isNull() || v.isUndefined())
1391+
{
1392+
return {};
1393+
}
1394+
return toString(v);
1395+
}
1396+
1397+
13911398
/** An error thrown or returned by Handlebars
13921399
13931400
An error returned or thrown by Handlebars environment when

share/gdb/mrdox_printers.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -74,17 +74,19 @@ def __init__(self, value):
7474
def children(self):
7575
# Get kind enum
7676
kind = self.value['kind_']
77-
if kind == 1:
77+
if kind == 2:
7878
yield 'Boolean', self.value['b_']
79-
elif kind == 2:
80-
yield 'Integer', self.value['i_']
8179
elif kind == 3:
82-
yield 'String', self.value['str_']
80+
yield 'Integer', self.value['i_']
8381
elif kind == 4:
84-
yield 'Array', self.value['arr_']
82+
yield 'String', self.value['str_']
8583
elif kind == 5:
86-
yield 'Object', self.value['obj_']['impl_']['_M_ptr']
84+
yield 'SafeString', self.value['str_']
8785
elif kind == 6:
86+
yield 'Array', self.value['arr_']
87+
elif kind == 7:
88+
yield 'Object', self.value['obj_']['impl_']['_M_ptr']
89+
elif kind == 8:
8890
yield 'Function', self.value['fn_']
8991
else:
9092
yield 'kind_', self.value['kind_']

src/lib/Dom/Array.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,14 @@ Array(
3838
{
3939
}
4040

41+
Array::
42+
Array(storage_type elements)
43+
: impl_(std::make_shared<DefaultArrayImpl>())
44+
{
45+
for(auto const& e : elements)
46+
impl_->emplace_back(e);
47+
}
48+
4149
Array&
4250
Array::
4351
operator=(

0 commit comments

Comments
 (0)