update /util

This commit is contained in:
Patrick Brosi 2019-06-28 15:10:15 +02:00
parent df1ba83a53
commit 79303f12f2
5 changed files with 1719 additions and 1354 deletions

View file

@ -32,23 +32,11 @@
#include "util/log/Log.h" #include "util/log/Log.h"
#include "util/Misc.h" #include "util/Misc.h"
#ifndef HOME_VAR #ifndef CFG_HOME_SUFFIX
#define HOME_VAR "HOME" #define CFG_HOME_SUFFIX "/.config"
#endif #endif
#ifndef XDG_DATA_HOME_SUFFIX #ifndef CFG_DIR
#define XDG_DATA_HOME_SUFFIX "/.local/share" #define CFG_DIR "/etc"
#endif
#ifndef XDG_CONFIG_HOME_SUFFIX
#define XDG_CONFIG_HOME_SUFFIX "/.config"
#endif
#ifndef XDG_CACHE_HOME_SUFFIX
#define XDG_CACHE_HOME_SUFFIX "/.cache"
#endif
#ifndef XDG_DATA_DIRS_DEFAULT
#define XDG_DATA_DIRS_DEFAULT "/usr/local/share"
#endif
#ifndef XDG_CONFIG_DIRS_DEFAULT
#define XDG_CONFIG_DIRS_DEFAULT "/etc"
#endif #endif
#ifndef CFG_FILE_NAME #ifndef CFG_FILE_NAME
#define CFG_FILE_NAME "pfaedle.cfg" #define CFG_FILE_NAME "pfaedle.cfg"
@ -343,7 +331,7 @@ std::vector<std::string> getCfgPaths(const Config& cfg) {
// install prefix global configuration path, if available // install prefix global configuration path, if available
{ {
auto path = std::string(INSTALL_PREFIX) + auto path = std::string(INSTALL_PREFIX) +
std::string(XDG_CONFIG_DIRS_DEFAULT) + "/" + "pfaedle" + "/" + std::string(CFG_DIR) + "/" + "pfaedle" + "/" +
CFG_FILE_NAME; CFG_FILE_NAME;
std::ifstream is(path); std::ifstream is(path);
@ -356,7 +344,7 @@ std::vector<std::string> getCfgPaths(const Config& cfg) {
// local user configuration path, if available // local user configuration path, if available
{ {
auto path = util::getHomeDir() + XDG_CONFIG_HOME_SUFFIX + "/" + auto path = util::getHomeDir() + CFG_HOME_SUFFIX + "/" +
"pfaedle" + "/" + CFG_FILE_NAME; "pfaedle" + "/" + CFG_FILE_NAME;
std::ifstream is(path); std::ifstream is(path);

View file

@ -27,7 +27,8 @@ struct CubicPolynom {
template <typename T> template <typename T>
class BezierCurve { class BezierCurve {
public: public:
BezierCurve(const Point<T>& a, const Point<T>& b, const Point<T>& c, const Point<T>& d); BezierCurve(const Point<T>& a, const Point<T>& b, const Point<T>& c,
const Point<T>& d);
const PolyLine<T>& render(double d); const PolyLine<T>& render(double d);

View file

@ -243,15 +243,21 @@ inline bool doubleEq(double a, double b) { return fabs(a - b) < EPSILON; }
// _____________________________________________________________________________ // _____________________________________________________________________________
template <typename T> template <typename T>
inline bool contains(const Point<T>& p, const Box<T>& box) { inline bool contains(const Point<T>& p, const Box<T>& box) {
return p.getX() >= box.getLowerLeft().getX() && // check if point lies in box
p.getX() <= box.getUpperRight().getX() && return (fabs(p.getX() - box.getLowerLeft().getX()) < EPSILON ||
p.getY() >= box.getLowerLeft().getY() && p.getX() > box.getLowerLeft().getX()) &&
p.getY() <= box.getUpperRight().getY(); (fabs(p.getX() - box.getUpperRight().getX()) < EPSILON ||
p.getX() < box.getUpperRight().getX()) &&
(fabs(p.getY() - box.getLowerLeft().getY()) < EPSILON ||
p.getY() > box.getLowerLeft().getY()) &&
(fabs(p.getY() - box.getUpperRight().getY()) < EPSILON ||
p.getY() < box.getUpperRight().getY());
} }
// _____________________________________________________________________________ // _____________________________________________________________________________
template <typename T> template <typename T>
inline bool contains(const Line<T>& l, const Box<T>& box) { inline bool contains(const Line<T>& l, const Box<T>& box) {
// check if line lies in box
for (const auto& p : l) for (const auto& p : l)
if (!contains(p, box)) return false; if (!contains(p, box)) return false;
return true; return true;
@ -260,24 +266,35 @@ inline bool contains(const Line<T>& l, const Box<T>& box) {
// _____________________________________________________________________________ // _____________________________________________________________________________
template <typename T> template <typename T>
inline bool contains(const LineSegment<T>& l, const Box<T>& box) { inline bool contains(const LineSegment<T>& l, const Box<T>& box) {
// check if line segment lies in box
return contains(l.first, box) && contains(l.second, box); return contains(l.first, box) && contains(l.second, box);
} }
// _____________________________________________________________________________ // _____________________________________________________________________________
template <typename T> template <typename T>
inline bool contains(const Box<T>& b, const Box<T>& box) { inline bool contains(const Box<T>& b, const Box<T>& box) {
// check if box b lies in box
return contains(b.getLowerLeft(), box) && contains(b.getUpperRight(), box); return contains(b.getLowerLeft(), box) && contains(b.getUpperRight(), box);
} }
// _____________________________________________________________________________ // _____________________________________________________________________________
template <typename T> template <typename T>
inline bool contains(const Point<T>& p, const LineSegment<T>& ls) { inline bool contains(const Point<T>& p, const LineSegment<T>& ls) {
// check if point p lies in (on) line segment ls
return fabs(crossProd(p, ls)) < EPSILON && contains(p, getBoundingBox(ls)); return fabs(crossProd(p, ls)) < EPSILON && contains(p, getBoundingBox(ls));
} }
// _____________________________________________________________________________
template <typename T>
inline bool contains(const LineSegment<T>& a, const LineSegment<T>& b) {
// check if line segment a is contained in line segment b
return contains(a.first, b) && contains(a.second, b);
}
// _____________________________________________________________________________ // _____________________________________________________________________________
template <typename T> template <typename T>
inline bool contains(const Point<T>& p, const Line<T>& l) { inline bool contains(const Point<T>& p, const Line<T>& l) {
// check if point p lies in line l
for (size_t i = 1; i < l.size(); i++) { for (size_t i = 1; i < l.size(); i++) {
if (contains(p, LineSegment<T>(l[i - 1], l[i]))) return true; if (contains(p, LineSegment<T>(l[i - 1], l[i]))) return true;
} }
@ -287,6 +304,8 @@ inline bool contains(const Point<T>& p, const Line<T>& l) {
// _____________________________________________________________________________ // _____________________________________________________________________________
template <typename T> template <typename T>
inline bool contains(const Point<T>& p, const Polygon<T>& poly) { inline bool contains(const Point<T>& p, const Polygon<T>& poly) {
// check if point p lies in polygon
// see https://de.wikipedia.org/wiki/Punkt-in-Polygon-Test_nach_Jordan // see https://de.wikipedia.org/wiki/Punkt-in-Polygon-Test_nach_Jordan
int8_t c = -1; int8_t c = -1;
@ -328,19 +347,53 @@ inline int8_t polyContCheck(const Point<T>& a, Point<T> b, Point<T> c) {
// _____________________________________________________________________________ // _____________________________________________________________________________
template <typename T> template <typename T>
inline bool contains(const Polygon<T>& polyC, const Polygon<T>& poly) { inline bool contains(const Polygon<T>& polyC, const Polygon<T>& poly) {
for (const auto& p : polyC.getOuter()) { // check if polygon polyC lies in polygon poly
if (!contains(p, poly)) {
for (size_t i = 1; i < polyC.getOuter().size(); i++) {
if (!contains(LineSegment<T>(polyC.getOuter()[i - 1], polyC.getOuter()[i]),
poly))
return false;
}
// also check the last hop
if (!contains(LineSegment<T>(polyC.getOuter().back(), polyC.getOuter().front()),
poly))
return false;
return true;
}
// _____________________________________________________________________________
template <typename T>
inline bool contains(const LineSegment<T>& ls, const Polygon<T>& p) {
// check if linesegment ls lies in polygon poly
// if one of the endpoints lies outside, abort
if (!contains(ls.first, p)) return false;
if (!contains(ls.second, p)) return false;
for (size_t i = 1; i < p.getOuter().size(); i++) {
auto seg = LineSegment<T>(p.getOuter()[i - 1], p.getOuter()[i]);
if (!(contains(ls.first, seg) || contains(ls.second, seg)) &&
intersects(seg, ls)) {
return false; return false;
} }
} }
auto seg = LineSegment<T>(p.getOuter().back(), p.getOuter().front());
if (!(contains(ls.first, seg) || contains(ls.second, seg)) &&
intersects(seg, ls)) {
return false;
}
return true; return true;
} }
// _____________________________________________________________________________ // _____________________________________________________________________________
template <typename T> template <typename T>
inline bool contains(const Line<T>& l, const Polygon<T>& poly) { inline bool contains(const Line<T>& l, const Polygon<T>& poly) {
for (const auto& p : l) { for (size_t i = 1; i < l.size(); i++) {
if (!contains(p, poly)) { if (!contains(LineSegment<T>(l[i - 1], l[i]), poly)) {
return false; return false;
} }
} }
@ -351,9 +404,7 @@ inline bool contains(const Line<T>& l, const Polygon<T>& poly) {
template <typename T> template <typename T>
inline bool contains(const Line<T>& l, const Line<T>& other) { inline bool contains(const Line<T>& l, const Line<T>& other) {
for (const auto& p : l) { for (const auto& p : l) {
if (!contains(p, other)) { if (!contains(p, other)) return false;
return false;
}
} }
return true; return true;
} }
@ -361,17 +412,13 @@ inline bool contains(const Line<T>& l, const Line<T>& other) {
// _____________________________________________________________________________ // _____________________________________________________________________________
template <typename T> template <typename T>
inline bool contains(const Box<T>& b, const Polygon<T>& poly) { inline bool contains(const Box<T>& b, const Polygon<T>& poly) {
return contains(b.getLowerLeft(), poly) && return contains(convexHull(b), poly);
contains(b.getUpperRight(), poly) &&
contains(Point<T>(b.getUpperRight().getX(), b.getLowerLeft().getY()),
poly) &&
contains(Point<T>(b.getLowerLeft().getX(), b.getUpperRight().getY()),
poly);
} }
// _____________________________________________________________________________ // _____________________________________________________________________________
template <typename T> template <typename T>
inline bool contains(const Polygon<T>& poly, const Box<T>& b) { inline bool contains(const Polygon<T>& poly, const Box<T>& b) {
// check of poly lies in box
for (const auto& p : poly.getOuter()) { for (const auto& p : poly.getOuter()) {
if (!contains(p, b)) return false; if (!contains(p, b)) return false;
} }
@ -400,6 +447,8 @@ inline bool contains(const std::vector<GeometryA<T>>& multigeo,
// _____________________________________________________________________________ // _____________________________________________________________________________
template <typename T> template <typename T>
inline bool intersects(const LineSegment<T>& ls1, const LineSegment<T>& ls2) { inline bool intersects(const LineSegment<T>& ls1, const LineSegment<T>& ls2) {
// check if two linesegments intersect
// two line segments intersect of there is a single, well-defined intersection // two line segments intersect of there is a single, well-defined intersection
// point between them. If more than 1 endpoint is colinear with any line, // point between them. If more than 1 endpoint is colinear with any line,
// the segments have infinite intersections. We handle this case as non- // the segments have infinite intersections. We handle this case as non-
@ -468,6 +517,39 @@ inline bool intersects(const Box<T>& b1, const Box<T>& b2) {
b1.getUpperRight().getY() >= b2.getLowerLeft().getY(); b1.getUpperRight().getY() >= b2.getLowerLeft().getY();
} }
// _____________________________________________________________________________
template <typename T>
inline bool intersects(const Box<T>& b, const Polygon<T>& poly) {
return intersects(b, poly);
}
// _____________________________________________________________________________
template <typename T>
inline bool intersects(const Polygon<T>& poly, const Box<T>& b) {
if (intersects(
LineSegment<T>(b.getLowerLeft(), Point<T>(b.getUpperRight().getX(),
b.getLowerLeft().getY())),
poly))
return true;
if (intersects(
LineSegment<T>(b.getLowerLeft(), Point<T>(b.getLowerLeft().getX(),
b.getUpperRight().getY())),
poly))
return true;
if (intersects(
LineSegment<T>(b.getUpperRight(), Point<T>(b.getLowerLeft().getX(),
b.getUpperRight().getY())),
poly))
return true;
if (intersects(
LineSegment<T>(b.getUpperRight(), Point<T>(b.getUpperRight().getX(),
b.getLowerLeft().getY())),
poly))
return true;
return contains(poly, b) || contains(b, poly);
}
// _____________________________________________________________________________ // _____________________________________________________________________________
template <typename T> template <typename T>
inline bool intersects(const LineSegment<T>& ls, const Box<T>& b) { inline bool intersects(const LineSegment<T>& ls, const Box<T>& b) {
@ -499,6 +581,7 @@ inline bool intersects(const LineSegment<T>& ls, const Polygon<T>& p) {
return true; return true;
} }
// also check the last hop
if (intersects(LineSegment<T>(p.getOuter().back(), p.getOuter().front()), ls)) if (intersects(LineSegment<T>(p.getOuter().back(), p.getOuter().front()), ls))
return true; return true;
@ -1186,7 +1269,7 @@ inline Polygon<T> convexHull(const RotatedBox<T>& b) {
// _____________________________________________________________________________ // _____________________________________________________________________________
template <typename T> template <typename T>
inline size_t convexHullImpl(const MultiPoint<T>& a, size_t p1, size_t p2, inline size_t convexHullImpl(const MultiPoint<T>& a, size_t p1, size_t p2,
Line<T>* h, uint8_t d) { Line<T>* h) {
// quickhull by Barber, Dobkin & Huhdanpaa // quickhull by Barber, Dobkin & Huhdanpaa
Point<T> pa; Point<T> pa;
bool found = false; bool found = false;
@ -1194,7 +1277,7 @@ inline size_t convexHullImpl(const MultiPoint<T>& a, size_t p1, size_t p2,
for (const auto& p : a) { for (const auto& p : a) {
double tmpDist = distToSegment((*h)[p1], (*h)[p2], p); double tmpDist = distToSegment((*h)[p1], (*h)[p2], p);
double cp = crossProd(p, LineSegment<T>((*h)[p1], (*h)[p2])); double cp = crossProd(p, LineSegment<T>((*h)[p1], (*h)[p2]));
if (((cp > 0 && !d) || (cp < 0 && d)) && tmpDist >= maxDist + EPSILON) { if ((cp > 0) && tmpDist > maxDist) {
pa = p; pa = p;
found = true; found = true;
maxDist = tmpDist; maxDist = tmpDist;
@ -1203,9 +1286,9 @@ inline size_t convexHullImpl(const MultiPoint<T>& a, size_t p1, size_t p2,
if (!found) return 0; if (!found) return 0;
h->insert(h->begin() + p2 + !d, pa); h->insert(h->begin() + p2, pa);
size_t in = 1 + convexHullImpl(a, p1, p2 + !d, h, d); size_t in = 1 + convexHullImpl(a, p1, p2, h);
return in + convexHullImpl(a, p2 + in * d + 1 - 2 * d, p2 + in * d, h, d); return in + convexHullImpl(a, p2 + in - 1, p2 + in, h);
} }
// _____________________________________________________________________________ // _____________________________________________________________________________
@ -1217,13 +1300,16 @@ inline Polygon<T> convexHull(const MultiPoint<T>& l) {
Point<T> left(std::numeric_limits<T>::max(), 0); Point<T> left(std::numeric_limits<T>::max(), 0);
Point<T> right(std::numeric_limits<T>::lowest(), 0); Point<T> right(std::numeric_limits<T>::lowest(), 0);
for (const auto& p : l) { for (const auto& p : l) {
if (p.getX() <= left.getX()) left = p; if (p.getX() < left.getX()) left = p;
if (p.getX() >= right.getX()) right = p; if (p.getX() > right.getX()) right = p;
} }
Line<T> hull{left, right}; Line<T> hull{left, right};
convexHullImpl(l, 0, 1, &hull, 1); convexHullImpl(l, 0, 1, &hull);
convexHullImpl(l, 0, hull.size() - 1, &hull, 0); hull.push_back(hull.front());
convexHullImpl(l, hull.size() - 2, hull.size() - 1, &hull);
hull.pop_back();
return Polygon<T>(hull); return Polygon<T>(hull);
} }

File diff suppressed because it is too large Load diff

View file

@ -31,7 +31,11 @@
#include <cmath> #include <cmath>
#include <cstddef> #include <cstddef>
#define lest_VERSION "1.33.1" #define lest_MAJOR 1
#define lest_MINOR 35
#define lest_PATCH 1
#define lest_VERSION lest_STRINGIFY(lest_MAJOR) "." lest_STRINGIFY(lest_MINOR) "." lest_STRINGIFY(lest_PATCH)
#ifndef lest_FEATURE_AUTO_REGISTER #ifndef lest_FEATURE_AUTO_REGISTER
# define lest_FEATURE_AUTO_REGISTER 0 # define lest_FEATURE_AUTO_REGISTER 0
@ -71,28 +75,33 @@
# include <regex> # include <regex>
#endif #endif
// Stringify:
#define lest_STRINGIFY( x ) lest_STRINGIFY_( x )
#define lest_STRINGIFY_( x ) #x
// Compiler warning suppression: // Compiler warning suppression:
#ifdef __clang__ #if defined (__clang__)
# pragma clang diagnostic ignored "-Waggregate-return" # pragma clang diagnostic ignored "-Waggregate-return"
# pragma clang diagnostic ignored "-Woverloaded-shift-op-parentheses" # pragma clang diagnostic ignored "-Woverloaded-shift-op-parentheses"
# pragma clang diagnostic push # pragma clang diagnostic push
# pragma clang diagnostic ignored "-Wunused-comparison" # pragma clang diagnostic ignored "-Wunused-comparison"
#elif defined __GNUC__ #elif defined (__GNUC__)
# pragma GCC diagnostic ignored "-Waggregate-return" # pragma GCC diagnostic ignored "-Waggregate-return"
# pragma GCC diagnostic push # pragma GCC diagnostic push
#endif #endif
// Suppress shadow and unused-value warning for sections: // Suppress shadow and unused-value warning for sections:
#if defined __clang__ #if defined (__clang__)
# define lest_SUPPRESS_WSHADOW _Pragma( "clang diagnostic push" ) \ # define lest_SUPPRESS_WSHADOW _Pragma( "clang diagnostic push" ) \
_Pragma( "clang diagnostic ignored \"-Wshadow\"" ) _Pragma( "clang diagnostic ignored \"-Wshadow\"" )
# define lest_SUPPRESS_WUNUSED _Pragma( "clang diagnostic push" ) \ # define lest_SUPPRESS_WUNUSED _Pragma( "clang diagnostic push" ) \
_Pragma( "clang diagnostic ignored \"-Wunused-value\"" ) _Pragma( "clang diagnostic ignored \"-Wunused-value\"" )
# define lest_RESTORE_WARNINGS _Pragma( "clang diagnostic pop" ) # define lest_RESTORE_WARNINGS _Pragma( "clang diagnostic pop" )
#elif defined __GNUC__ #elif defined (__GNUC__)
# define lest_SUPPRESS_WSHADOW _Pragma( "GCC diagnostic push" ) \ # define lest_SUPPRESS_WSHADOW _Pragma( "GCC diagnostic push" ) \
_Pragma( "GCC diagnostic ignored \"-Wshadow\"" ) _Pragma( "GCC diagnostic ignored \"-Wshadow\"" )
# define lest_SUPPRESS_WUNUSED _Pragma( "GCC diagnostic push" ) \ # define lest_SUPPRESS_WUNUSED _Pragma( "GCC diagnostic push" ) \
@ -104,12 +113,22 @@
# define lest_RESTORE_WARNINGS /*empty*/ # define lest_RESTORE_WARNINGS /*empty*/
#endif #endif
#ifdef _MSVC_LANG // C++ language version detection (C++20 is speculative):
# define lest_CPP17_OR_GREATER_MS ( _MSVC_LANG >= 201703L ) // Note: VC14.0/1900 (VS2015) lacks too much from C++14.
#ifndef lest_CPLUSPLUS
# if defined(_MSVC_LANG ) && !defined(__clang__)
# define lest_CPLUSPLUS (_MSC_VER == 1900 ? 201103L : _MSVC_LANG )
# else # else
# define lest_CPP17_OR_GREATER_MS 0 # define lest_CPLUSPLUS __cplusplus
# endif # endif
# define lest_CPP17_OR_GREATER ( __cplusplus >= 201703L || lest_CPP17_OR_GREATER_MS ) #endif
#define lest_CPP98_OR_GREATER ( lest_CPLUSPLUS >= 199711L )
#define lest_CPP11_OR_GREATER ( lest_CPLUSPLUS >= 201103L )
#define lest_CPP14_OR_GREATER ( lest_CPLUSPLUS >= 201402L )
#define lest_CPP17_OR_GREATER ( lest_CPLUSPLUS >= 201703L )
#define lest_CPP20_OR_GREATER ( lest_CPLUSPLUS >= 202000L )
#if ! defined( lest_NO_SHORT_MACRO_NAMES ) && ! defined( lest_NO_SHORT_ASSERTION_NAMES ) #if ! defined( lest_NO_SHORT_MACRO_NAMES ) && ! defined( lest_NO_SHORT_ASSERTION_NAMES )
# define MODULE lest_MODULE # define MODULE lest_MODULE
@ -186,7 +205,7 @@
if ( lest::result score = lest_DECOMPOSE( expr ) ) \ if ( lest::result score = lest_DECOMPOSE( expr ) ) \
throw lest::failure{ lest_LOCATION, #expr, score.decomposition }; \ throw lest::failure{ lest_LOCATION, #expr, score.decomposition }; \
else if ( lest_env.pass() ) \ else if ( lest_env.pass() ) \
lest::report( lest_env.os, lest::passing{ lest_LOCATION, #expr, score.decomposition }, lest_env.context() ); \ lest::report( lest_env.os, lest::passing{ lest_LOCATION, #expr, score.decomposition, lest_env.zen() }, lest_env.context() ); \
} \ } \
catch(...) \ catch(...) \
{ \ { \
@ -201,7 +220,7 @@
if ( lest::result score = lest_DECOMPOSE( expr ) ) \ if ( lest::result score = lest_DECOMPOSE( expr ) ) \
{ \ { \
if ( lest_env.pass() ) \ if ( lest_env.pass() ) \
lest::report( lest_env.os, lest::passing{ lest_LOCATION, lest::not_expr( #expr ), lest::not_expr( score.decomposition ) }, lest_env.context() ); \ lest::report( lest_env.os, lest::passing{ lest_LOCATION, lest::not_expr( #expr ), lest::not_expr( score.decomposition ), lest_env.zen() }, lest_env.context() ); \
} \ } \
else \ else \
throw lest::failure{ lest_LOCATION, lest::not_expr( #expr ), lest::not_expr( score.decomposition ) }; \ throw lest::failure{ lest_LOCATION, lest::not_expr( #expr ), lest::not_expr( score.decomposition ) }; \
@ -381,8 +400,8 @@ struct success : message
struct passing : success struct passing : success
{ {
passing( location where_, text expr_, text decomposition_ ) passing( location where_, text expr_, text decomposition_, bool zen )
: success( "passed", where_, expr_ + " for " + decomposition_) {} : success( "passed", where_, expr_ + (zen ? "":" for " + decomposition_) ) {}
}; };
struct got_none : success struct got_none : success
@ -524,14 +543,45 @@ inline char const * sfx( char const * txt ) { return txt; }
inline char const * sfx( char const * ) { return ""; } inline char const * sfx( char const * ) { return ""; }
#endif #endif
inline std::string transformed( char chr )
{
struct Tr { char chr; char const * str; } table[] =
{
{'\\', "\\\\" },
{'\r', "\\r" }, {'\f', "\\f" },
{'\n', "\\n" }, {'\t', "\\t" },
};
for ( auto tr : table )
{
if ( chr == tr.chr )
return tr.str;
}
auto unprintable = [](char c){ return 0 <= c && c < ' '; };
auto to_hex_string = [](char c)
{
std::ostringstream os;
os << "\\x" << std::hex << std::setw(2) << std::setfill('0') << static_cast<int>( static_cast<unsigned char>(c) );
return os.str();
};
return unprintable( chr ) ? to_hex_string( chr ) : std::string( 1, chr );
}
inline std::string make_tran_string( std::string const & txt ) { std::ostringstream os; for(auto c:txt) os << transformed(c); return os.str(); }
inline std::string make_strg_string( std::string const & txt ) { return "\"" + make_tran_string( txt ) + "\"" ; }
inline std::string make_char_string( char chr ) { return "\'" + make_tran_string( std::string( 1, chr ) ) + "\'" ; }
inline std::string to_string( std::nullptr_t ) { return "nullptr"; } inline std::string to_string( std::nullptr_t ) { return "nullptr"; }
inline std::string to_string( std::string const & txt ) { return "\"" + txt + "\"" ; } inline std::string to_string( std::string const & txt ) { return make_strg_string( txt ); }
#if lest_FEATURE_WSTRING #if lest_FEATURE_WSTRING
inline std::string to_string( std::wstring const & txt ) ; inline std::string to_string( std::wstring const & txt ) ;
#endif #endif
inline std::string to_string( char const * const txt ) { return txt ? to_string( std::string ( txt ) ) : "{null string}"; } inline std::string to_string( char const * const txt ) { return txt ? make_strg_string( txt ) : "{null string}"; }
inline std::string to_string( char * const txt ) { return txt ? to_string( std::string ( txt ) ) : "{null string}"; } inline std::string to_string( char * const txt ) { return txt ? make_strg_string( txt ) : "{null string}"; }
#if lest_FEATURE_WSTRING #if lest_FEATURE_WSTRING
inline std::string to_string( wchar_t const * const txt ) { return txt ? to_string( std::wstring( txt ) ) : "{null string}"; } inline std::string to_string( wchar_t const * const txt ) { return txt ? to_string( std::wstring( txt ) ) : "{null string}"; }
inline std::string to_string( wchar_t * const txt ) { return txt ? to_string( std::wstring( txt ) ) : "{null string}"; } inline std::string to_string( wchar_t * const txt ) { return txt ? to_string( std::wstring( txt ) ) : "{null string}"; }
@ -550,29 +600,9 @@ inline std::string to_string( unsigned long long value ) { return make_value_
inline std::string to_string( double value ) { return make_value_string( value ) ; } inline std::string to_string( double value ) { return make_value_string( value ) ; }
inline std::string to_string( float value ) { return make_value_string( value ) + sfx("f" ); } inline std::string to_string( float value ) { return make_value_string( value ) + sfx("f" ); }
inline std::string to_string( signed char chr ) { return to_string( static_cast<char>( chr ) ); } inline std::string to_string( signed char chr ) { return make_char_string( static_cast<char>( chr ) ); }
inline std::string to_string( unsigned char chr ) { return to_string( static_cast<char>( chr ) ); } inline std::string to_string( unsigned char chr ) { return make_char_string( static_cast<char>( chr ) ); }
inline std::string to_string( char chr ) { return make_char_string( chr ); }
inline std::string to_string( char chr )
{
struct Tr { char chr; char const * str; } table[] =
{
{'\r', "'\\r'" }, {'\f', "'\\f'" },
{'\n', "'\\n'" }, {'\t', "'\\t'" },
};
for ( auto tr : table )
{
if ( chr == tr.chr )
return tr.str;
}
auto unprintable = [](char c){ return 0 <= c && c < ' '; };
return unprintable( chr )
? to_string( static_cast<unsigned int>( chr ) )
: "\'" + std::string( 1, chr ) + "\'" ;
}
template< typename T > template< typename T >
struct is_streamable struct is_streamable
@ -968,7 +998,7 @@ inline bool select( text name, texts include )
inline int indefinite( int repeat ) { return repeat == -1; } inline int indefinite( int repeat ) { return repeat == -1; }
using seed_t = unsigned long; using seed_t = std::mt19937::result_type;
struct options struct options
{ {
@ -979,6 +1009,7 @@ struct options
bool tags = false; bool tags = false;
bool time = false; bool time = false;
bool pass = false; bool pass = false;
bool zen = false;
bool lexical = false; bool lexical = false;
bool random = false; bool random = false;
bool verbose = false; bool verbose = false;
@ -999,12 +1030,14 @@ struct env
env & operator()( text test ) env & operator()( text test )
{ {
testing = test; return *this; clear(); testing = test; return *this;
} }
bool abort() { return opt.abort; } bool abort() { return opt.abort; }
bool pass() { return opt.pass; } bool pass() { return opt.pass; }
bool zen() { return opt.zen; }
void clear() { ctx.clear(); }
void pop() { ctx.pop_back(); } void pop() { ctx.pop_back(); }
void push( text proposition ) { ctx.emplace_back( proposition ); } void push( text proposition ) { ctx.emplace_back( proposition ); }
@ -1311,6 +1344,7 @@ inline auto split_arguments( texts args ) -> std::tuple<options, texts>
else if ( opt == "-l" || "--list-tests" == opt ) { option.list = true; continue; } else if ( opt == "-l" || "--list-tests" == opt ) { option.list = true; continue; }
else if ( opt == "-t" || "--time" == opt ) { option.time = true; continue; } else if ( opt == "-t" || "--time" == opt ) { option.time = true; continue; }
else if ( opt == "-p" || "--pass" == opt ) { option.pass = true; continue; } else if ( opt == "-p" || "--pass" == opt ) { option.pass = true; continue; }
else if ( opt == "-z" || "--pass-zen" == opt ) { option.zen = true; continue; }
else if ( opt == "-v" || "--verbose" == opt ) { option.verbose = true; continue; } else if ( opt == "-v" || "--verbose" == opt ) { option.verbose = true; continue; }
else if ( "--version" == opt ) { option.version = true; continue; } else if ( "--version" == opt ) { option.version = true; continue; }
else if ( opt == "--order" && "declared" == val ) { /* by definition */ ; continue; } else if ( opt == "--order" && "declared" == val ) { /* by definition */ ; continue; }
@ -1322,6 +1356,8 @@ inline auto split_arguments( texts args ) -> std::tuple<options, texts>
} }
in.push_back( arg ); in.push_back( arg );
} }
option.pass = option.pass || option.zen;
return std::make_tuple( option, in ); return std::make_tuple( option, in );
} }
@ -1337,6 +1373,7 @@ inline int usage( std::ostream & os )
" -g, --list-tags list tags of selected tests\n" " -g, --list-tags list tags of selected tests\n"
" -l, --list-tests list selected tests\n" " -l, --list-tests list selected tests\n"
" -p, --pass also report passing tests\n" " -p, --pass also report passing tests\n"
" -z, --pass-zen ... without expansion\n"
" -t, --time list duration of selected tests\n" " -t, --time list duration of selected tests\n"
" -v, --verbose also report passing or failing sections\n" " -v, --verbose also report passing or failing sections\n"
" --order=declared use source code test order (default)\n" " --order=declared use source code test order (default)\n"
@ -1437,9 +1474,9 @@ int run( test const (&specification)[N], int argc, char * argv[], std::ostream &
} // namespace lest } // namespace lest
#ifdef __clang__ #if defined (__clang__)
# pragma clang diagnostic pop # pragma clang diagnostic pop
#elif defined __GNUC__ #elif defined (__GNUC__)
# pragma GCC diagnostic pop # pragma GCC diagnostic pop
#endif #endif