File: valarray.h

package info (click to toggle)
kdbg 1.2.4-2
  • links: PTS
  • area: main
  • in suites: woody
  • size: 2,504 kB
  • ctags: 1,945
  • sloc: cpp: 15,961; sh: 8,183; makefile: 481; perl: 71; ansic: 16
file content (166 lines) | stat: -rw-r--r-- 4,140 bytes parent folder | download | duplicates (2)
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
// $Id: valarray.h,v 1.5 2000/03/26 19:32:52 jsixt Exp $

// Copyright by Johannes Sixt
// This file is under GPL, the GNU General Public Licence

// an array template class that holds values (not pointers to values)

#ifndef VALARRAY_H
#define VALARRAY_H

// need a placement new
#include "config.h"
#ifdef HAVE_PLACEMENT_NEW
#include <new>
#else
inline void* operator new(size_t, void* p) { return p; }
#endif

template<class T>
class ValArray
{
public:
    ValArray() : m_pData(0), m_size(0), m_space(0) { }
    ~ValArray();
    void operator=(const ValArray<T>& src);
    const T& operator[](int i) const { return m_pData[i]; }
    T& operator[](int i) { return m_pData[i]; }
    void setSize(int newSize);
    int size() const { return m_size; }
    void append(const T& newElem, int count = 1) { expand(newElem, m_size+count); }
    void insertAt(int start, const T& newElem, int count = 1);
    void insertAt(int start, const ValArray<T>& newElems);
    void removeAt(int start, int count = 1);

protected:
    T* m_pData;
    int m_size;
    int m_space;

    void expand(const T& newElem, int newSize);
};

template<class T>
ValArray<T>::~ValArray()
{
    setSize(0);
    delete[] reinterpret_cast<char*>(m_pData);
}

template<class T>
void ValArray<T>::operator=(const ValArray<T>& src)
{
    setSize(src.size());
    for (int i = 0; i < src.size(); i++) {
	m_pData[i] = src.m_pData[i];
    }
}

template<class T>
void ValArray<T>::setSize(int newSize)
{
    if (newSize == m_size) return;
    if (newSize > m_size) {
	expand(T(), newSize);
    } else {
	do {
	    m_size--;
	    m_pData[m_size].~T();
	} while (m_size > newSize);
    }
}

template<class T>
void ValArray<T>::expand(const T& newElem, int newSize)
{
    if (newSize > m_space) {
	// reallocate
	int newSpace = m_space + m_space;
	if (newSpace < 8) newSpace = 8;
	if (newSpace < newSize) newSpace = newSize;
	T* newData = reinterpret_cast<T*>(new char[newSpace * sizeof(T)]);
	// care about exception safety as much as possible
	// copy-construct the elements into the new array
	// TODO: clean up when exception is thrown here
	for (int i = 0; i < m_size; i++) {
	    new(&newData[i]) T(m_pData[i]);
	}
	// replace the pointer
	T* oldData = m_pData;
	m_pData = newData;
	m_space = newSpace;
	// destruct the old data
	for (int i = m_size-1; i >= 0; i--) {
	    oldData[i].~T();
	}
	delete[] reinterpret_cast<char*>(oldData);
    }
    // copy the new element into the new space
    while (m_size < newSize) {
	new(&m_pData[m_size]) T(newElem);
	m_size++;
    }
}

template<class T>
void ValArray<T>::removeAt(int start, int count)
{
    if (count <= 0)
	return;
    // move elements down
    int nMove = m_size-start-count;
    for (int src = start+count; nMove > 0; src++, start++, nMove--) {
	// first destruct destination
	m_pData[start].~T();
	// copy-construct source to destination
	new(&m_pData[start]) T(m_pData[src]);
    }
    setSize(start);
}

template<class T>
void ValArray<T>::insertAt(int start, const T& newElem, int count)
{
    if (count <= 0)
	return;

    int nMove = m_size - start;
    int src = m_size-1;
    setSize(m_size+count);
    for (int dest = m_size-1; nMove > 0; src--, dest--, nMove--) {
	// first destruct destination
	m_pData[dest].~T();
	// copy-construct source to destination
	new(&m_pData[dest]) T(m_pData[src]);
    }
    // copy new elements (after destruction destination)
    for (; count > 0; start++, count--) {
	m_pData[start].~T();
	new(&m_pData[start]) T(newElem);
    }
}

template<class T>
void ValArray<T>::insertAt(int start, const ValArray<T>& newElems)
{
    int count = newElems.size();
    if (count <= 0)
	return;

    int nMove = m_size - start;
    int src = m_size-1;
    setSize(m_size+count);
    for (int dest = m_size-1; nMove > 0; src--, dest--, nMove--) {
	// first destruct destination
	m_pData[dest].~T();
	// copy-construct source to destination
	new(&m_pData[dest]) T(m_pData[src]);
    }
    // copy new elements (after destruction destination)
    for (int i = 0; count > 0; i++, start++, count--) {
	m_pData[start].~T();
	new(&m_pData[start]) T(newElems[i]);
    }
}

#endif // VALARRAY_H