#ifndef _GLIBMM_VECTORUTILS_H
#define _GLIBMM_VECTORUTILS_H
/* Copyright(C) 2011 The glibmm Development Team
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see .
*/
#include
#include
#include
#include
/* There are three types of functions:
* 1. Returning a container.
* 2. Taking a container as a parameter.
* 3. Returning a container as a parameter.
*
* Ad 1. When a function returns a container it can own:
* a) a container and data, callers ownership - none (caller owns neither
* container nor data),
* b) only data, callers ownership - shallow (caller owns only a container),
* c) nothing, callers ownership - deep (caller owns both container and data).
*
* Above cases are simple - here we just create a vector with copies of returned
* container's data and then, depending on ownership transfer, we destroy
* nothing or container only or both container and data.
*
* Ad 2. When a function takes a container as a parameter it can take
* an ownership of:
* a) a container and data, callers ownership - none (caller loses ownership
* of both container and data),
* b) only data, callers ownership - shallow (caller loses ownership of data),
* c) nothing, callers ownership - deep (caller does not lose ownership
* to both container and data).
*
* Above cases are also simple - from given vector we create a C copy
* of container and data, pass them to function and then, depending on ownership
* transfer, we destroy nothing or container only or both container and data.
* But note that a) and b) cases are probably wrong by design, so we don't cover
* them here.
*
* Ad 3. Such functions are best wrapped by hand if we want to use a vector
* here.
*/
namespace Glib
{
namespace Container_Helpers
{
#ifndef DOXYGEN_SHOULD_SKIP_THIS
// TODO: docs!
/* Count the number of elements in a 0-terminated sequence.
*/
template
inline std::size_t
compute_array_size2(const T* array)
{
if (array)
{
const T* pend(array);
while (*pend)
{
++pend;
}
return (pend - array);
}
return 0;
}
/* Allocate and fill a 0-terminated array. The size argument
* specifies the number of elements in the input sequence.
*/
template
typename Tr::CType*
create_array(typename std::vector::const_iterator pbegin, std::size_t size)
{
using CType = typename Tr::CType;
CType* const array(static_cast(g_malloc((size + 1) * sizeof(CType))));
CType* const array_end(array + size);
for (CType* pdest(array); pdest != array_end; ++pdest)
{
// Use & to force a warning if the iterator returns a temporary object.
*pdest = Tr::to_c_type(*&*pbegin);
++pbegin;
}
*array_end = CType();
return array;
}
/* first class function for bools, because std::vector is a specialization
* which does not conform to being an STL container.
*/
GLIBMM_API
gboolean* create_bool_array(std::vector::const_iterator pbegin, std::size_t size);
/* Create and fill a GList as efficient as possible.
* This requires bidirectional iterators.
*/
template
GList*
create_glist(const typename std::vector::const_iterator pbegin,
typename std::vector::const_iterator pend)
{
GList* head(nullptr);
while (pend != pbegin)
{
// Use & to force a warning if the iterator returns a temporary object.
const void* const item(Tr::to_c_type(*&*--pend));
head = g_list_prepend(head, const_cast(item));
}
return head;
}
/* Create and fill a GSList as efficient as possible.
* This requires bidirectional iterators.
*/
template
GSList*
create_gslist(const typename std::vector::const_iterator pbegin,
typename std::vector::const_iterator pend)
{
GSList* head(nullptr);
while (pend != pbegin)
{
// Use & to force a warning if the iterator returns a temporary object.
const void* const item(Tr::to_c_type(*&*--pend));
head = g_slist_prepend(head, const_cast(item));
}
return head;
}
#endif /* DOXYGEN_SHOULD_SKIP_THIS */
template
class ArrayIterator
{
public:
using CppType = typename Tr::CppType;
using CType = typename Tr::CType;
using iterator_category = std::random_access_iterator_tag;
using value_type = CppType;
using difference_type = std::ptrdiff_t;
using reference = value_type;
using pointer = void;
explicit inline ArrayIterator(const CType* pos);
inline value_type operator*() const;
inline value_type operator[](difference_type offset) const;
inline ArrayIterator& operator++();
inline const ArrayIterator
operator++(int);
// All this random access stuff is only there because STL algorithms
// usually have optimized specializations for random access iterators,
// and we don't want to give away efficiency for nothing.
inline ArrayIterator
& operator+=(difference_type rhs);
inline ArrayIterator
& operator-=(difference_type rhs);
inline const ArrayIterator
operator+(difference_type rhs) const;
inline const ArrayIterator
operator-(difference_type rhs) const;
inline difference_type operator-(const ArrayIterator
& rhs) const;
inline bool operator==(const ArrayIterator
& rhs) const;
inline bool operator!=(const ArrayIterator
& rhs) const;
inline bool operator<(const ArrayIterator
& rhs) const;
inline bool operator>(const ArrayIterator
& rhs) const;
inline bool operator<=(const ArrayIterator
& rhs) const;
inline bool operator>=(const ArrayIterator
& rhs) const;
private:
const CType* pos_;
};
template
class ListIterator
{
public:
using CppType = typename Tr::CppType;
using CType = typename Tr::CType;
using iterator_category = std::forward_iterator_tag;
using value_type = CppType;
using difference_type = std::ptrdiff_t;
using reference = value_type;
using pointer = void;
explicit inline ListIterator(const GList* node);
inline value_type operator*() const;
inline ListIterator& operator++();
inline const ListIterator
operator++(int);
inline bool operator==(const ListIterator
& rhs) const;
inline bool operator!=(const ListIterator
& rhs) const;
private:
const GList* node_;
};
template
class SListIterator
{
public:
using CppType = typename Tr::CppType;
using CType = typename Tr::CType;
using iterator_category = std::forward_iterator_tag;
using value_type = CppType;
using difference_type = std::ptrdiff_t;
using reference = value_type;
using pointer = void;
explicit inline SListIterator(const GSList* node);
inline value_type operator*() const;
inline SListIterator& operator++();
inline const SListIterator
operator++(int);
inline bool operator==(const SListIterator
& rhs) const;
inline bool operator!=(const SListIterator
& rhs) const;
private:
const GSList* node_;
};
/** A keeper class for C array.
*
* Primarily used by C++ wrappers like gtkmm.
*
* Its main purpose is to free its data when they are not needed. What will be
* destroyed depends on passed ownership upon construction.
*
* The most common usage of Glib::ArrayKeeper is getting its data when converting
* std::vector to a C array:
* @code
* void G::Temp::do_something(const std::vector& v)
* {
* g_temp_do_something(gobj(), Glib::ArrayHandler::vector_to_array(v).data());
* }
* @endcode
* Variables of this class are seldom defined directly - it is mostly used as
* a temporary variable returned by Glib::ArrayHandler::vector_to_array().
*
* Note that the usage above is correct with regards to C++ standard point 12.2.3.
* That means that data returned by data() method is valid through whole
* g_temp_do_something function and is destroyed, when this function returns.
*/
template
class ArrayKeeper
{
public:
using CppType = typename Tr::CppType;
using CType = typename Tr::CType;
/** Constructs an ArrayKeeper holding @a array of size @a array_size.
* @a ownership tells what should be destroyed with keeper destruction:
*
* - Glib::OWNERSHIP_NONE - keeper won't destroy data it holds.
* - Glib::OWNERSHIP_SHALLOW - keeper will destroy only container it holds.
* - Glib::OWNERSHIP_DEEP - keeper will destroy data and container it holds.
*
*
* @param array - C array to hold.
* @param array_size - length of @a array.
* @param ownership - ownership definition.
*/
explicit inline ArrayKeeper(
const CType* array, std::size_t array_size, Glib::OwnershipType ownership);
inline ArrayKeeper(const ArrayKeeper& keeper);
~ArrayKeeper() noexcept;
/** Gets data the keeper holds.
*
* Note that this data is owned by the keeper, so there is no need to free it.
*
* @return C array owned by ArrayKeeper.
*/
inline CType* data() const;
private:
CType* array_;
std::size_t array_size_;
mutable Glib::OwnershipType ownership_;
};
/** A keeper class for GList.
*
* Primarily used by C++ wrappers like gtkmm.
*
* Its main purpose is to free its data when they are not needed. What will be
* destroyed depends on passed ownership upon construction.
*
* The most common usage of Glib::GListKeeper is getting its data when converting
* std::vector to a GList*:
* @code
* void G::Temp::do_something(const std::vector& v)
* {
* g_temp_do_something(gobj(), Glib::ListHandler::vector_to_list(v).data());
* }
* @endcode
* Variables of this class are seldom defined directly - it is mostly used as
* a temporary variable returned by Glib::ListHandler::vector_to_list().
*
* Note that the usage above is correct with regards to C++ standard point 12.2.3.
* That means that data returned by data() method is valid through whole
* g_temp_do_something function and is destroyed, when this function returns.
*/
template
class GListKeeper
{
public:
using CppType = typename Tr::CppType;
using CType = typename Tr::CType;
/** Constructs an GListKeeper holding @a glist.
* @a ownership tells what should be destroyed with keeper destruction:
*
* - Glib::OWNERSHIP_NONE - keeper won't destroy data it holds.
* - Glib::OWNERSHIP_SHALLOW - keeper will destroy only container it holds.
* - Glib::OWNERSHIP_DEEP - keeper will destroy data and container it holds.
*
*
* @param glist - GList* to hold.
* @param ownership - ownership definition.
*/
explicit inline GListKeeper(const GList* glist, Glib::OwnershipType ownership);
inline GListKeeper(const GListKeeper& keeper);
~GListKeeper() noexcept;
/** Gets data the keeper holds.
*
* Note that this data is owned by the keeper, so there is no need to free it.
*
* @return GList* owned by GListKeeper.
*/
inline GList* data() const;
private:
GList* glist_;
mutable Glib::OwnershipType ownership_;
};
/** A keeper class for GSList.
*
* Primarily used by C++ wrappers like gtkmm.
*
* Its main purpose is to free its data when they are not needed. What will be
* destroyed depends on passed ownership upon construction.
*
* The most common usage of Glib::GSListKeeper is getting its data when converting
* std::vector to a GSList*:
* @code
* void G::Temp::do_something(const std::vector& v)
* {
* g_temp_do_something(gobj(), Glib::SListHandler::vector_to_slist(v).data());
* }
* @endcode
* Variables of this class are seldom defined directly - it is mostly used as
* a temporary variable returned by Glib::SListHandler::vector_to_slist().
*
* Note that the usage above is correct with regards to C++ standard point 12.2.3.
* That means that data returned by data() method is valid through whole
* g_temp_do_something function and is destroyed, when this function returns.
*/
template
class GSListKeeper
{
public:
using CppType = typename Tr::CppType;
using CType = typename Tr::CType;
/** Constructs an GSListKeeper holding @a gslist.
* @a ownership tells what should be destroyed with keeper destruction:
*
* - Glib::OWNERSHIP_NONE - keeper won't destroy data it holds.
* - Glib::OWNERSHIP_SHALLOW - keeper will destroy only container it holds.
* - Glib::OWNERSHIP_DEEP - keeper will destroy data and container it holds.
*
*
* @param gslist - GList* to hold.
* @param ownership - ownership definition.
*/
explicit inline GSListKeeper(const GSList* gslist, Glib::OwnershipType ownership);
inline GSListKeeper(const GSListKeeper& keeper);
~GSListKeeper() noexcept;
/** Gets data the keeper holds.
*
* Note that this data is owned by the keeper, so there is no need to free it.
*
* @return GSList* owned by GSListKeeper.
*/
inline GSList* data() const;
private:
GSList* gslist_;
mutable Glib::OwnershipType ownership_;
};
} // namespace Container_Helpers
// Note that this is a struct instead of templated functions because standard template arguments
// for function templates is a C++0x feature.
/** A utility for converting between std::vector and plain C arrays.
* This would normally only be used by glibmm or gtkmm itself, or similar
* libraries that wrap C APIs.
*
* For instance:
* @code
* std::vector PixbufFormat::get_mime_types() const
* {
* return
* Glib::ArrayHandler::array_to_vector(gdk_pixbuf_format_get_mime_types(const_cast(gobj())),
* Glib::OWNERSHIP_DEEP);
* }
* @endcode
* or
* @code
* void Display::store_clipboard(const Glib::RefPtr& clipboard_window, guint32 time_,
* const std::vector& targets)
* {
* if (!targets.size ())
* {
* gdk_display_store_clipboard(gobj(),
* Glib::unwrap (clipboard_window),
* time_,
* Glib::ArrayHandler::vector_to_array(targets).data (),
* targets.size ());
* }
* }
* @endcode
* Note that usage below is wrong - data() returns a pointer to data owned by
* a temporary ArrayKeeper returned by vector_to_array(), which is destroyed at
* the end of this instruction. For details, see Glib::ArrayKeeper.
* @code
* const char** array = Glib::ArrayHandler::vector_to_array(vec).data ();
* @endcode
*/
template >
class ArrayHandler
{
public:
using CType = typename Tr::CType;
using CppType = T;
using VectorType = std::vector;
using ArrayKeeperType = typename Glib::Container_Helpers::ArrayKeeper;
using ArrayIteratorType = typename Glib::Container_Helpers::ArrayIterator
;
// maybe think about using C++0x move constructors?
static VectorType array_to_vector(
const CType* array, std::size_t array_size, Glib::OwnershipType ownership);
static VectorType array_to_vector(const CType* array, Glib::OwnershipType ownership);
static ArrayKeeperType vector_to_array(const VectorType& vector);
};
template <>
class GLIBMM_API ArrayHandler
{
public:
using CType = gboolean;
using CppType = bool;
using VectorType = std::vector;
typedef Glib::Container_Helpers::ArrayKeeper>
ArrayKeeperType;
typedef Glib::Container_Helpers::ArrayIterator>
ArrayIteratorType;
// maybe think about using C++0x move constructors?
static VectorType array_to_vector(
const CType* array, std::size_t array_size, Glib::OwnershipType ownership);
static VectorType array_to_vector(const CType* array, Glib::OwnershipType ownership);
static ArrayKeeperType vector_to_array(const VectorType& vector);
};
/** A utility for converting between std::vector and GList.
* This would normally only be used by glibmm or gtkmm itself, or similar
* libraries that wrap C APIs.
*
* For instance:
* @code
* std::vector< Glib::RefPtr > Window::get_children()
* {
* return Glib::ListHandler
* >::list_to_vector(gdk_window_get_children(gobj()), Glib::OWNERSHIP_SHALLOW);
* }
* @endcode
* or
* @code
* void Window::set_icon_list(const std::vector< Glib::RefPtr >& pixbufs)
* {
* gdk_window_set_icon_list(gobj(), Glib::ListHandler
* >::vector_to_list(pixbufs).data ());
* }
* @endcode
* Note that usage below is wrong - data() returns a pointer to data owned by
* a temporary ListKeeper returned by vector_to_list(), which is destroyed at
* the end of this instruction. For details, see Glib::ListKeeper.
* @code
* GList* glist = Glib::ListHandler >::vector_to_list(pixbufs).data();
* @endcode
*/
template >
class ListHandler
{
public:
using CType = typename Tr::CType;
using CppType = T;
using VectorType = std::vector;
using GListKeeperType = typename Glib::Container_Helpers::GListKeeper;
using ListIteratorType = typename Glib::Container_Helpers::ListIterator
;
// maybe think about using C++0x move constructors?
static VectorType list_to_vector(GList* glist, Glib::OwnershipType ownership);
static GListKeeperType vector_to_list(const VectorType& vector);
};
/** A utility for converting between std::vector and GSList.
* This would normally only be used by glibmm or gtkmm itself, or similar
* libraries that wrap C APIs.
*
* For instance:
* @code
* std::vector< Glib::RefPtr > DisplayManager::list_displays()
* {
* return Glib::SListHandler
* >::slist_to_vector(gdk_display_manager_list_displays(gobj()), Glib::OWNERSHIP_SHALLOW);
* }
* @endcode
* or
* @code
* void Stuff::set_slist(const std::vector& ints)
* {
* g_stuff_set_slist(gobj(), Glib::SListHandler::vector_to_slist(ints).data ());
* }
* @endcode
* Note that usage below is wrong - data() returns a pointer to data owned by
* a temporary SListKeeper returned by vector_to_slist(), which is destroyed at
* the end of this instruction. For details, see Glib::SListKeeper.
* @code
* GSList* gslist = Glib::SListHandler< Glib::RefPtr >::vector_to_slist(vec).data();
* @endcode
*/
template >
class SListHandler
{
public:
using CType = typename Tr::CType;
using CppType = T;
using VectorType = std::vector;
using GSListKeeperType = typename Glib::Container_Helpers::GSListKeeper;
using SListIteratorType = typename Glib::Container_Helpers::SListIterator
;
// maybe think about using C++0x move constructors?
static VectorType slist_to_vector(GSList* gslist, Glib::OwnershipType ownership);
static GSListKeeperType vector_to_slist(const VectorType& vector);
};
/***************************************************************************/
/* Inline implementation */
/***************************************************************************/
#ifndef DOXYGEN_SHOULD_SKIP_THIS
namespace Container_Helpers
{
/**** Glib::Container_Helpers::ArrayIterator<> ***********************/
template
inline ArrayIterator::ArrayIterator(const CType* pos) : pos_(pos)
{
}
template
inline typename ArrayIterator::value_type ArrayIterator
::operator*() const
{
return Tr::to_cpp_type(*pos_);
}
template
inline
typename ArrayIterator::value_type ArrayIterator
::operator[](difference_type offset) const
{
return Tr::to_cpp_type(pos_[offset]);
}
template
inline ArrayIterator& ArrayIterator
::operator++()
{
++pos_;
return *this;
}
template
inline const ArrayIterator ArrayIterator
::operator++(int)
{
return ArrayIterator
(pos_++);
}
template
inline ArrayIterator&
ArrayIterator
::operator+=(typename ArrayIterator
::difference_type rhs)
{
pos_ += rhs;
return *this;
}
template
inline ArrayIterator&
ArrayIterator
::operator-=(typename ArrayIterator
::difference_type rhs)
{
pos_ -= rhs;
return *this;
}
template
inline const ArrayIterator
ArrayIterator
::operator+(typename ArrayIterator
::difference_type rhs) const
{
return ArrayIterator
(pos_ + rhs);
}
template
inline const ArrayIterator
ArrayIterator
::operator-(typename ArrayIterator
::difference_type rhs) const
{
return ArrayIterator
(pos_ - rhs);
}
template
inline typename ArrayIterator::difference_type
ArrayIterator
::operator-(const ArrayIterator
& rhs) const
{
return (pos_ - rhs.pos_);
}
template
inline bool
ArrayIterator::operator==(const ArrayIterator
& rhs) const
{
return (pos_ == rhs.pos_);
}
template
inline bool
ArrayIterator::operator!=(const ArrayIterator
& rhs) const
{
return (pos_ != rhs.pos_);
}
template
inline bool
ArrayIterator::operator<(const ArrayIterator
& rhs) const
{
return (pos_ < rhs.pos_);
}
template
inline bool
ArrayIterator::operator>(const ArrayIterator
& rhs) const
{
return (pos_ > rhs.pos_);
}
template
inline bool
ArrayIterator::operator<=(const ArrayIterator
& rhs) const
{
return (pos_ <= rhs.pos_);
}
template
inline bool
ArrayIterator::operator>=(const ArrayIterator
& rhs) const
{
return (pos_ >= rhs.pos_);
}
/**** Glib::Container_Helpers::ListIterator<> ************************/
template
inline ListIterator::ListIterator(const GList* node) : node_(node)
{
}
template
inline typename ListIterator::value_type ListIterator
::operator*() const
{
return Tr::to_cpp_type(static_cast(node_->data));
}
template
inline ListIterator& ListIterator
::operator++()
{
node_ = node_->next;
return *this;
}
template
inline const ListIterator ListIterator
::operator++(int)
{
const ListIterator
tmp(*this);
node_ = node_->next;
return tmp;
}
template
inline bool
ListIterator::operator==(const ListIterator
& rhs) const
{
return (node_ == rhs.node_);
}
template
inline bool
ListIterator::operator!=(const ListIterator
& rhs) const
{
return (node_ != rhs.node_);
}
/**** Glib::Container_Helpers::SListIterator<> ************************/
template
inline SListIterator::SListIterator(const GSList* node) : node_(node)
{
}
template
inline typename SListIterator::value_type SListIterator
::operator*() const
{
return Tr::to_cpp_type(static_cast(node_->data));
}
template
inline SListIterator& SListIterator
::operator++()
{
node_ = node_->next;
return *this;
}
template
inline const SListIterator SListIterator
::operator++(int)
{
const ListIterator
tmp(*this);
node_ = node_->next;
return tmp;
}
template
inline bool
SListIterator::operator==(const SListIterator
& rhs) const
{
return (node_ == rhs.node_);
}
template
inline bool
SListIterator::operator!=(const SListIterator
& rhs) const
{
return (node_ != rhs.node_);
}
/**** Glib::Container_Helpers::ArrayKeeper<> ************************/
template
inline ArrayKeeper::ArrayKeeper(
const CType* array, std::size_t array_size, Glib::OwnershipType ownership)
: array_(const_cast(array)), array_size_(array_size), ownership_(ownership)
{
}
template
inline ArrayKeeper::ArrayKeeper(const ArrayKeeper& keeper)
: array_(keeper.array_), array_size_(keeper.array_size_), ownership_(keeper.ownership_)
{
keeper.ownership_ = Glib::OWNERSHIP_NONE;
}
template
ArrayKeeper::~ArrayKeeper() noexcept
{
if (array_ && ownership_ != Glib::OWNERSHIP_NONE)
{
if (ownership_ != Glib::OWNERSHIP_SHALLOW)
{
// Deep ownership: release each container element.
const CType* const array_end(array_ + array_size_);
for (const CType* p(array_); p != array_end; ++p)
{
Tr::release_c_type(*p);
}
}
g_free(const_cast(array_));
}
}
template
inline typename Tr::CType*
ArrayKeeper::data() const
{
return array_;
}
/**** Glib::Container_Helpers::GListKeeper<> ************************/
template
inline GListKeeper::GListKeeper(const GList* glist, Glib::OwnershipType ownership)
: glist_(const_cast(glist)), ownership_(ownership)
{
}
template
inline GListKeeper::GListKeeper(const GListKeeper& keeper)
: glist_(keeper.glist_), ownership_(keeper.ownership_)
{
keeper.ownership_ = Glib::OWNERSHIP_NONE;
}
template
GListKeeper::~GListKeeper() noexcept
{
using CTypeNonConst = typename Tr::CTypeNonConst;
if (glist_ && ownership_ != Glib::OWNERSHIP_NONE)
{
if (ownership_ != Glib::OWNERSHIP_SHALLOW)
{
// Deep ownership: release each container element.
for (GList* node = glist_; node; node = node->next)
{
Tr::release_c_type(static_cast(node->data));
}
}
g_list_free(glist_);
}
}
template
inline GList*
GListKeeper::data() const
{
return glist_;
}
/**** Glib::Container_Helpers::GSListKeeper<> ************************/
template
inline GSListKeeper::GSListKeeper(const GSList* gslist, Glib::OwnershipType ownership)
: gslist_(const_cast(gslist)), ownership_(ownership)
{
}
template
inline GSListKeeper::GSListKeeper(const GSListKeeper& keeper)
: gslist_(keeper.gslist_), ownership_(keeper.ownership_)
{
keeper.ownership_ = Glib::OWNERSHIP_NONE;
}
template
GSListKeeper::~GSListKeeper() noexcept
{
using CTypeNonConst = typename Tr::CTypeNonConst;
if (gslist_ && ownership_ != Glib::OWNERSHIP_NONE)
{
if (ownership_ != Glib::OWNERSHIP_SHALLOW)
{
// Deep ownership: release each container element.
for (GSList* node = gslist_; node; node = node->next)
{
Tr::release_c_type(static_cast(node->data));
}
}
g_slist_free(gslist_);
}
}
template
inline GSList*
GSListKeeper::data() const
{
return gslist_;
}
} // namespace Container_Helpers
/**** Glib::ArrayHandler<> ************************/
template
typename ArrayHandler::VectorType
ArrayHandler::array_to_vector(
const CType* array, std::size_t array_size, Glib::OwnershipType ownership)
{
if (array)
{
// it will handle destroying data depending on passed ownership.
ArrayKeeperType keeper(array, array_size, ownership);
#ifdef GLIBMM_HAVE_TEMPLATE_SEQUENCE_CTORS
return VectorType(ArrayIteratorType(array), ArrayIteratorType(array + array_size));
#else
VectorType temp;
temp.reserve(array_size);
Glib::Container_Helpers::fill_container(
temp, ArrayIteratorType(array), ArrayIteratorType(array + array_size));
return temp;
#endif
}
return VectorType();
}
template
typename ArrayHandler::VectorType
ArrayHandler::array_to_vector(const CType* array, Glib::OwnershipType ownership)
{
return array_to_vector(array, Glib::Container_Helpers::compute_array_size2(array), ownership);
}
template
typename ArrayHandler::ArrayKeeperType
ArrayHandler::vector_to_array(const VectorType& vector)
{
return ArrayKeeperType(Glib::Container_Helpers::create_array(vector.begin(), vector.size()),
vector.size(), Glib::OWNERSHIP_SHALLOW);
}
/**** Glib::ListHandler<> ************************/
template
typename ListHandler::VectorType
ListHandler::list_to_vector(GList* glist, Glib::OwnershipType ownership)
{
// it will handle destroying data depending on passed ownership.
GListKeeperType keeper(glist, ownership);
#ifdef GLIBMM_HAVE_TEMPLATE_SEQUENCE_CTORS
return VectorType(ListIteratorType(glist), ListIteratorType(nullptr));
#else
VectorType temp;
temp.reserve(g_list_length(glist));
Glib::Container_Helpers::fill_container(temp, ListIteratorType(glist), ListIteratorType(nullptr));
return temp;
#endif
}
template
typename ListHandler::GListKeeperType
ListHandler::vector_to_list(const VectorType& vector)
{
return GListKeeperType(Glib::Container_Helpers::create_glist(vector.begin(), vector.end()),
Glib::OWNERSHIP_SHALLOW);
}
/**** Glib::SListHandler<> ************************/
template
typename SListHandler::VectorType
SListHandler::slist_to_vector(GSList* gslist, Glib::OwnershipType ownership)
{
// it will handle destroying data depending on passed ownership.
GSListKeeperType keeper(gslist, ownership);
#ifdef GLIBMM_HAVE_TEMPLATE_SEQUENCE_CTORS
return VectorType(SListIteratorType(gslist), SListIteratorType(nullptr));
#else
VectorType temp;
temp.reserve(g_slist_length(gslist));
Glib::Container_Helpers::fill_container(
temp, SListIteratorType(gslist), SListIteratorType(nullptr));
return temp;
#endif
}
template
typename SListHandler::GSListKeeperType
SListHandler::vector_to_slist(const VectorType& vector)
{
return GSListKeeperType(Glib::Container_Helpers::create_gslist(vector.begin(), vector.end()),
Glib::OWNERSHIP_SHALLOW);
}
#endif /* DOXYGEN_SHOULD_SKIP_THIS */
} // namespace Glib
#endif /* _GLIBMM_VECTORUTILS_H */