aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/SVector.h
blob: 9f56da52897df7698bf9d4fb3bdd3d8698e00cb3 (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
// Scintilla source code edit control
/** @file SVector.h
 ** A simple expandable vector.
 **/
// Copyright 1998-2001 by Neil Hodgson <neilh@hare.net.au>
// The License.txt file describes the conditions under which this software may be distributed.

#ifndef SVECTOR_H
#define SVECTOR_H

#ifdef SCI_NAMESPACE
namespace Scintilla {
#endif

/**
 * A simple expandable integer vector.
 * Storage not allocated for elements until an element is used.
 * This makes it very lightweight unless used so is a good match for optional features.
 */
class SVector {
	enum { allocSize = 4000 };
	
	int *v;				///< The vector
	unsigned int size;	///< Number of elements allocated
	unsigned int len;	///< Number of elements used in vector
	bool allocFailure;	///< A memory allocation call has failed
	
	/** Internally allocate more elements than the user wants
	 * to avoid thrashing the memory allocator. */
	void SizeTo(int newSize) {
		if (newSize < allocSize)
			newSize += allocSize;
		else 
			newSize = (newSize * 3) / 2;
		int* newv = new int[newSize];
		if (!newv) {
			allocFailure = true;
			return;
		}
		size = newSize;
        	unsigned int i=0;
		for (; i<len; i++) {
			newv[i] = v[i];
		}
		for (; i<size; i++) {
			newv[i] = 0;
		}
		delete []v;
		v = newv;
	}
	
public:
	SVector() {
		allocFailure = false;
		v = 0;
		len = 0;
		size = 0;
	}
	~SVector() {
		Free();
	}
	/// Constructor from another vector.
	SVector(const SVector &other) {
		allocFailure = false;
		v = 0;
		len = 0;
		size = 0;
		if (other.Length() > 0) {
			SizeTo(other.Length());
			if (!allocFailure) {
				for (int i=0;i<other.Length();i++)
					v[i] = other.v[i];
				len = other.Length();
			}
		}
	}
	/// Copy constructor.
	SVector &operator=(const SVector &other) {
		if (this != &other) {
			delete []v;
			allocFailure = false;
			v = 0;
			len = 0;
			size = 0;
			if (other.Length() > 0) {
				SizeTo(other.Length());
				if (!allocFailure) {
					for (int i=0;i<other.Length();i++)
						v[i] = other.v[i];
				}
				len = other.Length();
			}
		}
		return *this;
	}
	/** @brief Accessor.
	 * Allows to access values from the list, and grows it if accessing
	 * outside the current bounds. The returned value in this case is 0. */
	int &operator[](unsigned int i) {
		if (i >= len) {
			if (i >= size) {
				SizeTo(i);
			}
			len = i+1;
		}
		return v[i];
	}
	/// Reset vector.
	void Free() {
		delete []v;
		v = 0;
		size = 0;
		len = 0;
	}
	/** @brief Grow vector size.
	 * Doesn't allow a vector to be shrinked. */
	void SetLength(unsigned int newLength) {
		if (newLength > len) {
			if (newLength >= size) {
				SizeTo(newLength);
			}
		}
		len = newLength;
	}
	/// Get the current length (number of used elements) of the vector.
	int Length() const {
		return len;
	}
};

#ifdef SCI_NAMESPACE
}
#endif

#endif