16 #ifndef __AUTOMATION_VECTOR_H__
17 #define __AUTOMATION_VECTOR_H__
23 #define automation_vector std::vector
37 #pragma warning(disable : 4786)
46 template <
bool>
struct static_checker;
47 template <>
struct static_checker<true> {};
51 template <VARENUM varenum>
52 struct static_variant_info
54 enum { vt = varenum };
64 : vt == VT_DISPATCH ? 8
65 : vt == VT_UNKNOWN ? 8
68 : vt == VT_DISPATCH ? 4
69 : vt == VT_UNKNOWN ? 4
71 : vt == VT_VARIANT ? 16
74 static char size_checker[
83 : vt == VT_DISPATCH ? 8
84 : vt == VT_UNKNOWN ? 8
87 : vt == VT_DISPATCH ? 4
88 : vt == VT_UNKNOWN ? 4
90 : vt == VT_VARIANT ? 16
96 static_variant_info<VT_I1> deduceVARENUM(
char);
97 static_variant_info<VT_I1> deduceVARENUM(
signed char);
98 static_variant_info<VT_I1> deduceVARENUM(
unsigned char);
99 static_variant_info<VT_I2> deduceVARENUM(
short);
100 static_variant_info<VT_I2> deduceVARENUM(
unsigned short);
101 static_variant_info<VT_I4> deduceVARENUM(
int);
102 static_variant_info<VT_I4> deduceVARENUM(
unsigned int);
103 static_variant_info<VT_I4> deduceVARENUM(
long);
104 static_variant_info<VT_I4> deduceVARENUM(
unsigned long);
105 static_variant_info<VT_R4> deduceVARENUM(
float);
106 static_variant_info<VT_R8> deduceVARENUM(
double);
107 static_variant_info<VT_CY> deduceVARENUM(CURRENCY);
108 static_variant_info<VT_BSTR> deduceVARENUM(BSTR);
109 static_variant_info<VT_DISPATCH> deduceVARENUM(IDispatch *);
110 static_variant_info<VT_UNKNOWN> deduceVARENUM(IUnknown *);
111 static_variant_info<VT_VARIANT> deduceVARENUM(VARIANT);
112 static_variant_info<VT_VARIANT> deduceVARENUM(automation_vector_base);
119 friend void trace(VARIANT &v);
120 typedef automation_vector_base
self;
123 void swap(
self &that)
126 _ASSERT(that.valid());
127 std::swap(static_cast<VARIANT &>(m_Value),
128 static_cast<VARIANT &>(that.m_Value));
132 void attach(VARIANT &v) ;
135 void detach(VARIANT &v) ;
143 array_lock(SAFEARRAY &a) : pArray(&a)
144 { self::com_enforce(::SafeArrayLock(pArray)); }
145 void leave_ownership()
148 {
if (pArray && FAILED(::SafeArrayUnlock(pArray))) _ASSERT(
false); }
150 typedef size_t size_type;
151 typedef ptrdiff_t difference_type;
157 long low_bound() const
160 return empty() ? 0 : bounds().lLbound;
162 void low_bound(
long NewValue)
166 throw std::runtime_error(
"Cannot set lower bound on an empty array");
167 bounds().lLbound = NewValue;
170 long up_bound() const
175 const SAFEARRAYBOUND &Bounds = bounds();
176 return Bounds.lLbound + Bounds.cElements - 1;
178 VARTYPE plain_vartype()
const
182 static void com_enforce(HRESULT hr) ;
187 return m_Value.vt == VT_EMPTY ? 0 : bounds().cElements;
189 size_t capacity() const
198 ~automation_vector_base() ;
200 enum TCreateMode { MOVE, COPY };
203 self(
unsigned Elements, VARENUM VarType)
207 return array(m_Value);
209 const SAFEARRAY &array() const
211 return array(m_Value);
213 SAFEARRAYBOUND &bounds()
215 return array().rgsabound[0];
217 const SAFEARRAYBOUND &bounds() const
219 return array().rgsabound[0];
221 void resize(size_type NewSize, VARENUM
Type);
224 _ASSERT(!V_ISBYREF(&m_Value));
225 _ASSERT(empty() || array().cLocks == 0);
226 com_enforce(::VariantClear(&m_Value));
228 static void get_element(
const VARIANT &Array,
long Index, VARIANT &v)
230 static void put_element(VARIANT &Array,
long Index,
const VARIANT &v)
233 static SAFEARRAY &array(
const VARIANT &v)
235 _ASSERT(V_ISARRAY(&v));
236 _ASSERT(!V_ISBYREF(&v));
246 inline static_variant_info<VT_I1> deduceVARENUM(
char)
247 {
return static_variant_info<VT_I1>(); }
248 inline static_variant_info<VT_I1> deduceVARENUM(
signed char)
249 {
return static_variant_info<VT_I1>(); }
250 inline static_variant_info<VT_I1> deduceVARENUM(
unsigned char)
251 {
return static_variant_info<VT_I1>(); }
252 inline static_variant_info<VT_I2> deduceVARENUM(
short)
253 {
return static_variant_info<VT_I2>(); }
254 inline static_variant_info<VT_I2> deduceVARENUM(
unsigned short)
255 {
return static_variant_info<VT_I2>(); }
256 inline static_variant_info<VT_I4> deduceVARENUM(
int)
257 {
return static_variant_info<VT_I4>(); }
258 inline static_variant_info<VT_I4> deduceVARENUM(
unsigned int)
259 {
return static_variant_info<VT_I4>(); }
260 inline static_variant_info<VT_I4> deduceVARENUM(
long)
261 {
return static_variant_info<VT_I4>(); }
262 inline static_variant_info<VT_I4> deduceVARENUM(
unsigned long)
263 {
return static_variant_info<VT_I4>(); }
264 inline static_variant_info<VT_R4> deduceVARENUM(
float)
265 {
return static_variant_info<VT_R4>(); }
266 inline static_variant_info<VT_R8> deduceVARENUM(
double)
267 {
return static_variant_info<VT_R8>(); }
268 inline static_variant_info<VT_CY> deduceVARENUM(CURRENCY)
269 {
return static_variant_info<VT_CY>(); }
270 inline static_variant_info<VT_BSTR> deduceVARENUM(BSTR)
271 {
return static_variant_info<VT_BSTR>(); }
272 inline static_variant_info<VT_DISPATCH> deduceVARENUM(IDispatch *)
273 {
return static_variant_info<VT_DISPATCH>(); }
274 inline static_variant_info<VT_UNKNOWN> deduceVARENUM(IUnknown *)
275 {
return static_variant_info<VT_UNKNOWN>(); }
276 inline static_variant_info<VT_VARIANT> deduceVARENUM(VARIANT)
277 {
return static_variant_info<VT_VARIANT>(); }
278 inline static_variant_info<VT_VARIANT>
279 deduceVARENUM(automation_vector_base)
280 {
return static_variant_info<VT_VARIANT>(); }
283 inline void from_automation(SAFEARRAY &,
void *)
287 inline void to_automation(SAFEARRAY &,
void *)
292 void from_automation(SAFEARRAY &Array, automation_vector<T> *pDummy);
295 void to_automation(SAFEARRAY &Array, automation_vector<T> *pDummy);
299 typedef automation_vector_base base;
302 const self &const_this()
308 typedef T value_type;
309 typedef T &reference;
310 typedef const T &const_reference;
313 typedef const T *const_iterator;
314 typedef std::reverse_iterator<iterator> reverse_iterator;
315 typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
317 static VARENUM myVARENUM()
321 static_checker<
sizeof(T) ==
322 sizeof(Configure::deduceVARENUM(T()).size_checker)>();
323 return static_cast<VARENUM
>(Configure::deduceVARENUM(T()).vt);
332 : base(0, myVARENUM())
339 ::VariantCopy(&v, &vSource);
354 : base(0, myVARENUM())
359 VARIANT vSource, vCopy;
360 ::VariantInit(&vSource);
361 if (Array.rgsabound->cElements == 0)
362 vSource.vt = VT_EMPTY;
365 ::SafeArrayGetVartype(&Array, &vSource.vt);
366 vSource.vt |= VT_ARRAY;
367 vSource.parray = &Array;
368 ::VariantInit(&vCopy);
369 ::VariantCopy(&vCopy, &vSource);
382 : base(uElements, myVARENUM())
386 _ASSERT(
sizeof(T) == array().cbElements);
387 _ASSERT(array().cLocks == 0);
388 com_enforce(::SafeArrayLock(&array()));
389 std::uninitialized_fill(begin(), end(), t);
394 : base(vSource.size(), myVARENUM())
398 com_enforce(::SafeArrayLock(&array()));
399 std::uninitialized_copy(vSource.begin(), vSource.end(), begin());
402 : base(last - first, myVARENUM())
404 std::uninitialized_copy(first, last, begin());
413 std::copy(that.begin(), that.end(), begin());
422 ::VariantCopy(&v, &that);
429 void attach(VARIANT &vSource)
435 void attach(SAFEARRAY &vSource)
442 void detach(VARIANT &Var)
444 _ASSERT(_CrtIsValidPointer(&Var,
sizeof(VARIANT),
true));
445 com_enforce(::VariantClear(&Var));
451 VARIANT* v =
new VARIANT;
456 void assign(const_iterator first, const_iterator last)
459 insert(begin(), first, last);
461 void assign(size_type n,
const T &
x)
464 insert(begin(), n, x);
467 const_iterator begin() const
470 _ASSERT(empty() || array().cLocks == 1);
471 return empty() ? 0 :
static_cast<T *
>(array().pvData);
475 return const_cast<iterator
>(const_this().begin());
478 const_iterator end() const
483 _ASSERT(array().cLocks == 1);
484 const SAFEARRAY &a = array();
485 return static_cast<T *
>(a.pvData) + a.rgsabound[0].cElements;
489 return const_cast<iterator
>(const_this().end());
492 reverse_iterator rbegin()
494 return reverse_iterator(end());
496 const_reverse_iterator rbegin() const
498 return const_reverse_iterator(end());
501 reverse_iterator rend()
503 return reverse_iterator(begin());
505 const_reverse_iterator rend() const
507 return const_reverse_iterator(begin());
511 const_reference front() const
518 return const_cast<reference
>(const_this().front());
522 const_reference back() const
529 return const_cast<reference
>(const_this().back());
531 size_t max_size() const
533 return size_type(-1) /
sizeof(T);
537 const_reference operator[] (
long lIndex)
const
541 const SAFEARRAYBOUND &Bounds = bounds();
542 lIndex -= Bounds.lLbound;
543 _ASSERT(lIndex >= 0 && (
unsigned long)lIndex < Bounds.cElements);
544 return begin()[lIndex];
546 reference operator[](
long lIndex)
548 return const_cast<reference
>(const_this()[lIndex]);
550 const_reference at(
long lIndex)
const
554 throw std::out_of_range(
"out of range");
555 const SAFEARRAYBOUND &Bounds = bounds();
556 lIndex -= Bounds.lLbound;
557 if (lIndex < 0 || (
unsigned long)lIndex >= Bounds.cElements)
558 throw std::out_of_range(
"out of range");
559 return begin()[lIndex];
561 reference at(
long lIndex)
563 return const_cast<reference
>(const_this().at(lIndex));
565 void swap(
self &that)
571 iterator insert(iterator i,
const T& x = T())
573 _ASSERT(i >= begin() && i <= end());
574 size_t Offset = i - begin();
575 insert(i, (T *)&x, (T *)&x + 1);
576 return begin() + Offset;
579 void insert(iterator i,
size_t n,
const T &x)
581 size_t OldSize = size();
583 std::copy_backward(begin(), begin() + OldSize, end());
584 std::fill(begin(), begin() + n, x);
587 void insert(iterator i, const_iterator first, const_iterator last)
591 _ASSERT(last >= first);
592 _ASSERT(i >= begin() && i <= end());
593 size_t count = last - first;
596 size_t offset = i - begin(), old_size = size();
597 resize(old_size + count);
598 for (iterator j = begin() + old_size,
k = end(); j != begin() + offset; )
599 std::iter_swap(--j, --
k);
600 std::copy(first, last, begin() + offset);
603 iterator erase(iterator i)
605 unsigned Offset = i - begin();
606 std::copy(i + 1, end(), i);
608 return begin() + Offset;
610 iterator erase(iterator From, iterator To)
612 unsigned Offset = From - begin();
613 iterator i = std::copy(To, end(), From);
615 return begin() + Offset;
618 void resize(
size_t NewDim,
const T &FillWith);
619 void resize(
size_t NewDim)
624 void push_back(
const T &ToAdd)
627 insert(end(), ToAdd);
646 std::string ErrorMessage;
647 if (array().cbElements !=
sizeof(T))
648 ErrorMessage +=
"Element size (cbElements) is incorrect.\n";
649 VARENUM ElementType = VARENUM(plain_vartype() & VT_TYPEMASK);
650 if (ElementType != myVARENUM() &&
651 !(ElementType == VT_DATE && myVARENUM() == VT_R4) &&
652 !(ElementType == VT_ERROR && myVARENUM() == VT_I4))
653 ErrorMessage +=
"Element type is incorrect.\n";
654 if (ErrorMessage.empty())
656 throw std::runtime_error(
"The automation_vector is invalid due to the following problem(s):\n" + ErrorMessage);
665 automation_vector<T>::~automation_vector()
671 _ASSERT(plain_vartype() == VT_EMPTY || array().cLocks == 0);
681 void automation_vector<T>::clear()
689 void automation_vector<T>::resize(
size_t NewSize,
const T &t)
692 size_type OldSize = size();
694 base::resize(NewSize, myVARENUM());
697 if (OldSize < size())
698 std::uninitialized_fill(begin() + OldSize, end(), t);
702 void automation_vector<T>::lock()
708 _ASSERT(array().cLocks == 0);
710 array_lock MyLock(array());
713 from_automation(array(), static_cast<T *>(0));
715 MyLock.leave_ownership();
719 void automation_vector<T>::unlock()
725 to_automation(array(), static_cast<T *>(0));
727 com_enforce(::SafeArrayUnlock(&array()));
761 void automation_vector<T>::attach(VARIANT &vSource)
764 if (V_VT(&vSource) == VT_EMPTY)
769 if (!V_ISARRAY(&vSource))
770 throw std::invalid_argument(
"Invalid argument passed to attach()");
771 SAFEARRAY &Array = V_ISBYREF(&vSource) ? **vSource.pparray : *vSource.parray;
772 if (Array.cDims != 1)
773 throw std::invalid_argument(
"Only one-dimensional arrays are supported");
774 const VARENUM vt = VARENUM(vSource.vt & VT_TYPEMASK);
776 if (vt == myVARENUM())
779 com_enforce(::SafeArrayLock(&Array));
780 from_automation(Array, static_cast<T *>(0));
781 Temp.base::attach(vSource);
786 Temp.resize(Array.rgsabound[0].cElements);
787 VARIANT* Converted = Temp.detach();
788 long f = Array.rgsabound[0].lLbound,
789 t = f + Array.rgsabound[0].cElements;
791 ::VariantInit(&Buffer);
794 get_element(vSource, f, Buffer);
795 if (myVARENUM() != VT_VARIANT)
796 com_enforce(::VariantChangeType(&Buffer, &Buffer, 0, myVARENUM()));
797 put_element(*Converted, f, Buffer);
799 _ASSERT(Converted->vt == (myVARENUM() | VT_ARRAY));
800 Temp.attach(*Converted);
808 void automation_vector<T>::attach(SAFEARRAY &Array)
813 if (Array.rgsabound->cElements == 0)
817 ::SafeArrayGetVartype(&Array, &v.vt);
826 #endif //__AUTOMATION_VECTOR_H__