<commit_before>#ifndef __QUEUE_HPP_INCLUDED__
#define __QUEUE_HPP_INCLUDED__

#include <cstdint>
#include <fstream>
#include <mutex>

#include <boost/algorithm/string.hpp>
#include <boost/filesystem.hpp>

#include "serialization.hpp"

namespace fs = boost::filesystem;

template <typename T>
class BaseQueue
{
private:

    virtual T getElementAt(int64_t index) = 0;

    virtual int64_t getElementSizeAt(int64_t index) = 0;

    virtual int64_t getFirstElementIndex() = 0;

    virtual int64_t getLastElementIndex() = 0;

    class Iterator
    {
    public:

        Iterator(BaseQueue<T> *queue_, int64_t index_)
            : queue(queue_), index(index_)
        {
        }

        T operator*()
        {
            return queue->getElementAt(index);
        }

        Iterator& operator++()
        {
            int64_t size = queue->getElementSizeAt(index);
            index += size;
            return *this;
        }

        bool operator!=(const Iterator& iterator)
        {
            return index != iterator.index;
        }

    private:

        BaseQueue<T> *queue;

        int64_t index;
    };

public:

    virtual void Enqueue(T e) = 0;

    virtual void Dequeue() = 0;

    virtual T Last() = 0;

    Iterator begin()
    {
        return Iterator(this, getFirstElementIndex());
    }

    Iterator end()
    {
        return Iterator(this, getLastElementIndex());
    }
};

template <typename T>
class VolatileQueue : public BaseQueue<T>
{
public:

    void Enqueue(T e)
    {
        data.push_back(e);
    }

    void Dequeue()
    {
        if (!data.empty())
        {
            data.erase(data.begin());
        }
    }

    T Last()
    {
        T empty;
        return data.size() > 0 ? data[data.size() - 1 ] : empty;
    }

private:

    T getElementAt(int64_t index)
    {
        return data[index];
    }

    int64_t getElementSizeAt(int64_t index)
    {
        return 1;
    }

    int64_t getFirstElementIndex()
    {
        return 0;
    }

    int64_t getLastElementIndex()
    {
        return data.size();
    }

    std::vector<T> data;
};

template <typename T>
class PersistentQueue : public BaseQueue<T>
{
public:

    PersistentQueue(std::string filename)
        : PersistentQueue(".", filename)
    {
    }

    PersistentQueue(std::string dirname, std::string filename)
        : file((fs::path(dirname) / fs::path(filename)).string(),
               std::ios::out | std::ios::in | std::ios::app | std::ios::binary),
          stream(file),
          insert_file((fs::path(dirname) / fs::path(filename)).string(),
                       std::ios::in | std::ios::out | std::ios::binary),
          insert_stream(insert_file),
          start_position(0),
          end_position(0),
          mutex()
    {
        SaveOffsets();
        LoadOffsets();
    }

    PersistentQueue(std::iostream& stream)
        : stream(stream),
          insert_stream(stream),
          start_position(0),
          end_position(0),
          mutex()
    {
        SaveOffsets();
        LoadOffsets();
    }

    ~PersistentQueue()
    {
        stream.flush();
    }

    void SaveOffsets()
    {
        stream.seekg(0, std::ios::end);
        if (stream.tellg() < HEADER_SIZE)
        {
            start_position = HEADER_SIZE;
            end_position = UNINITIALIZED;
        }

        //insert_stream.seekp(0, std::ios::beg);
        insert_stream << std::setw(INDEX_SIZE) << start_position;
        insert_stream << std::setw(INDEX_SIZE) << end_position;
        insert_stream.flush();
    }

    void LoadOffsets()
    {
        stream.seekg(0, std::ios::beg);

        std::string buffer;
        stream.read(&buffer[0], INDEX_SIZE);
        boost::trim(buffer);
        start_position = std::stoi(buffer);

        stream.read(&buffer[0], INDEX_SIZE);
        boost::trim(buffer);
        end_position = std::stoi(buffer);
    }

    void Enqueue(T e)
    {
        std::lock_guard<std::recursive_mutex> lock(mutex);

        std::string element_as_string = Serialize<T>(e);

        LoadOffsets();

        stream.seekg(0, std::ios::end);
        end_position = stream.tellg();

        insert_stream.seekp(INDEX_SIZE, std::ios::beg);
        insert_stream << std::setw(INDEX_SIZE) << end_position;
        insert_stream.flush();

        stream.seekp(0, std::ios::end);
        stream << element_as_string;
        stream.flush();
    }

    void Dequeue()
    {
        std::lock_guard<std::recursive_mutex> lock(mutex);

        LoadOffsets();

        for (T element : *this)
        {
            start_position += Serialize<T>(element).length();
            stream.seekp(0, std::ios::beg);
            stream << std::setw(INDEX_SIZE) << start_position;
            break;
        }
    }

    T Last()
    {
        std::lock_guard<std::recursive_mutex> lock(mutex);

        T empty;
        stream.seekg(0, std::ios::end);
        if (stream.tellg() <= HEADER_SIZE)
        {
            return empty;
        }

        LoadOffsets();

        stream.seekg(end_position, std::ios::beg);

        return Deserialize<T>(stream);
    }

private:

    T getElementAt(int64_t index)
    {
        std::lock_guard<std::recursive_mutex> lock(mutex);

        stream.seekg(index, std::ios::beg);
        return Deserialize<T>(stream);
    }

    int64_t getElementSizeAt(int64_t index)
    {
        std::lock_guard<std::recursive_mutex> lock(mutex);

        stream.seekg(index, std::ios::beg);
        return Serialize<T>(Deserialize<T>(stream)).length();
    }

    int64_t getFirstElementIndex()
    {
        std::lock_guard<std::recursive_mutex> lock(mutex);

        LoadOffsets();

        return start_position;
    }

    int64_t getLastElementIndex()
    {
        std::lock_guard<std::recursive_mutex> lock(mutex);

        stream.seekg(0, std::ios::end);
        return stream.tellg();
    }

    std::fstream file;

    std::iostream& stream;

    std::fstream insert_file;

    std::iostream& insert_stream;

    std::streampos start_position;

    std::streampos end_position;

    std::recursive_mutex mutex;

    constexpr static const int64_t INDEX_SIZE = 10;

    constexpr static const int64_t HEADER_SIZE = INDEX_SIZE * 2;

    constexpr static const int64_t UNINITIALIZED = -1;
};

template <typename T>
class RolloverQueue
{
private:

    std::streampos get_start_position()
    {
        stream.seekg(0 * INDEX_SIZE, std::ios::beg);
        std::string buffer;
        stream.read(&buffer[0], INDEX_SIZE);
        boost::trim(buffer);
        return static_cast<std::streampos>(std::stoi(buffer));
    }

    std::streampos get_end_position()
    {
        if (file.is_open())
        {
            stream.rdbuf(file.rdbuf());
        }
        stream.seekg(1 * INDEX_SIZE, std::ios::beg);
        std::string buffer(INDEX_SIZE, '\0');
        stream.read(&buffer[0], INDEX_SIZE);
        boost::trim(buffer);
        return static_cast<std::streampos>(std::stoi(buffer));
    }

    std::streampos get_eof_position()
    {
        stream.seekg(0, std::ios::end);
        return stream.tellg();
    }

    std::fstream file;

    std::iostream& stream;

    std::streampos rollover_size;

    constexpr static const int64_t INDEX_SIZE = 10;

    constexpr static const int64_t UNINITIALIZED = 0;

    constexpr static const int64_t HEADER_SIZE = INDEX_SIZE * 2;

    constexpr static const int64_t DEFAULT_ROLLOVER_SIZE = 1000000000;

    class Iterator
    {
    public:

        Iterator(
            std::iostream& stream,
            std::streampos position,
            std::streampos rollover
        )
            : stream(stream),
              position(position),
              rollover(rollover)
        {
        }

        T operator*()
        {
            stream.seekg(position, std::ios::beg);

            return Deserialize<T>(stream);
        }

        Iterator& operator++()
        {
            if (position <= rollover)
            {
                stream.seekg(position, std::ios::beg);
                position += Serialize<T>(Deserialize<T>(stream)).length();
            }
            else
            {
                position = HEADER_SIZE;
            }

            return *this;
        }

        bool operator!=(const Iterator& iterator)
        {
            return position != iterator.position;
        }

    private:

        std::iostream& stream;

        std::streampos position;

        std::streampos rollover;

        constexpr static const int64_t INDEX_SIZE = 10;

        constexpr static const int64_t HEADER_SIZE = INDEX_SIZE * 3;
    };

public:

    RolloverQueue(std::string filename)
        : RolloverQueue(".", filename)
    {
    }

    RolloverQueue(
        std::string dirname,
        std::string filename,
        std::streampos rollover_size=DEFAULT_ROLLOVER_SIZE
    ) : file((boost::filesystem::path(dirname) /
              boost::filesystem::path(filename)).string(),
               std::ios::out | std::ios::in | std::ios::binary),
        stream(file),
        rollover_size(rollover_size)
    {
        auto path = (boost::filesystem::path(dirname) /
                     boost::filesystem::path(filename)).string();
        if (!boost::filesystem::exists(path))
        {
            file.open(path, std::ios::out | std::ios::app | std::ios::binary);
            file << std::setw(INDEX_SIZE) << HEADER_SIZE;
            file << std::setw(INDEX_SIZE) << UNINITIALIZED;
            file.flush();
            file.close();
            file.open(path, std::ios::out | std::ios::in | std::ios::binary);
        }
    }

    RolloverQueue(
        std::iostream& stream,
        std::streampos rollover_size=DEFAULT_ROLLOVER_SIZE
    ) : stream(stream),
        rollover_size(rollover_size)
    {
        stream.seekg(0, std::ios::end);
        if (stream.tellg() < HEADER_SIZE)
        {
            stream << std::setw(INDEX_SIZE) << HEADER_SIZE;
            stream << std::setw(INDEX_SIZE) << UNINITIALIZED;
        }
    }

    void Enqueue(T e)
    {
        std::string element_as_string = Serialize<T>(e);
        auto size = element_as_string.length();

        std::streampos position = get_end_position();
        if (position == UNINITIALIZED)
        {
            position = HEADER_SIZE;
        }
        else
        {
            stream.seekg(position, std::ios::beg);
            position += Serialize<T>(Deserialize<T>(stream)).length();
        }

        if (rollover_size < position + static_cast<std::streampos>(size))
        {
            std::streampos eof = get_eof_position();

            // rollover and over-write existing entries
            auto start = static_cast<std::streampos>(HEADER_SIZE);
            while (start - HEADER_SIZE < size && start != eof)
            {
                stream.seekg(start, std::ios::beg);
                start += Serialize<T>(Deserialize<T>(stream)).length();
            }

            if (start == eof)
            {
                start = HEADER_SIZE;
            }

            // update start position
            stream.seekp(0 * INDEX_SIZE, std::ios::beg);
            stream << std::setw(INDEX_SIZE) << start;
            stream.flush();
            position = start;
        }

        // flush element
        stream.seekp(position, std::ios::beg);
        stream << element_as_string;
        stream.flush();

        // update end position
        stream.seekp(1 * INDEX_SIZE, std::ios::beg);
        stream << std::setw(INDEX_SIZE) << position;
        stream.flush();
    }

    void Dequeue()
    {
        auto position = get_start_position();
        stream.seekg(position, std::ios::beg);

        auto next = position + static_cast<std::streampos>(
            Serialize<T>(Deserialize<T>(stream)).length());

        stream.seekp(0 * INDEX_SIZE, std::ios::beg);
        stream << std::setw(INDEX_SIZE) << next;
    }

    T Last()
    {
        auto position = get_end_position();

        stream.seekg(position, std::ios::beg);
        return Deserialize<T>(stream);
    }

    Iterator begin()
    {
        return Iterator(stream, get_start_position(), rollover_size);
    }

    Iterator end()
    {
        auto start = get_start_position();
        auto end = get_end_position();
        auto eof = get_eof_position();
        if (end == UNINITIALIZED || end == eof)
        {
            end = start;
        }
        else
        {
            stream.seekg(end, std::ios::beg);
            end += Serialize<T>(Deserialize<T>(stream)).length();
        }
        return Iterator(stream, end, rollover_size);
    }
};

#endif
<commit_msg>Update default ledger size to 4GB<commit_after>#ifndef __QUEUE_HPP_INCLUDED__
#define __QUEUE_HPP_INCLUDED__

#include <cstdint>
#include <fstream>
#include <mutex>

#include <boost/algorithm/string.hpp>
#include <boost/filesystem.hpp>

#include "serialization.hpp"

namespace fs = boost::filesystem;

template <typename T>
class BaseQueue
{
private:

    virtual T getElementAt(int64_t index) = 0;

    virtual int64_t getElementSizeAt(int64_t index) = 0;

    virtual int64_t getFirstElementIndex() = 0;

    virtual int64_t getLastElementIndex() = 0;

    class Iterator
    {
    public:

        Iterator(BaseQueue<T> *queue_, int64_t index_)
            : queue(queue_), index(index_)
        {
        }

        T operator*()
        {
            return queue->getElementAt(index);
        }

        Iterator& operator++()
        {
            int64_t size = queue->getElementSizeAt(index);
            index += size;
            return *this;
        }

        bool operator!=(const Iterator& iterator)
        {
            return index != iterator.index;
        }

    private:

        BaseQueue<T> *queue;

        int64_t index;
    };

public:

    virtual void Enqueue(T e) = 0;

    virtual void Dequeue() = 0;

    virtual T Last() = 0;

    Iterator begin()
    {
        return Iterator(this, getFirstElementIndex());
    }

    Iterator end()
    {
        return Iterator(this, getLastElementIndex());
    }
};

template <typename T>
class VolatileQueue : public BaseQueue<T>
{
public:

    void Enqueue(T e)
    {
        data.push_back(e);
    }

    void Dequeue()
    {
        if (!data.empty())
        {
            data.erase(data.begin());
        }
    }

    T Last()
    {
        T empty;
        return data.size() > 0 ? data[data.size() - 1 ] : empty;
    }

private:

    T getElementAt(int64_t index)
    {
        return data[index];
    }

    int64_t getElementSizeAt(int64_t index)
    {
        return 1;
    }

    int64_t getFirstElementIndex()
    {
        return 0;
    }

    int64_t getLastElementIndex()
    {
        return data.size();
    }

    std::vector<T> data;
};

template <typename T>
class PersistentQueue : public BaseQueue<T>
{
public:

    PersistentQueue(std::string filename)
        : PersistentQueue(".", filename)
    {
    }

    PersistentQueue(std::string dirname, std::string filename)
        : file((fs::path(dirname) / fs::path(filename)).string(),
               std::ios::out | std::ios::in | std::ios::app | std::ios::binary),
          stream(file),
          insert_file((fs::path(dirname) / fs::path(filename)).string(),
                       std::ios::in | std::ios::out | std::ios::binary),
          insert_stream(insert_file),
          start_position(0),
          end_position(0),
          mutex()
    {
        SaveOffsets();
        LoadOffsets();
    }

    PersistentQueue(std::iostream& stream)
        : stream(stream),
          insert_stream(stream),
          start_position(0),
          end_position(0),
          mutex()
    {
        SaveOffsets();
        LoadOffsets();
    }

    ~PersistentQueue()
    {
        stream.flush();
    }

    void SaveOffsets()
    {
        stream.seekg(0, std::ios::end);
        if (stream.tellg() < HEADER_SIZE)
        {
            start_position = HEADER_SIZE;
            end_position = UNINITIALIZED;
        }

        //insert_stream.seekp(0, std::ios::beg);
        insert_stream << std::setw(INDEX_SIZE) << start_position;
        insert_stream << std::setw(INDEX_SIZE) << end_position;
        insert_stream.flush();
    }

    void LoadOffsets()
    {
        stream.seekg(0, std::ios::beg);

        std::string buffer;
        stream.read(&buffer[0], INDEX_SIZE);
        boost::trim(buffer);
        start_position = std::stoi(buffer);

        stream.read(&buffer[0], INDEX_SIZE);
        boost::trim(buffer);
        end_position = std::stoi(buffer);
    }

    void Enqueue(T e)
    {
        std::lock_guard<std::recursive_mutex> lock(mutex);

        std::string element_as_string = Serialize<T>(e);

        LoadOffsets();

        stream.seekg(0, std::ios::end);
        end_position = stream.tellg();

        insert_stream.seekp(INDEX_SIZE, std::ios::beg);
        insert_stream << std::setw(INDEX_SIZE) << end_position;
        insert_stream.flush();

        stream.seekp(0, std::ios::end);
        stream << element_as_string;
        stream.flush();
    }

    void Dequeue()
    {
        std::lock_guard<std::recursive_mutex> lock(mutex);

        LoadOffsets();

        for (T element : *this)
        {
            start_position += Serialize<T>(element).length();
            stream.seekp(0, std::ios::beg);
            stream << std::setw(INDEX_SIZE) << start_position;
            break;
        }
    }

    T Last()
    {
        std::lock_guard<std::recursive_mutex> lock(mutex);

        T empty;
        stream.seekg(0, std::ios::end);
        if (stream.tellg() <= HEADER_SIZE)
        {
            return empty;
        }

        LoadOffsets();

        stream.seekg(end_position, std::ios::beg);

        return Deserialize<T>(stream);
    }

private:

    T getElementAt(int64_t index)
    {
        std::lock_guard<std::recursive_mutex> lock(mutex);

        stream.seekg(index, std::ios::beg);
        return Deserialize<T>(stream);
    }

    int64_t getElementSizeAt(int64_t index)
    {
        std::lock_guard<std::recursive_mutex> lock(mutex);

        stream.seekg(index, std::ios::beg);
        return Serialize<T>(Deserialize<T>(stream)).length();
    }

    int64_t getFirstElementIndex()
    {
        std::lock_guard<std::recursive_mutex> lock(mutex);

        LoadOffsets();

        return start_position;
    }

    int64_t getLastElementIndex()
    {
        std::lock_guard<std::recursive_mutex> lock(mutex);

        stream.seekg(0, std::ios::end);
        return stream.tellg();
    }

    std::fstream file;

    std::iostream& stream;

    std::fstream insert_file;

    std::iostream& insert_stream;

    std::streampos start_position;

    std::streampos end_position;

    std::recursive_mutex mutex;

    constexpr static const int64_t INDEX_SIZE = 10;

    constexpr static const int64_t HEADER_SIZE = INDEX_SIZE * 2;

    constexpr static const int64_t UNINITIALIZED = -1;
};

template <typename T>
class RolloverQueue
{
private:

    std::streampos get_start_position()
    {
        stream.seekg(0 * INDEX_SIZE, std::ios::beg);
        std::string buffer;
        stream.read(&buffer[0], INDEX_SIZE);
        boost::trim(buffer);
        return static_cast<std::streampos>(std::stoi(buffer));
    }

    std::streampos get_end_position()
    {
        if (file.is_open())
        {
            stream.rdbuf(file.rdbuf());
        }
        stream.seekg(1 * INDEX_SIZE, std::ios::beg);
        std::string buffer(INDEX_SIZE, '\0');
        stream.read(&buffer[0], INDEX_SIZE);
        boost::trim(buffer);
        return static_cast<std::streampos>(std::stoi(buffer));
    }

    std::streampos get_eof_position()
    {
        stream.seekg(0, std::ios::end);
        return stream.tellg();
    }

    std::fstream file;

    std::iostream& stream;

    std::streampos rollover_size;

    constexpr static const int64_t INDEX_SIZE = 10;

    constexpr static const int64_t UNINITIALIZED = 0;

    constexpr static const int64_t HEADER_SIZE = INDEX_SIZE * 2;

    constexpr static const int64_t DEFAULT_ROLLOVER_SIZE = 0x400000000;

    class Iterator
    {
    public:

        Iterator(
            std::iostream& stream,
            std::streampos position,
            std::streampos rollover
        )
            : stream(stream),
              position(position),
              rollover(rollover)
        {
        }

        T operator*()
        {
            stream.seekg(position, std::ios::beg);

            return Deserialize<T>(stream);
        }

        Iterator& operator++()
        {
            if (position <= rollover)
            {
                stream.seekg(position, std::ios::beg);
                position += Serialize<T>(Deserialize<T>(stream)).length();
            }
            else
            {
                position = HEADER_SIZE;
            }

            return *this;
        }

        bool operator!=(const Iterator& iterator)
        {
            return position != iterator.position;
        }

    private:

        std::iostream& stream;

        std::streampos position;

        std::streampos rollover;

        constexpr static const int64_t INDEX_SIZE = 10;

        constexpr static const int64_t HEADER_SIZE = INDEX_SIZE * 3;
    };

public:

    RolloverQueue(std::string filename)
        : RolloverQueue(".", filename)
    {
    }

    RolloverQueue(
        std::string dirname,
        std::string filename,
        std::streampos rollover_size=DEFAULT_ROLLOVER_SIZE
    ) : file((boost::filesystem::path(dirname) /
              boost::filesystem::path(filename)).string(),
               std::ios::out | std::ios::in | std::ios::binary),
        stream(file),
        rollover_size(rollover_size)
    {
        auto path = (boost::filesystem::path(dirname) /
                     boost::filesystem::path(filename)).string();
        if (!boost::filesystem::exists(path))
        {
            file.open(path, std::ios::out | std::ios::app | std::ios::binary);
            file << std::setw(INDEX_SIZE) << HEADER_SIZE;
            file << std::setw(INDEX_SIZE) << UNINITIALIZED;
            file.flush();
            file.close();
            file.open(path, std::ios::out | std::ios::in | std::ios::binary);
        }
    }

    RolloverQueue(
        std::iostream& stream,
        std::streampos rollover_size=DEFAULT_ROLLOVER_SIZE
    ) : stream(stream),
        rollover_size(rollover_size)
    {
        stream.seekg(0, std::ios::end);
        if (stream.tellg() < HEADER_SIZE)
        {
            stream << std::setw(INDEX_SIZE) << HEADER_SIZE;
            stream << std::setw(INDEX_SIZE) << UNINITIALIZED;
        }
    }

    void Enqueue(T e)
    {
        std::string element_as_string = Serialize<T>(e);
        auto size = element_as_string.length();

        std::streampos position = get_end_position();
        if (position == UNINITIALIZED)
        {
            position = HEADER_SIZE;
        }
        else
        {
            stream.seekg(position, std::ios::beg);
            position += Serialize<T>(Deserialize<T>(stream)).length();
        }

        if (rollover_size < position + static_cast<std::streampos>(size))
        {
            std::streampos eof = get_eof_position();

            // rollover and over-write existing entries
            auto start = static_cast<std::streampos>(HEADER_SIZE);
            while (start - HEADER_SIZE < size && start != eof)
            {
                stream.seekg(start, std::ios::beg);
                start += Serialize<T>(Deserialize<T>(stream)).length();
            }

            if (start == eof)
            {
                start = HEADER_SIZE;
            }

            // update start position
            stream.seekp(0 * INDEX_SIZE, std::ios::beg);
            stream << std::setw(INDEX_SIZE) << start;
            stream.flush();
            position = start;
        }

        // flush element
        stream.seekp(position, std::ios::beg);
        stream << element_as_string;
        stream.flush();

        // update end position
        stream.seekp(1 * INDEX_SIZE, std::ios::beg);
        stream << std::setw(INDEX_SIZE) << position;
        stream.flush();
    }

    void Dequeue()
    {
        auto position = get_start_position();
        stream.seekg(position, std::ios::beg);

        auto next = position + static_cast<std::streampos>(
            Serialize<T>(Deserialize<T>(stream)).length());

        stream.seekp(0 * INDEX_SIZE, std::ios::beg);
        stream << std::setw(INDEX_SIZE) << next;
    }

    T Last()
    {
        auto position = get_end_position();

        stream.seekg(position, std::ios::beg);
        return Deserialize<T>(stream);
    }

    Iterator begin()
    {
        return Iterator(stream, get_start_position(), rollover_size);
    }

    Iterator end()
    {
        auto start = get_start_position();
        auto end = get_end_position();
        auto eof = get_eof_position();
        if (end == UNINITIALIZED || end == eof)
        {
            end = start;
        }
        else
        {
            stream.seekg(end, std::ios::beg);
            end += Serialize<T>(Deserialize<T>(stream)).length();
        }
        return Iterator(stream, end, rollover_size);
    }
};

#endif
<|endoftext|>


<commit_before>#ifndef SIMPLE_XDMF_HPP_INCLUDED
#define SIMPLE_XDMF_HPP_INCLUDED

#include <string>

class SimpleXdmf {
    private:
        const std::string header = R"(<?xml version="1.0" ?>
<!DOCTYPE Xdmf SYSTEM "Xdmf.dtd" []>)";
        std::string version;
        std::string content;

    public:
        SimpleXdmf(const std::string& _version = "3.0") {
            version = _version;

            content = header;
        }

        enum class DataItemType {Uniform};
        enum class TopologyType {twoDRectMesh};
        enum class GeometryType {Uniform};
        enum class AttributeType {Scalar, Vector};
        enum class AttributeCenter {Node};

        static void addDomain();

        void beginTopology(TopologyType type) {
            content += "<Topology TopologyType=\"2DRectMesh\">";
        }
        void endTopology() {
            content += "</Topology>";
        }

        void beginGeometory(GeometryType type){
            content += "<Geometry GeometryType=\"2DRectMesh\">";
        }
        void endGeometory(){
            content += "</Geometry>";
        }

        void beginDataItem(DataItemType type) {
            content += "<DataItem ItemType=\"Uniform\">";
        }
        void endDataItem() {
            content += "</DataItem>";
        }
};

#endif<commit_msg>NewLineCode and Indentation Management.<commit_after>#ifndef SIMPLE_XDMF_HPP_INCLUDED
#define SIMPLE_XDMF_HPP_INCLUDED

#include <string>
#include <fstream>

class SimpleXdmf {
    private:
        const std::string header = R"(
<?xml version="1.0" ?>
<!DOCTYPE Xdmf SYSTEM "Xdmf.dtd" []>
)";
        std::string content;
        std::string version;
        std::string newLine;
        std::string indent;

        unsigned int currentIndentation = 0;
        bool endEdit = false;

        void addIndent() {
            ++currentIndentation;
        }

        void backIndent() {
            if (currentIndentation > 0) --currentIndentation;
        }

        void insertIndent() {
            for(unsigned int i = 0; i < currentIndentation; ++i) {
                content += indent;
            }
        }

        void beginElement() {
            addIndent();
            insertIndent();
        }

        void endElement() {
            backIndent();
        }

    public:
        SimpleXdmf(const std::string& _version = "3.0") {
            version = _version;
            setNewLineCode();
            setIndent();
            beginXdmf();
        }

        void setIndent(const int size = 4) {
            if (size == 0) {
                indent = '\t';
                return;
            }

            for (int i = 0; i < size; ++i) {
                indent += ' ';
            }
        }

        void setNewLineCode() {
            const char CR = '\r';
            const char LF = '\n';
            const char* CRLF = "\r\n";

            newLine = LF;
        }

        void generate(const std::string file_name) {
            if(!endEdit) endXdmf();

            std::ofstream ofs(file_name, std::ios::out);
            ofs << content << std::endl;
        }

        void beginXdmf() {
            endEdit = false;
            content = header + "<Xdmf Version=\"" + version + "\">" + newLine;
        }

        void endXdmf() {
            content += "</Xdmf>";
            endEdit = true;
        }

        enum class DataItemType {Uniform};
        enum class TopologyType {twoDRectMesh};
        enum class GeometryType {Uniform};
        enum class AttributeType {Scalar, Vector};
        enum class AttributeCenter {Node};

        void beginDomain() {
            beginElement();
            content += "<Domain>" + newLine;
        };

        void endDomain() {
            insertIndent();
            content += "</Domain>" + newLine;
            endElement();
        };

        void beginTopology(TopologyType type = TopologyType::twoDRectMesh) {
            beginElement();
            content += "<Topology TopologyType=\"2DRectMesh\">" + newLine;
        }
        void endTopology() {
            insertIndent();
            content += "</Topology>" + newLine;
            endElement();
        }

        void beginGeometory(GeometryType type = GeometryType::Uniform){
            beginElement();
            content += "<Geometry GeometryType=\"2DRectMesh\">" + newLine;
        }
        void endGeometory(){
            insertIndent();
            content += "</Geometry>" + newLine;
            endElement();
        }

        void beginDataItem(DataItemType type = DataItemType::Uniform) {
            beginElement();
            content += "<DataItem ItemType=\"Uniform\">" + newLine;
        }
        void endDataItem() {
            insertIndent();
            content += "</DataItem>" + newLine;
            endElement();
        }
};

#endif<|endoftext|>


<commit_before>#include "angort.h"
#include "cycle.h"

namespace angort {

Type *Type::head=NULL;
static bool createTypesDone=false;

int  GarbageCollected::globalCount=0;

//#define tdprintf printf
#define tdprintf if(0)printf

const char *Type::toString(bool *allocated,const Value *v) const{
    char buf[128];
    snprintf(buf,128,"<TYPE %s:%p>",name,v->v.s);
    *allocated=true;
    return strdup(buf);
}

float Type::toFloat(const Value *v) const{
    throw BadConversionException(v->t->name,Types::tFloat->name);
}

int Type::toInt(const Value *v) const {
    throw BadConversionException(v->t->name,Types::tInteger->name);
}

void Type::createIterator(Value *dest,Value *src){
    Iterator<Value *> *i = makeIterator(src);
    i->first();
    Types::tIter->set(dest,src,i);
}

void Type::clone(Value *out,const Value *in,bool deep){
    // default action is to just copy the value; collections
    // need to do more.
    out->copy(in);
}

void Type::add(const char *_name,const char *_id){
    if(getByName(_name))
        throw Exception().set("type already exists: %s",name);

    const unsigned char *n = (const unsigned char *)_id;
    id = n[0]+(n[1]<<8)+(n[2]<<16)+(n[3]<<24);
    name = _name;
    next = head;
    head = this;

    // normally symbols are generated after the static initialisation
    // but before anything else, in createTypes(). This is to make sure
    // the symbol system has been initialised.
    // If this type is being added later, say by a plugin, we need to
    // do it here.

    if(createTypesDone){
        nameSymb = SymbolType::getSymbol(name);
    }
}

Type *Type::getByID(const char *_id){
    const unsigned char *n = (const unsigned char *)_id;
    uint32_t i = n[0]+(n[1]<<8)+(n[2]<<16)+(n[3]<<24);

    for(Type *t = head;t;t=t->next)
        if(t->id == i)return t;
    return NULL;
}

char *BlockAllocType::allocate(Value *v,int len,Type *type){
    v->clr();
    BlockAllocHeader *h = (BlockAllocHeader *)malloc(len+sizeof(BlockAllocHeader));
    h->refct=1;
    v->v.block = h;
    v->t = type;
    return (char *)(h+1);
}

bool Type::isIn(Value *v,Value *item){
    Iterator<Value *> *iter = makeIterator(v);

    for(iter->first();!iter->isDone();iter->next()){
        if(iter->current()->equalForHashTable(item)){
            return true;
        }
    }
    return false;
}

const char *BlockAllocType::getData(const Value *v) const{
    return (const char *)(v->v.block+1);
}

void BlockAllocType::incRef(Value *v){
    BlockAllocHeader *h = v->v.block;
    h->refct++;
    if(!h->refct)
        throw RUNT("reference count too large");
}

void BlockAllocType::decRef(Value *v){
    BlockAllocHeader *h = v->v.block;
    h->refct--;
    if(h->refct==0){
        free(h);
    }
}

void GCType::incRef(Value *v){
    v->v.gc->incRefCt();
    tdprintf("incrementing ref count of %s:%p, now %d\n",name,v->v.gc,v->v.gc->refct);
}

void GCType::decRef(Value *v){
    bool b = v->v.gc->decRefCt();
    tdprintf("decrementing ref count of %s:%p, now %d\n",name,v->v.gc,v->v.gc->refct);
    if(b){
        tdprintf("  AND DELETING %s:%p\n",name,v->v.gc);
        delete v->v.gc;
    }
}

Iterator<class Value *> *GCType::makeKeyIterator(Value *v){
    return v->v.gc->makeKeyIterator();
}
Iterator<class Value *> *GCType::makeValueIterator(Value *v){
    return v->v.gc->makeValueIterator();
}

GarbageCollected *GCType::getGC(Value *v){
    return v->v.gc;
}

GarbageCollected::GarbageCollected(){
    refct=0;
    globalCount++;
    CycleDetector::getInstance()->add(this);
}

GarbageCollected::~GarbageCollected(){
    globalCount--;
    CycleDetector::getInstance()->remove(this);
}

/*
 *
 * New types go down here
 *
 */

static NoneType _tNone;
NoneType *Types::tNone= &_tNone;

static Type _tDeleted; // has to be added by hand in createTypes
Type *Types::tDeleted= &_tDeleted;

static IntegerType _Int;
IntegerType *Types::tInteger = &_Int;

static FloatType _Float;
FloatType *Types::tFloat = &_Float;

static StringType _String;
StringType *Types::tString = &_String;

static CodeType _Code;
CodeType *Types::tCode = &_Code;

static ClosureType _Closure;
ClosureType *Types::tClosure = &_Closure;

static RangeType<int> _IRange;
RangeType<int> *Types::tIRange = &_IRange;
static RangeType<float> _FRange;
RangeType<float> *Types::tFRange = &_FRange;

static ListType _List;
ListType *Types::tList = &_List;

static HashType _Hash;
HashType *Types::tHash = &_Hash;

static SymbolType _Symbol;
SymbolType *Types::tSymbol = &_Symbol;

static NativeType _Native;
NativeType *Types::tNative = &_Native;

static PropType _Prop;
PropType *Types::tProp = &_Prop;

static IteratorType _Iterator;
IteratorType *Types::tIter = &_Iterator;

void Types::createTypes(){
    tDeleted->add("DELETED","DELE");

    // because of the undefined execution order of static heap
    // objects, we set up all the type names here rather than in
    // "add" to make sure the symbol system is already up.

    // IF you add types later in plugins, the system should detect
    // this.

    for(Type *p = Type::head;p;p=p->next){
        p->nameSymb = SymbolType::getSymbol(p->name);
    }
    createTypesDone = true;

}
}
<commit_msg>Wasn't deleting the iterator for isIn()!<commit_after>#include "angort.h"
#include "cycle.h"

namespace angort {

Type *Type::head=NULL;
static bool createTypesDone=false;

int  GarbageCollected::globalCount=0;

//#define tdprintf printf
#define tdprintf if(0)printf

const char *Type::toString(bool *allocated,const Value *v) const{
    char buf[128];
    snprintf(buf,128,"<TYPE %s:%p>",name,v->v.s);
    *allocated=true;
    return strdup(buf);
}

float Type::toFloat(const Value *v) const{
    throw BadConversionException(v->t->name,Types::tFloat->name);
}

int Type::toInt(const Value *v) const {
    throw BadConversionException(v->t->name,Types::tInteger->name);
}

void Type::createIterator(Value *dest,Value *src){
    Iterator<Value *> *i = makeIterator(src);
    i->first();
    Types::tIter->set(dest,src,i);
}

void Type::clone(Value *out,const Value *in,bool deep){
    // default action is to just copy the value; collections
    // need to do more.
    out->copy(in);
}

void Type::add(const char *_name,const char *_id){
    if(getByName(_name))
        throw Exception().set("type already exists: %s",name);

    const unsigned char *n = (const unsigned char *)_id;
    id = n[0]+(n[1]<<8)+(n[2]<<16)+(n[3]<<24);
    name = _name;
    next = head;
    head = this;

    // normally symbols are generated after the static initialisation
    // but before anything else, in createTypes(). This is to make sure
    // the symbol system has been initialised.
    // If this type is being added later, say by a plugin, we need to
    // do it here.

    if(createTypesDone){
        nameSymb = SymbolType::getSymbol(name);
    }
}

Type *Type::getByID(const char *_id){
    const unsigned char *n = (const unsigned char *)_id;
    uint32_t i = n[0]+(n[1]<<8)+(n[2]<<16)+(n[3]<<24);

    for(Type *t = head;t;t=t->next)
        if(t->id == i)return t;
    return NULL;
}

char *BlockAllocType::allocate(Value *v,int len,Type *type){
    v->clr();
    BlockAllocHeader *h = (BlockAllocHeader *)malloc(len+sizeof(BlockAllocHeader));
    h->refct=1;
    v->v.block = h;
    v->t = type;
    return (char *)(h+1);
}

bool Type::isIn(Value *v,Value *item){
    Iterator<Value *> *iter = makeIterator(v);

    for(iter->first();!iter->isDone();iter->next()){
        if(iter->current()->equalForHashTable(item)){
            delete iter;
            return true;
        }
    }
    delete iter;
    return false;
}

const char *BlockAllocType::getData(const Value *v) const{
    return (const char *)(v->v.block+1);
}

void BlockAllocType::incRef(Value *v){
    BlockAllocHeader *h = v->v.block;
    h->refct++;
    if(!h->refct)
        throw RUNT("reference count too large");
}

void BlockAllocType::decRef(Value *v){
    BlockAllocHeader *h = v->v.block;
    h->refct--;
    if(h->refct==0){
        free(h);
    }
}

void GCType::incRef(Value *v){
    v->v.gc->incRefCt();
    tdprintf("incrementing ref count of %s:%p, now %d\n",name,v->v.gc,v->v.gc->refct);
}

void GCType::decRef(Value *v){
    bool b = v->v.gc->decRefCt();
    tdprintf("decrementing ref count of %s:%p, now %d\n",name,v->v.gc,v->v.gc->refct);
    if(b){
        tdprintf("  AND DELETING %s:%p\n",name,v->v.gc);
        delete v->v.gc;
    }
}

Iterator<class Value *> *GCType::makeKeyIterator(Value *v){
    return v->v.gc->makeKeyIterator();
}
Iterator<class Value *> *GCType::makeValueIterator(Value *v){
    return v->v.gc->makeValueIterator();
}

GarbageCollected *GCType::getGC(Value *v){
    return v->v.gc;
}

GarbageCollected::GarbageCollected(){
    refct=0;
    globalCount++;
    CycleDetector::getInstance()->add(this);
}

GarbageCollected::~GarbageCollected(){
    globalCount--;
    CycleDetector::getInstance()->remove(this);
}

/*
 *
 * New types go down here
 *
 */

static NoneType _tNone;
NoneType *Types::tNone= &_tNone;

static Type _tDeleted; // has to be added by hand in createTypes
Type *Types::tDeleted= &_tDeleted;

static IntegerType _Int;
IntegerType *Types::tInteger = &_Int;

static FloatType _Float;
FloatType *Types::tFloat = &_Float;

static StringType _String;
StringType *Types::tString = &_String;

static CodeType _Code;
CodeType *Types::tCode = &_Code;

static ClosureType _Closure;
ClosureType *Types::tClosure = &_Closure;

static RangeType<int> _IRange;
RangeType<int> *Types::tIRange = &_IRange;
static RangeType<float> _FRange;
RangeType<float> *Types::tFRange = &_FRange;

static ListType _List;
ListType *Types::tList = &_List;

static HashType _Hash;
HashType *Types::tHash = &_Hash;

static SymbolType _Symbol;
SymbolType *Types::tSymbol = &_Symbol;

static NativeType _Native;
NativeType *Types::tNative = &_Native;

static PropType _Prop;
PropType *Types::tProp = &_Prop;

static IteratorType _Iterator;
IteratorType *Types::tIter = &_Iterator;

void Types::createTypes(){
    tDeleted->add("DELETED","DELE");

    // because of the undefined execution order of static heap
    // objects, we set up all the type names here rather than in
    // "add" to make sure the symbol system is already up.

    // IF you add types later in plugins, the system should detect
    // this.

    for(Type *p = Type::head;p;p=p->next){
        p->nameSymb = SymbolType::getSymbol(p->name);
    }
    createTypesDone = true;

}
}
<|endoftext|>


<commit_before>#include "dataaccess.h"
#include "scientist.h"
#include <QtSql>
#include <iostream> // TEMP<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
#include <sstream>

using namespace std;

DataAccess::DataAccess()
{

    db = QSqlDatabase::addDatabase("QSQLITE");
    db.setDatabaseName("test.sqlite");  // witch database to select ( aka what file )
    db.open();

}
void DataAccess::saveScientists(const vector<Scientist>& scientists)  // From vector to text file
{
    /*
     * This function uses ofstream to save the vector of scientists to the scientists.txt file.
     */

    string sName, line, name, gender, birthYear, deathYear, age;
    //char charGender;
    //int intBirthYear, intDeathYear, intAge;

    name = "LSKDFJLSDKFJSDLKFJSD";
    gender = "m";
    birthYear = "1555";
    deathYear = "1665";

    sName = "INSERT INTO Scientists(name,gender,birth,death) VALUES(\"" + name
          + "\",\"" + gender + "\"," + birthYear + "," + deathYear + ")";

    cout << sName;

    QString input = QString::fromStdString(sName);

    //db = QSqlDatabase::addDatabase("QSQLITE");
    //db.setDatabaseName("test.sqlite");  // witch database to select ( aka what file )

    //db.open();      // open database
    QSqlQuery query;
    query.exec(input); // open table scientists
    db.close();

}
vector<Scientist> DataAccess::loadScientists()                  // From text file to vector
{
    /*
     * This function uses ifstream to read from scientists.txt file and read them into a vector.
     */

    vector<Scientist> scientists;
    string line, name, gender, birthYear, deathYear, age;
    //char charGender;
    int intBirthYear, intDeathYear, intAge;

    //db = QSqlDatabase::addDatabase("QSQLITE");
    //db.setDatabaseName("test.sqlite");  // witch database to select ( aka what file )

    //db.open();      // open database
    QSqlQuery query;
    query.exec("SELECT * FROM Scientists"); // open table scientists

    while (query.next())
    {
        string name = query.value(1).toString().toStdString();
        string stringGender = query.value(2).toString().toStdString();
        int intBirthYear = query.value(3).toInt();
        int intDeathYear = query.value(4).toInt();
        char charGender = stringGender[0];

        Scientist scientist(name, charGender, intBirthYear, intDeathYear, intAge);
        scientists.push_back(scientist);
    }

    //db.close();
    return scientists;
}

// OLD CODE
/*
ofstream file;
file.open("scientists.txt");

if(file.is_open())
{
    for(size_t i = 0; i < scientists.size(); i++)
    {
        file << scientists[i].getName()   <<  ",";
        file << scientists[i].getGender() <<  ",";
        file << scientists[i].getBirth()  <<  ",";
        file << scientists[i].getDeath()  <<  ",";
        file << scientists[i].getAge()    << endl;
    }
    file.close( );
}
*/

/*
vector<Scientist> scientists;

string line, name, gender, birthYear, deathYear, age;
const string delimiter = ",";
char charGender;
int intBirthYear, intDeathYear, intAge, delimiterPos;

ifstream file;
file.open("scientists.txt");

if(file.is_open())
{
    while(getline(file, line))
    {
        delimiterPos = line.find(delimiter);
        name = line.substr(0, delimiterPos);
        line.erase(0, delimiterPos + 1);

        delimiterPos = line.find(delimiter);
        gender = line.substr(0, delimiterPos);
        line.erase(0, delimiterPos + 1);

        delimiterPos = line.find(delimiter);
        birthYear = line.substr(0, delimiterPos);
        line.erase(0, delimiterPos + 1);

        delimiterPos = line.find(delimiter);
        deathYear = line.substr(0, delimiterPos);
        line.erase(0, delimiterPos + 1);

        delimiterPos = line.find(delimiter);
        age = line.substr(0, delimiterPos);

        charGender = gender[0];
        intBirthYear = atoi(birthYear.c_str());
        intDeathYear = atoi(deathYear.c_str());
        intAge = atoi(age.c_str());

        Scientist scientist(name, charGender, intBirthYear, intDeathYear, intAge);

        scientists.push_back(scientist);
    }

file.close( );
}

return scientists;

*/
<commit_msg>Dataaccess update David G<commit_after>#include "dataaccess.h"
#include "scientist.h"
#include <QtSql>
#include <iostream> // TEMP<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
#include <sstream>

using namespace std;

DataAccess::DataAccess()
{

    db = QSqlDatabase::addDatabase("QSQLITE");
    db.setDatabaseName("test.sqlite");  // witch database to select ( aka what file )
    db.open();

}
void DataAccess::saveScientists(const vector<Scientist>& scientists)  // From vector to text file
{
    /*
     * This function uses ofstream to save the vector of scientists to the scientists.txt file.
     */

    string sName, line, name, gender, birthYear, deathYear, age;
    //char charGender;
    //int intBirthYear, intDeathYear, intAge;

    name = "LSKDFJLSDKFJSDLKFJSD";
    gender = "m";
    birthYear = "1555";
    deathYear = "1665";

    sName = "INSERT INTO Scientists(name,gender,birth,death) VALUES(\"" + name
          + "\",\"" + gender + "\"," + birthYear + "," + deathYear + ")";

    cout << sName;

    QString input = QString::fromStdString(sName);

    //db = QSqlDatabase::addDatabase("QSQLITE");
    //db.setDatabaseName("test.sqlite");  // witch database to select ( aka what file )

    //db.open();      // open database
    QSqlQuery query;
    query.exec(input); // open table scientists
    db.close();

}
vector<Scientist> DataAccess::loadScientists()                  // From text file to vector
{
    /*
     * This function uses ifstream to read from scientists.txt file and read them into a vector.
     */

    vector<Scientist> scientists;
    string line, name, gender, birthYear, deathYear, age;
    //char charGender;
    int intBirthYear, intDeathYear, intAge;

    //db = QSqlDatabase::addDatabase("QSQLITE");
    //db.setDatabaseName("test.sqlite");  // witch database to select ( aka what file )

    //db.open();      // open database
    QSqlQuery query;
    query.exec("SELECT * FROM Scientists"); // open table scientists

    while (query.next())
    {
        string name = query.value(1).toString().toStdString();
        string stringGender = query.value(2).toString().toStdString();
        int intBirthYear = query.value(3).toInt();
        int intDeathYear = query.value(4).toInt();
        char charGender = stringGender[0];

        Scientist scientist(name, charGender, intBirthYear, intDeathYear, intAge);
        scientists.push_back(scientist);
    }

    //db.close();
    return scientists;
}

// OLD CODE
/*
ofstream file;
file.open("scientists.txt");

if(file.is_open())
{
    for(size_t i = 0; i < scientists.size(); i++)
    {
        file << scientists[i].getName()   <<  ",";
        file << scientists[i].getGender() <<  ",";
        file << scientists[i].getBirth()  <<  ",";
        file << scientists[i].getDeath()  <<  ",";
        file << scientists[i].getAge()    << endl;
    }
    file.close( );
}
*/

/*
vector<Scientist> scientists;

string line, name, gender, birthYear, deathYear, age;
const string delimiter = ",";
char charGender;
int intBirthYear, intDeathYear, intAge, delimiterPos;

ifstream file;
file.open("scientists.txt");

if(file.is_open())
{
    while(getline(file, line))
    {
        delimiterPos = line.find(delimiter);
        name = line.substr(0, delimiterPos);
        line.erase(0, delimiterPos + 1);

        delimiterPos = line.find(delimiter);
        gender = line.substr(0, delimiterPos);
        line.erase(0, delimiterPos + 1);

        delimiterPos = line.find(delimiter);
        birthYear = line.substr(0, delimiterPos);
        line.erase(0, delimiterPos + 1);

        delimiterPos = line.find(delimiter);
        deathYear = line.substr(0, delimiterPos);
        line.erase(0, delimiterPos + 1);

        delimiterPos = line.find(delimiter);
        age = line.substr(0, delimiterPos);

        charGender = gender[0];
        intBirthYear = atoi(birthYear.c_str());
        intDeathYear = atoi(deathYear.c_str());
        intAge = atoi(age.c_str());

        Scientist scientist(name, charGender, intBirthYear, intDeathYear, intAge);

        scientists.push_back(scientist);
    }

file.close( );
}

return scientists;

*/
<|endoftext|>


<commit_before>/*
 *
 * Copyright 2015, Google Inc.
 * 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 Google Inc. 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.
 *
 */

#include <memory>

#include "server.h"

#include <node.h>
#include <nan.h>

#include <vector>
#include "grpc/grpc.h"
#include "grpc/grpc_security.h"
#include "grpc/support/log.h"
#include "call.h"
#include "completion_queue_async_worker.h"
#include "server_credentials.h"
#include "timeval.h"

namespace grpc {
namespace node {

using std::unique_ptr;
using v8::Array;
using v8::Boolean;
using v8::Date;
using v8::Exception;
using v8::Function;
using v8::FunctionTemplate;
using v8::Handle;
using v8::HandleScope;
using v8::Local;
using v8::Number;
using v8::Object;
using v8::Persistent;
using v8::String;
using v8::Value;

NanCallback *Server::constructor;
Persistent<FunctionTemplate> Server::fun_tpl;

class NewCallOp : public Op {
 public:
  NewCallOp() {
    call = NULL;
    grpc_call_details_init(&details);
    grpc_metadata_array_init(&request_metadata);
  }

  ~NewCallOp() {
    grpc_call_details_destroy(&details);
    grpc_metadata_array_destroy(&request_metadata);
  }

  Handle<Value> GetNodeValue() const {
    NanEscapableScope();
    if (call == NULL) {
      return NanEscapeScope(NanNull());
    }
    Handle<Object> obj = NanNew<Object>();
    obj->Set(NanNew("call"), Call::WrapStruct(call));
    obj->Set(NanNew("method"), NanNew(details.method));
    obj->Set(NanNew("host"), NanNew(details.host));
    obj->Set(NanNew("deadline"),
             NanNew<Date>(TimespecToMilliseconds(details.deadline)));
    obj->Set(NanNew("metadata"), ParseMetadata(&request_metadata));
    return NanEscapeScope(obj);
  }

  bool ParseOp(Handle<Value> value, grpc_op *out,
               shared_ptr<Resources> resources) {
    return true;
  }

  grpc_call *call;
  grpc_call_details details;
  grpc_metadata_array request_metadata;

 protected:
  std::string GetTypeString() const {
    return "new_call";
  }
};

Server::Server(grpc_server *server) : wrapped_server(server) {
  shutdown_queue = grpc_completion_queue_create(NULL);
  grpc_server_register_completion_queue(server, shutdown_queue, NULL);
}

Server::~Server() {
  this->ShutdownServer();
  grpc_completion_queue_shutdown(this->shutdown_queue);
  grpc_server_destroy(wrapped_server);
  grpc_completion_queue_destroy(this->shutdown_queue);
}

void Server::Init(Handle<Object> exports) {
  NanScope();
  Local<FunctionTemplate> tpl = NanNew<FunctionTemplate>(New);
  tpl->SetClassName(NanNew("Server"));
  tpl->InstanceTemplate()->SetInternalFieldCount(1);
  NanSetPrototypeTemplate(tpl, "requestCall",
                          NanNew<FunctionTemplate>(RequestCall)->GetFunction());

  NanSetPrototypeTemplate(
      tpl, "addHttp2Port",
      NanNew<FunctionTemplate>(AddHttp2Port)->GetFunction());

  NanSetPrototypeTemplate(tpl, "start",
                          NanNew<FunctionTemplate>(Start)->GetFunction());

  NanSetPrototypeTemplate(tpl, "shutdown",
                          NanNew<FunctionTemplate>(Shutdown)->GetFunction());

  NanAssignPersistent(fun_tpl, tpl);
  Handle<Function> ctr = tpl->GetFunction();
  constructor = new NanCallback(ctr);
  exports->Set(NanNew("Server"), ctr);
}

bool Server::HasInstance(Handle<Value> val) {
  return NanHasInstance(fun_tpl, val);
}

void Server::ShutdownServer() {
  if (this->wrapped_server != NULL) {
    grpc_server_shutdown_and_notify(this->wrapped_server,
                                    this->shutdown_queue,
                                    NULL);
    grpc_completion_queue_pluck(this->shutdown_queue, NULL,
                                gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
    this->wrapped_server = NULL;
  }
}

NAN_METHOD(Server::New) {
  NanScope();

  /* If this is not a constructor call, make a constructor call and return
     the result */
  if (!args.IsConstructCall()) {
    const int argc = 1;
    Local<Value> argv[argc] = {args[0]};
    NanReturnValue(constructor->GetFunction()->NewInstance(argc, argv));
  }
  grpc_server *wrapped_server;
  grpc_completion_queue *queue = CompletionQueueAsyncWorker::GetQueue();
  if (args[0]->IsUndefined()) {
    wrapped_server = grpc_server_create(NULL, NULL);
  } else if (args[0]->IsObject()) {
    Handle<Object> args_hash(args[0]->ToObject());
    Handle<Array> keys(args_hash->GetOwnPropertyNames());
    grpc_channel_args channel_args;
    channel_args.num_args = keys->Length();
    channel_args.args = reinterpret_cast<grpc_arg *>(
        calloc(channel_args.num_args, sizeof(grpc_arg)));
    /* These are used to keep all strings until then end of the block, then
       destroy them */
    std::vector<NanUtf8String *> key_strings(keys->Length());
    std::vector<NanUtf8String *> value_strings(keys->Length());
    for (unsigned int i = 0; i < channel_args.num_args; i++) {
      Handle<String> current_key(keys->Get(i)->ToString());
      Handle<Value> current_value(args_hash->Get(current_key));
      key_strings[i] = new NanUtf8String(current_key);
      channel_args.args[i].key = **key_strings[i];
      if (current_value->IsInt32()) {
        channel_args.args[i].type = GRPC_ARG_INTEGER;
        channel_args.args[i].value.integer = current_value->Int32Value();
      } else if (current_value->IsString()) {
        channel_args.args[i].type = GRPC_ARG_STRING;
        value_strings[i] = new NanUtf8String(current_value);
        channel_args.args[i].value.string = **value_strings[i];
      } else {
        free(channel_args.args);
        return NanThrowTypeError("Arg values must be strings");
      }
    }
    wrapped_server = grpc_server_create(&channel_args, NULL);
    free(channel_args.args);
  } else {
    return NanThrowTypeError("Server expects an object");
  }
  grpc_server_register_completion_queue(wrapped_server, queue, NULL);
  Server *server = new Server(wrapped_server);
  server->Wrap(args.This());
  NanReturnValue(args.This());
}

NAN_METHOD(Server::RequestCall) {
  NanScope();
  if (!HasInstance(args.This())) {
    return NanThrowTypeError("requestCall can only be called on a Server");
  }
  Server *server = ObjectWrap::Unwrap<Server>(args.This());
  if (server->wrapped_server == NULL) {
    return NanThrowError("requestCall cannot be called on a shut down Server");
  }
  NewCallOp *op = new NewCallOp();
  unique_ptr<OpVec> ops(new OpVec());
  ops->push_back(unique_ptr<Op>(op));
  grpc_call_error error = grpc_server_request_call(
      server->wrapped_server, &op->call, &op->details, &op->request_metadata,
      CompletionQueueAsyncWorker::GetQueue(),
      CompletionQueueAsyncWorker::GetQueue(),
      new struct tag(new NanCallback(args[0].As<Function>()), ops.release(),
                     shared_ptr<Resources>(NULL)));
  if (error != GRPC_CALL_OK) {
    return NanThrowError("requestCall failed", error);
  }
  CompletionQueueAsyncWorker::Next();
  NanReturnUndefined();
}

NAN_METHOD(Server::AddHttp2Port) {
  NanScope();
  if (!HasInstance(args.This())) {
    return NanThrowTypeError(
        "addHttp2Port can only be called on a Server");
  }
  if (!args[0]->IsString()) {
    return NanThrowTypeError(
        "addHttp2Port's first argument must be a String");
  }
  if (!ServerCredentials::HasInstance(args[1])) {
    return NanThrowTypeError(
        "addHttp2Port's second argument must be ServerCredentials");
  }
  Server *server = ObjectWrap::Unwrap<Server>(args.This());
  if (server->wrapped_server == NULL) {
    return NanThrowError(
        "addHttp2Port cannot be called on a shut down Server");
  }
  ServerCredentials *creds_object = ObjectWrap::Unwrap<ServerCredentials>(
      args[1]->ToObject());
  grpc_server_credentials *creds = creds_object->GetWrappedServerCredentials();
  int port;
  if (creds == NULL) {
    port = grpc_server_add_insecure_http2_port(server->wrapped_server,
                                               *NanUtf8String(args[0]));
  } else {
    port = grpc_server_add_secure_http2_port(server->wrapped_server,
                                             *NanUtf8String(args[0]),
                                             creds);
  }
  NanReturnValue(NanNew<Number>(port));
}

NAN_METHOD(Server::Start) {
  NanScope();
  if (!HasInstance(args.This())) {
    return NanThrowTypeError("start can only be called on a Server");
  }
  Server *server = ObjectWrap::Unwrap<Server>(args.This());
  if (server->wrapped_server == NULL) {
    return NanThrowError("start cannot be called on a shut down Server");
  }
  grpc_server_start(server->wrapped_server);
  NanReturnUndefined();
}

NAN_METHOD(ShutdownCallback) {
  NanReturnUndefined();
}

NAN_METHOD(Server::Shutdown) {
  NanScope();
  if (!HasInstance(args.This())) {
    return NanThrowTypeError("shutdown can only be called on a Server");
  }
  Server *server = ObjectWrap::Unwrap<Server>(args.This());
  server->ShutdownServer();
  NanReturnUndefined();
}

}  // namespace node
}  // namespace grpc
<commit_msg>Reverted unintended change.<commit_after>/*
 *
 * Copyright 2015, Google Inc.
 * 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 Google Inc. 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.
 *
 */

#include <memory>

#include "server.h"

#include <node.h>
#include <nan.h>

#include <vector>
#include "grpc/grpc.h"
#include "grpc/grpc_security.h"
#include "grpc/support/log.h"
#include "call.h"
#include "completion_queue_async_worker.h"
#include "server_credentials.h"
#include "timeval.h"

namespace grpc {
namespace node {

using std::unique_ptr;
using v8::Array;
using v8::Boolean;
using v8::Date;
using v8::Exception;
using v8::Function;
using v8::FunctionTemplate;
using v8::Handle;
using v8::HandleScope;
using v8::Local;
using v8::Number;
using v8::Object;
using v8::Persistent;
using v8::String;
using v8::Value;

NanCallback *Server::constructor;
Persistent<FunctionTemplate> Server::fun_tpl;

class NewCallOp : public Op {
 public:
  NewCallOp() {
    call = NULL;
    grpc_call_details_init(&details);
    grpc_metadata_array_init(&request_metadata);
  }

  ~NewCallOp() {
    grpc_call_details_destroy(&details);
    grpc_metadata_array_destroy(&request_metadata);
  }

  Handle<Value> GetNodeValue() const {
    NanEscapableScope();
    if (call == NULL) {
      return NanEscapeScope(NanNull());
    }
    Handle<Object> obj = NanNew<Object>();
    obj->Set(NanNew("call"), Call::WrapStruct(call));
    obj->Set(NanNew("method"), NanNew(details.method));
    obj->Set(NanNew("host"), NanNew(details.host));
    obj->Set(NanNew("deadline"),
             NanNew<Date>(TimespecToMilliseconds(details.deadline)));
    obj->Set(NanNew("metadata"), ParseMetadata(&request_metadata));
    return NanEscapeScope(obj);
  }

  bool ParseOp(Handle<Value> value, grpc_op *out,
               shared_ptr<Resources> resources) {
    return true;
  }

  grpc_call *call;
  grpc_call_details details;
  grpc_metadata_array request_metadata;

 protected:
  std::string GetTypeString() const {
    return "new_call";
  }
};

Server::Server(grpc_server *server) : wrapped_server(server) {
  shutdown_queue = grpc_completion_queue_create(NULL);
  grpc_server_register_completion_queue(server, shutdown_queue, NULL);
}

Server::~Server() {
  this->ShutdownServer();
  grpc_completion_queue_shutdown(this->shutdown_queue);
  grpc_server_destroy(wrapped_server);
  grpc_completion_queue_destroy(this->shutdown_queue);
}

void Server::Init(Handle<Object> exports) {
  NanScope();
  Local<FunctionTemplate> tpl = NanNew<FunctionTemplate>(New);
  tpl->SetClassName(NanNew("Server"));
  tpl->InstanceTemplate()->SetInternalFieldCount(1);
  NanSetPrototypeTemplate(tpl, "requestCall",
                          NanNew<FunctionTemplate>(RequestCall)->GetFunction());

  NanSetPrototypeTemplate(
      tpl, "addHttp2Port",
      NanNew<FunctionTemplate>(AddHttp2Port)->GetFunction());

  NanSetPrototypeTemplate(tpl, "start",
                          NanNew<FunctionTemplate>(Start)->GetFunction());

  NanSetPrototypeTemplate(tpl, "shutdown",
                          NanNew<FunctionTemplate>(Shutdown)->GetFunction());

  NanAssignPersistent(fun_tpl, tpl);
  Handle<Function> ctr = tpl->GetFunction();
  constructor = new NanCallback(ctr);
  exports->Set(NanNew("Server"), ctr);
}

bool Server::HasInstance(Handle<Value> val) {
  return NanHasInstance(fun_tpl, val);
}

void Server::ShutdownServer() {
  if (this->wrapped_server != NULL) {
    grpc_server_shutdown_and_notify(this->wrapped_server,
                                    this->shutdown_queue,
                                    NULL);
    grpc_completion_queue_pluck(this->shutdown_queue, NULL,
                                gpr_inf_future(GPR_CLOCK_REALTIME), NULL);
    this->wrapped_server = NULL;
  }
}

NAN_METHOD(Server::New) {
  NanScope();

  /* If this is not a constructor call, make a constructor call and return
     the result */
  if (!args.IsConstructCall()) {
    const int argc = 1;
    Local<Value> argv[argc] = {args[0]};
    NanReturnValue(constructor->GetFunction()->NewInstance(argc, argv));
  }
  grpc_server *wrapped_server;
  grpc_completion_queue *queue = CompletionQueueAsyncWorker::GetQueue();
  if (args[0]->IsUndefined()) {
    wrapped_server = grpc_server_create(NULL, NULL);
  } else if (args[0]->IsObject()) {
    Handle<Object> args_hash(args[0]->ToObject());
    Handle<Array> keys(args_hash->GetOwnPropertyNames());
    grpc_channel_args channel_args;
    channel_args.num_args = keys->Length();
    channel_args.args = reinterpret_cast<grpc_arg *>(
        calloc(channel_args.num_args, sizeof(grpc_arg)));
    /* These are used to keep all strings until then end of the block, then
       destroy them */
    std::vector<NanUtf8String *> key_strings(keys->Length());
    std::vector<NanUtf8String *> value_strings(keys->Length());
    for (unsigned int i = 0; i < channel_args.num_args; i++) {
      Handle<String> current_key(keys->Get(i)->ToString());
      Handle<Value> current_value(args_hash->Get(current_key));
      key_strings[i] = new NanUtf8String(current_key);
      channel_args.args[i].key = **key_strings[i];
      if (current_value->IsInt32()) {
        channel_args.args[i].type = GRPC_ARG_INTEGER;
        channel_args.args[i].value.integer = current_value->Int32Value();
      } else if (current_value->IsString()) {
        channel_args.args[i].type = GRPC_ARG_STRING;
        value_strings[i] = new NanUtf8String(current_value);
        channel_args.args[i].value.string = **value_strings[i];
      } else {
        free(channel_args.args);
        return NanThrowTypeError("Arg values must be strings");
      }
    }
    wrapped_server = grpc_server_create(&channel_args, NULL);
    free(channel_args.args);
  } else {
    return NanThrowTypeError("Server expects an object");
  }
  grpc_server_register_completion_queue(wrapped_server, queue, NULL);
  Server *server = new Server(wrapped_server);
  server->Wrap(args.This());
  NanReturnValue(args.This());
}

NAN_METHOD(Server::RequestCall) {
  NanScope();
  if (!HasInstance(args.This())) {
    return NanThrowTypeError("requestCall can only be called on a Server");
  }
  Server *server = ObjectWrap::Unwrap<Server>(args.This());
  if (server->wrapped_server == NULL) {
    return NanThrowError("requestCall cannot be called on a shut down Server");
  }
  NewCallOp *op = new NewCallOp();
  unique_ptr<OpVec> ops(new OpVec());
  ops->push_back(unique_ptr<Op>(op));
  grpc_call_error error = grpc_server_request_call(
      server->wrapped_server, &op->call, &op->details, &op->request_metadata,
      CompletionQueueAsyncWorker::GetQueue(),
      CompletionQueueAsyncWorker::GetQueue(),
      new struct tag(new NanCallback(args[0].As<Function>()), ops.release(),
                     shared_ptr<Resources>(nullptr)));
  if (error != GRPC_CALL_OK) {
    return NanThrowError("requestCall failed", error);
  }
  CompletionQueueAsyncWorker::Next();
  NanReturnUndefined();
}

NAN_METHOD(Server::AddHttp2Port) {
  NanScope();
  if (!HasInstance(args.This())) {
    return NanThrowTypeError(
        "addHttp2Port can only be called on a Server");
  }
  if (!args[0]->IsString()) {
    return NanThrowTypeError(
        "addHttp2Port's first argument must be a String");
  }
  if (!ServerCredentials::HasInstance(args[1])) {
    return NanThrowTypeError(
        "addHttp2Port's second argument must be ServerCredentials");
  }
  Server *server = ObjectWrap::Unwrap<Server>(args.This());
  if (server->wrapped_server == NULL) {
    return NanThrowError(
        "addHttp2Port cannot be called on a shut down Server");
  }
  ServerCredentials *creds_object = ObjectWrap::Unwrap<ServerCredentials>(
      args[1]->ToObject());
  grpc_server_credentials *creds = creds_object->GetWrappedServerCredentials();
  int port;
  if (creds == NULL) {
    port = grpc_server_add_insecure_http2_port(server->wrapped_server,
                                               *NanUtf8String(args[0]));
  } else {
    port = grpc_server_add_secure_http2_port(server->wrapped_server,
                                             *NanUtf8String(args[0]),
                                             creds);
  }
  NanReturnValue(NanNew<Number>(port));
}

NAN_METHOD(Server::Start) {
  NanScope();
  if (!HasInstance(args.This())) {
    return NanThrowTypeError("start can only be called on a Server");
  }
  Server *server = ObjectWrap::Unwrap<Server>(args.This());
  if (server->wrapped_server == NULL) {
    return NanThrowError("start cannot be called on a shut down Server");
  }
  grpc_server_start(server->wrapped_server);
  NanReturnUndefined();
}

NAN_METHOD(ShutdownCallback) {
  NanReturnUndefined();
}

NAN_METHOD(Server::Shutdown) {
  NanScope();
  if (!HasInstance(args.This())) {
    return NanThrowTypeError("shutdown can only be called on a Server");
  }
  Server *server = ObjectWrap::Unwrap<Server>(args.This());
  server->ShutdownServer();
  NanReturnUndefined();
}

}  // namespace node
}  // namespace grpc
<|endoftext|>


<commit_before>/*! @file window.cc
 *  @brief Tests for SoundFeatureExtraction::Transforms::Window.
 *  @author Markovtsev Vadim <v.markovtsev@samsung.com>
 *  @version 1.0
 *
 *  @section Notes
 *  This code partially conforms to Google C++ Style Guide.
 *
 *  @section Copyright
 *  Copyright 2013 Samsung R&D Institute Russia
 */

#include <gtest/gtest.h>
#include "src/transforms/window.h"

using SoundFeatureExtraction::Formats::WindowF;
using SoundFeatureExtraction::Formats::WindowFormatF;
using SoundFeatureExtraction::BuffersBase;
using SoundFeatureExtraction::Transforms::Window;

class UnpackRDFTTest : public Window, public testing::Test {
 public:
  BuffersBase<WindowF> Input;
  BuffersBase<WindowF> Output;
  int Size;

  virtual void SetUp() {
    Size = 514;
    Input.Initialize(1, Size);
    for (int i = 0; i < Size; i++) {
      Input[0]->Data.get()[i] = i;
    }
    auto format = std::make_shared<WindowFormatF>(Size * 2000 / 16000, 16000);
    format->SetSize(Size);
    SetInputFormat(format);
    InitializeBuffers(Input, &Output);
  }
};

TEST_F(UnpackRDFTTest, Do) {
  SetParameter("predft", "false");
  Initialize();
  Do(Input, &Output);
}

TEST_F(UnpackRDFTTest, DoPreDft) {
  SetParameter("predft", "true");
  Initialize();
  Do(Input, &Output);
}

#include "tests/google/src/gtest_main.cc"
<commit_msg>Added extra assert to Window test<commit_after>/*! @file window.cc
 *  @brief Tests for SoundFeatureExtraction::Transforms::Window.
 *  @author Markovtsev Vadim <v.markovtsev@samsung.com>
 *  @version 1.0
 *
 *  @section Notes
 *  This code partially conforms to Google C++ Style Guide.
 *
 *  @section Copyright
 *  Copyright 2013 Samsung R&D Institute Russia
 */

#include <gtest/gtest.h>
#include "src/transforms/window.h"

using SoundFeatureExtraction::Formats::WindowF;
using SoundFeatureExtraction::Formats::WindowFormatF;
using SoundFeatureExtraction::BuffersBase;
using SoundFeatureExtraction::Transforms::Window;

class UnpackRDFTTest : public Window, public testing::Test {
 public:
  BuffersBase<WindowF> Input;
  BuffersBase<WindowF> Output;
  int Size;

  virtual void SetUp() {
    Size = 514;
    Input.Initialize(1, Size);
    for (int i = 0; i < Size; i++) {
      Input[0]->Data.get()[i] = i * (1 - 2 * (i % 2));
    }
    auto format = std::make_shared<WindowFormatF>(Size * 2000 / 16000, 16000);
    format->SetSize(Size);
    SetInputFormat(format);
    InitializeBuffers(Input, &Output);
  }
};

TEST_F(UnpackRDFTTest, Do) {
  SetParameter("predft", "false");
  Initialize();
  Do(Input, &Output);
  float output_na[Size] __attribute__ ((aligned (32)));
  ApplyWindow(false, window_.get(), Size, Input[0]->Data.get(), output_na);
  ASSERT_EQ(0, memcmp(Output[0]->Data.get(), output_na,
                      sizeof(float) * Size));
}

TEST_F(UnpackRDFTTest, DoPreDft) {
  SetParameter("predft", "true");
  Initialize();
  Do(Input, &Output);
}

#include "tests/google/src/gtest_main.cc"
<|endoftext|>


<commit_before>#include "xml_element.hpp"
// #include "xml_doc.hpp"
#include "gtest/gtest.h"
#include <iostream>
#include <map>
#include <vector>

TEST( ElementTest, Name ) {
    // xmlNode is created and destroyed outside of class
    xmlNode *n =
        xmlNewNode( NULL, reinterpret_cast<const unsigned char *>( "test-node" ) );

    XmlElement el{n};
    std::string currentName = el.name( );
    EXPECT_STREQ( "test-node", currentName.c_str( ) );

    std::string oldName = el.name( "changed-name" );
    EXPECT_STREQ( currentName.c_str( ), oldName.c_str( ) );
    currentName = el.name( );
    EXPECT_STREQ( "changed-name", currentName.c_str( ) );

    xmlFreeNode( n );
}

TEST( ElementTest, HasAttributes ) {
    xmlNode *n =
        xmlNewNode( NULL, reinterpret_cast<const unsigned char *>( "test-node" ) );

    XmlElement el{n};
    ASSERT_FALSE( el.hasAttributes( ) );

    xmlFreeNode( n );
}

TEST( ElementTest, Attribute ) {
    xmlNode *n =
        xmlNewNode( NULL, reinterpret_cast<const unsigned char *>( "test-node" ) );
    XmlElement el{n};
    ASSERT_FALSE( el.hasAttributes( ) );
    el.attribute( "id", "test-value" );
    ASSERT_TRUE( el.hasAttributes( ) );
    xmlFreeNode( n );
}

TEST( ElementTest, SetAttributes ) {
    xmlNode *n =
        xmlNewNode( NULL, reinterpret_cast<const unsigned char *>( "test-node" ) );
    XmlElement el{n};
    ASSERT_FALSE( el.hasAttributes( ) );
    std::map<std::string, std::string> attrs{{"class", "test-class"},
                                             {"test-attr", "test-value"}};
    el.attributes( attrs );
    ASSERT_TRUE( el.hasAttributes( ) );
    xmlFreeNode( n );
}

TEST( ElementTest, GetAttributes ) {
    xmlNode *n =
        xmlNewNode( NULL, reinterpret_cast<const unsigned char *>( "test-node" ) );
    XmlElement el{n};
    ASSERT_FALSE( el.hasAttributes( ) );
    std::map<std::string, std::string> attrs{{"class", "test-class"},
                                             {"test-attr", "test-value"}};
    el.attributes( attrs );
    ASSERT_TRUE( el.hasAttributes( ) );

    auto props = el.attributes( );
    for ( auto attr : props ) {
        auto key = attr.first;
        auto value = attr.second;
        auto look = attrs.find( key );
        ASSERT_STREQ( look->second.c_str( ), value.c_str( ) );
    }

    xmlFreeNode( n );
}

TEST( ElementTest, HasChild ) {
    xmlNode *n =
        xmlNewNode( NULL, reinterpret_cast<const unsigned char *>( "test-node" ) );
    XmlElement el{n};
    ASSERT_FALSE( el.hasChild( ) );
    xmlFreeNode( n );
}

TEST( ElementTest, SetChildName ) {
    xmlNode *n =
        xmlNewNode( NULL, reinterpret_cast<const unsigned char *>( "test-node" ) );
    XmlElement el{n};
    ASSERT_FALSE( el.hasChild( ) );
    XmlElement ch = el.child( "child-test" );
    ASSERT_TRUE( el.hasChild( ) );
    ASSERT_STREQ( "child-test", ch.name( ).c_str( ) );
    xmlFreeNode( n );
}

TEST( ElementTest, SetChild ) {
    xmlNode *n =
        xmlNewNode( NULL, reinterpret_cast<const unsigned char *>( "test-node" ) );
    XmlElement el{n};
    ASSERT_FALSE( el.hasChild( ) );
    std::map<std::string, std::string> attrs{{"class", "test-class"},
                                             {"test-attr", "test-value"}};
    XmlElement ch = el.child( "child-test", attrs );
    ASSERT_TRUE( el.hasChild( ) );
    ASSERT_STREQ( "child-test", ch.name( ).c_str( ) );
    ASSERT_TRUE( ch.hasAttributes( ) );
    auto props = ch.attributes( );
    for ( auto attr : props ) {
        auto key = attr.first;
        auto value = attr.second;
        auto look = attrs.find( key );
        ASSERT_STREQ( look->second.c_str( ), value.c_str( ) );
    }

    for ( auto attr : props ) {
        auto key = attr.first;
        auto value = attr.second;
        auto look = attrs.find( key );
        ASSERT_STREQ( look->second.c_str( ), value.c_str( ) );
    }

    xmlFreeNode( n );
}

TEST( ElementTest, Child ) {
    xmlNode *n =
        xmlNewNode( NULL, reinterpret_cast<const unsigned char *>( "test-node" ) );
    XmlElement el{n};
    ASSERT_FALSE( el.hasChild( ) );
    XmlElement ch = el.child( "child-test" );
    ASSERT_TRUE( el.hasChild( ) );
    ASSERT_STREQ( "child-test", ch.name( ).c_str( ) );
    el = el.child( );
    ASSERT_STREQ( "child-test", el.name( ).c_str( ) );
    xmlFreeNode( n );
}

TEST( ElementTest, HasSiblings ) {
    xmlNode *n =
        xmlNewNode( NULL, reinterpret_cast<const unsigned char *>( "test-node" ) );
    XmlElement el{n};
    ASSERT_FALSE( el.hasChild( ) );
    XmlElement ch1 = el.child( "first-child-test" );
    XmlElement ch2 = el.child( "second-child-test" );
    ASSERT_TRUE( ch1.hasSibling( ) );
    xmlFreeNode( n );
}

TEST( ElementTest, SetSiblingName ) {
    xmlNode *n =
        xmlNewNode( NULL, reinterpret_cast<const unsigned char *>( "test-node" ) );
    XmlElement el{n};
    XmlElement ch = el.child( "child" );
    XmlElement sibling = ch.sibling( "sibling-test" );
    ASSERT_TRUE( ch.hasSibling( ) );
    xmlFreeNode( n ); // only free's child nodes
}

TEST( ElementTest, SetSibling ) {
    xmlNode *n =
        xmlNewNode( NULL, reinterpret_cast<const unsigned char *>( "test-node" ) );
    XmlElement el{n};
    XmlElement ch = el.child( "child" );
    std::map<std::string, std::string> attrs{{"class", "test-class"},
                                             {"test-attr", "test-value"}};
    XmlElement sibling = ch.sibling( "sibling-test", attrs );
    ASSERT_TRUE( ch.hasSibling( ) );
    // ASSERT_EQ( attrs, sibling.attributes( ) );
    auto props = sibling.attributes( );
    for ( auto attr : props ) {
        auto key = attr.first;
        auto value = attr.second;
        auto look = attrs.find( key );
        ASSERT_STREQ( look->second.c_str( ), value.c_str( ) );
    }

    xmlFreeNode( n ); // only free's child nodes
}

TEST( ElementTest, HasContent ) {
    xmlNode *n =
        xmlNewNode( NULL, reinterpret_cast<const unsigned char *>( "test-node" ) );
    XmlElement el{n};
    XmlElement ch = el.child( "child" );
    std::map<std::string, std::string> attrs{{"class", "test-class"},
                                             {"test-attr", "test-value"}};
    XmlElement sibling = ch.sibling( "sibling-test", attrs );
    ASSERT_TRUE( ch.hasSibling( ) );
    // ASSERT_EQ( attrs, sibling.attributes( ) );
    auto props = sibling.attributes( );
    for ( auto attr : props ) {
        auto key = attr.first;
        auto value = attr.second;
        auto look = attrs.find( key );
        ASSERT_STREQ( look->second.c_str( ), value.c_str( ) );
    }

    ASSERT_FALSE( el.hasContent( ) );
    xmlFreeNode( n ); // only free's child nodes
}

TEST( ElementTest, Content ) {
    xmlNode *n =
        xmlNewNode( NULL, reinterpret_cast<const unsigned char *>( "test-node" ) );
    XmlElement el{n};
    el.content( "This is some test content" );
    ASSERT_TRUE( el.hasContent( ) );
    std::cerr << el.content( ) << std::endl;
    xmlFreeNode( n ); // only free's child nodes
    n = nullptr;

    n = xmlNewNode( NULL, reinterpret_cast<const unsigned char *>( "test-node" ) );
    el = XmlElement{n};
    XmlElement ch1 = el.child( "child" );
    XmlElement sibling = el.child( "sibling" );
    XmlElement ch2 = sibling.child( "child-of-sibling" );
    ch2.content( "This is some more test content" );
    ch2.child( "child-of-child-of-sibling" );
    ASSERT_TRUE( el.hasContent( ) );
    std::cerr << el.content( ) << std::endl;
    xmlFreeNode( n ); // only free's child nodes
    n = nullptr;
}

TEST( ElementTest, AddContent ) {
    xmlNode *n =
        xmlNewNode( NULL, reinterpret_cast<const unsigned char *>( "test-node" ) );
    XmlElement el{n};
    el.content( "This is some test content" );
    ASSERT_TRUE( el.hasContent( ) );
    xmlFreeNode( n ); // only free's child nodes
    n = nullptr;

    n = xmlNewNode( NULL, reinterpret_cast<const unsigned char *>( "test-node" ) );
    el = XmlElement{n};
    XmlElement ch1 = el.child( "child" );
    XmlElement sibling = el.child( "sibling" );
    XmlElement ch2 = sibling.child( "child-of-child" );
    ch2.content( "This is some test content" );
    ASSERT_TRUE( el.hasContent( ) );
    xmlFreeNode( n ); // only free's child nodes
    n = nullptr;

    n = xmlNewNode( NULL, reinterpret_cast<const unsigned char *>( "test-node" ) );
    el = XmlElement{n};
    ch1 = el.child( "child" );
    sibling = el.child( "sibling" );
    ch2 = sibling.child( "child-of-child" );
    ASSERT_FALSE( el.hasContent( ) );
    xmlFreeNode( n ); // only free's child nodes
}
<commit_msg>added relational and equality operators (for ElementSelections)<commit_after>#include "xml_element.hpp"
// #include "xml_doc.hpp"
#include "gtest/gtest.h"
#include <iostream>
#include <map>
#include <vector>

TEST( ElementTest, Name ) {
    // xmlNode is created and destroyed outside of class
    xmlNode *n =
        xmlNewNode( NULL, reinterpret_cast<const unsigned char *>( "test-node" ) );

    XmlElement el{n};
    std::string currentName = el.name( );
    EXPECT_STREQ( "test-node", currentName.c_str( ) );

    std::string oldName = el.name( "changed-name" );
    EXPECT_STREQ( currentName.c_str( ), oldName.c_str( ) );
    currentName = el.name( );
    EXPECT_STREQ( "changed-name", currentName.c_str( ) );

    xmlFreeNode( n );
}

TEST( ElementTest, HasAttributes ) {
    xmlNode *n =
        xmlNewNode( NULL, reinterpret_cast<const unsigned char *>( "test-node" ) );

    XmlElement el{n};
    ASSERT_FALSE( el.hasAttributes( ) );

    xmlFreeNode( n );
}

TEST( ElementTest, Attribute ) {
    xmlNode *n =
        xmlNewNode( NULL, reinterpret_cast<const unsigned char *>( "test-node" ) );
    XmlElement el{n};
    ASSERT_FALSE( el.hasAttributes( ) );
    el.attribute( "id", "test-value" );
    ASSERT_TRUE( el.hasAttributes( ) );
    xmlFreeNode( n );
}

TEST( ElementTest, SetAttributes ) {
    xmlNode *n =
        xmlNewNode( NULL, reinterpret_cast<const unsigned char *>( "test-node" ) );
    XmlElement el{n};
    ASSERT_FALSE( el.hasAttributes( ) );
    std::map<std::string, std::string> attrs{{"class", "test-class"},
                                             {"test-attr", "test-value"}};
    el.attributes( attrs );
    ASSERT_TRUE( el.hasAttributes( ) );
    xmlFreeNode( n );
}

TEST( ElementTest, GetAttributes ) {
    xmlNode *n =
        xmlNewNode( NULL, reinterpret_cast<const unsigned char *>( "test-node" ) );
    XmlElement el{n};
    ASSERT_FALSE( el.hasAttributes( ) );
    std::map<std::string, std::string> attrs{{"class", "test-class"},
                                             {"test-attr", "test-value"}};
    el.attributes( attrs );
    ASSERT_TRUE( el.hasAttributes( ) );

    auto props = el.attributes( );
    for ( auto attr : props ) {
        auto key = attr.first;
        auto value = attr.second;
        auto look = attrs.find( key );
        ASSERT_STREQ( look->second.c_str( ), value.c_str( ) );
    }

    xmlFreeNode( n );
}

TEST( ElementTest, HasChild ) {
    xmlNode *n =
        xmlNewNode( NULL, reinterpret_cast<const unsigned char *>( "test-node" ) );
    XmlElement el{n};
    ASSERT_FALSE( el.hasChild( ) );
    xmlFreeNode( n );
}

TEST( ElementTest, SetChildName ) {
    xmlNode *n =
        xmlNewNode( NULL, reinterpret_cast<const unsigned char *>( "test-node" ) );
    XmlElement el{n};
    ASSERT_FALSE( el.hasChild( ) );
    XmlElement ch = el.child( "child-test" );
    ASSERT_TRUE( el.hasChild( ) );
    ASSERT_STREQ( "child-test", ch.name( ).c_str( ) );
    xmlFreeNode( n );
}

TEST( ElementTest, SetChild ) {
    xmlNode *n =
        xmlNewNode( NULL, reinterpret_cast<const unsigned char *>( "test-node" ) );
    XmlElement el{n};
    ASSERT_FALSE( el.hasChild( ) );
    std::map<std::string, std::string> attrs{{"class", "test-class"},
                                             {"test-attr", "test-value"}};
    XmlElement ch = el.child( "child-test", attrs );
    ASSERT_TRUE( el.hasChild( ) );
    ASSERT_STREQ( "child-test", ch.name( ).c_str( ) );
    ASSERT_TRUE( ch.hasAttributes( ) );
    auto props = ch.attributes( );
    for ( auto attr : props ) {
        auto key = attr.first;
        auto value = attr.second;
        auto look = attrs.find( key );
        ASSERT_STREQ( look->second.c_str( ), value.c_str( ) );
    }

    for ( auto attr : props ) {
        auto key = attr.first;
        auto value = attr.second;
        auto look = attrs.find( key );
        ASSERT_STREQ( look->second.c_str( ), value.c_str( ) );
    }

    xmlFreeNode( n );
}

TEST( ElementTest, Child ) {
    xmlNode *n =
        xmlNewNode( NULL, reinterpret_cast<const unsigned char *>( "test-node" ) );
    XmlElement el{n};
    ASSERT_FALSE( el.hasChild( ) );
    XmlElement ch = el.child( "child-test" );
    ASSERT_TRUE( el.hasChild( ) );
    ASSERT_STREQ( "child-test", ch.name( ).c_str( ) );
    el = el.child( );
    ASSERT_STREQ( "child-test", el.name( ).c_str( ) );
    xmlFreeNode( n );
}

TEST( ElementTest, HasSiblings ) {
    xmlNode *n =
        xmlNewNode( NULL, reinterpret_cast<const unsigned char *>( "test-node" ) );
    XmlElement el{n};
    ASSERT_FALSE( el.hasChild( ) );
    XmlElement ch1 = el.child( "first-child-test" );
    XmlElement ch2 = el.child( "second-child-test" );
    ASSERT_TRUE( ch1.hasSibling( ) );
    xmlFreeNode( n );
}

TEST( ElementTest, SetSiblingName ) {
    xmlNode *n =
        xmlNewNode( NULL, reinterpret_cast<const unsigned char *>( "test-node" ) );
    XmlElement el{n};
    XmlElement ch = el.child( "child" );
    XmlElement sibling = ch.sibling( "sibling-test" );
    ASSERT_TRUE( ch.hasSibling( ) );
    xmlFreeNode( n ); // only free's child nodes
}

TEST( ElementTest, SetSibling ) {
    xmlNode *n =
        xmlNewNode( NULL, reinterpret_cast<const unsigned char *>( "test-node" ) );
    XmlElement el{n};
    XmlElement ch = el.child( "child" );
    std::map<std::string, std::string> attrs{{"class", "test-class"},
                                             {"test-attr", "test-value"}};
    XmlElement sibling = ch.sibling( "sibling-test", attrs );
    ASSERT_TRUE( ch.hasSibling( ) );
    // ASSERT_EQ( attrs, sibling.attributes( ) );
    auto props = sibling.attributes( );
    for ( auto attr : props ) {
        auto key = attr.first;
        auto value = attr.second;
        auto look = attrs.find( key );
        ASSERT_STREQ( look->second.c_str( ), value.c_str( ) );
    }

    xmlFreeNode( n ); // only free's child nodes
}

TEST( ElementTest, HasContent ) {
    xmlNode *n =
        xmlNewNode( NULL, reinterpret_cast<const unsigned char *>( "test-node" ) );
    XmlElement el{n};
    XmlElement ch = el.child( "child" );
    std::map<std::string, std::string> attrs{{"class", "test-class"},
                                             {"test-attr", "test-value"}};
    XmlElement sibling = ch.sibling( "sibling-test", attrs );
    ASSERT_TRUE( ch.hasSibling( ) );
    // ASSERT_EQ( attrs, sibling.attributes( ) );
    auto props = sibling.attributes( );
    for ( auto attr : props ) {
        auto key = attr.first;
        auto value = attr.second;
        auto look = attrs.find( key );
        ASSERT_STREQ( look->second.c_str( ), value.c_str( ) );
    }

    ASSERT_FALSE( el.hasContent( ) );
    xmlFreeNode( n ); // only free's child nodes
}

TEST( ElementTest, Content ) {
    xmlNode *n =
        xmlNewNode( NULL, reinterpret_cast<const unsigned char *>( "test-node" ) );
    XmlElement el{n};
    el.content( "This is some test content" );
    ASSERT_TRUE( el.hasContent( ) );
    std::cerr << el.content( ) << std::endl;
    xmlFreeNode( n ); // only free's child nodes
    n = nullptr;

    n = xmlNewNode( NULL, reinterpret_cast<const unsigned char *>( "test-node" ) );
    el = XmlElement{n};
    XmlElement ch1 = el.child( "child" );
    XmlElement sibling = el.child( "sibling" );
    XmlElement ch2 = sibling.child( "child-of-sibling" );
    ch2.content( "This is some more test content" );
    ch2.child( "child-of-child-of-sibling" );
    ASSERT_TRUE( el.hasContent( ) );
    std::cerr << el.content( ) << std::endl;
    xmlFreeNode( n ); // only free's child nodes
    n = nullptr;
}

TEST( ElementTest, AddContent ) {
    xmlNode *n =
        xmlNewNode( NULL, reinterpret_cast<const unsigned char *>( "test-node" ) );
    XmlElement el{n};
    el.content( "This is some test content" );
    ASSERT_TRUE( el.hasContent( ) );
    xmlFreeNode( n ); // only free's child nodes
    n = nullptr;

    n = xmlNewNode( NULL, reinterpret_cast<const unsigned char *>( "test-node" ) );
    el = XmlElement{n};
    XmlElement ch1 = el.child( "child" );
    XmlElement sibling = el.child( "sibling" );
    XmlElement ch2 = sibling.child( "child-of-child" );
    ch2.content( "This is some test content" );
    ASSERT_TRUE( el.hasContent( ) );
    xmlFreeNode( n ); // only free's child nodes
    n = nullptr;

    n = xmlNewNode( NULL, reinterpret_cast<const unsigned char *>( "test-node" ) );
    el = XmlElement{n};
    ch1 = el.child( "child" );
    sibling = el.child( "sibling" );
    ch2 = sibling.child( "child-of-child" );
    ASSERT_FALSE( el.hasContent( ) );
    xmlFreeNode( n ); // only free's child nodes
}

TEST( ElementTest, Equality ) {
    XmlElement nullEl;
    ASSERT_TRUE( nullEl == XmlElement{} );

    xmlNode *n =
        xmlNewNode( NULL, reinterpret_cast<const unsigned char *>( "test-node" ) );
    XmlElement el1{n};
    XmlElement ch1 = el1.child( "child" );
    ASSERT_FALSE( el1 == ch1 );
    ASSERT_FALSE( el1 == XmlElement{} );
    ASSERT_TRUE( el1 != ch1 );
    auto ch = el1.child( );
    ASSERT_TRUE( ch == ch1 );
    ASSERT_FALSE( ch != ch1 );
    ASSERT_TRUE( ch != XmlElement{} );
    xmlFreeNode( n );
}

TEST( ElementTest, StrictOrdering ) {
    XmlElement nullEl;
    ASSERT_FALSE( nullEl < XmlElement{} );
    ASSERT_FALSE( nullEl > XmlElement{} );
    xmlNode *n =
        xmlNewNode( NULL, reinterpret_cast<const unsigned char *>( "test-node" ) );
    XmlElement el{n};
    ASSERT_TRUE( el < nullEl );
    auto ch = el.child( "child-node" );
    ASSERT_TRUE( el < ch );
    ASSERT_FALSE( el < el );
    ASSERT_TRUE( ch > el );
    auto sblg = el.child( "sibling-of-child" );
    ASSERT_TRUE( el < sblg );
    ASSERT_TRUE( sblg > el );
    ASSERT_TRUE( ch < sblg );
    ASSERT_TRUE( sblg > ch );
    auto grch = ch.child( "child-of-child" );
    ASSERT_TRUE( ch < grch );
    ASSERT_TRUE( grch < sblg );
    auto grch1 = sblg.child( "child-of-siblg" );
    ASSERT_TRUE( grch < grch1 );
    ASSERT_TRUE( grch1 > grch );
    xmlFreeNode( n );
}

TEST( ElementTest, WeakOrdering ) {
    XmlElement nullEl;
    ASSERT_TRUE( nullEl <= XmlElement{} );
    ASSERT_TRUE( nullEl >= XmlElement{} );

    xmlNode *n =
        xmlNewNode( NULL, reinterpret_cast<const unsigned char *>( "test-node" ) );
    XmlElement el{n};
    ASSERT_TRUE( el >= el);
    ASSERT_TRUE( el <= el);
    xmlFreeNode( n );
}
<|endoftext|>


<commit_before>#include <vector>
#include <string>
using namespace std;

template <typename T>
class vector;

template <typename T>
class Foo {
public:
  typedef int Int;
  typedef T BaseType;
  typedef T* BaseTypePtr;
  typedef T BasTypeArray[3];
  typedef typename std::vector<T> Vector;
  typedef typename std::vector<T>::iterator Iterator;

  typedef enum {
    ENUM1, ENUM2
  } DeepEnum;

  enum {
    MIN_DIM=5, MAX_DIM=10
  };

  int someArray[MAX_DIM];

  typedef struct {
    int i, j;
  } NestedStruct;

  typedef class irrelevantTag {
  public:
    typedef enum {
      ENUM1, ENUM2
    } VeryDeepEnum;

    int i, j;
  } NestedClass;

  template <typename T1, typename T2>
  class OtherNestedClass {
  public:
    typedef enum {
      ENUM1, ENUM2
    } VeryDeepEnum;
    T1 val1;
    T2 val2;
  };

  void method(NestedClass & n);
};

template <typename T, int I>
class Bar{
public:
        typedef typename Foo<T>::NestedStruct MyStruct;

        typedef class {
        public:
                int val;

        } NestedClass;

        template<typename T1>
        class NestedClass2 {
        public:
                T1 val;
        };
};

class NoTemplate {
public:
        typedef enum {
                ENUM1, ENUM2
        } DeepEnum;
};
<commit_msg>Adapted the unit test<commit_after>#include <vector>
#include <string>
using namespace std;

template <typename T>
class vector;

#ifdef C2NIM
#mangle NestedClass FooNestedClass
#endif

template <typename T>
class Foo {
public:
  typedef int Int;
  typedef T BaseType;
  typedef T* BaseTypePtr;
  typedef T BasTypeArray[3];
  typedef typename std::vector<T> Vector;
  typedef typename std::vector<T>::iterator Iterator;

  typedef enum {
    ENUM1, ENUM2
  } DeepEnum;

  enum {
    MIN_DIM=5, MAX_DIM=10
  };

  int someArray[MAX_DIM];

  typedef struct {
    int i, j;
  } NestedStruct;

  typedef class irrelevantTag {
  public:
    typedef enum {
      ENUM1, ENUM2
    } VeryDeepEnum;

    int i, j;
  } NestedClass;

  template <typename T1, typename T2>
  class OtherNestedClass {
  public:
    typedef enum {
      ENUM1, ENUM2
    } VeryDeepEnum;
    T1 val1;
    T2 val2;
  };

  void method(NestedClass & n);
};

template <typename T, int I>
class Bar{
public:
        typedef typename Foo<T>::NestedStruct MyStruct;

        typedef class {
        public:
                int val;

        } NestedClass;

        template<typename T1>
        class NestedClass2 {
        public:
                T1 val;
        };
};

class NoTemplate {
public:
        typedef enum {
                ENUM1, ENUM2
        } DeepEnum;
};
<|endoftext|>