first commit
This commit is contained in:
82
include/QxCollection/IxCollection.h
Normal file
82
include/QxCollection/IxCollection.h
Normal file
@@ -0,0 +1,82 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** https://www.qxorm.com/
|
||||
** Copyright (C) 2013 XDL Team (ic-east.com)
|
||||
**
|
||||
** This file is part of the QxOrm library
|
||||
**
|
||||
** This software is provided 'as-is', without any express or implied
|
||||
** warranty. In no event will the authors be held liable for any
|
||||
** damages arising from the use of this software
|
||||
**
|
||||
** Commercial Usage
|
||||
** Licensees holding valid commercial QxOrm licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and XDL Team
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file 'license.gpl3.txt' included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met : http://www.gnu.org/copyleft/gpl.html
|
||||
**
|
||||
** If you are unsure which license is appropriate for your use, or
|
||||
** if you have questions regarding the use of this file, please contact :
|
||||
** ic-east.com
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef _IX_COLLECTION_H_
|
||||
#define _IX_COLLECTION_H_
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* \file IxCollection.h
|
||||
* \author XDL Team
|
||||
* \ingroup QxCollection
|
||||
* \brief Common interface for all QxOrm containers qx::QxCollection<Key, Value>
|
||||
*/
|
||||
|
||||
#include <QxTraits/get_class_name.h>
|
||||
|
||||
#include <QxCommon/QxAnyCastDynamic.h>
|
||||
|
||||
namespace qx
|
||||
{
|
||||
|
||||
/*!
|
||||
* \ingroup QxCollection
|
||||
* \brief qx::IxCollection : common interface for all QxOrm containers qx::QxCollection<Key, Value>
|
||||
*/
|
||||
class QX_DLL_EXPORT IxCollection
|
||||
{
|
||||
|
||||
public:
|
||||
IxCollection() { ; }
|
||||
virtual ~IxCollection() = 0;
|
||||
|
||||
virtual long _count() const = 0;
|
||||
virtual void _clear() = 0;
|
||||
virtual bool _remove(long index) = 0;
|
||||
virtual qx::any _at(long index) const = 0;
|
||||
|
||||
template <typename T>
|
||||
T _get(long index) const
|
||||
{
|
||||
return qx::any_cast_dynamic<T>::get(_at(index));
|
||||
}
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<qx::IxCollection> IxCollection_ptr;
|
||||
|
||||
} // namespace qx
|
||||
|
||||
QX_REGISTER_CLASS_NAME(IxCollection)
|
||||
|
||||
#endif // _IX_COLLECTION_H_
|
||||
285
include/QxCollection/QxCollection.h
Normal file
285
include/QxCollection/QxCollection.h
Normal file
@@ -0,0 +1,285 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** https://www.qxorm.com/
|
||||
** Copyright (C) 2013 XDL Team (ic-east.com)
|
||||
**
|
||||
** This file is part of the QxOrm library
|
||||
**
|
||||
** This software is provided 'as-is', without any express or implied
|
||||
** warranty. In no event will the authors be held liable for any
|
||||
** damages arising from the use of this software
|
||||
**
|
||||
** Commercial Usage
|
||||
** Licensees holding valid commercial QxOrm licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and XDL Team
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file 'license.gpl3.txt' included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met : http://www.gnu.org/copyleft/gpl.html
|
||||
**
|
||||
** If you are unsure which license is appropriate for your use, or
|
||||
** if you have questions regarding the use of this file, please contact :
|
||||
** ic-east.com
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef _QX_COLLECTION_H_
|
||||
#define _QX_COLLECTION_H_
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* \file QxCollection.h
|
||||
* \author XDL Team
|
||||
* \ingroup QxCollection
|
||||
* \brief QxOrm thread-safe container (keep insertion order + quick access by index + quick access by key)
|
||||
*/
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4996)
|
||||
#pragma warning(disable : 4503)
|
||||
#endif // _MSC_VER
|
||||
|
||||
#include <QtCore/qmutex.h>
|
||||
|
||||
#include <QxCollection/IxCollection.h>
|
||||
#include <QxCollection/QxForeach.h>
|
||||
|
||||
#include <QxCommon/QxHashValue.h>
|
||||
|
||||
#include <QxTraits/get_class_name.h>
|
||||
#include <QxTraits/is_smart_ptr.h>
|
||||
|
||||
namespace qx
|
||||
{
|
||||
|
||||
/*!
|
||||
* \ingroup QxCollection
|
||||
* \brief qx::QxCollection<Key, Value> : QxOrm thread-safe container (keep insertion order + quick access by index + quick access by key)
|
||||
*
|
||||
* Based on boost::multi_index_container, this collection has advantages of std::vector<T> (keep insertion order + quick access by index)
|
||||
* and boost::unordered_map<Key, Value> or QHash<Key, Value> (quick access by key : hash-map).
|
||||
*
|
||||
* <i>Note :</i> qx::QxCollection<Key, Value> is compatible with the foreach macro provided by Qt library and the BOOST_FOREACH macro provided by boost library.
|
||||
* However, each element returned by these 2 macros corresponds to an object of type std::pair<Key, Value>.
|
||||
* To obtain a more natural and more readable result, it is advised to use the _foreach macro : this macro uses BOOST_FOREACH for all the containers except for qx::QxCollection<Key, Value>.
|
||||
* In this case, the returned element corresponds to the Value type (cf. following sample).
|
||||
* The macro _foreach is compatible with all containers (stl, Qt, boost...) since it uses the macro BOOST_FOREACH.
|
||||
*
|
||||
* <i>Additional note :</i> qx::QxCollection<Key, Value> is particularly suited to receive data resulting from a database.
|
||||
* Indeed, these data can be sorted (by using ORDER BY in a SQL request for example), it is thus important to preserve the insertion order of the elements in the list.
|
||||
* Furthermore, each data resulting from a database has a unique id. It is thus important to be able to access quickly to an element based on this single identifier (hash-map).
|
||||
*
|
||||
* Quick sample using qx::QxCollection<Key, Value> container :
|
||||
* \code
|
||||
// definition of drug class with 3 properties : 'code', 'name' and 'description'
|
||||
class drug { public: QString code; QString name; QString desc; };
|
||||
|
||||
// typedef a smart-pointer of drug class
|
||||
typedef std::shared_ptr<drug> drug_ptr;
|
||||
|
||||
// collection of drugs indexed by 'code' property (QString type)
|
||||
qx::QxCollection<QString, drug_ptr> lstDrugs;
|
||||
|
||||
// create 3 new drugs
|
||||
drug_ptr d1; d1.reset(new drug()); d1->code = "code1"; d1->name = "name1"; d1->desc = "desc1";
|
||||
drug_ptr d2; d2.reset(new drug()); d2->code = "code2"; d2->name = "name2"; d2->desc = "desc2";
|
||||
drug_ptr d3; d3.reset(new drug()); d3->code = "code3"; d3->name = "name3"; d3->desc = "desc3";
|
||||
|
||||
// insert 3 drugs into the collection
|
||||
lstDrugs.insert(d1->code, d1);
|
||||
lstDrugs.insert(d2->code, d2);
|
||||
lstDrugs.insert(d3->code, d3);
|
||||
|
||||
// iterate over drugs container using QxOrm '_foreach' keyword
|
||||
_foreach(drug_ptr p, lstDrugs)
|
||||
{ qDebug() << qPrintable(p->name) << " " << qPrintable(p->desc); }
|
||||
|
||||
// iterate over drugs container using classic C++ 'for' keyword
|
||||
for (long l = 0; l < lstDrugs.count(); ++l)
|
||||
{
|
||||
drug_ptr p = lstDrugs.getByIndex(l);
|
||||
QString code = lstDrugs.getKeyByIndex(l);
|
||||
qDebug() << qPrintable(p->name) << " " << qPrintable(p->desc);
|
||||
}
|
||||
|
||||
// iterate over drugs container using 'qx::QxCollectionIterator' Java-style iterator
|
||||
qx::QxCollectionIterator<QString, drug_ptr> itr(lstDrugs);
|
||||
while (itr.next())
|
||||
{
|
||||
QString code = itr.key();
|
||||
qDebug() << qPrintable(itr.value()->name) << " " << qPrintable(itr.value()->desc);
|
||||
}
|
||||
|
||||
// sort drugs container ascending by key and sort descending by value
|
||||
lstDrugs.sortByKey(true);
|
||||
lstDrugs.sortByValue(false);
|
||||
|
||||
// access to a drug into the collection by its 'code' property
|
||||
drug_ptr p = lstDrugs.getByKey("code2");
|
||||
|
||||
// access to a drug into the collection by index (position in the list)
|
||||
drug_ptr p = lstDrugs.getByIndex(2);
|
||||
|
||||
// test if a drug exists into the collection and if the collection is empty
|
||||
bool bExist = lstDrugs.exist("code3");
|
||||
bool bEmpty = lstDrugs.empty();
|
||||
|
||||
// remove the second drug from the collection
|
||||
lstDrugs.removeByIndex(2);
|
||||
|
||||
// remove a drug from the collection using its 'code' property
|
||||
lstDrugs.removeByKey("code3");
|
||||
|
||||
// clear the collection : remove all items from the list
|
||||
lstDrugs.clear();
|
||||
* \endcode
|
||||
*/
|
||||
template <typename Key, typename Value>
|
||||
class QxCollection : public IxCollection
|
||||
{
|
||||
|
||||
public:
|
||||
typedef QPair<Key, Value> type_pair_key_value;
|
||||
|
||||
protected:
|
||||
typedef QList<type_pair_key_value> type_list_pair_key_value;
|
||||
typedef QHash<Key, long> type_hash_position;
|
||||
|
||||
public:
|
||||
typedef typename type_list_pair_key_value::iterator iterator;
|
||||
typedef typename type_list_pair_key_value::const_iterator const_iterator;
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
|
||||
typedef typename type_list_pair_key_value::reverse_iterator reverse_iterator;
|
||||
typedef typename type_list_pair_key_value::const_reverse_iterator const_reverse_iterator;
|
||||
#endif // (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
|
||||
|
||||
typedef const Key &const_reference_key;
|
||||
typedef const Value &const_reference_value;
|
||||
|
||||
protected:
|
||||
mutable QMutex m_mutex; //!< Mutex => qx::QxCollection is thread-safe
|
||||
type_list_pair_key_value m_list; //!< Container to keep insertion order
|
||||
type_hash_position m_hash; //!< Container for fast search by key
|
||||
bool m_batch; //!< Batch mode to sync internal containers
|
||||
|
||||
public:
|
||||
QxCollection(); //!< Construct an empty list
|
||||
QxCollection(const QxCollection<Key, Value> &other); //!< Construct a copy of 'other'
|
||||
virtual ~QxCollection(); //!< Destroy the list
|
||||
|
||||
QxCollection<Key, Value> &operator=(const QxCollection<Key, Value> &other); //!< Assign 'other' to this list and return a reference to this list
|
||||
bool operator==(const QxCollection<Key, Value> &other) const; //!< Return 'true' if 'other' is equal to this list, otherwise return 'false' (same values in the same order)
|
||||
bool operator!=(const QxCollection<Key, Value> &other) const; //!< Return 'true' if 'other' is not equal to this list, otherwise return 'false'
|
||||
|
||||
iterator begin(); //!< Return an STL-style iterator pointing to the first item in the list
|
||||
iterator end(); //!< Return an STL-style iterator pointing to the imaginary item after the last item in the list
|
||||
const_iterator begin() const; //!< Return a const STL-style iterator pointing to the first item in the list
|
||||
const_iterator end() const; //!< Return a const STL-style iterator pointing to the imaginary item after the last item in the list
|
||||
|
||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
|
||||
reverse_iterator rbegin(); //!< Return a reverse STL-style iterator pointing to the first item in the list
|
||||
reverse_iterator rend(); //!< Return a reverse STL-style iterator pointing to the imaginary item after the last item in the list
|
||||
const_reverse_iterator rbegin() const; //!< Return a const reverse STL-style iterator pointing to the first item in the list
|
||||
const_reverse_iterator rend() const; //!< Return a const reverse STL-style iterator pointing to the imaginary item after the last item in the list
|
||||
#endif // (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
|
||||
|
||||
void reserve(long size); //!< Request that the capacity of the allocated storage space for the items of the container be at least enough to hold 'size' elements
|
||||
void reverse(); //!< Reverse all items in the list
|
||||
void clear(); //!< Remove all items from the list
|
||||
long count() const; //!< Return the number of items in the list (same as 'size()')
|
||||
long size() const; //!< Return the number of items in the list (same as 'count()')
|
||||
bool contains(const Key &key) const; //!< Return 'true' if the list contains an occurrence of 'key', otherwise return 'false' (same as 'exist()')
|
||||
bool exist(const Key &key) const; //!< Return 'true' if the list contains an occurrence of 'key', otherwise return 'false' (same as 'contains()')
|
||||
bool empty() const; //!< Return 'true' if the list contains no items; otherwise return 'false'
|
||||
|
||||
bool push_back(const Key &key, const Value &value); //!< Add element 'value' at the end of the list indexed by 'key'
|
||||
bool push_front(const Key &key, const Value &value); //!< Insert 'value' at the beginning of the list indexed by 'key'
|
||||
bool insert(const Key &key, const Value &value); //!< Add element 'value' at the end of the list indexed by 'key'
|
||||
bool insert(long index, const Key &key, const Value &value); //!< Insert element 'value' at position 'index' in the list indexed by 'key'
|
||||
bool insert(const QxCollection<Key, Value> &other); //!< Add all items of 'other' at the end of the list
|
||||
bool insert(long index, const QxCollection<Key, Value> &other); //!< Insert all items of 'other' at the end of the list
|
||||
bool replace(long index, const Key &key, const Value &value); //!< Replace the item at index position 'index' with element 'value' indexed by 'key'
|
||||
bool swap(long index1, long index2); //!< Exchange the item at index position 'index1' with the item at index position 'index2'
|
||||
bool move(long indexFrom, long indexTo); //!< Move the item at index position 'indexFrom' to index position 'indexTo'
|
||||
|
||||
bool removeByKey(const Key &key); //!< Remove the item indexed by 'key' in the list
|
||||
bool removeByIndex(long index); //!< Remove the item at index position 'index'
|
||||
bool removeByIndex(long first, long last); //!< Remove all items from index position 'first' to index position 'last'
|
||||
bool removeFirst(); //!< Remove the first item in the list
|
||||
bool removeLast(); //!< Remove the last item in the list
|
||||
|
||||
const_reference_value getByKey(const Key &key) const; //!< Return the item associated with the 'key'
|
||||
const_reference_value getByIndex(long index) const; //!< Return the item at index position 'index'
|
||||
const_reference_value getFirst() const; //!< Return the first element in the list
|
||||
const_reference_value getLast() const; //!< Return the last element in the list
|
||||
const_reference_key getKeyByIndex(long index) const; //!< Return the key associated with the element at index position 'index'
|
||||
|
||||
void sortByKey(bool bAscending = true); //!< Sort all items in the list using associated keys to compare
|
||||
void sortByValue(bool bAscending = true); //!< Sort all items in the list
|
||||
|
||||
template <typename Compare>
|
||||
void sort(Compare comp)
|
||||
{
|
||||
{
|
||||
QMutexLocker locker(&m_mutex);
|
||||
std::sort(m_list.begin(), m_list.end(), comp);
|
||||
}
|
||||
updateHashPosition();
|
||||
}
|
||||
|
||||
protected:
|
||||
void cloneCollection(QxCollection<Key, Value> *pClone, const QxCollection<Key, Value> &pRef);
|
||||
bool isSameCollection(const QxCollection<Key, Value> *p1, const QxCollection<Key, Value> &p2) const;
|
||||
void updateHashPosition(long from = 0, long to = -1, bool check = false);
|
||||
|
||||
template <bool bIsPointer /* = false */, int dummy>
|
||||
struct compareKeyValue
|
||||
{
|
||||
static bool compareByKeyAscending(const type_pair_key_value &v1, const type_pair_key_value &v2) { return (v1.first < v2.first); }
|
||||
static bool compareByKeyDescending(const type_pair_key_value &v1, const type_pair_key_value &v2) { return (v1.first > v2.first); }
|
||||
static bool compareByValueAscending(const type_pair_key_value &v1, const type_pair_key_value &v2) { return (v1.second < v2.second); }
|
||||
static bool compareByValueDescending(const type_pair_key_value &v1, const type_pair_key_value &v2) { return (v1.second > v2.second); }
|
||||
};
|
||||
|
||||
template <int dummy>
|
||||
struct compareKeyValue<true, dummy>
|
||||
{
|
||||
static bool compareByKeyAscending(const type_pair_key_value &v1, const type_pair_key_value &v2) { return ((v1.first && v2.first) ? ((*v1.first) < (*v2.first)) : false); }
|
||||
static bool compareByKeyDescending(const type_pair_key_value &v1, const type_pair_key_value &v2) { return ((v1.first && v2.first) ? ((*v1.first) > (*v2.first)) : true); }
|
||||
static bool compareByValueAscending(const type_pair_key_value &v1, const type_pair_key_value &v2) { return ((v1.second && v2.second) ? ((*v1.second) < (*v2.second)) : false); }
|
||||
static bool compareByValueDescending(const type_pair_key_value &v1, const type_pair_key_value &v2) { return ((v1.second && v2.second) ? ((*v1.second) > (*v2.second)) : true); }
|
||||
};
|
||||
|
||||
public:
|
||||
virtual long _count() const { return this->count(); }
|
||||
virtual void _clear() { this->clear(); }
|
||||
virtual bool _remove(long index) { return this->removeByIndex(index); }
|
||||
virtual qx::any _at(long index) const
|
||||
{
|
||||
Value val = this->getByIndex(index);
|
||||
return qx::any(val);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace qx
|
||||
|
||||
#include "../../inl/QxCollection/QxCollection.inl"
|
||||
|
||||
QX_REGISTER_CLASS_NAME_TEMPLATE_2(qx::QxCollection)
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(pop)
|
||||
#endif // _MSC_VER
|
||||
|
||||
#endif // _QX_COLLECTION_H_
|
||||
100
include/QxCollection/QxCollectionIterator.h
Normal file
100
include/QxCollection/QxCollectionIterator.h
Normal file
@@ -0,0 +1,100 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** https://www.qxorm.com/
|
||||
** Copyright (C) 2013 XDL Team (ic-east.com)
|
||||
**
|
||||
** This file is part of the QxOrm library
|
||||
**
|
||||
** This software is provided 'as-is', without any express or implied
|
||||
** warranty. In no event will the authors be held liable for any
|
||||
** damages arising from the use of this software
|
||||
**
|
||||
** Commercial Usage
|
||||
** Licensees holding valid commercial QxOrm licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and XDL Team
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file 'license.gpl3.txt' included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met : http://www.gnu.org/copyleft/gpl.html
|
||||
**
|
||||
** If you are unsure which license is appropriate for your use, or
|
||||
** if you have questions regarding the use of this file, please contact :
|
||||
** ic-east.com
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef _QX_COLLECTION_ITERATOR_H_
|
||||
#define _QX_COLLECTION_ITERATOR_H_
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* \file QxCollectionIterator.h
|
||||
* \author XDL Team
|
||||
* \ingroup QxCollection
|
||||
* \brief Java-style iterator to iterate over a qx::QxCollection<Key, Value> container
|
||||
*/
|
||||
|
||||
#include <QxCollection/QxCollection.h>
|
||||
|
||||
namespace qx
|
||||
{
|
||||
|
||||
/*!
|
||||
* \ingroup QxCollection
|
||||
* \brief qx::QxCollectionIterator : Java-style iterator to iterate over a qx::QxCollection<Key, Value> container
|
||||
*
|
||||
* Quick sample using qx::QxCollectionIterator Java-style iterator :
|
||||
* \code
|
||||
// iterate over a drugs container using 'qx::QxCollectionIterator' Java-style iterator
|
||||
qx::QxCollectionIterator<QString, drug_ptr> itr(lstDrugs);
|
||||
while (itr.next())
|
||||
{
|
||||
QString code = itr.key();
|
||||
qDebug() << qPrintable(itr.value()->name) << " " << qPrintable(itr.value()->desc);
|
||||
}
|
||||
* \endcode
|
||||
*/
|
||||
template <typename Key, typename Value>
|
||||
class QxCollectionIterator
|
||||
{
|
||||
|
||||
private:
|
||||
const QxCollection<Key, Value> *m_pCollection; //!< Collection to iterate over
|
||||
long m_lCurrIndex; //!< Current index (position) in the collection
|
||||
|
||||
public:
|
||||
QxCollectionIterator(const QxCollection<Key, Value> &col); //!< Construct an iterator for traversing the collection. The iterator is set to be at the front of the list (before the first item)
|
||||
~QxCollectionIterator(); //!< Destroy the iterator
|
||||
|
||||
inline const Key &key() const; //!< Return the 'key' at current position
|
||||
inline const Value &value() const; //!< Return the 'value' at current position
|
||||
|
||||
inline void toFirst(); //!< Move the iterator to the front of the container (before the first item)
|
||||
inline void toLast(); //!< Move the iterator to the back of the container (after the last item)
|
||||
|
||||
inline bool next(); //!< Advance the iterator by one position. Return 'true' if there is at least one item ahead of the iterator, i.e. the iterator is not at the back of the container; otherwise return 'false'
|
||||
inline bool previous(); //!< Move the iterator back by one position. Return 'true' if there is at least one item behind the iterator, i.e. the iterator is not at the front of the container; otherwise return 'false'
|
||||
|
||||
private:
|
||||
QxCollectionIterator(const QxCollectionIterator &other) { Q_UNUSED(other); }
|
||||
QxCollectionIterator &operator=(const QxCollectionIterator &other)
|
||||
{
|
||||
Q_UNUSED(other);
|
||||
return (*this);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace qx
|
||||
|
||||
#include "../../inl/QxCollection/QxCollectionIterator.inl"
|
||||
|
||||
#endif // _QX_COLLECTION_ITERATOR_H_
|
||||
206
include/QxCollection/QxForeach.h
Normal file
206
include/QxCollection/QxForeach.h
Normal file
@@ -0,0 +1,206 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** https://www.qxorm.com/
|
||||
** Copyright (C) 2013 XDL Team (ic-east.com)
|
||||
**
|
||||
** This file is part of the QxOrm library
|
||||
**
|
||||
** This software is provided 'as-is', without any express or implied
|
||||
** warranty. In no event will the authors be held liable for any
|
||||
** damages arising from the use of this software
|
||||
**
|
||||
** Commercial Usage
|
||||
** Licensees holding valid commercial QxOrm licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and XDL Team
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file 'license.gpl3.txt' included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met : http://www.gnu.org/copyleft/gpl.html
|
||||
**
|
||||
** If you are unsure which license is appropriate for your use, or
|
||||
** if you have questions regarding the use of this file, please contact :
|
||||
** ic-east.com
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifdef _QX_ENABLE_BOOST
|
||||
#ifndef _QX_FOREACH_H_
|
||||
#define _QX_FOREACH_H_
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma once
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* \file QxForeach.h
|
||||
* \author XDL Team
|
||||
* \ingroup QxCollection
|
||||
* \brief foreach-style (based on BOOST_FOREACH macro) to iterate over all stl, boost and Qt containers + qx::QxCollection<Key, Value> QxOrm library container
|
||||
*
|
||||
* Quick sample using QX_FOREACH (or _foreach) macro :
|
||||
* \code
|
||||
// iterate over drugs container using QxOrm '_foreach' keyword
|
||||
_foreach(drug_ptr p, lstDrugs)
|
||||
{ qDebug() << qPrintable(p->name) << " " << qPrintable(p->desc); }
|
||||
* \endcode
|
||||
*
|
||||
* \note QxOrm library provides also other macros to iterator over all containers : _foreach_reverse, _foreach_if, _foreach_reverse_if
|
||||
*/
|
||||
|
||||
#include <boost/foreach.hpp>
|
||||
|
||||
#ifndef BOOST_FOREACH_ID
|
||||
#define BOOST_FOREACH_ID(x) x
|
||||
#endif
|
||||
|
||||
#include <QxTraits/is_qx_collection.h>
|
||||
|
||||
namespace qx
|
||||
{
|
||||
|
||||
namespace foreach
|
||||
{
|
||||
|
||||
template <typename T, typename C, bool is_qx_collection = false>
|
||||
struct qx_deref_boost_or_qx
|
||||
{
|
||||
typedef typename boost::foreach_detail_::foreach_reference<T, C>::type type;
|
||||
};
|
||||
|
||||
template <typename T, typename C>
|
||||
struct qx_deref_boost_or_qx<T, C, true>
|
||||
{
|
||||
typedef typename T::type_pair_key_value::second_type type;
|
||||
};
|
||||
|
||||
template <typename T, typename C, bool is_qx_collection = false>
|
||||
struct qx_deref_deduce
|
||||
{
|
||||
static inline typename qx::foreach::qx_deref_boost_or_qx<T, C, false>::type
|
||||
deref(boost::foreach_detail_::auto_any_t cur, boost::foreach_detail_::type2type<T, C> *ptmp)
|
||||
{
|
||||
return boost::foreach_detail_::deref(cur, ptmp);
|
||||
}
|
||||
|
||||
static inline typename qx::foreach::qx_deref_boost_or_qx<T, C, false>::type
|
||||
rderef(boost::foreach_detail_::auto_any_t cur, boost::foreach_detail_::type2type<T, C> *ptmp)
|
||||
{
|
||||
return boost::foreach_detail_::rderef(cur, ptmp);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, typename C>
|
||||
struct qx_deref_deduce<T, C, true>
|
||||
{
|
||||
static inline typename qx::foreach::qx_deref_boost_or_qx<T, C, true>::type
|
||||
deref(boost::foreach_detail_::auto_any_t cur, boost::foreach_detail_::type2type<T, C> *ptmp)
|
||||
{
|
||||
return boost::foreach_detail_::deref(cur, ptmp).second;
|
||||
}
|
||||
|
||||
static inline typename qx::foreach::qx_deref_boost_or_qx<T, C, true>::type
|
||||
rderef(boost::foreach_detail_::auto_any_t cur, boost::foreach_detail_::type2type<T, C> *ptmp)
|
||||
{
|
||||
return boost::foreach_detail_::rderef(cur, ptmp).second;
|
||||
}
|
||||
};
|
||||
|
||||
struct qx_deref
|
||||
{
|
||||
template <typename T, typename C>
|
||||
static inline typename qx::foreach::qx_deref_boost_or_qx<T, C, qx::trait::is_qx_collection<T>::value>::type
|
||||
deref(boost::foreach_detail_::auto_any_t cur, boost::foreach_detail_::type2type<T, C> *ptmp)
|
||||
{
|
||||
return qx::foreach::qx_deref_deduce<T, C, qx::trait::is_qx_collection<T>::value>::deref(cur, ptmp);
|
||||
}
|
||||
|
||||
template <typename T, typename C>
|
||||
static inline typename qx::foreach::qx_deref_boost_or_qx<T, C, qx::trait::is_qx_collection<T>::value>::type
|
||||
deref_reverse(boost::foreach_detail_::auto_any_t cur, boost::foreach_detail_::type2type<T, C> *ptmp)
|
||||
{
|
||||
return qx::foreach::qx_deref_deduce<T, C, qx::trait::is_qx_collection<T>::value>::rderef(cur, ptmp);
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace foreach
|
||||
|
||||
} // namespace qx
|
||||
|
||||
#define QX_FOREACH_DEREF(COL) \
|
||||
qx::foreach::qx_deref::deref(BOOST_FOREACH_ID(_foreach_cur), BOOST_FOREACH_TYPEOF(COL))
|
||||
|
||||
#define QX_FOREACH_DEREF_REVERSE(COL) \
|
||||
qx::foreach::qx_deref::deref_reverse(BOOST_FOREACH_ID(_foreach_cur), BOOST_FOREACH_TYPEOF(COL))
|
||||
|
||||
#define QX_FOREACH(VAR, COL) \
|
||||
BOOST_FOREACH_PREAMBLE() \
|
||||
if (boost::foreach_detail_::auto_any_t BOOST_FOREACH_ID(_foreach_col) = BOOST_FOREACH_CONTAIN(COL)) \
|
||||
{ \
|
||||
} \
|
||||
else if (boost::foreach_detail_::auto_any_t BOOST_FOREACH_ID(_foreach_cur) = BOOST_FOREACH_BEGIN(COL)) \
|
||||
{ \
|
||||
} \
|
||||
else if (boost::foreach_detail_::auto_any_t BOOST_FOREACH_ID(_foreach_end) = BOOST_FOREACH_END(COL)) \
|
||||
{ \
|
||||
} \
|
||||
else \
|
||||
for (bool BOOST_FOREACH_ID(_foreach_continue) = true; \
|
||||
BOOST_FOREACH_ID(_foreach_continue) && !BOOST_FOREACH_DONE(COL); \
|
||||
BOOST_FOREACH_ID(_foreach_continue) ? BOOST_FOREACH_NEXT(COL) : (void)0) \
|
||||
if (boost::foreach_detail_::set_false(BOOST_FOREACH_ID(_foreach_continue))) \
|
||||
{ \
|
||||
} \
|
||||
else \
|
||||
for (VAR = QX_FOREACH_DEREF(COL); !BOOST_FOREACH_ID(_foreach_continue); BOOST_FOREACH_ID(_foreach_continue) = true)
|
||||
|
||||
#define QX_FOREACH_REVERSE(VAR, COL) \
|
||||
BOOST_FOREACH_PREAMBLE() \
|
||||
if (boost::foreach_detail_::auto_any_t BOOST_FOREACH_ID(_foreach_col) = BOOST_FOREACH_CONTAIN(COL)) \
|
||||
{ \
|
||||
} \
|
||||
else if (boost::foreach_detail_::auto_any_t BOOST_FOREACH_ID(_foreach_cur) = BOOST_FOREACH_RBEGIN(COL)) \
|
||||
{ \
|
||||
} \
|
||||
else if (boost::foreach_detail_::auto_any_t BOOST_FOREACH_ID(_foreach_end) = BOOST_FOREACH_REND(COL)) \
|
||||
{ \
|
||||
} \
|
||||
else \
|
||||
for (bool BOOST_FOREACH_ID(_foreach_continue) = true; \
|
||||
BOOST_FOREACH_ID(_foreach_continue) && !BOOST_FOREACH_RDONE(COL); \
|
||||
BOOST_FOREACH_ID(_foreach_continue) ? BOOST_FOREACH_RNEXT(COL) : (void)0) \
|
||||
if (boost::foreach_detail_::set_false(BOOST_FOREACH_ID(_foreach_continue))) \
|
||||
{ \
|
||||
} \
|
||||
else \
|
||||
for (VAR = QX_FOREACH_DEREF_REVERSE(COL); !BOOST_FOREACH_ID(_foreach_continue); BOOST_FOREACH_ID(_foreach_continue) = true)
|
||||
|
||||
#ifdef _foreach
|
||||
#undef _foreach
|
||||
#endif // _foreach
|
||||
|
||||
#ifdef _foreach_reverse
|
||||
#undef _foreach_reverse
|
||||
#endif // _foreach_reverse
|
||||
|
||||
#ifdef _foreach_if
|
||||
#undef _foreach_if
|
||||
#endif // _foreach_if
|
||||
|
||||
#ifdef _foreach_reverse_if
|
||||
#undef _foreach_reverse_if
|
||||
#endif // _foreach_reverse_if
|
||||
|
||||
#define _foreach QX_FOREACH
|
||||
#define _foreach_reverse QX_FOREACH_REVERSE
|
||||
|
||||
#define _foreach_if(VAR, COL, COND) _foreach(VAR, COL) if (COND)
|
||||
#define _foreach_reverse_if(VAR, COL, COND) _foreach_reverse(VAR, COL) if (COND)
|
||||
|
||||
#endif // _QX_FOREACH_H_
|
||||
#endif // _QX_ENABLE_BOOST
|
||||
Reference in New Issue
Block a user