@@ -1291,6 +1291,12 @@ class UnaryOpExpr : public Expression {
1291
1291
}
1292
1292
};
1293
1293
1294
+ static bool in (const Value & value, const Value & container) {
1295
+ return (((container.is_array () || container.is_object ()) && container.contains (value)) ||
1296
+ (value.is_string () && container.is_string () &&
1297
+ container.to_str ().find (value.to_str ()) != std::string::npos));
1298
+ }
1299
+
1294
1300
class BinaryOpExpr : public Expression {
1295
1301
public:
1296
1302
enum class Op { StrConcat, Add, Sub, Mul, MulMul, Div, DivDiv, Mod, Eq, Ne, Lt, Gt, Le, Ge, And, Or, In, NotIn, Is, IsNot };
@@ -1355,13 +1361,8 @@ class BinaryOpExpr : public Expression {
1355
1361
case Op::Gt: return l > r;
1356
1362
case Op::Le: return l <= r;
1357
1363
case Op::Ge: return l >= r;
1358
- case Op::In: return (((r.is_array () || r.is_object ()) && r.contains (l)) ||
1359
- (l.is_string () && r.is_string () &&
1360
- r.to_str ().find (l.to_str ()) != std::string::npos));
1361
- case Op::NotIn:
1362
- return !(((r.is_array () || r.is_object ()) && r.contains (l)) ||
1363
- (l.is_string () && r.is_string () &&
1364
- r.to_str ().find (l.to_str ()) != std::string::npos));
1364
+ case Op::In: return in (l, r);
1365
+ case Op::NotIn: return !in (l, r);
1365
1366
default : break ;
1366
1367
}
1367
1368
throw std::runtime_error (" Unknown binary operator" );
@@ -1500,6 +1501,13 @@ class MethodCallExpr : public Expression {
1500
1501
} else if (method->get_name () == " pop" ) {
1501
1502
vargs.expectArgs (" pop method" , {1 , 1 }, {0 , 0 });
1502
1503
return obj.pop (vargs.args [0 ]);
1504
+ } else if (method->get_name () == " keys" ) {
1505
+ vargs.expectArgs (" keys method" , {0 , 0 }, {0 , 0 });
1506
+ auto result = Value::array ();
1507
+ for (const auto & key : obj.keys ()) {
1508
+ result.push_back (Value (key));
1509
+ }
1510
+ return result;
1503
1511
} else if (method->get_name () == " get" ) {
1504
1512
vargs.expectArgs (" get method" , {1 , 2 }, {0 , 0 });
1505
1513
auto key = vargs.args [0 ];
@@ -1541,6 +1549,16 @@ class MethodCallExpr : public Expression {
1541
1549
} else if (method->get_name () == " capitalize" ) {
1542
1550
vargs.expectArgs (" capitalize method" , {0 , 0 }, {0 , 0 });
1543
1551
return Value (capitalize (str));
1552
+ } else if (method->get_name () == " upper" ) {
1553
+ vargs.expectArgs (" upper method" , {0 , 0 }, {0 , 0 });
1554
+ auto result = str;
1555
+ std::transform (result.begin (), result.end (), result.begin (), ::toupper);
1556
+ return Value (result);
1557
+ } else if (method->get_name () == " lower" ) {
1558
+ vargs.expectArgs (" lower method" , {0 , 0 }, {0 , 0 });
1559
+ auto result = str;
1560
+ std::transform (result.begin (), result.end (), result.begin (), ::tolower);
1561
+ return Value (result);
1544
1562
} else if (method->get_name () == " endswith" ) {
1545
1563
vargs.expectArgs (" endswith method" , {1 , 1 }, {0 , 0 });
1546
1564
auto suffix = vargs.args [0 ].get <std::string>();
@@ -2646,15 +2664,11 @@ inline std::shared_ptr<Context> Context::builtins() {
2646
2664
auto items = Value::array ();
2647
2665
if (args.contains (" object" )) {
2648
2666
auto & obj = args.at (" object" );
2649
- if (obj.is_string ()) {
2650
- auto json_obj = json::parse (obj.get <std::string>());
2651
- for (const auto & kv : json_obj.items ()) {
2652
- items.push_back (Value::array ({kv.key (), kv.value ()}));
2653
- }
2654
- } else if (!obj.is_null ()) {
2655
- for (auto & key : obj.keys ()) {
2656
- items.push_back (Value::array ({key, obj.at (key)}));
2657
- }
2667
+ if (!obj.is_object ()) {
2668
+ throw std::runtime_error (" Can only get item pairs from a mapping" );
2669
+ }
2670
+ for (auto & key : obj.keys ()) {
2671
+ items.push_back (Value::array ({key, obj.at (key)}));
2658
2672
}
2659
2673
}
2660
2674
return items;
@@ -2782,6 +2796,9 @@ inline std::shared_ptr<Context> Context::builtins() {
2782
2796
if (!items.is_array ()) throw std::runtime_error (" object is not iterable" );
2783
2797
return items;
2784
2798
}));
2799
+ globals.set (" in" , simple_function (" in" , { " item" , " items" }, [](const std::shared_ptr<Context> &, Value & args) -> Value {
2800
+ return in (args.at (" item" ), args.at (" items" ));
2801
+ }));
2785
2802
globals.set (" unique" , simple_function (" unique" , { " items" }, [](const std::shared_ptr<Context> &, Value & args) -> Value {
2786
2803
auto & items = args.at (" items" );
2787
2804
if (!items.is_array ()) throw std::runtime_error (" object is not iterable" );
0 commit comments