#include "LauncherArgumentTokenizer.hxx"

LauncherArgumentTokenizer::LauncherArgumentTokenizer()
{

}

QList<LauncherArgumentTokenizer::Arg> LauncherArgumentTokenizer::tokenize(QString in) const
{
    int index = 0;
    const int len = in.count();
    QChar c, nc;
    State state = Start;
    QString key, value;
    QList<Arg> result;

    for (; index < len; ++index) {
        c = in.at(index);
        nc = index < (len - 1) ? in.at(index + 1) : QChar();

        switch (state) {
        case Start:
            if (c == QChar('-')) {
                if (nc == QChar('-')) {
                    state = Key;
                    key.clear();
                    ++index;
                } else {
                    // should we pemit single hyphen arguments?
                    // choosing to fail for now
                    return QList<Arg>();
                }
            } else if (c == QChar('#')) {
                state = Comment;
                break;
            } else if (c.isSpace()) {
                break;
            }
            break;

        case Key:
            if (c == QChar('=')) {
                state = Value;
                value.clear();
            } else if (c.isSpace()) {
                state = Start;
                result.append(Arg(key));
            } else {
                // could check for illegal charatcers here
                key.append(c);
            }
            break;

        case Value:
            if (c == QChar('"')) {
                state = Quoted;
            } else if (c.isSpace()) {
                state = Start;
                result.append(Arg(key, value));
            } else {
                value.append(c);
            }
            break;

        case Quoted:
            if (c == QChar('\\')) {
                // check for escaped double-quote inside quoted value
                if (nc == QChar('"')) {
                    ++index;
                }
            } else if (c == QChar('"')) {
                state = Value;
            } else {
                value.append(c);
            }
            break;

        case Comment:
            if ((c == QChar('\n')) || (c == QChar('\r'))) {
                state = Start;
                break;
            } else {
                // nothing to do, eat comment chars
            }
            break;
        } // of state switch
    } // of character loop

    // ensure last argument isn't lost
    if (state == Key) {
        result.append(Arg(key));
    } else if (state == Value) {
        result.append(Arg(key, value));
    }

    return result;
}
