Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
152a55ad78
20
Makefile.am
20
Makefile.am
@ -32,6 +32,8 @@ UTIL_FILES = \
|
|||||||
alloc/null.hpp \
|
alloc/null.hpp \
|
||||||
alloc/stack.cpp \
|
alloc/stack.cpp \
|
||||||
alloc/stack.hpp \
|
alloc/stack.hpp \
|
||||||
|
annotation.hpp \
|
||||||
|
ascii.hpp \
|
||||||
backtrace.hpp \
|
backtrace.hpp \
|
||||||
bezier.cpp \
|
bezier.cpp \
|
||||||
bezier.hpp \
|
bezier.hpp \
|
||||||
@ -44,6 +46,7 @@ UTIL_FILES = \
|
|||||||
colour.cpp \
|
colour.cpp \
|
||||||
colour.hpp \
|
colour.hpp \
|
||||||
colour.ipp \
|
colour.ipp \
|
||||||
|
coord/fwd.hpp \
|
||||||
coord/base.hpp \
|
coord/base.hpp \
|
||||||
coord.hpp \
|
coord.hpp \
|
||||||
coord/init.hpp \
|
coord/init.hpp \
|
||||||
@ -162,8 +165,6 @@ UTIL_FILES = \
|
|||||||
io.cpp \
|
io.cpp \
|
||||||
io.hpp \
|
io.hpp \
|
||||||
io.ipp \
|
io.ipp \
|
||||||
ip.cpp \
|
|
||||||
ip.hpp \
|
|
||||||
iterator.hpp \
|
iterator.hpp \
|
||||||
json/fwd.hpp \
|
json/fwd.hpp \
|
||||||
json/except.cpp \
|
json/except.cpp \
|
||||||
@ -274,14 +275,6 @@ UTIL_FILES = \
|
|||||||
|
|
||||||
|
|
||||||
POSIX_FILES = \
|
POSIX_FILES = \
|
||||||
net/address.cpp \
|
|
||||||
net/address.hpp \
|
|
||||||
net/except.cpp \
|
|
||||||
net/except.hpp \
|
|
||||||
net/socket.cpp \
|
|
||||||
net/socket.hpp \
|
|
||||||
net/types.cpp \
|
|
||||||
net/types.hpp \
|
|
||||||
memory/buffer/circular.cpp \
|
memory/buffer/circular.cpp \
|
||||||
memory/buffer/circular.hpp \
|
memory/buffer/circular.hpp \
|
||||||
memory/buffer/paged.cpp \
|
memory/buffer/paged.cpp \
|
||||||
@ -348,8 +341,8 @@ BACKTRACE_FILES=$(firstword $(__BACKTRACE_FILES) backtrace_null.cpp)
|
|||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
## Local build rules
|
## Local build rules
|
||||||
CLEANFILES = json.cpp version.cpp ip.cpp uri.cpp
|
CLEANFILES = json.cpp version.cpp uri.cpp
|
||||||
EXTRA_DIST = json/flat.cpp.rl version.cpp.rl ip.cpp.rl uri.cpp.rl
|
EXTRA_DIST = json/flat.cpp.rl version.cpp.rl uri.cpp.rl
|
||||||
|
|
||||||
RAGELFLAGS = -F1
|
RAGELFLAGS = -F1
|
||||||
SUFFIXES = .cpp .cpp.rl
|
SUFFIXES = .cpp .cpp.rl
|
||||||
@ -394,6 +387,7 @@ TEST_BIN = \
|
|||||||
test/alloc/dynamic \
|
test/alloc/dynamic \
|
||||||
test/alloc/linear \
|
test/alloc/linear \
|
||||||
test/alloc/stack \
|
test/alloc/stack \
|
||||||
|
test/affine \
|
||||||
test/backtrace \
|
test/backtrace \
|
||||||
test/bezier \
|
test/bezier \
|
||||||
test/bitwise \
|
test/bitwise \
|
||||||
@ -426,7 +420,6 @@ TEST_BIN = \
|
|||||||
test/hash/sha2 \
|
test/hash/sha2 \
|
||||||
test/hton \
|
test/hton \
|
||||||
test/introspection \
|
test/introspection \
|
||||||
test/ip \
|
|
||||||
test/json_types \
|
test/json_types \
|
||||||
test/maths \
|
test/maths \
|
||||||
test/matrix \
|
test/matrix \
|
||||||
@ -434,6 +427,7 @@ TEST_BIN = \
|
|||||||
test/point \
|
test/point \
|
||||||
test/polynomial \
|
test/polynomial \
|
||||||
test/pool \
|
test/pool \
|
||||||
|
test/quaternion \
|
||||||
test/rand/buckets \
|
test/rand/buckets \
|
||||||
test/random \
|
test/random \
|
||||||
test/range \
|
test/range \
|
||||||
|
33
annotation.hpp
Normal file
33
annotation.hpp
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* Copyright 2011 Danny Robson <danny@nerdcruft.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __UTIL_ANNOTATION_HPP
|
||||||
|
#define __UTIL_ANNOTATION_HPP
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
constexpr inline
|
||||||
|
bool
|
||||||
|
likely (T &&t)
|
||||||
|
{ return __builtin_expect (!!t, true); }
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
constexpr inline
|
||||||
|
bool
|
||||||
|
unlikely (T &&t)
|
||||||
|
{ return __builtin_expect (!!t, false); }
|
||||||
|
|
||||||
|
#endif
|
92
ascii.hpp
Normal file
92
ascii.hpp
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* Copyright 2016 Danny Robson <danny@nerdcruft.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __CRUFT_UTIL_ASCII_HPP
|
||||||
|
#define __CRUFT_UTIL_ASCII_HPP
|
||||||
|
|
||||||
|
#include "./annotation.hpp"
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
namespace util { namespace ascii {
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
constexpr inline
|
||||||
|
bool
|
||||||
|
is_digit (char c) noexcept
|
||||||
|
{
|
||||||
|
return c >= '0' && c <= '9';
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
constexpr inline
|
||||||
|
uint8_t
|
||||||
|
to_integer (char c)
|
||||||
|
{
|
||||||
|
return likely (is_digit (c)) ?
|
||||||
|
c - '0'
|
||||||
|
: throw std::invalid_argument ("character is not a digit");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
constexpr inline
|
||||||
|
bool
|
||||||
|
is_upper (char c) noexcept
|
||||||
|
{
|
||||||
|
return c >= 'A' && c <= 'Z';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
constexpr inline
|
||||||
|
char
|
||||||
|
to_upper (char c) noexcept
|
||||||
|
{
|
||||||
|
return c - 'a' + 'A';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
constexpr inline
|
||||||
|
char
|
||||||
|
to_lower (char c) noexcept
|
||||||
|
{
|
||||||
|
return c - 'A' + 'a';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
constexpr inline
|
||||||
|
bool
|
||||||
|
is_space (char c)
|
||||||
|
{
|
||||||
|
switch (c) {
|
||||||
|
case ' ':
|
||||||
|
case '\f':
|
||||||
|
case '\n':
|
||||||
|
case '\r':
|
||||||
|
case '\t':
|
||||||
|
case '\v':
|
||||||
|
return true;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} }
|
||||||
|
|
||||||
|
#endif
|
@ -41,7 +41,7 @@ debug::backtrace::backtrace (void):
|
|||||||
while ((last = ::backtrace (&m_frames[0], trunc_cast<int> (m_frames.size ()))) == size)
|
while ((last = ::backtrace (&m_frames[0], trunc_cast<int> (m_frames.size ()))) == size)
|
||||||
m_frames.resize (size = m_frames.size () * 2);
|
m_frames.resize (size = m_frames.size () * 2);
|
||||||
|
|
||||||
CHECK_GT (last, 0);
|
CHECK_GT (last, 0u);
|
||||||
m_frames.resize (last);
|
m_frames.resize (last);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,7 +81,7 @@ debug::operator <<(std::ostream &os, const debug::backtrace &rhs) {
|
|||||||
str_t names (backtrace_symbols (frames.data (), trunc_cast<int> (frames.size ())), ::free);
|
str_t names (backtrace_symbols (frames.data (), trunc_cast<int> (frames.size ())), ::free);
|
||||||
|
|
||||||
for (unsigned int i = 0; i < frames.size (); ++i)
|
for (unsigned int i = 0; i < frames.size (); ++i)
|
||||||
os << frames[i] << '\t' << names.get()[i] << '\t' << addr2line (frames[i]) << '\n';
|
os << frames[i] << '\t' << names.get()[i] << '\t' << addr2line (frames[i]);
|
||||||
|
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
#include "point.hpp"
|
#include "point.hpp"
|
||||||
#include "region.hpp"
|
#include "region.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <ostream>
|
||||||
|
|
||||||
namespace util {
|
namespace util {
|
||||||
template <size_t S>
|
template <size_t S>
|
||||||
|
39
colour.cpp
39
colour.cpp
@ -14,11 +14,12 @@
|
|||||||
* Copyright 2010-2016 Danny Robson <danny@nerdcruft.net>
|
* Copyright 2010-2016 Danny Robson <danny@nerdcruft.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "colour.hpp"
|
#include "./colour.hpp"
|
||||||
|
|
||||||
#include "range.hpp"
|
#include "./debug.hpp"
|
||||||
#include "random.hpp"
|
#include "./range.hpp"
|
||||||
#include "stream.hpp"
|
#include "./random.hpp"
|
||||||
|
#include "./stream.hpp"
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <map>
|
#include <map>
|
||||||
@ -439,14 +440,38 @@ util::operator>> (std::istream &is, util::colour<S,T> &c)
|
|||||||
template std::istream& util::operator>> (std::istream&, util::colour<3,uint8_t>&);
|
template std::istream& util::operator>> (std::istream&, util::colour<3,uint8_t>&);
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
#define INSTANTIATE_S_T(S,T) \
|
// we need to instantiate the various type_name specialisations for colour.
|
||||||
template struct util::colour<S,T>; \
|
//
|
||||||
template std::ostream& util::operator<< (std::ostream&, util::colour<S,T>);
|
// we provide a declaration here, before then instantiating a routine that we
|
||||||
|
// know will cause an implicit instantiation (ie util::to_string) for each
|
||||||
|
// colour specialisation we require.
|
||||||
|
template <size_t S, typename T>
|
||||||
|
constexpr
|
||||||
|
const char util::type_name<colour<S,T>>::value[];
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
#define INSTANTIATE_S_T(S,T) \
|
||||||
|
template \
|
||||||
|
struct util::colour<S,T>; \
|
||||||
|
\
|
||||||
|
template \
|
||||||
|
std::ostream& \
|
||||||
|
util::operator<< (std::ostream&, util::colour<S,T>); \
|
||||||
|
\
|
||||||
|
template \
|
||||||
|
const char* \
|
||||||
|
util::to_string<util::colour<S,T>> (void);
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
#define INSTANTIATE_S(S) \
|
#define INSTANTIATE_S(S) \
|
||||||
INSTANTIATE_S_T(S,uint8_t) \
|
INSTANTIATE_S_T(S,uint8_t) \
|
||||||
INSTANTIATE_S_T(S,float) \
|
INSTANTIATE_S_T(S,float) \
|
||||||
INSTANTIATE_S_T(S,double)
|
INSTANTIATE_S_T(S,double)
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
INSTANTIATE_S(1)
|
||||||
INSTANTIATE_S(3)
|
INSTANTIATE_S(3)
|
||||||
INSTANTIATE_S(4)
|
INSTANTIATE_S(4)
|
||||||
|
20
colour.hpp
20
colour.hpp
@ -18,8 +18,9 @@
|
|||||||
#define __UTIL_COLOUR_HPP
|
#define __UTIL_COLOUR_HPP
|
||||||
|
|
||||||
#include "coord.hpp"
|
#include "coord.hpp"
|
||||||
|
#include "introspection.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <ostream>
|
||||||
|
|
||||||
namespace util {
|
namespace util {
|
||||||
/// An RGBA colour POD type.
|
/// An RGBA colour POD type.
|
||||||
@ -28,6 +29,7 @@ namespace util {
|
|||||||
using coord::base<S,T,util::colour,coord::rgba,coord::hsv>::base;
|
using coord::base<S,T,util::colour,coord::rgba,coord::hsv>::base;
|
||||||
using base_t = coord::base<S,T,util::colour,coord::rgba,coord::hsv>;
|
using base_t = coord::base<S,T,util::colour,coord::rgba,coord::hsv>;
|
||||||
|
|
||||||
|
// overloaded cast operator which assumes values are unit normalised
|
||||||
template <typename U>
|
template <typename U>
|
||||||
colour<S,U>
|
colour<S,U>
|
||||||
cast (void) const;
|
cast (void) const;
|
||||||
@ -48,6 +50,7 @@ namespace util {
|
|||||||
template <typename T> using colour3 = colour<3,T>;
|
template <typename T> using colour3 = colour<3,T>;
|
||||||
template <typename T> using colour4 = colour<4,T>;
|
template <typename T> using colour4 = colour<4,T>;
|
||||||
|
|
||||||
|
typedef colour1<uint8_t> colour1u;
|
||||||
typedef colour3<uint8_t> colour3u;
|
typedef colour3<uint8_t> colour3u;
|
||||||
typedef colour4<uint8_t> colour4u;
|
typedef colour4<uint8_t> colour4u;
|
||||||
|
|
||||||
@ -55,15 +58,24 @@ namespace util {
|
|||||||
typedef colour3<float> colour3f;
|
typedef colour3<float> colour3f;
|
||||||
typedef colour4<float> colour4f;
|
typedef colour4<float> colour4f;
|
||||||
|
|
||||||
// RGB <-> HSV
|
// RGB/HSV conversions
|
||||||
colour3f rgb_to_hsv (colour3f);
|
colour3f rgb_to_hsv (colour3f);
|
||||||
colour3f hsv_to_rgb (colour3f);
|
colour3f hsv_to_rgb (colour3f);
|
||||||
|
|
||||||
|
// ostream/istream operators
|
||||||
template <size_t S, typename T>
|
template <size_t S, typename T>
|
||||||
std::ostream& operator<< (std::ostream&, util::colour<S,T>);
|
std::ostream&
|
||||||
|
operator<< (std::ostream&, util::colour<S,T>);
|
||||||
|
|
||||||
template <size_t S, typename T>
|
template <size_t S, typename T>
|
||||||
std::istream& operator>> (std::istream&, util::colour<S,T>&);
|
std::istream&
|
||||||
|
operator>> (std::istream&, util::colour<S,T>&);
|
||||||
|
|
||||||
|
// type name introspection specialisation
|
||||||
|
template <size_t S, typename T>
|
||||||
|
struct type_name<colour<S,T>> {
|
||||||
|
static constexpr const char value[] = "colour";
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#include "colour.ipp"
|
#include "colour.ipp"
|
||||||
|
@ -21,6 +21,7 @@ NC_CXX
|
|||||||
NC_PLATFORM
|
NC_PLATFORM
|
||||||
NC_OPTIMISATION
|
NC_OPTIMISATION
|
||||||
NC_WARNINGS
|
NC_WARNINGS
|
||||||
|
# NC_DEBUGGING is called further down, see notes at the call site.
|
||||||
|
|
||||||
LT_INIT
|
LT_INIT
|
||||||
|
|
||||||
@ -83,8 +84,6 @@ AC_SEARCH_LIBS([clock_gettime], [rt c], [], [
|
|||||||
|
|
||||||
AC_SEARCH_LIBS([cos], [m], [], [AC_MSG_ERROR([unable to find the maths library])])
|
AC_SEARCH_LIBS([cos], [m], [], [AC_MSG_ERROR([unable to find the maths library])])
|
||||||
|
|
||||||
AC_SEARCH_LIBS([htons], [ws2_32], [], [AC_MSG_ERROR([unable to find htons library])])
|
|
||||||
|
|
||||||
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
## Debug features
|
## Debug features
|
||||||
@ -126,7 +125,7 @@ AC_SUBST(LIBS)
|
|||||||
# failure on a clean build
|
# failure on a clean build
|
||||||
AX_APPEND_FLAG([-include config.h])
|
AX_APPEND_FLAG([-include config.h])
|
||||||
|
|
||||||
NC_SUBPACKAGE([util])
|
NC_SUBPACKAGE([cruft-util])
|
||||||
|
|
||||||
AC_CONFIG_FILES([
|
AC_CONFIG_FILES([
|
||||||
Doxyfile
|
Doxyfile
|
||||||
|
@ -45,7 +45,7 @@ namespace util { namespace coord {
|
|||||||
base () = default;
|
base () = default;
|
||||||
|
|
||||||
constexpr explicit base (T val)
|
constexpr explicit base (T val)
|
||||||
{ for (size_t i = 0; i < S; ++i) this->data[i] = val; }
|
{ std::fill (begin (), end (), val); }
|
||||||
|
|
||||||
constexpr base (const base<S,T,KLASS,tags...> &rhs) = default;
|
constexpr base (const base<S,T,KLASS,tags...> &rhs) = default;
|
||||||
base& operator= (const base<S,T,KLASS,tags...> &rhs) = default;
|
base& operator= (const base<S,T,KLASS,tags...> &rhs) = default;
|
||||||
@ -54,6 +54,9 @@ namespace util { namespace coord {
|
|||||||
T& operator[] (size_t i) { return this->data[i]; }
|
T& operator[] (size_t i) { return this->data[i]; }
|
||||||
constexpr const T& operator[] (size_t i) const { return this->data[i]; }
|
constexpr const T& operator[] (size_t i) const { return this->data[i]; }
|
||||||
|
|
||||||
|
auto cbegin (void) const { return std::cbegin (this->data); }
|
||||||
|
auto cend (void) const { return std::cend (this->data); }
|
||||||
|
|
||||||
auto begin (void) const { return std::begin (this->data); }
|
auto begin (void) const { return std::begin (this->data); }
|
||||||
auto end (void) const { return std::end (this->data); }
|
auto end (void) const { return std::end (this->data); }
|
||||||
|
|
||||||
|
28
coord/fwd.hpp
Normal file
28
coord/fwd.hpp
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* Copyright 2016 Danny Robson <danny@nerdcruft.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __UTIL_COORD_FWD_HPP
|
||||||
|
#define __UTIL_COORD_FWD_HPP
|
||||||
|
|
||||||
|
namespace util {
|
||||||
|
template <size_t,typename> struct colour;
|
||||||
|
template <size_t,typename> struct extent;
|
||||||
|
template <size_t,typename> struct point;
|
||||||
|
template <size_t,typename> struct quaternion;
|
||||||
|
template <size_t,typename> struct vector;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
@ -20,11 +20,23 @@
|
|||||||
namespace util { namespace coord {
|
namespace util { namespace coord {
|
||||||
///////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////
|
||||||
// tags for accessor names
|
// tags for accessor names
|
||||||
|
//
|
||||||
|
// colours
|
||||||
struct rgba { };
|
struct rgba { };
|
||||||
struct hsv { };
|
struct hsv { };
|
||||||
|
|
||||||
|
// physical positions
|
||||||
struct xyzw { };
|
struct xyzw { };
|
||||||
|
|
||||||
|
// texture coords
|
||||||
struct stpq { };
|
struct stpq { };
|
||||||
|
|
||||||
|
// physical dimensions
|
||||||
struct whd { };
|
struct whd { };
|
||||||
|
|
||||||
|
// quaternions
|
||||||
|
struct wxyz { };
|
||||||
|
struct abcd { };
|
||||||
} }
|
} }
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
330
coord/ops.hpp
330
coord/ops.hpp
@ -17,20 +17,16 @@
|
|||||||
#ifndef __UTIL_COORDS_OPS
|
#ifndef __UTIL_COORDS_OPS
|
||||||
#define __UTIL_COORDS_OPS
|
#define __UTIL_COORDS_OPS
|
||||||
|
|
||||||
|
#include "./fwd.hpp"
|
||||||
|
|
||||||
#include "../preprocessor.hpp"
|
#include "../preprocessor.hpp"
|
||||||
#include "../maths.hpp"
|
#include "../maths.hpp"
|
||||||
#include "../types/bits.hpp"
|
#include "../types/bits.hpp"
|
||||||
|
|
||||||
#include <cstdlib>
|
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
namespace util {
|
namespace util {
|
||||||
// forward declerations for traits
|
|
||||||
template <size_t,typename> struct point;
|
|
||||||
template <size_t,typename> struct extent;
|
|
||||||
template <size_t,typename> struct vector;
|
|
||||||
template <size_t,typename> struct colour;
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////
|
||||||
// operation traits
|
// operation traits
|
||||||
namespace coord {
|
namespace coord {
|
||||||
@ -38,26 +34,58 @@ namespace util {
|
|||||||
template <size_t,typename> class A,
|
template <size_t,typename> class A,
|
||||||
template <size_t,typename> class B
|
template <size_t,typename> class B
|
||||||
>
|
>
|
||||||
struct traits { };
|
struct result { };
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
template <> struct traits<colour,colour> { template <size_t S, typename T> using result = colour<S,T>; };
|
template <> struct result<colour,colour> { template <size_t S, typename T> using type = colour<S,T>; };
|
||||||
template <> struct traits<extent,extent> { template <size_t S, typename T> using result = extent<S,T>; };
|
template <> struct result<extent,extent> { template <size_t S, typename T> using type = extent<S,T>; };
|
||||||
template <> struct traits<extent,vector> { template <size_t S, typename T> using result = extent<S,T>; };
|
template <> struct result<extent,vector> { template <size_t S, typename T> using type = extent<S,T>; };
|
||||||
template <> struct traits<point,extent> { template <size_t S, typename T> using result = point <S,T>; };
|
template <> struct result<point,extent> { template <size_t S, typename T> using type = point <S,T>; };
|
||||||
template <> struct traits<point,vector> { template <size_t S, typename T> using result = point <S,T>; };
|
template <> struct result<point,vector> { template <size_t S, typename T> using type = point <S,T>; };
|
||||||
template <> struct traits<vector,point> { template <size_t S, typename T> using result = point <S,T>; };
|
template <> struct result<vector,point> { template <size_t S, typename T> using type = point <S,T>; };
|
||||||
template <> struct traits<vector,vector> { template <size_t S, typename T> using result = vector<S,T>; };
|
template <> struct result<vector,vector> { template <size_t S, typename T> using type = vector<S,T>; };
|
||||||
}
|
|
||||||
|
|
||||||
template <template <size_t,typename> class> struct is_coord : std::false_type { };
|
template <
|
||||||
|
template <size_t,typename> class A,
|
||||||
|
template <size_t,typename> class B
|
||||||
|
>
|
||||||
|
using result_t = typename result<A,B>::type;
|
||||||
|
|
||||||
template <> struct is_coord<point> : std::true_type { };
|
|
||||||
template <> struct is_coord<extent> : std::true_type { };
|
//---------------------------------------------------------------------
|
||||||
template <> struct is_coord<vector> : std::true_type { };
|
template <template <size_t,typename> class K>
|
||||||
template <> struct is_coord<colour> : std::true_type { };
|
struct has_norm : public std::false_type { };
|
||||||
|
|
||||||
|
template <> struct has_norm<vector> : public std::true_type { };
|
||||||
|
template <> struct has_norm<quaternion> : public std::true_type { };
|
||||||
|
|
||||||
template <template <size_t,typename> class K>
|
template <template <size_t,typename> class K>
|
||||||
|
constexpr auto has_norm_v = has_norm<K>::value;
|
||||||
|
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
template <template <size_t,typename> class K>
|
||||||
|
struct has_scalar_op : public std::false_type { };
|
||||||
|
|
||||||
|
template <> struct has_scalar_op<colour> : public std::true_type { };
|
||||||
|
template <> struct has_scalar_op<extent> : public std::true_type { };
|
||||||
|
template <> struct has_scalar_op<point> : public std::true_type { };
|
||||||
|
template <> struct has_scalar_op<quaternion> : public std::true_type { };
|
||||||
|
template <> struct has_scalar_op<vector> : public std::true_type { };
|
||||||
|
|
||||||
|
template <template <size_t,typename> class K>
|
||||||
|
constexpr auto has_scalar_op_v = has_scalar_op<K>::value;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class> struct is_coord : std::false_type { };
|
||||||
|
|
||||||
|
template <size_t S, typename T> struct is_coord<point<S,T>> : std::true_type { };
|
||||||
|
template <size_t S, typename T> struct is_coord<extent<S,T>> : std::true_type { };
|
||||||
|
template <size_t S, typename T> struct is_coord<vector<S,T>> : std::true_type { };
|
||||||
|
template <size_t S, typename T> struct is_coord<colour<S,T>> : std::true_type { };
|
||||||
|
template <size_t S, typename T> struct is_coord<quaternion<S,T>> : std::true_type { };
|
||||||
|
|
||||||
|
template <class K>
|
||||||
constexpr bool
|
constexpr bool
|
||||||
is_coord_v = is_coord<K>::value;
|
is_coord_v = is_coord<K>::value;
|
||||||
|
|
||||||
@ -71,7 +99,7 @@ namespace util {
|
|||||||
template <size_t,typename> class A, \
|
template <size_t,typename> class A, \
|
||||||
template <size_t,typename> class B, \
|
template <size_t,typename> class B, \
|
||||||
typename = std::enable_if_t< \
|
typename = std::enable_if_t< \
|
||||||
is_coord_v<A> && is_coord_v<B>, \
|
is_coord_v<A<S,T>> && is_coord_v<B<S,U>>, \
|
||||||
void \
|
void \
|
||||||
> \
|
> \
|
||||||
> \
|
> \
|
||||||
@ -79,7 +107,7 @@ namespace util {
|
|||||||
auto \
|
auto \
|
||||||
operator OP (A<S,T> a, B<S,U> b) \
|
operator OP (A<S,T> a, B<S,U> b) \
|
||||||
{ \
|
{ \
|
||||||
typename coord::traits<A,B>::template result< \
|
typename coord::result<A,B>::template type< \
|
||||||
S,std::common_type_t<T,U> \
|
S,std::common_type_t<T,U> \
|
||||||
> out {}; \
|
> out {}; \
|
||||||
for (size_t i = 0; i < S; ++i) \
|
for (size_t i = 0; i < S; ++i) \
|
||||||
@ -94,8 +122,8 @@ namespace util {
|
|||||||
template <size_t,typename> class A, \
|
template <size_t,typename> class A, \
|
||||||
template <size_t,typename> class B, \
|
template <size_t,typename> class B, \
|
||||||
typename = std::enable_if_t< \
|
typename = std::enable_if_t< \
|
||||||
is_coord_v<A> && \
|
is_coord_v<A<S,T>> && \
|
||||||
is_coord_v<B> && \
|
is_coord_v<B<S,U>> && \
|
||||||
std::is_same< \
|
std::is_same< \
|
||||||
std::common_type_t<T,U>, T \
|
std::common_type_t<T,U>, T \
|
||||||
>::value, \
|
>::value, \
|
||||||
@ -126,7 +154,7 @@ namespace util {
|
|||||||
typename U, \
|
typename U, \
|
||||||
template <size_t,typename> class K, \
|
template <size_t,typename> class K, \
|
||||||
typename = std::enable_if_t< \
|
typename = std::enable_if_t< \
|
||||||
is_coord_v<K>,void \
|
coord::has_scalar_op_v<K>, void \
|
||||||
> \
|
> \
|
||||||
> \
|
> \
|
||||||
constexpr \
|
constexpr \
|
||||||
@ -146,7 +174,7 @@ namespace util {
|
|||||||
typename U, \
|
typename U, \
|
||||||
template <size_t,typename> class K, \
|
template <size_t,typename> class K, \
|
||||||
typename = std::enable_if_t< \
|
typename = std::enable_if_t< \
|
||||||
is_coord<K>::value,void \
|
coord::has_scalar_op_v<K>,void \
|
||||||
> \
|
> \
|
||||||
> \
|
> \
|
||||||
constexpr \
|
constexpr \
|
||||||
@ -181,7 +209,7 @@ namespace util {
|
|||||||
typename U, \
|
typename U, \
|
||||||
template <size_t,typename> class K, \
|
template <size_t,typename> class K, \
|
||||||
typename = std::enable_if_t< \
|
typename = std::enable_if_t< \
|
||||||
is_coord<K>::value && \
|
is_coord<K<S,T>>::value && \
|
||||||
std::is_arithmetic<T>::value && \
|
std::is_arithmetic<T>::value && \
|
||||||
std::is_arithmetic<U>::value, \
|
std::is_arithmetic<U>::value, \
|
||||||
void \
|
void \
|
||||||
@ -219,7 +247,7 @@ namespace util {
|
|||||||
typename T, \
|
typename T, \
|
||||||
template <size_t,typename> class K, \
|
template <size_t,typename> class K, \
|
||||||
typename = std::enable_if_t< \
|
typename = std::enable_if_t< \
|
||||||
is_coord_v<K>, void \
|
is_coord_v<K<S,T>>, void \
|
||||||
> \
|
> \
|
||||||
> \
|
> \
|
||||||
constexpr \
|
constexpr \
|
||||||
@ -251,7 +279,7 @@ namespace util {
|
|||||||
typename T,
|
typename T,
|
||||||
template <size_t,typename> class K,
|
template <size_t,typename> class K,
|
||||||
typename = std::enable_if_t<
|
typename = std::enable_if_t<
|
||||||
is_coord_v<K>, void
|
is_coord_v<K<S,T>>, void
|
||||||
>
|
>
|
||||||
>
|
>
|
||||||
constexpr
|
constexpr
|
||||||
@ -273,7 +301,7 @@ namespace util {
|
|||||||
typename T,
|
typename T,
|
||||||
template <size_t,typename> class K,
|
template <size_t,typename> class K,
|
||||||
typename = std::enable_if_t<
|
typename = std::enable_if_t<
|
||||||
is_coord_v<K>, void
|
is_coord_v<K<S,T>>, void
|
||||||
>
|
>
|
||||||
>
|
>
|
||||||
constexpr
|
constexpr
|
||||||
@ -284,6 +312,27 @@ namespace util {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
template <
|
||||||
|
size_t S,
|
||||||
|
typename T,
|
||||||
|
template <size_t,typename> class K,
|
||||||
|
typename = std::enable_if_t<
|
||||||
|
is_coord_v<K<S,T>>, void
|
||||||
|
>
|
||||||
|
>
|
||||||
|
constexpr
|
||||||
|
bool
|
||||||
|
almost_zero (const K<S,T> &k)
|
||||||
|
{
|
||||||
|
return std::all_of (
|
||||||
|
std::cbegin (k),
|
||||||
|
std::cend (k),
|
||||||
|
[] (T t) { return almost_equal (t); }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// special operators
|
// special operators
|
||||||
|
|
||||||
@ -322,7 +371,7 @@ namespace util {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
///////////////////////////////////////////////////////////////////////////
|
||||||
template <
|
template <
|
||||||
size_t S,
|
size_t S,
|
||||||
typename T
|
typename T
|
||||||
@ -337,13 +386,15 @@ namespace util {
|
|||||||
return sum;
|
return sum;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
template <
|
template <
|
||||||
size_t S,
|
size_t S,
|
||||||
typename T,
|
typename T,
|
||||||
template <size_t,typename> class A,
|
template <size_t,typename> class A,
|
||||||
template <size_t,typename> class B,
|
template <size_t,typename> class B,
|
||||||
typename = std::enable_if_t<
|
typename = std::enable_if_t<
|
||||||
is_coord_v<A> && is_coord_v<B>, void
|
is_coord_v<A<S,T>> && is_coord_v<B<S,T>>, void
|
||||||
>
|
>
|
||||||
>
|
>
|
||||||
constexpr
|
constexpr
|
||||||
@ -354,12 +405,13 @@ namespace util {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
template <
|
template <
|
||||||
size_t S,
|
size_t S,
|
||||||
typename T,
|
typename T,
|
||||||
template <size_t,typename> class K,
|
template <size_t,typename> class K,
|
||||||
typename = std::enable_if_t<
|
typename = std::enable_if_t<
|
||||||
is_coord_v<K>, void
|
is_coord_v<K<S,T>>, void
|
||||||
>
|
>
|
||||||
>
|
>
|
||||||
constexpr
|
constexpr
|
||||||
@ -370,12 +422,13 @@ namespace util {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
template <
|
template <
|
||||||
size_t S,
|
size_t S,
|
||||||
typename T,
|
typename T,
|
||||||
template <size_t,typename> class K,
|
template <size_t,typename> class K,
|
||||||
typename = std::enable_if_t<
|
typename = std::enable_if_t<
|
||||||
is_coord_v<K>, void
|
is_coord_v<K<S,T>>, void
|
||||||
>
|
>
|
||||||
>
|
>
|
||||||
constexpr
|
constexpr
|
||||||
@ -386,13 +439,85 @@ namespace util {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
template <
|
||||||
|
size_t S,
|
||||||
|
typename T,
|
||||||
|
template <size_t,typename> class K,
|
||||||
|
typename = std::enable_if_t<coord::has_norm_v<K>,void>
|
||||||
|
>
|
||||||
|
constexpr
|
||||||
|
T
|
||||||
|
norm2 (const K<S,T> &k)
|
||||||
|
{
|
||||||
|
T sum = T{0};
|
||||||
|
for (auto &t: k)
|
||||||
|
sum += t * t;
|
||||||
|
return sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
template <
|
template <
|
||||||
size_t S,
|
size_t S,
|
||||||
typename T,
|
typename T,
|
||||||
template <size_t,typename> class K,
|
template <size_t,typename> class K,
|
||||||
typename = std::enable_if_t<
|
typename = std::enable_if_t<
|
||||||
is_coord_v<K>, void
|
coord::has_norm_v<K>,
|
||||||
|
void
|
||||||
|
>
|
||||||
|
>
|
||||||
|
constexpr
|
||||||
|
T
|
||||||
|
norm (const K<S,T> &k)
|
||||||
|
{
|
||||||
|
return std::sqrt (norm2 (k));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
template <
|
||||||
|
size_t S,
|
||||||
|
typename T,
|
||||||
|
template <size_t,typename> class K,
|
||||||
|
typename = std::enable_if_t<
|
||||||
|
coord::has_norm_v<K>,
|
||||||
|
void
|
||||||
|
>
|
||||||
|
>
|
||||||
|
constexpr
|
||||||
|
K<S,T>
|
||||||
|
normalised (const K<S,T> &k)
|
||||||
|
{
|
||||||
|
return k / norm (k);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
template <
|
||||||
|
size_t S,
|
||||||
|
typename T,
|
||||||
|
template <size_t,typename> class K,
|
||||||
|
typename = std::enable_if_t<
|
||||||
|
coord::has_norm_v<K>,
|
||||||
|
void
|
||||||
|
>
|
||||||
|
>
|
||||||
|
constexpr
|
||||||
|
bool
|
||||||
|
is_normalised (const K<S,T> &k)
|
||||||
|
{
|
||||||
|
return almost_equal (norm2 (k), T{1});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
template <
|
||||||
|
size_t S,
|
||||||
|
typename T,
|
||||||
|
template <size_t,typename> class K,
|
||||||
|
typename = std::enable_if_t<
|
||||||
|
is_coord_v<K<S,T>>, void
|
||||||
>
|
>
|
||||||
>
|
>
|
||||||
constexpr
|
constexpr
|
||||||
@ -404,13 +529,13 @@ namespace util {
|
|||||||
return k;
|
return k;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
///////////////////////////////////////////////////////////////////////////
|
||||||
template <
|
template <
|
||||||
size_t S,
|
size_t S,
|
||||||
typename T,
|
typename T,
|
||||||
template <size_t,typename> class K,
|
template <size_t,typename> class K,
|
||||||
typename = std::enable_if_t<
|
typename = std::enable_if_t<
|
||||||
is_coord_v<K>, void
|
is_coord_v<K<S,T>>, void
|
||||||
>
|
>
|
||||||
>
|
>
|
||||||
constexpr
|
constexpr
|
||||||
@ -422,6 +547,90 @@ namespace util {
|
|||||||
return k;
|
return k;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// root of sum of squares
|
||||||
|
template <
|
||||||
|
size_t S,
|
||||||
|
typename T,
|
||||||
|
template <size_t,typename> class K,
|
||||||
|
typename = std::enable_if_t<
|
||||||
|
is_coord_v<K<S,T>>, void
|
||||||
|
>
|
||||||
|
>
|
||||||
|
constexpr
|
||||||
|
T
|
||||||
|
hypot (K<S,T> k)
|
||||||
|
{
|
||||||
|
return std::sqrt (sum (k * k));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
template <
|
||||||
|
size_t S,
|
||||||
|
typename T,
|
||||||
|
template <size_t,typename> class K,
|
||||||
|
typename = std::enable_if_t<
|
||||||
|
is_coord_v<K<S,T>>, void
|
||||||
|
>
|
||||||
|
>
|
||||||
|
constexpr
|
||||||
|
K<S,T>
|
||||||
|
mod (K<S,T> k, T t)
|
||||||
|
{
|
||||||
|
std::transform (
|
||||||
|
std::cbegin (k),
|
||||||
|
std::cend (k),
|
||||||
|
std::begin (k),
|
||||||
|
[t] (auto v) { return mod (v, t);
|
||||||
|
});
|
||||||
|
return k;
|
||||||
|
}
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// trigonometric functions
|
||||||
|
template <
|
||||||
|
size_t S,
|
||||||
|
typename T,
|
||||||
|
template <size_t,typename> class K,
|
||||||
|
typename = std::enable_if_t<is_coord_v<K<S,T>>,void>
|
||||||
|
>
|
||||||
|
constexpr
|
||||||
|
K<S,T>
|
||||||
|
sin (K<S,T> k)
|
||||||
|
{
|
||||||
|
std::transform (
|
||||||
|
std::cbegin (k),
|
||||||
|
std::cend (k),
|
||||||
|
std::begin (k),
|
||||||
|
[] (auto v) { return std::sin (v); }
|
||||||
|
);
|
||||||
|
|
||||||
|
return k;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
template <
|
||||||
|
size_t S,
|
||||||
|
typename T,
|
||||||
|
template <size_t,typename> class K,
|
||||||
|
typename = std::enable_if_t<is_coord_v<K<S,T>>,void>
|
||||||
|
>
|
||||||
|
constexpr
|
||||||
|
K<S,T>
|
||||||
|
cos (K<S,T> k)
|
||||||
|
{
|
||||||
|
std::transform (
|
||||||
|
std::cbegin (k),
|
||||||
|
std::cend (k),
|
||||||
|
std::begin (k),
|
||||||
|
[] (auto v) { return std::cos (v); }
|
||||||
|
);
|
||||||
|
|
||||||
|
return k;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
// logical element operators
|
// logical element operators
|
||||||
@ -432,7 +641,7 @@ namespace util {
|
|||||||
typename T,
|
typename T,
|
||||||
template <size_t,typename> class K,
|
template <size_t,typename> class K,
|
||||||
typename = std::enable_if_t<
|
typename = std::enable_if_t<
|
||||||
is_coord_v<K>, void
|
is_coord_v<K<S,T>>, void
|
||||||
>
|
>
|
||||||
>
|
>
|
||||||
constexpr
|
constexpr
|
||||||
@ -453,7 +662,7 @@ namespace util {
|
|||||||
typename T,
|
typename T,
|
||||||
template <size_t,typename> class K,
|
template <size_t,typename> class K,
|
||||||
typename = std::enable_if_t<
|
typename = std::enable_if_t<
|
||||||
is_coord_v<K>, void
|
is_coord_v<K<S,T>>, void
|
||||||
>
|
>
|
||||||
>
|
>
|
||||||
constexpr
|
constexpr
|
||||||
@ -473,7 +682,7 @@ namespace util {
|
|||||||
typename T,
|
typename T,
|
||||||
template<size_t,typename> class K,
|
template<size_t,typename> class K,
|
||||||
typename = std::enable_if_t<
|
typename = std::enable_if_t<
|
||||||
is_coord_v<K>, void
|
is_coord_v<K<S,T>>, void
|
||||||
>
|
>
|
||||||
>
|
>
|
||||||
constexpr
|
constexpr
|
||||||
@ -489,7 +698,7 @@ namespace util {
|
|||||||
typename T,
|
typename T,
|
||||||
template<size_t,typename> class K,
|
template<size_t,typename> class K,
|
||||||
typename = std::enable_if_t<
|
typename = std::enable_if_t<
|
||||||
is_coord_v<K>, void
|
is_coord_v<K<S,T>>, void
|
||||||
>
|
>
|
||||||
>
|
>
|
||||||
constexpr
|
constexpr
|
||||||
@ -500,7 +709,24 @@ namespace util {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
template <
|
||||||
|
size_t S,
|
||||||
|
typename T,
|
||||||
|
template <size_t,typename> class K,
|
||||||
|
typename = std::enable_if_t<
|
||||||
|
is_coord_v<K<S,T>>, void
|
||||||
|
>
|
||||||
|
>
|
||||||
|
constexpr
|
||||||
|
T
|
||||||
|
sum (const K<S,T> k)
|
||||||
|
{
|
||||||
|
return sum (std::cbegin (k), std::cend (k));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
#define VECTOR_OP(OP) \
|
#define VECTOR_OP(OP) \
|
||||||
template < \
|
template < \
|
||||||
size_t S, \
|
size_t S, \
|
||||||
@ -509,7 +735,7 @@ namespace util {
|
|||||||
template <size_t,typename> class A, \
|
template <size_t,typename> class A, \
|
||||||
template <size_t,typename> class B, \
|
template <size_t,typename> class B, \
|
||||||
typename = std::enable_if_t< \
|
typename = std::enable_if_t< \
|
||||||
is_coord_v<A> && is_coord_v<B>, void \
|
is_coord_v<A<S,T>> && is_coord_v<B<S,U>>, void \
|
||||||
> \
|
> \
|
||||||
> \
|
> \
|
||||||
constexpr \
|
constexpr \
|
||||||
@ -526,6 +752,8 @@ namespace util {
|
|||||||
VECTOR_OP(>)
|
VECTOR_OP(>)
|
||||||
VECTOR_OP(<=)
|
VECTOR_OP(<=)
|
||||||
VECTOR_OP(>=)
|
VECTOR_OP(>=)
|
||||||
|
VECTOR_OP(&&)
|
||||||
|
VECTOR_OP(||)
|
||||||
|
|
||||||
#undef VECTOR_OP
|
#undef VECTOR_OP
|
||||||
|
|
||||||
@ -537,7 +765,7 @@ namespace util {
|
|||||||
typename U, \
|
typename U, \
|
||||||
template <size_t,typename> class K, \
|
template <size_t,typename> class K, \
|
||||||
typename = std::enable_if_t< \
|
typename = std::enable_if_t< \
|
||||||
is_coord_v<K>, void \
|
is_coord_v<K<S,T>>, void \
|
||||||
> \
|
> \
|
||||||
> \
|
> \
|
||||||
constexpr \
|
constexpr \
|
||||||
@ -554,6 +782,8 @@ namespace util {
|
|||||||
SCALAR_OP(>)
|
SCALAR_OP(>)
|
||||||
SCALAR_OP(<=)
|
SCALAR_OP(<=)
|
||||||
SCALAR_OP(>=)
|
SCALAR_OP(>=)
|
||||||
|
SCALAR_OP(&&)
|
||||||
|
SCALAR_OP(||)
|
||||||
|
|
||||||
#undef SCALAR_OP
|
#undef SCALAR_OP
|
||||||
|
|
||||||
@ -563,7 +793,7 @@ namespace util {
|
|||||||
size_t S,
|
size_t S,
|
||||||
template <size_t,typename> class K,
|
template <size_t,typename> class K,
|
||||||
typename = std::enable_if_t<
|
typename = std::enable_if_t<
|
||||||
is_coord_v<K>, void
|
is_coord_v<K<S,bool>>, void
|
||||||
>
|
>
|
||||||
>
|
>
|
||||||
constexpr
|
constexpr
|
||||||
@ -571,7 +801,7 @@ namespace util {
|
|||||||
any (const K<S,bool> k)
|
any (const K<S,bool> k)
|
||||||
{
|
{
|
||||||
return std::any_of (std::cbegin (k),
|
return std::any_of (std::cbegin (k),
|
||||||
std::cbegin (k),
|
std::cend (k),
|
||||||
identity<bool>);
|
identity<bool>);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -580,7 +810,7 @@ namespace util {
|
|||||||
size_t S,
|
size_t S,
|
||||||
template <size_t,typename> class K,
|
template <size_t,typename> class K,
|
||||||
typename = std::enable_if_t<
|
typename = std::enable_if_t<
|
||||||
is_coord_v<K>, void
|
is_coord_v<K<S,bool>>, void
|
||||||
>
|
>
|
||||||
>
|
>
|
||||||
constexpr
|
constexpr
|
||||||
@ -588,7 +818,7 @@ namespace util {
|
|||||||
all (const K<S,bool> k)
|
all (const K<S,bool> k)
|
||||||
{
|
{
|
||||||
return std::all_of (std::cbegin (k),
|
return std::all_of (std::cbegin (k),
|
||||||
std::cbegin (k),
|
std::cend (k),
|
||||||
identity<bool>);
|
identity<bool>);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -599,7 +829,7 @@ namespace util {
|
|||||||
typename T,
|
typename T,
|
||||||
template<size_t,typename> class K,
|
template<size_t,typename> class K,
|
||||||
typename = std::enable_if_t<
|
typename = std::enable_if_t<
|
||||||
is_coord_v<K> && std::is_floating_point<T>::value, void
|
is_coord_v<K<S,T>> && std::is_floating_point<T>::value, void
|
||||||
>
|
>
|
||||||
>
|
>
|
||||||
constexpr
|
constexpr
|
||||||
|
@ -168,6 +168,17 @@ namespace util { namespace coord {
|
|||||||
struct { T w,h,d; };
|
struct { T w,h,d; };
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
template <typename T>
|
||||||
|
struct store<4,T,wxyz,abcd> {
|
||||||
|
union {
|
||||||
|
T data[4];
|
||||||
|
struct { T w,x,y,z; };
|
||||||
|
struct { T a,b,c,d; };
|
||||||
|
};
|
||||||
|
};
|
||||||
} }
|
} }
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
86
debug.hpp
86
debug.hpp
@ -24,12 +24,10 @@
|
|||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
#ifdef ENABLE_DEBUGGING
|
#if !defined(NDEBUG)
|
||||||
#define DEBUG_ONLY(X) do { \
|
#define DEBUG_ONLY(X) do { X } while (0)
|
||||||
X \
|
|
||||||
} while (0)
|
|
||||||
#else
|
#else
|
||||||
#define DEBUG_ONLY(X)
|
#define DEBUG_ONLY(X) do { } while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@ -59,7 +57,7 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
#define _CHECK_PANIC(FMT,...) do { \
|
#define _CHECK_PANIC(FMT,...) do { \
|
||||||
panic ("%s:%s:%i:%s\n" FMT, \
|
panic ("%s:%s:%i:%s\n" FMT, \
|
||||||
PACKAGE, __FILE__, __LINE__, __FUNCTION__, \
|
PACKAGE, __FILE__, __LINE__, __func__, \
|
||||||
__VA_ARGS__); \
|
__VA_ARGS__); \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
@ -77,7 +75,7 @@
|
|||||||
#define CHECK_SANITY(A) do { \
|
#define CHECK_SANITY(A) do { \
|
||||||
DEBUG_ONLY( \
|
DEBUG_ONLY( \
|
||||||
const auto &__a = (A); \
|
const auto &__a = (A); \
|
||||||
if (!util::debug::valid (__a)) { \
|
if (!util::debug::is_valid (__a)) { \
|
||||||
_CHECK_PANIC("failed sanity test for %s, %!\n", #A, __a); \
|
_CHECK_PANIC("failed sanity test for %s, %!\n", #A, __a); \
|
||||||
} \
|
} \
|
||||||
); \
|
); \
|
||||||
@ -87,8 +85,8 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
#define CHECK_EQ(A,B) do { \
|
#define CHECK_EQ(A,B) do { \
|
||||||
DEBUG_ONLY( \
|
DEBUG_ONLY( \
|
||||||
const auto __a = (A); \
|
const auto &__a = (A); \
|
||||||
const auto __b = (B); \
|
const auto &__b = (B); \
|
||||||
\
|
\
|
||||||
if (!util::almost_equal (__a, __b)) { \
|
if (!util::almost_equal (__a, __b)) { \
|
||||||
_CHECK_PANIC("expected equality\n" \
|
_CHECK_PANIC("expected equality\n" \
|
||||||
@ -104,8 +102,8 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
#define CHECK_LT(A,B) do { \
|
#define CHECK_LT(A,B) do { \
|
||||||
DEBUG_ONLY( \
|
DEBUG_ONLY( \
|
||||||
const auto __a = (A); \
|
const auto &__a = (A); \
|
||||||
const auto __b = (B); \
|
const auto &__b = (B); \
|
||||||
\
|
\
|
||||||
if (__a >= __b) { \
|
if (__a >= __b) { \
|
||||||
_CHECK_PANIC("expected less than\n" \
|
_CHECK_PANIC("expected less than\n" \
|
||||||
@ -121,8 +119,8 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
#define CHECK_LE(A,B) do { \
|
#define CHECK_LE(A,B) do { \
|
||||||
DEBUG_ONLY( \
|
DEBUG_ONLY( \
|
||||||
const auto __a = (A); \
|
const auto &__a = (A); \
|
||||||
const auto __b = (B); \
|
const auto &__b = (B); \
|
||||||
\
|
\
|
||||||
if (__a > __b) { \
|
if (__a > __b) { \
|
||||||
_CHECK_PANIC("expected less than or equal\n" \
|
_CHECK_PANIC("expected less than or equal\n" \
|
||||||
@ -138,8 +136,8 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
#define CHECK_GT(A,B) do { \
|
#define CHECK_GT(A,B) do { \
|
||||||
DEBUG_ONLY( \
|
DEBUG_ONLY( \
|
||||||
const auto __a = (A); \
|
const auto &__a = (A); \
|
||||||
const auto __b = (B); \
|
const auto &__b = (B); \
|
||||||
\
|
\
|
||||||
if (__a <= __b) { \
|
if (__a <= __b) { \
|
||||||
_CHECK_PANIC ("expected greater than\n" \
|
_CHECK_PANIC ("expected greater than\n" \
|
||||||
@ -155,8 +153,8 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
#define CHECK_GE(A,B) do { \
|
#define CHECK_GE(A,B) do { \
|
||||||
DEBUG_ONLY( \
|
DEBUG_ONLY( \
|
||||||
const auto __a = (A); \
|
const auto &__a = (A); \
|
||||||
const auto __b = (B); \
|
const auto &__b = (B); \
|
||||||
\
|
\
|
||||||
if (__a < __b) { \
|
if (__a < __b) { \
|
||||||
_CHECK_PANIC ("expected greater or equal\n" \
|
_CHECK_PANIC ("expected greater or equal\n" \
|
||||||
@ -172,9 +170,9 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
#define CHECK_LIMIT(V,L,H) do { \
|
#define CHECK_LIMIT(V,L,H) do { \
|
||||||
DEBUG_ONLY( \
|
DEBUG_ONLY( \
|
||||||
const auto __v = (V); \
|
const auto &__v = (V); \
|
||||||
const auto __l = (L); \
|
const auto &__l = (L); \
|
||||||
const auto __h = (H); \
|
const auto &__h = (H); \
|
||||||
\
|
\
|
||||||
if (__v < __l || __v > __h) { \
|
if (__v < __l || __v > __h) { \
|
||||||
_CHECK_PANIC ("expected limit\n" \
|
_CHECK_PANIC ("expected limit\n" \
|
||||||
@ -191,8 +189,8 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
#define CHECK_NEQ(A,B) do { \
|
#define CHECK_NEQ(A,B) do { \
|
||||||
DEBUG_ONLY( \
|
DEBUG_ONLY( \
|
||||||
const auto __a = (A); \
|
const auto &__a = (A); \
|
||||||
const auto __b = (B); \
|
const auto &__b = (B); \
|
||||||
\
|
\
|
||||||
if (util::almost_equal (__a, __b)) { \
|
if (util::almost_equal (__a, __b)) { \
|
||||||
_CHECK_PANIC ("expected inequality\n" \
|
_CHECK_PANIC ("expected inequality\n" \
|
||||||
@ -208,7 +206,7 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
#define CHECK_ZERO(A) do { \
|
#define CHECK_ZERO(A) do { \
|
||||||
DEBUG_ONLY( \
|
DEBUG_ONLY( \
|
||||||
const auto __a = (A); \
|
const auto &__a = (A); \
|
||||||
\
|
\
|
||||||
if (!util::almost_zero (__a)) { \
|
if (!util::almost_zero (__a)) { \
|
||||||
_CHECK_PANIC ("expected zero\n" \
|
_CHECK_PANIC ("expected zero\n" \
|
||||||
@ -222,7 +220,7 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
#define CHECK_NEZ(A) do { \
|
#define CHECK_NEZ(A) do { \
|
||||||
DEBUG_ONLY( \
|
DEBUG_ONLY( \
|
||||||
const auto __a = (A); \
|
const auto &__a = (A); \
|
||||||
if (util::exactly_zero (__a)) \
|
if (util::exactly_zero (__a)) \
|
||||||
_CHECK_PANIC ("expected zero\n" \
|
_CHECK_PANIC ("expected zero\n" \
|
||||||
"__a: %s is %!", \
|
"__a: %s is %!", \
|
||||||
@ -231,6 +229,21 @@
|
|||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
#define CHECK_MOD(V,M) do { \
|
||||||
|
DEBUG_ONLY ( \
|
||||||
|
const auto &__check_mod_v = (V); \
|
||||||
|
const auto &__check_mod_m = (M); \
|
||||||
|
if (!util::exactly_zero (__check_mod_v % __check_mod_m)) \
|
||||||
|
_CHECK_PANIC ("expected zero modulus\n" \
|
||||||
|
"__v: %s is %!\n" \
|
||||||
|
"__m: %s is %!", \
|
||||||
|
#V, __check_mod_v, \
|
||||||
|
#M, __check_mod_m); \
|
||||||
|
); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
#if defined(ENABLE_DEBUGGING)
|
#if defined(ENABLE_DEBUGGING)
|
||||||
#define CHECK_ENUM(C, ...) do { \
|
#define CHECK_ENUM(C, ...) do { \
|
||||||
@ -286,8 +299,9 @@
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
constexpr void panic [[noreturn]] (const char*);
|
constexpr void panic [[noreturn]] (const char*);
|
||||||
|
|
||||||
template <typename ...Args>
|
template <typename ...Args, size_t N>
|
||||||
constexpr void panic [[noreturn]] (const char *fmt, const Args&...);
|
constexpr
|
||||||
|
void panic [[noreturn]] (const char (&fmt)[N], const Args&...);
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
@ -328,7 +342,14 @@ namespace util { namespace debug {
|
|||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool valid (const T&);
|
struct validator {
|
||||||
|
static bool is_valid (const T&);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool is_valid (const T &t)
|
||||||
|
{ return validator<T>::is_valid (t); }
|
||||||
|
|
||||||
|
|
||||||
template <
|
template <
|
||||||
@ -336,7 +357,7 @@ namespace util { namespace debug {
|
|||||||
size_t S,
|
size_t S,
|
||||||
typename ...Args
|
typename ...Args
|
||||||
>
|
>
|
||||||
struct validator {
|
struct validator<T<S,Args...>> {
|
||||||
static bool is_valid (const T<S,Args...>&);
|
static bool is_valid (const T<S,Args...>&);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -346,15 +367,15 @@ namespace util { namespace debug {
|
|||||||
size_t S,
|
size_t S,
|
||||||
typename ...Args
|
typename ...Args
|
||||||
>
|
>
|
||||||
bool valid (const T<S,Args...> &v)
|
bool is_valid (const T<S,Args...> &v)
|
||||||
{ return validator<T,S,Args...>::is_valid (v); }
|
{ return validator<T<S,Args...>>::is_valid (v); }
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void sanity (const T &t)
|
void sanity (const T &t)
|
||||||
{
|
{
|
||||||
(void)t;
|
(void)t;
|
||||||
CHECK (valid (t));
|
CHECK (is_valid (t));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -365,13 +386,14 @@ namespace util { namespace debug {
|
|||||||
void sanity (const T<Args...> &t)
|
void sanity (const T<Args...> &t)
|
||||||
{
|
{
|
||||||
(void)t;
|
(void)t;
|
||||||
CHECK (valid (t));
|
CHECK (is_valid (t));
|
||||||
}
|
}
|
||||||
} }
|
} }
|
||||||
|
|
||||||
|
|
||||||
#include "./debug.ipp"
|
#include "./debug.ipp"
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// XXX: maths needs to be included so that CHECK_EQ/NEQ can call almost_equal,
|
// XXX: maths needs to be included so that CHECK_EQ/NEQ can call almost_equal,
|
||||||
// but maths.hpp might be using CHECK_ macros so we must include maths.hpp
|
// but maths.hpp might be using CHECK_ macros so we must include maths.hpp
|
||||||
|
18
debug.ipp
18
debug.ipp
@ -28,9 +28,13 @@
|
|||||||
namespace util { namespace debug { namespace detail {
|
namespace util { namespace debug { namespace detail {
|
||||||
void panic [[noreturn]] (const char *msg);
|
void panic [[noreturn]] (const char *msg);
|
||||||
|
|
||||||
template <typename ...Args>
|
template <typename ...Args, size_t N>
|
||||||
void panic [[noreturn]] (const char *msg, const Args& ...args)
|
constexpr
|
||||||
{ panic (util::format::render (msg, args...).c_str ()); }
|
void panic [[noreturn]] (const char (&fmt)[N], const Args& ...args)
|
||||||
|
{
|
||||||
|
auto msg = util::format::render (fmt, args...);
|
||||||
|
panic (msg.c_str ());
|
||||||
|
}
|
||||||
|
|
||||||
void not_implemented [[noreturn]] (const char *msg);
|
void not_implemented [[noreturn]] (const char *msg);
|
||||||
void unreachable [[noreturn]] (const char *msg);
|
void unreachable [[noreturn]] (const char *msg);
|
||||||
@ -92,12 +96,10 @@ constexpr void panic [[noreturn]] (const char *msg)
|
|||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
template <typename ...Args>
|
template <typename ...Args, size_t N>
|
||||||
constexpr
|
constexpr
|
||||||
void
|
void
|
||||||
panic [[noreturn]] (const char *fmt, const Args& ...args)
|
panic [[noreturn]] (const char (&fmt)[N], const Args& ...args)
|
||||||
{
|
{
|
||||||
! fmt
|
util::debug::detail::panic (fmt, args...);
|
||||||
? panic ("unreachable constexpr panic helper")
|
|
||||||
: util::debug::detail::panic (fmt, args...);
|
|
||||||
}
|
}
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include "./except.hpp"
|
#include "./except.hpp"
|
||||||
|
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
40
extent.cpp
40
extent.cpp
@ -42,34 +42,6 @@ extent<S,T>::extent (vector<S,T> _v)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
template <size_t S, typename T>
|
|
||||||
T
|
|
||||||
extent<S,T>::diameter (void) const
|
|
||||||
{
|
|
||||||
return static_cast<T> (
|
|
||||||
std::sqrt (
|
|
||||||
std::accumulate (std::begin (this->data),
|
|
||||||
std::end (this->data),
|
|
||||||
T {0},
|
|
||||||
[] (auto a, auto b) { return a + b * b; })
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
template <size_t S, typename T>
|
|
||||||
T
|
|
||||||
extent<S,T>::area (void) const
|
|
||||||
{
|
|
||||||
return std::accumulate (std::begin (this->data),
|
|
||||||
std::end (this->data),
|
|
||||||
T {1},
|
|
||||||
std::multiplies<T> ());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
template <size_t S, typename T>
|
template <size_t S, typename T>
|
||||||
extent<S,T>
|
extent<S,T>
|
||||||
@ -216,7 +188,7 @@ extent_range<S,T>::iterator::operator!= (const iterator &rhs) const
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
namespace util { namespace debug {
|
namespace util { namespace debug {
|
||||||
template <size_t S, typename T>
|
template <size_t S, typename T>
|
||||||
struct validator<extent,S,T> {
|
struct validator<extent<S,T>> {
|
||||||
static bool is_valid (const extent<S,T> &e)
|
static bool is_valid (const extent<S,T> &e)
|
||||||
{
|
{
|
||||||
return std::all_of (std::begin (e.data),
|
return std::all_of (std::begin (e.data),
|
||||||
@ -226,11 +198,11 @@ namespace util { namespace debug {
|
|||||||
};
|
};
|
||||||
} }
|
} }
|
||||||
|
|
||||||
template bool util::debug::valid (const extent<2,float>&);
|
template bool util::debug::is_valid (const extent<2,float>&);
|
||||||
template bool util::debug::valid (const extent<2,double>&);
|
template bool util::debug::is_valid (const extent<2,double>&);
|
||||||
template bool util::debug::valid (const extent<2,uint16_t>&);
|
template bool util::debug::is_valid (const extent<2,uint16_t>&);
|
||||||
template bool util::debug::valid (const extent<2,uint32_t>&);
|
template bool util::debug::is_valid (const extent<2,uint32_t>&);
|
||||||
template bool util::debug::valid (const extent<2,uint64_t>&);
|
template bool util::debug::is_valid (const extent<2,uint64_t>&);
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
|
@ -34,10 +34,11 @@ namespace util {
|
|||||||
extent () = default;
|
extent () = default;
|
||||||
explicit extent (vector<S,T>);
|
explicit extent (vector<S,T>);
|
||||||
|
|
||||||
T area (void) const;
|
constexpr T area (void) const;
|
||||||
T diameter (void) const;
|
constexpr T diameter (void) const;
|
||||||
|
|
||||||
template <typename U = float>
|
template <typename U = float>
|
||||||
|
constexpr
|
||||||
U aspect (void) const;
|
U aspect (void) const;
|
||||||
|
|
||||||
template <typename U>
|
template <typename U>
|
||||||
|
31
extent.ipp
31
extent.ipp
@ -24,9 +24,40 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
template <size_t S, typename T>
|
||||||
|
constexpr
|
||||||
|
T
|
||||||
|
util::extent<S,T>::diameter (void) const
|
||||||
|
{
|
||||||
|
return static_cast<T> (
|
||||||
|
std::sqrt (
|
||||||
|
std::accumulate (std::begin (this->data),
|
||||||
|
std::end (this->data),
|
||||||
|
T {0},
|
||||||
|
[] (auto a, auto b) { return a + b * b; })
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
template <size_t S, typename T>
|
||||||
|
constexpr
|
||||||
|
T
|
||||||
|
util::extent<S,T>::area (void) const
|
||||||
|
{
|
||||||
|
return std::accumulate (std::begin (this->data),
|
||||||
|
std::end (this->data),
|
||||||
|
T {1},
|
||||||
|
std::multiplies<T> ());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
template <size_t S, typename T>
|
template <size_t S, typename T>
|
||||||
template <typename U>
|
template <typename U>
|
||||||
|
constexpr
|
||||||
U
|
U
|
||||||
util::extent<S,T>::aspect (void) const
|
util::extent<S,T>::aspect (void) const
|
||||||
{
|
{
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
#include "types/bits.hpp"
|
#include "types/bits.hpp"
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <iostream>
|
#include <ostream>
|
||||||
|
|
||||||
namespace util {
|
namespace util {
|
||||||
template <typename T, unsigned I, unsigned E>
|
template <typename T, unsigned I, unsigned E>
|
||||||
|
56
format.cpp
56
format.cpp
@ -17,3 +17,59 @@
|
|||||||
#include "format.hpp"
|
#include "format.hpp"
|
||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
|
|
||||||
|
namespace util { namespace format { namespace detail {
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
std::ostream&
|
||||||
|
operator<< (std::ostream &os, specifier::repr r)
|
||||||
|
{
|
||||||
|
switch (r) {
|
||||||
|
case specifier::repr::FIXED: return os << "FIXED";
|
||||||
|
case specifier::repr::SCIENTIFIC: return os << "SCIENTIFIC";
|
||||||
|
case specifier::repr::AUTO: return os << "AUTO";
|
||||||
|
}
|
||||||
|
|
||||||
|
unreachable ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
std::ostream&
|
||||||
|
operator<< (std::ostream &os, specifier::kind t)
|
||||||
|
{
|
||||||
|
switch (t) {
|
||||||
|
case specifier::kind::UNSIGNED: return os << "UNSIGNED";
|
||||||
|
case specifier::kind::SIGNED: return os << "SIGNED";
|
||||||
|
case specifier::kind::REAL: return os << "REAL";
|
||||||
|
case specifier::kind::STRING: return os << "STRING";
|
||||||
|
case specifier::kind::POINTER: return os << "POINTER";
|
||||||
|
case specifier::kind::CHARACTER: return os << "CHARACTER";
|
||||||
|
case specifier::kind::ESCAPE: return os << "ESCAPE";
|
||||||
|
case specifier::kind::OSTREAM: return os << "OSTREAM";
|
||||||
|
}
|
||||||
|
|
||||||
|
unreachable ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
std::ostream&
|
||||||
|
operator<< (std::ostream &os, const specifier &s)
|
||||||
|
{
|
||||||
|
return os << "specifier {"
|
||||||
|
"alternate_form: " << s.alternate_form << ", "
|
||||||
|
"left_adjusted: " << s.left_adjusted << ", "
|
||||||
|
"thousands_grouping: " << s.thousands_grouping << ", "
|
||||||
|
"padding_char: '" << s.padding_char << "', "
|
||||||
|
"positive_char: '" << s.positive_char << "', "
|
||||||
|
"uppercase: " << s.uppercase << ", "
|
||||||
|
"base: " << s.base << ", "
|
||||||
|
"repr: " << s.r << ", "
|
||||||
|
"kind: " << s.k << ", "
|
||||||
|
"width: " << s.width << ", "
|
||||||
|
"precision: " << s.precision << ", "
|
||||||
|
"length: " << s.length <<
|
||||||
|
" }";
|
||||||
|
}
|
||||||
|
} } }
|
||||||
|
35
format.hpp
35
format.hpp
@ -11,7 +11,7 @@
|
|||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*
|
*
|
||||||
* Copyright 2015-2016 Danny Robson <danny@nerdcruft.net>
|
* Copyright 2016 Danny Robson <danny@nerdcruft.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef __UTIL_FORMAT_HPP
|
#ifndef __UTIL_FORMAT_HPP
|
||||||
@ -20,12 +20,17 @@
|
|||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace util {
|
namespace util { namespace format {
|
||||||
namespace format {
|
//-------------------------------------------------------------------------
|
||||||
template <typename ...Args>
|
// render a format string using the provided values.
|
||||||
|
//
|
||||||
|
// we deliberately only take char[] formats so as to promote the use of
|
||||||
|
// only literal strings as format strings.
|
||||||
|
template <typename ...Args, size_t N>
|
||||||
std::string
|
std::string
|
||||||
render (const std::string &fmt, Args&&...);
|
render (const char (&fmt)[N], const Args&...);
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
class error : public std::runtime_error
|
class error : public std::runtime_error
|
||||||
{ using runtime_error::runtime_error; };
|
{ using runtime_error::runtime_error; };
|
||||||
|
|
||||||
@ -33,12 +38,18 @@ namespace util {
|
|||||||
class value_error : public error
|
class value_error : public error
|
||||||
{ using error::error; };
|
{ using error::error; };
|
||||||
|
|
||||||
|
struct conversion_error : public error
|
||||||
|
{ using error::error; };
|
||||||
|
|
||||||
|
struct length_error : public error
|
||||||
|
{ using error::error; };
|
||||||
|
|
||||||
// malformed format specifier
|
// malformed format specifier
|
||||||
class format_error : public error
|
class syntax_error : public error
|
||||||
{ using error::error; };
|
{ using error::error; };
|
||||||
|
|
||||||
template <typename ValueT>
|
template <typename ValueT>
|
||||||
class invalid_specifier : public format_error {
|
class invalid_specifier : error {
|
||||||
public:
|
public:
|
||||||
using value_type = ValueT;
|
using value_type = ValueT;
|
||||||
|
|
||||||
@ -52,9 +63,13 @@ namespace util {
|
|||||||
|
|
||||||
// missing format specifier
|
// missing format specifier
|
||||||
class missing_error : public error
|
class missing_error : public error
|
||||||
{ using error::error; };
|
{
|
||||||
}
|
public:
|
||||||
}
|
missing_error ():
|
||||||
|
error ("missing argument for specifier")
|
||||||
|
{ ; }
|
||||||
|
};
|
||||||
|
} }
|
||||||
|
|
||||||
#include "format.ipp"
|
#include "format.ipp"
|
||||||
|
|
||||||
|
1085
format.ipp
1085
format.ipp
File diff suppressed because it is too large
Load Diff
@ -16,6 +16,8 @@
|
|||||||
|
|
||||||
|
|
||||||
#include "./aabb.hpp"
|
#include "./aabb.hpp"
|
||||||
|
|
||||||
|
#include "./iostream.hpp"
|
||||||
#include "../debug.hpp"
|
#include "../debug.hpp"
|
||||||
|
|
||||||
using util::geom::AABB;
|
using util::geom::AABB;
|
||||||
@ -207,7 +209,7 @@ AABB<S,T>::operator== (const AABB<S,T> rhs) const
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
namespace util { namespace debug {
|
namespace util { namespace debug {
|
||||||
template <size_t S, typename T>
|
template <size_t S, typename T>
|
||||||
struct validator<AABB,S,T> {
|
struct validator<AABB<S,T>> {
|
||||||
static bool is_valid (const AABB<S,T> &b)
|
static bool is_valid (const AABB<S,T> &b)
|
||||||
{
|
{
|
||||||
for (size_t i = 0; i < S; ++i)
|
for (size_t i = 0; i < S; ++i)
|
||||||
@ -233,7 +235,7 @@ util::geom::operator<< (std::ostream &os, util::geom::AABB<S,T> b)
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
#define INSTANTIATE_S_T(S,T) \
|
#define INSTANTIATE_S_T(S,T) \
|
||||||
namespace util { namespace geom { template struct AABB<S,T>; } } \
|
namespace util { namespace geom { template struct AABB<S,T>; } } \
|
||||||
template bool util::debug::valid (const AABB<S,T>&); \
|
template bool util::debug::is_valid (const AABB<S,T>&); \
|
||||||
template std::ostream& util::geom::operator<< (std::ostream&, AABB<S,T>);
|
template std::ostream& util::geom::operator<< (std::ostream&, AABB<S,T>);
|
||||||
|
|
||||||
#define INSTANTIATE(T) \
|
#define INSTANTIATE(T) \
|
||||||
|
@ -65,9 +65,6 @@ namespace util { namespace geom {
|
|||||||
typedef AABB<3,float> AABB3f;
|
typedef AABB<3,float> AABB3f;
|
||||||
typedef AABB<3,size_t> AABB3u;
|
typedef AABB<3,size_t> AABB3u;
|
||||||
typedef AABB<3,intmax_t> AABB3i;
|
typedef AABB<3,intmax_t> AABB3i;
|
||||||
|
|
||||||
template <size_t S, typename T>
|
|
||||||
std::ostream& operator<< (std::ostream&, AABB<S,T>);
|
|
||||||
} }
|
} }
|
||||||
|
|
||||||
#include "aabb.ipp"
|
#include "aabb.ipp"
|
||||||
|
@ -28,10 +28,10 @@ cylinder<S,T>::includes (util::point<S,T> p_) const
|
|||||||
auto p_0 = p_ - p0;
|
auto p_0 = p_ - p0;
|
||||||
|
|
||||||
auto l = dot (p10, p_0);
|
auto l = dot (p10, p_0);
|
||||||
if (l < 0 || l > p10.magnitude2 ())
|
if (l < 0 || l > norm2 (p10))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
auto d = dot (p10, p10) - l * l * p10.magnitude2 ();
|
auto d = dot (p10, p10) - l * l * norm2 (p10);
|
||||||
if (d > radius * radius)
|
if (d > radius * radius)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -19,9 +19,17 @@
|
|||||||
|
|
||||||
#include "./fwd.hpp"
|
#include "./fwd.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <ostream>
|
||||||
|
|
||||||
namespace util { namespace geom {
|
namespace util { namespace geom {
|
||||||
|
template <size_t S, typename T>
|
||||||
|
std::ostream&
|
||||||
|
operator<< (std::ostream&, AABB<S,T>);
|
||||||
|
|
||||||
|
template <size_t S, typename T>
|
||||||
|
std::ostream&
|
||||||
|
operator<< (std::ostream&, ray<S,T>);
|
||||||
|
|
||||||
template <size_t S, typename T>
|
template <size_t S, typename T>
|
||||||
std::ostream&
|
std::ostream&
|
||||||
operator<< (std::ostream&, sphere<S,T>);
|
operator<< (std::ostream&, sphere<S,T>);
|
||||||
|
@ -29,7 +29,7 @@ plane<S,T>::plane (point<S,T> _p,
|
|||||||
p (_p),
|
p (_p),
|
||||||
n (_n)
|
n (_n)
|
||||||
{
|
{
|
||||||
CHECK_EQ (n.magnitude2 (), T{1});
|
CHECK (is_normalised (n));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
10
geom/ray.cpp
10
geom/ray.cpp
@ -14,9 +14,11 @@
|
|||||||
* Copyright 2015 Danny Robson <danny@nerdcruft.net>
|
* Copyright 2015 Danny Robson <danny@nerdcruft.net>
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "ray.hpp"
|
#include "./ray.hpp"
|
||||||
|
|
||||||
|
#include "./iostream.hpp"
|
||||||
|
#include "./ops.hpp"
|
||||||
|
|
||||||
#include "ops.hpp"
|
|
||||||
#include "../debug.hpp"
|
#include "../debug.hpp"
|
||||||
|
|
||||||
using util::geom::ray;
|
using util::geom::ray;
|
||||||
@ -29,7 +31,7 @@ ray<S,T>::ray (util::point<S,T> _origin,
|
|||||||
origin (_origin),
|
origin (_origin),
|
||||||
direction (_direction)
|
direction (_direction)
|
||||||
{
|
{
|
||||||
CHECK (direction.is_normalised ());
|
CHECK (is_normalised (direction));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -41,7 +43,7 @@ ray<S,T>::make (util::point<S,T> origin,
|
|||||||
{
|
{
|
||||||
return {
|
return {
|
||||||
origin,
|
origin,
|
||||||
(target - origin).normalised ()
|
normalised (target - origin)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
#include "../vector.hpp"
|
#include "../vector.hpp"
|
||||||
#include "../point.hpp"
|
#include "../point.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <ostream>
|
||||||
|
|
||||||
namespace util { namespace geom {
|
namespace util { namespace geom {
|
||||||
template <size_t S, typename T>
|
template <size_t S, typename T>
|
||||||
@ -50,9 +50,6 @@ namespace util { namespace geom {
|
|||||||
vector<S,T> direction;
|
vector<S,T> direction;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <size_t S, typename T>
|
|
||||||
std::ostream& operator<< (std::ostream&, ray<S,T>);
|
|
||||||
|
|
||||||
typedef ray<2,float> ray2f;
|
typedef ray<2,float> ray2f;
|
||||||
typedef ray<3,float> ray3f;
|
typedef ray<3,float> ray3f;
|
||||||
} }
|
} }
|
||||||
|
2
guid.cpp
2
guid.cpp
@ -24,6 +24,8 @@
|
|||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
|
using util::guid;
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
guid::guid (uint32_t _data1,
|
guid::guid (uint32_t _data1,
|
||||||
|
13
guid.hpp
13
guid.hpp
@ -21,7 +21,10 @@
|
|||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <istream>
|
#include <istream>
|
||||||
|
|
||||||
class guid {
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
namespace util {
|
||||||
|
class guid {
|
||||||
public:
|
public:
|
||||||
enum type {
|
enum type {
|
||||||
NCS_BACKWARD, // 0xx: Network Computing System backward compatibility
|
NCS_BACKWARD, // 0xx: Network Computing System backward compatibility
|
||||||
@ -52,9 +55,11 @@ class guid {
|
|||||||
|
|
||||||
bool operator< (const guid&) const;
|
bool operator< (const guid&) const;
|
||||||
bool operator== (const guid&) const;
|
bool operator== (const guid&) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
std::istream& operator>> (std::istream&, guid&);
|
||||||
|
std::ostream& operator<< (std::ostream&, const guid&);
|
||||||
|
}
|
||||||
|
|
||||||
std::istream& operator>> (std::istream&, guid&);
|
|
||||||
std::ostream& operator<< (std::ostream&, const guid&);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -86,7 +86,7 @@ RIPEMD::update (const void *restrict _data, size_t len) noexcept
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (m_length >> sizeof (m_length) * 8 - 3 != 0)
|
if (m_length >> sizeof (m_length) * 8 - 3 != 0)
|
||||||
throw std::length_error ("exceeded maximum message length");
|
panic ("exceeded maximum message length");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
#include <ostream>
|
||||||
|
|
||||||
|
|
||||||
using util::hash::SHA1;
|
using util::hash::SHA1;
|
||||||
@ -36,8 +37,8 @@ std::ostream&
|
|||||||
operator<< (std::ostream &os, SHA1::state_t t)
|
operator<< (std::ostream &os, SHA1::state_t t)
|
||||||
{
|
{
|
||||||
switch (t) {
|
switch (t) {
|
||||||
case SHA1::READY: os << "READY"; return os;
|
case SHA1::READY: return os << "READY";
|
||||||
case SHA1::FINISHED: os << "FINISHED"; return os;
|
case SHA1::FINISHED: return os << "FINISHED";
|
||||||
}
|
}
|
||||||
|
|
||||||
unreachable ();
|
unreachable ();
|
||||||
|
@ -18,21 +18,21 @@
|
|||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
constexpr char util::type_string<bool>::value[];
|
constexpr char util::type_name<bool>::value[];
|
||||||
|
|
||||||
constexpr char util::type_string< int8_t>::value[];
|
constexpr char util::type_name< int8_t>::value[];
|
||||||
constexpr char util::type_string< int16_t>::value[];
|
constexpr char util::type_name< int16_t>::value[];
|
||||||
constexpr char util::type_string< int32_t>::value[];
|
constexpr char util::type_name< int32_t>::value[];
|
||||||
constexpr char util::type_string< int64_t>::value[];
|
constexpr char util::type_name< int64_t>::value[];
|
||||||
|
|
||||||
constexpr char util::type_string< uint8_t>::value[];
|
constexpr char util::type_name< uint8_t>::value[];
|
||||||
constexpr char util::type_string<uint16_t>::value[];
|
constexpr char util::type_name<uint16_t>::value[];
|
||||||
constexpr char util::type_string<uint32_t>::value[];
|
constexpr char util::type_name<uint32_t>::value[];
|
||||||
constexpr char util::type_string<uint64_t>::value[];
|
constexpr char util::type_name<uint64_t>::value[];
|
||||||
|
|
||||||
constexpr char util::type_string<float>::value[];
|
constexpr char util::type_name<float>::value[];
|
||||||
constexpr char util::type_string<double>::value[];
|
constexpr char util::type_name<double>::value[];
|
||||||
|
|
||||||
constexpr char util::type_string<std::string>::value[];
|
constexpr char util::type_name<std::string>::value[];
|
||||||
constexpr char util::type_string<char*>::value[];
|
constexpr char util::type_name<char*>::value[];
|
||||||
constexpr char util::type_string<const char*>::value[];
|
constexpr char util::type_name<const char*>::value[];
|
||||||
|
@ -26,43 +26,39 @@
|
|||||||
#include <tuple>
|
#include <tuple>
|
||||||
|
|
||||||
namespace util {
|
namespace util {
|
||||||
template <
|
template <typename T>
|
||||||
typename T
|
struct type_name;
|
||||||
>
|
|
||||||
struct type_string {
|
|
||||||
// static const std::string value
|
|
||||||
};
|
|
||||||
|
|
||||||
template <> struct type_string<bool> { static constexpr const char value[] = "bool"; };
|
template <> struct type_name<bool> { static constexpr const char value[] = "bool"; };
|
||||||
|
|
||||||
template <> struct type_string<char> { static constexpr const char value[] = "char"; };
|
template <> struct type_name<char> { static constexpr const char value[] = "char"; };
|
||||||
template <> struct type_string<void*> { static constexpr const char value[] = "void*"; };
|
template <> struct type_name<void*> { static constexpr const char value[] = "void*"; };
|
||||||
|
|
||||||
template <> struct type_string< int8_t> { static constexpr const char value[] = "int8"; };
|
template <> struct type_name< int8_t> { static constexpr const char value[] = "int8"; };
|
||||||
template <> struct type_string< int16_t> { static constexpr const char value[] = "int16"; };
|
template <> struct type_name< int16_t> { static constexpr const char value[] = "int16"; };
|
||||||
template <> struct type_string< int32_t> { static constexpr const char value[] = "int32"; };
|
template <> struct type_name< int32_t> { static constexpr const char value[] = "int32"; };
|
||||||
template <> struct type_string< int64_t> { static constexpr const char value[] = "int64"; };
|
template <> struct type_name< int64_t> { static constexpr const char value[] = "int64"; };
|
||||||
|
|
||||||
template <> struct type_string< uint8_t> { static constexpr const char value[] = "uint8"; };
|
template <> struct type_name< uint8_t> { static constexpr const char value[] = "uint8"; };
|
||||||
template <> struct type_string<uint16_t> { static constexpr const char value[] = "uint16"; };
|
template <> struct type_name<uint16_t> { static constexpr const char value[] = "uint16"; };
|
||||||
template <> struct type_string<uint32_t> { static constexpr const char value[] = "uint32"; };
|
template <> struct type_name<uint32_t> { static constexpr const char value[] = "uint32"; };
|
||||||
template <> struct type_string<uint64_t> { static constexpr const char value[] = "uint64"; };
|
template <> struct type_name<uint64_t> { static constexpr const char value[] = "uint64"; };
|
||||||
|
|
||||||
template <> struct type_string<float > { static constexpr const char value[] = "float32"; };
|
template <> struct type_name<float > { static constexpr const char value[] = "float32"; };
|
||||||
template <> struct type_string<double > { static constexpr const char value[] = "float64"; };
|
template <> struct type_name<double > { static constexpr const char value[] = "float64"; };
|
||||||
|
|
||||||
template <> struct type_string<std::string> { static constexpr const char value[] = "string"; };
|
template <> struct type_name<std::string> { static constexpr const char value[] = "string"; };
|
||||||
template <> struct type_string<char*> { static constexpr const char value[] = "cstring"; };
|
template <> struct type_name<char*> { static constexpr const char value[] = "cstring"; };
|
||||||
template <> struct type_string<const char*> { static constexpr const char value[] = "cstring"; };
|
template <> struct type_name<const char*> { static constexpr const char value[] = "cstring"; };
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
constexpr
|
constexpr
|
||||||
const char* type_string_v = type_string<T>::value;
|
const char* type_name_v = type_name<T>::value;
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
const char*
|
const char*
|
||||||
to_string (void)
|
to_string (void)
|
||||||
{ return type_string_v<T>; }
|
{ return type_name_v<T>; }
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
@ -107,7 +103,7 @@ namespace util {
|
|||||||
}; \
|
}; \
|
||||||
\
|
\
|
||||||
template <> \
|
template <> \
|
||||||
struct type_string<::NS::E> { \
|
struct type_name<::NS::E> { \
|
||||||
static constexpr const char ns[] = #NS; \
|
static constexpr const char ns[] = #NS; \
|
||||||
static constexpr const char value[] = #E; \
|
static constexpr const char value[] = #E; \
|
||||||
}; \
|
}; \
|
||||||
@ -134,10 +130,10 @@ namespace util {
|
|||||||
> util::enum_traits<::NS::E>::names; \
|
> util::enum_traits<::NS::E>::names; \
|
||||||
\
|
\
|
||||||
constexpr \
|
constexpr \
|
||||||
const char util::type_string<::NS::E>::ns[]; \
|
const char util::type_name<::NS::E>::ns[]; \
|
||||||
\
|
\
|
||||||
constexpr \
|
constexpr \
|
||||||
const char util::type_string<::NS::E>::value[]; \
|
const char util::type_name<::NS::E>::value[]; \
|
||||||
|
|
||||||
|
|
||||||
///------------------------------------------------------------------------
|
///------------------------------------------------------------------------
|
||||||
|
1
io.cpp
1
io.cpp
@ -135,7 +135,6 @@ util::write (const posix::fd &out,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
int
|
int
|
||||||
indenter::overflow (int ch) {
|
indenter::overflow (int ch) {
|
||||||
|
16
io_posix.cpp
16
io_posix.cpp
@ -27,11 +27,14 @@
|
|||||||
using util::detail::posix::mapped_file;
|
using util::detail::posix::mapped_file;
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////
|
||||||
mapped_file::mapped_file (const char *_path, int fflags, int mflags)
|
mapped_file::mapped_file (const char *path, int fflags, int mflags):
|
||||||
{
|
mapped_file (util::posix::fd (path, fflags), mflags)
|
||||||
try {
|
{ ; }
|
||||||
::util::posix::fd src (_path, fflags);
|
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
mapped_file::mapped_file (const ::util::posix::fd &src, int mflags)
|
||||||
|
{
|
||||||
struct stat meta;
|
struct stat meta;
|
||||||
if (fstat (src, &meta) < 0)
|
if (fstat (src, &meta) < 0)
|
||||||
throw errno_error ();
|
throw errno_error ();
|
||||||
@ -40,11 +43,6 @@ mapped_file::mapped_file (const char *_path, int fflags, int mflags)
|
|||||||
m_data = (uint8_t *)mmap (NULL, m_size, mflags, MAP_SHARED, src, 0);
|
m_data = (uint8_t *)mmap (NULL, m_size, mflags, MAP_SHARED, src, 0);
|
||||||
if (m_data == MAP_FAILED)
|
if (m_data == MAP_FAILED)
|
||||||
throw errno_error ();
|
throw errno_error ();
|
||||||
} catch (const errno_error &e) {
|
|
||||||
// ignore zero length mapping error
|
|
||||||
if (e.code () == EINVAL && m_size == 0)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
#ifndef __UTIL_IO_POSIX_HPP
|
#ifndef __UTIL_IO_POSIX_HPP
|
||||||
#define __UTIL_IO_POSIX_HPP
|
#define __UTIL_IO_POSIX_HPP
|
||||||
|
|
||||||
#include "io.hpp"
|
#include "posix/fd.hpp"
|
||||||
|
|
||||||
#include "view.hpp"
|
#include "view.hpp"
|
||||||
|
|
||||||
@ -31,6 +31,7 @@ namespace util {
|
|||||||
class mapped_file {
|
class mapped_file {
|
||||||
public:
|
public:
|
||||||
mapped_file (const char *path, int fflags = O_RDONLY | O_BINARY, int mflags = PROT_READ);
|
mapped_file (const char *path, int fflags = O_RDONLY | O_BINARY, int mflags = PROT_READ);
|
||||||
|
mapped_file (const util::posix::fd&, int mflags = PROT_READ);
|
||||||
|
|
||||||
mapped_file (const mapped_file&) = delete;
|
mapped_file (const mapped_file&) = delete;
|
||||||
mapped_file& operator= (const mapped_file&) = delete;
|
mapped_file& operator= (const mapped_file&) = delete;
|
||||||
|
60
io_win32.cpp
60
io_win32.cpp
@ -59,39 +59,21 @@ DWORD
|
|||||||
mflags_to_protect (int mflags) {
|
mflags_to_protect (int mflags) {
|
||||||
DWORD res = 0;
|
DWORD res = 0;
|
||||||
|
|
||||||
if (mflags & util::detail::win32::PROT_READ) res |= PAGE_READONLY;
|
if (mflags & PROT_READ) res |= PAGE_READONLY;
|
||||||
if (mflags & util::detail::win32::PROT_WRITE) res |= PAGE_READWRITE;
|
if (mflags & PROT_WRITE) res |= PAGE_READWRITE;
|
||||||
if (mflags & util::detail::win32::PROT_EXEC) res |= PAGE_EXECUTE;
|
if (mflags & PROT_EXEC) res |= PAGE_EXECUTE;
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
mapped_file::mapped_file (const boost::filesystem::path &path,
|
mapped_file::mapped_file (::util::win32::handle &&src,
|
||||||
int fflags,
|
int fflags,
|
||||||
int mflags):
|
int mflags):
|
||||||
|
m_file (std::forward<::util::win32::handle> (src)),
|
||||||
m_data (nullptr, UnmapViewOfFile)
|
m_data (nullptr, UnmapViewOfFile)
|
||||||
{
|
{
|
||||||
// Cache the ASCII path to avoid memory scoping issues.
|
|
||||||
std::string path_str = path.string ();
|
|
||||||
|
|
||||||
// Get hold of the file we're attempting to map. Emulate some level of POXIS mmap.
|
|
||||||
m_file.reset (
|
|
||||||
CreateFile (
|
|
||||||
path_str.c_str (),
|
|
||||||
fflags_to_generic (fflags),
|
|
||||||
fflags == O_RDONLY ? FILE_SHARE_READ : 0,
|
|
||||||
nullptr,
|
|
||||||
OPEN_EXISTING,
|
|
||||||
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
|
|
||||||
nullptr
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
if (m_file == INVALID_HANDLE_VALUE)
|
|
||||||
win32_error::throw_code ();
|
|
||||||
|
|
||||||
// I would rather perform checks on filesize after mapping, but mapping
|
// I would rather perform checks on filesize after mapping, but mapping
|
||||||
// requires a check for empty files before we perform the mapping to
|
// requires a check for empty files before we perform the mapping to
|
||||||
// detect errors it throws in that specific situation.
|
// detect errors it throws in that specific situation.
|
||||||
@ -135,6 +117,38 @@ mapped_file::mapped_file (const boost::filesystem::path &path,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
mapped_file::mapped_file (const boost::filesystem::path &path,
|
||||||
|
int fflags,
|
||||||
|
int mflags):
|
||||||
|
mapped_file (
|
||||||
|
::util::win32::handle (
|
||||||
|
::CreateFile (
|
||||||
|
path.string ().c_str (),
|
||||||
|
fflags_to_generic (fflags),
|
||||||
|
fflags == O_RDONLY ? FILE_SHARE_READ : 0,
|
||||||
|
nullptr,
|
||||||
|
OPEN_EXISTING,
|
||||||
|
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN,
|
||||||
|
nullptr
|
||||||
|
)
|
||||||
|
),
|
||||||
|
fflags,
|
||||||
|
mflags
|
||||||
|
)
|
||||||
|
{ ; }
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
mapped_file::mapped_file (const util::fd &src,
|
||||||
|
int fflags,
|
||||||
|
int mflags):
|
||||||
|
mapped_file (util::win32::handle (reinterpret_cast<HANDLE> (_get_osfhandle (src))),
|
||||||
|
fflags,
|
||||||
|
mflags)
|
||||||
|
{ };
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
size_t
|
size_t
|
||||||
mapped_file::size (void) const
|
mapped_file::size (void) const
|
||||||
|
30
io_win32.hpp
30
io_win32.hpp
@ -17,6 +17,7 @@
|
|||||||
#ifndef __UTIL_IO_WIN32_HPP
|
#ifndef __UTIL_IO_WIN32_HPP
|
||||||
#define __UTIL_IO_WIN32_HPP
|
#define __UTIL_IO_WIN32_HPP
|
||||||
|
|
||||||
|
#include "./io.hpp"
|
||||||
#include "./win32/handle.hpp"
|
#include "./win32/handle.hpp"
|
||||||
#include "./view.hpp"
|
#include "./view.hpp"
|
||||||
|
|
||||||
@ -27,20 +28,41 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
namespace util {
|
|
||||||
namespace detail { namespace win32 {
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
enum {
|
// compatibility definitions
|
||||||
|
enum : int {
|
||||||
PROT_NONE = 0,
|
PROT_NONE = 0,
|
||||||
PROT_READ = 1 << 0,
|
PROT_READ = 1 << 0,
|
||||||
PROT_EXEC = 1 << 1,
|
PROT_EXEC = 1 << 1,
|
||||||
PROT_WRITE = 1 << 2
|
PROT_WRITE = 1 << 2
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
enum : int {
|
||||||
|
MAP_SHARED,
|
||||||
|
MAP_PRIVATE,
|
||||||
|
|
||||||
|
MAP_ANONYMOUS
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// implementation definitions
|
||||||
|
namespace util {
|
||||||
|
namespace detail { namespace win32 {
|
||||||
class mapped_file {
|
class mapped_file {
|
||||||
public:
|
public:
|
||||||
|
mapped_file (::util::win32::handle &&,
|
||||||
|
int fflags = O_RDONLY,
|
||||||
|
int mflags = PROT_READ);
|
||||||
mapped_file (const boost::filesystem::path &path,
|
mapped_file (const boost::filesystem::path &path,
|
||||||
int fflags = O_RDONLY,
|
int fflags = O_RDONLY,
|
||||||
int mflags = PROT_READ);
|
int mflags = PROT_READ);
|
||||||
|
mapped_file (const util::fd&,
|
||||||
|
int fflag = O_RDONLY,
|
||||||
|
int mflags = PROT_READ);
|
||||||
|
|
||||||
mapped_file (const mapped_file&) = delete;
|
mapped_file (const mapped_file&) = delete;
|
||||||
mapped_file& operator= (const mapped_file&) = delete;
|
mapped_file& operator= (const mapped_file&) = delete;
|
||||||
|
128
ip.cpp.rl
128
ip.cpp.rl
@ -1,128 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of libgim.
|
|
||||||
*
|
|
||||||
* libgim 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 3 of the License, or (at your option) any later
|
|
||||||
* version.
|
|
||||||
*
|
|
||||||
* libgim is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
||||||
* FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
|
||||||
* details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with libgim. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* Copyright 2011-2016 Danny Robson <danny@nerdcruft.net>
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "ip.hpp"
|
|
||||||
|
|
||||||
#include "cast.hpp"
|
|
||||||
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
const ipv4::ip ipv4::ip::LOOPBACK (127, 0, 0, 1);
|
|
||||||
const ipv4::ip ipv4::ip::ANY ( 0, 0, 0, 0);
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
const util::range<ipv4::port_t> ipv4::WELL_KNOWN_PORT ( 0, 1023),
|
|
||||||
ipv4::REGISTERED_PORT ( 1024, 49151),
|
|
||||||
ipv4::PRIVATE_PORT (49152, 65535);
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
ipv4::ip::ip (uint32_t _integer):
|
|
||||||
m_integer (_integer)
|
|
||||||
{ ; }
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
ipv4::ip::ip (uint8_t a, uint8_t b, uint8_t c, uint8_t d)
|
|
||||||
{
|
|
||||||
m_octets[0] = a;
|
|
||||||
m_octets[1] = b;
|
|
||||||
m_octets[2] = c;
|
|
||||||
m_octets[3] = d;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
bool
|
|
||||||
ipv4::ip::operator== (const ipv4::ip &rhs) const
|
|
||||||
{
|
|
||||||
return m_integer == rhs.m_integer;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
// RFC 3986
|
|
||||||
%%{
|
|
||||||
machine ipv4;
|
|
||||||
octet = ( [0-9][0-9]? |
|
|
||||||
'1'[0-9][0-9] |
|
|
||||||
'2'[0-4][0-9] |
|
|
||||||
'25'[0-5])
|
|
||||||
> {
|
|
||||||
octetstart = fpc;
|
|
||||||
}
|
|
||||||
% {
|
|
||||||
octetend = fpc;
|
|
||||||
__octet = 0;
|
|
||||||
|
|
||||||
for (auto i = octetstart; i < octetend; ++i)
|
|
||||||
__octet = __octet * 10u + sign_cast<unsigned> (*i - '0');
|
|
||||||
};
|
|
||||||
|
|
||||||
ipv4 := (octet %{ __octets[0] = __octet; } '.'
|
|
||||||
octet %{ __octets[1] = __octet; } '.'
|
|
||||||
octet %{ __octets[2] = __octet; } '.'
|
|
||||||
octet %{ __octets[3] = __octet; })
|
|
||||||
> { __success = false; }
|
|
||||||
% { __success = true; }
|
|
||||||
$!{ __success = false; };
|
|
||||||
}%%
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
%%write data;
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
ipv4::ip::ip (const std::string &data)
|
|
||||||
{
|
|
||||||
bool __success = true;
|
|
||||||
uint8_t __octets[4] = { 0, 0, 0, 0 };
|
|
||||||
const char *octetstart = data.data ();
|
|
||||||
const char *octetend = nullptr;
|
|
||||||
uint8_t __octet;
|
|
||||||
|
|
||||||
int cs = 0;
|
|
||||||
const char *p = data.data (),
|
|
||||||
*pe = p + data.size (),
|
|
||||||
*eof = pe;
|
|
||||||
|
|
||||||
%%write init;
|
|
||||||
%%write exec;
|
|
||||||
|
|
||||||
if (!__success)
|
|
||||||
throw ipv4::error ();
|
|
||||||
|
|
||||||
m_octets[0] = __octets[0];
|
|
||||||
m_octets[1] = __octets[1];
|
|
||||||
m_octets[2] = __octets[2];
|
|
||||||
m_octets[3] = __octets[3];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
ipv4::ip
|
|
||||||
ipv4::ip::parse (const std::string &data)
|
|
||||||
{ return ipv4::ip (data); }
|
|
||||||
|
|
79
ip.hpp
79
ip.hpp
@ -1,79 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
* Copyright 2011-2016 Danny Robson <danny@nerdcruft.net>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __UTIL_IP_HPP
|
|
||||||
#define __UTIL_IP_HPP
|
|
||||||
|
|
||||||
#include "range.hpp"
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
|
|
||||||
namespace ipv4 {
|
|
||||||
struct ip {
|
|
||||||
union {
|
|
||||||
uint8_t m_octets[4];
|
|
||||||
uint32_t m_integer;
|
|
||||||
};
|
|
||||||
|
|
||||||
explicit ip (const std::string &);
|
|
||||||
explicit ip (uint32_t i);
|
|
||||||
ip (uint8_t a, uint8_t b, uint8_t c, uint8_t d);
|
|
||||||
|
|
||||||
bool operator== (const ip &) const;
|
|
||||||
|
|
||||||
explicit operator uint32_t (void);
|
|
||||||
|
|
||||||
static ip parse (const std::string &);
|
|
||||||
|
|
||||||
static const ip LOOPBACK;
|
|
||||||
static const ip ANY;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
typedef uint16_t port_t;
|
|
||||||
typedef uint32_t mask_t;
|
|
||||||
|
|
||||||
extern const util::range<port_t> WELL_KNOWN_PORT,
|
|
||||||
REGISTERED_PORT,
|
|
||||||
PRIVATE_PORT;
|
|
||||||
|
|
||||||
class error : public std::exception { };
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
namespace ipv6 {
|
|
||||||
struct ip {
|
|
||||||
uint32_t m_quads[4];
|
|
||||||
|
|
||||||
explicit ip (const std::string&) { ; }
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef uint16_t port_t;
|
|
||||||
|
|
||||||
struct mask_t {
|
|
||||||
uint32_t m_quads[4];
|
|
||||||
|
|
||||||
explicit mask_t (uint32_t) { ; }
|
|
||||||
};
|
|
||||||
|
|
||||||
class error : public std::exception { };
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif // __UTIL_IP_HPP
|
|
@ -25,6 +25,7 @@
|
|||||||
#include "preprocessor.hpp"
|
#include "preprocessor.hpp"
|
||||||
|
|
||||||
#include <deque>
|
#include <deque>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
%%{
|
%%{
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
#define __UTIL_JSON_FLAT_HPP
|
#define __UTIL_JSON_FLAT_HPP
|
||||||
|
|
||||||
#include <boost/filesystem/path.hpp>
|
#include <boost/filesystem/path.hpp>
|
||||||
#include <iostream>
|
#include <ostream>
|
||||||
|
|
||||||
#include "../view.hpp"
|
#include "../view.hpp"
|
||||||
|
|
||||||
|
@ -32,6 +32,7 @@ struct length_error : public json::schema_error {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
struct format_error : public json::schema_error {
|
struct format_error : public json::schema_error {
|
||||||
using schema_error::schema_error;
|
using schema_error::schema_error;
|
||||||
};
|
};
|
||||||
@ -233,15 +234,47 @@ validate_number (T val, const json::tree::object &schema) {
|
|||||||
|
|
||||||
if (exclusiveMax != schema.end () && exclusiveMax->second->as_boolean ()) {
|
if (exclusiveMax != schema.end () && exclusiveMax->second->as_boolean ()) {
|
||||||
switch (cmp.repr ()) {
|
switch (cmp.repr ()) {
|
||||||
case R::REAL: if (val >= T(cmp.real ())) throw json::schema_error ("exclusiveMax"); break;
|
case R::REAL:
|
||||||
case R::SINT: if (val >= T(cmp.uint ())) throw json::schema_error ("exclusiveMax"); break;
|
if (T(val) >= cmp.real ())
|
||||||
case R::UINT: if (val >= T(cmp.sint ())) throw json::schema_error ("exclusiveMax"); break;
|
throw json::schema_error ("exclusiveMax");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case R::SINT:
|
||||||
|
if (json::tree::number::sint_t(std::numeric_limits<T>::max ()) >= cmp.sint () &&
|
||||||
|
val >= T(cmp.sint ()))
|
||||||
|
{
|
||||||
|
throw json::schema_error ("exclusiveMax");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case R::UINT:
|
||||||
|
if (json::tree::number::uint_t(std::numeric_limits<T>::max ()) >= cmp.uint () &&
|
||||||
|
val >= T(cmp.uint ()))
|
||||||
|
{
|
||||||
|
throw json::schema_error ("exclusiveMax");
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
switch (cmp.repr ()) {
|
switch (cmp.repr ()) {
|
||||||
case R::REAL: if (val > T(cmp.real ())) throw json::schema_error ("maximum"); break;
|
case R::REAL:
|
||||||
case R::SINT: if (val > T(cmp.sint ())) throw json::schema_error ("maximum"); break;
|
if (T(val) > cmp.real ())
|
||||||
case R::UINT: if (val > T(cmp.uint ())) throw json::schema_error ("maximum"); break;
|
throw json::schema_error ("maximum");
|
||||||
|
break;
|
||||||
|
case R::SINT:
|
||||||
|
if (json::tree::number::sint_t(std::numeric_limits<T>::max ()) >= cmp.sint () &&
|
||||||
|
val >= T(cmp.sint ()))
|
||||||
|
{
|
||||||
|
throw json::schema_error ("maximum");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case R::UINT:
|
||||||
|
if (json::tree::number::uint_t(std::numeric_limits<T>::max ()) >= cmp.uint () &&
|
||||||
|
val >= T(cmp.uint ()))
|
||||||
|
{
|
||||||
|
throw json::schema_error ("maximum");
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -257,15 +290,47 @@ validate_number (T val, const json::tree::object &schema) {
|
|||||||
|
|
||||||
if (exclusiveMin != schema.end () && exclusiveMin->second->as_boolean ()) {
|
if (exclusiveMin != schema.end () && exclusiveMin->second->as_boolean ()) {
|
||||||
switch (cmp.repr ()) {
|
switch (cmp.repr ()) {
|
||||||
case R::REAL: if (val <= T(cmp.real ())) throw json::schema_error ("exclusiveMin"); break;
|
case R::REAL:
|
||||||
case R::SINT: if (val <= T(cmp.sint ())) throw json::schema_error ("exclusiveMin"); break;
|
if (T(val) < cmp.real ())
|
||||||
case R::UINT: if (val <= T(cmp.uint ())) throw json::schema_error ("exclusiveMin"); break;
|
throw json::schema_error ("exclusiveMin");
|
||||||
|
break;
|
||||||
|
case R::SINT:
|
||||||
|
if (cmp.sint () > json::tree::number::sint_t(std::numeric_limits<T>::min ()) &&
|
||||||
|
val < T(cmp.sint ()))
|
||||||
|
{
|
||||||
|
throw json::schema_error ("exclusiveMin");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case R::UINT:
|
||||||
|
if (cmp.uint () > json::tree::number::uint_t(std::numeric_limits<T>::min ()) &&
|
||||||
|
val < T(cmp.uint ()))
|
||||||
|
{
|
||||||
|
throw json::schema_error ("exclusiveMin");
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
switch (cmp.repr ()) {
|
switch (cmp.repr ()) {
|
||||||
case R::REAL: if (val < T(cmp.real ())) throw json::schema_error ("minimum"); break;
|
case R::REAL:
|
||||||
case R::SINT: if (val < T(cmp.sint ())) throw json::schema_error ("minimum"); break;
|
if (T(val) <= cmp.real ())
|
||||||
case R::UINT: if (val < T(cmp.uint ())) throw json::schema_error ("minimum"); break;
|
throw json::schema_error ("minimum");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case R::SINT:
|
||||||
|
if (cmp.sint () >= json::tree::number::sint_t(std::numeric_limits<T>::min ()) &&
|
||||||
|
val <= T(cmp.sint ()))
|
||||||
|
{
|
||||||
|
throw json::schema_error ("minimum");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case R::UINT:
|
||||||
|
if (cmp.uint () >= json::tree::number::uint_t(std::numeric_limits<T>::min ()) &&
|
||||||
|
val <= T(cmp.uint ()))
|
||||||
|
{
|
||||||
|
throw json::schema_error ("minimum");
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -30,7 +30,6 @@
|
|||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <sstream>
|
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
@ -870,14 +869,26 @@ json::tree::number::operator ==(const json::tree::number &rhs) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
json::tree::number::real_t
|
json::tree::number::real_t
|
||||||
json::tree::number::real (void) const
|
json::tree::number::real (void) const
|
||||||
{
|
{
|
||||||
if (m_repr != REAL)
|
switch (repr ()) {
|
||||||
throw json::type_error ("number is not a real");
|
case REAL:
|
||||||
|
|
||||||
return m_value.r;
|
return m_value.r;
|
||||||
|
|
||||||
|
case UINT:
|
||||||
|
if (uint_t (real_t (m_value.u)) != m_value.u)
|
||||||
|
throw type_error ("number is not a real");
|
||||||
|
return m_value.u;
|
||||||
|
|
||||||
|
case SINT:
|
||||||
|
if (sint_t (real_t (m_value.s)) != m_value.s)
|
||||||
|
throw type_error ("number is not a real");
|
||||||
|
return m_value.s;
|
||||||
|
}
|
||||||
|
|
||||||
|
unreachable ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -885,10 +896,22 @@ json::tree::number::real (void) const
|
|||||||
json::tree::number::sint_t
|
json::tree::number::sint_t
|
||||||
json::tree::number::sint (void) const
|
json::tree::number::sint (void) const
|
||||||
{
|
{
|
||||||
if (m_repr != SINT)
|
switch (repr ()) {
|
||||||
throw json::type_error ("number is not a sint");
|
case SINT:
|
||||||
|
|
||||||
return m_value.s;
|
return m_value.s;
|
||||||
|
|
||||||
|
case REAL:
|
||||||
|
if (!::util::exactly_equal (real_t (sint_t (m_value.r)), m_value.r))
|
||||||
|
throw type_error ("number is not a sint");
|
||||||
|
return sint_t (m_value.r);
|
||||||
|
|
||||||
|
case UINT:
|
||||||
|
if (uint_t (sint_t (m_value.u)) != m_value.u)
|
||||||
|
throw type_error ("number is not a sint");
|
||||||
|
return m_value.s;
|
||||||
|
}
|
||||||
|
|
||||||
|
unreachable ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -896,14 +919,26 @@ json::tree::number::sint (void) const
|
|||||||
json::tree::number::uint_t
|
json::tree::number::uint_t
|
||||||
json::tree::number::uint (void) const
|
json::tree::number::uint (void) const
|
||||||
{
|
{
|
||||||
if (m_repr != UINT)
|
switch (repr ()) {
|
||||||
throw json::type_error ("number is not a uint");
|
case UINT:
|
||||||
|
|
||||||
return m_value.u;
|
return m_value.u;
|
||||||
|
|
||||||
|
case REAL:
|
||||||
|
if (!::util::exactly_equal (real_t (uint_t (m_value.r)), m_value.r))
|
||||||
|
throw type_error ("number is not a uint");
|
||||||
|
return uint_t (m_value.r);
|
||||||
|
|
||||||
|
case SINT:
|
||||||
|
if (sint_t (uint_t (m_value.s)) != m_value.s)
|
||||||
|
throw type_error ("number is not a uint");
|
||||||
|
return m_value.s;
|
||||||
|
}
|
||||||
|
|
||||||
|
unreachable ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
json::tree::number::operator json::tree::number::real_t (void) const
|
json::tree::number::operator json::tree::number::real_t (void) const
|
||||||
{
|
{
|
||||||
return real ();
|
return real ();
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
#include "../iterator.hpp"
|
#include "../iterator.hpp"
|
||||||
#include "../view.hpp"
|
#include "../view.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <ostream>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
6
log.cpp
6
log.cpp
@ -24,12 +24,12 @@
|
|||||||
#include "cast.hpp"
|
#include "cast.hpp"
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
#include <ctime>
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
#include <ctime>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <iostream>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <iomanip>
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
static
|
static
|
||||||
|
6
log.hpp
6
log.hpp
@ -20,7 +20,7 @@
|
|||||||
#include "./nocopy.hpp"
|
#include "./nocopy.hpp"
|
||||||
#include "./preprocessor.hpp"
|
#include "./preprocessor.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <ostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
// Windows.h or one of its friends defines a macro 'ERROR'. Screw Microsoft.
|
// Windows.h or one of its friends defines a macro 'ERROR'. Screw Microsoft.
|
||||||
@ -61,8 +61,8 @@ namespace util {
|
|||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
void log (level_t, const std::string &msg);
|
void log (level_t, const std::string &msg);
|
||||||
|
|
||||||
template <typename ...tail>
|
template <typename ...Args, size_t N>
|
||||||
void log (level_t, const std::string &format, tail&& ..._tail);
|
void log (level_t, const char (&fmt)[N], const Args&...);
|
||||||
|
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
|
6
log.ipp
6
log.ipp
@ -24,11 +24,11 @@
|
|||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
namespace util {
|
namespace util {
|
||||||
template <typename ...tail>
|
template <typename ...Args, size_t N>
|
||||||
void
|
void
|
||||||
log (level_t l, const std::string &format, tail&& ..._tail)
|
log (level_t l, const char (&fmt)[N], const Args& ...args)
|
||||||
{
|
{
|
||||||
log (l, format::render (format, std::forward<tail> (_tail)...));
|
log (l, format::render (fmt, args...));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,67 +0,0 @@
|
|||||||
# ===========================================================================
|
|
||||||
# http://www.gnu.org/software/autoconf-archive/ax_append_compile_flags.html
|
|
||||||
# ===========================================================================
|
|
||||||
#
|
|
||||||
# SYNOPSIS
|
|
||||||
#
|
|
||||||
# AX_APPEND_COMPILE_FLAGS([FLAG1 FLAG2 ...], [FLAGS-VARIABLE], [EXTRA-FLAGS], [INPUT])
|
|
||||||
#
|
|
||||||
# DESCRIPTION
|
|
||||||
#
|
|
||||||
# For every FLAG1, FLAG2 it is checked whether the compiler works with the
|
|
||||||
# flag. If it does, the flag is added FLAGS-VARIABLE
|
|
||||||
#
|
|
||||||
# If FLAGS-VARIABLE is not specified, the current language's flags (e.g.
|
|
||||||
# CFLAGS) is used. During the check the flag is always added to the
|
|
||||||
# current language's flags.
|
|
||||||
#
|
|
||||||
# If EXTRA-FLAGS is defined, it is added to the current language's default
|
|
||||||
# flags (e.g. CFLAGS) when the check is done. The check is thus made with
|
|
||||||
# the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to
|
|
||||||
# force the compiler to issue an error when a bad flag is given.
|
|
||||||
#
|
|
||||||
# INPUT gives an alternative input source to AC_COMPILE_IFELSE.
|
|
||||||
#
|
|
||||||
# NOTE: This macro depends on the AX_APPEND_FLAG and
|
|
||||||
# AX_CHECK_COMPILE_FLAG. Please keep this macro in sync with
|
|
||||||
# AX_APPEND_LINK_FLAGS.
|
|
||||||
#
|
|
||||||
# LICENSE
|
|
||||||
#
|
|
||||||
# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
|
|
||||||
#
|
|
||||||
# This program 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 3 of the License, or (at your
|
|
||||||
# option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful, but
|
|
||||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
|
||||||
# Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License along
|
|
||||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
#
|
|
||||||
# As a special exception, the respective Autoconf Macro's copyright owner
|
|
||||||
# gives unlimited permission to copy, distribute and modify the configure
|
|
||||||
# scripts that are the output of Autoconf when processing the Macro. You
|
|
||||||
# need not follow the terms of the GNU General Public License when using
|
|
||||||
# or distributing such scripts, even though portions of the text of the
|
|
||||||
# Macro appear in them. The GNU General Public License (GPL) does govern
|
|
||||||
# all other use of the material that constitutes the Autoconf Macro.
|
|
||||||
#
|
|
||||||
# This special exception to the GPL applies to versions of the Autoconf
|
|
||||||
# Macro released by the Autoconf Archive. When you make and distribute a
|
|
||||||
# modified version of the Autoconf Macro, you may extend this special
|
|
||||||
# exception to the GPL to apply to your modified version as well.
|
|
||||||
|
|
||||||
#serial 5
|
|
||||||
|
|
||||||
AC_DEFUN([AX_APPEND_COMPILE_FLAGS],
|
|
||||||
[AX_REQUIRE_DEFINED([AX_CHECK_COMPILE_FLAG])
|
|
||||||
AX_REQUIRE_DEFINED([AX_APPEND_FLAG])
|
|
||||||
for flag in $1; do
|
|
||||||
AX_CHECK_COMPILE_FLAG([$flag], [AX_APPEND_FLAG([$flag], [$2])], [], [$3], [$4])
|
|
||||||
done
|
|
||||||
])dnl AX_APPEND_COMPILE_FLAGS
|
|
@ -1,65 +0,0 @@
|
|||||||
# ===========================================================================
|
|
||||||
# http://www.gnu.org/software/autoconf-archive/ax_append_link_flags.html
|
|
||||||
# ===========================================================================
|
|
||||||
#
|
|
||||||
# SYNOPSIS
|
|
||||||
#
|
|
||||||
# AX_APPEND_LINK_FLAGS([FLAG1 FLAG2 ...], [FLAGS-VARIABLE], [EXTRA-FLAGS], [INPUT])
|
|
||||||
#
|
|
||||||
# DESCRIPTION
|
|
||||||
#
|
|
||||||
# For every FLAG1, FLAG2 it is checked whether the linker works with the
|
|
||||||
# flag. If it does, the flag is added FLAGS-VARIABLE
|
|
||||||
#
|
|
||||||
# If FLAGS-VARIABLE is not specified, the linker's flags (LDFLAGS) is
|
|
||||||
# used. During the check the flag is always added to the linker's flags.
|
|
||||||
#
|
|
||||||
# If EXTRA-FLAGS is defined, it is added to the linker's default flags
|
|
||||||
# when the check is done. The check is thus made with the flags: "LDFLAGS
|
|
||||||
# EXTRA-FLAGS FLAG". This can for example be used to force the linker to
|
|
||||||
# issue an error when a bad flag is given.
|
|
||||||
#
|
|
||||||
# INPUT gives an alternative input source to AC_COMPILE_IFELSE.
|
|
||||||
#
|
|
||||||
# NOTE: This macro depends on the AX_APPEND_FLAG and AX_CHECK_LINK_FLAG.
|
|
||||||
# Please keep this macro in sync with AX_APPEND_COMPILE_FLAGS.
|
|
||||||
#
|
|
||||||
# LICENSE
|
|
||||||
#
|
|
||||||
# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
|
|
||||||
#
|
|
||||||
# This program 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 3 of the License, or (at your
|
|
||||||
# option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful, but
|
|
||||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
|
||||||
# Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License along
|
|
||||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
#
|
|
||||||
# As a special exception, the respective Autoconf Macro's copyright owner
|
|
||||||
# gives unlimited permission to copy, distribute and modify the configure
|
|
||||||
# scripts that are the output of Autoconf when processing the Macro. You
|
|
||||||
# need not follow the terms of the GNU General Public License when using
|
|
||||||
# or distributing such scripts, even though portions of the text of the
|
|
||||||
# Macro appear in them. The GNU General Public License (GPL) does govern
|
|
||||||
# all other use of the material that constitutes the Autoconf Macro.
|
|
||||||
#
|
|
||||||
# This special exception to the GPL applies to versions of the Autoconf
|
|
||||||
# Macro released by the Autoconf Archive. When you make and distribute a
|
|
||||||
# modified version of the Autoconf Macro, you may extend this special
|
|
||||||
# exception to the GPL to apply to your modified version as well.
|
|
||||||
|
|
||||||
#serial 5
|
|
||||||
|
|
||||||
AC_DEFUN([AX_APPEND_LINK_FLAGS],
|
|
||||||
[AX_REQUIRE_DEFINED([AX_CHECK_LINK_FLAG])
|
|
||||||
AX_REQUIRE_DEFINED([AX_APPEND_FLAG])
|
|
||||||
for flag in $1; do
|
|
||||||
AX_CHECK_LINK_FLAG([$flag], [AX_APPEND_FLAG([$flag], [m4_default([$2], [LDFLAGS])])], [], [$3], [$4])
|
|
||||||
done
|
|
||||||
])dnl AX_APPEND_LINK_FLAGS
|
|
@ -1,74 +0,0 @@
|
|||||||
# ===========================================================================
|
|
||||||
# http://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html
|
|
||||||
# ===========================================================================
|
|
||||||
#
|
|
||||||
# SYNOPSIS
|
|
||||||
#
|
|
||||||
# AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT])
|
|
||||||
#
|
|
||||||
# DESCRIPTION
|
|
||||||
#
|
|
||||||
# Check whether the given FLAG works with the current language's compiler
|
|
||||||
# or gives an error. (Warnings, however, are ignored)
|
|
||||||
#
|
|
||||||
# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on
|
|
||||||
# success/failure.
|
|
||||||
#
|
|
||||||
# If EXTRA-FLAGS is defined, it is added to the current language's default
|
|
||||||
# flags (e.g. CFLAGS) when the check is done. The check is thus made with
|
|
||||||
# the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to
|
|
||||||
# force the compiler to issue an error when a bad flag is given.
|
|
||||||
#
|
|
||||||
# INPUT gives an alternative input source to AC_COMPILE_IFELSE.
|
|
||||||
#
|
|
||||||
# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this
|
|
||||||
# macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG.
|
|
||||||
#
|
|
||||||
# LICENSE
|
|
||||||
#
|
|
||||||
# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
|
|
||||||
# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
|
|
||||||
#
|
|
||||||
# This program 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 3 of the License, or (at your
|
|
||||||
# option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful, but
|
|
||||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
|
||||||
# Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License along
|
|
||||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
#
|
|
||||||
# As a special exception, the respective Autoconf Macro's copyright owner
|
|
||||||
# gives unlimited permission to copy, distribute and modify the configure
|
|
||||||
# scripts that are the output of Autoconf when processing the Macro. You
|
|
||||||
# need not follow the terms of the GNU General Public License when using
|
|
||||||
# or distributing such scripts, even though portions of the text of the
|
|
||||||
# Macro appear in them. The GNU General Public License (GPL) does govern
|
|
||||||
# all other use of the material that constitutes the Autoconf Macro.
|
|
||||||
#
|
|
||||||
# This special exception to the GPL applies to versions of the Autoconf
|
|
||||||
# Macro released by the Autoconf Archive. When you make and distribute a
|
|
||||||
# modified version of the Autoconf Macro, you may extend this special
|
|
||||||
# exception to the GPL to apply to your modified version as well.
|
|
||||||
|
|
||||||
#serial 4
|
|
||||||
|
|
||||||
AC_DEFUN([AX_CHECK_COMPILE_FLAG],
|
|
||||||
[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF
|
|
||||||
AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl
|
|
||||||
AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [
|
|
||||||
ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS
|
|
||||||
_AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1"
|
|
||||||
AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])],
|
|
||||||
[AS_VAR_SET(CACHEVAR,[yes])],
|
|
||||||
[AS_VAR_SET(CACHEVAR,[no])])
|
|
||||||
_AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags])
|
|
||||||
AS_VAR_IF(CACHEVAR,yes,
|
|
||||||
[m4_default([$2], :)],
|
|
||||||
[m4_default([$3], :)])
|
|
||||||
AS_VAR_POPDEF([CACHEVAR])dnl
|
|
||||||
])dnl AX_CHECK_COMPILE_FLAGS
|
|
@ -1,74 +0,0 @@
|
|||||||
# ===========================================================================
|
|
||||||
# http://www.gnu.org/software/autoconf-archive/ax_check_link_flag.html
|
|
||||||
# ===========================================================================
|
|
||||||
#
|
|
||||||
# SYNOPSIS
|
|
||||||
#
|
|
||||||
# AX_CHECK_LINK_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT])
|
|
||||||
#
|
|
||||||
# DESCRIPTION
|
|
||||||
#
|
|
||||||
# Check whether the given FLAG works with the linker or gives an error.
|
|
||||||
# (Warnings, however, are ignored)
|
|
||||||
#
|
|
||||||
# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on
|
|
||||||
# success/failure.
|
|
||||||
#
|
|
||||||
# If EXTRA-FLAGS is defined, it is added to the linker's default flags
|
|
||||||
# when the check is done. The check is thus made with the flags: "LDFLAGS
|
|
||||||
# EXTRA-FLAGS FLAG". This can for example be used to force the linker to
|
|
||||||
# issue an error when a bad flag is given.
|
|
||||||
#
|
|
||||||
# INPUT gives an alternative input source to AC_LINK_IFELSE.
|
|
||||||
#
|
|
||||||
# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this
|
|
||||||
# macro in sync with AX_CHECK_{PREPROC,COMPILE}_FLAG.
|
|
||||||
#
|
|
||||||
# LICENSE
|
|
||||||
#
|
|
||||||
# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
|
|
||||||
# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
|
|
||||||
#
|
|
||||||
# This program 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 3 of the License, or (at your
|
|
||||||
# option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful, but
|
|
||||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
|
||||||
# Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License along
|
|
||||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
#
|
|
||||||
# As a special exception, the respective Autoconf Macro's copyright owner
|
|
||||||
# gives unlimited permission to copy, distribute and modify the configure
|
|
||||||
# scripts that are the output of Autoconf when processing the Macro. You
|
|
||||||
# need not follow the terms of the GNU General Public License when using
|
|
||||||
# or distributing such scripts, even though portions of the text of the
|
|
||||||
# Macro appear in them. The GNU General Public License (GPL) does govern
|
|
||||||
# all other use of the material that constitutes the Autoconf Macro.
|
|
||||||
#
|
|
||||||
# This special exception to the GPL applies to versions of the Autoconf
|
|
||||||
# Macro released by the Autoconf Archive. When you make and distribute a
|
|
||||||
# modified version of the Autoconf Macro, you may extend this special
|
|
||||||
# exception to the GPL to apply to your modified version as well.
|
|
||||||
|
|
||||||
#serial 4
|
|
||||||
|
|
||||||
AC_DEFUN([AX_CHECK_LINK_FLAG],
|
|
||||||
[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF
|
|
||||||
AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_ldflags_$4_$1])dnl
|
|
||||||
AC_CACHE_CHECK([whether the linker accepts $1], CACHEVAR, [
|
|
||||||
ax_check_save_flags=$LDFLAGS
|
|
||||||
LDFLAGS="$LDFLAGS $4 $1"
|
|
||||||
AC_LINK_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])],
|
|
||||||
[AS_VAR_SET(CACHEVAR,[yes])],
|
|
||||||
[AS_VAR_SET(CACHEVAR,[no])])
|
|
||||||
LDFLAGS=$ax_check_save_flags])
|
|
||||||
AS_VAR_IF(CACHEVAR,yes,
|
|
||||||
[m4_default([$2], :)],
|
|
||||||
[m4_default([$3], :)])
|
|
||||||
AS_VAR_POPDEF([CACHEVAR])dnl
|
|
||||||
])dnl AX_CHECK_LINK_FLAGS
|
|
@ -1,87 +0,0 @@
|
|||||||
# ===========================================================================
|
|
||||||
# http://www.gnu.org/software/autoconf-archive/ax_compiler_vendor.html
|
|
||||||
# ===========================================================================
|
|
||||||
#
|
|
||||||
# SYNOPSIS
|
|
||||||
#
|
|
||||||
# AX_COMPILER_VENDOR
|
|
||||||
#
|
|
||||||
# DESCRIPTION
|
|
||||||
#
|
|
||||||
# Determine the vendor of the C/C++ compiler, e.g., gnu, intel, ibm, sun,
|
|
||||||
# hp, borland, comeau, dec, cray, kai, lcc, metrowerks, sgi, microsoft,
|
|
||||||
# watcom, etc. The vendor is returned in the cache variable
|
|
||||||
# $ax_cv_c_compiler_vendor for C and $ax_cv_cxx_compiler_vendor for C++.
|
|
||||||
#
|
|
||||||
# LICENSE
|
|
||||||
#
|
|
||||||
# Copyright (c) 2008 Steven G. Johnson <stevenj@alum.mit.edu>
|
|
||||||
# Copyright (c) 2008 Matteo Frigo
|
|
||||||
#
|
|
||||||
# This program 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 3 of the License, or (at your
|
|
||||||
# option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful, but
|
|
||||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
|
||||||
# Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License along
|
|
||||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
#
|
|
||||||
# As a special exception, the respective Autoconf Macro's copyright owner
|
|
||||||
# gives unlimited permission to copy, distribute and modify the configure
|
|
||||||
# scripts that are the output of Autoconf when processing the Macro. You
|
|
||||||
# need not follow the terms of the GNU General Public License when using
|
|
||||||
# or distributing such scripts, even though portions of the text of the
|
|
||||||
# Macro appear in them. The GNU General Public License (GPL) does govern
|
|
||||||
# all other use of the material that constitutes the Autoconf Macro.
|
|
||||||
#
|
|
||||||
# This special exception to the GPL applies to versions of the Autoconf
|
|
||||||
# Macro released by the Autoconf Archive. When you make and distribute a
|
|
||||||
# modified version of the Autoconf Macro, you may extend this special
|
|
||||||
# exception to the GPL to apply to your modified version as well.
|
|
||||||
|
|
||||||
#serial 15
|
|
||||||
|
|
||||||
AC_DEFUN([AX_COMPILER_VENDOR],
|
|
||||||
[AC_CACHE_CHECK([for _AC_LANG compiler vendor], ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor,
|
|
||||||
dnl Please add if possible support to ax_compiler_version.m4
|
|
||||||
[# note: don't check for gcc first since some other compilers define __GNUC__
|
|
||||||
vendors="intel: __ICC,__ECC,__INTEL_COMPILER
|
|
||||||
ibm: __xlc__,__xlC__,__IBMC__,__IBMCPP__
|
|
||||||
pathscale: __PATHCC__,__PATHSCALE__
|
|
||||||
clang: __clang__
|
|
||||||
cray: _CRAYC
|
|
||||||
fujitsu: __FUJITSU
|
|
||||||
gnu: __GNUC__
|
|
||||||
sun: __SUNPRO_C,__SUNPRO_CC
|
|
||||||
hp: __HP_cc,__HP_aCC
|
|
||||||
dec: __DECC,__DECCXX,__DECC_VER,__DECCXX_VER
|
|
||||||
borland: __BORLANDC__,__CODEGEARC__,__TURBOC__
|
|
||||||
comeau: __COMO__
|
|
||||||
kai: __KCC
|
|
||||||
lcc: __LCC__
|
|
||||||
sgi: __sgi,sgi
|
|
||||||
microsoft: _MSC_VER
|
|
||||||
metrowerks: __MWERKS__
|
|
||||||
watcom: __WATCOMC__
|
|
||||||
portland: __PGI
|
|
||||||
tcc: __TINYC__
|
|
||||||
unknown: UNKNOWN"
|
|
||||||
for ventest in $vendors; do
|
|
||||||
case $ventest in
|
|
||||||
*:) vendor=$ventest; continue ;;
|
|
||||||
*) vencpp="defined("`echo $ventest | sed 's/,/) || defined(/g'`")" ;;
|
|
||||||
esac
|
|
||||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM(,[
|
|
||||||
#if !($vencpp)
|
|
||||||
thisisanerror;
|
|
||||||
#endif
|
|
||||||
])], [break])
|
|
||||||
done
|
|
||||||
ax_cv_[]_AC_LANG_ABBREV[]_compiler_vendor=`echo $vendor | cut -d: -f1`
|
|
||||||
])
|
|
||||||
])
|
|
485
m4/ax_pthread.m4
485
m4/ax_pthread.m4
@ -1,485 +0,0 @@
|
|||||||
# ===========================================================================
|
|
||||||
# http://www.gnu.org/software/autoconf-archive/ax_pthread.html
|
|
||||||
# ===========================================================================
|
|
||||||
#
|
|
||||||
# SYNOPSIS
|
|
||||||
#
|
|
||||||
# AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
|
|
||||||
#
|
|
||||||
# DESCRIPTION
|
|
||||||
#
|
|
||||||
# This macro figures out how to build C programs using POSIX threads. It
|
|
||||||
# sets the PTHREAD_LIBS output variable to the threads library and linker
|
|
||||||
# flags, and the PTHREAD_CFLAGS output variable to any special C compiler
|
|
||||||
# flags that are needed. (The user can also force certain compiler
|
|
||||||
# flags/libs to be tested by setting these environment variables.)
|
|
||||||
#
|
|
||||||
# Also sets PTHREAD_CC to any special C compiler that is needed for
|
|
||||||
# multi-threaded programs (defaults to the value of CC otherwise). (This
|
|
||||||
# is necessary on AIX to use the special cc_r compiler alias.)
|
|
||||||
#
|
|
||||||
# NOTE: You are assumed to not only compile your program with these flags,
|
|
||||||
# but also to link with them as well. For example, you might link with
|
|
||||||
# $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
|
|
||||||
#
|
|
||||||
# If you are only building threaded programs, you may wish to use these
|
|
||||||
# variables in your default LIBS, CFLAGS, and CC:
|
|
||||||
#
|
|
||||||
# LIBS="$PTHREAD_LIBS $LIBS"
|
|
||||||
# CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
|
||||||
# CC="$PTHREAD_CC"
|
|
||||||
#
|
|
||||||
# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant
|
|
||||||
# has a nonstandard name, this macro defines PTHREAD_CREATE_JOINABLE to
|
|
||||||
# that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
|
|
||||||
#
|
|
||||||
# Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the
|
|
||||||
# PTHREAD_PRIO_INHERIT symbol is defined when compiling with
|
|
||||||
# PTHREAD_CFLAGS.
|
|
||||||
#
|
|
||||||
# ACTION-IF-FOUND is a list of shell commands to run if a threads library
|
|
||||||
# is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it
|
|
||||||
# is not found. If ACTION-IF-FOUND is not specified, the default action
|
|
||||||
# will define HAVE_PTHREAD.
|
|
||||||
#
|
|
||||||
# Please let the authors know if this macro fails on any platform, or if
|
|
||||||
# you have any other suggestions or comments. This macro was based on work
|
|
||||||
# by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help
|
|
||||||
# from M. Frigo), as well as ac_pthread and hb_pthread macros posted by
|
|
||||||
# Alejandro Forero Cuervo to the autoconf macro repository. We are also
|
|
||||||
# grateful for the helpful feedback of numerous users.
|
|
||||||
#
|
|
||||||
# Updated for Autoconf 2.68 by Daniel Richard G.
|
|
||||||
#
|
|
||||||
# LICENSE
|
|
||||||
#
|
|
||||||
# Copyright (c) 2008 Steven G. Johnson <stevenj@alum.mit.edu>
|
|
||||||
# Copyright (c) 2011 Daniel Richard G. <skunk@iSKUNK.ORG>
|
|
||||||
#
|
|
||||||
# This program 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 3 of the License, or (at your
|
|
||||||
# option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful, but
|
|
||||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
|
||||||
# Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU General Public License along
|
|
||||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
#
|
|
||||||
# As a special exception, the respective Autoconf Macro's copyright owner
|
|
||||||
# gives unlimited permission to copy, distribute and modify the configure
|
|
||||||
# scripts that are the output of Autoconf when processing the Macro. You
|
|
||||||
# need not follow the terms of the GNU General Public License when using
|
|
||||||
# or distributing such scripts, even though portions of the text of the
|
|
||||||
# Macro appear in them. The GNU General Public License (GPL) does govern
|
|
||||||
# all other use of the material that constitutes the Autoconf Macro.
|
|
||||||
#
|
|
||||||
# This special exception to the GPL applies to versions of the Autoconf
|
|
||||||
# Macro released by the Autoconf Archive. When you make and distribute a
|
|
||||||
# modified version of the Autoconf Macro, you may extend this special
|
|
||||||
# exception to the GPL to apply to your modified version as well.
|
|
||||||
|
|
||||||
#serial 22
|
|
||||||
|
|
||||||
AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD])
|
|
||||||
AC_DEFUN([AX_PTHREAD], [
|
|
||||||
AC_REQUIRE([AC_CANONICAL_HOST])
|
|
||||||
AC_REQUIRE([AC_PROG_CC])
|
|
||||||
AC_REQUIRE([AC_PROG_SED])
|
|
||||||
AC_LANG_PUSH([C])
|
|
||||||
ax_pthread_ok=no
|
|
||||||
|
|
||||||
# We used to check for pthread.h first, but this fails if pthread.h
|
|
||||||
# requires special compiler flags (e.g. on Tru64 or Sequent).
|
|
||||||
# It gets checked for in the link test anyway.
|
|
||||||
|
|
||||||
# First of all, check if the user has set any of the PTHREAD_LIBS,
|
|
||||||
# etcetera environment variables, and if threads linking works using
|
|
||||||
# them:
|
|
||||||
if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then
|
|
||||||
ax_pthread_save_CC="$CC"
|
|
||||||
ax_pthread_save_CFLAGS="$CFLAGS"
|
|
||||||
ax_pthread_save_LIBS="$LIBS"
|
|
||||||
AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"])
|
|
||||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
|
||||||
LIBS="$PTHREAD_LIBS $LIBS"
|
|
||||||
AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS])
|
|
||||||
AC_LINK_IFELSE([AC_LANG_CALL([], [pthread_join])], [ax_pthread_ok=yes])
|
|
||||||
AC_MSG_RESULT([$ax_pthread_ok])
|
|
||||||
if test "x$ax_pthread_ok" = "xno"; then
|
|
||||||
PTHREAD_LIBS=""
|
|
||||||
PTHREAD_CFLAGS=""
|
|
||||||
fi
|
|
||||||
CC="$ax_pthread_save_CC"
|
|
||||||
CFLAGS="$ax_pthread_save_CFLAGS"
|
|
||||||
LIBS="$ax_pthread_save_LIBS"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# We must check for the threads library under a number of different
|
|
||||||
# names; the ordering is very important because some systems
|
|
||||||
# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
|
|
||||||
# libraries is broken (non-POSIX).
|
|
||||||
|
|
||||||
# Create a list of thread flags to try. Items starting with a "-" are
|
|
||||||
# C compiler flags, and other items are library names, except for "none"
|
|
||||||
# which indicates that we try without any flags at all, and "pthread-config"
|
|
||||||
# which is a program returning the flags for the Pth emulation library.
|
|
||||||
|
|
||||||
ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
|
|
||||||
|
|
||||||
# The ordering *is* (sometimes) important. Some notes on the
|
|
||||||
# individual items follow:
|
|
||||||
|
|
||||||
# pthreads: AIX (must check this before -lpthread)
|
|
||||||
# none: in case threads are in libc; should be tried before -Kthread and
|
|
||||||
# other compiler flags to prevent continual compiler warnings
|
|
||||||
# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
|
|
||||||
# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64
|
|
||||||
# (Note: HP C rejects this with "bad form for `-t' option")
|
|
||||||
# -pthreads: Solaris/gcc (Note: HP C also rejects)
|
|
||||||
# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
|
|
||||||
# doesn't hurt to check since this sometimes defines pthreads and
|
|
||||||
# -D_REENTRANT too), HP C (must be checked before -lpthread, which
|
|
||||||
# is present but should not be used directly; and before -mthreads,
|
|
||||||
# because the compiler interprets this as "-mt" + "-hreads")
|
|
||||||
# -mthreads: Mingw32/gcc, Lynx/gcc
|
|
||||||
# pthread: Linux, etcetera
|
|
||||||
# --thread-safe: KAI C++
|
|
||||||
# pthread-config: use pthread-config program (for GNU Pth library)
|
|
||||||
|
|
||||||
case $host_os in
|
|
||||||
|
|
||||||
freebsd*)
|
|
||||||
|
|
||||||
# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
|
|
||||||
# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
|
|
||||||
|
|
||||||
ax_pthread_flags="-kthread lthread $ax_pthread_flags"
|
|
||||||
;;
|
|
||||||
|
|
||||||
hpux*)
|
|
||||||
|
|
||||||
# From the cc(1) man page: "[-mt] Sets various -D flags to enable
|
|
||||||
# multi-threading and also sets -lpthread."
|
|
||||||
|
|
||||||
ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags"
|
|
||||||
;;
|
|
||||||
|
|
||||||
openedition*)
|
|
||||||
|
|
||||||
# IBM z/OS requires a feature-test macro to be defined in order to
|
|
||||||
# enable POSIX threads at all, so give the user a hint if this is
|
|
||||||
# not set. (We don't define these ourselves, as they can affect
|
|
||||||
# other portions of the system API in unpredictable ways.)
|
|
||||||
|
|
||||||
AC_EGREP_CPP([AX_PTHREAD_ZOS_MISSING],
|
|
||||||
[
|
|
||||||
# if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS)
|
|
||||||
AX_PTHREAD_ZOS_MISSING
|
|
||||||
# endif
|
|
||||||
],
|
|
||||||
[AC_MSG_WARN([IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support.])])
|
|
||||||
;;
|
|
||||||
|
|
||||||
solaris*)
|
|
||||||
|
|
||||||
# On Solaris (at least, for some versions), libc contains stubbed
|
|
||||||
# (non-functional) versions of the pthreads routines, so link-based
|
|
||||||
# tests will erroneously succeed. (N.B.: The stubs are missing
|
|
||||||
# pthread_cleanup_push, or rather a function called by this macro,
|
|
||||||
# so we could check for that, but who knows whether they'll stub
|
|
||||||
# that too in a future libc.) So we'll check first for the
|
|
||||||
# standard Solaris way of linking pthreads (-mt -lpthread).
|
|
||||||
|
|
||||||
ax_pthread_flags="-mt,pthread pthread $ax_pthread_flags"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC)
|
|
||||||
|
|
||||||
AS_IF([test "x$GCC" = "xyes"],
|
|
||||||
[ax_pthread_flags="-pthread -pthreads $ax_pthread_flags"])
|
|
||||||
|
|
||||||
# The presence of a feature test macro requesting re-entrant function
|
|
||||||
# definitions is, on some systems, a strong hint that pthreads support is
|
|
||||||
# correctly enabled
|
|
||||||
|
|
||||||
case $host_os in
|
|
||||||
darwin* | hpux* | linux* | osf* | solaris*)
|
|
||||||
ax_pthread_check_macro="_REENTRANT"
|
|
||||||
;;
|
|
||||||
|
|
||||||
aix* | freebsd*)
|
|
||||||
ax_pthread_check_macro="_THREAD_SAFE"
|
|
||||||
;;
|
|
||||||
|
|
||||||
*)
|
|
||||||
ax_pthread_check_macro="--"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
AS_IF([test "x$ax_pthread_check_macro" = "x--"],
|
|
||||||
[ax_pthread_check_cond=0],
|
|
||||||
[ax_pthread_check_cond="!defined($ax_pthread_check_macro)"])
|
|
||||||
|
|
||||||
# Are we compiling with Clang?
|
|
||||||
|
|
||||||
AC_CACHE_CHECK([whether $CC is Clang],
|
|
||||||
[ax_cv_PTHREAD_CLANG],
|
|
||||||
[ax_cv_PTHREAD_CLANG=no
|
|
||||||
# Note that Autoconf sets GCC=yes for Clang as well as GCC
|
|
||||||
if test "x$GCC" = "xyes"; then
|
|
||||||
AC_EGREP_CPP([AX_PTHREAD_CC_IS_CLANG],
|
|
||||||
[/* Note: Clang 2.7 lacks __clang_[a-z]+__ */
|
|
||||||
# if defined(__clang__) && defined(__llvm__)
|
|
||||||
AX_PTHREAD_CC_IS_CLANG
|
|
||||||
# endif
|
|
||||||
],
|
|
||||||
[ax_cv_PTHREAD_CLANG=yes])
|
|
||||||
fi
|
|
||||||
])
|
|
||||||
ax_pthread_clang="$ax_cv_PTHREAD_CLANG"
|
|
||||||
|
|
||||||
ax_pthread_clang_warning=no
|
|
||||||
|
|
||||||
# Clang needs special handling, because older versions handle the -pthread
|
|
||||||
# option in a rather... idiosyncratic way
|
|
||||||
|
|
||||||
if test "x$ax_pthread_clang" = "xyes"; then
|
|
||||||
|
|
||||||
# Clang takes -pthread; it has never supported any other flag
|
|
||||||
|
|
||||||
# (Note 1: This will need to be revisited if a system that Clang
|
|
||||||
# supports has POSIX threads in a separate library. This tends not
|
|
||||||
# to be the way of modern systems, but it's conceivable.)
|
|
||||||
|
|
||||||
# (Note 2: On some systems, notably Darwin, -pthread is not needed
|
|
||||||
# to get POSIX threads support; the API is always present and
|
|
||||||
# active. We could reasonably leave PTHREAD_CFLAGS empty. But
|
|
||||||
# -pthread does define _REENTRANT, and while the Darwin headers
|
|
||||||
# ignore this macro, third-party headers might not.)
|
|
||||||
|
|
||||||
PTHREAD_CFLAGS="-pthread"
|
|
||||||
PTHREAD_LIBS=
|
|
||||||
|
|
||||||
ax_pthread_ok=yes
|
|
||||||
|
|
||||||
# However, older versions of Clang make a point of warning the user
|
|
||||||
# that, in an invocation where only linking and no compilation is
|
|
||||||
# taking place, the -pthread option has no effect ("argument unused
|
|
||||||
# during compilation"). They expect -pthread to be passed in only
|
|
||||||
# when source code is being compiled.
|
|
||||||
#
|
|
||||||
# Problem is, this is at odds with the way Automake and most other
|
|
||||||
# C build frameworks function, which is that the same flags used in
|
|
||||||
# compilation (CFLAGS) are also used in linking. Many systems
|
|
||||||
# supported by AX_PTHREAD require exactly this for POSIX threads
|
|
||||||
# support, and in fact it is often not straightforward to specify a
|
|
||||||
# flag that is used only in the compilation phase and not in
|
|
||||||
# linking. Such a scenario is extremely rare in practice.
|
|
||||||
#
|
|
||||||
# Even though use of the -pthread flag in linking would only print
|
|
||||||
# a warning, this can be a nuisance for well-run software projects
|
|
||||||
# that build with -Werror. So if the active version of Clang has
|
|
||||||
# this misfeature, we search for an option to squash it.
|
|
||||||
|
|
||||||
AC_CACHE_CHECK([whether Clang needs flag to prevent "argument unused" warning when linking with -pthread],
|
|
||||||
[ax_cv_PTHREAD_CLANG_NO_WARN_FLAG],
|
|
||||||
[ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown
|
|
||||||
# Create an alternate version of $ac_link that compiles and
|
|
||||||
# links in two steps (.c -> .o, .o -> exe) instead of one
|
|
||||||
# (.c -> exe), because the warning occurs only in the second
|
|
||||||
# step
|
|
||||||
ax_pthread_save_ac_link="$ac_link"
|
|
||||||
ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g'
|
|
||||||
ax_pthread_link_step=`$as_echo "$ac_link" | sed "$ax_pthread_sed"`
|
|
||||||
ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)"
|
|
||||||
ax_pthread_save_CFLAGS="$CFLAGS"
|
|
||||||
for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do
|
|
||||||
AS_IF([test "x$ax_pthread_try" = "xunknown"], [break])
|
|
||||||
CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS"
|
|
||||||
ac_link="$ax_pthread_save_ac_link"
|
|
||||||
AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])],
|
|
||||||
[ac_link="$ax_pthread_2step_ac_link"
|
|
||||||
AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])],
|
|
||||||
[break])
|
|
||||||
])
|
|
||||||
done
|
|
||||||
ac_link="$ax_pthread_save_ac_link"
|
|
||||||
CFLAGS="$ax_pthread_save_CFLAGS"
|
|
||||||
AS_IF([test "x$ax_pthread_try" = "x"], [ax_pthread_try=no])
|
|
||||||
ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try"
|
|
||||||
])
|
|
||||||
|
|
||||||
case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in
|
|
||||||
no | unknown) ;;
|
|
||||||
*) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
fi # $ax_pthread_clang = yes
|
|
||||||
|
|
||||||
if test "x$ax_pthread_ok" = "xno"; then
|
|
||||||
for ax_pthread_try_flag in $ax_pthread_flags; do
|
|
||||||
|
|
||||||
case $ax_pthread_try_flag in
|
|
||||||
none)
|
|
||||||
AC_MSG_CHECKING([whether pthreads work without any flags])
|
|
||||||
;;
|
|
||||||
|
|
||||||
-mt,pthread)
|
|
||||||
AC_MSG_CHECKING([whether pthreads work with -mt -lpthread])
|
|
||||||
PTHREAD_CFLAGS="-mt"
|
|
||||||
PTHREAD_LIBS="-lpthread"
|
|
||||||
;;
|
|
||||||
|
|
||||||
-*)
|
|
||||||
AC_MSG_CHECKING([whether pthreads work with $ax_pthread_try_flag])
|
|
||||||
PTHREAD_CFLAGS="$ax_pthread_try_flag"
|
|
||||||
;;
|
|
||||||
|
|
||||||
pthread-config)
|
|
||||||
AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no])
|
|
||||||
AS_IF([test "x$ax_pthread_config" = "xno"], [continue])
|
|
||||||
PTHREAD_CFLAGS="`pthread-config --cflags`"
|
|
||||||
PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
|
|
||||||
;;
|
|
||||||
|
|
||||||
*)
|
|
||||||
AC_MSG_CHECKING([for the pthreads library -l$ax_pthread_try_flag])
|
|
||||||
PTHREAD_LIBS="-l$ax_pthread_try_flag"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
ax_pthread_save_CFLAGS="$CFLAGS"
|
|
||||||
ax_pthread_save_LIBS="$LIBS"
|
|
||||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
|
||||||
LIBS="$PTHREAD_LIBS $LIBS"
|
|
||||||
|
|
||||||
# Check for various functions. We must include pthread.h,
|
|
||||||
# since some functions may be macros. (On the Sequent, we
|
|
||||||
# need a special flag -Kthread to make this header compile.)
|
|
||||||
# We check for pthread_join because it is in -lpthread on IRIX
|
|
||||||
# while pthread_create is in libc. We check for pthread_attr_init
|
|
||||||
# due to DEC craziness with -lpthreads. We check for
|
|
||||||
# pthread_cleanup_push because it is one of the few pthread
|
|
||||||
# functions on Solaris that doesn't have a non-functional libc stub.
|
|
||||||
# We try pthread_create on general principles.
|
|
||||||
|
|
||||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>
|
|
||||||
# if $ax_pthread_check_cond
|
|
||||||
# error "$ax_pthread_check_macro must be defined"
|
|
||||||
# endif
|
|
||||||
static void routine(void *a) { a = 0; }
|
|
||||||
static void *start_routine(void *a) { return a; }],
|
|
||||||
[pthread_t th; pthread_attr_t attr;
|
|
||||||
pthread_create(&th, 0, start_routine, 0);
|
|
||||||
pthread_join(th, 0);
|
|
||||||
pthread_attr_init(&attr);
|
|
||||||
pthread_cleanup_push(routine, 0);
|
|
||||||
pthread_cleanup_pop(0) /* ; */])],
|
|
||||||
[ax_pthread_ok=yes],
|
|
||||||
[])
|
|
||||||
|
|
||||||
CFLAGS="$ax_pthread_save_CFLAGS"
|
|
||||||
LIBS="$ax_pthread_save_LIBS"
|
|
||||||
|
|
||||||
AC_MSG_RESULT([$ax_pthread_ok])
|
|
||||||
AS_IF([test "x$ax_pthread_ok" = "xyes"], [break])
|
|
||||||
|
|
||||||
PTHREAD_LIBS=""
|
|
||||||
PTHREAD_CFLAGS=""
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Various other checks:
|
|
||||||
if test "x$ax_pthread_ok" = "xyes"; then
|
|
||||||
ax_pthread_save_CFLAGS="$CFLAGS"
|
|
||||||
ax_pthread_save_LIBS="$LIBS"
|
|
||||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
|
||||||
LIBS="$PTHREAD_LIBS $LIBS"
|
|
||||||
|
|
||||||
# Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
|
|
||||||
AC_CACHE_CHECK([for joinable pthread attribute],
|
|
||||||
[ax_cv_PTHREAD_JOINABLE_ATTR],
|
|
||||||
[ax_cv_PTHREAD_JOINABLE_ATTR=unknown
|
|
||||||
for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
|
|
||||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>],
|
|
||||||
[int attr = $ax_pthread_attr; return attr /* ; */])],
|
|
||||||
[ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break],
|
|
||||||
[])
|
|
||||||
done
|
|
||||||
])
|
|
||||||
AS_IF([test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \
|
|
||||||
test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \
|
|
||||||
test "x$ax_pthread_joinable_attr_defined" != "xyes"],
|
|
||||||
[AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE],
|
|
||||||
[$ax_cv_PTHREAD_JOINABLE_ATTR],
|
|
||||||
[Define to necessary symbol if this constant
|
|
||||||
uses a non-standard name on your system.])
|
|
||||||
ax_pthread_joinable_attr_defined=yes
|
|
||||||
])
|
|
||||||
|
|
||||||
AC_CACHE_CHECK([whether more special flags are required for pthreads],
|
|
||||||
[ax_cv_PTHREAD_SPECIAL_FLAGS],
|
|
||||||
[ax_cv_PTHREAD_SPECIAL_FLAGS=no
|
|
||||||
case $host_os in
|
|
||||||
solaris*)
|
|
||||||
ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
])
|
|
||||||
AS_IF([test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \
|
|
||||||
test "x$ax_pthread_special_flags_added" != "xyes"],
|
|
||||||
[PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS"
|
|
||||||
ax_pthread_special_flags_added=yes])
|
|
||||||
|
|
||||||
AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT],
|
|
||||||
[ax_cv_PTHREAD_PRIO_INHERIT],
|
|
||||||
[AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <pthread.h>]],
|
|
||||||
[[int i = PTHREAD_PRIO_INHERIT;]])],
|
|
||||||
[ax_cv_PTHREAD_PRIO_INHERIT=yes],
|
|
||||||
[ax_cv_PTHREAD_PRIO_INHERIT=no])
|
|
||||||
])
|
|
||||||
AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \
|
|
||||||
test "x$ax_pthread_prio_inherit_defined" != "xyes"],
|
|
||||||
[AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.])
|
|
||||||
ax_pthread_prio_inherit_defined=yes
|
|
||||||
])
|
|
||||||
|
|
||||||
CFLAGS="$ax_pthread_save_CFLAGS"
|
|
||||||
LIBS="$ax_pthread_save_LIBS"
|
|
||||||
|
|
||||||
# More AIX lossage: compile with *_r variant
|
|
||||||
if test "x$GCC" != "xyes"; then
|
|
||||||
case $host_os in
|
|
||||||
aix*)
|
|
||||||
AS_CASE(["x/$CC"],
|
|
||||||
[x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6],
|
|
||||||
[#handle absolute path differently from PATH based program lookup
|
|
||||||
AS_CASE(["x$CC"],
|
|
||||||
[x/*],
|
|
||||||
[AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])],
|
|
||||||
[AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])])
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
test -n "$PTHREAD_CC" || PTHREAD_CC="$CC"
|
|
||||||
|
|
||||||
AC_SUBST([PTHREAD_LIBS])
|
|
||||||
AC_SUBST([PTHREAD_CFLAGS])
|
|
||||||
AC_SUBST([PTHREAD_CC])
|
|
||||||
|
|
||||||
# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
|
|
||||||
if test "x$ax_pthread_ok" = "xyes"; then
|
|
||||||
ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1])
|
|
||||||
:
|
|
||||||
else
|
|
||||||
ax_pthread_ok=no
|
|
||||||
$2
|
|
||||||
fi
|
|
||||||
AC_LANG_POP
|
|
||||||
])dnl AX_PTHREAD
|
|
@ -1,37 +0,0 @@
|
|||||||
# ===========================================================================
|
|
||||||
# http://www.gnu.org/software/autoconf-archive/ax_require_defined.html
|
|
||||||
# ===========================================================================
|
|
||||||
#
|
|
||||||
# SYNOPSIS
|
|
||||||
#
|
|
||||||
# AX_REQUIRE_DEFINED(MACRO)
|
|
||||||
#
|
|
||||||
# DESCRIPTION
|
|
||||||
#
|
|
||||||
# AX_REQUIRE_DEFINED is a simple helper for making sure other macros have
|
|
||||||
# been defined and thus are available for use. This avoids random issues
|
|
||||||
# where a macro isn't expanded. Instead the configure script emits a
|
|
||||||
# non-fatal:
|
|
||||||
#
|
|
||||||
# ./configure: line 1673: AX_CFLAGS_WARN_ALL: command not found
|
|
||||||
#
|
|
||||||
# It's like AC_REQUIRE except it doesn't expand the required macro.
|
|
||||||
#
|
|
||||||
# Here's an example:
|
|
||||||
#
|
|
||||||
# AX_REQUIRE_DEFINED([AX_CHECK_LINK_FLAG])
|
|
||||||
#
|
|
||||||
# LICENSE
|
|
||||||
#
|
|
||||||
# Copyright (c) 2014 Mike Frysinger <vapier@gentoo.org>
|
|
||||||
#
|
|
||||||
# Copying and distribution of this file, with or without modification, are
|
|
||||||
# permitted in any medium without royalty provided the copyright notice
|
|
||||||
# and this notice are preserved. This file is offered as-is, without any
|
|
||||||
# warranty.
|
|
||||||
|
|
||||||
#serial 1
|
|
||||||
|
|
||||||
AC_DEFUN([AX_REQUIRE_DEFINED], [dnl
|
|
||||||
m4_ifndef([$1], [m4_fatal([macro ]$1[ is not defined; is a m4 file missing?])])
|
|
||||||
])dnl AX_REQUIRE_DEFINED
|
|
2
m4/nc
2
m4/nc
@ -1 +1 @@
|
|||||||
Subproject commit c5615481949aa6aaedd2c5d221ed17d2e05009b0
|
Subproject commit 006f69779160a490786399b1af6a7d1e251cd15c
|
20
maths.cpp
20
maths.cpp
@ -57,26 +57,6 @@ template uint32_t util::log2 (uint32_t);
|
|||||||
template uint64_t util::log2 (uint64_t);
|
template uint64_t util::log2 (uint64_t);
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
namespace util {
|
|
||||||
template <>
|
|
||||||
unsigned
|
|
||||||
digits (const uint32_t &v)
|
|
||||||
{
|
|
||||||
return (v >= 1000000000) ? 10 :
|
|
||||||
(v >= 100000000) ? 9 :
|
|
||||||
(v >= 10000000) ? 8 :
|
|
||||||
(v >= 1000000) ? 7 :
|
|
||||||
(v >= 100000) ? 6 :
|
|
||||||
(v >= 10000) ? 5 :
|
|
||||||
(v >= 1000) ? 4 :
|
|
||||||
(v >= 100) ? 3 :
|
|
||||||
(v >= 10) ? 2 :
|
|
||||||
1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename T>
|
template <typename T>
|
||||||
std::enable_if_t<
|
std::enable_if_t<
|
||||||
|
106
maths.hpp
106
maths.hpp
@ -17,13 +17,18 @@
|
|||||||
#ifndef __MATHS_HPP
|
#ifndef __MATHS_HPP
|
||||||
#define __MATHS_HPP
|
#define __MATHS_HPP
|
||||||
|
|
||||||
#include "./debug.hpp"
|
// DO NOT INCLUDE debug.hpp
|
||||||
|
// it triggers a circular dependency; debug -> format -> maths -> debug
|
||||||
|
// instead, just use cassert
|
||||||
|
|
||||||
#include "./types/traits.hpp"
|
#include "./types/traits.hpp"
|
||||||
#include "./float.hpp"
|
#include "./float.hpp"
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
#include <numeric>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
@ -281,9 +286,40 @@ namespace util {
|
|||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
template <typename T>
|
constexpr
|
||||||
unsigned
|
unsigned
|
||||||
digits (const T& value);
|
digits10 (uint32_t v) noexcept
|
||||||
|
{
|
||||||
|
return (v >= 1000000000) ? 10 :
|
||||||
|
(v >= 100000000) ? 9 :
|
||||||
|
(v >= 10000000) ? 8 :
|
||||||
|
(v >= 1000000) ? 7 :
|
||||||
|
(v >= 100000) ? 6 :
|
||||||
|
(v >= 10000) ? 5 :
|
||||||
|
(v >= 1000) ? 4 :
|
||||||
|
(v >= 100) ? 3 :
|
||||||
|
(v >= 10) ? 2 :
|
||||||
|
1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename ValueT, typename BaseT>
|
||||||
|
constexpr
|
||||||
|
std::enable_if_t<
|
||||||
|
std::is_integral<ValueT>::value && std::is_unsigned<BaseT>::value,
|
||||||
|
unsigned
|
||||||
|
>
|
||||||
|
digits (ValueT value, BaseT base) noexcept
|
||||||
|
{
|
||||||
|
if (value < 0)
|
||||||
|
value *= -1;
|
||||||
|
|
||||||
|
unsigned tally = 1;
|
||||||
|
while (value /= base)
|
||||||
|
++tally;
|
||||||
|
|
||||||
|
return tally;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
///----------------------------------------------------------------------------
|
///----------------------------------------------------------------------------
|
||||||
@ -326,8 +362,8 @@ namespace util {
|
|||||||
constexpr T
|
constexpr T
|
||||||
gcd (T a, T b)
|
gcd (T a, T b)
|
||||||
{
|
{
|
||||||
CHECK_NEZ (a);
|
assert (a);
|
||||||
CHECK_NEZ (b);
|
assert (b);
|
||||||
|
|
||||||
while (a != b) {
|
while (a != b) {
|
||||||
if (a > b)
|
if (a > b)
|
||||||
@ -349,6 +385,32 @@ namespace util {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// Modulus/etc
|
||||||
|
|
||||||
|
// namespaced wrapper for `man 3 fmod`
|
||||||
|
template <typename T>
|
||||||
|
constexpr
|
||||||
|
std::enable_if_t<
|
||||||
|
std::is_floating_point<T>::value, T
|
||||||
|
>
|
||||||
|
mod (T x, T y)
|
||||||
|
{
|
||||||
|
return std::fmod (x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
constexpr
|
||||||
|
std::enable_if_t<
|
||||||
|
std::is_integral<T>::value, T
|
||||||
|
>
|
||||||
|
mod (T x, T y)
|
||||||
|
{
|
||||||
|
return x % y;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// angles, trig
|
// angles, trig
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -434,13 +496,16 @@ namespace util {
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
// kahan summation for long floating point sequences
|
// kahan summation for long floating point sequences
|
||||||
|
|
||||||
template <class InputIt>
|
template <class InputT>
|
||||||
typename std::iterator_traits<InputIt>::value_type
|
std::enable_if_t<
|
||||||
fsum (InputIt first, InputIt last)
|
std::is_floating_point<
|
||||||
|
typename std::iterator_traits<InputT>::value_type
|
||||||
|
>::value,
|
||||||
|
typename std::iterator_traits<InputT>::value_type
|
||||||
|
>
|
||||||
|
sum (InputT first, InputT last)
|
||||||
{
|
{
|
||||||
using T = typename std::iterator_traits<InputIt>::value_type;
|
using T = typename std::iterator_traits<InputT>::value_type;
|
||||||
static_assert (std::is_floating_point<T>::value,
|
|
||||||
"fsum only works for floating point types");
|
|
||||||
|
|
||||||
T sum = 0;
|
T sum = 0;
|
||||||
T c = 0;
|
T c = 0;
|
||||||
@ -456,6 +521,21 @@ namespace util {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
template <class InputT>
|
||||||
|
std::enable_if_t<
|
||||||
|
std::is_integral<
|
||||||
|
typename std::iterator_traits<InputT>::value_type
|
||||||
|
>::value,
|
||||||
|
typename std::iterator_traits<InputT>::value_type
|
||||||
|
>
|
||||||
|
sum (InputT first, InputT last)
|
||||||
|
{
|
||||||
|
using T = typename std::iterator_traits<InputT>::value_type;
|
||||||
|
return std::accumulate (first, last, T{0});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////
|
||||||
/// Variadic minimum
|
/// Variadic minimum
|
||||||
template <typename T>
|
template <typename T>
|
||||||
@ -506,7 +586,7 @@ namespace util {
|
|||||||
constexpr T
|
constexpr T
|
||||||
limit (const T val, const U lo, const V hi)
|
limit (const T val, const U lo, const V hi)
|
||||||
{
|
{
|
||||||
CHECK_LE (lo, hi);
|
assert (lo <= hi);
|
||||||
|
|
||||||
return val > hi ? hi:
|
return val > hi ? hi:
|
||||||
val < lo ? lo:
|
val < lo ? lo:
|
||||||
@ -520,7 +600,7 @@ namespace util {
|
|||||||
T
|
T
|
||||||
smoothstep (T a, T b, T x)
|
smoothstep (T a, T b, T x)
|
||||||
{
|
{
|
||||||
CHECK_LE(a, b);
|
assert (a <= b);
|
||||||
x = limit ((x - a) / (b - a), T{0}, T{1});
|
x = limit ((x - a) / (b - a), T{0}, T{1});
|
||||||
return x * x * (3 - 2 * x);
|
return x * x * (3 - 2 * x);
|
||||||
}
|
}
|
||||||
|
198
matrix.cpp
198
matrix.cpp
@ -16,8 +16,9 @@
|
|||||||
|
|
||||||
#include "matrix.hpp"
|
#include "matrix.hpp"
|
||||||
|
|
||||||
#include "point.hpp"
|
|
||||||
#include "debug.hpp"
|
#include "debug.hpp"
|
||||||
|
#include "iterator.hpp"
|
||||||
|
#include "point.hpp"
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <cmath>
|
#include <cmath>
|
||||||
@ -129,7 +130,22 @@ util::matrix<S,T>::inverse (void) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
template <size_t S, typename T>
|
||||||
|
matrix<S,T>
|
||||||
|
util::transposed (const matrix<S,T> &m)
|
||||||
|
{
|
||||||
|
util::matrix<S,T> res;
|
||||||
|
|
||||||
|
for (size_t y = 0; y < S; ++y)
|
||||||
|
for (size_t x = 0; x < S; ++x)
|
||||||
|
res[y][x] = m[x][y];
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
template <size_t S, typename T>
|
template <size_t S, typename T>
|
||||||
matrix<S,T>
|
matrix<S,T>
|
||||||
matrix<S,T>::operator* (const matrix<S,T> &rhs) const
|
matrix<S,T>::operator* (const matrix<S,T> &rhs) const
|
||||||
@ -186,75 +202,6 @@ matrix<S,T>::operator* (const point<S,T> &rhs) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
template <size_t S, typename T>
|
|
||||||
matrix<S,T>
|
|
||||||
matrix<S,T>::operator* (T f) const
|
|
||||||
{
|
|
||||||
matrix<S,T> out;
|
|
||||||
|
|
||||||
for (size_t i = 0; i < S; ++i)
|
|
||||||
for (size_t j = 0; j < S; ++j)
|
|
||||||
out.values[i][j] = values[i][j] * f;
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
template <size_t S, typename T>
|
|
||||||
matrix<S,T>&
|
|
||||||
matrix<S,T>::operator*= (T f)
|
|
||||||
{
|
|
||||||
for (size_t i = 0; i < S; ++i)
|
|
||||||
for (size_t j = 0; j < S; ++j)
|
|
||||||
values[i][j] *= f;
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
template <size_t S, typename T>
|
|
||||||
util::matrix<S,T>
|
|
||||||
util::matrix<S,T>::operator/ (T t) const
|
|
||||||
{
|
|
||||||
auto out = *this;
|
|
||||||
|
|
||||||
for (auto &i: out.values)
|
|
||||||
for (auto &j: i)
|
|
||||||
j /= t;
|
|
||||||
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
template <size_t S, typename T>
|
|
||||||
matrix<S,T>&
|
|
||||||
matrix<S,T>::operator/= (T s)
|
|
||||||
{
|
|
||||||
for (size_t r = 0; r < rows; ++r)
|
|
||||||
for (size_t c = 0; c < cols; ++c)
|
|
||||||
values[r][c] /= s;
|
|
||||||
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
template <size_t S, typename T>
|
|
||||||
bool
|
|
||||||
matrix<S,T>::operator== (const matrix<S,T> &rhs) const
|
|
||||||
{
|
|
||||||
for (size_t r = 0; r < rows; ++r)
|
|
||||||
for (size_t c = 0; c < cols; ++c)
|
|
||||||
if (!almost_equal (rhs.values[r][c], values[r][c]))
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
template <size_t S, typename T>
|
template <size_t S, typename T>
|
||||||
bool
|
bool
|
||||||
@ -330,35 +277,37 @@ matrix<S,T>::perspective (T fov, T aspect, range<T> Z)
|
|||||||
template <size_t S, typename T>
|
template <size_t S, typename T>
|
||||||
matrix4<T>
|
matrix4<T>
|
||||||
matrix<S,T>::look_at (util::point<3,T> eye,
|
matrix<S,T>::look_at (util::point<3,T> eye,
|
||||||
util::point<3,T> centre,
|
util::point<3,T> target,
|
||||||
util::vector<3,T> up)
|
util::vector<3,T> up)
|
||||||
{
|
{
|
||||||
const auto f = (centre - eye).normalise ();
|
auto forward = normalised (eye.to (target));
|
||||||
const auto s = cross (f, up).normalise ();
|
auto side = normalised (cross (forward, up));
|
||||||
const auto u = cross (s, f);
|
up = cross (side, forward);
|
||||||
|
|
||||||
return { {
|
auto rot = util::matrix4<T> {{
|
||||||
{ s.x, s.y, s.z, -dot (s, eye) },
|
{ side[0], up[0], -forward[0], 0 },
|
||||||
{ u.x, u.y, u.z, -dot (u, eye) },
|
{ side[1], up[1], -forward[1], 0 },
|
||||||
{ -f.x, -f.y, -f.z, dot (f, eye) },
|
{ side[2], up[2], -forward[2], 0 },
|
||||||
{ 0, 0, 0, 1 },
|
{ 0, 0, 0, 1 }
|
||||||
} };
|
}};
|
||||||
|
|
||||||
|
return util::matrix4<T>::translation (-eye.template as<vector> ()) * rot;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
template <size_t S, typename T>
|
template <size_t S, typename T>
|
||||||
matrix4<T>
|
matrix4<T>
|
||||||
matrix<S,T>::translate (util::vector<2,T> v)
|
matrix<S,T>::translation (util::vector<2,T> v)
|
||||||
{
|
{
|
||||||
return translate ({v.x, v.y, 0});
|
return translation ({v.x, v.y, 0});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
template <size_t S, typename T>
|
template <size_t S, typename T>
|
||||||
matrix4<T>
|
matrix4<T>
|
||||||
matrix<S,T>::translate (util::vector<3,T> v)
|
matrix<S,T>::translation (util::vector<3,T> v)
|
||||||
{
|
{
|
||||||
return { {
|
return { {
|
||||||
{ 1.f, 0.f, 0.f, v.x },
|
{ 1.f, 0.f, 0.f, v.x },
|
||||||
@ -394,9 +343,9 @@ matrix<S,T>::scale (util::vector<3,T> v)
|
|||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
template <size_t S, typename T>
|
template <size_t S, typename T>
|
||||||
matrix4<T>
|
matrix4<T>
|
||||||
matrix<S,T>::rotate (T angle, util::vector<3,T> about)
|
matrix<S,T>::rotation (T angle, util::vector<3,T> about)
|
||||||
{
|
{
|
||||||
about.normalise ();
|
CHECK (is_normalised (about));
|
||||||
|
|
||||||
T c = std::cos (angle);
|
T c = std::cos (angle);
|
||||||
T s = std::sin (angle);
|
T s = std::sin (angle);
|
||||||
@ -434,45 +383,64 @@ matrix<S,T>::ZEROES { 0 };
|
|||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
namespace util {
|
template struct util::matrix<2,float>;
|
||||||
template struct matrix<2,float>;
|
template struct util::matrix<2,double>;
|
||||||
template struct matrix<2,double>;
|
|
||||||
|
|
||||||
template struct matrix<3,float>;
|
template struct util::matrix<3,float>;
|
||||||
template struct matrix<3,double>;
|
template struct util::matrix<3,double>;
|
||||||
|
|
||||||
template struct matrix<4,float>;
|
template struct util::matrix<4,float>;
|
||||||
template struct matrix<4,double>;
|
template struct util::matrix<4,double>;
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
// Uses the algorithm from:
|
||||||
|
// "Extracting Euler Angles from a Rotation Matrix" by
|
||||||
|
// Mike Day, Insomniac Games.
|
||||||
|
template <size_t S, typename T>
|
||||||
|
util::vector<3,T>
|
||||||
|
util::to_euler (const matrix<S,T> &m)
|
||||||
|
{
|
||||||
|
static_assert (S == 3 || S == 4, "only defined for 3d affine transforms");
|
||||||
|
|
||||||
|
const auto theta0 = std::atan2 (m[2][1], m[2][2]);
|
||||||
|
|
||||||
|
const auto c1 = std::hypot (m[0][0], m[1][0]);
|
||||||
|
const auto theta1 = std::atan2 (-m[2][0], c1);
|
||||||
|
|
||||||
|
const auto s0 = std::sin(theta0);
|
||||||
|
const auto c0 = std::cos(theta0);
|
||||||
|
const auto theta2 = std::atan2(
|
||||||
|
s0 * m[0][2] - c0 * m[0][1],
|
||||||
|
c0 * m[1][1] - s0 * m[1][2]
|
||||||
|
);
|
||||||
|
|
||||||
|
return { theta0, theta1, theta2 };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
namespace util {
|
template util::vector<3,float> util::to_euler (const matrix<3,float>&);
|
||||||
template <size_t S, typename T>
|
template util::vector<3,float> util::to_euler (const matrix<4,float>&);
|
||||||
std::ostream&
|
|
||||||
operator<< (std::ostream &os, const matrix<S,T> &m)
|
|
||||||
{
|
|
||||||
os << "{ {" << m.values[0][0] << ", "
|
|
||||||
<< m.values[0][1] << ", "
|
|
||||||
<< m.values[0][2] << ", "
|
|
||||||
<< m.values[0][3] << "}, "
|
|
||||||
<< "{" << m.values[1][0] << ", "
|
|
||||||
<< m.values[1][1] << ", "
|
|
||||||
<< m.values[1][2] << ", "
|
|
||||||
<< m.values[1][3] << "}, "
|
|
||||||
<< "{" << m.values[2][0] << ", "
|
|
||||||
<< m.values[2][1] << ", "
|
|
||||||
<< m.values[2][2] << ", "
|
|
||||||
<< m.values[2][3] << "}, "
|
|
||||||
<< "{" << m.values[3][0] << ", "
|
|
||||||
<< m.values[3][1] << ", "
|
|
||||||
<< m.values[3][2] << ", "
|
|
||||||
<< m.values[3][3] << "} }";
|
|
||||||
|
|
||||||
return os;
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
template <size_t S, typename T>
|
||||||
|
std::ostream&
|
||||||
|
util::operator<< (std::ostream &os, const matrix<S,T> &m)
|
||||||
|
{
|
||||||
|
os << "{ ";
|
||||||
|
|
||||||
|
for (size_t i = 0; i < S; ++i) {
|
||||||
|
os << "{ ";
|
||||||
|
std::copy (m[i], m[i]+S, util::infix_iterator<float> (os, ", "));
|
||||||
|
os << ((i == S - 1) ? " }" : " }, ");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return os << " }";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
template std::ostream& util::operator<< (std::ostream&, const matrix<4,float>&);
|
template std::ostream& util::operator<< (std::ostream&, const matrix<4,float>&);
|
||||||
template std::ostream& util::operator<< (std::ostream&, const matrix<4,double>&);
|
template std::ostream& util::operator<< (std::ostream&, const matrix<4,double>&);
|
||||||
|
109
matrix.hpp
109
matrix.hpp
@ -27,12 +27,22 @@ namespace util {
|
|||||||
struct matrix {
|
struct matrix {
|
||||||
T values[S][S];
|
T values[S][S];
|
||||||
|
|
||||||
static const size_t rows = S;
|
static constexpr size_t rows = S;
|
||||||
static const size_t cols = S;
|
static constexpr size_t cols = S;
|
||||||
|
|
||||||
|
// index operators return a pointer into the data array so that
|
||||||
|
// multidimensional array syntax can be used transparently on this
|
||||||
|
// type.
|
||||||
T* operator[] (size_t);
|
T* operator[] (size_t);
|
||||||
const T* operator[] (size_t) const;
|
const T* operator[] (size_t) const;
|
||||||
|
|
||||||
|
const T* begin (void) const;
|
||||||
|
const T* end (void) const;
|
||||||
|
T* begin (void);
|
||||||
|
T* end (void);
|
||||||
|
const T* cbegin (void) const;
|
||||||
|
const T* cend (void) const;
|
||||||
|
|
||||||
matrix& transpose (void);
|
matrix& transpose (void);
|
||||||
matrix transposed (void) const;
|
matrix transposed (void) const;
|
||||||
|
|
||||||
@ -43,21 +53,12 @@ namespace util {
|
|||||||
matrix inverse_affine (void) const;
|
matrix inverse_affine (void) const;
|
||||||
matrix& invert_affine (void);
|
matrix& invert_affine (void);
|
||||||
|
|
||||||
T det (void) const;
|
|
||||||
|
|
||||||
matrix operator* (const matrix&) const;
|
matrix operator* (const matrix&) const;
|
||||||
matrix& operator*=(const matrix&);
|
matrix& operator*=(const matrix&);
|
||||||
|
|
||||||
vector<S,T> operator* (const vector<S,T>&) const;
|
vector<S,T> operator* (const vector<S,T>&) const;
|
||||||
point<S,T> operator* (const point<S,T> &) const;
|
point<S,T> operator* (const point<S,T> &) const;
|
||||||
|
|
||||||
matrix operator* (T) const;
|
|
||||||
matrix& operator*= (T);
|
|
||||||
matrix operator/ (T) const;
|
|
||||||
matrix& operator/= (T);
|
|
||||||
|
|
||||||
bool operator== (const matrix&) const;
|
|
||||||
|
|
||||||
bool is_affine (void) const;
|
bool is_affine (void) const;
|
||||||
|
|
||||||
template <typename U>
|
template <typename U>
|
||||||
@ -67,14 +68,14 @@ namespace util {
|
|||||||
static matrix<4,T> ortho (T left, T right, T bottom, T top, T near, T far);
|
static matrix<4,T> ortho (T left, T right, T bottom, T top, T near, T far);
|
||||||
static matrix<4,T> ortho2D (T left, T right, T bottom, T top);
|
static matrix<4,T> ortho2D (T left, T right, T bottom, T top);
|
||||||
static matrix<4,T> perspective (T fov, T aspect, range<T> Z);
|
static matrix<4,T> perspective (T fov, T aspect, range<T> Z);
|
||||||
static matrix<4,T> look_at (point<3,T> eye, point<3,T> centre, vector<3,T> up);
|
static matrix<4,T> look_at (point<3,T> eye, point<3,T> target, vector<3,T> up);
|
||||||
|
|
||||||
// Affine matrices
|
// Affine matrices
|
||||||
static matrix<4,T> translate (util::vector<2,T>);
|
static matrix<4,T> translation (util::vector<2,T>);
|
||||||
static matrix<4,T> translate (util::vector<3,T>);
|
static matrix<4,T> translation (util::vector<3,T>);
|
||||||
static matrix<4,T> scale (util::vector<3,T>);
|
static matrix<4,T> scale (util::vector<3,T>);
|
||||||
static matrix<4,T> scale (T);
|
static matrix<4,T> scale (T);
|
||||||
static matrix<4,T> rotate (T angle, util::vector<3,T> about);
|
static matrix<4,T> rotation (T angle, util::vector<3,T> about);
|
||||||
|
|
||||||
// Constant matrices
|
// Constant matrices
|
||||||
static const matrix IDENTITY;
|
static const matrix IDENTITY;
|
||||||
@ -82,13 +83,87 @@ namespace util {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// Convert an affine rotation matrix to euler angles.
|
||||||
|
//
|
||||||
|
// Results are undefined if the matrix is not purely a rotation matrix,
|
||||||
|
// or if the dimension is not 3x3 or 4x4.
|
||||||
template <size_t S, typename T>
|
template <size_t S, typename T>
|
||||||
T determinant (const matrix<S,T>&);
|
vector<3,T>
|
||||||
|
to_euler (const matrix<S,T>&);
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// logical operations
|
||||||
|
template <size_t S, typename T>
|
||||||
|
constexpr
|
||||||
|
bool
|
||||||
|
operator== (const matrix<S,T>&, const matrix<S,T>&);
|
||||||
|
|
||||||
|
|
||||||
|
template <size_t S, typename T>
|
||||||
|
constexpr
|
||||||
|
bool
|
||||||
|
operator!= (const matrix<S,T>&, const matrix<S,T>&);
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// element operations
|
||||||
|
template <size_t S, typename T>
|
||||||
|
constexpr
|
||||||
|
matrix<S,T>
|
||||||
|
operator+ (const matrix<S,T>&, const matrix<S,T>&);
|
||||||
|
|
||||||
|
template <size_t S, typename T>
|
||||||
|
constexpr
|
||||||
|
matrix<S,T>
|
||||||
|
operator- (const matrix<S,T>&, const matrix<S,T>&);
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
// scalar operations
|
||||||
|
template <size_t S, typename T> constexpr matrix<S,T> operator* (const matrix<S,T>&, T);
|
||||||
|
template <size_t S, typename T> constexpr matrix<S,T> operator/ (const matrix<S,T>&, T);
|
||||||
|
template <size_t S, typename T> constexpr matrix<S,T> operator+ (const matrix<S,T>&, T);
|
||||||
|
template <size_t S, typename T> constexpr matrix<S,T> operator- (const matrix<S,T>&, T);
|
||||||
|
|
||||||
|
template <size_t S, typename T> constexpr matrix<S,T> operator* (T, const matrix<S,T>&);
|
||||||
|
template <size_t S, typename T> constexpr matrix<S,T> operator/ (T, const matrix<S,T>&);
|
||||||
|
template <size_t S, typename T> constexpr matrix<S,T> operator+ (T, const matrix<S,T>&);
|
||||||
|
template <size_t S, typename T> constexpr matrix<S,T> operator- (T, const matrix<S,T>&);
|
||||||
|
|
||||||
|
template <size_t S, typename T> constexpr matrix<S,T>& operator*= (matrix<S,T>&, T);
|
||||||
|
template <size_t S, typename T> constexpr matrix<S,T>& operator/= (matrix<S,T>&, T);
|
||||||
|
template <size_t S, typename T> constexpr matrix<S,T>& operator+= (matrix<S,T>&, T);
|
||||||
|
template <size_t S, typename T> constexpr matrix<S,T>& operator-= (matrix<S,T>&, T);
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
template <size_t S, typename T>
|
||||||
|
T
|
||||||
|
determinant (const matrix<S,T>&);
|
||||||
|
|
||||||
template <size_t S, typename T>
|
template <size_t S, typename T>
|
||||||
matrix<S,T>
|
matrix<S,T>
|
||||||
inverse (const matrix<S,T>&);
|
inverse (const matrix<S,T>&);
|
||||||
|
|
||||||
|
template <size_t S, typename T>
|
||||||
|
matrix<S,T>
|
||||||
|
transposed (const matrix<S,T>&);
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
template <size_t S, typename T>
|
||||||
|
matrix<S,T>
|
||||||
|
abs (const matrix<S,T>&);
|
||||||
|
|
||||||
|
template <size_t S, typename T>
|
||||||
|
constexpr
|
||||||
|
T
|
||||||
|
sum (const matrix<S,T>&);
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
template <typename T> using matrix3 = matrix<3,T>;
|
template <typename T> using matrix3 = matrix<3,T>;
|
||||||
template <typename T> using matrix4 = matrix<4,T>;
|
template <typename T> using matrix4 = matrix<4,T>;
|
||||||
|
|
||||||
@ -104,6 +179,8 @@ namespace util {
|
|||||||
typedef matrix<4,float> matrix4f;
|
typedef matrix<4,float> matrix4f;
|
||||||
typedef matrix<4,double> matrix4d;
|
typedef matrix<4,double> matrix4d;
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////
|
||||||
template <size_t S, typename T>
|
template <size_t S, typename T>
|
||||||
std::ostream& operator<< (std::ostream&, const matrix<S,T>&);
|
std::ostream& operator<< (std::ostream&, const matrix<S,T>&);
|
||||||
}
|
}
|
||||||
|
232
matrix.ipp
232
matrix.ipp
@ -39,25 +39,59 @@ util::matrix<S,T>::operator[] (size_t idx) const
|
|||||||
return this->values[idx];
|
return this->values[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
//template <size_t S, typename T>
|
//-----------------------------------------------------------------------------
|
||||||
//vector<3,T>
|
template <size_t S, typename T>
|
||||||
//matrix<S,T>::operator* (vector<3,T> v) const
|
const T*
|
||||||
//{
|
util::matrix<S,T>::begin (void) const
|
||||||
// return (
|
{
|
||||||
// *this * v.template homog<S> ()
|
return &(*this)[0][0];
|
||||||
// ).template redim<3> ();
|
}
|
||||||
//}
|
|
||||||
//
|
|
||||||
//
|
//-----------------------------------------------------------------------------
|
||||||
////-----------------------------------------------------------------------------
|
template <size_t S, typename T>
|
||||||
//template <size_t S, typename T>
|
const T*
|
||||||
//point<3,T>
|
util::matrix<S,T>::end (void) const
|
||||||
//matrix<S,T>::operator* (point<3,T> p) const
|
{
|
||||||
//{
|
return &(*this)[S][0];
|
||||||
// return (*this * p.template homog<S> ()).template redim<3> ();
|
}
|
||||||
//}
|
|
||||||
//
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template <size_t S, typename T>
|
||||||
|
const T*
|
||||||
|
util::matrix<S,T>::cbegin (void) const
|
||||||
|
{
|
||||||
|
return begin ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template <size_t S, typename T>
|
||||||
|
const T*
|
||||||
|
util::matrix<S,T>::cend (void) const
|
||||||
|
{
|
||||||
|
return end ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template <size_t S, typename T>
|
||||||
|
T*
|
||||||
|
util::matrix<S,T>::begin (void)
|
||||||
|
{
|
||||||
|
return &(*this)[0][0];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template <size_t S, typename T>
|
||||||
|
T*
|
||||||
|
util::matrix<S,T>::end (void)
|
||||||
|
{
|
||||||
|
return &(*this)[S][0];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
@ -67,56 +101,124 @@ util::matrix<S,U>
|
|||||||
util::matrix<S,T>::cast (void) const
|
util::matrix<S,T>::cast (void) const
|
||||||
{
|
{
|
||||||
util::matrix<S,U> out;
|
util::matrix<S,U> out;
|
||||||
|
std::copy (cbegin (), cend (), std::begin (out));
|
||||||
for (size_t i = 0; i < rows; ++i)
|
|
||||||
for (size_t j = 0; j < cols; ++j)
|
|
||||||
out.values[i][j] = values[i][j];
|
|
||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
//template <size_t S, typename T>
|
#define MATRIX_ELEMENT_OP(OP) \
|
||||||
//T
|
template <size_t S, typename T> \
|
||||||
//util::matrix<S,T>::determinant (void) const
|
constexpr \
|
||||||
//{
|
util::matrix<S,T> \
|
||||||
// return util::determinant (*this);
|
util::operator OP ( \
|
||||||
//}
|
const util::matrix<S,T> &a, \
|
||||||
//
|
const util::matrix<S,T> &b) \
|
||||||
//
|
{ \
|
||||||
////-----------------------------------------------------------------------------
|
util::matrix<S,T> res {}; \
|
||||||
//template <size_t S, typename T>
|
\
|
||||||
//util::matrix<S,T>
|
for (size_t i = 0; i < a.rows; ++i) \
|
||||||
//util::matrix<S,T>::inverse (void) const
|
for (size_t j = 0; j < a.cols; ++j) \
|
||||||
//{
|
res[i][j] = a[i][j] OP b[i][j]; \
|
||||||
// return util::inverse (*this);
|
\
|
||||||
//}
|
return res; \
|
||||||
|
}
|
||||||
|
|
||||||
|
MATRIX_ELEMENT_OP(-)
|
||||||
|
MATRIX_ELEMENT_OP(+)
|
||||||
|
|
||||||
|
#undef MATRIX_ELEMENT_OP
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
//template <size_t S, typename T>
|
#define MATRIX_SCALAR_OP(OP) \
|
||||||
//util::matrix<S,T>
|
template <size_t S, typename T> \
|
||||||
//util::matrix<S,T>::operator/ (T t) const
|
constexpr \
|
||||||
//{
|
util::matrix<S,T> \
|
||||||
// auto out = *this;
|
util::operator OP (const util::matrix<S,T> &m, const T t) \
|
||||||
//
|
{ \
|
||||||
// for (auto &i: out.values)
|
util::matrix<S,T> res {}; \
|
||||||
// for (auto &j: i)
|
\
|
||||||
// j /= t;
|
std::transform ( \
|
||||||
//
|
std::cbegin (m), \
|
||||||
// return out;
|
std::cend (m), \
|
||||||
//}
|
std::begin (res), \
|
||||||
//
|
[&t] (auto x) { return x OP t; } \
|
||||||
//
|
); \
|
||||||
/////////////////////////////////////////////////////////////////////////////////
|
\
|
||||||
//template <size_t S, typename T>
|
return res; \
|
||||||
//bool
|
} \
|
||||||
//util::matrix<S,T>::operator== (const matrix<S,T> &m) const
|
\
|
||||||
//{
|
\
|
||||||
// for (size_t i = 0; i < S; ++i)
|
template <size_t S, typename T> \
|
||||||
// for (size_t j = 0; j < S; ++j)
|
constexpr \
|
||||||
// if (!exactly_equal (values[i][j], m[i][j]))
|
util::matrix<S,T> \
|
||||||
// return false;
|
util::operator OP (const T t, const util::matrix<S,T> &m) \
|
||||||
// return true;
|
{ \
|
||||||
//}
|
return m OP t; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
\
|
||||||
|
template <size_t S, typename T> \
|
||||||
|
constexpr \
|
||||||
|
util::matrix<S,T>& \
|
||||||
|
util::operator OP##= (util::matrix<S,T> &m, T t) \
|
||||||
|
{ \
|
||||||
|
std::transform ( \
|
||||||
|
std::cbegin (m), \
|
||||||
|
std::cend (m), \
|
||||||
|
std::begin (m), \
|
||||||
|
[&t] (auto x) { return x OP t; } \
|
||||||
|
); \
|
||||||
|
\
|
||||||
|
return m; \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
MATRIX_SCALAR_OP(*)
|
||||||
|
MATRIX_SCALAR_OP(/)
|
||||||
|
MATRIX_SCALAR_OP(+)
|
||||||
|
MATRIX_SCALAR_OP(-)
|
||||||
|
|
||||||
|
#undef MATRIX_SCALAR_OP
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
template <size_t S, typename T>
|
||||||
|
constexpr
|
||||||
|
bool
|
||||||
|
util::operator== (const matrix<S,T> &a, const matrix<S,T> &b)
|
||||||
|
{
|
||||||
|
return std::equal (std::cbegin (a), std::cend (a), std::cbegin (b));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template <size_t S, typename T>
|
||||||
|
constexpr
|
||||||
|
bool
|
||||||
|
util::operator!= (const matrix<S,T> &a, const matrix<S,T> &b)
|
||||||
|
{
|
||||||
|
return !(a == b);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
template <size_t S, typename T>
|
||||||
|
util::matrix<S,T>
|
||||||
|
util::abs (const util::matrix<S,T> &src)
|
||||||
|
{
|
||||||
|
util::matrix<S,T> dst;
|
||||||
|
std::transform (std::cbegin (src), std::cend (src), std::begin (dst), util::abs<T>);
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
template <size_t S, typename T>
|
||||||
|
constexpr
|
||||||
|
T
|
||||||
|
util::sum (const util::matrix<S,T> &src)
|
||||||
|
{
|
||||||
|
return sum (std::cbegin (src), std::cend (src));
|
||||||
|
}
|
||||||
|
@ -17,9 +17,10 @@
|
|||||||
#include "./circular.hpp"
|
#include "./circular.hpp"
|
||||||
|
|
||||||
#include "../system.hpp"
|
#include "../system.hpp"
|
||||||
|
#include "../../debug.hpp"
|
||||||
#include "../../except.hpp"
|
#include "../../except.hpp"
|
||||||
#include "../../raii.hpp"
|
|
||||||
#include "../../maths.hpp"
|
#include "../../maths.hpp"
|
||||||
|
#include "../../raii.hpp"
|
||||||
#include "../../random.hpp"
|
#include "../../random.hpp"
|
||||||
|
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
167
net/address.cpp
167
net/address.cpp
@ -1,167 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
* Copyright 2011 Danny Robson <danny@nerdcruft.net>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "address.hpp"
|
|
||||||
|
|
||||||
#include "except.hpp"
|
|
||||||
#include "../debug.hpp"
|
|
||||||
#include "../endian.hpp"
|
|
||||||
#include "../types.hpp"
|
|
||||||
#include "../raii.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef __WIN32
|
|
||||||
#else
|
|
||||||
#include <netdb.h>
|
|
||||||
#include <arpa/inet.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
using net::address;
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
#ifdef __WIN32
|
|
||||||
const char* inet_ntop(int af, const void* src, char* dst, int size){
|
|
||||||
struct sockaddr_in srcaddr;
|
|
||||||
memset(&srcaddr, 0, sizeof(struct sockaddr_in));
|
|
||||||
memcpy(&(srcaddr.sin_addr), src, sizeof(srcaddr.sin_addr));
|
|
||||||
srcaddr.sin_family = af;
|
|
||||||
|
|
||||||
if (WSAAddressToString ((struct sockaddr*) &srcaddr, sizeof (struct sockaddr_in), 0, dst, (LPDWORD) &size) != 0)
|
|
||||||
net::error::throw_code ();
|
|
||||||
|
|
||||||
return dst;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
template <net::domain D>
|
|
||||||
typename address<D>::port_type
|
|
||||||
address<D>::port (void) const
|
|
||||||
{ return m_port; }
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
template <net::domain D>
|
|
||||||
void
|
|
||||||
address<D>::set_port (const port_type &_port)
|
|
||||||
{ m_port = _port; }
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
template <net::domain D>
|
|
||||||
typename address<D>::ip_type
|
|
||||||
address<D>::resolve (const std::string &str) {
|
|
||||||
addrinfo hint;
|
|
||||||
memset (&hint, 0, sizeof (hint));
|
|
||||||
hint.ai_family = static_cast<int> (D);
|
|
||||||
|
|
||||||
addrinfo* resolved;
|
|
||||||
int err = getaddrinfo (str.c_str (), nullptr, nullptr, &resolved);
|
|
||||||
if (err)
|
|
||||||
net::error::throw_code ();
|
|
||||||
|
|
||||||
auto deletor = [] (addrinfo *a) { freeaddrinfo (a); };
|
|
||||||
std::unique_ptr<addrinfo, decltype(deletor)> raii(resolved, deletor);
|
|
||||||
return ip_type (reinterpret_cast<sockaddr_type*> (resolved->ai_addr)->sin_addr.s_addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
namespace net {
|
|
||||||
template <>
|
|
||||||
address<net::domain::INET>::address (const sockaddr_type &addr):
|
|
||||||
m_ip (addr.sin_addr.s_addr),
|
|
||||||
m_mask (0),
|
|
||||||
m_port (ntoh (addr.sin_port))
|
|
||||||
{
|
|
||||||
CHECK (addr.sin_family == (int)net::domain::INET);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <net::domain D>
|
|
||||||
address<D>::address (const std::string &_addr,
|
|
||||||
port_type _port):
|
|
||||||
m_ip (resolve (_addr)),
|
|
||||||
m_mask ( 0),
|
|
||||||
m_port (_port)
|
|
||||||
{ ; }
|
|
||||||
|
|
||||||
|
|
||||||
template <>
|
|
||||||
address<net::domain::INET>::sockaddr_type
|
|
||||||
address<net::domain::INET>::to_sockaddr (void) const {
|
|
||||||
sockaddr_type addr;
|
|
||||||
|
|
||||||
addr.sin_family = (int)net::domain::INET;
|
|
||||||
addr.sin_port = hton (m_port);
|
|
||||||
addr.sin_addr.s_addr = m_ip.m_integer;
|
|
||||||
|
|
||||||
return addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <>
|
|
||||||
std::string
|
|
||||||
address<net::domain::INET>::to_string (void) const {
|
|
||||||
char dest[INET_ADDRSTRLEN + 1];
|
|
||||||
sockaddr_type addr = to_sockaddr ();
|
|
||||||
|
|
||||||
if (NULL == inet_ntop ((int)net::domain::INET, &addr.sin_addr, dest, sizeof (dest)))
|
|
||||||
net::error::throw_code ();
|
|
||||||
return dest;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <>
|
|
||||||
bool
|
|
||||||
address<net::domain::INET>::operator ==(const address<net::domain::INET> &rhs) {
|
|
||||||
return m_ip == rhs.m_ip &&
|
|
||||||
m_mask == rhs.m_mask &&
|
|
||||||
m_port == rhs.m_port;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
std::ostream&
|
|
||||||
net::operator<< (std::ostream &os, const address<net::domain::INET> &addr) {
|
|
||||||
os << addr.to_string () << ":" << addr.port ();
|
|
||||||
return os;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
template <> const address<net::domain::INET>
|
|
||||||
address<net::domain::INET>::LOOPBACK ("127.0.0.1", 0);
|
|
||||||
|
|
||||||
template <> const address<net::domain::INET>
|
|
||||||
address<net::domain::INET>::ANY ("0.0.0.0", 0);
|
|
||||||
|
|
||||||
namespace net {
|
|
||||||
template class address<net::domain::INET>;
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
//template <> const address<net::domain::INET6>
|
|
||||||
//address<net::domain::INET6>::LOOPBACK ("::1", 0);
|
|
||||||
//
|
|
||||||
//template <> const address<net::domain::INET6>
|
|
||||||
//address<net::domain::INET6>::ANY ("::0", 0);
|
|
||||||
//
|
|
||||||
//template class address<net::domain::INET6>;
|
|
||||||
|
|
@ -1,97 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
* Copyright 2011 Danny Robson <danny@nerdcruft.net>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __NET_ADDRESS_HPP
|
|
||||||
#define __NET_ADDRESS_HPP
|
|
||||||
|
|
||||||
#include "types.hpp"
|
|
||||||
#include "../ip.hpp"
|
|
||||||
|
|
||||||
#if defined(HAVE_WINSOCK2_H)
|
|
||||||
#include "ws2tcpip.h"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <iostream>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
namespace net {
|
|
||||||
/// Supporting types used for defining addresses in various domains
|
|
||||||
template <domain D>
|
|
||||||
struct address_types;
|
|
||||||
|
|
||||||
|
|
||||||
template <>
|
|
||||||
struct address_types <domain::INET> {
|
|
||||||
typedef ipv4::ip ip;
|
|
||||||
typedef ipv4::mask_t mask_t;
|
|
||||||
typedef ipv4::port_t port_t;
|
|
||||||
typedef sockaddr_in sockaddr;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
template <>
|
|
||||||
struct address_types <domain::INET6> {
|
|
||||||
typedef ipv6::ip ip;
|
|
||||||
typedef ipv6::mask_t mask_t;
|
|
||||||
typedef ipv6::port_t port_t;
|
|
||||||
typedef sockaddr_in6 sockaddr;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/// A full endpoint specification for a domain. Must be usable for bind/listen and send/recv.
|
|
||||||
template <domain D>
|
|
||||||
class address {
|
|
||||||
public:
|
|
||||||
typedef typename address_types<D>::ip ip_type;
|
|
||||||
typedef typename address_types<D>::mask_t mask_type;
|
|
||||||
typedef typename address_types<D>::port_t port_type;
|
|
||||||
typedef typename address_types<D>::sockaddr sockaddr_type;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
ip_type m_ip;
|
|
||||||
mask_type m_mask;
|
|
||||||
port_type m_port;
|
|
||||||
|
|
||||||
public:
|
|
||||||
static const address<D> LOOPBACK;
|
|
||||||
static const address<D> ANY;
|
|
||||||
|
|
||||||
explicit address (const sockaddr_type &);
|
|
||||||
address (const std::string &address, port_type);
|
|
||||||
|
|
||||||
port_type port (void) const;
|
|
||||||
void set_port (const port_type &);
|
|
||||||
|
|
||||||
ip_type ip (void) const { return m_ip; }
|
|
||||||
|
|
||||||
sockaddr_type to_sockaddr (void) const;
|
|
||||||
std::string to_string (void) const;
|
|
||||||
|
|
||||||
static ip_type resolve (const std::string &);
|
|
||||||
|
|
||||||
bool operator ==(const address<D> &rhs);
|
|
||||||
};
|
|
||||||
|
|
||||||
std::ostream&
|
|
||||||
operator<< (std::ostream &os, const net::address<net::domain::INET> &addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif // __NET_ADDRESS_HPP
|
|
||||||
|
|
122
net/except.cpp
122
net/except.cpp
@ -1,122 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
* Copyright 2011 Danny Robson <danny@nerdcruft.net>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "except.hpp"
|
|
||||||
|
|
||||||
#include "../debug.hpp"
|
|
||||||
#include "../cast.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
using net::error;
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
net::error::error (const std::string &_what):
|
|
||||||
runtime_error (_what)
|
|
||||||
{ ; }
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
net::error::error (int _code):
|
|
||||||
runtime_error (strerror (_code))
|
|
||||||
{ CHECK (_code != 0); }
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
std::string
|
|
||||||
net::error::code_to_string (int code) {
|
|
||||||
#ifdef __WIN32
|
|
||||||
char message[256];
|
|
||||||
|
|
||||||
// It should be fine to signcast the code here as Windows guarantees all
|
|
||||||
// error messages are positive but appears to use int for compatibility
|
|
||||||
DWORD output = FormatMessage (0, NULL, sign_cast<unsigned> (code), 0, message, sizeof (message), NULL);
|
|
||||||
CHECK_NEQ (output, 0);
|
|
||||||
|
|
||||||
return std::string (message);
|
|
||||||
#else
|
|
||||||
return strerror (code);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
void
|
|
||||||
net::error::throw_code (int code) {
|
|
||||||
#ifdef __WIN32
|
|
||||||
throw net::error (code);
|
|
||||||
#else
|
|
||||||
|
|
||||||
CHECK (code != 0);
|
|
||||||
switch (code) {
|
|
||||||
#define ERROR_CODE(c) \
|
|
||||||
case c: \
|
|
||||||
throw net::error_code<c> (); \
|
|
||||||
break;
|
|
||||||
|
|
||||||
ERROR_CODE(ECONNREFUSED);
|
|
||||||
ERROR_CODE(ECONNRESET);
|
|
||||||
ERROR_CODE(EINVAL);
|
|
||||||
ERROR_CODE(ENOTCONN);
|
|
||||||
|
|
||||||
default:
|
|
||||||
unreachable ();
|
|
||||||
#undef ERROR_CODE
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
net::error::throw_code (void)
|
|
||||||
{ throw_code (last_code ()); }
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
void
|
|
||||||
net::error::try_code (int err) {
|
|
||||||
if (__builtin_expect (err != 0, false))
|
|
||||||
throw_code (err);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
net::error::try_code (void)
|
|
||||||
{ try_code (last_code ()); }
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
int
|
|
||||||
net::error::last_code (void) {
|
|
||||||
#ifdef __WIN32
|
|
||||||
return WSAGetLastError ();
|
|
||||||
#else
|
|
||||||
return errno;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
template <int CODE>
|
|
||||||
net::error_code<CODE>::error_code (void):
|
|
||||||
net::error (CODE)
|
|
||||||
{ ; }
|
|
||||||
|
|
||||||
|
|
||||||
template <int CODE>
|
|
||||||
int
|
|
||||||
net::error_code<CODE>::code (void) const
|
|
||||||
{ return CODE; }
|
|
@ -1,74 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
* Copyright 2011 Danny Robson <danny@nerdcruft.net>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __NET_EXCEPT_HPP
|
|
||||||
#define __NET_EXCEPT_HPP
|
|
||||||
|
|
||||||
#if defined(HAVE_WINSOCK2_H)
|
|
||||||
#include <winsock2.h>
|
|
||||||
#else
|
|
||||||
#include <cerrno>
|
|
||||||
#include <cstring>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
namespace net {
|
|
||||||
class error : public std::runtime_error {
|
|
||||||
protected:
|
|
||||||
explicit error (const std::string &);
|
|
||||||
explicit error (int code);
|
|
||||||
|
|
||||||
static std::string
|
|
||||||
code_to_string (int code);
|
|
||||||
|
|
||||||
public:
|
|
||||||
/// Throw an error corresponding the a given code. Code must be a valid error code,
|
|
||||||
/// not success otherwise the application will (at best) abort.
|
|
||||||
static void
|
|
||||||
throw_code [[noreturn]] (int code);
|
|
||||||
|
|
||||||
/// Throw an error corresponding to the most recent error condition. This will check
|
|
||||||
/// the current error condition in a platform agnostic manner, and pass on to
|
|
||||||
/// throw_code(int). This should be used whenever an error has been detected, rather
|
|
||||||
/// than the more normal try_code(errno) due to Windows error reporting quirks.
|
|
||||||
static void
|
|
||||||
throw_code [[noreturn]] (void);
|
|
||||||
|
|
||||||
static void
|
|
||||||
try_code (int code);
|
|
||||||
|
|
||||||
static void
|
|
||||||
try_code (void);
|
|
||||||
|
|
||||||
static int
|
|
||||||
last_code (void);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
template <int CODE>
|
|
||||||
class error_code : public error {
|
|
||||||
public:
|
|
||||||
error_code ();
|
|
||||||
|
|
||||||
int code (void) const;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // __NET_EXCEPT_HPP
|
|
300
net/socket.cpp
300
net/socket.cpp
@ -1,300 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
* Copyright 2011 Danny Robson <danny@nerdcruft.net>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "socket.hpp"
|
|
||||||
|
|
||||||
#include "../debug.hpp"
|
|
||||||
#include "../except.hpp"
|
|
||||||
#include "../cast.hpp"
|
|
||||||
#include "../log.hpp"
|
|
||||||
#include "except.hpp"
|
|
||||||
|
|
||||||
#if defined(HAVE_WINSOCK2_H)
|
|
||||||
#include <winsock2.h>
|
|
||||||
#else
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
using namespace net;
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
template <domain D>
|
|
||||||
socket_domain<D>::socket_domain (socket_t _fd):
|
|
||||||
m_fd (_fd)
|
|
||||||
{
|
|
||||||
#ifdef __WIN32
|
|
||||||
#else
|
|
||||||
CHECK_GE (m_fd, 0);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(HAVE_WINSOCK2_H)
|
|
||||||
// TODO: Make this not retarded. Fucking Windows.
|
|
||||||
#define dup(X) (X)
|
|
||||||
|
|
||||||
// Winsock has incorrect return and parameter types (according to POSIX)
|
|
||||||
// so we need some wrappers around the system implementations that casts
|
|
||||||
// to expected types. Mainly int vs ssize_t returns, and int vs size_t
|
|
||||||
// parameters.
|
|
||||||
static_assert(sizeof(int) <= sizeof(ssize_t), "int != ssize_t");
|
|
||||||
static_assert(sizeof(int) <= sizeof( size_t), "int != size_t");
|
|
||||||
|
|
||||||
ssize_t recv(socket_t _socket, void *_buf, size_t _len, int _flags)
|
|
||||||
{ return (ssize_t)::recv(_socket, (char*)_buf, (int)_len, _flags); }
|
|
||||||
|
|
||||||
ssize_t recvfrom(socket_t _socket, void *_buf, size_t _len, int _flags, struct sockaddr *_sockaddr, socklen_t *_socklen)
|
|
||||||
{ return (ssize_t)::recvfrom(_socket, (char*)_buf, (int)_len, _flags, _sockaddr, (int*)_socklen); }
|
|
||||||
|
|
||||||
ssize_t sendto(socket_t _socket, const void *_buf, size_t _len, int _flags, const struct sockaddr *_sockaddr, socklen_t _socklen)
|
|
||||||
{ return (ssize_t)::sendto(_socket, (const char*)_buf, (int)_len, _flags, _sockaddr, (int)_socklen); }
|
|
||||||
|
|
||||||
ssize_t send(socket_t _socket, const void *_buf, size_t _len, int _flags)
|
|
||||||
{ return (ssize_t)::send(_socket, (const char*)_buf, (int)_len, _flags); }
|
|
||||||
#else
|
|
||||||
#define closesocket(X) close(X)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
template <domain D>
|
|
||||||
socket_domain<D>::socket_domain (const socket_domain<D> &rhs):
|
|
||||||
m_fd (dup (rhs.m_fd))
|
|
||||||
{ ; }
|
|
||||||
|
|
||||||
|
|
||||||
template <domain D>
|
|
||||||
socket_domain<D>::~socket_domain () {
|
|
||||||
if (closesocket (m_fd) < 0) {
|
|
||||||
LOG_DEBUG ("closesocket: %s", strerror (errno));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <domain D>
|
|
||||||
socket_t
|
|
||||||
socket_domain<D>::native (void) const
|
|
||||||
{ return m_fd; }
|
|
||||||
|
|
||||||
|
|
||||||
template <domain D>
|
|
||||||
void
|
|
||||||
socket_domain<D>::shutdown (void) {
|
|
||||||
#if defined(HAVE_WINSOCK2_H)
|
|
||||||
#define SHUT_SEND SD_SEND
|
|
||||||
#define SHUT_RECV SD_RECEIVE
|
|
||||||
#define SHUT_RDWR SD_BOTH
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (::shutdown (m_fd, SHUT_RDWR) < 0)
|
|
||||||
net::error::throw_code ();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <domain D>
|
|
||||||
template <typename T>
|
|
||||||
T
|
|
||||||
socket_domain<D>::get_option (level, option) {
|
|
||||||
not_implemented ();
|
|
||||||
return T ();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <domain D>
|
|
||||||
void
|
|
||||||
socket_domain<D>::set_option (level _level, option _option) {
|
|
||||||
if (setsockopt (this->m_fd, (int)_level, (int)_option, NULL, 0))
|
|
||||||
net::error::throw_code ();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <domain D>
|
|
||||||
template <typename T>
|
|
||||||
void
|
|
||||||
socket_domain<D>::set_option (level _level, option _option, const T &value) {
|
|
||||||
if (setsockopt (this->m_fd, (int)_level, (int)_option, (const char*)&value, sizeof (value)))
|
|
||||||
net::error::throw_code ();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <domain D>
|
|
||||||
void
|
|
||||||
socket_domain<D>::bind (const address_type &addr) {
|
|
||||||
typename address_type::sockaddr_type addr_in = addr.to_sockaddr ();
|
|
||||||
|
|
||||||
if (::bind (m_fd, (sockaddr *)&addr_in, sizeof (addr_in)) != 0)
|
|
||||||
net::error::throw_code ();
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
template <domain D>
|
|
||||||
net::socket<D, type::STREAM>::socket (socket_t _fd):
|
|
||||||
net::socket_domain<D> (_fd)
|
|
||||||
{ ; }
|
|
||||||
|
|
||||||
|
|
||||||
template <domain D>
|
|
||||||
net::socket<D, type::STREAM>::socket ():
|
|
||||||
net::socket_domain<D> (::socket ((int)D, (int)type::STREAM, (int)protocol::DEFAULT))
|
|
||||||
{ ; }
|
|
||||||
|
|
||||||
|
|
||||||
template <domain D>
|
|
||||||
net::socket<D, type::STREAM>::socket (const socket_type &rhs):
|
|
||||||
socket_domain<D> (rhs)
|
|
||||||
{ ; }
|
|
||||||
|
|
||||||
|
|
||||||
template <domain D>
|
|
||||||
void
|
|
||||||
net::socket<D, type::STREAM>::send (const uint8_t *restrict data, size_t len) {
|
|
||||||
CHECK (data != NULL);
|
|
||||||
CHECK_GT (len, 0);
|
|
||||||
|
|
||||||
for (size_t sent = 0; sent < len; ) {
|
|
||||||
ssize_t result = ::send (this->m_fd, static_cast<const void *>(data + sent), len - sent, 0);
|
|
||||||
|
|
||||||
if (result < 0)
|
|
||||||
net::error::throw_code ();
|
|
||||||
|
|
||||||
sent += sign_cast<size_t> (result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <domain D>
|
|
||||||
size_t
|
|
||||||
net::socket<D, type::STREAM>::recv (uint8_t *restrict data, size_t len) {
|
|
||||||
CHECK (data != NULL);
|
|
||||||
CHECK_GT (len, 0);
|
|
||||||
|
|
||||||
ssize_t received = ::recv (this->m_fd, data, len, 0);
|
|
||||||
if (received < 0)
|
|
||||||
net::error::throw_code ();
|
|
||||||
|
|
||||||
return sign_cast<size_t> (received);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <domain D>
|
|
||||||
void
|
|
||||||
net::socket<D, type::STREAM>::connect (const address_type &_addr) {
|
|
||||||
typename address_type::sockaddr_type addr (_addr.to_sockaddr ());
|
|
||||||
|
|
||||||
if (::connect (this->m_fd, reinterpret_cast<sockaddr *> (&addr), sizeof (addr)) < 0)
|
|
||||||
net::error::throw_code ();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <domain D>
|
|
||||||
void
|
|
||||||
net::socket<D, type::STREAM>::listen (const address_type &_addr, unsigned int _backlog) {
|
|
||||||
this->bind (_addr);
|
|
||||||
|
|
||||||
if (::listen (this->m_fd, sign_cast<int>(_backlog)) != 0)
|
|
||||||
net::error::throw_code ();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <domain D>
|
|
||||||
typename net::socket<D, type::STREAM>::socket_ptr
|
|
||||||
net::socket<D, type::STREAM>::accept (void) {
|
|
||||||
socket_t newfd = ::accept (this->m_fd, NULL, 0);
|
|
||||||
if (newfd == INVALID_SOCKET)
|
|
||||||
net::error::throw_code ();
|
|
||||||
|
|
||||||
return socket_ptr(new socket<D, type::STREAM> (newfd));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <domain D>
|
|
||||||
typename net::socket<D, type::STREAM>::address_type
|
|
||||||
net::socket<D, type::STREAM>::get_peer (void) const {
|
|
||||||
typename address_type::sockaddr_type addr;
|
|
||||||
socklen_t addr_len;
|
|
||||||
|
|
||||||
if (getpeername (this->m_fd, (sockaddr*)&addr, &addr_len))
|
|
||||||
net::error::throw_code ();
|
|
||||||
|
|
||||||
CHECK (addr_len == sizeof (addr));
|
|
||||||
return typename net::socket<D,type::STREAM>::address_type (addr);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
template <domain D>
|
|
||||||
net::socket<D, type::DGRAM>::socket (socket_t _fd):
|
|
||||||
net::socket_domain<D> (_fd)
|
|
||||||
{ ; }
|
|
||||||
|
|
||||||
|
|
||||||
template <domain D>
|
|
||||||
net::socket<D, type::DGRAM>::socket ():
|
|
||||||
net::socket_domain<D> (::socket ((int)D, (int)type::DGRAM, (int)protocol::DEFAULT))
|
|
||||||
{ ; }
|
|
||||||
|
|
||||||
|
|
||||||
template <domain D>
|
|
||||||
net::socket<D, type::DGRAM>::socket (const socket_type &rhs):
|
|
||||||
net::socket_domain<D> (rhs)
|
|
||||||
{ ; }
|
|
||||||
|
|
||||||
|
|
||||||
template <domain D>
|
|
||||||
void
|
|
||||||
net::socket<D, type::DGRAM>::send_addr (const address_type &addr,
|
|
||||||
const uint8_t *restrict data,
|
|
||||||
size_t len) {
|
|
||||||
CHECK (data != NULL);
|
|
||||||
CHECK_GT (len, 0);
|
|
||||||
|
|
||||||
typename address_type::sockaddr_type addr_in = addr.to_sockaddr ();
|
|
||||||
|
|
||||||
ssize_t sent = ::sendto (this->m_fd, data, len, 0, (sockaddr *)&addr_in, sizeof (addr_in));
|
|
||||||
if (sent < 0)
|
|
||||||
net::error::throw_code ();
|
|
||||||
|
|
||||||
CHECK_EQ (sign_cast<size_t>(sent), len);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
template <domain D>
|
|
||||||
typename net::socket<D, type::DGRAM>::address_type
|
|
||||||
net::socket<D, type::DGRAM>::recv_addr (uint8_t *restrict data,
|
|
||||||
size_t len) {
|
|
||||||
CHECK (data != NULL);
|
|
||||||
CHECK_GT (len, 0);
|
|
||||||
|
|
||||||
typename address_type::sockaddr_type addr_in;
|
|
||||||
socklen_t addr_len = sizeof (addr_in);
|
|
||||||
|
|
||||||
ssize_t recvd = recvfrom (this->m_fd, data, len, 0, (sockaddr *)&addr_in, &addr_len);
|
|
||||||
CHECK_EQ (sizeof (addr_in), addr_len);
|
|
||||||
if (recvd < 0)
|
|
||||||
net::error::throw_code ();
|
|
||||||
|
|
||||||
return net::socket<D,type::DGRAM>::address_type (addr_in);
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
template class net::socket_domain<domain::INET>;
|
|
||||||
template void net::socket_domain<domain::INET>::set_option<int>(level, option, const int&);
|
|
||||||
|
|
||||||
template class net::socket<domain::INET, type::STREAM>;
|
|
||||||
template class net::socket<domain::INET, type::DGRAM>;
|
|
||||||
|
|
108
net/socket.hpp
108
net/socket.hpp
@ -1,108 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
* Copyright 2011 Danny Robson <danny@nerdcruft.net>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __NET_SOCKET_HPP
|
|
||||||
#define __NET_SOCKET_HPP
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
|
|
||||||
#include "types.hpp"
|
|
||||||
#include "address.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
namespace net {
|
|
||||||
template <domain D>
|
|
||||||
class socket_domain {
|
|
||||||
public:
|
|
||||||
typedef address<D> address_type;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
socket_t m_fd;
|
|
||||||
|
|
||||||
socket_domain (socket_t _fd);
|
|
||||||
socket_domain (const socket_domain<D>&);
|
|
||||||
~socket_domain ();
|
|
||||||
|
|
||||||
public:
|
|
||||||
socket_t native (void) const;
|
|
||||||
|
|
||||||
void shutdown (void);
|
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
T get_option (level, option);
|
|
||||||
|
|
||||||
void set_option (level, option);
|
|
||||||
template <typename T>
|
|
||||||
void set_option (level, option, const T &value);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void bind (const address_type&);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
template <domain D, type T>
|
|
||||||
class socket;
|
|
||||||
|
|
||||||
|
|
||||||
template <domain D>
|
|
||||||
class socket<D, type::STREAM>: public socket_domain<D> {
|
|
||||||
public:
|
|
||||||
typedef socket<D, type::STREAM> socket_type;
|
|
||||||
typedef std::unique_ptr<socket_type> socket_ptr;
|
|
||||||
typedef address<D> address_type;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
static const unsigned int DEFAULT_BACKLOG = 5;
|
|
||||||
|
|
||||||
socket (socket_t _fd);
|
|
||||||
|
|
||||||
public:
|
|
||||||
socket ();
|
|
||||||
socket (const socket_type &);
|
|
||||||
|
|
||||||
void send (const uint8_t *restrict, size_t);
|
|
||||||
size_t recv (uint8_t *restrict, size_t);
|
|
||||||
|
|
||||||
void connect (const address_type&);
|
|
||||||
|
|
||||||
void listen (const address_type&, unsigned int backlog = DEFAULT_BACKLOG);
|
|
||||||
socket_ptr accept (void);
|
|
||||||
|
|
||||||
address_type get_peer (void) const;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
template <domain D>
|
|
||||||
class socket<D, type::DGRAM> : public socket_domain<D> {
|
|
||||||
public:
|
|
||||||
typedef socket<D, type::DGRAM> socket_type;
|
|
||||||
typedef address<D> address_type;
|
|
||||||
|
|
||||||
socket (socket_t _fd);
|
|
||||||
|
|
||||||
public:
|
|
||||||
socket ();
|
|
||||||
socket (const socket_type &);
|
|
||||||
|
|
||||||
void send_addr (const address_type&, const uint8_t *restrict, size_t);
|
|
||||||
address_type recv_addr (uint8_t *restrict, size_t);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#endif // __NET_SOCKET_HPP
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
* Copyright 2011 Danny Robson <danny@nerdcruft.net>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "types.hpp"
|
|
||||||
#include "../debug.hpp"
|
|
||||||
|
|
||||||
#if defined(HAVE_WINSOCK2_H)
|
|
||||||
#else
|
|
||||||
#include <netdb.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
using namespace net;
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
protocol
|
|
||||||
net::string_to_protocol (const std::string &_name)
|
|
||||||
{ return net::string_to_protocol (_name.c_str ()); }
|
|
||||||
|
|
||||||
|
|
||||||
protocol
|
|
||||||
net::string_to_protocol (const char *_name) {
|
|
||||||
struct protoent *entry = getprotobyname (_name);
|
|
||||||
// TODO: Throw an exception...
|
|
||||||
CHECK (entry);
|
|
||||||
return (protocol)entry->p_proto;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
std::string
|
|
||||||
net::protocol_to_string (protocol _protocol) {
|
|
||||||
struct protoent *entry = getprotobynumber ((int)_protocol);
|
|
||||||
CHECK (entry);
|
|
||||||
return entry->p_name;
|
|
||||||
}
|
|
||||||
|
|
180
net/types.hpp
180
net/types.hpp
@ -1,180 +0,0 @@
|
|||||||
/*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*
|
|
||||||
* Copyright 2011 Danny Robson <danny@nerdcruft.net>
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef __NET_TYPES_HPP
|
|
||||||
#define __NET_TYPES_HPP
|
|
||||||
|
|
||||||
|
|
||||||
#if defined(HAVE_WINSOCK2_H)
|
|
||||||
#include <winsock2.h>
|
|
||||||
#else
|
|
||||||
#include <netinet/in.h>
|
|
||||||
#include <netinet/tcp.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <cstring>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <stdexcept>
|
|
||||||
|
|
||||||
|
|
||||||
namespace net {
|
|
||||||
/// Cross platform socket type to deal with Winsock2
|
|
||||||
#if defined(HAVE_WINSOCK2_H)
|
|
||||||
typedef SOCKET socket_t;
|
|
||||||
#else
|
|
||||||
typedef int socket_t;
|
|
||||||
const socket_t INVALID_SOCKET = -1;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/// Defines the protocol family, or communication domain of a socket (see `man socket').
|
|
||||||
enum class domain : int {
|
|
||||||
#define DEFINE_DOMAIN(V) \
|
|
||||||
V = AF_##V
|
|
||||||
|
|
||||||
DEFINE_DOMAIN(UNIX),
|
|
||||||
//DEFINE_DOMAIN(LOCAL),
|
|
||||||
DEFINE_DOMAIN(INET),
|
|
||||||
DEFINE_DOMAIN(INET6),
|
|
||||||
DEFINE_DOMAIN(IPX),
|
|
||||||
//DEFINE_DOMAIN(NETLINK),
|
|
||||||
//DEFINE_DOMAIN(X25),
|
|
||||||
//DEFINE_DOMAIN(AX25),
|
|
||||||
//DEFINE_DOMAIN(ATMPVC),
|
|
||||||
DEFINE_DOMAIN(APPLETALK)
|
|
||||||
//DEFINE_DOMAIN(PACKET)
|
|
||||||
|
|
||||||
#undef DEFINE_DOMAIN
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/// Specifies the communication semantics of a socket; how a socket deals with data.
|
|
||||||
enum class type : int {
|
|
||||||
#define DEFINE_TYPE(V) \
|
|
||||||
V = SOCK_##V
|
|
||||||
|
|
||||||
DEFINE_TYPE(STREAM),
|
|
||||||
DEFINE_TYPE(DGRAM),
|
|
||||||
DEFINE_TYPE(SEQPACKET),
|
|
||||||
DEFINE_TYPE(RAW),
|
|
||||||
DEFINE_TYPE(RDM)
|
|
||||||
//DEFINE_TYPE(PACKET)
|
|
||||||
|
|
||||||
#undef DEFINE_TYPE
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/// Indicates the wire transmission protocol to use.
|
|
||||||
///
|
|
||||||
/// This DOES NOT mean what you think it does! It is included for completeness sake, and unless
|
|
||||||
/// you're doing something funky with the C API you really just want DEFAULT.
|
|
||||||
/// Values retrieved from /etc/protocols
|
|
||||||
enum class protocol : int {
|
|
||||||
DEFAULT = 0,
|
|
||||||
|
|
||||||
IP = 0,
|
|
||||||
ICMP = 1,
|
|
||||||
TCP = 6,
|
|
||||||
UDP = 17,
|
|
||||||
IPV6 = 41
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
protocol
|
|
||||||
string_to_protocol (const std::string&);
|
|
||||||
|
|
||||||
protocol
|
|
||||||
string_to_protocol (const char *name);
|
|
||||||
|
|
||||||
std::string
|
|
||||||
protocol_to_string (protocol);
|
|
||||||
|
|
||||||
|
|
||||||
enum class option : int {
|
|
||||||
#define DEFINE_OPTION(V) \
|
|
||||||
V = SO_##V
|
|
||||||
|
|
||||||
DEFINE_OPTION(DEBUG),
|
|
||||||
DEFINE_OPTION(REUSEADDR),
|
|
||||||
DEFINE_OPTION(TYPE),
|
|
||||||
//DEFINE_OPTION(ERROR),
|
|
||||||
DEFINE_OPTION(DONTROUTE),
|
|
||||||
DEFINE_OPTION(BROADCAST),
|
|
||||||
//DEFINE_OPTION(SNDBUF),
|
|
||||||
DEFINE_OPTION(RCVBUF),
|
|
||||||
//DEFINE_OPTION(SNDBUFFORCE),
|
|
||||||
//DEFINE_OPTION(RCVBUFFORCE),
|
|
||||||
DEFINE_OPTION(KEEPALIVE),
|
|
||||||
DEFINE_OPTION(OOBINLINE),
|
|
||||||
//DEFINE_OPTION(NO_CHECK),
|
|
||||||
//DEFINE_OPTION(PRIORITY),
|
|
||||||
DEFINE_OPTION(LINGER),
|
|
||||||
//DEFINE_OPTION(BSDCOMPAT),
|
|
||||||
|
|
||||||
//DEFINE_OPTION(PASSCRED),
|
|
||||||
//DEFINE_OPTION(PEERCRED),
|
|
||||||
DEFINE_OPTION(RCVLOWAT),
|
|
||||||
DEFINE_OPTION(SNDLOWAT),
|
|
||||||
DEFINE_OPTION(RCVTIMEO),
|
|
||||||
DEFINE_OPTION(SNDTIMEO),
|
|
||||||
|
|
||||||
//DEFINE_OPTION(BINDTODEVICE),
|
|
||||||
|
|
||||||
//DEFINE_OPTION(ATTACH_FILTER),
|
|
||||||
//DEFINE_OPTION(DETACH_FILTER),
|
|
||||||
|
|
||||||
//DEFINE_OPTION(PEERNAME),
|
|
||||||
//DEFINE_OPTION(TIMESTAMP),
|
|
||||||
|
|
||||||
DEFINE_OPTION(ACCEPTCONN),
|
|
||||||
|
|
||||||
//DEFINE_OPTION(PEERSEC),
|
|
||||||
//DEFINE_OPTION(PASSSEC),
|
|
||||||
//DEFINE_OPTION(TIMESTAMPNS),
|
|
||||||
|
|
||||||
//DEFINE_OPTION(MARK),
|
|
||||||
|
|
||||||
//DEFINE_OPTION(TIMESTAMPING)
|
|
||||||
#undef DEFINE_OPTION
|
|
||||||
|
|
||||||
#define DEFINE_OPTION(V) \
|
|
||||||
V = TCP_##V
|
|
||||||
|
|
||||||
//DEFINE_OPTION(CORK),
|
|
||||||
//DEFINE_OPTION(DEFER_ACCEPT),
|
|
||||||
//DEFINE_OPTION(INFO),
|
|
||||||
//DEFINE_OPTION(KEEPCNT),
|
|
||||||
//DEFINE_OPTION(KEEPIDLE),
|
|
||||||
//DEFINE_OPTION(KEEPINTVL),
|
|
||||||
//DEFINE_OPTION(LINGER2),
|
|
||||||
//DEFINE_OPTION(MAXSEG),
|
|
||||||
DEFINE_OPTION(NODELAY)
|
|
||||||
//DEFINE_OPTION(QUICKACK),
|
|
||||||
//DEFINE_OPTION(SYNCNT),
|
|
||||||
//DEFINE_OPTION(WINDOW_CLAMP)
|
|
||||||
#undef DEFINE_OPTION
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
enum class level : int {
|
|
||||||
SOCKET = SOL_SOCKET,
|
|
||||||
TCP = IPPROTO_TCP
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif // __NET_TYPES_HPP
|
|
||||||
|
|
38
posix/fd.cpp
38
posix/fd.cpp
@ -27,7 +27,7 @@ using util::posix::fd;
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
fd::fd (const char *path, int flags):
|
fd::fd (const char *path, int flags):
|
||||||
m_fd (open (path, flags))
|
m_fd (::open (path, flags))
|
||||||
{
|
{
|
||||||
if (m_fd < 0)
|
if (m_fd < 0)
|
||||||
errno_error::throw_code ();
|
errno_error::throw_code ();
|
||||||
@ -36,7 +36,7 @@ fd::fd (const char *path, int flags):
|
|||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
fd::fd (const char *path, int flags, mode_t mode):
|
fd::fd (const char *path, int flags, mode_t mode):
|
||||||
m_fd (open (path, flags, mode))
|
m_fd (::open (path, flags, mode))
|
||||||
{
|
{
|
||||||
if (m_fd < 0)
|
if (m_fd < 0)
|
||||||
errno_error::throw_code ();
|
errno_error::throw_code ();
|
||||||
@ -52,21 +52,35 @@ fd::fd (fd &&rhs):
|
|||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
fd::fd (const fd &rhs):
|
fd::fd (int _fd):
|
||||||
m_fd (dup (rhs.m_fd))
|
m_fd (_fd)
|
||||||
{
|
{
|
||||||
if (m_fd < 0)
|
if (_fd < 0)
|
||||||
errno_error::throw_code ();
|
throw std::invalid_argument ("invalid descriptor");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
fd
|
||||||
|
fd::dup (void) const
|
||||||
|
{
|
||||||
|
return dup (m_fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
fd::fd (int _fd):
|
fd
|
||||||
m_fd (_fd)
|
fd::dup (int _fd)
|
||||||
{ ; }
|
{
|
||||||
|
auto res = ::dup (_fd);
|
||||||
|
if (res < 0)
|
||||||
|
errno_error::throw_code ();
|
||||||
|
|
||||||
|
return fd (res);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
fd::~fd ()
|
fd::~fd ()
|
||||||
{
|
{
|
||||||
if (m_fd < 0)
|
if (m_fd < 0)
|
||||||
@ -93,7 +107,3 @@ fd::operator int (void) const
|
|||||||
{
|
{
|
||||||
return m_fd;
|
return m_fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
const fd fd::INVALID (-1);
|
|
||||||
|
@ -29,17 +29,18 @@ namespace util::posix {
|
|||||||
fd (const char *path, int flags, mode_t);
|
fd (const char *path, int flags, mode_t);
|
||||||
|
|
||||||
fd (fd &&);
|
fd (fd &&);
|
||||||
explicit fd (const fd&);
|
|
||||||
explicit fd (int);
|
explicit fd (int);
|
||||||
|
|
||||||
|
fd (const fd&) = delete;
|
||||||
|
fd dup (void) const;
|
||||||
|
static fd dup (int);
|
||||||
|
|
||||||
~fd ();
|
~fd ();
|
||||||
|
|
||||||
struct ::stat stat (void) const;
|
struct ::stat stat (void) const;
|
||||||
|
|
||||||
operator int (void) const;
|
operator int (void) const;
|
||||||
|
|
||||||
static const fd INVALID;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int m_fd;
|
int m_fd;
|
||||||
};
|
};
|
||||||
|
285
quaternion.cpp
285
quaternion.cpp
@ -15,74 +15,44 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "quaternion.hpp"
|
#include "./quaternion.hpp"
|
||||||
|
|
||||||
#include "maths.hpp"
|
#include "./debug.hpp"
|
||||||
|
#include "./maths.hpp"
|
||||||
|
#include "./vector.hpp"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
using util::quaternion;
|
using util::quaternion;
|
||||||
using util::matrix4;
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
template<> const quaternion< float> quaternion< float>::IDENTITY = { 1, 0, 0, 0 };
|
template<> const quaternion<4, float> quaternion<4, float>::IDENTITY = { 1, 0, 0, 0 };
|
||||||
template<> const quaternion<double> quaternion<double>::IDENTITY = { 1, 0, 0, 0 };
|
template<> const quaternion<4, double> quaternion<4, double>::IDENTITY = { 1, 0, 0, 0 };
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename T>
|
template <size_t S, typename T>
|
||||||
quaternion<T>::quaternion (T _a, T _b, T _c, T _d):
|
quaternion<S,T>
|
||||||
a (_a),
|
quaternion<S,T>::rotation (const T radians, const vector<3,T> axis)
|
||||||
b (_b),
|
{
|
||||||
c (_c),
|
CHECK (is_normalised (axis));
|
||||||
d (_d)
|
|
||||||
{ ; }
|
|
||||||
|
|
||||||
|
auto w = std::cos (radians / 2);
|
||||||
//-----------------------------------------------------------------------------
|
auto xyz = std::sin (radians / 2) * axis;
|
||||||
template <typename T>
|
|
||||||
quaternion<T>::quaternion (T _a):
|
|
||||||
a (_a),
|
|
||||||
b (T{}),
|
|
||||||
c (T{}),
|
|
||||||
d (T{})
|
|
||||||
{ ; }
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
template <typename T>
|
|
||||||
quaternion<T>::quaternion ():
|
|
||||||
quaternion (T{}, T{}, T{}, T{})
|
|
||||||
{ ; }
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
template <typename T>
|
|
||||||
quaternion<T>::quaternion (vector3<T> v):
|
|
||||||
quaternion (0, v.x, v.y, v.z)
|
|
||||||
{ ; }
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
template <typename T>
|
|
||||||
quaternion<T>
|
|
||||||
quaternion<T>::rotation (const T radians, const vector<3,T> axis) {
|
|
||||||
CHECK (axis.is_normalised ());
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
std::cos (radians / 2),
|
w, xyz.x, xyz.y, xyz.z
|
||||||
std::sin (radians / 2) * axis.x,
|
|
||||||
std::sin (radians / 2) * axis.y,
|
|
||||||
std::sin (radians / 2) * axis.z
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
template <typename T>
|
template <size_t S, typename T>
|
||||||
quaternion<T>
|
quaternion<S,T>
|
||||||
quaternion<T>::rotation (vector<3,T> src, vector<3,T> dst) {
|
quaternion<S,T>::rotation (const vector<3,T> src, const vector<3,T> dst)
|
||||||
|
{
|
||||||
auto v = util::cross (src, dst);
|
auto v = util::cross (src, dst);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -96,195 +66,102 @@ quaternion<T>::rotation (vector<3,T> src, vector<3,T> dst) {
|
|||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T
|
quaternion<4,T>
|
||||||
quaternion<T>::norm2 (void) const
|
util::conjugate (quaternion<4,T> q)
|
||||||
{
|
{
|
||||||
return a * a + b * b + c * c + d * d;
|
return { q.w, -q.x, -q.y, -q.z };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
template quaternion<4,float> util::conjugate (quaternion<4,float>);
|
||||||
template <typename T>
|
|
||||||
T
|
|
||||||
quaternion<T>::norm (void) const
|
|
||||||
{
|
|
||||||
return std::sqrt (norm2 ());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
template <typename T>
|
|
||||||
quaternion<T>
|
|
||||||
quaternion<T>::normalised (void) const
|
|
||||||
{
|
|
||||||
return *this / norm ();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename T>
|
template <size_t S, typename T>
|
||||||
quaternion<T>
|
quaternion<S,T>
|
||||||
quaternion<T>::operator- (void) const
|
util::operator* (const quaternion<S,T> a, const quaternion<S,T> b)
|
||||||
{
|
|
||||||
return { -a, -b, -c, -d };
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
template <typename T>
|
|
||||||
quaternion<T>
|
|
||||||
quaternion<T>::conjugate (void) const
|
|
||||||
{
|
|
||||||
return { a, -b, -c, -d };
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
template <typename T>
|
|
||||||
quaternion<T>
|
|
||||||
quaternion<T>::operator+ (const quaternion<T> q) const
|
|
||||||
{
|
{
|
||||||
return {
|
return {
|
||||||
a + q.a,
|
a.w * b.w - a.x * b.x - a.y * b.y - a.z * b.z,
|
||||||
b + q.b,
|
a.w * b.x + a.x * b.w + a.y * b.z - a.z * b.y,
|
||||||
c + q.c,
|
a.w * b.y - a.x * b.z + a.y * b.w + a.z * b.x,
|
||||||
d + q.d
|
a.w * b.z + a.x * b.y - a.y * b.x + a.z * b.w,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template quaternion<4,float> util::operator* (quaternion<4,float>, quaternion<4,float>);
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
template <typename T>
|
template <size_t S, typename T>
|
||||||
quaternion<T>
|
quaternion<S,T>
|
||||||
quaternion<T>::operator- (const quaternion<T> q) const
|
util::operator/ (const quaternion<S,T> a, const quaternion<S,T> b)
|
||||||
{
|
{
|
||||||
return {
|
CHECK (is_normalised (a));
|
||||||
a - q.a,
|
CHECK (is_normalised (b));
|
||||||
b - q.b,
|
|
||||||
c - q.c,
|
return quaternion<S,T> {
|
||||||
d - q.d
|
a.w * b.w + a.x * b.x + a.y * b.y + a.z * b.z,
|
||||||
|
- a.w * b.x + a.x * b.w + a.y * b.z - a.z * b.y,
|
||||||
|
- a.w * b.y - a.x * b.z + a.y * b.w + a.z * b.x,
|
||||||
|
- a.w * b.z + a.x * b.y - a.y * b.x + a.z * b.w,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template quaternion<4,float> util::operator/ (quaternion<4,float>, quaternion<4,float>);
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
template <typename T>
|
|
||||||
quaternion<T>
|
|
||||||
quaternion<T>::operator* (const quaternion<T> q) const {
|
|
||||||
return {
|
|
||||||
a * q.a - b * q.b - c * q.c - d * q.d,
|
|
||||||
a * q.b + b * q.a + c * q.d - d * q.c,
|
|
||||||
a * q.c - b * q.d + c * q.a + d * q.b,
|
|
||||||
a * q.d + b * q.c - c * q.b + d * q.a,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
template <typename T>
|
|
||||||
quaternion<T>
|
|
||||||
quaternion<T>::operator/ (const quaternion<T> q) const
|
|
||||||
{
|
|
||||||
auto n = q.norm2 ();
|
|
||||||
|
|
||||||
return {
|
|
||||||
( a * q.a + b * q.b + c * q.c + d * q.d) / n,
|
|
||||||
(- a * q.b + b * q.a + c * q.d - d * q.c) / n,
|
|
||||||
(- a * q.c - b * q.d + c * q.a + d * q.b) / n,
|
|
||||||
(- a * q.d + b * q.c - c * q.b + d * q.a) / n
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
template <typename T>
|
|
||||||
quaternion<T>
|
|
||||||
quaternion<T>::operator+ (const T t) const
|
|
||||||
{
|
|
||||||
return { a + t, b, c, d };
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
template <typename T>
|
|
||||||
quaternion<T>
|
|
||||||
quaternion<T>::operator- (const T t) const
|
|
||||||
{
|
|
||||||
return { a - t, b, c, d };
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
template <typename T>
|
|
||||||
quaternion<T>
|
|
||||||
quaternion<T>::operator* (const T t) const
|
|
||||||
{
|
|
||||||
return { a * t, b, c, d };
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
template <typename T>
|
|
||||||
quaternion<T>
|
|
||||||
quaternion<T>::operator/ (const T t) const
|
|
||||||
{
|
|
||||||
return { a / t, b, c, d };
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename T>
|
template <size_t S, typename T>
|
||||||
bool
|
util::matrix4<T>
|
||||||
quaternion<T>::operator== (const quaternion<T> rhs) const
|
quaternion<S, T>::as_matrix (void) const
|
||||||
{
|
{
|
||||||
return almost_equal (a, rhs.a) &&
|
CHECK (is_normalised (*this));
|
||||||
almost_equal (b, rhs.b) &&
|
|
||||||
almost_equal (c, rhs.c) &&
|
|
||||||
almost_equal (d, rhs.d);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
const T wx = this->w * this->x, wy = this->w * this->y, wz = this->w * this->z;
|
||||||
//-----------------------------------------------------------------------------
|
const T xx = this->x * this->x, xy = this->x * this->y, xz = this->x * this->z;
|
||||||
template <typename T>
|
const T yy = this->y * this->y, yz = this->y * this->z, zz = this->z * this->z;
|
||||||
bool
|
|
||||||
quaternion<T>::operator!= (const quaternion<T> rhs) const
|
|
||||||
{
|
|
||||||
return !(*this == rhs);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
|
||||||
template <typename T>
|
|
||||||
matrix4<T>
|
|
||||||
quaternion<T>::rotation_matrix (void) const
|
|
||||||
{
|
|
||||||
CHECK_EQ (T{1}, norm ());
|
|
||||||
|
|
||||||
const T wx = w * x, wy = w * y, wz = w * z;
|
|
||||||
const T xx = x * x, xy = x * y, xz = x * z;
|
|
||||||
const T yy = y * y, yz = y * z, zz = z * z;
|
|
||||||
|
|
||||||
return { {
|
return { {
|
||||||
{ 1 - 2 * (yy - zz), 2 * (xy - wz), 2 * (xz + wy), 0 },
|
{ 1 - 2 * (yy + zz), 2 * (xy - wz), 2 * (xz + wy), 0 },
|
||||||
{ 2 * (xy + wz), 1 - 2 * (xx - zz), 2 * (yz - wx), 0 },
|
{ 2 * (xy + wz), 1 - 2 * (xx + zz), 2 * (yz - wx), 0 },
|
||||||
{ 2 * (xz - wy), 2 * (yz + wx), 1 - 2 * (xx - yy), 0 },
|
{ 2 * (xz - wy), 2 * (yz + wx), 1 - 2 * (xx + yy), 0 },
|
||||||
{ 0, 0, 0, 1 }
|
{ 0, 0, 0, 1 }
|
||||||
} };
|
} };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename T>
|
template <size_t S, typename T>
|
||||||
std::ostream&
|
std::ostream&
|
||||||
util::operator<< (std::ostream &os, quaternion<T> q)
|
util::operator<< (std::ostream &os, const quaternion<S,T> q)
|
||||||
{
|
{
|
||||||
os << q.w << ' ' << q.x << "i " << q.y << "j " << q.z << 'k';
|
return os << "[" << q.w << ", " << q.x << ", " << q.y << ", " << q.z << "]";
|
||||||
return os;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
//-----------------------------------------------------------------------------
|
||||||
template struct util::quaternion<float>;
|
template std::ostream& util::operator<< (std::ostream&, quaternion<4,float>);
|
||||||
template struct util::quaternion<double>;
|
template std::ostream& util::operator<< (std::ostream&, quaternion<4,double>);
|
||||||
|
|
||||||
template std::ostream& util::operator<< (std::ostream&, quaternion<float>);
|
|
||||||
template std::ostream& util::operator<< (std::ostream&, quaternion<double>);
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
namespace util { namespace debug {
|
||||||
|
template <size_t S, typename T>
|
||||||
|
struct validator<quaternion<S,T>> {
|
||||||
|
static bool is_valid (const quaternion<S,T> &q)
|
||||||
|
{
|
||||||
|
return is_normalised (q);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
} }
|
||||||
|
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
template bool util::debug::is_valid(const quaternion<4,float>&);
|
||||||
|
template bool util::debug::is_valid(const quaternion<4,double>&);
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
template struct util::quaternion<4,float>;
|
||||||
|
template struct util::quaternion<4,double>;
|
||||||
|
@ -17,6 +17,8 @@
|
|||||||
#ifndef __UTIL_QUATERNION_HPP
|
#ifndef __UTIL_QUATERNION_HPP
|
||||||
#define __UTIL_QUATERNION_HPP
|
#define __UTIL_QUATERNION_HPP
|
||||||
|
|
||||||
|
#include "coord.hpp"
|
||||||
|
|
||||||
#include "vector.hpp"
|
#include "vector.hpp"
|
||||||
#include "matrix.hpp"
|
#include "matrix.hpp"
|
||||||
|
|
||||||
@ -24,53 +26,46 @@
|
|||||||
|
|
||||||
|
|
||||||
namespace util {
|
namespace util {
|
||||||
template <typename T>
|
// quaternions must be 4 elements, but we include a size parameter so it
|
||||||
struct quaternion {
|
// fits with the generic coord infrastructure more easily.
|
||||||
///////////////////////////////////////////////////////////////////////
|
//
|
||||||
union {
|
// specifically:
|
||||||
struct { T w, x, y, z; };
|
// large regions of base code require a template template parameter with
|
||||||
struct { T a, b, c, d; };
|
// size and type arguments, which is annoying to work around for this one
|
||||||
T data[4];
|
// case.
|
||||||
};
|
//
|
||||||
|
// we protect against invalid instantiations through static_assert
|
||||||
|
template <size_t S, typename T>
|
||||||
|
struct quaternion : public coord::base<4,T,quaternion,coord::wxyz,coord::abcd> {
|
||||||
|
static_assert (S == 4, "quaternions must be 4 elements");
|
||||||
|
|
||||||
static const quaternion IDENTITY;
|
using coord::base<S,T,::util::quaternion,::util::coord::wxyz,::util::coord::abcd>::base;
|
||||||
|
|
||||||
static quaternion rotation (T radians, vector<3,T> axis);
|
static quaternion rotation (T radians, vector<3,T> axis);
|
||||||
static quaternion rotation (vector<3,T> src, vector<3,T> dst);
|
static quaternion rotation (vector<3,T> src, vector<3,T> dst);
|
||||||
|
|
||||||
quaternion (T a, T b, T c, T d);
|
matrix4<T> as_matrix (void) const;
|
||||||
quaternion (T a);
|
|
||||||
quaternion ();
|
|
||||||
quaternion (vector<3,T>);
|
|
||||||
|
|
||||||
T norm (void) const;
|
static const quaternion IDENTITY;
|
||||||
T norm2 (void) const;
|
|
||||||
quaternion normalised (void) const;
|
|
||||||
|
|
||||||
quaternion operator- (void) const;
|
|
||||||
quaternion conjugate (void) const;
|
|
||||||
|
|
||||||
quaternion operator+ (const quaternion) const;
|
|
||||||
quaternion operator- (const quaternion) const;
|
|
||||||
quaternion operator* (const quaternion) const;
|
|
||||||
quaternion operator/ (const quaternion) const;
|
|
||||||
|
|
||||||
quaternion operator+ (const T) const;
|
|
||||||
quaternion operator- (const T) const;
|
|
||||||
quaternion operator* (const T) const;
|
|
||||||
quaternion operator/ (const T) const;
|
|
||||||
|
|
||||||
bool operator== (const quaternion) const;
|
|
||||||
bool operator!= (const quaternion) const;
|
|
||||||
|
|
||||||
matrix4<T> rotation_matrix (void) const;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef quaternion<float> quaternionf;
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
quaternion<4,T>
|
||||||
|
conjugate (quaternion<4,T>);
|
||||||
|
|
||||||
|
template <size_t S, typename T>
|
||||||
|
quaternion<S,T>
|
||||||
|
operator* (const quaternion<S,T>, const quaternion<S,T>);
|
||||||
|
|
||||||
|
template <size_t S, typename T>
|
||||||
|
quaternion<S,T>
|
||||||
|
operator/ (const quaternion<S,T>, const quaternion<S,T>);
|
||||||
|
|
||||||
|
typedef quaternion<4,float> quaternionf;
|
||||||
|
|
||||||
|
template <size_t S, typename T>
|
||||||
std::ostream&
|
std::ostream&
|
||||||
operator<< (std::ostream&, quaternion<T>);
|
operator<< (std::ostream&, quaternion<S,T>);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
#define __UTIL_RANGE_HPP
|
#define __UTIL_RANGE_HPP
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
#include <iostream>
|
#include <ostream>
|
||||||
|
|
||||||
namespace util {
|
namespace util {
|
||||||
/**
|
/**
|
||||||
|
@ -372,11 +372,11 @@ util::operator<< (std::ostream &os, const util::region<S,T> &rhs) {
|
|||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
namespace util { namespace debug {
|
namespace util { namespace debug {
|
||||||
template <size_t S, typename T>
|
template <size_t S, typename T>
|
||||||
struct validator<util::region,S,T> {
|
struct validator<util::region<S,T>> {
|
||||||
static bool is_valid (const util::region<S,T> &r)
|
static bool is_valid (const util::region<S,T> &r)
|
||||||
{
|
{
|
||||||
CHECK_GE (r.area (), 0);
|
CHECK_GE (r.area (), 0u);
|
||||||
CHECK_GE (min (r.e), 0);
|
CHECK_GE (min (r.e), 0u);
|
||||||
|
|
||||||
return r.area () >= 0 && min (r.e) >= 0;
|
return r.area () >= 0 && min (r.e) >= 0;
|
||||||
}
|
}
|
||||||
@ -388,7 +388,7 @@ namespace util { namespace debug {
|
|||||||
#define INSTANTIATE_S_T(S,T) \
|
#define INSTANTIATE_S_T(S,T) \
|
||||||
template struct util::region<S,T>; \
|
template struct util::region<S,T>; \
|
||||||
template std::ostream& util::operator<< (std::ostream&, const region<S,T>&); \
|
template std::ostream& util::operator<< (std::ostream&, const region<S,T>&); \
|
||||||
template struct util::debug::validator<util::region,S,T>;
|
template struct util::debug::validator<util::region<S,T>>;
|
||||||
|
|
||||||
#define INSTANTIATE(T) \
|
#define INSTANTIATE(T) \
|
||||||
INSTANTIATE_S_T(2,T) \
|
INSTANTIATE_S_T(2,T) \
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
#ifndef __UTIL_STATS_HPP
|
#ifndef __UTIL_STATS_HPP
|
||||||
#define __UTIL_STATS_HPP
|
#define __UTIL_STATS_HPP
|
||||||
|
|
||||||
#include <iostream>
|
#include <ostream>
|
||||||
|
|
||||||
|
|
||||||
namespace util {
|
namespace util {
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
#ifndef __UTIL_STREAM_HPP
|
#ifndef __UTIL_STREAM_HPP
|
||||||
#define __UTIL_STREAM_HPP
|
#define __UTIL_STREAM_HPP
|
||||||
|
|
||||||
#include <iostream>
|
#include <ostream>
|
||||||
|
|
||||||
namespace util {
|
namespace util {
|
||||||
namespace stream {
|
namespace stream {
|
||||||
|
44
tap.hpp
44
tap.hpp
@ -37,42 +37,42 @@ namespace util { namespace TAP {
|
|||||||
~logger ();
|
~logger ();
|
||||||
|
|
||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
template <typename ...Args>
|
template <typename ...Args, size_t N>
|
||||||
void expect (bool, const std::string &fmt, Args&&...);
|
void expect (bool, const char (&fmt)[N], Args&&...);
|
||||||
|
|
||||||
template <typename ...Args>
|
template <typename ...Args, size_t N>
|
||||||
void expect (const std::function<bool(Args...)>&, Args&&..., const std::string& msg);
|
void expect (const std::function<bool(Args...)>&, Args&&..., const char (&msg)[N]);
|
||||||
|
|
||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
template <typename T, typename U, typename ...Args>
|
template <typename T, typename U, typename ...Args, size_t N>
|
||||||
void expect_eq (const T&, const U&, const std::string &fmt, Args&&...);
|
void expect_eq (const T&, const U&, const char (&fmt)[N], Args&&...);
|
||||||
|
|
||||||
template <typename T, typename U, typename ...Args>
|
template <typename T, typename U, typename ...Args, size_t N>
|
||||||
void expect_neq (const T&, const U&, const std::string &fmt, Args&&...);
|
void expect_neq (const T&, const U&, const char (&fmt)[N], Args&&...);
|
||||||
|
|
||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
template <typename T, typename U, typename ...Args>
|
template <typename T, typename U, typename ...Args, size_t N>
|
||||||
void expect_gt (const T&, const U&, const std::string &fmt, Args&&...);
|
void expect_gt (const T&, const U&, const char (&fmt)[N], Args&&...);
|
||||||
|
|
||||||
template <typename T, typename U, typename ...Args>
|
template <typename T, typename U, typename ...Args, size_t N>
|
||||||
void expect_ge (const T&, const U&, const std::string &fmt, Args&&...);
|
void expect_ge (const T&, const U&, const char (&fmt)[N], Args&&...);
|
||||||
|
|
||||||
template <typename T, typename U, typename ...Args>
|
template <typename T, typename U, typename ...Args, size_t N>
|
||||||
void expect_lt (const T&, const U&, const std::string &fmt, Args&&...);
|
void expect_lt (const T&, const U&, const char (&fmt)[N], Args&&...);
|
||||||
|
|
||||||
template <typename T, typename U, typename ...Args>
|
template <typename T, typename U, typename ...Args, size_t N>
|
||||||
void expect_le (const T&, const U&, const std::string &fmt, Args&&...);
|
void expect_le (const T&, const U&, const char (&fmt)[N], Args&&...);
|
||||||
|
|
||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
template <typename T, typename ...Args>
|
template <typename T, typename ...Args, size_t N>
|
||||||
void expect_nan (const T&, const std::string &fmt, Args&&...);
|
void expect_nan (const T&, const char (&fmt)[N], Args&&...);
|
||||||
|
|
||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
template <typename T, typename ...Args>
|
template <typename T, typename ...Args, size_t N>
|
||||||
void expect_nothrow (T&&, const std::string &fmt, Args&&...);
|
void expect_nothrow (T&&, const char (&fmt)[N], Args&&...);
|
||||||
|
|
||||||
template <typename E, typename T, typename ...Args>
|
template <typename E, typename T, typename ...Args, size_t N>
|
||||||
void expect_throw (T&&, const std::string &fmt, Args&&...);
|
void expect_throw (T&&, const char (&fmt)[N], Args&&...);
|
||||||
|
|
||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
void skip (const std::string &msg);
|
void skip (const std::string &msg);
|
||||||
|
88
tap.ipp
88
tap.ipp
@ -29,9 +29,9 @@
|
|||||||
|
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename ...Args>
|
template <typename ...Args, size_t N>
|
||||||
void
|
void
|
||||||
util::TAP::logger::expect (bool test, const std::string &fmt, Args&&... args)
|
util::TAP::logger::expect (bool test, const char (&fmt)[N], Args&&... args)
|
||||||
{
|
{
|
||||||
std::cout << (test ? "ok " : "not ok ") << ++m_size
|
std::cout << (test ? "ok " : "not ok ") << ++m_size
|
||||||
<< " - "
|
<< " - "
|
||||||
@ -43,61 +43,46 @@ util::TAP::logger::expect (bool test, const std::string &fmt, Args&&... args)
|
|||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
template <typename... Args>
|
template <typename ...Args, size_t N>
|
||||||
void
|
void
|
||||||
util::TAP::logger::expect (const std::function<bool(Args...)> &test, Args&&... args, const std::string &msg)
|
util::TAP::logger::expect (const std::function<bool(Args...)> &test, Args&&... args, const char (&fmt)[N])
|
||||||
{
|
{
|
||||||
expect (test (std::forward<Args> (args)...), msg);
|
try {
|
||||||
|
expect (test (std::forward<Args> (args)...), fmt);
|
||||||
|
} catch (...) {
|
||||||
|
expect (false, fmt);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
template <typename T, typename U, typename ...Args, size_t N>
|
||||||
|
void
|
||||||
|
util::TAP::logger::expect_eq (const T&a, const U &b, const char (&fmt)[N], Args&&... args)
|
||||||
|
{
|
||||||
|
expect (almost_equal (a, b), fmt, std::forward<Args> (args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
template <typename T, typename U, typename ...Args>
|
template <typename T, typename U, typename ...Args, size_t N>
|
||||||
void
|
void
|
||||||
util::TAP::logger::expect_eq (const T&a, const U &b, const std::string &fmt, Args&&... args)
|
util::TAP::logger::expect_neq (const T&a, const U &b, const char (&fmt)[N], Args&&... args)
|
||||||
{
|
{
|
||||||
static const std::function<bool(const T&,const U&)> TEST = [] (const T &t, const U &u) -> bool {
|
expect (!almost_equal (a, b), fmt, std::forward<Args> (args)...);
|
||||||
return almost_equal (t, u);
|
|
||||||
};
|
|
||||||
|
|
||||||
expect<const T&, const U&> (TEST, a, b, util::format::render (fmt, std::forward<Args> (args)...));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
template <typename T, typename U, typename ...Args>
|
|
||||||
void
|
|
||||||
util::TAP::logger::expect_neq (const T&a, const U &b, const std::string &fmt, Args&&... args)
|
|
||||||
{
|
|
||||||
static const std::function<bool(const T&,const U&)> TEST = [] (const T &t, const U &u) -> bool {
|
|
||||||
return !almost_equal (t, u);
|
|
||||||
};
|
|
||||||
|
|
||||||
expect<const T&, const U&> (TEST, a, b, util::format::render (fmt, std::forward<Args> (args)...));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
#define TAP_TEST(SUFFIX,OP) \
|
#define TAP_TEST(SUFFIX,OP) \
|
||||||
template <typename T, typename U, typename ...Args> \
|
template <typename T, typename U, typename ...Args, size_t N> \
|
||||||
void \
|
void \
|
||||||
util::TAP::logger::expect_ ## SUFFIX (const T &a, \
|
util::TAP::logger::expect_ ## SUFFIX (const T &a, \
|
||||||
const U &b, \
|
const U &b, \
|
||||||
const std::string &fmt, \
|
const char (&fmt)[N], \
|
||||||
Args&&... args) \
|
Args&&... args) \
|
||||||
{ \
|
{ \
|
||||||
static const std::function< \
|
expect ((a) OP (b), fmt, std::forward<Args> (args)...); \
|
||||||
bool(const T&,const U&) \
|
|
||||||
> TEST = [] (const T&t, const U&u) { return t OP u; }; \
|
|
||||||
\
|
|
||||||
expect<const T&, const U&> ( \
|
|
||||||
TEST, \
|
|
||||||
a, b, \
|
|
||||||
util::format::render ( \
|
|
||||||
fmt, \
|
|
||||||
std::forward<Args> (args)... \
|
|
||||||
) \
|
|
||||||
); \
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TAP_TEST(gt, > )
|
TAP_TEST(gt, > )
|
||||||
@ -109,23 +94,18 @@ TAP_TEST(le, <=)
|
|||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
template <typename T, typename ...Args>
|
template <typename T, typename ...Args, size_t N>
|
||||||
void
|
void
|
||||||
util::TAP::logger::expect_nan (const T &t, const std::string &fmt, Args&&... args)
|
util::TAP::logger::expect_nan (const T &t, const char (&fmt)[N], Args&&... args)
|
||||||
{
|
{
|
||||||
bool(*func)(T) = std::isnan;
|
expect (std::isnan (t), fmt, std::forward<Args> (args)...);
|
||||||
expect<const T&> (
|
|
||||||
std::function<bool(const T&)> (func),
|
|
||||||
t,
|
|
||||||
util::format::render (fmt, std::forward<Args> (args)...)
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
template <typename T, typename ...Args>
|
template <typename T, typename ...Args, size_t N>
|
||||||
void
|
void
|
||||||
util::TAP::logger::expect_nothrow (T &&t, const std::string &fmt, Args&&... args)
|
util::TAP::logger::expect_nothrow (T &&t, const char (&fmt)[N], Args&&... args)
|
||||||
{
|
{
|
||||||
bool success = true;
|
bool success = true;
|
||||||
|
|
||||||
@ -135,14 +115,14 @@ util::TAP::logger::expect_nothrow (T &&t, const std::string &fmt, Args&&... args
|
|||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
expect (success, util::format::render (fmt, std::forward<Args> (args)...));
|
expect (success, fmt, std::forward<Args> (args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
template <typename E, typename T, typename ...Args>
|
template <typename E, typename T, typename ...Args, size_t N>
|
||||||
void
|
void
|
||||||
util::TAP::logger::expect_throw (T &&t, const std::string &fmt, Args&&... args)
|
util::TAP::logger::expect_throw (T &&t, const char (&fmt)[N], Args&&... args)
|
||||||
{
|
{
|
||||||
bool success = false;
|
bool success = false;
|
||||||
|
|
||||||
@ -154,5 +134,5 @@ util::TAP::logger::expect_throw (T &&t, const std::string &fmt, Args&&... args)
|
|||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
expect (success, util::format::render (fmt, std::forward<Args> (args)...));
|
expect (success, fmt, std::forward<Args> (args)...);
|
||||||
}
|
}
|
||||||
|
73
test/affine.cpp
Normal file
73
test/affine.cpp
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
#include "tap.hpp"
|
||||||
|
|
||||||
|
#include "vector.hpp"
|
||||||
|
#include "matrix.hpp"
|
||||||
|
#include "quaternion.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
void
|
||||||
|
test_mq_axis (util::TAP::logger &tap)
|
||||||
|
{
|
||||||
|
static const struct {
|
||||||
|
util::vector3f euler;
|
||||||
|
const char *msg;
|
||||||
|
} TESTS[] = {
|
||||||
|
{ { 1, 0, 0 }, "x-axis" },
|
||||||
|
{ { 0, 1, 0 }, "y-axis" },
|
||||||
|
{ { 0, 0, 1 }, "z-axis" },
|
||||||
|
};
|
||||||
|
|
||||||
|
for (auto t: TESTS) {
|
||||||
|
auto m = util::matrix4f::rotation (1, t.euler);
|
||||||
|
auto q = util::quaternionf::rotation (1, t.euler);
|
||||||
|
|
||||||
|
auto diff = sum (abs (m - q.as_matrix ()));
|
||||||
|
tap.expect_le (diff, 1e-6f, "matrix/quaternion rotation identities, %s", t.msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
void
|
||||||
|
test_mq_euler (util::TAP::logger &tap)
|
||||||
|
{
|
||||||
|
static const struct {
|
||||||
|
util::vector3f euler;
|
||||||
|
const char *msg;
|
||||||
|
} TESTS[] = {
|
||||||
|
{ { 0, 0, 0 }, "zeroes" },
|
||||||
|
{ { 1, 0, 0 }, "x-axis" },
|
||||||
|
{ { 0, 1, 0 }, "y-axis" },
|
||||||
|
{ { 0, 0, 1 }, "z-axis" },
|
||||||
|
{ { 1, 1, 1 }, "ones" },
|
||||||
|
{ { 9, 9, 9 }, "nines" }
|
||||||
|
};
|
||||||
|
|
||||||
|
for (auto t: TESTS) {
|
||||||
|
auto m = util::matrix4f::rotation (t.euler[0], { 1, 0, 0 }) *
|
||||||
|
util::matrix4f::rotation (t.euler[1], { 0, 1, 0 }) *
|
||||||
|
util::matrix4f::rotation (t.euler[2], { 0, 0, 1 });
|
||||||
|
auto q = (
|
||||||
|
util::quaternionf::rotation (t.euler[0], { 1, 0, 0 }) *
|
||||||
|
util::quaternionf::rotation (t.euler[1], { 0, 1, 0 }) *
|
||||||
|
util::quaternionf::rotation (t.euler[2], { 0, 0, 1 })
|
||||||
|
).as_matrix ();
|
||||||
|
|
||||||
|
auto diff = util::sum (abs (m - q));
|
||||||
|
tap.expect_le (diff, 1e-6f, "matrix-quaternion xyz euler rotations, %s", t.msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
int
|
||||||
|
main (int, char**)
|
||||||
|
{
|
||||||
|
util::TAP::logger tap;
|
||||||
|
|
||||||
|
test_mq_axis (tap);
|
||||||
|
test_mq_euler (tap);
|
||||||
|
|
||||||
|
return tap.status ();
|
||||||
|
}
|
@ -7,6 +7,8 @@ static char g_backing[1024*1024];
|
|||||||
|
|
||||||
|
|
||||||
struct setter {
|
struct setter {
|
||||||
|
setter (const setter&) = delete;
|
||||||
|
|
||||||
setter (bool &_target):
|
setter (bool &_target):
|
||||||
target (_target)
|
target (_target)
|
||||||
{ target = false; }
|
{ target = false; }
|
||||||
@ -30,7 +32,7 @@ main (void)
|
|||||||
|
|
||||||
// double check our testing object is working, because I'm tired and stupid
|
// double check our testing object is working, because I'm tired and stupid
|
||||||
{
|
{
|
||||||
auto val = setter (flag);
|
setter val (flag);
|
||||||
CHECK (!flag);
|
CHECK (!flag);
|
||||||
}
|
}
|
||||||
CHECK (flag);
|
CHECK (flag);
|
||||||
|
@ -86,13 +86,13 @@ test_bool (util::TAP::logger &tap)
|
|||||||
for (auto i: positive) {
|
for (auto i: positive) {
|
||||||
argv[2] = i;
|
argv[2] = i;
|
||||||
p.scan (argv.size (), argv.data ());
|
p.scan (argv.size (), argv.data ());
|
||||||
tap.expect_eq (value, true, i, "read bool, %s", i);
|
tap.expect_eq (value, true, "read bool, %s", i);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto i: negative) {
|
for (auto i: negative) {
|
||||||
argv[2] = i;
|
argv[2] = i;
|
||||||
p.scan (argv.size (), argv.data ());
|
p.scan (argv.size (), argv.data ());
|
||||||
tap.expect_eq (value, false, i, "read bool, %s", i);
|
tap.expect_eq (value, false, "read bool, %s", i);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check that invalid forms of boolean all throw exceptions
|
// Check that invalid forms of boolean all throw exceptions
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "tap.hpp"
|
#include "tap.hpp"
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
main (int, char**)
|
main (int, char**)
|
||||||
{
|
{
|
||||||
@ -44,8 +45,8 @@ main (int, char**)
|
|||||||
};
|
};
|
||||||
|
|
||||||
for (auto i: TESTS) {
|
for (auto i: TESTS) {
|
||||||
tap.expect_eq (util::rgb_to_hsv (i.rgb), i.hsv, i.name);
|
tap.expect_eq (util::rgb_to_hsv (i.rgb), i.hsv, "rgb-to-hsv %s", i.name);
|
||||||
tap.expect_eq (util::hsv_to_rgb (i.hsv), i.rgb, i.name);
|
tap.expect_eq (util::hsv_to_rgb (i.hsv), i.rgb, "hsv-to-rgb %s", i.name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
#include "tap.hpp"
|
#include "tap.hpp"
|
||||||
#include "point.hpp"
|
#include "point.hpp"
|
||||||
|
#include "vector.hpp"
|
||||||
|
|
||||||
#include "coord/iostream.hpp"
|
#include "coord/iostream.hpp"
|
||||||
|
|
||||||
@ -30,5 +31,10 @@ main (void)
|
|||||||
"unary point boolean negation has type bool"
|
"unary point boolean negation has type bool"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
auto vec = util::vector4f (0.5f);
|
||||||
|
t.expect_eq (vec, util::normalised (vec), "normalisation of normalised vector");
|
||||||
|
|
||||||
|
t.expect_eq (sum (util::vector4f::ONES), 4.f, "elementwise summation");
|
||||||
|
|
||||||
return t.status ();
|
return t.status ();
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#include "tap.hpp"
|
#include "tap.hpp"
|
||||||
#include "types.hpp"
|
#include "types.hpp"
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
main ()
|
main ()
|
||||||
{
|
{
|
||||||
@ -384,8 +385,6 @@ main ()
|
|||||||
success = success && std::equal (std::begin (data), std::end (data), std::begin (t.data[j]));
|
success = success && std::equal (std::begin (data), std::end (data), std::begin (t.data[j]));
|
||||||
};
|
};
|
||||||
|
|
||||||
std::ostringstream os;
|
tap.expect (success, "ARC4 %zu", i);
|
||||||
os << "ARC4: " << i;
|
|
||||||
tap.expect (success, os.str ());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,17 +50,8 @@ main ()
|
|||||||
std::array<uint32_t,2> dec (t.enc);
|
std::array<uint32_t,2> dec (t.enc);
|
||||||
gen.decrypt (dec.data (), dec.size ());
|
gen.decrypt (dec.data (), dec.size ());
|
||||||
|
|
||||||
{
|
tap.expect (enc == t.enc, "TEA_enc %zu", i);
|
||||||
std::ostringstream os;
|
tap.expect (dec == t.dec, "TEA_dec %zu", i);
|
||||||
os << "TEA_enc " << i;
|
|
||||||
tap.expect (enc == t.enc, os.str ());
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
std::ostringstream os;
|
|
||||||
os << "TEA_dec " << i;
|
|
||||||
tap.expect (dec == t.dec, os.str ());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return tap.status ();
|
return tap.status ();
|
||||||
|
@ -49,17 +49,8 @@ main ()
|
|||||||
std::array<uint32_t,2> dec (t.enc);
|
std::array<uint32_t,2> dec (t.enc);
|
||||||
gen.decrypt (dec.data (), dec.size ());
|
gen.decrypt (dec.data (), dec.size ());
|
||||||
|
|
||||||
{
|
tap.expect (enc == t.enc, "XTEA_enc %zu", i);
|
||||||
std::ostringstream os;
|
tap.expect (dec == t.dec, "XTEA_dec %zu", i);
|
||||||
os << "XTEA_enc " << i;
|
|
||||||
tap.expect (enc == t.enc, os.str ());
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
std::ostringstream os;
|
|
||||||
os << "XTEA_dec " << i;
|
|
||||||
tap.expect (dec == t.dec, os.str ());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return tap.status ();
|
return tap.status ();
|
||||||
|
@ -104,17 +104,8 @@ main ()
|
|||||||
std::vector<uint32_t> dec (enc);
|
std::vector<uint32_t> dec (enc);
|
||||||
gen.decrypt (dec.data (), dec.size ());
|
gen.decrypt (dec.data (), dec.size ());
|
||||||
|
|
||||||
{
|
tap.expect (enc == t.enc, "XXTEA_enc %zu", i);
|
||||||
std::ostringstream os;
|
tap.expect (dec == t.dec, "XXTEA_dec %zu", i);
|
||||||
os << "XXTEA_enc " << i;
|
|
||||||
tap.expect (enc == t.enc, os.str ());
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
std::ostringstream os;
|
|
||||||
os << "XXTEA_dec " << i;
|
|
||||||
tap.expect (dec == t.dec, os.str ());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return tap.status ();
|
return tap.status ();
|
||||||
|
@ -16,19 +16,19 @@ test_simple (util::TAP::logger &tap)
|
|||||||
std::ostringstream os;
|
std::ostringstream os;
|
||||||
os << "fixed<" << type_to_string<T> () << ',' << I << ',' << E << '>';
|
os << "fixed<" << type_to_string<T> () << ',' << I << ',' << E << '>';
|
||||||
|
|
||||||
tap.expect_eq (lo, lo, os.str () + " self equality");
|
tap.expect_eq (lo, lo, "%s self equality", os.str ());
|
||||||
tap.expect_eq (hi, hi, os.str () + " self equality");
|
tap.expect_eq (hi, hi, "%s self equality", os.str ());
|
||||||
|
|
||||||
tap.expect_neq (hi, lo, os.str () + " inequality");
|
tap.expect_neq (hi, lo, "%s inequality", os.str ());
|
||||||
tap.expect_neq (lo, hi, os.str () + " inequality");
|
tap.expect_neq (lo, hi, "%s inequality", os.str ());
|
||||||
|
|
||||||
tap.expect_lt (lo, hi, os.str () + " less than");
|
tap.expect_lt (lo, hi, "%s less than", os.str ());
|
||||||
tap.expect_le (lo, hi, os.str () + " less than equal");
|
tap.expect_le (lo, hi, "%s less than equal", os.str ());
|
||||||
tap.expect_le (lo, lo, os.str () + " less than equal");
|
tap.expect_le (lo, lo, "%s less than equal", os.str ());
|
||||||
|
|
||||||
tap.expect_gt (hi, lo, os.str () + " greater than");
|
tap.expect_gt (hi, lo, "%s greater than", os.str ());
|
||||||
tap.expect_ge (lo, lo, os.str () + " greater than equal");
|
tap.expect_ge (lo, lo, "%s greater than equal", os.str ());
|
||||||
tap.expect_ge (hi, lo, os.str () + " greater than equal");
|
tap.expect_ge (hi, lo, "%s greater than equal", os.str ());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
213
test/format.cpp
213
test/format.cpp
@ -2,28 +2,211 @@
|
|||||||
|
|
||||||
#include "tap.hpp"
|
#include "tap.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
|
struct userobj { };
|
||||||
|
|
||||||
|
static std::ostream&
|
||||||
|
operator<< (std::ostream &os, const userobj&)
|
||||||
|
{
|
||||||
|
return os << "userobj";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
///////////////////////////////////////////////////////////////////////////////
|
||||||
int
|
int
|
||||||
main (void)
|
main (void)
|
||||||
{
|
{
|
||||||
using namespace std::string_literals;
|
|
||||||
|
|
||||||
util::TAP::logger tap;
|
util::TAP::logger tap;
|
||||||
|
|
||||||
tap.expect_eq (util::format::render ("identity"), "identity"s, "identity literal");
|
#define CHECK_RENDER(fmt,res,...) do { \
|
||||||
tap.expect_eq (util::format::render ("%s", "identity"s), "identity"s, "identity string substitution");
|
auto val = util::format::render (fmt, ##__VA_ARGS__); \
|
||||||
tap.expect_eq (util::format::render ("%s", "identity" ), "identity"s, "identity char[] substitution");
|
tap.expect_eq (val, res, "render '%s'", fmt); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
tap.expect_throw<util::format::missing_error> ([] (void) {
|
CHECK_RENDER ("foo", "foo");
|
||||||
util::format::render ("%s");
|
|
||||||
}, "missing value");
|
|
||||||
|
|
||||||
tap.expect_throw<util::format::invalid_specifier<int>> ([] (void) {
|
CHECK_RENDER ("%i", "1", 1 );
|
||||||
util::format::render ("%<", 42);
|
CHECK_RENDER ("%3i", " 1", 1 );
|
||||||
}, "invalid specifier");
|
CHECK_RENDER ("%03i", "001", 1 );
|
||||||
|
CHECK_RENDER ("%.i", "", 0);
|
||||||
|
CHECK_RENDER ("% .i", " ", 0); // zero precision still requires a space
|
||||||
|
|
||||||
tap.expect_throw<util::format::format_error> ([] (void) {
|
CHECK_RENDER ("%hhi", "1", (signed char)1);
|
||||||
util::format::render ("%", 42);
|
CHECK_RENDER ("%hi", "1", (signed short)1);
|
||||||
}, "truncated specifier");
|
CHECK_RENDER ("%li", "1", (signed long)1);
|
||||||
|
CHECK_RENDER ("%lli", "1", (signed long long)1);
|
||||||
|
CHECK_RENDER ("%ji", "1", (intmax_t)1);
|
||||||
|
CHECK_RENDER ("%zi", "1", (ssize_t)1);
|
||||||
|
CHECK_RENDER ("%ti", "1", (ptrdiff_t)1);
|
||||||
|
|
||||||
return tap.status ();
|
CHECK_RENDER ("%u", "1", 1u);
|
||||||
|
CHECK_RENDER ("%03u", "001", 1u);
|
||||||
|
CHECK_RENDER ("% u", " 1", 1u);
|
||||||
|
CHECK_RENDER ("% 3u", " 1", 1u);
|
||||||
|
CHECK_RENDER ("% 03u", " 01", 1u);
|
||||||
|
CHECK_RENDER ("%-3u", "1 ", 1u);
|
||||||
|
CHECK_RENDER ("%64u", " 1", 1u);
|
||||||
|
|
||||||
|
CHECK_RENDER ("%hhu", "1", (unsigned char)1);
|
||||||
|
CHECK_RENDER ("%hu", "1", (unsigned short)1);
|
||||||
|
CHECK_RENDER ("%lu", "1", (unsigned long)1);
|
||||||
|
CHECK_RENDER ("%llu", "1", (unsigned long long)1);
|
||||||
|
CHECK_RENDER ("%ju", "1", (uintmax_t)1);
|
||||||
|
CHECK_RENDER ("%zu", "0", (size_t)0);
|
||||||
|
CHECK_RENDER ("%zu", "1", (size_t)1);
|
||||||
|
CHECK_RENDER ("%!", "1", 1u);
|
||||||
|
|
||||||
|
CHECK_RENDER ("%o", "1", 01u);
|
||||||
|
CHECK_RENDER ("%o", "13", 013u);
|
||||||
|
CHECK_RENDER ("%o", "13", 013u);
|
||||||
|
CHECK_RENDER ("%#o", "013", 013u);
|
||||||
|
|
||||||
|
CHECK_RENDER ("%x", "1", 0x1u);
|
||||||
|
CHECK_RENDER ("%x", "fe", 0xfeu);
|
||||||
|
CHECK_RENDER ("%X", "FE", 0xFEu);
|
||||||
|
CHECK_RENDER ("%#x", "0xfe", 0xfeu);
|
||||||
|
CHECK_RENDER ("%#X", "0XFE", 0xFEu);
|
||||||
|
|
||||||
|
CHECK_RENDER ("%e", "1.000000e+00", 1.);
|
||||||
|
CHECK_RENDER ("%e", "1.200000e+00", 1.2);
|
||||||
|
CHECK_RENDER ("%e", "1.234568e+00", 1.2345678);
|
||||||
|
|
||||||
|
CHECK_RENDER ("%E", "1.234568E+00", 1.2345678);
|
||||||
|
|
||||||
|
CHECK_RENDER ("%f", "1.000000", 1.);
|
||||||
|
CHECK_RENDER ("%f", "1.200000", 1.2);
|
||||||
|
CHECK_RENDER ("%f", "1.234560", 1.23456);
|
||||||
|
CHECK_RENDER ("%f", "1.234567", 1.234567);
|
||||||
|
CHECK_RENDER ("%f", "1.234568", 1.2345678);
|
||||||
|
|
||||||
|
CHECK_RENDER ("%g", "1", 1.);
|
||||||
|
CHECK_RENDER ("%g", "1.2", 1.2);
|
||||||
|
CHECK_RENDER ("%g", "1.23457", 1.2345678);
|
||||||
|
CHECK_RENDER ("%g", "0.000123457", 0.00012345678);
|
||||||
|
CHECK_RENDER ("%g", "1.23457e-05", 0.000012345678);
|
||||||
|
CHECK_RENDER ("%G", "1.23457E-05", 0.000012345678);
|
||||||
|
|
||||||
|
CHECK_RENDER ("%+e", "+1.234568e+00", 1.2345678);
|
||||||
|
CHECK_RENDER ("%+f", "+1.234568", 1.2345678);
|
||||||
|
CHECK_RENDER ("%+g", "+1.23457", 1.2345678);
|
||||||
|
CHECK_RENDER ("%+a", "+0x1.3c0ca2a5b1d5dp+0", 1.2345678);
|
||||||
|
|
||||||
|
CHECK_RENDER ("%#.e", "1.e+00", 1.2345678);
|
||||||
|
CHECK_RENDER ("%#.f", "1.", 1.2345678);
|
||||||
|
CHECK_RENDER ("%#.g", "1.", 1.2345678);
|
||||||
|
//CHECK_RENDER ("%#.a", "0x1.p+0", 1.2345678);
|
||||||
|
|
||||||
|
CHECK_RENDER ("%a", "0x1.3c0ca2a5b1d5dp+0", 1.2345678);
|
||||||
|
CHECK_RENDER ("%A", "0X1.3C0CA2A5B1D5DP+0", 1.2345678);
|
||||||
|
|
||||||
|
CHECK_RENDER ("%e", "inf", std::numeric_limits<double>::infinity ());
|
||||||
|
CHECK_RENDER ("%E", "INF", std::numeric_limits<double>::infinity ());
|
||||||
|
CHECK_RENDER ("%f", "inf", std::numeric_limits<double>::infinity ());
|
||||||
|
CHECK_RENDER ("%F", "INF", std::numeric_limits<double>::infinity ());
|
||||||
|
CHECK_RENDER ("%g", "inf", std::numeric_limits<double>::infinity ());
|
||||||
|
CHECK_RENDER ("%G", "INF", std::numeric_limits<double>::infinity ());
|
||||||
|
CHECK_RENDER ("%a", "inf", std::numeric_limits<double>::infinity ());
|
||||||
|
CHECK_RENDER ("%A", "INF", std::numeric_limits<double>::infinity ());
|
||||||
|
|
||||||
|
CHECK_RENDER ("%e", "nan", std::numeric_limits<double>::quiet_NaN ());
|
||||||
|
CHECK_RENDER ("%E", "NAN", std::numeric_limits<double>::quiet_NaN ());
|
||||||
|
CHECK_RENDER ("%f", "nan", std::numeric_limits<double>::quiet_NaN ());
|
||||||
|
CHECK_RENDER ("%F", "NAN", std::numeric_limits<double>::quiet_NaN ());
|
||||||
|
CHECK_RENDER ("%g", "nan", std::numeric_limits<double>::quiet_NaN ());
|
||||||
|
CHECK_RENDER ("%G", "NAN", std::numeric_limits<double>::quiet_NaN ());
|
||||||
|
CHECK_RENDER ("%a", "nan", std::numeric_limits<double>::quiet_NaN ());
|
||||||
|
CHECK_RENDER ("%A", "NAN", std::numeric_limits<double>::quiet_NaN ());
|
||||||
|
|
||||||
|
CHECK_RENDER ("%.f", "1", 1.2345678);
|
||||||
|
CHECK_RENDER ("%3.f", " 1", 1.2345678);
|
||||||
|
CHECK_RENDER ("%3.2f", "1.23", 1.2345678);
|
||||||
|
CHECK_RENDER ("%3.2f", "1234.57", 1234.5678);
|
||||||
|
|
||||||
|
CHECK_RENDER ("%!", "1", 1.);
|
||||||
|
|
||||||
|
CHECK_RENDER ("%c", "A", 'A');
|
||||||
|
CHECK_RENDER ("%!", "A", 'A');
|
||||||
|
|
||||||
|
CHECK_RENDER ("%s", "foo", "foo");
|
||||||
|
CHECK_RENDER ("%s", "foo", std::string ("foo"));
|
||||||
|
CHECK_RENDER ("%s", "foo", const_cast<char*> ("foo"));
|
||||||
|
CHECK_RENDER ("%.s", "", "foo");
|
||||||
|
CHECK_RENDER ("%.0s", "", "foo");
|
||||||
|
CHECK_RENDER ("%.2s", "fo", "foo");
|
||||||
|
CHECK_RENDER ("%.02s", "fo", "foo");
|
||||||
|
CHECK_RENDER ("%.64s", "foo", "foo");
|
||||||
|
CHECK_RENDER ("%3.1s", " f", "foo");
|
||||||
|
CHECK_RENDER ("%-3.1s", "f ", "foo");
|
||||||
|
CHECK_RENDER ("%!", "foo", "foo");
|
||||||
|
|
||||||
|
CHECK_RENDER ("%!", "userobj", userobj {});
|
||||||
|
|
||||||
|
CHECK_RENDER ("%p", "0x1234567", (void*)0x01234567);
|
||||||
|
CHECK_RENDER ("%p", "0x1234567", (int*)0x01234567);
|
||||||
|
CHECK_RENDER ("%p", "0x1234567", (char*)0x01234567);
|
||||||
|
CHECK_RENDER ("%p", "(nil)", nullptr);
|
||||||
|
CHECK_RENDER ("%p", "(nil)", NULL);
|
||||||
|
CHECK_RENDER ("%!", "0x1234567", (void*)0x01234567);
|
||||||
|
|
||||||
|
CHECK_RENDER ("%%", "%");
|
||||||
|
CHECK_RENDER ("%10%", "%");
|
||||||
|
CHECK_RENDER ("%.%", "%");
|
||||||
|
CHECK_RENDER ("% 0-+#12.34%", "%"); // escaped conversions should largely ignore flags, width, and precision.
|
||||||
|
|
||||||
|
// multiple components
|
||||||
|
CHECK_RENDER ("%%%%", "%%");
|
||||||
|
|
||||||
|
CHECK_RENDER (" %%", " %");
|
||||||
|
CHECK_RENDER ("%% ", "% ");
|
||||||
|
CHECK_RENDER ("%% %%", "% %");
|
||||||
|
CHECK_RENDER (" %% %% ", " % % ");
|
||||||
|
|
||||||
|
CHECK_RENDER ("%u %u", "1 2", 1u, 2u);
|
||||||
|
|
||||||
|
CHECK_RENDER ("%#o %o", "010 10", 8u, 8u);
|
||||||
|
CHECK_RENDER ("%#o %o %#o", "010 10 010", 8u, 8u, 8u);
|
||||||
|
CHECK_RENDER ("%X%x%X", "FfF", 0xfu, 0xfu, 0xfu);
|
||||||
|
|
||||||
|
tap.expect_eq (util::format::render ("%u\n", 1u), "1\n", "newline");
|
||||||
|
|
||||||
|
#define CHECK_THROW(fmt,except,...) do { \
|
||||||
|
tap.expect_throw<util::format::except> ([&] { \
|
||||||
|
util::format::render (fmt, ##__VA_ARGS__); \
|
||||||
|
}, "exception '%s' for format '%s'", #except, fmt); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
CHECK_THROW("%", syntax_error);
|
||||||
|
CHECK_THROW("%_", syntax_error);
|
||||||
|
CHECK_THROW("%_u", syntax_error);
|
||||||
|
|
||||||
|
CHECK_THROW("%u", missing_error);
|
||||||
|
CHECK_THROW("%!", missing_error);
|
||||||
|
|
||||||
|
CHECK_THROW("%d", conversion_error, 1u);
|
||||||
|
CHECK_THROW("%i", conversion_error, 1u);
|
||||||
|
CHECK_THROW("%i", conversion_error, nullptr);
|
||||||
|
|
||||||
|
CHECK_THROW("%hhi", length_error, (long long)1);
|
||||||
|
//CHECK_THROW("%lli", length_error, (signed char)1);
|
||||||
|
|
||||||
|
CHECK_THROW("%u", conversion_error, 1.);
|
||||||
|
CHECK_THROW("%u", conversion_error, "foo");
|
||||||
|
CHECK_THROW("%u", conversion_error, (void*)0);
|
||||||
|
CHECK_THROW("%u", conversion_error, 1);
|
||||||
|
CHECK_THROW("%u", conversion_error, nullptr);
|
||||||
|
|
||||||
|
CHECK_THROW("%hhu", length_error, (unsigned long long)1);
|
||||||
|
//CHECK_THROW("%llu", length_error, (unsigned char)1);
|
||||||
|
|
||||||
|
CHECK_THROW("%f", conversion_error, 1u);
|
||||||
|
CHECK_THROW("%f", conversion_error, "foo");
|
||||||
|
CHECK_THROW("%f", conversion_error, nullptr);
|
||||||
|
|
||||||
|
CHECK_THROW("%s", conversion_error, 1u);
|
||||||
|
CHECK_THROW("%s", conversion_error, '_');
|
||||||
|
CHECK_THROW("%s", conversion_error, nullptr);
|
||||||
|
|
||||||
|
CHECK_THROW("%c", conversion_error, 1u);
|
||||||
|
CHECK_THROW("%c", conversion_error, "foo");
|
||||||
}
|
}
|
||||||
|
@ -274,7 +274,7 @@ main (int, char**)
|
|||||||
util::TAP::logger tap;
|
util::TAP::logger tap;
|
||||||
|
|
||||||
for (size_t i = 0; i < elems (TESTS); ++i)
|
for (size_t i = 0; i < elems (TESTS); ++i)
|
||||||
tap.expect (TESTS[i].fun (TESTS[i].key, TESTS[i].dat, TESTS[i].res), "standard test vector %u", i);
|
tap.expect (TESTS[i].fun (TESTS[i].key, TESTS[i].dat, TESTS[i].res), "standard test vector %zu", i);
|
||||||
|
|
||||||
return tap.status ();
|
return tap.status ();
|
||||||
}
|
}
|
||||||
|
@ -116,7 +116,7 @@ main(int, char**) {
|
|||||||
obj.update (reinterpret_cast<const uint8_t*> (i.data), strlen (i.data));
|
obj.update (reinterpret_cast<const uint8_t*> (i.data), strlen (i.data));
|
||||||
obj.finish ();
|
obj.finish ();
|
||||||
|
|
||||||
tap.expect_eq (obj.digest (), i.output, i.msg);
|
tap.expect_eq (obj.digest (), i.output, "%s", i.msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Perform 'million-a' check
|
// Perform 'million-a' check
|
||||||
|
@ -66,7 +66,7 @@ main (int, char**)
|
|||||||
obj.update (reinterpret_cast<const uint8_t*> (i.input), strlen (i.input));
|
obj.update (reinterpret_cast<const uint8_t*> (i.input), strlen (i.input));
|
||||||
obj.finish ();
|
obj.finish ();
|
||||||
|
|
||||||
tap.expect_eq (obj.digest (), i.output, i.msg);
|
tap.expect_eq (obj.digest (), i.output, "%s", i.msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
return tap.status ();
|
return tap.status ();
|
||||||
|
@ -55,7 +55,7 @@ main (int, char **) {
|
|||||||
obj.update (reinterpret_cast<const uint8_t*> (i.input), strlen (i.input));
|
obj.update (reinterpret_cast<const uint8_t*> (i.input), strlen (i.input));
|
||||||
obj.finish ();
|
obj.finish ();
|
||||||
|
|
||||||
tap.expect_eq (obj.digest (), i.output, i.msg);
|
tap.expect_eq (obj.digest (), i.output, "%s", i.msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
return tap.status ();
|
return tap.status ();
|
||||||
|
10
test/ip.cpp
10
test/ip.cpp
@ -23,9 +23,8 @@ test_good (util::TAP::logger &tap)
|
|||||||
{ "127.0.0.1", { 127, 0, 0, 1 }, "localhost" }
|
{ "127.0.0.1", { 127, 0, 0, 1 }, "localhost" }
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const auto &i: TESTS) {
|
for (const auto &i: TESTS)
|
||||||
tap.expect_eq (ipv4::ip::parse (i.str), i.ip, i.msg);
|
tap.expect_eq (ipv4::ip::parse (i.str), i.ip, "%s", i.msg);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -43,9 +42,8 @@ test_bad (util::TAP::logger &tap)
|
|||||||
{ "256.0.0.1", "overflow" }
|
{ "256.0.0.1", "overflow" }
|
||||||
};
|
};
|
||||||
|
|
||||||
for (const auto &i: TESTS) {
|
for (const auto &i: TESTS)
|
||||||
tap.expect_throw<ipv4::error> ([&] { ipv4::ip::parse (i.str); }, i.msg);
|
tap.expect_throw<ipv4::error> ([&] { ipv4::ip::parse (i.str); }, "%s", i.msg);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
1
test/json/schema/signed_min.schema
Normal file
1
test/json/schema/signed_min.schema
Normal file
@ -0,0 +1 @@
|
|||||||
|
{ "type": "number", "minimum": -1 }
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user