<commit_before>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, 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.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QtTest/QtTest>

#include "multimedia/qgraphicsvideoitem.h"

#include "multimedia/qmediaobject.h"
#include "multimedia/qmediaservice.h"
#include "multimedia/qpaintervideosurface_p.h"
#include "multimedia/qvideooutputcontrol.h"
#include "multimedia/qvideorenderercontrol.h"

#include <QtMultimedia/qabstractvideosurface.h>
#include <QtMultimedia/qvideosurfaceformat.h>

#include <QtGui/qapplication.h>
#include <QtGui/qgraphicsscene.h>
#include <QtGui/qgraphicsview.h>

class tst_QGraphicsVideoItem : public QObject
{
    Q_OBJECT
private slots:
    void nullObject();
    void nullService();
    void nullOutputControl();
    void noOutputs();
    void serviceDestroyed();

    void show();

    void boundingRect_data();
    void boundingRect();

    void paint();
};

Q_DECLARE_METATYPE(const uchar *)

class QtTestOutputControl : public QVideoOutputControl
{
public:
    QtTestOutputControl() : m_output(NoOutput) {}

    QList<Output> availableOutputs() const { return m_outputs; }
    void setAvailableOutputs(const QList<Output> outputs) { m_outputs = outputs; }

    Output output() const { return m_output; }
    virtual void setOutput(Output output) { m_output = output; }

private:
    Output m_output;
    QList<Output> m_outputs;
};

class QtTestRendererControl : public QVideoRendererControl
{
public:
    QtTestRendererControl()
        : m_surface(0)
    {
    }

    QAbstractVideoSurface *surface() const { return m_surface; }
    void setSurface(QAbstractVideoSurface *surface) { m_surface = surface; }

private:
    QAbstractVideoSurface *m_surface;
};

class QtTestVideoService : public QMediaService
{
    Q_OBJECT
public:
    QtTestVideoService(
            QtTestOutputControl *output,
            QtTestRendererControl *renderer)
        : QMediaService(0)
        , outputControl(output)
        , rendererControl(renderer)
    {
    }

    ~QtTestVideoService()
    {
        delete outputControl;
        delete rendererControl;
    }

    QMediaControl *control(const char *name) const
    {
        if (qstrcmp(name, QVideoOutputControl_iid) == 0)
            return outputControl;
        else if (qstrcmp(name, QVideoRendererControl_iid) == 0)
            return rendererControl;
        else
            return 0;
    }

    QtTestOutputControl *outputControl;
    QtTestRendererControl *rendererControl;
};

class QtTestVideoObject : public QMediaObject
{
    Q_OBJECT
public:
    QtTestVideoObject(QtTestRendererControl *renderer):
        QMediaObject(0, new QtTestVideoService(new QtTestOutputControl, renderer))
    {
        testService = qobject_cast<QtTestVideoService*>(service());
        QList<QVideoOutputControl::Output> outputs;

        if (renderer)
            outputs.append(QVideoOutputControl::RendererOutput);

        testService->outputControl->setAvailableOutputs(outputs);
    }

    QtTestVideoObject(QtTestVideoService *service):
        QMediaObject(0, service),
        testService(service)
    {
    }

    ~QtTestVideoObject()
    {
        delete testService;
    }

    QtTestVideoService *testService;
};

class QtTestGraphicsVideoItem : public QGraphicsVideoItem
{
public:
    QtTestGraphicsVideoItem(QMediaObject *object, QGraphicsItem *parent = 0)
        : QGraphicsVideoItem(object, parent)
        , m_paintCount(0)
    {
    }

    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
    {
        ++m_paintCount;

        QTestEventLoop::instance().exitLoop();

        QGraphicsVideoItem::paint(painter, option, widget);
    }

    bool waitForPaint(int secs)
    {
        const int paintCount = m_paintCount;

        QTestEventLoop::instance().enterLoop(secs);

        return m_paintCount != paintCount;
    }

private:
    int m_paintCount;
};

void tst_QGraphicsVideoItem::nullObject()
{
    QGraphicsVideoItem item(0);

    QVERIFY(item.boundingRect().isEmpty());
}

void tst_QGraphicsVideoItem::nullService()
{
    QtTestVideoService *service = 0;

    QtTestVideoObject object(service);

    QtTestGraphicsVideoItem *item = new QtTestGraphicsVideoItem(&object);

    QVERIFY(item->boundingRect().isEmpty());

    item->hide();
    item->show();

    QGraphicsScene graphicsScene;
    graphicsScene.addItem(item);
    QGraphicsView graphicsView(&graphicsScene);
    graphicsView.show();

    item->waitForPaint(1);
}

void tst_QGraphicsVideoItem::nullOutputControl()
{
    QtTestVideoObject object(new QtTestVideoService(0, 0));

    QtTestGraphicsVideoItem *item = new QtTestGraphicsVideoItem(&object);

    QVERIFY(item->boundingRect().isEmpty());

    item->hide();
    item->show();

    QGraphicsScene graphicsScene;
    graphicsScene.addItem(item);
    QGraphicsView graphicsView(&graphicsScene);
    graphicsView.show();

    item->waitForPaint(1);
}

void tst_QGraphicsVideoItem::noOutputs()
{
    QtTestRendererControl *control = 0;
    QtTestVideoObject object(control);

    QtTestGraphicsVideoItem *item = new QtTestGraphicsVideoItem(&object);

    QVERIFY(item->boundingRect().isEmpty());

    item->hide();
    QCOMPARE(object.testService->outputControl->output(), QVideoOutputControl::NoOutput);
    item->show();
    QCOMPARE(object.testService->outputControl->output(), QVideoOutputControl::NoOutput);

    QGraphicsScene graphicsScene;
    graphicsScene.addItem(item);
    QGraphicsView graphicsView(&graphicsScene);
    graphicsView.show();

    QVERIFY(item->waitForPaint(1));
}

void tst_QGraphicsVideoItem::serviceDestroyed()
{
    QtTestVideoObject *object = new QtTestVideoObject(new QtTestRendererControl);

    QGraphicsVideoItem item(object);

    delete object;

    QVERIFY(item.boundingRect().isEmpty());
}

void tst_QGraphicsVideoItem::show()
{
    QtTestVideoObject object(new QtTestRendererControl);
    QGraphicsVideoItem item(&object);

    // Graphics items are visible by default
    QCOMPARE(object.testService->outputControl->output(), QVideoOutputControl::RendererOutput);
    QVERIFY(object.testService->rendererControl->surface() != 0);

    item.hide();
    QCOMPARE(object.testService->outputControl->output(), QVideoOutputControl::NoOutput);

    item.show();
    QCOMPARE(object.testService->outputControl->output(), QVideoOutputControl::RendererOutput);
    QVERIFY(object.testService->rendererControl->surface() != 0);
}

void tst_QGraphicsVideoItem::boundingRect_data()
{
    QTest::addColumn<QSize>("frameSize");
    QTest::addColumn<QRect>("viewport");
    QTest::addColumn<QSize>("pixelAspectRatio");
    QTest::addColumn<QRectF>("expectedRect");

    QTest::newRow("640x480")
            << QSize(640, 480)
            << QRect(0, 0, 640, 480)
            << QSize(1, 1)
            << QRectF(-319, -239, 640, 480);

    QTest::newRow("800x600, (80,60, 640x480) viewport")
            << QSize(800, 600)
            << QRect(80, 60, 640, 480)
            << QSize(1, 1)
            << QRectF(-319,-239, 640, 480);

    QTest::newRow("800x600, (80,60, 640x480) viewport, 4:3")
            << QSize(800, 600)
            << QRect(80, 60, 640, 480)
            << QSize(4, 3)
            << QRectF(-426, -239, 853, 480);

}

void tst_QGraphicsVideoItem::boundingRect()
{
    QFETCH(QSize, frameSize);
    QFETCH(QRect, viewport);
    QFETCH(QSize, pixelAspectRatio);
    QFETCH(QRectF, expectedRect);

    QtTestVideoObject object(new QtTestRendererControl);
    QGraphicsVideoItem item(&object);

    QVideoSurfaceFormat format(frameSize, QVideoFrame::Format_ARGB32);
    format.setViewport(viewport);
    format.setPixelAspectRatio(pixelAspectRatio);

    QVERIFY(object.testService->rendererControl->surface()->start(format));

    QCOMPARE(item.boundingRect(), expectedRect);
}

static const uchar rgb32ImageData[] =
{
    0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00,
    0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00
};

void tst_QGraphicsVideoItem::paint()
{
    QtTestVideoObject object(new QtTestRendererControl);
    QtTestGraphicsVideoItem *item = new QtTestGraphicsVideoItem(&object);

    QGraphicsScene graphicsScene;
    graphicsScene.addItem(item);
    QGraphicsView graphicsView(&graphicsScene);
    graphicsView.show();

    QPainterVideoSurface *surface = qobject_cast<QPainterVideoSurface *>(
            object.testService->rendererControl->surface());

    QVideoSurfaceFormat format(QSize(2, 2), QVideoFrame::Format_RGB32);

    QVERIFY(surface->start(format));
    QCOMPARE(surface->isStarted(), true);
    QCOMPARE(surface->isReady(), true);

    QVERIFY(item->waitForPaint(1));

    QCOMPARE(surface->isStarted(), true);
    QCOMPARE(surface->isReady(), true);

    QVideoFrame frame(sizeof(rgb32ImageData), QSize(2, 2), 8, QVideoFrame::Format_RGB32);

    frame.map(QAbstractVideoBuffer::WriteOnly);
    memcpy(frame.bits(), rgb32ImageData, frame.numBytes());
    frame.unmap();

    QVERIFY(surface->present(frame));
    QCOMPARE(surface->isStarted(), true);
    QCOMPARE(surface->isReady(), false);

    QVERIFY(item->waitForPaint(1));

    QCOMPARE(surface->isStarted(), true);
    QCOMPARE(surface->isReady(), true);
}

QTEST_MAIN(tst_QGraphicsVideoItem)

#include "tst_qgraphicsvideoitem.moc"
<commit_msg>Fixed tst_qgraphicsvideoitem on mac, made item to be painted<commit_after>/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the Qt Mobility Components.
**
** $QT_BEGIN_LICENSE:LGPL$
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
** contained in the Technology Preview License Agreement accompanying
** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, 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.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
**
**
**
**
**
**
**
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QtTest/QtTest>

#include "multimedia/qgraphicsvideoitem.h"

#include "multimedia/qmediaobject.h"
#include "multimedia/qmediaservice.h"
#include "multimedia/qpaintervideosurface_p.h"
#include "multimedia/qvideooutputcontrol.h"
#include "multimedia/qvideorenderercontrol.h"

#include <QtMultimedia/qabstractvideosurface.h>
#include <QtMultimedia/qvideosurfaceformat.h>

#include <QtGui/qapplication.h>
#include <QtGui/qgraphicsscene.h>
#include <QtGui/qgraphicsview.h>

class tst_QGraphicsVideoItem : public QObject
{
    Q_OBJECT
private slots:
    void nullObject();
    void nullService();
    void nullOutputControl();
    void noOutputs();
    void serviceDestroyed();

    void show();

    void boundingRect_data();
    void boundingRect();

    void paint();
};

Q_DECLARE_METATYPE(const uchar *)

class QtTestOutputControl : public QVideoOutputControl
{
public:
    QtTestOutputControl() : m_output(NoOutput) {}

    QList<Output> availableOutputs() const { return m_outputs; }
    void setAvailableOutputs(const QList<Output> outputs) { m_outputs = outputs; }

    Output output() const { return m_output; }
    virtual void setOutput(Output output) { m_output = output; }

private:
    Output m_output;
    QList<Output> m_outputs;
};

class QtTestRendererControl : public QVideoRendererControl
{
public:
    QtTestRendererControl()
        : m_surface(0)
    {
    }

    QAbstractVideoSurface *surface() const { return m_surface; }
    void setSurface(QAbstractVideoSurface *surface) { m_surface = surface; }

private:
    QAbstractVideoSurface *m_surface;
};

class QtTestVideoService : public QMediaService
{
    Q_OBJECT
public:
    QtTestVideoService(
            QtTestOutputControl *output,
            QtTestRendererControl *renderer)
        : QMediaService(0)
        , outputControl(output)
        , rendererControl(renderer)
    {
    }

    ~QtTestVideoService()
    {
        delete outputControl;
        delete rendererControl;
    }

    QMediaControl *control(const char *name) const
    {
        if (qstrcmp(name, QVideoOutputControl_iid) == 0)
            return outputControl;
        else if (qstrcmp(name, QVideoRendererControl_iid) == 0)
            return rendererControl;
        else
            return 0;
    }

    QtTestOutputControl *outputControl;
    QtTestRendererControl *rendererControl;
};

class QtTestVideoObject : public QMediaObject
{
    Q_OBJECT
public:
    QtTestVideoObject(QtTestRendererControl *renderer):
        QMediaObject(0, new QtTestVideoService(new QtTestOutputControl, renderer))
    {
        testService = qobject_cast<QtTestVideoService*>(service());
        QList<QVideoOutputControl::Output> outputs;

        if (renderer)
            outputs.append(QVideoOutputControl::RendererOutput);

        testService->outputControl->setAvailableOutputs(outputs);
    }

    QtTestVideoObject(QtTestVideoService *service):
        QMediaObject(0, service),
        testService(service)
    {
    }

    ~QtTestVideoObject()
    {
        delete testService;
    }

    QtTestVideoService *testService;
};

class QtTestGraphicsVideoItem : public QGraphicsVideoItem
{
public:
    QtTestGraphicsVideoItem(QMediaObject *object, QGraphicsItem *parent = 0)
        : QGraphicsVideoItem(object, parent)
        , m_paintCount(0)
    {
    }

    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
    {
        ++m_paintCount;

        QTestEventLoop::instance().exitLoop();

        QGraphicsVideoItem::paint(painter, option, widget);
    }

    bool waitForPaint(int secs)
    {
        const int paintCount = m_paintCount;

        QTestEventLoop::instance().enterLoop(secs);

        return m_paintCount != paintCount;
    }

    int paintCount() const
    {
        return m_paintCount;
    }

private:
    int m_paintCount;
};

void tst_QGraphicsVideoItem::nullObject()
{
    QGraphicsVideoItem item(0);

    QVERIFY(item.boundingRect().isEmpty());
}

void tst_QGraphicsVideoItem::nullService()
{
    QtTestVideoService *service = 0;

    QtTestVideoObject object(service);

    QtTestGraphicsVideoItem *item = new QtTestGraphicsVideoItem(&object);

    QVERIFY(item->boundingRect().isEmpty());

    item->hide();
    item->show();

    QGraphicsScene graphicsScene;
    graphicsScene.addItem(item);
    QGraphicsView graphicsView(&graphicsScene);
    graphicsView.show();
}

void tst_QGraphicsVideoItem::nullOutputControl()
{
    QtTestVideoObject object(new QtTestVideoService(0, 0));

    QtTestGraphicsVideoItem *item = new QtTestGraphicsVideoItem(&object);

    QVERIFY(item->boundingRect().isEmpty());

    item->hide();
    item->show();

    QGraphicsScene graphicsScene;
    graphicsScene.addItem(item);
    QGraphicsView graphicsView(&graphicsScene);
    graphicsView.show();
}

void tst_QGraphicsVideoItem::noOutputs()
{
    QtTestRendererControl *control = 0;
    QtTestVideoObject object(control);

    QtTestGraphicsVideoItem *item = new QtTestGraphicsVideoItem(&object);

    QVERIFY(item->boundingRect().isEmpty());

    item->hide();
    QCOMPARE(object.testService->outputControl->output(), QVideoOutputControl::NoOutput);
    item->show();
    QCOMPARE(object.testService->outputControl->output(), QVideoOutputControl::NoOutput);

    QGraphicsScene graphicsScene;
    graphicsScene.addItem(item);
    QGraphicsView graphicsView(&graphicsScene);
    graphicsView.show();
}

void tst_QGraphicsVideoItem::serviceDestroyed()
{
    QtTestVideoObject *object = new QtTestVideoObject(new QtTestRendererControl);

    QGraphicsVideoItem item(object);

    delete object;

    QVERIFY(item.boundingRect().isEmpty());
}

void tst_QGraphicsVideoItem::show()
{
    QtTestVideoObject object(new QtTestRendererControl);
    QtTestGraphicsVideoItem *item = new QtTestGraphicsVideoItem(&object);

    // Graphics items are visible by default
    QCOMPARE(object.testService->outputControl->output(), QVideoOutputControl::RendererOutput);
    QVERIFY(object.testService->rendererControl->surface() != 0);

    item->hide();
    QCOMPARE(object.testService->outputControl->output(), QVideoOutputControl::NoOutput);

    item->show();
    QCOMPARE(object.testService->outputControl->output(), QVideoOutputControl::RendererOutput);
    QVERIFY(object.testService->rendererControl->surface() != 0);

    QVERIFY(item->boundingRect().isEmpty());

    QVideoSurfaceFormat format(QSize(320,240),QVideoFrame::Format_RGB32);
    QVERIFY(object.testService->rendererControl->surface()->start(format));

    QVERIFY(!item->boundingRect().isEmpty());

    QGraphicsScene graphicsScene;
    graphicsScene.addItem(item);
    QGraphicsView graphicsView(&graphicsScene);
    graphicsView.show();

    QVERIFY(item->paintCount() || item->waitForPaint(1));
}

void tst_QGraphicsVideoItem::boundingRect_data()
{
    QTest::addColumn<QSize>("frameSize");
    QTest::addColumn<QRect>("viewport");
    QTest::addColumn<QSize>("pixelAspectRatio");
    QTest::addColumn<QRectF>("expectedRect");

    QTest::newRow("640x480")
            << QSize(640, 480)
            << QRect(0, 0, 640, 480)
            << QSize(1, 1)
            << QRectF(-319, -239, 640, 480);

    QTest::newRow("800x600, (80,60, 640x480) viewport")
            << QSize(800, 600)
            << QRect(80, 60, 640, 480)
            << QSize(1, 1)
            << QRectF(-319,-239, 640, 480);

    QTest::newRow("800x600, (80,60, 640x480) viewport, 4:3")
            << QSize(800, 600)
            << QRect(80, 60, 640, 480)
            << QSize(4, 3)
            << QRectF(-426, -239, 853, 480);

}

void tst_QGraphicsVideoItem::boundingRect()
{
    QFETCH(QSize, frameSize);
    QFETCH(QRect, viewport);
    QFETCH(QSize, pixelAspectRatio);
    QFETCH(QRectF, expectedRect);

    QtTestVideoObject object(new QtTestRendererControl);
    QGraphicsVideoItem item(&object);

    QVideoSurfaceFormat format(frameSize, QVideoFrame::Format_ARGB32);
    format.setViewport(viewport);
    format.setPixelAspectRatio(pixelAspectRatio);

    QVERIFY(object.testService->rendererControl->surface()->start(format));

    QCOMPARE(item.boundingRect(), expectedRect);
}

static const uchar rgb32ImageData[] =
{
    0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00,
    0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00
};

void tst_QGraphicsVideoItem::paint()
{
    QtTestVideoObject object(new QtTestRendererControl);
    QtTestGraphicsVideoItem *item = new QtTestGraphicsVideoItem(&object);

    QGraphicsScene graphicsScene;
    graphicsScene.addItem(item);
    QGraphicsView graphicsView(&graphicsScene);
    graphicsView.show();

    QPainterVideoSurface *surface = qobject_cast<QPainterVideoSurface *>(
            object.testService->rendererControl->surface());

    QVideoSurfaceFormat format(QSize(2, 2), QVideoFrame::Format_RGB32);

    QVERIFY(surface->start(format));
    QCOMPARE(surface->isStarted(), true);
    QCOMPARE(surface->isReady(), true);

    QVERIFY(item->waitForPaint(1));

    QCOMPARE(surface->isStarted(), true);
    QCOMPARE(surface->isReady(), true);

    QVideoFrame frame(sizeof(rgb32ImageData), QSize(2, 2), 8, QVideoFrame::Format_RGB32);

    frame.map(QAbstractVideoBuffer::WriteOnly);
    memcpy(frame.bits(), rgb32ImageData, frame.numBytes());
    frame.unmap();

    QVERIFY(surface->present(frame));
    QCOMPARE(surface->isStarted(), true);
    QCOMPARE(surface->isReady(), false);

    QVERIFY(item->waitForPaint(1));

    QCOMPARE(surface->isStarted(), true);
    QCOMPARE(surface->isReady(), true);
}

QTEST_MAIN(tst_QGraphicsVideoItem)

#include "tst_qgraphicsvideoitem.moc"
<|endoftext|>


<commit_before>/*
 * Copyright 2015 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "GrDrawContext.h"
#include "GrDrawingManager.h"
#include "GrDrawTarget.h"
#include "GrPathRenderingDrawContext.h"
#include "GrResourceProvider.h"
#include "GrSoftwarePathRenderer.h"
#include "SkTTopoSort.h"

#include "text/GrAtlasTextContext.h"
#include "text/GrStencilAndCoverTextContext.h"

void GrDrawingManager::cleanup() {
    for (int i = 0; i < fDrawTargets.count(); ++i) {
        fDrawTargets[i]->makeClosed();  // no drawTarget should receive a new command after this
        fDrawTargets[i]->clearRT();

        // We shouldn't need to do this, but it turns out some clients still hold onto drawtargets
        // after a cleanup
        fDrawTargets[i]->reset();
        fDrawTargets[i]->unref();
    }

    fDrawTargets.reset();

    delete fPathRendererChain;
    fPathRendererChain = nullptr;
    SkSafeSetNull(fSoftwarePathRenderer);
}

GrDrawingManager::~GrDrawingManager() {
    this->cleanup();
}

void GrDrawingManager::abandon() {
    fAbandoned = true;
    this->cleanup();
}

void GrDrawingManager::freeGpuResources() {
    // a path renderer may be holding onto resources
    delete fPathRendererChain;
    fPathRendererChain = nullptr;
    SkSafeSetNull(fSoftwarePathRenderer);
}

void GrDrawingManager::reset() {
    for (int i = 0; i < fDrawTargets.count(); ++i) {
        fDrawTargets[i]->reset();
    }
    fFlushState.reset();
}

void GrDrawingManager::flush() {
    if (fFlushing || this->wasAbandoned()) {
        return;
    }
    fFlushing = true;

    SkDEBUGCODE(bool result =)
                        SkTTopoSort<GrDrawTarget, GrDrawTarget::TopoSortTraits>(&fDrawTargets);
    SkASSERT(result);

    // Enable this to print out verbose batching information
#if 0
    for (int i = 0; i < fDrawTargets.count(); ++i) {
        SkDEBUGCODE(fDrawTargets[i]->dump();)
    }
#endif

    for (int i = 0; i < fDrawTargets.count(); ++i) {
        fDrawTargets[i]->prepareBatches(&fFlushState);
    }

    // Upload all data to the GPU
    fFlushState.preIssueDraws();

    for (int i = 0; i < fDrawTargets.count(); ++i) {
        fDrawTargets[i]->drawBatches(&fFlushState);
    }

    SkASSERT(fFlushState.nextDrawToken() == fFlushState.nextTokenToFlush());

    for (int i = 0; i < fDrawTargets.count(); ++i) {
        fDrawTargets[i]->reset();
#ifdef ENABLE_MDB
        fDrawTargets[i]->unref();
#endif
    }

#ifndef ENABLE_MDB
    // When MDB is disabled we keep reusing the same drawTarget
    if (fDrawTargets.count()) {
        SkASSERT(fDrawTargets.count() == 1);
        // Clear out this flag so the topological sort's SkTTopoSort_CheckAllUnmarked check
        // won't bark
        fDrawTargets[0]->resetFlag(GrDrawTarget::kWasOutput_Flag);
    }
#else
    fDrawTargets.reset();
#endif

    fFlushState.reset();
    fFlushing = false;
}

GrDrawTarget* GrDrawingManager::newDrawTarget(GrRenderTarget* rt) {
    SkASSERT(fContext);

#ifndef ENABLE_MDB
    // When MDB is disabled we always just return the single drawTarget
    if (fDrawTargets.count()) {
        SkASSERT(fDrawTargets.count() == 1);
        // In the non-MDB-world the same drawTarget gets reused for multiple render targets.
        // Update this pointer so all the asserts are happy
        rt->setLastDrawTarget(fDrawTargets[0]);
        // DrawingManager gets the creation ref - this ref is for the caller
        return SkRef(fDrawTargets[0]);
    }
#endif

    GrDrawTarget* dt = new GrDrawTarget(rt, fContext->getGpu(), fContext->resourceProvider(),
                                        fContext->getAuditTrail(), fOptionsForDrawTargets);

    *fDrawTargets.append() = dt;

    // DrawingManager gets the creation ref - this ref is for the caller
    return SkRef(dt);
}

/*
 * This method finds a path renderer that can draw the specified path on
 * the provided target.
 * Due to its expense, the software path renderer has split out so it can
 * can be individually allowed/disallowed via the "allowSW" boolean.
 */
GrPathRenderer* GrDrawingManager::getPathRenderer(const GrPathRenderer::CanDrawPathArgs& args,
                                                  bool allowSW,
                                                  GrPathRendererChain::DrawType drawType,
                                                  GrPathRenderer::StencilSupport* stencilSupport) {

    if (!fPathRendererChain) {
        fPathRendererChain = new GrPathRendererChain(fContext);
    }

    GrPathRenderer* pr = fPathRendererChain->getPathRenderer(args, drawType, stencilSupport);
    if (!pr && allowSW) {
        if (!fSoftwarePathRenderer) {
            fSoftwarePathRenderer = new GrSoftwarePathRenderer(fContext->textureProvider());
        }
        pr = fSoftwarePathRenderer;
    }

    return pr;
}

sk_sp<GrDrawContext> GrDrawingManager::drawContext(sk_sp<GrRenderTarget> rt,
                                                   const SkSurfaceProps* surfaceProps) {
    if (this->wasAbandoned()) {
        return nullptr;
    }

    bool useDIF = false;
    if (surfaceProps) {
        useDIF = surfaceProps->isUseDeviceIndependentFonts();
    }

    if (useDIF && fContext->caps()->shaderCaps()->pathRenderingSupport() &&
        rt->isStencilBufferMultisampled()) {
        GrStencilAttachment* sb = fContext->resourceProvider()->attachStencilAttachment(rt.get());
        if (sb) {
            return sk_sp<GrDrawContext>(new GrPathRenderingDrawContext(
                                                        fContext, this, std::move(rt),
                                                        surfaceProps,
                                                        fContext->getAuditTrail(), fSingleOwner));
        }
    }

    return sk_sp<GrDrawContext>(new GrDrawContext(fContext, this, std::move(rt), surfaceProps,
                                                  fContext->getAuditTrail(),
                                                  fSingleOwner));
}
<commit_msg>Move dump of batches to be after the forwardCombine call in prepareBatches<commit_after>/*
 * Copyright 2015 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "GrDrawContext.h"
#include "GrDrawingManager.h"
#include "GrDrawTarget.h"
#include "GrPathRenderingDrawContext.h"
#include "GrResourceProvider.h"
#include "GrSoftwarePathRenderer.h"
#include "SkTTopoSort.h"

#include "text/GrAtlasTextContext.h"
#include "text/GrStencilAndCoverTextContext.h"

void GrDrawingManager::cleanup() {
    for (int i = 0; i < fDrawTargets.count(); ++i) {
        fDrawTargets[i]->makeClosed();  // no drawTarget should receive a new command after this
        fDrawTargets[i]->clearRT();

        // We shouldn't need to do this, but it turns out some clients still hold onto drawtargets
        // after a cleanup
        fDrawTargets[i]->reset();
        fDrawTargets[i]->unref();
    }

    fDrawTargets.reset();

    delete fPathRendererChain;
    fPathRendererChain = nullptr;
    SkSafeSetNull(fSoftwarePathRenderer);
}

GrDrawingManager::~GrDrawingManager() {
    this->cleanup();
}

void GrDrawingManager::abandon() {
    fAbandoned = true;
    this->cleanup();
}

void GrDrawingManager::freeGpuResources() {
    // a path renderer may be holding onto resources
    delete fPathRendererChain;
    fPathRendererChain = nullptr;
    SkSafeSetNull(fSoftwarePathRenderer);
}

void GrDrawingManager::reset() {
    for (int i = 0; i < fDrawTargets.count(); ++i) {
        fDrawTargets[i]->reset();
    }
    fFlushState.reset();
}

void GrDrawingManager::flush() {
    if (fFlushing || this->wasAbandoned()) {
        return;
    }
    fFlushing = true;

    SkDEBUGCODE(bool result =)
                        SkTTopoSort<GrDrawTarget, GrDrawTarget::TopoSortTraits>(&fDrawTargets);
    SkASSERT(result);

    for (int i = 0; i < fDrawTargets.count(); ++i) {
        fDrawTargets[i]->prepareBatches(&fFlushState);
    }

    // Enable this to print out verbose batching information
#if 0
    for (int i = 0; i < fDrawTargets.count(); ++i) {
        SkDEBUGCODE(fDrawTargets[i]->dump();)
    }
#endif

    // Upload all data to the GPU
    fFlushState.preIssueDraws();

    for (int i = 0; i < fDrawTargets.count(); ++i) {
        fDrawTargets[i]->drawBatches(&fFlushState);
    }

    SkASSERT(fFlushState.nextDrawToken() == fFlushState.nextTokenToFlush());

    for (int i = 0; i < fDrawTargets.count(); ++i) {
        fDrawTargets[i]->reset();
#ifdef ENABLE_MDB
        fDrawTargets[i]->unref();
#endif
    }

#ifndef ENABLE_MDB
    // When MDB is disabled we keep reusing the same drawTarget
    if (fDrawTargets.count()) {
        SkASSERT(fDrawTargets.count() == 1);
        // Clear out this flag so the topological sort's SkTTopoSort_CheckAllUnmarked check
        // won't bark
        fDrawTargets[0]->resetFlag(GrDrawTarget::kWasOutput_Flag);
    }
#else
    fDrawTargets.reset();
#endif

    fFlushState.reset();
    fFlushing = false;
}

GrDrawTarget* GrDrawingManager::newDrawTarget(GrRenderTarget* rt) {
    SkASSERT(fContext);

#ifndef ENABLE_MDB
    // When MDB is disabled we always just return the single drawTarget
    if (fDrawTargets.count()) {
        SkASSERT(fDrawTargets.count() == 1);
        // In the non-MDB-world the same drawTarget gets reused for multiple render targets.
        // Update this pointer so all the asserts are happy
        rt->setLastDrawTarget(fDrawTargets[0]);
        // DrawingManager gets the creation ref - this ref is for the caller
        return SkRef(fDrawTargets[0]);
    }
#endif

    GrDrawTarget* dt = new GrDrawTarget(rt, fContext->getGpu(), fContext->resourceProvider(),
                                        fContext->getAuditTrail(), fOptionsForDrawTargets);

    *fDrawTargets.append() = dt;

    // DrawingManager gets the creation ref - this ref is for the caller
    return SkRef(dt);
}

/*
 * This method finds a path renderer that can draw the specified path on
 * the provided target.
 * Due to its expense, the software path renderer has split out so it can
 * can be individually allowed/disallowed via the "allowSW" boolean.
 */
GrPathRenderer* GrDrawingManager::getPathRenderer(const GrPathRenderer::CanDrawPathArgs& args,
                                                  bool allowSW,
                                                  GrPathRendererChain::DrawType drawType,
                                                  GrPathRenderer::StencilSupport* stencilSupport) {

    if (!fPathRendererChain) {
        fPathRendererChain = new GrPathRendererChain(fContext);
    }

    GrPathRenderer* pr = fPathRendererChain->getPathRenderer(args, drawType, stencilSupport);
    if (!pr && allowSW) {
        if (!fSoftwarePathRenderer) {
            fSoftwarePathRenderer = new GrSoftwarePathRenderer(fContext->textureProvider());
        }
        pr = fSoftwarePathRenderer;
    }

    return pr;
}

sk_sp<GrDrawContext> GrDrawingManager::drawContext(sk_sp<GrRenderTarget> rt,
                                                   const SkSurfaceProps* surfaceProps) {
    if (this->wasAbandoned()) {
        return nullptr;
    }

    bool useDIF = false;
    if (surfaceProps) {
        useDIF = surfaceProps->isUseDeviceIndependentFonts();
    }

    if (useDIF && fContext->caps()->shaderCaps()->pathRenderingSupport() &&
        rt->isStencilBufferMultisampled()) {
        GrStencilAttachment* sb = fContext->resourceProvider()->attachStencilAttachment(rt.get());
        if (sb) {
            return sk_sp<GrDrawContext>(new GrPathRenderingDrawContext(
                                                        fContext, this, std::move(rt),
                                                        surfaceProps,
                                                        fContext->getAuditTrail(), fSingleOwner));
        }
    }

    return sk_sp<GrDrawContext>(new GrDrawContext(fContext, this, std::move(rt), surfaceProps,
                                                  fContext->getAuditTrail(),
                                                  fSingleOwner));
}
<|endoftext|>


<commit_before>///
/// @file   EratBig.cpp
/// @brief  Segmented sieve of Eratosthenes optimized for big sieving
///         primes. This is an optimized implementation of Tomas
///         Oliveira e Silva's cache-friendly bucket sieve algorithm:
///         http://www.ieeta.pt/~tos/software/prime_sieve.html
///
/// Copyright (C) 2018 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <primesieve/EratBig.hpp>
#include <primesieve/Bucket.hpp>
#include <primesieve/MemoryPool.hpp>
#include <primesieve/pmath.hpp>
#include <primesieve/primesieve_error.hpp>
#include <primesieve/types.hpp>
#include <primesieve/Wheel.hpp>

#include <stdint.h>
#include <cassert>
#include <vector>

using namespace std;

namespace primesieve {

/// @stop:      Upper bound for sieving
/// @sieveSize: Sieve size in bytes
/// @maxPrime:  Sieving primes <= maxPrime
///
void EratBig::init(uint64_t stop, uint64_t sieveSize, uint64_t maxPrime)
{
  // '>> log2SieveSize' requires power of 2 sieveSize
  if (!isPow2(sieveSize))
    throw primesieve_error("EratBig: sieveSize is not a power of 2");

  enabled_ = true;
  maxPrime_ = maxPrime;
  log2SieveSize_ = ilog2(sieveSize);
  moduloSieveSize_ = sieveSize - 1;

  Wheel::init(stop, sieveSize);
  init(sieveSize);
}

void EratBig::init(uint64_t sieveSize)
{
  uint64_t maxSievingPrime  = maxPrime_ / 30;
  uint64_t maxNextMultiple  = maxSievingPrime * getMaxFactor() + getMaxFactor();
  uint64_t maxMultipleIndex = sieveSize - 1 + maxNextMultiple;
  uint64_t maxSegmentCount  = maxMultipleIndex >> log2SieveSize_;
  uint64_t size = maxSegmentCount + 1;

  lists_.resize(size, nullptr);

  for (Bucket*& list : lists_)
    memoryPool_.addBucket(list);
}

/// Add a new sieving prime to EratBig
void EratBig::storeSievingPrime(uint64_t prime, uint64_t multipleIndex, uint64_t wheelIndex)
{
  assert(prime <= maxPrime_);
  uint64_t sievingPrime = prime / 30;
  uint64_t segment = multipleIndex >> log2SieveSize_;
  multipleIndex &= moduloSieveSize_;

  if (!lists_[segment]->store(sievingPrime, multipleIndex, wheelIndex))
    memoryPool_.addBucket(lists_[segment]);
}

/// Cross-off the multiples of big sieving
/// primes from the sieve array.
///
void EratBig::crossOff(byte_t* sieve)
{
  while (lists_[0]->hasNext() ||
         !lists_[0]->empty())
  {
    Bucket* bucket = lists_[0];
    lists_[0] = nullptr;
    memoryPool_.addBucket(lists_[0]);

    while (bucket)
    {
      crossOff(sieve, bucket->begin(), bucket->end());
      Bucket* processed = bucket;
      bucket = bucket->next();
      memoryPool_.freeBucket(processed);
    }
  }

  rotate(lists_.begin(), lists_.begin() + 1, lists_.end());
}

/// Segmented sieve of Eratosthenes with wheel factorization
/// optimized for big sieving primes that have very few
/// multiples per segment. Cross-off the next multiple of
/// each sieving prime in the current bucket.
///
void EratBig::crossOff(byte_t* sieve, SievingPrime* primes, SievingPrime* end)
{
  Bucket** lists = &lists_[0];
  uint64_t moduloSieveSize = moduloSieveSize_;
  uint64_t log2SieveSize = log2SieveSize_;

  // 2 sieving primes are processed per loop iteration
  // to increase instruction level parallelism
  for (; primes + 2 <= end; primes += 2)
  {
    uint64_t multipleIndex0 = primes[0].getMultipleIndex();
    uint64_t wheelIndex0    = primes[0].getWheelIndex();
    uint64_t sievingPrime0  = primes[0].getSievingPrime();
    uint64_t multipleIndex1 = primes[1].getMultipleIndex();
    uint64_t wheelIndex1    = primes[1].getWheelIndex();
    uint64_t sievingPrime1  = primes[1].getSievingPrime();

    // cross-off the current multiple (unset bit)
    // and calculate the next multiple
    unsetBit(sieve, sievingPrime0, &multipleIndex0, &wheelIndex0);
    unsetBit(sieve, sievingPrime1, &multipleIndex1, &wheelIndex1);

    uint64_t segment0 = multipleIndex0 >> log2SieveSize;
    uint64_t segment1 = multipleIndex1 >> log2SieveSize;

    multipleIndex0 &= moduloSieveSize;
    multipleIndex1 &= moduloSieveSize;

    // move the 2 sieving primes to the list related
    // to their next multiple
    if (!lists[segment0]->store(sievingPrime0, multipleIndex0, wheelIndex0))
      memoryPool_.addBucket(lists_[segment0]);
    if (!lists[segment1]->store(sievingPrime1, multipleIndex1, wheelIndex1))
      memoryPool_.addBucket(lists_[segment1]);
  }

  if (primes != end)
  {
    uint64_t multipleIndex = primes->getMultipleIndex();
    uint64_t wheelIndex    = primes->getWheelIndex();
    uint64_t sievingPrime  = primes->getSievingPrime();

    unsetBit(sieve, sievingPrime, &multipleIndex, &wheelIndex);
    uint64_t segment = multipleIndex >> log2SieveSize;
    multipleIndex &= moduloSieveSize;

    if (!lists[segment]->store(sievingPrime, multipleIndex, wheelIndex))
      memoryPool_.addBucket(lists_[segment]);
  }
}

} // namespace
<commit_msg>Update comment<commit_after>///
/// @file   EratBig.cpp
/// @brief  Segmented sieve of Eratosthenes optimized for big sieving
///         primes. This is an optimized implementation of Tomas
///         Oliveira e Silva's cache-friendly bucket sieve algorithm:
///         http://www.ieeta.pt/~tos/software/prime_sieve.html
///
/// Copyright (C) 2018 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#include <primesieve/EratBig.hpp>
#include <primesieve/Bucket.hpp>
#include <primesieve/MemoryPool.hpp>
#include <primesieve/pmath.hpp>
#include <primesieve/primesieve_error.hpp>
#include <primesieve/types.hpp>
#include <primesieve/Wheel.hpp>

#include <stdint.h>
#include <cassert>
#include <vector>

using namespace std;

namespace primesieve {

/// @stop:      Upper bound for sieving
/// @sieveSize: Sieve size in bytes
/// @maxPrime:  Sieving primes <= maxPrime
///
void EratBig::init(uint64_t stop, uint64_t sieveSize, uint64_t maxPrime)
{
  // '>> log2SieveSize' requires power of 2 sieveSize
  if (!isPow2(sieveSize))
    throw primesieve_error("EratBig: sieveSize is not a power of 2");

  enabled_ = true;
  maxPrime_ = maxPrime;
  log2SieveSize_ = ilog2(sieveSize);
  moduloSieveSize_ = sieveSize - 1;

  Wheel::init(stop, sieveSize);
  init(sieveSize);
}

void EratBig::init(uint64_t sieveSize)
{
  uint64_t maxSievingPrime  = maxPrime_ / 30;
  uint64_t maxNextMultiple  = maxSievingPrime * getMaxFactor() + getMaxFactor();
  uint64_t maxMultipleIndex = sieveSize - 1 + maxNextMultiple;
  uint64_t maxSegmentCount  = maxMultipleIndex >> log2SieveSize_;
  uint64_t size = maxSegmentCount + 1;

  lists_.resize(size, nullptr);

  for (Bucket*& list : lists_)
    memoryPool_.addBucket(list);
}

/// Add a new sieving prime to EratBig
void EratBig::storeSievingPrime(uint64_t prime, uint64_t multipleIndex, uint64_t wheelIndex)
{
  assert(prime <= maxPrime_);
  uint64_t sievingPrime = prime / 30;
  uint64_t segment = multipleIndex >> log2SieveSize_;
  multipleIndex &= moduloSieveSize_;

  if (!lists_[segment]->store(sievingPrime, multipleIndex, wheelIndex))
    memoryPool_.addBucket(lists_[segment]);
}

/// Get the bucket list related to the current
/// segment, then iterate over its buckets
/// and call crossOff() for each bucket.
///
void EratBig::crossOff(byte_t* sieve)
{
  while (lists_[0]->hasNext() ||
         !lists_[0]->empty())
  {
    Bucket* bucket = lists_[0];
    lists_[0] = nullptr;
    memoryPool_.addBucket(lists_[0]);

    while (bucket)
    {
      crossOff(sieve, bucket->begin(), bucket->end());
      Bucket* processed = bucket;
      bucket = bucket->next();
      memoryPool_.freeBucket(processed);
    }
  }

  rotate(lists_.begin(), lists_.begin() + 1, lists_.end());
}

/// Segmented sieve of Eratosthenes with wheel factorization
/// optimized for big sieving primes that have very few
/// multiples per segment. Cross-off the next multiple of
/// each sieving prime in the current bucket.
///
void EratBig::crossOff(byte_t* sieve, SievingPrime* primes, SievingPrime* end)
{
  Bucket** lists = &lists_[0];
  uint64_t moduloSieveSize = moduloSieveSize_;
  uint64_t log2SieveSize = log2SieveSize_;

  // 2 sieving primes are processed per loop iteration
  // to increase instruction level parallelism
  for (; primes + 2 <= end; primes += 2)
  {
    uint64_t multipleIndex0 = primes[0].getMultipleIndex();
    uint64_t wheelIndex0    = primes[0].getWheelIndex();
    uint64_t sievingPrime0  = primes[0].getSievingPrime();
    uint64_t multipleIndex1 = primes[1].getMultipleIndex();
    uint64_t wheelIndex1    = primes[1].getWheelIndex();
    uint64_t sievingPrime1  = primes[1].getSievingPrime();

    // cross-off the current multiple (unset bit)
    // and calculate the next multiple
    unsetBit(sieve, sievingPrime0, &multipleIndex0, &wheelIndex0);
    unsetBit(sieve, sievingPrime1, &multipleIndex1, &wheelIndex1);

    uint64_t segment0 = multipleIndex0 >> log2SieveSize;
    uint64_t segment1 = multipleIndex1 >> log2SieveSize;

    multipleIndex0 &= moduloSieveSize;
    multipleIndex1 &= moduloSieveSize;

    // move the 2 sieving primes to the list related
    // to their next multiple
    if (!lists[segment0]->store(sievingPrime0, multipleIndex0, wheelIndex0))
      memoryPool_.addBucket(lists_[segment0]);
    if (!lists[segment1]->store(sievingPrime1, multipleIndex1, wheelIndex1))
      memoryPool_.addBucket(lists_[segment1]);
  }

  if (primes != end)
  {
    uint64_t multipleIndex = primes->getMultipleIndex();
    uint64_t wheelIndex    = primes->getWheelIndex();
    uint64_t sievingPrime  = primes->getSievingPrime();

    unsetBit(sieve, sievingPrime, &multipleIndex, &wheelIndex);
    uint64_t segment = multipleIndex >> log2SieveSize;
    multipleIndex &= moduloSieveSize;

    if (!lists[segment]->store(sievingPrime, multipleIndex, wheelIndex))
      memoryPool_.addBucket(lists_[segment]);
  }
}

} // namespace
<|endoftext|>


<commit_before>/*
 * File:   Factory.cpp
 * Author: iMer
 *
 * Created on 19. August 2014, 18:40
 */

#include "Factory.hpp"
#include "ParticleSystem.hpp"
#include "Text.hpp"
#include "Button.hpp"
#include "ObjectPlacer.hpp"
namespace engine {
	std::map<std::string, std::function<Node*(Json::Value& root, Node* parent) >> Factory::m_types = {
		std::make_pair(std::string("node"), std::function < Node * (Json::Value& root, Node * parent) >(Factory::CreateChildNode<Node>)),
		std::make_pair(std::string("sprite"), std::function < Node * (Json::Value& root, Node * parent) >(Factory::CreateChildNode<SpriteNode>)),
		std::make_pair(std::string("light"), std::function < Node * (Json::Value& root, Node * parent) >(Factory::CreateChildNode<Light>)),
		std::make_pair(std::string("text"), std::function < Node * (Json::Value& root, Node * parent) >(Factory::CreateChildNode<Text>)),
		std::make_pair(std::string("button"), std::function < Node * (Json::Value& root, Node * parent) >(Factory::CreateChildNode<Button>)),
		std::make_pair(std::string("objectPlacer"), std::function < Node * (Json::Value& root, Node * parent) >(Factory::CreateChildNode<ObjectPlacer>)),
		std::make_pair(std::string("particlesystem"), std::function < Node * (Json::Value& root, Node * parent) >(Factory::CreateChildNode<ParticleSystem>))
	};

	void Factory::RegisterType(std::string name, std::function<Node*(Json::Value& root, Node* parent) > callback) {
		m_types.insert(std::make_pair(name, callback));
	}

	void Factory::RemoveType(std::string name) {
		m_types.erase(name);
	}

	bool Factory::LoadJson(std::string filename, Json::Value & root) {
		Json::Reader reader;
		std::ifstream jconfig;
		jconfig.open(filename);
		if (!jconfig.good()) {
			std::cerr << "Could not open config file '" << filename << "': " << strerror(errno) << std::endl;
			return false;
		}
		if (!reader.parse(jconfig, root)) {
			std::cerr << "Couldn't parse config" << std::endl << reader.getFormattedErrorMessages() << std::endl;
			jconfig.seekg(0);
			std::cerr << jconfig.rdbuf() << std::endl;
			return false;
		}
		return true;
	}

	Node * Factory::CreateChild(Json::Value root, Node * parent) {
		Json::Value childData;
		if (root["childData"].isString()) {
			if (!LoadJson(root["childData"].asString(), childData)) {
				std::cerr << "Couldn't load childData from file" << std::endl;
				return nullptr;
			}
		} else {
			childData = root["childData"];
		}
		MergeJson(childData, root);
		std::string type = childData.get("type", "node").asString();
		auto it = m_types.find(type);
		if (it == m_types.end()) {
			std::cerr << "Type '" << type << "' was not registered. Cant load child." << std::endl;
			return nullptr;
		}
		Node* c = it->second(childData, parent);
		if (!c) {
			return nullptr;
		}
		if (root["childData"].isString()) {
			c->SetFilename(root["childData"].asString());
		}
		return c;
	}

	Node * Factory::CreateChildFromFile(std::string file, Node * parent) {
		Json::Value root;
		if (!Factory::LoadJson(file, root)) {
			return nullptr;
		}
		std::string type = root.get("type", "node").asString();
		auto it = m_types.find(type);
		if (it == m_types.end()) {
			std::cerr << "Type '" << type << "' was not registered. Cant load child." << std::endl;
			return nullptr;
		}
		Node* c = it->second(root, parent);
		if (!c) {
			return nullptr;
		}
		parent->AddNode(c);
		return c;
	}
	bool Factory::MakeChildren(Json::Value& children, Node* parent) {
		if (!children.isArray()) {
			std::cerr << "Children is expected to be an array";
			return false;
		}
		for (size_t i = 0; i < children.size(); i++) {
			auto child = children[i];
			if (!child.isObject()) {
				std::cerr << "Child has to be object" << std::endl;
				continue;
			}
			Node* nchild = CreateChild(child, parent->GetScene());
			if (nchild) {
				parent->AddNode(nchild);
			}
		}
		return true;
	}

	void Factory::MergeJson(Json::Value& a, Json::Value& b) { // http://stackoverflow.com/a/23860017/1318435
		if (!b.isObject()) return;

		for (const auto& key : b.getMemberNames()) {
			if (a[key].isObject()) {
				MergeJson(a[key], b[key]);
			} else {
				a[key] = b[key];
			}
		}
	}
}

<commit_msg>Set node filename properly<commit_after>/*
 * File:   Factory.cpp
 * Author: iMer
 *
 * Created on 19. August 2014, 18:40
 */

#include "Factory.hpp"
#include "ParticleSystem.hpp"
#include "Text.hpp"
#include "Button.hpp"
#include "ObjectPlacer.hpp"
namespace engine {
	std::map<std::string, std::function<Node*(Json::Value& root, Node* parent) >> Factory::m_types = {
		std::make_pair(std::string("node"), std::function < Node * (Json::Value& root, Node * parent) >(Factory::CreateChildNode<Node>)),
		std::make_pair(std::string("sprite"), std::function < Node * (Json::Value& root, Node * parent) >(Factory::CreateChildNode<SpriteNode>)),
		std::make_pair(std::string("light"), std::function < Node * (Json::Value& root, Node * parent) >(Factory::CreateChildNode<Light>)),
		std::make_pair(std::string("text"), std::function < Node * (Json::Value& root, Node * parent) >(Factory::CreateChildNode<Text>)),
		std::make_pair(std::string("button"), std::function < Node * (Json::Value& root, Node * parent) >(Factory::CreateChildNode<Button>)),
		std::make_pair(std::string("objectPlacer"), std::function < Node * (Json::Value& root, Node * parent) >(Factory::CreateChildNode<ObjectPlacer>)),
		std::make_pair(std::string("particlesystem"), std::function < Node * (Json::Value& root, Node * parent) >(Factory::CreateChildNode<ParticleSystem>))
	};

	void Factory::RegisterType(std::string name, std::function<Node*(Json::Value& root, Node* parent) > callback) {
		m_types.insert(std::make_pair(name, callback));
	}

	void Factory::RemoveType(std::string name) {
		m_types.erase(name);
	}

	bool Factory::LoadJson(std::string filename, Json::Value & root) {
		Json::Reader reader;
		std::ifstream jconfig;
		jconfig.open(filename);
		if (!jconfig.good()) {
			std::cerr << "Could not open config file '" << filename << "': " << strerror(errno) << std::endl;
			return false;
		}
		if (!reader.parse(jconfig, root)) {
			std::cerr << "Couldn't parse config" << std::endl << reader.getFormattedErrorMessages() << std::endl;
			jconfig.seekg(0);
			std::cerr << jconfig.rdbuf() << std::endl;
			return false;
		}
		return true;
	}

	Node * Factory::CreateChild(Json::Value root, Node * parent) {
		Json::Value childData;
		if (root["childData"].isString()) {
			if (!LoadJson(root["childData"].asString(), childData)) {
				std::cerr << "Couldn't load childData from file" << std::endl;
				return nullptr;
			}
		} else {
			childData = root["childData"];
		}
		MergeJson(childData, root);
		std::string type = childData.get("type", "node").asString();
		auto it = m_types.find(type);
		if (it == m_types.end()) {
			std::cerr << "Type '" << type << "' was not registered. Cant load child." << std::endl;
			return nullptr;
		}
		Node* c = it->second(childData, parent);
		if (!c) {
			return nullptr;
		}
		if (root["childData"].isString()) {
			c->SetFilename(root["childData"].asString());
		}
		return c;
	}

	Node * Factory::CreateChildFromFile(std::string file, Node * parent) {
		Json::Value root;
		if (!Factory::LoadJson(file, root)) {
			return nullptr;
		}
		std::string type = root.get("type", "node").asString();
		auto it = m_types.find(type);
		if (it == m_types.end()) {
			std::cerr << "Type '" << type << "' was not registered. Cant load child." << std::endl;
			return nullptr;
		}
		Node* c = it->second(root, parent);
		if (!c) {
			return nullptr;
		}
		c->SetFilename(file);
		parent->AddNode(c);
		return c;
	}
	bool Factory::MakeChildren(Json::Value& children, Node* parent) {
		if (!children.isArray()) {
			std::cerr << "Children is expected to be an array";
			return false;
		}
		for (size_t i = 0; i < children.size(); i++) {
			auto child = children[i];
			if (!child.isObject()) {
				std::cerr << "Child has to be object" << std::endl;
				continue;
			}
			Node* nchild = CreateChild(child, parent->GetScene());
			if (nchild) {
				parent->AddNode(nchild);
			}
		}
		return true;
	}

	void Factory::MergeJson(Json::Value& a, Json::Value& b) { // http://stackoverflow.com/a/23860017/1318435
		if (!b.isObject()) return;

		for (const auto& key : b.getMemberNames()) {
			if (a[key].isObject()) {
				MergeJson(a[key], b[key]);
			} else {
				a[key] = b[key];
			}
		}
	}
}

<|endoftext|>


<commit_before>#include <convert.hpp>
#include <errors.hpp>
#include <debug.hpp>

#include <ingridientWindow.hpp>
#include "ui_ingridientWindow.h"

IngridientWindow::IngridientWindow(QWidget* parent) :
    QDialog {parent},
    ui {new Ui::IngridientWindow},
    measureList {QStringList()} {

    setupMeasureList();
    ui->lineEdit_2->setDisabled(true);

    PRINT_OBJ("IngridientWindow created");
}

IngridientWindow::IngridientWindow(Item* item, QWidget* parent) :
    QDialog {parent},
    ui {new Ui::IngridientWindow},
    measureList {QStringList()},
    editMode {true},
    editedItem {item} {

    setupMeasureList();
    applyItemStats(item);
    this->setWindowTitle("Edit item");

    PRINT_OBJ("Existed item edit window created");
}

IngridientWindow::IngridientWindow(Food* food, QWidget* parent) :
    QDialog {parent},
    ui {new Ui::IngridientWindow},
    measureList {QStringList()},
    editMode {true},
    editedItem {food} {

    setupMeasureList();
    applyFoodStats(food);
    this->setWindowTitle("Edit food");

    PRINT_OBJ("Existed food edit window created");
}

IngridientWindow::~IngridientWindow() {
    delete ui;

    PRINT_OBJ("IngridientWindow destroyed");
}

void IngridientWindow::on_buttonBox_1_accepted() {
    if ( editMode ) {
        buttonBoxAcceptedEditMode();
    } else {
        buttonBoxAcceptedNewMode();
    }

    this->hide();

    PRINT_DEBUG("New item/food accepted");
}

void IngridientWindow::on_buttonBox_1_rejected() {
    this->hide();

    PRINT_DEBUG("New item/food rejected");
}

void IngridientWindow::setupMeasureList(void) {
    const std::string* names = Item::getItemMeasureTypeNamesList();

    ui->setupUi(this);

    for ( int i = 0; !names[i].empty(); i++ ) {
        measureList.append(QString::fromStdString(names[i]));
    }

    ui->comboBox_1->addItems(measureList);
}

void IngridientWindow::applyItemStats(Item* item) {
    ui->lineEdit_1->setText(QString::fromStdString(item->getName()));
    ui->lineEdit_1->setDisabled(true);
    ui->comboBox_1->setCurrentIndex(static_cast<int>(item->getUnitType()));
    if ( item->getUnitType() != Item::KGRAM ) {
        ui->lineEdit_2->setText(massToQString(item->getMass()));
    } else {
        ui->lineEdit_2->setDisabled(true);
    }
    ui->lineEdit_4->setText(priceToQString(item->getPrice()));

    on_radioButton_2_clicked();
    ui->radioButton_2->setChecked(true);
    ui->radioButton_1->setDisabled(true);

    PRINT_DEBUG("All items stats are applied");
}

void IngridientWindow::applyFoodStats(Food* food) {
    ui->lineEdit_1->setText(QString::fromStdString(food->getName()));
    ui->lineEdit_1->setDisabled(true);
    ui->comboBox_1->setCurrentIndex(static_cast<int>(food->getUnitType()));
    if ( food->getUnitType() != Item::KGRAM ) {
        ui->lineEdit_2->setText(massToQString(food->getMass()));
    } else {
        ui->lineEdit_2->setDisabled(true);
    }
    ui->lineEdit_4->setText(priceToQString(food->getPrice()));
    ui->lineEdit_3->setText(fatsToQString(food->getFats()));
    ui->lineEdit_5->setText(proteinsToQString(food->getProteins()));
    ui->lineEdit_6->setText(carbohydratesToQString(food->getCarbohydrates()));
    ui->lineEdit_7->setText(caloriesToQString(food->getCalories()));

    ui->radioButton_1->setChecked(true);
    ui->radioButton_2->setDisabled(true);

    PRINT_DEBUG("All food stats are applied");
}

Item* IngridientWindow::createNewItem(void) {
    PRINT_DEBUG("Creating new item");

    QString name = ui->lineEdit_1->text();
    QString mass = ui->lineEdit_2->text();
    QString price = ui->lineEdit_4->text();

    if ( name.isEmpty() ) {
        PRINT_ERR("Ingridient name could not be empty");

        throw EmptyIngridientNameException();
    }

    if ( mass.isEmpty() ) {
        PRINT_ERR("Ingridient mass could not be empty");

        throw EmptyIngridientMassException();
    }

    if ( price.isEmpty() ) {
        PRINT_ERR("Ingridient price could not be empty");

        throw EmptyIngridientPriceException();
    }

    return new Item(name.toStdString(), (!ui->comboBox_1->currentText().toStdString().compare("gram") ? 1 : QStringToMass(mass)),
                    QStringToPrice(price), static_cast<Item::MeasureType>(ui->comboBox_1->currentIndex()));
}

Food* IngridientWindow::createNewFood(void) {
    PRINT_DEBUG("Creating new food");

    QString name = ui->lineEdit_1->text();
    QString mass = ui->lineEdit_2->text();
    QString price = ui->lineEdit_4->text();
    QString fats = ui->lineEdit_3->text();
    QString proteins = ui->lineEdit_5->text();
    QString carbohydrates = ui->lineEdit_6->text();
    QString calories = ui->lineEdit_7->text();

    if ( name.isEmpty() ) {
        PRINT_ERR("Food name could not be empty");

        throw EmptyIngridientNameException();
    }

    if ( mass.isEmpty() ) {
        PRINT_ERR("Food mass could not be empty");

        throw EmptyIngridientMassException();
    }

    if ( price.isEmpty() ) {
        PRINT_ERR("Food price could not be empty");

        throw EmptyIngridientPriceException();
    }

    if ( fats.isEmpty() ) {
        PRINT_ERR("Food fats could not be empty");

        throw EmptyIngridientFatsException();
    }

    if ( proteins.isEmpty() ) {
        PRINT_ERR("Food proteins could not be empty");

        throw EmptyIngridientProteinsException();
    }

    if ( carbohydrates.isEmpty() ) {
        PRINT_ERR("Food carbohydrates could not be empty");

        throw EmptyIngridientCarbohydratesException();
    }

    if ( calories.isEmpty() ) {
        PRINT_ERR("Food calories could not be empty");

        throw EmptyIngridientCaloriesException();
    }

    return new Food(name.toStdString(), (!ui->comboBox_1->currentText().toStdString().compare("gram") ? 1 : QStringToMass(mass)),
                    QStringToPrice(price), static_cast<Item::MeasureType>(ui->comboBox_1->currentIndex()),
                    QStringToFats(fats),
                    QStringToProteins(proteins),
                    QStringToCarbohydrates(carbohydrates),
                    QStringToCalories(calories));
}

void IngridientWindow::editItem(Item* item) {
    PRINT_DEBUG("Editing item");

    if ( !ui->comboBox_1->currentText().toStdString().compare("gram") ) {
        item->setItemMass(1);
    } else {
        item->setItemMass(ui->lineEdit_2->text().toLong());
    }
    item->setItemPrice(ui->lineEdit_4->text().toLong());
    item->setItemUnitType(static_cast<Item::MeasureType>(ui->comboBox_1->currentIndex()));
}

void IngridientWindow::editFood(Food* food) {
    PRINT_DEBUG("Editing food");

    editItem(food);
    food->setItemFats(ui->lineEdit_3->text().toLong());
    food->setItemProteins(ui->lineEdit_5->text().toLong());
    food->setItemCarbohydrates(ui->lineEdit_6->text().toLong());
    food->setItemCalories(ui->lineEdit_7->text().toLong());
}

void IngridientWindow::buttonBoxAcceptedEditMode(void) {
    bool isFood = ui->radioButton_1->isChecked();

    if ( isFood ) {
        editFood(dynamic_cast<Food*>(editedItem));
    } else {
        editItem(editedItem);
    }
}

void IngridientWindow::buttonBoxAcceptedNewMode(void) {
    bool isFood = ui->radioButton_1->isChecked();

    if ( isFood ) {
        emit foodObjectReady(createNewFood());
    } else {
        emit itemObjectReady(createNewItem());
    }
}

void IngridientWindow::on_radioButton_1_clicked() {
    ui->lineEdit_3->setDisabled(false);
    ui->lineEdit_5->setDisabled(false);
    ui->lineEdit_6->setDisabled(false);
    ui->lineEdit_7->setDisabled(false);
}

void IngridientWindow::on_radioButton_2_clicked() {
    ui->lineEdit_3->setDisabled(true);
    ui->lineEdit_5->setDisabled(true);
    ui->lineEdit_6->setDisabled(true);
    ui->lineEdit_7->setDisabled(true);
}

void IngridientWindow::on_comboBox_1_currentIndexChanged(const QString& arg1) {
    if ( !arg1.toStdString().compare("gram") ) {
        ui->lineEdit_2->setDisabled(true);
    } else {
        ui->lineEdit_2->setDisabled(false);
    }

    PRINT_DEBUG(arg1.toStdString() << " selected");
}
<commit_msg>ingridientWindow: Catch item and food creation exceptions<commit_after>#include <convert.hpp>
#include <errors.hpp>
#include <debug.hpp>

#include <QMessageBox>
#include <ingridientWindow.hpp>
#include "ui_ingridientWindow.h"

IngridientWindow::IngridientWindow(QWidget* parent) :
    QDialog {parent},
    ui {new Ui::IngridientWindow},
    measureList {QStringList()} {

    setupMeasureList();
    ui->lineEdit_2->setDisabled(true);

    PRINT_OBJ("IngridientWindow created");
}

IngridientWindow::IngridientWindow(Item* item, QWidget* parent) :
    QDialog {parent},
    ui {new Ui::IngridientWindow},
    measureList {QStringList()},
    editMode {true},
    editedItem {item} {

    setupMeasureList();
    applyItemStats(item);
    this->setWindowTitle("Edit item");

    PRINT_OBJ("Existed item edit window created");
}

IngridientWindow::IngridientWindow(Food* food, QWidget* parent) :
    QDialog {parent},
    ui {new Ui::IngridientWindow},
    measureList {QStringList()},
    editMode {true},
    editedItem {food} {

    setupMeasureList();
    applyFoodStats(food);
    this->setWindowTitle("Edit food");

    PRINT_OBJ("Existed food edit window created");
}

IngridientWindow::~IngridientWindow() {
    delete ui;

    PRINT_OBJ("IngridientWindow destroyed");
}

void IngridientWindow::on_buttonBox_1_accepted() {
    if ( editMode ) {
        buttonBoxAcceptedEditMode();
    } else {
        buttonBoxAcceptedNewMode();
    }

    this->hide();

    PRINT_DEBUG("New item/food accepted");
}

void IngridientWindow::on_buttonBox_1_rejected() {
    this->hide();

    PRINT_DEBUG("New item/food rejected");
}

void IngridientWindow::setupMeasureList(void) {
    const std::string* names = Item::getItemMeasureTypeNamesList();

    ui->setupUi(this);

    for ( int i = 0; !names[i].empty(); i++ ) {
        measureList.append(QString::fromStdString(names[i]));
    }

    ui->comboBox_1->addItems(measureList);
}

void IngridientWindow::applyItemStats(Item* item) {
    ui->lineEdit_1->setText(QString::fromStdString(item->getName()));
    ui->lineEdit_1->setDisabled(true);
    ui->comboBox_1->setCurrentIndex(static_cast<int>(item->getUnitType()));
    if ( item->getUnitType() != Item::KGRAM ) {
        ui->lineEdit_2->setText(massToQString(item->getMass()));
    } else {
        ui->lineEdit_2->setDisabled(true);
    }
    ui->lineEdit_4->setText(priceToQString(item->getPrice()));

    on_radioButton_2_clicked();
    ui->radioButton_2->setChecked(true);
    ui->radioButton_1->setDisabled(true);

    PRINT_DEBUG("All items stats are applied");
}

void IngridientWindow::applyFoodStats(Food* food) {
    ui->lineEdit_1->setText(QString::fromStdString(food->getName()));
    ui->lineEdit_1->setDisabled(true);
    ui->comboBox_1->setCurrentIndex(static_cast<int>(food->getUnitType()));
    if ( food->getUnitType() != Item::KGRAM ) {
        ui->lineEdit_2->setText(massToQString(food->getMass()));
    } else {
        ui->lineEdit_2->setDisabled(true);
    }
    ui->lineEdit_4->setText(priceToQString(food->getPrice()));
    ui->lineEdit_3->setText(fatsToQString(food->getFats()));
    ui->lineEdit_5->setText(proteinsToQString(food->getProteins()));
    ui->lineEdit_6->setText(carbohydratesToQString(food->getCarbohydrates()));
    ui->lineEdit_7->setText(caloriesToQString(food->getCalories()));

    ui->radioButton_1->setChecked(true);
    ui->radioButton_2->setDisabled(true);

    PRINT_DEBUG("All food stats are applied");
}

Item* IngridientWindow::createNewItem(void) {
    PRINT_DEBUG("Creating new item");

    QString name = ui->lineEdit_1->text();
    QString mass = ui->lineEdit_2->text();
    QString price = ui->lineEdit_4->text();

    if ( name.isEmpty() ) {
        PRINT_ERR("Ingridient name could not be empty");

        throw EmptyIngridientNameException();
    }

    if ( mass.isEmpty() ) {
        PRINT_ERR("Ingridient mass could not be empty");

        throw EmptyIngridientMassException();
    }

    if ( price.isEmpty() ) {
        PRINT_ERR("Ingridient price could not be empty");

        throw EmptyIngridientPriceException();
    }

    return new Item(name.toStdString(), (!ui->comboBox_1->currentText().toStdString().compare("gram") ? 1 : QStringToMass(mass)),
                    QStringToPrice(price), static_cast<Item::MeasureType>(ui->comboBox_1->currentIndex()));
}

Food* IngridientWindow::createNewFood(void) {
    PRINT_DEBUG("Creating new food");

    QString name = ui->lineEdit_1->text();
    QString mass = ui->lineEdit_2->text();
    QString price = ui->lineEdit_4->text();
    QString fats = ui->lineEdit_3->text();
    QString proteins = ui->lineEdit_5->text();
    QString carbohydrates = ui->lineEdit_6->text();
    QString calories = ui->lineEdit_7->text();

    if ( name.isEmpty() ) {
        PRINT_ERR("Food name could not be empty");

        throw EmptyIngridientNameException();
    }

    if ( mass.isEmpty() ) {
        PRINT_ERR("Food mass could not be empty");

        throw EmptyIngridientMassException();
    }

    if ( price.isEmpty() ) {
        PRINT_ERR("Food price could not be empty");

        throw EmptyIngridientPriceException();
    }

    if ( fats.isEmpty() ) {
        PRINT_ERR("Food fats could not be empty");

        throw EmptyIngridientFatsException();
    }

    if ( proteins.isEmpty() ) {
        PRINT_ERR("Food proteins could not be empty");

        throw EmptyIngridientProteinsException();
    }

    if ( carbohydrates.isEmpty() ) {
        PRINT_ERR("Food carbohydrates could not be empty");

        throw EmptyIngridientCarbohydratesException();
    }

    if ( calories.isEmpty() ) {
        PRINT_ERR("Food calories could not be empty");

        throw EmptyIngridientCaloriesException();
    }

    return new Food(name.toStdString(), (!ui->comboBox_1->currentText().toStdString().compare("gram") ? 1 : QStringToMass(mass)),
                    QStringToPrice(price), static_cast<Item::MeasureType>(ui->comboBox_1->currentIndex()),
                    QStringToFats(fats),
                    QStringToProteins(proteins),
                    QStringToCarbohydrates(carbohydrates),
                    QStringToCalories(calories));
}

void IngridientWindow::editItem(Item* item) {
    PRINT_DEBUG("Editing item");

    if ( !ui->comboBox_1->currentText().toStdString().compare("gram") ) {
        item->setItemMass(1);
    } else {
        item->setItemMass(ui->lineEdit_2->text().toLong());
    }
    item->setItemPrice(ui->lineEdit_4->text().toLong());
    item->setItemUnitType(static_cast<Item::MeasureType>(ui->comboBox_1->currentIndex()));
}

void IngridientWindow::editFood(Food* food) {
    PRINT_DEBUG("Editing food");

    editItem(food);
    food->setItemFats(ui->lineEdit_3->text().toLong());
    food->setItemProteins(ui->lineEdit_5->text().toLong());
    food->setItemCarbohydrates(ui->lineEdit_6->text().toLong());
    food->setItemCalories(ui->lineEdit_7->text().toLong());
}

void IngridientWindow::buttonBoxAcceptedEditMode(void) {
    bool isFood = ui->radioButton_1->isChecked();

    if ( isFood ) {
        editFood(dynamic_cast<Food*>(editedItem));
    } else {
        editItem(editedItem);
    }
}

void IngridientWindow::buttonBoxAcceptedNewMode(void) {
    bool isFood = ui->radioButton_1->isChecked();
    Food* newFood = nullptr;
    Item* newItem = nullptr;

    try {
        if ( isFood ) {
            newFood = createNewFood();
        } else {
            newItem = createNewItem();
        }
    } catch ( IngridientWindowException e ) {
        QMessageBox msgBox;

        PRINT_ERR("Wrong value provided");

        msgBox.setText("Wrong value provided");
        msgBox.exec();

        return;
    } catch ( EngineException e ) {
        QMessageBox msgBox;

        PRINT_ERR("Engine calculation error");

        msgBox.setText("Engine calculation error");
        msgBox.exec();

        return;
    }

    if ( isFood ) {
        emit foodObjectReady(newFood);
    } else {
        emit itemObjectReady(newItem);
    }
}

void IngridientWindow::on_radioButton_1_clicked() {
    ui->lineEdit_3->setDisabled(false);
    ui->lineEdit_5->setDisabled(false);
    ui->lineEdit_6->setDisabled(false);
    ui->lineEdit_7->setDisabled(false);
}

void IngridientWindow::on_radioButton_2_clicked() {
    ui->lineEdit_3->setDisabled(true);
    ui->lineEdit_5->setDisabled(true);
    ui->lineEdit_6->setDisabled(true);
    ui->lineEdit_7->setDisabled(true);
}

void IngridientWindow::on_comboBox_1_currentIndexChanged(const QString& arg1) {
    if ( !arg1.toStdString().compare("gram") ) {
        ui->lineEdit_2->setDisabled(true);
    } else {
        ui->lineEdit_2->setDisabled(false);
    }

    PRINT_DEBUG(arg1.toStdString() << " selected");
}
<|endoftext|>


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

#include "cuckoo_utils.h"

#include <cstdint>
#include <cstdlib>
#include <limits>
#include <string>
#include <vector>

#include "absl/container/flat_hash_set.h"
#include "common/bit_packing.h"
#include "common/byte_coding.h"

namespace ci {

size_t GetMinNumBuckets(const size_t num_values, const size_t slots_per_bucket,
                        double max_load_factor) {
  assert(max_load_factor > 0.0 && max_load_factor < 1.0);
  const size_t min_num_buckets = static_cast<size_t>(std::ceil(
      (static_cast<double>(num_values) / max_load_factor) / slots_per_bucket));
  return min_num_buckets;
}

size_t GetMinNumBuckets(const size_t num_values,
                        const size_t slots_per_bucket) {
  if (slots_per_bucket == 1) {
    return GetMinNumBuckets(num_values, slots_per_bucket,
                            kMaxLoadFactor1SlotsPerBucket);
  } else if (slots_per_bucket == 2) {
    return GetMinNumBuckets(num_values, slots_per_bucket,
                            kMaxLoadFactor2SlotsPerBucket);
  } else if (slots_per_bucket == 4) {
    return GetMinNumBuckets(num_values, slots_per_bucket,
                            kMaxLoadFactor4SlotsPerBucket);
  } else if (slots_per_bucket == 8) {
    return GetMinNumBuckets(num_values, slots_per_bucket,
                            kMaxLoadFactor8SlotsPerBucket);
  }
  std::cerr << "No default max load factor for " << slots_per_bucket
            << " slots per bucket." << std::endl;
  exit(EXIT_FAILURE);
}

size_t GetMinCollisionFreeFingerprintLength(
    const std::vector<uint64_t>& fingerprints, const bool use_prefix_bits) {
  if (fingerprints.size() < 2) return 0;
  int num_bits = 1;
  for (; num_bits <= 64; ++num_bits) {
    absl::flat_hash_set<uint64_t> unique_fingerprints;
    bool success = true;
    for (const uint64_t fp : fingerprints) {
      // Extract `num_bits` prefix or suffix bits.
      const uint64_t fp_bits = use_prefix_bits
                                   ? GetFingerprintPrefix(fp, num_bits)
                                   : GetFingerprintSuffix(fp, num_bits);

      if (auto [_, was_inserted] = unique_fingerprints.insert(fp_bits);
          !was_inserted) {
        // Detected conflict. Try next higher number of bits.
        success = false;
        break;
      }
    }
    if (success) break;
  }
  if (num_bits == 65) {
    std::cerr << "Exhaused all 64 bits and still having collisions."
              << std::endl;
    exit(EXIT_FAILURE);
  }
  return num_bits;
}

size_t GetMinCollisionFreeFingerprintPrefixOrSuffix(
    const std::vector<uint64_t>& fingerprints, bool* use_prefix_bits) {
  // Determine minimum number of bits starting with lowest bit.
  const int num_suffix_bits = GetMinCollisionFreeFingerprintLength(
      fingerprints, /*use_prefix_bits=*/false);

  if (num_suffix_bits <= 1) {
    // No need to check prefix bits.
    *use_prefix_bits = false;
    return num_suffix_bits;
  }

  // Determine minimum number of bits starting with highest bit.
  const int num_prefix_bits = GetMinCollisionFreeFingerprintLength(
      fingerprints, /*use_prefix_bits=*/true);

  if (num_suffix_bits <= num_prefix_bits) {
    // Prefer using suffix bits.
    *use_prefix_bits = false;
    return num_suffix_bits;
  }

  *use_prefix_bits = true;
  return num_prefix_bits;
}

bool CheckWhetherAllBucketsOnlyContainSameSizeFingerprints(
    const std::vector<Fingerprint>& fingerprints,
    const size_t slots_per_bucket) {
  for (size_t i = 0; i < fingerprints.size(); i += slots_per_bucket) {
    bool found_active = false;
    size_t num_bits;
    for (size_t j = 0; j < slots_per_bucket; ++j) {
      const ci::Fingerprint& fp = fingerprints[i + j];
      if (!fp.active) continue;
      if (!found_active) {
        num_bits = fp.num_bits;
        found_active = true;
        continue;
      }
      if (fp.num_bits != num_bits) return false;
    }
  }
  return true;
}

bool Bucket::InsertValue(const CuckooValue& value) {
  if (slots_.size() < num_slots_) {
    slots_.push_back(value);
    return true;
  }
  return false;
}

namespace {

bool ContainsValue(absl::Span<const CuckooValue> values,
                   const CuckooValue& value) {
  for (const CuckooValue& val : values) {
    if (val.orig_value == value.orig_value) return true;
  }
  return false;
}

}  // namespace

bool Bucket::ContainsValue(const CuckooValue& value) const {
  return ci::ContainsValue(slots_, value);
}

bool LookupValueInBuckets(absl::Span<const Bucket> buckets,
                          const CuckooValue value, bool* in_primary) {
  if (buckets[value.primary_bucket].ContainsValue(value)) {
    *in_primary = true;
    return true;
  }
  if (buckets[value.secondary_bucket].ContainsValue(value)) {
    *in_primary = false;
    return true;
  }
  return false;
}

void FillKicked(absl::Span<const CuckooValue> values,
                absl::Span<Bucket> buckets) {
  for (const CuckooValue& value : values) {
    bool in_primary;
    LookupValueInBuckets(buckets, value, &in_primary);
    std::vector<CuckooValue>& kicked = buckets[value.primary_bucket].kicked_;
    // If the value isn't in its primary bucket and not in `kicked`, add it.
    if (!in_primary && !ContainsValue(kicked, value)) kicked.push_back(value);
  }
}

size_t GetRank(const Bitmap64& bitmap, const size_t idx) {
  assert(idx < bitmap.bits());
  return bitmap.GetOnesCountBeforeLimit(/*limit=*/idx);
}

namespace {
// Helper function that implements SelectOne() or SelectZero() depending on
// whether `count_ones` is set.
bool Select(const Bitmap64& bitmap, const size_t ith, const bool count_ones,
            size_t* pos) {
  size_t count = 0;
  for (size_t i = 0; i < bitmap.bits(); ++i) {
    if (bitmap.Get(i) == count_ones) {
      if (count == ith) {
        *pos = i;
        return true;
      }
      ++count;
    }
  }
  return false;
}
}  // namespace

bool SelectOne(const Bitmap64& bitmap, const size_t ith, size_t* pos) {
  return Select(bitmap, ith, /*count_ones=*/true, pos);
}

bool SelectZero(const Bitmap64& bitmap, const size_t ith, size_t* pos) {
  return Select(bitmap, ith, /*count_ones=*/false, pos);
}

Bitmap64Ptr GetEmptyBucketsBitmap(const Bitmap64& empty_slots_bitmap,
                                  const size_t slots_per_bucket) {
  assert(empty_slots_bitmap.bits() % slots_per_bucket == 0);
  Bitmap64Ptr empty_buckets_bitmap = absl::make_unique<Bitmap64>(
      /*size=*/empty_slots_bitmap.bits() / slots_per_bucket);
  for (size_t i = 0; i < empty_slots_bitmap.bits(); i += slots_per_bucket) {
    bool empty_bucket = true;
    for (size_t j = 0; j < slots_per_bucket; ++j) {
      if (!empty_slots_bitmap.Get(i + j)) {
        empty_bucket = false;
        break;
      }
    }
    if (empty_bucket) empty_buckets_bitmap->Set(i / slots_per_bucket, true);
  }
  return empty_buckets_bitmap;
}

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

#include "cuckoo_utils.h"

#include <cstdint>
#include <cstdlib>
#include <limits>
#include <string>
#include <vector>

#include "absl/container/flat_hash_set.h"
#include "common/bit_packing.h"
#include "common/byte_coding.h"

namespace ci {

size_t GetMinNumBuckets(const size_t num_values, const size_t slots_per_bucket,
                        double max_load_factor) {
  assert(max_load_factor > 0.0 && max_load_factor < 1.0);
  const size_t min_num_buckets = static_cast<size_t>(std::ceil(
      (static_cast<double>(num_values) / max_load_factor) / slots_per_bucket));
  return min_num_buckets;
}

size_t GetMinNumBuckets(const size_t num_values,
                        const size_t slots_per_bucket) {
  if (slots_per_bucket == 1) {
    return GetMinNumBuckets(num_values, slots_per_bucket,
                            kMaxLoadFactor1SlotsPerBucket);
  } else if (slots_per_bucket == 2) {
    return GetMinNumBuckets(num_values, slots_per_bucket,
                            kMaxLoadFactor2SlotsPerBucket);
  } else if (slots_per_bucket == 4) {
    return GetMinNumBuckets(num_values, slots_per_bucket,
                            kMaxLoadFactor4SlotsPerBucket);
  } else if (slots_per_bucket == 8) {
    return GetMinNumBuckets(num_values, slots_per_bucket,
                            kMaxLoadFactor8SlotsPerBucket);
  }
  std::cerr << "No default max load factor for " << slots_per_bucket
            << " slots per bucket." << std::endl;
  exit(EXIT_FAILURE);
}

size_t GetMinCollisionFreeFingerprintLength(
    const std::vector<uint64_t>& fingerprints, const bool use_prefix_bits) {
  if (fingerprints.size() < 2) return 0;
  int num_bits = 1;
  for (; num_bits <= 64; ++num_bits) {
    absl::flat_hash_set<uint64_t> unique_fingerprints;
    bool success = true;
    for (const uint64_t fp : fingerprints) {
      // Extract `num_bits` prefix or suffix bits.
      const uint64_t fp_bits = use_prefix_bits
                                   ? GetFingerprintPrefix(fp, num_bits)
                                   : GetFingerprintSuffix(fp, num_bits);

      if (auto [_, was_inserted] = unique_fingerprints.insert(fp_bits);
          !was_inserted) {
        // Detected conflict. Try next higher number of bits.
        success = false;
        break;
      }
    }
    if (success) break;
  }
  if (num_bits == 65) {
    std::cerr << "Exhaused all 64 bits and still having collisions."
              << std::endl;
    exit(EXIT_FAILURE);
  }
  return num_bits;
}

size_t GetMinCollisionFreeFingerprintPrefixOrSuffix(
    const std::vector<uint64_t>& fingerprints, bool* use_prefix_bits) {
  // Determine minimum number of bits starting with lowest bit.
  const int num_suffix_bits = GetMinCollisionFreeFingerprintLength(
      fingerprints, /*use_prefix_bits=*/false);

  if (num_suffix_bits <= 1) {
    // No need to check prefix bits.
    *use_prefix_bits = false;
    return num_suffix_bits;
  }

  // Determine minimum number of bits starting with highest bit.
  const int num_prefix_bits = GetMinCollisionFreeFingerprintLength(
      fingerprints, /*use_prefix_bits=*/true);

  if (num_suffix_bits <= num_prefix_bits) {
    // Prefer using suffix bits.
    *use_prefix_bits = false;
    return num_suffix_bits;
  }

  *use_prefix_bits = true;
  return num_prefix_bits;
}

bool CheckWhetherAllBucketsOnlyContainSameSizeFingerprints(
    const std::vector<Fingerprint>& fingerprints,
    const size_t slots_per_bucket) {
  for (size_t i = 0; i < fingerprints.size(); i += slots_per_bucket) {
    bool found_active = false;
    size_t num_bits;
    for (size_t j = 0; j < slots_per_bucket; ++j) {
      const ci::Fingerprint& fp = fingerprints[i + j];
      if (!fp.active) continue;
      if (!found_active) {
        num_bits = fp.num_bits;
        found_active = true;
        continue;
      }
      if (fp.num_bits != num_bits) return false;
    }
  }
  return true;
}

bool Bucket::InsertValue(const CuckooValue& value) {
  if (slots_.size() < num_slots_) {
    slots_.push_back(value);
    return true;
  }
  return false;
}

namespace {

bool ContainsValue(absl::Span<const CuckooValue> values,
                   const CuckooValue& value) {
  for (const CuckooValue& val : values) {
    if (val.orig_value == value.orig_value) return true;
  }
  return false;
}

}  // namespace

bool Bucket::ContainsValue(const CuckooValue& value) const {
  return ci::ContainsValue(slots_, value);
}

bool LookupValueInBuckets(absl::Span<const Bucket> buckets,
                          const CuckooValue value, bool* in_primary) {
  if (buckets[value.primary_bucket].ContainsValue(value)) {
    *in_primary = true;
    return true;
  }
  if (buckets[value.secondary_bucket].ContainsValue(value)) {
    *in_primary = false;
    return true;
  }
  return false;
}

void FillKicked(absl::Span<const CuckooValue> values,
                absl::Span<Bucket> buckets) {
  for (const CuckooValue& value : values) {
    bool in_primary;
    LookupValueInBuckets(buckets, value, &in_primary);
    std::vector<CuckooValue>& kicked = buckets[value.primary_bucket].kicked_;
    // If the value isn't in its primary bucket and not in `kicked`, add it.
    if (!in_primary && !ContainsValue(kicked, value)) kicked.push_back(value);
  }
}

size_t GetRank(const Bitmap64& bitmap, const size_t idx) {
  assert(idx <= bitmap.bits());
  return bitmap.GetOnesCountBeforeLimit(/*limit=*/idx);
}

namespace {
// Helper function that implements SelectOne() or SelectZero() depending on
// whether `count_ones` is set.
bool Select(const Bitmap64& bitmap, const size_t ith, const bool count_ones,
            size_t* pos) {
  size_t count = 0;
  for (size_t i = 0; i < bitmap.bits(); ++i) {
    if (bitmap.Get(i) == count_ones) {
      if (count == ith) {
        *pos = i;
        return true;
      }
      ++count;
    }
  }
  return false;
}
}  // namespace

bool SelectOne(const Bitmap64& bitmap, const size_t ith, size_t* pos) {
  return Select(bitmap, ith, /*count_ones=*/true, pos);
}

bool SelectZero(const Bitmap64& bitmap, const size_t ith, size_t* pos) {
  return Select(bitmap, ith, /*count_ones=*/false, pos);
}

Bitmap64Ptr GetEmptyBucketsBitmap(const Bitmap64& empty_slots_bitmap,
                                  const size_t slots_per_bucket) {
  assert(empty_slots_bitmap.bits() % slots_per_bucket == 0);
  Bitmap64Ptr empty_buckets_bitmap = absl::make_unique<Bitmap64>(
      /*size=*/empty_slots_bitmap.bits() / slots_per_bucket);
  for (size_t i = 0; i < empty_slots_bitmap.bits(); i += slots_per_bucket) {
    bool empty_bucket = true;
    for (size_t j = 0; j < slots_per_bucket; ++j) {
      if (!empty_slots_bitmap.Get(i + j)) {
        empty_bucket = false;
        break;
      }
    }
    if (empty_bucket) empty_buckets_bitmap->Set(i / slots_per_bucket, true);
  }
  return empty_buckets_bitmap;
}

}  // namespace ci
<|endoftext|>


<commit_before>/*
 * Copyright 2010 MQWeb - Franky Braem
 *
 * Licensed under the EUPL, Version 1.1 or – as soon they
 * will be approved by the European Commission - subsequent
 * versions of the EUPL (the "Licence");
 * You may not use this work except in compliance with the
 * Licence.
 * You may obtain a copy of the Licence at:
 *
 * http://joinup.ec.europa.eu/software/page/eupl
 *
 * Unless required by applicable law or agreed to in
 * writing, software distributed under the Licence is
 * distributed on an "AS IS" basis,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied.
 * See the Licence for the specific language governing
 * permissions and limitations under the Licence.
 */
#include <sstream>

#include "MQ/Web/Controller.h"
#include "MQ/MQSubsystem.h"

#include "Poco/Util/Application.h"
#include "Poco/NullStream.h"
#include "Poco/StreamCopier.h"
#include "Poco/URI.h"

#include "Poco/JSON/Parser.h"

namespace MQ
{
namespace Web
{

Controller::Controller() : _data(new Poco::JSON::Object()), _request(NULL), _response(NULL)
{
}

Controller::~Controller()
{
}

void Controller::handlePart(const Poco::Net::MessageHeader& header, std::istream& stream)
{
	//TODO
}

void Controller::handle(const std::vector<std::string>& parameters, Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response)
{
	_parameters = parameters;
	_request = &request;
	_response = &response;

	if ( _parameters.size() > 0 )
	{
		_action = _parameters.front();
		_parameters.erase(_parameters.begin());
	}
	else
	{
		setResponseStatus(Poco::Net::HTTPResponse::HTTP_BAD_REQUEST, "Invalid URI parameters");
		return;
	}

	for(std::vector<std::string>::iterator it = _parameters.begin(); it != _parameters.end(); ++it)
	{
		size_t pos = it->find_first_of(':');
		if ( pos != std::string::npos )
		{
			std::string name = it->substr(0, pos);
			std::string value = it->substr(pos+1);
			_namedParameters[name] = value;
		}
	}

	std::string contentType = request.getContentType();
	if ( contentType == "application/json" )
	{
		Poco::JSON::Parser parser;
		try
		{
			Poco::Dynamic::Var json = parser.parse(request.stream());
			if ( ! json.isEmpty() && json.type() == typeid(Poco::JSON::Object::Ptr) )
			{
				_data->set("input", json.extract<Poco::JSON::Object::Ptr>());
			}
		}
		catch(Poco::JSON::JSONException& jsone)
		{
			// Make sure everything is read, otherwise this can result
			// in Bad Request error in the next call.
			Poco::NullOutputStream nos;
			Poco::StreamCopier::copyStream(request.stream(), nos);

			setResponseStatus(Poco::Net::HTTPResponse::HTTP_BAD_REQUEST, "JSON error occurred: " + jsone.displayText());
			return;
		}
	}
	else
	{
		_form.load(request, request.stream(), *this);
	}

	// Make sure everything is read, otherwise this can result
	// in Bad Request error in the next call.
	Poco::NullOutputStream nos;
	Poco::StreamCopier::copyStream(request.stream(), nos);

	beforeAction();

	if ( response.getStatus() != Poco::Net::HTTPResponse::HTTP_OK
		|| _data->has("error") )
	{
		//TODO: return error template file or json error
	}

	const ActionMap& actions = getActions();
	ActionMap::const_iterator it = actions.find(_action);
	if ( it == actions.end() )
	{
		setResponseStatus(Poco::Net::HTTPResponse::HTTP_NOT_FOUND, "Invalid action '" + _action + "' specified.");
		return;
	}

	ActionFn action = it->second;
	(this->*action)();

	afterAction();
}

void Controller::render()
{
	response().setChunkedTransferEncoding(true);
	response().setContentType("application/json");
	response().set("Cache-Controle", "no-cache,no-store,must-revalidate"); // HTTP 1.1
	response().set("Pragma", "no-cache"); // HTTP 1.0
	response().set("Expires", "0"); // Proxies

	std::stringstream ss;

	if ( _form.has("callback") )
	{
		ss << _form.get("callback") << '(';
	}

	data().stringify(ss);
	ss.flush();

	if ( _form.has("callback") )
	{
		ss << ");";
	}

	Poco::StreamCopier::copyStream(ss, _response->send());
}

void Controller::formElementToJSONArray(const std::string& name, Poco::JSON::Array::Ptr arr)
{
	for(Poco::Net::NameValueCollection::ConstIterator it = form().find(name);
		it != form().end() && Poco::icompare(it->first, name) == 0;
		++it)
	{
		arr->add(it->second);
	}
}

std::string Controller::htmlize(const std::string &str)
{
	std::string::const_iterator it(str.begin());
	std::string::const_iterator end(str.end());
	std::string html;
	for (; it != end; ++it)
	{
		switch (*it)
		{
		case '<': html += "<"; break;
		case '>': html += ">"; break;
		case '"': html += """; break;
		case '&': html += "&"; break;
		default: html += *it; break;
		}
	}
	return html;
}

} } // Namespace MQ::Web
<commit_msg>Don't call action when an error occurred in beforeAction<commit_after>/*
 * Copyright 2010 MQWeb - Franky Braem
 *
 * Licensed under the EUPL, Version 1.1 or – as soon they
 * will be approved by the European Commission - subsequent
 * versions of the EUPL (the "Licence");
 * You may not use this work except in compliance with the
 * Licence.
 * You may obtain a copy of the Licence at:
 *
 * http://joinup.ec.europa.eu/software/page/eupl
 *
 * Unless required by applicable law or agreed to in
 * writing, software distributed under the Licence is
 * distributed on an "AS IS" basis,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
 * express or implied.
 * See the Licence for the specific language governing
 * permissions and limitations under the Licence.
 */
#include <sstream>

#include "MQ/Web/Controller.h"
#include "MQ/MQSubsystem.h"

#include "Poco/Util/Application.h"
#include "Poco/NullStream.h"
#include "Poco/StreamCopier.h"
#include "Poco/URI.h"

#include "Poco/JSON/Parser.h"

namespace MQ
{
namespace Web
{

Controller::Controller() : _data(new Poco::JSON::Object()), _request(NULL), _response(NULL)
{
}

Controller::~Controller()
{
}

void Controller::handlePart(const Poco::Net::MessageHeader& header, std::istream& stream)
{
	//TODO
}

void Controller::handle(const std::vector<std::string>& parameters, Poco::Net::HTTPServerRequest& request, Poco::Net::HTTPServerResponse& response)
{
	_parameters = parameters;
	_request = &request;
	_response = &response;

	if ( _parameters.size() > 0 )
	{
		_action = _parameters.front();
		_parameters.erase(_parameters.begin());
	}
	else
	{
		setResponseStatus(Poco::Net::HTTPResponse::HTTP_BAD_REQUEST, "Invalid URI parameters");
		return;
	}

	for(std::vector<std::string>::iterator it = _parameters.begin(); it != _parameters.end(); ++it)
	{
		size_t pos = it->find_first_of(':');
		if ( pos != std::string::npos )
		{
			std::string name = it->substr(0, pos);
			std::string value = it->substr(pos+1);
			_namedParameters[name] = value;
		}
	}

	std::string contentType = request.getContentType();
	if ( contentType == "application/json" )
	{
		Poco::JSON::Parser parser;
		try
		{
			Poco::Dynamic::Var json = parser.parse(request.stream());
			if ( ! json.isEmpty() && json.type() == typeid(Poco::JSON::Object::Ptr) )
			{
				_data->set("input", json.extract<Poco::JSON::Object::Ptr>());
			}
		}
		catch(Poco::JSON::JSONException& jsone)
		{
			// Make sure everything is read, otherwise this can result
			// in Bad Request error in the next call.
			Poco::NullOutputStream nos;
			Poco::StreamCopier::copyStream(request.stream(), nos);

			setResponseStatus(Poco::Net::HTTPResponse::HTTP_BAD_REQUEST, "JSON error occurred: " + jsone.displayText());
			return;
		}
	}
	else
	{
		_form.load(request, request.stream(), *this);
	}

	// Make sure everything is read, otherwise this can result
	// in Bad Request error in the next call.
	Poco::NullOutputStream nos;
	Poco::StreamCopier::copyStream(request.stream(), nos);

	beforeAction();

	// It's possible that already an error occurred in beforeAction.
	// So check for it and don't do anything when there was already a problem.
	if ( response.getStatus() == Poco::Net::HTTPResponse::HTTP_OK
		&& !_data->has("error") )
	{
		const ActionMap& actions = getActions();
		ActionMap::const_iterator it = actions.find(_action);
		if ( it == actions.end() )
		{
			setResponseStatus(Poco::Net::HTTPResponse::HTTP_NOT_FOUND, "Invalid action '" + _action + "' specified.");
			return;
		}

		ActionFn action = it->second;
		(this->*action)();

		afterAction();
	}
}

void Controller::render()
{
	response().setChunkedTransferEncoding(true);
	response().setContentType("application/json");
	response().set("Cache-Controle", "no-cache,no-store,must-revalidate"); // HTTP 1.1
	response().set("Pragma", "no-cache"); // HTTP 1.0
	response().set("Expires", "0"); // Proxies

	std::stringstream ss;

	if ( _form.has("callback") )
	{
		ss << _form.get("callback") << '(';
	}

	data().stringify(ss);
	ss.flush();

	if ( _form.has("callback") )
	{
		ss << ");";
	}

	Poco::StreamCopier::copyStream(ss, _response->send());
}

void Controller::formElementToJSONArray(const std::string& name, Poco::JSON::Array::Ptr arr)
{
	for(Poco::Net::NameValueCollection::ConstIterator it = form().find(name);
		it != form().end() && Poco::icompare(it->first, name) == 0;
		++it)
	{
		arr->add(it->second);
	}
}

std::string Controller::htmlize(const std::string &str)
{
	std::string::const_iterator it(str.begin());
	std::string::const_iterator end(str.end());
	std::string html;
	for (; it != end; ++it)
	{
		switch (*it)
		{
		case '<': html += "<"; break;
		case '>': html += ">"; break;
		case '"': html += """; break;
		case '&': html += "&"; break;
		default: html += *it; break;
		}
	}
	return html;
}

} } // Namespace MQ::Web
<|endoftext|>