2 #ifndef _GLIBMM_ARRAYHANDLE_H
3 #define _GLIBMM_ARRAYHANDLE_H
5 /* $Id: arrayhandle.h 32 2003-04-21 17:39:41Z murrayc $ */
7 /* Copyright (C) 2002 The gtkmm Development Team
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
19 * You should have received a copy of the GNU Library General Public
20 * License along with this library; if not, write to the Free
21 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include <glibmm/containerhandle_shared.h>
30 namespace Container_Helpers
33 #ifndef DOXYGEN_SHOULD_SKIP_THIS
35 /* Count the number of elements in a 0-terminated sequence.
37 template <class T> inline
38 size_t compute_array_size(const T* array)
40 const T* pend = array;
45 return (pend - array);
48 /* Allocate and fill a 0-terminated array. The size argument
49 * specifies the number of elements in the input sequence.
51 template <class For, class Tr>
52 typename Tr::CType* create_array(For pbegin, size_t size, Tr)
54 typedef typename Tr::CType CType;
56 CType *const array = static_cast<CType*>(g_malloc((size + 1) * sizeof(CType)));
57 CType *const array_end = array + size;
59 for(CType* pdest = array; pdest != array_end; ++pdest)
61 // Use & to force a warning if the iterator returns a temporary object.
62 *pdest = Tr::to_c_type(*&*pbegin);
71 /* Convert from any container that supports forward
72 * iterators and has a size() method.
74 template <class Tr, class Cont>
75 struct ArraySourceTraits
77 typedef typename Tr::CType CType;
79 static size_t get_size(const Cont& cont)
80 { return cont.size(); }
82 static const CType* get_data(const Cont& cont, size_t size)
83 { return Glib::Container_Helpers::create_array(cont.begin(), size, Tr()); }
85 static const Glib::OwnershipType initial_ownership = Glib::OWNERSHIP_SHALLOW;
88 /* Convert from a 0-terminated array. The Cont argument must be a pointer
89 * to the first element. Note that only arrays of the C type are supported.
91 template <class Tr, class Cont>
92 struct ArraySourceTraits<Tr,Cont*>
94 typedef typename Tr::CType CType;
96 static size_t get_size(const CType* array)
97 { return (array) ? Glib::Container_Helpers::compute_array_size(array) : 0; }
99 static const CType* get_data(const CType* array, size_t)
102 static const Glib::OwnershipType initial_ownership = Glib::OWNERSHIP_NONE;
105 template <class Tr, class Cont>
106 struct ArraySourceTraits<Tr,const Cont*> : ArraySourceTraits<Tr,Cont*>
109 /* Convert from a 0-terminated array. The Cont argument must be a pointer
110 * to the first element. Note that only arrays of the C type are supported.
111 * For consistency, the array must be 0-terminated, even though the array
112 * size is known at compile time.
114 template <class Tr, class Cont, size_t N>
115 struct ArraySourceTraits<Tr,Cont[N]>
117 typedef typename Tr::CType CType;
119 static size_t get_size(const CType*)
122 static const CType* get_data(const CType* array, size_t)
125 static const Glib::OwnershipType initial_ownership = Glib::OWNERSHIP_NONE;
128 template <class Tr, class Cont, size_t N>
129 struct ArraySourceTraits<Tr,const Cont[N]> : ArraySourceTraits<Tr,Cont[N]>
132 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
136 * @ingroup ContHelpers
139 class ArrayHandleIterator
142 typedef typename Tr::CppType CppType;
143 typedef typename Tr::CType CType;
145 typedef std::random_access_iterator_tag iterator_category;
146 typedef CppType value_type;
147 typedef ptrdiff_t difference_type;
148 typedef value_type reference;
149 typedef void pointer;
151 explicit inline ArrayHandleIterator(const CType* pos);
153 inline value_type operator*() const;
154 inline value_type operator[](difference_type offset) const;
156 inline ArrayHandleIterator<Tr> & operator++();
157 inline const ArrayHandleIterator<Tr> operator++(int);
159 // All this random access stuff is only there because STL algorithms
160 // usually have optimized specializations for random access iterators,
161 // and we don't want to give away efficiency for nothing.
163 inline ArrayHandleIterator<Tr> & operator+=(difference_type rhs);
164 inline ArrayHandleIterator<Tr> & operator-=(difference_type rhs);
165 inline const ArrayHandleIterator<Tr> operator+ (difference_type rhs) const;
166 inline const ArrayHandleIterator<Tr> operator- (difference_type rhs) const;
167 inline difference_type operator-(const ArrayHandleIterator<Tr>& rhs) const;
169 inline bool operator==(const ArrayHandleIterator<Tr>& rhs) const;
170 inline bool operator!=(const ArrayHandleIterator<Tr>& rhs) const;
171 inline bool operator< (const ArrayHandleIterator<Tr>& rhs) const;
172 inline bool operator> (const ArrayHandleIterator<Tr>& rhs) const;
173 inline bool operator<=(const ArrayHandleIterator<Tr>& rhs) const;
174 inline bool operator>=(const ArrayHandleIterator<Tr>& rhs) const;
180 } // namespace Container_Helpers
183 /** If a method takes this as an argument, or has this as a return type, then you can use a standard
184 * container such as std::list or std::vector.
185 * @ingroup ContHandles
187 template < class T, class Tr = Glib::Container_Helpers::TypeTraits<T> >
191 typedef typename Tr::CppType CppType;
192 typedef typename Tr::CType CType;
194 typedef CppType value_type;
195 typedef size_t size_type;
196 typedef ptrdiff_t difference_type;
198 typedef Glib::Container_Helpers::ArrayHandleIterator<Tr> const_iterator;
199 typedef Glib::Container_Helpers::ArrayHandleIterator<Tr> iterator;
201 template <class Cont> inline
202 ArrayHandle(const Cont& container);
204 // Take over ownership of an array created by GTK+ functions.
205 inline ArrayHandle(const CType* array, size_t array_size, Glib::OwnershipType ownership);
206 inline ArrayHandle(const CType* array, Glib::OwnershipType ownership);
208 // Copying clears the ownership flag of the source handle.
209 inline ArrayHandle(const ArrayHandle<T,Tr>& other);
213 inline const_iterator begin() const;
214 inline const_iterator end() const;
216 template <class U> inline operator std::vector<U>() const;
217 template <class U> inline operator std::deque<U>() const;
218 template <class U> inline operator std::list<U>() const;
220 template <class Cont> inline
221 void assign_to(Cont& container) const;
223 template <class Out> inline
224 void copy(Out pdest) const;
226 inline const CType* data() const;
227 inline size_t size() const;
228 inline bool empty() const;
232 const CType* parray_;
233 mutable Glib::OwnershipType ownership_;
235 // No copy assignment.
236 ArrayHandle<T, Tr>& operator=(const ArrayHandle<T,Tr>&);
239 /** If a method takes this as an argument, or has this as a return type, then you can use a standard
240 * container such as std::list<Glib::ustring> or std::vector<Glib::ustring>.
241 * @ingroup ContHandles
243 typedef ArrayHandle<Glib::ustring> StringArrayHandle;
246 /***************************************************************************/
247 /* Inline implementation */
248 /***************************************************************************/
250 #ifndef DOXYGEN_SHOULD_SKIP_THIS
252 namespace Container_Helpers
255 /**** Glib::Container_Helpers::ArrayHandleIterator<> ***********************/
257 template <class Tr> inline
258 ArrayHandleIterator<Tr>::ArrayHandleIterator(const CType* pos)
263 template <class Tr> inline
264 typename ArrayHandleIterator<Tr>::value_type ArrayHandleIterator<Tr>::operator*() const
266 return Tr::to_cpp_type(*pos_);
269 template <class Tr> inline
270 typename ArrayHandleIterator<Tr>::value_type
271 ArrayHandleIterator<Tr>::operator[](difference_type offset) const
273 return Tr::to_cpp_type(pos_[offset]);
276 template <class Tr> inline
277 ArrayHandleIterator<Tr>& ArrayHandleIterator<Tr>::operator++()
283 template <class Tr> inline
284 const ArrayHandleIterator<Tr> ArrayHandleIterator<Tr>::operator++(int)
286 return ArrayHandleIterator<Tr>(pos_++);
289 template <class Tr> inline
290 ArrayHandleIterator<Tr>&
291 ArrayHandleIterator<Tr>::operator+=(typename ArrayHandleIterator<Tr>::difference_type rhs)
297 template <class Tr> inline
298 ArrayHandleIterator<Tr>&
299 ArrayHandleIterator<Tr>::operator-=(typename ArrayHandleIterator<Tr>::difference_type rhs)
305 template <class Tr> inline
306 const ArrayHandleIterator<Tr>
307 ArrayHandleIterator<Tr>::operator+(typename ArrayHandleIterator<Tr>::difference_type rhs) const
309 return ArrayHandleIterator<Tr>(pos_ + rhs);
312 template <class Tr> inline
313 const ArrayHandleIterator<Tr>
314 ArrayHandleIterator<Tr>::operator-(typename ArrayHandleIterator<Tr>::difference_type rhs) const
316 return ArrayHandleIterator<Tr>(pos_ - rhs);
319 template <class Tr> inline
320 typename ArrayHandleIterator<Tr>::difference_type
321 ArrayHandleIterator<Tr>::operator-(const ArrayHandleIterator<Tr>& rhs) const
323 return (pos_ - rhs.pos_);
326 template <class Tr> inline
327 bool ArrayHandleIterator<Tr>::operator==(const ArrayHandleIterator<Tr>& rhs) const
329 return (pos_ == rhs.pos_);
332 template <class Tr> inline
333 bool ArrayHandleIterator<Tr>::operator!=(const ArrayHandleIterator<Tr>& rhs) const
335 return (pos_ != rhs.pos_);
338 template <class Tr> inline
339 bool ArrayHandleIterator<Tr>::operator<(const ArrayHandleIterator<Tr>& rhs) const
341 return (pos_ < rhs.pos_);
344 template <class Tr> inline
345 bool ArrayHandleIterator<Tr>::operator>(const ArrayHandleIterator<Tr>& rhs) const
347 return (pos_ > rhs.pos_);
350 template <class Tr> inline
351 bool ArrayHandleIterator<Tr>::operator<=(const ArrayHandleIterator<Tr>& rhs) const
353 return (pos_ <= rhs.pos_);
356 template <class Tr> inline
357 bool ArrayHandleIterator<Tr>::operator>=(const ArrayHandleIterator<Tr>& rhs) const
359 return (pos_ >= rhs.pos_);
362 } // namespace Container_Helpers
365 /**** Glib::ArrayHandle<> **************************************************/
367 template <class T, class Tr>
368 template <class Cont>
370 ArrayHandle<T,Tr>::ArrayHandle(const Cont& container)
372 size_ (Glib::Container_Helpers::ArraySourceTraits<Tr,Cont>::get_size(container)),
373 parray_ (Glib::Container_Helpers::ArraySourceTraits<Tr,Cont>::get_data(container, size_)),
374 ownership_ (Glib::Container_Helpers::ArraySourceTraits<Tr,Cont>::initial_ownership)
377 template <class T, class Tr> inline
378 ArrayHandle<T,Tr>::ArrayHandle(const typename ArrayHandle<T,Tr>::CType* array, size_t array_size,
379 Glib::OwnershipType ownership)
383 ownership_ (ownership)
386 template <class T, class Tr> inline
387 ArrayHandle<T,Tr>::ArrayHandle(const typename ArrayHandle<T,Tr>::CType* array,
388 Glib::OwnershipType ownership)
390 size_ ((array) ? Glib::Container_Helpers::compute_array_size(array) : 0),
392 ownership_ (ownership)
395 template <class T, class Tr> inline
396 ArrayHandle<T,Tr>::ArrayHandle(const ArrayHandle<T,Tr>& other)
399 parray_ (other.parray_),
400 ownership_ (other.ownership_)
402 other.ownership_ = Glib::OWNERSHIP_NONE;
405 template <class T, class Tr>
406 ArrayHandle<T,Tr>::~ArrayHandle()
408 if(ownership_ != Glib::OWNERSHIP_NONE)
410 if(ownership_ != Glib::OWNERSHIP_SHALLOW)
412 // Deep ownership: release each container element.
413 const CType *const pend = parray_ + size_;
414 for(const CType* p = parray_; p != pend; ++p)
415 Tr::release_c_type(*p);
417 g_free(const_cast<CType*>(parray_));
421 template <class T, class Tr> inline
422 typename ArrayHandle<T,Tr>::const_iterator ArrayHandle<T,Tr>::begin() const
424 return Glib::Container_Helpers::ArrayHandleIterator<Tr>(parray_);
427 template <class T, class Tr> inline
428 typename ArrayHandle<T,Tr>::const_iterator ArrayHandle<T,Tr>::end() const
430 return Glib::Container_Helpers::ArrayHandleIterator<Tr>(parray_ + size_);
433 template <class T, class Tr>
436 ArrayHandle<T,Tr>::operator std::vector<U>() const
438 #ifdef GLIBMM_HAVE_TEMPLATE_SEQUENCE_CTORS
439 return std::vector<U>(this->begin(), this->end());
442 temp.reserve(this->size());
443 Glib::Container_Helpers::fill_container(temp, this->begin(), this->end());
448 template <class T, class Tr>
451 ArrayHandle<T,Tr>::operator std::deque<U>() const
453 #ifdef GLIBMM_HAVE_TEMPLATE_SEQUENCE_CTORS
454 return std::deque<U>(this->begin(), this->end());
457 Glib::Container_Helpers::fill_container(temp, this->begin(), this->end());
462 template <class T, class Tr>
465 ArrayHandle<T,Tr>::operator std::list<U>() const
467 #ifdef GLIBMM_HAVE_TEMPLATE_SEQUENCE_CTORS
468 return std::list<U>(this->begin(), this->end());
471 Glib::Container_Helpers::fill_container(temp, this->begin(), this->end());
476 template <class T, class Tr>
477 template <class Cont>
479 void ArrayHandle<T,Tr>::assign_to(Cont& container) const
481 #ifdef GLIBMM_HAVE_TEMPLATE_SEQUENCE_CTORS
482 container.assign(this->begin(), this->end());
485 Glib::Container_Helpers::fill_container(temp, this->begin(), this->end());
486 container.swap(temp);
490 template <class T, class Tr>
493 void ArrayHandle<T,Tr>::copy(Out pdest) const
495 std::copy(this->begin(), this->end(), pdest);
498 template <class T, class Tr> inline
499 const typename ArrayHandle<T,Tr>::CType* ArrayHandle<T,Tr>::data() const
504 template <class T, class Tr> inline
505 size_t ArrayHandle<T,Tr>::size() const
510 template <class T, class Tr> inline
511 bool ArrayHandle<T,Tr>::empty() const
516 #endif /* DOXYGEN_SHOULD_SKIP_THIS */
521 #endif /* _GLIBMM_ARRAYHANDLE_H */