<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "viewlogger.h"
#include <QDebug>
#include <QTemporaryFile>
#include <QDir>
#include <variantproperty.h>
#include <bindingproperty.h>
#include <nodeabstractproperty.h>
#include <nodelistproperty.h>

namespace QmlDesigner {
namespace Internal {

static QString serialize(AbstractView::PropertyChangeFlags change)
{
    QStringList tokenList;

    if (change.testFlag(AbstractView::PropertiesAdded))
        tokenList.append(QLatin1String("PropertiesAdded"));

    if (change.testFlag(AbstractView::EmptyPropertiesRemoved))
        tokenList.append(QLatin1String("EmptyPropertiesRemoved"));

    return tokenList.join(" ");

    return QString();
}

static QString indent(const QString &name = QString()) {
    return name.leftJustified(30, ' ');
}

QString ViewLogger::time() const
{
    return QString::number(m_timer.elapsed()).leftJustified(7, ' ');
}

ViewLogger::ViewLogger(QObject *parent)
    : AbstractView(parent)
{
#ifdef Q_OS_MAC
    const QLatin1String logPath("Library/Logs/Bauhaus");
    QDir logDir(QDir::homePath());
    logDir.mkpath(logPath);
    const QString tempPath = QDir::homePath() + QDir::separator() + logPath;
#else
    const QString tempPath = QDir::tempPath();
#endif

    QTemporaryFile *temporaryFile = new QTemporaryFile(tempPath + QString("/bauhaus-logger-%1-XXXXXX.txt").arg(QDateTime::currentDateTime().toString(Qt::ISODate).replace(":", "-")), this);
    temporaryFile->setAutoRemove(false);
    if (temporaryFile->open()) {
        qDebug() << "TemporaryLoggerFile is:" << temporaryFile->fileName();

        m_output.setDevice(temporaryFile);
    }

    m_timer.start();
}

void ViewLogger::modelAttached(Model *model)
{
    m_output << time() << indent("modelAttached:") << model << endl;
    AbstractView::modelAttached(model);
}

void ViewLogger::modelAboutToBeDetached(Model *model)
{
    m_output << time() << indent("modelAboutToBeDetached:") << model << endl;
    AbstractView::modelAboutToBeDetached(model);
}

void ViewLogger::nodeCreated(const ModelNode &createdNode)
{
    m_output << time() << indent("nodeCreated:") << createdNode << endl;
}

void ViewLogger::nodeAboutToBeRemoved(const ModelNode &removedNode)
{
    m_output << time() << indent("nodeAboutToBeRemoved:") << removedNode << endl;
}

void ViewLogger::nodeRemoved(const ModelNode &removedNode, const NodeAbstractProperty &parentProperty, PropertyChangeFlags propertyChange)
{
    m_output << time() << indent("nodeRemoved:") << removedNode << parentProperty << serialize(propertyChange) << endl;
}

void ViewLogger::nodeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, AbstractView::PropertyChangeFlags propertyChange)
{
    m_output << time() << indent("nodeReparented:") << node << "\t" << newPropertyParent << "\t" << oldPropertyParent << "\t" << serialize(propertyChange) << endl;
}

void ViewLogger::nodeIdChanged(const ModelNode& node, const QString& newId, const QString& oldId)
{
    m_output << time() << indent("nodeIdChanged:") << node << "\t" << newId << "\t" << oldId << endl;
}

void ViewLogger::propertiesAboutToBeRemoved(const QList<AbstractProperty>& propertyList)
{
    m_output << time() << indent("propertiesAboutToBeRemoved:") << endl;
    foreach (const AbstractProperty &property, propertyList)
        m_output << time() << indent() << property << endl;
}

void ViewLogger::propertiesRemoved(const QList<AbstractProperty> &propertyList)
{
    m_output << time() << indent("propertiesRemoved:") << endl;
    foreach (const AbstractProperty &property, propertyList)
        m_output << time() << indent() << property << endl;
}

void ViewLogger::variantPropertiesChanged(const QList<VariantProperty>& propertyList, PropertyChangeFlags propertyChange)
{
    m_output << time() << indent("variantPropertiesChanged:") << serialize(propertyChange) << endl;
    foreach(const VariantProperty &property, propertyList)
        m_output << time() << indent() << property << endl;
}

void ViewLogger::bindingPropertiesChanged(const QList<BindingProperty>& propertyList, PropertyChangeFlags propertyChange)
{
    m_output << time() << indent("bindingPropertiesChanged:") << serialize(propertyChange) << endl;
    foreach(const BindingProperty &property, propertyList)
        m_output << time() << indent() << property << endl;
}

void ViewLogger::rootNodeTypeChanged(const QString &type, int majorVersion, int minorVersion)
{
    m_output << time() << indent("rootNodeTypeChanged:") << rootModelNode() << type << majorVersion << minorVersion << endl;
}

void ViewLogger::selectedNodesChanged(const QList<ModelNode> &selectedNodeList,
                                  const QList<ModelNode> &lastSelectedNodeList)
{
    m_output << time() << indent("selectedNodesChanged:") << endl;
    foreach(const ModelNode &node, selectedNodeList)
        m_output << time() << indent("new: ") << node << endl;
    foreach(const ModelNode &node, lastSelectedNodeList)
        m_output << time() << indent("old: ") << node << endl;
}

void ViewLogger::fileUrlChanged(const QUrl &oldUrl, const QUrl &newUrl)
{
    m_output << time() << indent("fileUrlChanged:") << oldUrl.toString() << "\t" << newUrl.toString() << endl;
}

void ViewLogger::nodeOrderChanged(const NodeListProperty &listProperty, const ModelNode &movedNode, int oldIndex)
{
    m_output << time() << indent("nodeOrderChanged:") << listProperty << movedNode << oldIndex << endl;
}

void ViewLogger::importsChanged()
{
    m_output << time() << indent("importsChanged:") << endl;
}

void ViewLogger::auxiliaryDataChanged(const ModelNode &node, const QString &name, const QVariant &data)
{
    m_output << time() << indent("auxiliaryDataChanged:") << node << "\t" << name << "\t" << data.toString() << endl;
}

void ViewLogger::customNotification(const AbstractView *view, const QString &identifier, const QList<ModelNode> &nodeList, const QList<QVariant> &data)
{
    m_output << time() << indent("customNotification:") << view << identifier << endl;
    foreach(const ModelNode &node, nodeList)
        m_output << time() << indent("node: ") << node << endl;
    foreach(const QVariant &variant, data)
        m_output << time() << indent("data: ") << variant.toString() << endl;
}

} // namespace Internal
} // namespace QmlDesigner
<commit_msg>QmlDesigner: fixes viewlogger for Windows<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/

#include "viewlogger.h"
#include <QDebug>
#include <QTemporaryFile>
#include <QDir>
#include <variantproperty.h>
#include <bindingproperty.h>
#include <nodeabstractproperty.h>
#include <nodelistproperty.h>

namespace QmlDesigner {
namespace Internal {

static QString serialize(AbstractView::PropertyChangeFlags change)
{
    QStringList tokenList;

    if (change.testFlag(AbstractView::PropertiesAdded))
        tokenList.append(QLatin1String("PropertiesAdded"));

    if (change.testFlag(AbstractView::EmptyPropertiesRemoved))
        tokenList.append(QLatin1String("EmptyPropertiesRemoved"));

    return tokenList.join(" ");

    return QString();
}

static QString indent(const QString &name = QString()) {
    return name.leftJustified(30, ' ');
}

QString ViewLogger::time() const
{
    return QString::number(m_timer.elapsed()).leftJustified(7, ' ');
}

ViewLogger::ViewLogger(QObject *parent)
    : AbstractView(parent)
{
#ifdef Q_OS_MAC
    const QLatin1String logPath("Library/Logs/Bauhaus");
    QDir logDir(QDir::homePath());
    logDir.mkpath(logPath);
    const QString tempPath = QDir::homePath() + QDir::separator() + logPath;
#else
    const QString tempPath = QDir::tempPath();
#endif

    QTemporaryFile *temporaryFile = new QTemporaryFile(tempPath + QString("/bauhaus-logger-%1-XXXXXX.txt").arg(QDateTime::currentDateTime().toString(Qt::ISODate).replace(":", "-")), this);
    QString tempFileName = tempPath + QString("/bauhaus-logger-%1-XXXXXX.txt").arg(QDateTime::currentDateTime().toString(Qt::ISODate).replace(':', '-'));

    temporaryFile->setAutoRemove(false);
    if (temporaryFile->open()) {
        qDebug() << "ViewLogger: TemporaryLoggerFile is:" << temporaryFile->fileName();
        m_output.setDevice(temporaryFile);
    } else {
        qDebug() << "ViewLogger: failed to open:" << temporaryFile->fileName();
    }

    m_timer.start();
}

void ViewLogger::modelAttached(Model *model)
{
    m_output << time() << indent("modelAttached:") << model << endl;
    AbstractView::modelAttached(model);
}

void ViewLogger::modelAboutToBeDetached(Model *model)
{
    m_output << time() << indent("modelAboutToBeDetached:") << model << endl;
    AbstractView::modelAboutToBeDetached(model);
}

void ViewLogger::nodeCreated(const ModelNode &createdNode)
{
    m_output << time() << indent("nodeCreated:") << createdNode << endl;
}

void ViewLogger::nodeAboutToBeRemoved(const ModelNode &removedNode)
{
    m_output << time() << indent("nodeAboutToBeRemoved:") << removedNode << endl;
}

void ViewLogger::nodeRemoved(const ModelNode &removedNode, const NodeAbstractProperty &parentProperty, PropertyChangeFlags propertyChange)
{
    m_output << time() << indent("nodeRemoved:") << removedNode << parentProperty << serialize(propertyChange) << endl;
}

void ViewLogger::nodeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, AbstractView::PropertyChangeFlags propertyChange)
{
    m_output << time() << indent("nodeReparented:") << node << "\t" << newPropertyParent << "\t" << oldPropertyParent << "\t" << serialize(propertyChange) << endl;
}

void ViewLogger::nodeIdChanged(const ModelNode& node, const QString& newId, const QString& oldId)
{
    m_output << time() << indent("nodeIdChanged:") << node << "\t" << newId << "\t" << oldId << endl;
}

void ViewLogger::propertiesAboutToBeRemoved(const QList<AbstractProperty>& propertyList)
{
    m_output << time() << indent("propertiesAboutToBeRemoved:") << endl;
    foreach (const AbstractProperty &property, propertyList)
        m_output << time() << indent() << property << endl;
}

void ViewLogger::propertiesRemoved(const QList<AbstractProperty> &propertyList)
{
    m_output << time() << indent("propertiesRemoved:") << endl;
    foreach (const AbstractProperty &property, propertyList)
        m_output << time() << indent() << property << endl;
}

void ViewLogger::variantPropertiesChanged(const QList<VariantProperty>& propertyList, PropertyChangeFlags propertyChange)
{
    m_output << time() << indent("variantPropertiesChanged:") << serialize(propertyChange) << endl;
    foreach(const VariantProperty &property, propertyList)
        m_output << time() << indent() << property << endl;
}

void ViewLogger::bindingPropertiesChanged(const QList<BindingProperty>& propertyList, PropertyChangeFlags propertyChange)
{
    m_output << time() << indent("bindingPropertiesChanged:") << serialize(propertyChange) << endl;
    foreach(const BindingProperty &property, propertyList)
        m_output << time() << indent() << property << endl;
}

void ViewLogger::rootNodeTypeChanged(const QString &type, int majorVersion, int minorVersion)
{
    m_output << time() << indent("rootNodeTypeChanged:") << rootModelNode() << type << majorVersion << minorVersion << endl;
}

void ViewLogger::selectedNodesChanged(const QList<ModelNode> &selectedNodeList,
                                  const QList<ModelNode> &lastSelectedNodeList)
{
    m_output << time() << indent("selectedNodesChanged:") << endl;
    foreach(const ModelNode &node, selectedNodeList)
        m_output << time() << indent("new: ") << node << endl;
    foreach(const ModelNode &node, lastSelectedNodeList)
        m_output << time() << indent("old: ") << node << endl;
}

void ViewLogger::fileUrlChanged(const QUrl &oldUrl, const QUrl &newUrl)
{
    m_output << time() << indent("fileUrlChanged:") << oldUrl.toString() << "\t" << newUrl.toString() << endl;
}

void ViewLogger::nodeOrderChanged(const NodeListProperty &listProperty, const ModelNode &movedNode, int oldIndex)
{
    m_output << time() << indent("nodeOrderChanged:") << listProperty << movedNode << oldIndex << endl;
}

void ViewLogger::importsChanged()
{
    m_output << time() << indent("importsChanged:") << endl;
}

void ViewLogger::auxiliaryDataChanged(const ModelNode &node, const QString &name, const QVariant &data)
{
    m_output << time() << indent("auxiliaryDataChanged:") << node << "\t" << name << "\t" << data.toString() << endl;
}

void ViewLogger::customNotification(const AbstractView *view, const QString &identifier, const QList<ModelNode> &nodeList, const QList<QVariant> &data)
{
    m_output << time() << indent("customNotification:") << view << identifier << endl;
    foreach(const ModelNode &node, nodeList)
        m_output << time() << indent("node: ") << node << endl;
    foreach(const QVariant &variant, data)
        m_output << time() << indent("data: ") << variant.toString() << endl;
}

} // namespace Internal
} // namespace QmlDesigner
<|endoftext|>


<commit_before>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact:  Qt Software Information (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
**
**************************************************************************/

#include "qmlprojectnodes.h"
#include "qmlprojectmanager.h"
#include "qmlproject.h"

#include <coreplugin/ifile.h>
#include <projectexplorer/projectexplorer.h>

#include <QFileInfo>

using namespace QmlProjectManager;
using namespace QmlProjectManager::Internal;

QmlProjectNode::QmlProjectNode(QmlProject *project, Core::IFile *projectFile)
    : ProjectExplorer::ProjectNode(QFileInfo(projectFile->fileName()).absolutePath()),
      m_project(project),
      m_projectFile(projectFile)
{
    setFolderName(QFileInfo(projectFile->fileName()).completeBaseName());
}

QmlProjectNode::~QmlProjectNode()
{ }

Core::IFile *QmlProjectNode::projectFile() const
{ return m_projectFile; }

QString QmlProjectNode::projectFilePath() const
{ return m_projectFile->fileName(); }

void QmlProjectNode::refresh()
{
    using namespace ProjectExplorer;

    // remove the existing nodes.
    removeFileNodes(fileNodes(), this);
    removeFolderNodes(subFolderNodes(), this);

    //ProjectExplorerPlugin::instance()->setCurrentNode(0); // ### remove me

    FileNode *projectFilesNode = new FileNode(m_project->filesFileName(),
                                              ProjectFileType,
                                              /* generated = */ false);

    QStringList files = m_project->files();
    files.removeAll(m_project->filesFileName());

    addFileNodes(QList<FileNode *>()
                 << projectFilesNode,
                 this);

    QStringList filePaths;
    QHash<QString, QStringList> filesInPath;

    foreach (const QString &absoluteFileName, files) {
        QFileInfo fileInfo(absoluteFileName);
        const QString absoluteFilePath = fileInfo.path();

        if (! absoluteFilePath.startsWith(path()))
            continue; // `file' is not part of the project.

        const QString relativeFilePath = absoluteFilePath.mid(path().length() + 1);

        if (! filePaths.contains(relativeFilePath))
            filePaths.append(relativeFilePath);

        filesInPath[relativeFilePath].append(absoluteFileName);
    }

    foreach (const QString &filePath, filePaths) {
        FolderNode *folder = findOrCreateFolderByName(filePath);

        QList<FileNode *> fileNodes;
        foreach (const QString &file, filesInPath.value(filePath)) {
            FileType fileType = SourceType; // ### FIXME
            FileNode *fileNode = new FileNode(file, fileType, /*generated = */ false);
            fileNodes.append(fileNode);
        }

        addFileNodes(fileNodes, folder);
    }

    m_folderByName.clear();
}

ProjectExplorer::FolderNode *QmlProjectNode::findOrCreateFolderByName(const QStringList &components, int end)
{
    if (! end)
        return 0;

    QString folderName;
    for (int i = 0; i < end; ++i) {
        folderName.append(components.at(i));
        folderName += QLatin1Char('/'); // ### FIXME
    }

    const QString component = components.at(end - 1);

    if (component.isEmpty())
        return this;

    else if (FolderNode *folder = m_folderByName.value(folderName))
        return folder;

    FolderNode *folder = new FolderNode(component);
    m_folderByName.insert(folderName, folder);

    FolderNode *parent = findOrCreateFolderByName(components, end - 1);
    if (! parent)
        parent = this;
    addFolderNodes(QList<FolderNode*>() << folder, parent);

    return folder;
}

ProjectExplorer::FolderNode *QmlProjectNode::findOrCreateFolderByName(const QString &filePath)
{
    QStringList components = filePath.split(QLatin1Char('/'));
    return findOrCreateFolderByName(components, components.length());
}

bool QmlProjectNode::hasTargets() const
{
    return true;
}

QList<ProjectExplorer::ProjectNode::ProjectAction> QmlProjectNode::supportedActions() const
{
    QList<ProjectAction> actions;
    actions.append(AddFile);
    return actions;
}

bool QmlProjectNode::addSubProjects(const QStringList &proFilePaths)
{
    Q_UNUSED(proFilePaths);
    return false;
}

bool QmlProjectNode::removeSubProjects(const QStringList &proFilePaths)
{
    Q_UNUSED(proFilePaths);
    return false;
}

bool QmlProjectNode::addFiles(const ProjectExplorer::FileType,
                              const QStringList &filePaths, QStringList *notAdded)
{
    QDir projectDir(QFileInfo(projectFilePath()).dir());

    QFile file(projectFilePath());
    if (! file.open(QFile::WriteOnly | QFile::Append))
        return false;

    QTextStream stream(&file);
    QStringList failedFiles;

    bool first = true;
    foreach (const QString &filePath, filePaths) {
        const QString rel = projectDir.relativeFilePath(filePath);

        if (rel.isEmpty() || rel.startsWith(QLatin1Char('.'))) {
            failedFiles.append(rel);
        } else {
            if (first) {
                stream << endl;
                first = false;
            }

            stream << rel << endl;
        }
    }

    if (notAdded)
        *notAdded += failedFiles;

    if (! first)
        m_project->projectManager()->notifyChanged(projectFilePath());

    return failedFiles.isEmpty();
}

bool QmlProjectNode::removeFiles(const ProjectExplorer::FileType fileType,
                                 const QStringList &filePaths, QStringList *notRemoved)
{
    Q_UNUSED(fileType);
    Q_UNUSED(filePaths);
    Q_UNUSED(notRemoved);
    return false;
}

bool QmlProjectNode::renameFile(const ProjectExplorer::FileType fileType,
                                    const QString &filePath, const QString &newFilePath)
{
    Q_UNUSED(fileType);
    Q_UNUSED(filePath);
    Q_UNUSED(newFilePath);
    return false;
}
<commit_msg>Compile.<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact:  Qt Software Information (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, 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.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at qt-sales@nokia.com.
**
**************************************************************************/

#include "qmlprojectnodes.h"
#include "qmlprojectmanager.h"
#include "qmlproject.h"

#include <coreplugin/ifile.h>
#include <projectexplorer/projectexplorer.h>

#include <QFileInfo>
#include <QDir>

using namespace QmlProjectManager;
using namespace QmlProjectManager::Internal;

QmlProjectNode::QmlProjectNode(QmlProject *project, Core::IFile *projectFile)
    : ProjectExplorer::ProjectNode(QFileInfo(projectFile->fileName()).absolutePath()),
      m_project(project),
      m_projectFile(projectFile)
{
    setFolderName(QFileInfo(projectFile->fileName()).completeBaseName());
}

QmlProjectNode::~QmlProjectNode()
{ }

Core::IFile *QmlProjectNode::projectFile() const
{ return m_projectFile; }

QString QmlProjectNode::projectFilePath() const
{ return m_projectFile->fileName(); }

void QmlProjectNode::refresh()
{
    using namespace ProjectExplorer;

    // remove the existing nodes.
    removeFileNodes(fileNodes(), this);
    removeFolderNodes(subFolderNodes(), this);

    //ProjectExplorerPlugin::instance()->setCurrentNode(0); // ### remove me

    FileNode *projectFilesNode = new FileNode(m_project->filesFileName(),
                                              ProjectFileType,
                                              /* generated = */ false);

    QStringList files = m_project->files();
    files.removeAll(m_project->filesFileName());

    addFileNodes(QList<FileNode *>()
                 << projectFilesNode,
                 this);

    QStringList filePaths;
    QHash<QString, QStringList> filesInPath;

    foreach (const QString &absoluteFileName, files) {
        QFileInfo fileInfo(absoluteFileName);
        const QString absoluteFilePath = fileInfo.path();

        if (! absoluteFilePath.startsWith(path()))
            continue; // `file' is not part of the project.

        const QString relativeFilePath = absoluteFilePath.mid(path().length() + 1);

        if (! filePaths.contains(relativeFilePath))
            filePaths.append(relativeFilePath);

        filesInPath[relativeFilePath].append(absoluteFileName);
    }

    foreach (const QString &filePath, filePaths) {
        FolderNode *folder = findOrCreateFolderByName(filePath);

        QList<FileNode *> fileNodes;
        foreach (const QString &file, filesInPath.value(filePath)) {
            FileType fileType = SourceType; // ### FIXME
            FileNode *fileNode = new FileNode(file, fileType, /*generated = */ false);
            fileNodes.append(fileNode);
        }

        addFileNodes(fileNodes, folder);
    }

    m_folderByName.clear();
}

ProjectExplorer::FolderNode *QmlProjectNode::findOrCreateFolderByName(const QStringList &components, int end)
{
    if (! end)
        return 0;

    QString folderName;
    for (int i = 0; i < end; ++i) {
        folderName.append(components.at(i));
        folderName += QLatin1Char('/'); // ### FIXME
    }

    const QString component = components.at(end - 1);

    if (component.isEmpty())
        return this;

    else if (FolderNode *folder = m_folderByName.value(folderName))
        return folder;

    FolderNode *folder = new FolderNode(component);
    m_folderByName.insert(folderName, folder);

    FolderNode *parent = findOrCreateFolderByName(components, end - 1);
    if (! parent)
        parent = this;
    addFolderNodes(QList<FolderNode*>() << folder, parent);

    return folder;
}

ProjectExplorer::FolderNode *QmlProjectNode::findOrCreateFolderByName(const QString &filePath)
{
    QStringList components = filePath.split(QLatin1Char('/'));
    return findOrCreateFolderByName(components, components.length());
}

bool QmlProjectNode::hasTargets() const
{
    return true;
}

QList<ProjectExplorer::ProjectNode::ProjectAction> QmlProjectNode::supportedActions() const
{
    QList<ProjectAction> actions;
    actions.append(AddFile);
    return actions;
}

bool QmlProjectNode::addSubProjects(const QStringList &proFilePaths)
{
    Q_UNUSED(proFilePaths);
    return false;
}

bool QmlProjectNode::removeSubProjects(const QStringList &proFilePaths)
{
    Q_UNUSED(proFilePaths);
    return false;
}

bool QmlProjectNode::addFiles(const ProjectExplorer::FileType,
                              const QStringList &filePaths, QStringList *notAdded)
{
    QDir projectDir(QFileInfo(projectFilePath()).dir());

    QFile file(projectFilePath());
    if (! file.open(QFile::WriteOnly | QFile::Append))
        return false;

    QTextStream stream(&file);
    QStringList failedFiles;

    bool first = true;
    foreach (const QString &filePath, filePaths) {
        const QString rel = projectDir.relativeFilePath(filePath);

        if (rel.isEmpty() || rel.startsWith(QLatin1Char('.'))) {
            failedFiles.append(rel);
        } else {
            if (first) {
                stream << endl;
                first = false;
            }

            stream << rel << endl;
        }
    }

    if (notAdded)
        *notAdded += failedFiles;

    if (! first)
        m_project->projectManager()->notifyChanged(projectFilePath());

    return failedFiles.isEmpty();
}

bool QmlProjectNode::removeFiles(const ProjectExplorer::FileType fileType,
                                 const QStringList &filePaths, QStringList *notRemoved)
{
    Q_UNUSED(fileType);
    Q_UNUSED(filePaths);
    Q_UNUSED(notRemoved);
    return false;
}

bool QmlProjectNode::renameFile(const ProjectExplorer::FileType fileType,
                                    const QString &filePath, const QString &newFilePath)
{
    Q_UNUSED(fileType);
    Q_UNUSED(filePath);
    Q_UNUSED(newFilePath);
    return false;
}
<|endoftext|>


<commit_before><commit_msg>drop annoying empty (slide) entry in inset->envelope->format<commit_after><|endoftext|>


<commit_before>/*
    Copyright (C) 2018, BogDan Vatra <bogdan@kde.org>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as
    published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <getodac/abstract_server_session.h>
#include <getodac/abstract_service_session.h>
#include <getodac/exceptions.h>
#include <getodac/logging.h>
#include <getodac/restful.h>
#include <getodac/utils.h>

#include <iostream>
#include <mutex>

#include <boost/algorithm/string.hpp>
#include <boost/filesystem.hpp>
#include <boost/iostreams/device/mapped_file.hpp>
#include <boost/property_tree/info_parser.hpp>
#include <boost/property_tree/ptree.hpp>

namespace {
using FileMapPtr = std::shared_ptr<boost::iostreams::mapped_file_source>;
Getodac::LRUCache<std::string, std::pair<std::time_t, FileMapPtr>> s_filesCache(100);
std::vector<std::pair<std::string, std::string>> s_urls;
TaggedLogger<> logger{"staticContent"};

class StaticContent : public Getodac::AbstractServiceSession
{
public:
    StaticContent(Getodac::AbstractServerSession *serverSession, const std::string &root, const std::string &path)
        : Getodac::AbstractServiceSession(serverSession)
    {
        try {
            auto p = boost::filesystem::canonical(path, root);
            TRACE(logger) << "Serving " << p.string();
            m_file = s_filesCache.getValue(p.string());
            auto lastWriteTime = boost::filesystem::last_write_time(p);
            if (!m_file.second || m_file.first != lastWriteTime) {
                m_file = std::make_pair(lastWriteTime, std::make_shared<boost::iostreams::mapped_file_source>(p));
                s_filesCache.put(p.string(), m_file);
            }
        } catch (const boost::filesystem::filesystem_error &e) {
            TRACE(logger) << e.what();
            throw Getodac::ResponseStatusError(404, e.what());
        } catch (...) {
            throw Getodac::ResponseStatusError(404, "Unhandled error");
        }
    }

    // ServiceSession interface
    void headerFieldValue(const std::string &, const std::string &) override {}
    bool acceptContentLength(size_t) override {return false;}
    void headersComplete() override {}
    void body(const char *, size_t) override {}
    void requestComplete() override
    {
        m_serverSession->responseStatus(200);
        m_serverSession->responseEndHeader(m_file.second->size());
    }

    void writeResponse(Getodac::AbstractServerSession::Yield &yield) override
    {
        m_serverSession->write(yield, m_file.second->data(), m_file.second->size());
        m_serverSession->responseComplete();
    }

private:
    std::pair<std::time_t, FileMapPtr> m_file;
};

} // namespace

PLUGIN_EXPORT std::shared_ptr<Getodac::AbstractServiceSession> createSession(Getodac::AbstractServerSession *serverSession, const std::string &url, const std::string &/*method*/)
{
    for (const auto &pair : s_urls) {
        if (boost::starts_with(url, pair.first)) {
            if (boost::starts_with(pair.first, "/~")) {
                auto pos = url.find('/', 1);
                if (pos == std::string::npos)
                    break;
                return std::make_shared<StaticContent>(serverSession, pair.second, url.substr(2, pos - 1) + "public_html" + url.substr(pos, url.size() - pos));
            } else {
                return std::make_shared<StaticContent>(serverSession, pair.second, url.c_str() + pair.first.size());
            }
        }
    }

    return std::shared_ptr<Getodac::AbstractServiceSession>();
}

PLUGIN_EXPORT bool initPlugin(const std::string &confDir)
{
    INFO(logger) << "Initializing plugin";
    namespace pt = boost::property_tree;
    pt::ptree properties;
    pt::read_info(boost::filesystem::path(confDir).append("/staticFiles.conf").string(), properties);
    for (const auto &p : properties.get_child("paths")) {
        DEBUG(logger) << "Mapping \"" << p.first << "\" to \"" << p.second.get_value<std::string>() << "\"";
        s_urls.emplace_back(std::make_pair(p.first, p.second.get_value<std::string>()));
    }

    return !s_urls.empty();
}

PLUGIN_EXPORT uint32_t pluginOrder()
{
    return UINT32_MAX;
}

PLUGIN_EXPORT void destoryPlugin()
{
}
<commit_msg>Advertise content type<commit_after>/*
    Copyright (C) 2018, BogDan Vatra <bogdan@kde.org>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Affero General Public License as
    published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.

    You should have received a copy of the GNU Affero General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include <getodac/abstract_server_session.h>
#include <getodac/abstract_service_session.h>
#include <getodac/exceptions.h>
#include <getodac/logging.h>
#include <getodac/restful.h>
#include <getodac/utils.h>

#include <iostream>
#include <mutex>

#include <boost/algorithm/string.hpp>
#include <boost/filesystem.hpp>
#include <boost/iostreams/device/mapped_file.hpp>
#include <boost/property_tree/info_parser.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/utility/string_view.hpp>

namespace {
using FileMapPtr = std::shared_ptr<boost::iostreams::mapped_file_source>;
Getodac::LRUCache<std::string, std::pair<std::time_t, FileMapPtr>> s_filesCache(100);
std::vector<std::pair<std::string, std::string>> s_urls;
TaggedLogger<> logger{"staticContent"};

inline std::string mimeType(boost::string_view ext)
{
    if (ext == ".htm")  return "text/html";
    if (ext == ".html") return "text/html";
    if (ext == ".php")  return "text/html";
    if (ext == ".css")  return "text/css";
    if (ext == ".js")   return "application/javascript";
    if (ext == ".json") return "application/json";
    if (ext == ".xml")  return "application/xml";
    if (ext == ".png")  return "image/png";
    if (ext == ".jpe")  return "image/jpeg";
    if (ext == ".jpeg") return "image/jpeg";
    if (ext == ".jpg")  return "image/jpeg";
    if (ext == ".gif")  return "image/gif";
    if (ext == ".bmp")  return "image/bmp";
    if (ext == ".tiff") return "image/tiff";
    if (ext == ".tif")  return "image/tiff";
    if (ext == ".svg")  return "image/svg+xml";
    if (ext == ".svgz") return "image/svg+xml";
    if (ext == ".txt")  return "text/plain";
    if (ext == ".webp")  return "image/webp";
    if (ext == ".webm")  return "video/webmx";
    if (ext == ".weba")  return "audio/webm";
    if (ext == ".swf")  return "application/x-shockwave-flash";
    if (ext == ".flv")  return "video/x-flv";
    return "application/octet-stream";
}

class StaticContent : public Getodac::AbstractServiceSession
{
public:
    StaticContent(Getodac::AbstractServerSession *serverSession, const std::string &root, const std::string &path)
        : Getodac::AbstractServiceSession(serverSession)
    {
        try {
            auto p = boost::filesystem::canonical(path, root);
            TRACE(logger) << "Serving " << p.string();
            m_file = s_filesCache.getValue(p.string());
            auto lastWriteTime = boost::filesystem::last_write_time(p);
            if (!m_file.second || m_file.first != lastWriteTime) {
                m_file = std::make_pair(lastWriteTime, std::make_shared<boost::iostreams::mapped_file_source>(p));
                s_filesCache.put(p.string(), m_file);
            }
            m_mimeType = mimeType(p.extension().string());
        } catch (const boost::filesystem::filesystem_error &e) {
            TRACE(logger) << e.what();
            throw Getodac::ResponseStatusError(404, e.what());
        } catch (...) {
            throw Getodac::ResponseStatusError(404, "Unhandled error");
        }
    }

    // ServiceSession interface
    void headerFieldValue(const std::string &, const std::string &) override {}
    bool acceptContentLength(size_t) override {return false;}
    void headersComplete() override {}
    void body(const char *, size_t) override {}
    void requestComplete() override
    {
        m_serverSession->responseStatus(200);
        m_serverSession->responseHeader("Content-Type", m_mimeType);
        m_serverSession->responseEndHeader(m_file.second->size());
    }

    void writeResponse(Getodac::AbstractServerSession::Yield &yield) override
    {
        m_serverSession->write(yield, m_file.second->data(), m_file.second->size());
        m_serverSession->responseComplete();
    }

private:
    std::pair<std::time_t, FileMapPtr> m_file;
    std::string m_mimeType;
};

} // namespace

PLUGIN_EXPORT std::shared_ptr<Getodac::AbstractServiceSession> createSession(Getodac::AbstractServerSession *serverSession, const std::string &url, const std::string &/*method*/)
{
    for (const auto &pair : s_urls) {
        if (boost::starts_with(url, pair.first)) {
            if (boost::starts_with(pair.first, "/~")) {
                auto pos = url.find('/', 1);
                if (pos == std::string::npos)
                    break;
                return std::make_shared<StaticContent>(serverSession, pair.second, url.substr(2, pos - 1) + "public_html" + url.substr(pos, url.size() - pos));
            } else {
                return std::make_shared<StaticContent>(serverSession, pair.second, url.c_str() + pair.first.size());
            }
        }
    }

    return std::shared_ptr<Getodac::AbstractServiceSession>();
}

PLUGIN_EXPORT bool initPlugin(const std::string &confDir)
{
    INFO(logger) << "Initializing plugin";
    namespace pt = boost::property_tree;
    pt::ptree properties;
    pt::read_info(boost::filesystem::path(confDir).append("/staticFiles.conf").string(), properties);
    for (const auto &p : properties.get_child("paths")) {
        DEBUG(logger) << "Mapping \"" << p.first << "\" to \"" << p.second.get_value<std::string>() << "\"";
        s_urls.emplace_back(std::make_pair(p.first, p.second.get_value<std::string>()));
    }

    return !s_urls.empty();
}

PLUGIN_EXPORT uint32_t pluginOrder()
{
    return UINT32_MAX;
}

PLUGIN_EXPORT void destoryPlugin()
{
}
<|endoftext|>


<commit_before>#pragma once

#include "kl/detail/macros.hpp"

/*
 * Requirements: boost 1.57+, C++14 compiler and preprocessor
 * Sample usage:

namespace ns {

enum class enum_
{
    A, B, C
};
KL_REFLECT_ENUM(enum_, A, (B, bb), C)
}

 * First argument is unqualified enum type name
 * The rest is a list of enum values. Each value can be optionally a
   tuple (pair) of its real name and name used for to-from string conversions
 * Macro should be placed inside the same namespace as the enum type

 * Use kl::enum_reflector<ns::enum_> to query enum properties:
     kl::enum_reflector<ns::enum_>::to_string(ns::enum_{C});
     kl::enum_reflector<ns::enum_>::from_string("bb");
     kl::enum_reflector<ns::enum_>::count();
     kl::enum_reflector<ns::enum_>::values();
 * Alternatively, use kl::reflect<ns::enum_>()

 * Remarks: Macro KL_REFLECT_ENUM works for unscoped as well as scoped
   enums

 * Above definition is expanded to:

     inline constexpr ::kl::enum_reflection_pair<enum_>
         kl_enum_description356[] = {{enum_::A, "A"},
                                     {enum_::B, "bb"},
                                     {enum_::C, "C"},
                                     {enum_{}, nullptr}};
     constexpr auto reflect_enum(::kl::enum_class<enum_>) noexcept
     {
         return ::kl::enum_reflection_view{kl_enum_description356};
     }
 */

namespace kl {

// clang-format off
template <typename Enum>
class enum_class {};

template <typename Enum>
inline constexpr auto enum_ = enum_class<Enum>{};
// clang-format on

template <typename Enum>
struct enum_reflection_pair
{
    Enum value;
    const char* name;
};

struct enum_reflection_sentinel
{
    template <typename Enum>
    constexpr friend bool operator!=(const enum_reflection_pair<Enum>* it,
                                     enum_reflection_sentinel) noexcept
    {
        return it->name;
    }
};

template <typename Enum>
class enum_reflection_view
{
public:
    constexpr explicit enum_reflection_view(
        const kl::enum_reflection_pair<Enum>* first) noexcept
        : first_{first}
    {
    }

    constexpr auto begin() const noexcept { return first_; }
    constexpr auto end() const noexcept { return enum_reflection_sentinel{}; }

private:
    const kl::enum_reflection_pair<Enum>* first_;
};
} // namespace kl

#define KL_REFLECT_ENUM(name_, ...)                                            \
    KL_REFLECT_ENUM_TUPLE(name_, KL_VARIADIC_TO_TUPLE(__VA_ARGS__))

#define KL_REFLECT_ENUM_TUPLE(name_, values_)                                  \
    KL_REFLECT_ENUM_IMPL(name_, values_, __COUNTER__)

#define KL_REFLECT_ENUM_IMPL(name_, values_, counter_)                         \
    inline constexpr ::kl::enum_reflection_pair<name_>                         \
        KL_REFLECT_ENUM_VARNAME(counter_)[] = {                                \
            KL_REFLECT_ENUM_REFLECTION_PAIRS(name_, values_){name_{},          \
                                                             nullptr}};        \
    constexpr auto reflect_enum(::kl::enum_class<name_>) noexcept              \
    {                                                                          \
        return ::kl::enum_reflection_view{KL_REFLECT_ENUM_VARNAME(counter_)};  \
    }

#define KL_REFLECT_ENUM_VARNAME(counter_)                                      \
    KL_CONCAT(kl_enum_description, counter_)

#define KL_REFLECT_ENUM_REFLECTION_PAIRS(name_, values_)                       \
    KL_TUPLE_FOR_EACH2(name_, values_, KL_REFLECT_ENUM_REFLECTION_PAIR)

#define KL_REFLECT_ENUM_REFLECTION_PAIR(name_, value_)                         \
    KL_REFLECT_ENUM_REFLECTION_PAIR2(name_, KL_TUPLE_EXTEND_BY_FIRST(value_))

// Assumes value_ is a tuple: (x, x) or (x, y) where `x` is the name and `y` is
// the string form of the enum value
#define KL_REFLECT_ENUM_REFLECTION_PAIR2(name_, value_)                        \
    {name_::KL_TUPLE_ELEM(0, value_), KL_STRINGIZE(KL_TUPLE_ELEM(1, value_))},
<commit_msg>Fix around the __COUNTER__ being not unique across the TUs<commit_after>#pragma once

#include "kl/detail/macros.hpp"

/*
 * Requirements: boost 1.57+, C++14 compiler and preprocessor
 * Sample usage:

namespace ns {

enum class enum_
{
    A, B, C
};
KL_REFLECT_ENUM(enum_, A, (B, bb), C)
}

 * First argument is unqualified enum type name
 * The rest is a list of enum values. Each value can be optionally a
   tuple (pair) of its real name and name used for to-from string conversions
 * Macro should be placed inside the same namespace as the enum type

 * Use kl::enum_reflector<ns::enum_> to query enum properties:
     kl::enum_reflector<ns::enum_>::to_string(ns::enum_{C});
     kl::enum_reflector<ns::enum_>::from_string("bb");
     kl::enum_reflector<ns::enum_>::count();
     kl::enum_reflector<ns::enum_>::values();
 * Alternatively, use kl::reflect<ns::enum_>()

 * Remarks: Macro KL_REFLECT_ENUM works for unscoped as well as scoped
   enums

 * Above definition is expanded to:

     namespace kl_reflect_enum_ {
     inline constexpr ::kl::enum_reflection_pair<enum_> reflection_data[] = {
         {enum_::A, "A"},
         {enum_::B, "bb"},
         {enum_::C, "C"},
         {enum_{}, nullptr}};
     }
     constexpr auto reflect_enum(::kl::enum_class<enum_>) noexcept
     {
         return ::kl::enum_reflection_view{kl_reflect_enum_::reflection_data};
     }
 */

namespace kl {

// clang-format off
template <typename Enum>
class enum_class {};

template <typename Enum>
inline constexpr auto enum_ = enum_class<Enum>{};
// clang-format on

template <typename Enum>
struct enum_reflection_pair
{
    Enum value;
    const char* name;
};

struct enum_reflection_sentinel
{
    template <typename Enum>
    constexpr friend bool operator!=(const enum_reflection_pair<Enum>* it,
                                     enum_reflection_sentinel) noexcept
    {
        return it->name;
    }
};

template <typename Enum>
class enum_reflection_view
{
public:
    constexpr explicit enum_reflection_view(
        const kl::enum_reflection_pair<Enum>* first) noexcept
        : first_{first}
    {
    }

    constexpr auto begin() const noexcept { return first_; }
    constexpr auto end() const noexcept { return enum_reflection_sentinel{}; }

private:
    const kl::enum_reflection_pair<Enum>* first_;
};
} // namespace kl

#define KL_REFLECT_ENUM(name_, ...)                                            \
    KL_REFLECT_ENUM_IMPL(name_, KL_VARIADIC_TO_TUPLE(__VA_ARGS__))

#define KL_REFLECT_ENUM_IMPL(name_, values_)                                   \
    namespace KL_REFLECT_ENUM_NSNAME(name_)                                    \
    {                                                                          \
        inline constexpr ::kl::enum_reflection_pair<name_> reflection_data[] = \
            {KL_REFLECT_ENUM_REFLECTION_PAIRS(name_, values_){name_{},         \
                                                              nullptr}};       \
    }                                                                          \
    constexpr auto reflect_enum(::kl::enum_class<name_>) noexcept              \
    {                                                                          \
        return ::kl::enum_reflection_view{                                     \
            KL_REFLECT_ENUM_NSNAME(name_)::reflection_data};                   \
    }

#define KL_REFLECT_ENUM_NSNAME(name_) KL_CONCAT(kl_reflect_, name_)

#define KL_REFLECT_ENUM_REFLECTION_PAIRS(name_, values_)                       \
    KL_TUPLE_FOR_EACH2(name_, values_, KL_REFLECT_ENUM_REFLECTION_PAIR)

#define KL_REFLECT_ENUM_REFLECTION_PAIR(name_, value_)                         \
    KL_REFLECT_ENUM_REFLECTION_PAIR2(name_, KL_TUPLE_EXTEND_BY_FIRST(value_))

// Assumes value_ is a tuple: (x, x) or (x, y) where `x` is the name and `y` is
// the string form of the enum value
#define KL_REFLECT_ENUM_REFLECTION_PAIR2(name_, value_)                        \
    {name_::KL_TUPLE_ELEM(0, value_), KL_STRINGIZE(KL_TUPLE_ELEM(1, value_))},
<|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 "VertexArray.h"

#include "../base/Exception.h"
#include "../base/WideLine.h"
//#include "../base/ObjectCounter.h"

#include <iostream>
#include <stddef.h>
#include <string.h>

using namespace std;
using namespace boost;

namespace avg {

thread_specific_ptr<vector<unsigned int> > VertexArray::s_pGLVertexBufferIDs;
thread_specific_ptr<vector<unsigned int> > VertexArray::s_pGLIndexBufferIDs;

VertexArray::VertexArray(int reserveVerts, int reserveIndexes)
    : m_NumVerts(0),
      m_NumIndexes(0),
      m_ReserveVerts(reserveVerts),
      m_ReserveIndexes(reserveIndexes),
      m_bSizeChanged(true),
      m_bDataChanged(true)
{
//    ObjectCounter::get()->incRef(&typeid(*this));
    if (m_ReserveVerts < 10) {
        m_ReserveVerts = 10;
    }
    if (m_ReserveIndexes < 20) {
        m_ReserveIndexes = 20;
    }
    m_pVertexData = new T2V3C4Vertex[m_ReserveVerts];
    m_pIndexData = new unsigned int[m_ReserveIndexes];

    initBufferCache();
    if (s_pGLVertexBufferIDs->empty() || m_ReserveVerts != 10 ||
            m_ReserveIndexes != 20)
    {
        glproc::GenBuffers(1, &m_GLVertexBufferID);
        glproc::GenBuffers(1, &m_GLIndexBufferID);
        setBufferSize();
    } else {
        m_GLVertexBufferID = s_pGLVertexBufferIDs->back();
        s_pGLVertexBufferIDs->pop_back();
        m_GLIndexBufferID = s_pGLIndexBufferIDs->back();
        s_pGLIndexBufferIDs->pop_back();
    }
}

VertexArray::~VertexArray()
{
    if (m_ReserveVerts == 10) {
        s_pGLVertexBufferIDs->push_back(m_GLVertexBufferID);
    } else {
        glproc::DeleteBuffers(1, &m_GLVertexBufferID);
    }
    if (m_ReserveIndexes == 20) {
        s_pGLIndexBufferIDs->push_back(m_GLIndexBufferID);
    } else {
        glproc::DeleteBuffers(1, &m_GLIndexBufferID);
    }
    delete[] m_pVertexData;
    delete[] m_pIndexData;
//    ObjectCounter::get()->decRef(&typeid(*this));
}

void VertexArray::appendPos(const DPoint& pos,
        const DPoint& texPos, const Pixel32& color)
{
    if (m_NumVerts >= m_ReserveVerts-1) {
        grow();
    }
    T2V3C4Vertex* pVertex = &(m_pVertexData[m_NumVerts]);
    pVertex->m_Pos[0] = (GLfloat)pos.x;
    pVertex->m_Pos[1] = (GLfloat)pos.y;
    pVertex->m_Pos[2] = 0.0;
    pVertex->m_Tex[0] = (GLfloat)texPos.x;
    pVertex->m_Tex[1] = (GLfloat)texPos.y;
    pVertex->m_Color = color;
    m_bDataChanged = true;
    m_NumVerts++;
}

void VertexArray::appendTriIndexes(int v0, int v1, int v2)
{
    if (m_NumIndexes >= m_ReserveIndexes-3) {
        grow();
    }
    m_pIndexData[m_NumIndexes] = v0;
    m_pIndexData[m_NumIndexes+1] = v1;
    m_pIndexData[m_NumIndexes+2] = v2;
    m_NumIndexes += 3;
}

void VertexArray::appendQuadIndexes(int v0, int v1, int v2, int v3)
{
    if (m_NumIndexes >= m_ReserveIndexes-6) {
        grow();
    }
    m_pIndexData[m_NumIndexes] = v0;
    m_pIndexData[m_NumIndexes+1] = v1;
    m_pIndexData[m_NumIndexes+2] = v2;
    m_pIndexData[m_NumIndexes+3] = v1;
    m_pIndexData[m_NumIndexes+4] = v2;
    m_pIndexData[m_NumIndexes+5] = v3;
    m_NumIndexes += 6;
}

void VertexArray::addLineData(Pixel32 color, const DPoint& p1, const DPoint& p2,
        double width, double TC1, double TC2)
{
    WideLine wl(p1, p2, width);
    int curVertex = getCurVert();
    appendPos(wl.pl0, DPoint(TC1, 1), color);
    appendPos(wl.pr0, DPoint(TC1, 0), color);
    appendPos(wl.pl1, DPoint(TC2, 1), color);
    appendPos(wl.pr1, DPoint(TC2, 0), color);
    appendQuadIndexes(curVertex+1, curVertex, curVertex+3, curVertex+2);
}

void VertexArray::reset()
{
    m_NumVerts = 0;
    m_NumIndexes = 0;
}

void VertexArray::update()
{
    if (m_bSizeChanged) {
        setBufferSize();
        m_bSizeChanged = false;
    }
    if (m_bDataChanged) {
        glproc::BindBuffer(GL_ARRAY_BUFFER, m_GLVertexBufferID);
        glproc::BufferData(GL_ARRAY_BUFFER, m_ReserveVerts*sizeof(T2V3C4Vertex), 0,
            GL_STREAM_DRAW);
        glproc::BufferSubData(GL_ARRAY_BUFFER, 0, m_NumVerts*sizeof(T2V3C4Vertex),
                m_pVertexData);
        glproc::BindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_GLIndexBufferID);
        glproc::BufferData(GL_ELEMENT_ARRAY_BUFFER,
            m_ReserveIndexes*sizeof(unsigned int), 0, GL_STREAM_DRAW);
        glproc::BufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, m_NumIndexes*sizeof(unsigned int),
                m_pIndexData);
        OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "VertexArray::update");
    }
    m_bDataChanged = false;
}

void VertexArray::draw()
{
    update();
    glproc::BindBuffer(GL_ARRAY_BUFFER, m_GLVertexBufferID);
    glTexCoordPointer(2, GL_FLOAT, sizeof(T2V3C4Vertex), 0);
    glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(T2V3C4Vertex),
            (void *)(offsetof(T2V3C4Vertex, m_Color)));
    glVertexPointer(3, GL_FLOAT, sizeof(T2V3C4Vertex),
            (void *)(offsetof(T2V3C4Vertex, m_Pos)));
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "VertexArray::draw:1");

    glproc::BindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_GLIndexBufferID);
    glDrawElements(GL_TRIANGLES, m_NumIndexes, GL_UNSIGNED_INT, 0);
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "VertexArray::draw():2");
}

int VertexArray::getCurVert() const
{
    return m_NumVerts;
}

int VertexArray::getCurIndex() const
{
    return m_NumIndexes;
}

void VertexArray::grow()
{
    bool bChanged = false;
    if (m_NumVerts >= m_ReserveVerts-1) {
        bChanged = true;
        int oldReserveVerts = m_ReserveVerts;
        m_ReserveVerts = int(m_ReserveVerts*1.5);
        if (m_ReserveVerts < m_NumVerts) {
            m_ReserveVerts = m_NumVerts;
        }
        T2V3C4Vertex* pVertexData = m_pVertexData;
        m_pVertexData = new T2V3C4Vertex[m_ReserveVerts];
        memcpy(m_pVertexData, pVertexData, sizeof(T2V3C4Vertex)*oldReserveVerts);
        delete[] pVertexData;
    }
    if (m_NumIndexes >= m_ReserveIndexes-6) {
        bChanged = true;
        int oldReserveIndexes = m_ReserveIndexes;
        m_ReserveIndexes = int(m_ReserveIndexes*1.5);
        if (m_ReserveIndexes < m_NumIndexes) {
            m_ReserveIndexes = m_NumIndexes;
        }
        unsigned int * pIndexData = m_pIndexData;
        m_pIndexData = new unsigned int[m_ReserveIndexes];
        memcpy(m_pIndexData, pIndexData, sizeof(unsigned int)*oldReserveIndexes);
        delete[] pIndexData;
    }
    if (bChanged) {
        m_bSizeChanged = true;
        m_bDataChanged = true;
    }
}

void VertexArray::setBufferSize()
{
    glproc::BindBuffer(GL_ARRAY_BUFFER, m_GLVertexBufferID);
    glproc::BufferData(GL_ARRAY_BUFFER, m_ReserveVerts*sizeof(T2V3C4Vertex), 0,
            GL_STREAM_DRAW);
    glproc::BindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_GLIndexBufferID);
    glproc::BufferData(GL_ELEMENT_ARRAY_BUFFER,
            m_ReserveIndexes*sizeof(unsigned int), 0, GL_STREAM_DRAW);
}

void VertexArray::initBufferCache()
{
    if (s_pGLVertexBufferIDs.get() == 0) {
        s_pGLVertexBufferIDs.reset(new vector<unsigned int>);
    }
    if (s_pGLIndexBufferIDs.get() == 0) {
        s_pGLIndexBufferIDs.reset(new vector<unsigned int>);
    }
}

void VertexArray::deleteBufferCache()
{
    if (s_pGLVertexBufferIDs.get() != 0) {
        for (unsigned i=0; i<s_pGLVertexBufferIDs->size(); ++i) {
            glproc::DeleteBuffers(1, &((*s_pGLVertexBufferIDs)[i]));
        }
        s_pGLVertexBufferIDs->clear();
    }
    if (s_pGLIndexBufferIDs.get() != 0) {
        for (unsigned i=0; i<s_pGLIndexBufferIDs->size(); ++i) {
            glproc::DeleteBuffers(1, &((*s_pGLIndexBufferIDs)[i]));
        }
        s_pGLIndexBufferIDs->clear();
    }
}

}

<commit_msg>Added VertexArray ObjectCounter.<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 "VertexArray.h"

#include "../base/Exception.h"
#include "../base/WideLine.h"
#include "../base/ObjectCounter.h"

#include <iostream>
#include <stddef.h>
#include <string.h>

using namespace std;
using namespace boost;

namespace avg {

thread_specific_ptr<vector<unsigned int> > VertexArray::s_pGLVertexBufferIDs;
thread_specific_ptr<vector<unsigned int> > VertexArray::s_pGLIndexBufferIDs;

VertexArray::VertexArray(int reserveVerts, int reserveIndexes)
    : m_NumVerts(0),
      m_NumIndexes(0),
      m_ReserveVerts(reserveVerts),
      m_ReserveIndexes(reserveIndexes),
      m_bSizeChanged(true),
      m_bDataChanged(true)
{
    ObjectCounter::get()->incRef(&typeid(*this));
    if (m_ReserveVerts < 10) {
        m_ReserveVerts = 10;
    }
    if (m_ReserveIndexes < 20) {
        m_ReserveIndexes = 20;
    }
    m_pVertexData = new T2V3C4Vertex[m_ReserveVerts];
    m_pIndexData = new unsigned int[m_ReserveIndexes];

    initBufferCache();
    if (s_pGLVertexBufferIDs->empty() || m_ReserveVerts != 10 ||
            m_ReserveIndexes != 20)
    {
        glproc::GenBuffers(1, &m_GLVertexBufferID);
        glproc::GenBuffers(1, &m_GLIndexBufferID);
        setBufferSize();
    } else {
        m_GLVertexBufferID = s_pGLVertexBufferIDs->back();
        s_pGLVertexBufferIDs->pop_back();
        m_GLIndexBufferID = s_pGLIndexBufferIDs->back();
        s_pGLIndexBufferIDs->pop_back();
    }
}

VertexArray::~VertexArray()
{
    if (m_ReserveVerts == 10) {
        s_pGLVertexBufferIDs->push_back(m_GLVertexBufferID);
    } else {
        glproc::DeleteBuffers(1, &m_GLVertexBufferID);
    }
    if (m_ReserveIndexes == 20) {
        s_pGLIndexBufferIDs->push_back(m_GLIndexBufferID);
    } else {
        glproc::DeleteBuffers(1, &m_GLIndexBufferID);
    }
    delete[] m_pVertexData;
    delete[] m_pIndexData;
    ObjectCounter::get()->decRef(&typeid(*this));
}

void VertexArray::appendPos(const DPoint& pos,
        const DPoint& texPos, const Pixel32& color)
{
    if (m_NumVerts >= m_ReserveVerts-1) {
        grow();
    }
    T2V3C4Vertex* pVertex = &(m_pVertexData[m_NumVerts]);
    pVertex->m_Pos[0] = (GLfloat)pos.x;
    pVertex->m_Pos[1] = (GLfloat)pos.y;
    pVertex->m_Pos[2] = 0.0;
    pVertex->m_Tex[0] = (GLfloat)texPos.x;
    pVertex->m_Tex[1] = (GLfloat)texPos.y;
    pVertex->m_Color = color;
    m_bDataChanged = true;
    m_NumVerts++;
}

void VertexArray::appendTriIndexes(int v0, int v1, int v2)
{
    if (m_NumIndexes >= m_ReserveIndexes-3) {
        grow();
    }
    m_pIndexData[m_NumIndexes] = v0;
    m_pIndexData[m_NumIndexes+1] = v1;
    m_pIndexData[m_NumIndexes+2] = v2;
    m_NumIndexes += 3;
}

void VertexArray::appendQuadIndexes(int v0, int v1, int v2, int v3)
{
    if (m_NumIndexes >= m_ReserveIndexes-6) {
        grow();
    }
    m_pIndexData[m_NumIndexes] = v0;
    m_pIndexData[m_NumIndexes+1] = v1;
    m_pIndexData[m_NumIndexes+2] = v2;
    m_pIndexData[m_NumIndexes+3] = v1;
    m_pIndexData[m_NumIndexes+4] = v2;
    m_pIndexData[m_NumIndexes+5] = v3;
    m_NumIndexes += 6;
}

void VertexArray::addLineData(Pixel32 color, const DPoint& p1, const DPoint& p2,
        double width, double TC1, double TC2)
{
    WideLine wl(p1, p2, width);
    int curVertex = getCurVert();
    appendPos(wl.pl0, DPoint(TC1, 1), color);
    appendPos(wl.pr0, DPoint(TC1, 0), color);
    appendPos(wl.pl1, DPoint(TC2, 1), color);
    appendPos(wl.pr1, DPoint(TC2, 0), color);
    appendQuadIndexes(curVertex+1, curVertex, curVertex+3, curVertex+2);
}

void VertexArray::reset()
{
    m_NumVerts = 0;
    m_NumIndexes = 0;
}

void VertexArray::update()
{
    if (m_bSizeChanged) {
        setBufferSize();
        m_bSizeChanged = false;
    }
    if (m_bDataChanged) {
        glproc::BindBuffer(GL_ARRAY_BUFFER, m_GLVertexBufferID);
        glproc::BufferData(GL_ARRAY_BUFFER, m_ReserveVerts*sizeof(T2V3C4Vertex), 0,
            GL_STREAM_DRAW);
        glproc::BufferSubData(GL_ARRAY_BUFFER, 0, m_NumVerts*sizeof(T2V3C4Vertex),
                m_pVertexData);
        glproc::BindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_GLIndexBufferID);
        glproc::BufferData(GL_ELEMENT_ARRAY_BUFFER,
            m_ReserveIndexes*sizeof(unsigned int), 0, GL_STREAM_DRAW);
        glproc::BufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, m_NumIndexes*sizeof(unsigned int),
                m_pIndexData);
        OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "VertexArray::update");
    }
    m_bDataChanged = false;
}

void VertexArray::draw()
{
    update();
    glproc::BindBuffer(GL_ARRAY_BUFFER, m_GLVertexBufferID);
    glTexCoordPointer(2, GL_FLOAT, sizeof(T2V3C4Vertex), 0);
    glColorPointer(4, GL_UNSIGNED_BYTE, sizeof(T2V3C4Vertex),
            (void *)(offsetof(T2V3C4Vertex, m_Color)));
    glVertexPointer(3, GL_FLOAT, sizeof(T2V3C4Vertex),
            (void *)(offsetof(T2V3C4Vertex, m_Pos)));
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "VertexArray::draw:1");

    glproc::BindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_GLIndexBufferID);
    glDrawElements(GL_TRIANGLES, m_NumIndexes, GL_UNSIGNED_INT, 0);
    OGLErrorCheck(AVG_ERR_VIDEO_GENERAL, "VertexArray::draw():2");
}

int VertexArray::getCurVert() const
{
    return m_NumVerts;
}

int VertexArray::getCurIndex() const
{
    return m_NumIndexes;
}

void VertexArray::grow()
{
    bool bChanged = false;
    if (m_NumVerts >= m_ReserveVerts-1) {
        bChanged = true;
        int oldReserveVerts = m_ReserveVerts;
        m_ReserveVerts = int(m_ReserveVerts*1.5);
        if (m_ReserveVerts < m_NumVerts) {
            m_ReserveVerts = m_NumVerts;
        }
        T2V3C4Vertex* pVertexData = m_pVertexData;
        m_pVertexData = new T2V3C4Vertex[m_ReserveVerts];
        memcpy(m_pVertexData, pVertexData, sizeof(T2V3C4Vertex)*oldReserveVerts);
        delete[] pVertexData;
    }
    if (m_NumIndexes >= m_ReserveIndexes-6) {
        bChanged = true;
        int oldReserveIndexes = m_ReserveIndexes;
        m_ReserveIndexes = int(m_ReserveIndexes*1.5);
        if (m_ReserveIndexes < m_NumIndexes) {
            m_ReserveIndexes = m_NumIndexes;
        }
        unsigned int * pIndexData = m_pIndexData;
        m_pIndexData = new unsigned int[m_ReserveIndexes];
        memcpy(m_pIndexData, pIndexData, sizeof(unsigned int)*oldReserveIndexes);
        delete[] pIndexData;
    }
    if (bChanged) {
        m_bSizeChanged = true;
        m_bDataChanged = true;
    }
}

void VertexArray::setBufferSize()
{
    glproc::BindBuffer(GL_ARRAY_BUFFER, m_GLVertexBufferID);
    glproc::BufferData(GL_ARRAY_BUFFER, m_ReserveVerts*sizeof(T2V3C4Vertex), 0,
            GL_STREAM_DRAW);
    glproc::BindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_GLIndexBufferID);
    glproc::BufferData(GL_ELEMENT_ARRAY_BUFFER,
            m_ReserveIndexes*sizeof(unsigned int), 0, GL_STREAM_DRAW);
}

void VertexArray::initBufferCache()
{
    if (s_pGLVertexBufferIDs.get() == 0) {
        s_pGLVertexBufferIDs.reset(new vector<unsigned int>);
    }
    if (s_pGLIndexBufferIDs.get() == 0) {
        s_pGLIndexBufferIDs.reset(new vector<unsigned int>);
    }
}

void VertexArray::deleteBufferCache()
{
    if (s_pGLVertexBufferIDs.get() != 0) {
        for (unsigned i=0; i<s_pGLVertexBufferIDs->size(); ++i) {
            glproc::DeleteBuffers(1, &((*s_pGLVertexBufferIDs)[i]));
        }
        s_pGLVertexBufferIDs->clear();
    }
    if (s_pGLIndexBufferIDs.get() != 0) {
        for (unsigned i=0; i<s_pGLIndexBufferIDs->size(); ++i) {
            glproc::DeleteBuffers(1, &((*s_pGLIndexBufferIDs)[i]));
        }
        s_pGLIndexBufferIDs->clear();
    }
}

}

<|endoftext|>


<commit_before>/******************************************************************************
 * $Id$
 *
 * Project:  libLAS - http://liblas.org - A BSD library for LAS format data.
 * Purpose:  LAS Dimension implementation for C++ libLAS
 * Author:   Howard Butler, hobu.inc@gmail.com
 *
 ******************************************************************************
 * Copyright (c) 2010, Howard Butler
 *
 * 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 Martin Isenburg or Iowa Department
 *       of Natural Resources 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.
 ****************************************************************************/

#ifndef LIBPC_DIMENSION_HPP_INCLUDED
#define LIBPC_DIMENSION_HPP_INCLUDED

#include <libpc/libpc.hpp>
#include <libpc/Utils.hpp>
#include <boost/property_tree/ptree.hpp>

namespace libpc
{

/// A Dimension consists of a name, a datatype, and (for the bitfield datatype), the number
/// of bits the dimension requires.
///
/// When a dimension is added to a Schema, it also gets two more properties: the position (index)
/// of this dimension in the schema's list of dimensions, and the byte offset where the dimension
/// is stored in the PointBuffer's raw bytes
class LIBPC_DLL Dimension
{
public:
    enum Field
    {
        Field_INVALID = 0,
        Field_X,
        Field_Y,
        Field_Z,
        Field_Intensity,
        Field_ReturnNumber,
        Field_NumberOfReturns,
        Field_ScanDirectionFlag,
        Field_EdgeOfFlightLine,
        Field_Classification,
        Field_ScanAngleRank,
        Field_UserData,
        Field_PointSourceId,
        Field_Time,
        Field_Red,
        Field_Green,
        Field_Blue,
        Field_WavePacketDescriptorIndex,
        Field_WaveformDataOffset,
        Field_ReturnPointWaveformLocation,
        Field_WaveformXt,
        Field_WaveformYt,
        Field_WaveformZt,
        // ...

        // add more here
        Field_User1 = 512,
        Field_User2,
        Field_User3,
        Field_User4,
        Field_User5,
        Field_User6,
        Field_User7,
        Field_User8,
        Field_User9,
        Field_User10,
        Field_User11,
        Field_User12,
        Field_User13,
        Field_User14,
        Field_User15,
        // ...
        // feel free to use your own int here

        Field_LAST = 1023
    };

    // Do not explicitly specify these enum values because they
    // are (probably wrongly) used to iterate through for Schema::getX, Schema::getY, Schema::getZ
    enum DataType
    {
        Int8,
        Uint8,
        Int16,
        Uint16,
        Int32,
        Uint32,
        Int64,
        Uint64,
        Float,       // 32 bits
        Double,       // 64 bits
        Undefined
    };

public:
    Dimension(Field field, DataType type);
    Dimension& operator=(Dimension const& rhs);
    Dimension(Dimension const& other);

    bool operator==(const Dimension& other) const;
    bool operator!=(const Dimension& other) const;

    std::string const& getFieldName() const;

    Field getField() const
    {
        return m_field;
    }

    DataType getDataType() const
    {
        return m_dataType;
    }

    static std::string getDataTypeName(DataType);
    static DataType getDataTypeFromString(const std::string&);
    static std::size_t getDataTypeSize(DataType);
    static bool getDataTypeIsNumeric(DataType);
    static bool getDataTypeIsSigned(DataType);
    static bool getDataTypeIsInteger(DataType);
    static std::string const& getFieldName(Field);

    /// bytes, physical/serialisation size of record
    // for bitfields, this will be rounded up to the next largest byte
    std::size_t getByteSize() const
    {
       return m_byteSize;
    }

    inline std::string getDescription() const
    {
        return m_description;
    }
    inline void setDescription(std::string const& v)
    {
        m_description = v;
    }

    /// Is this dimension a numeric dimension.  Dimensions with IsNumeric == false
    /// are considered generic bit/byte fields
    inline bool isNumeric() const
    {
        return getDataTypeIsNumeric(m_dataType);
    }

    /// Does this dimension have a sign?  Only applicable to dimensions with
    /// IsNumeric == true.
    inline bool isSigned() const
    {
        return getDataTypeIsSigned(m_dataType);
    }

    /// Does this dimension interpret to an integer?  Only applicable to dimensions
    /// with IsNumeric == true.
    inline bool isInteger() const
    {
        return getDataTypeIsInteger(m_dataType);
    }

    /// The minimum value of this dimension as a double
    inline double getMinimum() const
    {
        return m_min;
    }
    inline void setMinimum(double min)
    {
        m_min = min;
    }

    /// The maximum value of this dimension as a double
    inline double getMaximum() const
    {
        return m_max;
    }
    inline void setMaximum(double max)
    {
        m_max = max;
    }

    /// The scaling value for this dimension as a double.  This should
    /// be positive or negative powers of ten.
    inline double getNumericScale() const
    {
        return m_numericScale;
    }
    inline void setNumericScale(double v)
    {
        m_numericScale = v;
    }

    /// The offset value for this dimension.  Usually zero, but it
    /// can be set to any value in combination with the scale to
    /// allow for more expressive ranges.
    /// (this is not called just "Offset" anymore, since that term also
    /// means "what bit/byte position a field is located at")
    inline double getNumericOffset() const
    {
        return m_numericOffset;
    }
    inline void setNumericOffset(double v)
    {
        m_numericOffset = v;
    }

    template<class T>
    double applyScaling(T v) const
    {
        return (double)v * m_numericScale + m_numericOffset;
    }

    template<class T>
    T removeScaling(double v) const
    {
        T output = static_cast<T>(Utils::sround((v - m_numericOffset)/ m_numericScale));
        return output;
    }

    /// If true, this dimension uses the numeric scale/offset values
    inline bool isFinitePrecision() const
    {
        return m_precise;
    }
    inline void isFinitePrecision(bool v)
    {
        m_precise = v;
    }

    /// The scaling value for this dimension as a double.  This should
    /// be positive or negative powers of ten.
    inline EndianType getEndianness() const
    {
        return m_endian;
    }
    inline void setEndianness(EndianType v)
    {
        m_endian = v;
    }

    boost::property_tree::ptree GetPTree() const;

private:
    DataType m_dataType;
    Field m_field;
    EndianType m_endian;
    std::size_t m_byteSize;
    std::string m_description;
    double m_min;
    double m_max;
    bool m_precise;
    double m_numericScale;
    double m_numericOffset;

    static void initFieldNames();
    static bool s_fieldNamesValid;
    static std::string s_fieldNames[Field_LAST];
};

LIBPC_DLL std::ostream& operator<<(std::ostream& os, libpc::Dimension const& d);

} // namespace libpc

#endif // LIBPC_DIMENSION_HPP_INCLUDED
<commit_msg>applyScaling should be a no-op in the case where the m_numericScale is 0.0<commit_after>/******************************************************************************
 * $Id$
 *
 * Project:  libLAS - http://liblas.org - A BSD library for LAS format data.
 * Purpose:  LAS Dimension implementation for C++ libLAS
 * Author:   Howard Butler, hobu.inc@gmail.com
 *
 ******************************************************************************
 * Copyright (c) 2010, Howard Butler
 *
 * 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 Martin Isenburg or Iowa Department
 *       of Natural Resources 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.
 ****************************************************************************/

#ifndef LIBPC_DIMENSION_HPP_INCLUDED
#define LIBPC_DIMENSION_HPP_INCLUDED

#include <libpc/libpc.hpp>
#include <libpc/Utils.hpp>
#include <boost/property_tree/ptree.hpp>

namespace libpc
{

/// A Dimension consists of a name, a datatype, and (for the bitfield datatype), the number
/// of bits the dimension requires.
///
/// When a dimension is added to a Schema, it also gets two more properties: the position (index)
/// of this dimension in the schema's list of dimensions, and the byte offset where the dimension
/// is stored in the PointBuffer's raw bytes
class LIBPC_DLL Dimension
{
public:
    enum Field
    {
        Field_INVALID = 0,
        Field_X,
        Field_Y,
        Field_Z,
        Field_Intensity,
        Field_ReturnNumber,
        Field_NumberOfReturns,
        Field_ScanDirectionFlag,
        Field_EdgeOfFlightLine,
        Field_Classification,
        Field_ScanAngleRank,
        Field_UserData,
        Field_PointSourceId,
        Field_Time,
        Field_Red,
        Field_Green,
        Field_Blue,
        Field_WavePacketDescriptorIndex,
        Field_WaveformDataOffset,
        Field_ReturnPointWaveformLocation,
        Field_WaveformXt,
        Field_WaveformYt,
        Field_WaveformZt,
        // ...

        // add more here
        Field_User1 = 512,
        Field_User2,
        Field_User3,
        Field_User4,
        Field_User5,
        Field_User6,
        Field_User7,
        Field_User8,
        Field_User9,
        Field_User10,
        Field_User11,
        Field_User12,
        Field_User13,
        Field_User14,
        Field_User15,
        // ...
        // feel free to use your own int here

        Field_LAST = 1023
    };

    // Do not explicitly specify these enum values because they
    // are (probably wrongly) used to iterate through for Schema::getX, Schema::getY, Schema::getZ
    enum DataType
    {
        Int8,
        Uint8,
        Int16,
        Uint16,
        Int32,
        Uint32,
        Int64,
        Uint64,
        Float,       // 32 bits
        Double,       // 64 bits
        Undefined
    };

public:
    Dimension(Field field, DataType type);
    Dimension& operator=(Dimension const& rhs);
    Dimension(Dimension const& other);

    bool operator==(const Dimension& other) const;
    bool operator!=(const Dimension& other) const;

    std::string const& getFieldName() const;

    Field getField() const
    {
        return m_field;
    }

    DataType getDataType() const
    {
        return m_dataType;
    }

    static std::string getDataTypeName(DataType);
    static DataType getDataTypeFromString(const std::string&);
    static std::size_t getDataTypeSize(DataType);
    static bool getDataTypeIsNumeric(DataType);
    static bool getDataTypeIsSigned(DataType);
    static bool getDataTypeIsInteger(DataType);
    static std::string const& getFieldName(Field);

    /// bytes, physical/serialisation size of record
    // for bitfields, this will be rounded up to the next largest byte
    std::size_t getByteSize() const
    {
       return m_byteSize;
    }

    inline std::string getDescription() const
    {
        return m_description;
    }
    inline void setDescription(std::string const& v)
    {
        m_description = v;
    }

    /// Is this dimension a numeric dimension.  Dimensions with IsNumeric == false
    /// are considered generic bit/byte fields
    inline bool isNumeric() const
    {
        return getDataTypeIsNumeric(m_dataType);
    }

    /// Does this dimension have a sign?  Only applicable to dimensions with
    /// IsNumeric == true.
    inline bool isSigned() const
    {
        return getDataTypeIsSigned(m_dataType);
    }

    /// Does this dimension interpret to an integer?  Only applicable to dimensions
    /// with IsNumeric == true.
    inline bool isInteger() const
    {
        return getDataTypeIsInteger(m_dataType);
    }

    /// The minimum value of this dimension as a double
    inline double getMinimum() const
    {
        return m_min;
    }
    inline void setMinimum(double min)
    {
        m_min = min;
    }

    /// The maximum value of this dimension as a double
    inline double getMaximum() const
    {
        return m_max;
    }
    inline void setMaximum(double max)
    {
        m_max = max;
    }

    /// The scaling value for this dimension as a double.  This should
    /// be positive or negative powers of ten.
    inline double getNumericScale() const
    {
        return m_numericScale;
    }
    inline void setNumericScale(double v)
    {
        m_numericScale = v;
    }

    /// The offset value for this dimension.  Usually zero, but it
    /// can be set to any value in combination with the scale to
    /// allow for more expressive ranges.
    /// (this is not called just "Offset" anymore, since that term also
    /// means "what bit/byte position a field is located at")
    inline double getNumericOffset() const
    {
        return m_numericOffset;
    }
    inline void setNumericOffset(double v)
    {
        m_numericOffset = v;
    }

    template<class T>
    double applyScaling(T v) const
    {
        if ( !Utils::compare_approx(m_numericScale, 0.0, (std::numeric_limits<double>::min)()))
            return (double)v * m_numericScale + m_numericOffset;
        else
        {
            return v;
        }
    }

    template<class T>
    T removeScaling(double v) const
    {
        T output = static_cast<T>(Utils::sround((v - m_numericOffset)/ m_numericScale));
        return output;
    }

    /// If true, this dimension uses the numeric scale/offset values
    inline bool isFinitePrecision() const
    {
        return m_precise;
    }
    inline void isFinitePrecision(bool v)
    {
        m_precise = v;
    }

    /// The scaling value for this dimension as a double.  This should
    /// be positive or negative powers of ten.
    inline EndianType getEndianness() const
    {
        return m_endian;
    }
    inline void setEndianness(EndianType v)
    {
        m_endian = v;
    }

    boost::property_tree::ptree GetPTree() const;

private:
    DataType m_dataType;
    Field m_field;
    EndianType m_endian;
    std::size_t m_byteSize;
    std::string m_description;
    double m_min;
    double m_max;
    bool m_precise;
    double m_numericScale;
    double m_numericOffset;

    static void initFieldNames();
    static bool s_fieldNamesValid;
    static std::string s_fieldNames[Field_LAST];
};

LIBPC_DLL std::ostream& operator<<(std::ostream& os, libpc::Dimension const& d);

} // namespace libpc

#endif // LIBPC_DIMENSION_HPP_INCLUDED
<|endoftext|>


<commit_before>/*

Copyright (c) 2003, Arvid Norberg
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 author 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.

*/

#ifndef TORRENT_FILE_HPP_INCLUDED
#define TORRENT_FILE_HPP_INCLUDED

#include <memory>

#include <boost/noncopyable.hpp>
#include <boost/filesystem/path.hpp>

namespace libtorrent
{

	struct file_error: std::runtime_error
	{
		file_error(std::string const& msg): std::runtime_error(msg) {}
	};

	class file: public boost::noncopyable
	{
	public:

#ifdef _MSC_VER
		typedef _int64 size_type;
#else
		typedef long long int size_type;
#endif

		class seek_mode
		{
		friend file;
		seek_mode(int v): m_val(v) {}
		int m_val;
		};

		const static seek_mode begin;
		const static seek_mode end;

		class open_mode
		{
		friend file;
		public:

			open_mode(): m_mask(0) {}

			open_mode operator|(open_mode m) const
			{ return open_mode(m.m_mask | m_mask); }

			open_mode operator|=(open_mode m)
			{
				m_mask |= m.m_mask;
				return *this;
			}

		private:

			open_mode(int val): m_mask(val) {}
			int m_mask;
		};

		const static open_mode in;
		const static open_mode out;

		file();
		file(boost::filesystem::path const& p, open_mode m);
		~file();

		void open(boost::filesystem::path const& p, open_mode m);
		void close();

		size_type write(const char*, size_type num_bytes);
		size_type read(char*, size_type num_bytes);

		void seek(size_type pos, seek_mode m);
		size_type tell();

	private:

		struct impl;
		const std::auto_ptr<impl> m_impl;

	};

}

#endif // TORRENT_FILE_HPP_INCLUDED

<commit_msg>*** empty log message ***<commit_after>/*

Copyright (c) 2003, Arvid Norberg
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 author 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.

*/

#ifndef TORRENT_FILE_HPP_INCLUDED
#define TORRENT_FILE_HPP_INCLUDED

#include <memory>

#include <boost/noncopyable.hpp>
#include <boost/filesystem/path.hpp>
#include <boost/cstdint.hpp>

namespace libtorrent
{

	struct file_error: std::runtime_error
	{
		file_error(std::string const& msg): std::runtime_error(msg) {}
	};

	class file: public boost::noncopyable
	{
	public:

		typedef boost::int64_t size_type;

		class seek_mode
		{
		friend file;
		private:
			seek_mode(int v): m_val(v) {}
			int m_val;
		};

		const static seek_mode begin;
		const static seek_mode end;

		class open_mode
		{
		friend file;
		public:

			open_mode(): m_mask(0) {}

			open_mode operator|(open_mode m) const
			{ return open_mode(m.m_mask | m_mask); }

			open_mode operator|=(open_mode m)
			{
				m_mask |= m.m_mask;
				return *this;
			}

		private:

			open_mode(int val): m_mask(val) {}
			int m_mask;
		};

		const static open_mode in;
		const static open_mode out;

		file();
		file(boost::filesystem::path const& p, open_mode m);
		~file();

		void open(boost::filesystem::path const& p, open_mode m);
		void close();

		size_type write(const char*, size_type num_bytes);
		size_type read(char*, size_type num_bytes);

		void seek(size_type pos, seek_mode m);
		size_type tell();

	private:

		struct impl;
		const std::auto_ptr<impl> m_impl;

	};

}

#endif // TORRENT_FILE_HPP_INCLUDED

<|endoftext|>


<commit_before><commit_msg>grt: clang-format<commit_after><|endoftext|>