<commit_before>/**************************************************************************
**
** This file is part of the Qt Build Suite
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file.
** Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**************************************************************************/
#include <QtCore/QCoreApplication>
#include <QtCore/QProcess>
#include <QtCore/QDir>
#include <QtCore/QDirIterator>
#include <QtCore/QStringList>
#include <QtCore/QDebug>
#include <QtCore/QTextStream>
#include <QtCore/QSettings>

#include <tools/platform.h>
#include "msvcprobe.h"

using namespace qbs;

static QString searchPath(const QString &path, const QString &me)
{
    //TODO: use native seperator
    foreach (const QString &ppath, path.split(":")) {
        if (QFileInfo(ppath +  "/"  +  me).exists()) {
            return QDir::cleanPath(ppath +  "/"  +  me);
        }
    }
    return QString();
}

static QString qsystem(const QString &exe, const QStringList &args = QStringList())
{
    QProcess p;
    p.setProcessChannelMode(QProcess::MergedChannels);
    p.start(exe, args);
    p.waitForStarted();
    p.waitForFinished();
    return QString::fromLocal8Bit(p.readAll());
}

static int specific_probe(const QString &settingsPath,
                          QHash<QString, Platform::Ptr> &platforms,
                          QString cc,
                          bool printComfortingMessage = false)
{
    QTextStream qstdout(stdout);

    QString toolchainType;
    if(cc.contains("clang"))
        toolchainType = "clang";
    else if (cc.contains("gcc"))
        toolchainType = "gcc";

    QString path       = QString::fromLocal8Bit(qgetenv("PATH"));
    QString cxx        = QString::fromLocal8Bit(qgetenv("CXX"));
    QString ld         = QString::fromLocal8Bit(qgetenv("LD"));
    QString cflags     = QString::fromLocal8Bit(qgetenv("CFLAGS"));
    QString cxxflags   = QString::fromLocal8Bit(qgetenv("CXXFLAGS"));
    QString ldflags    = QString::fromLocal8Bit(qgetenv("LDFLAGS"));
    QString cross      = QString::fromLocal8Bit(qgetenv("CROSS_COMPILE"));
    QString arch       = QString::fromLocal8Bit(qgetenv("ARCH"));

    QString pathToGcc;
    QString architecture;
    QString endianness;

    QString name;
    QString sysroot;

    QString uname = qsystem("uname", QStringList() << "-m").simplified();

    if (arch.isEmpty())
        arch = uname;

#ifdef Q_OS_MAC
    // HACK: "uname -m" reports "i386" but "gcc -dumpmachine" reports "i686" on MacOS.
    if (arch == "i386")
        arch = "i686";
#endif

    if (ld.isEmpty())
        ld = "ld";
    if (cxx.isEmpty()) {
        if (toolchainType == "gcc")
            cxx = "g++";
        else if(toolchainType == "clang")
            cxx = "clang++";
    }
    if(!cross.isEmpty() && !cc.startsWith("/")) {
        pathToGcc = searchPath(path, cross + cc);
        if (QFileInfo(pathToGcc).exists()) {
            if (!cc.contains(cross))
                cc.prepend(cross);
            if (!cxx.contains(cross))
                cxx.prepend(cross);
            if (!ld.contains(cross))
                ld.prepend(cross);
        }
    }
    if (cc.startsWith("/"))
        pathToGcc = cc;
    else
        pathToGcc = searchPath(path, cc);

    if (!QFileInfo(pathToGcc).exists()) {
        fprintf(stderr, "Cannot find %s.", qPrintable(cc));
        if (printComfortingMessage)
            fprintf(stderr, " But that's not a problem. I've already found other platforms.\n");
        else
            fprintf(stderr, "\n");
        return 1;
    }

    Platform::Ptr s;
    foreach (Platform::Ptr p, platforms.values()) {
        QString path = p->settings.value(Platform::internalKey() + "/completeccpath").toString();
        if (path == pathToGcc) {
            name = p->name;
            s = p;
            name = s->name;
            break;
        }
    }

    QString compilerTriplet = qsystem(pathToGcc, QStringList() << "-dumpmachine").simplified();
    QStringList compilerTripletl = compilerTriplet.split('-');
    if (compilerTripletl.count() < 2 ||
            !(compilerTripletl.at(0).contains(QRegExp(".86")) ||
              compilerTripletl.at(0).contains("arm") )
            ) {
        qDebug("detected %s , but i don't understand it's architecture: %s",
                qPrintable(pathToGcc), qPrintable(compilerTriplet));
                return 12;
    }

    architecture = compilerTripletl.at(0);
    if (architecture.contains("arm")) {
        endianness = "big-endian";
    } else {
        endianness = "little-endian";
    }

    QStringList pathToGccL = pathToGcc.split('/');
    QString compilerName = pathToGccL.takeLast().replace(cc, cxx);

    if (cflags.contains("--sysroot")) {
        QStringList flagl = cflags.split(' ');

        bool nextitis = false;
        foreach (const QString &flag, flagl) {
            if (nextitis) {
                sysroot = flag;
                break;
            }
            if (flag == "--sysroot") {
                nextitis = true;
            }
        }
    }

    qstdout << "==> " << (s?"reconfiguring " + name :"detected")
            << " " << pathToGcc << "\n"
            << "     triplet:  " << compilerTriplet << "\n"
            << "     arch:     " << architecture << "\n"
            << "     bin:      " << pathToGccL.join("/") << "\n"
            << "     cc:       " << cc << "\n"
            ;

    if (!cxx.isEmpty())
       qstdout << "     cxx:      " << cxx << "\n";
    if (!ld.isEmpty())
       qstdout << "     ld:       " << ld << "\n";

    if (!sysroot.isEmpty())
        qstdout << "     sysroot:  " << sysroot << "\n";
    if (!cflags.isEmpty())
            qstdout << "     CFLAGS:   " << cflags << "\n";
    if (!cxxflags.isEmpty())
            qstdout << "     CXXFLAGS: " << cxxflags << "\n";
    if (!ldflags.isEmpty())
            qstdout << "     CXXFLAGS: " << ldflags << "\n";

    qstdout  << flush;

    if (!s) {
        if (name.isEmpty())
            name = toolchainType;
       s = Platform::Ptr(new Platform(name, settingsPath + "/" + name));
    }

    // fixme should be cpp.toolchain
    // also there is no toolchain:clang
    s->settings.setValue("toolchain", "gcc");
    s->settings.setValue(Platform::internalKey() + "/completeccpath", pathToGcc);
    s->settings.setValue(Platform::internalKey() + "/target-triplet", compilerTriplet);
    s->settings.setValue("architecture", architecture);
    s->settings.setValue("endianness", endianness);

#if defined(Q_OS_MAC)
    s->settings.setValue("targetOS", "mac");
#elif defined(Q_OS_LINUX)
    s->settings.setValue("targetOS", "linux");
#else
    s->settings.setValue("targetOS", "unknown"); //fixme
#endif

    if (compilerName.contains('-')) {
        QStringList nl = compilerName.split('-');
        s->settings.setValue("cpp/compilerName", nl.takeLast());
        s->settings.setValue("cpp/toolchainPrefix", nl.join("-") + '-');
    } else {
        s->settings.setValue("cpp/compilerName", compilerName);
    }
    s->settings.setValue("cpp/toolchainInstallPath", pathToGccL.join("/"));

    if (!cross.isEmpty())
        s->settings.setValue("environment/CROSS_COMPILE", cross);
    if (!cflags.isEmpty())
        s->settings.setValue("environment/CFLAGS", cflags);
    if (!cxxflags.isEmpty())
        s->settings.setValue("environment/CXXFLAGS", cxxflags);
    if (!ldflags.isEmpty())
        s->settings.setValue("environment/LDFLAGS", ldflags);

    platforms.insert(s->name, s);
    return 0;
}

#ifdef Q_OS_WIN
static void mingwProbe(const QString &settingsPath, QHash<QString, Platform::Ptr> &platforms)
{
    QString mingwPath;
    QString mingwBinPath;
    QString gccPath;
    QByteArray envPath = qgetenv("PATH");
    foreach (const QByteArray &dir, envPath.split(';')) {
        QFileInfo fi(dir + "/gcc.exe");
        if (fi.exists()) {
            mingwPath = QFileInfo(dir + "/..").canonicalFilePath();
            gccPath = fi.absoluteFilePath();
            mingwBinPath = fi.absolutePath();
            break;
        }
    }
    if (gccPath.isEmpty())
        return;
    QProcess process;
    process.start(gccPath, QStringList() << "-dumpmachine");
    if (!process.waitForStarted()) {
        fprintf(stderr, "Could not start \"gcc -dumpmachine\".\n");
        return;
    }
    process.waitForFinished(-1);
    QByteArray gccMachineName = process.readAll().trimmed();
    if (gccMachineName != "mingw32" && gccMachineName != "mingw64") {
        fprintf(stderr, "Detected gcc platform '%s' is not supported.\n", gccMachineName.data());
        return;
    }

    Platform::Ptr platform = platforms.value(gccMachineName);
    printf("Platform '%s' detected in '%s'.", gccMachineName.data(), qPrintable(QDir::toNativeSeparators(mingwPath)));
    if (!platform) {
       platform = Platform::Ptr(new Platform(gccMachineName, settingsPath + "/" + gccMachineName));
       platforms.insert(platform->name, platform);
    }
    platform->settings.setValue("targetOS", "windows");
    platform->settings.setValue("cpp/toolchainInstallPath", QDir::toNativeSeparators(mingwBinPath));
    platform->settings.setValue("toolchain", "mingw");
}
#endif

int probe(const QString &settingsPath, QHash<QString, Platform::Ptr> &platforms)
{
#ifdef Q_OS_WIN
    msvcProbe(settingsPath, platforms);
    mingwProbe(settingsPath, platforms);
#else
    QString cc = QString::fromLocal8Bit(qgetenv("CC"));
    if (cc.isEmpty()) {
        bool somethingFound = false;
        if (specific_probe(settingsPath, platforms, "gcc") == 0)
            somethingFound = true;
        specific_probe(settingsPath, platforms, "clang", somethingFound);
    } else {
        specific_probe(settingsPath, platforms, cc);
    }
#endif
    if (platforms.isEmpty())
        fprintf(stderr, "Could not detect any platforms.\n");
    return 0;
}
<commit_msg>platform prober: do not read the CC environment variable<commit_after>/**************************************************************************
**
** This file is part of the Qt Build Suite
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (info@qt.nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU General
** Public License version 3.0 as published by the Free Software Foundation
** and appearing in the file LICENSE.GPL included in the packaging of this
** file.
** Please review the following information to ensure the GNU General
** Public License version 3.0 requirements will be met:
** http://www.gnu.org/copyleft/gpl.html.
**
** Other Usage
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
**************************************************************************/
#include <QtCore/QCoreApplication>
#include <QtCore/QProcess>
#include <QtCore/QDir>
#include <QtCore/QDirIterator>
#include <QtCore/QStringList>
#include <QtCore/QDebug>
#include <QtCore/QTextStream>
#include <QtCore/QSettings>

#include <tools/platform.h>
#include "msvcprobe.h"

using namespace qbs;

static QString searchPath(const QString &path, const QString &me)
{
    //TODO: use native seperator
    foreach (const QString &ppath, path.split(":")) {
        if (QFileInfo(ppath +  "/"  +  me).exists()) {
            return QDir::cleanPath(ppath +  "/"  +  me);
        }
    }
    return QString();
}

static QString qsystem(const QString &exe, const QStringList &args = QStringList())
{
    QProcess p;
    p.setProcessChannelMode(QProcess::MergedChannels);
    p.start(exe, args);
    p.waitForStarted();
    p.waitForFinished();
    return QString::fromLocal8Bit(p.readAll());
}

static int specific_probe(const QString &settingsPath,
                          QHash<QString, Platform::Ptr> &platforms,
                          QString cc,
                          bool printComfortingMessage = false)
{
    QTextStream qstdout(stdout);

    QString toolchainType;
    if(cc.contains("clang"))
        toolchainType = "clang";
    else if (cc.contains("gcc"))
        toolchainType = "gcc";

    QString path       = QString::fromLocal8Bit(qgetenv("PATH"));
    QString cxx        = QString::fromLocal8Bit(qgetenv("CXX"));
    QString ld         = QString::fromLocal8Bit(qgetenv("LD"));
    QString cflags     = QString::fromLocal8Bit(qgetenv("CFLAGS"));
    QString cxxflags   = QString::fromLocal8Bit(qgetenv("CXXFLAGS"));
    QString ldflags    = QString::fromLocal8Bit(qgetenv("LDFLAGS"));
    QString cross      = QString::fromLocal8Bit(qgetenv("CROSS_COMPILE"));
    QString arch       = QString::fromLocal8Bit(qgetenv("ARCH"));

    QString pathToGcc;
    QString architecture;
    QString endianness;

    QString name;
    QString sysroot;

    QString uname = qsystem("uname", QStringList() << "-m").simplified();

    if (arch.isEmpty())
        arch = uname;

#ifdef Q_OS_MAC
    // HACK: "uname -m" reports "i386" but "gcc -dumpmachine" reports "i686" on MacOS.
    if (arch == "i386")
        arch = "i686";
#endif

    if (ld.isEmpty())
        ld = "ld";
    if (cxx.isEmpty()) {
        if (toolchainType == "gcc")
            cxx = "g++";
        else if(toolchainType == "clang")
            cxx = "clang++";
    }
    if(!cross.isEmpty() && !cc.startsWith("/")) {
        pathToGcc = searchPath(path, cross + cc);
        if (QFileInfo(pathToGcc).exists()) {
            if (!cc.contains(cross))
                cc.prepend(cross);
            if (!cxx.contains(cross))
                cxx.prepend(cross);
            if (!ld.contains(cross))
                ld.prepend(cross);
        }
    }
    if (cc.startsWith("/"))
        pathToGcc = cc;
    else
        pathToGcc = searchPath(path, cc);

    if (!QFileInfo(pathToGcc).exists()) {
        fprintf(stderr, "Cannot find %s.", qPrintable(cc));
        if (printComfortingMessage)
            fprintf(stderr, " But that's not a problem. I've already found other platforms.\n");
        else
            fprintf(stderr, "\n");
        return 1;
    }

    Platform::Ptr s;
    foreach (Platform::Ptr p, platforms.values()) {
        QString path = p->settings.value(Platform::internalKey() + "/completeccpath").toString();
        if (path == pathToGcc) {
            name = p->name;
            s = p;
            name = s->name;
            break;
        }
    }

    QString compilerTriplet = qsystem(pathToGcc, QStringList() << "-dumpmachine").simplified();
    QStringList compilerTripletl = compilerTriplet.split('-');
    if (compilerTripletl.count() < 2 ||
            !(compilerTripletl.at(0).contains(QRegExp(".86")) ||
              compilerTripletl.at(0).contains("arm") )
            ) {
        qDebug("detected %s , but i don't understand it's architecture: %s",
                qPrintable(pathToGcc), qPrintable(compilerTriplet));
                return 12;
    }

    architecture = compilerTripletl.at(0);
    if (architecture.contains("arm")) {
        endianness = "big-endian";
    } else {
        endianness = "little-endian";
    }

    QStringList pathToGccL = pathToGcc.split('/');
    QString compilerName = pathToGccL.takeLast().replace(cc, cxx);

    if (cflags.contains("--sysroot")) {
        QStringList flagl = cflags.split(' ');

        bool nextitis = false;
        foreach (const QString &flag, flagl) {
            if (nextitis) {
                sysroot = flag;
                break;
            }
            if (flag == "--sysroot") {
                nextitis = true;
            }
        }
    }

    qstdout << "==> " << (s?"reconfiguring " + name :"detected")
            << " " << pathToGcc << "\n"
            << "     triplet:  " << compilerTriplet << "\n"
            << "     arch:     " << architecture << "\n"
            << "     bin:      " << pathToGccL.join("/") << "\n"
            << "     cc:       " << cc << "\n"
            ;

    if (!cxx.isEmpty())
       qstdout << "     cxx:      " << cxx << "\n";
    if (!ld.isEmpty())
       qstdout << "     ld:       " << ld << "\n";

    if (!sysroot.isEmpty())
        qstdout << "     sysroot:  " << sysroot << "\n";
    if (!cflags.isEmpty())
            qstdout << "     CFLAGS:   " << cflags << "\n";
    if (!cxxflags.isEmpty())
            qstdout << "     CXXFLAGS: " << cxxflags << "\n";
    if (!ldflags.isEmpty())
            qstdout << "     CXXFLAGS: " << ldflags << "\n";

    qstdout  << flush;

    if (!s) {
        if (name.isEmpty())
            name = toolchainType;
       s = Platform::Ptr(new Platform(name, settingsPath + "/" + name));
    }

    // fixme should be cpp.toolchain
    // also there is no toolchain:clang
    s->settings.setValue("toolchain", "gcc");
    s->settings.setValue(Platform::internalKey() + "/completeccpath", pathToGcc);
    s->settings.setValue(Platform::internalKey() + "/target-triplet", compilerTriplet);
    s->settings.setValue("architecture", architecture);
    s->settings.setValue("endianness", endianness);

#if defined(Q_OS_MAC)
    s->settings.setValue("targetOS", "mac");
#elif defined(Q_OS_LINUX)
    s->settings.setValue("targetOS", "linux");
#else
    s->settings.setValue("targetOS", "unknown"); //fixme
#endif

    if (compilerName.contains('-')) {
        QStringList nl = compilerName.split('-');
        s->settings.setValue("cpp/compilerName", nl.takeLast());
        s->settings.setValue("cpp/toolchainPrefix", nl.join("-") + '-');
    } else {
        s->settings.setValue("cpp/compilerName", compilerName);
    }
    s->settings.setValue("cpp/toolchainInstallPath", pathToGccL.join("/"));

    if (!cross.isEmpty())
        s->settings.setValue("environment/CROSS_COMPILE", cross);
    if (!cflags.isEmpty())
        s->settings.setValue("environment/CFLAGS", cflags);
    if (!cxxflags.isEmpty())
        s->settings.setValue("environment/CXXFLAGS", cxxflags);
    if (!ldflags.isEmpty())
        s->settings.setValue("environment/LDFLAGS", ldflags);

    platforms.insert(s->name, s);
    return 0;
}

#ifdef Q_OS_WIN
static void mingwProbe(const QString &settingsPath, QHash<QString, Platform::Ptr> &platforms)
{
    QString mingwPath;
    QString mingwBinPath;
    QString gccPath;
    QByteArray envPath = qgetenv("PATH");
    foreach (const QByteArray &dir, envPath.split(';')) {
        QFileInfo fi(dir + "/gcc.exe");
        if (fi.exists()) {
            mingwPath = QFileInfo(dir + "/..").canonicalFilePath();
            gccPath = fi.absoluteFilePath();
            mingwBinPath = fi.absolutePath();
            break;
        }
    }
    if (gccPath.isEmpty())
        return;
    QProcess process;
    process.start(gccPath, QStringList() << "-dumpmachine");
    if (!process.waitForStarted()) {
        fprintf(stderr, "Could not start \"gcc -dumpmachine\".\n");
        return;
    }
    process.waitForFinished(-1);
    QByteArray gccMachineName = process.readAll().trimmed();
    if (gccMachineName != "mingw32" && gccMachineName != "mingw64") {
        fprintf(stderr, "Detected gcc platform '%s' is not supported.\n", gccMachineName.data());
        return;
    }

    Platform::Ptr platform = platforms.value(gccMachineName);
    printf("Platform '%s' detected in '%s'.", gccMachineName.data(), qPrintable(QDir::toNativeSeparators(mingwPath)));
    if (!platform) {
       platform = Platform::Ptr(new Platform(gccMachineName, settingsPath + "/" + gccMachineName));
       platforms.insert(platform->name, platform);
    }
    platform->settings.setValue("targetOS", "windows");
    platform->settings.setValue("cpp/toolchainInstallPath", QDir::toNativeSeparators(mingwBinPath));
    platform->settings.setValue("toolchain", "mingw");
}
#endif

int probe(const QString &settingsPath, QHash<QString, Platform::Ptr> &platforms)
{
#ifdef Q_OS_WIN
    msvcProbe(settingsPath, platforms);
    mingwProbe(settingsPath, platforms);
#else
    bool somethingFound = false;
    if (specific_probe(settingsPath, platforms, "gcc") == 0)
        somethingFound = true;
    specific_probe(settingsPath, platforms, "clang", somethingFound);
#endif
    if (platforms.isEmpty())
        fprintf(stderr, "Could not detect any platforms.\n");
    return 0;
}
<|endoftext|>


<commit_before>#include "stdafx.h"

#include "Ogre_glTF_materialLoader.hpp"
#include "Ogre_glTF_textureImporter.hpp"
#include "Ogre_glTF_common.hpp"
#include <OgreHlmsPbsDatablock.h>
#include <OgreHlms.h>
#include <OgreHlmsManager.h>
#include <OgreLogManager.h>
#include "Ogre_glTF_internal_utils.hpp"

using namespace Ogre_glTF;

Ogre::Vector3 materialLoader::convertColor(const tinygltf::ColorValue& color)
{
	std::array<float, 4> colorBuffer{};
	internal_utils::container_double_to_float(color, colorBuffer);
	return Ogre::Vector3 { colorBuffer.data() };
}

void materialLoader::setBaseColor(Ogre::HlmsPbsDatablock* block, Ogre::Vector3 color) const
{
	block->setDiffuse(color);
}

void materialLoader::setMetallicValue(Ogre::HlmsPbsDatablock* block, Ogre::Real value) const
{
	block->setMetalness(value);
}

void materialLoader::setRoughnesValue(Ogre::HlmsPbsDatablock* block, Ogre::Real value) const
{
	block->setRoughness(value);
}

void materialLoader::setEmissiveColor(Ogre::HlmsPbsDatablock* block, Ogre::Vector3 color) const
{
	block->setEmissive(color);
}

bool materialLoader::isTextureIndexValid(int value) const
{
	return !(value < 0);
}

void materialLoader::setBaseColorTexture(Ogre::HlmsPbsDatablock* block, int value) const
{
	if(!isTextureIndexValid(value)) return;
	auto texture = textureImporterRef.getTexture(value);
	if(texture)
	{
		//OgreLog("diffuse texture from textureImporter : " + texture->getName());
		block->setTexture(Ogre::PbsTextureTypes::PBSM_DIFFUSE, 0, texture);
	}
}

void materialLoader::setMetalRoughTexture(Ogre::HlmsPbsDatablock* block, int gltfTextureID) const
{
	if(!isTextureIndexValid(gltfTextureID)) return;
	//Ogre cannot use combined metal rough textures. Metal is in the R channel, and rough in the G channel. It seems that the images are loaded as BGR by the libarry
	//R channel is channel 2 (from 0), G channel is 1.

	auto metalTexure = textureImporterRef.generateGreyScaleFromChannel(gltfTextureID, 2);
	auto roughTexure = textureImporterRef.generateGreyScaleFromChannel(gltfTextureID, 1);

	if(metalTexure)
	{
		//OgreLog("metalness grey-scale texture extracted by textureImporter : " + metalTexure->getName());
		block->setTexture(Ogre::PBSM_METALLIC, 0, metalTexure);
	}

	if(roughTexure)
	{
		//OgreLog("roughness grey-scale texture extracted by textureImporter : " + roughTexure->getName());
		block->setTexture(Ogre::PBSM_ROUGHNESS, 0, roughTexure);
	}
}

void materialLoader::setNormalTexture(Ogre::HlmsPbsDatablock* block, int value) const
{
	if(!isTextureIndexValid(value)) return;
	auto texture = textureImporterRef.getNormalSNORM(value);
	if(texture)
	{
		//OgreLog("normal texture from textureImporter : " + texture->getName());
		block->setTexture(Ogre::PbsTextureTypes::PBSM_NORMAL, 0, texture);
	}
}

void materialLoader::setOcclusionTexture(Ogre::HlmsPbsDatablock* block, int value) const
{
	if(!isTextureIndexValid(value)) return;
	auto texture = textureImporterRef.getTexture(value);
	if(texture)
	{
		//OgreLog("occlusion texture from textureImporter : " + texture->getName());
		//OgreLog("Warning: Ogre doesn't support occlusion map in it's HLMS PBS implementation!");
		//block->setTexture(Ogre::PbsTextureTypes::PBSM_, 0, texture);
	}
}

void materialLoader::setEmissiveTexture(Ogre::HlmsPbsDatablock* block, int value) const
{
	if(!isTextureIndexValid(value)) return;
	auto texture = textureImporterRef.getTexture(value);
	if(texture)
	{
		//OgreLog("emissive texture from textureImporter : " + texture->getName());
		block->setTexture(Ogre::PbsTextureTypes::PBSM_EMISSIVE, 0, texture);
	}
}

void materialLoader::setAlphaMode(Ogre::HlmsPbsDatablock* block, const std::string& mode) const
{
	if(mode == "BLEND")
	{
		auto blendBlock = *block->getBlendblock();
		blendBlock.setBlendType(Ogre::SBT_TRANSPARENT_ALPHA);
		block->setBlendblock(blendBlock);
	}
	else if(mode =="MASK")
	{
		block->setAlphaTest( Ogre::CMPF_GREATER_EQUAL );
	}
}

void materialLoader::setAlphaCutoff(Ogre::HlmsPbsDatablock* block, Ogre::Real value) const
{
	block->setAlphaTestThreshold(value);
}

materialLoader::materialLoader(tinygltf::Model& input, textureImporter& textureInterface) :
	textureImporterRef(textureInterface),
	model(input)
{
}

Ogre::HlmsDatablock* materialLoader::getDatablock(size_t index) const
{
	//OgreLog("Loading material...");
	//TODO this will need some modification if we support multiple meshes by glTF file
	auto HlmsPbs			 = static_cast<Ogre::HlmsPbs*>(Ogre::Root::getSingleton().getHlmsManager()->getHlms(Ogre::HlmsTypes::HLMS_PBS));
	//const auto mainMeshIndex = (model.defaultScene != 0 ? model.nodes[model.scenes[model.defaultScene].nodes.front()].mesh : 0);
	//const auto& mesh		 = model.meshes[mainMeshIndex];
	//const auto material    = model.materials[mesh.primitives.at(index).material];
    const auto material		 = model.materials[index];

    std::string mtlName = material.name + "_" + std::to_string(index);
	auto datablock = static_cast<Ogre::HlmsPbsDatablock*>(HlmsPbs->getDatablock(Ogre::IdString(mtlName)));
	if(datablock)
	{
		//OgreLog("Found HlmsPbsDatablock " + material.name + " in Ogre::HlmsPbs");
		return datablock;
	}
    datablock = static_cast<Ogre::HlmsPbsDatablock*>(HlmsPbs->createDatablock(Ogre::IdString(mtlName),
																			  mtlName,
																			  Ogre::HlmsMacroblock(),
																			  Ogre::HlmsBlendblock(),
																			  Ogre::HlmsParamVec()));
	datablock->setWorkflow(Ogre::HlmsPbsDatablock::Workflows::MetallicWorkflow);

	//OgreLog("Create HlmsPbsDatablock " + mtlName);
	//TODO refactor these almost exact pieces of code
	for(const auto& content : material.values)
	{
		//OgreLog(content.first);
		if(content.first == "baseColorTexture")
			setBaseColorTexture(datablock, content.second.TextureIndex());

		if(content.first == "metallicRoughnessTexture")
			setMetalRoughTexture(datablock, content.second.TextureIndex());

		if(content.first == "baseColorFactor")
			setBaseColor(datablock, convertColor(content.second.ColorFactor()));

		if(content.first == "metallicFactor")
			setMetallicValue(datablock, static_cast<float>(content.second.Factor()));

		if(content.first == "roughnessFactor")
			setRoughnesValue(datablock, static_cast<float>(content.second.Factor()));
	}

	//OgreLog("additionalValues");
	for(const auto& content : material.additionalValues)
	{
		//OgreLog(content.first);
		if(content.first == "normalTexture")
			setNormalTexture(datablock, content.second.TextureIndex());

		//if (content.first == "occlusionTexture")
		//	setOcclusionTexture(datablock, getTextureIndex(content));

		if(content.first == "emissiveTexture")
			setEmissiveTexture(datablock, content.second.TextureIndex());

		if(content.first == "emissiveFactor")
			setEmissiveColor(datablock, convertColor(content.second.ColorFactor()));

		if(content.first == "alphaMode")
			setAlphaMode(datablock, content.second.string_value);

		if(content.first == "alphaCutoff")
			setAlphaCutoff(datablock, static_cast<Ogre::Real>(content.second.number_value));
	}

	//	OgreLog("extCommonValues");
	//	for(const auto& content : material.extCommonValues)
	//		OgreLog(content.first);

	//	OgreLog("extPBRValues");
	//	for(const auto& content : material.extPBRValues)
	//		OgreLog(content.first);
    auto hlmsTextureManager = Ogre::Root::getSingleton().getHlmsManager()->getTextureManager();
    if (datablock->getTexture(Ogre::PBSM_REFLECTION).isNull())
    {
        auto envMap = hlmsTextureManager->createOrRetrieveTexture("env.dds", Ogre::HlmsTextureManager::TEXTURE_TYPE_ENV_MAP);
        datablock->setTexture(Ogre::PBSM_REFLECTION, envMap.xIdx, envMap.texture);
    }
	return datablock;
}

size_t materialLoader::getDatablockCount() const //todo this could use some refactoring. This information is actually fetched like, twice.
{
	const auto mainMeshIndex = (model.defaultScene != 0 ? model.nodes[model.scenes[model.defaultScene].nodes.front()].mesh : 0);
	const auto& mesh = model.meshes[mainMeshIndex];
	return mesh.primitives.size();
}
<commit_msg>Set transparency from the alpha channel of baseColorFactor in glTF materials<commit_after>#include "stdafx.h"

#include "Ogre_glTF_materialLoader.hpp"
#include "Ogre_glTF_textureImporter.hpp"
#include "Ogre_glTF_common.hpp"
#include <OgreHlmsPbsDatablock.h>
#include <OgreHlms.h>
#include <OgreHlmsManager.h>
#include <OgreLogManager.h>
#include "Ogre_glTF_internal_utils.hpp"

using namespace Ogre_glTF;

Ogre::Vector3 materialLoader::convertColor(const tinygltf::ColorValue& color)
{
	std::array<float, 4> colorBuffer{};
	internal_utils::container_double_to_float(color, colorBuffer);
	return Ogre::Vector3 { colorBuffer.data() };
}

void materialLoader::setBaseColor(Ogre::HlmsPbsDatablock* block, Ogre::Vector3 color) const
{
	block->setDiffuse(color);
}

void materialLoader::setMetallicValue(Ogre::HlmsPbsDatablock* block, Ogre::Real value) const
{
	block->setMetalness(value);
}

void materialLoader::setRoughnesValue(Ogre::HlmsPbsDatablock* block, Ogre::Real value) const
{
	block->setRoughness(value);
}

void materialLoader::setEmissiveColor(Ogre::HlmsPbsDatablock* block, Ogre::Vector3 color) const
{
	block->setEmissive(color);
}

bool materialLoader::isTextureIndexValid(int value) const
{
	return !(value < 0);
}

void materialLoader::setBaseColorTexture(Ogre::HlmsPbsDatablock* block, int value) const
{
	if(!isTextureIndexValid(value)) return;
	auto texture = textureImporterRef.getTexture(value);
	if(texture)
	{
		//OgreLog("diffuse texture from textureImporter : " + texture->getName());
		block->setTexture(Ogre::PbsTextureTypes::PBSM_DIFFUSE, 0, texture);
	}
}

void materialLoader::setMetalRoughTexture(Ogre::HlmsPbsDatablock* block, int gltfTextureID) const
{
	if(!isTextureIndexValid(gltfTextureID)) return;
	//Ogre cannot use combined metal rough textures. Metal is in the R channel, and rough in the G channel. It seems that the images are loaded as BGR by the libarry
	//R channel is channel 2 (from 0), G channel is 1.

	auto metalTexure = textureImporterRef.generateGreyScaleFromChannel(gltfTextureID, 2);
	auto roughTexure = textureImporterRef.generateGreyScaleFromChannel(gltfTextureID, 1);

	if(metalTexure)
	{
		//OgreLog("metalness grey-scale texture extracted by textureImporter : " + metalTexure->getName());
		block->setTexture(Ogre::PBSM_METALLIC, 0, metalTexure);
	}

	if(roughTexure)
	{
		//OgreLog("roughness grey-scale texture extracted by textureImporter : " + roughTexure->getName());
		block->setTexture(Ogre::PBSM_ROUGHNESS, 0, roughTexure);
	}
}

void materialLoader::setNormalTexture(Ogre::HlmsPbsDatablock* block, int value) const
{
	if(!isTextureIndexValid(value)) return;
	auto texture = textureImporterRef.getNormalSNORM(value);
	if(texture)
	{
		//OgreLog("normal texture from textureImporter : " + texture->getName());
		block->setTexture(Ogre::PbsTextureTypes::PBSM_NORMAL, 0, texture);
	}
}

void materialLoader::setOcclusionTexture(Ogre::HlmsPbsDatablock* block, int value) const
{
	if(!isTextureIndexValid(value)) return;
	auto texture = textureImporterRef.getTexture(value);
	if(texture)
	{
		//OgreLog("occlusion texture from textureImporter : " + texture->getName());
		//OgreLog("Warning: Ogre doesn't support occlusion map in it's HLMS PBS implementation!");
		//block->setTexture(Ogre::PbsTextureTypes::PBSM_, 0, texture);
	}
}

void materialLoader::setEmissiveTexture(Ogre::HlmsPbsDatablock* block, int value) const
{
	if(!isTextureIndexValid(value)) return;
	auto texture = textureImporterRef.getTexture(value);
	if(texture)
	{
		//OgreLog("emissive texture from textureImporter : " + texture->getName());
		block->setTexture(Ogre::PbsTextureTypes::PBSM_EMISSIVE, 0, texture);
	}
}

void materialLoader::setAlphaMode(Ogre::HlmsPbsDatablock* block, const std::string& mode) const
{
	if(mode == "BLEND")
	{
		auto blendBlock = *block->getBlendblock();
		blendBlock.setBlendType(Ogre::SBT_TRANSPARENT_ALPHA);
		block->setBlendblock(blendBlock);
	}
	else if(mode =="MASK")
	{
		block->setAlphaTest( Ogre::CMPF_GREATER_EQUAL );
	}
}

void materialLoader::setAlphaCutoff(Ogre::HlmsPbsDatablock* block, Ogre::Real value) const
{
	block->setAlphaTestThreshold(value);
}

materialLoader::materialLoader(tinygltf::Model& input, textureImporter& textureInterface) :
	textureImporterRef(textureInterface),
	model(input)
{
}

Ogre::HlmsDatablock* materialLoader::getDatablock(size_t index) const
{
	//OgreLog("Loading material...");
	//TODO this will need some modification if we support multiple meshes by glTF file
	auto HlmsPbs			 = static_cast<Ogre::HlmsPbs*>(Ogre::Root::getSingleton().getHlmsManager()->getHlms(Ogre::HlmsTypes::HLMS_PBS));
	//const auto mainMeshIndex = (model.defaultScene != 0 ? model.nodes[model.scenes[model.defaultScene].nodes.front()].mesh : 0);
	//const auto& mesh		 = model.meshes[mainMeshIndex];
	//const auto material    = model.materials[mesh.primitives.at(index).material];
    const auto material		 = model.materials[index];

    std::string mtlName = material.name + "_" + std::to_string(index);
	auto datablock = static_cast<Ogre::HlmsPbsDatablock*>(HlmsPbs->getDatablock(Ogre::IdString(mtlName)));
	if(datablock)
	{
		//OgreLog("Found HlmsPbsDatablock " + material.name + " in Ogre::HlmsPbs");
		return datablock;
	}
    datablock = static_cast<Ogre::HlmsPbsDatablock*>(HlmsPbs->createDatablock(Ogre::IdString(mtlName),
																			  mtlName,
																			  Ogre::HlmsMacroblock(),
																			  Ogre::HlmsBlendblock(),
																			  Ogre::HlmsParamVec()));
	datablock->setWorkflow(Ogre::HlmsPbsDatablock::Workflows::MetallicWorkflow);

	//OgreLog("Create HlmsPbsDatablock " + mtlName);
	//TODO refactor these almost exact pieces of code
	for (const auto& content : material.values)
	{
		//OgreLog(content.first);
        if (content.first == "baseColorTexture")
            setBaseColorTexture(datablock, content.second.TextureIndex());

		if (content.first == "metallicRoughnessTexture")
			setMetalRoughTexture(datablock, content.second.TextureIndex());

        if (content.first == "baseColorFactor")
        {
            setBaseColor(datablock, convertColor(content.second.ColorFactor()));
            float alpha = content.second.number_array[3];
            datablock->setTransparency(alpha);
        }

		if (content.first == "metallicFactor")
			setMetallicValue(datablock, static_cast<float>(content.second.Factor()));

		if (content.first == "roughnessFactor")
			setRoughnesValue(datablock, static_cast<float>(content.second.Factor()));
	}

	//OgreLog("additionalValues");
	for (const auto& content : material.additionalValues)
	{
		//OgreLog(content.first);
		if(content.first == "normalTexture")
			setNormalTexture(datablock, content.second.TextureIndex());

		//if (content.first == "occlusionTexture")
		//	setOcclusionTexture(datablock, getTextureIndex(content));

		if(content.first == "emissiveTexture")
			setEmissiveTexture(datablock, content.second.TextureIndex());

		if(content.first == "emissiveFactor")
			setEmissiveColor(datablock, convertColor(content.second.ColorFactor()));

		if(content.first == "alphaMode")
			setAlphaMode(datablock, content.second.string_value);

		if(content.first == "alphaCutoff")
			setAlphaCutoff(datablock, static_cast<Ogre::Real>(content.second.number_value));
	}

	//	OgreLog("extCommonValues");
	//	for(const auto& content : material.extCommonValues)
	//		OgreLog(content.first);

	//	OgreLog("extPBRValues");
	//	for(const auto& content : material.extPBRValues)
	//		OgreLog(content.first);
    auto hlmsTextureManager = Ogre::Root::getSingleton().getHlmsManager()->getTextureManager();
    if (datablock->getTexture(Ogre::PBSM_REFLECTION).isNull())
    {
        auto envMap = hlmsTextureManager->createOrRetrieveTexture("env.dds", Ogre::HlmsTextureManager::TEXTURE_TYPE_ENV_MAP);
        datablock->setTexture(Ogre::PBSM_REFLECTION, envMap.xIdx, envMap.texture);
    }
	return datablock;
}

size_t materialLoader::getDatablockCount() const //todo this could use some refactoring. This information is actually fetched like, twice.
{
	const auto mainMeshIndex = (model.defaultScene != 0 ? model.nodes[model.scenes[model.defaultScene].nodes.front()].mesh : 0);
	const auto& mesh = model.meshes[mainMeshIndex];
	return mesh.primitives.size();
}
<|endoftext|>


<commit_before>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999, 2000 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */
// Class header file...
#include "XalanOutputStream.hpp"

#include <util/TransService.hpp>
#include <util/XMLException.hpp>

#include "XalanTranscodingServices.hpp"

XalanOutputStream::XalanOutputStream(
			BufferType::size_type			theBufferSize,
			TranscodeVectorType::size_type	theTranscoderBlockSize) :
	m_transcoderBlockSize(theTranscoderBlockSize),
	m_transcoder(0),
	m_bufferSize(theBufferSize),
	m_buffer(),
	m_encoding(),
	m_writeAsUTF16(false),
	m_transcodingBuffer()
{
}

XalanOutputStream::~XalanOutputStream()
{
	XalanTranscodingServices::destroyTranscoder(m_transcoder);
}

void
XalanOutputStream::flush()
{
	flushBuffer();

	doFlush();
}

void
XalanOutputStream::write(char	theChar)
{
	write(&theChar, 1);
}

void
XalanOutputStream::write(XalanDOMChar	theChar)
{
	write(&theChar, 1);
}

void
XalanOutputStream::write(
			const XalanDOMChar*		theBuffer,
			unsigned long			theBufferLength)
{
	assert(theBuffer != 0);

	if (theBufferLength + m_buffer.size() > m_bufferSize)
	{
		flushBuffer();
	}

	if (theBufferLength > m_bufferSize)
	{
		doWrite(theBuffer, theBufferLength);
	}
	else
	{
		m_buffer.insert(m_buffer.end(),
						theBuffer,
						theBuffer + theBufferLength);
	}
}

void
XalanOutputStream::write(const XalanDOMChar*	theBuffer)
{
	if (theBuffer != 0)
	{
		write(theBuffer, length(theBuffer));
	}
}

void
XalanOutputStream::write(const char*	theBuffer)
{
	assert(theBuffer != 0);

	flushBuffer();

	writeData(theBuffer,
		      strlen(theBuffer));
}

void
XalanOutputStream::write(
			const char*		theBuffer,
			unsigned long	theBufferLength)
{
	assert(theBuffer != 0);

	flushBuffer();

	writeData(theBuffer,
			  theBufferLength);
}

void
XalanOutputStream::transcode(
			const XalanDOMChar*		theBuffer,
			TranscodeVectorType&	theDestination)
{
	// This is a special version that will short-cut when
	// transocding to the local code page.  On platforms
	// where XalanDOMChar == wchar_t, it saves copying
	// to a temporary buffer for the purposes of null-
	// terminating the string.
	if (m_transcoder == 0)
	{
		if (TranscodeToLocalCodePage(
				theBuffer,
				theDestination) == false)
		{
			throw TranscodingException();
		}
	}
	else
	{
		transcode(theBuffer, length(theBuffer), theDestination);
	}
}

void
XalanOutputStream::transcode(
			const XalanDOMChar*		theBuffer,
			unsigned long			theBufferLength,
			TranscodeVectorType&	theDestination)
{
	if (m_transcoder == 0)
	{
		if (TranscodeToLocalCodePage(
				theBuffer,
				theBufferLength,
				theDestination) == false)
		{
			throw TranscodingException();
		}
	}
	else
	{
		bool					fDone = false;

		// Keep track of the total bytes we've added to the
		// destination vector, and the total bytes we've
		// eaten from theBuffer.
		unsigned int			theTotalBytesFilled = 0;
		unsigned int			theTotalBytesEaten = 0;

		// Keep track of the current position in the input buffer,
		// and amount remaining in the buffer, since we may not be
		// able to transcode it all at once.
		const XalanDOMChar*		theBufferPosition = theBuffer;
		unsigned int			theRemainingBufferLength = theBufferLength;

		// Keep track of the destination size, and the target size, which is
		// the size of the destination that has not yet been filled with
		// transcoded characters.  Double the buffer size, in case we're
		// transcoding to a 16-bit encoding.
		// $$$ ToDo: We need to know the size of an encoding, so we can
		// do the right thing with the destination size.
		unsigned int			theDestinationSize = theBufferLength * 2;
		unsigned int			theTargetSize = theDestinationSize;

		do
		{
			// Resize the buffer...
			theDestination.resize(theDestinationSize + 1);

			unsigned int						theSourceBytesEaten = 0;
			unsigned int						theTargetBytesEaten = 0;

			XalanTranscodingServices::eCode		theResult =
				m_transcoder->transcode(
						theBufferPosition,
						theRemainingBufferLength,
#if defined(XALAN_OLD_STYLE_CASTS)
						(XMLByte*)&theDestination[0] + theTotalBytesFilled,
#else
						reinterpret_cast<XMLByte*>(&theDestination[0]) + theTotalBytesFilled,
#endif
						theTargetSize,
						theSourceBytesEaten,
						theTargetBytesEaten);

			if(theResult != XalanTranscodingServices::OK)
			{
				throw TranscodingException();
			}

			theTotalBytesFilled += theTargetBytesEaten;
			theTotalBytesEaten += theSourceBytesEaten;

			if (theTotalBytesEaten == theBufferLength)
			{
				fDone = true;
			}
			else
			{
				assert(theTotalBytesEaten < theBufferLength);

				// Update everything...
				theBufferPosition += theSourceBytesEaten;
				theRemainingBufferLength -= theSourceBytesEaten;

				// The new target size will always be the
				// current destination size, since we
				// grow by a factor of 2.  This will
				// need to change if the factor is
				// every changed.
				theTargetSize = theDestinationSize;

				// Grow the destination by a factor of
				// two 2.  See the previous comment if
				// you want to change this.
				theDestinationSize = theDestinationSize * 2;
			}
		} while(fDone == false);

		// Resize things, if there are any extra bytes...
		if (theDestination.size() != theTotalBytesFilled)
		{
			theDestination.resize(theTotalBytesFilled);
		}
	}
}

const XalanDOMString&
XalanOutputStream::getOutputEncoding() const
{
	return m_encoding;
}

void
XalanOutputStream::setOutputEncoding(const XalanDOMString&	theEncoding)
{
	// Flush, just in case.  This should probably be an error...
	flushBuffer();

	XalanTranscodingServices::destroyTranscoder(m_transcoder);

	XalanTranscodingServices::eCode		theCode = XalanTranscodingServices::OK;

	// This turns on an optimization that we can only do if
	// XalanDOMChar == sizeof(ushort).  See doWrite().
#if !defined(XALAN_XALANDOMCHAR_USHORT_MISMATCH)
	if (XalanTranscodingServices::encodingIsUTF16(theEncoding) == true)
	{
		m_writeAsUTF16 = true;
	}
	else
#endif
	{
		m_transcoder = XalanTranscodingServices::makeNewTranscoder(
					theEncoding,
					theCode,
					m_transcoderBlockSize);

		if (theCode == XalanTranscodingServices::UnsupportedEncoding)
		{
			throw UnsupportedEncodingException(theEncoding);
		}
		else if (theCode != XalanTranscodingServices::OK)
		{
			throw TranscoderInternalFailureException(theEncoding);
		}

		assert(m_transcoder != 0);
	}

	m_encoding = theEncoding;

	typedef XalanTranscodingServices::XalanXMLByteVectorType	XalanXMLByteVectorType;

	const XalanXMLByteVectorType&	theProlog =
		XalanTranscodingServices::getStreamProlog(theEncoding);

	const XalanXMLByteVectorType::size_type		theSize = theProlog.size();

	if (theSize > 0)
	{
#if defined(XALAN_OLD_STYLE_CASTS)
		write((const char*)theProlog[0], theProlog.size());
#else
		write(reinterpret_cast<const char*>(&theProlog[0]), theProlog.size());
#endif
	}
}

void
XalanOutputStream::flushBuffer()
{
	if (m_buffer.size() > 0)
	{
		m_buffer.push_back(0);

		doWrite(&*m_buffer.begin());

		m_buffer.clear();
	}
}

void
XalanOutputStream::doWrite(const XalanDOMChar*	theBuffer)
{
	assert(theBuffer != 0);

	try
	{
		if (m_writeAsUTF16 == true)
		{
			assert(sizeof(XalanDOMChar) == sizeof(char) * 2);

			// This is a hack to write UTF-16 through as if it
			// were just chars.  Saves lots of time "transcoding."
#if defined(XALAN_OLD_STYLE_CASTS)
			writeData((const char*)theBuffer, length(theBuffer) * 2);
#else
			writeData(reinterpret_cast<const char*>(theBuffer), length(theBuffer) * 2);
#endif
		}
		else
		{
			transcode(theBuffer, m_transcodingBuffer);

			assert(&m_transcodingBuffer[0] != 0);

			writeData(&m_transcodingBuffer[0],
					  m_transcodingBuffer.size());
		}
	}
	catch(const XalanOutputStreamException&)
	{
		// Have to catch this error and flush any output remaining...
		m_buffer.clear();

		throw;
	}
}

void
XalanOutputStream::doWrite(
			const XalanDOMChar*		theBuffer,
			unsigned long			theBufferLength)
{
	// $$$ ToDo: Revisit this!!!
	BufferType	theLocalBuffer(theBuffer, theBuffer + theBufferLength);

	theLocalBuffer.push_back(0);

	doWrite(&theLocalBuffer[0]);
}

void
XalanOutputStream::setBufferSize(BufferType::size_type		theBufferSize)
{
	flushBuffer();

	m_bufferSize = theBufferSize;

	if (m_buffer.size() < m_bufferSize)
	{
		// Enlarge the buffer...
		m_buffer.reserve(theBufferSize);
	}
	else if (m_buffer.size() > m_bufferSize)
	{
		// Shrink the buffer.

		// Create a temp buffer and make it
		// the correct size.
		BufferType	temp;

		temp.reserve(theBufferSize);

		// Swap temp with m_buffer so that
		// m_buffer is now the correct size.
		temp.swap(m_buffer);
	}
}

XalanOutputStream::XalanOutputStreamException::XalanOutputStreamException(
			const XalanDOMString&	theMessage,
			const XalanDOMString&	theType) :
	XSLException(theMessage, theType)
{
}

XalanOutputStream::XalanOutputStreamException::~XalanOutputStreamException()
{
}

XalanOutputStream::UnknownEncodingException::UnknownEncodingException() :
	XalanOutputStreamException(
			TranscodeFromLocalCodePage("Unknown error occurred while transcoding!"),
			TranscodeFromLocalCodePage("UnknownEncodingException"))
{
}

XalanOutputStream::UnknownEncodingException::~UnknownEncodingException()
{
}

XalanOutputStream::UnsupportedEncodingException::UnsupportedEncodingException(const XalanDOMString&	theEncoding) :
	XalanOutputStreamException(
			TranscodeFromLocalCodePage("Unsupported encoding: ") + theEncoding,
			TranscodeFromLocalCodePage("UnsupportedEncodingException")),
	m_encoding(theEncoding)
{
}

XalanOutputStream::UnsupportedEncodingException::~UnsupportedEncodingException()
{
}

XalanOutputStream::TranscoderInternalFailureException::TranscoderInternalFailureException(const XalanDOMString&	theEncoding) :
	XalanOutputStreamException(
			TranscodeFromLocalCodePage("Unknown error occurred while transcoding to ") +
					theEncoding +
					TranscodeFromLocalCodePage("!"),
			TranscodeFromLocalCodePage("TranscoderInternalFailureException")),
	m_encoding(theEncoding)
{
}

XalanOutputStream::TranscoderInternalFailureException::~TranscoderInternalFailureException()
{
}

XalanOutputStream::TranscodingException::TranscodingException() :
	XalanOutputStreamException(
			TranscodeFromLocalCodePage("An error occurred while transcoding!"),
			TranscodeFromLocalCodePage("TranscodingException"))
{
}

XalanOutputStream::TranscodingException::~TranscodingException()
{
}
<commit_msg>Reserve an extra space for the terminating byte.<commit_after>/*
 * The Apache Software License, Version 1.1
 *
 *
 * Copyright (c) 1999, 2000 The Apache Software Foundation.  All rights
 * reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * 3. The end-user documentation included with the redistribution,
 *    if any, must include the following acknowledgment:
 *       "This product includes software developed by the
 *        Apache Software Foundation (http://www.apache.org/)."
 *    Alternately, this acknowledgment may appear in the software itself,
 *    if and wherever such third-party acknowledgments normally appear.
 *
 * 4. The names "Xalan" and "Apache Software Foundation" must
 *    not be used to endorse or promote products derived from this
 *    software without prior written permission. For written
 *    permission, please contact apache@apache.org.
 *
 * 5. Products derived from this software may not be called "Apache",
 *    nor may "Apache" appear in their name, without prior written
 *    permission of the Apache Software Foundation.
 *
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 * ====================================================================
 *
 * This software consists of voluntary contributions made by many
 * individuals on behalf of the Apache Software Foundation and was
 * originally based on software copyright (c) 1999, International
 * Business Machines, Inc., http://www.ibm.com.  For more
 * information on the Apache Software Foundation, please see
 * <http://www.apache.org/>.
 */
// Class header file...
#include "XalanOutputStream.hpp"

#include <util/TransService.hpp>
#include <util/XMLException.hpp>

#include "XalanTranscodingServices.hpp"

XalanOutputStream::XalanOutputStream(
			BufferType::size_type			theBufferSize,
			TranscodeVectorType::size_type	theTranscoderBlockSize) :
	m_transcoderBlockSize(theTranscoderBlockSize),
	m_transcoder(0),
	m_bufferSize(theBufferSize),
	m_buffer(),
	m_encoding(),
	m_writeAsUTF16(false),
	m_transcodingBuffer()
{
	m_buffer.reserve(theBufferSize + 1);
}

XalanOutputStream::~XalanOutputStream()
{
	XalanTranscodingServices::destroyTranscoder(m_transcoder);
}

void
XalanOutputStream::flush()
{
	flushBuffer();

	doFlush();
}

void
XalanOutputStream::write(char	theChar)
{
	write(&theChar, 1);
}

void
XalanOutputStream::write(XalanDOMChar	theChar)
{
	write(&theChar, 1);
}

void
XalanOutputStream::write(
			const XalanDOMChar*		theBuffer,
			unsigned long			theBufferLength)
{
	assert(theBuffer != 0);

	if (theBufferLength + m_buffer.size() > m_bufferSize)
	{
		flushBuffer();
	}

	if (theBufferLength > m_bufferSize)
	{
		doWrite(theBuffer, theBufferLength);
	}
	else
	{
		m_buffer.insert(m_buffer.end(),
						theBuffer,
						theBuffer + theBufferLength);
	}
}

void
XalanOutputStream::write(const XalanDOMChar*	theBuffer)
{
	if (theBuffer != 0)
	{
		write(theBuffer, length(theBuffer));
	}
}

void
XalanOutputStream::write(const char*	theBuffer)
{
	assert(theBuffer != 0);

	flushBuffer();

	writeData(theBuffer,
		      strlen(theBuffer));
}

void
XalanOutputStream::write(
			const char*		theBuffer,
			unsigned long	theBufferLength)
{
	assert(theBuffer != 0);

	flushBuffer();

	writeData(theBuffer,
			  theBufferLength);
}

void
XalanOutputStream::transcode(
			const XalanDOMChar*		theBuffer,
			TranscodeVectorType&	theDestination)
{
	// This is a special version that will short-cut when
	// transocding to the local code page.  On platforms
	// where XalanDOMChar == wchar_t, it saves copying
	// to a temporary buffer for the purposes of null-
	// terminating the string.
	if (m_transcoder == 0)
	{
		if (TranscodeToLocalCodePage(
				theBuffer,
				theDestination) == false)
		{
			throw TranscodingException();
		}
	}
	else
	{
		transcode(theBuffer, length(theBuffer), theDestination);
	}
}

void
XalanOutputStream::transcode(
			const XalanDOMChar*		theBuffer,
			unsigned long			theBufferLength,
			TranscodeVectorType&	theDestination)
{
	if (m_transcoder == 0)
	{
		if (TranscodeToLocalCodePage(
				theBuffer,
				theBufferLength,
				theDestination) == false)
		{
			throw TranscodingException();
		}
	}
	else
	{
		bool					fDone = false;

		// Keep track of the total bytes we've added to the
		// destination vector, and the total bytes we've
		// eaten from theBuffer.
		unsigned int			theTotalBytesFilled = 0;
		unsigned int			theTotalBytesEaten = 0;

		// Keep track of the current position in the input buffer,
		// and amount remaining in the buffer, since we may not be
		// able to transcode it all at once.
		const XalanDOMChar*		theBufferPosition = theBuffer;
		unsigned int			theRemainingBufferLength = theBufferLength;

		// Keep track of the destination size, and the target size, which is
		// the size of the destination that has not yet been filled with
		// transcoded characters.  Double the buffer size, in case we're
		// transcoding to a 16-bit encoding.
		// $$$ ToDo: We need to know the size of an encoding, so we can
		// do the right thing with the destination size.
		unsigned int			theDestinationSize = theBufferLength * 2;
		unsigned int			theTargetSize = theDestinationSize;

		do
		{
			// Resize the buffer...
			theDestination.resize(theDestinationSize + 1);

			unsigned int						theSourceBytesEaten = 0;
			unsigned int						theTargetBytesEaten = 0;

			XalanTranscodingServices::eCode		theResult =
				m_transcoder->transcode(
						theBufferPosition,
						theRemainingBufferLength,
#if defined(XALAN_OLD_STYLE_CASTS)
						(XMLByte*)&theDestination[0] + theTotalBytesFilled,
#else
						reinterpret_cast<XMLByte*>(&theDestination[0]) + theTotalBytesFilled,
#endif
						theTargetSize,
						theSourceBytesEaten,
						theTargetBytesEaten);

			if(theResult != XalanTranscodingServices::OK)
			{
				throw TranscodingException();
			}

			theTotalBytesFilled += theTargetBytesEaten;
			theTotalBytesEaten += theSourceBytesEaten;

			if (theTotalBytesEaten == theBufferLength)
			{
				fDone = true;
			}
			else
			{
				assert(theTotalBytesEaten < theBufferLength);

				// Update everything...
				theBufferPosition += theSourceBytesEaten;
				theRemainingBufferLength -= theSourceBytesEaten;

				// The new target size will always be the
				// current destination size, since we
				// grow by a factor of 2.  This will
				// need to change if the factor is
				// every changed.
				theTargetSize = theDestinationSize;

				// Grow the destination by a factor of
				// two 2.  See the previous comment if
				// you want to change this.
				theDestinationSize = theDestinationSize * 2;
			}
		} while(fDone == false);

		// Resize things, if there are any extra bytes...
		if (theDestination.size() != theTotalBytesFilled)
		{
			theDestination.resize(theTotalBytesFilled);
		}
	}
}

const XalanDOMString&
XalanOutputStream::getOutputEncoding() const
{
	return m_encoding;
}

void
XalanOutputStream::setOutputEncoding(const XalanDOMString&	theEncoding)
{
	// Flush, just in case.  This should probably be an error...
	flushBuffer();

	XalanTranscodingServices::destroyTranscoder(m_transcoder);

	XalanTranscodingServices::eCode		theCode = XalanTranscodingServices::OK;

	// This turns on an optimization that we can only do if
	// XalanDOMChar == sizeof(ushort).  See doWrite().
#if !defined(XALAN_XALANDOMCHAR_USHORT_MISMATCH)
	if (XalanTranscodingServices::encodingIsUTF16(theEncoding) == true)
	{
		m_writeAsUTF16 = true;
	}
	else
#endif
	{
		m_transcoder = XalanTranscodingServices::makeNewTranscoder(
					theEncoding,
					theCode,
					m_transcoderBlockSize);

		if (theCode == XalanTranscodingServices::UnsupportedEncoding)
		{
			throw UnsupportedEncodingException(theEncoding);
		}
		else if (theCode != XalanTranscodingServices::OK)
		{
			throw TranscoderInternalFailureException(theEncoding);
		}

		assert(m_transcoder != 0);
	}

	m_encoding = theEncoding;

	typedef XalanTranscodingServices::XalanXMLByteVectorType	XalanXMLByteVectorType;

	const XalanXMLByteVectorType&	theProlog =
		XalanTranscodingServices::getStreamProlog(theEncoding);

	const XalanXMLByteVectorType::size_type		theSize = theProlog.size();

	if (theSize > 0)
	{
#if defined(XALAN_OLD_STYLE_CASTS)
		write((const char*)theProlog[0], theProlog.size());
#else
		write(reinterpret_cast<const char*>(&theProlog[0]), theProlog.size());
#endif
	}
}

void
XalanOutputStream::flushBuffer()
{
	if (m_buffer.size() > 0)
	{
		m_buffer.push_back(0);

		doWrite(&*m_buffer.begin());

		m_buffer.clear();
	}
}

void
XalanOutputStream::doWrite(const XalanDOMChar*	theBuffer)
{
	assert(theBuffer != 0);

	try
	{
		if (m_writeAsUTF16 == true)
		{
			assert(sizeof(XalanDOMChar) == sizeof(char) * 2);

			// This is a hack to write UTF-16 through as if it
			// were just chars.  Saves lots of time "transcoding."
#if defined(XALAN_OLD_STYLE_CASTS)
			writeData((const char*)theBuffer, length(theBuffer) * 2);
#else
			writeData(reinterpret_cast<const char*>(theBuffer), length(theBuffer) * 2);
#endif
		}
		else
		{
			transcode(theBuffer, m_transcodingBuffer);

			assert(&m_transcodingBuffer[0] != 0);

			writeData(&m_transcodingBuffer[0],
					  m_transcodingBuffer.size());
		}
	}
	catch(const XalanOutputStreamException&)
	{
		// Have to catch this error and flush any output remaining...
		m_buffer.clear();

		throw;
	}
}

void
XalanOutputStream::doWrite(
			const XalanDOMChar*		theBuffer,
			unsigned long			theBufferLength)
{
	// $$$ ToDo: Revisit this!!!
	BufferType	theLocalBuffer(theBuffer, theBuffer + theBufferLength);

	theLocalBuffer.push_back(0);

	doWrite(&theLocalBuffer[0]);
}

void
XalanOutputStream::setBufferSize(BufferType::size_type		theBufferSize)
{
	flushBuffer();

	m_bufferSize = theBufferSize;

	if (m_buffer.size() < m_bufferSize)
	{
		// Enlarge the buffer...
		m_buffer.reserve(theBufferSize + 1);
	}
	else if (m_buffer.size() > m_bufferSize)
	{
		// Shrink the buffer.

		// Create a temp buffer and make it
		// the correct size.
		BufferType	temp;

		temp.reserve(theBufferSize + 1);

		// Swap temp with m_buffer so that
		// m_buffer is now the correct size.
		temp.swap(m_buffer);
	}
}

XalanOutputStream::XalanOutputStreamException::XalanOutputStreamException(
			const XalanDOMString&	theMessage,
			const XalanDOMString&	theType) :
	XSLException(theMessage, theType)
{
}

XalanOutputStream::XalanOutputStreamException::~XalanOutputStreamException()
{
}

XalanOutputStream::UnknownEncodingException::UnknownEncodingException() :
	XalanOutputStreamException(
			TranscodeFromLocalCodePage("Unknown error occurred while transcoding!"),
			TranscodeFromLocalCodePage("UnknownEncodingException"))
{
}

XalanOutputStream::UnknownEncodingException::~UnknownEncodingException()
{
}

XalanOutputStream::UnsupportedEncodingException::UnsupportedEncodingException(const XalanDOMString&	theEncoding) :
	XalanOutputStreamException(
			TranscodeFromLocalCodePage("Unsupported encoding: ") + theEncoding,
			TranscodeFromLocalCodePage("UnsupportedEncodingException")),
	m_encoding(theEncoding)
{
}

XalanOutputStream::UnsupportedEncodingException::~UnsupportedEncodingException()
{
}

XalanOutputStream::TranscoderInternalFailureException::TranscoderInternalFailureException(const XalanDOMString&	theEncoding) :
	XalanOutputStreamException(
			TranscodeFromLocalCodePage("Unknown error occurred while transcoding to ") +
					theEncoding +
					TranscodeFromLocalCodePage("!"),
			TranscodeFromLocalCodePage("TranscoderInternalFailureException")),
	m_encoding(theEncoding)
{
}

XalanOutputStream::TranscoderInternalFailureException::~TranscoderInternalFailureException()
{
}

XalanOutputStream::TranscodingException::TranscodingException() :
	XalanOutputStreamException(
			TranscodeFromLocalCodePage("An error occurred while transcoding!"),
			TranscodeFromLocalCodePage("TranscodingException"))
{
}

XalanOutputStream::TranscodingException::~TranscodingException()
{
}
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2003-2005 The Regents of The University of Michigan
 * Copyright (c) 2007-2008 The Florida State University
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Stephen Hines
 */

#ifndef __ARCH_ARM_LINUX_LINUX_HH__
#define __ARCH_ARM_LINUX_LINUX_HH__

#include "kern/linux/linux.hh"

class ArmLinux : public Linux
{
  public:

    /// This table maps the target open() flags to the corresponding
    /// host open() flags.
    static OpenFlagTransTable openFlagTable[];

    /// Number of entries in openFlagTable[].
    static const int NUM_OPEN_FLAGS;

    //@{
    /// open(2) flag values.
    static const int TGT_O_RDONLY    = 00000000; //!< O_RDONLY
    static const int TGT_O_WRONLY    = 00000001; //!< O_WRONLY
    static const int TGT_O_RDWR      = 00000002; //!< O_RDWR
    static const int TGT_O_CREAT     = 00000100; //!< O_CREAT
    static const int TGT_O_EXCL      = 00000200; //!< O_EXCL
    static const int TGT_O_NOCTTY    = 00000400; //!< O_NOCTTY
    static const int TGT_O_TRUNC     = 00001000; //!< O_TRUNC
    static const int TGT_O_APPEND    = 00002000; //!< O_APPEND
    static const int TGT_O_NONBLOCK  = 00004000; //!< O_NONBLOCK
    static const int TGT_O_SYNC      = 00010000; //!< O_SYNC
    static const int TGT_FASYNC      = 00020000; //!< FASYNC
    static const int TGT_O_DIRECTORY = 00040000; //!< O_DIRECTORY
    static const int TGT_O_NOFOLLOW  = 00100000; //!< O_NOFOLLOW
    static const int TGT_O_DIRECT    = 00200000; //!< O_DIRECT
    static const int TGT_O_LARGEFILE = 00400000; //!< O_LARGEFILE
    static const int TGT_O_NOATIME   = 01000000; //!< O_NOATIME
    //@}

    /// For mmap().
    static const unsigned TGT_MAP_ANONYMOUS = 0x20;

    //@{
    /// For getrusage().
    static const int TGT_RUSAGE_SELF = 0;
    static const int TGT_RUSAGE_CHILDREN = -1;
    static const int TGT_RUSAGE_BOTH = -2;
    //@}

    //@{
    /// ioctl() command codes.
    static const unsigned TIOCGETP_   = 0x40067408;
    static const unsigned TIOCSETP_   = 0x80067409;
    static const unsigned TIOCSETN_   = 0x8006740a;
    static const unsigned TIOCSETC_   = 0x80067411;
    static const unsigned TIOCGETC_   = 0x40067412;
    static const unsigned FIONREAD_   = 0x4004667f;
    static const unsigned TIOCISATTY_ = 0x2000745e;
    static const unsigned TIOCGETS_   = 0x402c7413;
    static const unsigned TIOCGETA_   = 0x40127417;
    //@}

    /// For table().
    static const int TBL_SYSINFO = 12;

    /// Resource enumeration for getrlimit().
    enum rlimit_resources {
        TGT_RLIMIT_CPU = 0,
        TGT_RLIMIT_FSIZE = 1,
        TGT_RLIMIT_DATA = 2,
        TGT_RLIMIT_STACK = 3,
        TGT_RLIMIT_CORE = 4,
        TGT_RLIMIT_RSS = 5,
        TGT_RLIMIT_NPROC = 6,
        TGT_RLIMIT_NOFILE = 7,
        TGT_RLIMIT_MEMLOCK = 8,
        TGT_RLIMIT_AS = 9,
        TGT_RLIMIT_LOCKS = 10
    };

    typedef struct {
        uint32_t st_dev;
        uint32_t st_ino;
        uint16_t st_mode;
        uint16_t st_nlink;
        uint16_t st_uid;
        uint16_t st_gid;
        uint32_t st_rdev;
        uint32_t st_size;
        uint32_t st_blksize;
        uint32_t st_blocks;
        uint32_t st_atimeX;
        uint32_t st_atime_nsec;
        uint32_t st_mtimeX;
        uint32_t st_mtime_nsec;
        uint32_t st_ctimeX;
        uint32_t st_ctime_nsec;
    } tgt_stat;

    typedef struct {
        uint64_t  st_dev;
        uint8_t   __pad0[4];
        uint32_t  __st_ino;
        uint32_t  st_mode;
        uint32_t  st_nlink;
        uint32_t  st_uid;
        uint32_t  st_gid;
        uint64_t  st_rdev;
        uint8_t   __pad3[4];
        int64_t   __attribute__ ((aligned (8))) st_size;
        uint32_t  st_blksize;
        uint64_t  __attribute__ ((aligned (8))) st_blocks;
        uint32_t  st_atimeX;
        uint32_t  st_atime_nsec;
        uint32_t  st_mtimeX;
        uint32_t  st_mtime_nsec;
        uint32_t  st_ctimeX;
        uint32_t  st_ctime_nsec;
        uint64_t  st_ino;
    } tgt_stat64;

};

#endif
<commit_msg>ARM: Fix an ioctl constant.<commit_after>/*
 * Copyright (c) 2003-2005 The Regents of The University of Michigan
 * Copyright (c) 2007-2008 The Florida State University
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Stephen Hines
 */

#ifndef __ARCH_ARM_LINUX_LINUX_HH__
#define __ARCH_ARM_LINUX_LINUX_HH__

#include "kern/linux/linux.hh"

class ArmLinux : public Linux
{
  public:

    /// This table maps the target open() flags to the corresponding
    /// host open() flags.
    static OpenFlagTransTable openFlagTable[];

    /// Number of entries in openFlagTable[].
    static const int NUM_OPEN_FLAGS;

    //@{
    /// open(2) flag values.
    static const int TGT_O_RDONLY    = 00000000; //!< O_RDONLY
    static const int TGT_O_WRONLY    = 00000001; //!< O_WRONLY
    static const int TGT_O_RDWR      = 00000002; //!< O_RDWR
    static const int TGT_O_CREAT     = 00000100; //!< O_CREAT
    static const int TGT_O_EXCL      = 00000200; //!< O_EXCL
    static const int TGT_O_NOCTTY    = 00000400; //!< O_NOCTTY
    static const int TGT_O_TRUNC     = 00001000; //!< O_TRUNC
    static const int TGT_O_APPEND    = 00002000; //!< O_APPEND
    static const int TGT_O_NONBLOCK  = 00004000; //!< O_NONBLOCK
    static const int TGT_O_SYNC      = 00010000; //!< O_SYNC
    static const int TGT_FASYNC      = 00020000; //!< FASYNC
    static const int TGT_O_DIRECTORY = 00040000; //!< O_DIRECTORY
    static const int TGT_O_NOFOLLOW  = 00100000; //!< O_NOFOLLOW
    static const int TGT_O_DIRECT    = 00200000; //!< O_DIRECT
    static const int TGT_O_LARGEFILE = 00400000; //!< O_LARGEFILE
    static const int TGT_O_NOATIME   = 01000000; //!< O_NOATIME
    //@}

    /// For mmap().
    static const unsigned TGT_MAP_ANONYMOUS = 0x20;

    //@{
    /// For getrusage().
    static const int TGT_RUSAGE_SELF = 0;
    static const int TGT_RUSAGE_CHILDREN = -1;
    static const int TGT_RUSAGE_BOTH = -2;
    //@}

    //@{
    /// ioctl() command codes.
    static const unsigned TIOCGETP_   = 0x5401;
    static const unsigned TIOCSETP_   = 0x80067409;
    static const unsigned TIOCSETN_   = 0x8006740a;
    static const unsigned TIOCSETC_   = 0x80067411;
    static const unsigned TIOCGETC_   = 0x40067412;
    static const unsigned FIONREAD_   = 0x4004667f;
    static const unsigned TIOCISATTY_ = 0x2000745e;
    static const unsigned TIOCGETS_   = 0x402c7413;
    static const unsigned TIOCGETA_   = 0x40127417;
    //@}

    /// For table().
    static const int TBL_SYSINFO = 12;

    /// Resource enumeration for getrlimit().
    enum rlimit_resources {
        TGT_RLIMIT_CPU = 0,
        TGT_RLIMIT_FSIZE = 1,
        TGT_RLIMIT_DATA = 2,
        TGT_RLIMIT_STACK = 3,
        TGT_RLIMIT_CORE = 4,
        TGT_RLIMIT_RSS = 5,
        TGT_RLIMIT_NPROC = 6,
        TGT_RLIMIT_NOFILE = 7,
        TGT_RLIMIT_MEMLOCK = 8,
        TGT_RLIMIT_AS = 9,
        TGT_RLIMIT_LOCKS = 10
    };

    typedef struct {
        uint32_t st_dev;
        uint32_t st_ino;
        uint16_t st_mode;
        uint16_t st_nlink;
        uint16_t st_uid;
        uint16_t st_gid;
        uint32_t st_rdev;
        uint32_t st_size;
        uint32_t st_blksize;
        uint32_t st_blocks;
        uint32_t st_atimeX;
        uint32_t st_atime_nsec;
        uint32_t st_mtimeX;
        uint32_t st_mtime_nsec;
        uint32_t st_ctimeX;
        uint32_t st_ctime_nsec;
    } tgt_stat;

    typedef struct {
        uint64_t  st_dev;
        uint8_t   __pad0[4];
        uint32_t  __st_ino;
        uint32_t  st_mode;
        uint32_t  st_nlink;
        uint32_t  st_uid;
        uint32_t  st_gid;
        uint64_t  st_rdev;
        uint8_t   __pad3[4];
        int64_t   __attribute__ ((aligned (8))) st_size;
        uint32_t  st_blksize;
        uint64_t  __attribute__ ((aligned (8))) st_blocks;
        uint32_t  st_atimeX;
        uint32_t  st_atime_nsec;
        uint32_t  st_mtimeX;
        uint32_t  st_mtime_nsec;
        uint32_t  st_ctimeX;
        uint32_t  st_ctime_nsec;
        uint64_t  st_ino;
    } tgt_stat64;

};

#endif
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2003-2005 The Regents of The University of Michigan
 * Copyright (c) 2007-2008 The Florida State University
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Stephen Hines
 */

#ifndef __ARCH_ARM_LINUX_LINUX_HH__
#define __ARCH_ARM_LINUX_LINUX_HH__

#include "kern/linux/linux.hh"

class ArmLinux : public Linux
{
  public:

    /// This table maps the target open() flags to the corresponding
    /// host open() flags.
    static OpenFlagTransTable openFlagTable[];

    /// Number of entries in openFlagTable[].
    static const int NUM_OPEN_FLAGS;

    //@{
    /// open(2) flag values.
    static const int TGT_O_RDONLY	= 0x00000000;	//!< O_RDONLY
    static const int TGT_O_WRONLY	= 0x00000001;	//!< O_WRONLY
    static const int TGT_O_RDWR	        = 0x00000002;	//!< O_RDWR
    static const int TGT_O_CREAT	= 0x00000100;	//!< O_CREAT
    static const int TGT_O_EXCL	        = 0x00000200;	//!< O_EXCL
    static const int TGT_O_NOCTTY	= 0x00000400;	//!< O_NOCTTY
    static const int TGT_O_TRUNC	= 0x00001000;	//!< O_TRUNC
    static const int TGT_O_APPEND	= 0x00002000;	//!< O_APPEND
    static const int TGT_O_NONBLOCK     = 0x00004000;	//!< O_NONBLOCK
    static const int TGT_O_SYNC	        = 0x00010000;	//!< O_SYNC
    static const int TGT_FASYNC		= 0x00020000;	//!< FASYNC
    static const int TGT_O_DIRECT	= 0x00040000;	//!< O_DIRECT
    static const int TGT_O_LARGEFILE	= 0x00100000;	//!< O_LARGEFILE
    static const int TGT_O_DIRECTORY	= 0x00200000;	//!< O_DIRECTORY
    static const int TGT_O_NOFOLLOW	= 0x00400000;	//!< O_NOFOLLOW
    static const int TGT_O_NOATIME	= 0x01000000;	//!< O_NOATIME
    //@}

    /// For mmap().
    static const unsigned TGT_MAP_ANONYMOUS = 0x800;

    //@{
    /// For getsysinfo().
    static const unsigned GSI_PLATFORM_NAME = 103;  //!< platform name as string
    static const unsigned GSI_CPU_INFO = 59;	//!< CPU information
    static const unsigned GSI_PROC_TYPE = 60;	//!< get proc_type
    static const unsigned GSI_MAX_CPU = 30;         //!< max # cpu's on this machine
    static const unsigned GSI_CPUS_IN_BOX = 55;	//!< number of CPUs in system
    static const unsigned GSI_PHYSMEM = 19;	        //!< Physical memory in KB
    static const unsigned GSI_CLK_TCK = 42;	        //!< clock freq in Hz
    //@}

    //@{
    /// For getrusage().
    static const int TGT_RUSAGE_SELF = 0;
    static const int TGT_RUSAGE_CHILDREN = -1;
    static const int TGT_RUSAGE_BOTH = -2;
    //@}

    //@{
    /// For setsysinfo().
    static const unsigned SSI_IEEE_FP_CONTROL = 14; //!< ieee_set_fp_control()
    //@}

    //@{
    /// ioctl() command codes.
    static const unsigned TIOCGETP_   = 0x40067408;
    static const unsigned TIOCSETP_   = 0x80067409;
    static const unsigned TIOCSETN_   = 0x8006740a;
    static const unsigned TIOCSETC_   = 0x80067411;
    static const unsigned TIOCGETC_   = 0x40067412;
    static const unsigned FIONREAD_   = 0x4004667f;
    static const unsigned TIOCISATTY_ = 0x2000745e;
    static const unsigned TIOCGETS_   = 0x402c7413;
    static const unsigned TIOCGETA_   = 0x40127417;
    //@}

    /// For table().
    static const int TBL_SYSINFO = 12;

    /// Resource enumeration for getrlimit().
    enum rlimit_resources {
        TGT_RLIMIT_CPU = 0,
        TGT_RLIMIT_FSIZE = 1,
        TGT_RLIMIT_DATA = 2,
        TGT_RLIMIT_STACK = 3,
        TGT_RLIMIT_CORE = 4,
        TGT_RLIMIT_NOFILE = 5,
        TGT_RLIMIT_AS = 6,
        TGT_RLIMIT_RSS = 7,
        TGT_RLIMIT_VMEM = 7,
        TGT_RLIMIT_NPROC = 8,
        TGT_RLIMIT_MEMLOCK = 9,
        TGT_RLIMIT_LOCKS = 10
    };

};

#endif
<commit_msg>ARM: Fix the "open" flag constants.<commit_after>/*
 * Copyright (c) 2003-2005 The Regents of The University of Michigan
 * Copyright (c) 2007-2008 The Florida State University
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met: redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer;
 * redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution;
 * neither the name of the copyright holders nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 * Authors: Stephen Hines
 */

#ifndef __ARCH_ARM_LINUX_LINUX_HH__
#define __ARCH_ARM_LINUX_LINUX_HH__

#include "kern/linux/linux.hh"

class ArmLinux : public Linux
{
  public:

    /// This table maps the target open() flags to the corresponding
    /// host open() flags.
    static OpenFlagTransTable openFlagTable[];

    /// Number of entries in openFlagTable[].
    static const int NUM_OPEN_FLAGS;

    //@{
    /// open(2) flag values.
    static const int TGT_O_RDONLY    = 00000000; //!< O_RDONLY
    static const int TGT_O_WRONLY    = 00000001; //!< O_WRONLY
    static const int TGT_O_RDWR      = 00000002; //!< O_RDWR
    static const int TGT_O_CREAT     = 00000100; //!< O_CREAT
    static const int TGT_O_EXCL      = 00000200; //!< O_EXCL
    static const int TGT_O_NOCTTY    = 00000400; //!< O_NOCTTY
    static const int TGT_O_TRUNC     = 00001000; //!< O_TRUNC
    static const int TGT_O_APPEND    = 00002000; //!< O_APPEND
    static const int TGT_O_NONBLOCK  = 00004000; //!< O_NONBLOCK
    static const int TGT_O_SYNC      = 00010000; //!< O_SYNC
    static const int TGT_FASYNC      = 00020000; //!< FASYNC
    static const int TGT_O_DIRECTORY = 00040000; //!< O_DIRECTORY
    static const int TGT_O_NOFOLLOW  = 00100000; //!< O_NOFOLLOW
    static const int TGT_O_DIRECT    = 00200000; //!< O_DIRECT
    static const int TGT_O_LARGEFILE = 00400000; //!< O_LARGEFILE
    static const int TGT_O_NOATIME   = 01000000; //!< O_NOATIME
    //@}

    /// For mmap().
    static const unsigned TGT_MAP_ANONYMOUS = 0x800;

    //@{
    /// For getsysinfo().
    static const unsigned GSI_PLATFORM_NAME = 103; //!< platform name as string
    static const unsigned GSI_CPU_INFO = 59;       //!< CPU information
    static const unsigned GSI_PROC_TYPE = 60;      //!< get proc_type
    static const unsigned GSI_MAX_CPU = 30;        //!< max # cpu's on this machine
    static const unsigned GSI_CPUS_IN_BOX = 55;    //!< number of CPUs in system
    static const unsigned GSI_PHYSMEM = 19;        //!< Physical memory in KB
    static const unsigned GSI_CLK_TCK = 42;        //!< clock freq in Hz
    //@}

    //@{
    /// For getrusage().
    static const int TGT_RUSAGE_SELF = 0;
    static const int TGT_RUSAGE_CHILDREN = -1;
    static const int TGT_RUSAGE_BOTH = -2;
    //@}

    //@{
    /// For setsysinfo().
    static const unsigned SSI_IEEE_FP_CONTROL = 14; //!< ieee_set_fp_control()
    //@}

    //@{
    /// ioctl() command codes.
    static const unsigned TIOCGETP_   = 0x40067408;
    static const unsigned TIOCSETP_   = 0x80067409;
    static const unsigned TIOCSETN_   = 0x8006740a;
    static const unsigned TIOCSETC_   = 0x80067411;
    static const unsigned TIOCGETC_   = 0x40067412;
    static const unsigned FIONREAD_   = 0x4004667f;
    static const unsigned TIOCISATTY_ = 0x2000745e;
    static const unsigned TIOCGETS_   = 0x402c7413;
    static const unsigned TIOCGETA_   = 0x40127417;
    //@}

    /// For table().
    static const int TBL_SYSINFO = 12;

    /// Resource enumeration for getrlimit().
    enum rlimit_resources {
        TGT_RLIMIT_CPU = 0,
        TGT_RLIMIT_FSIZE = 1,
        TGT_RLIMIT_DATA = 2,
        TGT_RLIMIT_STACK = 3,
        TGT_RLIMIT_CORE = 4,
        TGT_RLIMIT_NOFILE = 5,
        TGT_RLIMIT_AS = 6,
        TGT_RLIMIT_RSS = 7,
        TGT_RLIMIT_VMEM = 7,
        TGT_RLIMIT_NPROC = 8,
        TGT_RLIMIT_MEMLOCK = 9,
        TGT_RLIMIT_LOCKS = 10
    };

};

#endif
<|endoftext|>