<commit_before>/*************************************************************************************
 *  Copyright (C) 2012 by Alejandro Fiestas Olivares <afiestas@kde.org>              *
 *                                                                                *
 *  This program is free software; you can redistribute it and/or                    *
 *  modify it under the terms of the GNU General Public License                      *
 *  as published by the Free Software Foundation; either version 2                   *
 *  of the License, or (at your option) any later version.                           *
 *                                                                                *
 *  This program is distributed in the hope that it will be useful,                  *
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of                   *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                    *
 *  GNU General Public License for more details.                                     *
 *                                                                                *
 *  You should have received a copy of the GNU General Public License                *
 *  along with this program; if not, write to the Free Software                      *
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA   *
 *************************************************************************************/

#include "serializer.h"

#include <QtCore/QStringList>
#include <QtCore/QCryptographicHash>
#include <QtCore/QFile>
#include <QtCore/QVariant>
#include <QtCore/QVariantList>
#include <QtCore/QVariantMap>
#include <QtCore/QDebug>

#include <qjson/serializer.h>
#include <qjson/parser.h>

#include <kscreen/config.h>
#include <kscreen/output.h>
#include <kscreen/edid.h>
#include <KStandardDirs>

QString Serializer::currentId()
{
    KScreen::OutputList outputs = KScreen::Config::current()->outputs();

    QStringList hashList;
    Q_FOREACH(const KScreen::Output* output, outputs) {
        if (!output->isConnected()) {
            continue;
        }
        hashList.insert(0, output->edid()->hash());
    }

    qSort(hashList.begin(), hashList.end());

    QCryptographicHash hash(QCryptographicHash::Md5);
    hash.addData(hashList.join(QString()).toAscii());
    return hash.result().toHex();
}

bool Serializer::configExists()
{
    return Serializer::configExists(Serializer::currentId());
}

bool Serializer::configExists(const QString& id)
{
    QString path = KStandardDirs::locateLocal("data", "kscreen/"+id);
    return QFile::exists(path);
}

KScreen::Config* Serializer::config(const QString& id)
{
    QJson::Parser parser;
    KScreen::Config* config = KScreen::Config::current();
    if (!config) {
        return 0;
    }

    KScreen::OutputList outputList = config->outputs();
    QFile file(KStandardDirs::locateLocal("data", "kscreen/"+id));
    file.open(QIODevice::ReadOnly);

    QVariantList outputs = parser.parse(file.readAll()).toList();
    Q_FOREACH(KScreen::Output* output, outputList) {
        if (!output->isConnected() && output->isEnabled()) {
            output->setEnabled(false);
        }
    }

    Q_FOREACH(const QVariant &info, outputs) {
        KScreen::Output* output = Serializer::findOutput(info.toMap());
        if (!output) {
            continue;
        }

        delete outputList.take(output->id());
        outputList.insert(output->id(), output);
    }
    config->setOutputs(outputList);

    return config;
}

bool Serializer::saveConfig(KScreen::Config* config)
{
    KScreen::OutputList outputs = config->outputs();

    QVariantList outputList;
    Q_FOREACH(KScreen::Output *output, outputs) {
        if (!output->isConnected()) {
            continue;
        }

        QVariantMap info;
        info["hash"] = output->edid()->hash();
        info["primary"] = output->isPrimary();
        info["enabled"] = output->isEnabled();
        info["rotation"] = output->rotation();

        QVariantMap pos;
        pos["x"] = output->pos().x();
        pos["y"] = output->pos().y();
        info["pos"] = pos;

        if (output->isEnabled()) {
            KScreen::Mode *mode = output->mode(output->currentMode());

            QVariantMap modeInfo;
            modeInfo["refresh"] = mode->refreshRate();

            QVariantMap modeSize;
            modeSize["width"] = mode->size().width();
            modeSize["height"] = mode->size().height();
            modeInfo["size"] = modeSize;

            info["mode"] = modeInfo;
        }

        outputList.append(info);
    }

    qDebug() << outputList.count();
    bool ok;
    QJson::Serializer serializer;
    QByteArray json = serializer.serialize(outputList);

    QString path = KStandardDirs::locateLocal("data", "kscreen/"+ Serializer::currentId());
    QFile file(path);
    file.open(QIODevice::WriteOnly);
    file.write(json);
    file.close();

    qDebug() << "Config saved on: " << path;
    return true;
}

KScreen::Output* Serializer::findOutput(const QVariantMap& info)
{
    KScreen::Config *config = KScreen::Config::current();
    if (!config) {
        return 0;
    }

    KScreen::OutputList outputs = config->outputs();
    Q_FOREACH(KScreen::Output* output, outputs) {
        if (!output->isConnected()) {
            continue;
        }
        if (!output->edid()->isValid()) {
            continue;
        }
        if (output->edid()->hash() != info["hash"].toString()) {
            continue;
        }

        QVariantMap posInfo = info["pos"].toMap();
        QPoint point(posInfo["x"].toInt(), posInfo["y"].toInt());
        output->setPos(point);
        output->setPrimary(info["primary"].toBool());
        output->setEnabled(info["enabled"].toBool());
        output->setRotation(static_cast<KScreen::Output::Rotation>(info["rotation"].toInt()));

        QVariantMap modeInfo = info["mode"].toMap();
        QVariantMap modeSize = modeInfo["size"].toMap();
        QSize size(modeSize["width"].toInt(), modeSize["height"].toInt());

        qDebug() << "Finding a mode with: ";
        qDebug() << size;
        qDebug() << modeInfo["refresh"].toString();

        KScreen::ModeList modes = output->modes();
        Q_FOREACH(KScreen::Mode* mode, modes) {
            if (mode->size() != size) {
                continue;
            }
            if (QString::number(mode->refreshRate()) != modeInfo["refresh"].toString()) {
                continue;
            }

            qDebug() << "Found: " << mode->id() << " " << mode->name();
            output->setCurrentMode(mode->id());
            break;
        }
        return output;
    }

    return 0;
}<commit_msg>Use the output->name if no EDID is found<commit_after>/*************************************************************************************
 *  Copyright (C) 2012 by Alejandro Fiestas Olivares <afiestas@kde.org>              *
 *                                                                                *
 *  This program is free software; you can redistribute it and/or                    *
 *  modify it under the terms of the GNU General Public License                      *
 *  as published by the Free Software Foundation; either version 2                   *
 *  of the License, or (at your option) any later version.                           *
 *                                                                                *
 *  This program is distributed in the hope that it will be useful,                  *
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of                   *
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                    *
 *  GNU General Public License for more details.                                     *
 *                                                                                *
 *  You should have received a copy of the GNU General Public License                *
 *  along with this program; if not, write to the Free Software                      *
 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA   *
 *************************************************************************************/

#include "serializer.h"

#include <QtCore/QStringList>
#include <QtCore/QCryptographicHash>
#include <QtCore/QFile>
#include <QtCore/QVariant>
#include <QtCore/QVariantList>
#include <QtCore/QVariantMap>
#include <QtCore/QDebug>

#include <qjson/serializer.h>
#include <qjson/parser.h>

#include <kscreen/config.h>
#include <kscreen/output.h>
#include <kscreen/edid.h>
#include <KStandardDirs>

QString Serializer::currentId()
{
    KScreen::OutputList outputs = KScreen::Config::current()->outputs();

    QStringList hashList;
    Q_FOREACH(const KScreen::Output* output, outputs) {
        if (!output->isConnected()) {
            continue;
        }
        if (output->edid()) {
            hashList.insert(0, output->edid()->hash());
            continue;
        }

        hashList.insert(0, output->name());
    }

    qSort(hashList.begin(), hashList.end());

    QCryptographicHash hash(QCryptographicHash::Md5);
    hash.addData(hashList.join(QString()).toAscii());
    return hash.result().toHex();
}

bool Serializer::configExists()
{
    return Serializer::configExists(Serializer::currentId());
}

bool Serializer::configExists(const QString& id)
{
    QString path = KStandardDirs::locateLocal("data", "kscreen/"+id);
    return QFile::exists(path);
}

KScreen::Config* Serializer::config(const QString& id)
{
    QJson::Parser parser;
    KScreen::Config* config = KScreen::Config::current();
    if (!config) {
        return 0;
    }

    KScreen::OutputList outputList = config->outputs();
    QFile file(KStandardDirs::locateLocal("data", "kscreen/"+id));
    file.open(QIODevice::ReadOnly);

    QVariantList outputs = parser.parse(file.readAll()).toList();
    Q_FOREACH(KScreen::Output* output, outputList) {
        if (!output->isConnected() && output->isEnabled()) {
            output->setEnabled(false);
        }
    }

    Q_FOREACH(const QVariant &info, outputs) {
        KScreen::Output* output = Serializer::findOutput(info.toMap());
        if (!output) {
            continue;
        }

        delete outputList.take(output->id());
        outputList.insert(output->id(), output);
    }
    config->setOutputs(outputList);

    return config;
}

bool Serializer::saveConfig(KScreen::Config* config)
{
    KScreen::OutputList outputs = config->outputs();

    QVariantList outputList;
    Q_FOREACH(KScreen::Output *output, outputs) {
        if (!output->isConnected()) {
            continue;
        }

        QVariantMap info;
        info["hash"] = output->edid()->hash();
        info["primary"] = output->isPrimary();
        info["enabled"] = output->isEnabled();
        info["rotation"] = output->rotation();

        QVariantMap pos;
        pos["x"] = output->pos().x();
        pos["y"] = output->pos().y();
        info["pos"] = pos;

        if (output->isEnabled()) {
            KScreen::Mode *mode = output->mode(output->currentMode());

            QVariantMap modeInfo;
            modeInfo["refresh"] = mode->refreshRate();

            QVariantMap modeSize;
            modeSize["width"] = mode->size().width();
            modeSize["height"] = mode->size().height();
            modeInfo["size"] = modeSize;

            info["mode"] = modeInfo;
        }

        outputList.append(info);
    }

    qDebug() << outputList.count();
    bool ok;
    QJson::Serializer serializer;
    QByteArray json = serializer.serialize(outputList);

    QString path = KStandardDirs::locateLocal("data", "kscreen/"+ Serializer::currentId());
    QFile file(path);
    file.open(QIODevice::WriteOnly);
    file.write(json);
    file.close();

    qDebug() << "Config saved on: " << path;
    return true;
}

KScreen::Output* Serializer::findOutput(const QVariantMap& info)
{
    KScreen::Config *config = KScreen::Config::current();
    if (!config) {
        return 0;
    }

    KScreen::OutputList outputs = config->outputs();
    Q_FOREACH(KScreen::Output* output, outputs) {
        if (!output->isConnected()) {
            continue;
        }
        if (!output->edid()->isValid()) {
            continue;
        }
        if (output->edid()->hash() != info["hash"].toString()) {
            continue;
        }

        QVariantMap posInfo = info["pos"].toMap();
        QPoint point(posInfo["x"].toInt(), posInfo["y"].toInt());
        output->setPos(point);
        output->setPrimary(info["primary"].toBool());
        output->setEnabled(info["enabled"].toBool());
        output->setRotation(static_cast<KScreen::Output::Rotation>(info["rotation"].toInt()));

        QVariantMap modeInfo = info["mode"].toMap();
        QVariantMap modeSize = modeInfo["size"].toMap();
        QSize size(modeSize["width"].toInt(), modeSize["height"].toInt());

        qDebug() << "Finding a mode with: ";
        qDebug() << size;
        qDebug() << modeInfo["refresh"].toString();

        KScreen::ModeList modes = output->modes();
        Q_FOREACH(KScreen::Mode* mode, modes) {
            if (mode->size() != size) {
                continue;
            }
            if (QString::number(mode->refreshRate()) != modeInfo["refresh"].toString()) {
                continue;
            }

            qDebug() << "Found: " << mode->id() << " " << mode->name();
            output->setCurrentMode(mode->id());
            break;
        }
        return output;
    }

    return 0;
}<|endoftext|>


<commit_before>// $Id$
//
// AliRoot Configuration for running aliroot with Monte Carlo.
// genExtFileConfig() includes the common setting for all MCs
// which has to be called after MC is instantiated.
// Called from MC specific configs (g3Config.C, g4Config.C).
//
// Extracted from G3 specific Config.C
// by I. Hrivnacova, IPN Orsay

// Functions
Float_t EtaToTheta(Float_t arg);
AliGenerator* GeneratorFactory(Int_t startEvent);

void genExtFileConfig(const TString& srun, Int_t startEvent=0)
{
  cout << "Running genExtFileConfig.C ... " << endl;

  //=======================================================================
  // Steering parameters for ALICE simulation
  //=======================================================================

  gMC->SetProcess("DCAY",1);
  gMC->SetProcess("PAIR",1);
  gMC->SetProcess("COMP",1);
  gMC->SetProcess("PHOT",1);
  gMC->SetProcess("PFIS",0);
  gMC->SetProcess("DRAY",0);
  gMC->SetProcess("ANNI",1);
  gMC->SetProcess("BREM",1);
  gMC->SetProcess("MUNU",1);
  gMC->SetProcess("CKOV",1);
  gMC->SetProcess("HADR",1);
  gMC->SetProcess("LOSS",2);
  gMC->SetProcess("MULS",1);
  //gMC->SetProcess("RAYL",1);

  Float_t cut = 1.e-3;        // 1MeV cut by default
  Float_t tofmax = 1.e10;

  gMC->SetCut("CUTGAM", cut);
  gMC->SetCut("CUTELE", cut);
  gMC->SetCut("CUTNEU", cut);
  gMC->SetCut("CUTHAD", cut);
  gMC->SetCut("CUTMUO", cut);
  gMC->SetCut("BCUTE",  cut);
  gMC->SetCut("BCUTM",  cut);
  gMC->SetCut("DCUTE",  cut);
  gMC->SetCut("DCUTM",  cut);
  gMC->SetCut("PPCUTM", cut);
  gMC->SetCut("TOFMAX", tofmax);

  //=======================================================================
  // External decayer
  //=======================================================================

  // Set External decayer
  AliDecayer *decayer = new AliDecayerPythia();

  switch (srun) {
  case kD0PbPb5500:
    decayer->SetForceDecay(kHadronicD);
    break;
  case kCharmSemiElPbPb5500:
    decayer->SetForceDecay(kSemiElectronic);
    break;
  case kBeautySemiElPbPb5500:
    decayer->SetForceDecay(kSemiElectronic);
    break;
  default:
    decayer->SetForceDecay(kAll);
    break;
  }
  decayer->Init();
  gMC->SetExternalDecayer(decayer);

  //=======================================================================
  // Event generator
  //=======================================================================

  // External generator configuration
  AliGenerator* gener = GeneratorFactory(startEvent);
  gener->SetOrigin(0, 0, 0);    // vertex position
  //gener->SetSigma(0, 0, 5.3);   // Sigma in (X,Y,Z) (cm) on IP position
  //gener->SetCutVertexZ(1.);     // Truncate at 1 sigma
  //gener->SetVertexSmear(kPerEvent);
  gener->SetTrackingFlag(1);
  gener->Init();

  cout << "Running genExtFileConfig.C finished ... " << endl;
}

Float_t EtaToTheta(Float_t arg){
  return (180./TMath::Pi())*2.*atan(exp(-arg));
}

AliGenerator* GeneratorFactory(Int_t startEvent) {

  AliGenExtFile *gener = new AliGenExtFile(-1);
  AliGenReaderTreeK * reader = new AliGenReaderTreeK();

  reader->SetFileName("galice.root");
  reader->AddDir("gen");
  gener->SetReader(reader);
  gener->SetStartEvent(startEvent);

  return gener;
}

<commit_msg>Randomize vertex<commit_after>// $Id$
//
// AliRoot Configuration for running aliroot with Monte Carlo.
// genExtFileConfig() includes the common setting for all MCs
// which has to be called after MC is instantiated.
// Called from MC specific configs (g3Config.C, g4Config.C).
//
// Extracted from G3 specific Config.C
// by I. Hrivnacova, IPN Orsay

// Functions
Float_t EtaToTheta(Float_t arg);
AliGenerator* GeneratorFactory(Int_t startEvent);

void genExtFileConfig(const TString& srun, Int_t startEvent=0)
{
  cout << "Running genExtFileConfig.C ... " << endl;

  //=======================================================================
  // Steering parameters for ALICE simulation
  //=======================================================================

  gMC->SetProcess("DCAY",1);
  gMC->SetProcess("PAIR",1);
  gMC->SetProcess("COMP",1);
  gMC->SetProcess("PHOT",1);
  gMC->SetProcess("PFIS",0);
  gMC->SetProcess("DRAY",0);
  gMC->SetProcess("ANNI",1);
  gMC->SetProcess("BREM",1);
  gMC->SetProcess("MUNU",1);
  gMC->SetProcess("CKOV",1);
  gMC->SetProcess("HADR",1);
  gMC->SetProcess("LOSS",2);
  gMC->SetProcess("MULS",1);
  //gMC->SetProcess("RAYL",1);

  Float_t cut = 1.e-3;        // 1MeV cut by default
  Float_t tofmax = 1.e10;

  gMC->SetCut("CUTGAM", cut);
  gMC->SetCut("CUTELE", cut);
  gMC->SetCut("CUTNEU", cut);
  gMC->SetCut("CUTHAD", cut);
  gMC->SetCut("CUTMUO", cut);
  gMC->SetCut("BCUTE",  cut);
  gMC->SetCut("BCUTM",  cut);
  gMC->SetCut("DCUTE",  cut);
  gMC->SetCut("DCUTM",  cut);
  gMC->SetCut("PPCUTM", cut);
  gMC->SetCut("TOFMAX", tofmax);

  //=======================================================================
  // External decayer
  //=======================================================================

  // Set External decayer
  AliDecayer *decayer = new AliDecayerPythia();

  switch (srun) {
  case kD0PbPb5500:
    decayer->SetForceDecay(kHadronicD);
    break;
  case kCharmSemiElPbPb5500:
    decayer->SetForceDecay(kSemiElectronic);
    break;
  case kBeautySemiElPbPb5500:
    decayer->SetForceDecay(kSemiElectronic);
    break;
  default:
    decayer->SetForceDecay(kAll);
    break;
  }
  decayer->Init();
  gMC->SetExternalDecayer(decayer);

  //=======================================================================
  // Event generator
  //=======================================================================

  // External generator configuration: particles generated by rungen (strictly at 0,0,0 vertex)
  // will be transferred to randomly generated vertex
  AliGenerator* gener = GeneratorFactory(startEvent);
  gener->SetOrigin(0, 0, 0);    // vertex position
  gener->SetSigma(0, 0, 5.3);   // Sigma in (X,Y,Z) (cm) on IP position
  gener->SetCutVertexZ(1.);     // Truncate at 1 sigma
  gener->SetVertexSmear(kPerEvent);
  gener->SetTrackingFlag(1);
  gener->Init();

  cout << "Running genExtFileConfig.C finished ... " << endl;
}

Float_t EtaToTheta(Float_t arg){
  return (180./TMath::Pi())*2.*atan(exp(-arg));
}

AliGenerator* GeneratorFactory(Int_t startEvent) {

  AliGenExtFile *gener = new AliGenExtFile(-1);
  AliGenReaderTreeK * reader = new AliGenReaderTreeK();

  reader->SetFileName("galice.root");
  reader->AddDir("gen");
  gener->SetReader(reader);
  gener->SetStartEvent(startEvent);

  return gener;
}

<|endoftext|>


<commit_before>// Time:  O((|E| + |V|) * log|V|) = O(|E| * log|V|)
// Space: O(|E| + |V|)

// Dijkstra's algorithm
class Solution {
public:
    int networkDelayTime(vector<vector<int>>& times, int N, int K) {
        using P = pair<int, int>;
        vector<vector<P>> adj(N);
        for (const auto& time : times) {
            int u, v, w;
            tie(u, v, w) = make_tuple(time[0] - 1, time[1] - 1, time[2]);
            adj[u].emplace_back(v, w);
        }

        int result = 0;
        unordered_set<int> lookup;
        priority_queue<P, vector<P>, greater<P>> min_heap;
        min_heap.emplace(0, K - 1);
        while (!min_heap.empty() && lookup.size() != N) {
            int u;
            tie(result, u) = min_heap.top(); min_heap.pop();
            lookup.emplace(u);
            for (const auto& kvp : adj[u]) {
                int v, w;
                tie(v, w) = kvp;
                if (lookup.count(v)) continue;
                min_heap.emplace(result + w, v);
            }
        }
        return lookup.size() == N ? result : -1;
    }
};
<commit_msg>Update network-delay-time.cpp<commit_after>// Time:  O((|E| + |V|) * log|V|) = O(|E| * log|V|)
// Space: O(|E| + |V|) = O(|E|)

// Dijkstra's algorithm
class Solution {
public:
    int networkDelayTime(vector<vector<int>>& times, int N, int K) {
        using P = pair<int, int>;
        vector<vector<P>> adj(N);
        for (const auto& time : times) {
            int u, v, w;
            tie(u, v, w) = make_tuple(time[0] - 1, time[1] - 1, time[2]);
            adj[u].emplace_back(v, w);
        }

        int result = 0;
        unordered_set<int> lookup;
        priority_queue<P, vector<P>, greater<P>> min_heap;
        min_heap.emplace(0, K - 1);
        while (!min_heap.empty() && lookup.size() != N) {
            int u;
            tie(result, u) = min_heap.top(); min_heap.pop();
            lookup.emplace(u);
            for (const auto& kvp : adj[u]) {
                int v, w;
                tie(v, w) = kvp;
                if (lookup.count(v)) continue;
                min_heap.emplace(result + w, v);
            }
        }
        return lookup.size() == N ? result : -1;
    }
};
<|endoftext|>


<commit_before>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2008 Ulrich von Zadow
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Current versions can be found at www.libavg.de
//

#include "ConfigMgr.h"
#include "Logger.h"
#include "Exception.h"
#include "OSHelper.h"

#include <libxml/xmlmemory.h>

#include <iostream>
#include <stdlib.h>
#include <errno.h>

#ifndef _WIN32
#include <unistd.h>
#else
#include  <io.h>
#endif

using namespace std;

namespace avg {

ConfigOption::ConfigOption(const string& sName, const string& sValue,
            const string& sDescription)
    : m_sName(sName),
      m_sValue(sValue),
      m_sDescription(sDescription)
{
}

ConfigMgr* ConfigMgr::m_pGlobalConfigMgr = 0;

void deleteConfigMgr()
{
    delete ConfigMgr::m_pGlobalConfigMgr;
    ConfigMgr::m_pGlobalConfigMgr = 0;
}

ConfigMgr* ConfigMgr::get()
{
    if (!m_pGlobalConfigMgr) {
        m_pGlobalConfigMgr = new ConfigMgr;
        atexit(deleteConfigMgr);
    }
    return m_pGlobalConfigMgr;
}

ConfigMgr::ConfigMgr()
{
    addSubsys("scr");
    addOption("scr", "bpp", "24",
            "Screen bits per pixel. Valid values are 15, 16, 24 and 32.");
    addOption("scr", "fullscreen", "false",
            "Whether to run fullscreen (true) or in a window (false).");
    addOption("scr", "windowwidth", "0",
            "The width of the window to use. Contents are scaled.");
    addOption("scr", "windowheight", "0",
            "The height of the window to use. Contents are scaled.");
    addOption("scr", "usepow2textures", "false",
            "If set to true, use only power of 2 textures.");
    addOption("scr", "useshaders", "true",
            "Whether to use shaders.");
    addOption("scr", "usepixelbuffers", "true",
            "Whether to use pixel buffer objects.");
    addOption("scr", "multisamplesamples", "1",
            "Whether to use multisampling and how many"
            "samples per pixel to use.");
    addOption("scr", "gamma", "-1,-1,-1",
            "Display gamma correction values for red,"
            "green and blue.");
    addOption("scr", "vsyncmode", "auto",
            "How to synchronize the display refresh."
            "Valid values are auto, ogl, dri and none.");

    addSubsys("aud");
    addOption("aud", "channels", "2",
            "Number of output audio channels.");
    addOption("aud", "samplerate", "44100",
            "Sampling rate (Hz) of output audio.");
    addOption("aud", "outputbuffersamples", "1024",
            "Size of the SDL audio buffer in samples.");

    m_sFName = "avgrc";
    loadFile(getGlobalConfigDir()+m_sFName);
    char * pHome = getenv("HOME");
    if (!pHome) {
        AVG_TRACE(Logger::WARNING, "No home directory set.");
    } else {
        loadFile(string(pHome)+"/."+m_sFName);
    }
}

void ConfigMgr::addSubsys(const string& sName)
{
    m_SubsysOptionMap[sName] = ConfigOptionVector();
}

void ConfigMgr::addOption(const string& sSubsys, const string& sName,
        const std::string& sDefault, const string& sDescription)
{
    ConfigOptionVector& Subsys = m_SubsysOptionMap[sSubsys];
    Subsys.push_back(ConfigOption(sName, sDefault, sDescription));
}

void ConfigMgr::addGlobalOption(const string& sName, const string& sDefault,
        const string& sDescription)
{
    m_GlobalOptions.push_back(ConfigOption(sName, sDefault, sDescription));
}

const ConfigOptionVector* ConfigMgr::getOptions(const string& sSubsys) const
{
    SubsysOptionMap::const_iterator it = m_SubsysOptionMap.find(sSubsys);
    if (it == m_SubsysOptionMap.end()) {
        return 0;
    } else {
        return &(*it).second;
    }
}

const string* ConfigMgr::getOption(const string& sSubsys,
        const string& sName) const
{
    const ConfigOptionVector* pOptionVector = getOptions(sSubsys);
    if (!pOptionVector) {
        return 0;
    } else {
        for (unsigned int i=0; i<pOptionVector->size(); i++) {
            if ((*pOptionVector)[i].m_sName == sName) {
                return &(*pOptionVector)[i].m_sValue;
            }
        }
        return 0;
    }
}

bool ConfigMgr::getBoolOption(const std::string& sSubsys,
            const std::string& sName, bool bDefault) const
{
    const string * psOption = getOption(sSubsys, sName);
    if (psOption == 0) {
        return bDefault;
    }
    if (*psOption == "true") {
        return true;
    } else if (*psOption == "false") {
        return false;
    } else {
        AVG_TRACE(Logger::ERROR,
                m_sFName << ": Unrecognized value for option "<<sName<<": "
                << *psOption << ". Must be true or false. Aborting.");
        exit(-1);
    }
}

int ConfigMgr::getIntOption(const std::string& sSubsys,
        const std::string& sName, int Default) const
{
    errno = 0;
    const string * psOption = getOption(sSubsys, sName);
    if (psOption == 0) {
        return Default;
    }
    int Result = strtol(psOption->c_str(), 0, 10);
    int rc = errno;
    if (rc == EINVAL || rc == ERANGE) {
        AVG_TRACE(Logger::ERROR,
                m_sFName << ": Unrecognized value for option "<<sName<<": "
                << *psOption << ". Must be an integer. Aborting.");
        exit(-1);
    }
    return Result;
}

void ConfigMgr::getGammaOption(const std::string& sSubsys,
            const std::string& sName, double* Val) const
{
    const string * psOption = getOption(sSubsys, sName);
    if (psOption == 0) {
        return;
    }
    int rc = sscanf(psOption->c_str(), "%lf,%lf,%lf", Val, Val+1, Val+2);
    if (rc < 3) {
        AVG_TRACE(Logger::ERROR,
                m_sFName << ": Unrecognized value for option "<<sName<<": "
                << *psOption << ". Must be three comma-separated numbers. Aborting.");
        exit(-1);
    }
}

const ConfigOptionVector* ConfigMgr::getGlobalOptions() const
{
    return &m_GlobalOptions;
}

const string* ConfigMgr::getGlobalOption(const string& sName) const
{
    for (unsigned int i=0; i<m_GlobalOptions.size(); i++) {
        if (m_GlobalOptions[i].m_sName == sName) {
            return &m_GlobalOptions[i].m_sValue;
        }
    }
    return 0;

}

bool ConfigMgr::loadFile(const std::string& sPath) {
    string sSubsys;
    try {
#ifndef _WIN32
        // I don't think read permissions on config files are an issue under windows.
        int err = access(sPath.c_str(), R_OK);
        if (err == -1) {
            if (errno == EACCES) {
                AVG_TRACE(Logger::WARNING,
                        sPath+": File exists, but process doesn't have read permissions!");
            }
            return false;
        }
#else
        // but this actually prevents ugly XML parsing errors when file does not exist
        // and cygwin is used
        int err = _access(sPath.c_str(), 0);
        if (err == -1) {
            return false;
        }
#endif
        xmlDocPtr doc;
        doc = xmlParseFile(sPath.c_str());
        if (!doc) {
            return false;
        }
        xmlNodePtr pRoot = xmlDocGetRootElement(doc);
        if (xmlStrcmp(pRoot->name, (const xmlChar *)(m_sFName.c_str()))) {
            AVG_TRACE(Logger::ERROR,
                    sPath+": Root node must be <"+m_sFName+">, found "
                    << pRoot->name << ". Aborting.");
            exit(255);
        }
        xmlNodePtr pSubsysNode = pRoot->xmlChildrenNode;
        while (pSubsysNode) {
            if (xmlStrcmp(pSubsysNode->name, (const xmlChar *)"text") &&
                    xmlStrcmp(pSubsysNode->name, (const xmlChar *)"comment"))
            {
                sSubsys = ((const char *)pSubsysNode->name);
                xmlNodePtr pOptionNode = pSubsysNode->xmlChildrenNode;
                if (!pOptionNode) {
                    AVG_TRACE(Logger::ERROR,
                            sPath << ": Option " << sSubsys
                            << " has no value. Ignoring.");
                } else {
                    if (!xmlStrcmp(pOptionNode->name, (const xmlChar *)"text") &&
                            !pOptionNode->next)
                    {   // This is a global option, not a list of subsystem options.
                        setOption(m_GlobalOptions, doc, pSubsysNode);
                    } else {
                        ConfigOptionVector& CurSubsys = getSubsys(sSubsys);
                        while (pOptionNode) {
                            if (xmlStrcmp(pOptionNode->name, (const xmlChar *)"text") &&
                                    xmlStrcmp(pOptionNode->name, (const xmlChar *)"comment"))
                            {
                                setOption(CurSubsys, doc, pOptionNode);
                            }
                            pOptionNode = pOptionNode->next;
                        }
                    }
                }
            }
            pSubsysNode = pSubsysNode->next;
        }
        xmlFreeDoc(doc);
    } catch (Exception& e) {
        switch (e.GetCode()) {
            case AVG_ERR_OPTION_SUBSYS_UNKNOWN:
                AVG_TRACE(Logger::ERROR, "While parsing " << sPath
                        << ": Option group " << e.GetStr() << " unknown. Aborting.");
                exit(255);
            case AVG_ERR_OPTION_UNKNOWN:
                AVG_TRACE(Logger::ERROR, "While parsing " << sPath
                        << ": Option " << sSubsys << ":" << e.GetStr()
                        << " unknown. Aborting.");
                exit(255);
            default:
                throw;
        }
    }
    return true;
}

ConfigOptionVector& ConfigMgr::getSubsys(const string& sName)
{
    SubsysOptionMap::iterator pos = m_SubsysOptionMap.find(sName);
    if (pos == m_SubsysOptionMap.end()) {
        throw Exception(AVG_ERR_OPTION_SUBSYS_UNKNOWN, sName);
    } else {
        return pos->second;
    }
}

void ConfigMgr::setOption(ConfigOptionVector& OptionVector,
        xmlDocPtr doc, xmlNodePtr pNode)
{
    string sName = (const char *)pNode->name;
    xmlChar * pVal =
            xmlNodeListGetString(doc, pNode->xmlChildrenNode, 1);
    string sValue = (const char *)pVal;
    xmlFree(pVal);
    setOption(OptionVector, sName, sValue);
}

void ConfigMgr::setOption(ConfigOptionVector& OptionVector,
        const string& sName, const string& sValue)
{
    // TODO: Change OptionVector into a map?
    for (unsigned int i=0; i<OptionVector.size(); i++) {
        if (OptionVector[i].m_sName == sName) {
            OptionVector[i].m_sValue = sValue;
            return;
        }
    }
    throw Exception(AVG_ERR_OPTION_UNKNOWN, sName);
}

void ConfigMgr::dump() const
{
    cerr << "Global options: " << endl;
    for (unsigned int i=0; i<m_GlobalOptions.size(); ++i) {
        cerr << "  " << m_GlobalOptions[i].m_sName << ": "
                << m_GlobalOptions[i].m_sValue << endl;
    }
    SubsysOptionMap::const_iterator it;
    for (it=m_SubsysOptionMap.begin(); it != m_SubsysOptionMap.end(); ++it) {
        cerr << (*it).first << ": " << endl;
        const ConfigOptionVector& SubsysOptions = (*it).second;
        for (unsigned int j=0; j<SubsysOptions.size(); ++j) {
            cerr << "  " << SubsysOptions[j].m_sName << ": "
                << SubsysOptions[j].m_sValue << endl;
        }
    }
}

string getGlobalConfigDir()
{
#ifdef _WIN32
    return getAvgLibPath()+"/etc/";
#else
    return "/etc/";
#endif
}

}

<commit_msg>Better error checking for avgrc parsing.<commit_after>//
//  libavg - Media Playback Engine.
//  Copyright (C) 2003-2008 Ulrich von Zadow
//
//  This library is free software; you can redistribute it and/or
//  modify it under the terms of the GNU Lesser General Public
//  License as published by the Free Software Foundation; either
//  version 2 of the License, or (at your option) any later version.
//
//  This library is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//  Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with this library; if not, write to the Free Software
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//
//  Current versions can be found at www.libavg.de
//

#include "ConfigMgr.h"
#include "Logger.h"
#include "Exception.h"
#include "OSHelper.h"

#include <libxml/xmlmemory.h>

#include <iostream>
#include <stdlib.h>
#include <errno.h>

#ifndef _WIN32
#include <unistd.h>
#else
#include  <io.h>
#endif

using namespace std;

namespace avg {

ConfigOption::ConfigOption(const string& sName, const string& sValue,
            const string& sDescription)
    : m_sName(sName),
      m_sValue(sValue),
      m_sDescription(sDescription)
{
}

ConfigMgr* ConfigMgr::m_pGlobalConfigMgr = 0;

void deleteConfigMgr()
{
    delete ConfigMgr::m_pGlobalConfigMgr;
    ConfigMgr::m_pGlobalConfigMgr = 0;
}

ConfigMgr* ConfigMgr::get()
{
    if (!m_pGlobalConfigMgr) {
        m_pGlobalConfigMgr = new ConfigMgr;
        atexit(deleteConfigMgr);
    }
    return m_pGlobalConfigMgr;
}

ConfigMgr::ConfigMgr()
{
    addSubsys("scr");
    addOption("scr", "bpp", "24",
            "Screen bits per pixel. Valid values are 15, 16, 24 and 32.");
    addOption("scr", "fullscreen", "false",
            "Whether to run fullscreen (true) or in a window (false).");
    addOption("scr", "windowwidth", "0",
            "The width of the window to use. Contents are scaled.");
    addOption("scr", "windowheight", "0",
            "The height of the window to use. Contents are scaled.");
    addOption("scr", "usepow2textures", "false",
            "If set to true, use only power of 2 textures.");
    addOption("scr", "useshaders", "true",
            "Whether to use shaders.");
    addOption("scr", "usepixelbuffers", "true",
            "Whether to use pixel buffer objects.");
    addOption("scr", "multisamplesamples", "1",
            "Whether to use multisampling and how many"
            "samples per pixel to use.");
    addOption("scr", "gamma", "-1,-1,-1",
            "Display gamma correction values for red,"
            "green and blue.");
    addOption("scr", "vsyncmode", "auto",
            "How to synchronize the display refresh."
            "Valid values are auto, ogl, dri and none.");

    addSubsys("aud");
    addOption("aud", "channels", "2",
            "Number of output audio channels.");
    addOption("aud", "samplerate", "44100",
            "Sampling rate (Hz) of output audio.");
    addOption("aud", "outputbuffersamples", "1024",
            "Size of the SDL audio buffer in samples.");

    m_sFName = "avgrc";
    loadFile(getGlobalConfigDir()+m_sFName);
    char * pHome = getenv("HOME");
    if (!pHome) {
        AVG_TRACE(Logger::WARNING, "No home directory set.");
    } else {
        loadFile(string(pHome)+"/."+m_sFName);
    }
}

void ConfigMgr::addSubsys(const string& sName)
{
    m_SubsysOptionMap[sName] = ConfigOptionVector();
}

void ConfigMgr::addOption(const string& sSubsys, const string& sName,
        const std::string& sDefault, const string& sDescription)
{
    ConfigOptionVector& Subsys = m_SubsysOptionMap[sSubsys];
    Subsys.push_back(ConfigOption(sName, sDefault, sDescription));
}

void ConfigMgr::addGlobalOption(const string& sName, const string& sDefault,
        const string& sDescription)
{
    m_GlobalOptions.push_back(ConfigOption(sName, sDefault, sDescription));
}

const ConfigOptionVector* ConfigMgr::getOptions(const string& sSubsys) const
{
    SubsysOptionMap::const_iterator it = m_SubsysOptionMap.find(sSubsys);
    if (it == m_SubsysOptionMap.end()) {
        return 0;
    } else {
        return &(*it).second;
    }
}

const string* ConfigMgr::getOption(const string& sSubsys,
        const string& sName) const
{
    const ConfigOptionVector* pOptionVector = getOptions(sSubsys);
    if (!pOptionVector) {
        return 0;
    } else {
        for (unsigned int i=0; i<pOptionVector->size(); i++) {
            if ((*pOptionVector)[i].m_sName == sName) {
                return &(*pOptionVector)[i].m_sValue;
            }
        }
        return 0;
    }
}

bool ConfigMgr::getBoolOption(const std::string& sSubsys,
            const std::string& sName, bool bDefault) const
{
    const string * psOption = getOption(sSubsys, sName);
    if (psOption == 0) {
        return bDefault;
    }
    if (*psOption == "true") {
        return true;
    } else if (*psOption == "false") {
        return false;
    } else {
        AVG_TRACE(Logger::ERROR,
                m_sFName << ": Unrecognized value for option "<<sName<<": "
                << *psOption << ". Must be true or false. Aborting.");
        exit(-1);
    }
}

int ConfigMgr::getIntOption(const std::string& sSubsys,
        const std::string& sName, int Default) const
{
    errno = 0;
    const string * psOption = getOption(sSubsys, sName);
    if (psOption == 0) {
        return Default;
    }
    int Result = strtol(psOption->c_str(), 0, 10);
    int rc = errno;
    if (rc == EINVAL || rc == ERANGE) {
        AVG_TRACE(Logger::ERROR,
                m_sFName << ": Unrecognized value for option "<<sName<<": "
                << *psOption << ". Must be an integer. Aborting.");
        exit(-1);
    }
    return Result;
}

void ConfigMgr::getGammaOption(const std::string& sSubsys,
            const std::string& sName, double* Val) const
{
    const string * psOption = getOption(sSubsys, sName);
    if (psOption == 0) {
        return;
    }
    int rc = sscanf(psOption->c_str(), "%lf,%lf,%lf", Val, Val+1, Val+2);
    if (rc < 3) {
        AVG_TRACE(Logger::ERROR,
                m_sFName << ": Unrecognized value for option "<<sName<<": "
                << *psOption << ". Must be three comma-separated numbers. Aborting.");
        exit(-1);
    }
}

const ConfigOptionVector* ConfigMgr::getGlobalOptions() const
{
    return &m_GlobalOptions;
}

const string* ConfigMgr::getGlobalOption(const string& sName) const
{
    for (unsigned int i=0; i<m_GlobalOptions.size(); i++) {
        if (m_GlobalOptions[i].m_sName == sName) {
            return &m_GlobalOptions[i].m_sValue;
        }
    }
    return 0;

}

bool ConfigMgr::loadFile(const std::string& sPath) {
    string sSubsys;
    try {
#ifndef _WIN32
        // I don't think read permissions on config files are an issue under windows.
        int err = access(sPath.c_str(), R_OK);
        if (err == -1) {
            if (errno == EACCES) {
                AVG_TRACE(Logger::WARNING,
                        sPath+": File exists, but process doesn't have read permissions!");
            }
            return false;
        }
#else
        // but this actually prevents ugly XML parsing errors when file does not exist
        // and cygwin is used
        int err = _access(sPath.c_str(), 0);
        if (err == -1) {
            return false;
        }
#endif
        xmlDocPtr doc;
        doc = xmlParseFile(sPath.c_str());
        if (!doc) {
            throw Exception(AVG_ERR_XML_VALID, "Error parsing "+sPath
                    +". File is not well-formed.");
        }
        xmlNodePtr pRoot = xmlDocGetRootElement(doc);
        if (xmlStrcmp(pRoot->name, (const xmlChar *)(m_sFName.c_str()))) {
            AVG_TRACE(Logger::ERROR,
                    sPath+": Root node must be <"+m_sFName+">, found "
                    << pRoot->name << ". Aborting.");
            exit(255);
        }
        xmlNodePtr pSubsysNode = pRoot->xmlChildrenNode;
        while (pSubsysNode) {
            if (xmlStrcmp(pSubsysNode->name, (const xmlChar *)"text") &&
                    xmlStrcmp(pSubsysNode->name, (const xmlChar *)"comment"))
            {
                sSubsys = ((const char *)pSubsysNode->name);
                xmlNodePtr pOptionNode = pSubsysNode->xmlChildrenNode;
                if (!pOptionNode) {
                    AVG_TRACE(Logger::ERROR,
                            sPath << ": Option " << sSubsys
                            << " has no value. Ignoring.");
                } else {
                    if (!xmlStrcmp(pOptionNode->name, (const xmlChar *)"text") &&
                            !pOptionNode->next)
                    {   // This is a global option, not a list of subsystem options.
                        setOption(m_GlobalOptions, doc, pSubsysNode);
                    } else {
                        ConfigOptionVector& CurSubsys = getSubsys(sSubsys);
                        while (pOptionNode) {
                            if (xmlStrcmp(pOptionNode->name, (const xmlChar *)"text") &&
                                    xmlStrcmp(pOptionNode->name, (const xmlChar *)"comment"))
                            {
                                setOption(CurSubsys, doc, pOptionNode);
                            }
                            pOptionNode = pOptionNode->next;
                        }
                    }
                }
            }
            pSubsysNode = pSubsysNode->next;
        }
        xmlFreeDoc(doc);
    } catch (Exception& e) {
        switch (e.GetCode()) {
            case AVG_ERR_OPTION_SUBSYS_UNKNOWN:
                AVG_TRACE(Logger::ERROR, "While parsing " << sPath
                        << ": Option group " << e.GetStr() << " unknown. Aborting.");
                exit(255);
            case AVG_ERR_OPTION_UNKNOWN:
                AVG_TRACE(Logger::ERROR, "While parsing " << sPath
                        << ": Option " << sSubsys << ":" << e.GetStr()
                        << " unknown. Aborting.");
                exit(255);
            default:
                throw;
        }
    }
    return true;
}

ConfigOptionVector& ConfigMgr::getSubsys(const string& sName)
{
    SubsysOptionMap::iterator pos = m_SubsysOptionMap.find(sName);
    if (pos == m_SubsysOptionMap.end()) {
        throw Exception(AVG_ERR_OPTION_SUBSYS_UNKNOWN, sName);
    } else {
        return pos->second;
    }
}

void ConfigMgr::setOption(ConfigOptionVector& OptionVector,
        xmlDocPtr doc, xmlNodePtr pNode)
{
    string sName = (const char *)pNode->name;
    xmlChar * pVal =
            xmlNodeListGetString(doc, pNode->xmlChildrenNode, 1);
    string sValue = (const char *)pVal;
    xmlFree(pVal);
    setOption(OptionVector, sName, sValue);
}

void ConfigMgr::setOption(ConfigOptionVector& OptionVector,
        const string& sName, const string& sValue)
{
    // TODO: Change OptionVector into a map?
    for (unsigned int i=0; i<OptionVector.size(); i++) {
        if (OptionVector[i].m_sName == sName) {
            OptionVector[i].m_sValue = sValue;
            return;
        }
    }
    throw Exception(AVG_ERR_OPTION_UNKNOWN, sName);
}

void ConfigMgr::dump() const
{
    cerr << "Global options: " << endl;
    for (unsigned int i=0; i<m_GlobalOptions.size(); ++i) {
        cerr << "  " << m_GlobalOptions[i].m_sName << ": "
                << m_GlobalOptions[i].m_sValue << endl;
    }
    SubsysOptionMap::const_iterator it;
    for (it=m_SubsysOptionMap.begin(); it != m_SubsysOptionMap.end(); ++it) {
        cerr << (*it).first << ": " << endl;
        const ConfigOptionVector& SubsysOptions = (*it).second;
        for (unsigned int j=0; j<SubsysOptions.size(); ++j) {
            cerr << "  " << SubsysOptions[j].m_sName << ": "
                << SubsysOptions[j].m_sValue << endl;
        }
    }
}

string getGlobalConfigDir()
{
#ifdef _WIN32
    return getAvgLibPath()+"/etc/";
#else
    return "/etc/";
#endif
}

}

<|endoftext|>


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

#include "perfetto/ext/base/file_utils.h"

#include <sys/stat.h>
#include <sys/types.h>

#include <algorithm>
#include <deque>
#include <string>
#include <vector>

#include "perfetto/base/build_config.h"
#include "perfetto/base/logging.h"
#include "perfetto/base/platform_handle.h"
#include "perfetto/base/status.h"
#include "perfetto/ext/base/scoped_file.h"
#include "perfetto/ext/base/utils.h"

#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
#include <Windows.h>
#include <direct.h>
#include <io.h>
#else
#include <dirent.h>
#include <unistd.h>
#endif

namespace perfetto {
namespace base {
namespace {
constexpr size_t kBufSize = 2048;

#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
// Wrap FindClose to: (1) make the return unix-style; (2) deal with stdcall.
int CloseFindHandle(HANDLE h) {
  return FindClose(h) ? 0 : -1;
};
#endif

}  // namespace

ssize_t Read(int fd, void* dst, size_t dst_size) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  return _read(fd, dst, static_cast<unsigned>(dst_size));
#else
  return PERFETTO_EINTR(read(fd, dst, dst_size));
#endif
}

bool ReadFileDescriptor(int fd, std::string* out) {
  // Do not override existing data in string.
  size_t i = out->size();

  struct stat buf {};
  if (fstat(fd, &buf) != -1) {
    if (buf.st_size > 0)
      out->resize(i + static_cast<size_t>(buf.st_size));
  }

  ssize_t bytes_read;
  for (;;) {
    if (out->size() < i + kBufSize)
      out->resize(out->size() + kBufSize);

    bytes_read = Read(fd, &((*out)[i]), kBufSize);
    if (bytes_read > 0) {
      i += static_cast<size_t>(bytes_read);
    } else {
      out->resize(i);
      return bytes_read == 0;
    }
  }
}

bool ReadPlatformHandle(PlatformHandle h, std::string* out) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  // Do not override existing data in string.
  size_t i = out->size();

  for (;;) {
    if (out->size() < i + kBufSize)
      out->resize(out->size() + kBufSize);
    DWORD bytes_read = 0;
    auto res = ::ReadFile(h, &((*out)[i]), kBufSize, &bytes_read, nullptr);
    if (res && bytes_read > 0) {
      i += static_cast<size_t>(bytes_read);
    } else {
      out->resize(i);
      const bool is_eof = res && bytes_read == 0;
      auto err = res ? 0 : GetLastError();
      // The "Broken pipe" error on Windows is slighly different than Unix:
      // On Unix: a "broken pipe" error can happen only on the writer side. On
      // the reader there is no broken pipe, just a EOF.
      // On windows: the reader also sees a broken pipe error.
      // Here we normalize on the Unix behavior, treating broken pipe as EOF.
      return is_eof || err == ERROR_BROKEN_PIPE;
    }
  }
#else
  return ReadFileDescriptor(h, out);
#endif
}

bool ReadFileStream(FILE* f, std::string* out) {
  return ReadFileDescriptor(fileno(f), out);
}

bool ReadFile(const std::string& path, std::string* out) {
  base::ScopedFile fd = base::OpenFile(path, O_RDONLY);
  if (!fd)
    return false;

  return ReadFileDescriptor(*fd, out);
}

ssize_t WriteAll(int fd, const void* buf, size_t count) {
  size_t written = 0;
  while (written < count) {
    // write() on windows takes an unsigned int size.
    uint32_t bytes_left = static_cast<uint32_t>(
        std::min(count - written, static_cast<size_t>(UINT32_MAX)));
    ssize_t wr = PERFETTO_EINTR(
        write(fd, static_cast<const char*>(buf) + written, bytes_left));
    if (wr == 0)
      break;
    if (wr < 0)
      return wr;
    written += static_cast<size_t>(wr);
  }
  return static_cast<ssize_t>(written);
}

ssize_t WriteAllHandle(PlatformHandle h, const void* buf, size_t count) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  DWORD wsize = 0;
  if (::WriteFile(h, buf, static_cast<DWORD>(count), &wsize, nullptr)) {
    return wsize;
  } else {
    return -1;
  }
#else
  return WriteAll(h, buf, count);
#endif
}

bool FlushFile(int fd) {
  PERFETTO_DCHECK(fd != 0);
#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
  return !PERFETTO_EINTR(fdatasync(fd));
#elif PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  return !PERFETTO_EINTR(_commit(fd));
#else
  return !PERFETTO_EINTR(fsync(fd));
#endif
}

bool Mkdir(const std::string& path) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  return _mkdir(path.c_str()) == 0;
#else
  return mkdir(path.c_str(), 0755) == 0;
#endif
}

bool Rmdir(const std::string& path) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  return _rmdir(path.c_str()) == 0;
#else
  return rmdir(path.c_str()) == 0;
#endif
}

int CloseFile(int fd) {
  return close(fd);
}

ScopedFile OpenFile(const std::string& path, int flags, FileOpenMode mode) {
  PERFETTO_DCHECK((flags & O_CREAT) == 0 || mode != kFileModeInvalid);
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  // Always use O_BINARY on Windows, to avoid silly EOL translations.
  ScopedFile fd(_open(path.c_str(), flags | O_BINARY, mode));
#else
  // Always open a ScopedFile with O_CLOEXEC so we can safely fork and exec.
  ScopedFile fd(open(path.c_str(), flags | O_CLOEXEC, mode));
#endif
  return fd;
}

bool FileExists(const std::string& path) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  return _access(path.c_str(), 0) == 0;
#else
  return access(path.c_str(), F_OK) == 0;
#endif
}

// Declared in base/platform_handle.h.
int ClosePlatformHandle(PlatformHandle handle) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  // Make the return value UNIX-style.
  return CloseHandle(handle) ? 0 : -1;
#else
  return close(handle);
#endif
}

base::Status ListFilesRecursive(const std::string& dir_path,
                                std::vector<std::string>& output) {
  std::string root_dir_path = dir_path;
  if (root_dir_path.back() == '\\') {
    root_dir_path.back() = '/';
  } else if (root_dir_path.back() != '/') {
    root_dir_path.push_back('/');
  }

  // dir_queue contains full paths to the directories. The paths include the
  // root_dir_path at the beginning and the trailing slash at the end.
  std::deque<std::string> dir_queue;
  dir_queue.push_back(root_dir_path);

  while (!dir_queue.empty()) {
    const std::string cur_dir = std::move(dir_queue.front());
    dir_queue.pop_front();
#if PERFETTO_BUILDFLAG(PERFETTO_OS_NACL)
    return base::ErrStatus("ListFilesRecursive not supported yet");
#elif PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
    std::string glob_path = cur_dir + "*";
    // + 1 because we also have to count the NULL terminator.
    if (glob_path.length() + 1 > MAX_PATH)
      return base::ErrStatus("Directory path %s is too long", dir_path.c_str());
    WIN32_FIND_DATAA ffd;

    base::ScopedResource<HANDLE, CloseFindHandle, nullptr, false,
                         base::PlatformHandleChecker>
        hFind(FindFirstFileA(glob_path.c_str(), &ffd));
    if (!hFind) {
      // For empty directories, there should be at least one entry '.'.
      // If FindFirstFileA returns INVALID_HANDLE_VALUE, this means directory
      // couldn't be accessed.
      return base::ErrStatus("Failed to open directory %s", cur_dir.c_str());
    }
    do {
      if (strcmp(ffd.cFileName, ".") == 0 || strcmp(ffd.cFileName, "..") == 0)
        continue;
      if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
        std::string subdir_path = cur_dir + ffd.cFileName + '/';
        dir_queue.push_back(subdir_path);
      } else {
        const std::string full_path = cur_dir + ffd.cFileName;
        PERFETTO_CHECK(full_path.length() > root_dir_path.length());
        output.push_back(full_path.substr(root_dir_path.length()));
      }
    } while (FindNextFileA(*hFind, &ffd));
#else
    ScopedDir dir = ScopedDir(opendir(cur_dir.c_str()));
    if (!dir) {
      return base::ErrStatus("Failed to open directory %s", cur_dir.c_str());
    }
    for (auto* dirent = readdir(dir.get()); dirent != nullptr;
         dirent = readdir(dir.get())) {
      if (strcmp(dirent->d_name, ".") == 0 ||
          strcmp(dirent->d_name, "..") == 0) {
        continue;
      }
      if (dirent->d_type == DT_DIR) {
        dir_queue.push_back(cur_dir + dirent->d_name + '/');
      } else if (dirent->d_type == DT_REG) {
        const std::string full_path = cur_dir + dirent->d_name;
        PERFETTO_CHECK(full_path.length() > root_dir_path.length());
        output.push_back(full_path.substr(root_dir_path.length()));
      }
    }
#endif
  }
  return base::OkStatus();
}

std::string GetFileExtension(const std::string& filename) {
  auto ext_idx = filename.rfind('.');
  if (ext_idx == std::string::npos)
    return std::string();
  return filename.substr(ext_idx);
}

base::Optional<size_t> GetFileSize(const std::string& file_path) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  HANDLE file =
      CreateFileA(file_path.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr,
                  OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
  if (file == INVALID_HANDLE_VALUE) {
    return nullopt;
  }
  LARGE_INTEGER file_size;
  file_size.QuadPart = 0;
  BOOL ok = GetFileSizeEx(file, &file_size);
  CloseHandle(file);
  if (!ok) {
    return nullopt;
  }
  return static_cast<size_t>(file_size.QuadPart);
#else
  base::ScopedFile fd(base::OpenFile(file_path, O_RDONLY | O_CLOEXEC));
  if (!fd) {
    return nullopt;
  }
  struct stat buf{};
  if (fstat(*fd, &buf) == -1) {
    return nullopt;
  }
  return static_cast<size_t>(buf.st_size);
#endif
}

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

#include "perfetto/ext/base/file_utils.h"

#include <sys/stat.h>
#include <sys/types.h>

#include <algorithm>
#include <deque>
#include <string>
#include <vector>

#include "perfetto/base/build_config.h"
#include "perfetto/base/logging.h"
#include "perfetto/base/platform_handle.h"
#include "perfetto/base/status.h"
#include "perfetto/ext/base/scoped_file.h"
#include "perfetto/ext/base/utils.h"

#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
#include <Windows.h>
#include <direct.h>
#include <io.h>
#else
#include <dirent.h>
#include <unistd.h>
#endif

namespace perfetto {
namespace base {
namespace {
constexpr size_t kBufSize = 2048;

#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
// Wrap FindClose to: (1) make the return unix-style; (2) deal with stdcall.
int CloseFindHandle(HANDLE h) {
  return FindClose(h) ? 0 : -1;
}
#endif

}  // namespace

ssize_t Read(int fd, void* dst, size_t dst_size) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  return _read(fd, dst, static_cast<unsigned>(dst_size));
#else
  return PERFETTO_EINTR(read(fd, dst, dst_size));
#endif
}

bool ReadFileDescriptor(int fd, std::string* out) {
  // Do not override existing data in string.
  size_t i = out->size();

  struct stat buf {};
  if (fstat(fd, &buf) != -1) {
    if (buf.st_size > 0)
      out->resize(i + static_cast<size_t>(buf.st_size));
  }

  ssize_t bytes_read;
  for (;;) {
    if (out->size() < i + kBufSize)
      out->resize(out->size() + kBufSize);

    bytes_read = Read(fd, &((*out)[i]), kBufSize);
    if (bytes_read > 0) {
      i += static_cast<size_t>(bytes_read);
    } else {
      out->resize(i);
      return bytes_read == 0;
    }
  }
}

bool ReadPlatformHandle(PlatformHandle h, std::string* out) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  // Do not override existing data in string.
  size_t i = out->size();

  for (;;) {
    if (out->size() < i + kBufSize)
      out->resize(out->size() + kBufSize);
    DWORD bytes_read = 0;
    auto res = ::ReadFile(h, &((*out)[i]), kBufSize, &bytes_read, nullptr);
    if (res && bytes_read > 0) {
      i += static_cast<size_t>(bytes_read);
    } else {
      out->resize(i);
      const bool is_eof = res && bytes_read == 0;
      auto err = res ? 0 : GetLastError();
      // The "Broken pipe" error on Windows is slighly different than Unix:
      // On Unix: a "broken pipe" error can happen only on the writer side. On
      // the reader there is no broken pipe, just a EOF.
      // On windows: the reader also sees a broken pipe error.
      // Here we normalize on the Unix behavior, treating broken pipe as EOF.
      return is_eof || err == ERROR_BROKEN_PIPE;
    }
  }
#else
  return ReadFileDescriptor(h, out);
#endif
}

bool ReadFileStream(FILE* f, std::string* out) {
  return ReadFileDescriptor(fileno(f), out);
}

bool ReadFile(const std::string& path, std::string* out) {
  base::ScopedFile fd = base::OpenFile(path, O_RDONLY);
  if (!fd)
    return false;

  return ReadFileDescriptor(*fd, out);
}

ssize_t WriteAll(int fd, const void* buf, size_t count) {
  size_t written = 0;
  while (written < count) {
    // write() on windows takes an unsigned int size.
    uint32_t bytes_left = static_cast<uint32_t>(
        std::min(count - written, static_cast<size_t>(UINT32_MAX)));
    ssize_t wr = PERFETTO_EINTR(
        write(fd, static_cast<const char*>(buf) + written, bytes_left));
    if (wr == 0)
      break;
    if (wr < 0)
      return wr;
    written += static_cast<size_t>(wr);
  }
  return static_cast<ssize_t>(written);
}

ssize_t WriteAllHandle(PlatformHandle h, const void* buf, size_t count) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  DWORD wsize = 0;
  if (::WriteFile(h, buf, static_cast<DWORD>(count), &wsize, nullptr)) {
    return wsize;
  } else {
    return -1;
  }
#else
  return WriteAll(h, buf, count);
#endif
}

bool FlushFile(int fd) {
  PERFETTO_DCHECK(fd != 0);
#if PERFETTO_BUILDFLAG(PERFETTO_OS_LINUX) || \
    PERFETTO_BUILDFLAG(PERFETTO_OS_ANDROID)
  return !PERFETTO_EINTR(fdatasync(fd));
#elif PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  return !PERFETTO_EINTR(_commit(fd));
#else
  return !PERFETTO_EINTR(fsync(fd));
#endif
}

bool Mkdir(const std::string& path) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  return _mkdir(path.c_str()) == 0;
#else
  return mkdir(path.c_str(), 0755) == 0;
#endif
}

bool Rmdir(const std::string& path) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  return _rmdir(path.c_str()) == 0;
#else
  return rmdir(path.c_str()) == 0;
#endif
}

int CloseFile(int fd) {
  return close(fd);
}

ScopedFile OpenFile(const std::string& path, int flags, FileOpenMode mode) {
  PERFETTO_DCHECK((flags & O_CREAT) == 0 || mode != kFileModeInvalid);
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  // Always use O_BINARY on Windows, to avoid silly EOL translations.
  ScopedFile fd(_open(path.c_str(), flags | O_BINARY, mode));
#else
  // Always open a ScopedFile with O_CLOEXEC so we can safely fork and exec.
  ScopedFile fd(open(path.c_str(), flags | O_CLOEXEC, mode));
#endif
  return fd;
}

bool FileExists(const std::string& path) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  return _access(path.c_str(), 0) == 0;
#else
  return access(path.c_str(), F_OK) == 0;
#endif
}

// Declared in base/platform_handle.h.
int ClosePlatformHandle(PlatformHandle handle) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  // Make the return value UNIX-style.
  return CloseHandle(handle) ? 0 : -1;
#else
  return close(handle);
#endif
}

base::Status ListFilesRecursive(const std::string& dir_path,
                                std::vector<std::string>& output) {
  std::string root_dir_path = dir_path;
  if (root_dir_path.back() == '\\') {
    root_dir_path.back() = '/';
  } else if (root_dir_path.back() != '/') {
    root_dir_path.push_back('/');
  }

  // dir_queue contains full paths to the directories. The paths include the
  // root_dir_path at the beginning and the trailing slash at the end.
  std::deque<std::string> dir_queue;
  dir_queue.push_back(root_dir_path);

  while (!dir_queue.empty()) {
    const std::string cur_dir = std::move(dir_queue.front());
    dir_queue.pop_front();
#if PERFETTO_BUILDFLAG(PERFETTO_OS_NACL)
    return base::ErrStatus("ListFilesRecursive not supported yet");
#elif PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
    std::string glob_path = cur_dir + "*";
    // + 1 because we also have to count the NULL terminator.
    if (glob_path.length() + 1 > MAX_PATH)
      return base::ErrStatus("Directory path %s is too long", dir_path.c_str());
    WIN32_FIND_DATAA ffd;

    base::ScopedResource<HANDLE, CloseFindHandle, nullptr, false,
                         base::PlatformHandleChecker>
        hFind(FindFirstFileA(glob_path.c_str(), &ffd));
    if (!hFind) {
      // For empty directories, there should be at least one entry '.'.
      // If FindFirstFileA returns INVALID_HANDLE_VALUE, this means directory
      // couldn't be accessed.
      return base::ErrStatus("Failed to open directory %s", cur_dir.c_str());
    }
    do {
      if (strcmp(ffd.cFileName, ".") == 0 || strcmp(ffd.cFileName, "..") == 0)
        continue;
      if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
        std::string subdir_path = cur_dir + ffd.cFileName + '/';
        dir_queue.push_back(subdir_path);
      } else {
        const std::string full_path = cur_dir + ffd.cFileName;
        PERFETTO_CHECK(full_path.length() > root_dir_path.length());
        output.push_back(full_path.substr(root_dir_path.length()));
      }
    } while (FindNextFileA(*hFind, &ffd));
#else
    ScopedDir dir = ScopedDir(opendir(cur_dir.c_str()));
    if (!dir) {
      return base::ErrStatus("Failed to open directory %s", cur_dir.c_str());
    }
    for (auto* dirent = readdir(dir.get()); dirent != nullptr;
         dirent = readdir(dir.get())) {
      if (strcmp(dirent->d_name, ".") == 0 ||
          strcmp(dirent->d_name, "..") == 0) {
        continue;
      }
      if (dirent->d_type == DT_DIR) {
        dir_queue.push_back(cur_dir + dirent->d_name + '/');
      } else if (dirent->d_type == DT_REG) {
        const std::string full_path = cur_dir + dirent->d_name;
        PERFETTO_CHECK(full_path.length() > root_dir_path.length());
        output.push_back(full_path.substr(root_dir_path.length()));
      }
    }
#endif
  }
  return base::OkStatus();
}

std::string GetFileExtension(const std::string& filename) {
  auto ext_idx = filename.rfind('.');
  if (ext_idx == std::string::npos)
    return std::string();
  return filename.substr(ext_idx);
}

base::Optional<size_t> GetFileSize(const std::string& file_path) {
#if PERFETTO_BUILDFLAG(PERFETTO_OS_WIN)
  HANDLE file =
      CreateFileA(file_path.c_str(), GENERIC_READ, FILE_SHARE_READ, nullptr,
                  OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
  if (file == INVALID_HANDLE_VALUE) {
    return nullopt;
  }
  LARGE_INTEGER file_size;
  file_size.QuadPart = 0;
  BOOL ok = GetFileSizeEx(file, &file_size);
  CloseHandle(file);
  if (!ok) {
    return nullopt;
  }
  return static_cast<size_t>(file_size.QuadPart);
#else
  base::ScopedFile fd(base::OpenFile(file_path, O_RDONLY | O_CLOEXEC));
  if (!fd) {
    return nullopt;
  }
  struct stat buf{};
  if (fstat(*fd, &buf) == -1) {
    return nullopt;
  }
  return static_cast<size_t>(buf.st_size);
#endif
}

}  // namespace base
}  // namespace perfetto
<|endoftext|>


<commit_before>// Code partially copyright Edd Dawson 2007
//
// Boost Software License - Version 1.0 - August 17th, 2003
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

#include "libmesh/libmesh_config.h"
#include "libmesh/print_trace.h"
#include "libmesh/libmesh.h"

#include <unistd.h>  // needed for getpid()
#include <fstream>
#include <sstream>

#if defined(LIBMESH_HAVE_GCC_ABI_DEMANGLE) && defined(LIBMESH_HAVE_GLIBC_BACKTRACE)

#include <iostream>
#include <string>
#include <execinfo.h>
#include <cxxabi.h>
#include <cstdlib>

namespace libMesh
{

std::string process_trace(const char *name)
{
  std::string fullname = name;
  std::string saved_begin, saved_end;
  size_t namestart, nameend;

  /**
   * The Apple backtrace function returns more information than the Linux version.
   * We need to pass only the function name to the demangler or it won't decode it for us.
   *
   * lineno: stackframeno                 address functionname + offset
   */

#ifdef __APPLE__
  namestart = fullname.find("0x");
  if (namestart != std::string::npos)
    {
      namestart = fullname.find(' ', namestart) + 1;
      saved_begin = fullname.substr(0, namestart);
    }
  else
    namestart = 0;
  nameend = fullname.find('+');
  if (nameend == std::string::npos ||
      nameend <= namestart)
    nameend = fullname.size();
  else
    {
      nameend -= 1;
      saved_end = fullname.substr(nameend, fullname.length());
    }
#else
  namestart = fullname.find('(');
  if (namestart == std::string::npos)
    return fullname;
  else
    namestart++;
  nameend = fullname.find('+');
  if (nameend == std::string::npos ||
      nameend <= namestart)
    return fullname;
#endif

  std::string type_name = fullname.substr(namestart, nameend - namestart);

  // Try to demangle now
  return saved_begin + demangle(type_name.c_str()) + saved_end;
}

std::string demangle(const char *name)
{
  int status = 0;
  std::string ret = name;

  // Actually do the demangling
  char *demangled_name = abi::__cxa_demangle(name, 0, 0, &status);

  // If demangling returns non-NULL, save the result in a string.
  if (demangled_name)
    ret = demangled_name;

  // According to cxxabi.h docs, the caller is responsible for
  // deallocating memory.
  std::free(demangled_name);

  return ret;
}

void print_trace(std::ostream &out_stream)
{
  void *addresses[40];
  char **strings;

  int size = backtrace(addresses, 40);
  strings = backtrace_symbols(addresses, size);
  out_stream << "Stack frames: " << size << std::endl;
  for(int i = 0; i < size; i++)
    out_stream << i << ": " << process_trace(strings[i]) << std::endl;
  std::free(strings);
}

} // namespace libMesh

#else

namespace libMesh
{
void print_trace(std::ostream &) {}

std::string demangle(const char *name) { return std::string(name); }
}

#endif

namespace libMesh
{
void write_traceout()
{
#ifdef LIBMESH_ENABLE_TRACEFILES
  std::stringstream outname;
  outname << "traceout_" << static_cast<std::size_t>(libMesh::global_processor_id()) << '_' << getpid() << ".txt";
  std::ofstream traceout(outname.str().c_str(), std::ofstream::app);
  libMesh::print_trace(traceout);
#endif
}
}
<commit_msg>Adding gdb_backtrace() function.<commit_after>// Code partially copyright Edd Dawson 2007
//
// Boost Software License - Version 1.0 - August 17th, 2003
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
// 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT
// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.

#include "libmesh/libmesh_config.h"
#include "libmesh/print_trace.h"
#include "libmesh/libmesh.h"

#include <unistd.h>  // needed for getpid()
#include <fstream>
#include <sstream>
#include <string>
#include <cstdio> // std::remove
#include <cstdlib> // std::system
#include <sys/types.h> // pid_t

#if defined(LIBMESH_HAVE_GCC_ABI_DEMANGLE) && defined(LIBMESH_HAVE_GLIBC_BACKTRACE)

#include <execinfo.h>
#include <cxxabi.h>

namespace libMesh
{

std::string process_trace(const char *name)
{
  std::string fullname = name;
  std::string saved_begin, saved_end;
  size_t namestart, nameend;

  /**
   * The Apple backtrace function returns more information than the Linux version.
   * We need to pass only the function name to the demangler or it won't decode it for us.
   *
   * lineno: stackframeno                 address functionname + offset
   */

#ifdef __APPLE__
  namestart = fullname.find("0x");
  if (namestart != std::string::npos)
    {
      namestart = fullname.find(' ', namestart) + 1;
      saved_begin = fullname.substr(0, namestart);
    }
  else
    namestart = 0;
  nameend = fullname.find('+');
  if (nameend == std::string::npos ||
      nameend <= namestart)
    nameend = fullname.size();
  else
    {
      nameend -= 1;
      saved_end = fullname.substr(nameend, fullname.length());
    }
#else
  namestart = fullname.find('(');
  if (namestart == std::string::npos)
    return fullname;
  else
    namestart++;
  nameend = fullname.find('+');
  if (nameend == std::string::npos ||
      nameend <= namestart)
    return fullname;
#endif

  std::string type_name = fullname.substr(namestart, nameend - namestart);

  // Try to demangle now
  return saved_begin + demangle(type_name.c_str()) + saved_end;
}

std::string demangle(const char *name)
{
  int status = 0;
  std::string ret = name;

  // Actually do the demangling
  char *demangled_name = abi::__cxa_demangle(name, 0, 0, &status);

  // If demangling returns non-NULL, save the result in a string.
  if (demangled_name)
    ret = demangled_name;

  // According to cxxabi.h docs, the caller is responsible for
  // deallocating memory.
  std::free(demangled_name);

  return ret;
}

bool gdb_backtrace(std::ostream &out_stream)
{
  // Eventual return value, true if gdb succeeds, false otherwise.
  bool success = true;

  // The system() call does not allow us to redirect the output to a
  // C++ ostream, so we redirect gdb's output to a (known) temporary
  // file, and then send output that to the user's stream.
  char temp_file[] = "temp_print_trace.XXXXXX";
  int fd = mkstemp(temp_file);

  // If mkstemp fails, we failed.
  if (fd == -1)
    success = false;
  else
    {
      // Run gdb using a system() call, redirecting the output to our
      // temporary file.
      pid_t this_pid = getpid();
      std::ostringstream command;
      command << "gdb -p " << this_pid << " -batch -ex bt 2>/dev/null 1>" << temp_file;
      std::system(command.str().c_str());

      // If we can open the temp_file and it is not empty, we'll
      // assume that gdb worked, so copy the file's contents to the
      // user's requested stream.  This rdbuf() thing is apparently
      // how you do this... otherwise, report failure.
      std::ifstream fin(temp_file);
      if (fin && (fin.peek() != std::ifstream::traits_type::eof()))
        out_stream << fin.rdbuf();
      else
        success = false;
    }

  // Clean up the temporary file, regardless of whether it was opened successfully.
  std::remove(temp_file);

  return success;
}

void print_trace(std::ostream &out_stream)
{
  // First try a GDB backtrace.  They are better than what you get
  // from calling backtrace() because you don't have to do any
  // demangling, and they include line numbers!  If the GDB backtrace
  // fails, for example if your system does not have GDB, fall back to
  // calling backtrace().
  bool gdb_worked = gdb_backtrace(out_stream);

  if (!gdb_worked)
    {
      void *addresses[40];
      char **strings;

      int size = backtrace(addresses, 40);
      strings = backtrace_symbols(addresses, size);
      out_stream << "Stack frames: " << size << std::endl;
      for(int i = 0; i < size; i++)
        out_stream << i << ": " << process_trace(strings[i]) << std::endl;
      std::free(strings);
    }
}

} // namespace libMesh

#else

namespace libMesh
{
void print_trace(std::ostream &) {}

std::string demangle(const char *name) { return std::string(name); }
}

#endif

namespace libMesh
{
void write_traceout()
{
#ifdef LIBMESH_ENABLE_TRACEFILES
  std::stringstream outname;
  outname << "traceout_" << static_cast<std::size_t>(libMesh::global_processor_id()) << '_' << getpid() << ".txt";
  std::ofstream traceout(outname.str().c_str(), std::ofstream::app);
  libMesh::print_trace(traceout);
#endif
}
}
<|endoftext|>


<commit_before>// Copyright (c) 2010 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 "chrome/browser/geolocation/wifi_data_provider_common.h"

#include <vector>

#include "base/scoped_ptr.h"
#include "base/string_util.h"
#include "testing/gtest/include/gtest/gtest.h"

class MockWlanApi : public WifiDataProviderCommon::WlanApiInterface {
 public:
  MockWlanApi() : calls_(0), bool_return_(true) {
  }
  virtual bool GetAccessPointData(WifiData::AccessPointDataSet* data) {
    ++calls_;
    *data = data_out_;
    return bool_return_;
  }
  int calls_;
  bool bool_return_;
  WifiData::AccessPointDataSet data_out_;
};

// Stops the specified (nested) message loop when the listener is called back.
class MessageLoopQuitListener
    : public WifiDataProviderCommon::ListenerInterface {
 public:
  explicit MessageLoopQuitListener(MessageLoop* message_loop)
      : message_loop_to_quit_(message_loop) {
    CHECK(message_loop_to_quit_ != NULL);
  }
  // ListenerInterface
  virtual void DeviceDataUpdateAvailable(
      DeviceDataProvider<WifiData>* provider) {
    // Provider should call back on client's thread.
    EXPECT_EQ(MessageLoop::current(), message_loop_to_quit_);
    provider_ = provider;
    message_loop_to_quit_->Quit();
  }
  MessageLoop* message_loop_to_quit_;
  DeviceDataProvider<WifiData>* provider_;
};

class WifiDataProviderCommonWithMock : public WifiDataProviderCommon {
 public:
  WifiDataProviderCommonWithMock()
      : new_wlan_api_(new MockWlanApi) {}

  // WifiDataProviderCommon
  virtual WlanApiInterface* NewWlanApi() {
    CHECK(new_wlan_api_ != NULL);
    return new_wlan_api_.release();
  }
  virtual PollingPolicyInterface* NewPolicyPolicy() {
    return new GenericPollingPolicy<1, 2, 3>;
  }

  scoped_ptr<MockWlanApi> new_wlan_api_;

  DISALLOW_COPY_AND_ASSIGN(WifiDataProviderCommonWithMock);
};

WifiDataProviderImplBase* CreateWifiDataProviderCommonWithMock() {
  return new WifiDataProviderCommonWithMock;
}

// Main test fixture
class GeolocationWifiDataProviderCommonTest : public testing::Test {
 public:
  virtual void SetUp() {
    provider_ = new WifiDataProviderCommonWithMock;
    wlan_api_ = provider_->new_wlan_api_.get();
  }
  virtual void TearDown() {
    provider_->StopDataProvider();
    provider_ = NULL;
  }

 protected:
  MessageLoop main_message_loop_;
  scoped_refptr<WifiDataProviderCommonWithMock> provider_;
  MockWlanApi* wlan_api_;
};

TEST_F(GeolocationWifiDataProviderCommonTest, CreateDestroy) {
  // Test fixture members were SetUp correctly.
  EXPECT_EQ(&main_message_loop_, MessageLoop::current());
  EXPECT_TRUE(NULL != provider_.get());
  EXPECT_TRUE(NULL != wlan_api_);
}

TEST_F(GeolocationWifiDataProviderCommonTest, StartThread) {
  EXPECT_TRUE(provider_->StartDataProvider());
  provider_->StopDataProvider();
  SUCCEED();
}

TEST_F(GeolocationWifiDataProviderCommonTest, DoAnEmptyScan) {
  MessageLoopQuitListener quit_listener(&main_message_loop_);
  provider_->AddListener(&quit_listener);
  EXPECT_TRUE(provider_->StartDataProvider());
  main_message_loop_.Run();
  // Check we had at least one call. The worker thread may have raced ahead
  // and made multiple calls.
  EXPECT_GT(wlan_api_->calls_, 0);
  WifiData data;
  EXPECT_TRUE(provider_->GetData(&data));
  EXPECT_EQ(0, static_cast<int>(data.access_point_data.size()));
  provider_->RemoveListener(&quit_listener);
}

TEST_F(GeolocationWifiDataProviderCommonTest, DoScanWithResults) {
  MessageLoopQuitListener quit_listener(&main_message_loop_);
  provider_->AddListener(&quit_listener);
  AccessPointData single_access_point;
  single_access_point.age = 1;
  single_access_point.channel = 2;
  single_access_point.mac_address = 3;
  single_access_point.radio_signal_strength = 4;
  single_access_point.signal_to_noise = 5;
  single_access_point.ssid = ASCIIToUTF16("foossid");
  wlan_api_->data_out_.insert(single_access_point);

  EXPECT_TRUE(provider_->StartDataProvider());
  main_message_loop_.Run();
  EXPECT_GT(wlan_api_->calls_, 0);
  WifiData data;
  EXPECT_TRUE(provider_->GetData(&data));
  EXPECT_EQ(1, static_cast<int>(data.access_point_data.size()));
  EXPECT_EQ(single_access_point.age, data.access_point_data.begin()->age);
  EXPECT_EQ(single_access_point.ssid, data.access_point_data.begin()->ssid);
  provider_->RemoveListener(&quit_listener);
}

TEST_F(GeolocationWifiDataProviderCommonTest,
       StartThreadViaDeviceDataProvider) {
  MessageLoopQuitListener quit_listener(&main_message_loop_);
  WifiDataProvider::SetFactory(CreateWifiDataProviderCommonWithMock);
  DeviceDataProvider<WifiData>::Register(&quit_listener);
  main_message_loop_.Run();
  DeviceDataProvider<WifiData>::Unregister(&quit_listener);
  DeviceDataProvider<WifiData>::ResetFactory();
}
<commit_msg>Annotate test-only data race as benign BUG=35560 Review URL: http://codereview.chromium.org/606022<commit_after>// Copyright (c) 2010 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 "chrome/browser/geolocation/wifi_data_provider_common.h"

#include <vector>

#include "base/dynamic_annotations.h"
#include "base/scoped_ptr.h"
#include "base/string_util.h"
#include "testing/gtest/include/gtest/gtest.h"

class MockWlanApi : public WifiDataProviderCommon::WlanApiInterface {
 public:
  MockWlanApi() : calls_(0), bool_return_(true) {
    ANNOTATE_BENIGN_RACE(&calls_, "This is a test-only data race on a counter");
  }
  virtual bool GetAccessPointData(WifiData::AccessPointDataSet* data) {
    ++calls_;
    *data = data_out_;
    return bool_return_;
  }
  int calls_;
  bool bool_return_;
  WifiData::AccessPointDataSet data_out_;
};

// Stops the specified (nested) message loop when the listener is called back.
class MessageLoopQuitListener
    : public WifiDataProviderCommon::ListenerInterface {
 public:
  explicit MessageLoopQuitListener(MessageLoop* message_loop)
      : message_loop_to_quit_(message_loop) {
    CHECK(message_loop_to_quit_ != NULL);
  }
  // ListenerInterface
  virtual void DeviceDataUpdateAvailable(
      DeviceDataProvider<WifiData>* provider) {
    // Provider should call back on client's thread.
    EXPECT_EQ(MessageLoop::current(), message_loop_to_quit_);
    provider_ = provider;
    message_loop_to_quit_->Quit();
  }
  MessageLoop* message_loop_to_quit_;
  DeviceDataProvider<WifiData>* provider_;
};

class WifiDataProviderCommonWithMock : public WifiDataProviderCommon {
 public:
  WifiDataProviderCommonWithMock()
      : new_wlan_api_(new MockWlanApi) {}

  // WifiDataProviderCommon
  virtual WlanApiInterface* NewWlanApi() {
    CHECK(new_wlan_api_ != NULL);
    return new_wlan_api_.release();
  }
  virtual PollingPolicyInterface* NewPolicyPolicy() {
    return new GenericPollingPolicy<1, 2, 3>;
  }

  scoped_ptr<MockWlanApi> new_wlan_api_;

  DISALLOW_COPY_AND_ASSIGN(WifiDataProviderCommonWithMock);
};

WifiDataProviderImplBase* CreateWifiDataProviderCommonWithMock() {
  return new WifiDataProviderCommonWithMock;
}

// Main test fixture
class GeolocationWifiDataProviderCommonTest : public testing::Test {
 public:
  virtual void SetUp() {
    provider_ = new WifiDataProviderCommonWithMock;
    wlan_api_ = provider_->new_wlan_api_.get();
  }
  virtual void TearDown() {
    provider_->StopDataProvider();
    provider_ = NULL;
  }

 protected:
  MessageLoop main_message_loop_;
  scoped_refptr<WifiDataProviderCommonWithMock> provider_;
  MockWlanApi* wlan_api_;
};

TEST_F(GeolocationWifiDataProviderCommonTest, CreateDestroy) {
  // Test fixture members were SetUp correctly.
  EXPECT_EQ(&main_message_loop_, MessageLoop::current());
  EXPECT_TRUE(NULL != provider_.get());
  EXPECT_TRUE(NULL != wlan_api_);
}

TEST_F(GeolocationWifiDataProviderCommonTest, StartThread) {
  EXPECT_TRUE(provider_->StartDataProvider());
  provider_->StopDataProvider();
  SUCCEED();
}

TEST_F(GeolocationWifiDataProviderCommonTest, DoAnEmptyScan) {
  MessageLoopQuitListener quit_listener(&main_message_loop_);
  provider_->AddListener(&quit_listener);
  EXPECT_TRUE(provider_->StartDataProvider());
  main_message_loop_.Run();
  // Check we had at least one call. The worker thread may have raced ahead
  // and made multiple calls.
  EXPECT_GT(wlan_api_->calls_, 0);
  WifiData data;
  EXPECT_TRUE(provider_->GetData(&data));
  EXPECT_EQ(0, static_cast<int>(data.access_point_data.size()));
  provider_->RemoveListener(&quit_listener);
}

TEST_F(GeolocationWifiDataProviderCommonTest, DoScanWithResults) {
  MessageLoopQuitListener quit_listener(&main_message_loop_);
  provider_->AddListener(&quit_listener);
  AccessPointData single_access_point;
  single_access_point.age = 1;
  single_access_point.channel = 2;
  single_access_point.mac_address = 3;
  single_access_point.radio_signal_strength = 4;
  single_access_point.signal_to_noise = 5;
  single_access_point.ssid = ASCIIToUTF16("foossid");
  wlan_api_->data_out_.insert(single_access_point);

  EXPECT_TRUE(provider_->StartDataProvider());
  main_message_loop_.Run();
  EXPECT_GT(wlan_api_->calls_, 0);
  WifiData data;
  EXPECT_TRUE(provider_->GetData(&data));
  EXPECT_EQ(1, static_cast<int>(data.access_point_data.size()));
  EXPECT_EQ(single_access_point.age, data.access_point_data.begin()->age);
  EXPECT_EQ(single_access_point.ssid, data.access_point_data.begin()->ssid);
  provider_->RemoveListener(&quit_listener);
}

TEST_F(GeolocationWifiDataProviderCommonTest,
       StartThreadViaDeviceDataProvider) {
  MessageLoopQuitListener quit_listener(&main_message_loop_);
  WifiDataProvider::SetFactory(CreateWifiDataProviderCommonWithMock);
  DeviceDataProvider<WifiData>::Register(&quit_listener);
  main_message_loop_.Run();
  DeviceDataProvider<WifiData>::Unregister(&quit_listener);
  DeviceDataProvider<WifiData>::ResetFactory();
}
<|endoftext|>


<commit_before>// Copyright (c) 2015-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <bench/bench.h>

// Extremely fast-running benchmark:
#include <math.h>

volatile double sum = 0.0; // volatile, global so not optimized away

static void Trig(benchmark::Bench& bench)
{
    double d = 0.01;
    bench.run([&] {
        sum += sin(d);
        d += 0.000001;
    });
}

BENCHMARK(Trig);
<commit_msg>bench: Avoid deprecated use of volatile +=<commit_after>// Copyright (c) 2015-2020 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.

#include <bench/bench.h>

// Extremely fast-running benchmark:
#include <math.h>

volatile double sum = 0.0; // volatile, global so not optimized away

static void Trig(benchmark::Bench& bench)
{
    double d = 0.01;
    bench.run([&] {
        sum = sum + sin(d);
        d += 0.000001;
    });
}

BENCHMARK(Trig);
<|endoftext|>


<commit_before>//=======================================================================
// Copyright Baptiste Wicht 2013.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include "stl/types.hpp"

#include "vesa.hpp"
#include "paging.hpp"

#include "console.hpp"

/**
 * VESA Drawing implementation.
 *
 * This implemenation only supports 32bpp. Moreover, it also erases the
 * reserved bits of each pixel.
 */

namespace {

uint32_t* screen;

size_t x_shift;
size_t y_shift;

size_t red_shift;
size_t blue_shift;
size_t green_shift;

uint8_t font[256 * 8];

void init_font(){
    auto start = font + 8 * 'a';

    start[0] = 0x18;
    start[1] = 0x3C;
    start[2] = 0x66;
    start[3] = 0x7E;
    start[4] = 0x66;
    start[5] = 0x66;
    start[6] = 0x00;
    start[7] = 0x00;
}

#include "Liberation.c"

} //end of anonymous namespace

void vesa::init(){
    auto& block = vesa::mode_info_block;

    //Compute the address of the LFB
    screen = reinterpret_cast<uint32_t*>(block.linear_video_buffer);

    x_shift = 1;
    y_shift = block.bytes_per_scan_line / 4;

    red_shift = block.linear_red_mask_position;
    blue_shift = block.linear_blue_mask_position;
    green_shift = block.linear_green_mask_position;

    size_t total_size = static_cast<size_t>(block.height) * block.bytes_per_scan_line;

    auto first_page = reinterpret_cast<uintptr_t>(paging::page_align(screen));
    auto left_padding = reinterpret_cast<uintptr_t>(screen) - first_page;
    auto bytes = left_padding + paging::PAGE_SIZE + total_size;
    auto pages = (bytes / paging::PAGE_SIZE) + 1;

    paging::identity_map(reinterpret_cast<void*>(first_page), pages);

    init_font();
}

void vesa::draw_pixel(size_t x, size_t y, uint8_t r, uint8_t g, uint8_t b){
    auto where = x + y * y_shift;

    screen[where] = (r << red_shift) + (g << green_shift) + (b << blue_shift);
}

void vesa::draw_hline(size_t x, size_t y, size_t w, uint8_t r, uint8_t g, uint8_t b){
    auto where = x + y * y_shift;

    uint32_t color = (r << red_shift) + (g << green_shift) + (b << blue_shift);
    for(size_t i = 0; i < w; ++i){
        screen[where + i] = color;
    }
}

void vesa::draw_vline(size_t x, size_t y, size_t h, uint8_t r, uint8_t g, uint8_t b){
    auto where = x + y * y_shift;

    uint32_t color = (r << red_shift) + (g << green_shift) + (b << blue_shift);
    for(size_t i = 0; i < h; ++i){
        screen[where + i * y_shift] = color;
    }
}

void vesa::draw_char(size_t x, size_t y, char c, uint8_t r, uint8_t g, uint8_t b){
    //auto where = x + y * y_shift;
    //uint32_t color = (r << red_shift) + (g << green_shift) + (b << blue_shift);

    auto font_char = &Liberation_VESA_data[c * 16];

    for(size_t i = 0; i < 16; ++i){
        for(size_t j = 0; j < 8; ++j){
            if(font_char[i] & (1 << j)){
                draw_pixel(x + (8 - j), y + i, r, g, b);
            }
        }
    }
}
<commit_msg>Clean<commit_after>//=======================================================================
// Copyright Baptiste Wicht 2013.
// Distributed under the Boost Software License, Version 1.0.
// (See accompanying file LICENSE_1_0.txt or copy at
//  http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================

#include "stl/types.hpp"

#include "vesa.hpp"
#include "paging.hpp"

#include "console.hpp"

/**
 * VESA Drawing implementation.
 *
 * This implemenation only supports 32bpp. Moreover, it also erases the
 * reserved bits of each pixel.
 */

namespace {

uint32_t* screen;

size_t x_shift;
size_t y_shift;

size_t red_shift;
size_t blue_shift;
size_t green_shift;

uint8_t font[256 * 8];

void init_font(){
    auto start = font + 8 * 'a';

    start[0] = 0x18;
    start[1] = 0x3C;
    start[2] = 0x66;
    start[3] = 0x7E;
    start[4] = 0x66;
    start[5] = 0x66;
    start[6] = 0x00;
    start[7] = 0x00;
}

#include "Liberation.c"

} //end of anonymous namespace

void vesa::init(){
    auto& block = vesa::mode_info_block;

    //Compute the address of the LFB
    screen = reinterpret_cast<uint32_t*>(block.linear_video_buffer);

    x_shift = 1;
    y_shift = block.bytes_per_scan_line / 4;

    red_shift = block.linear_red_mask_position;
    blue_shift = block.linear_blue_mask_position;
    green_shift = block.linear_green_mask_position;

    size_t total_size = static_cast<size_t>(block.height) * block.bytes_per_scan_line;

    auto first_page = reinterpret_cast<uintptr_t>(paging::page_align(screen));
    auto left_padding = reinterpret_cast<uintptr_t>(screen) - first_page;
    auto bytes = left_padding + paging::PAGE_SIZE + total_size;
    auto pages = (bytes / paging::PAGE_SIZE) + 1;

    paging::identity_map(reinterpret_cast<void*>(first_page), pages);

    init_font();
}

void vesa::draw_pixel(size_t x, size_t y, uint8_t r, uint8_t g, uint8_t b){
    auto where = x + y * y_shift;

    screen[where] = (r << red_shift) + (g << green_shift) + (b << blue_shift);
}

void vesa::draw_hline(size_t x, size_t y, size_t w, uint8_t r, uint8_t g, uint8_t b){
    auto where = x + y * y_shift;

    uint32_t color = (r << red_shift) + (g << green_shift) + (b << blue_shift);
    for(size_t i = 0; i < w; ++i){
        screen[where + i] = color;
    }
}

void vesa::draw_vline(size_t x, size_t y, size_t h, uint8_t r, uint8_t g, uint8_t b){
    auto where = x + y * y_shift;

    uint32_t color = (r << red_shift) + (g << green_shift) + (b << blue_shift);
    for(size_t i = 0; i < h; ++i){
        screen[where + i * y_shift] = color;
    }
}

void vesa::draw_char(size_t x, size_t y, char c, uint8_t r, uint8_t g, uint8_t b){
    //auto where = x + y * y_shift;
    //uint32_t color = (r << red_shift) + (g << green_shift) + (b << blue_shift);

    auto font_char = &Liberation_VESA_data[c * 16];

    for(size_t i = 0; i < 16; ++i){
        for(size_t j = 0; j < 8; ++j){
            if(font_char[i] & (1 << (8 - j))){
                draw_pixel(x + j, y + i, r, g, b);
            }
        }
    }
}
<|endoftext|>