<commit_before>#include <cassert>
#include <iostream>
#include <algorithm>

#include "structures/extended_formula.h"

using namespace satsolver;

#define EF ExtendedFormula
#define SPEF std::shared_ptr<EF>
#define SPCEF std::shared_ptr<const EF>

#define remove_minus(str) ((str[0] == '-' ? str.erase(str.begin()+1, str.end())), str)

int EF::last_id = 0;

EF::EF(const EF *that) : type(that->type), f1(that->f1), f2(that->f2), literal(that->literal), id(++this->last_id) {
}

EF::EF(EF::Type type) : type (type), id(++this->last_id) {
    assert(type == EF::TRUE || type == EF::FALSE);
}

EF::EF(EF::Type type, std::string literal) : type (type), literal(literal), id(++this->last_id) {
    assert(type == EF::LITERAL);
}

EF::EF(EF::Type type, SPEF f) : type (type), f1(f), id(++this->last_id) {
    assert(type == EF::NOT);;
}

EF::EF(EF::Type type, SPEF f1, SPEF f2) : type (type), f1(f1), f2(f2), id(++this->last_id) {
    assert(type != EF::TRUE);
    assert(type != EF::FALSE);
    assert(type != EF::LITERAL);
    assert(type != EF::NOT);
    if (type == EF::IMPLIES) {
        this->translation = SPEF(new ExtendedFormula(EF::OR, SPEF(new EF(EF::NOT, this->f1)), this->f2));
    }
}

std::string EF::make_literal() const {
    if (this->type == EF::LITERAL)
        return this->literal;
    else
        return std::string("@") + std::to_string(this->id);
}

std::vector<std::vector<std::string>*>* EF::reduce_all() const {
    std::vector<const EF *> *formulas = new std::vector<const EF *>();
    std::vector<std::vector<std::string>*> *clauses = new std::vector<std::vector<std::string>*>();
    const EF (*formula);
    formulas->push_back(this);
    while (formulas->size()) {
        formula = formulas->at(formulas->size()-1);
        formulas->pop_back();
        formula->reduce(formulas, clauses);
    }
    delete formulas;
    return clauses;
}
void EF::reduce(std::vector<const EF*> *formulas, std::vector<std::vector<std::string>*> *clauses) const {
    std::vector<std::string> *clause;
    const EF *f;

    if (type == EF::LITERAL || type == EF::TRUE || type == EF::FALSE) {
    }
    else if (type == EF::NOT) {
        formulas->push_back(&*this->f1);
    }
    else {
        formulas->push_back(&*this->f1);
        formulas->push_back(&*this->f2);
    }

    switch (this->type) {
        case AND:
            clause = new std::vector<std::string>{
                    std::string("-") + this->f1->make_literal(),
                    std::string("-") + this->f2->make_literal(),
                    this->make_literal()
                };
            clauses->push_back(clause); // -A v -B v C
            clause = new std::vector<std::string>{
                    this->f1->make_literal(),
                    std::string("-") + this->make_literal(),
                    ""
                };
            clauses->push_back(clause); // A v -C
            clause = new std::vector<std::string>{
                    this->f2->make_literal(),
                    std::string("-") + this->make_literal(),
                    ""
                };
            clauses->push_back(clause); // B v -C
            break;
        case OR:
            clause = new std::vector<std::string>{
                    this->f1->make_literal(),
                    this->f2->make_literal(),
                    std::string("-") + this->make_literal()
                };
            clauses->push_back(clause); // A v B v -C
            clause = new std::vector<std::string>{
                    std::string("-") + this->f1->make_literal(),
                    this->make_literal(),
                    ""
                };
            clauses->push_back(clause); // -A v C
            clause = new std::vector<std::string>{
                    std::string("-") + this->f2->make_literal(),
                    this->make_literal(),
                    ""
                };
            clauses->push_back(clause); // -B v C
            break;
        case XOR:
            clause = new std::vector<std::string>{
                    std::string("-") + this->f1->make_literal(),
                    std::string("-") + this->f2->make_literal(),
                    std::string("-") + this->make_literal()
                };
            clauses->push_back(clause); // -A v -B v -C
            clause = new std::vector<std::string>{
                    this->f1->make_literal(),
                    this->f2->make_literal(),
                    std::string("-") + this->make_literal()
                };
            clauses->push_back(clause); // A v B v -C
            clause = new std::vector<std::string>{
                    this->f1->make_literal(),
                    std::string("-") + this->f2->make_literal(),
                    this->make_literal()
                };
            clauses->push_back(clause); // A v -B v C
            clause = new std::vector<std::string>{
                    std::string("-") + this->f1->make_literal(),
                    this->f2->make_literal(),
                    this->make_literal()
                };
            clauses->push_back(clause); // -A v B v C
            break;
        case NOT:
            clause = new std::vector<std::string>{
                    std::string("-") + this->f1->make_literal(),
                    std::string("-") + this->make_literal(),
                    ""
                };
            clauses->push_back(clause); // -A v -B
            clause = new std::vector<std::string>{
                    this->f1->make_literal(),
                    this->make_literal(),
                    ""
                };
            clauses->push_back(clause); // A v B
            break;
        case IMPLIES:
            f = &*this->translation;
            formulas->push_back(f);
            clause = new std::vector<std::string>{
                    f->make_literal(),
                    std::string("-") + this->make_literal(),
                    ""
                };
            clauses->push_back(clause); // A v -B
            clause = new std::vector<std::string>{
                    std::string("-") + f->make_literal(),
                    this->make_literal(),
                    ""
                };
            clauses->push_back(clause); // -A v B
        case LITERAL:
        case TRUE:
        case FALSE:
            break;
    }
}

std::shared_ptr<Formula> EF::reduce_to_formula(std::shared_ptr<std::map<std::string, int>> *name_to_variable_ptr) const {
    std::vector<std::vector<std::string>*> *raw_clauses = this->reduce_all();
    std::shared_ptr<std::map<std::string, int>> name_to_variable = std::make_shared<std::map<std::string, int>>();
    int nb_variables = 0;
    int i;
    std::vector<std::shared_ptr<satsolver::Clause>> clauses;
    std::shared_ptr<std::vector<int>> int_literals;
    std::string string_literal;

    raw_clauses->push_back(new std::vector<std::string>{this->make_literal(), "", ""});

    for (auto raw_clause : *raw_clauses) {
        for (i=0; i<3; i++) {
            string_literal = raw_clause->at(i);
            if (string_literal[0] == '-')
                string_literal.erase(string_literal.begin(), string_literal.begin()+1);
            if (string_literal != "" && name_to_variable->find(string_literal) == name_to_variable->end()) {
                name_to_variable->insert(std::make_pair(string_literal, ++nb_variables));
            }
        }
    }

    for (auto raw_clause : *raw_clauses) {
        int_literals = std::make_shared<std::vector<int>>();
        for (i=0; i<3; i++) {
            string_literal = raw_clause->at(i);
            if (string_literal[0] == '-') {
                string_literal.erase(string_literal.begin(), string_literal.begin()+1);
                int_literals->push_back(- name_to_variable->at(string_literal));
            }
            else if (string_literal[0]) {
                int_literals->push_back(name_to_variable->at(string_literal));
            }
        }
        assert(int_literals->size());
        clauses.push_back(std::shared_ptr<satsolver::Clause>(new satsolver::Clause(nb_variables, int_literals)));
        delete raw_clause;
    }
    delete raw_clauses;
    if (clauses.size() == 1) // Conjonction of zero clauses
        return NULL;

    if (name_to_variable_ptr)
        *name_to_variable_ptr = name_to_variable;
    return std::shared_ptr<Formula>(new Formula(clauses, nb_variables));

}

std::string EF::to_string() const {
    switch (this->type) {
        case EF::XOR:
            return "(" + this->f1->to_string() + "⊻" + this->f2->to_string() + ")";
        case EF::OR:
            return "(" + this->f1->to_string() + "∨" + this->f2->to_string() + ")";
        case EF::AND:
            return "(" + this->f1->to_string() + "∧" + this->f2->to_string() + ")";
        case EF::IMPLIES:
            return "(" + this->f1->to_string() + "→" + this->f2->to_string() + ")";
        case EF::NOT:
            return "(¬" + this->f1->to_string() + ")";
        case EF::LITERAL:
            return "“" + this->literal + "”";
        case EF::TRUE:
            return "⊤";
        case EF::FALSE:
            return "⊥";
    }
    assert(false);
}

bool EF::operator==(const ExtendedFormula &that) const {
    if (this->type != that.type) {
        return false;
    }
    switch (this->type) {
        case EF::OR:
        case EF::XOR:
        case EF::AND:
            return ((*this->f1 == *that.f1 && *this->f2 == *that.f2) || (*this->f1 == *that.f2 && *this->f2 == *that.f1));
        case EF::IMPLIES:
            return (*this->f1 == *that.f1 && *this->f2 == *that.f2);
        case EF::NOT:
            return *this->f1 == *that.f1;
        case EF::LITERAL:
            return this->literal == that.literal;
        case TRUE:
        case FALSE:
            return true;
    }
    assert(false);
}

bool EF::operator!=(const ExtendedFormula &that) const {
    return !(*this == that);
}

SPEF EF::simplify() const {
    SPEF f1, f2;
    switch(this->type) {
        case EF::OR:
        case EF::AND:
        case EF::XOR:
        case EF::IMPLIES:
            f1 = this->f1->simplify();
            f2 = this->f2->simplify();
            break;
        case EF::NOT:
            f1 = this->f1->simplify();
            break;
        default:
            break;
    }
    switch (this->type) {
        case EF::OR:
            if (f1->type == EF::TRUE)
                return f1;
            else if (f2->type == EF::TRUE)
                return f2;
            else if (*f1 == EF(EF::NOT, f2))
                return SPEF(new EF(EF::TRUE));
            else if (*f2 == EF(EF::NOT, f1))
                return SPEF(new EF(EF::TRUE));
            else if (f1->type == EF::FALSE)
                return SPEF(new EF(*f2));
            else if (f2->type == EF::FALSE)
                return SPEF(new EF(*f1));
            break;
        case EF::AND:
            if (f1->type == EF::FALSE)
                return f1;
            else if (f2->type == EF::FALSE)
                return f2;
            else if (*f1 == *f2)
                return SPEF(new EF(*f1));
            else if (f1->type == TRUE)
                return SPEF(new EF(*f2));
            else if (f2->type == TRUE)
                return SPEF(new EF(*f1));
            if (*f1 == EF(EF::NOT, f2))
                return SPEF(new EF(EF::FALSE));
            else if (*f2 == EF(EF::NOT, f1))
                return SPEF(new EF(EF::FALSE));
            break;
        case EF::IMPLIES:
            if (f1->type == EF::FALSE)
                return SPEF(new EF(EF::TRUE));
            else if (f2->type == EF::TRUE)
                return SPEF(new EF(EF::TRUE));
            else if (f1->type == EF::TRUE)
                return f2;
            else if (f2->type == EF::FALSE)
                return SPEF(new EF(EF::NOT, f1));
            break;
        default:
            break;
    }
    switch(this->type) {
        case EF::OR:
        case EF::AND:
        case EF::XOR:
        case EF::IMPLIES:
            return SPEF(new EF(this->type, f1, f2));
        case EF::NOT:
            if (f1->type == EF::NOT)
                return SPEF(new EF(*f1->f1));
            else
                return SPEF(new EF(this->type, f1));
        default:
            return SPEF(new EF(this));
    }
    assert(false);
}

std::shared_ptr<std::unordered_set<std::string>> EF::get_literals() const {
    std::shared_ptr<std::unordered_set<std::string>> items1, items2;
    switch (this->type) {
        case EF::TRUE:
        case EF::FALSE:
            return std::make_shared<std::unordered_set<std::string>>();
        case EF::LITERAL:
            items1 = std::make_shared<std::unordered_set<std::string>>();
            items1->insert(this->literal);
            return items1;
        case EF::NOT:
            return this->f1->get_literals();
        case EF::AND:
        case EF::OR:
        case EF::IMPLIES:
        case EF::XOR:
            items1 = this->f1->get_literals();
            items2 = this->f2->get_literals();
            items1->insert(items2->begin(), items2->end());
            return items1;
    }
    assert(false);
}
<commit_msg>Fix infinite loop.<commit_after>#include <cassert>
#include <iostream>
#include <algorithm>

#include "structures/extended_formula.h"

using namespace satsolver;

#define EF ExtendedFormula
#define SPEF std::shared_ptr<EF>
#define SPCEF std::shared_ptr<const EF>

#define remove_minus(str) ((str[0] == '-' ? str.erase(str.begin()+1, str.end())), str)

int EF::last_id = 0;

EF::EF(const EF *that) : type(that->type), f1(that->f1), f2(that->f2), literal(that->literal), id(++this->last_id) {
}

EF::EF(EF::Type type) : type (type), id(++this->last_id) {
    assert(type == EF::TRUE || type == EF::FALSE);
}

EF::EF(EF::Type type, std::string literal) : type (type), literal(literal), id(++this->last_id) {
    assert(type == EF::LITERAL);
}

EF::EF(EF::Type type, SPEF f) : type (type), f1(f), id(++this->last_id) {
    assert(type == EF::NOT);;
}

EF::EF(EF::Type type, SPEF f1, SPEF f2) : type (type), f1(f1), f2(f2), id(++this->last_id) {
    assert(type != EF::TRUE);
    assert(type != EF::FALSE);
    assert(type != EF::LITERAL);
    assert(type != EF::NOT);
    if (type == EF::IMPLIES) {
        this->translation = SPEF(new ExtendedFormula(EF::OR, SPEF(new EF(EF::NOT, this->f1)), this->f2));
    }
}

std::string EF::make_literal() const {
    if (this->type == EF::LITERAL)
        return this->literal;
    else
        return std::string("@") + std::to_string(this->id);
}

std::vector<std::vector<std::string>*>* EF::reduce_all() const {
    std::unordered_set<int> handled;
    std::vector<const EF *> *formulas = new std::vector<const EF *>();
    std::vector<std::vector<std::string>*> *clauses = new std::vector<std::vector<std::string>*>();
    const EF (*formula);
    formulas->push_back(this);
    while (formulas->size()) {
        formula = formulas->at(formulas->size()-1);
        formulas->pop_back();
        if (handled.find(formula->id) != handled.end())
            continue; // This formula has already been handled. Why?
        formula->reduce(formulas, clauses);
    }
    delete formulas;
    return clauses;
}
void EF::reduce(std::vector<const EF*> *formulas, std::vector<std::vector<std::string>*> *clauses) const {
    std::vector<std::string> *clause;
    const EF *f;

    if (type == EF::LITERAL || type == EF::TRUE || type == EF::FALSE) {
    }
    else if (type == EF::NOT) {
        formulas->push_back(&*this->f1);
    }
    else {
        formulas->push_back(&*this->f1);
        formulas->push_back(&*this->f2);
    }

    switch (this->type) {
        case AND:
            clause = new std::vector<std::string>{
                    std::string("-") + this->f1->make_literal(),
                    std::string("-") + this->f2->make_literal(),
                    this->make_literal()
                };
            clauses->push_back(clause); // -A v -B v C
            clause = new std::vector<std::string>{
                    this->f1->make_literal(),
                    std::string("-") + this->make_literal(),
                    ""
                };
            clauses->push_back(clause); // A v -C
            clause = new std::vector<std::string>{
                    this->f2->make_literal(),
                    std::string("-") + this->make_literal(),
                    ""
                };
            clauses->push_back(clause); // B v -C
            break;
        case OR:
            clause = new std::vector<std::string>{
                    this->f1->make_literal(),
                    this->f2->make_literal(),
                    std::string("-") + this->make_literal()
                };
            clauses->push_back(clause); // A v B v -C
            clause = new std::vector<std::string>{
                    std::string("-") + this->f1->make_literal(),
                    this->make_literal(),
                    ""
                };
            clauses->push_back(clause); // -A v C
            clause = new std::vector<std::string>{
                    std::string("-") + this->f2->make_literal(),
                    this->make_literal(),
                    ""
                };
            clauses->push_back(clause); // -B v C
            break;
        case XOR:
            clause = new std::vector<std::string>{
                    std::string("-") + this->f1->make_literal(),
                    std::string("-") + this->f2->make_literal(),
                    std::string("-") + this->make_literal()
                };
            clauses->push_back(clause); // -A v -B v -C
            clause = new std::vector<std::string>{
                    this->f1->make_literal(),
                    this->f2->make_literal(),
                    std::string("-") + this->make_literal()
                };
            clauses->push_back(clause); // A v B v -C
            clause = new std::vector<std::string>{
                    this->f1->make_literal(),
                    std::string("-") + this->f2->make_literal(),
                    this->make_literal()
                };
            clauses->push_back(clause); // A v -B v C
            clause = new std::vector<std::string>{
                    std::string("-") + this->f1->make_literal(),
                    this->f2->make_literal(),
                    this->make_literal()
                };
            clauses->push_back(clause); // -A v B v C
            break;
        case NOT:
            clause = new std::vector<std::string>{
                    std::string("-") + this->f1->make_literal(),
                    std::string("-") + this->make_literal(),
                    ""
                };
            clauses->push_back(clause); // -A v -B
            clause = new std::vector<std::string>{
                    this->f1->make_literal(),
                    this->make_literal(),
                    ""
                };
            clauses->push_back(clause); // A v B
            break;
        case IMPLIES:
            f = &*this->translation;
            formulas->push_back(f);
            clause = new std::vector<std::string>{
                    f->make_literal(),
                    std::string("-") + this->make_literal(),
                    ""
                };
            clauses->push_back(clause); // A v -B
            clause = new std::vector<std::string>{
                    std::string("-") + f->make_literal(),
                    this->make_literal(),
                    ""
                };
            clauses->push_back(clause); // -A v B
        case LITERAL:
        case TRUE:
        case FALSE:
            break;
    }
}

std::shared_ptr<Formula> EF::reduce_to_formula(std::shared_ptr<std::map<std::string, int>> *name_to_variable_ptr) const {
    std::vector<std::vector<std::string>*> *raw_clauses = this->reduce_all();
    std::shared_ptr<std::map<std::string, int>> name_to_variable = std::make_shared<std::map<std::string, int>>();
    int nb_variables = 0;
    int i;
    std::vector<std::shared_ptr<satsolver::Clause>> clauses;
    std::shared_ptr<std::vector<int>> int_literals;
    std::string string_literal;

    raw_clauses->push_back(new std::vector<std::string>{this->make_literal(), "", ""});

    for (auto raw_clause : *raw_clauses) {
        for (i=0; i<3; i++) {
            string_literal = raw_clause->at(i);
            if (string_literal[0] == '-')
                string_literal.erase(string_literal.begin(), string_literal.begin()+1);
            if (string_literal != "" && name_to_variable->find(string_literal) == name_to_variable->end()) {
                name_to_variable->insert(std::make_pair(string_literal, ++nb_variables));
            }
        }
    }

    for (auto raw_clause : *raw_clauses) {
        int_literals = std::make_shared<std::vector<int>>();
        for (i=0; i<3; i++) {
            string_literal = raw_clause->at(i);
            if (string_literal[0] == '-') {
                string_literal.erase(string_literal.begin(), string_literal.begin()+1);
                int_literals->push_back(- name_to_variable->at(string_literal));
            }
            else if (string_literal[0]) {
                int_literals->push_back(name_to_variable->at(string_literal));
            }
        }
        assert(int_literals->size());
        clauses.push_back(std::shared_ptr<satsolver::Clause>(new satsolver::Clause(nb_variables, int_literals)));
        delete raw_clause;
    }
    delete raw_clauses;
    if (clauses.size() == 1) // Conjonction of zero clauses
        return NULL;

    if (name_to_variable_ptr)
        *name_to_variable_ptr = name_to_variable;
    return std::shared_ptr<Formula>(new Formula(clauses, nb_variables));

}

std::string EF::to_string() const {
    switch (this->type) {
        case EF::XOR:
            return "(" + this->f1->to_string() + "⊻" + this->f2->to_string() + ")";
        case EF::OR:
            return "(" + this->f1->to_string() + "∨" + this->f2->to_string() + ")";
        case EF::AND:
            return "(" + this->f1->to_string() + "∧" + this->f2->to_string() + ")";
        case EF::IMPLIES:
            return "(" + this->f1->to_string() + "→" + this->f2->to_string() + ")";
        case EF::NOT:
            return "(¬" + this->f1->to_string() + ")";
        case EF::LITERAL:
            return "“" + this->literal + "”";
        case EF::TRUE:
            return "⊤";
        case EF::FALSE:
            return "⊥";
    }
    assert(false);
}

bool EF::operator==(const ExtendedFormula &that) const {
    if (this->type != that.type) {
        return false;
    }
    switch (this->type) {
        case EF::OR:
        case EF::XOR:
        case EF::AND:
            return ((*this->f1 == *that.f1 && *this->f2 == *that.f2) || (*this->f1 == *that.f2 && *this->f2 == *that.f1));
        case EF::IMPLIES:
            return (*this->f1 == *that.f1 && *this->f2 == *that.f2);
        case EF::NOT:
            return *this->f1 == *that.f1;
        case EF::LITERAL:
            return this->literal == that.literal;
        case TRUE:
        case FALSE:
            return true;
    }
    assert(false);
}

bool EF::operator!=(const ExtendedFormula &that) const {
    return !(*this == that);
}

SPEF EF::simplify() const {
    SPEF f1, f2;
    switch(this->type) {
        case EF::OR:
        case EF::AND:
        case EF::XOR:
        case EF::IMPLIES:
            f1 = this->f1->simplify();
            f2 = this->f2->simplify();
            break;
        case EF::NOT:
            f1 = this->f1->simplify();
            break;
        default:
            break;
    }
    switch (this->type) {
        case EF::OR:
            if (f1->type == EF::TRUE)
                return f1;
            else if (f2->type == EF::TRUE)
                return f2;
            else if (*f1 == EF(EF::NOT, f2))
                return SPEF(new EF(EF::TRUE));
            else if (*f2 == EF(EF::NOT, f1))
                return SPEF(new EF(EF::TRUE));
            else if (f1->type == EF::FALSE)
                return SPEF(new EF(*f2));
            else if (f2->type == EF::FALSE)
                return SPEF(new EF(*f1));
            break;
        case EF::AND:
            if (f1->type == EF::FALSE)
                return f1;
            else if (f2->type == EF::FALSE)
                return f2;
            else if (*f1 == *f2)
                return SPEF(new EF(*f1));
            else if (f1->type == TRUE)
                return SPEF(new EF(*f2));
            else if (f2->type == TRUE)
                return SPEF(new EF(*f1));
            if (*f1 == EF(EF::NOT, f2))
                return SPEF(new EF(EF::FALSE));
            else if (*f2 == EF(EF::NOT, f1))
                return SPEF(new EF(EF::FALSE));
            break;
        case EF::IMPLIES:
            if (f1->type == EF::FALSE)
                return SPEF(new EF(EF::TRUE));
            else if (f2->type == EF::TRUE)
                return SPEF(new EF(EF::TRUE));
            else if (f1->type == EF::TRUE)
                return f2;
            else if (f2->type == EF::FALSE)
                return SPEF(new EF(EF::NOT, f1));
            break;
        default:
            break;
    }
    switch(this->type) {
        case EF::OR:
        case EF::AND:
        case EF::XOR:
        case EF::IMPLIES:
            return SPEF(new EF(this->type, f1, f2));
        case EF::NOT:
            if (f1->type == EF::NOT)
                return SPEF(new EF(*f1->f1));
            else
                return SPEF(new EF(this->type, f1));
        default:
            return SPEF(new EF(this));
    }
    assert(false);
}

std::shared_ptr<std::unordered_set<std::string>> EF::get_literals() const {
    std::shared_ptr<std::unordered_set<std::string>> items1, items2;
    switch (this->type) {
        case EF::TRUE:
        case EF::FALSE:
            return std::make_shared<std::unordered_set<std::string>>();
        case EF::LITERAL:
            items1 = std::make_shared<std::unordered_set<std::string>>();
            items1->insert(this->literal);
            return items1;
        case EF::NOT:
            return this->f1->get_literals();
        case EF::AND:
        case EF::OR:
        case EF::IMPLIES:
        case EF::XOR:
            items1 = this->f1->get_literals();
            items2 = this->f2->get_literals();
            items1->insert(items2->begin(), items2->end());
            return items1;
    }
    assert(false);
}
<|endoftext|>


<commit_before>// Copyright (c) 2013 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

#include "atom/app/atom_main.h"

#include <stdlib.h>

#if defined(OS_WIN)
#include <windows.h>  // windows.h must be included first

#include <shellapi.h>
#include <shellscalingapi.h>
#include <tchar.h>

#include "atom/app/atom_main_delegate.h"
#include "atom/common/crash_reporter/win/crash_service_main.h"
#include "base/environment.h"
#include "base/process/launch.h"
#include "base/win/windows_version.h"
#include "content/public/app/sandbox_helper_win.h"
#include "sandbox/win/src/sandbox_types.h"
#elif defined(OS_LINUX)  // defined(OS_WIN)
#include "atom/app/atom_main_delegate.h"  // NOLINT
#include "content/public/app/content_main.h"
#else  // defined(OS_LINUX)
#include "atom/app/atom_library_main.h"
#endif  // defined(OS_MACOSX)

#include "atom/common/atom_command_line.h"
#include "base/at_exit.h"
#include "base/i18n/icu_util.h"

namespace {

const char* kRunAsNode = "ELECTRON_RUN_AS_NODE";

bool IsEnvSet(const char* name) {
#if defined(OS_WIN)
  size_t required_size;
  getenv_s(&required_size, nullptr, 0, name);
  return required_size != 0;
#else
  char* indicator = getenv(name);
  return indicator && indicator[0] != '\0';
#endif
}

}  // namespace

#if defined(OS_WIN)
int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) {
  int argc = 0;
  wchar_t** wargv = ::CommandLineToArgvW(::GetCommandLineW(), &argc);

  bool run_as_node = IsEnvSet(kRunAsNode);

  // Make sure the output is printed to console.
  if (run_as_node || !IsEnvSet("ELECTRON_NO_ATTACH_CONSOLE"))
    base::RouteStdioToConsole(false);

  // Convert argv to to UTF8
  char** argv = new char*[argc];
  for (int i = 0; i < argc; i++) {
    // Compute the size of the required buffer
    DWORD size = WideCharToMultiByte(CP_UTF8,
                                     0,
                                     wargv[i],
                                     -1,
                                     NULL,
                                     0,
                                     NULL,
                                     NULL);
    if (size == 0) {
      // This should never happen.
      fprintf(stderr, "Could not convert arguments to utf8.");
      exit(1);
    }
    // Do the actual conversion
    argv[i] = new char[size];
    DWORD result = WideCharToMultiByte(CP_UTF8,
                                       0,
                                       wargv[i],
                                       -1,
                                       argv[i],
                                       size,
                                       NULL,
                                       NULL);
    if (result == 0) {
      // This should never happen.
      fprintf(stderr, "Could not convert arguments to utf8.");
      exit(1);
    }
  }

  // if (IsEnvSet("ELECTRON_INTERNAL_CRASH_SERVICE")) {
  //   return crash_service::Main(cmd);
  // }

  sandbox::SandboxInterfaceInfo sandbox_info = {0};
  content::InitializeSandboxInfo(&sandbox_info);
  atom::AtomMainDelegate delegate;

  content::ContentMainParams params(&delegate);
  params.instance = instance;
  params.sandbox_info = &sandbox_info;
  atom::AtomCommandLine::Init(argc, argv);
  atom::AtomCommandLine::InitW(argc, wargv);
  return content::ContentMain(params);
}

#elif defined(OS_LINUX)  // defined(OS_WIN)

int main(int argc, const char* argv[]) {
  atom::AtomMainDelegate delegate;
  content::ContentMainParams params(&delegate);
  params.argc = argc;
  params.argv = argv;
  atom::AtomCommandLine::Init(argc, argv);
  return content::ContentMain(params);
}

#else  // defined(OS_LINUX)

int main(int argc, const char* argv[]) {
  // if (IsEnvSet(kRunAsNode)) {
  //   return AtomInitializeICUandStartNode(argc, const_cast<char**>(argv));
  // }

  return AtomMain(argc, argv);
}

#endif  // defined(OS_MACOSX)
<commit_msg>Re-add crash_service::Main to make google_breakpad::ExceptionHandler out of process again<commit_after>// Copyright (c) 2013 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

#include "atom/app/atom_main.h"

#include <stdlib.h>

#if defined(OS_WIN)
#include <windows.h>  // windows.h must be included first

#include <shellapi.h>
#include <shellscalingapi.h>
#include <tchar.h>

#include "atom/app/atom_main_delegate.h"
#include "atom/common/crash_reporter/win/crash_service_main.h"
#include "base/environment.h"
#include "base/process/launch.h"
#include "base/win/windows_version.h"
#include "content/public/app/sandbox_helper_win.h"
#include "sandbox/win/src/sandbox_types.h"
#elif defined(OS_LINUX)  // defined(OS_WIN)
#include "atom/app/atom_main_delegate.h"  // NOLINT
#include "content/public/app/content_main.h"
#else  // defined(OS_LINUX)
#include "atom/app/atom_library_main.h"
#endif  // defined(OS_MACOSX)

#include "atom/common/atom_command_line.h"
#include "base/at_exit.h"
#include "base/i18n/icu_util.h"

namespace {

const char* kRunAsNode = "ELECTRON_RUN_AS_NODE";

bool IsEnvSet(const char* name) {
#if defined(OS_WIN)
  size_t required_size;
  getenv_s(&required_size, nullptr, 0, name);
  return required_size != 0;
#else
  char* indicator = getenv(name);
  return indicator && indicator[0] != '\0';
#endif
}

}  // namespace

#if defined(OS_WIN)
int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) {
  int argc = 0;
  wchar_t** wargv = ::CommandLineToArgvW(::GetCommandLineW(), &argc);

  bool run_as_node = IsEnvSet(kRunAsNode);

  // Make sure the output is printed to console.
  if (run_as_node || !IsEnvSet("ELECTRON_NO_ATTACH_CONSOLE"))
    base::RouteStdioToConsole(false);

  // Convert argv to to UTF8
  char** argv = new char*[argc];
  for (int i = 0; i < argc; i++) {
    // Compute the size of the required buffer
    DWORD size = WideCharToMultiByte(CP_UTF8,
                                     0,
                                     wargv[i],
                                     -1,
                                     NULL,
                                     0,
                                     NULL,
                                     NULL);
    if (size == 0) {
      // This should never happen.
      fprintf(stderr, "Could not convert arguments to utf8.");
      exit(1);
    }
    // Do the actual conversion
    argv[i] = new char[size];
    DWORD result = WideCharToMultiByte(CP_UTF8,
                                       0,
                                       wargv[i],
                                       -1,
                                       argv[i],
                                       size,
                                       NULL,
                                       NULL);
    if (result == 0) {
      // This should never happen.
      fprintf(stderr, "Could not convert arguments to utf8.");
      exit(1);
    }
  }

  if (isenvset("electron_internal_crash_service")) {
    return crash_service::main(cmd);
  }

  sandbox::SandboxInterfaceInfo sandbox_info = {0};
  content::InitializeSandboxInfo(&sandbox_info);
  atom::AtomMainDelegate delegate;

  content::ContentMainParams params(&delegate);
  params.instance = instance;
  params.sandbox_info = &sandbox_info;
  atom::AtomCommandLine::Init(argc, argv);
  atom::AtomCommandLine::InitW(argc, wargv);
  return content::ContentMain(params);
}

#elif defined(OS_LINUX)  // defined(OS_WIN)

int main(int argc, const char* argv[]) {
  atom::AtomMainDelegate delegate;
  content::ContentMainParams params(&delegate);
  params.argc = argc;
  params.argv = argv;
  atom::AtomCommandLine::Init(argc, argv);
  return content::ContentMain(params);
}

#else  // defined(OS_LINUX)

int main(int argc, const char* argv[]) {
  // if (IsEnvSet(kRunAsNode)) {
  //   return AtomInitializeICUandStartNode(argc, const_cast<char**>(argv));
  // }

  return AtomMain(argc, argv);
}

#endif  // defined(OS_MACOSX)
<|endoftext|>


<commit_before>// Copyright (c) 2015 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

#include "atom/app/node_main.h"

#include "atom/app/uv_task_runner.h"
#include "atom/browser/javascript_environment.h"
#include "atom/browser/node_debugger.h"
#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/threading/thread_task_runner_handle.h"
#include "gin/array_buffer.h"
#include "gin/public/isolate_holder.h"
#include "gin/v8_initializer.h"

#include "atom/common/node_includes.h"

namespace atom {

int NodeMain(int argc, char *argv[]) {
  base::CommandLine::Init(argc, argv);

  int exit_code = 1;
  {
    // Feed gin::PerIsolateData with a task runner.
    argv = uv_setup_args(argc, argv);
    uv_loop_t* loop = uv_default_loop();
    scoped_refptr<UvTaskRunner> uv_task_runner(new UvTaskRunner(loop));
    base::ThreadTaskRunnerHandle handle(uv_task_runner);

    // Initialize feature list.
    std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
    feature_list->InitializeFromCommandLine("", "");
    base::FeatureList::SetInstance(std::move(feature_list));

    gin::V8Initializer::LoadV8Snapshot();
    gin::V8Initializer::LoadV8Natives();
    JavascriptEnvironment gin_env;

    int exec_argc;
    const char** exec_argv;
    node::Init(&argc, const_cast<const char**>(argv), &exec_argc, &exec_argv);

    node::Environment* env = node::CreateEnvironment(
        gin_env.isolate(), loop, gin_env.context(), argc, argv,
        exec_argc, exec_argv);

    // Start our custom debugger implementation.
    NodeDebugger node_debugger(gin_env.isolate());
    if (node_debugger.IsRunning())
      env->AssignToContext(v8::Debug::GetDebugContext());

    node::LoadEnvironment(env);

    bool more;
    do {
      more = uv_run(env->event_loop(), UV_RUN_ONCE);
      if (more == false) {
        node::EmitBeforeExit(env);

        // Emit `beforeExit` if the loop became alive either after emitting
        // event, or after running some callbacks.
        more = uv_loop_alive(env->event_loop());
        if (uv_run(env->event_loop(), UV_RUN_NOWAIT) != 0)
          more = true;
      }
    } while (more == true);

    exit_code = node::EmitExit(env);
    node::RunAtExit(env);

    node::FreeEnvironment(env);
  }

  v8::V8::Dispose();

  return exit_code;
}

}  // namespace atom
<commit_msg>Expose process.log when running as node<commit_after>// Copyright (c) 2015 GitHub, Inc.
// Use of this source code is governed by the MIT license that can be
// found in the LICENSE file.

#include "atom/app/node_main.h"

#include <iostream>

#include "atom/app/uv_task_runner.h"
#include "atom/browser/javascript_environment.h"
#include "atom/browser/node_debugger.h"
#include "atom/common/native_mate_converters/string16_converter.h"
#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/threading/thread_task_runner_handle.h"
#include "gin/array_buffer.h"
#include "gin/public/isolate_holder.h"
#include "gin/v8_initializer.h"
#include "native_mate/dictionary.h"

#include "atom/common/node_includes.h"

namespace atom {

void Log(const base::string16& message) {
  std::cout << message << std::flush;
}

int NodeMain(int argc, char *argv[]) {
  base::CommandLine::Init(argc, argv);

  int exit_code = 1;
  {
    // Feed gin::PerIsolateData with a task runner.
    argv = uv_setup_args(argc, argv);
    uv_loop_t* loop = uv_default_loop();
    scoped_refptr<UvTaskRunner> uv_task_runner(new UvTaskRunner(loop));
    base::ThreadTaskRunnerHandle handle(uv_task_runner);

    // Initialize feature list.
    std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
    feature_list->InitializeFromCommandLine("", "");
    base::FeatureList::SetInstance(std::move(feature_list));

    gin::V8Initializer::LoadV8Snapshot();
    gin::V8Initializer::LoadV8Natives();
    JavascriptEnvironment gin_env;

    int exec_argc;
    const char** exec_argv;
    node::Init(&argc, const_cast<const char**>(argv), &exec_argc, &exec_argv);

    node::Environment* env = node::CreateEnvironment(
        gin_env.isolate(), loop, gin_env.context(), argc, argv,
        exec_argc, exec_argv);

    // Start our custom debugger implementation.
    NodeDebugger node_debugger(gin_env.isolate());
    if (node_debugger.IsRunning())
      env->AssignToContext(v8::Debug::GetDebugContext());

    node::LoadEnvironment(env);

    mate::Dictionary dict(gin_env.isolate(), env->process_object());
    dict.SetMethod("log", &Log);

    bool more;
    do {
      more = uv_run(env->event_loop(), UV_RUN_ONCE);
      if (more == false) {
        node::EmitBeforeExit(env);

        // Emit `beforeExit` if the loop became alive either after emitting
        // event, or after running some callbacks.
        more = uv_loop_alive(env->event_loop());
        if (uv_run(env->event_loop(), UV_RUN_NOWAIT) != 0)
          more = true;
      }
    } while (more == true);

    exit_code = node::EmitExit(env);
    node::RunAtExit(env);

    node::FreeEnvironment(env);
  }

  v8::V8::Dispose();

  return exit_code;
}

}  // namespace atom
<|endoftext|>


<commit_before>#include "BasicBlock.h"
#include "MemStream.h"
#include "offsetof_def.h"
#include "MipsJitter.h"
#include "Jitter_CodeGenFactory.h"

#if defined(AOT_BUILD_CACHE) || defined(AOT_USE_CACHE)
#define AOT_ENABLED
#endif

#ifdef AOT_ENABLED

#include <zlib.h>
#include "StdStream.h"
#include "StdStreamUtils.h"

#endif

#ifdef VTUNE_ENABLED
#include <jitprofiling.h>
#include "string_format.h"
#endif

#ifdef AOT_USE_CACHE

struct AOT_BLOCK
{
	AOT_BLOCK_KEY	key;
	void*			fct;
};

extern "C" AOT_BLOCK	_aot_firstBlock;
extern "C" uint32		_aot_blockCount;

#endif

CBasicBlock::CBasicBlock(CMIPS& context, uint32 begin, uint32 end)
: m_begin(begin)
, m_end(end)
, m_context(context)
, m_selfLoopCount(0)
#ifdef AOT_USE_CACHE
, m_function(nullptr)
#endif
{
	assert(m_end >= m_begin);
}

CBasicBlock::~CBasicBlock()
{

}

#ifdef AOT_BUILD_CACHE

Framework::CStdStream*	CBasicBlock::m_aotBlockOutputStream(nullptr);
std::mutex				CBasicBlock::m_aotBlockOutputStreamMutex;

void CBasicBlock::SetAotBlockOutputStream(Framework::CStdStream* outputStream)
{
	assert(m_aotBlockOutputStream == nullptr || outputStream == nullptr);
	m_aotBlockOutputStream = outputStream;
}

#endif

void CBasicBlock::Compile()
{
#ifndef AOT_USE_CACHE

	Framework::CMemStream stream;
	{
		static __declspec(thread) CMipsJitter* jitter = NULL;
		if(jitter == NULL)
		{
			Jitter::CCodeGen* codeGen = Jitter::CreateCodeGen();
			jitter = new CMipsJitter(codeGen);

			for(unsigned int i = 0; i < 4; i++)
			{
				jitter->SetVariableAsConstant(
					offsetof(CMIPS, m_State.nGPR[CMIPS::R0].nV[i]),
					0
					);
			}
		}

		jitter->SetStream(&stream);
		jitter->Begin();
		CompileRange(jitter);
//		codeGen.DumpVariables(0);
//		codeGen.EndQuota();
		jitter->End();
	}

	m_function = CMemoryFunction(stream.GetBuffer(), stream.GetSize());

#ifdef VTUNE_ENABLED
	if(iJIT_IsProfilingActive() == iJIT_SAMPLING_ON)
	{
		iJIT_Method_Load jmethod = {};
		jmethod.method_id = iJIT_GetNewMethodID();
		jmethod.class_file_name = "";
		jmethod.source_file_name = __FILE__;

		jmethod.method_load_address = m_function.GetCode();
		jmethod.method_size = m_function.GetSize();
		jmethod.line_number_size = 0;

		auto functionName = string_format("BasicBlock_0x%0.8X_0x%0.8X", m_begin, m_end);

		jmethod.method_name = const_cast<char*>(functionName.c_str());
		iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, reinterpret_cast<void*>(&jmethod));
	}
#endif

#endif

#ifdef AOT_ENABLED

	size_t blockSize = ((m_end - m_begin) / 4) + 1;
	auto blockData = new uint32[blockSize];

	for(uint32 i = 0; i < blockSize; i++)
	{
		blockData[i] = m_context.m_pMemoryMap->GetWord(m_begin + (i * 4));
	}

	uint32 blockChecksum = crc32(0, reinterpret_cast<Bytef*>(blockData), blockSize * 4);

#endif

#ifdef AOT_USE_CACHE

	AOT_BLOCK* blocksBegin = &_aot_firstBlock;
	AOT_BLOCK* blocksEnd = blocksBegin + _aot_blockCount;

	AOT_BLOCK blockRef = { blockChecksum, m_begin, m_end, nullptr };

	static const auto blockComparer =
		[] (const AOT_BLOCK& item1, const AOT_BLOCK& item2)
		{
			return item1.key < item2.key;
		};

//	assert(std::is_sorted(blocksBegin, blocksEnd, blockComparer));

	bool blockExists = std::binary_search(blocksBegin, blocksEnd, blockRef, blockComparer);
	auto blockIterator = std::lower_bound(blocksBegin, blocksEnd, blockRef, blockComparer);

	assert(blockExists);
	assert(blockIterator != blocksEnd);
	assert(blockIterator->key.crc == blockChecksum);
	assert(blockIterator->key.begin == m_begin);
	assert(blockIterator->key.end == m_end);

	m_function = reinterpret_cast<void (*)(void*)>(blockIterator->fct);

#endif

#ifdef AOT_BUILD_CACHE
	{
		std::lock_guard<std::mutex> lock(m_aotBlockOutputStreamMutex);

		m_aotBlockOutputStream->Write32(blockChecksum);
		m_aotBlockOutputStream->Write32(m_begin);
		m_aotBlockOutputStream->Write32(m_end);
		m_aotBlockOutputStream->Write(blockData, blockSize * 4);
	}
#endif
}

void CBasicBlock::CompileRange(CMipsJitter* jitter)
{
	for(uint32 address = m_begin; address <= m_end; address += 4)
	{
		m_context.m_pArch->CompileInstruction(
			address,
			jitter,
			&m_context);
		//Sanity check
		assert(jitter->IsStackEmpty());
	}
}

unsigned int CBasicBlock::Execute()
{
	m_function(&m_context);

	if(m_context.m_State.nDelayedJumpAddr != MIPS_INVALID_PC)
	{
		m_context.m_State.nPC = m_context.m_State.nDelayedJumpAddr;
		m_context.m_State.nDelayedJumpAddr = MIPS_INVALID_PC;
	}
	else
	{
		m_context.m_State.nPC = m_end + 4;
	}

	assert((m_context.m_State.nGPR[CMIPS::RA].nV0 & 3) == 0);
	assert(m_context.m_State.nCOP2[0].nV0 == 0x00000000);
	assert(m_context.m_State.nCOP2[0].nV1 == 0x00000000);
	assert(m_context.m_State.nCOP2[0].nV2 == 0x00000000);
	assert(m_context.m_State.nCOP2[0].nV3 == 0x3F800000);

	return ((m_end - m_begin) / 4) + 1;
}

uint32 CBasicBlock::GetBeginAddress() const
{
	return m_begin;
}

uint32 CBasicBlock::GetEndAddress() const
{
	return m_end;
}

bool CBasicBlock::IsCompiled() const
{
#ifndef AOT_USE_CACHE
	return !m_function.IsEmpty();
#else
	return (m_function != nullptr);
#endif
}

unsigned int CBasicBlock::GetSelfLoopCount() const
{
	return m_selfLoopCount;
}

void CBasicBlock::SetSelfLoopCount(unsigned int selfLoopCount)
{
	m_selfLoopCount = selfLoopCount;
}
<commit_msg>Added check to make sure R0 isn't trashed.<commit_after>#include "BasicBlock.h"
#include "MemStream.h"
#include "offsetof_def.h"
#include "MipsJitter.h"
#include "Jitter_CodeGenFactory.h"

#if defined(AOT_BUILD_CACHE) || defined(AOT_USE_CACHE)
#define AOT_ENABLED
#endif

#ifdef AOT_ENABLED

#include <zlib.h>
#include "StdStream.h"
#include "StdStreamUtils.h"

#endif

#ifdef VTUNE_ENABLED
#include <jitprofiling.h>
#include "string_format.h"
#endif

#ifdef AOT_USE_CACHE

struct AOT_BLOCK
{
	AOT_BLOCK_KEY	key;
	void*			fct;
};

extern "C" AOT_BLOCK	_aot_firstBlock;
extern "C" uint32		_aot_blockCount;

#endif

CBasicBlock::CBasicBlock(CMIPS& context, uint32 begin, uint32 end)
: m_begin(begin)
, m_end(end)
, m_context(context)
, m_selfLoopCount(0)
#ifdef AOT_USE_CACHE
, m_function(nullptr)
#endif
{
	assert(m_end >= m_begin);
}

CBasicBlock::~CBasicBlock()
{

}

#ifdef AOT_BUILD_CACHE

Framework::CStdStream*	CBasicBlock::m_aotBlockOutputStream(nullptr);
std::mutex				CBasicBlock::m_aotBlockOutputStreamMutex;

void CBasicBlock::SetAotBlockOutputStream(Framework::CStdStream* outputStream)
{
	assert(m_aotBlockOutputStream == nullptr || outputStream == nullptr);
	m_aotBlockOutputStream = outputStream;
}

#endif

void CBasicBlock::Compile()
{
#ifndef AOT_USE_CACHE

	Framework::CMemStream stream;
	{
		static __declspec(thread) CMipsJitter* jitter = NULL;
		if(jitter == NULL)
		{
			Jitter::CCodeGen* codeGen = Jitter::CreateCodeGen();
			jitter = new CMipsJitter(codeGen);

			for(unsigned int i = 0; i < 4; i++)
			{
				jitter->SetVariableAsConstant(
					offsetof(CMIPS, m_State.nGPR[CMIPS::R0].nV[i]),
					0
					);
			}
		}

		jitter->SetStream(&stream);
		jitter->Begin();
		CompileRange(jitter);
//		codeGen.DumpVariables(0);
//		codeGen.EndQuota();
		jitter->End();
	}

	m_function = CMemoryFunction(stream.GetBuffer(), stream.GetSize());

#ifdef VTUNE_ENABLED
	if(iJIT_IsProfilingActive() == iJIT_SAMPLING_ON)
	{
		iJIT_Method_Load jmethod = {};
		jmethod.method_id = iJIT_GetNewMethodID();
		jmethod.class_file_name = "";
		jmethod.source_file_name = __FILE__;

		jmethod.method_load_address = m_function.GetCode();
		jmethod.method_size = m_function.GetSize();
		jmethod.line_number_size = 0;

		auto functionName = string_format("BasicBlock_0x%0.8X_0x%0.8X", m_begin, m_end);

		jmethod.method_name = const_cast<char*>(functionName.c_str());
		iJIT_NotifyEvent(iJVM_EVENT_TYPE_METHOD_LOAD_FINISHED, reinterpret_cast<void*>(&jmethod));
	}
#endif

#endif

#ifdef AOT_ENABLED

	size_t blockSize = ((m_end - m_begin) / 4) + 1;
	auto blockData = new uint32[blockSize];

	for(uint32 i = 0; i < blockSize; i++)
	{
		blockData[i] = m_context.m_pMemoryMap->GetWord(m_begin + (i * 4));
	}

	uint32 blockChecksum = crc32(0, reinterpret_cast<Bytef*>(blockData), blockSize * 4);

#endif

#ifdef AOT_USE_CACHE

	AOT_BLOCK* blocksBegin = &_aot_firstBlock;
	AOT_BLOCK* blocksEnd = blocksBegin + _aot_blockCount;

	AOT_BLOCK blockRef = { blockChecksum, m_begin, m_end, nullptr };

	static const auto blockComparer =
		[] (const AOT_BLOCK& item1, const AOT_BLOCK& item2)
		{
			return item1.key < item2.key;
		};

//	assert(std::is_sorted(blocksBegin, blocksEnd, blockComparer));

	bool blockExists = std::binary_search(blocksBegin, blocksEnd, blockRef, blockComparer);
	auto blockIterator = std::lower_bound(blocksBegin, blocksEnd, blockRef, blockComparer);

	assert(blockExists);
	assert(blockIterator != blocksEnd);
	assert(blockIterator->key.crc == blockChecksum);
	assert(blockIterator->key.begin == m_begin);
	assert(blockIterator->key.end == m_end);

	m_function = reinterpret_cast<void (*)(void*)>(blockIterator->fct);

#endif

#ifdef AOT_BUILD_CACHE
	{
		std::lock_guard<std::mutex> lock(m_aotBlockOutputStreamMutex);

		m_aotBlockOutputStream->Write32(blockChecksum);
		m_aotBlockOutputStream->Write32(m_begin);
		m_aotBlockOutputStream->Write32(m_end);
		m_aotBlockOutputStream->Write(blockData, blockSize * 4);
	}
#endif
}

void CBasicBlock::CompileRange(CMipsJitter* jitter)
{
	for(uint32 address = m_begin; address <= m_end; address += 4)
	{
		m_context.m_pArch->CompileInstruction(
			address,
			jitter,
			&m_context);
		//Sanity check
		assert(jitter->IsStackEmpty());
	}
}

unsigned int CBasicBlock::Execute()
{
	m_function(&m_context);

	if(m_context.m_State.nDelayedJumpAddr != MIPS_INVALID_PC)
	{
		m_context.m_State.nPC = m_context.m_State.nDelayedJumpAddr;
		m_context.m_State.nDelayedJumpAddr = MIPS_INVALID_PC;
	}
	else
	{
		m_context.m_State.nPC = m_end + 4;
	}

	assert(m_context.m_State.nGPR[0].nV0 == 0);
	assert(m_context.m_State.nGPR[0].nV1 == 0);
	assert(m_context.m_State.nGPR[0].nV2 == 0);
	assert(m_context.m_State.nGPR[0].nV3 == 0);
	assert((m_context.m_State.nGPR[CMIPS::RA].nV0 & 3) == 0);
	assert(m_context.m_State.nCOP2[0].nV0 == 0x00000000);
	assert(m_context.m_State.nCOP2[0].nV1 == 0x00000000);
	assert(m_context.m_State.nCOP2[0].nV2 == 0x00000000);
	assert(m_context.m_State.nCOP2[0].nV3 == 0x3F800000);

	return ((m_end - m_begin) / 4) + 1;
}

uint32 CBasicBlock::GetBeginAddress() const
{
	return m_begin;
}

uint32 CBasicBlock::GetEndAddress() const
{
	return m_end;
}

bool CBasicBlock::IsCompiled() const
{
#ifndef AOT_USE_CACHE
	return !m_function.IsEmpty();
#else
	return (m_function != nullptr);
#endif
}

unsigned int CBasicBlock::GetSelfLoopCount() const
{
	return m_selfLoopCount;
}

void CBasicBlock::SetSelfLoopCount(unsigned int selfLoopCount)
{
	m_selfLoopCount = selfLoopCount;
}
<|endoftext|>


<commit_before>/*
 * Copyright (C) 2018 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 "src/trace_processor/thread_table.h"

#include "perfetto/base/logging.h"
#include "src/trace_processor/query_constraints.h"
#include "src/trace_processor/sqlite_utils.h"

namespace perfetto {
namespace trace_processor {

namespace {

using namespace sqlite_utils;

}  // namespace

ThreadTable::ThreadTable(sqlite3*, const TraceStorage* storage)
    : storage_(storage) {}

void ThreadTable::RegisterTable(sqlite3* db, const TraceStorage* storage) {
  Table::Register<ThreadTable>(db, storage, "thread");
}

base::Optional<Table::Schema> ThreadTable::Init(int, const char* const*) {
  return Schema(
      {
          Table::Column(Column::kUtid, "utid", ColumnType::kInt),
          Table::Column(Column::kUpid, "upid", ColumnType::kInt),
          Table::Column(Column::kName, "name", ColumnType::kString),
          Table::Column(Column::kTid, "tid", ColumnType::kInt),
      },
      {Column::kUtid});
}

std::unique_ptr<Table::Cursor> ThreadTable::CreateCursor(
    const QueryConstraints& qc,
    sqlite3_value** argv) {
  return std::unique_ptr<Table::Cursor>(new Cursor(storage_, qc, argv));
}

int ThreadTable::BestIndex(const QueryConstraints& qc, BestIndexInfo* info) {
  info->estimated_cost = static_cast<uint32_t>(storage_->thread_count());

  // If the query has a constraint on the |utid| field, return a reduced cost
  // because we can do that filter efficiently.
  const auto& constraints = qc.constraints();
  if (constraints.size() == 1 && constraints.front().iColumn == Column::kUtid) {
    info->estimated_cost = IsOpEq(constraints.front().op) ? 1 : 10;
  }

  return SQLITE_OK;
}

ThreadTable::Cursor::Cursor(const TraceStorage* storage,
                            const QueryConstraints& qc,
                            sqlite3_value** argv)
    : storage_(storage) {
  min = 0;
  max = static_cast<uint32_t>(storage_->thread_count());
  desc = false;
  current = min;
  for (size_t j = 0; j < qc.constraints().size(); j++) {
    const auto& cs = qc.constraints()[j];
    if (cs.iColumn == Column::kUtid) {
      UniqueTid constraint_utid =
          static_cast<UniqueTid>(sqlite3_value_int(argv[j]));
      // Filter the range of utids that we are interested in, based on the
      // constraints in the query. Everything between min and max (inclusive)
      // will be returned.
      if (IsOpEq(cs.op)) {
        min = constraint_utid;
        max = constraint_utid;
      } else if (IsOpGe(cs.op) || IsOpGt(cs.op)) {
        min = IsOpGt(cs.op) ? constraint_utid + 1 : constraint_utid;
      } else if (IsOpLe(cs.op) || IsOpLt(cs.op)) {
        max = IsOpLt(cs.op) ? constraint_utid - 1 : constraint_utid;
      }
    }
  }
  for (const auto& ob : qc.order_by()) {
    if (ob.iColumn == Column::kUtid) {
      desc = ob.desc;
      current = desc ? max : min;
    }
  }
}

int ThreadTable::Cursor::Column(sqlite3_context* context, int N) {
  const auto& thread = storage_->GetThread(current);
  switch (N) {
    case Column::kUtid: {
      sqlite3_result_int64(context, current);
      break;
    }
    case Column::kUpid: {
      sqlite3_result_int64(context, thread.upid.value_or(0));
      break;
    }
    case Column::kName: {
      const auto& name = storage_->GetString(thread.name_id);
      sqlite3_result_text(context, name.c_str(),
                          static_cast<int>(name.length()), kSqliteStatic);
      break;
    }
    case Column::kTid: {
      sqlite3_result_int64(context, thread.tid);
      break;
    }
    default: {
      PERFETTO_FATAL("Unknown column %d", N);
      break;
    }
  }
  return SQLITE_OK;
}

int ThreadTable::Cursor::Next() {
  if (desc) {
    --current;
  } else {
    ++current;
  }
  return SQLITE_OK;
}

int ThreadTable::Cursor::Eof() {
  return desc ? current < min : current > max;
}
}  // namespace trace_processor
}  // namespace perfetto
<commit_msg>trace_processor: fix null vs 0 bug in thread table am: 1aa852a0ca am: b0a6e82b0e am: dbf79fc830<commit_after>/*
 * Copyright (C) 2018 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 "src/trace_processor/thread_table.h"

#include "perfetto/base/logging.h"
#include "src/trace_processor/query_constraints.h"
#include "src/trace_processor/sqlite_utils.h"

namespace perfetto {
namespace trace_processor {

namespace {

using namespace sqlite_utils;

}  // namespace

ThreadTable::ThreadTable(sqlite3*, const TraceStorage* storage)
    : storage_(storage) {}

void ThreadTable::RegisterTable(sqlite3* db, const TraceStorage* storage) {
  Table::Register<ThreadTable>(db, storage, "thread");
}

base::Optional<Table::Schema> ThreadTable::Init(int, const char* const*) {
  return Schema(
      {
          Table::Column(Column::kUtid, "utid", ColumnType::kInt),
          Table::Column(Column::kUpid, "upid", ColumnType::kInt),
          Table::Column(Column::kName, "name", ColumnType::kString),
          Table::Column(Column::kTid, "tid", ColumnType::kInt),
      },
      {Column::kUtid});
}

std::unique_ptr<Table::Cursor> ThreadTable::CreateCursor(
    const QueryConstraints& qc,
    sqlite3_value** argv) {
  return std::unique_ptr<Table::Cursor>(new Cursor(storage_, qc, argv));
}

int ThreadTable::BestIndex(const QueryConstraints& qc, BestIndexInfo* info) {
  info->estimated_cost = static_cast<uint32_t>(storage_->thread_count());

  // If the query has a constraint on the |utid| field, return a reduced cost
  // because we can do that filter efficiently.
  const auto& constraints = qc.constraints();
  if (constraints.size() == 1 && constraints.front().iColumn == Column::kUtid) {
    info->estimated_cost = IsOpEq(constraints.front().op) ? 1 : 10;
  }

  return SQLITE_OK;
}

ThreadTable::Cursor::Cursor(const TraceStorage* storage,
                            const QueryConstraints& qc,
                            sqlite3_value** argv)
    : storage_(storage) {
  min = 0;
  max = static_cast<uint32_t>(storage_->thread_count());
  desc = false;
  current = min;
  for (size_t j = 0; j < qc.constraints().size(); j++) {
    const auto& cs = qc.constraints()[j];
    if (cs.iColumn == Column::kUtid) {
      UniqueTid constraint_utid =
          static_cast<UniqueTid>(sqlite3_value_int(argv[j]));
      // Filter the range of utids that we are interested in, based on the
      // constraints in the query. Everything between min and max (inclusive)
      // will be returned.
      if (IsOpEq(cs.op)) {
        min = constraint_utid;
        max = constraint_utid;
      } else if (IsOpGe(cs.op) || IsOpGt(cs.op)) {
        min = IsOpGt(cs.op) ? constraint_utid + 1 : constraint_utid;
      } else if (IsOpLe(cs.op) || IsOpLt(cs.op)) {
        max = IsOpLt(cs.op) ? constraint_utid - 1 : constraint_utid;
      }
    }
  }
  for (const auto& ob : qc.order_by()) {
    if (ob.iColumn == Column::kUtid) {
      desc = ob.desc;
      current = desc ? max : min;
    }
  }
}

int ThreadTable::Cursor::Column(sqlite3_context* context, int N) {
  const auto& thread = storage_->GetThread(current);
  switch (N) {
    case Column::kUtid: {
      sqlite3_result_int64(context, current);
      break;
    }
    case Column::kUpid: {
      if (thread.upid.has_value()) {
        sqlite3_result_int64(context, thread.upid.value());
      } else {
        sqlite3_result_null(context);
      }
      break;
    }
    case Column::kName: {
      const auto& name = storage_->GetString(thread.name_id);
      sqlite3_result_text(context, name.c_str(),
                          static_cast<int>(name.length()), kSqliteStatic);
      break;
    }
    case Column::kTid: {
      sqlite3_result_int64(context, thread.tid);
      break;
    }
    default: {
      PERFETTO_FATAL("Unknown column %d", N);
      break;
    }
  }
  return SQLITE_OK;
}

int ThreadTable::Cursor::Next() {
  if (desc) {
    --current;
  } else {
    ++current;
  }
  return SQLITE_OK;
}

int ThreadTable::Cursor::Eof() {
  return desc ? current < min : current > max;
}
}  // namespace trace_processor
}  // namespace perfetto
<|endoftext|>


<commit_before>#include "being.h"
#include "parse.h"
#include "obj.h"

int blackSun(TBeing *vict, cmdTypeT cmd, const char *arg, TObj *o, TObj *)
{
  affectedData aff;
  TBeing *ch;

  if(cmd != CMD_GENERIC_PULSE)
    return FALSE;

  if (!(ch = dynamic_cast<TBeing *>(o->equippedBy)))
    return FALSE;

  if(::number(0,99))
    return FALSE;

  aff.type = SPELL_PLASMA_MIRROR;
  aff.duration = Pulse::UPDATES_PER_MUDHOUR/4;
  aff.modifier = 0;
  aff.location = APPLY_NONE;
  aff.bitvector = 0;
  aff.level = 40;

  colorAct(COLOR_SPELLS, "<k>Ancient visions of a dark land overcome you.<1>",
	   FALSE, ch, NULL, 0, TO_CHAR);
  colorAct(COLOR_SPELLS, "<k>A black sun grows unbearably <1><Y>hot<1><k> and <1><r>burns<1><k> your flesh.<1>",
	   FALSE, ch, NULL, 0, TO_CHAR);
  colorAct(COLOR_SPELLS, "<k>You snap back to reality gasping for breath, as a swirling shield of plasma surround you.<1>",
	   FALSE, ch, NULL, 0, TO_CHAR);

  colorAct(COLOR_SPELLS, "<k>$n looks momentarily startled as a swirling shield of plasma surrounds $m.<1>",
	   FALSE, ch, NULL, 0, TO_ROOM);

  ch->affectJoin(ch, &aff, AVG_DUR_NO, AVG_EFF_YES);

  return TRUE;
}
<commit_msg>Update spec_objs_black_sun.cc<commit_after>#include "being.h"
#include "parse.h"
#include "obj.h"

int blackSun(TBeing *vict, cmdTypeT cmd, const char *arg, TObj *o, TObj *)
{
  affectedData aff;
  TBeing *ch;

  if(cmd != CMD_GENERIC_PULSE)
    return FALSE;

  if (!(ch = dynamic_cast<TBeing *>(o->equippedBy)))
    return FALSE;

  if(::number(0,99))
    return FALSE;

  aff.type = SPELL_PLASMA_MIRROR;
  aff.duration = Pulse::UPDATES_PER_MUDHOUR*2;
  aff.modifier = 0;
  aff.location = APPLY_NONE;
  aff.bitvector = 0;
  aff.level = 40;

  colorAct(COLOR_SPELLS, "<k>Ancient visions of a dark land overcome you.<1>",
	   FALSE, ch, NULL, 0, TO_CHAR);
  colorAct(COLOR_SPELLS, "<k>A black sun grows unbearably <1><Y>hot<1><k> and <1><r>burns<1><k> your flesh.<1>",
	   FALSE, ch, NULL, 0, TO_CHAR);
  colorAct(COLOR_SPELLS, "<k>You snap back to reality gasping for breath, as a swirling shield of plasma surround you.<1>",
	   FALSE, ch, NULL, 0, TO_CHAR);

  colorAct(COLOR_SPELLS, "<k>$n looks momentarily startled as a swirling shield of plasma surrounds $m.<1>",
	   FALSE, ch, NULL, 0, TO_ROOM);

  ch->affectJoin(ch, &aff, AVG_DUR_NO, AVG_EFF_YES);

  return TRUE;
}
<|endoftext|>


<commit_before>/*
 *	Copyright 2014 David Moreno Montero <dmoreno@coralbits.com>
 *
 *	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.
 */

#pragma once
#include <string>
#include <vector>
#include <boost/concept_check.hpp>
#include "underscore.hpp"

namespace underscore{
	class string;

	typedef ::underscore::underscore<std::vector<string>> string_list;
	typedef std::vector<string> std_string_list;

	class string{
		std::string _str;

		ssize_t _wrap_position(ssize_t p) const{
			ssize_t s=size();
			if (p>s)
				return s;
			if (p<0){
				p=s+p;
				if (p<0)
					return 0;
				return p;
			}
			return p;
		}
	public:

		string(std::string &&str) : _str(std::move(str)){};
		string(const std::string &str) : _str(str){};
		string(const char *str) : _str(str){};
		template<typename T> string(const T &v) : _str(std::to_string(v)){};
		string() : _str(){};

		string_list split(const char &sep=',', bool insert_empty_elements=false) const {
			std_string_list v;
			std::string el;

			std::string::const_iterator I=_str.begin(), endI=_str.end();
			std::string::const_iterator p;
			do{
				p=std::find(I, endI, sep);

				el=std::string(I, p);
				if (insert_empty_elements || !el.empty())
					v.push_back(std::move(el));
				I=p+1;
			}while(p!=endI);

			return string_list(std::move(v));
		}

		string_list split(const std::string &sep, bool insert_empty_elements=false) const {
			std_string_list v;
			std::string el;

			auto I=_str.begin(), endI=_str.end(), sepBegin=sep.begin(), sepEnd=sep.end();
			std::string::const_iterator p;

			do{
				p=std::search(I, endI, sepBegin, sepEnd);

				el=std::string(I, p);
				if (insert_empty_elements || !el.empty())
					v.push_back(el);
				I=p+sep.size();
			}while(p!=endI);

			return string_list(std::move(v));
		}

		string lower() const{
			std::string ret;
			ret.reserve(_str.size());
			for (auto c: _str)
				ret.push_back(::tolower(c));
			return string(std::move(ret));
		};
		string upper() const{
			std::string ret;
			ret.reserve(_str.size());
			for (auto c: _str)
				ret.push_back(::toupper(c));
			return string(std::move(ret));
		};

		bool startswith(const std::string &starting) const {
			if (_str.size()<starting.size())
				return false;
			return (_str.substr(0,starting.size())==starting);
		}

		bool endswith(const std::string &ending) const {
			if (_str.size()<ending.size())
				return false;
			return (_str.substr(_str.size()-ending.size())==ending);
		}
		bool contains(const std::string &substr) const {
			return _str.find(substr)!=std::string::npos;
		}

		string replace(const std::string &orig, const std::string &replace_with) const{
			std::string ret=_str;
			size_t pos = 0;
			size_t orig_length = orig.length();
			size_t replace_with_length = replace_with.length();
			while((pos = ret.find(orig, pos)) != std::string::npos)
			{
				ret.replace(pos, orig_length, replace_with);
				pos += replace_with_length;
			}
			return ret;
		}

		/**
		 * @short Removes all spaces, new lines and tabs from begining and end.
		 */
		string strip() const{
			auto begin=_str.find_first_not_of(" \n\t");
			auto end=_str.find_last_not_of(" \n\t");
			return slice(begin, end+1);
		}

		operator std::string() const{
			return _str;
		}

		size_t size() const {
			return _str.size();
		}

		size_t length() const{
			return size();
		}

		bool empty() const{
			return _str.empty();
		}

		const char *c_str() const{
			return _str.c_str();
		}

		/**
		 * @short Returns the index of the first ocurrence of that char, or -1.
		 */
		ssize_t index(char c) const{
			auto p=_str.find(c);
			if (p==std::string::npos)
				return -1;
			return p;
		}
		ssize_t index(const std::string &s) const{
			auto p=_str.find(s);
			if (p==std::string::npos)
				return -1;
			return p;
		}

		ssize_t rindex(char c, ssize_t start=0, ssize_t end=std::numeric_limits<ssize_t>::max()) const{
			start=_wrap_position(start); end=_wrap_position(end);
			for(int i=end;i>=start;--i)
				if (_str[i]==c)
					return i;
				return -1;
		}

		ssize_t rindex(const std::string &s, ssize_t start=0, ssize_t end=std::numeric_limits<ssize_t>::max()) const{
			start=_wrap_position(start); end=_wrap_position(end);
			auto p=slice(start,end)._str.rfind(s);
			if (p==std::string::npos)
				return -1;
			return start+p;
		}

		string slice(ssize_t start, ssize_t end=std::numeric_limits<ssize_t>::max()) const{
			start=_wrap_position(start);
			end=_wrap_position(end);
			if (end<start)
				return string();
			ssize_t s=size();
			if (start==0 && end==s)
				return *this;
			return _str.substr(start, end-start);
		}

		string format(const string &a){
			return format({a});
		}
		string format(const string &a, const string &b){
			return format({a,b});
		}
		string format(const string &a, const string &b, const string &c){
			return format({a,b,c});
		}
		string format(const string &a, const string &b, const string &c, const string &d){
			return format({a,b,c,d});
		}

		string format(std::initializer_list<string> &&str_list){
			auto ulist=string_list(str_list);
// 			std::cout<<"as ulist "<<ulist.join(", ")<<std::endl;
			return format(ulist);
		}

		class invalid_format : public std::exception{
		public:
			const char *what() const throw(){ return "Invalid string format"; };
		};
		class invalid_format_require_more_arguments : public invalid_format{
		public:
			const char *what() const throw(){ return "Invalid string format, requires more arguments."; };
		};
		class invalid_format_too_many_arguments : public invalid_format{
		public:
			const char *what() const throw(){ return "Invalid string format, it has too many arguments."; };
		};

		string format(const string_list &sl){
			std::string ret;
			auto res=size() + sl.reduce<size_t>([](const string &str, size_t s){ return s+str.size(); }, 0);
// 			std::cout<<"reserve "<<res<<std::endl;
			ret.reserve(res);

			signed long n=0;
			signed long sl_size=sl.size();
			for (auto &part: split("{}", true)){
				ret+=part;
				if (n<sl_size){
					ret+=sl[n];
				}
				else if (n>sl_size){
					throw invalid_format_require_more_arguments();
				}
				// else is just enought aguments, so ok.
				n++;
// 				std::cout<<"format "<<ret<<std::endl;
			}
			if (n<=sl_size){
				throw invalid_format_too_many_arguments();
			}
			return ret;
		}

		long to_long() const {
			size_t n;
			long l=stol(_str, &n);
			if (n!=_str.size())
				throw std::invalid_argument(_str);
			return l;
		}
		double to_double() const {
			size_t n;
			double f=stod(_str, &n);
			if (n!=_str.size())
				throw std::invalid_argument(_str);
			return f;
		}
		float to_float() const {
			size_t n;
			float f=stof(_str, &n);
			if (n!=_str.size())
				throw std::invalid_argument(_str);
			return f;
		}

		friend std::ostream& operator <<(std::ostream &output, const string &str) {
			output << "" << str._str;
			return output;
		}

		bool operator==(const std::string &str){
			return _str==str;
		}
	};

	inline bool operator==(const std::string &a, const string &b){
		return b==a;
	}
	inline bool operator<(const string &a, const string &b){
		return std::string(a)<std::string(b);
	}

	inline string operator+(const string &a, const string &b){
		return std::string(a)+std::string(b);
	}

	inline string _(std::string &&s){
		return string(std::move(s));
	}
	inline string _(const char *s){
		return string(std::string(s));
	}

};<commit_msg>Added fast and slow methods for string index. One for full string, other for part of it.<commit_after>/*
 *	Copyright 2014 David Moreno Montero <dmoreno@coralbits.com>
 *
 *	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.
 */

#pragma once
#include <string>
#include <vector>
#include <boost/concept_check.hpp>
#include "underscore.hpp"

namespace underscore{
	class string;

	typedef ::underscore::underscore<std::vector<string>> string_list;
	typedef std::vector<string> std_string_list;

	class string{
		std::string _str;

		ssize_t _wrap_position(ssize_t p) const{
			ssize_t s=size();
			if (p>s)
				return s;
			if (p<0){
				p=s+p;
				if (p<0)
					return 0;
				return p;
			}
			return p;
		}
	public:

		string(std::string &&str) : _str(std::move(str)){};
		string(const std::string &str) : _str(str){};
		string(const char *str) : _str(str){};
		template<typename T> string(const T &v) : _str(std::to_string(v)){};
		string() : _str(){};

		string_list split(const char &sep=',', bool insert_empty_elements=false) const {
			std_string_list v;
			std::string el;

			std::string::const_iterator I=_str.begin(), endI=_str.end();
			std::string::const_iterator p;
			do{
				p=std::find(I, endI, sep);

				el=std::string(I, p);
				if (insert_empty_elements || !el.empty())
					v.push_back(std::move(el));
				I=p+1;
			}while(p!=endI);

			return string_list(std::move(v));
		}

		string_list split(const std::string &sep, bool insert_empty_elements=false) const {
			std_string_list v;
			std::string el;

			auto I=_str.begin(), endI=_str.end(), sepBegin=sep.begin(), sepEnd=sep.end();
			std::string::const_iterator p;

			do{
				p=std::search(I, endI, sepBegin, sepEnd);

				el=std::string(I, p);
				if (insert_empty_elements || !el.empty())
					v.push_back(el);
				I=p+sep.size();
			}while(p!=endI);

			return string_list(std::move(v));
		}

		string lower() const{
			std::string ret;
			ret.reserve(_str.size());
			for (auto c: _str)
				ret.push_back(::tolower(c));
			return string(std::move(ret));
		};
		string upper() const{
			std::string ret;
			ret.reserve(_str.size());
			for (auto c: _str)
				ret.push_back(::toupper(c));
			return string(std::move(ret));
		};

		bool startswith(const std::string &starting) const {
			if (_str.size()<starting.size())
				return false;
			return (_str.substr(0,starting.size())==starting);
		}

		bool endswith(const std::string &ending) const {
			if (_str.size()<ending.size())
				return false;
			return (_str.substr(_str.size()-ending.size())==ending);
		}
		bool contains(const std::string &substr) const {
			return _str.find(substr)!=std::string::npos;
		}

		string replace(const std::string &orig, const std::string &replace_with) const{
			std::string ret=_str;
			size_t pos = 0;
			size_t orig_length = orig.length();
			size_t replace_with_length = replace_with.length();
			while((pos = ret.find(orig, pos)) != std::string::npos)
			{
				ret.replace(pos, orig_length, replace_with);
				pos += replace_with_length;
			}
			return ret;
		}

		/**
		 * @short Removes all spaces, new lines and tabs from begining and end.
		 */
		string strip() const{
			auto begin=_str.find_first_not_of(" \n\t");
			auto end=_str.find_last_not_of(" \n\t");
			return slice(begin, end+1);
		}

		operator std::string() const{
			return _str;
		}

		size_t size() const {
			return _str.size();
		}

		size_t length() const{
			return size();
		}

		bool empty() const{
			return _str.empty();
		}

		const char *c_str() const{
			return _str.c_str();
		}

		/**
		 * @short Returns the index of the first ocurrence of that char, or -1.
		 */
		ssize_t index(char c) const{
			auto p=_str.find(c);
			if (p==std::string::npos)
				return -1;
			return p;
		}
		ssize_t index(char c, ssize_t start, ssize_t end=std::numeric_limits<ssize_t>::max()) const{
			start=_wrap_position(start); end=_wrap_position(end);
			return slice(start, end).index(c) + start;
		}

		ssize_t index(const std::string &s) const{
			auto p=_str.find(s);
			if (p==std::string::npos)
				return -1;
			return p;
		}
		ssize_t index(const std::string &s, ssize_t start, ssize_t end=std::numeric_limits<ssize_t>::max()) const{
			start=_wrap_position(start); end=_wrap_position(end);
			return slice(start, end).index(s) + start;
		}

		ssize_t rindex(char c, ssize_t start, ssize_t end=std::numeric_limits<ssize_t>::max()) const{
			start=_wrap_position(start); end=_wrap_position(end);
			for(int i=end;i>=start;--i)
				if (_str[i]==c)
					return i;
			return -1;
		}
		ssize_t rindex(char c) const{
			auto p=_str.rfind(c);
			if (p==std::string::npos)
				return -1;
			return p;
		}

		ssize_t rindex(const std::string &s, ssize_t start, ssize_t end=std::numeric_limits<ssize_t>::max()) const{
			start=_wrap_position(start); end=_wrap_position(end);
			return slice(start,end).rindex(s);
		}
		ssize_t rindex(const std::string &s) const{
			auto p=_str.rfind(s);
			if (p==std::string::npos)
				return -1;
			return p;
		}

		string slice(ssize_t start, ssize_t end=std::numeric_limits<ssize_t>::max()) const{
			start=_wrap_position(start);
			end=_wrap_position(end);
			if (end<start)
				return string();
			ssize_t s=size();
			if (start==0 && end==s)
				return *this;
			return _str.substr(start, end-start);
		}

		string format(const string &a){
			return format({a});
		}
		string format(const string &a, const string &b){
			return format({a,b});
		}
		string format(const string &a, const string &b, const string &c){
			return format({a,b,c});
		}
		string format(const string &a, const string &b, const string &c, const string &d){
			return format({a,b,c,d});
		}

		string format(std::initializer_list<string> &&str_list){
			auto ulist=string_list(str_list);
// 			std::cout<<"as ulist "<<ulist.join(", ")<<std::endl;
			return format(ulist);
		}

		class invalid_format : public std::exception{
		public:
			const char *what() const throw(){ return "Invalid string format"; };
		};
		class invalid_format_require_more_arguments : public invalid_format{
		public:
			const char *what() const throw(){ return "Invalid string format, requires more arguments."; };
		};
		class invalid_format_too_many_arguments : public invalid_format{
		public:
			const char *what() const throw(){ return "Invalid string format, it has too many arguments."; };
		};

		string format(const string_list &sl){
			std::string ret;
			auto res=size() + sl.reduce<size_t>([](const string &str, size_t s){ return s+str.size(); }, 0);
// 			std::cout<<"reserve "<<res<<std::endl;
			ret.reserve(res);

			signed long n=0;
			signed long sl_size=sl.size();
			for (auto &part: split("{}", true)){
				ret+=part;
				if (n<sl_size){
					ret+=sl[n];
				}
				else if (n>sl_size){
					throw invalid_format_require_more_arguments();
				}
				// else is just enought aguments, so ok.
				n++;
// 				std::cout<<"format "<<ret<<std::endl;
			}
			if (n<=sl_size){
				throw invalid_format_too_many_arguments();
			}
			return ret;
		}

		long to_long() const {
			size_t n;
			long l=stol(_str, &n);
			if (n!=_str.size())
				throw std::invalid_argument(_str);
			return l;
		}
		double to_double() const {
			size_t n;
			double f=stod(_str, &n);
			if (n!=_str.size())
				throw std::invalid_argument(_str);
			return f;
		}
		float to_float() const {
			size_t n;
			float f=stof(_str, &n);
			if (n!=_str.size())
				throw std::invalid_argument(_str);
			return f;
		}

		friend std::ostream& operator <<(std::ostream &output, const string &str) {
			output << "" << str._str;
			return output;
		}

		bool operator==(const std::string &str){
			return _str==str;
		}
	};

	inline bool operator==(const std::string &a, const string &b){
		return b==a;
	}
	inline bool operator<(const string &a, const string &b){
		return std::string(a)<std::string(b);
	}

	inline string operator+(const string &a, const string &b){
		return std::string(a)+std::string(b);
	}

	inline string _(std::string &&s){
		return string(std::move(s));
	}
	inline string _(const char *s){
		return string(std::string(s));
	}

};<|endoftext|>


<commit_before>/*
// $Id$
// Fennel is a library of data storage and processing components.
// Copyright (C) 2006-2006 The Eigenbase Project
// Copyright (C) 2006-2006 Disruptive Tech
// Copyright (C) 2006-2006 LucidEra, Inc.
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your option)
// any later version approved by The Eigenbase Project.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include "fennel/common/CommonPreamble.h"
#include "fennel/exec/ExecStreamBufAccessor.h"
#include "fennel/exec/ExecStreamGraph.h"
#include "fennel/farrago/JavaTransformExecStream.h"
#include "fennel/farrago/JniUtil.h"

FENNEL_BEGIN_CPPFILE("$Id$");

JavaTransformExecStreamParams::JavaTransformExecStreamParams()
{
    outputTupleFormat = TUPLE_FORMAT_STANDARD;
    javaClassName = "";
}

JavaTransformExecStream::JavaTransformExecStream()
{
    pStreamGraphHandle = NULL;
    outputByteBuffer = NULL;
    farragoTransform = NULL;
}

void JavaTransformExecStream::setInputBufAccessors(
    std::vector<SharedExecStreamBufAccessor> const &inAccessorsInit)
{
    inAccessors = inAccessorsInit;
}

void JavaTransformExecStream::setOutputBufAccessors(
    std::vector<SharedExecStreamBufAccessor> const &outAccessors)
{
    assert(outAccessors.size() <= 1);

    if (outAccessors.size() > 0) {
        pOutAccessor = outAccessors[0];
    }
}

void JavaTransformExecStream::prepare(
    JavaTransformExecStreamParams const &params)
{
    ExecStream::prepare(params);

    if (pOutAccessor) {
        assert(pOutAccessor->getProvision() == getOutputBufProvision());
        if (pOutAccessor->getTupleDesc().empty()) {
            assert(!params.outputTupleDesc.empty());
            pOutAccessor->setTupleShape(
                params.outputTupleDesc,
                params.outputTupleFormat);
        }
    }

    for (uint i = 0; i < inAccessors.size(); ++i) {
        assert(inAccessors[i]->getProvision() == getInputBufProvision());
    }

    JniEnvAutoRef pEnv;

    farragoTransformClassName = params.javaClassName;
    pStreamGraphHandle = params.pStreamGraphHandle;

    // TODO: SWZ: 3/17/06: Avoid allocating scratch space when there's
    // no output accessor.  Also need to change getResourceRequirements.
    scratchAccessor = params.scratchAccessor;
    bufferLock.accessSegment(scratchAccessor);
}

void JavaTransformExecStream::getResourceRequirements(
    ExecStreamResourceQuantity &minQuantity,
    ExecStreamResourceQuantity &optQuantity)
{
    ExecStream::getResourceRequirements(minQuantity,optQuantity);

    // one page for scratch buffer
    minQuantity.nCachePages += 1;
    optQuantity = minQuantity;
}

void JavaTransformExecStream::open(bool restart)
{
    FENNEL_TRACE(TRACE_FINER, "open" << (restart? " (restart)" : ""));

    ExecStream::open(restart);

    JniEnvAutoRef pEnv;

    if (restart) {
        if (pOutAccessor) {
            pOutAccessor->clear();
        }

        // restart inputs
        for (uint i = 0; i < inAccessors.size(); ++i) {
            inAccessors[i]->clear();
            pGraph->getStreamInput(getStreamId(),i)->open(true);
        }

        assert(farragoTransform);

        pEnv->CallVoidMethod(
            farragoTransform,
            JniUtil::methFarragoTransformRestart,
            NULL);
        return;
    }

    FENNEL_TRACE(
        TRACE_FINER,
        "java class name: " << farragoTransformClassName.c_str());

    // Need to use a call on the FarragoRuntimeContext to get the
    // class (we need the right class loader).

    jstring javaClassName =
        pEnv->NewStringUTF(farragoTransformClassName.c_str());

    // net.sf.farrago.runtime.FarragoTransform implementation (can't be done
    // in JniUtil because it's different for each transform)
    jclass classFarragoTransform =
        reinterpret_cast<jclass>(
            pEnv->CallObjectMethod(
                pStreamGraphHandle->javaRuntimeContext,
                JniUtil::methFarragoRuntimeContextStatementClassForName,
                javaClassName));
    assert(classFarragoTransform);

    // FarragoTransform implementation constructor
    jmethodID methFarragoTransformCons =
        pEnv->GetMethodID(classFarragoTransform, "<init>", "()V");
    assert(methFarragoTransformCons);

    // initialize parameters for FarragoTransform.init()
    jobjectArray inputBindingArray = NULL;

    if (inAccessors.size() > 0) {
        inputBindingArray =
            pEnv->NewObjectArray(
                inAccessors.size(),
                JniUtil::classFarragoTransformInputBinding,
                NULL);

        ExecStreamGraph &streamGraph = getGraph();

        for(uint ordinal = 0; ordinal < inAccessors.size(); ordinal++) {
            std::string inputStreamName =
                streamGraph.getStreamInput(getStreamId(), ordinal)->getName();

            jstring jInputStreamName =
                pEnv->NewStringUTF(inputStreamName.c_str());
            jint jOrdinal = static_cast<jint>(ordinal);

            jobject inputBinding =
                pEnv->NewObject(
                    JniUtil::classFarragoTransformInputBinding,
                    JniUtil::methFarragoTransformInputBindingCons,
                    jInputStreamName,
                    jOrdinal);
            assert(inputBinding);

            pEnv->SetObjectArrayElement(
                inputBindingArray, jOrdinal, inputBinding);
        }
    }

    // Create FarragoTransform instance and initialize it
    jobject xformRef =
        pEnv->NewObject(classFarragoTransform, methFarragoTransformCons);
    assert(xformRef);

    farragoTransform = pEnv->NewGlobalRef(xformRef);
    assert(farragoTransform);

    const std::string &streamName = getName();

    jstring javaStreamName = pEnv->NewStringUTF(streamName.c_str());

    pEnv->CallVoidMethod(
        farragoTransform,
        JniUtil::methFarragoTransformInit,
        pStreamGraphHandle->javaRuntimeContext,
        javaStreamName,
        inputBindingArray);

    // Allocate output buffer.
    bufferLock.allocatePage();
    outputByteBuffer = pEnv->NewDirectByteBuffer(
        bufferLock.getPage().getWritableData(),
        bufferLock.getPage().getCache().getPageSize());
    outputByteBuffer = pEnv->NewGlobalRef(outputByteBuffer);
    FENNEL_TRACE(
        TRACE_FINER, "allocated 1 java ByteBuffer " << outputByteBuffer);
    assert(outputByteBuffer);
}

ExecStreamResult JavaTransformExecStream::execute(
    ExecStreamQuantum const &quantum)
{
    FENNEL_TRACE(TRACE_FINEST, "execute");

    if (pOutAccessor) {
        switch(pOutAccessor->getState()) {
        case EXECBUF_NONEMPTY:
        case EXECBUF_OVERFLOW:
            FENNEL_TRACE(TRACE_FINEST, "overflow");
            return EXECRC_BUF_OVERFLOW;
        case EXECBUF_EOS:
            FENNEL_TRACE(TRACE_FINEST, "eos");
            return EXECRC_EOS;
        default:
            break;
        }
    }

    for (uint i = 0; i < inAccessors.size(); ++i) {
        SharedExecStreamBufAccessor inAccessor = inAccessors[i];

        // Request production on empty inputs.
        if (inAccessor->getState() == EXECBUF_EMPTY) {
            inAccessor->requestProduction();
        }
    }

    jlong jquantum = static_cast<jlong>(quantum.nTuplesMax);

    JniEnvAutoRef pEnv;
    assert(farragoTransform);
    int cb = pEnv->CallIntMethod(
        farragoTransform,
        JniUtil::methFarragoTransformExecute,
        outputByteBuffer,
        jquantum);

    FENNEL_TRACE(TRACE_FINER, "read " << cb << " bytes");

    if (cb > 0) {
        assert(pOutAccessor);
        pOutAccessor->provideBufferForConsumption(
            bufferLock.getPage().getWritableData(),
            bufferLock.getPage().getWritableData() + cb);

        FENNEL_TRACE(TRACE_FINER, "write overflow");
        return EXECRC_BUF_OVERFLOW;
    } else if (cb < 0) {
        FENNEL_TRACE(TRACE_FINEST, "underflow");
        return EXECRC_BUF_UNDERFLOW;
    } else {
        FENNEL_TRACE(TRACE_FINEST, "marking EOS");

        if (pOutAccessor) {
            pOutAccessor->markEOS();
        }
        return EXECRC_EOS;
    }
}

void JavaTransformExecStream::closeImpl()
{
    JniEnvAutoRef pEnv;

    // REVIEW: SWZ: 3/8/2006: Call closeAllocation on farragoTransform?

    if (farragoTransform) {
        pEnv->DeleteGlobalRef(farragoTransform);
        farragoTransform = NULL;
    }

    if (outputByteBuffer) {
        pEnv->DeleteGlobalRef(outputByteBuffer);
        outputByteBuffer = NULL;
    }

    bufferLock.unlock();

    ExecStream::closeImpl();
}

ExecStreamBufProvision JavaTransformExecStream::getInputBufProvision() const
{
    return BUFPROV_PRODUCER;
}

ExecStreamBufProvision JavaTransformExecStream::getOutputBufProvision() const
{
    return BUFPROV_PRODUCER;
}

FENNEL_END_CPPFILE("$Id$");

// End JavaTransformExecStream.cpp
<commit_msg>FENNEL: clearer tracing from JavaTransformExecStream.<commit_after>/*
// $Id$
// Fennel is a library of data storage and processing components.
// Copyright (C) 2006-2006 The Eigenbase Project
// Copyright (C) 2006-2006 Disruptive Tech
// Copyright (C) 2006-2006 LucidEra, Inc.
//
// This program is free software; you can redistribute it and/or modify it
// under the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 of the License, or (at your option)
// any later version approved by The Eigenbase Project.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include "fennel/common/CommonPreamble.h"
#include "fennel/exec/ExecStreamBufAccessor.h"
#include "fennel/exec/ExecStreamGraph.h"
#include "fennel/farrago/JavaTransformExecStream.h"
#include "fennel/farrago/JniUtil.h"

FENNEL_BEGIN_CPPFILE("$Id$");

JavaTransformExecStreamParams::JavaTransformExecStreamParams()
{
    outputTupleFormat = TUPLE_FORMAT_STANDARD;
    javaClassName = "";
}

JavaTransformExecStream::JavaTransformExecStream()
{
    pStreamGraphHandle = NULL;
    outputByteBuffer = NULL;
    farragoTransform = NULL;
}

void JavaTransformExecStream::setInputBufAccessors(
    std::vector<SharedExecStreamBufAccessor> const &inAccessorsInit)
{
    inAccessors = inAccessorsInit;
}

void JavaTransformExecStream::setOutputBufAccessors(
    std::vector<SharedExecStreamBufAccessor> const &outAccessors)
{
    assert(outAccessors.size() <= 1);

    if (outAccessors.size() > 0) {
        pOutAccessor = outAccessors[0];
    }
}

void JavaTransformExecStream::prepare(
    JavaTransformExecStreamParams const &params)
{
    ExecStream::prepare(params);

    if (pOutAccessor) {
        assert(pOutAccessor->getProvision() == getOutputBufProvision());
        if (pOutAccessor->getTupleDesc().empty()) {
            assert(!params.outputTupleDesc.empty());
            pOutAccessor->setTupleShape(
                params.outputTupleDesc,
                params.outputTupleFormat);
        }
    }

    for (uint i = 0; i < inAccessors.size(); ++i) {
        assert(inAccessors[i]->getProvision() == getInputBufProvision());
    }

    JniEnvAutoRef pEnv;

    farragoTransformClassName = params.javaClassName;
    pStreamGraphHandle = params.pStreamGraphHandle;

    // TODO: SWZ: 3/17/06: Avoid allocating scratch space when there's
    // no output accessor.  Also need to change getResourceRequirements.
    scratchAccessor = params.scratchAccessor;
    bufferLock.accessSegment(scratchAccessor);
}

void JavaTransformExecStream::getResourceRequirements(
    ExecStreamResourceQuantity &minQuantity,
    ExecStreamResourceQuantity &optQuantity)
{
    ExecStream::getResourceRequirements(minQuantity,optQuantity);

    // one page for scratch buffer
    minQuantity.nCachePages += 1;
    optQuantity = minQuantity;
}

void JavaTransformExecStream::open(bool restart)
{
    FENNEL_TRACE(TRACE_FINER, "open" << (restart? " (restart)" : ""));

    ExecStream::open(restart);

    JniEnvAutoRef pEnv;

    if (restart) {
        if (pOutAccessor) {
            pOutAccessor->clear();
        }

        // restart inputs
        for (uint i = 0; i < inAccessors.size(); ++i) {
            inAccessors[i]->clear();
            pGraph->getStreamInput(getStreamId(),i)->open(true);
        }

        assert(farragoTransform);

        pEnv->CallVoidMethod(
            farragoTransform,
            JniUtil::methFarragoTransformRestart,
            NULL);
        return;
    }

    FENNEL_TRACE(
        TRACE_FINER,
        "java class name: " << farragoTransformClassName.c_str());

    // Need to use a call on the FarragoRuntimeContext to get the
    // class (we need the right class loader).

    jstring javaClassName =
        pEnv->NewStringUTF(farragoTransformClassName.c_str());

    // net.sf.farrago.runtime.FarragoTransform implementation (can't be done
    // in JniUtil because it's different for each transform)
    jclass classFarragoTransform =
        reinterpret_cast<jclass>(
            pEnv->CallObjectMethod(
                pStreamGraphHandle->javaRuntimeContext,
                JniUtil::methFarragoRuntimeContextStatementClassForName,
                javaClassName));
    assert(classFarragoTransform);

    // FarragoTransform implementation constructor
    jmethodID methFarragoTransformCons =
        pEnv->GetMethodID(classFarragoTransform, "<init>", "()V");
    assert(methFarragoTransformCons);

    // initialize parameters for FarragoTransform.init()
    jobjectArray inputBindingArray = NULL;

    if (inAccessors.size() > 0) {
        inputBindingArray =
            pEnv->NewObjectArray(
                inAccessors.size(),
                JniUtil::classFarragoTransformInputBinding,
                NULL);

        ExecStreamGraph &streamGraph = getGraph();

        for(uint ordinal = 0; ordinal < inAccessors.size(); ordinal++) {
            std::string inputStreamName =
                streamGraph.getStreamInput(getStreamId(), ordinal)->getName();

            jstring jInputStreamName =
                pEnv->NewStringUTF(inputStreamName.c_str());
            jint jOrdinal = static_cast<jint>(ordinal);

            jobject inputBinding =
                pEnv->NewObject(
                    JniUtil::classFarragoTransformInputBinding,
                    JniUtil::methFarragoTransformInputBindingCons,
                    jInputStreamName,
                    jOrdinal);
            assert(inputBinding);

            pEnv->SetObjectArrayElement(
                inputBindingArray, jOrdinal, inputBinding);
        }
    }

    // Create FarragoTransform instance and initialize it
    jobject xformRef =
        pEnv->NewObject(classFarragoTransform, methFarragoTransformCons);
    assert(xformRef);

    farragoTransform = pEnv->NewGlobalRef(xformRef);
    assert(farragoTransform);

    const std::string &streamName = getName();

    jstring javaStreamName = pEnv->NewStringUTF(streamName.c_str());

    pEnv->CallVoidMethod(
        farragoTransform,
        JniUtil::methFarragoTransformInit,
        pStreamGraphHandle->javaRuntimeContext,
        javaStreamName,
        inputBindingArray);

    // Allocate output buffer.
    bufferLock.allocatePage();
    outputByteBuffer = pEnv->NewDirectByteBuffer(
        bufferLock.getPage().getWritableData(),
        bufferLock.getPage().getCache().getPageSize());
    outputByteBuffer = pEnv->NewGlobalRef(outputByteBuffer);
    FENNEL_TRACE(
        TRACE_FINER, "allocated 1 java ByteBuffer " << outputByteBuffer);
    assert(outputByteBuffer);
}

ExecStreamResult JavaTransformExecStream::execute(
    ExecStreamQuantum const &quantum)
{
    FENNEL_TRACE(TRACE_FINEST, "execute");

    if (pOutAccessor) {
        switch(pOutAccessor->getState()) {
        case EXECBUF_NONEMPTY:
        case EXECBUF_OVERFLOW:
            FENNEL_TRACE(TRACE_FINER, "overflow");
            return EXECRC_BUF_OVERFLOW;
        case EXECBUF_EOS:
            FENNEL_TRACE(TRACE_FINER, "eos");
            return EXECRC_EOS;
        default:
            break;
        }
    }

    for (uint i = 0; i < inAccessors.size(); ++i) {
        SharedExecStreamBufAccessor inAccessor = inAccessors[i];

        // Request production on empty inputs.
        if (inAccessor->getState() == EXECBUF_EMPTY) {
            inAccessor->requestProduction();
        }
    }

    jlong jquantum = static_cast<jlong>(quantum.nTuplesMax);

    JniEnvAutoRef pEnv;
    assert(farragoTransform);
    int cb = pEnv->CallIntMethod(
        farragoTransform,
        JniUtil::methFarragoTransformExecute,
        outputByteBuffer,
        jquantum);

    if (cb > 0) {
        assert(pOutAccessor);
        pOutAccessor->provideBufferForConsumption(
            bufferLock.getPage().getWritableData(),
            bufferLock.getPage().getWritableData() + cb);

        FENNEL_TRACE(TRACE_FINER, "wrote " << cb << " bytes");
        return EXECRC_BUF_OVERFLOW;
    } else if (cb < 0) {
        FENNEL_TRACE(TRACE_FINER, "underflow");
        return EXECRC_BUF_UNDERFLOW;
    } else {
        FENNEL_TRACE(TRACE_FINER, "marking EOS");
        if (pOutAccessor) {
            pOutAccessor->markEOS();
        }
        return EXECRC_EOS;
    }
}

void JavaTransformExecStream::closeImpl()
{
    JniEnvAutoRef pEnv;

    // REVIEW: SWZ: 3/8/2006: Call closeAllocation on farragoTransform?

    if (farragoTransform) {
        pEnv->DeleteGlobalRef(farragoTransform);
        farragoTransform = NULL;
    }

    if (outputByteBuffer) {
        pEnv->DeleteGlobalRef(outputByteBuffer);
        outputByteBuffer = NULL;
    }

    bufferLock.unlock();

    ExecStream::closeImpl();
}

ExecStreamBufProvision JavaTransformExecStream::getInputBufProvision() const
{
    return BUFPROV_PRODUCER;
}

ExecStreamBufProvision JavaTransformExecStream::getOutputBufProvision() const
{
    return BUFPROV_PRODUCER;
}

FENNEL_END_CPPFILE("$Id$");

// End JavaTransformExecStream.cpp
<|endoftext|>