InDesign SDK  20.5
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
K2STLUtilities.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 // ADOBE CONFIDENTIAL. Portions Copyright 2013 Adobe Systems Incorporated. All rights reserved.
16 //
17 // NOTICE: All information contained herein is, and remain the property of Adobe Systems Incorporated
18 // and its suppliers, if any. The intellectual and technical concepts contained herein are proprietary
19 // to Adobe Systems Incorporated and its suppliers and are protected by all applicable intellectual property
20 // laws, including trade secret and copyright laws. Dissemination of this information or reproduction of
21 // this material is strictly forbidden unless prior written permission is obtained from Adobe Systems Incorporated.
22 //
23 // NOTICE: Adobe permits you to use, modify, and distribute this file in accordance
24 // with the terms of the Adobe license agreement accompanying it. If you have received
25 // this file from a source other than Adobe, then your use, modification, or
26 // distribution of it requires the prior written permission of Adobe.
27 //
28 //
29 // Summary: This file includes implementations of selected algorithms from STL. Normally
30 // the STL versions will work fine. However K2's collection classes contain inline calls
31 // to some of the algorithms. If these algorithms are exported from Public via the explicit
32 // instantiations in templates_pub.cpp the tiniest change in the functions signature could
33 // change the mangled name and break the old plugin.
34 //
35 // Copyright (c) 1994
36 // Hewlett-Packard Company
37 //
38 // Copyright (c) 1996,1997
39 // Silicon Graphics Computer Systems, Inc.
40 //
41 // Copyright (c) 1997
42 // Moscow Center for SPARC Technology
43 //
44 // Copyright (c) 1999
45 // Boris Fomitchev
46 //
47 // This material is provided "as is", with absolutely no warranty expressed
48 // or implied. Any use is at your own risk.
49 //
50 // Permission to use or copy this software for any purpose is hereby granted
51 // without fee, provided the above notices are retained on all copies.
52 // Permission to modify the code and to distribute modified code is granted,
53 // provided the above notices are retained, and a notice that the code was
54 // modified is included with the above copyright notice.
55 //
56 //========================================================================================
57 
58 #ifndef __K2STLUtilities__
59 #define __K2STLUtilities__
60 
61 #include "K2TypeTraits.h"
62 
63 #include "MetaProgramming.h"
64 #include "InterfaceTrackingUtils.h"
65 
66 #if MACINTOSH
67 using std::memset;
68 #endif
69 
70 // ===================================================================================
71 // IsBaseOrOjectType
72 // ===================================================================================
73 template <class T>
74 inline typename PODTraits<T>::data_type IsBaseOrObjectType(const T*)
75 {
76  typedef typename PODTraits<T>::data_type loc_data_type;
77  return loc_data_type();
78 }
79 
80 
81 // ===================================================================================
82 // K2destroy and K2construct
83 // ===================================================================================
84 
85 // ---- __value is a keyword, when compiling with managed code. [amb]
86 
87 template <class T>
88 inline void K2destroy(T* pointer)
89 {
90  ASSERT(pointer != nil);
91  pointer->~T ();
92 }
93 
94 namespace K2Internals {
95  template <class ForwardIterator>
96  inline void destroyAux(ForwardIterator, ForwardIterator, base_type)
97  {
98  }
99 
100  template <class ForwardIterator>
101  inline void destroyAux(ForwardIterator first, ForwardIterator last, object_type)
102  {
103  for(; first < last; ++first)
104  K2destroy(&*first);
105  }
106 } //namespace K2Internals
107 
108 
109 template <class ForwardIterator>
110 inline void K2destroy(ForwardIterator first, ForwardIterator last)
111 {
112  K2Internals::destroyAux(first, last, IsBaseOrObjectType(first));
113 }
114 
115 namespace K2Internals {
116  template <class _T1, class _T2>
117  inline void _K2Construct(_T1* __p, const _T2& __v) {
118  new (__p) _T1(__v);
119  }
120 
121  template <class _T1>
122  inline void _K2Construct(_T1* __p) {
123  new (__p) _T1();
124  }
125 
126 } //namespace K2Internals
127 
128 template <class _T1, class _T2>
129 inline void K2construct(_T1* __p, const _T2& __v) {
130  K2Internals::_K2Construct(__p, __v);
131 }
132 
133 template <class _T1>
134 inline void K2construct(_T1* __p) {
135  K2Internals::_K2Construct(__p);
136 }
137 
138 // ===================================================================================
139 // K2fill and family
140 // ===================================================================================
141 
142 template <class _ForwardIter, class _Tp>
143 void K2fill(_ForwardIter __first, _ForwardIter __last, const _Tp& __v) {
144  for ( ; __first != __last; ++__first)
145  *__first = __v;
146 }
147 
148 template <class _OutputIter, class _Size, class _Tp>
149 _OutputIter K2fill_n(_OutputIter __first, _Size __n, const _Tp& __v) {
150  for ( ; __n > 0; --__n, ++__first)
151  *__first = __v;
152  return __first;
153 }
154 
155 
156 // Specialization: for one-byte types we can use memset.
157 
158 inline void K2fill(unsigned char* __first, unsigned char* __last,
159  const unsigned char& __c) {
160  unsigned char __tmp = __c;
161  memset(__first, __tmp, __last - __first);
162 }
163 
164 inline void K2fill(signed char* __first, signed char* __last,
165  const signed char& __c) {
166  signed char __tmp = __c;
167  memset(__first, static_cast<unsigned char>(__tmp), __last - __first);
168 }
169 
170 inline void K2fill(char* __first, char* __last, const char& __c) {
171  char __tmp = __c;
172  memset(__first, static_cast<unsigned char>(__tmp), __last - __first);
173 }
174 
175 //
176 
177 
178 // ===================================================================================
179 // K2uninitialized_fill and family
180 // ===================================================================================
181 
182 namespace K2Internals {
183 // Valid if copy construction is equivalent to assignment, and if the
184 // destructor is trivial.
185  template <class _ForwardIter, class _Tp>
186  inline void
187  __uninitialized_fill_aux(_ForwardIter __first, _ForwardIter __last,
188  const _Tp& __x, K2Meta::META_TRUE)
189  {
190  K2fill(__first, __last, __x);
191  }
192 
193  template <class _ForwardIter, class _Tp>
194  void
195  __uninitialized_fill_aux(_ForwardIter __first, _ForwardIter __last,
196  const _Tp& __x, K2Meta::META_FALSE)
197  {
198  _ForwardIter __cur = __first;
199  for ( ; __cur != __last; ++__cur)
200  K2construct(&*__cur, __x);
201  }
202 
203 
204  // Valid if copy construction is equivalent to assignment, and if the
205  // destructor is trivial.
206  template <class _ForwardIter, class _Size, class _Tp>
207  inline _ForwardIter
208  __uninitialized_fill_n_aux(_ForwardIter __first, _Size __n,
209  const _Tp& __x, K2Meta::META_TRUE)
210  {
211  return K2fill_n(__first, __n, __x);
212  }
213 
214  template <class _ForwardIter, class _Size, class _Tp>
215  _ForwardIter
216  __uninitialized_fill_n_aux(_ForwardIter __first, _Size __n,
217  const _Tp& __x, K2Meta::META_FALSE)
218  {
219  _ForwardIter __cur = __first;
220  for ( ; __n > 0; --__n, ++__cur)
221  K2Internals::_K2Construct(&*__cur, __x);
222  return __cur;
223  }
224 
225 } //namespace K2Internals
226 
227 template <class _ForwardIter, class _Tp>
228 inline void K2uninitialized_fill(_ForwardIter __first,
229  _ForwardIter __last,
230  const _Tp& __x)
231 {
232  //$$$ Could do better: _ForwardIter doesn't have to be a POD ptr. Need metafunction IS_POD_ITER
233  K2Internals::__uninitialized_fill_aux(__first, __last, __x, K2Meta::BOOL_TO_TYPE<K2Meta::IS_POD_PTR<_ForwardIter>::RET>::RET());
234 }
235 
236 template <class _ForwardIter, class _Size, class _Tp>
237 inline _ForwardIter
238 K2uninitialized_fill_n(_ForwardIter __first, _Size __n, const _Tp& __x)
239 {
240  //$$$ Could do better: _ForwardIter doesn't have to be a POD ptr. Need metafunction IS_POD_ITER
241  typedef typename K2Meta::BOOL_TO_TYPE<K2Meta::IS_POD_PTR<_ForwardIter>::RET>::RET loc_tag;
242  return K2Internals::__uninitialized_fill_n_aux(__first, __n, __x, loc_tag()
243  );
244 }
245 
246 
247 
248 
249 
250 
251 namespace K2Internals {
252  template <class InputIter, class ForwardIter>
253  struct SafeCopy {
254  static ForwardIter copy(InputIter first, InputIter last, ForwardIter result);
255  static ForwardIter copy_backward(InputIter first, InputIter last, ForwardIter result);
256  static ForwardIter uninitialized_copy(InputIter first, InputIter last, ForwardIter result);
257  };
258 
259  template <class InputIter, class ForwardIter>
260  struct FastCopy {
261  static ForwardIter copy(InputIter first, InputIter last, ForwardIter result);
262  static ForwardIter copy_backward(InputIter first, InputIter last, ForwardIter result);
263  static ForwardIter uninitialized_copy(InputIter first, InputIter last, ForwardIter result);
264  };
265 
266 }
267 
268 
269 
270 namespace K2Internals {
271  template <class InputIter, class ForwardIter>
272  inline ForwardIter SafeCopy<InputIter, ForwardIter>::copy(InputIter first, InputIter last, ForwardIter result)
273  {
274  for (; first != last; ++first, ++result) // object type
275  *result = *first;
276  return result;
277  }
278 
279 
280  template <class InputIter, class ForwardIter>
281  inline ForwardIter SafeCopy<InputIter, ForwardIter>::copy_backward(InputIter first, InputIter last, ForwardIter result)
282  {
283  while (last != first) // object type or custom iterators
284  *--result = *--last;
285  return result;
286  }
287 
288 
289  template <class InputIter, class ForwardIter>
290  inline ForwardIter SafeCopy<InputIter, ForwardIter>::uninitialized_copy(InputIter first, InputIter last, ForwardIter result)
291  {
292  return std::uninitialized_copy(first, last, result);
293  }
294 
295 
296  class FastCopy_on_bad_types { // not instantiable (private default ctor)
298  };
299 
300  template <class InputIter, class ForwardIter>
301  inline ForwardIter FastCopy<InputIter, ForwardIter>::copy(InputIter first, InputIter last, ForwardIter result)
302  {
303  using namespace K2Meta;
304  META_ASSERT<IS_PTR<InputIter>::RET
308  && sizeof(*first) == sizeof(*result),
310  std::ptrdiff_t count = last - first; // POD type and pointer iterators
311  std::memmove((void*) result, (void*) first, count*sizeof(*first));
312  return result + count;
313  }
314  template <class InputIter, class ForwardIter>
315  inline ForwardIter FastCopy<InputIter, ForwardIter>::copy_backward(InputIter first, InputIter last, ForwardIter result)
316  {
317  using namespace K2Meta;
318  META_ASSERT<IS_PTR<InputIter>::RET
322  && sizeof(*first) == sizeof(*result),
323  FastCopy_on_bad_types>();
324  std::ptrdiff_t count = last - first; // POD type and pointer iterators
325  std::memmove((void*) (result - count), (void*) first, count*sizeof(*first));
326  return result - count;
327  }
328 
329  template <class InputIter, class ForwardIter>
330  inline ForwardIter FastCopy<InputIter, ForwardIter>::uninitialized_copy(InputIter first, InputIter last, ForwardIter result)
331  {
332  using namespace K2Meta;
333  META_ASSERT<IS_PTR<InputIter>::RET
337  && sizeof(*first) == sizeof(*result),
338  FastCopy_on_bad_types>();
339  std::ptrdiff_t count = last - first; // POD type and pointer iterators
340  std::memmove((void*) result, (void*) first, count*sizeof(*first));
341  return result + count;
342  }
343 }
344 
345 template <class InputIter, class ForwardIter>
346 inline ForwardIter K2copy(InputIter first, InputIter last, ForwardIter result)
347 {
348  using namespace K2Meta;
353  && sizeof(*first) == sizeof(*result),
356  >::RET::copy(first, last, result);
357 }
358 
359 
360 
361 // ===================================================================================
362 // K2uninitialized_copy
363 // ===================================================================================
364 
365 template <class InputIter, class ForwardIter>
366 inline ForwardIter K2uninitialized_copy(InputIter first, InputIter last, ForwardIter result)
367 {
368  using namespace K2Meta;
373  && sizeof(*first) == sizeof(*result),
376  >::RET::uninitialized_copy(first, last, result);
377 }
378 
379 
380 // ===================================================================================
381 // K2copy_backward
382 // ===================================================================================
383 
384 
385 template <class InputIter, class ForwardIter>
386 inline ForwardIter K2copy_backward(InputIter first, InputIter last, ForwardIter result)
387 {
388  using namespace K2Meta;
393  && sizeof(*first) == sizeof(*result),
396  >::RET::copy_backward(first, last, result);
397 }
398 
399 
400 
401 // ===================================================================================
402 // Shrink
403 // Releases the memory consumed by the container's reserve bytes.
404 // ===================================================================================
405 template <class CONTAINER>
406 void Shrink(CONTAINER& c, int32 newlen)
407 {
408  ASSERT_MSG(newlen >= c.size(), "Shrink: newlen is too small");
409  ASSERT_MSG(newlen <= c.capacity(), "Shrink: newlen is too large");
410 
411  if (newlen < c.capacity()) {
412  CONTAINER temp;
413  temp.reserve(newlen);
414  temp.assign(c.begin(), c.begin() + c.size());
415 
416  c.swap(temp); // this looks a bit odd, but it's just as efficient as the more cumbersome hand-coded version
417  }
418 }
419 
420 
421 // ===================================================================================
422 // K2EmptyMemberOpt
423 // A helper class for Nathan Myers empty member optimization. See for example
424 // <http://www.cantrip.org/emptyopt.html>. The purpose is to save 4 bytes in
425 // classes which have an empty class as a member. We use it in K2vector. The
426 // fAllocatedSize member shares space with the (empty) fAllocator member.
427 // ===================================================================================
428 template <class Base, class Member>
429 struct K2EmptyMemberOpt : public Base
430 {
432  K2EmptyMemberOpt(Base const & base);
433  K2EmptyMemberOpt(Base const & base, Member const& member);
434 
435  Member f;
436 };
437 
438 template <class Base, class Member>
440  : Base(Base()),
441  f(Member())
442 {
443 }
444 
445 template <class Base, class Member>
446 inline K2EmptyMemberOpt<Base, Member>::K2EmptyMemberOpt(Base const & base)
447  : Base(base),
448  f(Member())
449 {
450 }
451 
452 template <class Base, class Member>
453 inline K2EmptyMemberOpt<Base, Member>::K2EmptyMemberOpt(Base const & base, Member const& member)
454  : Base(base),
455  f(member)
456 {
457 }
458 
459 
460 // ===================================================================================
461 // K2find
462 // ===================================================================================
463 #ifndef INTERFACEPROXIES_SUPPORTED
464 template <class InputIterator, class T>
465 inline InputIterator // in release builds the codegen is quite a bit better when this is inline
466 K2find(InputIterator first, InputIterator last, const T& value)
467 {
468  while (first != last && !(*first == value))
469  ++first;
470  return first;
471 }
472 #else
473 // this should be used from main thread only. That is only what makes it thread safe.
474 extern bool16 ts_tkSupportInterfaceProxies;
475 
476 template <class InputIterator, class T>
477 class NotPtr_K2Find
478 {
479 public:
480  static InputIterator execute(InputIterator first, InputIterator last, const T& value);
481 };
482 
483 template <class InputIterator, class T>
484 inline InputIterator NotPtr_K2Find<InputIterator, T>::execute(InputIterator first, InputIterator last, const T& value)
485  {
486  while (first != last && !(*first == value))
487  ++first;
488  return first;
489  }
490 
491 template <class InputIterator, class T>
492 class Ptr_K2Find
493 {
494 public:
495  static InputIterator execute(InputIterator first, InputIterator last, const T& value);
496 };
497 
498 template <class InputIterator, class T>
499 InputIterator Ptr_K2Find<InputIterator, T>:: execute(InputIterator first, InputIterator last, const T& value)
500 {
501  if (ts_tkSupportInterfaceProxies) {
502  while (first != last &&
503  (InterfaceTrackingUtils::ExtractInterfaceImplementation (*first) !=
504  InterfaceTrackingUtils::ExtractInterfaceImplementation (value)))
505  ++first;
506  return first;
507  }
508  return
509  NotPtr_K2Find<InputIterator,T>::execute(first, last, value);
510 }
511 
512 
513 template <class InputIterator, class T>
514 inline InputIterator
515 K2find(InputIterator first, InputIterator last, const T& value)
516 {
518  Ptr_K2Find<InputIterator,T>,
519  NotPtr_K2Find<InputIterator,T> >::RET::execute(first, last, value);
520 }
521 
522 #endif
523 
524 template <typename CONTAINER, class T>
525 inline typename CONTAINER::iterator
526 K2find(CONTAINER& c, const T& value)
527 {
528  return K2find(c.begin(), c.end(), value);
529 }
530 
531 template <typename CONTAINER, class T>
532 inline typename CONTAINER::const_iterator
533 K2find(const CONTAINER& c, const T& value)
534 {
535  return K2find(c.begin(), c.end(), value);
536 }
537 
538 template <class InputIterator, class T>
539 inline bool
540 K2notfound(InputIterator first, InputIterator last, const T& value)
541 {
542  return (std::find(first, last, value) == last);
543 }
544 
545 template <typename CONTAINER, class T>
546 inline bool
547 K2notfound(const CONTAINER& c, const T& value)
548 {
549  return (std::find(std::begin(c), std::end(c), value) == std::end(c));
550 }
551 
552 template <class InputIterator, class T>
553 inline bool
554 K2found(InputIterator first, InputIterator last, const T& value)
555 {
556  return (std::find(first, last, value) != last);
557 }
558 
559 template <typename CONTAINER, class T>
560 inline bool
561 K2found(const CONTAINER& c, const T& value)
562 {
563  return (std::find(std::begin(c), std::end(c), value) != std::end(c));
564 }
565 
566 #ifdef ID_DEPRECATED
567 // Temporarily added function K2location as an out-of-class
568 // replacement for deprecated K2Vector method Location.
569 // Only use it where actual location index was intended to
570 // be used. Otherwise, use K2found or K2notfound where
571 // existence or non-existence in container is to be checked.
572 // Though a large function, defining it in the header
573 // could help avoid clients declaring operator == for
574 // the type being searched for.
575 // Only tested for K2Vector.
576 template <typename CONTAINER, class T>
577 inline int32 K2location(const CONTAINER& c, const T& value)
578 {
579  typename CONTAINER::const_iterator i = std::find(c.begin(), c.end(), value);
580  int32 index = i != c.end() ? i - c.begin() : -1;
581  return index;
582 }
583 
584 // Temporarily added function K2length to replace K2Vector deprecated Length API and to
585 // convert size_type value returned by size() API to int32.
586 // When we clean up the data types to replace signed int32 with actual size_type, this API should
587 // also be removed. It is needed currently because some existing code compares int32 value of -1
588 // with the value returned by Length() API, which also returns an int32 value. If the Length()
589 // API was replaced with size() API directly, the return type would become K2Vector's size_type,
590 // which is uint32. In this case, the compiler would convert the int32 value of -1 being compared
591 // to the maximum possible value for uint32.
592 // So a comparison like (val < k2vec.Length()) which would have succeeded for val == -1,
593 // would start failing if the replacement code is (val < k2vec.size()) because -1 would get converted
594 // to maximum possible value of uint32. To avoid this until the int32 cleanup happens across the code base,
595 // one would need to use static_cast<int32>(k2vec.size()).
596 // This function is provided as a simpler notation than repeatedly writing static_cast<int32>(k2vec.size()).
597 template <typename CONTAINER>
598 inline int32 K2length(const CONTAINER& c)
599 {
600  return static_cast<int32>(c.size());
601 }
602 
603 #endif //ID_DEPRECATED
604 
605 #endif //__K2STLUtilities__