Skip to content

Commit 4a92c2e

Browse files
authored
Stencil improvements (#1494)
* remove unescaped * inverted sections * Update stencil.md * normal sections tests * nested inverted test * More documentation * Update stencil.md * Revert "Merge branch 'main' into stencil" This reverts commit 9654610, reversing changes made to 5852674.
1 parent f97bba6 commit 4a92c2e

File tree

3 files changed

+62
-38
lines changed

3 files changed

+62
-38
lines changed

docs/stencil.md

+36-5
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,7 @@
44
>
55
> glz::stencil is still somewhat experimental. The API may not be as stable as other parts of Glaze.
66
7-
Glaze supports string interpolation support for serializing structs.
8-
9-
Example:
7+
Glaze supports string interpolation for serializing structs using `glz::stencil`.
108

119
```c++
1210
struct person
@@ -15,14 +13,47 @@ struct person
1513
std::string last_name{};
1614
uint32_t age{};
1715
bool hungry{};
16+
bool employed{};
1817
};
1918

2019
"person"_test = [] {
21-
std::string_view layout = R"({{first_name}} | {{last_name}} = {{age}})";
20+
std::string_view layout = R"({{first_name}} {{last_name}}, age: {{age}})";
21+
22+
person p{"Henry", "Foster", 34};
23+
auto result = glz::stencil(layout, p);
24+
expect(result == "Henry Foster, age: 34");
25+
};
26+
27+
"comment"_test = [] {
28+
std::string_view layout = R"({{first_name}} {{! This is a comment }}{{last_name}})";
2229

2330
person p{"Henry", "Foster", 34};
2431
auto result = glz::stencil(layout, p).value_or("error");
25-
expect(result == "Henry | Foster = 34");
32+
expect(result == "Henry Foster") << result;
33+
};
34+
35+
"section_true"_test = [] {
36+
std::string_view layout = R"({{first_name}} {{last_name}} {{#employed}}Employed{{/employed}})";
37+
38+
person p{"Alice", "Johnson", 28, true, true}; // employed is true
39+
auto result = glz::stencil(layout, p).value_or("error");
40+
expect(result == "Alice Johnson Employed") << result;
41+
};
42+
43+
"section_with_inner_placeholders"_test = [] {
44+
std::string_view layout = R"({{first_name}} {{last_name}} {{#employed}}Status: Employed, Age: {{age}}{{/employed}})";
45+
46+
person p{"Carol", "Davis", 30, true, true};
47+
auto result = glz::stencil(layout, p).value_or("error");
48+
expect(result == "Carol Davis Status: Employed, Age: 30") << result;
49+
};
50+
51+
"inverted_section_true"_test = [] {
52+
std::string_view layout = R"({{first_name}} {{last_name}} {{^hungry}}I'm not hungry{{/hungry}})";
53+
54+
person p{"Henry", "Foster", 34, false}; // hungry is false
55+
auto result = glz::stencil(layout, p).value_or("error");
56+
expect(result == "Henry Foster I'm not hungry") << result;
2657
};
2758
```
2859

include/glaze/stencil/stencil.hpp

+5-4
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ namespace glz
9090
ctx.error = error_code::unexpected_end;
9191
return {ctx.error, "Closing tag not found for section", size_t(it - start)};
9292
}
93-
93+
9494
if (it + 1 < end) {
9595
it += 2; // Skip '}}'
9696
}
@@ -105,8 +105,8 @@ namespace glz
105105
static constexpr auto N = reflect<T>::size;
106106
static constexpr auto HashInfo = detail::hash_info<T>;
107107

108-
const auto index = detail::decode_hash_with_size<STENCIL, T, HashInfo, HashInfo.type>::op(
109-
start, end, key.size());
108+
const auto index =
109+
detail::decode_hash_with_size<STENCIL, T, HashInfo, HashInfo.type>::op(start, end, key.size());
110110

111111
if (index >= N) {
112112
ctx.error = error_code::unknown_key;
@@ -137,7 +137,8 @@ namespace glz
137137
index);
138138
}
139139
}
140-
140+
141+
141142
if (bool(ctx.error)) [[unlikely]] {
142143
return {ctx.error, ctx.custom_error_message, size_t(it - start)};
143144
}

tests/stencil/stencil_test.cpp

+21-29
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ suite mustache_tests = [] {
2020
std::string_view layout = R"({{first_name}} {{last_name}} {{age}})";
2121

2222
person p{"Henry", "Foster", 34};
23-
auto result = glz::stencil(layout, p).value_or("error");
24-
expect(result == "Henry Foster 34") << result;
23+
auto result = glz::stencil(layout, p);
24+
expect(result == "Henry Foster 34");
2525
};
2626

2727
"person"_test = [] {
@@ -48,7 +48,7 @@ suite mustache_tests = [] {
4848
auto result = glz::stencil(layout, p).value_or("error");
4949
expect(result == "Henry Foster") << result;
5050
};
51-
51+
5252
// **Regular Section Tests (#)**
5353

5454
"section_true"_test = [] {
@@ -68,8 +68,7 @@ suite mustache_tests = [] {
6868
};
6969

7070
"section_with_inner_placeholders"_test = [] {
71-
std::string_view layout =
72-
R"({{first_name}} {{last_name}} {{#employed}}Status: Employed, Age: {{age}}{{/employed}})";
71+
std::string_view layout = R"({{first_name}} {{last_name}} {{#employed}}Status: Employed, Age: {{age}}{{/employed}})";
7372

7473
person p{"Carol", "Davis", 30, true, true};
7574
auto result = glz::stencil(layout, p).value_or("error");
@@ -93,8 +92,7 @@ suite mustache_tests = [] {
9392
};
9493

9594
"nested_sections"_test = [] {
96-
std::string_view layout =
97-
R"({{first_name}} {{last_name}} {{#employed}}Status: Employed {{#hungry}}and Hungry{{/hungry}}{{/employed}})";
95+
std::string_view layout = R"({{first_name}} {{last_name}} {{#employed}}Status: Employed {{#hungry}}and Hungry{{/hungry}}{{/employed}})";
9896

9997
person p1{"Frank", "Taylor", 50, true, true}; // employed is true, hungry is true
10098
auto result1 = glz::stencil(layout, p1);
@@ -115,15 +113,14 @@ suite mustache_tests = [] {
115113
};
116114

117115
"section_mismatched_closing_tag"_test = [] {
118-
std::string_view layout =
119-
R"({{first_name}} {{last_name}} {{#employed}}Employed{{/employment}})"; // Mismatched closing tag
116+
std::string_view layout = R"({{first_name}} {{last_name}} {{#employed}}Employed{{/employment}})"; // Mismatched closing tag
120117

121118
person p{"Ivy", "Thomas", 29, false, true};
122119
auto result = glz::stencil(layout, p);
123120
expect(not result.has_value());
124121
expect(result.error() == glz::error_code::unexpected_end);
125122
};
126-
123+
127124
// **Inverted Section Tests**
128125

129126
"inverted_section_true"_test = [] {
@@ -143,40 +140,36 @@ suite mustache_tests = [] {
143140
};
144141

145142
"inverted_section_with_extra_text_true"_test = [] {
146-
std::string_view layout =
147-
R"({{first_name}} {{last_name}} {{^hungry}}I'm not hungry{{/hungry}}. Have a nice day!)";
143+
std::string_view layout = R"({{first_name}} {{last_name}} {{^hungry}}I'm not hungry{{/hungry}}. Have a nice day!)";
148144

149145
person p{"Henry", "Foster", 34, false}; // hungry is false
150146
auto result = glz::stencil(layout, p).value_or("error");
151147
expect(result == "Henry Foster I'm not hungry. Have a nice day!") << result;
152148
};
153149

154150
"inverted_section_with_extra_text_false"_test = [] {
155-
std::string_view layout =
156-
R"({{first_name}} {{last_name}} {{^hungry}}I'm not hungry{{/hungry}}. Have a nice day!)";
151+
std::string_view layout = R"({{first_name}} {{last_name}} {{^hungry}}I'm not hungry{{/hungry}}. Have a nice day!)";
157152

158153
person p{"Henry", "Foster", 34, true}; // hungry is true
159154
auto result = glz::stencil(layout, p).value_or("error");
160155
expect(result == "Henry Foster . Have a nice day!") << result;
161156
};
162157

163158
"nested_inverted_section"_test = [] {
164-
std::string_view layout =
165-
R"({{first_name}} {{last_name}} {{^hungry}}I'm not hungry {{^employed}}and not employed{{/employed}}{{/hungry}})";
159+
std::string_view layout = R"({{first_name}} {{last_name}} {{^hungry}}I'm not hungry {{^employed}}and not employed{{/employed}}{{/hungry}})";
166160

167-
person p1{"Henry", "Foster", 34, false, false};
168-
auto result1 = glz::stencil(layout, p1).value_or("error");
169-
expect(result1 == "Henry Foster I'm not hungry and not employed") << result1;
161+
person p1{"Henry", "Foster", 34, false, false};
162+
auto result1 = glz::stencil(layout, p1).value_or("error");
163+
expect(result1 == "Henry Foster I'm not hungry and not employed") << result1;
170164

171-
person p2{"Henry", "Foster", 34, false, true};
172-
auto result2 = glz::stencil(layout, p2).value_or("error");
173-
expect(result2 == "Henry Foster I'm not hungry ") << result2;
165+
person p2{"Henry", "Foster", 34, false, true};
166+
auto result2 = glz::stencil(layout, p2).value_or("error");
167+
expect(result2 == "Henry Foster I'm not hungry ") << result2;
174168

175-
person p3{"Henry", "Foster", 34, true, false};
176-
std::string_view layout_skip =
177-
R"({{first_name}} {{last_name}} {{^hungry}}I'm not hungry {{^employed}}and not employed{{/employed}}{{/hungry}})";
178-
auto result3 = glz::stencil(layout_skip, p3).value_or("error");
179-
expect(result3 == "Henry Foster ") << result3;
169+
person p3{"Henry", "Foster", 34, true, false};
170+
std::string_view layout_skip = R"({{first_name}} {{last_name}} {{^hungry}}I'm not hungry {{^employed}}and not employed{{/employed}}{{/hungry}})";
171+
auto result3 = glz::stencil(layout_skip, p3).value_or("error");
172+
expect(result3 == "Henry Foster ") << result3;
180173
};
181174

182175
"inverted_section_unknown_key"_test = [] {
@@ -189,8 +182,7 @@ suite mustache_tests = [] {
189182
};
190183

191184
"inverted_section_mismatched_closing_tag"_test = [] {
192-
std::string_view layout =
193-
R"({{first_name}} {{last_name}} {{^hungry}}I'm not hungry{{/hunger}})"; // Mismatched closing tag
185+
std::string_view layout = R"({{first_name}} {{last_name}} {{^hungry}}I'm not hungry{{/hunger}})"; // Mismatched closing tag
194186

195187
person p{"Henry", "Foster", 34, false};
196188
auto result = glz::stencil(layout, p);

0 commit comments

Comments
 (0)