<commit_before>#ifndef XML11_HPP
#define XML11_HPP

#include <string>
#include <memory>
#include <vector>

namespace xml11 {

using NodeList = std::vector<class Node>;
using ValueFilter = std::string (const std::string& value);

class Node {
public:
    enum class Type : char {
        ELEMENT,
        ATTRIBUTE,
        OPTIONAL
    };

    class Xml11Exception final : public std::runtime_error {
    public:
        using std::runtime_error::runtime_error;
    };

public:
    static Node fromString(const std::string& text, const bool isCaseInsensitive=true, ValueFilter valueFilter = nullptr);
    std::string toString(const bool indent = true, ValueFilter valueFilter = nullptr) const;

public:
    ~Node() noexcept;
    Node(const std::shared_ptr<class NodeImpl>& node) noexcept;
    Node(const Node& node) noexcept;
    Node(Node&& node) noexcept;
    Node(std::string name);
    Node(std::string name, const Node& node);
    Node(std::string name, Node&& node);
    Node(std::string name, std::string value);
    Node(std::string name, std::string value, const Type type);
    Node(std::string name, const NodeList& nodes);
    Node(std::string name, NodeList&& nodes);

    static void AddNode(Node&)
    {

    }

    template<class Head, class... Tail>
    static void AddNode(Node& node, Head&& head, Tail&& ...tail)
    {
        node += std::forward<Head>(head);
        AddNode(node, std::forward<Tail>(tail)...);
    }

    template<class... Tail>
    Node(std::string name, const NodeList& nodes, Tail&& ...tail)
        : Node(std::move(name), nodes)
    {
        AddNode(*const_cast<Node*>(this), std::forward<Tail>(tail)...);
    }

    template<class... Tail>
    Node(std::string name, const Node& node, Tail&& ...tail)
        : Node(std::move(name), node)
    {
        AddNode(*const_cast<Node*>(this), std::forward<Tail>(tail)...);
    }

    template<class T,
             class=typename std::enable_if<
                 decltype(std::to_string(T()), true)(true),
                 void
             >::type>
    Node(std::string name, T&& value)
        : Node {std::move(name), std::to_string(std::forward<T>(value))}
    {

    }

    Node& operator = (const Node& node) noexcept;
    Node& operator = (Node&& node) noexcept;
    bool operator == (const Node& node) const noexcept;
    bool operator != (const Node& node) const noexcept;
    operator bool() const noexcept;

    NodeList operator [] (const std::string& name);
    NodeList operator [] (const char* name);
    NodeList operator [] (const Type& type);
    const NodeList operator [] (const std::string& name) const;
    const NodeList operator [] (const char* name) const;
    const NodeList operator [] (const Type& type) const;

    NodeList findNodes(const std::string& name);
    NodeList findNodes(const Type& type);
    const NodeList findNodes(const std::string& name) const;
    const NodeList findNodes(const Type& type) const;

    NodeList findNodesXPath(const std::string& name);
    const NodeList findNodesXPath(const std::string& name) const;

    Node operator () (const std::string& name);
    Node operator () (const Type& type);
    const Node operator () (const std::string& name) const;
    const Node operator () (const Type& type) const;

    Node findNode(const std::string& name);
    Node findNode(const Type& type);
    const Node findNode(const std::string& name) const;
    const Node findNode(const Type& type) const;

    Node findNodeXPath(const std::string& name);
    const Node findNodeXPath(const std::string& name) const;

    Node& operator += (const Node& root);
    Node& operator += (Node&& root);
    Node& operator += (const NodeList& nodes);
    Node& operator += (NodeList&& nodes);

    Node& addNode(const Node& node);
    Node& addNode(Node&& node);
    Node& addNode(std::string name);
    Node& addNode(std::string name, std::string value);
    Node& addNode(std::string name, std::string value, const Node::Type type);

    template<class T,
             class=typename std::enable_if<
                 decltype(std::to_string(T()), true)(true),
             T>::type>
    Node& addNode(std::string name, T&& value)
    {
        return addNode(std::move(name), std::to_string(std::forward<T>(value)));
    }

    Node& addAttribute(std::string name);
    Node& addAttribute(std::string name, std::string value);

    Node& addNodes(const NodeList& node);
    Node& addNodes(NodeList&& node);

    Node& operator -= (const Node& root);

    Node& eraseNode(const Node& node);
    Node& eraseNodes(const NodeList& node);

    std::vector<Node> nodes();
    const std::vector<Node> nodes() const;

    Node::Type type() const;
    void type(const Node::Type type);

    std::string& name() const;
    void name(std::string name);

    std::string& text() const;
    void text(std::string value);

    void value(std::string text);
    void value(const Node& node);
    void value(Node&& node);

    void isCaseInsensitive(const bool isCaseInsensitive);
    bool isCaseInsensitive() const;

private:
    std::shared_ptr<class NodeImpl> pimpl {nullptr};
};

namespace literals {

Node operator "" _xml(const char* value, size_t size);

} /* literals */

} /* namespace xml11 */

#endif // XML11_HPP
<commit_msg>feature. we optionally create nodes from optional strings or optional values which can be strings<commit_after>#ifndef XML11_HPP
#define XML11_HPP

#include <string>
#include <memory>
#include <vector>

namespace xml11 {

using NodeList = std::vector<class Node>;
using ValueFilter = std::string (const std::string& value);

class Node {
public:
    enum class Type : char {
        ELEMENT,
        ATTRIBUTE,
        OPTIONAL
    };

    class Xml11Exception final : public std::runtime_error {
    public:
        using std::runtime_error::runtime_error;
    };

public:
    static Node fromString(const std::string& text, const bool isCaseInsensitive=true, ValueFilter valueFilter = nullptr);
    std::string toString(const bool indent = true, ValueFilter valueFilter = nullptr) const;

public:
    ~Node() noexcept;
    Node(const std::shared_ptr<class NodeImpl>& node) noexcept;
    Node(const Node& node) noexcept;
    Node(Node&& node) noexcept;
    Node(std::string name);
    Node(std::string name, const Node& node);
    Node(std::string name, Node&& node);
    Node(std::string name, std::string value);
    Node(std::string name, std::string value, const Type type);
    Node(std::string name, const NodeList& nodes);
    Node(std::string name, NodeList&& nodes);

    /*
     * We can instantly create new node with random length parameters of Nodes and NodeLists.
     */
    static void AddNode(Node&)
    {

    }

    template<class Head, class... Tail>
    static void AddNode(Node& node, Head&& head, Tail&& ...tail)
    {
        node += std::forward<Head>(head);
        AddNode(node, std::forward<Tail>(tail)...);
    }

    template<class... Tail>
    Node(std::string name, const NodeList& nodes, Tail&& ...tail)
        : Node(std::move(name), nodes)
    {
        AddNode(*const_cast<Node*>(this), std::forward<Tail>(tail)...);
    }

    template<class... Tail>
    Node(std::string name, const Node& node, Tail&& ...tail)
        : Node(std::move(name), node)
    {
        AddNode(*const_cast<Node*>(this), std::forward<Tail>(tail)...);
    }

    /*
     * We can optionally create optional value or pointer, if it valid.
     * If it is not a string it will be converted to the string.
     */
    template<class T,
             class=typename std::enable_if<
                 decltype(*std::declval<T&>(), true)(true) &&
                 decltype(std::to_string(*std::declval<T&>()), true)(true) &&
                 !std::is_same<std::string, typename std::decay<decltype(*std::declval<T&>())>::type>::value &&
                 !std::is_same<std::string, typename std::decay<T>::type>::value &&
                 !std::is_same<char*, typename std::decay<T>::type>::value,
                 T
             >::type,
             class=void>
    Node(std::string name, const T& value)
        : Node {std::move(name)}
    {
        if (value) {
            this->value(std::to_string(*value));
        }
    }

    /*
     * We can optionally create optional value or pointer, if it valid.
     * This function works if optional value contains the string.
     */
    template<class T,
             class=typename std::enable_if<
                 decltype(*std::declval<T&>(), true)(true) &&
                 std::is_same<std::string, typename std::decay<decltype(*std::declval<T&>())>::type>::value &&
                 !std::is_same<std::string, typename std::decay<T>::type>::value &&
                 !std::is_same<char*, typename std::decay<T>::type>::value,
                 T
             >::type,
             class=void,
             class=void>
    Node(std::string name, const T& value)
        : Node {std::move(name)}
    {
        if (value) {
            this->value(*value);
        }
    }

    /*
     * We can create Node from everything that can be represented as string.
     */
    template<class T,
             class=typename std::enable_if<
                 decltype(std::to_string(std::declval<T&>()), true)(true),
                 void
             >::type>
    Node(std::string name, T&& value)
        : Node {std::move(name), std::to_string(std::forward<T>(value))}
    {

    }

    Node& operator = (const Node& node) noexcept;
    Node& operator = (Node&& node) noexcept;
    bool operator == (const Node& node) const noexcept;
    bool operator != (const Node& node) const noexcept;
    operator bool() const noexcept;

    NodeList operator [] (const std::string& name);
    NodeList operator [] (const char* name);
    NodeList operator [] (const Type& type);
    const NodeList operator [] (const std::string& name) const;
    const NodeList operator [] (const char* name) const;
    const NodeList operator [] (const Type& type) const;

    NodeList findNodes(const std::string& name);
    NodeList findNodes(const Type& type);
    const NodeList findNodes(const std::string& name) const;
    const NodeList findNodes(const Type& type) const;

    NodeList findNodesXPath(const std::string& name);
    const NodeList findNodesXPath(const std::string& name) const;

    Node operator () (const std::string& name);
    Node operator () (const Type& type);
    const Node operator () (const std::string& name) const;
    const Node operator () (const Type& type) const;

    Node findNode(const std::string& name);
    Node findNode(const Type& type);
    const Node findNode(const std::string& name) const;
    const Node findNode(const Type& type) const;

    Node findNodeXPath(const std::string& name);
    const Node findNodeXPath(const std::string& name) const;

    Node& operator += (const Node& root);
    Node& operator += (Node&& root);
    Node& operator += (const NodeList& nodes);
    Node& operator += (NodeList&& nodes);

    Node& addNode(const Node& node);
    Node& addNode(Node&& node);
    Node& addNode(std::string name);
    Node& addNode(std::string name, std::string value);
    Node& addNode(std::string name, std::string value, const Node::Type type);

    template<class T,
             class=typename std::enable_if<
                 decltype(std::to_string(T()), true)(true),
             T>::type>
    Node& addNode(std::string name, T&& value)
    {
        return addNode(std::move(name), std::to_string(std::forward<T>(value)));
    }

    Node& addAttribute(std::string name);
    Node& addAttribute(std::string name, std::string value);

    Node& addNodes(const NodeList& node);
    Node& addNodes(NodeList&& node);

    Node& operator -= (const Node& root);

    Node& eraseNode(const Node& node);
    Node& eraseNodes(const NodeList& node);

    std::vector<Node> nodes();
    const std::vector<Node> nodes() const;

    Node::Type type() const;
    void type(const Node::Type type);

    std::string& name() const;
    void name(std::string name);

    std::string& text() const;
    void text(std::string value);

    void value(std::string text);
    void value(const Node& node);
    void value(Node&& node);

    void isCaseInsensitive(const bool isCaseInsensitive);
    bool isCaseInsensitive() const;

private:
    std::shared_ptr<class NodeImpl> pimpl {nullptr};
};

namespace literals {

Node operator "" _xml(const char* value, size_t size);

} /* literals */

} /* namespace xml11 */

#endif // XML11_HPP
<|endoftext|>


<commit_before>/*
  This file is part of the Ofi Labs X2 project.

  Copyright (C) 2010 Ariya Hidayat <ariya.hidayat@gmail.com>

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
    * Neither the name of the <organization> nor the
      names of its contributors may be used to endorse or promote products
      derived from this software without specific prior written permission.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "kineticmodel.h"

#include <QTimer>
#include <QDateTime>

static const int KineticModelDefaultUpdateInterval = 15; // ms

class KineticModelPrivate
{
public:
    QTimer ticker;

    bool released;
    int duration;
    qreal position;
    qreal velocity;
    qreal deacceleration;

    QTime timestamp;
    qreal lastPosition;

    KineticModelPrivate();
};

KineticModelPrivate::KineticModelPrivate()
    : released(false)
    , duration(1403)
    , position(0)
    , velocity(0)
    , deacceleration(0)
    , lastPosition(0)
{

}

KineticModel::KineticModel(QObject *parent)
    : QObject(parent)
    , d_ptr(new KineticModelPrivate)
{
    connect(&d_ptr->ticker, SIGNAL(timeout()), SLOT(update()));
    d_ptr->ticker.setInterval(KineticModelDefaultUpdateInterval);
}

KineticModel::~KineticModel()
{

}

int KineticModel::duration() const
{
    return d_ptr->duration;
}

void KineticModel::setDuration(int ms)
{
    d_ptr->duration = ms;
}

qreal KineticModel::position() const
{
    return d_ptr->position;
}

void KineticModel::setPosition(qreal pos)
{
    d_ptr->released = false;

    qreal oldPos = d_ptr->position;
    d_ptr->position = pos;
    if (!qFuzzyCompare(pos, oldPos))
        emit positionChanged(pos);

    update();
    if (!d_ptr->ticker.isActive())
        d_ptr->ticker.start();
}

int KineticModel::updateInterval() const
{
    return d_ptr->ticker.interval();
}

void KineticModel::setUpdateInterval(int ms)
{
    d_ptr->ticker.setInterval(ms);
}

void KineticModel::resetSpeed()
{
    d_ptr->velocity = 0;
    d_ptr->lastPosition = d_ptr->position;
}

void KineticModel::release()
{
    Q_D(KineticModel);

    d->released = true;

    d->deacceleration = d->velocity * 1000 / (1 + d_ptr->duration);
    if (d->deacceleration < 0)
        d->deacceleration = -d->deacceleration;

    if (!d->ticker.isActive())
        d->ticker.start();

    update();
}

void KineticModel::update()
{
    Q_D(KineticModel);

    int elapsed = d_ptr->timestamp.elapsed();

    // too fast gives less accuracy
    if (elapsed < 5)
        return;

    qreal delta = static_cast<qreal>(elapsed) / 1000.0;

    if (d->released) {
        d->position += (d->velocity * delta);
        qreal vstep = d->deacceleration * delta;
        if (d->velocity < vstep && d->velocity >= -vstep) {
            d->velocity = 0;
            d->ticker.stop();
        } else {
            if (d->velocity > 0)
                d->velocity -= vstep;
            else
                d->velocity += vstep;
        }
        emit positionChanged(d->position);
    } else {
        qreal lastSpeed = d->velocity;
        qreal currentSpeed = (d->position - d->lastPosition) / delta;
        d->velocity = .75 * lastSpeed + .25 * currentSpeed;
        d->lastPosition = d->position;
    }

    d->timestamp.start();
}
<commit_msg>widget/kineticmodel: Improve speed filtering.<commit_after>/*
  This file is part of the Ofi Labs X2 project.

  Copyright (C) 2010 Ariya Hidayat <ariya.hidayat@gmail.com>

  Redistribution and use in source and binary forms, with or without
  modification, are permitted provided that the following conditions are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
    * Neither the name of the <organization> nor the
      names of its contributors may be used to endorse or promote products
      derived from this software without specific prior written permission.

  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
  DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

#include "kineticmodel.h"

#include <QTimer>
#include <QDateTime>

static const int KineticModelDefaultUpdateInterval = 15; // ms

class KineticModelPrivate
{
public:
    QTimer ticker;

    bool released;
    int duration;
    qreal position;
    qreal velocity;
    qreal deacceleration;

    QTime timestamp;
    qreal lastPosition;

    KineticModelPrivate();
};

KineticModelPrivate::KineticModelPrivate()
    : released(false)
    , duration(1403)
    , position(0)
    , velocity(0)
    , deacceleration(0)
    , lastPosition(0)
{

}

KineticModel::KineticModel(QObject *parent)
    : QObject(parent)
    , d_ptr(new KineticModelPrivate)
{
    connect(&d_ptr->ticker, SIGNAL(timeout()), SLOT(update()));
    d_ptr->ticker.setInterval(KineticModelDefaultUpdateInterval);
}

KineticModel::~KineticModel()
{

}

int KineticModel::duration() const
{
    return d_ptr->duration;
}

void KineticModel::setDuration(int ms)
{
    d_ptr->duration = ms;
}

qreal KineticModel::position() const
{
    return d_ptr->position;
}

void KineticModel::setPosition(qreal pos)
{
    d_ptr->released = false;

    qreal oldPos = d_ptr->position;
    d_ptr->position = pos;
    if (!qFuzzyCompare(pos, oldPos))
        emit positionChanged(pos);

    update();
    if (!d_ptr->ticker.isActive())
        d_ptr->ticker.start();
}

int KineticModel::updateInterval() const
{
    return d_ptr->ticker.interval();
}

void KineticModel::setUpdateInterval(int ms)
{
    d_ptr->ticker.setInterval(ms);
}

void KineticModel::resetSpeed()
{
    d_ptr->velocity = 0;
    d_ptr->lastPosition = d_ptr->position;
}

void KineticModel::release()
{
    Q_D(KineticModel);

    d->released = true;

    d->deacceleration = d->velocity * 1000 / (1 + d_ptr->duration);
    if (d->deacceleration < 0)
        d->deacceleration = -d->deacceleration;

    if (!d->ticker.isActive())
        d->ticker.start();

    update();
}

void KineticModel::update()
{
    Q_D(KineticModel);

    int elapsed = d_ptr->timestamp.elapsed();

    // too fast gives less accuracy
    if (elapsed < 5)
        return;

    qreal delta = static_cast<qreal>(elapsed) / 1000.0;

    if (d->released) {
        d->position += (d->velocity * delta);
        qreal vstep = d->deacceleration * delta;
        if (d->velocity < vstep && d->velocity >= -vstep) {
            d->velocity = 0;
            d->ticker.stop();
        } else {
            if (d->velocity > 0)
                d->velocity -= vstep;
            else
                d->velocity += vstep;
        }
        emit positionChanged(d->position);
    } else {
        qreal lastSpeed = d->velocity;
        qreal currentSpeed = (d->position - d->lastPosition) / delta;
        d->velocity = .2 * lastSpeed + .8 * currentSpeed;
        d->lastPosition = d->position;
    }

    d->timestamp.start();
}
<|endoftext|>


<commit_before>// force debugging asserts
#ifdef OPTIMIZE
	#warning Debugging asserts have been re-enabled for testing.
	#undef OPTIMIZE
#endif

#include "test_tensor.h"
#include "critics/test_criticsequencer.h"
#include "critics/test_mse.h"
#include "critics/test_nll.h"
#include "math/test_math_base.h"
#include "math/test_math_blas.h"
#include "nn/test_batchnorm.h"
#include "nn/test_concat.h"
#include "nn/test_identity.h"
#include "nn/test_linear.h"
#include "nn/test_logistic.h"
#include "nn/test_logsoftmax.h"
#include "nn/test_lstm.h"
#include "nn/test_recurrent.h"
#include "nn/test_relu.h"
#include "nn/test_sequencer.h"
#include "nn/test_sequential.h"
#include "nn/test_tanh.h"
using namespace nnlib;

#include <iostream>
#include <string>
#include <initializer_list>
#include <tuple>
#include <functional>
using namespace std;

#define TEST(Class) { string("Testing ") + #Class, Test##Class }

int main()
{
	int ret = 0;

	initializer_list<pair<string, function<void()>>> tests = {
		// critics
		TEST(CriticSequencer),
		TEST(MSE),
		TEST(NLL),

		// math
		TEST(MathBase),
		TEST(MathBLAS),

		// nn
		TEST(BatchNorm),
		TEST(Concat),
		TEST(Identity),
		TEST(Linear),
		TEST(Logistic),
		TEST(LogSoftMax),
		TEST(LSTM),
		TEST(Recurrent),
		TEST(ReLU),
		TEST(Sequencer),
		TEST(Sequential),
		TEST(TanH)
	};

	try
	{
		for(auto test : tests)
		{
			cout << test.first << "..." << flush;
			test.second();
			cout << " Passed!" << endl;
		}

		cout << "All tests passed!" << endl;
	}
	catch(const Error &e)
	{
		cerr << endl << "An unexpected error occurred:\n\t" << e.what() << endl;
		ret = 1;
	}
	return ret;
}
<commit_msg>Added all of nnlib to test, which should make a more accurate code coverage.<commit_after>// force debugging asserts
#ifdef OPTIMIZE
	#warning Debugging asserts have been re-enabled for testing.
	#undef OPTIMIZE
#endif

#include "nnlib.h"
#include "test_tensor.h"
#include "critics/test_criticsequencer.h"
#include "critics/test_mse.h"
#include "critics/test_nll.h"
#include "math/test_math_base.h"
#include "math/test_math_blas.h"
#include "nn/test_batchnorm.h"
#include "nn/test_concat.h"
#include "nn/test_identity.h"
#include "nn/test_linear.h"
#include "nn/test_logistic.h"
#include "nn/test_logsoftmax.h"
#include "nn/test_lstm.h"
#include "nn/test_recurrent.h"
#include "nn/test_relu.h"
#include "nn/test_sequencer.h"
#include "nn/test_sequential.h"
#include "nn/test_tanh.h"
using namespace nnlib;

#include <iostream>
#include <string>
#include <initializer_list>
#include <tuple>
#include <functional>
using namespace std;

#define TEST(Class) { string("Testing ") + #Class, Test##Class }

int main()
{
	int ret = 0;

	initializer_list<pair<string, function<void()>>> tests = {
		// critics
		TEST(CriticSequencer),
		TEST(MSE),
		TEST(NLL),

		// math
		TEST(MathBase),
		TEST(MathBLAS),

		// nn
		TEST(BatchNorm),
		TEST(Concat),
		TEST(Identity),
		TEST(Linear),
		TEST(Logistic),
		TEST(LogSoftMax),
		TEST(LSTM),
		TEST(Recurrent),
		TEST(ReLU),
		TEST(Sequencer),
		TEST(Sequential),
		TEST(TanH)
	};

	try
	{
		for(auto test : tests)
		{
			cout << test.first << "..." << flush;
			test.second();
			cout << " Passed!" << endl;
		}

		cout << "All tests passed!" << endl;
	}
	catch(const Error &e)
	{
		cerr << endl << "An unexpected error occurred:\n\t" << e.what() << endl;
		ret = 1;
	}
	return ret;
}
<|endoftext|>


<commit_before>#include <catch_with_main.hpp>
#include <vmu.hpp>
#include <memory>

template<class Address, class Address2>
void check_region(const vmu::basic_region<Address> region, Address2 addr)
{
    REQUIRE(static_cast<bool>(region));
    CHECK(region.protection().readable());
    CHECK(region.protection().writable());
    CHECK(region.size() != 0);
    CHECK(vmu::detail::uintptr_cast(region.begin()) <= vmu::detail::uintptr_cast(addr));
    CHECK(vmu::detail::uintptr_cast(region.end()) >= vmu::detail::uintptr_cast(addr));
}

TEST_CASE("query")
{
    int  i     = 5;
    auto ret   = vmu::query(&i);
    check_region(ret, &i);
}

TEST_CASE("query error code")
{
    std::error_code ec;
    int  i     = 5;
    auto ptr_i = reinterpret_cast<std::uintptr_t>(&i);
    auto ret   = vmu::query(ptr_i, ec);
    check_region(ret, ptr_i);
}

TEST_CASE("query_range")
{
    int  i    = 5;
    auto ptr  = reinterpret_cast<std::uintptr_t>(&i);
    const auto rets = vmu::query_range(ptr, ptr + 16);

    REQUIRE_FALSE(rets.empty());
    for(const auto& ret : rets)
        check_region(ret, ptr);
}

TEST_CASE("query_range error code")
{
    int  i    = 5;
    auto ptr  = reinterpret_cast<std::uintptr_t>(&i);
    std::error_code ec;
    const auto rets = vmu::query_range(&i, &i + 16, ec);

    REQUIRE_FALSE(ec);
    REQUIRE_FALSE(rets.empty());
    for(const auto& ret : rets)
        check_region(ret, ptr);
}

TEST_CASE("protection_guard")
{
    auto random_data = std::make_unique<unsigned char[]>(4096 * 3);
    auto testing_arr = random_data.get();
    // needed on linux
    memset((void*)testing_arr, 12, 4096 * 3);
    auto result = vmu::query(testing_arr);
    REQUIRE(result);

    // TODO using FlushInstructionCache might be a thing to do
    {
        const auto new_prot = vmu::access::read;
        CHECK_FALSE(new_prot == result.protection().to_flags());

        vmu::protection_guard pg(testing_arr, new_prot);

        auto new_flags = vmu::query(testing_arr);
        CHECK(new_flags);
        CHECK(new_flags.protection().to_flags() == new_prot);
    }

    auto result2 = vmu::query(testing_arr);
    REQUIRE(result2.shared() == result.shared());
    REQUIRE(result2.begin() == result.begin());
    REQUIRE(result2.protection().to_flags() == result.protection().to_flags());
    REQUIRE(result2.guarded() == result.guarded());
}
<commit_msg>added a sanity check test for address casting<commit_after>#include <catch_with_main.hpp>
#include <vmu.hpp>
#include <memory>

template<class Address, class Address2>
void check_region(const vmu::basic_region<Address> region, Address2 addr)
{
    REQUIRE(static_cast<bool>(region));
    CHECK(region.protection().readable());
    CHECK(region.protection().writable());
    CHECK(region.size() != 0);
    CHECK(vmu::detail::uintptr_cast(region.begin()) <= vmu::detail::uintptr_cast(addr));
    CHECK(vmu::detail::uintptr_cast(region.end()) >= vmu::detail::uintptr_cast(addr));
}

TEST_CASE("address_cast sanity check")
{
    std::uintptr_t uintptr = 0xdeadbeef;
    void* ptr = vmu::detail::address_cast<void*>(uintptr);
    REQUIRE(memcmp(&uintptr, &ptr, sizeof(void*)) == 0);
}

TEST_CASE("query")
{
    int  i     = 5;
    auto ret   = vmu::query(&i);
    check_region(ret, &i);
}

TEST_CASE("query error code")
{
    std::error_code ec;
    int  i     = 5;
    auto ptr_i = reinterpret_cast<std::uintptr_t>(&i);
    auto ret   = vmu::query(ptr_i, ec);
    check_region(ret, ptr_i);
}

TEST_CASE("query_range")
{
    int  i    = 5;
    auto ptr  = reinterpret_cast<std::uintptr_t>(&i);
    const auto rets = vmu::query_range(ptr, ptr + 16);

    REQUIRE_FALSE(rets.empty());
    for(const auto& ret : rets)
        check_region(ret, ptr);
}

TEST_CASE("query_range error code")
{
    int  i    = 5;
    auto ptr  = reinterpret_cast<std::uintptr_t>(&i);
    std::error_code ec;
    const auto rets = vmu::query_range(&i, &i + 16, ec);

    REQUIRE_FALSE(ec);
    REQUIRE_FALSE(rets.empty());
    for(const auto& ret : rets)
        check_region(ret, ptr);
}

TEST_CASE("protection_guard")
{
    auto random_data = std::make_unique<unsigned char[]>(4096 * 3);
    auto testing_arr = random_data.get();
    // needed on linux
    memset((void*)testing_arr, 12, 4096 * 3);
    auto result = vmu::query(testing_arr);
    REQUIRE(result);

    // TODO using FlushInstructionCache might be a thing to do
    {
        const auto new_prot = vmu::access::read;
        CHECK_FALSE(new_prot == result.protection().to_flags());

        vmu::protection_guard pg(testing_arr, new_prot);

        auto new_flags = vmu::query(testing_arr);
        CHECK(new_flags);
        CHECK(new_flags.protection().to_flags() == new_prot);
    }

    auto result2 = vmu::query(testing_arr);
    REQUIRE(result2.shared() == result.shared());
    REQUIRE(result2.begin() == result.begin());
    REQUIRE(result2.protection().to_flags() == result.protection().to_flags());
    REQUIRE(result2.guarded() == result.guarded());
}
<|endoftext|>


<commit_before>/**
 * \file
 * \brief ThreadControlBlock class implementation
 *
 * \author Copyright (C) 2014-2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * \date 2015-02-17
 */

#include "distortos/scheduler/ThreadControlBlock.hpp"

#include "distortos/scheduler/getScheduler.hpp"
#include "distortos/scheduler/Scheduler.hpp"

#include "distortos/synchronization/MutexControlBlock.hpp"

#include "distortos/architecture/InterruptMaskingLock.hpp"

namespace distortos
{

namespace scheduler
{

/*---------------------------------------------------------------------------------------------------------------------+
| public functions
+---------------------------------------------------------------------------------------------------------------------*/

ThreadControlBlock::ThreadControlBlock(architecture::Stack&& stack, const uint8_t priority,
		const SchedulingPolicy schedulingPolicy, ThreadBase& owner) :
		stack_{std::move(stack)},
		owner_(owner),
		ownedProtocolMutexControlBlocksList_
		{
				MutexControlBlockListAllocator{getScheduler().getMutexControlBlockListAllocatorPool()}
		},
		priorityInheritanceMutexControlBlock_{},
		list_{},
		iterator_{},
		unblockReason_{},
		pendingSignalSet_{SignalSet::empty},
		waitingSignalSet_{},
		reent_(_REENT_INIT(reent_)),
		priority_{priority},
		boostedPriority_{},
		roundRobinQuantum_{},
		schedulingPolicy_{schedulingPolicy},
		state_{State::New}
{

}

ThreadControlBlock::~ThreadControlBlock()
{
	_reclaim_reent(&reent_);
}

int ThreadControlBlock::acceptPendingSignal(const uint8_t signalNumber)
{
	architecture::InterruptMaskingLock interruptMaskingLock;
	return pendingSignalSet_.remove(signalNumber);
}

SignalSet ThreadControlBlock::getPendingSignalSet() const
{
	architecture::InterruptMaskingLock interruptMaskingLock;
	return pendingSignalSet_;
}

int ThreadControlBlock::generateSignal(const uint8_t signalNumber)
{
	architecture::InterruptMaskingLock interruptMaskingLock;

	const auto ret = pendingSignalSet_.add(signalNumber);
	if (ret != 0)
		return ret;

	if (waitingSignalSet_ == nullptr)
		return 0;

	const auto testResult = waitingSignalSet_->test(signalNumber);
	if (testResult.first != 0)
		return testResult.first;
	if (testResult.second == false)	// signalNumber is not "waited for"?
		return 0;

	getScheduler().unblock(iterator_);
	waitingSignalSet_ = {};
	return 0;
}

void ThreadControlBlock::setPriority(const uint8_t priority, const bool alwaysBehind)
{
	architecture::InterruptMaskingLock interruptMaskingLock;

	if (priority_ == priority)
		return;

	// special case of new priority UINT8_MAX does need to be handled, as it will never be "lowering" of priority anyway
	const auto loweringBefore = alwaysBehind == false && priority_ > priority;

	const auto previousEffectivePriority = getEffectivePriority();
	priority_ = priority;

	if (previousEffectivePriority == getEffectivePriority() || list_ == nullptr)
		return;

	reposition(loweringBefore);

	if (priorityInheritanceMutexControlBlock_ != nullptr)
		priorityInheritanceMutexControlBlock_->getOwner()->updateBoostedPriority();
}

void ThreadControlBlock::setSchedulingPolicy(const SchedulingPolicy schedulingPolicy)
{
	architecture::InterruptMaskingLock interruptMaskingLock;

	schedulingPolicy_ = schedulingPolicy;
	roundRobinQuantum_.reset();
}

void ThreadControlBlock::unblockHook(const UnblockReason unblockReason)
{
	roundRobinQuantum_.reset();
	const auto unblockFunctor = unblockFunctor_;
	unblockReason_ = unblockReason;
	if (unblockFunctor != nullptr)
		(*unblockFunctor)(*this);
}

void ThreadControlBlock::updateBoostedPriority(const uint8_t boostedPriority)
{
	decltype(boostedPriority_) newBoostedPriority {boostedPriority};

	for (const auto &mutexControlBlock : ownedProtocolMutexControlBlocksList_)
	{
		const auto mutexBoostedPriority = mutexControlBlock.get().getBoostedPriority();
		newBoostedPriority = std::max(newBoostedPriority, mutexBoostedPriority);
	}

	if (boostedPriority_ == newBoostedPriority)
		return;

	const auto oldEffectivePriority = getEffectivePriority();
	boostedPriority_ = newBoostedPriority;
	const auto newEffectivePriority = getEffectivePriority();

	if (oldEffectivePriority == newEffectivePriority || list_ == nullptr)
		return;

	const auto loweringBefore = newEffectivePriority < oldEffectivePriority;

	reposition(loweringBefore);

	// this code is placed here, even though it could be moved to ThreadControlBlock::reposition(), simplifying
	// ThreadControlBlock::setPriority(). This way optimizer can remove recursive calls to this function, reducing
	// memory usage of threads.
	if (priorityInheritanceMutexControlBlock_ != nullptr)
		priorityInheritanceMutexControlBlock_->getOwner()->updateBoostedPriority();
}

/*---------------------------------------------------------------------------------------------------------------------+
| private functions
+---------------------------------------------------------------------------------------------------------------------*/

void ThreadControlBlock::reposition(const bool loweringBefore)
{
	const auto oldPriority = priority_;

	if (loweringBefore == true)
		priority_ = getEffectivePriority() + 1;

	list_->sortedSplice(*list_, iterator_);

	if (loweringBefore == true)
		priority_ = oldPriority;

	getScheduler().maybeRequestContextSwitch();
}

}	// namespace scheduler

}	// namespace distortos
<commit_msg>ThreadControlBlock::generateSignal(): clearing waitingSignalSet_ is no longer necessary - this should be done by unblock functor<commit_after>/**
 * \file
 * \brief ThreadControlBlock class implementation
 *
 * \author Copyright (C) 2014-2015 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
 *
 * \par License
 * This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
 * distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * \date 2015-02-21
 */

#include "distortos/scheduler/ThreadControlBlock.hpp"

#include "distortos/scheduler/getScheduler.hpp"
#include "distortos/scheduler/Scheduler.hpp"

#include "distortos/synchronization/MutexControlBlock.hpp"

#include "distortos/architecture/InterruptMaskingLock.hpp"

namespace distortos
{

namespace scheduler
{

/*---------------------------------------------------------------------------------------------------------------------+
| public functions
+---------------------------------------------------------------------------------------------------------------------*/

ThreadControlBlock::ThreadControlBlock(architecture::Stack&& stack, const uint8_t priority,
		const SchedulingPolicy schedulingPolicy, ThreadBase& owner) :
		stack_{std::move(stack)},
		owner_(owner),
		ownedProtocolMutexControlBlocksList_
		{
				MutexControlBlockListAllocator{getScheduler().getMutexControlBlockListAllocatorPool()}
		},
		priorityInheritanceMutexControlBlock_{},
		list_{},
		iterator_{},
		unblockReason_{},
		pendingSignalSet_{SignalSet::empty},
		waitingSignalSet_{},
		reent_(_REENT_INIT(reent_)),
		priority_{priority},
		boostedPriority_{},
		roundRobinQuantum_{},
		schedulingPolicy_{schedulingPolicy},
		state_{State::New}
{

}

ThreadControlBlock::~ThreadControlBlock()
{
	_reclaim_reent(&reent_);
}

int ThreadControlBlock::acceptPendingSignal(const uint8_t signalNumber)
{
	architecture::InterruptMaskingLock interruptMaskingLock;
	return pendingSignalSet_.remove(signalNumber);
}

SignalSet ThreadControlBlock::getPendingSignalSet() const
{
	architecture::InterruptMaskingLock interruptMaskingLock;
	return pendingSignalSet_;
}

int ThreadControlBlock::generateSignal(const uint8_t signalNumber)
{
	architecture::InterruptMaskingLock interruptMaskingLock;

	const auto ret = pendingSignalSet_.add(signalNumber);
	if (ret != 0)
		return ret;

	if (waitingSignalSet_ == nullptr)
		return 0;

	const auto testResult = waitingSignalSet_->test(signalNumber);
	if (testResult.first != 0)
		return testResult.first;
	if (testResult.second == false)	// signalNumber is not "waited for"?
		return 0;

	getScheduler().unblock(iterator_);
	return 0;
}

void ThreadControlBlock::setPriority(const uint8_t priority, const bool alwaysBehind)
{
	architecture::InterruptMaskingLock interruptMaskingLock;

	if (priority_ == priority)
		return;

	// special case of new priority UINT8_MAX does need to be handled, as it will never be "lowering" of priority anyway
	const auto loweringBefore = alwaysBehind == false && priority_ > priority;

	const auto previousEffectivePriority = getEffectivePriority();
	priority_ = priority;

	if (previousEffectivePriority == getEffectivePriority() || list_ == nullptr)
		return;

	reposition(loweringBefore);

	if (priorityInheritanceMutexControlBlock_ != nullptr)
		priorityInheritanceMutexControlBlock_->getOwner()->updateBoostedPriority();
}

void ThreadControlBlock::setSchedulingPolicy(const SchedulingPolicy schedulingPolicy)
{
	architecture::InterruptMaskingLock interruptMaskingLock;

	schedulingPolicy_ = schedulingPolicy;
	roundRobinQuantum_.reset();
}

void ThreadControlBlock::unblockHook(const UnblockReason unblockReason)
{
	roundRobinQuantum_.reset();
	const auto unblockFunctor = unblockFunctor_;
	unblockReason_ = unblockReason;
	if (unblockFunctor != nullptr)
		(*unblockFunctor)(*this);
}

void ThreadControlBlock::updateBoostedPriority(const uint8_t boostedPriority)
{
	decltype(boostedPriority_) newBoostedPriority {boostedPriority};

	for (const auto &mutexControlBlock : ownedProtocolMutexControlBlocksList_)
	{
		const auto mutexBoostedPriority = mutexControlBlock.get().getBoostedPriority();
		newBoostedPriority = std::max(newBoostedPriority, mutexBoostedPriority);
	}

	if (boostedPriority_ == newBoostedPriority)
		return;

	const auto oldEffectivePriority = getEffectivePriority();
	boostedPriority_ = newBoostedPriority;
	const auto newEffectivePriority = getEffectivePriority();

	if (oldEffectivePriority == newEffectivePriority || list_ == nullptr)
		return;

	const auto loweringBefore = newEffectivePriority < oldEffectivePriority;

	reposition(loweringBefore);

	// this code is placed here, even though it could be moved to ThreadControlBlock::reposition(), simplifying
	// ThreadControlBlock::setPriority(). This way optimizer can remove recursive calls to this function, reducing
	// memory usage of threads.
	if (priorityInheritanceMutexControlBlock_ != nullptr)
		priorityInheritanceMutexControlBlock_->getOwner()->updateBoostedPriority();
}

/*---------------------------------------------------------------------------------------------------------------------+
| private functions
+---------------------------------------------------------------------------------------------------------------------*/

void ThreadControlBlock::reposition(const bool loweringBefore)
{
	const auto oldPriority = priority_;

	if (loweringBefore == true)
		priority_ = getEffectivePriority() + 1;

	list_->sortedSplice(*list_, iterator_);

	if (loweringBefore == true)
		priority_ = oldPriority;

	getScheduler().maybeRequestContextSwitch();
}

}	// namespace scheduler

}	// namespace distortos
<|endoftext|>


<commit_before>/*
 * Copyright 2015 - 2021 gary@drinkingtea.net
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#pragma once

#include <json/json.h>

#include <ox/model/optype.hpp>
#include <ox/model/types.hpp>
#include <ox/std/byteswap.hpp>
#include <ox/std/hashmap.hpp>
#include <ox/std/memops.hpp>
#include <ox/std/string.hpp>
#include <ox/std/vector.hpp>

namespace ox {

class OrganicClawReader {

	private:
		Json::Value m_json;
		Json::ArrayIndex m_fieldIt = 0;
		int m_unionIdx = -1;

	public:
		OrganicClawReader() = default;

		OrganicClawReader(const uint8_t *buff, std::size_t buffSize);

		OrganicClawReader(const char *json, std::size_t buffSize);

		OrganicClawReader(const Json::Value &json, int unionIdx = -1);

		Error field(const char *key, int8_t *val);
		Error field(const char *key, int16_t *val);
		Error field(const char *key, int32_t *val);
		Error field(const char *key, int64_t *val);

		Error field(const char *key, uint8_t *val);
		Error field(const char *key, uint16_t *val);
		Error field(const char *key, uint32_t *val);
		Error field(const char *key, uint64_t *val);

		Error field(const char *key, bool *val);

		// array handler
		template<typename T>
		Error field(const char *key, T *val, std::size_t len);

		template<typename T>
		Error field(const char *key, Vector<T> *val);

		template<typename T>
		Error field(const char*, HashMap<String, T> *val);

		template<typename T>
		Error field(const char *key, T *val);

		template<typename U>
		Error field(const char *key, UnionView<U> val);

		template<std::size_t L>
		Error field(const char *key, ox::BString<L> *val);

		Error field(const char *key, SerStr val);

		/**
		 * Reads an array length from the current location in the buffer.
		 * @param pass indicates that the parsing should iterate past the array length
		 */
		Result<std::size_t> arrayLength(const char *key, bool pass = true);

		/**
		 * Reads an string length from the current location in the buffer.
		 */
		[[nodiscard]] std::size_t stringLength(const char *name);

		template<typename T = void>
		constexpr void setTypeInfo(const char* = T::TypeName, int = T::Fields) {
		}

		/**
		 * Returns a OrganicClawReader to parse a child object.
		 */
		[[nodiscard]] OrganicClawReader child(const char *key, int unionIdx = -1);

		// compatibility stub
		constexpr void nextField() noexcept {}

		bool fieldPresent(const char *key);

		static constexpr auto opType() {
			return OpType::Read;
		}

	private:

		Json::Value &value(const char *key);

		bool targetValid() noexcept;

};

template<typename T>
Error OrganicClawReader::field(const char *key, T *val) {
	auto err = OxError(0);
	if (targetValid()) {
		const auto &jv = value(key);
		if (jv.empty() || jv.isObject()) {
			auto reader = child(key);
			return model(&reader, val);
		} else {
			err = OxError(1, "Type mismatch");
		}
	}
	++m_fieldIt;
	return err;
}

template<typename U>
Error OrganicClawReader::field(const char *key, UnionView<U> val) {
	auto err = OxError(0);
	if (targetValid()) {
		const auto &jv = value(key);
		if (jv.empty() || jv.isObject()) {
			auto reader = child(key, val.idx());
			err = model(&reader, val.get());
		} else {
			err = OxError(1, "Type mismatch");
		}
	}
	++m_fieldIt;
	return err;
}

template<std::size_t L>
Error OrganicClawReader::field(const char *name, ox::BString<L> *val) {
	return field(name, SerStr(val->data(), val->cap()));
}

// array handler
template<typename T>
Error OrganicClawReader::field(const char *key, T *val, std::size_t valLen) {
	const auto &srcVal = value(key);
	auto srcSize = srcVal.size();
	if (srcSize > valLen) {
		return OxError(1);
	}
	OrganicClawReader r(srcVal);
	for (decltype(srcSize) i = 0; i < srcSize; ++i) {
		oxReturnError(r.field("", &val[i]));
	}
	return OxError(0);
}

template<typename T>
Error OrganicClawReader::field(const char *key, ox::Vector<T> *val) {
	return field(key, val->data(), val->size());
}

template<typename T>
Error OrganicClawReader::field(const char *key, HashMap<String, T> *val) {
	const auto &srcVal = value(key);
	auto keys = srcVal.getMemberNames();
	auto srcSize = srcVal.size();
	OrganicClawReader r(srcVal);
	for (decltype(srcSize) i = 0; i < srcSize; ++i) {
		auto k = keys[i].c_str();
		oxReturnError(r.field(k, &val->operator[](k)));
	}
	return OxError(0);
}

template<typename T>
Error readOC(const char *json, std::size_t jsonSize, T *val) noexcept {
	// OrganicClawReader constructor can throw, but readOC should return its errors.
	try {
		Json::Value doc;
		Json::CharReaderBuilder parserBuilder;
		auto parser = std::unique_ptr<Json::CharReader>(parserBuilder.newCharReader());
		if (!parser->parse(json, json + jsonSize, &doc, nullptr)) {
			return OxError(1, "Could not parse JSON");
		}
		OrganicClawReader reader(json, jsonSize);
		return model(&reader, val);
	} catch (Error err) {
		return err;
	} catch (...) {
		return OxError(1, "Unkown Error");
	}
}

template<typename T>
Result<std::unique_ptr<T>> readOC(const char *json) {
	auto val = std::make_unique<T>();
	oxReturnError(readOC(json, ox_strlen(json), val.get()));
	return val;
}

}
<commit_msg>[ox/oc] Replace std::unique_ptr usage with ox::UniquePtr<commit_after>/*
 * Copyright 2015 - 2021 gary@drinkingtea.net
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */

#pragma once

#include <json/json.h>

#include <ox/model/optype.hpp>
#include <ox/model/types.hpp>
#include <ox/std/byteswap.hpp>
#include <ox/std/hashmap.hpp>
#include <ox/std/memops.hpp>
#include <ox/std/memory.hpp>
#include <ox/std/string.hpp>
#include <ox/std/vector.hpp>

namespace ox {

class OrganicClawReader {

	private:
		Json::Value m_json;
		Json::ArrayIndex m_fieldIt = 0;
		int m_unionIdx = -1;

	public:
		OrganicClawReader() = default;

		OrganicClawReader(const uint8_t *buff, std::size_t buffSize);

		OrganicClawReader(const char *json, std::size_t buffSize);

		OrganicClawReader(const Json::Value &json, int unionIdx = -1);

		Error field(const char *key, int8_t *val);
		Error field(const char *key, int16_t *val);
		Error field(const char *key, int32_t *val);
		Error field(const char *key, int64_t *val);

		Error field(const char *key, uint8_t *val);
		Error field(const char *key, uint16_t *val);
		Error field(const char *key, uint32_t *val);
		Error field(const char *key, uint64_t *val);

		Error field(const char *key, bool *val);

		// array handler
		template<typename T>
		Error field(const char *key, T *val, std::size_t len);

		template<typename T>
		Error field(const char *key, Vector<T> *val);

		template<typename T>
		Error field(const char*, HashMap<String, T> *val);

		template<typename T>
		Error field(const char *key, T *val);

		template<typename U>
		Error field(const char *key, UnionView<U> val);

		template<std::size_t L>
		Error field(const char *key, ox::BString<L> *val);

		Error field(const char *key, SerStr val);

		/**
		 * Reads an array length from the current location in the buffer.
		 * @param pass indicates that the parsing should iterate past the array length
		 */
		Result<std::size_t> arrayLength(const char *key, bool pass = true);

		/**
		 * Reads an string length from the current location in the buffer.
		 */
		[[nodiscard]]
		std::size_t stringLength(const char *name);

		template<typename T = void>
		constexpr void setTypeInfo(const char* = T::TypeName, int = T::Fields) {
		}

		/**
		 * Returns a OrganicClawReader to parse a child object.
		 */
		[[nodiscard]]
		OrganicClawReader child(const char *key, int unionIdx = -1);

		// compatibility stub
		constexpr void nextField() noexcept {}

		bool fieldPresent(const char *key);

		static constexpr auto opType() {
			return OpType::Read;
		}

	private:

		Json::Value &value(const char *key);

		bool targetValid() noexcept;

};

template<typename T>
Error OrganicClawReader::field(const char *key, T *val) {
	auto err = OxError(0);
	if (targetValid()) {
		const auto &jv = value(key);
		if (jv.empty() || jv.isObject()) {
			auto reader = child(key);
			return model(&reader, val);
		} else {
			err = OxError(1, "Type mismatch");
		}
	}
	++m_fieldIt;
	return err;
}

template<typename U>
Error OrganicClawReader::field(const char *key, UnionView<U> val) {
	auto err = OxError(0);
	if (targetValid()) {
		const auto &jv = value(key);
		if (jv.empty() || jv.isObject()) {
			auto reader = child(key, val.idx());
			err = model(&reader, val.get());
		} else {
			err = OxError(1, "Type mismatch");
		}
	}
	++m_fieldIt;
	return err;
}

template<std::size_t L>
Error OrganicClawReader::field(const char *name, ox::BString<L> *val) {
	return field(name, SerStr(val->data(), val->cap()));
}

// array handler
template<typename T>
Error OrganicClawReader::field(const char *key, T *val, std::size_t valLen) {
	const auto &srcVal = value(key);
	auto srcSize = srcVal.size();
	if (srcSize > valLen) {
		return OxError(1);
	}
	OrganicClawReader r(srcVal);
	for (decltype(srcSize) i = 0; i < srcSize; ++i) {
		oxReturnError(r.field("", &val[i]));
	}
	return OxError(0);
}

template<typename T>
Error OrganicClawReader::field(const char *key, ox::Vector<T> *val) {
	return field(key, val->data(), val->size());
}

template<typename T>
Error OrganicClawReader::field(const char *key, HashMap<String, T> *val) {
	const auto &srcVal = value(key);
	auto keys = srcVal.getMemberNames();
	auto srcSize = srcVal.size();
	OrganicClawReader r(srcVal);
	for (decltype(srcSize) i = 0; i < srcSize; ++i) {
		auto k = keys[i].c_str();
		oxReturnError(r.field(k, &val->operator[](k)));
	}
	return OxError(0);
}

template<typename T>
Error readOC(const char *json, std::size_t jsonSize, T *val) noexcept {
	// OrganicClawReader constructor can throw, but readOC should return its errors.
	try {
		Json::Value doc;
		Json::CharReaderBuilder parserBuilder;
		auto parser = std::unique_ptr<Json::CharReader>(parserBuilder.newCharReader());
		if (!parser->parse(json, json + jsonSize, &doc, nullptr)) {
			return OxError(1, "Could not parse JSON");
		}
		OrganicClawReader reader(json, jsonSize);
		return model(&reader, val);
	} catch (Error err) {
		return err;
	} catch (...) {
		return OxError(1, "Unkown Error");
	}
}

template<typename T>
Result<ox::UniquePtr<T>> readOC(const char *json) {
	auto val = ox::make_unique<T>();
	oxReturnError(readOC(json, ox_strlen(json), val.get()));
	return val;
}

}
<|endoftext|>


<commit_before>//
//  test.c
//  ios_test
//
//  Created by Resident Evil on 16.06.14.
//  Copyright (c) 2014 Resident Evil. All rights reserved.
//

#include <stdio.h>

#include <fayecpp.h>

class FayeClientDelegate : public FayeCpp::Delegate
{
public:
	virtual void onFayeTransportConnected(FayeCpp::Client * client)
	{

	}

	virtual void onFayeTransportDisconnected(FayeCpp::Client * client)
	{

	}

	virtual void onFayeClientConnected(FayeCpp::Client * client)
	{

	}

	virtual void onFayeClientDisconnected(FayeCpp::Client * client)
	{

	}

	virtual void onFayeClientSubscribedToChannel(FayeCpp::Client * client,
												 const FayeCpp::REString & channel)
	{

	}

	virtual void onFayeClientUnsubscribedFromChannel(FayeCpp::Client * client,
													 const FayeCpp::REString & channel)
	{

	}

	virtual void onFayeClientReceivedMessageFromChannel(FayeCpp::Client * client,
														const FayeCpp::VariantMap & message,
														const FayeCpp::REString & channel)
	{

	}

	virtual void onFayeClientWillSendMessage(FayeCpp::Client * client,
											 FayeCpp::VariantMap & message)
	{

	}

	virtual void onFayeClientWillReceiveMessage(FayeCpp::Client * client,
												FayeCpp::VariantMap & message)
	{

	}

	virtual void onFayeErrorString(FayeCpp::Client * client,
								   const FayeCpp::REString & errorString)
	{

	}

	FayeClientDelegate() { }
	virtual ~FayeClientDelegate() { }
};

static FayeCpp::Client * _client = NULL;
static FayeClientDelegate * _delegate = NULL;

int testInit()
{
	_client = new FayeCpp::Client();
	_delegate = new FayeClientDelegate();
	if (!_client || !_delegate) return 1;

	_client->setUrl("ws://host:80/path");
	_client->setDelegate(_delegate);
	_client->connect();
	_client->subscribeToChannel("/channel");

	return 0;
}

<commit_msg>Travis integration<commit_after>
#include <stdio.h>

#include <fayecpp.h>

class FayeClientDelegate : public FayeCpp::Delegate
{
public:
	virtual void onFayeTransportConnected(FayeCpp::Client * client)
	{

	}

	virtual void onFayeTransportDisconnected(FayeCpp::Client * client)
	{

	}

	virtual void onFayeClientConnected(FayeCpp::Client * client)
	{

	}

	virtual void onFayeClientDisconnected(FayeCpp::Client * client)
	{

	}

	virtual void onFayeClientSubscribedToChannel(FayeCpp::Client * client,
												 const FayeCpp::REString & channel)
	{

	}

	virtual void onFayeClientUnsubscribedFromChannel(FayeCpp::Client * client,
													 const FayeCpp::REString & channel)
	{

	}

	virtual void onFayeClientReceivedMessageFromChannel(FayeCpp::Client * client,
														const FayeCpp::VariantMap & message,
														const FayeCpp::REString & channel)
	{

	}

	virtual void onFayeClientWillSendMessage(FayeCpp::Client * client,
											 FayeCpp::VariantMap & message)
	{

	}

	virtual void onFayeClientWillReceiveMessage(FayeCpp::Client * client,
												FayeCpp::VariantMap & message)
	{

	}

	virtual void onFayeErrorString(FayeCpp::Client * client,
								   const FayeCpp::REString & errorString)
	{

	}

	FayeClientDelegate() { }
	virtual ~FayeClientDelegate() { }
};

static FayeCpp::Client * _client = NULL;
static FayeClientDelegate * _delegate = NULL;

int testInit()
{
	_client = new FayeCpp::Client();
	_delegate = new FayeClientDelegate();
	if (!_client || !_delegate) return 1;

	_client->setUrl("ws://host:80/path");
	_client->setDelegate(_delegate);
	_client->connect();
	_client->subscribeToChannel("/channel");

	return 0;
}

<|endoftext|>


<commit_before>/*
// Copyright (c) 2015 Pierre Guillot.
// For information on usage and redistribution, and for a DISCLAIMER OF ALL
// WARRANTIES, see the file, "LICENSE.txt," in this distribution.
*/

#include "test.hpp"
#include <iostream>
#include <string>
#include <string.h>
#include <stdio.h>

#ifdef _WIN32
#include <direct.h>
#else
#include <unistd.h>
#endif

extern "C"
{
#include "../thread/src/thd.h"
}

using namespace xpd;

static std::string get_test_dir()
{
    std::string path;
    std::cout << "start looking for test.pd\n";
    char cwd[1024];
#ifdef _WIN32
    if(_getcwd(cwd, sizeof(cwd)) == NULL)
#else
    if(getcwd(cwd, sizeof(cwd)) == NULL)
#endif
    {
        return "";
    }
    path = cwd;
    std::cout << path << "\n";
    size_t pos = path.find("zpd");
    if(pos != std::string::npos)
    {
        path.erase(path.begin()+pos+4, path.end());
        path.append("test");
        std::cout << path << "\n";
    }
    std::cout << "end looking for test.pd\n";
    return path;
}

typedef void (*test_method)(void *);

struct dual_instance
{
    instance_test inst1;
    instance_test inst2;
};

void test_post(dual_instance* ins)
{
    thd_thread t1, t2;
    std::cout << "perform tests for console posts...";
    {
        thd_thread_detach(&t1, (thd_thread_method)(&instance_test::test_post), &ins->inst1);
        thd_thread_detach(&t2, (thd_thread_method)(&instance_test::test_post), &ins->inst2);
        thd_thread_join(&t1);
        thd_thread_join(&t2);
    }
    std::cout << "ok\n";
}

void test_binding(dual_instance* ins)
{
    thd_thread t1, t2;
    std::cout << "perform tests for binding and atoms...";
    {
        thd_thread_detach(&t1, (thd_thread_method)(&instance_test::test_message), &ins->inst1);
        thd_thread_detach(&t2, (thd_thread_method)(&instance_test::test_message), &ins->inst2);
        thd_thread_join(&t1);
        thd_thread_join(&t2);
    }
    std::cout << "ok\n";
}

void test_midi(dual_instance* ins)
{
    thd_thread t1, t2;
    std::cout << "perform tests for midi events...";
    {
        thd_thread_detach(&t1, (thd_thread_method)(&instance_test::test_midi), &ins->inst1);
        thd_thread_detach(&t2, (thd_thread_method)(&instance_test::test_midi), &ins->inst2);
        thd_thread_join(&t1);
        thd_thread_join(&t2);
    }
    std::cout << "ok\n";
}

void test_dsp(dual_instance* ins)
{
    thd_thread t1, t2;
    std::cout << "perform tests for dsp...";
    {
        thd_thread_detach(&t1, (thd_thread_method)(&instance_test::test_dsp), &ins->inst1);
        thd_thread_detach(&t2, (thd_thread_method)(&instance_test::test_dsp), &ins->inst2);
        thd_thread_join(&t1);
        thd_thread_join(&t2);
    }
    std::cout << "ok\n";
}

void test_patch(dual_instance* ins)
{
    thd_thread t1, t2;
    std::cout << "perform tests for patch, object & gui...";
    {
        thd_thread_detach(&t1, (thd_thread_method)(&instance_test::test_patch), &ins->inst1);
        thd_thread_detach(&t2, (thd_thread_method)(&instance_test::test_patch), &ins->inst2);
        thd_thread_join(&t1);
        thd_thread_join(&t2);
    }
    std::cout << "ok\n";
}

int main(int argc, char** argv)
{
    dual_instance is;

    thd_thread ta, tb, tc, td, te;
    std::cout << "tests xpd version " << environment::version_major()
    << "." << environment::version_minor()
    << "." << environment::version_bug() << "\n";

    environment::searpath_clear();
    environment::searchpath_add(get_test_dir());

    std::cout << "perform tie, symbol and atom...";
    type_test::test_tie();
    type_test::test_symbol();
    type_test::test_atom();
    std::cout << "ok\n";

    thd_thread_detach(&ta, (thd_thread_method)(test_post), &is);
    thd_thread_join(&ta);

    thd_thread_detach(&tb, (thd_thread_method)(test_binding), &is);
    thd_thread_join(&tb);

    thd_thread_detach(&tc, (thd_thread_method)(test_midi), &is);
    thd_thread_join(&tc);

    thd_thread_detach(&td, (thd_thread_method)(test_dsp), &is);
    thd_thread_join(&td);

    thd_thread_detach(&te, (thd_thread_method)(test_patch), &is);
    thd_thread_join(&te);

    return 0;
}<commit_msg>missing // or \<commit_after>/*
// Copyright (c) 2015 Pierre Guillot.
// For information on usage and redistribution, and for a DISCLAIMER OF ALL
// WARRANTIES, see the file, "LICENSE.txt," in this distribution.
*/

#include "test.hpp"
#include <iostream>
#include <string>
#include <string.h>
#include <stdio.h>

#ifdef _WIN32
#include <direct.h>
#else
#include <unistd.h>
#endif

extern "C"
{
#include "../thread/src/thd.h"
}

using namespace xpd;

static std::string get_test_dir()
{
    std::string path;
    std::cout << "start looking for test.pd\n";
    char cwd[1024];
#ifdef _WIN32
    if(_getcwd(cwd, sizeof(cwd)) == NULL)
#else
    if(getcwd(cwd, sizeof(cwd)) == NULL)
#endif
    {
        return "";
    }
    path = cwd;
    std::cout << path << "\n";
    size_t pos = path.find("zpd");
    if(pos != std::string::npos)
    {
        path.erase(path.begin()+pos+4, path.end());
#ifdef _WIN32
        path.append("test\\");
#else
        path.append("test/");
#endif
        std::cout << path << "\n";
    }
    std::cout << "end looking for test.pd\n";
    return path;
}

typedef void (*test_method)(void *);

struct dual_instance
{
    instance_test inst1;
    instance_test inst2;
};

void test_post(dual_instance* ins)
{
    thd_thread t1, t2;
    std::cout << "perform tests for console posts...";
    {
        thd_thread_detach(&t1, (thd_thread_method)(&instance_test::test_post), &ins->inst1);
        thd_thread_detach(&t2, (thd_thread_method)(&instance_test::test_post), &ins->inst2);
        thd_thread_join(&t1);
        thd_thread_join(&t2);
    }
    std::cout << "ok\n";
}

void test_binding(dual_instance* ins)
{
    thd_thread t1, t2;
    std::cout << "perform tests for binding and atoms...";
    {
        thd_thread_detach(&t1, (thd_thread_method)(&instance_test::test_message), &ins->inst1);
        thd_thread_detach(&t2, (thd_thread_method)(&instance_test::test_message), &ins->inst2);
        thd_thread_join(&t1);
        thd_thread_join(&t2);
    }
    std::cout << "ok\n";
}

void test_midi(dual_instance* ins)
{
    thd_thread t1, t2;
    std::cout << "perform tests for midi events...";
    {
        thd_thread_detach(&t1, (thd_thread_method)(&instance_test::test_midi), &ins->inst1);
        thd_thread_detach(&t2, (thd_thread_method)(&instance_test::test_midi), &ins->inst2);
        thd_thread_join(&t1);
        thd_thread_join(&t2);
    }
    std::cout << "ok\n";
}

void test_dsp(dual_instance* ins)
{
    thd_thread t1, t2;
    std::cout << "perform tests for dsp...";
    {
        thd_thread_detach(&t1, (thd_thread_method)(&instance_test::test_dsp), &ins->inst1);
        thd_thread_detach(&t2, (thd_thread_method)(&instance_test::test_dsp), &ins->inst2);
        thd_thread_join(&t1);
        thd_thread_join(&t2);
    }
    std::cout << "ok\n";
}

void test_patch(dual_instance* ins)
{
    thd_thread t1, t2;
    std::cout << "perform tests for patch, object & gui...";
    {
        thd_thread_detach(&t1, (thd_thread_method)(&instance_test::test_patch), &ins->inst1);
        thd_thread_detach(&t2, (thd_thread_method)(&instance_test::test_patch), &ins->inst2);
        thd_thread_join(&t1);
        thd_thread_join(&t2);
    }
    std::cout << "ok\n";
}

int main(int argc, char** argv)
{
    dual_instance is;

    thd_thread ta, tb, tc, td, te;
    std::cout << "tests xpd version " << environment::version_major()
    << "." << environment::version_minor()
    << "." << environment::version_bug() << "\n";

    environment::searpath_clear();
    environment::searchpath_add(get_test_dir());

    std::cout << "perform tie, symbol and atom...";
    type_test::test_tie();
    type_test::test_symbol();
    type_test::test_atom();
    std::cout << "ok\n";

    thd_thread_detach(&ta, (thd_thread_method)(test_post), &is);
    thd_thread_join(&ta);

    thd_thread_detach(&tb, (thd_thread_method)(test_binding), &is);
    thd_thread_join(&tb);

    thd_thread_detach(&tc, (thd_thread_method)(test_midi), &is);
    thd_thread_join(&tc);

    thd_thread_detach(&td, (thd_thread_method)(test_dsp), &is);
    thd_thread_join(&td);

    thd_thread_detach(&te, (thd_thread_method)(test_patch), &is);
    thd_thread_join(&te);

    return 0;
}<|endoftext|>


<commit_before>/*

Copyright (c) 2008, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef TEST_HPP
#define TEST_HPP

#include <boost/config.hpp>
#include <exception>
#include <sstream>

#include "libtorrent/config.hpp"

#ifdef TORRENT_BUILDING_TEST_SHARED
#define EXPORT BOOST_SYMBOL_EXPORT
#else
#define EXPORT BOOST_SYMBOL_IMPORT
#endif

// the unit tests need access to these.
// they are built into the unit test library as well.
// not exported from libtorrent itself
extern "C"
{
	int TORRENT_EXPORT ed25519_create_seed(unsigned char *seed);
	void TORRENT_EXPORT ed25519_create_keypair(unsigned char *public_key, unsigned char *private_key, const unsigned char *seed);
	void TORRENT_EXPORT ed25519_sign(unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key, const unsigned char *private_key);
	int TORRENT_EXPORT ed25519_verify(const unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *private_key);
	void TORRENT_EXPORT ed25519_add_scalar(unsigned char *public_key, unsigned char *private_key, const unsigned char *scalar);
	void TORRENT_EXPORT ed25519_key_exchange(unsigned char *shared_secret, const unsigned char *public_key, const unsigned char *private_key);
}

void EXPORT report_failure(char const* err, char const* file, int line);

#if defined(_MSC_VER)
#define COUNTER_GUARD(x)
#else
#define COUNTER_GUARD(type) \
    struct BOOST_PP_CAT(type, _counter_guard) \
    { \
        ~BOOST_PP_CAT(type, _counter_guard()) \
        { \
            TEST_CHECK(counted_type<type>::count == 0); \
        } \
    } BOOST_PP_CAT(type, _guard)
#endif

#define TEST_REPORT_AUX(x, line, file) \
	report_failure(x, line, file)

#ifdef BOOST_NO_EXCEPTIONS
#define TEST_CHECK(x) \
	if (!(x)) \
		TEST_REPORT_AUX("TEST_CHECK failed: \"" #x "\"", __FILE__, __LINE__);
#define TEST_EQUAL(x, y) \
	if (x != y) { \
		std::stringstream s__; \
		s__ << "TEST_EQUAL_ERROR:\n" #x ": " << x << "\nexpected: " << y << std::endl; \
		TEST_REPORT_AUX(s__.str().c_str(), __FILE__, __LINE__); \
	}
#else
#define TEST_CHECK(x) \
	try \
	{ \
		if (!(x)) \
			TEST_REPORT_AUX("TEST_CHECK failed: \"" #x "\"", __FILE__, __LINE__); \
	} \
	catch (std::exception& e) \
	{ \
		TEST_ERROR("Exception thrown: " #x " :" + std::string(e.what())); \
	} \
	catch (...) \
	{ \
		TEST_ERROR("Exception thrown: " #x); \
	}

#define TEST_EQUAL(x, y) \
	try { \
		if (x != y) { \
			std::stringstream s__; \
			s__ << "TEST_EQUAL_ERROR: " #x ": " << x << " expected: " << y << std::endl; \
			TEST_REPORT_AUX(s__.str().c_str(), __FILE__, __LINE__); \
		} \
	} \
	catch (std::exception& e) \
	{ \
		TEST_ERROR("Exception thrown: " #x " :" + std::string(e.what())); \
	} \
	catch (...) \
	{ \
		TEST_ERROR("Exception thrown: " #x); \
	}
#endif

#define TEST_ERROR(x) \
	TEST_REPORT_AUX((std::string("ERROR: \"") + x + "\"").c_str(), __FILE__, __LINE__)

#define TEST_NOTHROW(x) \
	try \
	{ \
		x; \
	} \
	catch (...) \
	{ \
		TEST_ERROR("Exception thrown: " #x); \
	}

#endif // TEST_HPP

<commit_msg>use export macro from test<commit_after>/*

Copyright (c) 2008, Arvid Norberg
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:

    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in
      the documentation and/or other materials provided with the distribution.
    * Neither the name of the author nor the names of its
      contributors may be used to endorse or promote products derived
      from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

*/

#ifndef TEST_HPP
#define TEST_HPP

#include <boost/config.hpp>
#include <exception>
#include <sstream>

#include "libtorrent/config.hpp"

#ifdef TORRENT_BUILDING_TEST_SHARED
#define EXPORT BOOST_SYMBOL_EXPORT
#else
#define EXPORT BOOST_SYMBOL_IMPORT
#endif

// the unit tests need access to these.
// they are built into the unit test library as well.
// not exported from libtorrent itself
extern "C"
{
	int EXPORT ed25519_create_seed(unsigned char *seed);
	void EXPORT ed25519_create_keypair(unsigned char *public_key, unsigned char *private_key, const unsigned char *seed);
	void EXPORT ed25519_sign(unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *public_key, const unsigned char *private_key);
	int EXPORT ed25519_verify(const unsigned char *signature, const unsigned char *message, size_t message_len, const unsigned char *private_key);
	void EXPORT ed25519_add_scalar(unsigned char *public_key, unsigned char *private_key, const unsigned char *scalar);
	void EXPORT ed25519_key_exchange(unsigned char *shared_secret, const unsigned char *public_key, const unsigned char *private_key);
}

void EXPORT report_failure(char const* err, char const* file, int line);

#if defined(_MSC_VER)
#define COUNTER_GUARD(x)
#else
#define COUNTER_GUARD(type) \
    struct BOOST_PP_CAT(type, _counter_guard) \
    { \
        ~BOOST_PP_CAT(type, _counter_guard()) \
        { \
            TEST_CHECK(counted_type<type>::count == 0); \
        } \
    } BOOST_PP_CAT(type, _guard)
#endif

#define TEST_REPORT_AUX(x, line, file) \
	report_failure(x, line, file)

#ifdef BOOST_NO_EXCEPTIONS
#define TEST_CHECK(x) \
	if (!(x)) \
		TEST_REPORT_AUX("TEST_CHECK failed: \"" #x "\"", __FILE__, __LINE__);
#define TEST_EQUAL(x, y) \
	if (x != y) { \
		std::stringstream s__; \
		s__ << "TEST_EQUAL_ERROR:\n" #x ": " << x << "\nexpected: " << y << std::endl; \
		TEST_REPORT_AUX(s__.str().c_str(), __FILE__, __LINE__); \
	}
#else
#define TEST_CHECK(x) \
	try \
	{ \
		if (!(x)) \
			TEST_REPORT_AUX("TEST_CHECK failed: \"" #x "\"", __FILE__, __LINE__); \
	} \
	catch (std::exception& e) \
	{ \
		TEST_ERROR("Exception thrown: " #x " :" + std::string(e.what())); \
	} \
	catch (...) \
	{ \
		TEST_ERROR("Exception thrown: " #x); \
	}

#define TEST_EQUAL(x, y) \
	try { \
		if (x != y) { \
			std::stringstream s__; \
			s__ << "TEST_EQUAL_ERROR: " #x ": " << x << " expected: " << y << std::endl; \
			TEST_REPORT_AUX(s__.str().c_str(), __FILE__, __LINE__); \
		} \
	} \
	catch (std::exception& e) \
	{ \
		TEST_ERROR("Exception thrown: " #x " :" + std::string(e.what())); \
	} \
	catch (...) \
	{ \
		TEST_ERROR("Exception thrown: " #x); \
	}
#endif

#define TEST_ERROR(x) \
	TEST_REPORT_AUX((std::string("ERROR: \"") + x + "\"").c_str(), __FILE__, __LINE__)

#define TEST_NOTHROW(x) \
	try \
	{ \
		x; \
	} \
	catch (...) \
	{ \
		TEST_ERROR("Exception thrown: " #x); \
	}

#endif // TEST_HPP

<|endoftext|>


<commit_before>/* Copyright © 2001-2014, Canal TP and/or its affiliates. All rights reserved.

This file is part of Navitia,
    the software to build cool stuff with public transport.

Hope you'll enjoy and contribute to this project,
    powered by Canal TP (www.canaltp.fr).
Help us simplify mobility and open public transport:
    a non ending quest to the responsive locomotion way of traveling!

LICENCE: This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.

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

Stay tuned using
twitter @navitia
IRC #navitia on freenode
https://groups.google.com/d/forum/navitia
www.navitia.io
*/

#include "departure_boards.h"
#include "request_handle.h"
#include "get_stop_times.h"
#include "type/pb_converter.h"
#include "boost/lexical_cast.hpp"
#include "boost/date_time/posix_time/posix_time.hpp"
#include "utils/paginate.h"

namespace pt = boost::posix_time;

namespace navitia { namespace timetables {

static pbnavitia::Response
render_v1(const std::map<uint32_t, pbnavitia::ResponseStatus>& response_status,
          const std::map<stop_point_line, vector_dt_st>& map_route_stop_point,
          DateTime datetime,
          DateTime max_datetime,
          boost::optional<const std::string> calendar_id,
          uint32_t depth,
          const bool show_codes,
          const type::Data& data) {
    pbnavitia::Response response;
    auto current_time = pt::second_clock::universal_time();
    pt::time_period action_period(to_posix_time(datetime, data),
                                  to_posix_time(max_datetime, data));

//    bool display_date = ! calendar_id;
    for(auto id_vec : map_route_stop_point) {
        auto schedule = response.add_stop_schedules();
        //Each schedule has a stop_point and a route
        fill_pb_object(data.pt_data->stop_points[id_vec.first.first], data,
                       schedule->mutable_stop_point(), depth,
                       current_time, action_period, show_codes);

        auto m_route = schedule->mutable_route();
        fill_pb_object(data.pt_data->routes[id_vec.first.second], data,
                               m_route, depth, current_time, action_period, show_codes);
        if (data.pt_data->routes[id_vec.first.second]->line != nullptr){
            auto m_line = m_route->mutable_line();
            fill_pb_object(data.pt_data->routes[id_vec.first.second]->line, data,
                                   m_line, 0, current_time, action_period, show_codes);
        }
        auto pt_display_information = schedule->mutable_pt_display_informations();

        fill_pb_object(data.pt_data->routes[id_vec.first.second], data,
                               pt_display_information, 0, current_time, action_period);

        //Now we fill the date_times
        for(auto dt_st : id_vec.second) {
            auto date_time = schedule->add_date_times();
            fill_pb_object(dt_st.second, data, date_time, 0,
                           current_time, action_period, dt_st.first, calendar_id);
        }
        const auto& it = response_status.find(id_vec.first.second);
        if(it != response_status.end()){
            schedule->set_response_status(it->second);
        }
    }
    return response;
}

pbnavitia::Response
departure_board(const std::string& request,
                boost::optional<const std::string> calendar_id,
                const std::vector<std::string>& forbidden_uris,
                const pt::ptime date,
                uint32_t duration, uint32_t depth,
                uint32_t max_date_times,
                int interface_version,
                int count, int start_page, const type::Data &data, bool disruption_active,
                bool show_codes) {

    RequestHandle handler(request, forbidden_uris, date,  duration, data, calendar_id);

    if(handler.pb_response.has_error())
        return handler.pb_response;

    if(handler.journey_pattern_points.size() == 0)
        return handler.pb_response;

    if (calendar_id) {
        //check whether that calendar exists, to raise an early error
        if (data.pt_data->calendars_map.find(*calendar_id) == data.pt_data->calendars_map.end()) {
            fill_pb_error(pbnavitia::Error::bad_filter, "stop_schedules : calendar does not exist", handler.pb_response.mutable_error());
            return handler.pb_response;
        }
    }
    //  <idx_route, status>
    std::map<uint32_t, pbnavitia::ResponseStatus> response_status;

    std::map<stop_point_line, vector_dt_st> map_route_stop_point;
    //Mapping route/stop_point
    std::vector<stop_point_line> sps_routes;
    for(auto jpp_idx : handler.journey_pattern_points) {
        auto jpp = data.pt_data->journey_pattern_points[jpp_idx];
        auto route_idx  = jpp->journey_pattern->route->idx;
        auto sp_idx = jpp->stop_point->idx;
        stop_point_line key = stop_point_line(sp_idx, route_idx);
        auto find_predicate = [&](stop_point_line spl) {
            return spl.first == key.first && spl.second == key.second;
        };
        auto it = std::find_if(sps_routes.begin(), sps_routes.end(), find_predicate);
        if(it == sps_routes.end()){
            sps_routes.push_back(key);
        }
    }
    size_t total_result = sps_routes.size();
    sps_routes = paginate(sps_routes, count, start_page);
    //Trie des vecteurs de date_times stop_times
    auto sort_predicate = [](datetime_stop_time dt1, datetime_stop_time dt2) {
                    return dt1.first < dt2.first;
                };
    // On regroupe entre eux les stop_times appartenant
    // au meme couple (stop_point, route)
    // On veut en effet afficher les départs regroupés par route
    // (une route étant une vague direction commerciale
    for(auto sp_route : sps_routes) {
        std::vector<datetime_stop_time> stop_times;
        const type::StopPoint* stop_point = data.pt_data->stop_points[sp_route.first];
        const type::Route* route = data.pt_data->routes[sp_route.second];
        auto jpps = stop_point->journey_pattern_point_list;
        for(auto jpp : jpps) {
            if(jpp->journey_pattern->route != route) {
                continue;
            }
            if(stop_point->idx == jpp->journey_pattern->journey_pattern_point_list.back()->stop_point->idx) { // for terminus
                auto it = response_status.find(route->idx);
                if (it == response_status.end()) {
                    response_status[route->idx] = pbnavitia::ResponseStatus::terminus;
                } else {
                    response_status[route->idx] = pbnavitia::ResponseStatus::partial_terminus;
                }
            } else {
                auto it = response_status.find(route->idx);
                if (it != response_status.end() && it->second == pbnavitia::ResponseStatus::terminus) {
                    response_status[route->idx] = pbnavitia::ResponseStatus::partial_terminus;
                } else {
                    response_status[route->idx] = pbnavitia::ResponseStatus::none;
                }
            }
            std::vector<datetime_stop_time> tmp;
            if (! calendar_id) {
                tmp = get_stop_times({jpp->idx}, handler.date_time,
                                          handler.max_datetime,
                                          max_date_times, data, disruption_active);
            } else {
                tmp = get_stop_times({jpp->idx}, DateTimeUtils::hour(handler.date_time),
                                     DateTimeUtils::hour(handler.max_datetime), data, *calendar_id);
            }
            if (! tmp.empty()) {
                stop_times.insert(stop_times.end(), tmp.begin(), tmp.end());
            }
        }
        if ( ! calendar_id) {
            std::sort(stop_times.begin(), stop_times.end(), sort_predicate);
        } else {
            // for calendar we want to sort the result a quite a strange way
            // we want the first stop time to start from handler.date_time
            std::sort(stop_times.begin(), stop_times.end(),
                      [&handler](datetime_stop_time dst1, datetime_stop_time dst2) {
                auto is_before_start1 = (DateTimeUtils::hour(dst1.first) < DateTimeUtils::hour(handler.date_time));
                auto is_before_start2 = (DateTimeUtils::hour(dst2.first) < DateTimeUtils::hour(handler.date_time));

                if (is_before_start1 != is_before_start2) {
                    //if one is before and one is after, we want the one after first
                    return ! is_before_start1;
                }
                return DateTimeUtils::hour(dst1.first) < DateTimeUtils::hour(dst2.first);
                });
            if (stop_times.size() > max_date_times) {
                stop_times.resize(max_date_times);
            }
        }
        auto to_insert = std::pair<stop_point_line, vector_dt_st>(sp_route, stop_times);
        map_route_stop_point.insert(to_insert);
    }

    //we check if we have at least one departure for each route (and no other error)
    for(auto sp_route : sps_routes) {
        const type::Route* route = data.pt_data->routes[sp_route.second];
        if (map_route_stop_point[sp_route].empty() &&
                response_status[route->idx] == pbnavitia::ResponseStatus::none) {
            response_status[route->idx] = pbnavitia::ResponseStatus::no_departure_this_day;
        }
    }

    if(interface_version == 1) {
        handler.pb_response = render_v1(response_status, map_route_stop_point,
                                        handler.date_time,
                                        handler.max_datetime,
                                        calendar_id, depth, show_codes, data);
    } else {
        fill_pb_error(pbnavitia::Error::bad_filter, "invalid interface version", handler.pb_response.mutable_error());
        return handler.pb_response;
    }

    auto pagination = handler.pb_response.mutable_pagination();
    pagination->set_totalresult(total_result);
    pagination->set_startpage(start_page);
    pagination->set_itemsperpage(count);
    pagination->set_itemsonpage(std::max(handler.pb_response.departure_boards_size(),
                                         handler.pb_response.stop_schedules_size()));

    return handler.pb_response;
}
}
}
<commit_msg>kraken: corrections and refactoring<commit_after>/* Copyright © 2001-2014, Canal TP and/or its affiliates. All rights reserved.

This file is part of Navitia,
    the software to build cool stuff with public transport.

Hope you'll enjoy and contribute to this project,
    powered by Canal TP (www.canaltp.fr).
Help us simplify mobility and open public transport:
    a non ending quest to the responsive locomotion way of traveling!

LICENCE: This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.

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

Stay tuned using
twitter @navitia
IRC #navitia on freenode
https://groups.google.com/d/forum/navitia
www.navitia.io
*/

#include "departure_boards.h"
#include "request_handle.h"
#include "get_stop_times.h"
#include "type/pb_converter.h"
#include "boost/lexical_cast.hpp"
#include "boost/date_time/posix_time/posix_time.hpp"
#include "utils/paginate.h"

namespace pt = boost::posix_time;

namespace navitia { namespace timetables {

static pbnavitia::Response
render_v1(const std::map<uint32_t, pbnavitia::ResponseStatus>& response_status,
          const std::map<stop_point_line, vector_dt_st>& map_route_stop_point,
          DateTime datetime,
          DateTime max_datetime,
          boost::optional<const std::string> calendar_id,
          uint32_t depth,
          const bool show_codes,
          const type::Data& data) {
    pbnavitia::Response response;
    auto current_time = pt::second_clock::universal_time();
    pt::time_period action_period(to_posix_time(datetime, data),
                                  to_posix_time(max_datetime, data));

//    bool display_date = ! calendar_id;
    for(auto id_vec : map_route_stop_point) {
        auto schedule = response.add_stop_schedules();
        //Each schedule has a stop_point and a route
        fill_pb_object(data.pt_data->stop_points[id_vec.first.first], data,
                       schedule->mutable_stop_point(), depth,
                       current_time, action_period, show_codes);

        auto m_route = schedule->mutable_route();
        fill_pb_object(data.pt_data->routes[id_vec.first.second], data,
                               m_route, depth, current_time, action_period, show_codes);
        if (data.pt_data->routes[id_vec.first.second]->line != nullptr){
            auto m_line = m_route->mutable_line();
            fill_pb_object(data.pt_data->routes[id_vec.first.second]->line, data,
                                   m_line, 0, current_time, action_period, show_codes);
        }
        auto pt_display_information = schedule->mutable_pt_display_informations();

        fill_pb_object(data.pt_data->routes[id_vec.first.second], data,
                               pt_display_information, 0, current_time, action_period);

        //Now we fill the date_times
        for(auto dt_st : id_vec.second) {
            auto date_time = schedule->add_date_times();
            fill_pb_object(dt_st.second, data, date_time, 0,
                           current_time, action_period, dt_st.first, calendar_id);
        }
        const auto& it = response_status.find(id_vec.first.second);
        if(it != response_status.end()){
            schedule->set_response_status(it->second);
        }
    }
    return response;
}

pbnavitia::Response
departure_board(const std::string& request,
                boost::optional<const std::string> calendar_id,
                const std::vector<std::string>& forbidden_uris,
                const pt::ptime date,
                uint32_t duration, uint32_t depth,
                uint32_t max_date_times,
                int interface_version,
                int count, int start_page, const type::Data &data, bool disruption_active,
                bool show_codes) {

    RequestHandle handler(request, forbidden_uris, date,  duration, data, calendar_id);

    if(handler.pb_response.has_error())
        return handler.pb_response;

    if(handler.journey_pattern_points.size() == 0)
        return handler.pb_response;

    if (calendar_id) {
        //check whether that calendar exists, to raise an early error
        if (data.pt_data->calendars_map.find(*calendar_id) == data.pt_data->calendars_map.end()) {
            fill_pb_error(pbnavitia::Error::bad_filter, "stop_schedules : calendar does not exist", handler.pb_response.mutable_error());
            return handler.pb_response;
        }
    }
    //  <idx_route, status>
    std::map<uint32_t, pbnavitia::ResponseStatus> response_status;

    std::map<stop_point_line, vector_dt_st> map_route_stop_point;
    //Mapping route/stop_point
    std::vector<stop_point_line> sps_routes;
    for(auto jpp_idx : handler.journey_pattern_points) {
        auto jpp = data.pt_data->journey_pattern_points[jpp_idx];
        auto route_idx  = jpp->journey_pattern->route->idx;
        auto sp_idx = jpp->stop_point->idx;
        stop_point_line key = stop_point_line(sp_idx, route_idx);
        auto find_predicate = [&](stop_point_line spl) {
            return spl.first == key.first && spl.second == key.second;
        };
        auto it = std::find_if(sps_routes.begin(), sps_routes.end(), find_predicate);
        if(it == sps_routes.end()){
            sps_routes.push_back(key);
        }
    }
    size_t total_result = sps_routes.size();
    sps_routes = paginate(sps_routes, count, start_page);
    //Trie des vecteurs de date_times stop_times
    auto sort_predicate = [](datetime_stop_time dt1, datetime_stop_time dt2) {
                    return dt1.first < dt2.first;
                };
    // On regroupe entre eux les stop_times appartenant
    // au meme couple (stop_point, route)
    // On veut en effet afficher les départs regroupés par route
    // (une route étant une vague direction commerciale
    for(auto sp_route : sps_routes) {
        std::vector<datetime_stop_time> stop_times;
        const type::StopPoint* stop_point = data.pt_data->stop_points[sp_route.first];
        const type::Route* route = data.pt_data->routes[sp_route.second];
        auto jpps = stop_point->journey_pattern_point_list;
        for(auto jpp : jpps) {
            if(jpp->journey_pattern->route != route) {
                continue;
            }
            std::vector<datetime_stop_time> tmp;
            if (! calendar_id) {
                tmp = get_stop_times({jpp->idx}, handler.date_time,
                                          handler.max_datetime,
                                          max_date_times, data, disruption_active);
            } else {
                tmp = get_stop_times({jpp->idx}, DateTimeUtils::hour(handler.date_time),
                                     DateTimeUtils::hour(handler.max_datetime), data, *calendar_id);
            }
            if (! tmp.empty()) {
                stop_times.insert(stop_times.end(), tmp.begin(), tmp.end());
            } else {
                if (stop_point == jpp->journey_pattern->journey_pattern_point_list.back()->stop_point){
                    if(jpp->stop_point->stop_area == route->destination){
                        response_status[route->idx] = pbnavitia::ResponseStatus::terminus;
                    }else{
                        response_status[route->idx] = pbnavitia::ResponseStatus::partial_terminus;
                    }
                }
            }
        }
        if ( ! calendar_id) {
            std::sort(stop_times.begin(), stop_times.end(), sort_predicate);
        } else {
            // for calendar we want to sort the result a quite a strange way
            // we want the first stop time to start from handler.date_time
            std::sort(stop_times.begin(), stop_times.end(),
                      [&handler](datetime_stop_time dst1, datetime_stop_time dst2) {
                auto is_before_start1 = (DateTimeUtils::hour(dst1.first) < DateTimeUtils::hour(handler.date_time));
                auto is_before_start2 = (DateTimeUtils::hour(dst2.first) < DateTimeUtils::hour(handler.date_time));

                if (is_before_start1 != is_before_start2) {
                    //if one is before and one is after, we want the one after first
                    return ! is_before_start1;
                }
                return DateTimeUtils::hour(dst1.first) < DateTimeUtils::hour(dst2.first);
                });
            if (stop_times.size() > max_date_times) {
                stop_times.resize(max_date_times);
            }
        }
        if(stop_times.empty() && (response_status.find(route->idx) == response_status.end())){
            response_status[route->idx] = pbnavitia::ResponseStatus::no_departure_this_day;
        }
        auto to_insert = std::pair<stop_point_line, vector_dt_st>(sp_route, stop_times);
        map_route_stop_point.insert(to_insert);
    }

    if(interface_version == 1) {
        handler.pb_response = render_v1(response_status, map_route_stop_point,
                                        handler.date_time,
                                        handler.max_datetime,
                                        calendar_id, depth, show_codes, data);
    } else {
        fill_pb_error(pbnavitia::Error::bad_filter, "invalid interface version", handler.pb_response.mutable_error());
        return handler.pb_response;
    }

    auto pagination = handler.pb_response.mutable_pagination();
    pagination->set_totalresult(total_result);
    pagination->set_startpage(start_page);
    pagination->set_itemsperpage(count);
    pagination->set_itemsonpage(std::max(handler.pb_response.departure_boards_size(),
                                         handler.pb_response.stop_schedules_size()));

    return handler.pb_response;
}
}
}
<|endoftext|>