InDesign SDK  20.5
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
K2VectorBase.h
1 //========================================================================================
2 //
3 // $File$
4 //
5 // Owner: Mat Marcus and Jesse Jones
6 //
7 // $Author$
8 //
9 // $DateTime$
10 //
11 // $Revision$
12 //
13 // $Change$
14 //
15 // Copyright 1997-2010 Adobe Systems Incorporated. All rights reserved.
16 //
17 // NOTICE: Adobe permits you to use, modify, and distribute this file in accordance
18 // with the terms of the Adobe license agreement accompanying it. If you have received
19 // this file from a source other than Adobe, then your use, modification, or
20 // distribution of it requires the prior written permission of Adobe.
21 //
22 //
23 // Summary: K2Vector is an implementation of STL's vector class with two differences:
24 // 1) the K2Vector(uint32) ctor reserves space instead of resizing the array 2) a number
25 // of deprecated methods have been added for backward compatibility.
26 //
27 // So, why do we need to define our own vector class? The problem with the compiler provided
28 // STL implementations is that they are not interface classes and we have no control over the
29 // implementation. So, if an interface in Public returns a reference to a std::vector a plugin
30 // compiled with a different version of the compiler may experience difficulties since the
31 // internals of the vector may have changed.
32 //
33 //========================================================================================
34 
35 #ifndef __K2VectorBase__
36 #define __K2VectorBase__
37 
38 #include <algorithm>
39 #include <typeinfo>
40 #include <limits>
41 #include <cstddef>
42 #include "K2Assert.h"
43 #include "K2Allocator.h"
44 #include "K2Iterator.h"
45 #include "MetaProgramming.h"
46 #include "K2VectorHelpers.h"
47 
48 namespace K2Meta {
49 
50  template <typename T>
51  struct IS_INTEGER {
52  enum { RET = std::numeric_limits<T>::is_integer};
53  };
54 
55  template <typename T, typename U>
56  struct ITER_TAG_EQUALS {
58  };
59 
60  template <typename T>
62  typedef typename IF_IS_PTR<T,
63  META_FALSE,
65  //IS_SAME_TYPE<std::input_iterator_tag, std::iterator_traits<T>::iterator_category>
66  >::RET RESULT;
67  public:
68  enum { RET = RESULT::RET};
69  };
70 
71 }
72 
73 template <class T, class A>
74 class K2Vector;
75 
76 namespace K2Internals {
77 // ===================================================================================
78 // K2VectorBase
79 // ===================================================================================
80 
81 
83 
84  template <typename Arg>
85  struct GET_ITER_TAG {
89  >::RET RET;
90  };
91 
92  template <typename Arg>
93  struct CHOOSE_HELPER {
97  >::RET RESULT1; // introduce a dummy typedef for MSVC...
98  typedef typename RESULT1::RET RET;
99  };
100 
101 
102 template <class T, class Allocator = K2Allocator<T> >
104  enum { kInitialAllocSize = 8};
105  friend class K2Vector<T, Allocator>;
106 public:
107  typedef object_type data_type;
108 
109  typedef T value_type;
110  typedef value_type* pointer;
111  typedef const value_type* const_pointer;
112  typedef value_type* iterator;
113  typedef const value_type* const_iterator;
114  typedef value_type& reference;
115  typedef const value_type& const_reference;
116  typedef uint32 size_type;
117  typedef std::ptrdiff_t difference_type;
118  typedef Allocator allocator_type;
119 
122 
123 
124  ~K2VectorBase() {this->DoCleanup();}
125 
126 public:
127  explicit K2VectorBase(const Allocator& a = Allocator());
128  K2VectorBase(size_type count, const T& value, const Allocator& a = Allocator());
129 
130 
131 
132 
133 
134 
135 
136  template <class InputIterator>
137  K2VectorBase(InputIterator first, InputIterator last, const Allocator& a)
138  : fAllocator(a)
139  {
140  fArray = InitialArrayValue();
141  fLength = 0;
142  VectorHelpers::initialize(first, last, this, Hole(), typename CHOOSE_HELPER<InputIterator>::RET());
143 
144  }
145 
146  template <class InputIterator>
147  K2VectorBase(InputIterator first, InputIterator last)
148  : fAllocator(Allocator())
149  {
150  fArray = InitialArrayValue();
151  fLength = 0;
152  VectorHelpers::initialize(first, last, this, Hole(), typename CHOOSE_HELPER<InputIterator>::RET());
153  }
154 
155 
156  void initialize(size_type count, const T& value);
157  void fill_assign(size_type, const T&);
158  void fill_insert(iterator, size_type, const T&);
159 
160 
161 
162  class Hole;
163  friend class K2VectorBase<T, Allocator>::Hole;
164  class Hole { // used by 'K2VectorHelpers.h" to get at the K2Vector internals
165  friend class K2VectorBase<T, Allocator>;
166  public:
168  { return v->fAllocator; }
169  size_type& LengthRef(K2VectorBase<T, Allocator>* v)
170  { return v->fLength; }
171  pointer& ArrayRef(K2VectorBase<T, Allocator>* v)
172  { return v->fArray; }
173  static inline size_type InitialAllocSize()
175  private:
176  Hole() {}
177  };
178 
179 
180  K2VectorBase(const K2VectorBase& rhs);
181  K2VectorBase(K2VectorBase&& rhs) noexcept
182  : fAllocator(rhs.fAllocator),
183  fLength(rhs.fLength),
184  fArray(nil)
185  {
186  if (rhs.fArray == (pointer)rhs.fPrivateBuffer)
187  {
188  memcpy(fPrivateBuffer, rhs.fPrivateBuffer, kPrivateBufferBytes);
189  fArray = (pointer)fPrivateBuffer;
190  }
191  else
192  fArray = rhs.fArray;
193  rhs.fLength = 0;
194  rhs.fArray = nil;
195  }
196 
197  void CopyConstructHelper(const K2VectorBase& rhs);
198 
199 public:
200  iterator begin() {return fArray;}
201  const_iterator begin() const {return fArray;}
202  iterator end() {return fArray + fLength;}
203  const_iterator end() const {return fArray + fLength;}
204  reverse_iterator rbegin() {return reverse_iterator(end());}
205  const_reverse_iterator rbegin() const {return const_reverse_iterator(end());}
206  reverse_iterator rend() {return reverse_iterator(begin());}
207  const_reverse_iterator rend() const {return const_reverse_iterator(begin());}
208 
209  size_type size() const {return fLength;}
210  size_type max_size() const {return static_cast<size_type>(fAllocator.max_size());}
211  size_type capacity() const {return fArray == (pointer)fPrivateBuffer ? kPrivateBufferBytes / sizeof (value_type) : fAllocator.f;}
212  bool16 empty() const {return fLength == 0;}
213 
214  allocator_type get_allocator() const {return fAllocator;}
215  K2VectorBase& operator=(const K2VectorBase& rhs)
216  {
217  if (this != &rhs)
218  assign(rhs.begin(), rhs.end());
219 
220  return *this;
221  }
222 
223  K2VectorBase& operator=(K2VectorBase&& rhs) noexcept
224  {
225  this->swap(rhs);
226  return *this;
227  }
228  void reserve(size_type capacity);
229 
230  template <class InputIter>
231  void assign(InputIter first, InputIter last)
232  {
233  VectorHelpers::assign(first, last, this, Hole(), typename CHOOSE_HELPER<InputIter>::RET());
234  }
235  void assign(size_type count, const T& u) { fill_assign(count, u); }
236 
237 
238  reference operator[](size_type i) {ASSERT(i < fLength); return fArray[i];}
239  const_reference operator[](size_type i) const {ASSERT(i < fLength); return fArray[i];}
240  const_reference at(size_type i) const {ASSERT(i < fLength); return fArray[i];}
241  reference at(size_type i) {ASSERT(i < fLength); return fArray[i];}
242  reference front() {ASSERT(fLength > 0); return fArray[0];}
243  const_reference front() const {ASSERT(fLength > 0); return fArray[0];}
244  reference back() {ASSERT(fLength > 0); return fArray[fLength - 1];}
245  const_reference back() const {ASSERT(fLength > 0); return fArray[fLength - 1];}
246 
247  void push_back(const T& x);
248  void pop_back();
249  iterator insert(iterator position, const T& x);
250  void insert(iterator position, size_type n, const T& x);
251  template <class InputIter>
252  void insert(iterator pos, InputIter first, InputIter last)
253  {
254  VectorHelpers::insert(pos, first, last, this, Hole(), typename CHOOSE_HELPER<InputIter>::RET());
255  }
256  iterator erase(iterator position);
257  iterator erase(iterator first, iterator last);
258  void swap(K2VectorBase&) noexcept;
259  void clear();
260  //void resize(size_type sz);
261  void resize(size_type newsize, const T& value);
262 
263 // void PreventInstantiation() {fAllocator.Instantiate_K2Vector_Not_K2VectorBase();}
264 
265 public: // can't be private: the methods aren't exported on Windows
266  void DoCleanup();
267  size_type DoGetCapacity(size_type newLength);
268  void DoReset(pointer newData, size_type newLength, size_type newCap);
269 
270 private:
271  K2EmptyMemberOpt<Allocator, size_type> fAllocator; // f is capacity, except when fArray is fPrivateBuffer
272  size_type fLength;
273  pointer fArray;
274 
275  enum {kPrivateBufferBytes = 32};
276 
277  union {
278  double forAlignmentPurposes;
279  char fPrivateBuffer [kPrivateBufferBytes];
280  };
281 
282  pointer InitialArrayValue() const { return kPrivateBufferBytes / sizeof (value_type) ? (pointer)fPrivateBuffer : 0; }
283 };
284 
285 // ===================================================================================
286 // Inlines
287 // ===================================================================================
288 template <typename T>
289 inline bool16 operator==(const K2VectorBase<T>& lhs, const K2VectorBase<T>& rhs) {return lhs.size() == rhs.size() && std::equal(lhs.begin(), lhs.end(), rhs.begin());}
290 
291 template <typename T>
292 inline bool16 operator!=(const K2VectorBase<T>& lhs, const K2VectorBase<T>& rhs) {return !(lhs == rhs);}
293 
294 template <typename T>
295 inline bool16 operator< (const K2VectorBase<T>& lhs, const K2VectorBase<T>& rhs) {return std::lexicographical_compare(lhs.begin(), lhs.end(), rhs.begin(), rhs.end());}
296 
297 template <typename T>
298 inline bool16 operator> (const K2VectorBase<T>& lhs, const K2VectorBase<T>& rhs) {return rhs < lhs;}
299 
300 template <typename T>
301 inline bool16 operator>=(const K2VectorBase<T>& lhs, const K2VectorBase<T>& rhs) {return !(lhs < rhs);}
302 
303 template <typename T>
304 inline bool16 operator<=(const K2VectorBase<T>& lhs, const K2VectorBase<T>& rhs) {return !(rhs < lhs);}
305 
306 template <class T, class Allocator>
307 inline K2VectorBase<T, Allocator>::K2VectorBase(const K2Internals::K2VectorBase<T, Allocator>& rhs)
308  : fAllocator(rhs.fAllocator, rhs.fLength)
309 {
310  CopyConstructHelper(rhs);
311 }
312 
313 template <class T, class Allocator>
314 inline K2VectorBase<T, Allocator>::K2VectorBase(const Allocator& a)
315  : fAllocator(a),
316  fLength(0),
317  fArray(InitialArrayValue())
318 {
319 }
320 
321 template <class T, class Allocator>
322 inline K2VectorBase<T, Allocator>::K2VectorBase(size_type n, const T& value, const Allocator& a)
323  : fAllocator(a),
324  fLength(0),
325  fArray(InitialArrayValue())
326 {
327  initialize(n, value);
328 }
329 
330 
331 
332 template <class T, class Allocator>
333 inline typename K2VectorBase<T, Allocator>::iterator
334 K2VectorBase<T, Allocator>::insert(iterator position, const T& x)
335 {
336  size_type pos = size_type(position - fArray);
337  insert(position, 1, x);
338  return fArray + pos;
339 }
340 
341 
342 template <class T, class Allocator>
343 inline void
344 K2VectorBase<T, Allocator>::insert(iterator position, size_type count, const T& x)
345 {
346  fill_insert(position, count, x);
347 }
348 
349 template <class T, class Allocator>
350 inline void swap(K2VectorBase<T, Allocator>& x, K2VectorBase<T, Allocator>& y) noexcept
351 {
352  x.swap(y);
353 }
354 }//namespace K2Internals
355 
356 #endif // __K2VectorBase__
357