File indexing completed on 2024-04-28 15:40:25

0001 /*
0002   SPDX-FileCopyrightText: 2006-2020 Tuomas Suutari <thsuut@utu.fi>
0003 
0004   SPDX-License-Identifier: GPL-2.0-or-later
0005 
0006   This program is distributed in the hope that it will be useful, but
0007   WITHOUT ANY WARRANTY; without even the implied warranty of
0008   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0009   General Public License for more details.
0010 
0011   You should have received a copy of the GNU General Public License
0012   along with this program (see the file COPYING); if not, write to the
0013   Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
0014   MA 02110-1301 USA.
0015 */
0016 
0017 #include "List.h"
0018 
0019 #include <DB/RawId.h>
0020 #include <kpabase/FileName.h>
0021 
0022 #include <QList>
0023 #include <QStringList>
0024 #include <QTime>
0025 #include <algorithm> // std::swap
0026 #include <stdlib.h> // rand
0027 
0028 template <class T>
0029 QList<T> Utilities::mergeListsUniqly(const QList<T> &l1, const QList<T> &l2)
0030 {
0031     QList<T> r = l1;
0032     for (const T &x : l2)
0033         if (!r.contains(x))
0034             r.append(x);
0035     return r;
0036 }
0037 
0038 namespace
0039 {
0040 template <class T>
0041 class AutoDeletedArray
0042 {
0043 public:
0044     AutoDeletedArray(uint size)
0045         : m_ptr(new T[size])
0046     {
0047     }
0048     operator T *() const { return m_ptr; }
0049     ~AutoDeletedArray() { delete[] m_ptr; }
0050 
0051 private:
0052     T *m_ptr;
0053 };
0054 }
0055 
0056 template <class T>
0057 QList<T> Utilities::shuffleList(const QList<T> &list)
0058 {
0059     static bool init = false;
0060     if (!init) {
0061         QTime midnight(0, 0, 0);
0062         srand(midnight.secsTo(QTime::currentTime()));
0063         init = true;
0064     }
0065 
0066     // Take pointers from input list to an array for shuffling
0067     uint N = list.size();
0068     AutoDeletedArray<const T *> deck(N);
0069     const T **p = deck;
0070     for (typename QList<T>::const_iterator i = list.begin();
0071          i != list.end(); ++i) {
0072         *p = &(*i);
0073         ++p;
0074     }
0075 
0076     // Shuffle the array of pointers
0077     for (uint i = 0; i < N; i++) {
0078         uint r = i + static_cast<uint>(static_cast<double>(N - i) * rand() / static_cast<double>(RAND_MAX));
0079         std::swap(deck[r], deck[i]);
0080     }
0081 
0082     // Create new list from the array
0083     QList<T> result;
0084     const T **const onePastLast = deck + N;
0085     for (p = deck; p != onePastLast; ++p)
0086         result.push_back(**p);
0087 
0088     return result;
0089 }
0090 
0091 #define INSTANTIATE_MERGELISTSUNIQLY(T) \
0092     template QList<T> Utilities::mergeListsUniqly(const QList<T> &l1, const QList<T> &l2)
0093 
0094 #define INSTANTIATE_SHUFFLELIST(T) \
0095     template QList<T> Utilities::shuffleList(const QList<T> &list)
0096 
0097 INSTANTIATE_MERGELISTSUNIQLY(DB::RawId);
0098 INSTANTIATE_MERGELISTSUNIQLY(QString);
0099 INSTANTIATE_SHUFFLELIST(DB::FileName);
0100 // vi:expandtab:tabstop=4 shiftwidth=4: