Repository: bitcoin/bitcoin
File: src/script/miniscript.h (C/C++)

Code before:
            } else if (Const("ripemd160(", in)) {
                auto res = ParseHexStrEnd(in, 20, ctx);
                if (!res) return {};
                auto& [hash, hash_size] = *res;
                constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::RIPEMD160, std::move(hash)));
                in = in.subspan(hash_size + 1);
                script_size += 26;
            } else if (Const("hash256(", in)) {
                auto res = ParseHexStrEnd(in, 32, ctx);
                if (!res) return {};
                auto& [hash, hash_size] = *res;
                constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::HASH256, std::move(hash)));
                in = in.subspan(hash_size + 1);
                script_size += 38;
            } else if (Const("hash160(", in)) {
                auto res = ParseHexStrEnd(in, 20, ctx);
                if (!res) return {};
                auto& [hash, hash_size] = *res;
                constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::HASH160, std::move(hash)));
                in = in.subspan(hash_size + 1);
                script_size += 26;
            } else if (Const("after(", in)) {
                int arg_size = FindNextChar(in, ')');
                if (arg_size < 1) return {};
                int64_t num;
                if (!ParseInt64(std::string(in.begin(), in.begin() + arg_size), &num)) return {};
                if (num < 1 || num >= 0x80000000L) return {};
                constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::AFTER, num));
                in = in.subspan(arg_size + 1);
                script_size += 1 + (num > 16) + (num > 0x7f) + (num > 0x7fff) + (num > 0x7fffff);
            } else if (Const("older(", in)) {
                int arg_size = FindNextChar(in, ')');
                if (arg_size < 1) return {};
                int64_t num;
                if (!ParseInt64(std::string(in.begin(), in.begin() + arg_size), &num)) return {};
                if (num < 1 || num >= 0x80000000L) return {};
                constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::OLDER, num));
                in = in.subspan(arg_size + 1);
                script_size += 1 + (num > 16) + (num > 0x7f) + (num > 0x7fff) + (num > 0x7fffff);
            } else if (Const("multi(", in)) {
                if (!parse_multi_exp(in, /* is_multi_a = */false)) return {};
            } else if (Const("multi_a(", in)) {
                if (!parse_multi_exp(in, /* is_multi_a = */true)) return {};
            } else if (Const("thresh(", in)) {
                int next_comma = FindNextChar(in, ',');
                if (next_comma < 1) return {};
                if (!ParseInt64(std::string(in.begin(), in.begin() + next_comma), &k)) return {};
                if (k < 1) return {};
                in = in.subspan(next_comma + 1);
                // n = 1 here because we read the first WRAPPED_EXPR before reaching THRESH
                to_parse.emplace_back(ParseContext::THRESH, 1, k);

Review comment (performance):
Yes, seems more efficient to use `string_view` here.
Same for the other `ToIntegral()` calls (useful `string_view` constructors may help).

https://en.cppreference.com/w/cpp/string/basic_string_view/basic_string_view

Code after:
                script_size += 38;
            } else if (Const("ripemd160(", in)) {
                auto res = ParseHexStrEnd(in, 20, ctx);
                if (!res) return {};
                auto& [hash, hash_size] = *res;
                constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::RIPEMD160, std::move(hash)));
                in = in.subspan(hash_size + 1);
                script_size += 26;
            } else if (Const("hash256(", in)) {
                auto res = ParseHexStrEnd(in, 32, ctx);
                if (!res) return {};
                auto& [hash, hash_size] = *res;
                constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::HASH256, std::move(hash)));
                in = in.subspan(hash_size + 1);
                script_size += 38;
            } else if (Const("hash160(", in)) {
                auto res = ParseHexStrEnd(in, 20, ctx);
                if (!res) return {};
                auto& [hash, hash_size] = *res;
                constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::HASH160, std::move(hash)));
                in = in.subspan(hash_size + 1);
                script_size += 26;
            } else if (Const("after(", in)) {
                int arg_size = FindNextChar(in, ')');
                if (arg_size < 1) return {};
                const auto num{ToIntegral<int64_t>(std::string_view(in.begin(), arg_size))};
                if (!num.has_value() || *num < 1 || *num >= 0x80000000L) return {};
                constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::AFTER, *num));
                in = in.subspan(arg_size + 1);
                script_size += 1 + (*num > 16) + (*num > 0x7f) + (*num > 0x7fff) + (*num > 0x7fffff);
            } else if (Const("older(", in)) {
                int arg_size = FindNextChar(in, ')');
                if (arg_size < 1) return {};
                const auto num{ToIntegral<int64_t>(std::string_view(in.begin(), arg_size))};
                if (!num.has_value() || *num < 1 || *num >= 0x80000000L) return {};
                constructed.push_back(MakeNodeRef<Key>(internal::NoDupCheck{}, ctx.MsContext(), Fragment::OLDER, *num));
                in = in.subspan(arg_size + 1);
                script_size += 1 + (*num > 16) + (*num > 0x7f) + (*num > 0x7fff) + (*num > 0x7fffff);
            } else if (Const("multi(", in)) {
                if (!parse_multi_exp(in, /* is_multi_a = */false)) return {};
            } else if (Const("multi_a(", in)) {
                if (!parse_multi_exp(in, /* is_multi_a = */true)) return {};
            } else if (Const("thresh(", in)) {
                int next_comma = FindNextChar(in, ',');
                if (next_comma < 1) return {};
                const auto k{ToIntegral<int64_t>(std::string_view(in.begin(), next_comma))};
                if (!k.has_value() || *k < 1) return {};
                in = in.subspan(next_comma + 1);
                // n = 1 here because we read the first WRAPPED_EXPR before reaching THRESH
                to_parse.emplace_back(ParseContext::THRESH, 1, *k);
                to_parse.emplace_back(ParseContext::WRAPPED_EXPR, -1, -1);