<commit_before>#include <evolve.h>

#include <exmars/exhaust.h>
#include <exmars/insn.h>
#include <FitnessEvaluator.h>

#include <FastRng.h>

#include <string>
#include <iostream>
#include <iomanip>
#include <conio.h>

#include <Windows.h>
#ifdef max
#undef max
#endif

void rngIns(FastRng& rng, std::vector<int>& ins, u32_t coresize, size_t idx) {
    switch (idx) {
    case 0:
        // no LDP and no STP
        ins[0] = rng(EX_LDP);
        break;

    case 1:
        ins[1] = rng(EX_MODIFIER_END);
        break;

    case 2:
        ins[2] = rng(EX_ADDRMODE_END);
        break;

    case 3:
        if (rng(2)) {
            ins[3] = rng(coresize);
        } else {
            int change = rng(17) - 8;
            ins[3] = change;
            if (change < 0) {
                ins[3] += coresize;
            }
        }
        break;

    case 4:
        ins[4] = rng(EX_ADDRMODE_END);
        break;

    case 5:
        if (rng(2)) {
            ins[5] = rng(coresize);
        } else {
            int change = rng(17) - 8;
            ins[5] = change;
            if (change < 0) {
                ins[5] += coresize;
            }
        }
        break;

    default:
        throw std::runtime_error("rngIns");
    }
}

std::vector<int> rngIns(FastRng& rng, u32_t coresize) {
    std::vector<int> ins(6);
    for (size_t i = 0; i < ins.size(); ++i) {
        rngIns(rng, ins, coresize, i);
    }
    return ins;
}

void evolve(FastRng& rng,
    const WarriorAry& wSrcOriginal,
    WarriorAry& wTgt,
    u32_t coresize,
    u32_t maxWarriorLength)
{
    // change at least once, and probably multiple times.
    auto wSrc = wSrcOriginal;
    bool isOriginal = true;
    while (isOriginal || rng.rand01() < 0.5) {
        switch (rng(14)) {
        case 0:
            // insert random instruction
            if (wSrc.ins.size() < maxWarriorLength) {
                wTgt = wSrc;
                int pos = rng(static_cast<unsigned>(wTgt.ins.size() + 1));
                wTgt.ins.insert(wTgt.ins.begin() + pos, rngIns(rng, coresize));
                if (pos <= wTgt.startOffset) {
                    ++wTgt.startOffset;
                }
                isOriginal = false;
            }
            break;

        case 1:
        case 7:
        case 12:
            // remove random instruction
            if (wSrc.ins.size() > 1) {
                wTgt = wSrc;
                int pos = rng(static_cast<unsigned>(wTgt.ins.size()));
                wTgt.ins.erase(wTgt.ins.begin() + pos);
                if (pos < wTgt.startOffset || wTgt.startOffset == wTgt.ins.size()) {
                    --wTgt.startOffset;
                }
                isOriginal = false;
            }
            break;

        case 2:
            // swap random instructions
            if (wSrc.ins.size() > 2) {
                unsigned pos1 = rng(static_cast<unsigned>(wSrc.ins.size()));
                unsigned pos2;
                do {
                    pos2 = rng(static_cast<unsigned>(wSrc.ins.size()));
                } while (pos1 == pos2);

                wTgt = wSrc;
                std::swap(wTgt.ins[pos1], wTgt.ins[pos2]);
                isOriginal = false;
            }
            break;

        case 3:
            // change single pos
            if (!wSrc.ins.empty()) {
                wTgt = wSrc;
                unsigned pos = rng(static_cast<unsigned>(wSrc.ins.size()));
                rngIns(rng, wTgt.ins[pos], coresize, rng(6));
                isOriginal = false;
            }
            break;

        case 4:
            // change whole instruction
            if (!wSrc.ins.empty()) {
                wTgt = wSrc;
                unsigned pos = rng(static_cast<unsigned>(wSrc.ins.size()));
                wTgt.ins[pos] = rngIns(rng, coresize);
                isOriginal = false;
            }
            break;

        case 5:
            // change start
            if (wSrc.ins.size() > 1) {
                size_t pos;
                do {
                    pos = rng(static_cast<unsigned>(wSrc.ins.size()));
                } while (pos == wSrc.startOffset);
                wTgt = wSrc;
                wTgt.startOffset = pos;
                isOriginal = false;
            }
            break;

        case 6:
            // duplicate an instruction
            if (wSrc.ins.size() < maxWarriorLength && !wSrc.ins.empty()) {
                wTgt = wSrc;
                int pos = rng(static_cast<unsigned>(wTgt.ins.size()));
                auto tmp = wTgt.ins[pos];
                wTgt.ins.insert(wTgt.ins.begin() + pos, tmp);
                if (pos < wTgt.startOffset) {
                    ++wTgt.startOffset;
                }
                isOriginal = false;
            }
            break;

        case 8:
            // swap numbers within instruction
            if (!wSrc.ins.empty()) {
                wTgt = wSrc;
                unsigned pos = rng(static_cast<unsigned>(wSrc.ins.size()));
                std::swap(wTgt.ins[pos][3], wTgt.ins[pos][5]);
                isOriginal = false;
            }
            break;

        case 9:
            // swap address mode within instruction
            if (!wSrc.ins.empty()) {
                wTgt = wSrc;
                unsigned pos = rng(static_cast<unsigned>(wSrc.ins.size()));
                std::swap(wTgt.ins[pos][2], wTgt.ins[pos][4]);
                isOriginal = false;
            }
            break;

        case 10:
            // increase/decrease a number up to 8
            if (!wSrc.ins.empty()) {
                wTgt = wSrc;
                unsigned pos = rng(static_cast<unsigned>(wSrc.ins.size()));
                int idx = 3;
                if (rng(2)) {
                    idx = 5;
                }

                // -8 to +8, without 0
                int change = rng(16) - 8;
                if (change >= 0) {
                    ++change;
                }
                change += wTgt.ins[pos][idx];

                // handle over and underflow
                if (change < 0) {
                    wTgt.ins[pos][idx] = change + coresize;
                } else if (change >= static_cast<int>(coresize)) {
                    wTgt.ins[pos][idx] = change - coresize;
                } else {
                    wTgt.ins[pos][idx] = change;
                }

                isOriginal = false;
            }
            break;

        case 11:
            // duplicate to random position
            if (wSrc.ins.size() < maxWarriorLength && !wSrc.ins.empty()) {
                wTgt = wSrc;
                int pos = rng(static_cast<unsigned>(wTgt.ins.size()));
                auto tmp = wTgt.ins[pos];

                int insertPos = rng(static_cast<unsigned>(wTgt.ins.size() + 1));
                wTgt.ins.insert(wTgt.ins.begin() + insertPos, tmp);
                if (pos <= wTgt.startOffset) {
                    ++wTgt.startOffset;
                }
                isOriginal = false;
            }
            break;

        case 13:
            // swap random within index
            if (wSrc.ins.size() > 2) {
                unsigned pos1 = rng(static_cast<unsigned>(wSrc.ins.size()));
                unsigned pos2;
                do {
                    pos2 = rng(static_cast<unsigned>(wSrc.ins.size()));
                } while (pos1 == pos2);

                wTgt = wSrc;

                //    0       1       2       3     4       5
                //  EX_MOV, EX_mI, EX_DIRECT, 0, EX_DIRECT, 1 } }

                // random swap a and b value/mode
                int idx1 = rng(4);
                int idx2 = idx1;
                if (idx1 >= 2 && rng(2)) {
                    idx2 += 2;
                }
                std::swap(wTgt.ins[pos1][idx1], wTgt.ins[pos2][idx2]);
                isOriginal = false;
            }
            break;

            /*
        case 13:
            // copy single value to random other instruction.
            // unfortunately copying the full instruction seems to destroy diversity.
            // Just copy one entry instead.
            if (wSrc.ins.size() > 1) {
                wTgt = wSrc;
                int pos1 = rng(static_cast<unsigned>(wTgt.ins.size()));
                int pos2;
                do {
                    pos2 = rng(static_cast<unsigned>(wTgt.ins.size()));
                } while (pos1 == pos2);
                auto idx = rng(6);
                wTgt.ins[pos1][idx] = wTgt.ins[pos2][idx];
                isOriginal = false;
            }
            break;
            */

        default:
            std::cout << "error!" << std::endl;
            throw std::runtime_error("evolve switch");
        }

        // update wSrc for next round
        wSrc = wTgt;
    }
}

std::string print(const WarriorAry& w, u32_t coresize);

void printStatus(size_t iter, const WarriorAry& w, mars_t* mars, double acceptanceRate, double beta) {
    std::cout.precision(15);
    std::cout
        << std::endl
        << ";redcode-94nop" << std::endl
        << ";name YaceReloaded " << w.iteration << ": " << w.fitness << std::endl
        << ";author Martin Ankerl" << std::endl
        << ";strategy Markov Chain Monte Carlo sampling" << std::endl
        << ";strategy with Metropolis-Hastings Algorithm" << std::endl
        << ";strategy " << std::fixed << std::setprecision(2) << w.score << " testset score" << std::endl
        << ";strategy " << acceptanceRate << " acceptance rate" << std::endl
        << ";strategy " << iter << " current iteration" << std::endl
        << ";strategy " << beta << " beta" << std::endl
        << ";assert 1" << std::endl
        << print(w, mars->coresize);
}

void printStats(const FitnessEvaluator& fe) {
    std::cout << fe.printStats() << std::endl;
}

int evolve(int argc, char** argv) {

    // TODO use protobuf configuration instead of argc and argv
    mars_t* mars = init(argc, argv);
    std::vector<std::string> warriorFiles;
    auto* w = mars->warriorNames;
    while (w) {
        warriorFiles.push_back(w->warriorName);
        w = w->next;
    }

    FitnessEvaluator fe(
        mars->rounds,
        mars->cycles,
        mars->coresize,
        mars->minsep,
        mars->maxWarriorLength,
        mars->processes,
        warriorFiles,
        123);

    FastRng rng;
    //rng.seed(3211);

    // create a random start warrior
    WarriorAry wCurrent;
    int initialLength = rng(mars->maxWarriorLength);
    for (size_t i = 0; i < initialLength; ++i) {
        wCurrent.ins.push_back(rngIns(rng, mars->coresize));
    }
    wCurrent.startOffset = rng(initialLength);
    double score;
    wCurrent.fitness = fe.calcFitness(wCurrent, std::numeric_limits<double>::max(), score);
    wCurrent.score = score;

    WarriorAry wTrial;

    double beta = 400;
    WarriorAry wBest;
    wBest.fitness = std::numeric_limits<double>::max();

    size_t iter = 0;
    double acceptanceRate = 0.5;

    // see http://msdn.microsoft.com/en-us/library/windows/desktop/ms686277%28v=vs.85%29.aspx
    //SetThreadPriority(GetCurrentThread(), THREAD_MODE_BACKGROUND_BEGIN);

    bool isAutoPrintBestActive = true;

    //while (iter < 10000) {
    // set priority to very low
    SetPriorityClass(GetCurrentProcess(), PROCESS_MODE_BACKGROUND_BEGIN);
    while (true) {
        evolve(rng, wCurrent, wTrial, mars->coresize, mars->maxWarriorLength);

        // see https://github.com/StanfordPL/stoke-release/blob/232ca096de53be8f1f528b22f3b610566f386cae/src/search/search.cc#L142
        const auto maxFitness = wCurrent.fitness - std::log(rng.rand01()) / beta;
        wTrial.fitness = fe.calcFitness(wTrial, maxFitness, wTrial.score);
        ++iter;
        double gotAccepted = 0;
        if (wTrial.fitness <= maxFitness) {
            gotAccepted = 1;
            wCurrent = wTrial;

            if (wCurrent.fitness < wBest.fitness) {
                wBest = wCurrent;
                wBest.iteration = iter;
                if (isAutoPrintBestActive) {
                    printStatus(iter, wBest, mars, acceptanceRate, beta);
                }
            }
        }

        acceptanceRate = acceptanceRate * 0.99 + gotAccepted * 0.01;

        if (_kbhit()) {
            switch (_getch()) {
            case 'r':
                wCurrent = wBest;
                std::cout << "resetted current to best" << std::endl;
                break;

            case 'p':
                printStatus(iter, wBest, mars, acceptanceRate, beta);
                break;

            case 'B':
                beta *= 2;
                std::cout << "doubling beta to " << beta << std::endl;
                break;

            case 'b':
                beta /= 2;
                std::cout << "halfing beta to " << beta << std::endl;
                break;

            case 'a':
                isAutoPrintBestActive = !isAutoPrintBestActive;
                std::cout << "automatically print new best is " << (isAutoPrintBestActive ? "ON" : "OFF") << std::endl;
                break;

            case 's':
                printStats(fe);
                break;

            default:
                std::cout << "usage:" << std::endl
                    << " h: this help" << std::endl
                    << " a: toggle automatic printing of new best warrior" << std::endl
                    << " p: print best warrior" << std::endl
                    << " r: reset current warrior to best warrior" << std::endl
                    << " B: double beta" << std::endl
                    << " b: half beta" << std::endl
                    << " s: print stats" << std::endl
                    << std::endl;
                break;
            }
        }
    }
    printStatus(iter, wBest, mars, acceptanceRate, beta);
    printStats(fe);

    // set priority back.
    SetPriorityClass(GetCurrentProcess(), PROCESS_MODE_BACKGROUND_END);

    //SetThreadPriority(GetCurrentThread(), THREAD_MODE_BACKGROUND_END);

    //const auto stop = std::chrono::system_clock::now();
    //auto t = std::chrono::duration<double>(stop - start).count();
    return 0;
}<commit_msg>initial length is now 20 or less. stupid cout is stupid. printf would be much simpler.<commit_after>#include <evolve.h>

#include <exmars/exhaust.h>
#include <exmars/insn.h>
#include <FitnessEvaluator.h>

#include <FastRng.h>

#include <string>
#include <iostream>
#include <iomanip>
#include <algorithm>
#include <conio.h>

#include <Windows.h>
#ifdef max
#undef max
#endif
#ifdef min
#undef min
#endif

void rngIns(FastRng& rng, std::vector<int>& ins, u32_t coresize, size_t idx) {
    switch (idx) {
    case 0:
        // no LDP and no STP
        ins[0] = rng(EX_LDP);
        break;

    case 1:
        ins[1] = rng(EX_MODIFIER_END);
        break;

    case 2:
        ins[2] = rng(EX_ADDRMODE_END);
        break;

    case 3:
        if (rng(2)) {
            ins[3] = rng(coresize);
        } else {
            int change = rng(17) - 8;
            ins[3] = change;
            if (change < 0) {
                ins[3] += coresize;
            }
        }
        break;

    case 4:
        ins[4] = rng(EX_ADDRMODE_END);
        break;

    case 5:
        if (rng(2)) {
            ins[5] = rng(coresize);
        } else {
            int change = rng(17) - 8;
            ins[5] = change;
            if (change < 0) {
                ins[5] += coresize;
            }
        }
        break;

    default:
        throw std::runtime_error("rngIns");
    }
}

std::vector<int> rngIns(FastRng& rng, u32_t coresize) {
    std::vector<int> ins(6);
    for (size_t i = 0; i < ins.size(); ++i) {
        rngIns(rng, ins, coresize, i);
    }
    return ins;
}

void evolve(FastRng& rng,
    const WarriorAry& wSrcOriginal,
    WarriorAry& wTgt,
    u32_t coresize,
    u32_t maxWarriorLength)
{
    // change at least once, and probably multiple times.
    auto wSrc = wSrcOriginal;
    bool isOriginal = true;
    while (isOriginal || rng.rand01() < 0.5) {
        switch (rng(14)) {
        case 0:
            // insert random instruction
            if (wSrc.ins.size() < maxWarriorLength) {
                wTgt = wSrc;
                int pos = rng(static_cast<unsigned>(wTgt.ins.size() + 1));
                wTgt.ins.insert(wTgt.ins.begin() + pos, rngIns(rng, coresize));
                if (pos <= wTgt.startOffset) {
                    ++wTgt.startOffset;
                }
                isOriginal = false;
            }
            break;

        case 1:
        case 7:
        case 12:
            // remove random instruction
            if (wSrc.ins.size() > 1) {
                wTgt = wSrc;
                int pos = rng(static_cast<unsigned>(wTgt.ins.size()));
                wTgt.ins.erase(wTgt.ins.begin() + pos);
                if (pos < wTgt.startOffset || wTgt.startOffset == wTgt.ins.size()) {
                    --wTgt.startOffset;
                }
                isOriginal = false;
            }
            break;

        case 2:
            // swap random instructions
            if (wSrc.ins.size() > 2) {
                unsigned pos1 = rng(static_cast<unsigned>(wSrc.ins.size()));
                unsigned pos2;
                do {
                    pos2 = rng(static_cast<unsigned>(wSrc.ins.size()));
                } while (pos1 == pos2);

                wTgt = wSrc;
                std::swap(wTgt.ins[pos1], wTgt.ins[pos2]);
                isOriginal = false;
            }
            break;

        case 3:
            // change single pos
            if (!wSrc.ins.empty()) {
                wTgt = wSrc;
                unsigned pos = rng(static_cast<unsigned>(wSrc.ins.size()));
                rngIns(rng, wTgt.ins[pos], coresize, rng(6));
                isOriginal = false;
            }
            break;

        case 4:
            // change whole instruction
            if (!wSrc.ins.empty()) {
                wTgt = wSrc;
                unsigned pos = rng(static_cast<unsigned>(wSrc.ins.size()));
                wTgt.ins[pos] = rngIns(rng, coresize);
                isOriginal = false;
            }
            break;

        case 5:
            // change start
            if (wSrc.ins.size() > 1) {
                size_t pos;
                do {
                    pos = rng(static_cast<unsigned>(wSrc.ins.size()));
                } while (pos == wSrc.startOffset);
                wTgt = wSrc;
                wTgt.startOffset = pos;
                isOriginal = false;
            }
            break;

        case 6:
            // duplicate an instruction
            if (wSrc.ins.size() < maxWarriorLength && !wSrc.ins.empty()) {
                wTgt = wSrc;
                int pos = rng(static_cast<unsigned>(wTgt.ins.size()));
                auto tmp = wTgt.ins[pos];
                wTgt.ins.insert(wTgt.ins.begin() + pos, tmp);
                if (pos < wTgt.startOffset) {
                    ++wTgt.startOffset;
                }
                isOriginal = false;
            }
            break;

        case 8:
            // swap numbers within instruction
            if (!wSrc.ins.empty()) {
                wTgt = wSrc;
                unsigned pos = rng(static_cast<unsigned>(wSrc.ins.size()));
                std::swap(wTgt.ins[pos][3], wTgt.ins[pos][5]);
                isOriginal = false;
            }
            break;

        case 9:
            // swap address mode within instruction
            if (!wSrc.ins.empty()) {
                wTgt = wSrc;
                unsigned pos = rng(static_cast<unsigned>(wSrc.ins.size()));
                std::swap(wTgt.ins[pos][2], wTgt.ins[pos][4]);
                isOriginal = false;
            }
            break;

        case 10:
            // increase/decrease a number up to 8
            if (!wSrc.ins.empty()) {
                wTgt = wSrc;
                unsigned pos = rng(static_cast<unsigned>(wSrc.ins.size()));
                int idx = 3;
                if (rng(2)) {
                    idx = 5;
                }

                // -8 to +8, without 0
                int change = rng(16) - 8;
                if (change >= 0) {
                    ++change;
                }
                change += wTgt.ins[pos][idx];

                // handle over and underflow
                if (change < 0) {
                    wTgt.ins[pos][idx] = change + coresize;
                } else if (change >= static_cast<int>(coresize)) {
                    wTgt.ins[pos][idx] = change - coresize;
                } else {
                    wTgt.ins[pos][idx] = change;
                }

                isOriginal = false;
            }
            break;

        case 11:
            // duplicate to random position
            if (wSrc.ins.size() < maxWarriorLength && !wSrc.ins.empty()) {
                wTgt = wSrc;
                int pos = rng(static_cast<unsigned>(wTgt.ins.size()));
                auto tmp = wTgt.ins[pos];

                int insertPos = rng(static_cast<unsigned>(wTgt.ins.size() + 1));
                wTgt.ins.insert(wTgt.ins.begin() + insertPos, tmp);
                if (pos <= wTgt.startOffset) {
                    ++wTgt.startOffset;
                }
                isOriginal = false;
            }
            break;

        case 13:
            // swap random within index
            if (wSrc.ins.size() > 2) {
                unsigned pos1 = rng(static_cast<unsigned>(wSrc.ins.size()));
                unsigned pos2;
                do {
                    pos2 = rng(static_cast<unsigned>(wSrc.ins.size()));
                } while (pos1 == pos2);

                wTgt = wSrc;

                //    0       1       2       3     4       5
                //  EX_MOV, EX_mI, EX_DIRECT, 0, EX_DIRECT, 1 } }

                // random swap a and b value/mode
                int idx1 = rng(4);
                int idx2 = idx1;
                if (idx1 >= 2 && rng(2)) {
                    idx2 += 2;
                }
                std::swap(wTgt.ins[pos1][idx1], wTgt.ins[pos2][idx2]);
                isOriginal = false;
            }
            break;

            /*
        case 13:
            // copy single value to random other instruction.
            // unfortunately copying the full instruction seems to destroy diversity.
            // Just copy one entry instead.
            if (wSrc.ins.size() > 1) {
                wTgt = wSrc;
                int pos1 = rng(static_cast<unsigned>(wTgt.ins.size()));
                int pos2;
                do {
                    pos2 = rng(static_cast<unsigned>(wTgt.ins.size()));
                } while (pos1 == pos2);
                auto idx = rng(6);
                wTgt.ins[pos1][idx] = wTgt.ins[pos2][idx];
                isOriginal = false;
            }
            break;
            */

        default:
            std::cout << "error!" << std::endl;
            throw std::runtime_error("evolve switch");
        }

        // update wSrc for next round
        wSrc = wTgt;
    }
}

std::string print(const WarriorAry& w, u32_t coresize);

void printStatus(size_t iter, const WarriorAry& w, mars_t* mars, double acceptanceRate, double beta) {
    std::cout
        << std::endl
        << ";redcode-94nop" << std::endl
        << ";name YaceReloaded " << w.iteration << ": " << w.fitness << std::endl
        << ";author Martin Ankerl" << std::endl
        << ";strategy Markov Chain Monte Carlo sampling" << std::endl
        << ";strategy with Metropolis-Hastings Algorithm" << std::endl
        << ";strategy " << std::fixed << std::setprecision(2) << w.score << " testset score" << std::endl
        << ";strategy " << std::defaultfloat << std::setprecision(10) << acceptanceRate << " acceptance rate" << std::endl
        << ";strategy " << iter << " current iteration" << std::endl
        << ";strategy " << beta << " beta" << std::endl
        << ";assert 1" << std::endl
        << print(w, mars->coresize);
}

void printStats(const FitnessEvaluator& fe) {
    std::cout << fe.printStats() << std::endl;
}

int evolve(int argc, char** argv) {

    // TODO use protobuf configuration instead of argc and argv
    mars_t* mars = init(argc, argv);
    std::vector<std::string> warriorFiles;
    auto* w = mars->warriorNames;
    while (w) {
        warriorFiles.push_back(w->warriorName);
        w = w->next;
    }

    FitnessEvaluator fe(
        mars->rounds,
        mars->cycles,
        mars->coresize,
        mars->minsep,
        mars->maxWarriorLength,
        mars->processes,
        warriorFiles,
        123);

    FastRng rng;
    //rng.seed(3211);

    // create a random start warrior
    WarriorAry wCurrent;
    int initialLength = rng(std::min((u32_t)20, mars->maxWarriorLength));
    for (size_t i = 0; i < initialLength; ++i) {
        wCurrent.ins.push_back(rngIns(rng, mars->coresize));
    }
    wCurrent.startOffset = rng(initialLength);
    double score;
    wCurrent.fitness = fe.calcFitness(wCurrent, std::numeric_limits<double>::max(), score);
    wCurrent.score = score;

    WarriorAry wTrial;

    double beta = 400;
    WarriorAry wBest;
    wBest.fitness = std::numeric_limits<double>::max();

    size_t iter = 0;
    double acceptanceRate = 0.5;

    // see http://msdn.microsoft.com/en-us/library/windows/desktop/ms686277%28v=vs.85%29.aspx
    //SetThreadPriority(GetCurrentThread(), THREAD_MODE_BACKGROUND_BEGIN);

    bool isAutoPrintBestActive = true;

    //while (iter < 10000) {
    // set priority to very low
    SetPriorityClass(GetCurrentProcess(), PROCESS_MODE_BACKGROUND_BEGIN);
    while (true) {
        evolve(rng, wCurrent, wTrial, mars->coresize, mars->maxWarriorLength);

        // see https://github.com/StanfordPL/stoke-release/blob/232ca096de53be8f1f528b22f3b610566f386cae/src/search/search.cc#L142
        const auto maxFitness = wCurrent.fitness - std::log(rng.rand01()) / beta;
        wTrial.fitness = fe.calcFitness(wTrial, maxFitness, wTrial.score);
        ++iter;
        double gotAccepted = 0;
        if (wTrial.fitness <= maxFitness) {
            gotAccepted = 1;
            wCurrent = wTrial;

            if (wCurrent.fitness < wBest.fitness) {
                wBest = wCurrent;
                wBest.iteration = iter;
                if (isAutoPrintBestActive) {
                    printStatus(iter, wBest, mars, acceptanceRate, beta);
                }
            }
        }

        acceptanceRate = acceptanceRate * 0.99 + gotAccepted * 0.01;

        if (_kbhit()) {
            switch (_getch()) {
            case 'r':
                wCurrent = wBest;
                std::cout << "resetted current to best" << std::endl;
                break;

            case 'p':
                printStatus(iter, wBest, mars, acceptanceRate, beta);
                break;

            case 'B':
                beta *= 2;
                std::cout << "doubling beta to " << beta << std::endl;
                break;

            case 'b':
                beta /= 2;
                std::cout << "halfing beta to " << beta << std::endl;
                break;

            case 'a':
                isAutoPrintBestActive = !isAutoPrintBestActive;
                std::cout << "automatically print new best is " << (isAutoPrintBestActive ? "ON" : "OFF") << std::endl;
                break;

            case 's':
                printStats(fe);
                break;

            default:
                std::cout << "usage:" << std::endl
                    << " h: this help" << std::endl
                    << " a: toggle automatic printing of new best warrior" << std::endl
                    << " p: print best warrior" << std::endl
                    << " r: reset current warrior to best warrior" << std::endl
                    << " B: double beta" << std::endl
                    << " b: half beta" << std::endl
                    << " s: print stats" << std::endl
                    << std::endl;
                break;
            }
        }
    }
    printStatus(iter, wBest, mars, acceptanceRate, beta);
    printStats(fe);

    // set priority back.
    SetPriorityClass(GetCurrentProcess(), PROCESS_MODE_BACKGROUND_END);

    //SetThreadPriority(GetCurrentThread(), THREAD_MODE_BACKGROUND_END);

    //const auto stop = std::chrono::system_clock::now();
    //auto t = std::chrono::duration<double>(stop - start).count();
    return 0;
}<|endoftext|>


<commit_before>
/*

                        /~` _  _ _|_. _     _ |_ | _
                        \_,(_)| | | || ||_|(_||_)|(/_

                    https://github.com/Naios/continuable
                                   v3.0.0

  Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>

  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files(the "Software"), to deal
  in the Software without restriction, including without limitation the rights
  to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
  copies of the Software, and to permit persons to whom the Software is
  furnished to do so, subject to the following conditions :

  The above copyright notice and this permission notice shall be included in
  all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  SOFTWARE.
**/

#ifndef CONTINUABLE_DETAIL_CONNECTION_HPP_INCLUDED
#define CONTINUABLE_DETAIL_CONNECTION_HPP_INCLUDED

#include <cassert>
#include <tuple>
#include <type_traits>
#include <utility>
#include <continuable/continuable-traverse.hpp>
#include <continuable/detail/core/base.hpp>
#include <continuable/detail/core/types.hpp>
#include <continuable/detail/utility/traits.hpp>
#include <continuable/detail/utility/util.hpp>

namespace cti {
namespace detail {
/// The namespace `connection` offers methods to chain continuations together
/// with `all`, `any` or `seq` logic.
namespace connection {
template <typename T>
struct is_connection_strategy // ...
    : std::false_type {};

/// Adds the given continuation tuple to the left connection
template <typename... LeftArgs, typename... RightArgs>
auto chain_connection(std::tuple<LeftArgs...> leftPack,
                      std::tuple<RightArgs...> rightPack) {

  return std::tuple_cat(std::move(leftPack), std::move(rightPack));
}

/// Normalizes a continuation to a tuple holding an arbitrary count of
/// continuations matching the given strategy.
///
/// Basically we can encounter 3 cases:
/// - The continuable isn't in any strategy:
///   -> make a tuple containing the continuable as only element
template <
    typename Strategy, typename Data, typename Annotation,
    std::enable_if_t<!is_connection_strategy<Annotation>::value>* = nullptr>
auto normalize(Strategy /*strategy*/,
               continuable_base<Data, Annotation>&& continuation) {

  // If the continuation isn't a strategy initialize the strategy
  return std::make_tuple(std::move(continuation));
}
/// - The continuable is in a different strategy then the current one:
///   -> materialize it
template <
    typename Strategy, typename Data, typename Annotation,
    std::enable_if_t<is_connection_strategy<Annotation>::value>* = nullptr>
auto normalize(Strategy /*strategy*/,
               continuable_base<Data, Annotation>&& continuation) {

  // If the right continuation is a different strategy materialize it
  // in order to keep the precedence in cases where: `c1 && (c2 || c3)`.
  return std::make_tuple(std::move(continuation).finish());
}
/// - The continuable is inside the current strategy state:
///   -> return the data of the tuple
template <typename Strategy, typename Data>
auto normalize(Strategy /*strategy*/,
               continuable_base<Data, Strategy>&& continuation) {

  // If we are in the given strategy we can just use the data of the continuable
  return base::attorney::consume(std::move(continuation));
}

/// Entry function for connecting two continuables with a given strategy.
template <typename Strategy, typename LData, typename LAnnotation,
          typename RData, typename RAnnotation>
auto connect(Strategy strategy, continuable_base<LData, LAnnotation>&& left,
             continuable_base<RData, RAnnotation>&& right) {

  auto ownership_ =
      base::attorney::ownership_of(left) | base::attorney::ownership_of(right);

  left.freeze();
  right.freeze();

  // Make the new data which consists of a tuple containing
  // all connected continuables.
  auto data = chain_connection(normalize(strategy, std::move(left)),
                               normalize(strategy, std::move(right)));

  // Return a new continuable containing the tuple and holding
  // the current strategy as annotation.
  return base::attorney::create_from_raw(std::move(data), strategy, ownership_);
}

/// All strategies should specialize this class in order to provide:
/// - A finalize static method that creates the callable object which
///   is invoked with the callback to call when the connection is finished.
/// - A static method hint that returns the new signature hint.
template <typename Strategy>
struct connection_finalizer;

template <typename Strategy>
struct connection_annotation_trait {
  /// Finalizes the connection logic of a given connection
  template <typename Continuable>
  static auto finish(Continuable&& continuable) {
    using continuable_t = traits::unrefcv_t<Continuable>;

    using finalizer = connection_finalizer<Strategy>;

    util::ownership ownership = base::attorney::ownership_of(continuable);
    auto connection =
        base::attorney::consume(std::forward<Continuable>(continuable));

    // Return a new continuable which
    return finalizer::finalize(std::move(connection), std::move(ownership));
  }
};

class prepare_continuables {
  util::ownership& ownership_;

public:
  explicit constexpr prepare_continuables(util::ownership& ownership)
      : ownership_(ownership) {
  }

  template <typename Continuable,
            std::enable_if_t<base::is_continuable<
                std::decay_t<Continuable>>::value>* = nullptr>
  auto operator()(Continuable&& continuable) noexcept {
    util::ownership current = base::attorney::ownership_of(continuable);
    assert(current.is_acquired() &&
           "Only valid continuables should be passed!");

    // Propagate a frozen state to the new continuable
    if (!ownership_.is_frozen() && current.is_frozen()) {
      ownership_.freeze();
    }

    // Freeze the continuable since it is stored for later usage
    continuable.freeze();

    // Materialize every continuable
    // TODO Actually we would just need to consume the data here
    return std::forward<Continuable>(continuable).finish();
  }
};

template <typename Strategy, typename... Args>
auto apply_connection(Strategy, Args&&... args) {
  using finalizer = connection_finalizer<Strategy>;

  // Freeze every continuable inside the given arguments,
  // and freeze the ownership if one of the continuables
  // is frozen already.
  // Additionally test whether every continuable is acquired.
  // Also materialize every continuable.
  util::ownership ownership;
  auto connection = map_pack(prepare_continuables{ownership},
                             std::make_tuple(std::forward<Args>(args)...));

  return finalizer::finalize(std::move(connection), std::move(ownership));
}
} // namespace connection
} // namespace detail
} // namespace cti

#endif // CONTINUABLE_DETAIL_CONNECTION_HPP_INCLUDED
<commit_msg>Remove an unused using<commit_after>
/*

                        /~` _  _ _|_. _     _ |_ | _
                        \_,(_)| | | || ||_|(_||_)|(/_

                    https://github.com/Naios/continuable
                                   v3.0.0

  Copyright(c) 2015 - 2018 Denis Blank <denis.blank at outlook dot com>

  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files(the "Software"), to deal
  in the Software without restriction, including without limitation the rights
  to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
  copies of the Software, and to permit persons to whom the Software is
  furnished to do so, subject to the following conditions :

  The above copyright notice and this permission notice shall be included in
  all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  SOFTWARE.
**/

#ifndef CONTINUABLE_DETAIL_CONNECTION_HPP_INCLUDED
#define CONTINUABLE_DETAIL_CONNECTION_HPP_INCLUDED

#include <cassert>
#include <tuple>
#include <type_traits>
#include <utility>
#include <continuable/continuable-traverse.hpp>
#include <continuable/detail/core/base.hpp>
#include <continuable/detail/core/types.hpp>
#include <continuable/detail/utility/traits.hpp>
#include <continuable/detail/utility/util.hpp>

namespace cti {
namespace detail {
/// The namespace `connection` offers methods to chain continuations together
/// with `all`, `any` or `seq` logic.
namespace connection {
template <typename T>
struct is_connection_strategy // ...
    : std::false_type {};

/// Adds the given continuation tuple to the left connection
template <typename... LeftArgs, typename... RightArgs>
auto chain_connection(std::tuple<LeftArgs...> leftPack,
                      std::tuple<RightArgs...> rightPack) {

  return std::tuple_cat(std::move(leftPack), std::move(rightPack));
}

/// Normalizes a continuation to a tuple holding an arbitrary count of
/// continuations matching the given strategy.
///
/// Basically we can encounter 3 cases:
/// - The continuable isn't in any strategy:
///   -> make a tuple containing the continuable as only element
template <
    typename Strategy, typename Data, typename Annotation,
    std::enable_if_t<!is_connection_strategy<Annotation>::value>* = nullptr>
auto normalize(Strategy /*strategy*/,
               continuable_base<Data, Annotation>&& continuation) {

  // If the continuation isn't a strategy initialize the strategy
  return std::make_tuple(std::move(continuation));
}
/// - The continuable is in a different strategy then the current one:
///   -> materialize it
template <
    typename Strategy, typename Data, typename Annotation,
    std::enable_if_t<is_connection_strategy<Annotation>::value>* = nullptr>
auto normalize(Strategy /*strategy*/,
               continuable_base<Data, Annotation>&& continuation) {

  // If the right continuation is a different strategy materialize it
  // in order to keep the precedence in cases where: `c1 && (c2 || c3)`.
  return std::make_tuple(std::move(continuation).finish());
}
/// - The continuable is inside the current strategy state:
///   -> return the data of the tuple
template <typename Strategy, typename Data>
auto normalize(Strategy /*strategy*/,
               continuable_base<Data, Strategy>&& continuation) {

  // If we are in the given strategy we can just use the data of the continuable
  return base::attorney::consume(std::move(continuation));
}

/// Entry function for connecting two continuables with a given strategy.
template <typename Strategy, typename LData, typename LAnnotation,
          typename RData, typename RAnnotation>
auto connect(Strategy strategy, continuable_base<LData, LAnnotation>&& left,
             continuable_base<RData, RAnnotation>&& right) {

  auto ownership_ =
      base::attorney::ownership_of(left) | base::attorney::ownership_of(right);

  left.freeze();
  right.freeze();

  // Make the new data which consists of a tuple containing
  // all connected continuables.
  auto data = chain_connection(normalize(strategy, std::move(left)),
                               normalize(strategy, std::move(right)));

  // Return a new continuable containing the tuple and holding
  // the current strategy as annotation.
  return base::attorney::create_from_raw(std::move(data), strategy, ownership_);
}

/// All strategies should specialize this class in order to provide:
/// - A finalize static method that creates the callable object which
///   is invoked with the callback to call when the connection is finished.
/// - A static method hint that returns the new signature hint.
template <typename Strategy>
struct connection_finalizer;

template <typename Strategy>
struct connection_annotation_trait {
  /// Finalizes the connection logic of a given connection
  template <typename Continuable>
  static auto finish(Continuable&& continuable) {
    using finalizer = connection_finalizer<Strategy>;

    util::ownership ownership = base::attorney::ownership_of(continuable);
    auto connection =
        base::attorney::consume(std::forward<Continuable>(continuable));

    // Return a new continuable which
    return finalizer::finalize(std::move(connection), std::move(ownership));
  }
};

class prepare_continuables {
  util::ownership& ownership_;

public:
  explicit constexpr prepare_continuables(util::ownership& ownership)
      : ownership_(ownership) {
  }

  template <typename Continuable,
            std::enable_if_t<base::is_continuable<
                std::decay_t<Continuable>>::value>* = nullptr>
  auto operator()(Continuable&& continuable) noexcept {
    util::ownership current = base::attorney::ownership_of(continuable);
    assert(current.is_acquired() &&
           "Only valid continuables should be passed!");

    // Propagate a frozen state to the new continuable
    if (!ownership_.is_frozen() && current.is_frozen()) {
      ownership_.freeze();
    }

    // Freeze the continuable since it is stored for later usage
    continuable.freeze();

    // Materialize every continuable
    // TODO Actually we would just need to consume the data here
    return std::forward<Continuable>(continuable).finish();
  }
};

template <typename Strategy, typename... Args>
auto apply_connection(Strategy, Args&&... args) {
  using finalizer = connection_finalizer<Strategy>;

  // Freeze every continuable inside the given arguments,
  // and freeze the ownership if one of the continuables
  // is frozen already.
  // Additionally test whether every continuable is acquired.
  // Also materialize every continuable.
  util::ownership ownership;
  auto connection = map_pack(prepare_continuables{ownership},
                             std::make_tuple(std::forward<Args>(args)...));

  return finalizer::finalize(std::move(connection), std::move(ownership));
}
} // namespace connection
} // namespace detail
} // namespace cti

#endif // CONTINUABLE_DETAIL_CONNECTION_HPP_INCLUDED
<|endoftext|>


<commit_before>// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "mojo/services/html_viewer/blink_platform_impl.h"

#include <cmath>

#include "base/rand_util.h"
#include "base/stl_util.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/platform_thread.h"
#include "base/time/time.h"
#include "mojo/services/html_viewer/blink_resource_constants.h"
#include "mojo/services/html_viewer/webthread_impl.h"
#include "net/base/data_url.h"
#include "net/base/mime_util.h"
#include "net/base/net_errors.h"
#include "third_party/WebKit/public/platform/WebWaitableEvent.h"

namespace html_viewer {
namespace {

// TODO(darin): Figure out what our UA should really be.
const char kUserAgentString[] =
  "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) "
  "Chrome/35.0.1916.153 Safari/537.36";

class WebWaitableEventImpl : public blink::WebWaitableEvent {
 public:
  WebWaitableEventImpl() : impl_(new base::WaitableEvent(false, false)) {}
  virtual ~WebWaitableEventImpl() {}

  virtual void wait() { impl_->Wait(); }
  virtual void signal() { impl_->Signal(); }

  base::WaitableEvent* impl() {
    return impl_.get();
  }

 private:
  scoped_ptr<base::WaitableEvent> impl_;
  DISALLOW_COPY_AND_ASSIGN(WebWaitableEventImpl);
};

}  // namespace

BlinkPlatformImpl::BlinkPlatformImpl()
    : main_loop_(base::MessageLoop::current()),
      shared_timer_func_(NULL),
      shared_timer_fire_time_(0.0),
      shared_timer_fire_time_was_set_while_suspended_(false),
      shared_timer_suspended_(0),
      current_thread_slot_(&DestroyCurrentThread),
      scheduler_(main_loop_->message_loop_proxy()) {
}

BlinkPlatformImpl::~BlinkPlatformImpl() {
}

blink::WebMimeRegistry* BlinkPlatformImpl::mimeRegistry() {
  return &mime_registry_;
}

blink::WebThemeEngine* BlinkPlatformImpl::themeEngine() {
  return &theme_engine_;
}

blink::WebScheduler* BlinkPlatformImpl::scheduler() {
  return &scheduler_;
}

blink::WebString BlinkPlatformImpl::defaultLocale() {
  return blink::WebString::fromUTF8("en-US");
}

double BlinkPlatformImpl::currentTime() {
  return base::Time::Now().ToDoubleT();
}

double BlinkPlatformImpl::monotonicallyIncreasingTime() {
  return base::TimeTicks::Now().ToInternalValue() /
      static_cast<double>(base::Time::kMicrosecondsPerSecond);
}

void BlinkPlatformImpl::cryptographicallyRandomValues(unsigned char* buffer,
                                                      size_t length) {
  base::RandBytes(buffer, length);
}

void BlinkPlatformImpl::setSharedTimerFiredFunction(void (*func)()) {
  shared_timer_func_ = func;
}

void BlinkPlatformImpl::setSharedTimerFireInterval(
    double interval_seconds) {
  shared_timer_fire_time_ = interval_seconds + monotonicallyIncreasingTime();
  if (shared_timer_suspended_) {
    shared_timer_fire_time_was_set_while_suspended_ = true;
    return;
  }

  // By converting between double and int64 representation, we run the risk
  // of losing precision due to rounding errors. Performing computations in
  // microseconds reduces this risk somewhat. But there still is the potential
  // of us computing a fire time for the timer that is shorter than what we
  // need.
  // As the event loop will check event deadlines prior to actually firing
  // them, there is a risk of needlessly rescheduling events and of
  // needlessly looping if sleep times are too short even by small amounts.
  // This results in measurable performance degradation unless we use ceil() to
  // always round up the sleep times.
  int64 interval = static_cast<int64>(
      ceil(interval_seconds * base::Time::kMillisecondsPerSecond)
      * base::Time::kMicrosecondsPerMillisecond);

  if (interval < 0)
    interval = 0;

  shared_timer_.Stop();
  shared_timer_.Start(FROM_HERE, base::TimeDelta::FromMicroseconds(interval),
                      this, &BlinkPlatformImpl::DoTimeout);
}

void BlinkPlatformImpl::stopSharedTimer() {
  shared_timer_.Stop();
}

void BlinkPlatformImpl::callOnMainThread(
    void (*func)(void*), void* context) {
  main_loop_->PostTask(FROM_HERE, base::Bind(func, context));
}

bool BlinkPlatformImpl::isThreadedCompositingEnabled() {
  return true;
}

blink::WebCompositorSupport* BlinkPlatformImpl::compositorSupport() {
  return &compositor_support_;
}

blink::WebScrollbarBehavior* BlinkPlatformImpl::scrollbarBehavior() {
  return &scrollbar_behavior_;
}

const unsigned char* BlinkPlatformImpl::getTraceCategoryEnabledFlag(
    const char* category_name) {
  static const unsigned char buf[] = "*";
  return buf;
}

blink::WebData BlinkPlatformImpl::loadResource(const char* resource) {
  for (size_t i = 0; i < arraysize(kDataResources); ++i) {
    if (!strcmp(resource, kDataResources[i].name)) {
      int length;
      const char* data =
          blink_resource_map_.GetResource(kDataResources[i].id, &length);
      CHECK(data != nullptr && length > 0);
      return blink::WebData(data, length);
    }
  }
  NOTREACHED() << "Requested resource is unavailable!";
  return blink::WebData();
}

blink::WebURLLoader* BlinkPlatformImpl::createURLLoader() {
  return NULL;
}

blink::WebSocketHandle* BlinkPlatformImpl::createWebSocketHandle() {
  return NULL;
}

blink::WebString BlinkPlatformImpl::userAgent() {
  return blink::WebString::fromUTF8(kUserAgentString);
}

blink::WebData BlinkPlatformImpl::parseDataURL(
    const blink::WebURL& url,
    blink::WebString& mimetype_out,
    blink::WebString& charset_out) {
  std::string mimetype, charset, data;
  if (net::DataURL::Parse(url, &mimetype, &charset, &data)
      && net::IsSupportedMimeType(mimetype)) {
    mimetype_out = blink::WebString::fromUTF8(mimetype);
    charset_out = blink::WebString::fromUTF8(charset);
    return data;
  }
  return blink::WebData();
}

blink::WebURLError BlinkPlatformImpl::cancelledError(const blink::WebURL& url)
    const {
  blink::WebURLError error;
  error.domain = blink::WebString::fromUTF8(net::kErrorDomain);
  error.reason = net::ERR_ABORTED;
  error.unreachableURL = url;
  error.staleCopyInCache = false;
  error.isCancellation = true;
  return error;
}

blink::WebThread* BlinkPlatformImpl::createThread(const char* name) {
  return new WebThreadImpl(name);
}

blink::WebThread* BlinkPlatformImpl::currentThread() {
  WebThreadImplForMessageLoop* thread =
      static_cast<WebThreadImplForMessageLoop*>(current_thread_slot_.Get());
  if (thread)
    return (thread);

  scoped_refptr<base::MessageLoopProxy> message_loop =
      base::MessageLoopProxy::current();
  if (!message_loop.get())
    return NULL;

  thread = new WebThreadImplForMessageLoop(message_loop.get());
  current_thread_slot_.Set(thread);
  return thread;
}

void BlinkPlatformImpl::yieldCurrentThread() {
  base::PlatformThread::YieldCurrentThread();
}

blink::WebWaitableEvent* BlinkPlatformImpl::createWaitableEvent() {
  return new WebWaitableEventImpl();
}

blink::WebWaitableEvent* BlinkPlatformImpl::waitMultipleEvents(
    const blink::WebVector<blink::WebWaitableEvent*>& web_events) {
  std::vector<base::WaitableEvent*> events;
  for (size_t i = 0; i < web_events.size(); ++i)
    events.push_back(static_cast<WebWaitableEventImpl*>(web_events[i])->impl());
  size_t idx = base::WaitableEvent::WaitMany(
      vector_as_array(&events), events.size());
  DCHECK_LT(idx, web_events.size());
  return web_events[idx];
}

// static
void BlinkPlatformImpl::DestroyCurrentThread(void* thread) {
  WebThreadImplForMessageLoop* impl =
      static_cast<WebThreadImplForMessageLoop*>(thread);
  delete impl;
}

}  // namespace html_viewer
<commit_msg>Add logging for missing resource.<commit_after>// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "mojo/services/html_viewer/blink_platform_impl.h"

#include <cmath>

#include "base/rand_util.h"
#include "base/stl_util.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/platform_thread.h"
#include "base/time/time.h"
#include "mojo/services/html_viewer/blink_resource_constants.h"
#include "mojo/services/html_viewer/webthread_impl.h"
#include "net/base/data_url.h"
#include "net/base/mime_util.h"
#include "net/base/net_errors.h"
#include "third_party/WebKit/public/platform/WebWaitableEvent.h"

namespace html_viewer {
namespace {

// TODO(darin): Figure out what our UA should really be.
const char kUserAgentString[] =
  "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) "
  "Chrome/35.0.1916.153 Safari/537.36";

class WebWaitableEventImpl : public blink::WebWaitableEvent {
 public:
  WebWaitableEventImpl() : impl_(new base::WaitableEvent(false, false)) {}
  virtual ~WebWaitableEventImpl() {}

  virtual void wait() { impl_->Wait(); }
  virtual void signal() { impl_->Signal(); }

  base::WaitableEvent* impl() {
    return impl_.get();
  }

 private:
  scoped_ptr<base::WaitableEvent> impl_;
  DISALLOW_COPY_AND_ASSIGN(WebWaitableEventImpl);
};

}  // namespace

BlinkPlatformImpl::BlinkPlatformImpl()
    : main_loop_(base::MessageLoop::current()),
      shared_timer_func_(NULL),
      shared_timer_fire_time_(0.0),
      shared_timer_fire_time_was_set_while_suspended_(false),
      shared_timer_suspended_(0),
      current_thread_slot_(&DestroyCurrentThread),
      scheduler_(main_loop_->message_loop_proxy()) {
}

BlinkPlatformImpl::~BlinkPlatformImpl() {
}

blink::WebMimeRegistry* BlinkPlatformImpl::mimeRegistry() {
  return &mime_registry_;
}

blink::WebThemeEngine* BlinkPlatformImpl::themeEngine() {
  return &theme_engine_;
}

blink::WebScheduler* BlinkPlatformImpl::scheduler() {
  return &scheduler_;
}

blink::WebString BlinkPlatformImpl::defaultLocale() {
  return blink::WebString::fromUTF8("en-US");
}

double BlinkPlatformImpl::currentTime() {
  return base::Time::Now().ToDoubleT();
}

double BlinkPlatformImpl::monotonicallyIncreasingTime() {
  return base::TimeTicks::Now().ToInternalValue() /
      static_cast<double>(base::Time::kMicrosecondsPerSecond);
}

void BlinkPlatformImpl::cryptographicallyRandomValues(unsigned char* buffer,
                                                      size_t length) {
  base::RandBytes(buffer, length);
}

void BlinkPlatformImpl::setSharedTimerFiredFunction(void (*func)()) {
  shared_timer_func_ = func;
}

void BlinkPlatformImpl::setSharedTimerFireInterval(
    double interval_seconds) {
  shared_timer_fire_time_ = interval_seconds + monotonicallyIncreasingTime();
  if (shared_timer_suspended_) {
    shared_timer_fire_time_was_set_while_suspended_ = true;
    return;
  }

  // By converting between double and int64 representation, we run the risk
  // of losing precision due to rounding errors. Performing computations in
  // microseconds reduces this risk somewhat. But there still is the potential
  // of us computing a fire time for the timer that is shorter than what we
  // need.
  // As the event loop will check event deadlines prior to actually firing
  // them, there is a risk of needlessly rescheduling events and of
  // needlessly looping if sleep times are too short even by small amounts.
  // This results in measurable performance degradation unless we use ceil() to
  // always round up the sleep times.
  int64 interval = static_cast<int64>(
      ceil(interval_seconds * base::Time::kMillisecondsPerSecond)
      * base::Time::kMicrosecondsPerMillisecond);

  if (interval < 0)
    interval = 0;

  shared_timer_.Stop();
  shared_timer_.Start(FROM_HERE, base::TimeDelta::FromMicroseconds(interval),
                      this, &BlinkPlatformImpl::DoTimeout);
}

void BlinkPlatformImpl::stopSharedTimer() {
  shared_timer_.Stop();
}

void BlinkPlatformImpl::callOnMainThread(
    void (*func)(void*), void* context) {
  main_loop_->PostTask(FROM_HERE, base::Bind(func, context));
}

bool BlinkPlatformImpl::isThreadedCompositingEnabled() {
  return true;
}

blink::WebCompositorSupport* BlinkPlatformImpl::compositorSupport() {
  return &compositor_support_;
}

blink::WebScrollbarBehavior* BlinkPlatformImpl::scrollbarBehavior() {
  return &scrollbar_behavior_;
}

const unsigned char* BlinkPlatformImpl::getTraceCategoryEnabledFlag(
    const char* category_name) {
  static const unsigned char buf[] = "*";
  return buf;
}

blink::WebData BlinkPlatformImpl::loadResource(const char* resource) {
  for (size_t i = 0; i < arraysize(kDataResources); ++i) {
    if (!strcmp(resource, kDataResources[i].name)) {
      int length;
      const char* data =
          blink_resource_map_.GetResource(kDataResources[i].id, &length);
      CHECK(data != nullptr && length > 0);
      return blink::WebData(data, length);
    }
  }
  NOTREACHED() << "Requested resource is unavailable: " << resource;
  return blink::WebData();
}

blink::WebURLLoader* BlinkPlatformImpl::createURLLoader() {
  return NULL;
}

blink::WebSocketHandle* BlinkPlatformImpl::createWebSocketHandle() {
  return NULL;
}

blink::WebString BlinkPlatformImpl::userAgent() {
  return blink::WebString::fromUTF8(kUserAgentString);
}

blink::WebData BlinkPlatformImpl::parseDataURL(
    const blink::WebURL& url,
    blink::WebString& mimetype_out,
    blink::WebString& charset_out) {
  std::string mimetype, charset, data;
  if (net::DataURL::Parse(url, &mimetype, &charset, &data)
      && net::IsSupportedMimeType(mimetype)) {
    mimetype_out = blink::WebString::fromUTF8(mimetype);
    charset_out = blink::WebString::fromUTF8(charset);
    return data;
  }
  return blink::WebData();
}

blink::WebURLError BlinkPlatformImpl::cancelledError(const blink::WebURL& url)
    const {
  blink::WebURLError error;
  error.domain = blink::WebString::fromUTF8(net::kErrorDomain);
  error.reason = net::ERR_ABORTED;
  error.unreachableURL = url;
  error.staleCopyInCache = false;
  error.isCancellation = true;
  return error;
}

blink::WebThread* BlinkPlatformImpl::createThread(const char* name) {
  return new WebThreadImpl(name);
}

blink::WebThread* BlinkPlatformImpl::currentThread() {
  WebThreadImplForMessageLoop* thread =
      static_cast<WebThreadImplForMessageLoop*>(current_thread_slot_.Get());
  if (thread)
    return (thread);

  scoped_refptr<base::MessageLoopProxy> message_loop =
      base::MessageLoopProxy::current();
  if (!message_loop.get())
    return NULL;

  thread = new WebThreadImplForMessageLoop(message_loop.get());
  current_thread_slot_.Set(thread);
  return thread;
}

void BlinkPlatformImpl::yieldCurrentThread() {
  base::PlatformThread::YieldCurrentThread();
}

blink::WebWaitableEvent* BlinkPlatformImpl::createWaitableEvent() {
  return new WebWaitableEventImpl();
}

blink::WebWaitableEvent* BlinkPlatformImpl::waitMultipleEvents(
    const blink::WebVector<blink::WebWaitableEvent*>& web_events) {
  std::vector<base::WaitableEvent*> events;
  for (size_t i = 0; i < web_events.size(); ++i)
    events.push_back(static_cast<WebWaitableEventImpl*>(web_events[i])->impl());
  size_t idx = base::WaitableEvent::WaitMany(
      vector_as_array(&events), events.size());
  DCHECK_LT(idx, web_events.size());
  return web_events[idx];
}

// static
void BlinkPlatformImpl::DestroyCurrentThread(void* thread) {
  WebThreadImplForMessageLoop* impl =
      static_cast<WebThreadImplForMessageLoop*>(thread);
  delete impl;
}

}  // namespace html_viewer
<|endoftext|>


<commit_before>// @(#)root/editline:$Id$
// Author: Mary-Louise Gill, 2009

/*************************************************************************
 * Copyright (C) 1995-2011, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "Getline_color.h"

#include <stack>
#include <string>

#include "TROOT.h"
#include "TInterpreter.h"
#include "textinput/Range.h"
#include "textinput/Text.h"

using namespace std;
using namespace textinput;

namespace {

   Color ColorFromName(const char* name) {
      // Convert a color name to a Color.
      Color ret;

      std::string lowname(name);
      size_t lenname = strlen(name);
      for (size_t i = 0; i < lenname; ++i)
         lowname[i] = tolower(lowname[i]);

      if (lowname.find("bold") != std::string::npos
          || lowname.find("light") != std::string::npos)
         ret.fModifiers |= Color::kModBold;
      if (lowname.find("under") != std::string::npos)
         ret.fModifiers |= Color::kModUnderline;

      size_t poshash = lowname.find('#');
      size_t lenrgb = 0;
      if (poshash != std::string::npos) {
         int endrgb = poshash + 1;
         while ((lowname[endrgb] >= '0' && lowname[endrgb] <= '9')
                || (lowname[endrgb] >= 'a' && lowname[endrgb] <= 'f')) {
            ++endrgb;
         }
         lenrgb = endrgb - poshash - 1;
      }

      int rgb[3] = {0};
      if (lenrgb == 3) {
         for (int i = 0; i < 3; ++i) {
            rgb[i] = lowname[poshash + 1 + i] - '0';
            if (rgb[i] > 9) {
               rgb[i] = rgb[i] + '0' - 'a' + 10;
            }
            rgb[i] *= 16; // only upper 4 bits are set.
         }
         return ret;
      } else if (lenrgb == 6) {
         for (int i = 0; i < 6; ++i) {
            int v = lowname[poshash + 1 + i] - '0';
            if (v > 9) {
               v = v + '0' - 'a' + 10;
            }
            if (i % 2 == 0) {
               v *= 16;
            }
            rgb[i / 2] += v;
         }
         ret.fR = rgb[0];
         ret.fG = rgb[1];
         ret.fB = rgb[2];
         return ret;
      } else {
         if (lowname.find("default") != std::string::npos) {
            return ret;
         }

         static const char* colornames[] = {
            "black", "red", "green", "yellow",
            "blue", "magenta", "cyan", "white", 0
         };
         static const unsigned char colorrgb[][3] = {
            {0,0,0}, {127,0,0}, {0,127,0}, {127,127,0},
            {0,0,127}, {127,0,127}, {0,127,127}, {127,127,127},
            {0}
         };

         for (int i = 0; colornames[i]; ++i) {
            if (lowname.find(colornames[i]) != std::string::npos) {
               int boldify = 0;
               if (ret.fModifiers & Color::kModBold)
                  boldify = 64;
               ret.fR = colorrgb[i][0] + boldify;
               ret.fG = colorrgb[i][1] + boldify;
               ret.fB = colorrgb[i][2] + boldify;
               return ret;
            }
         }
      }
      fprintf(stderr, "Getline_color/ColorFromName: cannot parse color %s!\n", name);
      return Color();
   } // ColorFromName()

   bool IsAlnum_(char c) { return c == '_' || isalnum(c); }
   bool IsAlpha_(char c) { return c == '_' || isalpha(c); }
} // unnamed namespace

ROOT::TextInputColorizer::TextInputColorizer():
   fColorIsDefault(), fPrevBracketColor(kColorNone) {
   // Set the default colors.
   // fColors[kColorNone] stays default initialized.
   fColors[kColorType] = ColorFromName("blue");
   fColors[kColorTabComp] = ColorFromName("magenta");
   fColors[kColorBracket] = ColorFromName("green");
   fColors[kColorBadBracket] = ColorFromName("red");
   fColors[kColorPrompt] = ColorFromName("default");
   fColorIsDefault[kColorPrompt] = true;
}

ROOT::TextInputColorizer::~TextInputColorizer() {
   // pin vtable
}

void ROOT::TextInputColorizer::ExtendRangeAndSetColor(Text& input,
                                                      size_t idx, char col,
                                                      Range& disp) {
   // Utility function that updates the display modification range if the
   // color at index idx is different from what it was before.

   if (fColorIsDefault[(int)col]) {
      // Never mind the color: use use default.
      col = 0;
   }
   if (input.GetColor(idx) != col) {
      input.SetColor(idx, col);
      disp.Extend(idx);
   }
}

bool ROOT::TextInputColorizer::GetColor(char type, Color& col) {
   // Set the Color corresponding to an entry in EColorTypes.
   // Returns false if the type index is out of range.

   if (type < (int)kNumColors) {
      col = fColors[(size_t)type];
      return true;
   }
   col = Color();
   return false;
}

void ROOT::TextInputColorizer::SetColors(const char* colorType,
                                         const char* colorTabComp,
                                         const char* colorBracket,
                                         const char* colorBadBracket,
                                         const char* colorPrompt) {
   // Set the colors of the different items as either
   // #RGB
   // #RRGGBB or
   // color name, optionally prepended by "underline" or "bold"

   fColors[kColorType] = ColorFromName(colorType);
   fColorIsDefault[kColorType] = (fColors[kColorType] == Color());
   fColors[kColorTabComp] = ColorFromName(colorTabComp);
   fColorIsDefault[kColorTabComp] = (fColors[kColorTabComp] == Color());
   fColors[kColorBracket] = ColorFromName(colorBracket);
   fColorIsDefault[kColorBracket] = (fColors[kColorBracket] == Color());
   fColors[kColorBadBracket] = ColorFromName(colorBadBracket);
   fColorIsDefault[kColorBadBracket] = (fColors[kColorBadBracket] == Color());
   fColors[kColorPrompt] = ColorFromName(colorPrompt);
   fColorIsDefault[kColorPrompt] = (fColors[kColorPrompt] == Color());
}

void ROOT::TextInputColorizer::ProcessTextChange(EditorRange& Modification,
                                                 Text& input) {
   // The text has changed; look for word that are types.

   const std::string& text = input.GetText();

   size_t modStart = Modification.fEdit.fStart;
   size_t inputLength = input.length();

   // Find end of modified word:
   size_t modEnd = Modification.fEdit.fLength;
   if (modEnd == (size_t) -1) {
      modEnd = inputLength;
   } else {
      modEnd += modStart;
      if (modEnd > inputLength) {
         modEnd = inputLength;
      } else {
         while (modEnd < inputLength && IsAlnum_(text[modEnd]))
            ++modEnd;
      }
   }

   // Find beginning of modified word. Don't treat
   // "12ull" specially, it will fall out below.
   while (modStart && IsAlnum_(text[modStart])) --modStart;

   // Ignore spaces
   while (modStart < modEnd && isspace(text[modStart]))
      ++modStart;
   while (modEnd > modStart && isspace(text[modEnd]))
      --modStart;

   for (size_t i = modStart; i < modEnd;) {
      // i points to beginning of word here.
      if (isdigit(text[i])) {
         // "12", or "12ull". Default color.
         ExtendRangeAndSetColor(input, i, 0, Modification.fDisplay);
         ++i;
         while (i < modEnd && IsAlnum_(text[i])) {
            ExtendRangeAndSetColor(input, i, 0, Modification.fDisplay);
            ++i;
         }
      } else if (IsAlpha_(text[i])) {
         // identifier, but is it a type?
         size_t wordLen = 1;
         while (i + wordLen < modEnd && IsAlnum_(text[i + wordLen])) {
            ++wordLen;
         }
         std::string word = text.substr(i, wordLen);
         char color = kColorNone;
         if (gROOT->GetListOfTypes()->FindObject(word.c_str())
             || gInterpreter->CheckClassInfo(word.c_str(), kFALSE)) {
            color = kColorType;
         }
         for (size_t ic = i; ic < i + wordLen; ++ic) {
            ExtendRangeAndSetColor(input, ic, color, Modification.fDisplay);
         }
         i += wordLen;
      } else {
         size_t wordLen = 1;
         while (i + wordLen < modEnd && !IsAlnum_(text[i + wordLen]))
            ++wordLen;
         for (size_t ic = i; ic < i + wordLen; ++ic) {
            // protect colored parens
            char oldColor = input.GetColor(ic);
            if (oldColor != kColorBracket && oldColor != kColorBadBracket) {
               ExtendRangeAndSetColor(input, ic, kColorNone, Modification.fDisplay);
            }
         }
         i += wordLen;
      }

      // skip trailing whitespace.
      while (i < modEnd && isspace(text[i])) {
         ExtendRangeAndSetColor(input, i, kColorNone, Modification.fDisplay);
         ++i;
      }
   }
}

void ROOT::TextInputColorizer::ProcessPromptChange(Text& prompt) {
   int idx = kColorPrompt;
   if (fColorIsDefault[kColorPrompt]) {
      idx = 0;
   }
   prompt.SetColor(Range::AllText(), idx);
}

void ROOT::TextInputColorizer::ProcessCursorChange(size_t Cursor,
                                                   Text& input,
                                                   Range& DisplayR) {
   // Check each char to see if it is an opening bracket,
   // if so, check for its closing one and color them green.

   static const int numBrackets = 3;
   static const char bTypes[numBrackets][3] = {"()", "{}", "[]"};

   if (input.empty()) return;

   if (fPrevBracketColor != kColorNone) {
      // Remove previous bracket coloring.
      const char* colors = &input.GetColors()[0];
      const char* prevBracket = (const char*) memchr(colors, fPrevBracketColor,
                                                     input.length());
      if (prevBracket) {
         ExtendRangeAndSetColor(input, prevBracket - colors, kColorNone, DisplayR);
         if (fPrevBracketColor == kColorBracket) {
            // There will be two.
            prevBracket = (const char*) memchr(prevBracket, fPrevBracketColor,
                                               input.length() - (prevBracket - colors));
            if (prevBracket) {
               ExtendRangeAndSetColor(input, prevBracket - colors, kColorNone,
                                      DisplayR);
            }
         }
      }
   }

   // locations of brackets
   stack<size_t> locBrackets;
   int foundParenIdx = -1;
   int parenType = 0;
   const std::string& text = input.GetText();

   if (Cursor < input.length()) {
      // check against each bracket type
      for (; parenType < numBrackets; parenType++) {
         // if current char is equal to opening bracket, push onto stack
         if (text[Cursor] == bTypes[parenType][0]) {
            locBrackets.push(Cursor);
            foundParenIdx = 0;
            break;
         } else if (text[Cursor] == bTypes[parenType][1]) {
            locBrackets.push(Cursor);
            foundParenIdx = 1;
            break;
         }
      }
   }

   // current cursor char is not an open bracket, and there is a previous char
   // to check
   if (foundParenIdx == -1 && Cursor > 0) {
      // check previously typed char for being a closing bracket
      --Cursor;
      // check against each bracket type
      parenType = 0;

      for (; parenType < numBrackets; parenType++) {
         // if current char is equal to closing bracket, push onto stack
         if (text[Cursor] == bTypes[parenType][1]) {
            locBrackets.push(Cursor);
            foundParenIdx = 1;
            break;
         }
      }
   }
   // no bracket found on either current or previous char, return.
   if (foundParenIdx == -1) {
      return;
   }

   // terate through remaining letters until find a matching closing bracket
   // if another open bracket of the same type is found, push onto stack
   // and pop on next closing bracket match
   int direction = 1;

   if (foundParenIdx == 1) {
      direction = -1;
   }

   size_t lenLine = input.length();
   // direction == -1: Cursor - 1 to front.
   size_t scanBegin = (Cursor > 0) ? Cursor - 1 : 0;
   size_t scanLast = 0;
   if (direction == 1) {
      // direction == 1: Cursor + 1 to end.
      scanBegin = Cursor + 1;
      scanLast = lenLine - 1;
      if (scanBegin > scanLast) return;
   }
   for (size_t i = scanBegin; true /*avoid "unsigned >= 0" condition*/; i += direction) {
      // if current char is equal to another opening bracket, push onto stack
      if (text[i] == bTypes[parenType][foundParenIdx]) {
         // push index of bracket
         locBrackets.push(i);
      }
      // if current char is equal to closing bracket
      else if (text[i] == bTypes[parenType][1 - foundParenIdx]) {
         // pop previous opening bracket off stack
         locBrackets.pop();
         // if previous opening was the last entry and we are at the cursor, then highlight match
         if (locBrackets.empty()) {
            ExtendRangeAndSetColor(input, i, kColorBracket, DisplayR);
            ExtendRangeAndSetColor(input, Cursor, kColorBracket, DisplayR);
            fPrevBracketColor = kColorBracket;
            break;
         }
      }
      // loop termination check before possible underflow ("--0")
      if (i == scanLast) break;
   }

   if (!locBrackets.empty()) {
      ExtendRangeAndSetColor(input, Cursor, kColorBadBracket, DisplayR);
      fPrevBracketColor = kColorBadBracket;
   }

} // matchParentheses
<commit_msg>Don't use CheckClassInfo() which might trigger autoloading. Instead, use GetListOfClasses() for classes that don't have a rootmap file but are loaded, and TInterpreter::GetClassSharedLibs() for classes that are not yet loaded but have a rootmap entry.<commit_after>// @(#)root/editline:$Id$
// Author: Mary-Louise Gill, 2009

/*************************************************************************
 * Copyright (C) 1995-2011, Rene Brun and Fons Rademakers.               *
 * All rights reserved.                                                  *
 *                                                                       *
 * For the licensing terms see $ROOTSYS/LICENSE.                         *
 * For the list of contributors see $ROOTSYS/README/CREDITS.             *
 *************************************************************************/

#include "Getline_color.h"

#include <stack>
#include <string>

#include "TROOT.h"
#include "TInterpreter.h"
#include "textinput/Range.h"
#include "textinput/Text.h"

using namespace std;
using namespace textinput;

namespace {

   Color ColorFromName(const char* name) {
      // Convert a color name to a Color.
      Color ret;

      std::string lowname(name);
      size_t lenname = strlen(name);
      for (size_t i = 0; i < lenname; ++i)
         lowname[i] = tolower(lowname[i]);

      if (lowname.find("bold") != std::string::npos
          || lowname.find("light") != std::string::npos)
         ret.fModifiers |= Color::kModBold;
      if (lowname.find("under") != std::string::npos)
         ret.fModifiers |= Color::kModUnderline;

      size_t poshash = lowname.find('#');
      size_t lenrgb = 0;
      if (poshash != std::string::npos) {
         int endrgb = poshash + 1;
         while ((lowname[endrgb] >= '0' && lowname[endrgb] <= '9')
                || (lowname[endrgb] >= 'a' && lowname[endrgb] <= 'f')) {
            ++endrgb;
         }
         lenrgb = endrgb - poshash - 1;
      }

      int rgb[3] = {0};
      if (lenrgb == 3) {
         for (int i = 0; i < 3; ++i) {
            rgb[i] = lowname[poshash + 1 + i] - '0';
            if (rgb[i] > 9) {
               rgb[i] = rgb[i] + '0' - 'a' + 10;
            }
            rgb[i] *= 16; // only upper 4 bits are set.
         }
         return ret;
      } else if (lenrgb == 6) {
         for (int i = 0; i < 6; ++i) {
            int v = lowname[poshash + 1 + i] - '0';
            if (v > 9) {
               v = v + '0' - 'a' + 10;
            }
            if (i % 2 == 0) {
               v *= 16;
            }
            rgb[i / 2] += v;
         }
         ret.fR = rgb[0];
         ret.fG = rgb[1];
         ret.fB = rgb[2];
         return ret;
      } else {
         if (lowname.find("default") != std::string::npos) {
            return ret;
         }

         static const char* colornames[] = {
            "black", "red", "green", "yellow",
            "blue", "magenta", "cyan", "white", 0
         };
         static const unsigned char colorrgb[][3] = {
            {0,0,0}, {127,0,0}, {0,127,0}, {127,127,0},
            {0,0,127}, {127,0,127}, {0,127,127}, {127,127,127},
            {0}
         };

         for (int i = 0; colornames[i]; ++i) {
            if (lowname.find(colornames[i]) != std::string::npos) {
               int boldify = 0;
               if (ret.fModifiers & Color::kModBold)
                  boldify = 64;
               ret.fR = colorrgb[i][0] + boldify;
               ret.fG = colorrgb[i][1] + boldify;
               ret.fB = colorrgb[i][2] + boldify;
               return ret;
            }
         }
      }
      fprintf(stderr, "Getline_color/ColorFromName: cannot parse color %s!\n", name);
      return Color();
   } // ColorFromName()

   bool IsAlnum_(char c) { return c == '_' || isalnum(c); }
   bool IsAlpha_(char c) { return c == '_' || isalpha(c); }
} // unnamed namespace

ROOT::TextInputColorizer::TextInputColorizer():
   fColorIsDefault(), fPrevBracketColor(kColorNone) {
   // Set the default colors.
   // fColors[kColorNone] stays default initialized.
   fColors[kColorType] = ColorFromName("blue");
   fColors[kColorTabComp] = ColorFromName("magenta");
   fColors[kColorBracket] = ColorFromName("green");
   fColors[kColorBadBracket] = ColorFromName("red");
   fColors[kColorPrompt] = ColorFromName("default");
   fColorIsDefault[kColorPrompt] = true;
}

ROOT::TextInputColorizer::~TextInputColorizer() {
   // pin vtable
}

void ROOT::TextInputColorizer::ExtendRangeAndSetColor(Text& input,
                                                      size_t idx, char col,
                                                      Range& disp) {
   // Utility function that updates the display modification range if the
   // color at index idx is different from what it was before.

   if (fColorIsDefault[(int)col]) {
      // Never mind the color: use use default.
      col = 0;
   }
   if (input.GetColor(idx) != col) {
      input.SetColor(idx, col);
      disp.Extend(idx);
   }
}

bool ROOT::TextInputColorizer::GetColor(char type, Color& col) {
   // Set the Color corresponding to an entry in EColorTypes.
   // Returns false if the type index is out of range.

   if (type < (int)kNumColors) {
      col = fColors[(size_t)type];
      return true;
   }
   col = Color();
   return false;
}

void ROOT::TextInputColorizer::SetColors(const char* colorType,
                                         const char* colorTabComp,
                                         const char* colorBracket,
                                         const char* colorBadBracket,
                                         const char* colorPrompt) {
   // Set the colors of the different items as either
   // #RGB
   // #RRGGBB or
   // color name, optionally prepended by "underline" or "bold"

   fColors[kColorType] = ColorFromName(colorType);
   fColorIsDefault[kColorType] = (fColors[kColorType] == Color());
   fColors[kColorTabComp] = ColorFromName(colorTabComp);
   fColorIsDefault[kColorTabComp] = (fColors[kColorTabComp] == Color());
   fColors[kColorBracket] = ColorFromName(colorBracket);
   fColorIsDefault[kColorBracket] = (fColors[kColorBracket] == Color());
   fColors[kColorBadBracket] = ColorFromName(colorBadBracket);
   fColorIsDefault[kColorBadBracket] = (fColors[kColorBadBracket] == Color());
   fColors[kColorPrompt] = ColorFromName(colorPrompt);
   fColorIsDefault[kColorPrompt] = (fColors[kColorPrompt] == Color());
}

void ROOT::TextInputColorizer::ProcessTextChange(EditorRange& Modification,
                                                 Text& input) {
   // The text has changed; look for word that are types.

   const std::string& text = input.GetText();

   size_t modStart = Modification.fEdit.fStart;
   size_t inputLength = input.length();

   // Find end of modified word:
   size_t modEnd = Modification.fEdit.fLength;
   if (modEnd == (size_t) -1) {
      modEnd = inputLength;
   } else {
      modEnd += modStart;
      if (modEnd > inputLength) {
         modEnd = inputLength;
      } else {
         while (modEnd < inputLength && IsAlnum_(text[modEnd]))
            ++modEnd;
      }
   }

   // Find beginning of modified word. Don't treat
   // "12ull" specially, it will fall out below.
   while (modStart && IsAlnum_(text[modStart])) --modStart;

   // Ignore spaces
   while (modStart < modEnd && isspace(text[modStart]))
      ++modStart;
   while (modEnd > modStart && isspace(text[modEnd]))
      --modStart;

   for (size_t i = modStart; i < modEnd;) {
      // i points to beginning of word here.
      if (isdigit(text[i])) {
         // "12", or "12ull". Default color.
         ExtendRangeAndSetColor(input, i, 0, Modification.fDisplay);
         ++i;
         while (i < modEnd && IsAlnum_(text[i])) {
            ExtendRangeAndSetColor(input, i, 0, Modification.fDisplay);
            ++i;
         }
      } else if (IsAlpha_(text[i])) {
         // identifier, but is it a type?
         size_t wordLen = 1;
         while (i + wordLen < modEnd && IsAlnum_(text[i + wordLen])) {
            ++wordLen;
         }
         std::string word = text.substr(i, wordLen);
         char color = kColorNone;
         if (gROOT->GetListOfTypes()->FindObject(word.c_str())
             || gROOT->GetListOfClasses()->FindObject(word.c_str())
             || gInterpreter->GetClassSharedLibs(word.c_str())) {
            color = kColorType;
         }
         for (size_t ic = i; ic < i + wordLen; ++ic) {
            ExtendRangeAndSetColor(input, ic, color, Modification.fDisplay);
         }
         i += wordLen;
      } else {
         size_t wordLen = 1;
         while (i + wordLen < modEnd && !IsAlnum_(text[i + wordLen]))
            ++wordLen;
         for (size_t ic = i; ic < i + wordLen; ++ic) {
            // protect colored parens
            char oldColor = input.GetColor(ic);
            if (oldColor != kColorBracket && oldColor != kColorBadBracket) {
               ExtendRangeAndSetColor(input, ic, kColorNone, Modification.fDisplay);
            }
         }
         i += wordLen;
      }

      // skip trailing whitespace.
      while (i < modEnd && isspace(text[i])) {
         ExtendRangeAndSetColor(input, i, kColorNone, Modification.fDisplay);
         ++i;
      }
   }
}

void ROOT::TextInputColorizer::ProcessPromptChange(Text& prompt) {
   int idx = kColorPrompt;
   if (fColorIsDefault[kColorPrompt]) {
      idx = 0;
   }
   prompt.SetColor(Range::AllText(), idx);
}

void ROOT::TextInputColorizer::ProcessCursorChange(size_t Cursor,
                                                   Text& input,
                                                   Range& DisplayR) {
   // Check each char to see if it is an opening bracket,
   // if so, check for its closing one and color them green.

   static const int numBrackets = 3;
   static const char bTypes[numBrackets][3] = {"()", "{}", "[]"};

   if (input.empty()) return;

   if (fPrevBracketColor != kColorNone) {
      // Remove previous bracket coloring.
      const char* colors = &input.GetColors()[0];
      const char* prevBracket = (const char*) memchr(colors, fPrevBracketColor,
                                                     input.length());
      if (prevBracket) {
         ExtendRangeAndSetColor(input, prevBracket - colors, kColorNone, DisplayR);
         if (fPrevBracketColor == kColorBracket) {
            // There will be two.
            prevBracket = (const char*) memchr(prevBracket, fPrevBracketColor,
                                               input.length() - (prevBracket - colors));
            if (prevBracket) {
               ExtendRangeAndSetColor(input, prevBracket - colors, kColorNone,
                                      DisplayR);
            }
         }
      }
   }

   // locations of brackets
   stack<size_t> locBrackets;
   int foundParenIdx = -1;
   int parenType = 0;
   const std::string& text = input.GetText();

   if (Cursor < input.length()) {
      // check against each bracket type
      for (; parenType < numBrackets; parenType++) {
         // if current char is equal to opening bracket, push onto stack
         if (text[Cursor] == bTypes[parenType][0]) {
            locBrackets.push(Cursor);
            foundParenIdx = 0;
            break;
         } else if (text[Cursor] == bTypes[parenType][1]) {
            locBrackets.push(Cursor);
            foundParenIdx = 1;
            break;
         }
      }
   }

   // current cursor char is not an open bracket, and there is a previous char
   // to check
   if (foundParenIdx == -1 && Cursor > 0) {
      // check previously typed char for being a closing bracket
      --Cursor;
      // check against each bracket type
      parenType = 0;

      for (; parenType < numBrackets; parenType++) {
         // if current char is equal to closing bracket, push onto stack
         if (text[Cursor] == bTypes[parenType][1]) {
            locBrackets.push(Cursor);
            foundParenIdx = 1;
            break;
         }
      }
   }
   // no bracket found on either current or previous char, return.
   if (foundParenIdx == -1) {
      return;
   }

   // terate through remaining letters until find a matching closing bracket
   // if another open bracket of the same type is found, push onto stack
   // and pop on next closing bracket match
   int direction = 1;

   if (foundParenIdx == 1) {
      direction = -1;
   }

   size_t lenLine = input.length();
   // direction == -1: Cursor - 1 to front.
   size_t scanBegin = (Cursor > 0) ? Cursor - 1 : 0;
   size_t scanLast = 0;
   if (direction == 1) {
      // direction == 1: Cursor + 1 to end.
      scanBegin = Cursor + 1;
      scanLast = lenLine - 1;
      if (scanBegin > scanLast) return;
   }
   for (size_t i = scanBegin; true /*avoid "unsigned >= 0" condition*/; i += direction) {
      // if current char is equal to another opening bracket, push onto stack
      if (text[i] == bTypes[parenType][foundParenIdx]) {
         // push index of bracket
         locBrackets.push(i);
      }
      // if current char is equal to closing bracket
      else if (text[i] == bTypes[parenType][1 - foundParenIdx]) {
         // pop previous opening bracket off stack
         locBrackets.pop();
         // if previous opening was the last entry and we are at the cursor, then highlight match
         if (locBrackets.empty()) {
            ExtendRangeAndSetColor(input, i, kColorBracket, DisplayR);
            ExtendRangeAndSetColor(input, Cursor, kColorBracket, DisplayR);
            fPrevBracketColor = kColorBracket;
            break;
         }
      }
      // loop termination check before possible underflow ("--0")
      if (i == scanLast) break;
   }

   if (!locBrackets.empty()) {
      ExtendRangeAndSetColor(input, Cursor, kColorBadBracket, DisplayR);
      fPrevBracketColor = kColorBadBracket;
   }

} // matchParentheses
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/perv/p9_sbe_chiplet_reset.H $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2017                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
//------------------------------------------------------------------------------
/// @file  p9_sbe_chiplet_reset.H
///
/// @brief Identify all good chiplets excluding EQ/EC
/// Setup multicast groups for all chiplets
/// For all good chiplets excluding EQ/EC
/// For all enabled chiplets
// *!
// *! OWNER NAME  : Abhishek Agarwal  Email: abagarw8@in.ibm.com
// *! BACKUP NAME :                   Email:
//------------------------------------------------------------------------------
// *HWP HWP Owner   : Abhishek Agarwal <abagarw8@in.ibm.com>
// *HWP FW Owner    : Brian Silver <bsilver@us.ibm.com>
// *HWP Team        : Perv
// *HWP Level       : 1
// *HWP Consumed by : SBE
//------------------------------------------------------------------------------

#ifndef _P9_SBE_CHIPLET_RESET_H_
#define _P9_SBE_CHIPLET_RESET_H_

#include <fapi2.H>

typedef fapi2::ReturnCode (*p9_sbe_chiplet_reset_FP_t)(const
        fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>&);

/// @brief Identify all good chiplets excluding EQ/EC
///      -- All chiplets will be reset and PLLs started
///      -- Partial bad - All nest Chiplets must be good, MC, IO can be partial bad
/// Setup multicast groups for all chiplets
///      -- Can't use the multicast for all non-nest chiplets
///      -- This is intended to be the eventual product setting
///      -- This includes the core/cache chiplets
/// For all good chiplets excluding EQ/EC
///      -- Setup Chiplet GP3 regs
///          -- Reset to default state
///          -- Set chiplet enable on all all good chiplets excluding EQ/EC
/// For all enabled chiplets
///      -- Start vital clocks and release endpoint reset
///      -- PCB Slave error register Reset
///
///
/// @param[in]     i_target_chip   Reference to TARGET_TYPE_PROC_CHIP target
/// @return  FAPI2_RC_SUCCESS if success, else error code.
extern "C"
{
    fapi2::ReturnCode p9_sbe_chiplet_reset(const
                                           fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target_chip);
}

#endif
<commit_msg>Level 2 Procedure - p9_sbe_chiplet_reset<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/import/chips/p9/procedures/hwp/perv/p9_sbe_chiplet_reset.H $ */
/*                                                                        */
/* OpenPOWER HostBoot Project                                             */
/*                                                                        */
/* Contributors Listed Below - COPYRIGHT 2015,2017                        */
/* [+] International Business Machines Corp.                              */
/*                                                                        */
/*                                                                        */
/* 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.                         */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
//------------------------------------------------------------------------------
/// @file  p9_sbe_chiplet_reset.H
///
/// @brief Steps:-
///     1) Identify Partical good chiplet and configure Multicasting register
///     2) Similar way, Configure hang pulse counter for Nest/MC/OBus/XBus/PCIe
///     3) Similar way,  set fence for Nest and MC chiplet
///     4) Similar way,  Reset sys.config and OPCG setting for Nest and MC chiplet in sync mode
///
/// Done
//------------------------------------------------------------------------------
// *HWP HW Owner        : Abhishek Agarwal <abagarw8@in.ibm.com>
// *HWP HW Backup Owner : Srinivas V. Naga <srinivan@in.ibm.com>
// *HWP FW Owner        : Brian Silver <bsilver@us.ibm.com>
// *HWP Team            : Perv
// *HWP Level           : 2
// *HWP Consumed by     : SBE
//------------------------------------------------------------------------------

#ifndef _P9_SBE_CHIPLET_RESET_H_
#define _P9_SBE_CHIPLET_RESET_H_

#include <fapi2.H>

namespace p9SbeChipletReset
{
enum P9_SBE_CHIPLET_RESET_Public_Constants
{
    MCGR0_CNFG_SETTINGS = 0xE0001C0000000000ull,
    MCGR1_CNFG_SETTINGS = 0xE4001C0000000000ull,
    MCGR2_CNFG_SETTINGS = 0xE8001C0000000000ull,
    MCGR3_CNFG_SETTINGS = 0xEC001C0000000000ull,
    NET_CNTL0_HW_INIT_VALUE = 0x7C16222000000000ull,
    HANG_PULSE_0X10 = 0x10,
    HANG_PULSE_0X0F = 0x0F,
    HANG_PULSE_0X06 = 0x06,
    HANG_PULSE_0X17 = 0x18,
    HANG_PULSE_0X18 = 0x18,
    HANG_PULSE_0X22 = 0x22,
    HANG_PULSE_0X13 = 0x13,
    HANG_PULSE_0X03 = 0x03,
    OPCG_ALIGN_SETTING = 0x5000000000003020ull,
    INOP_ALIGN_SETTING_0X9 = 0x9,
    OPCG_WAIT_CYCLE_0X020 = 0x020,
    SCAN_RATIO_0X3 = 0x3,
    SYNC_PULSE_DELAY_0X0 = 0X00,
    SYNC_CONFIG_DEFAULT = 0X0000000000000000,
    HANG_PULSE_0X00 = 0x00,
    HANG_PULSE_0X01 = 0x01,
    HANG_PULSE_0X04 = 0x04,
    HANG_PULSE_0X1A = 0x1A,
    NET_CNTL1_HW_INIT_VALUE = 0x6000000000000000ull
};
}

typedef fapi2::ReturnCode (*p9_sbe_chiplet_reset_FP_t)(const
        fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>&);

/// @brief Identify all good chiplets excluding EQ/EC
///  -- All chiplets will be reset and PLLs started
///  -- Partial bad - All nest Chiplets must be good, MC, IO can be partial bad
/// Setup multicast groups for all chiplets
///  -- Can't use the multicast for all non-nest chiplets
///  -- This is intended to be the eventual product setting
///  -- This includes the core/cache chiplets
/// For all good chiplets excluding EQ/EC
/// -- Setup Chiplet GP3 regs
///  -- Reset to default state
///  -- Set chiplet enable on all all good chiplets excluding EQ/EC
/// For all enabled chiplets excluding EQ/EC/Buses
///  -- Start vital clocks and release endpoint reset
///  -- PCB Slave error register Reset
///
///
/// @param[in]     i_target_chip   Reference to TARGET_TYPE_PROC_CHIP target
/// @return  FAPI2_RC_SUCCESS if success, else error code.
extern "C"
{
    fapi2::ReturnCode p9_sbe_chiplet_reset(const
                                           fapi2::Target<fapi2::TARGET_TYPE_PROC_CHIP>& i_target_chip);
}

#endif
<|endoftext|>