update /util
This commit is contained in:
parent
df1ba83a53
commit
79303f12f2
5 changed files with 1719 additions and 1354 deletions
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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
|
@ -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
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue