@@ -29,7 +29,7 @@ struct StringEncoder : public visitors::BaseVisitor<>
29
29
30
30
for (auto & ch : str)
31
31
{
32
- D:: EncodeChar (ch, [&result](auto ... chs) {AppendChar (result, chs...);});
32
+ static_cast < const D*>( this )-> EncodeChar (ch, [&result](auto ... chs) {AppendChar (result, chs...);});
33
33
}
34
34
35
35
return result;
@@ -46,13 +46,26 @@ struct StringEncoder : public visitors::BaseVisitor<>
46
46
str.push_back (static_cast <typename Str::value_type>(ch));
47
47
AppendChar (str, chs...);
48
48
}
49
+ };
49
50
51
+ template <typename Fn>
52
+ struct GenericStringEncoder : public StringEncoder <GenericStringEncoder<Fn>>
53
+ {
54
+ GenericStringEncoder (Fn fn) : m_fn(std::move(fn)) {}
55
+
56
+ template <typename CharT, typename AppendFn>
57
+ void EncodeChar (CharT ch, AppendFn&& fn) const
58
+ {
59
+ m_fn (ch, std::forward<AppendFn>(fn));
60
+ }
61
+
62
+ mutable Fn m_fn;
50
63
};
51
64
52
65
struct UrlStringEncoder : public StringEncoder <UrlStringEncoder>
53
66
{
54
67
template <typename CharT, typename Fn>
55
- static void EncodeChar (CharT ch, Fn&& fn)
68
+ void EncodeChar (CharT ch, Fn&& fn) const
56
69
{
57
70
switch (ch)
58
71
{
@@ -145,12 +158,13 @@ struct StringConverterImpl : public visitors::BaseVisitor<>
145
158
const Fn& m_fn;
146
159
};
147
160
148
- template <typename Fn>
161
+ template <template < typename > class Cvt = StringConverterImpl, typename Fn>
149
162
auto ApplyConverter (const InternalValue& str, Fn&& fn)
150
163
{
151
- return Apply<StringConverterImpl <Fn>>(str, std::forward<Fn>(fn));
164
+ return Apply<Cvt <Fn>>(str, std::forward<Fn>(fn));
152
165
}
153
166
167
+
154
168
StringConverter::StringConverter (FilterParams params, StringConverter::Mode mode)
155
169
: m_mode(mode)
156
170
{
@@ -165,6 +179,9 @@ StringConverter::StringConverter(FilterParams params, StringConverter::Mode mode
165
179
InternalValue StringConverter::Filter (const InternalValue& baseVal, RenderContext& context)
166
180
{
167
181
InternalValue result;
182
+
183
+ auto isAlpha = ba::is_alpha ();
184
+ auto isAlNum = ba::is_alnum ();
168
185
169
186
switch (m_mode)
170
187
{
@@ -174,6 +191,50 @@ InternalValue StringConverter::Filter(const InternalValue& baseVal, RenderContex
174
191
return str;
175
192
});
176
193
break ;
194
+ case TitleMode:
195
+ result = ApplyConverter<GenericStringEncoder>(baseVal, [isDelim = true , &isAlpha, &isAlNum](auto ch, auto && fn) mutable {
196
+ if (isDelim && isAlpha (ch))
197
+ {
198
+ isDelim = false ;
199
+ fn (std::toupper (ch, std::locale ()));
200
+ return ;
201
+ }
202
+
203
+ isDelim = !isAlNum (ch);
204
+ fn (ch);
205
+ });
206
+ break ;
207
+ case WordCountMode:
208
+ {
209
+ int64_t wc = 0 ;
210
+ ApplyConverter<GenericStringEncoder>(baseVal, [isDelim = true , &wc, &isAlpha, &isAlNum](auto ch, auto && fn) mutable {
211
+ if (isDelim && isAlNum (ch))
212
+ {
213
+ isDelim = false ;
214
+ wc ++;
215
+ return ;
216
+ }
217
+ isDelim = !isAlNum (ch);
218
+ });
219
+ result = wc;
220
+ break ;
221
+ }
222
+ case UpperMode:
223
+ result = ApplyConverter<GenericStringEncoder>(baseVal, [&isAlpha](auto ch, auto && fn) mutable {
224
+ if (isAlpha (ch))
225
+ fn (std::toupper (ch, std::locale ()));
226
+ else
227
+ fn (ch);
228
+ });
229
+ break ;
230
+ case LowerMode:
231
+ result = ApplyConverter<GenericStringEncoder>(baseVal, [&isAlpha](auto ch, auto && fn) mutable {
232
+ if (isAlpha (ch))
233
+ fn (std::tolower (ch, std::locale ()));
234
+ else
235
+ fn (ch);
236
+ });
237
+ break ;
177
238
case ReplaceMode:
178
239
break ;
179
240
case UrlEncodeMode:
0 commit comments