summaryrefslogtreecommitdiff
path: root/thirdparty/thekla_atlas/nvcore/Array.h
blob: b295cb2b0c86fa91b1ed478530931373df6f8f18 (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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
// This code is in the public domain -- Ignacio Castaño <castano@gmail.com>

#pragma once
#ifndef NV_CORE_ARRAY_H
#define NV_CORE_ARRAY_H

/*
This array class requires the elements to be relocable; it uses memmove and realloc. Ideally I should be 
using swap, but I honestly don't care. The only thing that you should be aware of is that internal pointers
are not supported.

Note also that push_back and resize does not support inserting arguments elements that are in the same 
container. This is forbidden to prevent an extra copy.
*/


#include "Memory.h"
#include "Debug.h"
#include "ForEach.h" // PseudoIndex


namespace nv 
{
    class Stream;

    /**
    * Replacement for std::vector that is easier to debug and provides
    * some nice foreach enumerators. 
    */
    template<typename T>
    class NVCORE_CLASS Array {
    public:
        typedef uint size_type;

        // Default constructor.
        NV_FORCEINLINE Array() : m_buffer(NULL), m_capacity(0), m_size(0) {}

        // Copy constructor.
        NV_FORCEINLINE Array(const Array & a) : m_buffer(NULL), m_capacity(0), m_size(0) {
            copy(a.m_buffer, a.m_size);
        }

        // Constructor that initializes the vector with the given elements.
        NV_FORCEINLINE Array(const T * ptr, uint num) : m_buffer(NULL), m_capacity(0), m_size(0) {
            copy(ptr, num);
        }

        // Allocate array.
        NV_FORCEINLINE explicit Array(uint capacity) : m_buffer(NULL), m_capacity(0), m_size(0) {
            setArrayCapacity(capacity);
        }

        // Destructor.
        NV_FORCEINLINE ~Array() {
            clear();
            free<T>(m_buffer);
        }


        /// Const element access.
        NV_FORCEINLINE const T & operator[]( uint index ) const
        {
            nvDebugCheck(index < m_size);
            return m_buffer[index];
        }
        NV_FORCEINLINE const T & at( uint index ) const
        {
            nvDebugCheck(index < m_size);
            return m_buffer[index];
        }

        /// Element access.
        NV_FORCEINLINE T & operator[] ( uint index )
        {
            nvDebugCheck(index < m_size);
            return m_buffer[index];
        }
        NV_FORCEINLINE T & at( uint index )
        {
            nvDebugCheck(index < m_size);
            return m_buffer[index];
        }

        /// Get vector size.
        NV_FORCEINLINE uint size() const { return m_size; }

        /// Get vector size.
        NV_FORCEINLINE uint count() const { return m_size; }

        /// Get vector capacity.
        NV_FORCEINLINE uint capacity() const { return m_capacity; }

        /// Get const vector pointer.
        NV_FORCEINLINE const T * buffer() const { return m_buffer; }

        /// Get vector pointer.
        NV_FORCEINLINE T * buffer() { return m_buffer; }

        /// Provide begin/end pointers for C++11 range-based for loops.
        NV_FORCEINLINE T * begin() { return m_buffer; }
        NV_FORCEINLINE T * end() { return m_buffer + m_size; }
        NV_FORCEINLINE const T * begin() const { return m_buffer; }
        NV_FORCEINLINE const T * end() const { return m_buffer + m_size; }

        /// Is vector empty.
        NV_FORCEINLINE bool isEmpty() const { return m_size == 0; }

        /// Is a null vector.
        NV_FORCEINLINE bool isNull() const { return m_buffer == NULL; }


        T & append();
        void push_back( const T & val );
        void pushBack( const T & val );
        Array<T> & append( const T & val );
        Array<T> & operator<< ( T & t );
        void pop_back();
        void popBack(uint count = 1);
        void popFront(uint count = 1);
        const T & back() const;
        T & back();
        const T & front() const;
        T & front();
        bool contains(const T & e) const;
        bool find(const T & element, uint * indexPtr) const;
        bool find(const T & element, uint begin, uint end, uint * indexPtr) const;
        void removeAt(uint index);
        bool remove(const T & element);
        void insertAt(uint index, const T & val = T());
        void append(const Array<T> & other);
        void append(const T other[], uint count);
        void replaceWithLast(uint index);
        void resize(uint new_size);
        void resize(uint new_size, const T & elem);
        void fill(const T & elem);
        void clear();
        void shrink();
        void reserve(uint desired_size);
        void copy(const T * data, uint count);
        Array<T> & operator=( const Array<T> & a );
        T * release();


        // Array enumerator.
        typedef uint PseudoIndex;

        NV_FORCEINLINE PseudoIndex start() const { return 0; }
        NV_FORCEINLINE bool isDone(const PseudoIndex & i) const { nvDebugCheck(i <= this->m_size); return i == this->m_size; }
        NV_FORCEINLINE void advance(PseudoIndex & i) const { nvDebugCheck(i <= this->m_size); i++; }

#if NV_NEED_PSEUDOINDEX_WRAPPER
        NV_FORCEINLINE T & operator[]( const PseudoIndexWrapper & i ) {
            return m_buffer[i(this)];
        }
        NV_FORCEINLINE const T & operator[]( const PseudoIndexWrapper & i ) const {
            return m_buffer[i(this)];
        }
#endif

        // Friends.
        template <typename Typ> 
        friend Stream & operator<< ( Stream & s, Array<Typ> & p );

        template <typename Typ>
        friend void swap(Array<Typ> & a, Array<Typ> & b);


    protected:

        void setArraySize(uint new_size);
        void setArrayCapacity(uint new_capacity);

        T * m_buffer;
        uint m_capacity;
        uint m_size;

    };


} // nv namespace

#endif // NV_CORE_ARRAY_H