aboutsummaryrefslogtreecommitdiff
path: root/include/sibs/Functional.hpp
blob: 7c51883f16f347a474dc87b963cfd15a9af5c01a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#pragma once

#include <vector>

namespace sibs
{
    template <typename T>
    class Function;

    template <typename T>
    class FunctionIterator
    {
    public:
        FunctionIterator(T *_it, Function<T> *_func, std::size_t _funcIndex) : 
            it(_it),
            func(_func),
            funcIndex(_funcIndex)
        {

        }

        bool operator == (FunctionIterator<T> &rhs) const
        {
            return it == rhs.it && funcIndex == rhs.funcIndex;
        }

        bool operator != (FunctionIterator<T> &rhs) const
        {
            return !(*this == rhs);
        }

        T& operator * ()
        { 
            return *it;
        }

        void operator ++ ()
        {
            ++it;
            if(it == func->endIt)
            {
                if(funcIndex < func->connections.size())
                {
                    it = func->connections[funcIndex].beginIt;
                    ++funcIndex;
                }
            }
        }
    private:
        T *it;
        Function<T> *func;
        std::size_t funcIndex;
    };

    template <typename T>
    class Function
    {
        friend class FunctionIterator<T>;
    public:
        typedef FunctionIterator<T> iterator;
        typedef const FunctionIterator<T> const_iterator;

        Function(T *begin, T *end) : 
            beginIt(begin),
            endIt(end)
        {
            
        }

        Function(std::vector<T> &vec) : 
            beginIt(vec.data()),
            endIt(vec.data() + vec.size())
        {
            
        }

        Function& merge(const Function &otherFunc)
        {
            connections.push_back(otherFunc);
            return *this;
        }

        iterator begin()
        {
            return FunctionIterator<T>(beginIt, this, 0);
        }

        iterator end()
        {
            T *it = endIt;
            if(!connections.empty())
                it = connections.back().endIt;
            return FunctionIterator<T>(it, this, connections.size());
        }

        const_iterator begin() const
        {
            return FunctionIterator<T>(beginIt, this, 0);
        }

        const_iterator end() const
        {
            T *it = endIt;
            if(!connections.empty())
                it = connections.back().endIt;
            return FunctionIterator<T>(it, this, connections.size());
        }
    private:
        T *beginIt;
        T *endIt;
        std::vector<Function> connections;
    };

    template <typename T>
    static Function<T> makeFunction(T *begin, T *end)
    {
        return Function<T>(begin, end);
    }

    template <typename T>
    static Function<T> makeFunction(std::vector<T> &vec)
    {
        return Function<T>(vec.data(), vec.data() + vec.size());
    }
}