예제 #1
0
void quicksort(int *A, int begin, int end)
{
    int split;
    if (end - begin <= 1)
        return;
    split = get_split(A, begin, end);
    swap(A, begin, split - 1);
    assume(split > begin);
    assume(split <= end);
    quicksort(A, begin, split - 1);
    quicksort(A, split, end);
}
예제 #2
0
/**
 * filter format:
 * \code{regex}
 *  option = "ocr" | "kbd" | "content" | "regex" | "exact-content" | "exact-regex"
 *  option_separator = "," | "-"
 *  filter
 *      = \s* pattern
 *      | \s* "$:" pattern
 *      | \s* "$" option ( option_separator option )* ":" pattern
 * \endcode
 *
 * With \c conf_regex = KBD_INPUT, exact-content and exact-regex are respectively equivalent to content and regex
 */
PatternValue get_pattern_value(array_view_const_char const pattern_rule)
{
    using Cat = PatternValue::Cat;

    struct IsWordSeparator
    {
        bool operator == (char c) const {
            return c == '-' || c == ',';
        }
    };

    PatternValue pattern_value;
    constexpr PatternValue empty_pattern_value {};

    auto av = array_view_const_char{
        ltrim(pattern_rule.begin(), pattern_rule.end()), pattern_rule.end()};

    if (not av.empty() && av.front() == '$') {
        auto end_option_list = std::find(av.begin()+1, av.end(), ':');
        if (end_option_list != av.end() && end_option_list+1 != av.end()) {
            array_view_const_char options(av.begin()+1, end_option_list);
            bool is_exact = false;
            for (auto token : get_split(options, IsWordSeparator{})) {
                auto eq = [](range<char const*> b, array_view_const_char a) {
                    return a.size() == b.size() && std::equal(a.begin(), a.end(), b.begin());
                };

                if (eq(token, cstr_array_view("exact"))) {
                    is_exact = true;
                }
                else {
                    if (eq(token, cstr_array_view("ocr"))) {
                        pattern_value.is_ocr = true;
                        if (is_exact) {
                            pattern_value.cat = Cat::is_exact_str;
                        }
                    }
                    else if (eq(token, cstr_array_view("kbd"))) {
                        pattern_value.is_kbd = true;
                        if (is_exact) {
                            pattern_value.cat = Cat::is_exact_str;
                        }
                    }
                    else if (eq(token, cstr_array_view("regex"))) {
                        pattern_value.cat = is_exact ? Cat::is_exact_reg : Cat::is_reg;
                    }
                    else if (eq(token, cstr_array_view("content"))) {
                        pattern_value.cat = is_exact ? Cat::is_exact_str : Cat::is_str;
                    }
                    else {
                        LOG(LOG_WARNING, "Unknown filter option=\"%.*s\" at char %d in \"%.*s\"",
                            int(token.size()), token.begin(),
                            int(token.begin() - pattern_rule.begin()),
                            int(pattern_rule.size()), pattern_rule.begin());
                        return empty_pattern_value;
                    }
                    is_exact = false;
                }
            }
            if (is_exact) {
                pattern_value.cat = Cat::is_exact_str;
            }
            if (not pattern_value.is_ocr && not pattern_value.is_kbd) {
                pattern_value.is_ocr = true;
            }

            pattern_value.pattern = {end_option_list+1, av.end()};
        }
    }
    else {
        pattern_value.pattern = av;
        pattern_value.is_ocr = true;
    }

    return pattern_value;
}
예제 #3
0
AuthorizationChannels::AuthorizationChannels(std::string const & allow, std::string const & deny)
{
    std::vector<CHANNELS::ChannelNameId> allow_ids;
    std::vector<CHANNELS::ChannelNameId> deny_ids;
    std::vector<array_view_const_char> allow_large_ids;
    std::vector<array_view_const_char> deny_large_ids;

    auto extract = [](
        array_view_const_char list,
        std::vector<CHANNELS::ChannelNameId> & ids,
        std::vector<array_view_const_char> & large_ids
    ) {
        bool all = false;
        for (auto && r : get_split(list.begin(), list.end(), ',')) {
            auto trimmed = trim(begin(r), end(r));
            if (trimmed.empty()) {
                continue;
            }
            if (trimmed[0] == '*') {
                all = true;
            }
            else {
                switch (trimmed.size()) {
                    case 0: break;
                    case 1: ids.emplace_back(c_array<1>(trimmed.begin())); break;
                    case 2: ids.emplace_back(c_array<2>(trimmed.begin())); break;
                    case 3: ids.emplace_back(c_array<3>(trimmed.begin())); break;
                    case 4: ids.emplace_back(c_array<4>(trimmed.begin())); break;
                    case 5: ids.emplace_back(c_array<5>(trimmed.begin())); break;
                    case 6: ids.emplace_back(c_array<6>(trimmed.begin())); break;
                    case 7: ids.emplace_back(c_array<7>(trimmed.begin())); break;
                    default: large_ids.emplace_back(trimmed.begin(), trimmed.end());
                }
            }
        }
        return all;
    };

    this->all_allow_ = extract(allow, allow_ids, allow_large_ids);
    this->all_deny_ = extract(deny, deny_ids, deny_large_ids);

    if (this->all_allow_ && !this->all_deny_) {
        this->rdpdr_restriction_.fill(true);
        this->cliprdr_restriction_.fill(true);
        this->rdpsnd_restriction_.fill(true);
    }

    auto normalize = [this](
        bool set,
        std::vector<CHANNELS::ChannelNameId> & ids,
        std::vector<array_view_const_char> & large_ids
    ) {
        ::normalize(ids, large_ids, channel_names::cliprdr, set, this->cliprdr_restriction_, cliprde_list());
        ::normalize(ids, large_ids, channel_names::rdpdr, set, this->rdpdr_restriction_, rdpdr_list());
        ::normalize(ids, large_ids, channel_names::rdpsnd, set, this->rdpsnd_restriction_, rdpsnd_list());
    };

    normalize(true, allow_ids, allow_large_ids);
    normalize(false, deny_ids, deny_large_ids);

    auto normalize_channel = [&](CHANNELS::ChannelNameId channel_name, bool is_allowed) {
        if (is_allowed) {
            allow_ids.emplace_back(channel_name);
        }
        else {
            deny_ids.emplace_back(channel_name);
        }
    };

    normalize_channel(
        channel_names::cliprdr,
        cliprdr_up_is_authorized() || cliprdr_down_is_authorized());
    bool const is_allowed = (
        contains_true(this->rdpdr_restriction_)
        || contains_true(this->rdpsnd_restriction_));
    normalize_channel(channel_names::rdpdr, is_allowed);
    normalize_channel(channel_names::rdpsnd, is_allowed);

    auto optimize = [](std::vector<CHANNELS::ChannelNameId> & ids) {
        auto cmp = [](CHANNELS::ChannelNameId name1, CHANNELS::ChannelNameId name2){
            return uint64_t(name1) < uint64_t(name2);
        };
        std::sort(ids.begin(), ids.end(), cmp);
        ids.erase(std::unique(ids.begin(), ids.end()), ids.end());
    };

    optimize(allow_ids);
    optimize(deny_ids);

    this->allow_and_deny_.reserve(allow_ids.size() + deny_ids.size());
    this->allow_and_deny_.insert(this->allow_and_deny_.end(), allow_ids.begin(), allow_ids.end());
    this->allow_and_deny_.insert(this->allow_and_deny_.end(), deny_ids.begin(), deny_ids.end());
    this->allow_and_deny_pivot_ = this->allow_and_deny_.data() + allow_ids.size();
}