<commit_before>#ifndef GUARD_handle_hpp
#define GUARD_handle_hpp

#include "sqloxx_exceptions.hpp"

namespace sqloxx
{

/**
 * Handle for handling business objects of type T where T is a class
 * derived from PersistentObject and is
 * managed via IdentityMap<T> to ensure only one instance of T exists in
 * memory at any one time, in relation to any given record in a given
 * database.
 *
 * @todo Testing and documentation.
 */
template <typename T>
class Handle
{
public:

	/** Construct a Handle<T> from a T*.
	 *
	 * @throws sqloxx::OverflowException if the maximum number
	 * of handles for this underlying instance of T has been reached.
	 * The circumstances under which this occurs depend on the
	 * implementation of T::notify_handle_construction(), but should
	 * be extremely rare.
	 *
	 * Exception safety: strong guarantee.
	 *
	 * @todo Testing.
	 */
	Handle(T* p_pointer);

	/**
	 * Preconditions:\n
	 * the object must have been managed
	 * throughout its life by (a single instance of) IdentityMap,
	 * and must only have ever been
	 * accessed via instances of Handle<Derived>; and\n
	 * The destructor of Derived must be non-throwing.
	 *
	 * Exception safety: nothrow guarantee, provided the
	 * preconditions are met.
	 *
	 * @todo Testing.
	 */
	~Handle();

	/**
	 * @throws sqloxx::OverflowException in the extremely unlikely
	 * event that the number of Handle instances pointing to the
	 * underlying instance of T is too large to be safely counted
	 * by the type PersistentObject<T, Connection>::HandleCounter.
	 *
	 * Exception safety: strong guarantee.
	 *
	 * @todo Testing.
	 */
	Handle(Handle const& rhs);

	/**
	 * @todo Testing and documentation.
	 */
	Handle& operator=(Handle const& rhs);

	/**
	 * @todo Testing and documentation.
	 */
	operator bool() const;

	/**
	 * @todo Testing and documentation.
	 */
	T& operator*() const;

	/**
	 * @todo Testing and documentation.
	 */
	T* operator->() const;

private:
	T* m_pointer;
};

template <typename T>
Handle<T>::Handle(T* p_pointer):
	m_pointer(p_pointer)
{
	// Strong guarantee. Might throw OverflowException, though this
	// is extremely unlikely.
	p_pointer->notify_handle_construction();
}

template <typename T>
Handle<T>::~Handle()
{
	// Nothrow provided preconditions met, viz. object must have
	// been handled throughout its life via Handle<T>, with the
	// Handle having been copied from another Handle<T>, or else
	// provided by IdentityMap via a call to provide_handle(...).
	// Also, the destructor of T must never throw.
	m_pointer->notify_handle_destruction();
}

template <typename T>
Handle<T>::Handle(Handle const& rhs)
{
	m_pointer = rhs.m_pointer;  // nothrow

	// Strong guarantee. Might throw OverflowException, though this
	// is extremely unlikely.
	m_pointer->notify_handle_copy_construction();
}

template <typename T>
Handle<T>&
Handle<T>::operator=(Handle const& rhs)
{
	// Strong guarantee, provided rhs has a valid pointer...
	rhs.m_pointer->notify_rhs_assignment_operation();

	// Nothrow guarantee, provided preconditions met, and
	// provided rhs has a valid pointer.
	m_pointer->notify_lhs_assignment_operation();

	m_pointer = rhs.m_pointer;  // nothrow

	return *this;  // throw, provided we have a valid pointer
}

template <typename T>
Handle<T>::operator bool() const
{
	return static_cast<bool>(m_pointer);  // nothrow
}

template <typename T>
T&
Handle<T>::operator*() const
{
	if (static_cast<bool>(m_pointer))  // nothrow
	{
		return *m_pointer;  // nothrow
	}
	throw (UnboundHandleException("Unbound Handle."));
}

template <typename T>
T*
Handle<T>::operator->() const
{
	if (static_cast<bool>(m_pointer))  // nothrow
	{
		return m_pointer;  // nothrow
	}
	throw (UnboundHandleException("Unbound Handle."));
}

}  // namespace sqloxx

#endif  // GUARD_handle_hpp
<commit_msg>Worked on documentation of sqloxx::Handle<T>.<commit_after>#ifndef GUARD_handle_hpp
#define GUARD_handle_hpp

#include "sqloxx_exceptions.hpp"

namespace sqloxx
{

/**
 * Handle for handling business objects of type T where T is a class
 * derived from PersistentObject and is
 * managed via IdentityMap<T> to ensure only one instance of T exists in
 * memory at any one time, in relation to any given record in a given
 * database.
 *
 * @todo Testing and documentation.
 */
template <typename T>
class Handle
{
public:

	/** Construct a Handle<T> from a T*.
	 *
	 * @throws sqloxx::OverflowException if the maximum number
	 * of handles for this underlying instance of T has been reached.
	 * The circumstances under which this occurs depend on the
	 * implementation of T::notify_handle_construction(), but should
	 * be extremely rare.
	 *
	 * Exception safety: strong guarantee.
	 *
	 * @todo Testing.
	 */
	Handle(T* p_pointer);

	/**
	 * Preconditions:\n
	 * the object must have been managed
	 * throughout its life by (a single instance of) IdentityMap,
	 * and must only have ever been
	 * accessed via instances of Handle<Derived>; and\n
	 * The destructor of Derived must be non-throwing.
	 *
	 * Exception safety: nothrow guarantee, provided the
	 * preconditions are met.
	 *
	 * @todo Testing.
	 */
	~Handle();

	/**
	 * @throws sqloxx::OverflowException in the extremely unlikely
	 * event that the number of Handle instances pointing to the
	 * underlying instance of T is too large to be safely counted
	 * by the type PersistentObject<T, Connection>::HandleCounter.
	 *
	 * Exception safety: strong guarantee.
	 *
	 * @todo Testing.
	 */
	Handle(Handle const& rhs);

	/**
	 * @throws sqloxx::OverflowException in the extremely unlikely
	 * event that the number of Handle instances pointing to the
	 * underlying instance of T is too large to be safely counted
	 * by the type PersistentObject<T, Connection>::HandleCounter.
	 *
	 * Exception safety: strong guarantee.
	 *
	 * @todo Testing.
	 */
	Handle& operator=(Handle const& rhs);

	/**
	 * @return \e true if this Handle<T> is bound to some instance
	 * of T; otherwise returns \e false.
	 *
	 * Exception safety: nothrow guarantee.
	 *
	 * @todo Testing.
	 */
	operator bool() const;

	/**
	 * @todo Testing and documentation.
	 */
	T& operator*() const;

	/**
	 * @todo Testing and documentation.
	 */
	T* operator->() const;

private:
	T* m_pointer;
};

template <typename T>
Handle<T>::Handle(T* p_pointer):
	m_pointer(p_pointer)
{
	p_pointer->notify_handle_construction();
}

template <typename T>
Handle<T>::~Handle()
{
	m_pointer->notify_handle_destruction();
}

template <typename T>
Handle<T>::Handle(Handle const& rhs)
{
	m_pointer = rhs.m_pointer;
	m_pointer->notify_handle_copy_construction();
}

template <typename T>
Handle<T>&
Handle<T>::operator=(Handle const& rhs)
{
	// Strong guarantee, provided rhs has a valid pointer...
	rhs.m_pointer->notify_rhs_assignment_operation();

	// Nothrow guarantee, provided preconditions met, and
	// provided rhs has a valid pointer.
	m_pointer->notify_lhs_assignment_operation();

	m_pointer = rhs.m_pointer;  // nothrow

	return *this;  // throw, provided we have a valid pointer
}

template <typename T>
Handle<T>::operator bool() const
{
	return static_cast<bool>(m_pointer);  // nothrow
}

template <typename T>
T&
Handle<T>::operator*() const
{
	if (static_cast<bool>(m_pointer))  // nothrow
	{
		return *m_pointer;  // nothrow
	}
	throw (UnboundHandleException("Unbound Handle."));
}

template <typename T>
T*
Handle<T>::operator->() const
{
	if (static_cast<bool>(m_pointer))  // nothrow
	{
		return m_pointer;  // nothrow
	}
	throw (UnboundHandleException("Unbound Handle."));
}

}  // namespace sqloxx

#endif  // GUARD_handle_hpp
<|endoftext|>


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

#include "searchwidget.h"
#include "localhelpmanager.h"
#include "openpagesmanager.h"

#include <coreplugin/icore.h>
#include <coreplugin/progressmanager/progressmanager.h>
#include <utils/styledbar.h>

#include <QMap>
#include <QString>
#include <QStringList>

#include <QMenu>
#include <QLayout>
#include <QKeyEvent>
#include <QClipboard>
#include <QApplication>
#include <QTextBrowser>

#include <QHelpEngine>
#include <QHelpSearchEngine>
#include <QHelpSearchQueryWidget>
#include <QHelpSearchResultWidget>

using namespace Help::Internal;

SearchWidget::SearchWidget()
    : zoomCount(0)
    , m_progress(0)
    , searchEngine(0)
    , resultWidget(0)
{
}

SearchWidget::~SearchWidget()
{
}

void SearchWidget::zoomIn()
{
    QTextBrowser* browser = qFindChild<QTextBrowser*>(resultWidget);
    if (browser && zoomCount != 10) {
        zoomCount++;
        browser->zoomIn();
    }
}

void SearchWidget::zoomOut()
{
    QTextBrowser* browser = qFindChild<QTextBrowser*>(resultWidget);
    if (browser && zoomCount != -5) {
        zoomCount--;
        browser->zoomOut();
    }
}

void SearchWidget::resetZoom()
{
    if (zoomCount == 0)
        return;

    QTextBrowser* browser = qFindChild<QTextBrowser*>(resultWidget);
    if (browser) {
        browser->zoomOut(zoomCount);
        zoomCount = 0;
    }
}

void SearchWidget::showEvent(QShowEvent *event)
{
    if (!event->spontaneous() && !searchEngine) {
        QVBoxLayout *vLayout = new QVBoxLayout(this);
        vLayout->setMargin(0);
        vLayout->setSpacing(0);

        searchEngine = (&LocalHelpManager::helpEngine())->searchEngine();

        Utils::StyledBar *toolbar = new Utils::StyledBar(this);
        toolbar->setSingleRow(false);
        QHelpSearchQueryWidget *queryWidget = searchEngine->queryWidget();
        QLayout *tbLayout = new QVBoxLayout();
        tbLayout->setSpacing(6);
        tbLayout->setMargin(4);
        tbLayout->addWidget(queryWidget);
        toolbar->setLayout(tbLayout);

        Utils::StyledBar *toolbar2 = new Utils::StyledBar(this);
        toolbar2->setSingleRow(false);
        tbLayout = new QVBoxLayout();
        tbLayout->setSpacing(0);
        tbLayout->setMargin(0);
        tbLayout->addWidget(resultWidget = searchEngine->resultWidget());
        toolbar2->setLayout(tbLayout);

        vLayout->addWidget(toolbar);
        vLayout->addWidget(toolbar2);

        setFocusProxy(queryWidget);

        connect(queryWidget, SIGNAL(search()), this, SLOT(search()));
        connect(resultWidget, SIGNAL(requestShowLink(QUrl)), this,
            SIGNAL(linkActivated(QUrl)));

        connect(searchEngine, SIGNAL(searchingStarted()), this,
            SLOT(searchingStarted()));
        connect(searchEngine, SIGNAL(searchingFinished(int)), this,
            SLOT(searchingFinished(int)));

        QTextBrowser* browser = qFindChild<QTextBrowser*>(resultWidget);
        browser->viewport()->installEventFilter(this);

        connect(searchEngine, SIGNAL(indexingStarted()), this,
            SLOT(indexingStarted()));
        connect(searchEngine, SIGNAL(indexingFinished()), this,
            SLOT(indexingFinished()));

        QMetaObject::invokeMethod(&LocalHelpManager::helpEngine(), "setupFinished",
            Qt::QueuedConnection);
    }
}

void SearchWidget::search() const
{
    static QStringList charsToEscapeList;
    if (charsToEscapeList.isEmpty()) {
        charsToEscapeList << QLatin1String("\\") << QLatin1String("+")
            << QLatin1String("-") << QLatin1String("!") << QLatin1String("(")
            << QLatin1String(")") << QLatin1String(":") << QLatin1String("^")
            << QLatin1String("[") << QLatin1String("]") << QLatin1String("{")
            << QLatin1String("}") << QLatin1String("~");
    }

    static QString escapeChar(QLatin1String("\\"));
    static QRegExp regExp(QLatin1String("[\\+\\-\\!\\(\\)\\^\\[\\]\\{\\}~:]"));

    QList<QHelpSearchQuery> escapedQueries;
    const QList<QHelpSearchQuery> queries = searchEngine->queryWidget()->query();
    foreach (const QHelpSearchQuery &query, queries) {
        QHelpSearchQuery escapedQuery;
        escapedQuery.fieldName = query.fieldName;
        foreach (QString word, query.wordList) {
            if (word.contains(regExp)) {
                foreach (const QString &charToEscape, charsToEscapeList)
                    word.replace(charToEscape, escapeChar + charToEscape);
                escapedQuery.wordList.append(word);
            }
        }
        escapedQueries.append(escapedQuery);
    }
    searchEngine->search(escapedQueries);
}

void SearchWidget::searchingStarted()
{
    qApp->setOverrideCursor(QCursor(Qt::WaitCursor));
}

void SearchWidget::searchingFinished(int hits)
{
    Q_UNUSED(hits)
    qApp->restoreOverrideCursor();
}

void SearchWidget::indexingStarted()
{
    Q_ASSERT(!m_progress);
    m_progress = new QFutureInterface<void>();
    Core::ICore::progressManager() ->addTask(m_progress->future(),
        tr("Indexing"), QLatin1String("Help.Indexer"));
    m_progress->setProgressRange(0, 2);
    m_progress->setProgressValueAndText(1, tr("Indexing Documentation..."));
    m_progress->reportStarted();

    m_watcher.setFuture(m_progress->future());
    connect(&m_watcher, SIGNAL(canceled()), searchEngine, SLOT(cancelIndexing()));
}

void SearchWidget::indexingFinished()
{
    m_progress->reportFinished();

    delete m_progress;
    m_progress = NULL;
}

bool SearchWidget::eventFilter(QObject *o, QEvent *e)
{
    QTextBrowser *browser = qFindChild<QTextBrowser *>(resultWidget);
    if (browser && o == browser->viewport()
        && e->type() == QEvent::MouseButtonRelease){
        QMouseEvent *me = static_cast<QMouseEvent *>(e);
        QUrl link = resultWidget->linkAt(me->pos());
        if (!link.isEmpty() || link.isValid()) {
            bool controlPressed = me->modifiers() & Qt::ControlModifier;
            if ((me->button() == Qt::LeftButton && controlPressed)
                || (me->button() == Qt::MidButton)) {
                    OpenPagesManager::instance().createPageFromSearch(link);
            }
        }
    }
    return QWidget::eventFilter(o,e);
}

void SearchWidget::contextMenuEvent(QContextMenuEvent *contextMenuEvent)
{
    QTextBrowser *browser = qFindChild<QTextBrowser *>(resultWidget);
    if (!browser)
        return;

    QPoint point = browser->mapFromGlobal(contextMenuEvent->globalPos());
    if (!browser->rect().contains(point, true))
        return;

    QAction *openLink = 0;
    QAction *openLinkInNewTab = 0;
    QAction *copyAnchorAction = 0;

    QMenu menu;
    QUrl link = browser->anchorAt(point);
    if (!link.isEmpty() && link.isValid()) {
        if (link.isRelative())
            link = browser->source().resolved(link);
        openLink = menu.addAction(tr("Open Link"));
        openLinkInNewTab = menu.addAction(tr("Open Link as New Page"));
        copyAnchorAction = menu.addAction(tr("Copy Link"));
    } else if (browser->textCursor().hasSelection()) {
        menu.addAction(tr("Copy"), browser, SLOT(copy()));
    } else {
        menu.addAction(tr("Reload"), browser, SLOT(reload()));
    }

    QAction *usedAction = menu.exec(mapToGlobal(contextMenuEvent->pos()));
    if (usedAction == openLink) {
        browser->selectAll();
    } else if (usedAction == openLinkInNewTab) {
        OpenPagesManager::instance().createPageFromSearch(link);
    } else if (usedAction == copyAnchorAction) {
        QApplication::clipboard()->setText(link.toString());
    }
}
<commit_msg>Fix 38fe616d857234845b9169576433c28aa54fee89<commit_after>/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights. These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**************************************************************************/

#include "searchwidget.h"
#include "localhelpmanager.h"
#include "openpagesmanager.h"

#include <coreplugin/icore.h>
#include <coreplugin/progressmanager/progressmanager.h>
#include <utils/styledbar.h>

#include <QMap>
#include <QString>
#include <QStringList>

#include <QMenu>
#include <QLayout>
#include <QKeyEvent>
#include <QClipboard>
#include <QApplication>
#include <QTextBrowser>

#include <QHelpEngine>
#include <QHelpSearchEngine>
#include <QHelpSearchQueryWidget>
#include <QHelpSearchResultWidget>

using namespace Help::Internal;

SearchWidget::SearchWidget()
    : zoomCount(0)
    , m_progress(0)
    , searchEngine(0)
    , resultWidget(0)
{
}

SearchWidget::~SearchWidget()
{
}

void SearchWidget::zoomIn()
{
    QTextBrowser* browser = qFindChild<QTextBrowser*>(resultWidget);
    if (browser && zoomCount != 10) {
        zoomCount++;
        browser->zoomIn();
    }
}

void SearchWidget::zoomOut()
{
    QTextBrowser* browser = qFindChild<QTextBrowser*>(resultWidget);
    if (browser && zoomCount != -5) {
        zoomCount--;
        browser->zoomOut();
    }
}

void SearchWidget::resetZoom()
{
    if (zoomCount == 0)
        return;

    QTextBrowser* browser = qFindChild<QTextBrowser*>(resultWidget);
    if (browser) {
        browser->zoomOut(zoomCount);
        zoomCount = 0;
    }
}

void SearchWidget::showEvent(QShowEvent *event)
{
    if (!event->spontaneous() && !searchEngine) {
        QVBoxLayout *vLayout = new QVBoxLayout(this);
        vLayout->setMargin(0);
        vLayout->setSpacing(0);

        searchEngine = (&LocalHelpManager::helpEngine())->searchEngine();

        Utils::StyledBar *toolbar = new Utils::StyledBar(this);
        toolbar->setSingleRow(false);
        QHelpSearchQueryWidget *queryWidget = searchEngine->queryWidget();
        QLayout *tbLayout = new QVBoxLayout();
        tbLayout->setSpacing(6);
        tbLayout->setMargin(4);
        tbLayout->addWidget(queryWidget);
        toolbar->setLayout(tbLayout);

        Utils::StyledBar *toolbar2 = new Utils::StyledBar(this);
        toolbar2->setSingleRow(false);
        tbLayout = new QVBoxLayout();
        tbLayout->setSpacing(0);
        tbLayout->setMargin(0);
        tbLayout->addWidget(resultWidget = searchEngine->resultWidget());
        toolbar2->setLayout(tbLayout);

        vLayout->addWidget(toolbar);
        vLayout->addWidget(toolbar2);

        setFocusProxy(queryWidget);

        connect(queryWidget, SIGNAL(search()), this, SLOT(search()));
        connect(resultWidget, SIGNAL(requestShowLink(QUrl)), this,
            SIGNAL(linkActivated(QUrl)));

        connect(searchEngine, SIGNAL(searchingStarted()), this,
            SLOT(searchingStarted()));
        connect(searchEngine, SIGNAL(searchingFinished(int)), this,
            SLOT(searchingFinished(int)));

        QTextBrowser* browser = qFindChild<QTextBrowser*>(resultWidget);
        browser->viewport()->installEventFilter(this);

        connect(searchEngine, SIGNAL(indexingStarted()), this,
            SLOT(indexingStarted()));
        connect(searchEngine, SIGNAL(indexingFinished()), this,
            SLOT(indexingFinished()));

        QMetaObject::invokeMethod(&LocalHelpManager::helpEngine(), "setupFinished",
            Qt::QueuedConnection);
    }
}

void SearchWidget::search() const
{
    static QStringList charsToEscapeList;
    if (charsToEscapeList.isEmpty()) {
        charsToEscapeList << QLatin1String("\\") << QLatin1String("+")
            << QLatin1String("-") << QLatin1String("!") << QLatin1String("(")
            << QLatin1String(")") << QLatin1String(":") << QLatin1String("^")
            << QLatin1String("[") << QLatin1String("]") << QLatin1String("{")
            << QLatin1String("}") << QLatin1String("~");
    }

    static QString escapeChar(QLatin1String("\\"));
    static QRegExp regExp(QLatin1String("[\\+\\-\\!\\(\\)\\^\\[\\]\\{\\}~:]"));

    QList<QHelpSearchQuery> escapedQueries;
    const QList<QHelpSearchQuery> queries = searchEngine->queryWidget()->query();
    foreach (const QHelpSearchQuery &query, queries) {
        QHelpSearchQuery escapedQuery;
        escapedQuery.fieldName = query.fieldName;
        foreach (QString word, query.wordList) {
            if (word.contains(regExp)) {
                foreach (const QString &charToEscape, charsToEscapeList)
                    word.replace(charToEscape, escapeChar + charToEscape);
            }
            escapedQuery.wordList.append(word);
        }
        escapedQueries.append(escapedQuery);
    }
    searchEngine->search(escapedQueries);
}

void SearchWidget::searchingStarted()
{
    qApp->setOverrideCursor(QCursor(Qt::WaitCursor));
}

void SearchWidget::searchingFinished(int hits)
{
    Q_UNUSED(hits)
    qApp->restoreOverrideCursor();
}

void SearchWidget::indexingStarted()
{
    Q_ASSERT(!m_progress);
    m_progress = new QFutureInterface<void>();
    Core::ICore::progressManager() ->addTask(m_progress->future(),
        tr("Indexing"), QLatin1String("Help.Indexer"));
    m_progress->setProgressRange(0, 2);
    m_progress->setProgressValueAndText(1, tr("Indexing Documentation..."));
    m_progress->reportStarted();

    m_watcher.setFuture(m_progress->future());
    connect(&m_watcher, SIGNAL(canceled()), searchEngine, SLOT(cancelIndexing()));
}

void SearchWidget::indexingFinished()
{
    m_progress->reportFinished();

    delete m_progress;
    m_progress = NULL;
}

bool SearchWidget::eventFilter(QObject *o, QEvent *e)
{
    QTextBrowser *browser = qFindChild<QTextBrowser *>(resultWidget);
    if (browser && o == browser->viewport()
        && e->type() == QEvent::MouseButtonRelease){
        QMouseEvent *me = static_cast<QMouseEvent *>(e);
        QUrl link = resultWidget->linkAt(me->pos());
        if (!link.isEmpty() || link.isValid()) {
            bool controlPressed = me->modifiers() & Qt::ControlModifier;
            if ((me->button() == Qt::LeftButton && controlPressed)
                || (me->button() == Qt::MidButton)) {
                    OpenPagesManager::instance().createPageFromSearch(link);
            }
        }
    }
    return QWidget::eventFilter(o,e);
}

void SearchWidget::contextMenuEvent(QContextMenuEvent *contextMenuEvent)
{
    QTextBrowser *browser = qFindChild<QTextBrowser *>(resultWidget);
    if (!browser)
        return;

    QPoint point = browser->mapFromGlobal(contextMenuEvent->globalPos());
    if (!browser->rect().contains(point, true))
        return;

    QAction *openLink = 0;
    QAction *openLinkInNewTab = 0;
    QAction *copyAnchorAction = 0;

    QMenu menu;
    QUrl link = browser->anchorAt(point);
    if (!link.isEmpty() && link.isValid()) {
        if (link.isRelative())
            link = browser->source().resolved(link);
        openLink = menu.addAction(tr("Open Link"));
        openLinkInNewTab = menu.addAction(tr("Open Link as New Page"));
        copyAnchorAction = menu.addAction(tr("Copy Link"));
    } else if (browser->textCursor().hasSelection()) {
        menu.addAction(tr("Copy"), browser, SLOT(copy()));
    } else {
        menu.addAction(tr("Reload"), browser, SLOT(reload()));
    }

    QAction *usedAction = menu.exec(mapToGlobal(contextMenuEvent->pos()));
    if (usedAction == openLink) {
        browser->selectAll();
    } else if (usedAction == openLinkInNewTab) {
        OpenPagesManager::instance().createPageFromSearch(link);
    } else if (usedAction == copyAnchorAction) {
        QApplication::clipboard()->setText(link.toString());
    }
}
<|endoftext|>


<commit_before>#include "Atm_servo.hpp"

/* Add optional parameters for the state machine to begin()
 * Add extra initialization code
 */

Atm_servo& Atm_servo::begin( int pin, int pos ) {
  // clang-format off
  const static state_t state_table[] PROGMEM = {
    /*                  ON_ENTER    ON_LOOP  ON_EXIT  EVT_MVUP  EVT_MVDN  EVT_TIMER      ELSE */
    /*      IDLE */     ENT_IDLE,        -1,      -1,       UP,     DOWN,        -1,       -1,
    /*        UP */       ENT_UP,        -1,      -1,       -1,       -1,   UP_NEXT,       -1,
    /*   UP_NEXT */           -1,        -1,      -1,       UP,     DOWN,        -1, FINISHED,
    /*      DOWN */     ENT_DOWN,        -1,      -1,       -1,       -1, DOWN_NEXT,       -1,
    /* DOWN_NEXT */           -1,        -1,      -1,       UP,     DOWN,        -1, FINISHED,
    /*  FINISHED */ ENT_FINISHED,        -1,      -1,       -1,       -1,        -1,     IDLE,
  };
  // clang-format on
  Machine::begin( state_table, ELSE );
  this->pin = pin;
  servo.attach( pin );
  servo_pos = pos;
  servo_dest = pos;
  step_size = 180;
  timer.set( step_time = 0 );
  servo.write( servo_dest );
  return *this;
}

/* Add C++ code for each internally handled event (input)
 * The code must return 1 to trigger the event
 */

int Atm_servo::event( int id ) {
  switch ( id ) {
    case EVT_MVUP:
      return servo_dest > servo_pos;
    case EVT_MVDN:
      return servo_dest < servo_pos;
    case EVT_TIMER:
      return timer.expired( this );
  }
  return 0;
}

/* Add C++ code for each action
 * This generates the 'output' for the state machine
 */

void Atm_servo::action( int id ) {
  switch ( id ) {
    case ENT_IDLE:
      return;
    case ENT_UP:
      push( connectors, ON_CHANGE, true, servo_pos, 1 );
      servo_pos += step_size;
      if ( servo_pos > servo_dest ) servo_pos = servo_dest;
      servo.write( servo_pos );
      timer.set( step_time );
      return;
    case ENT_DOWN:
      push( connectors, ON_CHANGE, false, servo_pos, 0 );
      servo_pos -= step_size;
      if ( servo_pos < servo_dest ) servo_pos = servo_dest;
      servo.write( servo_pos );
      timer.set( step_time );
      return;
    case ENT_FINISHED:
      push( connectors, ON_FINISH, 0, servo_pos, 0 );
      return;
  }
}

Atm_servo& Atm_servo::step( int degrees, int time ) {
  step_size = degrees;
  timer.set( step_time = time );
  return *this;
}

Atm_servo& Atm_servo::position( int pos ) {
  servo_dest = pos;
  return *this;
}

int Atm_servo::position( void ) {
  return servo_pos;
}

/* Optionally override the default trigger() method
 * Control how your machine processes triggers
 */

Atm_servo& Atm_servo::trigger( int event ) {
  switch ( event ) {
    case EVT_MVUP:
      servo_dest += step_size;
      if ( servo_dest > 180 ) servo_dest = 180;
      break;
    case EVT_MVDN:
      servo_dest -= step_size;
      if ( servo_dest < 0 ) servo_dest = 0;
      break;
    default:
      servo_dest = event;
      break;
  }
  return *this;
}

/* Optionally override the default state() method
 * Control what the machine returns when another process requests its state
 */

int Atm_servo::state( void ) {
  return Machine::state();
}

/* Nothing customizable below this line
 ************************************************************************************************
*/

/* onChange() push connector variants ( slots 2, autostore 0, broadcast 0 )
 *
 * Usage in action() handler: push( connectors, ON_CHANGE, sub, v, up );
 */

Atm_servo& Atm_servo::onChange( Machine& machine, int event ) {
  onPush( connectors, ON_CHANGE, 0, 2, 1, machine, event );
  return *this;
}
Atm_servo& Atm_servo::onChange( atm_cb_push_t callback, int idx ) {
  onPush( connectors, ON_CHANGE, 0, 2, 1, callback, idx );
  return *this;
}
Atm_servo& Atm_servo::onChange( int sub, Machine& machine, int event ) {
  onPush( connectors, ON_CHANGE, sub, 2, 0, machine, event );
  return *this;
}
Atm_servo& Atm_servo::onChange( int sub, atm_cb_push_t callback, int idx ) {
  onPush( connectors, ON_CHANGE, sub, 2, 0, callback, idx );
  return *this;
}

/* onFinish() push connector variants ( slots 1, autostore 0, broadcast 0 )
 *
 * Usage in action() handler: push( connectors, ON_FINISH, 0, v, up );
 */

Atm_servo& Atm_servo::onFinish( Machine& machine, int event ) {
  onPush( connectors, ON_FINISH, 0, 1, 1, machine, event );
  return *this;
}
Atm_servo& Atm_servo::onFinish( atm_cb_push_t callback, int idx ) {
  onPush( connectors, ON_FINISH, 0, 1, 1, callback, idx );
  return *this;
}

/* State trace method
 * Sets the symbol table and the default logging method for serial monitoring
 */

Atm_servo& Atm_servo::trace( Stream& stream ) {
  Machine::setTrace( &stream, atm_serial_debug::trace, "SERVO\0EVT_MVUP\0EVT_MVDN\0EVT_TIMER\0ELSE\0IDLE\0UP\0UP_NEXT\0DOWN\0DOWN_NEXT\0FINISHED" );
  return *this;
}
<commit_msg>Fixed trigger values<commit_after>#include "Atm_servo.hpp"

/* Add optional parameters for the state machine to begin()
 * Add extra initialization code
 */

Atm_servo& Atm_servo::begin( int pin, int pos ) {
  // clang-format off
  const static state_t state_table[] PROGMEM = {
    /*                  ON_ENTER    ON_LOOP  ON_EXIT  EVT_MVUP  EVT_MVDN  EVT_TIMER      ELSE */
    /*      IDLE */     ENT_IDLE,        -1,      -1,       UP,     DOWN,        -1,       -1,
    /*        UP */       ENT_UP,        -1,      -1,       -1,       -1,   UP_NEXT,       -1,
    /*   UP_NEXT */           -1,        -1,      -1,       UP,     DOWN,        -1, FINISHED,
    /*      DOWN */     ENT_DOWN,        -1,      -1,       -1,       -1, DOWN_NEXT,       -1,
    /* DOWN_NEXT */           -1,        -1,      -1,       UP,     DOWN,        -1, FINISHED,
    /*  FINISHED */ ENT_FINISHED,        -1,      -1,       -1,       -1,        -1,     IDLE,
  };
  // clang-format on
  Machine::begin( state_table, ELSE );
  this->pin = pin;
  servo.attach( pin );
  servo_pos = pos;
  servo_dest = pos;
  step_size = 180;
  timer.set( step_time = 0 );
  servo.write( servo_dest );
  return *this;
}

/* Add C++ code for each internally handled event (input)
 * The code must return 1 to trigger the event
 */

int Atm_servo::event( int id ) {
  switch ( id ) {
    case EVT_MVUP:
      return servo_dest > servo_pos;
    case EVT_MVDN:
      return servo_dest < servo_pos;
    case EVT_TIMER:
      return timer.expired( this );
  }
  return 0;
}

/* Add C++ code for each action
 * This generates the 'output' for the state machine
 */

void Atm_servo::action( int id ) {
  switch ( id ) {
    case ENT_IDLE:
      return;
    case ENT_UP:
      push( connectors, ON_CHANGE, true, servo_pos, 1 );
      servo_pos += step_size;
      if ( servo_pos > servo_dest ) servo_pos = servo_dest;
      servo.write( servo_pos );
      timer.set( step_time );
      return;
    case ENT_DOWN:
      push( connectors, ON_CHANGE, false, servo_pos, 0 );
      servo_pos -= step_size;
      if ( servo_pos < servo_dest ) servo_pos = servo_dest;
      servo.write( servo_pos );
      timer.set( step_time );
      return;
    case ENT_FINISHED:
      push( connectors, ON_FINISH, 0, servo_pos, 0 );
      return;
  }
}

Atm_servo& Atm_servo::step( int degrees, int time ) {
  step_size = degrees;
  timer.set( step_time = time );
  return *this;
}

Atm_servo& Atm_servo::position( int pos ) {
  servo_dest = pos;
  return *this;
}

int Atm_servo::position( void ) {
  return servo_pos;
}

/* Optionally override the default trigger() method
 * Control how your machine processes triggers
 */

Atm_servo& Atm_servo::trigger( int event ) {
  switch ( event ) {
    case EVT_UP:
      servo_dest += step_size;
      if ( servo_dest > 180 ) servo_dest = 180;
      break;
    case EVT_DOWN:
      servo_dest -= step_size;
      if ( servo_dest < 0 ) servo_dest = 0;
      break;
    default:
      servo_dest = event;
      break;
  }
  return *this;
}

/* Optionally override the default state() method
 * Control what the machine returns when another process requests its state
 */

int Atm_servo::state( void ) {
  return Machine::state();
}

/* Nothing customizable below this line
 ************************************************************************************************
*/

/* onChange() push connector variants ( slots 2, autostore 0, broadcast 0 )
 *
 * Usage in action() handler: push( connectors, ON_CHANGE, sub, v, up );
 */

Atm_servo& Atm_servo::onChange( Machine& machine, int event ) {
  onPush( connectors, ON_CHANGE, 0, 2, 1, machine, event );
  return *this;
}
Atm_servo& Atm_servo::onChange( atm_cb_push_t callback, int idx ) {
  onPush( connectors, ON_CHANGE, 0, 2, 1, callback, idx );
  return *this;
}
Atm_servo& Atm_servo::onChange( int sub, Machine& machine, int event ) {
  onPush( connectors, ON_CHANGE, sub, 2, 0, machine, event );
  return *this;
}
Atm_servo& Atm_servo::onChange( int sub, atm_cb_push_t callback, int idx ) {
  onPush( connectors, ON_CHANGE, sub, 2, 0, callback, idx );
  return *this;
}

/* onFinish() push connector variants ( slots 1, autostore 0, broadcast 0 )
 *
 * Usage in action() handler: push( connectors, ON_FINISH, 0, v, up );
 */

Atm_servo& Atm_servo::onFinish( Machine& machine, int event ) {
  onPush( connectors, ON_FINISH, 0, 1, 1, machine, event );
  return *this;
}
Atm_servo& Atm_servo::onFinish( atm_cb_push_t callback, int idx ) {
  onPush( connectors, ON_FINISH, 0, 1, 1, callback, idx );
  return *this;
}

/* State trace method
 * Sets the symbol table and the default logging method for serial monitoring
 */

Atm_servo& Atm_servo::trace( Stream& stream ) {
  Machine::setTrace( &stream, atm_serial_debug::trace, "SERVO\0EVT_MVUP\0EVT_MVDN\0EVT_TIMER\0ELSE\0IDLE\0UP\0UP_NEXT\0DOWN\0DOWN_NEXT\0FINISHED" );
  return *this;
}
<|endoftext|>


<commit_before>/*
This file is part of WME Lite.
http://dead-code.org/redir.php?target=wmelite

Copyright (c) 2011 Jan Nedoma

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 "dcgf.h"
#include "BViewport.h"

namespace WinterMute {

IMPLEMENT_PERSISTENT(CBViewport, false)

//////////////////////////////////////////////////////////////////////////
CBViewport::CBViewport(CBGame *inGame): CBBase(inGame) {
	CBPlatform::SetRectEmpty(&m_Rect);
	m_MainObject = NULL;
	m_OffsetX = m_OffsetY = 0;
}

//////////////////////////////////////////////////////////////////////////
CBViewport::~CBViewport() {

}

//////////////////////////////////////////////////////////////////////////
HRESULT CBViewport::Persist(CBPersistMgr *PersistMgr) {

	PersistMgr->Transfer(TMEMBER(Game));

	PersistMgr->Transfer(TMEMBER(m_MainObject));
	PersistMgr->Transfer(TMEMBER(m_OffsetX));
	PersistMgr->Transfer(TMEMBER(m_OffsetY));
	PersistMgr->Transfer(TMEMBER(m_Rect));

	return S_OK;
}

//////////////////////////////////////////////////////////////////////////
HRESULT CBViewport::SetRect(int left, int top, int right, int bottom, bool NoCheck) {
	if (!NoCheck) {
		left = std::max(left, 0);
		top = std::max(top, 0);
		right = std::min(right, Game->m_Renderer->m_Width);
		bottom = std::min(bottom, Game->m_Renderer->m_Height);
	}

	CBPlatform::SetRect(&m_Rect, left, top, right, bottom);
	m_OffsetX = left;
	m_OffsetY = top;
	return S_OK;
}

//////////////////////////////////////////////////////////////////////////
RECT *CBViewport::GetRect() {
	return &m_Rect;
}

//////////////////////////////////////////////////////////////////////////
int CBViewport::GetWidth() {
	return m_Rect.right - m_Rect.left;
}

//////////////////////////////////////////////////////////////////////////
int CBViewport::GetHeight() {
	return m_Rect.bottom - m_Rect.top;
}

} // end of namespace WinterMute
<commit_msg>WINTERMUTE: Make BViewPort independent of dcgf<commit_after>/*
This file is part of WME Lite.
http://dead-code.org/redir.php?target=wmelite

Copyright (c) 2011 Jan Nedoma

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 "BGame.h"
#include "PlatformSDL.h"
#include "BViewport.h"

namespace WinterMute {

IMPLEMENT_PERSISTENT(CBViewport, false)

//////////////////////////////////////////////////////////////////////////
CBViewport::CBViewport(CBGame *inGame): CBBase(inGame) {
	CBPlatform::SetRectEmpty(&m_Rect);
	m_MainObject = NULL;
	m_OffsetX = m_OffsetY = 0;
}

//////////////////////////////////////////////////////////////////////////
CBViewport::~CBViewport() {

}

//////////////////////////////////////////////////////////////////////////
HRESULT CBViewport::Persist(CBPersistMgr *PersistMgr) {

	PersistMgr->Transfer(TMEMBER(Game));

	PersistMgr->Transfer(TMEMBER(m_MainObject));
	PersistMgr->Transfer(TMEMBER(m_OffsetX));
	PersistMgr->Transfer(TMEMBER(m_OffsetY));
	PersistMgr->Transfer(TMEMBER(m_Rect));

	return S_OK;
}

//////////////////////////////////////////////////////////////////////////
HRESULT CBViewport::SetRect(int left, int top, int right, int bottom, bool NoCheck) {
	if (!NoCheck) {
		left = std::max(left, 0);
		top = std::max(top, 0);
		right = std::min(right, Game->m_Renderer->m_Width);
		bottom = std::min(bottom, Game->m_Renderer->m_Height);
	}

	CBPlatform::SetRect(&m_Rect, left, top, right, bottom);
	m_OffsetX = left;
	m_OffsetY = top;
	return S_OK;
}

//////////////////////////////////////////////////////////////////////////
RECT *CBViewport::GetRect() {
	return &m_Rect;
}

//////////////////////////////////////////////////////////////////////////
int CBViewport::GetWidth() {
	return m_Rect.right - m_Rect.left;
}

//////////////////////////////////////////////////////////////////////////
int CBViewport::GetHeight() {
	return m_Rect.bottom - m_Rect.top;
}

} // end of namespace WinterMute
<|endoftext|>


<commit_before>/** \file   Archive.cc
 *  \brief  Implementations of the archive processing functions and classes.
 *  \author Dr. Johannes Ruscheinski (johannes.ruscheinski@uni-tuebingen.de)
 *
 *  \copyright 2016-2018 Universitätsbibliothek Tübingen.  All rights reserved.
 *
 *  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 "Archive.h"
#include <cstring>
#include <fcntl.h>
#include "Compiler.h"
#include "File.h"
#include "FileUtil.h"
#include "StringUtil.h"
#include "util.h"

namespace Archive {

const std::string Reader::EntryInfo::getFilename() const {
    return ::archive_entry_pathname(archive_entry_);
}

bool Reader::EntryInfo::isRegularFile() const {
    return ::archive_entry_filetype(archive_entry_) == AE_IFREG;
}

bool Reader::EntryInfo::isDirectory() const {
    return ::archive_entry_filetype(archive_entry_) == AE_IFDIR;
}

const unsigned DEFAULT_BLOCKSIZE(10240);

Reader::Reader(const std::string &archive_file_name) {
    archive_handle_ = ::archive_read_new();
    ::archive_read_support_filter_all(archive_handle_);
    ::archive_read_support_format_all(archive_handle_);
    if (unlikely(::archive_read_open_filename(archive_handle_, archive_file_name.c_str(), DEFAULT_BLOCKSIZE)
                 != ARCHIVE_OK))
        LOG_ERROR("archive_read_open_filename(3) failed: " + std::string(::archive_error_string(archive_handle_)));
}

Reader::~Reader() {
    if (unlikely(::archive_read_free(archive_handle_) != ARCHIVE_OK))
        LOG_ERROR("archive_read_free(3) failed!");
}

bool Reader::getNext(EntryInfo * const info) {
    int status;
    while ((status = ::archive_read_next_header(archive_handle_, &info->archive_entry_)) == ARCHIVE_RETRY)
        /* Intentionally empty! */;

    if (status == ARCHIVE_OK)
        return true;
    if (status == ARCHIVE_EOF)
        return false;

    LOG_ERROR("something went wrong! (" + std::string(::archive_error_string(archive_handle_)) + ")");
}

ssize_t Reader::read(char * const buffer, const size_t size) {
    ssize_t retval;
    do
        retval = ::archive_read_data(archive_handle_, reinterpret_cast<void * const>(buffer), size);
    while (retval == ARCHIVE_RETRY);

    return (retval == ARCHIVE_FATAL or retval == ARCHIVE_WARN) ? -1 : retval;
}

bool Reader::extractEntry(const std::string &member_name, std::string output_filename) {
    if (output_filename.empty())
        output_filename = member_name;

    EntryInfo entry_info;
    while (getNext(&entry_info)) {
        if (entry_info.getFilename() != member_name)
            continue;

        if (entry_info.isDirectory())
            LOG_ERROR("an't extract a directory!");

        const int to_fd(::open(output_filename.c_str(), O_WRONLY | O_CREAT, 0600));
        if (unlikely(to_fd == -1))
            LOG_ERROR("failed to open \"" + output_filename  + "\" for writing!");

        char buf[BUFSIZ];
        for (;;) {
            const ssize_t no_of_bytes(read(&buf[0], sizeof(buf)));
            if (no_of_bytes == 0) {
                ::close(to_fd);
                return true;
            }

            if (unlikely(no_of_bytes < 0))
                LOG_ERROR(getLastErrorMessage());

            if (unlikely(::write(to_fd, &buf[0], no_of_bytes) != no_of_bytes))
                LOG_ERROR("write(2) failed!");
        }

        ::close(to_fd);
    }

    return false;
}

Writer::Writer(const std::string &archive_file_name, const std::string &archive_write_options, const FileType file_type)
    : archive_entry_(nullptr)
{
    archive_handle_ = ::archive_write_new();

    switch (file_type) {
    case FileType::AUTO:
        if (StringUtil::EndsWith(archive_file_name, ".tar")) {
            if (unlikely(not archive_write_options.empty()))
                LOG_ERROR("no write options are currently supported for the uncompressed tar format!");
            ::archive_write_set_format_pax_restricted(archive_handle_);
        } else if (StringUtil::EndsWith(archive_file_name, ".tar.gz")) {
            ::archive_write_add_filter_gzip(archive_handle_);
            if (unlikely(::archive_write_set_options(archive_handle_, archive_write_options.c_str()) != ARCHIVE_OK))
                LOG_ERROR("failed to call archive_write_set_options(3) w/ \"" + archive_write_options + "\"!");
            ::archive_write_set_format_pax_restricted(archive_handle_);
        } else
            LOG_ERROR("FileType::AUTO selected but," " can't guess the file type from the given filename \"" + archive_file_name + "\"!");
        break;
    case FileType::TAR:
        if (unlikely(not archive_write_options.empty()))
            LOG_ERROR("no write options are currently supported for the uncompressed tar format! (2)");
        ::archive_write_set_format_pax_restricted(archive_handle_);
        break;
    case FileType::GZIPPED_TAR:
        ::archive_write_add_filter_gzip(archive_handle_);
        if (unlikely(::archive_write_set_options(archive_handle_, archive_write_options.c_str()) != ARCHIVE_OK))
            LOG_ERROR("failed to call archive_write_set_options(3) w/ \"" + archive_write_options + "\"! (2)");
        ::archive_write_set_format_pax_restricted(archive_handle_);
        break;
    }

    if (unlikely(::archive_write_open_filename(archive_handle_, archive_file_name.c_str()) != ARCHIVE_OK))
        LOG_ERROR("archive_write_open_filename(3) failed: " + std::string(::archive_error_string(archive_handle_)));
}

Writer::~Writer() {
    if (archive_entry_ != nullptr)
        ::archive_entry_free(archive_entry_);

    if (unlikely(::archive_write_close(archive_handle_) != ARCHIVE_OK))
        LOG_ERROR("archive_write_close(3) failed: " + std::string(::archive_error_string(archive_handle_)));
    if (unlikely(::archive_write_free(archive_handle_) != ARCHIVE_OK))
        LOG_ERROR("archive_write_free(3) failed: " + std::string(::archive_error_string(archive_handle_)));
}

void Writer::add(const std::string &filename, std::string archive_name) {
    if (archive_name.empty())
        archive_name = filename;
    if (unlikely(already_seen_archive_names_.find(archive_name) != already_seen_archive_names_.end()))
        LOG_ERROR("attempt to store a duplicate archive entry name \"" + archive_name + "\"!");
    else
        already_seen_archive_names_.emplace(archive_name);

    struct stat stat_buf;
    if (unlikely(::stat(filename.c_str(), &stat_buf) != 0))
        LOG_ERROR("stat(2) on \"" + filename + "\" failed: " + std::string(::strerror(errno)));

    if (archive_entry_ == nullptr)
        archive_entry_ = ::archive_entry_new();
    else
        ::archive_entry_clear(archive_entry_);
    ::archive_entry_set_pathname(archive_entry_, archive_name.c_str());
    ::archive_entry_copy_stat(archive_entry_, &stat_buf);

    int status;
    while ((status = ::archive_write_header(archive_handle_, archive_entry_)) == ARCHIVE_RETRY)
        /* Intentionally empty! */;
    if (unlikely(status != ARCHIVE_OK))
        LOG_ERROR("archive_write_header(3) failed! (" + std::string(::archive_error_string(archive_handle_)));

    File input(filename, "r", File::THROW_ON_ERROR);
    char buffer[DEFAULT_BLOCKSIZE];
    size_t count;
    while ((count = input.read(buffer, DEFAULT_BLOCKSIZE)) > 0) {
        if (count < DEFAULT_BLOCKSIZE and input.anErrorOccurred())
            LOG_ERROR("error reading \"" + filename + "\" !");
        if (unlikely(::archive_write_data(archive_handle_, buffer, count) != static_cast<const ssize_t>(count)))
            LOG_ERROR("archive_write_data(3) failed: " + std::string(::archive_error_string(archive_handle_)));
    }
}

void Writer::addEntry(const std::string &filename, const int64_t size, const mode_t mode, const EntryType entry_type) {
    if (archive_entry_ != nullptr)
        ::archive_entry_clear(archive_entry_);
    else
        archive_entry_ = ::archive_entry_new();

    ::archive_entry_set_pathname(archive_entry_, filename.c_str());
    ::archive_entry_set_size(archive_entry_, size);
    if (entry_type == EntryType::REGULAR_FILE)
        ::archive_entry_set_filetype(archive_entry_, AE_IFREG);
    else
        LOG_ERROR("unsupported entry type: " + std::to_string(static_cast<int>(entry_type)) + "!");
    ::archive_entry_set_perm(archive_entry_, mode);
}

void Writer::write(char * const buffer, const size_t size) {
    if (::archive_write_data(archive_handle_, buffer, size) < 0)
        LOG_ERROR("archive_write_data failed!");
}

void UnpackArchive(const std::string &archive_name, const std::string &directory) {
    if (unlikely(not FileUtil::MakeDirectory(directory)))
        LOG_ERROR("failed to create directory \"" + directory + "\"!");

    Reader reader(archive_name);
    Reader::EntryInfo file_info;
    while (reader.getNext(&file_info)) {
        if (file_info.empty())
            continue;

        if (unlikely(not file_info.isRegularFile()))
            LOG_ERROR("unexpectedly, the entry \"" + file_info.getFilename() + "\" in \"" + archive_name + "\" is not a regular file!");

        const std::string output_filename(directory + "/" + file_info.getFilename());
        const auto output(FileUtil::OpenOutputFileOrDie(output_filename));

        char buf[8192];
        size_t read_count;
        while ((read_count = reader.read(buf, sizeof buf)) > 0) {
            if (unlikely(output->write(buf, read_count) != read_count))
                LOG_ERROR("failed to write data to \"" + output->getPath() + "\"! (No room?)");
        }
    }

}

} // namespace Archive
<commit_msg>Added missing call.<commit_after>/** \file   Archive.cc
 *  \brief  Implementations of the archive processing functions and classes.
 *  \author Dr. Johannes Ruscheinski (johannes.ruscheinski@uni-tuebingen.de)
 *
 *  \copyright 2016-2018 Universitätsbibliothek Tübingen.  All rights reserved.
 *
 *  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 "Archive.h"
#include <cstring>
#include <fcntl.h>
#include "Compiler.h"
#include "File.h"
#include "FileUtil.h"
#include "StringUtil.h"
#include "util.h"

namespace Archive {

const std::string Reader::EntryInfo::getFilename() const {
    return ::archive_entry_pathname(archive_entry_);
}

bool Reader::EntryInfo::isRegularFile() const {
    return ::archive_entry_filetype(archive_entry_) == AE_IFREG;
}

bool Reader::EntryInfo::isDirectory() const {
    return ::archive_entry_filetype(archive_entry_) == AE_IFDIR;
}

const unsigned DEFAULT_BLOCKSIZE(10240);

Reader::Reader(const std::string &archive_file_name) {
    archive_handle_ = ::archive_read_new();
    ::archive_read_support_filter_all(archive_handle_);
    ::archive_read_support_format_all(archive_handle_);
    if (unlikely(::archive_read_open_filename(archive_handle_, archive_file_name.c_str(), DEFAULT_BLOCKSIZE)
                 != ARCHIVE_OK))
        LOG_ERROR("archive_read_open_filename(3) failed: " + std::string(::archive_error_string(archive_handle_)));
}

Reader::~Reader() {
    if (unlikely(::archive_read_free(archive_handle_) != ARCHIVE_OK))
        LOG_ERROR("archive_read_free(3) failed!");
}

bool Reader::getNext(EntryInfo * const info) {
    int status;
    while ((status = ::archive_read_next_header(archive_handle_, &info->archive_entry_)) == ARCHIVE_RETRY)
        /* Intentionally empty! */;

    if (status == ARCHIVE_OK)
        return true;
    if (status == ARCHIVE_EOF)
        return false;

    LOG_ERROR("something went wrong! (" + std::string(::archive_error_string(archive_handle_)) + ")");
}

ssize_t Reader::read(char * const buffer, const size_t size) {
    ssize_t retval;
    do
        retval = ::archive_read_data(archive_handle_, reinterpret_cast<void * const>(buffer), size);
    while (retval == ARCHIVE_RETRY);

    return (retval == ARCHIVE_FATAL or retval == ARCHIVE_WARN) ? -1 : retval;
}

bool Reader::extractEntry(const std::string &member_name, std::string output_filename) {
    if (output_filename.empty())
        output_filename = member_name;

    EntryInfo entry_info;
    while (getNext(&entry_info)) {
        if (entry_info.getFilename() != member_name)
            continue;

        if (entry_info.isDirectory())
            LOG_ERROR("an't extract a directory!");

        const int to_fd(::open(output_filename.c_str(), O_WRONLY | O_CREAT, 0600));
        if (unlikely(to_fd == -1))
            LOG_ERROR("failed to open \"" + output_filename  + "\" for writing!");

        char buf[BUFSIZ];
        for (;;) {
            const ssize_t no_of_bytes(read(&buf[0], sizeof(buf)));
            if (no_of_bytes == 0) {
                ::close(to_fd);
                return true;
            }

            if (unlikely(no_of_bytes < 0))
                LOG_ERROR(getLastErrorMessage());

            if (unlikely(::write(to_fd, &buf[0], no_of_bytes) != no_of_bytes))
                LOG_ERROR("write(2) failed!");
        }

        ::close(to_fd);
    }

    return false;
}

Writer::Writer(const std::string &archive_file_name, const std::string &archive_write_options, const FileType file_type)
    : archive_entry_(nullptr)
{
    archive_handle_ = ::archive_write_new();

    switch (file_type) {
    case FileType::AUTO:
        if (StringUtil::EndsWith(archive_file_name, ".tar")) {
            if (unlikely(not archive_write_options.empty()))
                LOG_ERROR("no write options are currently supported for the uncompressed tar format!");
            ::archive_write_set_format_pax_restricted(archive_handle_);
        } else if (StringUtil::EndsWith(archive_file_name, ".tar.gz")) {
            ::archive_write_add_filter_gzip(archive_handle_);
            if (unlikely(::archive_write_set_options(archive_handle_, archive_write_options.c_str()) != ARCHIVE_OK))
                LOG_ERROR("failed to call archive_write_set_options(3) w/ \"" + archive_write_options + "\"!");
            ::archive_write_set_format_pax_restricted(archive_handle_);
        } else
            LOG_ERROR("FileType::AUTO selected but," " can't guess the file type from the given filename \"" + archive_file_name + "\"!");
        break;
    case FileType::TAR:
        if (unlikely(not archive_write_options.empty()))
            LOG_ERROR("no write options are currently supported for the uncompressed tar format! (2)");
        ::archive_write_set_format_pax_restricted(archive_handle_);
        break;
    case FileType::GZIPPED_TAR:
        ::archive_write_add_filter_gzip(archive_handle_);
        if (unlikely(::archive_write_set_options(archive_handle_, archive_write_options.c_str()) != ARCHIVE_OK))
            LOG_ERROR("failed to call archive_write_set_options(3) w/ \"" + archive_write_options + "\"! (2)");
        ::archive_write_set_format_pax_restricted(archive_handle_);
        break;
    }

    if (unlikely(::archive_write_open_filename(archive_handle_, archive_file_name.c_str()) != ARCHIVE_OK))
        LOG_ERROR("archive_write_open_filename(3) failed: " + std::string(::archive_error_string(archive_handle_)));
}

Writer::~Writer() {
    if (archive_entry_ != nullptr)
        ::archive_entry_free(archive_entry_);

    if (unlikely(::archive_write_close(archive_handle_) != ARCHIVE_OK))
        LOG_ERROR("archive_write_close(3) failed: " + std::string(::archive_error_string(archive_handle_)));
    if (unlikely(::archive_write_free(archive_handle_) != ARCHIVE_OK))
        LOG_ERROR("archive_write_free(3) failed: " + std::string(::archive_error_string(archive_handle_)));
}

void Writer::add(const std::string &filename, std::string archive_name) {
    if (archive_name.empty())
        archive_name = filename;
    if (unlikely(already_seen_archive_names_.find(archive_name) != already_seen_archive_names_.end()))
        LOG_ERROR("attempt to store a duplicate archive entry name \"" + archive_name + "\"!");
    else
        already_seen_archive_names_.emplace(archive_name);

    struct stat stat_buf;
    if (unlikely(::stat(filename.c_str(), &stat_buf) != 0))
        LOG_ERROR("stat(2) on \"" + filename + "\" failed: " + std::string(::strerror(errno)));

    if (archive_entry_ == nullptr)
        archive_entry_ = ::archive_entry_new();
    else
        ::archive_entry_clear(archive_entry_);
    ::archive_entry_set_pathname(archive_entry_, archive_name.c_str());
    ::archive_entry_copy_stat(archive_entry_, &stat_buf);

    int status;
    while ((status = ::archive_write_header(archive_handle_, archive_entry_)) == ARCHIVE_RETRY)
        /* Intentionally empty! */;
    if (unlikely(status != ARCHIVE_OK))
        LOG_ERROR("archive_write_header(3) failed! (" + std::string(::archive_error_string(archive_handle_)));

    File input(filename, "r", File::THROW_ON_ERROR);
    char buffer[DEFAULT_BLOCKSIZE];
    size_t count;
    while ((count = input.read(buffer, DEFAULT_BLOCKSIZE)) > 0) {
        if (count < DEFAULT_BLOCKSIZE and input.anErrorOccurred())
            LOG_ERROR("error reading \"" + filename + "\" !");
        if (unlikely(::archive_write_data(archive_handle_, buffer, count) != static_cast<const ssize_t>(count)))
            LOG_ERROR("archive_write_data(3) failed: " + std::string(::archive_error_string(archive_handle_)));
    }
}

void Writer::addEntry(const std::string &filename, const int64_t size, const mode_t mode, const EntryType entry_type) {
    if (archive_entry_ != nullptr)
        ::archive_entry_clear(archive_entry_);
    else
        archive_entry_ = ::archive_entry_new();

    ::archive_entry_set_pathname(archive_entry_, filename.c_str());
    ::archive_entry_set_size(archive_entry_, size);
    if (entry_type == EntryType::REGULAR_FILE)
        ::archive_entry_set_filetype(archive_entry_, AE_IFREG);
    else
        LOG_ERROR("unsupported entry type: " + std::to_string(static_cast<int>(entry_type)) + "!");
    ::archive_entry_set_perm(archive_entry_, mode);
    ::archive_write_header(archive_handle_, archive_entry_);
}

void Writer::write(char * const buffer, const size_t size) {
    if (::archive_write_data(archive_handle_, buffer, size) < 0)
        LOG_ERROR("archive_write_data failed!");
}

void UnpackArchive(const std::string &archive_name, const std::string &directory) {
    if (unlikely(not FileUtil::MakeDirectory(directory)))
        LOG_ERROR("failed to create directory \"" + directory + "\"!");

    Reader reader(archive_name);
    Reader::EntryInfo file_info;
    while (reader.getNext(&file_info)) {
        if (file_info.empty())
            continue;

        if (unlikely(not file_info.isRegularFile()))
            LOG_ERROR("unexpectedly, the entry \"" + file_info.getFilename() + "\" in \"" + archive_name + "\" is not a regular file!");

        const std::string output_filename(directory + "/" + file_info.getFilename());
        const auto output(FileUtil::OpenOutputFileOrDie(output_filename));

        char buf[8192];
        size_t read_count;
        while ((read_count = reader.read(buf, sizeof buf)) > 0) {
            if (unlikely(output->write(buf, read_count) != read_count))
                LOG_ERROR("failed to write data to \"" + output->getPath() + "\"! (No room?)");
        }
    }

}

} // namespace Archive
<|endoftext|>


<commit_before>/** \file   BSZUtil.h
 *  \brief  Various utility functions related to data etc. having to do w/ the BSZ.
 *  \author Dr. Johannes Ruscheinski (johannes.ruscheinski@uni-tuebingen.de)
 *  \author Oliver Obenland (oliver.obenland@uni-tuebingen.de)
 *
 *  \copyright 2017 Universitätsbibliothek Tübingen.  All rights reserved.
 *
 *  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 "BSZUtil.h"
#include "StringUtil.h"
#include "util.h"
#include "RegexMatcher.h"

namespace BSZUtil {

// Use the following indicators to select whether to fully delete a record or remove its local data
// For a description of indicators
// c.f. https://wiki.bsz-bw.de/doku.php?id=v-team:daten:datendienste:sekkor (20160426)
const char FULL_RECORD_DELETE_INDICATORS[] = { 'A', 'B', 'C', 'D', 'E' };
const char LOCAL_DATA_DELETE_INDICATORS[] = { '3', '4', '5', '9' };

/*
 * The PPN length was increased from 9 to 10 in 2018.
 * The 10th character can optionally be a space
 */
const size_t MAX_LINE_LENGTH_OLD_WITH_ILN(25);
const size_t MAX_LINE_LENGTH_OLD_NO_ILN(21);
const size_t MAX_LINE_LENGTH_NEW_WITH_ILN(26);
const size_t MAX_LINE_LENGTH_NEW_NO_ILN(22);

const size_t PPN_LENGTH_OLD(9);
const size_t PPN_LENGTH_NEW(10);
const size_t PPN_START_INDEX(12);
const size_t SEPARATOR_INDEX(PPN_START_INDEX - 1);

void ExtractDeletionIds(File * const deletion_list, std::unordered_set <std::string> * const delete_full_record_ids,
                        std::unordered_set <std::string> * const local_deletion_ids)
{
    unsigned line_no(0);
top_loop:
    while (not deletion_list->eof()) {
        const std::string line(StringUtil::Trim(deletion_list->getline()));
        ++line_no;
        if (unlikely(line.empty())) // Ignore empty lines.
            continue;

        const size_t line_len(line.length());
        size_t ppn_len(0);

        if (line_len == MAX_LINE_LENGTH_OLD_WITH_ILN or line_len == MAX_LINE_LENGTH_OLD_NO_ILN)
            ppn_len = PPN_LENGTH_OLD;
        else if (line_len == MAX_LINE_LENGTH_NEW_WITH_ILN or line_len == MAX_LINE_LENGTH_NEW_NO_ILN)
            ppn_len = PPN_LENGTH_NEW;
        else {
            LOG_WARNING("unexpected line length " + std::to_string(line_len)
                       + " for entry on line " + std::to_string(line_no)
                       + " in deletion list file \"" + deletion_list->getPath() + "\"!");
            ppn_len = PPN_LENGTH_OLD;       // fallback to the more conservative of the two lengths
        }

        for (const char indicator : FULL_RECORD_DELETE_INDICATORS) {
            if (line[SEPARATOR_INDEX] == indicator) {
                if (line_len != MAX_LINE_LENGTH_OLD_NO_ILN and line_len != MAX_LINE_LENGTH_NEW_NO_ILN) {
                    LOG_ERROR("unexpected line length " + std::to_string(line_len)
                             + " for non-local entry on line " + std::to_string(line_no)
                             + " in deletion list file \"" + deletion_list->getPath() + "\"!");
                }

                delete_full_record_ids->insert(StringUtil::Trim(line.substr(PPN_START_INDEX, ppn_len)));
                goto top_loop;
            }
        }
        for (const char indicator : LOCAL_DATA_DELETE_INDICATORS) {
            if (line[SEPARATOR_INDEX] == indicator) {
                if (line_len != MAX_LINE_LENGTH_OLD_WITH_ILN and line_len != MAX_LINE_LENGTH_NEW_WITH_ILN) {
                    LOG_ERROR("unexpected line length " + std::to_string(line_len)
                             + " for local entry on line " + std::to_string(line_no)
                             + " in deletion list file \"" + deletion_list->getPath() + "\"!");
                }

                local_deletion_ids->insert(StringUtil::Trim(line.substr(PPN_START_INDEX, ppn_len)));
                goto top_loop;
            }
        }
        LOG_WARNING("in \"" + deletion_list->getPath() + " \" on line #" + std::to_string(line_no)
                   + " unknown indicator: '" + line.substr(SEPARATOR_INDEX, 1) + "'!");
    }
}

std::string ExtractDateFromFilenameOrDie(const std::string &filename) {
    static const std::string DATE_EXTRACTION_REGEX(".*(\\d{6}).*");
    static RegexMatcher *matcher;
    if (matcher == nullptr) {
        std::string err_msg;
        matcher = RegexMatcher::RegexMatcherFactory(DATE_EXTRACTION_REGEX, &err_msg);
        if (unlikely(not err_msg.empty()))
            LOG_ERROR("in ExtractDateFromFilenameOrDie: failed to compile regex: \"" + DATE_EXTRACTION_REGEX
                     + "\".");
    }

    if (unlikely(not matcher->matched(filename)))
        LOG_ERROR("in ExtractDateFromFilenameOrDie: \"" + filename + "\" failed to match the regex \""
                 + DATE_EXTRACTION_REGEX + "\"!");

    return (*matcher)[1];
}

} // namespace BSZUtil
<commit_msg>Cosmetic.<commit_after>/** \file   BSZUtil.h
 *  \brief  Various utility functions related to data etc. having to do w/ the BSZ.
 *  \author Dr. Johannes Ruscheinski (johannes.ruscheinski@uni-tuebingen.de)
 *  \author Oliver Obenland (oliver.obenland@uni-tuebingen.de)
 *
 *  \copyright 2017,2018 Universitätsbibliothek Tübingen.  All rights reserved.
 *
 *  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 "BSZUtil.h"
#include "StringUtil.h"
#include "util.h"
#include "RegexMatcher.h"

namespace BSZUtil {

// Use the following indicators to select whether to fully delete a record or remove its local data
// For a description of indicators
// c.f. https://wiki.bsz-bw.de/doku.php?id=v-team:daten:datendienste:sekkor (20160426)
const char FULL_RECORD_DELETE_INDICATORS[] = { 'A', 'B', 'C', 'D', 'E' };
const char LOCAL_DATA_DELETE_INDICATORS[] = { '3', '4', '5', '9' };

/*
 * The PPN length was increased from 9 to 10 in 2018.
 * The 10th character can optionally be a space
 */
const size_t MAX_LINE_LENGTH_OLD_WITH_ILN(25);
const size_t MAX_LINE_LENGTH_OLD_NO_ILN(21);
const size_t MAX_LINE_LENGTH_NEW_WITH_ILN(26);
const size_t MAX_LINE_LENGTH_NEW_NO_ILN(22);

const size_t PPN_LENGTH_OLD(9);
const size_t PPN_LENGTH_NEW(10);
const size_t PPN_START_INDEX(12);
const size_t SEPARATOR_INDEX(PPN_START_INDEX - 1);

void ExtractDeletionIds(File * const deletion_list, std::unordered_set <std::string> * const delete_full_record_ids,
                        std::unordered_set <std::string> * const local_deletion_ids)
{
    unsigned line_no(0);
top_loop:
    while (not deletion_list->eof()) {
        const std::string line(StringUtil::Trim(deletion_list->getline()));
        ++line_no;
        if (unlikely(line.empty())) // Ignore empty lines.
            continue;

        const size_t line_len(line.length());
        size_t ppn_len(0);

        if (line_len == MAX_LINE_LENGTH_OLD_WITH_ILN or line_len == MAX_LINE_LENGTH_OLD_NO_ILN)
            ppn_len = PPN_LENGTH_OLD;
        else if (line_len == MAX_LINE_LENGTH_NEW_WITH_ILN or line_len == MAX_LINE_LENGTH_NEW_NO_ILN)
            ppn_len = PPN_LENGTH_NEW;
        else {
            LOG_WARNING("unexpected line length " + std::to_string(line_len)
                       + " for entry on line " + std::to_string(line_no)
                       + " in deletion list file \"" + deletion_list->getPath() + "\"!");
            ppn_len = PPN_LENGTH_OLD;       // fallback to the more conservative of the two lengths
        }

        for (const char indicator : FULL_RECORD_DELETE_INDICATORS) {
            if (line[SEPARATOR_INDEX] == indicator) {
                if (line_len != MAX_LINE_LENGTH_OLD_NO_ILN and line_len != MAX_LINE_LENGTH_NEW_NO_ILN) {
                    LOG_ERROR("unexpected line length " + std::to_string(line_len)
                             + " for non-local entry on line " + std::to_string(line_no)
                             + " in deletion list file \"" + deletion_list->getPath() + "\"!");
                }

                delete_full_record_ids->insert(StringUtil::Trim(line.substr(PPN_START_INDEX, ppn_len)));
                goto top_loop;
            }
        }
        for (const char indicator : LOCAL_DATA_DELETE_INDICATORS) {
            if (line[SEPARATOR_INDEX] == indicator) {
                if (line_len != MAX_LINE_LENGTH_OLD_WITH_ILN and line_len != MAX_LINE_LENGTH_NEW_WITH_ILN) {
                    LOG_ERROR("unexpected line length " + std::to_string(line_len)
                             + " for local entry on line " + std::to_string(line_no)
                             + " in deletion list file \"" + deletion_list->getPath() + "\"!");
                }

                local_deletion_ids->insert(StringUtil::Trim(line.substr(PPN_START_INDEX, ppn_len)));
                goto top_loop;
            }
        }
        LOG_WARNING("in \"" + deletion_list->getPath() + " \" on line #" + std::to_string(line_no)
                   + " unknown indicator: '" + line.substr(SEPARATOR_INDEX, 1) + "'!");
    }
}

std::string ExtractDateFromFilenameOrDie(const std::string &filename) {
    static const std::string DATE_EXTRACTION_REGEX(".*(\\d{6}).*");
    static RegexMatcher *matcher;
    if (matcher == nullptr) {
        std::string err_msg;
        matcher = RegexMatcher::RegexMatcherFactory(DATE_EXTRACTION_REGEX, &err_msg);
        if (unlikely(not err_msg.empty()))
            LOG_ERROR("in ExtractDateFromFilenameOrDie: failed to compile regex: \"" + DATE_EXTRACTION_REGEX
                     + "\".");
    }

    if (unlikely(not matcher->matched(filename)))
        LOG_ERROR("in ExtractDateFromFilenameOrDie: \"" + filename + "\" failed to match the regex \""
                 + DATE_EXTRACTION_REGEX + "\"!");

    return (*matcher)[1];
}

} // namespace BSZUtil
<|endoftext|>


<commit_before>
// Copyright (c) 2013-2014 Quanta Research Cambridge, Inc.

// 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 <assert.h>
#include "dmaManager.h"
#include "MMURequest.h"
#include "MMUIndication.h"
#include "MemServerRequest.h"
#include "MemServerIndication.h"

#define PLATFORM_TILE 0

class PortalPoller;
int mmu_error_limit = 20;
int mem_error_limit = 20;
const char *dmaErrors[] = {
				"None",
				"SGL Id out of range for read",
				"SGL Id out of range for write",
				"MMU out of range for read",
				"MMU out of range for write",
				"Offset out of range",
				"SGL Id invalid",
				"Tile tag out of range"
				};
class MMUIndication : public MMUIndicationWrapper
{
  DmaManager *portalMemory;
 public:
  MMUIndication(DmaManager *pm, unsigned int  id, int tile=PLATFORM_TILE) : MMUIndicationWrapper(id,tile), portalMemory(pm) {}
  MMUIndication(DmaManager *pm, unsigned int  id, PortalTransportFunctions *item, void *param) : MMUIndicationWrapper(id, item, param), portalMemory(pm) {}
  virtual void configResp(uint32_t pointer){
    portalMemory->confResp(pointer);
  }
  virtual void error (uint32_t code, uint32_t pointer, uint64_t offset, uint64_t extra) {
    fprintf(stderr, "MMUIndication::error(code=0x%x:%s, pointer=0x%x, offset=0x%" PRIx64 " extra=0x%" PRIx64 "\n", code, dmaErrors[code], pointer, offset, extra);
    if (--mmu_error_limit < 0)
        exit(-1);
  }
  virtual void idResponse(uint32_t sglId){
    portalMemory->sglIdResp(sglId);
  }
};

class MemServerIndication : public MemServerIndicationWrapper
{
  MemServerRequestProxy *memServerRequestProxy;
  sem_t mtSem;
  uint64_t mtCnt;
  void init(){
    if (sem_init(&mtSem, 0, 0))
      PORTAL_PRINTF("MemServerIndication::init failed to init mtSem\n");
  }
 public:
  MemServerIndication(unsigned int  id, int tile=PLATFORM_TILE) : MemServerIndicationWrapper(id,tile), memServerRequestProxy(NULL) {init();}
  MemServerIndication(MemServerRequestProxy *p, unsigned int  id, int tile=PLATFORM_TILE) : MemServerIndicationWrapper(id,tile), memServerRequestProxy(p) {init();}
  virtual void addrResponse(uint64_t physAddr){
    fprintf(stderr, "DmaIndication::addrResponse(physAddr=%" PRIx64 ")\n", physAddr);
  }
  virtual void reportStateDbg(const DmaDbgRec rec){
    fprintf(stderr, "MemServerIndication::reportStateDbg: {x:%08x y:%08x z:%08x w:%08x}\n", rec.x,rec.y,rec.z,rec.w);
  }
  virtual void reportMemoryTraffic(uint64_t words){
    //fprintf(stderr, "reportMemoryTraffic: words=%" PRIx64 "\n", words);
    mtCnt = words;
    sem_post(&mtSem);
  }
  virtual void error (uint32_t code, uint32_t pointer, uint64_t offset, uint64_t extra) {
    fprintf(stderr, "MemServerIndication::error(code=%x, pointer=%x, offset=%" PRIx64 " extra=%" PRIx64 "\n", code, pointer, offset, extra);
    if (--mem_error_limit < 0)
      exit(-1);
  }
  uint64_t receiveMemoryTraffic(){
    sem_wait(&mtSem);
    return mtCnt;
  }
  uint64_t getMemoryTraffic(const ChannelType rc){
    assert(memServerRequestProxy);
    memServerRequestProxy->memoryTraffic(rc);
    return receiveMemoryTraffic();
  }
};

static MemServerRequestProxy *hostMemServerRequest;
static MemServerIndication *hostMemServerIndication;
static MMUIndication *mmuIndication;
static DmaManager *dma;
static pthread_once_t once_control = PTHREAD_ONCE_INIT;
void platformInitOnce(void)
{
    hostMemServerRequest = new MemServerRequestProxy(PlatformIfcNames_MemServerRequestS2H, PLATFORM_TILE);
    MMURequestProxy *dmap = new MMURequestProxy(PlatformIfcNames_MMURequestS2H, PLATFORM_TILE);
    dma = new DmaManager(dmap);
    hostMemServerIndication = new MemServerIndication(hostMemServerRequest, PlatformIfcNames_MemServerIndicationH2S, PLATFORM_TILE);
    mmuIndication = new MMUIndication(dma, PlatformIfcNames_MMUIndicationH2S, PLATFORM_TILE);

#ifdef FPGA0_CLOCK_FREQ
    long req_freq = FPGA0_CLOCK_FREQ;
    long freq = 0;
    setClockFrequency(0, req_freq, &freq);
    fprintf(stderr, "Requested FCLK[0]=%ld actually %ld\n", req_freq, freq);
#endif
}
DmaManager *platformInit(void)
{
    pthread_once(&once_control, platformInitOnce);
    return dma;
}

void platformStatistics(void)
{
    uint64_t cycles = portalTimerLap(0);
    hostMemServerRequest->memoryTraffic(ChannelType_Read);
    uint64_t read_beats = hostMemServerIndication->receiveMemoryTraffic();
    float read_util = (float)read_beats/(float)cycles;
    hostMemServerRequest->memoryTraffic(ChannelType_Write);
    uint64_t write_beats = hostMemServerIndication->receiveMemoryTraffic();
    float write_util = (float)write_beats/(float)cycles;
    fprintf(stderr, "   read_beats: %lld\n", (long long)read_beats);
    fprintf(stderr, "  write_beats: %lld\n", (long long)write_beats);
    fprintf(stderr, "       cycles: %lld\n", (long long)cycles);
    fprintf(stderr, "memory utilization (beats/cycle): read %f write %f\n", read_util, write_util);
}
<commit_msg>set the requested clock frequency on zynq boards<commit_after>
// Copyright (c) 2013-2014 Quanta Research Cambridge, Inc.

// 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 <assert.h>
#include "dmaManager.h"
#include "MMURequest.h"
#include "MMUIndication.h"
#include "MemServerRequest.h"
#include "MemServerIndication.h"

#define PLATFORM_TILE 0

class PortalPoller;
int mmu_error_limit = 20;
int mem_error_limit = 20;
const char *dmaErrors[] = {
				"None",
				"SGL Id out of range for read",
				"SGL Id out of range for write",
				"MMU out of range for read",
				"MMU out of range for write",
				"Offset out of range",
				"SGL Id invalid",
				"Tile tag out of range"
				};
class MMUIndication : public MMUIndicationWrapper
{
  DmaManager *portalMemory;
 public:
  MMUIndication(DmaManager *pm, unsigned int  id, int tile=PLATFORM_TILE) : MMUIndicationWrapper(id,tile), portalMemory(pm) {}
  MMUIndication(DmaManager *pm, unsigned int  id, PortalTransportFunctions *item, void *param) : MMUIndicationWrapper(id, item, param), portalMemory(pm) {}
  virtual void configResp(uint32_t pointer){
    portalMemory->confResp(pointer);
  }
  virtual void error (uint32_t code, uint32_t pointer, uint64_t offset, uint64_t extra) {
    fprintf(stderr, "MMUIndication::error(code=0x%x:%s, pointer=0x%x, offset=0x%" PRIx64 " extra=0x%" PRIx64 "\n", code, dmaErrors[code], pointer, offset, extra);
    if (--mmu_error_limit < 0)
        exit(-1);
  }
  virtual void idResponse(uint32_t sglId){
    portalMemory->sglIdResp(sglId);
  }
};

class MemServerIndication : public MemServerIndicationWrapper
{
  MemServerRequestProxy *memServerRequestProxy;
  sem_t mtSem;
  uint64_t mtCnt;
  void init(){
    if (sem_init(&mtSem, 0, 0))
      PORTAL_PRINTF("MemServerIndication::init failed to init mtSem\n");
  }
 public:
  MemServerIndication(unsigned int  id, int tile=PLATFORM_TILE) : MemServerIndicationWrapper(id,tile), memServerRequestProxy(NULL) {init();}
  MemServerIndication(MemServerRequestProxy *p, unsigned int  id, int tile=PLATFORM_TILE) : MemServerIndicationWrapper(id,tile), memServerRequestProxy(p) {init();}
  virtual void addrResponse(uint64_t physAddr){
    fprintf(stderr, "DmaIndication::addrResponse(physAddr=%" PRIx64 ")\n", physAddr);
  }
  virtual void reportStateDbg(const DmaDbgRec rec){
    fprintf(stderr, "MemServerIndication::reportStateDbg: {x:%08x y:%08x z:%08x w:%08x}\n", rec.x,rec.y,rec.z,rec.w);
  }
  virtual void reportMemoryTraffic(uint64_t words){
    //fprintf(stderr, "reportMemoryTraffic: words=%" PRIx64 "\n", words);
    mtCnt = words;
    sem_post(&mtSem);
  }
  virtual void error (uint32_t code, uint32_t pointer, uint64_t offset, uint64_t extra) {
    fprintf(stderr, "MemServerIndication::error(code=%x, pointer=%x, offset=%" PRIx64 " extra=%" PRIx64 "\n", code, pointer, offset, extra);
    if (--mem_error_limit < 0)
      exit(-1);
  }
  uint64_t receiveMemoryTraffic(){
    sem_wait(&mtSem);
    return mtCnt;
  }
  uint64_t getMemoryTraffic(const ChannelType rc){
    assert(memServerRequestProxy);
    memServerRequestProxy->memoryTraffic(rc);
    return receiveMemoryTraffic();
  }
};

static MemServerRequestProxy *hostMemServerRequest;
static MemServerIndication *hostMemServerIndication;
static MMUIndication *mmuIndication;
static DmaManager *dma;
static pthread_once_t once_control = PTHREAD_ONCE_INIT;
void platformInitOnce(void)
{
    hostMemServerRequest = new MemServerRequestProxy(PlatformIfcNames_MemServerRequestS2H, PLATFORM_TILE);
    MMURequestProxy *dmap = new MMURequestProxy(PlatformIfcNames_MMURequestS2H, PLATFORM_TILE);
    dma = new DmaManager(dmap);
    hostMemServerIndication = new MemServerIndication(hostMemServerRequest, PlatformIfcNames_MemServerIndicationH2S, PLATFORM_TILE);
    mmuIndication = new MMUIndication(dma, PlatformIfcNames_MMUIndicationH2S, PLATFORM_TILE);

#ifdef MainClockPeriod
    long req_freq = (long)(1e9 / MainClockPeriod);
    long freq = 0;
    setClockFrequency(0, req_freq, &freq);
    fprintf(stderr, "Requested FCLK[0]=%ld actually %ld\n", req_freq, freq);
#endif
}
DmaManager *platformInit(void)
{
    pthread_once(&once_control, platformInitOnce);
    return dma;
}

void platformStatistics(void)
{
    uint64_t cycles = portalTimerLap(0);
    hostMemServerRequest->memoryTraffic(ChannelType_Read);
    uint64_t read_beats = hostMemServerIndication->receiveMemoryTraffic();
    float read_util = (float)read_beats/(float)cycles;
    hostMemServerRequest->memoryTraffic(ChannelType_Write);
    uint64_t write_beats = hostMemServerIndication->receiveMemoryTraffic();
    float write_util = (float)write_beats/(float)cycles;
    fprintf(stderr, "   read_beats: %lld\n", (long long)read_beats);
    fprintf(stderr, "  write_beats: %lld\n", (long long)write_beats);
    fprintf(stderr, "       cycles: %lld\n", (long long)cycles);
    fprintf(stderr, "memory utilization (beats/cycle): read %f write %f\n", read_util, write_util);
}
<|endoftext|>


<commit_before>/**
 * @cond ___LICENSE___
 *
 * Copyright (c) 2017 Zefiros Software.
 *
 * 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.
 *
 * @endcond
 */

#include "plot/surfPlot.h"
#include "plot/properties/heatMapProperties.h"

PLOTLIB_INLINE SurfPlot::SurfPlot( const PVec &x, const std::vector<PVec> &y, const std::vector<PVec> &z )
    : SurfPlot()
{
    mStream << "X=[";

    for ( auto &Y : y )
    {
        mStream << this->ToArray( x ) << ",";
    }

    mStream << "]\n"
            << "Y=[";

    for ( auto &Y : y )
    {
        mStream << this->ToArray( Y ) << ",";
    }

    mStream << "]\n"
            << "Z=[";

    for ( auto &Z : z )
    {
        mStream << this->ToArray( Z ) << ",";
    }

    mStream << "]\n"
            << "surf = ax.plot_surface( X, Y, Z";
}

PLOTLIB_INLINE SurfPlot::SurfPlot( const PVec &x, const PVec &y, const std::vector<PVec> &z )
    : SurfPlot()
{
    mStream << "X=[";

    for ( auto &Y : y.GetData() )
    {
        mStream << this->ToArray( x ) << ",";
    }

    mStream << "]\n"
            << "Y=[";

    for ( auto &Y : y.GetData() )
    {
        mStream << this->ToArray( std::vector<double>( x.GetSize(), Y ) ) << ",";
    }

    mStream << "]\n"
            << "Z=[";

    for ( auto &Z : z )
    {
        mStream << this->ToArray( Z ) << ",";
    }

    mStream << "]\n"
            << "surf = ax.plot_surface( X, Y, Z";
}

PLOTLIB_INLINE SurfPlot::SurfPlot( const PMat &x, const PMat &y, const PMat &z )
    : SurfPlot()
{
    mStream << "X=" << this->ToArray( x ) << "\n"
            << "Y=" << this->ToArray( y ) << "\n"
            << "Z=" << this->ToArray( z ) << "\n"
            << "surf = ax.plot_surface( X, Y, Z";
}

PLOTLIB_INLINE std::string SurfPlot::ToString()
{
    if ( !mHasColourMap )
    {
        SetColourMap( ColourMap::Diverging::Coolwarm );
    }

    return mStream.str() +
           ", antialiased = True )\n" +
           ( mShowColourBar ? "fig.colorbar( surf, shrink = 0.5, aspect = 5 )" : "" );
}

PLOTLIB_INLINE SurfPlot &SurfPlot::SetColourMap( const ColourMap &pallet )
{
    this->AddArgument( "cmap", pallet.ToString() );
    mHasColourMap = true;
    return *this;
}

PLOTLIB_INLINE SurfPlot &SurfPlot::ColourBar( bool bar )
{
    mShowColourBar = bar;
    return *this;
}

SurfPlot::SurfPlot()
    : mHasColourMap( false ),
      mShowColourBar( false )
{
    mStream << "\nfrom mpl_toolkits.mplot3d import Axes3D\n"
            << "from matplotlib import cm\n\n"
            << "fig = plt.figure()\n"
            << "ax = fig.gca(projection='3d')\n";
}
<commit_msg>Fixed x repetition in surfplot<commit_after>/**
 * @cond ___LICENSE___
 *
 * Copyright (c) 2017 Zefiros Software.
 *
 * 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.
 *
 * @endcond
 */

#include "plot/surfPlot.h"
#include "plot/properties/heatMapProperties.h"

PLOTLIB_INLINE SurfPlot::SurfPlot( const PVec &x, const std::vector<PVec> &y, const std::vector<PVec> &z )
    : SurfPlot()
{
    mStream << "X=[";

    for ( auto &Y : y )
    {
        mStream << this->ToArray( x ) << ",";
    }

    mStream << "]\n"
            << "Y=[";

    for ( auto &Y : y )
    {
        mStream << this->ToArray( Y ) << ",";
    }

    mStream << "]\n"
            << "Z=[";

    for ( auto &Z : z )
    {
        mStream << this->ToArray( Z ) << ",";
    }

    mStream << "]\n"
            << "surf = ax.plot_surface( X, Y, Z";
}

PLOTLIB_INLINE SurfPlot::SurfPlot( const PVec &x, const PVec &y, const std::vector<PVec> &z )
    : SurfPlot()
{
    mStream << "X=[";

    for ( auto &Z : z )
    {
        mStream << this->ToArray( x ) << ",";
    }

    mStream << "]\n"
            << "Y=[";

    for ( auto &Y : y.GetData() )
    {
        mStream << this->ToArray( std::vector<double>( x.GetSize(), Y ) ) << ",";
    }

    mStream << "]\n"
            << "Z=[";

    for ( auto &Z : z )
    {
        mStream << this->ToArray( Z ) << ",";
    }

    mStream << "]\n"
            << "surf = ax.plot_surface( X, Y, Z";
}

PLOTLIB_INLINE SurfPlot::SurfPlot( const PMat &x, const PMat &y, const PMat &z )
    : SurfPlot()
{
    mStream << "X=" << this->ToArray( x ) << "\n"
            << "Y=" << this->ToArray( y ) << "\n"
            << "Z=" << this->ToArray( z ) << "\n"
            << "surf = ax.plot_surface( X, Y, Z";
}

PLOTLIB_INLINE std::string SurfPlot::ToString()
{
    if ( !mHasColourMap )
    {
        SetColourMap( ColourMap::Diverging::Coolwarm );
    }

    return mStream.str() +
           ", antialiased = True )\n" +
           ( mShowColourBar ? "fig.colorbar( surf, shrink = 0.5, aspect = 5 )" : "" );
}

PLOTLIB_INLINE SurfPlot &SurfPlot::SetColourMap( const ColourMap &pallet )
{
    this->AddArgument( "cmap", pallet.ToString() );
    mHasColourMap = true;
    return *this;
}

PLOTLIB_INLINE SurfPlot &SurfPlot::ColourBar( bool bar )
{
    mShowColourBar = bar;
    return *this;
}

SurfPlot::SurfPlot()
    : mHasColourMap( false ),
      mShowColourBar( false )
{
    mStream << "\nfrom mpl_toolkits.mplot3d import Axes3D\n"
            << "from matplotlib import cm\n\n"
            << "fig = plt.figure()\n"
            << "ax = fig.gca(projection='3d')\n";
}
<|endoftext|>


<commit_before>#include <pybind11/pybind11.h>
#include "intersection.h"

namespace py = pybind11;

namespace jtrace {
    void pyExportIntersection(py::module &m) {
        py::class_<Intersection>(m, "Intersection")
            .def_readonly("point", &Intersection::point)
            .def_readonly("surfaceNormal", &Intersection::surfaceNormal)
            .def("__repr__", &Intersection::repr)
            .def_readonly("t", &Intersection::t)
            .def_readonly("point", &Intersection::point)
            .def_readonly("surfaceNormal", &Intersection::surfaceNormal)
            .def("reflectedRay", &Intersection::reflectedRay);
    }
}
<commit_msg>Clean up pysrc/intersection.cpp<commit_after>#include <pybind11/pybind11.h>
#include "intersection.h"

namespace py = pybind11;

namespace jtrace {
    void pyExportIntersection(py::module &m) {
        py::class_<Intersection>(m, "Intersection")
            .def_readonly("t", &Intersection::t)
            .def_readonly("point", &Intersection::point)
            .def_readonly("surfaceNormal", &Intersection::surfaceNormal)
            .def("__repr__", &Intersection::repr)
            .def("reflectedRay", &Intersection::reflectedRay);
    }
}
<|endoftext|>


<commit_before>

#include "src/utils/md5.h"
#include "others/mbedtls/md5.h"

namespace modsecurity {
namespace Utils {

std::string Md5::hexdigest(std::string& input) {
    unsigned char digest[16];

    mbedtls_md5(reinterpret_cast<const unsigned char *>(input.c_str()),
        input.size(), digest);

    char buf[32];
    for (int i = 0; i < 16; i++) {
        sprintf(buf+i*2, "%02x", digest[i]);
    }

    return std::string(buf, 32);
}

std::string Md5::digest(std::string& input) {
    unsigned char output[16];
    std::string ret;

    mbedtls_md5(reinterpret_cast<const unsigned char *>(input.c_str()),
        input.size(), output);

    ret.assign(reinterpret_cast<const char *>(output), 16);

    return ret;
}

}  // namespace Utils
}  // namespace modsecurity

<commit_msg>Fixed buffer overflow in Utils::Md5::hexdigest()<commit_after>

#include "src/utils/md5.h"
#include "others/mbedtls/md5.h"

namespace modsecurity {
namespace Utils {

std::string Md5::hexdigest(std::string& input) {
    unsigned char digest[16];

    mbedtls_md5(reinterpret_cast<const unsigned char *>(input.c_str()),
        input.size(), digest);

    char buf[33];
    for (int i = 0; i < 16; i++) {
        sprintf(buf+i*2, "%02x", digest[i]);
    }

    return std::string(buf, 32);
}

std::string Md5::digest(std::string& input) {
    unsigned char output[16];
    std::string ret;

    mbedtls_md5(reinterpret_cast<const unsigned char *>(input.c_str()),
        input.size(), output);

    ret.assign(reinterpret_cast<const char *>(output), 16);

    return ret;
}

}  // namespace Utils
}  // namespace modsecurity

<|endoftext|>