<commit_before>/**************************************************************************
**
** Copyright (c) 2014 Lorenz Haas
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** 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.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "beautifierplugin.h"

#include "beautifierconstants.h"
#include "command.h"

#include "artisticstyle/artisticstyle.h"
#include "clangformat/clangformat.h"
#include "uncrustify/uncrustify.h"

#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/command.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/icontext.h>
#include <coreplugin/icore.h>
#include <coreplugin/messagemanager.h>
#include <diffeditor/differ.h>
#include <texteditor/basetextdocument.h>
#include <texteditor/basetextdocumentlayout.h>
#include <texteditor/basetexteditor.h>
#include <texteditor/texteditorconstants.h>
#include <utils/fileutils.h>

#include <QAction>
#include <QDir>
#include <QFileInfo>
#include <QDir>
#include <QPlainTextEdit>
#include <QProcess>
#include <QScrollBar>
#include <QTextBlock>
#include <QTimer>
#include <QtPlugin>

namespace Beautifier {
namespace Internal {

BeautifierPlugin::BeautifierPlugin()
{
}

BeautifierPlugin::~BeautifierPlugin()
{
}

bool BeautifierPlugin::initialize(const QStringList &arguments, QString *errorString)
{
    Q_UNUSED(arguments)
    Q_UNUSED(errorString)

    m_tools << new ArtisticStyle::ArtisticStyle(this);
    m_tools << new ClangFormat::ClangFormat(this);
    m_tools << new Uncrustify::Uncrustify(this);

    Core::ActionContainer *menu = Core::ActionManager::createMenu(Constants::MENU_ID);
    menu->menu()->setTitle(QLatin1String("Beautifier"));
    Core::ActionManager::actionContainer(Core::Constants::M_TOOLS)->addMenu(menu);

    for (int i = 0, total = m_tools.count(); i < total; ++i) {
        BeautifierAbstractTool *tool = m_tools.at(i);
        tool->initialize();
        const QList<QObject *> autoReleasedObjects = tool->autoReleaseObjects();
        for (int j = 0, total = autoReleasedObjects.count(); j < total; ++j)
            addAutoReleasedObject(autoReleasedObjects.at(j));
    }

    // The single shot is needed, otherwise the menu will stay disabled even
    // when the submenu's actions get enabled later on.
    QTimer::singleShot(0, this, SLOT(updateActions()));
    return true;
}

void BeautifierPlugin::extensionsInitialized()
{
    if (const Core::EditorManager *editorManager = Core::EditorManager::instance()) {
        connect(editorManager, SIGNAL(currentEditorChanged(Core::IEditor*)),
                this, SLOT(updateActions(Core::IEditor*)));
    }
}

ExtensionSystem::IPlugin::ShutdownFlag BeautifierPlugin::aboutToShutdown()
{
    return SynchronousShutdown;
}

void BeautifierPlugin::updateActions(Core::IEditor *editor)
{
    for (int i = 0, total = m_tools.count(); i < total; ++i)
        m_tools.at(i)->updateActions(editor);
}

QString BeautifierPlugin::format(const QString &text, const Command &command, const QString &fileName)
{
    const QString executable = command.executable();
    if (executable.isEmpty())
        return QString();

    switch (command.processing()) {
    case Command::FileProcessing: {
        // Save text to temporary file
        QFileInfo fi(fileName);
        Utils::TempFileSaver sourceFile(QDir::tempPath() + QLatin1String("/qtc_beautifier_XXXXXXXX.")
                                        + fi.suffix());
        sourceFile.setAutoRemove(true);
        sourceFile.write(text.toUtf8());
        if (!sourceFile.finalize()) {
            showError(tr("Cannot create temporary file \"%1\": %2.")
                      .arg(sourceFile.fileName()).arg(sourceFile.errorString()));
            return QString();
        }

        // Format temporary file
        QProcess process;
        QStringList options = command.options();
        options.replaceInStrings(QLatin1String("%file"), sourceFile.fileName());
        process.start(executable, options);
        if (!process.waitForFinished()) {
            showError(tr("Cannot call %1 or some other error occurred.").arg(executable));
            return QString();
        }
        const QByteArray output = process.readAllStandardError();
        if (!output.isEmpty())
            showError(executable + QLatin1String(": ") + QString::fromUtf8(output));

        // Read text back
        Utils::FileReader reader;
        if (!reader.fetch(sourceFile.fileName(), QIODevice::Text)) {
            showError(tr("Cannot read file \"%1\": %2.")
                      .arg(sourceFile.fileName()).arg(reader.errorString()));
            return QString();
        }
        return QString::fromUtf8(reader.data());
    } break;

    case Command::PipeProcessing: {
        QProcess process;
        QStringList options = command.options();
        options.replaceInStrings(QLatin1String("%file"), fileName);
        process.start(executable, options);
        if (!process.waitForStarted()) {
            showError(tr("Cannot call %1 or some other error occurred.").arg(executable));
            return QString();
        }
        process.write(text.toUtf8());
        process.closeWriteChannel();
        if (!process.waitForFinished()) {
            showError(tr("Cannot call %1 or some other error occurred.").arg(executable));
            return QString();
        }
        const QByteArray error = process.readAllStandardError();
        if (!error.isEmpty()) {
            showError(executable + QLatin1String(": ") + QString::fromUtf8(error));
            return QString();
        }

        if (command.pipeAddsNewline()) {
            QString formatted = QString::fromUtf8(process.readAllStandardOutput());
            formatted.remove(QRegExp(QLatin1String("(\\r\\n|\\n)$")));
            return formatted;
        }
        return QString::fromUtf8(process.readAllStandardOutput());
    }
    }

    return QString();
}

void BeautifierPlugin::formatCurrentFile(const Command &command)
{
    QPlainTextEdit *textEditor = 0;
    if (TextEditor::BaseTextEditor *editor
            = qobject_cast<TextEditor::BaseTextEditor *>(Core::EditorManager::currentEditor()))
        textEditor = qobject_cast<QPlainTextEdit *>(editor->editorWidget());
    if (!textEditor)
        return;

    const QString sourceData = textEditor->toPlainText();
    if (sourceData.isEmpty())
        return;

    const QString formattedData = format(sourceData, command,
                                         Core::EditorManager::currentDocument()->filePath());
    if ((sourceData == formattedData) || formattedData.isEmpty())
        return;

    // Since QTextCursor does not work properly with folded blocks, all blocks must be unfolded.
    // To restore the current state at the end, keep track of which block is folded.
    QList<int> foldedBlocks;
    QTextBlock block = textEditor->document()->firstBlock();
    while (block.isValid()) {
        if (const TextEditor::TextBlockUserData *userdata
                = static_cast<TextEditor::TextBlockUserData *>(block.userData())) {
            if (userdata->folded()) {
                foldedBlocks << block.blockNumber();
                TextEditor::BaseTextDocumentLayout::doFoldOrUnfold(block, true);
            }
        }
        block = block.next();
    }
    textEditor->update();

    // Save the current viewport position of the cursor to ensure the same vertical position after
    // the formatted text has set to the editor.
    int absoluteVerticalCursorOffset = textEditor->cursorRect().y();

    // Calculate diff
    DiffEditor::Differ differ;
    const QList<DiffEditor::Diff> diff = differ.diff(sourceData, formattedData);

    // Update changed lines and keep track of the cursor position
    QTextCursor cursor = textEditor->textCursor();
    int charactersInfrontOfCursor = cursor.position();
    int newCursorPos = charactersInfrontOfCursor;
    cursor.beginEditBlock();
    cursor.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor);
    const int diffSize = diff.size();
    for (int i = 0; i < diffSize; ++i) {
        const DiffEditor::Diff d = diff.at(i);
        switch (d.command) {
        case DiffEditor::Diff::Insert:
        {
            // Adjust cursor position if we do work in front of the cursor.
            if (charactersInfrontOfCursor > 0) {
                const int size = d.text.size();
                charactersInfrontOfCursor += size;
                newCursorPos += size;
            }
            // Adjust folded blocks, if a new block is added.
            if (d.text.contains(QLatin1Char('\n'))) {
                const int newLineCount = d.text.count(QLatin1Char('\n'));
                const int number = cursor.blockNumber();
                const int total = foldedBlocks.size();
                for (int i = 0; i < total; ++i) {
                    if (foldedBlocks.at(i) > number)
                        foldedBlocks[i] += newLineCount;
                }
            }
            cursor.insertText(d.text);
        }
            break;
        case DiffEditor::Diff::Delete:
        {
            // Adjust cursor position if we do work in front of the cursor.
            if (charactersInfrontOfCursor > 0) {
                const int size = d.text.size();
                charactersInfrontOfCursor -= size;
                newCursorPos -= size;
                // Cursor was inside the deleted text, so adjust the new cursor position
                if (charactersInfrontOfCursor < 0)
                    newCursorPos -= charactersInfrontOfCursor;
            }
            // Adjust folded blocks, if at least one block is being deleted.
            if (d.text.contains(QLatin1Char('\n'))) {
                const int newLineCount = d.text.count(QLatin1Char('\n'));
                const int number = cursor.blockNumber();
                for (int i = 0, total = foldedBlocks.size(); i < total; ++i) {
                    if (foldedBlocks.at(i) > number) {
                        foldedBlocks[i] -= newLineCount;
                        if (foldedBlocks[i] < number) {
                            foldedBlocks.removeAt(i);
                            --i;
                            --total;
                        }
                    }
                }
            }
            cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, d.text.size());
            cursor.removeSelectedText();
        }
            break;
        case DiffEditor::Diff::Equal:
            // Adjust cursor position
            charactersInfrontOfCursor -= d.text.size();
            cursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, d.text.size());
            break;
        }
    }
    cursor.endEditBlock();
    cursor.setPosition(newCursorPos);
    textEditor->setTextCursor(cursor);

    // Adjust vertical scrollbar
    absoluteVerticalCursorOffset = textEditor->cursorRect().y() - absoluteVerticalCursorOffset;
    const double fontHeight = QFontMetrics(textEditor->document()->defaultFont()).height();
    textEditor->verticalScrollBar()->setValue(textEditor->verticalScrollBar()->value()
                                              + absoluteVerticalCursorOffset / fontHeight);
    // Restore folded blocks
    const QTextDocument *doc = textEditor->document();
    const int total = foldedBlocks.size();
    for (int i = 0; i < total; ++i) {
        QTextBlock block = doc->findBlockByNumber(qMax(0, foldedBlocks.at(i)));
        if (block.isValid())
            TextEditor::BaseTextDocumentLayout::doFoldOrUnfold(block, false);
    }

    textEditor->document()->setModified(true);
}

void BeautifierPlugin::showError(const QString &error)
{
    Core::MessageManager::write(tr("Error in Beautifier: %1").arg(error.trimmed()));
}

QString BeautifierPlugin::msgCannotGetConfigurationFile(const QString &command)
{
    return tr("Cannot get configuration file for %1.").arg(command);
}

QString BeautifierPlugin::msgFormatCurrentFile()
{
    //: Menu entry
    return tr("Format Current File");
}

QString BeautifierPlugin::msgFormatSelectedText()
{
    //: Menu entry
    return tr("Format Selected Text");
}

QString BeautifierPlugin::msgCommandPromptDialogTitle(const QString &command)
{
    //: File dialog title for path chooser when choosing binary
    return tr("%1 Command").arg(command);
}

} // namespace Internal
} // namespace Beautifier

Q_EXPORT_PLUGIN(Beautifier::Internal::BeautifierPlugin)
<commit_msg>Beautifier: Remove duplicate include<commit_after>/**************************************************************************
**
** Copyright (c) 2014 Lorenz Haas
** Contact: http://www.qt-project.org/legal
**
** This file is part of Qt Creator.
**
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia.  For licensing terms and
** conditions see http://qt.digia.com/licensing.  For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** 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.
**
** In addition, as a special exception, Digia gives you certain additional
** rights.  These rights are described in the Digia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
****************************************************************************/

#include "beautifierplugin.h"

#include "beautifierconstants.h"
#include "command.h"

#include "artisticstyle/artisticstyle.h"
#include "clangformat/clangformat.h"
#include "uncrustify/uncrustify.h"

#include <coreplugin/actionmanager/actioncontainer.h>
#include <coreplugin/actionmanager/actionmanager.h>
#include <coreplugin/actionmanager/command.h>
#include <coreplugin/coreconstants.h>
#include <coreplugin/editormanager/editormanager.h>
#include <coreplugin/editormanager/ieditor.h>
#include <coreplugin/icontext.h>
#include <coreplugin/icore.h>
#include <coreplugin/messagemanager.h>
#include <diffeditor/differ.h>
#include <texteditor/basetextdocument.h>
#include <texteditor/basetextdocumentlayout.h>
#include <texteditor/basetexteditor.h>
#include <texteditor/texteditorconstants.h>
#include <utils/fileutils.h>

#include <QAction>
#include <QDir>
#include <QFileInfo>
#include <QPlainTextEdit>
#include <QProcess>
#include <QScrollBar>
#include <QTextBlock>
#include <QTimer>
#include <QtPlugin>

namespace Beautifier {
namespace Internal {

BeautifierPlugin::BeautifierPlugin()
{
}

BeautifierPlugin::~BeautifierPlugin()
{
}

bool BeautifierPlugin::initialize(const QStringList &arguments, QString *errorString)
{
    Q_UNUSED(arguments)
    Q_UNUSED(errorString)

    m_tools << new ArtisticStyle::ArtisticStyle(this);
    m_tools << new ClangFormat::ClangFormat(this);
    m_tools << new Uncrustify::Uncrustify(this);

    Core::ActionContainer *menu = Core::ActionManager::createMenu(Constants::MENU_ID);
    menu->menu()->setTitle(QLatin1String("Beautifier"));
    Core::ActionManager::actionContainer(Core::Constants::M_TOOLS)->addMenu(menu);

    for (int i = 0, total = m_tools.count(); i < total; ++i) {
        BeautifierAbstractTool *tool = m_tools.at(i);
        tool->initialize();
        const QList<QObject *> autoReleasedObjects = tool->autoReleaseObjects();
        for (int j = 0, total = autoReleasedObjects.count(); j < total; ++j)
            addAutoReleasedObject(autoReleasedObjects.at(j));
    }

    // The single shot is needed, otherwise the menu will stay disabled even
    // when the submenu's actions get enabled later on.
    QTimer::singleShot(0, this, SLOT(updateActions()));
    return true;
}

void BeautifierPlugin::extensionsInitialized()
{
    if (const Core::EditorManager *editorManager = Core::EditorManager::instance()) {
        connect(editorManager, SIGNAL(currentEditorChanged(Core::IEditor*)),
                this, SLOT(updateActions(Core::IEditor*)));
    }
}

ExtensionSystem::IPlugin::ShutdownFlag BeautifierPlugin::aboutToShutdown()
{
    return SynchronousShutdown;
}

void BeautifierPlugin::updateActions(Core::IEditor *editor)
{
    for (int i = 0, total = m_tools.count(); i < total; ++i)
        m_tools.at(i)->updateActions(editor);
}

QString BeautifierPlugin::format(const QString &text, const Command &command, const QString &fileName)
{
    const QString executable = command.executable();
    if (executable.isEmpty())
        return QString();

    switch (command.processing()) {
    case Command::FileProcessing: {
        // Save text to temporary file
        QFileInfo fi(fileName);
        Utils::TempFileSaver sourceFile(QDir::tempPath() + QLatin1String("/qtc_beautifier_XXXXXXXX.")
                                        + fi.suffix());
        sourceFile.setAutoRemove(true);
        sourceFile.write(text.toUtf8());
        if (!sourceFile.finalize()) {
            showError(tr("Cannot create temporary file \"%1\": %2.")
                      .arg(sourceFile.fileName()).arg(sourceFile.errorString()));
            return QString();
        }

        // Format temporary file
        QProcess process;
        QStringList options = command.options();
        options.replaceInStrings(QLatin1String("%file"), sourceFile.fileName());
        process.start(executable, options);
        if (!process.waitForFinished()) {
            showError(tr("Cannot call %1 or some other error occurred.").arg(executable));
            return QString();
        }
        const QByteArray output = process.readAllStandardError();
        if (!output.isEmpty())
            showError(executable + QLatin1String(": ") + QString::fromUtf8(output));

        // Read text back
        Utils::FileReader reader;
        if (!reader.fetch(sourceFile.fileName(), QIODevice::Text)) {
            showError(tr("Cannot read file \"%1\": %2.")
                      .arg(sourceFile.fileName()).arg(reader.errorString()));
            return QString();
        }
        return QString::fromUtf8(reader.data());
    } break;

    case Command::PipeProcessing: {
        QProcess process;
        QStringList options = command.options();
        options.replaceInStrings(QLatin1String("%file"), fileName);
        process.start(executable, options);
        if (!process.waitForStarted()) {
            showError(tr("Cannot call %1 or some other error occurred.").arg(executable));
            return QString();
        }
        process.write(text.toUtf8());
        process.closeWriteChannel();
        if (!process.waitForFinished()) {
            showError(tr("Cannot call %1 or some other error occurred.").arg(executable));
            return QString();
        }
        const QByteArray error = process.readAllStandardError();
        if (!error.isEmpty()) {
            showError(executable + QLatin1String(": ") + QString::fromUtf8(error));
            return QString();
        }

        if (command.pipeAddsNewline()) {
            QString formatted = QString::fromUtf8(process.readAllStandardOutput());
            formatted.remove(QRegExp(QLatin1String("(\\r\\n|\\n)$")));
            return formatted;
        }
        return QString::fromUtf8(process.readAllStandardOutput());
    }
    }

    return QString();
}

void BeautifierPlugin::formatCurrentFile(const Command &command)
{
    QPlainTextEdit *textEditor = 0;
    if (TextEditor::BaseTextEditor *editor
            = qobject_cast<TextEditor::BaseTextEditor *>(Core::EditorManager::currentEditor()))
        textEditor = qobject_cast<QPlainTextEdit *>(editor->editorWidget());
    if (!textEditor)
        return;

    const QString sourceData = textEditor->toPlainText();
    if (sourceData.isEmpty())
        return;

    const QString formattedData = format(sourceData, command,
                                         Core::EditorManager::currentDocument()->filePath());
    if ((sourceData == formattedData) || formattedData.isEmpty())
        return;

    // Since QTextCursor does not work properly with folded blocks, all blocks must be unfolded.
    // To restore the current state at the end, keep track of which block is folded.
    QList<int> foldedBlocks;
    QTextBlock block = textEditor->document()->firstBlock();
    while (block.isValid()) {
        if (const TextEditor::TextBlockUserData *userdata
                = static_cast<TextEditor::TextBlockUserData *>(block.userData())) {
            if (userdata->folded()) {
                foldedBlocks << block.blockNumber();
                TextEditor::BaseTextDocumentLayout::doFoldOrUnfold(block, true);
            }
        }
        block = block.next();
    }
    textEditor->update();

    // Save the current viewport position of the cursor to ensure the same vertical position after
    // the formatted text has set to the editor.
    int absoluteVerticalCursorOffset = textEditor->cursorRect().y();

    // Calculate diff
    DiffEditor::Differ differ;
    const QList<DiffEditor::Diff> diff = differ.diff(sourceData, formattedData);

    // Update changed lines and keep track of the cursor position
    QTextCursor cursor = textEditor->textCursor();
    int charactersInfrontOfCursor = cursor.position();
    int newCursorPos = charactersInfrontOfCursor;
    cursor.beginEditBlock();
    cursor.movePosition(QTextCursor::Start, QTextCursor::MoveAnchor);
    const int diffSize = diff.size();
    for (int i = 0; i < diffSize; ++i) {
        const DiffEditor::Diff d = diff.at(i);
        switch (d.command) {
        case DiffEditor::Diff::Insert:
        {
            // Adjust cursor position if we do work in front of the cursor.
            if (charactersInfrontOfCursor > 0) {
                const int size = d.text.size();
                charactersInfrontOfCursor += size;
                newCursorPos += size;
            }
            // Adjust folded blocks, if a new block is added.
            if (d.text.contains(QLatin1Char('\n'))) {
                const int newLineCount = d.text.count(QLatin1Char('\n'));
                const int number = cursor.blockNumber();
                const int total = foldedBlocks.size();
                for (int i = 0; i < total; ++i) {
                    if (foldedBlocks.at(i) > number)
                        foldedBlocks[i] += newLineCount;
                }
            }
            cursor.insertText(d.text);
        }
            break;
        case DiffEditor::Diff::Delete:
        {
            // Adjust cursor position if we do work in front of the cursor.
            if (charactersInfrontOfCursor > 0) {
                const int size = d.text.size();
                charactersInfrontOfCursor -= size;
                newCursorPos -= size;
                // Cursor was inside the deleted text, so adjust the new cursor position
                if (charactersInfrontOfCursor < 0)
                    newCursorPos -= charactersInfrontOfCursor;
            }
            // Adjust folded blocks, if at least one block is being deleted.
            if (d.text.contains(QLatin1Char('\n'))) {
                const int newLineCount = d.text.count(QLatin1Char('\n'));
                const int number = cursor.blockNumber();
                for (int i = 0, total = foldedBlocks.size(); i < total; ++i) {
                    if (foldedBlocks.at(i) > number) {
                        foldedBlocks[i] -= newLineCount;
                        if (foldedBlocks[i] < number) {
                            foldedBlocks.removeAt(i);
                            --i;
                            --total;
                        }
                    }
                }
            }
            cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, d.text.size());
            cursor.removeSelectedText();
        }
            break;
        case DiffEditor::Diff::Equal:
            // Adjust cursor position
            charactersInfrontOfCursor -= d.text.size();
            cursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, d.text.size());
            break;
        }
    }
    cursor.endEditBlock();
    cursor.setPosition(newCursorPos);
    textEditor->setTextCursor(cursor);

    // Adjust vertical scrollbar
    absoluteVerticalCursorOffset = textEditor->cursorRect().y() - absoluteVerticalCursorOffset;
    const double fontHeight = QFontMetrics(textEditor->document()->defaultFont()).height();
    textEditor->verticalScrollBar()->setValue(textEditor->verticalScrollBar()->value()
                                              + absoluteVerticalCursorOffset / fontHeight);
    // Restore folded blocks
    const QTextDocument *doc = textEditor->document();
    const int total = foldedBlocks.size();
    for (int i = 0; i < total; ++i) {
        QTextBlock block = doc->findBlockByNumber(qMax(0, foldedBlocks.at(i)));
        if (block.isValid())
            TextEditor::BaseTextDocumentLayout::doFoldOrUnfold(block, false);
    }

    textEditor->document()->setModified(true);
}

void BeautifierPlugin::showError(const QString &error)
{
    Core::MessageManager::write(tr("Error in Beautifier: %1").arg(error.trimmed()));
}

QString BeautifierPlugin::msgCannotGetConfigurationFile(const QString &command)
{
    return tr("Cannot get configuration file for %1.").arg(command);
}

QString BeautifierPlugin::msgFormatCurrentFile()
{
    //: Menu entry
    return tr("Format Current File");
}

QString BeautifierPlugin::msgFormatSelectedText()
{
    //: Menu entry
    return tr("Format Selected Text");
}

QString BeautifierPlugin::msgCommandPromptDialogTitle(const QString &command)
{
    //: File dialog title for path chooser when choosing binary
    return tr("%1 Command").arg(command);
}

} // namespace Internal
} // namespace Beautifier

Q_EXPORT_PLUGIN(Beautifier::Internal::BeautifierPlugin)
<|endoftext|>


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

#include "mappers/logging_wrapper.h"

#include "realm/logging.h"
#include "mappers/mapping_utilities.h"

using namespace Legion::Mapping::Utilities;

Realm::Logger log_maplog("mapper");

namespace Legion {
namespace Mapping {

class MessageBuffer {
 public:
  MessageBuffer(MapperRuntime* _runtime, const MapperContext _ctx)
      : runtime(_runtime), ctx(_ctx) {
    // Do nothing;
  }
  ~MessageBuffer() {
    for (std::vector<std::stringstream*>::iterator it = lines.begin();
         it != lines.end(); ++it) {
      log_maplog.info() << (*it)->str();
      delete(*it);
    }
  }
 public:
  std::stringstream& line() {
    lines.push_back(new std::stringstream());
    return *(lines.back());
  }
  void report(const RegionRequirement& req,
              const std::vector<PhysicalInstance>& instances,
              unsigned req_idx) {
    line() << "    " << to_string(runtime, ctx, req, req_idx);
    for (std::vector<PhysicalInstance>::const_iterator it = instances.begin();
         it != instances.end(); ++it) {
      line() << "      " << to_string(runtime, ctx, *it);
    }
  }
  void report(const std::vector<RegionRequirement>& reqs,
              const std::vector<std::vector<PhysicalInstance> >& instances) {
    for (size_t idx = 0; idx < reqs.size(); ++idx) {
      report(reqs[idx], instances[idx], idx);
    }
  }
  void report(const Task& task, const Mapper::MapTaskOutput& output) {
    std::stringstream& ss = line();
    ss << "  TARGET PROCS:";
    for (std::vector<Processor>::const_iterator it =
           output.target_procs.begin(); it != output.target_procs.end(); ++it) {
      ss << " " << *it;
    }
    const char *variant =
      runtime->find_task_variant_name(ctx, task.task_id, output.chosen_variant);
    line() << "  CHOSEN VARIANT: " << variant;
    line() << "  OUTPUT INSTANCES:";
    report(task.regions, output.chosen_instances);
  }
 private:
  MapperRuntime* const runtime;
  const MapperContext ctx;
  std::vector<std::stringstream*> lines;
};

LoggingWrapper::LoggingWrapper(Mapper* mapper)
    : ForwardingMapper(mapper) {
  MessageBuffer buf(runtime, NULL);
  Machine machine = Machine::get_machine();
  AddressSpace rank = Processor::get_executing_processor().address_space();
  buf.line() << "Memories on rank " << rank << ":";
  Machine::MemoryQuery mem_query(machine);
  mem_query.local_address_space();
  for (Machine::MemoryQuery::iterator it = mem_query.begin();
       it != mem_query.end(); ++it) {
    buf.line() << "  " << *it << " (" << to_string(it->kind()) << ")";
  }
  buf.line() << "Processors on rank " << rank << ":";
  Machine::ProcessorQuery proc_query(machine);
  proc_query.local_address_space();
  for (Machine::ProcessorQuery::iterator pit = proc_query.begin();
       pit != proc_query.end(); ++pit) {
    std::stringstream& line = buf.line();
    line << "  " << *pit << " (" << to_string(pit->kind()) << ") can see";
    Machine::MemoryQuery mem_query(Machine::get_machine());
    mem_query.has_affinity_to(*pit);
    for (Machine::MemoryQuery::iterator mit = mem_query.begin();
         mit != mem_query.end(); ++mit) {
      Machine::AffinityDetails details;
      machine.has_affinity(*pit, *mit, &details);
      line << " " << *mit << "(bw=" << details.bandwidth << ")";
    }
  }
}

LoggingWrapper::~LoggingWrapper() {
  // Do nothing.
}

#ifndef NO_LEGION_CONTROL_REPLICATION
void LoggingWrapper::map_replicate_task(const MapperContext ctx,
                                        const Task& task,
                                        const MapTaskInput& input,
                                        const MapTaskOutput& default_output,
                                        MapReplicateTaskOutput& output) {
  MessageBuffer buf(runtime, ctx);
  buf.line() << "MAP_REPLICATE_TASK for " << to_string(runtime, ctx, task);
  buf.line() << "  INPUT:";
  buf.report(task.regions, input.valid_instances);
  mapper->map_replicate_task(ctx, task, input, default_output, output);
  buf.line() << "  OUTPUT:";
  for (unsigned i = 0; i < output.task_mappings.size(); ++i) {
    std::stringstream& ss = buf.line();
    ss << "  REPLICANT " << i;
    if (!output.control_replication_map.empty()) {
      ss << " -> " << output.control_replication_map[i];
    }
    buf.report(task, output.task_mappings[i]);
  }
}
#endif // NO_LEGION_CONTROL_REPLICATION

void LoggingWrapper::slice_task(const MapperContext ctx,
                                const Task& task,
                                const SliceTaskInput& input,
                                SliceTaskOutput& output) {
  MessageBuffer buf(runtime, ctx);
  buf.line() << "SLICE_TASK for " << to_string(runtime, ctx, task);
  buf.line() << "  INPUT: " << to_string(runtime, ctx, input.domain);
  mapper->slice_task(ctx, task, input, output);
  buf.line() << "  OUTPUT:";
  for (std::vector<TaskSlice>::const_iterator it = output.slices.begin();
       it != output.slices.end(); ++it) {
    buf.line() << "    " << to_string(runtime, ctx, it->domain)
               << " -> " << it->proc;
  }
}

void LoggingWrapper::map_task(const MapperContext ctx,
                              const Task& task,
                              const MapTaskInput& input,
                              MapTaskOutput& output) {
  MessageBuffer buf(runtime, ctx);
  buf.line() << "MAP_TASK for " << to_string(runtime, ctx, task);
  buf.line() << "  INPUT:";
  buf.report(task.regions, input.valid_instances);
  mapper->map_task(ctx, task, input, output);
  buf.report(task, output);
}

void LoggingWrapper::select_task_sources(const MapperContext ctx,
                                         const Task& task,
                                         const SelectTaskSrcInput& input,
                                         SelectTaskSrcOutput& output) {
  MessageBuffer buf(runtime, ctx);
  buf.line() << "SELECT_TASK_SOURCES for " << to_string(runtime, ctx, task);
  buf.line() << "  INPUT:";
  buf.report(task.regions[input.region_req_index],
             input.source_instances,
             input.region_req_index);
  buf.line() << "  TARGET:";
  buf.line() << "      " << to_string(runtime, ctx, input.target);
  mapper->select_task_sources(ctx, task, input, output);
  buf.line() << "  OUTPUT:";
  for (std::deque<PhysicalInstance>::iterator it =
         output.chosen_ranking.begin();
       it != output.chosen_ranking.end(); ++it) {
    buf.line() << "      " << to_string(runtime, ctx, *it);
  }
}

void LoggingWrapper::map_inline(const MapperContext ctx,
                                const InlineMapping& inline_op,
                                const MapInlineInput& input,
                                MapInlineOutput& output) {
  MessageBuffer buf(runtime, ctx);
  buf.line() << "MAP_INLINE in "
             << to_string(runtime, ctx, *(inline_op.parent_task));
  buf.line() << "  INPUT:";
  buf.report(inline_op.requirement, input.valid_instances, 0);
  mapper->map_inline(ctx, inline_op, input, output);
  buf.line() << "  OUTPUT:";
  buf.report(inline_op.requirement, output.chosen_instances, 0);
}

void LoggingWrapper::select_inline_sources(const MapperContext ctx,
                                           const InlineMapping& inline_op,
                                           const SelectInlineSrcInput& input,
                                           SelectInlineSrcOutput& output) {
  MessageBuffer buf(runtime, ctx);
  buf.line() << "SELECT_INLINE_SOURCES in "
             << to_string(runtime, ctx, *(inline_op.parent_task));
  buf.line() << "  INPUT:";
  buf.report(inline_op.requirement, input.source_instances, 0);
  buf.line() << "  TARGET:";
  buf.line() << "      " << to_string(runtime, ctx, input.target);
  mapper->select_inline_sources(ctx, inline_op, input, output);
  buf.line() << "  OUTPUT:";
  for (std::deque<PhysicalInstance>::iterator it =
         output.chosen_ranking.begin();
       it != output.chosen_ranking.end(); ++it) {
    buf.line() << "      " << to_string(runtime, ctx, *it);
  }
}

}; // namespace Mapping
}; // namespace Legion
<commit_msg>mappers: don't crash if parent_task is NULL<commit_after>/* Copyright 2020 Stanford University, NVIDIA Corporation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "mappers/logging_wrapper.h"

#include "realm/logging.h"
#include "mappers/mapping_utilities.h"

using namespace Legion::Mapping::Utilities;

Realm::Logger log_maplog("mapper");

namespace Legion {
namespace Mapping {

class MessageBuffer {
 public:
  MessageBuffer(MapperRuntime* _runtime, const MapperContext _ctx)
      : runtime(_runtime), ctx(_ctx) {
    // Do nothing;
  }
  ~MessageBuffer() {
    for (std::vector<std::stringstream*>::iterator it = lines.begin();
         it != lines.end(); ++it) {
      log_maplog.info() << (*it)->str();
      delete(*it);
    }
  }
 public:
  std::stringstream& line() {
    lines.push_back(new std::stringstream());
    return *(lines.back());
  }
  void report(const RegionRequirement& req,
              const std::vector<PhysicalInstance>& instances,
              unsigned req_idx) {
    line() << "    " << to_string(runtime, ctx, req, req_idx);
    for (std::vector<PhysicalInstance>::const_iterator it = instances.begin();
         it != instances.end(); ++it) {
      line() << "      " << to_string(runtime, ctx, *it);
    }
  }
  void report(const std::vector<RegionRequirement>& reqs,
              const std::vector<std::vector<PhysicalInstance> >& instances) {
    for (size_t idx = 0; idx < reqs.size(); ++idx) {
      report(reqs[idx], instances[idx], idx);
    }
  }
  void report(const Task& task, const Mapper::MapTaskOutput& output) {
    std::stringstream& ss = line();
    ss << "  TARGET PROCS:";
    for (std::vector<Processor>::const_iterator it =
           output.target_procs.begin(); it != output.target_procs.end(); ++it) {
      ss << " " << *it;
    }
    const char *variant =
      runtime->find_task_variant_name(ctx, task.task_id, output.chosen_variant);
    line() << "  CHOSEN VARIANT: " << variant;
    line() << "  OUTPUT INSTANCES:";
    report(task.regions, output.chosen_instances);
  }
 private:
  MapperRuntime* const runtime;
  const MapperContext ctx;
  std::vector<std::stringstream*> lines;
};

LoggingWrapper::LoggingWrapper(Mapper* mapper)
    : ForwardingMapper(mapper) {
  MessageBuffer buf(runtime, NULL);
  Machine machine = Machine::get_machine();
  AddressSpace rank = Processor::get_executing_processor().address_space();
  buf.line() << "Memories on rank " << rank << ":";
  Machine::MemoryQuery mem_query(machine);
  mem_query.local_address_space();
  for (Machine::MemoryQuery::iterator it = mem_query.begin();
       it != mem_query.end(); ++it) {
    buf.line() << "  " << *it << " (" << to_string(it->kind()) << ")";
  }
  buf.line() << "Processors on rank " << rank << ":";
  Machine::ProcessorQuery proc_query(machine);
  proc_query.local_address_space();
  for (Machine::ProcessorQuery::iterator pit = proc_query.begin();
       pit != proc_query.end(); ++pit) {
    std::stringstream& line = buf.line();
    line << "  " << *pit << " (" << to_string(pit->kind()) << ") can see";
    Machine::MemoryQuery mem_query(Machine::get_machine());
    mem_query.has_affinity_to(*pit);
    for (Machine::MemoryQuery::iterator mit = mem_query.begin();
         mit != mem_query.end(); ++mit) {
      Machine::AffinityDetails details;
      machine.has_affinity(*pit, *mit, &details);
      line << " " << *mit << "(bw=" << details.bandwidth << ")";
    }
  }
}

LoggingWrapper::~LoggingWrapper() {
  // Do nothing.
}

#ifndef NO_LEGION_CONTROL_REPLICATION
void LoggingWrapper::map_replicate_task(const MapperContext ctx,
                                        const Task& task,
                                        const MapTaskInput& input,
                                        const MapTaskOutput& default_output,
                                        MapReplicateTaskOutput& output) {
  MessageBuffer buf(runtime, ctx);
  buf.line() << "MAP_REPLICATE_TASK for " << to_string(runtime, ctx, task);
  buf.line() << "  INPUT:";
  buf.report(task.regions, input.valid_instances);
  mapper->map_replicate_task(ctx, task, input, default_output, output);
  buf.line() << "  OUTPUT:";
  for (unsigned i = 0; i < output.task_mappings.size(); ++i) {
    std::stringstream& ss = buf.line();
    ss << "  REPLICANT " << i;
    if (!output.control_replication_map.empty()) {
      ss << " -> " << output.control_replication_map[i];
    }
    buf.report(task, output.task_mappings[i]);
  }
}
#endif // NO_LEGION_CONTROL_REPLICATION

void LoggingWrapper::slice_task(const MapperContext ctx,
                                const Task& task,
                                const SliceTaskInput& input,
                                SliceTaskOutput& output) {
  MessageBuffer buf(runtime, ctx);
  buf.line() << "SLICE_TASK for " << to_string(runtime, ctx, task);
  buf.line() << "  INPUT: " << to_string(runtime, ctx, input.domain);
  mapper->slice_task(ctx, task, input, output);
  buf.line() << "  OUTPUT:";
  for (std::vector<TaskSlice>::const_iterator it = output.slices.begin();
       it != output.slices.end(); ++it) {
    buf.line() << "    " << to_string(runtime, ctx, it->domain)
               << " -> " << it->proc;
  }
}

void LoggingWrapper::map_task(const MapperContext ctx,
                              const Task& task,
                              const MapTaskInput& input,
                              MapTaskOutput& output) {
  MessageBuffer buf(runtime, ctx);
  buf.line() << "MAP_TASK for " << to_string(runtime, ctx, task);
  buf.line() << "  INPUT:";
  buf.report(task.regions, input.valid_instances);
  mapper->map_task(ctx, task, input, output);
  buf.report(task, output);
}

void LoggingWrapper::select_task_sources(const MapperContext ctx,
                                         const Task& task,
                                         const SelectTaskSrcInput& input,
                                         SelectTaskSrcOutput& output) {
  MessageBuffer buf(runtime, ctx);
  buf.line() << "SELECT_TASK_SOURCES for " << to_string(runtime, ctx, task);
  buf.line() << "  INPUT:";
  buf.report(task.regions[input.region_req_index],
             input.source_instances,
             input.region_req_index);
  buf.line() << "  TARGET:";
  buf.line() << "      " << to_string(runtime, ctx, input.target);
  mapper->select_task_sources(ctx, task, input, output);
  buf.line() << "  OUTPUT:";
  for (std::deque<PhysicalInstance>::iterator it =
         output.chosen_ranking.begin();
       it != output.chosen_ranking.end(); ++it) {
    buf.line() << "      " << to_string(runtime, ctx, *it);
  }
}

void LoggingWrapper::map_inline(const MapperContext ctx,
                                const InlineMapping& inline_op,
                                const MapInlineInput& input,
                                MapInlineOutput& output) {
  MessageBuffer buf(runtime, ctx);
  buf.line() << "MAP_INLINE in "
             << (inline_op.parent_task == NULL ? "(remote task)" :
                 to_string(runtime, ctx, *(inline_op.parent_task)));
  buf.line() << "  INPUT:";
  buf.report(inline_op.requirement, input.valid_instances, 0);
  mapper->map_inline(ctx, inline_op, input, output);
  buf.line() << "  OUTPUT:";
  buf.report(inline_op.requirement, output.chosen_instances, 0);
}

void LoggingWrapper::select_inline_sources(const MapperContext ctx,
                                           const InlineMapping& inline_op,
                                           const SelectInlineSrcInput& input,
                                           SelectInlineSrcOutput& output) {
  MessageBuffer buf(runtime, ctx);
  buf.line() << "SELECT_INLINE_SOURCES in "
             << (inline_op.parent_task == NULL ? "(remote task)" :
                 to_string(runtime, ctx, *(inline_op.parent_task)));
  buf.line() << "  INPUT:";
  buf.report(inline_op.requirement, input.source_instances, 0);
  buf.line() << "  TARGET:";
  buf.line() << "      " << to_string(runtime, ctx, input.target);
  mapper->select_inline_sources(ctx, inline_op, input, output);
  buf.line() << "  OUTPUT:";
  for (std::deque<PhysicalInstance>::iterator it =
         output.chosen_ranking.begin();
       it != output.chosen_ranking.end(); ++it) {
    buf.line() << "      " << to_string(runtime, ctx, *it);
  }
}

}; // namespace Mapping
}; // namespace Legion
<|endoftext|>


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

// per-dimension instantiator for image.cc

#define REALM_TEMPLATES_ONLY
#include "./image.cc"

#ifndef INST_N1
  #error INST_N1 must be defined!
#endif
#ifndef INST_N2
  #error INST_N2 must be defined!
#endif

#define FOREACH_TT(__func__) \
  __func__(int,int) \
  __func__(int,unsigned) \
  __func__(int,long long) \
  __func__(unsigned,int) \
  __func__(unsigned,unsigned) \
  __func__(unsigned,long long) \
  __func__(long long,int) \
  __func__(long long,unsigned) \
  __func__(long long,long long)

namespace Realm {

#define N1 INST_N1
#define N2 INST_N2

#define DOIT(T1,T2)			                                  \
  template class StructuredImageMicroOp<N1,T1,N2,T2>;     \
  template class ImageMicroOp<N1,T1,N2,T2>;               \
  template class ImageOperation<N1,T1,N2,T2>;             \
  template ImageMicroOp<N1,T1,N2,T2>::ImageMicroOp(NodeID, AsyncMicroOp *, Serialization::FixedBufferDeserializer&); \
  template Event IndexSpace<N1, T1>::create_subspaces_by_image(               \
      const DomainTransform<N1, T1, N2, T2> &, const std::vector<IndexSpace<N2, T2> > &,            \
      std::vector<IndexSpace<N1, T1> > &, const ProfilingRequestSet &, Event) \
      const; \
  template Event IndexSpace<N1,T1>::create_subspaces_by_image_with_difference( \
      const DomainTransform<N1, T1, N2, T2> &, \
									       const std::vector<IndexSpace<N2,T2> >&,	\
									       const std::vector<IndexSpace<N1,T1> >&,	\
									       std::vector<IndexSpace<N1,T1> >&, \
									       const ProfilingRequestSet&, \
									       Event) const;

  FOREACH_TT(DOIT)

  };  // namespace Realm
<commit_msg>Refactor image_tmpl.cc<commit_after>/* Copyright 2022 Stanford University, NVIDIA Corporation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// per-dimension instantiator for image.cc

#define REALM_TEMPLATES_ONLY
#include "./image.cc"

#ifndef INST_N1
  #error INST_N1 must be defined!
#endif
#ifndef INST_N2
  #error INST_N2 must be defined!
#endif

#define FOREACH_TT(__func__) \
  __func__(int,int) \
  __func__(int,unsigned) \
  __func__(int,long long) \
  __func__(unsigned,int) \
  __func__(unsigned,unsigned) \
  __func__(unsigned,long long) \
  __func__(long long,int) \
  __func__(long long,unsigned) \
  __func__(long long,long long)

namespace Realm {

#define N1 INST_N1
#define N2 INST_N2

#define DOIT(T1,T2)			                                                                             \
  template class StructuredImageMicroOp<N1,T1,N2,T2>;                                                                \
  template class ImageMicroOp<N1,T1,N2,T2>;                                                                          \
  template class ImageOperation<N1,T1,N2,T2>;                                                                        \
  template ImageMicroOp<N1,T1,N2,T2>::ImageMicroOp(NodeID, AsyncMicroOp *, Serialization::FixedBufferDeserializer&); \
  template Event IndexSpace<N1, T1>::create_subspaces_by_image(                                                      \
      const DomainTransform<N1, T1, N2, T2> &, const std::vector<IndexSpace<N2, T2> > &,                             \
      std::vector<IndexSpace<N1, T1> > &, const ProfilingRequestSet &, Event)                                        \
      const;                                                                                \
  template Event IndexSpace<N1,T1>::create_subspaces_by_image_with_difference(                                       \
      const DomainTransform<N1, T1, N2, T2> &,                                                                       \
									       const std::vector<IndexSpace<N2,T2> >&,                                                     \
									       const std::vector<IndexSpace<N1,T1> >&,                                                     \
									       std::vector<IndexSpace<N1,T1> >&,                                                           \
									       const ProfilingRequestSet&,                                                                 \
									       Event) const;

  FOREACH_TT(DOIT)

  };  // namespace Realm
<|endoftext|>


<commit_before>//=======================================================================
// Copyright (c) 2014 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#ifndef MNIST_READER_HPP
#define MNIST_READER_HPP

#include <fstream>
#include <iostream>
#include <vector>
#include <cstdint>
#include <memory>

namespace mnist {

template<typename Pixel = uint8_t, typename Label = uint8_t>
struct MNIST_dataset {
    std::vector<std::vector<Pixel>> training_images;
    std::vector<std::vector<Pixel>> test_images;
    std::vector<Label> training_labels;
    std::vector<Label> test_labels;
};

inline uint32_t read_header(const std::unique_ptr<char[]>& buffer, size_t position){
    auto header = reinterpret_cast<uint32_t*>(buffer.get());

    auto value = *(header + position);
    return (value << 24) | ((value << 8) & 0x00FF0000) | ((value >> 8) & 0X0000FF00) | (value >> 24);
}

template<typename Pixel = uint8_t, typename Label = uint8_t>
std::vector<std::vector<Pixel>> read_mnist_image_file(const std::string& path){
    std::ifstream file;
    file.open(path, std::ios::in | std::ios::binary | std::ios::ate);

    if(!file){
        std::cout << "Error opening file" << std::endl;
    } else {
        auto size = file.tellg();
        std::unique_ptr<char[]> buffer(new char[size]);

        //Read the entire file at once
        file.seekg(0, std::ios::beg);
        file.read(buffer.get(), size);
        file.close();

        auto magic = read_header(buffer, 0);

        if(magic != 0x803){
            std::cout << "Invalid magic number, probably not a MNIST file" << std::endl;
        } else {
            auto count = read_header(buffer, 1);
            auto rows = read_header(buffer, 2);
            auto columns = read_header(buffer, 3);

            if(size < count * rows * columns + 16){
                std::cout << "The file is not large enough to hold all the data, probably corrupted" << std::endl;
            } else {
                //Skip the header
                //Cast to unsigned char is necessary cause signedness of char is
                //platform-specific
                auto image_buffer = reinterpret_cast<unsigned char*>(buffer.get() + 16);

                std::vector<std::vector<Pixel>> images;
                images.reserve(count);

                for(size_t i = 0; i < count; ++i){
                    images.emplace_back(rows * columns);

                    for(size_t j = 0; j < rows * columns; ++j){
                        auto pixel = *image_buffer++;
                        images[i][j] = static_cast<Pixel>(pixel);
                    }
                }

                return std::move(images);
            }
        }
    }

    return {};
}

template<typename Label = uint8_t>
std::vector<Label> read_mnist_label_file(const std::string& path){
    std::ifstream file;
    file.open(path, std::ios::in | std::ios::binary | std::ios::ate);

    if(!file){
        std::cout << "Error opening file" << std::endl;
    } else {
        auto size = file.tellg();
        std::unique_ptr<char[]> buffer(new char[size]);

        //Read the entire file at once
        file.seekg(0, std::ios::beg);
        file.read(buffer.get(), size);
        file.close();

        auto magic = read_header(buffer, 0);

        if(magic != 0x801){
            std::cout << "Invalid magic number, probably not a MNIST file" << std::endl;
        } else {
            auto count = read_header(buffer, 1);

            if(size < count + 8){
                std::cout << "The file is not large enough to hold all the data, probably corrupted" << std::endl;
            } else {
                //Skip the header
                //Cast to unsigned char is necessary cause signedness of char is
                //platform-specific
                auto label_buffer = reinterpret_cast<unsigned char*>(buffer.get() + 8);

                std::vector<Label> labels(count);

                for(size_t i = 0; i < count; ++i){
                    auto label = *label_buffer++;
                    labels[i] = static_cast<Label>(label);
                }

                return std::move(labels);
            }
        }
    }

    return {};
}

template<typename Pixel = uint8_t, typename Label = uint8_t>
std::vector<std::vector<Pixel>> read_training_images(){
    return read_mnist_image_file<std::vector,std::vector,Pixel>("mnist/train-images-idx3-ubyte");
}

template<typename Pixel = uint8_t, typename Label = uint8_t>
std::vector<std::vector<Pixel>> read_test_images(){
    return read_mnist_image_file<std::vector,std::vector,Pixel>("mnist/t10k-images-idx3-ubyte");
}

template<typename Label = uint8_t>
std::vector<Label> read_training_labels(){
    return read_mnist_label_file<std::vector>("mnist/train-labels-idx1-ubyte");
}

template<typename Label = uint8_t>
std::vector<Label> read_test_labels(){
    return read_mnist_label_file<std::vector>("mnist/t10k-labels-idx1-ubyte");
}

template<typename Pixel = uint8_t, typename Label = uint8_t>
MNIST_dataset<Pixel, Label> read_dataset(){
    MNIST_dataset<Pixel, Label> dataset;

    dataset.training_images = read_training_images<Pixel>();
    dataset.training_labels = read_training_labels<Label>();

    dataset.test_images = read_test_images<Pixel>();
    dataset.test_labels = read_test_labels<Label>();

    return std::move(dataset);
}

} //end of namespace mnist

#endif
<commit_msg>Do not hinder RVO<commit_after>//=======================================================================
// Copyright (c) 2014 Baptiste Wicht
// Distributed under the terms of the MIT License.
// (See accompanying file LICENSE or copy at
//  http://opensource.org/licenses/MIT)
//=======================================================================

#ifndef MNIST_READER_HPP
#define MNIST_READER_HPP

#include <fstream>
#include <iostream>
#include <vector>
#include <cstdint>
#include <memory>

namespace mnist {

template<typename Pixel = uint8_t, typename Label = uint8_t>
struct MNIST_dataset {
    std::vector<std::vector<Pixel>> training_images;
    std::vector<std::vector<Pixel>> test_images;
    std::vector<Label> training_labels;
    std::vector<Label> test_labels;
};

inline uint32_t read_header(const std::unique_ptr<char[]>& buffer, size_t position){
    auto header = reinterpret_cast<uint32_t*>(buffer.get());

    auto value = *(header + position);
    return (value << 24) | ((value << 8) & 0x00FF0000) | ((value >> 8) & 0X0000FF00) | (value >> 24);
}

template<typename Pixel = uint8_t, typename Label = uint8_t>
std::vector<std::vector<Pixel>> read_mnist_image_file(const std::string& path){
    std::ifstream file;
    file.open(path, std::ios::in | std::ios::binary | std::ios::ate);

    if(!file){
        std::cout << "Error opening file" << std::endl;
    } else {
        auto size = file.tellg();
        std::unique_ptr<char[]> buffer(new char[size]);

        //Read the entire file at once
        file.seekg(0, std::ios::beg);
        file.read(buffer.get(), size);
        file.close();

        auto magic = read_header(buffer, 0);

        if(magic != 0x803){
            std::cout << "Invalid magic number, probably not a MNIST file" << std::endl;
        } else {
            auto count = read_header(buffer, 1);
            auto rows = read_header(buffer, 2);
            auto columns = read_header(buffer, 3);

            if(size < count * rows * columns + 16){
                std::cout << "The file is not large enough to hold all the data, probably corrupted" << std::endl;
            } else {
                //Skip the header
                //Cast to unsigned char is necessary cause signedness of char is
                //platform-specific
                auto image_buffer = reinterpret_cast<unsigned char*>(buffer.get() + 16);

                std::vector<std::vector<Pixel>> images;
                images.reserve(count);

                for(size_t i = 0; i < count; ++i){
                    images.emplace_back(rows * columns);

                    for(size_t j = 0; j < rows * columns; ++j){
                        auto pixel = *image_buffer++;
                        images[i][j] = static_cast<Pixel>(pixel);
                    }
                }

                return images;
            }
        }
    }

    return {};
}

template<typename Label = uint8_t>
std::vector<Label> read_mnist_label_file(const std::string& path){
    std::ifstream file;
    file.open(path, std::ios::in | std::ios::binary | std::ios::ate);

    if(!file){
        std::cout << "Error opening file" << std::endl;
    } else {
        auto size = file.tellg();
        std::unique_ptr<char[]> buffer(new char[size]);

        //Read the entire file at once
        file.seekg(0, std::ios::beg);
        file.read(buffer.get(), size);
        file.close();

        auto magic = read_header(buffer, 0);

        if(magic != 0x801){
            std::cout << "Invalid magic number, probably not a MNIST file" << std::endl;
        } else {
            auto count = read_header(buffer, 1);

            if(size < count + 8){
                std::cout << "The file is not large enough to hold all the data, probably corrupted" << std::endl;
            } else {
                //Skip the header
                //Cast to unsigned char is necessary cause signedness of char is
                //platform-specific
                auto label_buffer = reinterpret_cast<unsigned char*>(buffer.get() + 8);

                std::vector<Label> labels(count);

                for(size_t i = 0; i < count; ++i){
                    auto label = *label_buffer++;
                    labels[i] = static_cast<Label>(label);
                }

                return labels;
            }
        }
    }

    return {};
}

template<typename Pixel = uint8_t, typename Label = uint8_t>
std::vector<std::vector<Pixel>> read_training_images(){
    return read_mnist_image_file<std::vector,std::vector,Pixel>("mnist/train-images-idx3-ubyte");
}

template<typename Pixel = uint8_t, typename Label = uint8_t>
std::vector<std::vector<Pixel>> read_test_images(){
    return read_mnist_image_file<std::vector,std::vector,Pixel>("mnist/t10k-images-idx3-ubyte");
}

template<typename Label = uint8_t>
std::vector<Label> read_training_labels(){
    return read_mnist_label_file<std::vector>("mnist/train-labels-idx1-ubyte");
}

template<typename Label = uint8_t>
std::vector<Label> read_test_labels(){
    return read_mnist_label_file<std::vector>("mnist/t10k-labels-idx1-ubyte");
}

template<typename Pixel = uint8_t, typename Label = uint8_t>
MNIST_dataset<Pixel, Label> read_dataset(){
    MNIST_dataset<Pixel, Label> dataset;

    dataset.training_images = read_training_images<Pixel>();
    dataset.training_labels = read_training_labels<Label>();

    dataset.test_images = read_test_images<Pixel>();
    dataset.test_labels = read_test_labels<Label>();

    return dataset;
}

} //end of namespace mnist

#endif
<|endoftext|>


<commit_before>/**
 * The Seeks proxy and plugin framework are part of the SEEKS project.
 * Copyright (C) 2009 Emmanuel Benazera, juban@free.fr
 *
 * 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 "query_interceptor.h"
#include "websearch.h"
#include "cgi.h"
#include "miscutil.h"
#include "errlog.h"
#include "encode.h"

#include <iostream>

namespace seeks_plugins
{
   std::string query_interceptor::_p_filename = "websearch/patterns/qi_patterns";

   query_interceptor::query_interceptor(plugin *parent)
     :interceptor_plugin((seeks_proxy::_datadir.empty() ? std::string(plugin_manager::_plugin_repository
								      + query_interceptor::_p_filename).c_str()
			  : std::string(seeks_proxy::_datadir + "/plugins/" + query_interceptor::_p_filename).c_str()),parent)
       {
       }

   http_response* query_interceptor::plugin_response(client_state *csp)
     {
	// - parse intercepted query.

	std::cerr << "url: " << csp->_http._url << std::endl;

	hash_map<const char*,const char*,hash<const char*>,eqstr> *params
	  = parse_query(&csp->_http);

	if (!params)
	  {
	     errlog::log_error(LOG_LEVEL_ERROR, "No parameters to intercepted query: %s%s",
			       csp->_http._host, csp->_http._path);
	     return cgi::cgi_error_memory(); // ok, this is not a memory error, but this does the job for now.
	  }

	// debug
	/* std::cerr << "params size: " << params->size() << std::endl;
	hash_map<const char*, const char*, hash<const char*>, eqstr>::const_iterator hit
	  = params->begin();
	while(hit!=params->end())
	  {
	     std::cerr << (*hit).first << " --> " << (*hit).second << std::endl;
	     ++hit;
	  } */
	// debug

	// - send it to the generic search interface.
	http_response *rsp;
	if (NULL == (rsp = new http_response()))
	  {
	     return cgi::cgi_error_memory();
	  }

	// - return the response to the client.
	// default query detection.
	const char *intercepted_query = miscutil::lookup(params,"q");
	char *intercepted_query_enc = encode::url_encode(intercepted_query);

	if (!intercepted_query)
	  {
	     return NULL; // wrong interception, cancel.
	  }

	// build up query to seeks proxy.
	char *q = strdup(CGI_PREFIX);
	miscutil::string_append(&q,"search?q=");
	miscutil::string_append(&q,intercepted_query_enc);
	free(intercepted_query_enc);
	miscutil::string_append(&q,"&page=1");
	miscutil::string_append(&q,"&expansion=1");
	miscutil::string_append(&q,"&action=expand");
	cgi::cgi_redirect(rsp,q);

	return cgi::finish_http_response(csp,rsp);
     }

   hash_map<const char*,const char*,hash<const char*>,eqstr>* query_interceptor::parse_query(http_request *http) const
     {
	if (http->_path)
	  {
	     hash_map<const char*,const char*,hash<const char*>,eqstr> *search_params
	       = cgi::parse_cgi_parameters(http->_path);
	     return search_params;
	  }
	else return NULL;
     }

} /* end of namespace. */
<commit_msg>removed debug from websearch query interceptor<commit_after>/**
 * The Seeks proxy and plugin framework are part of the SEEKS project.
 * Copyright (C) 2009 Emmanuel Benazera, juban@free.fr
 *
 * 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 "query_interceptor.h"
#include "websearch.h"
#include "cgi.h"
#include "miscutil.h"
#include "errlog.h"
#include "encode.h"

#include <iostream>

namespace seeks_plugins
{
   std::string query_interceptor::_p_filename = "websearch/patterns/qi_patterns";

   query_interceptor::query_interceptor(plugin *parent)
     :interceptor_plugin((seeks_proxy::_datadir.empty() ? std::string(plugin_manager::_plugin_repository
								      + query_interceptor::_p_filename).c_str()
			  : std::string(seeks_proxy::_datadir + "/plugins/" + query_interceptor::_p_filename).c_str()),parent)
       {
       }

   http_response* query_interceptor::plugin_response(client_state *csp)
     {
	// - parse intercepted query.

	//std::cerr << "url: " << csp->_http._url << std::endl;

	hash_map<const char*,const char*,hash<const char*>,eqstr> *params
	  = parse_query(&csp->_http);

	if (!params)
	  {
	     errlog::log_error(LOG_LEVEL_ERROR, "No parameters to intercepted query: %s%s",
			       csp->_http._host, csp->_http._path);
	     return cgi::cgi_error_memory(); // ok, this is not a memory error, but this does the job for now.
	  }

	// debug
	/* std::cerr << "params size: " << params->size() << std::endl;
	hash_map<const char*, const char*, hash<const char*>, eqstr>::const_iterator hit
	  = params->begin();
	while(hit!=params->end())
	  {
	     std::cerr << (*hit).first << " --> " << (*hit).second << std::endl;
	     ++hit;
	  } */
	// debug

	// - send it to the generic search interface.
	http_response *rsp;
	if (NULL == (rsp = new http_response()))
	  {
	     return cgi::cgi_error_memory();
	  }

	// - return the response to the client.
	// default query detection.
	const char *intercepted_query = miscutil::lookup(params,"q");
	char *intercepted_query_enc = encode::url_encode(intercepted_query);

	if (!intercepted_query)
	  {
	     return NULL; // wrong interception, cancel.
	  }

	// build up query to seeks proxy.
	char *q = strdup(CGI_PREFIX);
	miscutil::string_append(&q,"search?q=");
	miscutil::string_append(&q,intercepted_query_enc);
	free(intercepted_query_enc);
	miscutil::string_append(&q,"&page=1");
	miscutil::string_append(&q,"&expansion=1");
	miscutil::string_append(&q,"&action=expand");
	cgi::cgi_redirect(rsp,q);

	return cgi::finish_http_response(csp,rsp);
     }

   hash_map<const char*,const char*,hash<const char*>,eqstr>* query_interceptor::parse_query(http_request *http) const
     {
	if (http->_path)
	  {
	     hash_map<const char*,const char*,hash<const char*>,eqstr> *search_params
	       = cgi::parse_cgi_parameters(http->_path);
	     return search_params;
	  }
	else return NULL;
     }

} /* end of namespace. */
<|endoftext|>


<commit_before>#include <Artnet.h>

Artnet::Artnet() {}

void Artnet::begin(byte mac[], byte ip[])
{
  Ethernet.begin(mac,ip);
  Udp.begin(ART_NET_PORT);
}

uint16_t Artnet::read()
{
  packetSize = Udp.parsePacket();

  if (packetSize <= MAX_BUFFER_ARTNET && packetSize > 0)
  {
      Udp.read(artnetPacket, MAX_BUFFER_ARTNET);

      // Check that packetID is "Art-Net" else ignore
      for (byte i = 0 ; i < 9 ; i++)
      {
        if (artnetPacket[i] != ART_NET_ID[i])
          return 0;
      }

      opcode = artnetPacket[8] | artnetPacket[9] << 8;

      if (opcode == ART_DMX)
      {
        sequence = artnetPacket[12];
        incomingUniverse = artnetPacket[14] | artnetPacket[15] << 8;
        dmxDataLength = artnetPacket[17] | artnetPacket[16] << 8;

        if (artDmxCallback) (*artDmxCallback)(incomingUniverse, dmxDataLength, sequence, artnetPacket + ART_DMX_START);
        return ART_DMX;
      }
      if (opcode == ART_POLL)
      {
        return ART_POLL;
      }
  }
  else
  {
    return 0;
  }
}

void Artnet::printPacketHeader()
{
  Serial.print("packet size = ");
  Serial.print(packetSize);
  Serial.print("\topcode = ");
  Serial.print(opcode, HEX);
  Serial.print("\tuniverse number = ");
  Serial.print(incomingUniverse);
  Serial.print("\tdata length = ");
  Serial.print(dmxDataLength);
  Serial.print("\tsequence n0. = ");
  Serial.println(sequence);
}

void Artnet::printPacketContent()
{
  for (uint16_t i = ART_DMX_START ; i < dmxDataLength ; i++){
    Serial.print(artnetPacket[i], DEC);
    Serial.print("  ");
  }
  Serial.println('\n');
}
<commit_msg>LICENSE<commit_after>/*The MIT License (MIT)

Copyright (c) 2014 Nathanaël Lécaudé
https://github.com/natcl/Artnet, http://forum.pjrc.com/threads/24688-Artnet-to-OctoWS2811

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

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

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

#include <Artnet.h>

Artnet::Artnet() {}

void Artnet::begin(byte mac[], byte ip[])
{
  Ethernet.begin(mac,ip);
  Udp.begin(ART_NET_PORT);
}

uint16_t Artnet::read()
{
  packetSize = Udp.parsePacket();

  if (packetSize <= MAX_BUFFER_ARTNET && packetSize > 0)
  {
      Udp.read(artnetPacket, MAX_BUFFER_ARTNET);

      // Check that packetID is "Art-Net" else ignore
      for (byte i = 0 ; i < 9 ; i++)
      {
        if (artnetPacket[i] != ART_NET_ID[i])
          return 0;
      }

      opcode = artnetPacket[8] | artnetPacket[9] << 8;

      if (opcode == ART_DMX)
      {
        sequence = artnetPacket[12];
        incomingUniverse = artnetPacket[14] | artnetPacket[15] << 8;
        dmxDataLength = artnetPacket[17] | artnetPacket[16] << 8;

        if (artDmxCallback) (*artDmxCallback)(incomingUniverse, dmxDataLength, sequence, artnetPacket + ART_DMX_START);
        return ART_DMX;
      }
      if (opcode == ART_POLL)
      {
        return ART_POLL;
      }
  }
  else
  {
    return 0;
  }
}

void Artnet::printPacketHeader()
{
  Serial.print("packet size = ");
  Serial.print(packetSize);
  Serial.print("\topcode = ");
  Serial.print(opcode, HEX);
  Serial.print("\tuniverse number = ");
  Serial.print(incomingUniverse);
  Serial.print("\tdata length = ");
  Serial.print(dmxDataLength);
  Serial.print("\tsequence n0. = ");
  Serial.println(sequence);
}

void Artnet::printPacketContent()
{
  for (uint16_t i = ART_DMX_START ; i < dmxDataLength ; i++){
    Serial.print(artnetPacket[i], DEC);
    Serial.print("  ");
  }
  Serial.println('\n');
}
<|endoftext|>


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

#include <fcntl.h>
#include <errno.h>
#include <math.h>
#include <poll.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/select.h>
#include <cutils/log.h>

#include "PressureSensor.h"
#include "sensors.h"

#define FETCH_FULL_EVENT_BEFORE_RETURN 	1

#define	EVENT_TYPE_PRESSURE		ABS_PRESSURE

#define CONVERT_PRESSURE		(0.01)

#define IGNORE_EVENT_TIME		0

/*****************************************************************************/

PressureSensor::PressureSensor()
	: SensorBase(NULL, "barometer_sensor"),
	  mEnabled(0),
	  mInputReader(4),
	  mHasPendingEvent(false),
	  mEnabledTime(0)
{
	mPendingEvent.version = sizeof(sensors_event_t);
	mPendingEvent.sensor = SENSORS_PRESSURE_HANDLE;
	mPendingEvent.type = SENSOR_TYPE_PRESSURE;
	memset(mPendingEvent.data, 0, sizeof(mPendingEvent.data));

	if (data_fd) {
		strcpy(input_sysfs_path, "/sys/class/input/");
		strcat(input_sysfs_path, input_name);
		strcat(input_sysfs_path, "/device/device/");
		input_sysfs_path_len = strlen(input_sysfs_path);
		enable(0, 1);
	}
}

PressureSensor::~PressureSensor() {
	if (mEnabled) {
		enable(0, 0);
	}
}

int PressureSensor::setInitialState() {
	struct input_absinfo absinfo;
	float value;
	if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_PRESSURE), &absinfo)) {
		value = absinfo.value;
		mPendingEvent.pressure = value * CONVERT_PRESSURE;
		mHasPendingEvent = true;
	}
	return 0;
}

int PressureSensor::enable(int32_t, int en) {
	int flags = en ? 1 : 0;
	if (flags != mEnabled) {
		int fd;
		strcpy(&input_sysfs_path[input_sysfs_path_len], "enable");
		fd = open(input_sysfs_path, O_RDWR);
		if (fd >= 0) {
			char buf[2];
			int err;
			buf[1] = 0;
			if (flags) {
				buf[0] = '1';
				mEnabledTime = getTimestamp() + IGNORE_EVENT_TIME;
			} else {
				buf[0] = '0';
			}
			err = write(fd, buf, sizeof(buf));
			close(fd);
			mEnabled = flags;
			setInitialState();
			return 0;
		}
		return -1;
	}
	return 0;
}

bool PressureSensor::hasPendingEvents() const {
	return mHasPendingEvent;
}

int PressureSensor::setDelay(int32_t handle, int64_t delay_ns)
{
	int fd;
	strcpy(&input_sysfs_path[input_sysfs_path_len], "poll_delay");
	fd = open(input_sysfs_path, O_RDWR);
	if (fd >= 0) {
		char buf[80];
		sprintf(buf, "%lld", delay_ns);
		write(fd, buf, strlen(buf)+1);
		close(fd);
		return 0;
	}
	return -1;
}

int PressureSensor::readEvents(sensors_event_t* data, int count)
{
	if (count < 1)
		return -EINVAL;

	if (mHasPendingEvent) {
		mHasPendingEvent = false;
		mPendingEvent.timestamp = getTimestamp();
		*data = mPendingEvent;
		return mEnabled ? 1 : 0;
	}

	ssize_t n = mInputReader.fill(data_fd);
	if (n < 0)
		return n;

	int numEventReceived = 0;
	input_event const* event;

#if FETCH_FULL_EVENT_BEFORE_RETURN
again:
#endif
	while (count && mInputReader.readEvent(&event)) {
		int type = event->type;
		if (type == EV_ABS) {
			float value = event->value;
			mPendingEvent.pressure = value * CONVERT_PRESSURE;
		} else if (type == EV_SYN) {
			mPendingEvent.timestamp = timevalToNano(event->time);
			if (mEnabled) {
				if (mPendingEvent.timestamp >= mEnabledTime) {
					*data++ = mPendingEvent;
					numEventReceived++;
				}
				count--;
			}
		} else {
			ALOGE("PressureSensor: unknown event (type=%d, code=%d)",
					type, event->code);
		}
		mInputReader.next();
	}

#if FETCH_FULL_EVENT_BEFORE_RETURN
	/* if we didn't read a complete event, see if we can fill and
	   try again instead of returning with nothing and redoing poll. */
	if (numEventReceived == 0 && mEnabled == 1) {
		n = mInputReader.fill(data_fd);
		if (n)
			goto again;
	}
#endif

	return numEventReceived;
}

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

#include <fcntl.h>
#include <errno.h>
#include <math.h>
#include <poll.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/select.h>
#include <cutils/log.h>

#include "PressureSensor.h"
#include "sensors.h"

#define FETCH_FULL_EVENT_BEFORE_RETURN 	1

#define	EVENT_TYPE_PRESSURE		ABS_PRESSURE

#define CONVERT_PRESSURE		(0.01)

#define IGNORE_EVENT_TIME		0

/*****************************************************************************/

PressureSensor::PressureSensor()
	: SensorBase(NULL, "bmp18x"),
	  mEnabled(0),
	  mInputReader(4),
	  mHasPendingEvent(false),
	  mEnabledTime(0)
{
	mPendingEvent.version = sizeof(sensors_event_t);
	mPendingEvent.sensor = SENSORS_PRESSURE_HANDLE;
	mPendingEvent.type = SENSOR_TYPE_PRESSURE;
	memset(mPendingEvent.data, 0, sizeof(mPendingEvent.data));

	if (data_fd) {
		strcpy(input_sysfs_path, "/sys/class/input/");
		strcat(input_sysfs_path, input_name);
		strcat(input_sysfs_path, "/device/device/");
		input_sysfs_path_len = strlen(input_sysfs_path);
		enable(0, 1);
	}
}

PressureSensor::~PressureSensor() {
	if (mEnabled) {
		enable(0, 0);
	}
}

int PressureSensor::setInitialState() {
	struct input_absinfo absinfo;
	float value;
	if (!ioctl(data_fd, EVIOCGABS(EVENT_TYPE_PRESSURE), &absinfo)) {
		value = absinfo.value;
		mPendingEvent.pressure = value * CONVERT_PRESSURE;
		mHasPendingEvent = true;
	}
	return 0;
}

int PressureSensor::enable(int32_t, int en) {
	int flags = en ? 1 : 0;
	if (flags != mEnabled) {
		int fd;
		strcpy(&input_sysfs_path[input_sysfs_path_len], "enable");
		fd = open(input_sysfs_path, O_RDWR);
		if (fd >= 0) {
			char buf[2];
			int err;
			buf[1] = 0;
			if (flags) {
				buf[0] = '1';
				mEnabledTime = getTimestamp() + IGNORE_EVENT_TIME;
			} else {
				buf[0] = '0';
			}
			err = write(fd, buf, sizeof(buf));
			close(fd);
			mEnabled = flags;
			setInitialState();
			return 0;
		}
		return -1;
	}
	return 0;
}

bool PressureSensor::hasPendingEvents() const {
	return mHasPendingEvent;
}

int PressureSensor::setDelay(int32_t handle, int64_t delay_ns)
{
	int fd;
	int delay_ms = delay_ns / 1000000;
	strcpy(&input_sysfs_path[input_sysfs_path_len], "pollrate_ms");
	fd = open(input_sysfs_path, O_RDWR);
	if (fd >= 0) {
		char buf[80];
		sprintf(buf, "%d", delay_ms);
		write(fd, buf, strlen(buf)+1);
		close(fd);
		return 0;
	}
	return -1;
}

int PressureSensor::readEvents(sensors_event_t* data, int count)
{
	if (count < 1)
		return -EINVAL;

	if (mHasPendingEvent) {
		mHasPendingEvent = false;
		mPendingEvent.timestamp = getTimestamp();
		*data = mPendingEvent;
		return mEnabled ? 1 : 0;
	}

	ssize_t n = mInputReader.fill(data_fd);
	if (n < 0)
		return n;

	int numEventReceived = 0;
	input_event const* event;

#if FETCH_FULL_EVENT_BEFORE_RETURN
again:
#endif
	while (count && mInputReader.readEvent(&event)) {
		int type = event->type;
		if (type == EV_ABS) {
			float value = event->value;
			mPendingEvent.pressure = value * CONVERT_PRESSURE;
		} else if (type == EV_SYN) {
			mPendingEvent.timestamp = timevalToNano(event->time);
			if (mEnabled) {
				if (mPendingEvent.timestamp >= mEnabledTime) {
					*data++ = mPendingEvent;
					numEventReceived++;
				}
				count--;
			}
		} else {
			ALOGE("PressureSensor: unknown event (type=%d, code=%d)",
					type, event->code);
		}
		mInputReader.next();
	}

#if FETCH_FULL_EVENT_BEFORE_RETURN
	/* if we didn't read a complete event, see if we can fill and
	   try again instead of returning with nothing and redoing poll. */
	if (numEventReceived == 0 && mEnabled == 1) {
		n = mInputReader.fill(data_fd);
		if (n)
			goto again;
	}
#endif

	return numEventReceived;
}

<|endoftext|>


<commit_before>
// must be first include because of Python stuff, see ffmpeg.h comment
#include "PyThreading.hpp" // mlock

#include <algorithm>
#include "Buffer.hpp"

Buffer::Chunk::Chunk() : start(0), end(0) { mlock(this, sizeof(*this)); }
Buffer::Buffer() : _size(0) { mlock(this, sizeof(*this)); }

size_t Buffer::pop(uint8_t* target, size_t target_size) {
	size_t c = 0;
	while(!chunks.empty()) {
		auto chunkPtr = chunks.front();
		assert(chunkPtr->isData(false));
		Chunk& chunk = chunkPtr->value;
		Chunk::Idx chunkEnd = chunk.end;
		int s = chunkEnd - chunk.start;
		if(s == 0) {
			// push() but not yet any data added
			break;
		}
		if((size_t)s > target_size) s = (int)target_size;
		memcpy(target, chunk.data + chunk.start, s);
		chunk.start += s;
		_size -= s;
		target += s;
		target_size -= s;
		c += s;
		if(chunk.start < chunkEnd) {
			assert(target_size == 0);
			break;
		}
		if(chunkEnd < Chunk::BufferSize()) {
			// push() would have filled it further
			break;
		}
		assert(chunk.start == chunkEnd);
		assert(chunkEnd == Chunk::BufferSize());
		chunks.pop_front();
	}
	return c;
}

void Buffer::push(const uint8_t* data, size_t size) {
	while(size > 0) {
		auto chunkBackPtr = chunks.back();
		if(!chunkBackPtr->isData(false)) // it means chunks is empty
			chunks.push_back();
		else if(!chunkBackPtr->value.freeDataAvailable())
			chunks.push_back();
		auto chunkPtr = chunks.back();
		assert(chunkPtr->isData(false));
		Chunk& chunk = chunkPtr->value;
		size_t s = std::min(size, (size_t)chunk.freeDataAvailable());
		assert(s > 0);
		memcpy(chunk.data + chunk.end, data, s);
		data += s;
		size -= s;
		chunk.end += s;
		_size += s;
	}
}

<commit_msg>comment<commit_after>
// must be first include because of Python stuff, see ffmpeg.h comment
#include "PyThreading.hpp" // mlock

#include <algorithm>
#include "Buffer.hpp"

Buffer::Chunk::Chunk() : start(0), end(0) { mlock(this, sizeof(*this)); }
Buffer::Buffer() : _size(0) { mlock(this, sizeof(*this)); }

size_t Buffer::pop(uint8_t* target, size_t target_size) {
	size_t c = 0;
	while(!chunks.empty()) {
		auto chunkPtr = chunks.front();
		assert(chunkPtr->isData(false));
		Chunk& chunk = chunkPtr->value;
		Chunk::Idx chunkEnd = chunk.end;
		int s = chunkEnd - chunk.start;
		if(s == 0) {
			// push() but not yet any data added
			break;
		}
		if((size_t)s > target_size) s = (int)target_size;
		memcpy(target, chunk.data + chunk.start, s);
		chunk.start += s;
		_size -= s;
		target += s;
		target_size -= s;
		c += s;
		if(chunk.start < chunkEnd) {
			assert(target_size == 0);
			break;
		}
		if(chunkEnd < Chunk::BufferSize()) {
			// push() would have filled it further
			break;
		}
		assert(chunk.start == chunkEnd);
		assert(chunkEnd == Chunk::BufferSize());

		// Is `free` lock-free? If not, we might let the push()
		// do the pop_front().
		chunks.pop_front();
	}
	return c;
}

void Buffer::push(const uint8_t* data, size_t size) {
	while(size > 0) {
		auto chunkBackPtr = chunks.back();
		if(!chunkBackPtr->isData(false)) // it means chunks is empty
			chunks.push_back();
		else if(!chunkBackPtr->value.freeDataAvailable())
			chunks.push_back();
		auto chunkPtr = chunks.back();
		assert(chunkPtr->isData(false));
		Chunk& chunk = chunkPtr->value;
		size_t s = std::min(size, (size_t)chunk.freeDataAvailable());
		assert(s > 0);
		memcpy(chunk.data + chunk.end, data, s);
		data += s;
		size -= s;
		chunk.end += s;
		_size += s;
	}
}

<|endoftext|>


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

#include "sandbox/win/src/sync_dispatcher.h"

#include "base/win/windows_version.h"
#include "sandbox/win/src/crosscall_client.h"
#include "sandbox/win/src/interception.h"
#include "sandbox/win/src/interceptors.h"
#include "sandbox/win/src/ipc_tags.h"
#include "sandbox/win/src/policy_broker.h"
#include "sandbox/win/src/policy_params.h"
#include "sandbox/win/src/sandbox.h"
#include "sandbox/win/src/sync_interception.h"
#include "sandbox/win/src/sync_policy.h"

namespace sandbox {

SyncDispatcher::SyncDispatcher(PolicyBase* policy_base)
    : policy_base_(policy_base) {
  static const IPCCall create_params = {
    {IPC_CREATEEVENT_TAG, WCHAR_TYPE, ULONG_TYPE, ULONG_TYPE},
    reinterpret_cast<CallbackGeneric>(&SyncDispatcher::CreateEvent)
  };

  static const IPCCall open_params = {
    {IPC_OPENEVENT_TAG, WCHAR_TYPE, ULONG_TYPE, ULONG_TYPE},
    reinterpret_cast<CallbackGeneric>(&SyncDispatcher::OpenEvent)
  };

  ipc_calls_.push_back(create_params);
  ipc_calls_.push_back(open_params);
}

bool SyncDispatcher::SetupService(InterceptionManager* manager,
                                  int service) {
  bool ret = false;
  static const wchar_t* kWin32SyncDllName =
      base::win::GetVersion() >= base::win::VERSION_WIN8 ? kKernelBasedllName :
          kKerneldllName;

  // We need to intercept kernelbase.dll on Windows 8 and beyond and
  // kernel32.dll for earlier versions.
  if (IPC_CREATEEVENT_TAG == service) {
    ret = INTERCEPT_EAT(manager, kWin32SyncDllName, CreateEventW,
                        CREATE_EVENTW_ID, 20);
    if (ret) {
      ret = INTERCEPT_EAT(manager, kWin32SyncDllName, CreateEventA,
                          CREATE_EVENTA_ID, 20);
    }
  } else if (IPC_OPENEVENT_TAG == service) {
    ret = INTERCEPT_EAT(manager, kWin32SyncDllName, OpenEventW, OPEN_EVENTW_ID,
                        16);
    if (ret) {
      ret = INTERCEPT_EAT(manager, kWin32SyncDllName, OpenEventW,
                          OPEN_EVENTA_ID, 16);
    }
  }
  return ret;
}

bool SyncDispatcher::CreateEvent(IPCInfo* ipc, std::wstring* name,
                                 DWORD manual_reset, DWORD initial_state) {
  const wchar_t* event_name = name->c_str();
  CountedParameterSet<NameBased> params;
  params[NameBased::NAME] = ParamPickerMake(event_name);

  EvalResult result = policy_base_->EvalPolicy(IPC_CREATEEVENT_TAG,
                                               params.GetBase());
  HANDLE handle = NULL;
  DWORD ret = SyncPolicy::CreateEventAction(result, *ipc->client_info, *name,
                                            manual_reset, initial_state,
                                            &handle);
  // Return operation status on the IPC.
  ipc->return_info.win32_result = ret;
  ipc->return_info.handle = handle;
  return true;
}

bool SyncDispatcher::OpenEvent(IPCInfo* ipc, std::wstring* name,
                               DWORD desired_access, DWORD inherit_handle) {
  const wchar_t* event_name = name->c_str();

  CountedParameterSet<OpenEventParams> params;
  params[OpenEventParams::NAME] = ParamPickerMake(event_name);
  params[OpenEventParams::ACCESS] = ParamPickerMake(desired_access);

  EvalResult result = policy_base_->EvalPolicy(IPC_OPENEVENT_TAG,
                                               params.GetBase());
  HANDLE handle = NULL;
  DWORD ret = SyncPolicy::OpenEventAction(result, *ipc->client_info, *name,
                                          desired_access, inherit_handle,
                                          &handle);
  // Return operation status on the IPC.
  ipc->return_info.win32_result = ret;
  ipc->return_info.handle = handle;
  return true;
}

}  // namespace sandbox
<commit_msg>Fix a hang in the GPU process in the XP presentation path.<commit_after>// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "sandbox/win/src/sync_dispatcher.h"

#include "base/win/windows_version.h"
#include "sandbox/win/src/crosscall_client.h"
#include "sandbox/win/src/interception.h"
#include "sandbox/win/src/interceptors.h"
#include "sandbox/win/src/ipc_tags.h"
#include "sandbox/win/src/policy_broker.h"
#include "sandbox/win/src/policy_params.h"
#include "sandbox/win/src/sandbox.h"
#include "sandbox/win/src/sync_interception.h"
#include "sandbox/win/src/sync_policy.h"

namespace sandbox {

SyncDispatcher::SyncDispatcher(PolicyBase* policy_base)
    : policy_base_(policy_base) {
  static const IPCCall create_params = {
    {IPC_CREATEEVENT_TAG, WCHAR_TYPE, ULONG_TYPE, ULONG_TYPE},
    reinterpret_cast<CallbackGeneric>(&SyncDispatcher::CreateEvent)
  };

  static const IPCCall open_params = {
    {IPC_OPENEVENT_TAG, WCHAR_TYPE, ULONG_TYPE, ULONG_TYPE},
    reinterpret_cast<CallbackGeneric>(&SyncDispatcher::OpenEvent)
  };

  ipc_calls_.push_back(create_params);
  ipc_calls_.push_back(open_params);
}

bool SyncDispatcher::SetupService(InterceptionManager* manager,
                                  int service) {
  bool ret = false;
  static const wchar_t* kWin32SyncDllName =
      base::win::GetVersion() >= base::win::VERSION_WIN7 ? kKernelBasedllName :
          kKerneldllName;

  // We need to intercept kernelbase.dll on Windows 8 and beyond and
  // kernel32.dll for earlier versions.
  if (IPC_CREATEEVENT_TAG == service) {
    ret = INTERCEPT_EAT(manager, kWin32SyncDllName, CreateEventW,
                        CREATE_EVENTW_ID, 20);
    if (ret) {
      ret = INTERCEPT_EAT(manager, kWin32SyncDllName, CreateEventA,
                          CREATE_EVENTA_ID, 20);
    }
  } else if (IPC_OPENEVENT_TAG == service) {
    ret = INTERCEPT_EAT(manager, kWin32SyncDllName, OpenEventW, OPEN_EVENTW_ID,
                        16);
    if (ret) {
      ret = INTERCEPT_EAT(manager, kWin32SyncDllName, OpenEventW,
                          OPEN_EVENTA_ID, 16);
    }
  }
  return ret;
}

bool SyncDispatcher::CreateEvent(IPCInfo* ipc, std::wstring* name,
                                 DWORD manual_reset, DWORD initial_state) {
  const wchar_t* event_name = name->c_str();
  CountedParameterSet<NameBased> params;
  params[NameBased::NAME] = ParamPickerMake(event_name);

  EvalResult result = policy_base_->EvalPolicy(IPC_CREATEEVENT_TAG,
                                               params.GetBase());
  HANDLE handle = NULL;
  DWORD ret = SyncPolicy::CreateEventAction(result, *ipc->client_info, *name,
                                            manual_reset, initial_state,
                                            &handle);
  // Return operation status on the IPC.
  ipc->return_info.win32_result = ret;
  ipc->return_info.handle = handle;
  return true;
}

bool SyncDispatcher::OpenEvent(IPCInfo* ipc, std::wstring* name,
                               DWORD desired_access, DWORD inherit_handle) {
  const wchar_t* event_name = name->c_str();

  CountedParameterSet<OpenEventParams> params;
  params[OpenEventParams::NAME] = ParamPickerMake(event_name);
  params[OpenEventParams::ACCESS] = ParamPickerMake(desired_access);

  EvalResult result = policy_base_->EvalPolicy(IPC_OPENEVENT_TAG,
                                               params.GetBase());
  HANDLE handle = NULL;
  DWORD ret = SyncPolicy::OpenEventAction(result, *ipc->client_info, *name,
                                          desired_access, inherit_handle,
                                          &handle);
  // Return operation status on the IPC.
  ipc->return_info.win32_result = ret;
  ipc->return_info.handle = handle;
  return true;
}

}  // namespace sandbox
<|endoftext|>