#include <map>

/* Example mask:
 *    [Goto:%0 [If:%1]]
 */
template<typename CharT>
bool Match(const std::basic_string<CharT>& input,
           const std::basic_string<CharT>& mask,
           std::basic_string<CharT>& p0,
           std::basic_string<CharT>& p1)
{
    std::basic_string<CharT> key;
    std::map<unsigned, std::pair<std::size_t,std::size_t>> parts;
    unsigned prev = ~0u;
    std::size_t input_start      = 0;
    std::size_t mask_start       = 0;
    while(mask_start != mask.size())
    {
        std::size_t percent_position = mask.find(U'%', mask_start);

        unsigned match_index = ~0u;
        if(percent_position != key.npos &&
            (mask[percent_position+1] == '0' || mask[percent_position+1] == '1'))
        {
            match_index = mask[percent_position+1]-'0';
        }
        else
            percent_position = mask.npos;

        std::size_t candidate;
        if(percent_position == mask.npos)
        {
            key.assign(mask.begin()+mask_start, mask.end());

            candidate = input.find(key, input_start);
            // Find last
            if(candidate != input.npos)
                for(;;)
                {
                    std::size_t p = input.find(key, candidate+1);
                    if(p == input.npos) break;
                    candidate = p;
                }
        }
        else
        {
            key.assign(mask.begin()+mask_start, mask.begin()+percent_position);
            candidate = input.find(key, input_start);
        }

        if(candidate == input.npos) return false;
        if(candidate != 0 && prev == ~0u) return false;

        input_start = candidate + key.size();

        if(prev != ~0u) parts[prev].second = candidate;
        if(percent_position == mask.npos)
        {
            prev = ~0u;
            break;
        }

        parts[match_index].first = input_start;
        prev       = match_index;
        mask_start = percent_position + 2;
    }
    if(prev != ~0u) { parts[prev].second = input.size(); input_start = input.size(); }

    /*std::fprintf(stderr, "Match(\"%s\", \"%s\") prev=%u:\n", input.c_str(), mask.c_str(), prev);
    for(auto p: parts)
        std::fprintf(stderr, " p %u: %zu,%zu\n", p.first, p.second.first, p.second.second);*/

    for(auto p: parts)
        if(p.first == 0)
            p0.assign(input.begin() + p.second.first, input.begin() + p.second.second);
        else
            p1.assign(input.begin() + p.second.first, input.begin() + p.second.second);

    if(input_start != input.size()) return false;
    return true;
}

/*
template<typename CharT>
void RegexReplace(const std::basic_string<CharT>& pattern,
                  const std::basic_string<CharT>& replacement,
                  std::basic_string<CharT>& subject)
{
    std::basic_regex<CharT> exp(pattern);
    subject = std::regex_replace(subject, exp, replacement, std::regex_constants::format_sed);
}
*/
