Gaia
gvarlengtharray.h
1 /*
2  * Copyright (C) 2006-2013 Music Technology Group - Universitat Pompeu Fabra
3  *
4  * This file is part of Gaia
5  *
6  * Gaia is free software: you can redistribute it and/or modify it under
7  * the terms of the GNU Affero General Public License as published by the Free
8  * Software Foundation (FSF), either version 3 of the License, or (at your
9  * option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14  * details.
15  *
16  * You should have received a copy of the Affero GNU General Public License
17  * version 3 along with this program. If not, see http://www.gnu.org/licenses/
18  */
19 
20 /****************************************************************************
21 **
22 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
23 ** All rights reserved.
24 ** Contact: Nokia Corporation (qt-info@nokia.com)
25 **
26 ** This file is part of the QtCore module of the Qt Toolkit.
27 **
28 ** $QT_BEGIN_LICENSE:LGPL$
29 ** Commercial Usage
30 ** Licensees holding valid Qt Commercial licenses may use this file in
31 ** accordance with the Qt Commercial License Agreement provided with the
32 ** Software or, alternatively, in accordance with the terms contained in
33 ** a written agreement between you and Nokia.
34 **
35 ** GNU Lesser General Public License Usage
36 ** Alternatively, this file may be used under the terms of the GNU Lesser
37 ** General Public License version 2.1 as published by the Free Software
38 ** Foundation and appearing in the file LICENSE.LGPL included in the
39 ** packaging of this file. Please review the following information to
40 ** ensure the GNU Lesser General Public License version 2.1 requirements
41 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
42 **
43 ** In addition, as a special exception, Nokia gives you certain additional
44 ** rights. These rights are described in the Nokia Qt LGPL Exception
45 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
46 **
47 ** GNU General Public License Usage
48 ** Alternatively, this file may be used under the terms of the GNU
49 ** General Public License version 3.0 as published by the Free Software
50 ** Foundation and appearing in the file LICENSE.GPL included in the
51 ** packaging of this file. Please review the following information to
52 ** ensure the GNU General Public License version 3.0 requirements will be
53 ** met: http://www.gnu.org/copyleft/gpl.html.
54 **
55 ** If you have questions regarding the use of this file, please contact
56 ** Nokia at qt-info@nokia.com.
57 ** $QT_END_LICENSE$
58 **
59 ****************************************************************************/
60 
61 #ifndef GAIA_QVARLENGTHARRAY_H
62 #define GAIA_QVARLENGTHARRAY_H
63 
64 #include <QtCore/qcontainerfwd.h>
65 #include <QtCore/qglobal.h>
66 #include <new>
67 #include <cstdlib>
68 
69 QT_BEGIN_HEADER
70 
71 QT_BEGIN_NAMESPACE
72 
73 QT_MODULE(Core)
74 
75 // Prealloc = 256 by default, specified in qcontainerfwd.h
76 template<class T, int Prealloc>
78 {
79 public:
80  inline explicit GVarLengthArray(int size = 0);
81 
82  inline GVarLengthArray(const GVarLengthArray<T, Prealloc> &other)
83  : a(Prealloc), s(0), ptr(reinterpret_cast<T *>(array))
84  {
85  append(other.constData(), other.size());
86  }
87 
88  inline ~GVarLengthArray() {
89  if (QTypeInfo<T>::isComplex) {
90  T *i = ptr + s;
91  while (i-- != ptr)
92  i->~T();
93  }
94  if (ptr != reinterpret_cast<T *>(array))
95  std::free(ptr);
96  }
97  inline GVarLengthArray<T, Prealloc> &operator=(const GVarLengthArray<T, Prealloc> &other)
98  {
99  if (this != &other) {
100  clear();
101  append(other.constData(), other.size());
102  }
103  return *this;
104  }
105 
106  inline void removeLast() {
107  Q_ASSERT(s > 0);
108  realloc(s - 1, a);
109  }
110  inline int size() const { return s; }
111  inline int count() const { return s; }
112  inline bool isEmpty() const { return (s == 0); }
113  inline void resize(int size);
114  inline void clear() { resize(0); }
115 
116  inline int capacity() const { return a; }
117  inline void reserve(int size);
118 
119  inline T &operator[](int idx) {
120  Q_ASSERT(idx >= 0 && idx < s);
121  return ptr[idx];
122  }
123  inline const T &operator[](int idx) const {
124  Q_ASSERT(idx >= 0 && idx < s);
125  return ptr[idx];
126  }
127 
128  inline void append(const T &t) {
129  if (s == a) // i.e. s != 0
130  realloc(s, s<<1);
131  const int idx = s++;
132  if (QTypeInfo<T>::isComplex) {
133  new (ptr + idx) T(t);
134  } else {
135  ptr[idx] = t;
136  }
137  }
138  void append(const T *buf, int size);
139 
140  inline T *data() { return ptr; }
141  inline const T *data() const { return ptr; }
142  inline const T * constData() const { return ptr; }
143 
144 private:
145  void realloc(int size, int alloc);
146 
147  int a;
148  int s;
149  T *ptr;
150  union {
151  // ### Qt 5: Use 'Prealloc * sizeof(T)' as array size
152  char array[sizeof(qint64) * (((Prealloc * sizeof(T)) / sizeof(qint64)) + 1)];
153  qint64 q_for_alignment_1;
154  double q_for_alignment_2;
155  };
156 };
157 
158 template <class T, int Prealloc>
159 Q_INLINE_TEMPLATE GVarLengthArray<T, Prealloc>::GVarLengthArray(int asize)
160  : s(asize) {
161  if (s > Prealloc) {
162  ptr = reinterpret_cast<T *>(std::malloc(s * sizeof(T)));
163  a = s;
164  } else {
165  ptr = reinterpret_cast<T *>(array);
166  a = Prealloc;
167  }
168  if (QTypeInfo<T>::isComplex) {
169  T *i = ptr + s;
170  while (i != ptr)
171  new (--i) T;
172  }
173 }
174 
175 template <class T, int Prealloc>
176 Q_INLINE_TEMPLATE void GVarLengthArray<T, Prealloc>::resize(int asize)
177 { realloc(asize, qMax(asize, a)); }
178 
179 template <class T, int Prealloc>
180 Q_INLINE_TEMPLATE void GVarLengthArray<T, Prealloc>::reserve(int asize)
181 { if (asize > a) realloc(s, asize); }
182 
183 template <class T, int Prealloc>
184 Q_OUTOFLINE_TEMPLATE void GVarLengthArray<T, Prealloc>::append(const T *abuf, int asize)
185 {
186  Q_ASSERT(abuf);
187  if (asize <= 0)
188  return;
189 
190  const int idx = s;
191  const int news = s + asize;
192  if (news >= a)
193  realloc(s, qMax(s<<1, news));
194  s = news;
195 
196  if (QTypeInfo<T>::isComplex) {
197  T *i = ptr + idx;
198  T *j = i + asize;
199  while (i < j)
200  new (i++) T(*abuf++);
201  } else {
202  qMemCopy(&ptr[idx], abuf, asize * sizeof(T));
203  }
204 }
205 
206 template <class T, int Prealloc>
207 Q_OUTOFLINE_TEMPLATE void GVarLengthArray<T, Prealloc>::realloc(int asize, int aalloc)
208 {
209  Q_ASSERT(aalloc >= asize);
210  T *oldPtr = ptr;
211  int osize = s;
212  s = asize;
213 
214  if (aalloc != a) {
215  ptr = reinterpret_cast<T *>(std::malloc(aalloc * sizeof(T)));
216  if (ptr) {
217  a = aalloc;
218 
219  if (QTypeInfo<T>::isStatic) {
220  T *i = ptr + osize;
221  T *j = oldPtr + osize;
222  while (i != ptr) {
223  new (--i) T(*--j);
224  j->~T();
225  }
226  } else {
227  qMemCopy(ptr, oldPtr, osize * sizeof(T));
228  }
229  } else {
230  ptr = oldPtr;
231  s = 0;
232  asize = 0;
233  }
234  }
235 
236  if (QTypeInfo<T>::isComplex) {
237  if (asize < osize) {
238  T *i = oldPtr + osize;
239  T *j = oldPtr + asize;
240  while (i-- != j)
241  i->~T();
242  } else {
243  T *i = ptr + asize;
244  T *j = ptr + osize;
245  while (i != j)
246  new (--i) T;
247  }
248  }
249 
250  if (oldPtr != reinterpret_cast<T *>(array) && oldPtr != ptr)
251  std::free(oldPtr);
252 }
253 
254 QT_END_NAMESPACE
255 
256 QT_END_HEADER
257 
258 #endif // GAIA_QVARLENGTHARRAY_H
Definition: gvarlengtharray.h:77