Repository: ggerganov/llama.cpp
File: common/jinja/value.cpp (C++)

Code before:
            }
            const value_array_t * arr = cast_val<value_array>(args.get_pos(0));
            // need to use const_cast here to modify the array
            value_array_t * arr_editable = const_cast<value_array_t *>(arr);
            arr_editable->push_back(args.get_pos(1));
            return args.get_pos(0);
        }},
        {"pop", [](const func_args & args) -> value {
            args.ensure_count(1, 2);
            args.ensure_vals<value_array, value_int>(true, false);
            int64_t index = args.count() == 2 ? args.get_pos(1)->as_int() : -1;
            const value_array_t * arr = cast_val<value_array>(args.get_pos(0));
            // need to use const_cast here to modify the array
            value_array_t * arr_editable = const_cast<value_array_t *>(arr);
            return arr_editable->pop_at(index);
        }},
        {"sort", [](const func_args & args) -> value {
            args.ensure_count(1, 4);
            if (!is_val<value_array>(args.get_pos(0))) {
                throw raised_exception("sort: first argument must be an array");
            }
            value val_reverse = args.get_kwarg_or_pos("reverse",        1);
            value val_case    = args.get_kwarg_or_pos("case_sensitive", 2);
            value attribute   = args.get_kwarg_or_pos("attribute",      3);
            // FIXME: sorting is case sensitive
            //const bool case_sensitive = val_case->as_bool(); // undefined == false
            const bool reverse = val_reverse->as_bool(); // undefined == false
            const bool attr_is_int = is_val<value_int>(attribute);
            const int64_t attr_int = attr_is_int ? attribute->as_int() : 0;
            const std::string attr_name = attribute->is_undefined() ? "" : attribute->as_string().str();
            std::vector<value> arr = cast_val<value_array>(args.get_pos(0))->as_array(); // copy
            std::sort(arr.begin(), arr.end(),[&](const value & a, const value & b) {
                value val_a = a;
                value val_b = b;
                if (!attribute->is_undefined()) {
                    if (attr_is_int && is_val<value_array>(a) && is_val<value_array>(b)) {
                        val_a = a->at(attr_int);
                        val_b = b->at(attr_int);
                    } else if (!attr_is_int && !attr_name.empty() && is_val<value_object>(a) && is_val<value_object>(b)) {
                        val_a = a->at(attr_name);
                        val_b = b->at(attr_name);
                    } else {
                        throw raised_exception("sort: unsupported object attribute comparison");
                    }
                }
                return value_compare(val_a, val_b, reverse ? value_compare_op::gt : value_compare_op::lt);
            });
            return mk_val<value_array>(arr);
        }},
        {"reverse", [](const func_args & args) -> value {
            args.ensure_vals<value_array>();

Review comment (security):
maybe throw `not_implemented_exception` if `case_sensitive` is set?

Code after:
            }
            const value_array_t * arr = cast_val<value_array>(args.get_pos(0));
            // need to use const_cast here to modify the array
            value_array_t * arr_editable = const_cast<value_array_t *>(arr);
            arr_editable->push_back(args.get_pos(1));
            return args.get_pos(0);
        }},
        {"pop", [](const func_args & args) -> value {
            args.ensure_count(1, 2);
            args.ensure_vals<value_array, value_int>(true, false);
            int64_t index = args.count() == 2 ? args.get_pos(1)->as_int() : -1;
            const value_array_t * arr = cast_val<value_array>(args.get_pos(0));
            // need to use const_cast here to modify the array
            value_array_t * arr_editable = const_cast<value_array_t *>(arr);
            return arr_editable->pop_at(index);
        }},
        {"sort", [](const func_args & args) -> value {
            args.ensure_count(1, 4);
            if (!is_val<value_array>(args.get_pos(0))) {
                throw raised_exception("sort: first argument must be an array");
            }
            value val_reverse = args.get_kwarg_or_pos("reverse",        1);
            value val_case    = args.get_kwarg_or_pos("case_sensitive", 2);
            value attribute   = args.get_kwarg_or_pos("attribute",      3);
            // FIXME: sorting is currently always case sensitive
            //const bool case_sensitive = val_case->as_bool(); // undefined == false
            const bool reverse = val_reverse->as_bool(); // undefined == false
            const bool attr_is_int = is_val<value_int>(attribute);
            const int64_t attr_int = attr_is_int ? attribute->as_int() : 0;
            const std::string attr_name = attribute->is_undefined() ? "" : attribute->as_string().str();
            std::vector<value> arr = cast_val<value_array>(args.get_pos(0))->as_array(); // copy
            std::sort(arr.begin(), arr.end(),[&](const value & a, const value & b) {
                value val_a = a;
                value val_b = b;
                if (!attribute->is_undefined()) {
                    if (attr_is_int && is_val<value_array>(a) && is_val<value_array>(b)) {
                        val_a = a->at(attr_int);
                        val_b = b->at(attr_int);
                    } else if (!attr_is_int && !attr_name.empty() && is_val<value_object>(a) && is_val<value_object>(b)) {
                        val_a = a->at(attr_name);
                        val_b = b->at(attr_name);
                    } else {
                        throw raised_exception("sort: unsupported object attribute comparison");
                    }
                }
                return value_compare(val_a, val_b, reverse ? value_compare_op::gt : value_compare_op::lt);
            });
            return mk_val<value_array>(arr);
        }},
        {"reverse", [](const func_args & args) -> value {
            args.ensure_vals<value_array>();