@@ -4192,6 +4192,105 @@ replace_fn(dom::Array const& arguments)
4192
4192
}
4193
4193
}
4194
4194
4195
+ dom::Value
4196
+ find_index_fn (
4197
+ dom::Array const & arguments)
4198
+ {
4199
+ dom::Value range;
4200
+ dom::Value val;
4201
+ std::int64_t start = 0 ;
4202
+ std::int64_t end = 0 ;
4203
+
4204
+ std::size_t const n = arguments.size ();
4205
+ dom::Value options = arguments.back ();
4206
+ dom::Value fn = options.get (" fn" );
4207
+ dom::Value firstArg = arguments.get (0 );
4208
+ dom::Value secondArg = arguments.get (1 );
4209
+
4210
+ bool const isBlock = static_cast <bool >(fn);
4211
+ if (isBlock)
4212
+ {
4213
+ // val, start, end
4214
+ range = static_cast <std::string>(fn ());
4215
+ val = firstArg.getString ();
4216
+ end = static_cast <std::int64_t >(range.size ());
4217
+ if (n > 2 )
4218
+ {
4219
+ start = secondArg.getInteger ();
4220
+ if (n > 3 )
4221
+ {
4222
+ end = arguments.get (2 ).getInteger ();
4223
+ }
4224
+ }
4225
+ }
4226
+ else
4227
+ {
4228
+ // range, val, start, end
4229
+ range = firstArg;
4230
+ val = secondArg;
4231
+ end = static_cast <std::int64_t >(range.size ());
4232
+ if (n > 3 )
4233
+ {
4234
+ start = arguments.at (2 ).getInteger ();
4235
+ if (n > 4 )
4236
+ {
4237
+ end = arguments.at (3 ).getInteger ();
4238
+ }
4239
+ }
4240
+ }
4241
+ start = normalize_index (start, static_cast <std::int64_t >(range.size ()));
4242
+ end = normalize_index (end, static_cast <std::int64_t >(range.size ()));
4243
+ if (range.isString ())
4244
+ {
4245
+ // Find position of substring val in range
4246
+ std::size_t pos = range.getString ().get ().find (val.getString (), start);
4247
+ if (pos == std::string::npos || static_cast <std::int64_t >(pos) >= end) {
4248
+ return static_cast <std::int64_t >(-1 );
4249
+ }
4250
+ return static_cast <std::int64_t >(pos);
4251
+ }
4252
+ if (range.isArray ())
4253
+ {
4254
+ // Find position of item val in array
4255
+ auto const & arr = range.getArray ();
4256
+ for (std::int64_t i = start; i < end; i++)
4257
+ {
4258
+ if (arr.get (i) == val)
4259
+ {
4260
+ return i;
4261
+ }
4262
+ }
4263
+ return static_cast <std::int64_t >(-1 );
4264
+ }
4265
+ else if (range.isObject ())
4266
+ {
4267
+ // Find key of item val in object
4268
+ auto const & obj = range.getObject ();
4269
+ dom::Value res (dom::Kind::Undefined);
4270
+ auto i = 0 ;
4271
+ obj.visit ([&](dom::String const & k, dom::Value const & v) -> bool
4272
+ {
4273
+ if (i < start)
4274
+ {
4275
+ ++i;
4276
+ return true ;
4277
+ }
4278
+ if (i >= end)
4279
+ {
4280
+ return false ;
4281
+ }
4282
+ if (v == val)
4283
+ {
4284
+ res = k;
4285
+ return false ;
4286
+ }
4287
+ return true ;
4288
+ });
4289
+ return res;
4290
+ }
4291
+ return range;
4292
+ }
4293
+
4195
4294
void
4196
4295
registerStringHelpers (Handlebars& hbs)
4197
4296
{
@@ -4508,63 +4607,26 @@ registerStringHelpers(Handlebars& hbs)
4508
4607
return res;
4509
4608
}));
4510
4609
4511
- static constexpr auto find_index_fn = [](
4512
- dom::Array const & arguments)
4610
+ hbs.registerHelper (" find" , dom::makeVariadicInvocable (find_index_fn));
4611
+ hbs.registerHelper (" index_of" , dom::makeVariadicInvocable (find_index_fn));
4612
+
4613
+ hbs.registerHelper (" includes" , dom::makeVariadicInvocable ([](
4614
+ dom::Array const & arguments) -> bool
4513
4615
{
4514
- std::string str;
4515
- std::string sub;
4516
- std::int64_t start = 0 ;
4517
- std::int64_t end = 0 ;
4518
- std::size_t const n = arguments.size ();
4519
- dom::Value options = arguments.back ();
4520
- dom::Value fn = options.get (" fn" );
4521
- dom::Value firstArg = arguments.get (0 );
4522
- dom::Value secondArg = arguments.get (1 );
4523
- bool const isBlock = static_cast <bool >(fn);
4524
- if (isBlock)
4616
+ dom::Value res = find_index_fn (arguments);
4617
+ if (res.isInteger ())
4525
4618
{
4526
- str = static_cast <std::string>(fn ());
4527
- sub = firstArg.getString ();
4528
- end = static_cast <std::int64_t >(str.size ());
4529
- if (n > 2 )
4530
- {
4531
- start = secondArg.getInteger ();
4532
- if (n > 3 )
4533
- {
4534
- end = arguments.at (2 ).getInteger ();
4535
- }
4536
- }
4619
+ return res.getInteger () >= 0 ;
4537
4620
}
4538
- else
4621
+ if (res. isUndefined ())
4539
4622
{
4540
- str = firstArg.getString ();
4541
- sub = secondArg.getString ();
4542
- end = static_cast <std::int64_t >(str.size ());
4543
- if (n > 3 )
4544
- {
4545
- start = arguments.at (2 ).getInteger ();
4546
- if (n > 4 )
4547
- {
4548
- end = arguments.at (3 ).getInteger ();
4549
- }
4550
- }
4623
+ return false ;
4551
4624
}
4552
- start = normalize_index (start, static_cast <std::int64_t >(str.size ()));
4553
- end = normalize_index (end, static_cast <std::int64_t >(str.size ()));
4554
- std::size_t pos = str.find (sub, start);
4555
- if (pos == std::string::npos || static_cast <std::int64_t >(pos) >= end) {
4556
- return static_cast <std::int64_t >(-1 );
4625
+ if (res.isString ())
4626
+ {
4627
+ return true ;
4557
4628
}
4558
- return static_cast <std::int64_t >(pos);
4559
- };
4560
-
4561
- hbs.registerHelper (" find" , dom::makeVariadicInvocable (find_index_fn));
4562
- hbs.registerHelper (" index_of" , dom::makeVariadicInvocable (find_index_fn));
4563
-
4564
- hbs.registerHelper (" includes" , dom::makeVariadicInvocable ([](
4565
- dom::Array const & arguments)
4566
- {
4567
- return find_index_fn (arguments) != -1 ;
4629
+ return res.isTruthy ();
4568
4630
}));
4569
4631
4570
4632
auto rfind_index_fn = [](
@@ -5700,37 +5762,8 @@ registerContainerHelpers(Handlebars& hbs)
5700
5762
hbs.registerHelper (" del" , del_fn);
5701
5763
hbs.registerHelper (" delete" , del_fn);
5702
5764
5703
- static auto find_fn = dom::makeInvocable ([](
5704
- dom::Value range, dom::Value const & val) -> dom::Value {
5705
- if (range.isArray ())
5706
- {
5707
- auto const & arr = range.getArray ();
5708
- auto const n = static_cast <std::int64_t >(arr.size ());
5709
- for (std::int64_t i = 0 ; i < n; i++)
5710
- {
5711
- if (arr[i] == val)
5712
- return i;
5713
- }
5714
- return static_cast <std::int64_t >(-1 );
5715
- }
5716
- else if (range.isObject ())
5717
- {
5718
- auto const & obj = range.getObject ();
5719
- for (auto const & [k, v]: obj)
5720
- {
5721
- if (v == val)
5722
- return k;
5723
- }
5724
- return nullptr ;
5725
- }
5726
- else
5727
- {
5728
- return range;
5729
- }
5730
- });
5731
-
5732
- hbs.registerHelper (" find" , find_fn);
5733
- hbs.registerHelper (" index_of" , find_fn);
5765
+ hbs.registerHelper (" find" , dom::makeVariadicInvocable (find_index_fn));
5766
+ hbs.registerHelper (" index_of" , dom::makeVariadicInvocable (find_index_fn));
5734
5767
5735
5768
static auto has_fn = dom::makeInvocable ([](
5736
5769
dom::Value const & ctx, dom::Value const & prop)
0 commit comments