source: trunk/include/qvaluevector.h@ 81

Last change on this file since 81 was 2, checked in by dmik, 20 years ago

Imported xplatform parts of the official release 3.3.1 from Trolltech

  • Property svn:keywords set to Id
File size: 12.6 KB
Line 
1/****************************************************************************
2** $Id: qvaluevector.h 2 2005-11-16 15:49:26Z dmik $
3**
4** Definition of QValueVector class
5**
6** Copyright (C) 1992-2002 Trolltech AS. All rights reserved.
7**
8** This file is part of the tools module of the Qt GUI Toolkit.
9**
10** This file may be distributed under the terms of the Q Public License
11** as defined by Trolltech AS of Norway and appearing in the file
12** LICENSE.QPL included in the packaging of this file.
13**
14** This file may be distributed and/or modified under the terms of the
15** GNU General Public License version 2 as published by the Free Software
16** Foundation and appearing in the file LICENSE.GPL included in the
17** packaging of this file.
18**
19** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
20** licenses may use this file in accordance with the Qt Commercial License
21** Agreement provided with the Software.
22**
23** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
24** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
25**
26** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
27** information about Qt Commercial License Agreements.
28** See http://www.trolltech.com/qpl/ for QPL licensing information.
29** See http://www.trolltech.com/gpl/ for GPL licensing information.
30**
31** Contact info@trolltech.com if any conditions of this licensing are
32** not clear to you.
33**
34**********************************************************************/
35
36#ifndef QVALUEVECTOR_H
37#define QVALUEVECTOR_H
38
39#ifndef QT_H
40#include "qtl.h"
41#include "qshared.h"
42#include "qdatastream.h"
43#endif // QT_H
44
45#ifndef QT_NO_STL
46#include <vector>
47#endif
48
49template <class T>
50class QValueVectorPrivate : public QShared
51{
52public:
53 typedef T value_type;
54 typedef T* pointer;
55
56 QValueVectorPrivate()
57 : start( 0 ), finish( 0 ), end( 0 )
58 {
59 }
60
61 QValueVectorPrivate( const QValueVectorPrivate<T>& x );
62 QValueVectorPrivate( size_t size );
63
64 void derefAndDelete() // work-around for hp-cc
65 {
66 if ( deref() )
67 delete this;
68 }
69
70#if defined(Q_TEMPLATEDLL)
71 // Workaround MS bug in memory de/allocation in DLL vs. EXE
72 virtual
73#endif
74 ~QValueVectorPrivate()
75 {
76 delete[] start;
77 }
78
79 size_t size() const
80 {
81 return finish - start;
82 }
83
84 bool empty() const
85 {
86 return start == finish;
87 }
88
89 size_t capacity() const
90 {
91 return end - start;
92 }
93
94 void insert( pointer pos, const T& x );
95 void insert( pointer pos, size_t n, const T& x );
96 void reserve( size_t n );
97
98 void clear()
99 {
100 delete[] start;
101 start = 0;
102 finish = 0;
103 end = 0;
104 }
105
106
107 pointer start;
108 pointer finish;
109 pointer end;
110
111private:
112 pointer growAndCopy( size_t n, pointer s, pointer f );
113
114 QValueVectorPrivate<T>& operator=( const QValueVectorPrivate<T>& x );
115
116};
117
118template <class T>
119Q_INLINE_TEMPLATES QValueVectorPrivate<T>::QValueVectorPrivate( const QValueVectorPrivate<T>& x )
120 : QShared()
121{
122 int i = x.size();
123 if ( i > 0 ) {
124 start = new T[ i ];
125 finish = start + i;
126 end = start + i;
127#if defined(__xlC__) && __xlC__ < 0x400 // xlC 3.6 confused by const
128 qCopy( (pointer)x.start, (pointer)x.finish, start );
129#else
130 qCopy( x.start, x.finish, start );
131#endif
132 } else {
133 start = 0;
134 finish = 0;
135 end = 0;
136 }
137}
138
139template <class T>
140Q_INLINE_TEMPLATES QValueVectorPrivate<T>::QValueVectorPrivate( size_t size )
141{
142 if ( size > 0 ) {
143 start = new T[size];
144 finish = start + size;
145 end = start + size;
146 } else {
147 start = 0;
148 finish = 0;
149 end = 0;
150 }
151}
152
153template <class T>
154Q_INLINE_TEMPLATES void QValueVectorPrivate<T>::insert( pointer pos, const T& x )
155{
156 const size_t lastSize = size();
157 const size_t n = lastSize !=0 ? 2*lastSize : 1;
158 const size_t offset = pos - start;
159 pointer newStart = new T[n];
160 pointer newFinish = newStart + offset;
161 qCopy( start, pos, newStart );
162 *newFinish = x;
163 qCopy( pos, finish, ++newFinish );
164 delete[] start;
165 start = newStart;
166 finish = newStart + lastSize + 1;
167 end = newStart + n;
168}
169
170template <class T>
171Q_INLINE_TEMPLATES void QValueVectorPrivate<T>::insert( pointer pos, size_t n, const T& x )
172{
173 if ( size_t( end - finish ) >= n ) {
174 // enough room
175 const size_t elems_after = finish - pos;
176 pointer old_finish = finish;
177 if ( elems_after > n ) {
178 qCopy( finish - n, finish, finish );
179 finish += n;
180 qCopyBackward( pos, old_finish - n, old_finish );
181 qFill( pos, pos + n, x );
182 } else {
183 pointer filler = finish;
184 size_t i = n - elems_after;
185 for ( ; i > 0; --i, ++filler )
186 *filler = x;
187 finish += n - elems_after;
188 qCopy( pos, old_finish, finish );
189 finish += elems_after;
190 qFill( pos, old_finish, x );
191 }
192 } else {
193 // not enough room
194 const size_t lastSize = size();
195 const size_t len = lastSize + QMAX( lastSize, n );
196 pointer newStart = new T[len];
197 pointer newFinish = qCopy( start, pos, newStart );
198 // fill up inserted space
199 size_t i = n;
200 for ( ; i > 0; --i, ++newFinish )
201 *newFinish = x;
202 newFinish = qCopy( pos, finish, newFinish );
203 delete[] start;
204 start = newStart;
205 finish = newFinish;
206 end = newStart + len;
207 }
208}
209
210template <class T>
211Q_INLINE_TEMPLATES void QValueVectorPrivate<T>::reserve( size_t n )
212{
213 const size_t lastSize = size();
214 pointer tmp = growAndCopy( n, start, finish );
215 start = tmp;
216 finish = tmp + lastSize;
217 end = start + n;
218}
219
220template <class T>
221Q_INLINE_TEMPLATES Q_TYPENAME QValueVectorPrivate<T>::pointer QValueVectorPrivate<T>::growAndCopy( size_t n, pointer s, pointer f )
222{
223 pointer newStart = new T[n];
224 qCopy( s, f, newStart );
225 delete[] start;
226 return newStart;
227}
228
229template <class T> class QDeepCopy;
230
231template <class T>
232class QValueVector
233{
234public:
235 typedef T value_type;
236 typedef value_type* pointer;
237 typedef const value_type* const_pointer;
238 typedef value_type* iterator;
239 typedef const value_type* const_iterator;
240 typedef value_type& reference;
241 typedef const value_type& const_reference;
242 typedef size_t size_type;
243#ifndef QT_NO_STL
244 typedef ptrdiff_t difference_type;
245#else
246 typedef int difference_type;
247#endif
248
249 QValueVector()
250 {
251 sh = new QValueVectorPrivate<T>;
252 }
253
254 QValueVector( const QValueVector<T>& v )
255 {
256 sh = v.sh;
257 sh->ref();
258 }
259
260 QValueVector( size_type n, const T& val = T() );
261
262#ifndef QT_NO_STL
263 QValueVector( std::vector<T>& v ) // ### remove in 4.0
264 {
265 sh = new QValueVectorPrivate<T>( v.size() );
266 qCopy( v.begin(), v.end(), begin() );
267 }
268
269 QValueVector( const std::vector<T>& v )
270 {
271 sh = new QValueVectorPrivate<T>( v.size() );
272 qCopy( v.begin(), v.end(), begin() );
273 }
274#endif
275
276 ~QValueVector()
277 {
278 sh->derefAndDelete();
279 }
280
281 QValueVector<T>& operator= ( const QValueVector<T>& v )
282 {
283 v.sh->ref();
284 sh->derefAndDelete();
285 sh = v.sh;
286 return *this;
287 }
288
289#ifndef QT_NO_STL
290 QValueVector<T>& operator= ( const std::vector<T>& v )
291 {
292 clear();
293 resize( v.size() );
294 qCopy( v.begin(), v.end(), begin() );
295 return *this;
296 }
297#endif
298
299 size_type size() const { return sh->size(); }
300
301 bool empty() const { return sh->empty(); }
302
303 size_type capacity() const
304 {
305 return size_type( sh->capacity() );
306 }
307
308 iterator begin()
309 {
310 detach();
311 return sh->start;
312 }
313
314 const_iterator begin() const
315 {
316 return sh->start;
317 }
318
319 const_iterator constBegin() const
320 {
321 return sh->start;
322 }
323
324 iterator end()
325 {
326 detach();
327 return sh->finish;
328 }
329
330 const_iterator end() const
331 {
332 return sh->finish;
333 }
334
335 const_iterator constEnd() const
336 {
337 return sh->finish;
338 }
339
340 reference at( size_type i, bool* ok = 0 )
341 {
342 detach();
343 if ( ok )
344 *ok = ( i < size() );
345 return *( begin() + i );
346 }
347
348 const_reference at( size_type i, bool* ok = 0 ) const
349 {
350 if ( ok )
351 *ok = ( i < size() );
352 return *( begin() + i );
353 }
354
355 reference operator[]( size_type i )
356 {
357 detach();
358 return *( begin() + i );
359 }
360
361 const_reference operator[]( size_type i ) const
362 {
363 return *( begin() + i );
364 }
365
366 reference front()
367 {
368 Q_ASSERT( !empty() );
369 detach();
370 return *begin();
371 }
372
373 const_reference front() const
374 {
375 Q_ASSERT( !empty() );
376 return *begin();
377 }
378
379 reference back()
380 {
381 Q_ASSERT( !empty() );
382 detach();
383 return *( end() - 1 );
384 }
385
386 const_reference back() const
387 {
388 Q_ASSERT( !empty() );
389 return *( end() - 1 );
390 }
391
392 void push_back( const T& x )
393 {
394 detach();
395 if ( sh->finish == sh->end ) {
396 sh->reserve( size()+size()/2+1 );
397 }
398 *sh->finish = x;
399 ++sh->finish;
400 }
401
402 void pop_back()
403 {
404 detach();
405 if ( empty() )
406 return;
407 --sh->finish;
408 }
409
410 iterator insert( iterator pos, const T& x );
411 iterator insert( iterator pos, size_type n, const T& x );
412
413 void reserve( size_type n )
414 {
415 if ( capacity() < n ) {
416 detach();
417 sh->reserve( n );
418 }
419 }
420
421 void resize( size_type n, const T& val = T() )
422 {
423 if ( n < size() )
424 erase( begin() + n, end() );
425 else
426 insert( end(), n - size(), val );
427 }
428
429 void clear()
430 {
431 detach();
432 sh->clear();
433 }
434
435 iterator erase( iterator pos )
436 {
437 detach();
438 if ( pos + 1 != end() )
439 qCopy( pos + 1, sh->finish, pos );
440 --sh->finish;
441 return pos;
442 }
443
444 iterator erase( iterator first, iterator last )
445 {
446 detach();
447 qCopy( last, sh->finish, first );
448 sh->finish = sh->finish - ( last - first );
449 return first;
450 }
451
452 // ### remove in Qt 4.0
453 bool operator==( const QValueVector<T>& x )
454 {
455 return size()==x.size() ? qEqual( constBegin(), constEnd(), x.begin()) : FALSE;
456 }
457
458 bool operator==( const QValueVector<T>& x ) const
459 {
460 return size()==x.size() ? qEqual( begin(), end(), x.begin() ) : FALSE;
461 }
462
463 typedef T ValueType;
464 typedef ValueType *Iterator;
465 typedef const ValueType *ConstIterator;
466
467 size_type count() const { return size(); }
468 bool isEmpty() const { return empty(); }
469
470 reference first() { return front(); }
471 const_reference first() const { return front(); }
472 reference last() { return back(); }
473 const_reference last() const { return back(); }
474 void append( const T& x ) { push_back( x ); }
475
476protected:
477 void detach()
478 {
479 if ( sh->count > 1 ) { detachInternal(); }
480 }
481 void detachInternal();
482 QValueVectorPrivate<T>* sh;
483
484private:
485 friend class QDeepCopy< QValueVector<T> >;
486};
487
488template <class T>
489Q_INLINE_TEMPLATES QValueVector<T>::QValueVector( size_type n, const T& val )
490{
491 sh = new QValueVectorPrivate<T>( n );
492 qFill( begin(), end(), val );
493}
494
495template <class T>
496Q_INLINE_TEMPLATES void QValueVector<T>::detachInternal()
497{
498 sh->deref();
499 sh = new QValueVectorPrivate<T>( *sh );
500}
501
502template <class T>
503Q_INLINE_TEMPLATES Q_TYPENAME QValueVector<T>::iterator QValueVector<T>::insert( iterator pos, const T& x )
504{
505 size_type offset = pos - sh->start;
506 detach();
507 if ( pos == end() ) {
508 if ( sh->finish == sh->end )
509 push_back( x );
510 else {
511 *sh->finish = x;
512 ++sh->finish;
513 }
514 } else {
515 if ( sh->finish == sh->end ) {
516 sh->insert( pos, x );
517 } else {
518 *sh->finish = *(sh->finish - 1);
519 ++sh->finish;
520 qCopyBackward( pos, sh->finish - 2, sh->finish - 1 );
521 *pos = x;
522 }
523 }
524 return begin() + offset;
525}
526
527template <class T>
528Q_INLINE_TEMPLATES Q_TYPENAME QValueVector<T>::iterator QValueVector<T>::insert( iterator pos, size_type n, const T& x )
529{
530 if ( n != 0 ) {
531 size_type offset = pos - sh->start;
532 detach();
533 pos = begin() + offset;
534 sh->insert( pos, n, x );
535 }
536 return pos;
537}
538
539
540#ifndef QT_NO_DATASTREAM
541template<class T>
542Q_INLINE_TEMPLATES QDataStream& operator>>( QDataStream& s, QValueVector<T>& v )
543{
544 v.clear();
545 Q_UINT32 c;
546 s >> c;
547 v.resize( c );
548 for( Q_UINT32 i = 0; i < c; ++i )
549 {
550 T t;
551 s >> t;
552 v[i] = t;
553 }
554 return s;
555}
556
557template<class T>
558Q_INLINE_TEMPLATES QDataStream& operator<<( QDataStream& s, const QValueVector<T>& v )
559{
560 s << (Q_UINT32)v.size();
561 // ### use typename QValueVector<T>::const_iterator once all supported
562 // ### compilers know about the 'typename' keyword.
563 const T* it = v.begin();
564 for( ; it != v.end(); ++it )
565 s << *it;
566 return s;
567}
568#endif // QT_NO_DATASTREAM
569
570#define Q_DEFINED_QVALUEVECTOR
571#include "qwinexport.h"
572#endif // QVALUEVECTOR_H
Note: See TracBrowser for help on using the repository browser.