<commit_before>/** \file json-voorhees/value.hpp
 *
 *  Copyright (c) 2012 by Travis Gockel. All rights reserved.
 *
 *  This program is free software: you can redistribute it and/or modify it under the terms of the Apache License
 *  as published by the Apache Software Foundation, either version 2 of the License, or (at your option) any later
 *  version.
 *
 *  \author Travis Gockel (travis@gockelhut.com)
**/
#ifndef __JSON_VOORHEES_VALUE_HPP_INCLUDED__
#define __JSON_VOORHEES_VALUE_HPP_INCLUDED__

#include "standard.hpp"

#include <cstdint>
#include <iterator>
#include <ostream>
#include <stdexcept>
#include <string>
#include <utility>

namespace jsonv
{

namespace detail
{

class object_impl;
class array_impl;
class string_impl;

union value_storage
{
    object_impl* object;
    array_impl*  array;
    string_impl* string;
    int64_t      integer;
    double       decimal;
    bool         boolean;
};

}

enum class value_type
{
    null,
    object,
    array,
    string,
    integer,
    decimal,
    boolean
};

class value_type_error :
        public std::logic_error
{
public:
    explicit value_type_error(const std::string& description);

    virtual ~value_type_error() throw();
};

class object_view;
class array_view;

/** \see http://json.org/
**/
class value
{
public:
    /// Default-construct this to null.
    value();
    value(const value& source);
    value(const string_type& val);
    value(const char_type* val);
    value(int64_t val);
    value(double val);
    value(bool val);
    value(const object_view& obj_view);
    value(const array_view& array_view);

    #define JSONV_VALUE_INTEGER_ALTERNATIVE_CTOR_PROTO_GENERATOR(type_)              \
        value(type_ val);
    JSON_VOORHEES_INTEGER_ALTERNATES_LIST(JSONV_VALUE_INTEGER_ALTERNATIVE_CTOR_PROTO_GENERATOR)

    // Don't allow any implicit conversions that we have not specified.
    template <typename T>
    value(T) = delete;

    ~value();

    /** Copy-assigns \c source to this.
     *
     *  If an exception is thrown during the copy, it is propagated out. This instance will be set to a null value - any
     *  value will be disposed.
    **/
    value& operator=(const value& source);

    value(value&& source);

    /** Move-assigns \c source to this.
     *
     *  Unlike a copy, this will never throw.
    **/
    value& operator=(value&& source);

    static value make_object();
    static value make_array();

    /// Resets this value to null.
    void clear();

    inline value_type type() const
    {
        return _type;
    }

    object_view as_object();
    const object_view as_object() const;

    array_view as_array();
    const array_view as_array() const;

    string_type& as_string();
    const string_type& as_string() const;

    int64_t& as_integer();
    int64_t  as_integer() const;

    double& as_decimal();
    double  as_decimal() const;

    bool& as_boolean();
    bool  as_boolean() const;

    /** Compares two JSON values for equality. Two JSON values are equal if and only if all of the following conditions
     *  apply:
     *
     *   1. They have the same valid value for \c type.
     *      - If \c type is invalid (memory corruption), then two JSON values are \e not equal, even if they have been
     *        corrupted in the same way and even if they share \c this (a corrupt object is not equal to itself).
     *   2. The type comparison is also equal:
     *      a. Two null values are always equivalent.
     *      b. string, integer, decimal and boolean follow the classic rules for their type.
     *      c. objects are equal if they have the same keys and values corresponding with the same key are also equal.
     *      d. arrays are equal if they have the same length and the values at each index are also equal.
     *
     *  \note
     *  The rules for equality are based on Python \c dict.
    **/
    bool operator ==(const value& other) const;

    /** Compares two JSON values for inequality. The rules for inequality are the exact opposite of equality.
    **/
    bool operator !=(const value& other) const;

    // FUTURE: I guess do it just like Python?
    // bool operator <(const value& other) const;

    friend ostream_type& operator <<(ostream_type& stream, const value& val);

private:
    detail::value_storage _data;
    value_type            _type;
};

/** A "view" of a JSON \c value as a JSON object (obtain with \c value::as_object). This does not ensure the object you
 *  are viewing stays alive, so you must do that yourself -- an \c object_view just has a pointer, so if that pointer
 *  goes bad, the behavior is undefined. After the awkward lifetime management, this is pretty much an associative
 *  container for mapping a string to a JSON \c value.
 *
 *  @example
 *  @code
 *  jsonv::value val = something();
 *  jsonv::object_view obj = val.as_object();
 *  foo(obj["bar"]);
 *  @endcode
 *
 *  This is a pretty awkward way to do things, actually. The alternative is to roll indexing operator and iterators into
 *  \c value, which leads to having a bunch of operators inside the class. I figured this is the lesser of two evils.
**/
class object_view
{
public:
    typedef size_t                              size_type;
    typedef string_type                         key_type;
    typedef value                               mapped_type;
    typedef std::pair<const string_type, value> value_type;
    typedef std::equal_to<string_type>          key_compare;
    typedef value_type&                         reference;
    typedef const value_type&                   const_reference;
    typedef value_type*                         pointer;
    typedef const value_type*                   const_pointer;

    template <typename T>
    struct basic_iterator :
            public std::iterator<std::bidirectional_iterator_tag, T>
    {
    public:
        basic_iterator();

        basic_iterator(const basic_iterator& source)
        {
            copy_from(source._storage);
        }

        basic_iterator& operator++()
        {
            increment();
            return *this;
        }

        basic_iterator operator++(int) const
        {
            basic_iterator clone(*this);
            clone.increment();
            return clone;
        }

        basic_iterator& operator--()
        {
            decrement();
            return *this;
        }

        basic_iterator operator--(int) const
        {
            basic_iterator clone(*this);
            clone.decrement();
            return clone;
        }

        template <typename U>
        bool operator ==(const basic_iterator<U>& other) const
        {
            return equals(other._storage);
        }

        template <typename U>
        bool operator !=(const basic_iterator<U>& other) const
        {
            return !equals(other._storage);
        }

        T& operator *() const
        {
            return current();
        }

        T* operator ->() const
        {
            return &current();
        }

    private:
        friend class object_view;

        template <typename U>
        explicit basic_iterator(const U&);

        void increment();
        void decrement();
        T&   current() const;
        bool equals(const char* other_storage) const;
        void copy_from(const char* other_storage);

    private:
        char _storage[sizeof(void*)];
    };

    typedef basic_iterator<value_type>       iterator;
    typedef basic_iterator<const value_type> const_iterator;

public:
    size_type size() const;

    iterator begin();
    const_iterator begin() const;

    iterator end();
    const_iterator end() const;

    value& operator[](const string_type& key);
    const value& operator[](const string_type& key) const;

    iterator find(const string_type& key);
    const_iterator find(const string_type& key) const;

    void insert(const value_type& pair);

    void insert_many()
    { }

    template <typename T, typename... TRest>
    void insert_many(T&& pair, TRest&&... rest)
    {
        insert(std::forward<T>(pair));
        insert_many(std::forward<TRest>(rest)...);
    }

    /// \see value::operator==
    bool operator==(const object_view& other) const;

    /// \see value::operator!=
    bool operator!=(const object_view& other) const;

    friend ostream_type& operator <<(ostream_type& stream, const object_view& view);

private:
    friend class value;
    explicit object_view(detail::object_impl* source);

private:
    detail::object_impl* _source;
};

/** This is a view of a \c value as a JSON array (with the same lack of lifetime management as \c object_view). It is a
 *  sequence container which behaves a lot like an \c std::deque (probably because that is the type that backs it).
**/
class array_view
{
public:
    typedef size_t       size_type;
    typedef value        value_type;
    typedef value&       reference;
    typedef const value& const_reference;
    typedef value*       pointer;
    typedef const value* const_pointer;

    template <typename T, typename TArrayView>
    struct basic_iterator :
            public std::iterator<std::random_access_iterator_tag, T>
    {
    public:
        basic_iterator() :
                _owner(0),
                _index(0)
        { }

        basic_iterator(TArrayView* owner, size_type index) :
                _owner(owner),
                _index(index)
        { }

        basic_iterator& operator ++()
        {
            ++_index;
            return *this;
        }

        basic_iterator operator ++(int) const
        {
            basic_iterator clone = *this;
            ++clone;
            return clone;
        }

        basic_iterator& operator --()
        {
            --_index;
            return *this;
        }

        basic_iterator operator --(int) const
        {
            basic_iterator clone = *this;
            --clone;
            return clone;
        }

        template <typename U, typename UArrayView>
        bool operator ==(const basic_iterator<U, UArrayView>& other) const
        {
            return _owner == other._owner && _index == other._index;
        }

        template <typename U, typename UArrayView>
        bool operator !=(const basic_iterator<U, UArrayView>& other) const
        {
            return !operator==(other);
        }

        T& operator *() const
        {
            return _owner->operator[](_index);
        }

        T* operator ->() const
        {
            return &_owner->operator[](_index);
        }

        basic_iterator& operator +=(size_type n)
        {
            _index += n;
            return *this;
        }

        basic_iterator operator +(size_type n) const
        {
            basic_iterator clone = *this;
            clone += n;
            return clone;
        }

        basic_iterator& operator -=(size_type n)
        {
            _index -= n;
            return *this;
        }

        basic_iterator operator -(size_type n) const
        {
            basic_iterator clone = *this;
            clone -= n;
            return clone;
        }

        bool operator <(const basic_iterator& rhs) const
        {
            return _index < rhs._index;
        }

        bool operator <=(const basic_iterator& rhs) const
        {
            return _index <= rhs._index;
        }

        bool operator >(const basic_iterator& rhs) const
        {
            return _index > rhs._index;
        }

        bool operator >=(const basic_iterator& rhs) const
        {
            return _index >= rhs._index;
        }

        T& operator[](size_type n) const
        {
            return _owner->operator[](_index + n);
        }

    private:
        TArrayView* _owner;
        size_type   _index;
    };

    typedef basic_iterator<value, array_view>             iterator;
    typedef basic_iterator<const value, const array_view> const_iterator;

public:
    size_type size() const;
    bool empty() const;

    iterator begin();
    const_iterator begin() const;

    iterator end();
    const_iterator end() const;

    value& operator[](size_type idx);
    const value& operator[](size_type idx) const;

    void push_back(const value& value);
    void pop_back();

    void push_front(const value& value);
    void pop_front();

    void clear();
    void resize(size_type count, const value& val = value());

    /// \see value::operator==
    bool operator==(const array_view& other) const;

    /// \see value::operator!=
    bool operator!=(const array_view& other) const;

    void push_back_many()
    { }

    template <typename T, typename... TRest>
    void push_back_many(T&& val, TRest&&... rest)
    {
        push_back(std::forward<T>(val));
        push_back_many(std::forward<TRest>(rest)...);
    }

    friend ostream_type& operator <<(ostream_type& stream, const array_view& view);

private:
    friend class value;
    explicit array_view(detail::array_impl* source);

private:
    detail::array_impl* _source;
};

/** Creates an array with the given \a values.
 *
 *  \example
 *  \code
 *  jsonv::value val = jsonv::make_array(1, 2, 3, "foo");
 *  // Creates: [1, 2, 3, "foo"]
 *  \endcode
**/
template <typename... T>
value make_array(T&&... values)
{
    value val = value::make_array();
    val.as_array().push_back_many(std::forward<T>(values)...);
    return val;
}

/** Creates an object with the given \a pairs.
 *
 *  \example
 *  \code
 *  jsonv::value val = jsonv::make_object({"foo", 8}, {"bar", "wat"});
 *  // Creates: { "bar": "wat", "foo": 8 }
 *  \endcode
**/
template <typename... T>
value make_object(T&&... pairs)
{
    value val = value::make_object();
    val.as_object().insert_many(std::forward<T>(pairs)...);
    return val;
}

}

#endif/*__JSON_VOORHEES_VALUE_HPP_INCLUDED__*/
<commit_msg>Changes the way make_object works to something more convenient.<commit_after>/** \file json-voorhees/value.hpp
 *
 *  Copyright (c) 2012 by Travis Gockel. All rights reserved.
 *
 *  This program is free software: you can redistribute it and/or modify it under the terms of the Apache License
 *  as published by the Apache Software Foundation, either version 2 of the License, or (at your option) any later
 *  version.
 *
 *  \author Travis Gockel (travis@gockelhut.com)
**/
#ifndef __JSON_VOORHEES_VALUE_HPP_INCLUDED__
#define __JSON_VOORHEES_VALUE_HPP_INCLUDED__

#include "standard.hpp"

#include <cstdint>
#include <iterator>
#include <ostream>
#include <stdexcept>
#include <string>
#include <utility>

namespace jsonv
{

namespace detail
{

class object_impl;
class array_impl;
class string_impl;

union value_storage
{
    object_impl* object;
    array_impl*  array;
    string_impl* string;
    int64_t      integer;
    double       decimal;
    bool         boolean;
};

}

enum class value_type
{
    null,
    object,
    array,
    string,
    integer,
    decimal,
    boolean
};

class value_type_error :
        public std::logic_error
{
public:
    explicit value_type_error(const std::string& description);

    virtual ~value_type_error() throw();
};

class object_view;
class array_view;

/** \see http://json.org/
**/
class value
{
public:
    /// Default-construct this to null.
    value();
    value(const value& source);
    value(const string_type& val);
    value(const char_type* val);
    value(int64_t val);
    value(double val);
    value(bool val);
    value(const object_view& obj_view);
    value(const array_view& array_view);

    #define JSONV_VALUE_INTEGER_ALTERNATIVE_CTOR_PROTO_GENERATOR(type_)              \
        value(type_ val);
    JSON_VOORHEES_INTEGER_ALTERNATES_LIST(JSONV_VALUE_INTEGER_ALTERNATIVE_CTOR_PROTO_GENERATOR)

    // Don't allow any implicit conversions that we have not specified.
    template <typename T>
    value(T) = delete;

    ~value();

    /** Copy-assigns \c source to this.
     *
     *  If an exception is thrown during the copy, it is propagated out. This instance will be set to a null value - any
     *  value will be disposed.
    **/
    value& operator=(const value& source);

    value(value&& source);

    /** Move-assigns \c source to this.
     *
     *  Unlike a copy, this will never throw.
    **/
    value& operator=(value&& source);

    static value make_object();
    static value make_array();

    /// Resets this value to null.
    void clear();

    inline value_type type() const
    {
        return _type;
    }

    object_view as_object();
    const object_view as_object() const;

    array_view as_array();
    const array_view as_array() const;

    string_type& as_string();
    const string_type& as_string() const;

    int64_t& as_integer();
    int64_t  as_integer() const;

    double& as_decimal();
    double  as_decimal() const;

    bool& as_boolean();
    bool  as_boolean() const;

    /** Compares two JSON values for equality. Two JSON values are equal if and only if all of the following conditions
     *  apply:
     *
     *   1. They have the same valid value for \c type.
     *      - If \c type is invalid (memory corruption), then two JSON values are \e not equal, even if they have been
     *        corrupted in the same way and even if they share \c this (a corrupt object is not equal to itself).
     *   2. The type comparison is also equal:
     *      a. Two null values are always equivalent.
     *      b. string, integer, decimal and boolean follow the classic rules for their type.
     *      c. objects are equal if they have the same keys and values corresponding with the same key are also equal.
     *      d. arrays are equal if they have the same length and the values at each index are also equal.
     *
     *  \note
     *  The rules for equality are based on Python \c dict.
    **/
    bool operator ==(const value& other) const;

    /** Compares two JSON values for inequality. The rules for inequality are the exact opposite of equality.
    **/
    bool operator !=(const value& other) const;

    // FUTURE: I guess do it just like Python?
    // bool operator <(const value& other) const;

    friend ostream_type& operator <<(ostream_type& stream, const value& val);

private:
    detail::value_storage _data;
    value_type            _type;
};

/** A "view" of a JSON \c value as a JSON object (obtain with \c value::as_object). This does not ensure the object you
 *  are viewing stays alive, so you must do that yourself -- an \c object_view just has a pointer, so if that pointer
 *  goes bad, the behavior is undefined. After the awkward lifetime management, this is pretty much an associative
 *  container for mapping a string to a JSON \c value.
 *
 *  @example
 *  @code
 *  jsonv::value val = something();
 *  jsonv::object_view obj = val.as_object();
 *  foo(obj["bar"]);
 *  @endcode
 *
 *  This is a pretty awkward way to do things, actually. The alternative is to roll indexing operator and iterators into
 *  \c value, which leads to having a bunch of operators inside the class. I figured this is the lesser of two evils.
**/
class object_view
{
public:
    typedef size_t                              size_type;
    typedef string_type                         key_type;
    typedef value                               mapped_type;
    typedef std::pair<const string_type, value> value_type;
    typedef std::equal_to<string_type>          key_compare;
    typedef value_type&                         reference;
    typedef const value_type&                   const_reference;
    typedef value_type*                         pointer;
    typedef const value_type*                   const_pointer;

    template <typename T>
    struct basic_iterator :
            public std::iterator<std::bidirectional_iterator_tag, T>
    {
    public:
        basic_iterator();

        basic_iterator(const basic_iterator& source)
        {
            copy_from(source._storage);
        }

        basic_iterator& operator++()
        {
            increment();
            return *this;
        }

        basic_iterator operator++(int) const
        {
            basic_iterator clone(*this);
            clone.increment();
            return clone;
        }

        basic_iterator& operator--()
        {
            decrement();
            return *this;
        }

        basic_iterator operator--(int) const
        {
            basic_iterator clone(*this);
            clone.decrement();
            return clone;
        }

        template <typename U>
        bool operator ==(const basic_iterator<U>& other) const
        {
            return equals(other._storage);
        }

        template <typename U>
        bool operator !=(const basic_iterator<U>& other) const
        {
            return !equals(other._storage);
        }

        T& operator *() const
        {
            return current();
        }

        T* operator ->() const
        {
            return &current();
        }

    private:
        friend class object_view;

        template <typename U>
        explicit basic_iterator(const U&);

        void increment();
        void decrement();
        T&   current() const;
        bool equals(const char* other_storage) const;
        void copy_from(const char* other_storage);

    private:
        char _storage[sizeof(void*)];
    };

    typedef basic_iterator<value_type>       iterator;
    typedef basic_iterator<const value_type> const_iterator;

public:
    size_type size() const;

    iterator begin();
    const_iterator begin() const;

    iterator end();
    const_iterator end() const;

    value& operator[](const string_type& key);
    const value& operator[](const string_type& key) const;

    iterator find(const string_type& key);
    const_iterator find(const string_type& key) const;

    void insert(const value_type& pair);

    void insert_many()
    { }

    template <typename T, typename... TRest>
    void insert_many(T&& pair, TRest&&... rest)
    {
        insert(std::forward<T>(pair));
        insert_many(std::forward<TRest>(rest)...);
    }

    /// \see value::operator==
    bool operator==(const object_view& other) const;

    /// \see value::operator!=
    bool operator!=(const object_view& other) const;

    friend ostream_type& operator <<(ostream_type& stream, const object_view& view);

private:
    friend class value;
    explicit object_view(detail::object_impl* source);

private:
    detail::object_impl* _source;
};

/** This is a view of a \c value as a JSON array (with the same lack of lifetime management as \c object_view). It is a
 *  sequence container which behaves a lot like an \c std::deque (probably because that is the type that backs it).
**/
class array_view
{
public:
    typedef size_t       size_type;
    typedef value        value_type;
    typedef value&       reference;
    typedef const value& const_reference;
    typedef value*       pointer;
    typedef const value* const_pointer;

    template <typename T, typename TArrayView>
    struct basic_iterator :
            public std::iterator<std::random_access_iterator_tag, T>
    {
    public:
        basic_iterator() :
                _owner(0),
                _index(0)
        { }

        basic_iterator(TArrayView* owner, size_type index) :
                _owner(owner),
                _index(index)
        { }

        basic_iterator& operator ++()
        {
            ++_index;
            return *this;
        }

        basic_iterator operator ++(int) const
        {
            basic_iterator clone = *this;
            ++clone;
            return clone;
        }

        basic_iterator& operator --()
        {
            --_index;
            return *this;
        }

        basic_iterator operator --(int) const
        {
            basic_iterator clone = *this;
            --clone;
            return clone;
        }

        template <typename U, typename UArrayView>
        bool operator ==(const basic_iterator<U, UArrayView>& other) const
        {
            return _owner == other._owner && _index == other._index;
        }

        template <typename U, typename UArrayView>
        bool operator !=(const basic_iterator<U, UArrayView>& other) const
        {
            return !operator==(other);
        }

        T& operator *() const
        {
            return _owner->operator[](_index);
        }

        T* operator ->() const
        {
            return &_owner->operator[](_index);
        }

        basic_iterator& operator +=(size_type n)
        {
            _index += n;
            return *this;
        }

        basic_iterator operator +(size_type n) const
        {
            basic_iterator clone = *this;
            clone += n;
            return clone;
        }

        basic_iterator& operator -=(size_type n)
        {
            _index -= n;
            return *this;
        }

        basic_iterator operator -(size_type n) const
        {
            basic_iterator clone = *this;
            clone -= n;
            return clone;
        }

        bool operator <(const basic_iterator& rhs) const
        {
            return _index < rhs._index;
        }

        bool operator <=(const basic_iterator& rhs) const
        {
            return _index <= rhs._index;
        }

        bool operator >(const basic_iterator& rhs) const
        {
            return _index > rhs._index;
        }

        bool operator >=(const basic_iterator& rhs) const
        {
            return _index >= rhs._index;
        }

        T& operator[](size_type n) const
        {
            return _owner->operator[](_index + n);
        }

    private:
        TArrayView* _owner;
        size_type   _index;
    };

    typedef basic_iterator<value, array_view>             iterator;
    typedef basic_iterator<const value, const array_view> const_iterator;

public:
    size_type size() const;
    bool empty() const;

    iterator begin();
    const_iterator begin() const;

    iterator end();
    const_iterator end() const;

    value& operator[](size_type idx);
    const value& operator[](size_type idx) const;

    void push_back(const value& value);
    void pop_back();

    void push_front(const value& value);
    void pop_front();

    void clear();
    void resize(size_type count, const value& val = value());

    /// \see value::operator==
    bool operator==(const array_view& other) const;

    /// \see value::operator!=
    bool operator!=(const array_view& other) const;

    void push_back_many()
    { }

    template <typename T, typename... TRest>
    void push_back_many(T&& val, TRest&&... rest)
    {
        push_back(std::forward<T>(val));
        push_back_many(std::forward<TRest>(rest)...);
    }

    friend ostream_type& operator <<(ostream_type& stream, const array_view& view);

private:
    friend class value;
    explicit array_view(detail::array_impl* source);

private:
    detail::array_impl* _source;
};

/** Creates an array with the given \a values.
 *
 *  \example
 *  \code
 *  jsonv::value val = jsonv::make_array(1, 2, 3, "foo");
 *  // Creates: [1, 2, 3, "foo"]
 *  \endcode
**/
template <typename... T>
value make_array(T&&... values)
{
    value val = value::make_array();
    val.as_array().push_back_many(std::forward<T>(values)...);
    return val;
}

namespace detail
{

inline void make_object_impl(jsonv::object_view&)
{ }

template <typename TKey, typename TValue, typename... TRest>
void make_object_impl(jsonv::object_view& obj, TKey&& key, TValue&& value, TRest&&... rest)
{
    obj.insert(object_view::value_type(std::forward<TKey>(key), std::forward<TValue>(value)));
    make_object_impl(obj, std::forward<TRest>(rest)...);
}

}

/** Creates an object with the given \a entries.
 *
 *  \example
 *  \code
 *  jsonv::value val = jsonv::make_object("foo", 8, "bar", "wat");
 *  // Creates: { "bar": "wat", "foo": 8 }
 *  \endcode
**/
template <typename... T>
value make_object(T&&... entries)
{
    static_assert(sizeof...(T) % 2 == 0, "Must have even number of entries: (key0, value0, key1, value1, ...)");

    value val = value::make_object();
    object_view obj = val.as_object();
    detail::make_object_impl(obj, std::forward<T>(entries)...);
    return val;
}

}

#endif/*__JSON_VOORHEES_VALUE_HPP_INCLUDED__*/
<|endoftext|>


<commit_before>/**
 * \file    TestIssues.cpp
 * \brief   Issues submitted
 * \author  Frank Bergmann
 *
 * <!--------------------------------------------------------------------------
 *
 * This file is part of libSEDML.  Please visit http://sed-ml.org for more
 * information about SED-ML. The latest version of libSEDML can be found on
 * github: https://github.com/fbergmann/libSEDML/
 *
 *
 * Copyright (c) 2013-2014, Frank T. Bergmann
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 * 2. 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.
 *
 * 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.
 *
 * ---------------------------------------------------------------------- -->
 *
 */

#include <limits>

#include <iostream>
#include <check.h>
#include <string>
#include <sstream>

#include <sbml/common/libsbml-version.h>
#include <sedml/common/libsedml-version.h>

#include <sedml/SedDocument.h>
#include <sedml/SedDataGenerator.h>
#include <sedml/SedWriter.h>

#include <sbml/math/L3FormulaFormatter.h>
#include <sbml/math/L3Parser.h>

/** @cond doxygenIgnored */

using namespace std;
LIBSBML_CPP_NAMESPACE_USE
LIBSEDML_CPP_NAMESPACE_USE

/** @endcond */

CK_CPPSTART

START_TEST (test_mathml_issue1)
{

  SedDocument doc;
  SedDataGenerator* sdg = doc.createDataGenerator();
  ASTNode* astn = SBML_parseL3Formula("S1/S2");
  sdg->setMath(astn);
  ostringstream stream;
  SedWriter sw;
  sw.writeSedML(&doc, stream);
  string v1 = stream.str();
  stream.str("");
  astn = SBML_parseL3Formula("log(S1/S2)");
  sdg->setMath(astn->getChild(1));
  sw.writeSedML(&doc, stream);
  string v2 = stream.str();
  //cout << v1 << endl << endl << v2 << endl << endl;
  fail_unless( v1 == v2 );
}
END_TEST

Suite *
create_suite_SedMLIssues (void)
{
  Suite *suite = suite_create("SedMLIssues");
  TCase *tcase = tcase_create("SedMLIssues");

  cout << "Testing issues reported using: " << endl;
  cout << "  libSBML  : " << getLibSBMLDottedVersion() << endl;
  cout << "  libSEDML : " << getLibSEDMLDottedVersion() << endl << endl;

  tcase_add_test( tcase, test_mathml_issue1         );

  suite_add_tcase(suite, tcase);

  return suite;
}

CK_CPPEND
<commit_msg>- print information about legacy math<commit_after>/**
 * \file    TestIssues.cpp
 * \brief   Issues submitted
 * \author  Frank Bergmann
 *
 * <!--------------------------------------------------------------------------
 *
 * This file is part of libSEDML.  Please visit http://sed-ml.org for more
 * information about SED-ML. The latest version of libSEDML can be found on
 * github: https://github.com/fbergmann/libSEDML/
 *
 *
 * Copyright (c) 2013-2014, Frank T. Bergmann
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 * 2. 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.
 *
 * 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.
 *
 * ---------------------------------------------------------------------- -->
 *
 */

#include <limits>

#include <iostream>
#include <check.h>
#include <string>
#include <sstream>

#include <sbml/common/libsbml-version.h>
#include <sedml/common/libsedml-version.h>

#include <sedml/SedDocument.h>
#include <sedml/SedDataGenerator.h>
#include <sedml/SedWriter.h>

#include <sbml/math/L3FormulaFormatter.h>
#include <sbml/math/L3Parser.h>

/** @cond doxygenIgnored */

using namespace std;
LIBSBML_CPP_NAMESPACE_USE
LIBSEDML_CPP_NAMESPACE_USE

/** @endcond */

CK_CPPSTART

START_TEST (test_mathml_issue1)
{

  SedDocument doc;
  SedDataGenerator* sdg = doc.createDataGenerator();
  ASTNode* astn = SBML_parseL3Formula("S1/S2");
  sdg->setMath(astn);
  ostringstream stream;
  SedWriter sw;
  sw.writeSedML(&doc, stream);
  string v1 = stream.str();
  stream.str("");
  astn = SBML_parseL3Formula("log(S1/S2)");
  sdg->setMath(astn->getChild(1));
  sw.writeSedML(&doc, stream);
  string v2 = stream.str();
  //cout << v1 << endl << endl << v2 << endl << endl;
  fail_unless( v1 == v2 );
}
END_TEST

Suite *
create_suite_SedMLIssues (void)
{
  Suite *suite = suite_create("SedMLIssues");
  TCase *tcase = tcase_create("SedMLIssues");

  cout << "Testing issues reported using: " << endl;
  cout << "  libSBML  : " << getLibSBMLDottedVersion()
  #if LIBSBML_USE_LEGACY_MATH
      << " (using legacy math) "
  #else
      << " (using new ASTnode implementation) "
  #endif
      << endl;
  cout << "  libSEDML : " << getLibSEDMLDottedVersion() << endl << endl;

  tcase_add_test( tcase, test_mathml_issue1         );

  suite_add_tcase(suite, tcase);

  return suite;
}

CK_CPPEND
<|endoftext|>


<commit_before>/**
 * @file
 * TestRunner.cpp
 *
 * @brief The main method in this file runs all CppUnit tests.
 *
 * @date: Oct 16, 2009
 * @author: sblume
 */

#include <cppunit/CompilerOutputter.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <cppunit/ui/text/TestRunner.h>

int main(int argc, char* argv[]) {

	/*see also: http://cppunit.sourceforge.net/doc/lastest/money_example.html#sec_running_test */
	// Get the top level suite from the registry
	CppUnit::Test *suite = CppUnit::TestFactoryRegistry::getRegistry().makeTest();

	// Adds the test to the list of test to run
	CppUnit::TextUi::TestRunner runner;
	runner.addTest(suite);

	// Change the default outputter to a compiler error format outputter
	runner.setOutputter(new CppUnit::CompilerOutputter(&runner.result(), std::cerr));

	// Run the tests.
	bool wasSucessful = runner.run();

	// Return error code 1 if the one of test failed.
	return wasSucessful ? 0 : 1;
}

/* EOF */
<commit_msg>Optional XML output for unittests added. <commit_after>/**
 * @file
 * TestRunner.cpp
 *
 * @brief The main method in this file runs all CppUnit tests.
 *
 * @date: Oct 16, 2009
 * @author: sblume
 */

#include <fstream>
#include <cppunit/CompilerOutputter.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
#include <cppunit/ui/text/TestRunner.h>
#include <cppunit/XmlOutputter.h>

int main(int argc, char* argv[]) {

	/*see also: http://cppunit.sourceforge.net/doc/lastest/money_example.html#sec_running_test */
	// Get the top level suite from the registry
	CppUnit::Test *suite = CppUnit::TestFactoryRegistry::getRegistry().makeTest();

	// Adds the test to the list of test to run
	CppUnit::TextUi::TestRunner runner;
	runner.addTest(suite);

	// Check the set parameters.
	bool useXmlOutput = false;
	if (argc == 2) {
		std::string parameter = argv[1];
		if (parameter.compare("--report-xml") == 0) {
			useXmlOutput = true;
		}
	}

	// Decide which output format to take.
	std::ofstream outputStream;
	if (useXmlOutput) {
		// Change the default outputter to a XML outputter
		outputStream.open("unit_test_results.xml");
		runner.setOutputter(new CppUnit::XmlOutputter(&runner.result(), outputStream, std::string("ISO-8859-1")));
	} else {
		// Change the default outputter to a compiler error format outputter
		runner.setOutputter(new CppUnit::CompilerOutputter(&runner.result(), std::cerr));
	}

	// Run the tests.
	bool wasSucessful = runner.run();

	// Return error code 1 if the one of test failed.
	return wasSucessful ? 0 : 1;
}

/* EOF */
<|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 TORRENT_BITFIELD_HPP_INCLUDED
#define TORRENT_BITFIELD_HPP_INCLUDED

#include "libtorrent/assert.hpp"
#include "libtorrent/config.hpp"
#include <cstring> // for memset and memcpy
#include <cstdlib> // for malloc, free and realloc

namespace libtorrent
{
	struct TORRENT_EXPORT bitfield
	{
		bitfield(): m_bytes(0), m_size(0), m_own(false) {}
		bitfield(int bits): m_bytes(0), m_size(0), m_own(false)
		{ resize(bits); }
		bitfield(int bits, bool val): m_bytes(0), m_size(0), m_own(false)
		{ resize(bits, val); }
		bitfield(char const* b, int bits): m_bytes(0), m_size(0), m_own(false)
		{ assign(b, bits); }
		bitfield(bitfield const& rhs): m_bytes(0), m_size(0), m_own(false)
		{ assign(rhs.bytes(), rhs.size()); }

		void borrow_bytes(char* b, int bits)
		{
			dealloc();
			m_bytes = (unsigned char*)b;
			m_size = bits;
			m_own = false;
		}
		~bitfield() { dealloc(); }

		void assign(char const* b, int bits)
		{ resize(bits); std::memcpy(m_bytes, b, (bits + 7) / 8); clear_trailing_bits(); }

		bool operator[](int index) const
		{ return get_bit(index); }

		bool get_bit(int index) const
		{
			TORRENT_ASSERT(index >= 0);
			TORRENT_ASSERT(index < m_size);
			return (m_bytes[index / 8] & (0x80 >> (index & 7))) != 0;
		}

		void clear_bit(int index)
		{
			TORRENT_ASSERT(index >= 0);
			TORRENT_ASSERT(index < m_size);
			m_bytes[index / 8] &= ~(0x80 >> (index & 7));
		}

		void set_bit(int index)
		{
			TORRENT_ASSERT(index >= 0);
			TORRENT_ASSERT(index < m_size);
			m_bytes[index / 8] |= (0x80 >> (index & 7));
		}

		std::size_t size() const { return m_size; }
		bool empty() const { return m_size == 0; }

		char const* bytes() const { return (char*)m_bytes; }

		bitfield& operator=(bitfield const& rhs)
		{
			assign(rhs.bytes(), rhs.size());
			return *this;
		}

		int count() const
		{
			// 0000, 0001, 0010, 0011, 0100, 0101, 0110, 0111,
			// 1000, 1001, 1010, 1011, 1100, 1101, 1110, 1111
			const static char num_bits[] =
			{
				0, 1, 1, 2, 1, 2, 2, 3,
				1, 2, 2, 3, 2, 3, 3, 4
			};

			int ret = 0;
			const int num_bytes = m_size / 8;
			for (int i = 0; i < num_bytes; ++i)
			{
				ret += num_bits[m_bytes[i] & 0xf] + num_bits[m_bytes[i] >> 4];
			}

			int rest = m_size - num_bytes * 8;
			for (int i = 0; i < rest; ++i)
			{
				ret += (m_bytes[num_bytes] >> (7-i)) & 1;
			}
			TORRENT_ASSERT(ret <= m_size);
			TORRENT_ASSERT(ret >= 0);
			return ret;
		}

		struct const_iterator
		{
		friend struct bitfield;

			typedef bool value_type;
			typedef ptrdiff_t difference_type;
			typedef bool const* pointer;
			typedef bool& reference;
			typedef std::forward_iterator_tag iterator_category;

			bool operator*() { return (*byte & bit) != 0; }
			const_iterator& operator++() { inc(); return *this; }
			const_iterator operator++(int)
			{ const_iterator ret(*this); inc(); return ret; }
			const_iterator& operator--() { dec(); return *this; }
			const_iterator operator--(int)
			{ const_iterator ret(*this); dec(); return ret; }

			const_iterator(): byte(0), bit(0x80) {}
			bool operator==(const_iterator const& rhs) const
			{ return byte == rhs.byte && bit == rhs.bit; }

			bool operator!=(const_iterator const& rhs) const
			{ return byte != rhs.byte || bit != rhs.bit; }

		private:
			void inc()
			{
				TORRENT_ASSERT(byte);
				if (bit == 0x01)
				{
					bit = 0x80;
					++byte;
				}
				else
				{
					bit >>= 1;
				}
			}
			void dec()
			{
				TORRENT_ASSERT(byte);
				if (bit == 0x80)
				{
					bit = 0x01;
					--byte;
				}
				else
				{
					bit <<= 1;
				}
			}
			const_iterator(unsigned char const* ptr, int offset)
				: byte(ptr), bit(0x80 >> offset) {}
			unsigned char const* byte;
			int bit;
		};

		const_iterator begin() const { return const_iterator(m_bytes, 0); }
		const_iterator end() const { return const_iterator(m_bytes + m_size / 8, m_size & 7); }

		void resize(int bits, bool val)
		{
			int s = m_size;
			int b = m_size & 7;
			resize(bits);
			if (s >= m_size) return;
			int old_size_bytes = (s + 7) / 8;
			int new_size_bytes = (m_size + 7) / 8;
			if (val)
			{
				if (old_size_bytes && b) m_bytes[old_size_bytes - 1] |= (0xff >> b);
				if (old_size_bytes < new_size_bytes)
					std::memset(m_bytes + old_size_bytes, 0xff, new_size_bytes - old_size_bytes);
				clear_trailing_bits();
			}
			else
			{
				if (old_size_bytes < new_size_bytes)
					std::memset(m_bytes + old_size_bytes, 0x00, new_size_bytes - old_size_bytes);
			}
		}

		void set_all()
		{
			std::memset(m_bytes, 0xff, (m_size + 7) / 8);
			clear_trailing_bits();
		}

		void clear_all()
		{
			std::memset(m_bytes, 0x00, (m_size + 7) / 8);
		}

		void resize(int bits)
		{
			const int b = (bits + 7) / 8;
			if (m_bytes)
			{
				if (m_own)
				{
					m_bytes = (unsigned char*)std::realloc(m_bytes, b);
					m_own = true;
				}
				else if (bits > m_size)
				{
					unsigned char* tmp = (unsigned char*)std::malloc(b);
					std::memcpy(tmp, m_bytes, (std::min)(int(m_size + 7)/ 8, b));
					m_bytes = tmp;
					m_own = true;
				}
			}
			else
			{
				m_bytes = (unsigned char*)std::malloc(b);
				m_own = true;
			}
			m_size = bits;
			clear_trailing_bits();
		}

		void free() { dealloc(); m_size = 0; }

	private:

		void clear_trailing_bits()
		{
			// clear the tail bits in the last byte
			if (m_size & 7) m_bytes[(m_size + 7) / 8 - 1] &= 0xff << (8 - (m_size & 7));
		}

		void dealloc() { if (m_own) std::free(m_bytes); m_bytes = 0; }
		unsigned char* m_bytes;
		int m_size:31; // in bits
		bool m_own:1;
	};

}

#endif // TORRENT_BITFIELD_HPP_INCLUDED

<commit_msg>make electric fence happy by not allocating 0 bytes<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 TORRENT_BITFIELD_HPP_INCLUDED
#define TORRENT_BITFIELD_HPP_INCLUDED

#include "libtorrent/assert.hpp"
#include "libtorrent/config.hpp"
#include <cstring> // for memset and memcpy
#include <cstdlib> // for malloc, free and realloc

namespace libtorrent
{
	struct TORRENT_EXPORT bitfield
	{
		bitfield(): m_bytes(0), m_size(0), m_own(false) {}
		bitfield(int bits): m_bytes(0), m_size(0), m_own(false)
		{ resize(bits); }
		bitfield(int bits, bool val): m_bytes(0), m_size(0), m_own(false)
		{ resize(bits, val); }
		bitfield(char const* b, int bits): m_bytes(0), m_size(0), m_own(false)
		{ assign(b, bits); }
		bitfield(bitfield const& rhs): m_bytes(0), m_size(0), m_own(false)
		{ assign(rhs.bytes(), rhs.size()); }

		void borrow_bytes(char* b, int bits)
		{
			dealloc();
			m_bytes = (unsigned char*)b;
			m_size = bits;
			m_own = false;
		}
		~bitfield() { dealloc(); }

		void assign(char const* b, int bits)
		{ resize(bits); std::memcpy(m_bytes, b, (bits + 7) / 8); clear_trailing_bits(); }

		bool operator[](int index) const
		{ return get_bit(index); }

		bool get_bit(int index) const
		{
			TORRENT_ASSERT(index >= 0);
			TORRENT_ASSERT(index < m_size);
			return (m_bytes[index / 8] & (0x80 >> (index & 7))) != 0;
		}

		void clear_bit(int index)
		{
			TORRENT_ASSERT(index >= 0);
			TORRENT_ASSERT(index < m_size);
			m_bytes[index / 8] &= ~(0x80 >> (index & 7));
		}

		void set_bit(int index)
		{
			TORRENT_ASSERT(index >= 0);
			TORRENT_ASSERT(index < m_size);
			m_bytes[index / 8] |= (0x80 >> (index & 7));
		}

		std::size_t size() const { return m_size; }
		bool empty() const { return m_size == 0; }

		char const* bytes() const { return (char*)m_bytes; }

		bitfield& operator=(bitfield const& rhs)
		{
			assign(rhs.bytes(), rhs.size());
			return *this;
		}

		int count() const
		{
			// 0000, 0001, 0010, 0011, 0100, 0101, 0110, 0111,
			// 1000, 1001, 1010, 1011, 1100, 1101, 1110, 1111
			const static char num_bits[] =
			{
				0, 1, 1, 2, 1, 2, 2, 3,
				1, 2, 2, 3, 2, 3, 3, 4
			};

			int ret = 0;
			const int num_bytes = m_size / 8;
			for (int i = 0; i < num_bytes; ++i)
			{
				ret += num_bits[m_bytes[i] & 0xf] + num_bits[m_bytes[i] >> 4];
			}

			int rest = m_size - num_bytes * 8;
			for (int i = 0; i < rest; ++i)
			{
				ret += (m_bytes[num_bytes] >> (7-i)) & 1;
			}
			TORRENT_ASSERT(ret <= m_size);
			TORRENT_ASSERT(ret >= 0);
			return ret;
		}

		struct const_iterator
		{
		friend struct bitfield;

			typedef bool value_type;
			typedef ptrdiff_t difference_type;
			typedef bool const* pointer;
			typedef bool& reference;
			typedef std::forward_iterator_tag iterator_category;

			bool operator*() { return (*byte & bit) != 0; }
			const_iterator& operator++() { inc(); return *this; }
			const_iterator operator++(int)
			{ const_iterator ret(*this); inc(); return ret; }
			const_iterator& operator--() { dec(); return *this; }
			const_iterator operator--(int)
			{ const_iterator ret(*this); dec(); return ret; }

			const_iterator(): byte(0), bit(0x80) {}
			bool operator==(const_iterator const& rhs) const
			{ return byte == rhs.byte && bit == rhs.bit; }

			bool operator!=(const_iterator const& rhs) const
			{ return byte != rhs.byte || bit != rhs.bit; }

		private:
			void inc()
			{
				TORRENT_ASSERT(byte);
				if (bit == 0x01)
				{
					bit = 0x80;
					++byte;
				}
				else
				{
					bit >>= 1;
				}
			}
			void dec()
			{
				TORRENT_ASSERT(byte);
				if (bit == 0x80)
				{
					bit = 0x01;
					--byte;
				}
				else
				{
					bit <<= 1;
				}
			}
			const_iterator(unsigned char const* ptr, int offset)
				: byte(ptr), bit(0x80 >> offset) {}
			unsigned char const* byte;
			int bit;
		};

		const_iterator begin() const { return const_iterator(m_bytes, 0); }
		const_iterator end() const { return const_iterator(m_bytes + m_size / 8, m_size & 7); }

		void resize(int bits, bool val)
		{
			int s = m_size;
			int b = m_size & 7;
			resize(bits);
			if (s >= m_size) return;
			int old_size_bytes = (s + 7) / 8;
			int new_size_bytes = (m_size + 7) / 8;
			if (val)
			{
				if (old_size_bytes && b) m_bytes[old_size_bytes - 1] |= (0xff >> b);
				if (old_size_bytes < new_size_bytes)
					std::memset(m_bytes + old_size_bytes, 0xff, new_size_bytes - old_size_bytes);
				clear_trailing_bits();
			}
			else
			{
				if (old_size_bytes < new_size_bytes)
					std::memset(m_bytes + old_size_bytes, 0x00, new_size_bytes - old_size_bytes);
			}
		}

		void set_all()
		{
			std::memset(m_bytes, 0xff, (m_size + 7) / 8);
			clear_trailing_bits();
		}

		void clear_all()
		{
			std::memset(m_bytes, 0x00, (m_size + 7) / 8);
		}

		void resize(int bits)
		{
			TORRENT_ASSERT(bits >= 0);
			const int b = (bits + 7) / 8;
			if (m_bytes)
			{
				if (m_own)
				{
					m_bytes = (unsigned char*)std::realloc(m_bytes, b);
					m_own = true;
				}
				else if (bits > m_size)
				{
					unsigned char* tmp = (unsigned char*)std::malloc(b);
					std::memcpy(tmp, m_bytes, (std::min)(int(m_size + 7)/ 8, b));
					m_bytes = tmp;
					m_own = true;
				}
			}
			else if (bits > 0)
			{
				m_bytes = (unsigned char*)std::malloc(b);
				m_own = true;
			}
			m_size = bits;
			clear_trailing_bits();
		}

		void free() { dealloc(); m_size = 0; }

	private:

		void clear_trailing_bits()
		{
			// clear the tail bits in the last byte
			if (m_size & 7) m_bytes[(m_size + 7) / 8 - 1] &= 0xff << (8 - (m_size & 7));
		}

		void dealloc() { if (m_own) std::free(m_bytes); m_bytes = 0; }
		unsigned char* m_bytes;
		int m_size:31; // in bits
		bool m_own:1;
	};

}

#endif // TORRENT_BITFIELD_HPP_INCLUDED

<|endoftext|>


<commit_before>/*
  Automaton.cpp - Library for creating and running Finite State Machines.
  Published under the MIT License (MIT), Copyright (c) 2015, J.P. van der Landen
*/

#include "Automaton.h"

void atm_timer_millis::set( uint32_t v ) {
    value = v;
}

void atm_timer_micros::set( uint32_t v ) {
    value = v;
}

int atm_timer_millis::expired( BaseMachine * machine ) {
    return value == ATM_TIMER_OFF ? 0 : millis() - machine->state_millis >= value;
}

int atm_timer_micros::expired( Machine * machine ) {
    return value == ATM_TIMER_OFF ? 0 : micros() - machine->state_micros >= value;
}

void atm_counter::set( uint16_t v )
{
    value = v;
}

uint16_t atm_counter::decrement( void )
{
    return value > 0 && value != ATM_COUNTER_OFF ? --value : 0;
}

uint8_t atm_counter::expired()
{
    return value == ATM_COUNTER_OFF ? 0 : ( value > 0 ? 0 : 1 );
}

Machine & Machine::state(state_t state)
{
    next = state;
    last_trigger = -1;
    flags &= ~ATM_SLEEP_FLAG;
    if ( ( flags & ATM_MSGAC_FLAG ) > 0 ) msgClear();
    return *this;
}

state_t Machine::state()
{
    return current;
}

int Machine::trigger( int evt )
{
    if ( current == -1 ) cycle();
    if ( current > -1 ) {
        int new_state = read_state( state_table + ( current * state_width ) + evt + ATM_ON_EXIT + 1 );
        if ( new_state > -1 ) {
	      state( new_state );
          last_trigger = evt;
          return 1;
        }
    }
    return 0;
}

Machine & Machine::onSwitch( swcb_sym_t callback, const char sym_s[], const char sym_e[] )
{
    callback_sym = callback;
    sym_states = sym_s;
    sym_events = sym_e;
    return *this;
}

Machine & Machine::label( const char label[] )
{
    inst_label = label;
    return *this;
}

int8_t Machine::priority()
{
    return prio;
}

Machine & Machine::priority( int8_t priority )
{
    prio = priority;
    return *this;
}

// .asleep() Returns true if the machine is in a sleeping state

uint8_t BaseMachine::asleep()
{
    return ( flags & ATM_SLEEP_FLAG ) > 0;
}

BaseMachine & BaseMachine::sleep( uint8_t v )
{
    flags |=  ATM_SLEEP_FLAG;
    flags = v ? flags | ATM_SLEEP_FLAG : flags & ~ATM_SLEEP_FLAG;
    return *this;
}

Machine & Machine::begin( const state_t* tbl, int width )
{
    state_table = tbl;
    state_width = ATM_ON_EXIT + width + 2;
    prio = ATM_DEFAULT_PRIO;
    if ( !inst_label ) inst_label = class_label;
    return *this;
}

Machine & Machine::msgQueue( atm_msg_t msg[], int width, uint8_t autoclear /* = 0 */ )
{
    msg_table = msg;
    msg_width = width;
    flags = autoclear ? flags | ATM_MSGAC_FLAG : flags & ~ATM_MSGAC_FLAG;
    return *this;
}

unsigned char Machine::pinChange( uint8_t pin ) {

  unsigned char v = digitalRead( pin ) ? 1 : 0;
  if ( (( pinstate >> pin ) & 1 ) != ( v == 1 ) ) {
    pinstate ^= ( (uint32_t)1 << pin );
    return 1;
  }
  return 0;
}

int Machine::msgRead( uint8_t id_msg, int cnt /* = 1 */, int clear /* = 0 */ )
{
  if ( msg_table[id_msg] > 0 ) {
    if ( cnt >= msg_table[id_msg] ) {
        msg_table[id_msg] = 0;
    } else {
        msg_table[id_msg] -= cnt;
    }
	if ( clear ) {
		for ( int i = 0; i < msg_width; i++ ) {
			msg_table[i] = 0;
		}
    }
    return 1;
  }
  return 0;
}

int Machine::msgPeek( uint8_t id_msg )
{
  return msg_table[id_msg];
}

int Machine::msgClear( uint8_t id_msg ) // Destructive read (clears queue for this type)
{
  flags &= ~ATM_SLEEP_FLAG;
  if ( msg_table[id_msg] > 0 ) {
    msg_table[id_msg] = 0;
    return 1;
  }
  return 0;
}

Machine & Machine::msgClear()
{
  flags &= ~ATM_SLEEP_FLAG;
  for ( int i = 0; i < msg_width; i++ ) {
    msg_table[i] = 0;
  }
  return *this;
}

Machine & Machine::msgWrite( uint8_t id_msg, int cnt /* = 1 */ )
{
  flags &= ~ATM_SLEEP_FLAG;
  msg_table[id_msg] += cnt;
  return *this;
}

const char * Machine::map_symbol( int id, const char map[] )
{
  int cnt = 0;
  int i = 0;
  if ( id == -1 ) return "*NONE*";
  if ( id ==  0 ) return map;
  while ( 1 ) {
    if ( map[i] == '\0' && ++cnt == id ) {
      i++;
      break;
    }
    i++;
  }
  return &map[i];
}

// .cycle() Executes one cycle of a state machine
Machine & Machine::cycle()
{
    if ( ( flags & ATM_SLEEP_FLAG ) == 0 ) {
        cycles++;
        if ( next != -1 ) {
            action( ATM_ON_SWITCH );
            if ( callback_sym ) {
                callback_sym( inst_label,
                    map_symbol(      current, sym_states ),
                    map_symbol(         next, sym_states ),
                    map_symbol( last_trigger, sym_events ), millis() - state_millis, cycles );
            }
            if ( current > -1 )
		action( read_state( state_table + ( current * state_width ) + ATM_ON_EXIT ) );
            previous = current;
            current = next;
            next = -1;
            state_millis = millis();
            state_micros = micros();
            action( read_state( state_table + ( current * state_width ) + ATM_ON_ENTER ) );
            if ( read_state( state_table + ( current * state_width ) + ATM_ON_LOOP ) == ATM_SLEEP ) {
                  flags |= ATM_SLEEP_FLAG;
            } else {
                  flags &= ~ATM_SLEEP_FLAG;
            }
            cycles = 0;
        }
        state_t i = read_state( state_table + ( current * state_width ) + ATM_ON_LOOP );
        if ( i != -1 ) { action( i ); }
        for ( i = ATM_ON_EXIT + 1; i < state_width; i++ ) {
            if ( ( read_state( state_table + ( current * state_width ) + i ) != -1 ) && ( i == state_width - 1 || event( i - ATM_ON_EXIT - 1 ) ) ) {
                state( read_state( state_table + ( current * state_width ) + i ) );
                last_trigger = i - ATM_ON_EXIT - 1;
                return *this;
            }
        }
    }
    return *this;
}

// TINY MACHINE

TinyMachine & TinyMachine::state( tiny_state_t state )
{
    next = state;
    flags &= ~ATM_SLEEP_FLAG;
    return *this;
}

tiny_state_t TinyMachine::state()
{
    return current;
}

int TinyMachine::trigger( int evt )
{
    if ( current == -1 ) cycle();
    if ( current > -1 ) {
        int new_state = tiny_read_state( state_table + ( current * state_width ) + evt + ATM_ON_EXIT + 1 );
        if ( new_state > -1 ) {
          state( new_state );
          return 1;
        }
    }
    return 0;
}

TinyMachine & TinyMachine::begin( const tiny_state_t* tbl, int width )
{
    state_table = tbl;
    state_width = ATM_ON_EXIT + width + 2;
    return *this;
}

// .cycle() Executes one cycle of a state machine
TinyMachine & TinyMachine::cycle()
{
    if ( ( flags & ATM_SLEEP_FLAG ) == 0 ) {
        if ( next != -1 ) {
            action( ATM_ON_SWITCH );
            if ( current > -1 )
                action( tiny_read_state( state_table + ( current * state_width ) + ATM_ON_EXIT ) );
            current = next;
            next = -1;
            state_millis = millis();
            action( tiny_read_state( state_table + ( current * state_width ) + ATM_ON_ENTER ) );
            if ( read_state( state_table + ( current * state_width ) + ATM_ON_LOOP ) == ATM_SLEEP ) {
                  flags |= ATM_SLEEP_FLAG;
            } else {
                  flags &= ~ATM_SLEEP_FLAG;
            }
        }
        tiny_state_t i = tiny_read_state( state_table + ( current * state_width ) + ATM_ON_LOOP );
        if ( i != -1 ) { action( i ); }
        for ( i = ATM_ON_EXIT + 1; i < state_width; i++ ) {
            if ( ( tiny_read_state( state_table + ( current * state_width ) + i ) != -1 ) && ( i == state_width - 1 || event( i - ATM_ON_EXIT - 1 ) ) ) {
                state( tiny_read_state( state_table + ( current * state_width ) + i ) );
                return *this;
            }
        }
    }
    return *this;
}

// FACTORY

// .calibrate() Distributes the machines in the inventory to the appropriate priority queues
void Factory::calibrate( void )
{
    // Reset all priority queues to empty lists
    for ( int8_t i = 0; i < ATM_NO_OF_QUEUES; i++ )
        priority_root[i] = 0;
    // Walk the inventory list that contains all state machines in this factory
    Machine * m = inventory_root;
    while ( m ) {
        // Prepend every machine to the appropriate priority queue
        if ( m->prio < ATM_NO_OF_QUEUES ) {
            m->priority_next = priority_root[m->prio];
            priority_root[m->prio] = m;
        }
        m = m->inventory_next;
    }
    recalibrate = 0;
}

// .run( q ) Traverses an individual priority queue and cycles the machines in it once (except for queue 0)
void Factory::run( int q )
{
    Machine * m = priority_root[ q ];
    while ( m ) {
        if ( q > 0 && ( m->flags & ATM_SLEEP_FLAG ) == 0 ) m->cycle();
        // Request a recalibrate if the prio field doesn't match the current queue
        if ( m->prio != q ) recalibrate = 1;
        // Move to the next machine
        m = m->priority_next;
    }
}

// .add( machine ) Adds a state machine to the factory by prepending it to the inventory list
Factory & Factory::add( Machine & machine )
{
    machine.inventory_next = inventory_root;
    inventory_root = &machine;
    machine.factory = this;
    recalibrate = 1;
    return *this;
}

// .find() Search the factory inventory for a machine by instance label
Machine * Factory::find( const char label[] )
{
    Machine * m = inventory_root;
    while ( m ) {
        if ( strcmp( label, m->inst_label ) == 0 ) {
            return m;
        }
        m = m->inventory_next;
    }
    return 0;
}

int Factory::msgSend( const char label[], int msg, int cnt /* = 1 */ )
{
    int r = 0;
    Machine * m = inventory_root;
    while ( m ) {
        if ( strcmp( label, m->inst_label ) == 0 ) {
            m->msgWrite( msg, cnt );
            r++;
        }
        m = m->inventory_next;
    }
    return r;
}

int Factory::msgSendClass( const char label[], int msg, int cnt /* = 1 */ )
{
    int r = 0;
    Machine * m = inventory_root;
    while ( m ) {
        if ( strcmp( label, m->class_label ) == 0 ) {
            m->msgWrite( msg, cnt );
            r++;
        }
        m = m->inventory_next;
    }
    return r;
}

// .cycle() executes one factory cycle (runs all priority queues a certain number of times)
Factory & Factory::cycle( void )
{
    if ( recalibrate ) calibrate();
    run( 1 ); run( 2 );	run( 1 ); run( 2 );
    run( 1 ); run( 3 );	run( 1 ); run( 4 );
    run( 1 ); run( 2 );	run( 1 ); run( 3 );
    run( 1 ); run( 2 );	run( 1 ); run( 0 );
    return  *this;
}

<commit_msg>Removed redundant code in sleep()<commit_after>/*
  Automaton.cpp - Library for creating and running Finite State Machines.
  Published under the MIT License (MIT), Copyright (c) 2015, J.P. van der Landen
*/

#include "Automaton.h"

void atm_timer_millis::set( uint32_t v ) {
    value = v;
}

void atm_timer_micros::set( uint32_t v ) {
    value = v;
}

int atm_timer_millis::expired( BaseMachine * machine ) {
    return value == ATM_TIMER_OFF ? 0 : millis() - machine->state_millis >= value;
}

int atm_timer_micros::expired( Machine * machine ) {
    return value == ATM_TIMER_OFF ? 0 : micros() - machine->state_micros >= value;
}

void atm_counter::set( uint16_t v )
{
    value = v;
}

uint16_t atm_counter::decrement( void )
{
    return value > 0 && value != ATM_COUNTER_OFF ? --value : 0;
}

uint8_t atm_counter::expired()
{
    return value == ATM_COUNTER_OFF ? 0 : ( value > 0 ? 0 : 1 );
}

Machine & Machine::state(state_t state)
{
    next = state;
    last_trigger = -1;
    flags &= ~ATM_SLEEP_FLAG;
    if ( ( flags & ATM_MSGAC_FLAG ) > 0 ) msgClear();
    return *this;
}

state_t Machine::state()
{
    return current;
}

int Machine::trigger( int evt )
{
    if ( current == -1 ) cycle();
    if ( current > -1 ) {
        int new_state = read_state( state_table + ( current * state_width ) + evt + ATM_ON_EXIT + 1 );
        if ( new_state > -1 ) {
	      state( new_state );
          last_trigger = evt;
          return 1;
        }
    }
    return 0;
}

Machine & Machine::onSwitch( swcb_sym_t callback, const char sym_s[], const char sym_e[] )
{
    callback_sym = callback;
    sym_states = sym_s;
    sym_events = sym_e;
    return *this;
}

Machine & Machine::label( const char label[] )
{
    inst_label = label;
    return *this;
}

int8_t Machine::priority()
{
    return prio;
}

Machine & Machine::priority( int8_t priority )
{
    prio = priority;
    return *this;
}

// .asleep() Returns true if the machine is in a sleeping state

uint8_t BaseMachine::asleep()
{
    return ( flags & ATM_SLEEP_FLAG ) > 0;
}

BaseMachine & BaseMachine::sleep( uint8_t v /* = 1 */ )
{
    flags = v ? flags | ATM_SLEEP_FLAG : flags & ~ATM_SLEEP_FLAG;
    return *this;
}

Machine & Machine::begin( const state_t* tbl, int width )
{
    state_table = tbl;
    state_width = ATM_ON_EXIT + width + 2;
    prio = ATM_DEFAULT_PRIO;
    if ( !inst_label ) inst_label = class_label;
    return *this;
}

Machine & Machine::msgQueue( atm_msg_t msg[], int width, uint8_t autoclear /* = 0 */ )
{
    msg_table = msg;
    msg_width = width;
    flags = autoclear ? flags | ATM_MSGAC_FLAG : flags & ~ATM_MSGAC_FLAG;
    return *this;
}

unsigned char Machine::pinChange( uint8_t pin ) {

  unsigned char v = digitalRead( pin ) ? 1 : 0;
  if ( (( pinstate >> pin ) & 1 ) != ( v == 1 ) ) {
    pinstate ^= ( (uint32_t)1 << pin );
    return 1;
  }
  return 0;
}

int Machine::msgRead( uint8_t id_msg, int cnt /* = 1 */, int clear /* = 0 */ )
{
  if ( msg_table[id_msg] > 0 ) {
    if ( cnt >= msg_table[id_msg] ) {
        msg_table[id_msg] = 0;
    } else {
        msg_table[id_msg] -= cnt;
    }
	if ( clear ) {
		for ( int i = 0; i < msg_width; i++ ) {
			msg_table[i] = 0;
		}
    }
    return 1;
  }
  return 0;
}

int Machine::msgPeek( uint8_t id_msg )
{
  return msg_table[id_msg];
}

int Machine::msgClear( uint8_t id_msg ) // Destructive read (clears queue for this type)
{
  flags &= ~ATM_SLEEP_FLAG;
  if ( msg_table[id_msg] > 0 ) {
    msg_table[id_msg] = 0;
    return 1;
  }
  return 0;
}

Machine & Machine::msgClear()
{
  flags &= ~ATM_SLEEP_FLAG;
  for ( int i = 0; i < msg_width; i++ ) {
    msg_table[i] = 0;
  }
  return *this;
}

Machine & Machine::msgWrite( uint8_t id_msg, int cnt /* = 1 */ )
{
  flags &= ~ATM_SLEEP_FLAG;
  msg_table[id_msg] += cnt;
  return *this;
}

const char * Machine::map_symbol( int id, const char map[] )
{
  int cnt = 0;
  int i = 0;
  if ( id == -1 ) return "*NONE*";
  if ( id ==  0 ) return map;
  while ( 1 ) {
    if ( map[i] == '\0' && ++cnt == id ) {
      i++;
      break;
    }
    i++;
  }
  return &map[i];
}

// .cycle() Executes one cycle of a state machine
Machine & Machine::cycle()
{
    if ( ( flags & ATM_SLEEP_FLAG ) == 0 ) {
        cycles++;
        if ( next != -1 ) {
            action( ATM_ON_SWITCH );
            if ( callback_sym ) {
                callback_sym( inst_label,
                    map_symbol(      current, sym_states ),
                    map_symbol(         next, sym_states ),
                    map_symbol( last_trigger, sym_events ), millis() - state_millis, cycles );
            }
            if ( current > -1 )
		action( read_state( state_table + ( current * state_width ) + ATM_ON_EXIT ) );
            previous = current;
            current = next;
            next = -1;
            state_millis = millis();
            state_micros = micros();
            action( read_state( state_table + ( current * state_width ) + ATM_ON_ENTER ) );
            if ( read_state( state_table + ( current * state_width ) + ATM_ON_LOOP ) == ATM_SLEEP ) {
                  flags |= ATM_SLEEP_FLAG;
            } else {
                  flags &= ~ATM_SLEEP_FLAG;
            }
            cycles = 0;
        }
        state_t i = read_state( state_table + ( current * state_width ) + ATM_ON_LOOP );
        if ( i != -1 ) { action( i ); }
        for ( i = ATM_ON_EXIT + 1; i < state_width; i++ ) {
            if ( ( read_state( state_table + ( current * state_width ) + i ) != -1 ) && ( i == state_width - 1 || event( i - ATM_ON_EXIT - 1 ) ) ) {
                state( read_state( state_table + ( current * state_width ) + i ) );
                last_trigger = i - ATM_ON_EXIT - 1;
                return *this;
            }
        }
    }
    return *this;
}

// TINY MACHINE

TinyMachine & TinyMachine::state( tiny_state_t state )
{
    next = state;
    flags &= ~ATM_SLEEP_FLAG;
    return *this;
}

tiny_state_t TinyMachine::state()
{
    return current;
}

int TinyMachine::trigger( int evt )
{
    if ( current == -1 ) cycle();
    if ( current > -1 ) {
        int new_state = tiny_read_state( state_table + ( current * state_width ) + evt + ATM_ON_EXIT + 1 );
        if ( new_state > -1 ) {
          state( new_state );
          return 1;
        }
    }
    return 0;
}

TinyMachine & TinyMachine::begin( const tiny_state_t* tbl, int width )
{
    state_table = tbl;
    state_width = ATM_ON_EXIT + width + 2;
    return *this;
}

// .cycle() Executes one cycle of a state machine
TinyMachine & TinyMachine::cycle()
{
    if ( ( flags & ATM_SLEEP_FLAG ) == 0 ) {
        if ( next != -1 ) {
            action( ATM_ON_SWITCH );
            if ( current > -1 )
                action( tiny_read_state( state_table + ( current * state_width ) + ATM_ON_EXIT ) );
            current = next;
            next = -1;
            state_millis = millis();
            action( tiny_read_state( state_table + ( current * state_width ) + ATM_ON_ENTER ) );
            if ( read_state( state_table + ( current * state_width ) + ATM_ON_LOOP ) == ATM_SLEEP ) {
                  flags |= ATM_SLEEP_FLAG;
            } else {
                  flags &= ~ATM_SLEEP_FLAG;
            }
        }
        tiny_state_t i = tiny_read_state( state_table + ( current * state_width ) + ATM_ON_LOOP );
        if ( i != -1 ) { action( i ); }
        for ( i = ATM_ON_EXIT + 1; i < state_width; i++ ) {
            if ( ( tiny_read_state( state_table + ( current * state_width ) + i ) != -1 ) && ( i == state_width - 1 || event( i - ATM_ON_EXIT - 1 ) ) ) {
                state( tiny_read_state( state_table + ( current * state_width ) + i ) );
                return *this;
            }
        }
    }
    return *this;
}

// FACTORY

// .calibrate() Distributes the machines in the inventory to the appropriate priority queues
void Factory::calibrate( void )
{
    // Reset all priority queues to empty lists
    for ( int8_t i = 0; i < ATM_NO_OF_QUEUES; i++ )
        priority_root[i] = 0;
    // Walk the inventory list that contains all state machines in this factory
    Machine * m = inventory_root;
    while ( m ) {
        // Prepend every machine to the appropriate priority queue
        if ( m->prio < ATM_NO_OF_QUEUES ) {
            m->priority_next = priority_root[m->prio];
            priority_root[m->prio] = m;
        }
        m = m->inventory_next;
    }
    recalibrate = 0;
}

// .run( q ) Traverses an individual priority queue and cycles the machines in it once (except for queue 0)
void Factory::run( int q )
{
    Machine * m = priority_root[ q ];
    while ( m ) {
        if ( q > 0 && ( m->flags & ATM_SLEEP_FLAG ) == 0 ) m->cycle();
        // Request a recalibrate if the prio field doesn't match the current queue
        if ( m->prio != q ) recalibrate = 1;
        // Move to the next machine
        m = m->priority_next;
    }
}

// .add( machine ) Adds a state machine to the factory by prepending it to the inventory list
Factory & Factory::add( Machine & machine )
{
    machine.inventory_next = inventory_root;
    inventory_root = &machine;
    machine.factory = this;
    recalibrate = 1;
    return *this;
}

// .find() Search the factory inventory for a machine by instance label
Machine * Factory::find( const char label[] )
{
    Machine * m = inventory_root;
    while ( m ) {
        if ( strcmp( label, m->inst_label ) == 0 ) {
            return m;
        }
        m = m->inventory_next;
    }
    return 0;
}

int Factory::msgSend( const char label[], int msg, int cnt /* = 1 */ )
{
    int r = 0;
    Machine * m = inventory_root;
    while ( m ) {
        if ( strcmp( label, m->inst_label ) == 0 ) {
            m->msgWrite( msg, cnt );
            r++;
        }
        m = m->inventory_next;
    }
    return r;
}

int Factory::msgSendClass( const char label[], int msg, int cnt /* = 1 */ )
{
    int r = 0;
    Machine * m = inventory_root;
    while ( m ) {
        if ( strcmp( label, m->class_label ) == 0 ) {
            m->msgWrite( msg, cnt );
            r++;
        }
        m = m->inventory_next;
    }
    return r;
}

// .cycle() executes one factory cycle (runs all priority queues a certain number of times)
Factory & Factory::cycle( void )
{
    if ( recalibrate ) calibrate();
    run( 1 ); run( 2 );	run( 1 ); run( 2 );
    run( 1 ); run( 3 );	run( 1 ); run( 4 );
    run( 1 ); run( 2 );	run( 1 ); run( 3 );
    run( 1 ); run( 2 );	run( 1 ); run( 0 );
    return  *this;
}

<|endoftext|>


<commit_before>///
/// @file   iterator.hpp
/// @brief  The iterator class allows to easily iterate (forward and
///         backward) over prime numbers.
///
/// Copyright (C) 2014 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#ifndef PRIMESIEVE_ITERATOR_HPP
#define PRIMESIEVE_ITERATOR_HPP

#include <vector>
#include <cstddef>

namespace primesieve {

uint64_t get_max_stop();

/// Iterate over prime numbers.
/// primesieve::iterator allows to easily iterate over primes both
/// forwards and backwards. Note that generating the first prime uses
/// O(n^0.5 log log n^0.5) operations, after that any additional
/// prime is generated in amortized O(log n) operations. The memory
/// usage is about pi(sqrt(n)) * 16 bytes. primesieve::iterator
/// objects are very convenient to use at the cost of being slightly
/// slower than the callback_primes() functions.
///
class iterator
{
public:
  /// Create a new iterator object.
  /// @param start      Start iterating at this number. If start is a
  ///                   prime then first calling either next_prime()
  ///                   or previous_prime() will return start.
  /// @param stop_hint  Stop number optimization hint, gives significant
  ///                   speed up if few primes are generated. E.g. if
  ///                   you want to generate the primes below 1000 use
  ///                   stop_hint = 1000.
  /// @pre              start <= 2^64 - 2^32 * 10
  ///
  iterator(uint64_t start = 0, uint64_t stop_hint = get_max_stop());

  /// Reinitialize this iterator object to start.
  /// @param start      Start iterating at this number. If start is a
  ///                   prime then first calling either next_prime()
  ///                   or previous_prime() will return start.
  /// @param stop_hint  Stop number optimization hint, gives significant
  ///                   speed up if few primes are generated. E.g. if
  ///                   you want to generate the primes below 1000 use
  ///                   stop_hint = 1000.
  /// @pre              start <= 2^64 - 2^32 * 10
  ///
  void skipto(uint64_t start, uint64_t stop_hint = get_max_stop());

  /// Free all memory, same as skipto(0).
  void clear();

  /// Advance the iterator by one position.
  /// @return  The next prime.
  ///
  uint64_t next_prime()
  {
    if (i_++ == last_idx_)
      generate_next_primes();
    return primes_[i_];
  }

  /// Decrease the iterator by one position.
  /// @return  The previous prime.
  ///
  uint64_t previous_prime()
  {
    if (i_-- == 0)
      generate_previous_primes();
    return primes_[i_];
  }
private:
  std::size_t i_;
  std::size_t last_idx_;
  std::vector<uint64_t> primes_;
  uint64_t start_;
  uint64_t stop_;
  uint64_t stop_hint_;
  uint64_t count_;
  uint64_t get_interval_size(uint64_t);
  void generate_primes(uint64_t, uint64_t);
  void generate_next_primes();
  void generate_previous_primes();
};

} // end namespace

#endif
<commit_msg>Update documentation<commit_after>///
/// @file   iterator.hpp
/// @brief  The iterator class allows to easily iterate (forward and
///         backward) over prime numbers.
///
/// Copyright (C) 2014 Kim Walisch, <kim.walisch@gmail.com>
///
/// This file is distributed under the BSD License. See the COPYING
/// file in the top level directory.
///

#ifndef PRIMESIEVE_ITERATOR_HPP
#define PRIMESIEVE_ITERATOR_HPP

#include <vector>
#include <cstddef>

namespace primesieve {

uint64_t get_max_stop();

/// Iterate over prime numbers.
/// primesieve::iterator allows to easily iterate over primes both
/// forwards and backwards. Generating the first prime uses
/// O(n^0.5 log n^0.5) operations, after that any additional prime is
/// generated in amortized O(log n) operations. The memory usage is
/// about pi(n^0.5) * 16 bytes. primesieve::iterator objects are very
/// convenient to use at the cost of being slightly slower than the
/// callback_primes() functions.
///
class iterator
{
public:
  /// Create a new iterator object.
  /// @param start      Start iterating at this number. If start is a
  ///                   prime then first calling either next_prime()
  ///                   or previous_prime() will return start.
  /// @param stop_hint  Stop number optimization hint, gives significant
  ///                   speed up if few primes are generated. E.g. if
  ///                   you want to generate the primes below 1000 use
  ///                   stop_hint = 1000.
  /// @pre              start <= 2^64 - 2^32 * 10
  ///
  iterator(uint64_t start = 0, uint64_t stop_hint = get_max_stop());

  /// Reinitialize this iterator object to start.
  /// @param start      Start iterating at this number. If start is a
  ///                   prime then first calling either next_prime()
  ///                   or previous_prime() will return start.
  /// @param stop_hint  Stop number optimization hint, gives significant
  ///                   speed up if few primes are generated. E.g. if
  ///                   you want to generate the primes below 1000 use
  ///                   stop_hint = 1000.
  /// @pre              start <= 2^64 - 2^32 * 10
  ///
  void skipto(uint64_t start, uint64_t stop_hint = get_max_stop());

  /// Free all memory, same as skipto(0).
  void clear();

  /// Advance the iterator by one position.
  /// @return  The next prime.
  ///
  uint64_t next_prime()
  {
    if (i_++ == last_idx_)
      generate_next_primes();
    return primes_[i_];
  }

  /// Decrease the iterator by one position.
  /// @return  The previous prime.
  ///
  uint64_t previous_prime()
  {
    if (i_-- == 0)
      generate_previous_primes();
    return primes_[i_];
  }
private:
  std::size_t i_;
  std::size_t last_idx_;
  std::vector<uint64_t> primes_;
  uint64_t start_;
  uint64_t stop_;
  uint64_t stop_hint_;
  uint64_t count_;
  uint64_t get_interval_size(uint64_t);
  void generate_primes(uint64_t, uint64_t);
  void generate_next_primes();
  void generate_previous_primes();
};

} // end namespace

#endif
<|endoftext|>


<commit_before>//
// Copyright (C) 2013-2017 University of Amsterdam
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program.  If not, see
// <http://www.gnu.org/licenses/>.
//

#include "ribbonanalysis.h"
#include "ui_ribbonanalysis.h"

#include <QMenu>
#include <QDebug>

RibbonAnalysis::RibbonAnalysis(QWidget *parent) :
	RibbonWidget(parent),
	ui(new Ui::RibbonAnalysis)
{
	ui->setupUi(this);

	addRibbonButton(ui->Descriptives);
	addRibbonButton(ui->ttestButton);
	addRibbonButton(ui->anovaButton);
	addRibbonButton(ui->frequenciesButton);
	addRibbonButton(ui->regressionButton);
	addRibbonButton(ui->BFFromT);
	addRibbonButton(ui->factoranalysisButton);

	ui->BFFromT->setDataSetNotNeeded();

//	connect(ui->Descriptives, SIGNAL(clicked()), this, SLOT(itemSelected()));

	QMenu *menu;

	menu = new QMenu(this);
	menu->addAction(QString("Descriptive Statistics"), this, SLOT(itemSelected()))->setObjectName("Descriptives");
	menu->addAction(QString("Reliability Analysis"), this, SLOT(itemSelected()))->setObjectName("ReliabilityAnalysis");

	ui->Descriptives->setMenu(menu);

	menu = new QMenu(this);
	menu->addAction(QString("Independent Samples T-Test"), this, SLOT(itemSelected()))->setObjectName("TTestIndependentSamples");
	menu->addAction(QString("Paired Samples T-Test"), this, SLOT(itemSelected()))->setObjectName("TTestPairedSamples");
	menu->addAction(QString("One Sample T-Test"), this, SLOT(itemSelected()))->setObjectName("TTestOneSample");

	menu->addSeparator();

	menu->addAction(QString("Bayesian Independent Samples T-Test"), this, SLOT(itemSelected()))->setObjectName("TTestBayesianIndependentSamples");
	menu->addAction(QString("Bayesian Paired Samples T-Test"), this, SLOT(itemSelected()))->setObjectName("TTestBayesianPairedSamples");
	menu->addAction(QString("Bayesian One Sample T-Test"), this, SLOT(itemSelected()))->setObjectName("TTestBayesianOneSample");

	ui->ttestButton->setMenu(menu);

	menu = new QMenu(this);

	menu->addAction(QString("ANOVA"), this, SLOT(itemSelected()))->setObjectName("Anova");
	menu->addAction(QString("Repeated Measures ANOVA"), this, SLOT(itemSelected()))->setObjectName("AnovaRepeatedMeasures");
	menu->addAction(QString("ANCOVA"), this, SLOT(itemSelected()))->setObjectName("Ancova");

	menu->addSeparator();

	menu->addAction(QString("Bayesian ANOVA"), this, SLOT(itemSelected()))->setObjectName("AnovaBayesian");
	menu->addAction(QString("Bayesian Repeated Measures ANOVA"), this, SLOT(itemSelected()))->setObjectName("AnovaRepeatedMeasuresBayesian");
	menu->addAction(QString("Bayesian ANCOVA"), this, SLOT(itemSelected()))->setObjectName("AncovaBayesian");

	ui->anovaButton->setMenu(menu);

	menu = new QMenu(this);

	menu->addAction(QString("Correlation Matrix"), this, SLOT(itemSelected()))->setObjectName("Correlation");
	menu->addAction(QString("Linear Regression"), this, SLOT(itemSelected()))->setObjectName("RegressionLinear");
	menu->addAction(QString("Logistic Regression"), this, SLOT(itemSelected()))->setObjectName("RegressionLogistic");

	menu->addSeparator();

	menu->addAction(QString("Bayesian Correlation Matrix"), this, SLOT(itemSelected()))->setObjectName("CorrelationBayesian");
	menu->addAction(QString("Bayesian Correlation Pairs"), this, SLOT(itemSelected()))->setObjectName("CorrelationBayesianPairs");
	menu->addAction(QString("Bayesian Linear Regression"), this, SLOT(itemSelected()))->setObjectName("RegressionLinearBayesian");

#ifdef QT_DEBUG
	menu->addSeparator();
	menu->addAction(QString("BAS Regression Linear link"), this, SLOT(itemSelected()))->setObjectName("BASRegressionLinearLink");
#endif
	ui->regressionButton->setMenu(menu);

	menu = new QMenu(this);

	menu->addAction(QString("Binomial Test"), this, SLOT(itemSelected()))->setObjectName("BinomialTest");
	menu->addAction(QString("Multinomial Test"), this, SLOT(itemSelected()))->setObjectName("MultinomialTest");
	menu->addAction(QString("Contingency Tables"), this, SLOT(itemSelected()))->setObjectName("ContingencyTables");
    menu->addAction(QString("Log-Linear Regression"), this, SLOT(itemSelected()))->setObjectName("RegressionLogLinear");

	menu->addSeparator();
	menu->addAction(QString("Bayesian Binomial Test"), this, SLOT(itemSelected()))->setObjectName("BinomialTestBayesian");
	menu->addAction(QString("Bayesian Contingency Tables"), this, SLOT(itemSelected()))->setObjectName("ContingencyTablesBayesian");
    menu->addAction(QString("Bayesian Log-Linear Regression"), this, SLOT(itemSelected()))->setObjectName("RegressionLogLinearBayesian");

	ui->frequenciesButton->setMenu(menu);

	menu = new QMenu(this);
	menu->addAction(QString("Principal Component Analysis"), this, SLOT(itemSelected()))->setObjectName("PrincipalComponentAnalysis");
	menu->addAction(QString("Exploratory Factor Analysis"), this, SLOT(itemSelected()))->setObjectName("ExploratoryFactorAnalysis");

	ui->factoranalysisButton->setMenu(menu);

#ifndef QT_DEBUG
	ui->BFFromT->hide();
#else
	menu = new QMenu(this);
	menu->addAction(QString("BF From t"), this, SLOT(itemSelected()))->setObjectName("BFFromT");

	ui->BFFromT->setMenu(menu);
#endif
}

RibbonAnalysis::~RibbonAnalysis()
{
	delete ui;
}
<commit_msg>Hide unfinished multinomial analysis from ribbon<commit_after>//
// Copyright (C) 2013-2017 University of Amsterdam
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public
// License along with this program.  If not, see
// <http://www.gnu.org/licenses/>.
//

#include "ribbonanalysis.h"
#include "ui_ribbonanalysis.h"

#include <QMenu>
#include <QDebug>

RibbonAnalysis::RibbonAnalysis(QWidget *parent) :
	RibbonWidget(parent),
	ui(new Ui::RibbonAnalysis)
{
	ui->setupUi(this);

	addRibbonButton(ui->Descriptives);
	addRibbonButton(ui->ttestButton);
	addRibbonButton(ui->anovaButton);
	addRibbonButton(ui->frequenciesButton);
	addRibbonButton(ui->regressionButton);
	addRibbonButton(ui->BFFromT);
	addRibbonButton(ui->factoranalysisButton);

	ui->BFFromT->setDataSetNotNeeded();

//	connect(ui->Descriptives, SIGNAL(clicked()), this, SLOT(itemSelected()));

	QMenu *menu;

	menu = new QMenu(this);
	menu->addAction(QString("Descriptive Statistics"), this, SLOT(itemSelected()))->setObjectName("Descriptives");
	menu->addAction(QString("Reliability Analysis"), this, SLOT(itemSelected()))->setObjectName("ReliabilityAnalysis");

	ui->Descriptives->setMenu(menu);

	menu = new QMenu(this);
	menu->addAction(QString("Independent Samples T-Test"), this, SLOT(itemSelected()))->setObjectName("TTestIndependentSamples");
	menu->addAction(QString("Paired Samples T-Test"), this, SLOT(itemSelected()))->setObjectName("TTestPairedSamples");
	menu->addAction(QString("One Sample T-Test"), this, SLOT(itemSelected()))->setObjectName("TTestOneSample");

	menu->addSeparator();

	menu->addAction(QString("Bayesian Independent Samples T-Test"), this, SLOT(itemSelected()))->setObjectName("TTestBayesianIndependentSamples");
	menu->addAction(QString("Bayesian Paired Samples T-Test"), this, SLOT(itemSelected()))->setObjectName("TTestBayesianPairedSamples");
	menu->addAction(QString("Bayesian One Sample T-Test"), this, SLOT(itemSelected()))->setObjectName("TTestBayesianOneSample");

	ui->ttestButton->setMenu(menu);

	menu = new QMenu(this);

	menu->addAction(QString("ANOVA"), this, SLOT(itemSelected()))->setObjectName("Anova");
	menu->addAction(QString("Repeated Measures ANOVA"), this, SLOT(itemSelected()))->setObjectName("AnovaRepeatedMeasures");
	menu->addAction(QString("ANCOVA"), this, SLOT(itemSelected()))->setObjectName("Ancova");

	menu->addSeparator();

	menu->addAction(QString("Bayesian ANOVA"), this, SLOT(itemSelected()))->setObjectName("AnovaBayesian");
	menu->addAction(QString("Bayesian Repeated Measures ANOVA"), this, SLOT(itemSelected()))->setObjectName("AnovaRepeatedMeasuresBayesian");
	menu->addAction(QString("Bayesian ANCOVA"), this, SLOT(itemSelected()))->setObjectName("AncovaBayesian");

	ui->anovaButton->setMenu(menu);

	menu = new QMenu(this);

	menu->addAction(QString("Correlation Matrix"), this, SLOT(itemSelected()))->setObjectName("Correlation");
	menu->addAction(QString("Linear Regression"), this, SLOT(itemSelected()))->setObjectName("RegressionLinear");
	menu->addAction(QString("Logistic Regression"), this, SLOT(itemSelected()))->setObjectName("RegressionLogistic");

	menu->addSeparator();

	menu->addAction(QString("Bayesian Correlation Matrix"), this, SLOT(itemSelected()))->setObjectName("CorrelationBayesian");
	menu->addAction(QString("Bayesian Correlation Pairs"), this, SLOT(itemSelected()))->setObjectName("CorrelationBayesianPairs");
	menu->addAction(QString("Bayesian Linear Regression"), this, SLOT(itemSelected()))->setObjectName("RegressionLinearBayesian");

#ifdef QT_DEBUG
	menu->addSeparator();
	menu->addAction(QString("BAS Regression Linear link"), this, SLOT(itemSelected()))->setObjectName("BASRegressionLinearLink");
#endif
	ui->regressionButton->setMenu(menu);

	menu = new QMenu(this);

	menu->addAction(QString("Binomial Test"), this, SLOT(itemSelected()))->setObjectName("BinomialTest");
#ifdef QT_DEBUG
	menu->addAction(QString("Multinomial Test"), this, SLOT(itemSelected()))->setObjectName("MultinomialTest");
#endif
	menu->addAction(QString("Contingency Tables"), this, SLOT(itemSelected()))->setObjectName("ContingencyTables");
    menu->addAction(QString("Log-Linear Regression"), this, SLOT(itemSelected()))->setObjectName("RegressionLogLinear");

	menu->addSeparator();
	menu->addAction(QString("Bayesian Binomial Test"), this, SLOT(itemSelected()))->setObjectName("BinomialTestBayesian");
	menu->addAction(QString("Bayesian Contingency Tables"), this, SLOT(itemSelected()))->setObjectName("ContingencyTablesBayesian");
    menu->addAction(QString("Bayesian Log-Linear Regression"), this, SLOT(itemSelected()))->setObjectName("RegressionLogLinearBayesian");

	ui->frequenciesButton->setMenu(menu);

	menu = new QMenu(this);
	menu->addAction(QString("Principal Component Analysis"), this, SLOT(itemSelected()))->setObjectName("PrincipalComponentAnalysis");
	menu->addAction(QString("Exploratory Factor Analysis"), this, SLOT(itemSelected()))->setObjectName("ExploratoryFactorAnalysis");

	ui->factoranalysisButton->setMenu(menu);

#ifndef QT_DEBUG
	ui->BFFromT->hide();
#else
	menu = new QMenu(this);
	menu->addAction(QString("BF From t"), this, SLOT(itemSelected()))->setObjectName("BFFromT");

	ui->BFFromT->setMenu(menu);
#endif
}

RibbonAnalysis::~RibbonAnalysis()
{
	delete ui;
}
<|endoftext|>