2007-08-17 00:36:07 +02:00
|
|
|
|
/*
|
2007-08-23 17:52:33 +02:00
|
|
|
|
UTIL.hpp - collection of small helper functions used "everywhere"
|
2010-12-17 23:28:49 +01:00
|
|
|
|
|
Copyright: clarify and simplify the file headers
* Lumiera source code always was copyrighted by individual contributors
* there is no entity "Lumiera.org" which holds any copyrights
* Lumiera source code is provided under the GPL Version 2+
== Explanations ==
Lumiera as a whole is distributed under Copyleft, GNU General Public License Version 2 or above.
For this to become legally effective, the ''File COPYING in the root directory is sufficient.''
The licensing header in each file is not strictly necessary, yet considered good practice;
attaching a licence notice increases the likeliness that this information is retained
in case someone extracts individual code files. However, it is not by the presence of some
text, that legally binding licensing terms become effective; rather the fact matters that a
given piece of code was provably copyrighted and published under a license. Even reformatting
the code, renaming some variables or deleting parts of the code will not alter this legal
situation, but rather creates a derivative work, which is likewise covered by the GPL!
The most relevant information in the file header is the notice regarding the
time of the first individual copyright claim. By virtue of this initial copyright,
the first author is entitled to choose the terms of licensing. All further
modifications are permitted and covered by the License. The specific wording
or format of the copyright header is not legally relevant, as long as the
intention to publish under the GPL remains clear. The extended wording was
based on a recommendation by the FSF. It can be shortened, because the full terms
of the license are provided alongside the distribution, in the file COPYING.
2024-11-17 23:42:55 +01:00
|
|
|
|
Copyright (C)
|
|
|
|
|
|
2008, Hermann Vosseler <Ichthyostega@web.de>
|
2010-12-17 23:28:49 +01:00
|
|
|
|
|
Copyright: clarify and simplify the file headers
* Lumiera source code always was copyrighted by individual contributors
* there is no entity "Lumiera.org" which holds any copyrights
* Lumiera source code is provided under the GPL Version 2+
== Explanations ==
Lumiera as a whole is distributed under Copyleft, GNU General Public License Version 2 or above.
For this to become legally effective, the ''File COPYING in the root directory is sufficient.''
The licensing header in each file is not strictly necessary, yet considered good practice;
attaching a licence notice increases the likeliness that this information is retained
in case someone extracts individual code files. However, it is not by the presence of some
text, that legally binding licensing terms become effective; rather the fact matters that a
given piece of code was provably copyrighted and published under a license. Even reformatting
the code, renaming some variables or deleting parts of the code will not alter this legal
situation, but rather creates a derivative work, which is likewise covered by the GPL!
The most relevant information in the file header is the notice regarding the
time of the first individual copyright claim. By virtue of this initial copyright,
the first author is entitled to choose the terms of licensing. All further
modifications are permitted and covered by the License. The specific wording
or format of the copyright header is not legally relevant, as long as the
intention to publish under the GPL remains clear. The extended wording was
based on a recommendation by the FSF. It can be shortened, because the full terms
of the license are provided alongside the distribution, in the file COPYING.
2024-11-17 23:42:55 +01:00
|
|
|
|
**Lumiera** is free software; you can redistribute it and/or modify it
|
|
|
|
|
|
under the terms of the GNU General Public License as published by the
|
|
|
|
|
|
Free Software Foundation; either version 2 of the License, or (at your
|
|
|
|
|
|
option) any later version. See the file COPYING for further details.
|
2010-12-17 23:28:49 +01:00
|
|
|
|
|
2007-08-17 00:36:07 +02:00
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
2017-04-02 04:22:51 +02:00
|
|
|
|
/** @file lib/util.hpp
|
2016-11-08 13:18:05 +01:00
|
|
|
|
** Tiny helper functions and shortcuts to be used _everywhere_
|
|
|
|
|
|
** Consider this header to be effectively included in almost every translation unit.
|
|
|
|
|
|
** @remark The motivation of using these helpers is conciseness and uniformity of expression.
|
2024-11-14 22:10:43 +01:00
|
|
|
|
** Further extensions and not-so-frequently used supplements are packaged into separate headers.
|
2016-11-08 13:18:05 +01:00
|
|
|
|
** @warning be sure to understand the ramifications of including _anything_ here...
|
|
|
|
|
|
** @see util-coll.hpp
|
|
|
|
|
|
** @see util-quant.hpp
|
2024-11-14 22:10:43 +01:00
|
|
|
|
** @see util-foreach.hpp
|
2016-11-03 18:20:10 +01:00
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
|
2012-03-04 01:34:18 +01:00
|
|
|
|
#ifndef LIB_UTIL_H
|
|
|
|
|
|
#define LIB_UTIL_H
|
2007-08-17 00:36:07 +02:00
|
|
|
|
|
2024-03-12 20:14:29 +01:00
|
|
|
|
#include "include/limits.hpp"
|
2014-08-17 08:03:21 +02:00
|
|
|
|
#include "lib/hash-standard.hpp"
|
2012-12-11 04:07:06 +01:00
|
|
|
|
|
2007-08-17 00:36:07 +02:00
|
|
|
|
#include <string>
|
2024-03-16 00:01:49 +01:00
|
|
|
|
|
|
|
|
|
|
namespace std {// forward declarations to avoid pervasive includes
|
|
|
|
|
|
|
|
|
|
|
|
template<typename T>
|
|
|
|
|
|
class allocator;
|
|
|
|
|
|
template<typename K, typename CMP, class ALLO>
|
|
|
|
|
|
class set;
|
|
|
|
|
|
|
|
|
|
|
|
template<typename IT, typename V>
|
2025-06-18 16:50:19 +02:00
|
|
|
|
constexpr IT find (IT, IT, V const&);
|
2024-03-16 00:01:49 +01:00
|
|
|
|
template<typename IT, typename V>
|
2025-06-18 16:50:19 +02:00
|
|
|
|
constexpr IT remove (IT, IT, V const&);
|
2024-03-16 00:01:49 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const char* cStr (std::string const&);
|
2007-08-17 00:36:07 +02:00
|
|
|
|
|
2007-09-06 22:13:26 +02:00
|
|
|
|
|
2007-08-17 00:36:07 +02:00
|
|
|
|
|
2008-12-03 06:02:54 +01:00
|
|
|
|
namespace util {
|
|
|
|
|
|
|
2007-08-17 00:36:07 +02:00
|
|
|
|
using std::string;
|
2024-03-16 00:01:49 +01:00
|
|
|
|
using CStr = const char*;
|
2008-12-03 06:02:54 +01:00
|
|
|
|
|
2007-09-19 05:05:25 +02:00
|
|
|
|
|
|
|
|
|
|
template <class NUM>
|
2025-06-18 16:50:19 +02:00
|
|
|
|
inline constexpr int
|
2007-09-19 05:05:25 +02:00
|
|
|
|
sgn (NUM n)
|
|
|
|
|
|
{
|
|
|
|
|
|
return (n==0)? 0 :((n<0)? -1:+1 );
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2009-07-18 22:07:46 +02:00
|
|
|
|
template <class N1, class N2>
|
2025-06-18 16:50:19 +02:00
|
|
|
|
inline constexpr N1
|
2009-07-18 22:07:46 +02:00
|
|
|
|
min (N1 n1, N2 n2)
|
|
|
|
|
|
{
|
|
|
|
|
|
return n2 < n1? N1(n2) : n1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <class N1, class N2>
|
2025-06-18 16:50:19 +02:00
|
|
|
|
inline constexpr N1
|
2009-07-18 22:07:46 +02:00
|
|
|
|
max (N1 n1, N2 n2)
|
|
|
|
|
|
{
|
|
|
|
|
|
return n1 < n2? N1(n2) : n1;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2012-12-11 04:07:06 +01:00
|
|
|
|
/** cut a numeric value to be >=0 */
|
|
|
|
|
|
template <typename NUM>
|
2025-06-18 16:50:19 +02:00
|
|
|
|
inline constexpr NUM
|
2012-12-11 04:07:06 +01:00
|
|
|
|
noneg (NUM val)
|
|
|
|
|
|
{
|
|
|
|
|
|
return (0<val? val : 0);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** force a numeric to be within bounds, inclusively */
|
|
|
|
|
|
template <typename NUM, typename NB>
|
2025-06-18 16:50:19 +02:00
|
|
|
|
inline constexpr NUM
|
2012-12-11 04:07:06 +01:00
|
|
|
|
limited (NB lowerBound, NUM val, NB upperBound)
|
|
|
|
|
|
{
|
|
|
|
|
|
return min ( max (val, lowerBound)
|
|
|
|
|
|
, upperBound);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-01-01 22:42:51 +01:00
|
|
|
|
template <typename NUM, typename NB>
|
2025-06-18 16:50:19 +02:00
|
|
|
|
inline constexpr bool
|
2024-01-01 22:42:51 +01:00
|
|
|
|
isLimited (NB lowerBound, NUM val, NB upperBound)
|
|
|
|
|
|
{
|
|
|
|
|
|
return lowerBound <= val
|
|
|
|
|
|
and val <= upperBound;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-06-19 15:22:26 +02:00
|
|
|
|
template <typename UN, typename N2>
|
2025-06-18 16:50:19 +02:00
|
|
|
|
inline constexpr UN
|
2024-06-19 15:22:26 +02:00
|
|
|
|
positiveDiff (N2 newVal, UN refVal)
|
|
|
|
|
|
{
|
|
|
|
|
|
return UN(newVal) > refVal? UN(newVal) - refVal
|
|
|
|
|
|
: UN(0);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2012-12-11 04:07:06 +01:00
|
|
|
|
/** positive integral number from textual representation
|
2021-08-20 14:33:21 +02:00
|
|
|
|
* @return always a number, 0 in case of unparseable text,
|
2012-12-11 04:07:06 +01:00
|
|
|
|
* limited to 0 <= num <= LUMIERA_MAX_ORDINAL_NUMBER */
|
|
|
|
|
|
inline uint
|
2024-03-16 00:01:49 +01:00
|
|
|
|
uNum (CStr charPtr)
|
2012-12-11 04:07:06 +01:00
|
|
|
|
{
|
2024-03-16 00:01:49 +01:00
|
|
|
|
if (!charPtr) return 0;
|
|
|
|
|
|
int parsedNumber (std::atoi (charPtr));
|
2012-12-11 04:07:06 +01:00
|
|
|
|
return limited (0, parsedNumber, LUMIERA_MAX_ORDINAL_NUMBER);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
inline int
|
2024-03-16 00:01:49 +01:00
|
|
|
|
sNum (CStr charPtr)
|
2012-12-11 04:07:06 +01:00
|
|
|
|
{
|
2024-03-16 00:01:49 +01:00
|
|
|
|
if (!charPtr) return 0;
|
|
|
|
|
|
int parsedNumber (std::atoi (charPtr));
|
2012-12-11 04:07:06 +01:00
|
|
|
|
return limited (-LUMIERA_MAX_ORDINAL_NUMBER, parsedNumber, LUMIERA_MAX_ORDINAL_NUMBER);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-03-16 00:01:49 +01:00
|
|
|
|
template<class OBJ>
|
2012-12-11 04:07:06 +01:00
|
|
|
|
inline uint
|
2024-03-16 00:01:49 +01:00
|
|
|
|
uNum (OBJ const& spec)
|
2012-12-11 04:07:06 +01:00
|
|
|
|
{
|
2024-03-16 00:01:49 +01:00
|
|
|
|
return uNum (cStr(spec));
|
2012-12-11 04:07:06 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2024-03-16 00:01:49 +01:00
|
|
|
|
template<class OBJ>
|
2012-12-11 04:07:06 +01:00
|
|
|
|
inline int
|
2024-03-16 00:01:49 +01:00
|
|
|
|
sNum (OBJ const& spec)
|
2012-12-11 04:07:06 +01:00
|
|
|
|
{
|
2024-03-16 00:01:49 +01:00
|
|
|
|
return sNum (cStr(spec));
|
2012-12-11 04:07:06 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2011-01-20 21:30:48 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* ======== generic empty check ========= */
|
2008-12-03 06:02:54 +01:00
|
|
|
|
|
2007-08-29 05:03:21 +02:00
|
|
|
|
/** a family of util functions providing a "no value whatsoever" test.
|
|
|
|
|
|
Works on strings and all STL containers, includes NULL test for pointers */
|
|
|
|
|
|
template <class CONT>
|
2007-09-07 23:24:13 +02:00
|
|
|
|
inline bool
|
2007-09-19 05:05:25 +02:00
|
|
|
|
isnil (const CONT& container)
|
2007-08-26 19:14:39 +02:00
|
|
|
|
{
|
2007-08-29 05:03:21 +02:00
|
|
|
|
return container.empty();
|
2007-08-26 19:14:39 +02:00
|
|
|
|
}
|
2007-08-23 17:52:33 +02:00
|
|
|
|
|
2007-08-29 05:03:21 +02:00
|
|
|
|
template <class CONT>
|
2007-09-07 23:24:13 +02:00
|
|
|
|
inline bool
|
2007-09-19 05:05:25 +02:00
|
|
|
|
isnil (const CONT* pContainer)
|
2007-08-26 19:14:39 +02:00
|
|
|
|
{
|
2019-11-08 20:49:37 +01:00
|
|
|
|
return !pContainer or pContainer->empty();
|
2007-08-26 19:14:39 +02:00
|
|
|
|
}
|
2007-08-23 17:52:33 +02:00
|
|
|
|
|
2009-01-10 16:15:17 +01:00
|
|
|
|
template <class CONT>
|
|
|
|
|
|
inline bool
|
|
|
|
|
|
isnil (CONT* pContainer)
|
|
|
|
|
|
{
|
2019-11-08 20:49:37 +01:00
|
|
|
|
return !pContainer or pContainer->empty();
|
2009-01-10 16:15:17 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
2007-09-07 23:24:13 +02:00
|
|
|
|
inline bool
|
2024-03-16 00:01:49 +01:00
|
|
|
|
isnil (CStr charPtr)
|
2007-08-26 19:14:39 +02:00
|
|
|
|
{
|
2024-03-16 00:01:49 +01:00
|
|
|
|
return !charPtr or !(*charPtr);
|
2007-08-26 19:14:39 +02:00
|
|
|
|
}
|
2008-12-03 06:02:54 +01:00
|
|
|
|
|
2007-08-23 17:52:33 +02:00
|
|
|
|
|
|
|
|
|
|
|
2024-11-14 22:10:43 +01:00
|
|
|
|
/* ======== string and containment ========= */
|
|
|
|
|
|
|
2015-07-03 02:53:27 +02:00
|
|
|
|
/** check if string starts with a given prefix */
|
|
|
|
|
|
inline bool
|
|
|
|
|
|
startsWith (string const& str, string const& prefix)
|
|
|
|
|
|
{
|
2024-03-16 00:01:49 +01:00
|
|
|
|
return 0 == str.rfind (prefix, 0);
|
2015-07-03 02:53:27 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
inline bool
|
2024-03-16 00:01:49 +01:00
|
|
|
|
startsWith (string const& str, CStr prefix)
|
2015-07-03 02:53:27 +02:00
|
|
|
|
{
|
2024-03-16 00:01:49 +01:00
|
|
|
|
return 0 == str.rfind (prefix, 0);
|
2015-07-03 02:53:27 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2016-01-02 22:32:42 +01:00
|
|
|
|
/** check if string ends with the given suffix */
|
|
|
|
|
|
inline bool
|
|
|
|
|
|
endsWith (string const& str, string const& suffix)
|
|
|
|
|
|
{
|
|
|
|
|
|
size_t l = suffix.length();
|
|
|
|
|
|
if (l > str.length()) return false;
|
|
|
|
|
|
size_t pos = str.length() - l;
|
2024-03-16 00:01:49 +01:00
|
|
|
|
return pos == str.find (suffix, pos);
|
2016-01-02 22:32:42 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
inline bool
|
2024-03-16 00:01:49 +01:00
|
|
|
|
endsWith (string const& str, CStr suffix)
|
2016-01-02 22:32:42 +01:00
|
|
|
|
{
|
|
|
|
|
|
return endsWith (str, string(suffix));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
inline void
|
|
|
|
|
|
removePrefix (string& str, string const& prefix)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (not startsWith (str,prefix)) return;
|
|
|
|
|
|
str = str.substr (prefix.length());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
inline void
|
|
|
|
|
|
removeSuffix (string& str, string const& suffix)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (not endsWith (str,suffix)) return;
|
|
|
|
|
|
str.resize(str.length() - suffix.length());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2015-07-03 02:53:27 +02:00
|
|
|
|
|
2007-08-23 17:52:33 +02:00
|
|
|
|
/** shortcut for containment test on a map */
|
|
|
|
|
|
template <typename MAP>
|
2021-08-20 14:33:21 +02:00
|
|
|
|
inline bool
|
2009-09-26 04:19:57 +02:00
|
|
|
|
contains (MAP& map, typename MAP::key_type const& key)
|
2007-08-26 19:14:39 +02:00
|
|
|
|
{
|
|
|
|
|
|
return map.find(key) != map.end();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2007-09-25 23:39:46 +02:00
|
|
|
|
/** shortcut for set value containment test */
|
2024-03-16 00:01:49 +01:00
|
|
|
|
template <typename T, class CMP, class ALO>
|
2021-08-20 14:33:21 +02:00
|
|
|
|
inline bool
|
2024-03-16 00:01:49 +01:00
|
|
|
|
contains (std::set<T,CMP,ALO> const& set, T const& val)
|
2007-09-25 23:39:46 +02:00
|
|
|
|
{
|
|
|
|
|
|
return set.end() != set.find (val);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2008-01-12 18:19:37 +01:00
|
|
|
|
/** shortcut for string value containment test */
|
|
|
|
|
|
template <typename T>
|
2021-08-20 14:33:21 +02:00
|
|
|
|
inline bool
|
2009-07-25 19:20:21 +02:00
|
|
|
|
contains (std::string const& str, const T& val)
|
2008-01-12 18:19:37 +01:00
|
|
|
|
{
|
|
|
|
|
|
return str.find (val) != std::string::npos;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2007-09-25 23:39:46 +02:00
|
|
|
|
/** shortcut for brute-force containment test
|
2008-12-03 06:02:54 +01:00
|
|
|
|
* in any sequential container */
|
2007-09-25 23:39:46 +02:00
|
|
|
|
template <typename SEQ>
|
2021-08-20 14:33:21 +02:00
|
|
|
|
inline bool
|
2009-07-25 19:20:21 +02:00
|
|
|
|
contains (SEQ const& cont, typename SEQ::const_reference val)
|
2007-09-25 23:39:46 +02:00
|
|
|
|
{
|
2007-11-21 06:08:01 +01:00
|
|
|
|
typename SEQ::const_iterator begin = cont.begin();
|
|
|
|
|
|
typename SEQ::const_iterator end = cont.end();
|
|
|
|
|
|
|
|
|
|
|
|
return end != std::find(begin,end, val);
|
2007-09-25 23:39:46 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
2019-11-08 20:49:37 +01:00
|
|
|
|
/** use (and exhaust) a »Lumiera Forward Iterator« for linear search */
|
|
|
|
|
|
template <class IT>
|
|
|
|
|
|
inline bool
|
|
|
|
|
|
linearSearch (IT iter, typename IT::value_type const& val)
|
|
|
|
|
|
{
|
|
|
|
|
|
IT end{};
|
|
|
|
|
|
return end != std::find (std::move (iter), end, val);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2009-09-26 04:19:57 +02:00
|
|
|
|
/** fetch value from a Map, or return a default if not found */
|
|
|
|
|
|
template <typename MAP>
|
2009-09-26 16:42:57 +02:00
|
|
|
|
inline typename MAP::mapped_type
|
2009-09-26 04:19:57 +02:00
|
|
|
|
getValue_or_default (MAP& map, typename MAP::key_type const& key
|
2009-09-26 16:42:57 +02:00
|
|
|
|
, typename MAP::mapped_type defaultVal)
|
2009-09-26 04:19:57 +02:00
|
|
|
|
{
|
2009-09-26 16:42:57 +02:00
|
|
|
|
typename MAP::const_iterator pos = map.find (key);
|
2009-09-26 04:19:57 +02:00
|
|
|
|
if (pos != map.end())
|
|
|
|
|
|
return pos->second;
|
|
|
|
|
|
else
|
|
|
|
|
|
return defaultVal;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2013-09-07 02:37:17 +02:00
|
|
|
|
/** expose a reference to a map entry, with fall-back to some default object
|
|
|
|
|
|
* @note exposing a const reference; especially the default needs to reside
|
|
|
|
|
|
* somewhere at a safe storage location.
|
|
|
|
|
|
* @see lib::NullValue
|
|
|
|
|
|
*/
|
|
|
|
|
|
template <typename MAP>
|
|
|
|
|
|
inline typename MAP::mapped_type const &
|
|
|
|
|
|
access_or_default (MAP& map, typename MAP::key_type const& key
|
|
|
|
|
|
, typename MAP::mapped_type const& refDefault)
|
|
|
|
|
|
{
|
|
|
|
|
|
typename MAP::const_iterator pos = map.find (key);
|
|
|
|
|
|
if (pos != map.end())
|
|
|
|
|
|
return pos->second;
|
|
|
|
|
|
else
|
|
|
|
|
|
return refDefault;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2007-11-19 04:58:18 +01:00
|
|
|
|
/** shortcut for removing all copies of an Element
|
2008-12-03 06:02:54 +01:00
|
|
|
|
* in any sequential collection */
|
2007-11-19 04:58:18 +01:00
|
|
|
|
template <typename SEQ>
|
2021-08-20 14:33:21 +02:00
|
|
|
|
inline typename SEQ::iterator
|
2019-12-21 23:57:53 +01:00
|
|
|
|
removeall (SEQ& coll, typename SEQ::value_type const& val)
|
2007-11-19 04:58:18 +01:00
|
|
|
|
{
|
|
|
|
|
|
typename SEQ::iterator collEnd = coll.end();
|
|
|
|
|
|
return coll.erase (std::remove (coll.begin(), collEnd, val),
|
|
|
|
|
|
collEnd
|
|
|
|
|
|
);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2007-08-23 17:52:33 +02:00
|
|
|
|
|
2008-03-31 03:21:28 +02:00
|
|
|
|
/** remove all elements fulfilling a given predicate
|
|
|
|
|
|
* from a (sorted) set.
|
|
|
|
|
|
* @return true if anything has been removed. */
|
2019-11-08 20:49:37 +01:00
|
|
|
|
template<class SET, typename FUN>
|
|
|
|
|
|
bool remove_if (SET& set, FUN test)
|
2008-03-31 03:21:28 +02:00
|
|
|
|
{
|
|
|
|
|
|
typedef typename SET::iterator Itor;
|
|
|
|
|
|
bool found = false;
|
|
|
|
|
|
Itor end = set.end();
|
|
|
|
|
|
Itor begin = set.begin();
|
|
|
|
|
|
Itor pos = begin;
|
|
|
|
|
|
while (pos!=end)
|
|
|
|
|
|
{
|
2019-11-08 20:49:37 +01:00
|
|
|
|
if (not test(*pos))
|
|
|
|
|
|
++pos;
|
2008-03-31 03:21:28 +02:00
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
found = true;
|
2021-08-20 14:33:21 +02:00
|
|
|
|
if (pos==begin)
|
2008-03-31 03:21:28 +02:00
|
|
|
|
{
|
|
|
|
|
|
set.erase(pos);
|
|
|
|
|
|
pos = begin = set.begin();
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
set.erase(pos--);
|
|
|
|
|
|
++pos;
|
|
|
|
|
|
}
|
|
|
|
|
|
end = set.end();
|
|
|
|
|
|
} }
|
|
|
|
|
|
return found;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2024-11-14 22:10:43 +01:00
|
|
|
|
|
|
|
|
|
|
|
2009-06-20 23:17:22 +02:00
|
|
|
|
/** shortcut to save some typing when having to define
|
|
|
|
|
|
* const and non-const variants of member functions
|
2024-11-14 22:10:43 +01:00
|
|
|
|
* @remark the »social contract« when using this function is
|
|
|
|
|
|
* that the programmer has to ensure effective const correctness!
|
2009-06-20 23:17:22 +02:00
|
|
|
|
*/
|
|
|
|
|
|
template<class OBJ>
|
2021-11-05 21:19:10 +01:00
|
|
|
|
inline OBJ*
|
2009-06-20 23:17:22 +02:00
|
|
|
|
unConst (const OBJ* o)
|
|
|
|
|
|
{
|
|
|
|
|
|
return const_cast<OBJ*> (o);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2009-10-05 00:49:37 +02:00
|
|
|
|
template<class OBJ>
|
2021-11-05 21:19:10 +01:00
|
|
|
|
inline OBJ&
|
2009-10-05 00:49:37 +02:00
|
|
|
|
unConst (OBJ const& ro)
|
|
|
|
|
|
{
|
|
|
|
|
|
return const_cast<OBJ&> (ro);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2007-11-26 04:27:27 +01:00
|
|
|
|
|
2024-11-14 22:10:43 +01:00
|
|
|
|
|
|
|
|
|
|
/* ======== address and identity ========= */
|
2009-07-04 02:43:49 +02:00
|
|
|
|
|
2023-05-05 01:34:41 +02:00
|
|
|
|
/** extract address but strip any type info */
|
|
|
|
|
|
template<class X>
|
|
|
|
|
|
inline const void*
|
2024-11-14 22:10:43 +01:00
|
|
|
|
getAdr (X& x)
|
2023-05-05 01:34:41 +02:00
|
|
|
|
{
|
|
|
|
|
|
return static_cast<const void*> (std::addressof(x));
|
|
|
|
|
|
}
|
|
|
|
|
|
template<class X>
|
|
|
|
|
|
inline const void*
|
2024-11-14 22:10:43 +01:00
|
|
|
|
getAdr (X* x)
|
2023-05-05 01:34:41 +02:00
|
|
|
|
{
|
|
|
|
|
|
return static_cast<const void*> (x);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2024-11-14 22:10:43 +01:00
|
|
|
|
/** generate an unique numeric ID based on the referred entity */
|
|
|
|
|
|
template<class X>
|
2023-11-24 15:43:26 +01:00
|
|
|
|
inline size_t
|
2024-11-14 22:10:43 +01:00
|
|
|
|
addrID (X const& x)
|
2023-11-24 15:43:26 +01:00
|
|
|
|
{
|
2024-11-14 22:10:43 +01:00
|
|
|
|
return size_t(getAdr (x));
|
2023-11-24 15:43:26 +01:00
|
|
|
|
}
|
2024-11-14 22:10:43 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** the addressable memory »slot« — platform dependent. */
|
2023-11-24 15:43:26 +01:00
|
|
|
|
template<typename X>
|
|
|
|
|
|
inline size_t
|
2024-11-14 22:10:43 +01:00
|
|
|
|
slotNr (X const& x)
|
2023-11-24 15:43:26 +01:00
|
|
|
|
{
|
2024-11-14 22:10:43 +01:00
|
|
|
|
return addrID(x) / sizeof(size_t);
|
2023-11-24 15:43:26 +01:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2024-11-14 22:10:43 +01:00
|
|
|
|
/** compare plain object address identity, disregarding type.
|
|
|
|
|
|
* @note the pointee is compared when passing pointer(s)
|
|
|
|
|
|
*/
|
|
|
|
|
|
template<class A, class B>
|
|
|
|
|
|
inline bool
|
|
|
|
|
|
isSameAdr (A const& a, B const& b)
|
|
|
|
|
|
{
|
|
|
|
|
|
return getAdr(a) == getAdr(b);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** compare plain object identity,
|
|
|
|
|
|
* based directly on the referee's memory identities.
|
|
|
|
|
|
*/
|
|
|
|
|
|
template<class A, class B>
|
|
|
|
|
|
inline bool
|
|
|
|
|
|
isSameObject (A const& a, B const& b)
|
|
|
|
|
|
{
|
|
|
|
|
|
return static_cast<const void*> (std::addressof(a))
|
|
|
|
|
|
== static_cast<const void*> (std::addressof(b));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2023-11-24 15:43:26 +01:00
|
|
|
|
/** determine heuristically if two objects
|
|
|
|
|
|
* are located „close to each other“ in memory.
|
2024-11-14 22:10:43 +01:00
|
|
|
|
* @remark can be used to find out about heap versus stack allocation
|
|
|
|
|
|
* @warning relies on platform and implementation-defined observable behaviour
|
2023-11-24 15:43:26 +01:00
|
|
|
|
*/
|
|
|
|
|
|
template<typename A, typename B>
|
|
|
|
|
|
inline bool
|
|
|
|
|
|
isCloseBy (A&& a, B&& b, size_t consideredNearby =50)
|
|
|
|
|
|
{
|
|
|
|
|
|
size_t loc1 = slotNr (std::forward<A> (a));
|
|
|
|
|
|
size_t loc2 = slotNr (std::forward<B> (b));
|
|
|
|
|
|
size_t dist = loc2 > loc1? loc2-loc1:loc1-loc2;
|
|
|
|
|
|
return dist < consideredNearby;
|
|
|
|
|
|
}
|
2023-05-05 01:34:41 +02:00
|
|
|
|
|
2009-07-04 02:43:49 +02:00
|
|
|
|
|
|
|
|
|
|
|
2007-09-06 22:13:26 +02:00
|
|
|
|
|
|
|
|
|
|
/** produce an identifier based on the given string.
|
2021-08-20 14:33:21 +02:00
|
|
|
|
* remove non-standard-chars, reduce sequences of punctuation
|
2008-12-03 06:02:54 +01:00
|
|
|
|
* and whitespace to single underscores. The sanitised string
|
2007-09-14 19:18:11 +02:00
|
|
|
|
* will start with an alphanumeric character.
|
2021-08-20 14:33:21 +02:00
|
|
|
|
*
|
2007-09-14 19:18:11 +02:00
|
|
|
|
* @par Example Conversions
|
2011-05-13 06:28:55 +02:00
|
|
|
|
\verbatim
|
2018-10-12 23:45:49 +02:00
|
|
|
|
"Word" --> "Word"
|
|
|
|
|
|
"a Sentence" --> "a_Sentence"
|
|
|
|
|
|
"trailing Withespace \t \n" --> "trailing_Withespace"
|
|
|
|
|
|
"with a lot \nof Whitespace" --> "with_a_lot_of_Whitespace"
|
|
|
|
|
|
"@with\".\'much ($punctuation)[]!" --> "@with.much_($punctuation)"
|
|
|
|
|
|
"§&Ω%€ leading garbage" --> "leading_garbage"
|
|
|
|
|
|
"mixed Ω garbage" --> "mixed_garbage"
|
|
|
|
|
|
"Bääääh!!" --> "Bh"
|
2007-09-14 19:18:11 +02:00
|
|
|
|
\endverbatim
|
2018-10-03 04:43:16 +02:00
|
|
|
|
* @see \ref UtilSanitizedIdentifier_test
|
|
|
|
|
|
* @see \ref lib::meta::sanitisedSymbol()
|
2007-09-06 22:13:26 +02:00
|
|
|
|
*/
|
2009-08-02 20:57:04 +02:00
|
|
|
|
string sanitise (string const& org);
|
2007-09-14 19:18:11 +02:00
|
|
|
|
|
|
|
|
|
|
|
2015-08-17 01:22:01 +02:00
|
|
|
|
/** remove leading and trailing whitespace
|
|
|
|
|
|
* @return a trimmed copy (default locale)
|
|
|
|
|
|
*/
|
|
|
|
|
|
string trim (string const& org);
|
|
|
|
|
|
|
|
|
|
|
|
|
2018-10-03 04:43:16 +02:00
|
|
|
|
/** interpret text representation of a boolean value.
|
|
|
|
|
|
* @remarks this function detects the relevant token rather strict....
|
|
|
|
|
|
* - yields `true` for the tokens "true", "True", "TRUE", "yes", "Yes", "YES", "1", "+"
|
|
|
|
|
|
* - yields `false` for the tokens "false", "False", "FALSE", "no", "No, "NO", "0", "-"
|
|
|
|
|
|
* - leading and trailing whitespace is ignored
|
|
|
|
|
|
* @throws lumiera::error::Invalid for any other text content
|
|
|
|
|
|
*/
|
2019-11-08 20:49:37 +01:00
|
|
|
|
bool boolVal (string const&);
|
2018-10-03 04:43:16 +02:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** check the given text if it can be interpreted as affirmative answer (bool `true`).
|
|
|
|
|
|
* @remarks this function just fishes for the known `true` tokens and interprets
|
|
|
|
|
|
* all other content as `false`, including empty strings. Never throws.
|
|
|
|
|
|
*/
|
2019-11-08 20:49:37 +01:00
|
|
|
|
bool isYes (string const&) noexcept;
|
2018-10-03 04:43:16 +02:00
|
|
|
|
|
2024-03-25 02:19:46 +01:00
|
|
|
|
/** check if the given text is empty or can be interpreted as rejection (bool `false`)-
|
|
|
|
|
|
* @remarks this function fishes for the known `false` tokens;
|
|
|
|
|
|
* any other non-empty content counts as _not no._
|
|
|
|
|
|
*/
|
|
|
|
|
|
bool isNo (string const&) noexcept;
|
|
|
|
|
|
|
2007-08-17 00:36:07 +02:00
|
|
|
|
} // namespace util
|
2007-08-23 17:52:33 +02:00
|
|
|
|
|
2007-10-19 06:39:52 +02:00
|
|
|
|
|
|
|
|
|
|
|
2024-11-14 22:10:43 +01:00
|
|
|
|
|
2007-10-19 06:39:52 +02:00
|
|
|
|
/* === some common macro definitions === */
|
2007-08-23 17:52:33 +02:00
|
|
|
|
|
2008-12-03 06:02:54 +01:00
|
|
|
|
/** suppress "warning: unused variable" on vars, which are
|
2007-11-10 21:50:55 +01:00
|
|
|
|
* introduced into a scope because of some sideeffect, i.e. Locking
|
2007-09-14 19:18:11 +02:00
|
|
|
|
*/
|
|
|
|
|
|
#define SIDEEFFECT __attribute__ ((unused));
|
|
|
|
|
|
|
2007-08-23 17:52:33 +02:00
|
|
|
|
/** this macro wraps its parameter into a cstring literal */
|
|
|
|
|
|
#define STRINGIFY(TOKEN) __STRNGFY(TOKEN)
|
|
|
|
|
|
#define __STRNGFY(TOKEN) #TOKEN
|
|
|
|
|
|
|
2007-11-10 21:50:55 +01:00
|
|
|
|
/** shortcut for subclass test, intended for assertions only.
|
|
|
|
|
|
* @note it is considered bad style to use such in non-assertion code,
|
|
|
|
|
|
* and we probably will enforce this design rule in future. */
|
2007-11-20 05:20:01 +01:00
|
|
|
|
#define INSTANCEOF(CLASS, EXPR) (dynamic_cast<const CLASS*> (EXPR))
|
2007-08-23 17:52:33 +02:00
|
|
|
|
|
2009-06-07 03:22:08 +02:00
|
|
|
|
/** the inevitable MAX macro, sometimes still necessary in template code */
|
2008-12-06 15:47:00 +01:00
|
|
|
|
#ifndef MAX // this is present to make this definition play nice with GLib
|
|
|
|
|
|
#define MAX(A,B) ((A < B) ? (B) : (A))
|
|
|
|
|
|
#endif
|
2008-07-14 03:34:18 +02:00
|
|
|
|
|
2007-08-17 00:36:07 +02:00
|
|
|
|
#endif /*UTIL_HPP_*/
|