/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <ctype.h>

#include <utils/String8.h>

#include "LogWhiteBlackList.h"

// White and Black list

Prune::Prune(uid_t uid, pid_t pid) : mUid(uid), mPid(pid) {
}

int Prune::cmp(uid_t uid, pid_t pid) const {
    if ((mUid == uid_all) || (mUid == uid)) {
        if (mPid == pid_all) {
            return 0;
        }
        return pid - mPid;
    }
    return uid - mUid;
}

void Prune::format(char **strp) {
    if (mUid != uid_all) {
        if (mPid != pid_all) {
            asprintf(strp, "%u/%u", mUid, mPid);
        } else {
            asprintf(strp, "%u", mUid);
        }
    } else if (mPid != pid_all) {
        asprintf(strp, "/%u", mPid);
    } else { // NB: mPid == pid_all can not happen if mUid == uid_all
        asprintf(strp, "/");
    }
}

PruneList::PruneList() : mWorstUidEnabled(true) {
    mNaughty.clear();
    mNice.clear();
}

PruneList::~PruneList() {
    PruneCollection::iterator it;
    for (it = mNice.begin(); it != mNice.end();) {
        delete (*it);
        it = mNice.erase(it);
    }
    for (it = mNaughty.begin(); it != mNaughty.end();) {
        delete (*it);
        it = mNaughty.erase(it);
    }
}

int PruneList::init(char *str) {
    mWorstUidEnabled = true;
    PruneCollection::iterator it;
    for (it = mNice.begin(); it != mNice.end();) {
        delete (*it);
        it = mNice.erase(it);
    }
    for (it = mNaughty.begin(); it != mNaughty.end();) {
        delete (*it);
        it = mNaughty.erase(it);
    }

    if (!str) {
        return 0;
    }

    mWorstUidEnabled = false;

    for(; *str; ++str) {
        if (isspace(*str)) {
            continue;
        }

        PruneCollection *list;
        if ((*str == '~') || (*str == '!')) { // ~ supported, ! undocumented
            ++str;
            // special case, translates to worst UID at priority in blacklist
            if (*str == '!') {
                mWorstUidEnabled = true;
                ++str;
                if (!*str) {
                    break;
                }
                if (!isspace(*str)) {
                    return 1;
                }
                continue;
            }
            if (!*str) {
                return 1;
            }
            list = &mNaughty;
        } else {
            list = &mNice;
        }

        uid_t uid = Prune::uid_all;
        if (isdigit(*str)) {
            uid = 0;
            do {
                uid = uid * 10 + *str++ - '0';
            } while (isdigit(*str));
        }

        pid_t pid = Prune::pid_all;
        if (*str == '/') {
            ++str;
            if (isdigit(*str)) {
                pid = 0;
                do {
                    pid = pid * 10 + *str++ - '0';
                } while (isdigit(*str));
            }
        }

        if ((uid == Prune::uid_all) && (pid == Prune::pid_all)) {
            return 1;
        }

        if (*str && !isspace(*str)) {
            return 1;
        }

        // insert sequentially into list
        PruneCollection::iterator it = list->begin();
        while (it != list->end()) {
            Prune *p = *it;
            int m = uid - p->mUid;
            if (m == 0) {
                if (p->mPid == p->pid_all) {
                    break;
                }
                if ((pid == p->pid_all) && (p->mPid != p->pid_all)) {
                    it = list->erase(it);
                    continue;
                }
                m = pid - p->mPid;
            }
            if (m <= 0) {
                if (m < 0) {
                    list->insert(it, new Prune(uid,pid));
                }
                break;
            }
            ++it;
        }
        if (it == list->end()) {
            list->push_back(new Prune(uid,pid));
        }
        if (!*str) {
            break;
        }
    }

    return 0;
}

void PruneList::format(char **strp) {
    if (*strp) {
        free(*strp);
        *strp = NULL;
    }

    static const char nice_format[] = " %s";
    const char *fmt = nice_format + 1;

    android::String8 string;

    if (mWorstUidEnabled) {
        string.setTo("~!");
        fmt = nice_format;
    }

    PruneCollection::iterator it;

    for (it = mNice.begin(); it != mNice.end(); ++it) {
        char *a = NULL;
        (*it)->format(&a);

        string.appendFormat(fmt, a);
        fmt = nice_format;

        free(a);
    }

    static const char naughty_format[] = " ~%s";
    fmt = naughty_format + (*fmt != ' ');
    for (it = mNaughty.begin(); it != mNaughty.end(); ++it) {
        char *a = NULL;
        (*it)->format(&a);

        string.appendFormat(fmt, a);
        fmt = naughty_format;

        free(a);
    }

    *strp = strdup(string.string());
}

// ToDo: Lists are in sorted order, Prune->cmp() returns + or -
// If there is scaling issues, resort to a better algorithm than linear
// based on these assumptions.

bool PruneList::naughty(LogBufferElement *element) {
    PruneCollection::iterator it;
    for (it = mNaughty.begin(); it != mNaughty.end(); ++it) {
        if (!(*it)->cmp(element)) {
            return true;
        }
    }
    return false;
}

bool PruneList::nice(LogBufferElement *element) {
    PruneCollection::iterator it;
    for (it = mNice.begin(); it != mNice.end(); ++it) {
        if (!(*it)->cmp(element)) {
            return true;
        }
    }
    return false;
}
