From c4daffc001e8aaaa40869433bd86b34fec51bd19 Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Wed, 27 Jul 2016 13:21:37 +1000 Subject: [PATCH 001/100] build: add forgotten includes --- colour.cpp | 9 +++++---- hash/sha1.cpp | 5 +++-- memory/buffer/circular.cpp | 3 ++- quaternion.cpp | 1 + 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/colour.cpp b/colour.cpp index 4d0e5c1d..42b99bfa 100644 --- a/colour.cpp +++ b/colour.cpp @@ -14,11 +14,12 @@ * Copyright 2010-2016 Danny Robson */ -#include "colour.hpp" +#include "./colour.hpp" -#include "range.hpp" -#include "random.hpp" -#include "stream.hpp" +#include "./debug.hpp" +#include "./range.hpp" +#include "./random.hpp" +#include "./stream.hpp" #include #include diff --git a/hash/sha1.cpp b/hash/sha1.cpp index 25243082..2c6995fb 100644 --- a/hash/sha1.cpp +++ b/hash/sha1.cpp @@ -26,6 +26,7 @@ #include #include #include +#include using util::hash::SHA1; @@ -36,8 +37,8 @@ std::ostream& operator<< (std::ostream &os, SHA1::state_t t) { switch (t) { - case SHA1::READY: os << "READY"; return os; - case SHA1::FINISHED: os << "FINISHED"; return os; + case SHA1::READY: return os << "READY"; + case SHA1::FINISHED: return os << "FINISHED"; } unreachable (); diff --git a/memory/buffer/circular.cpp b/memory/buffer/circular.cpp index a89571fd..0195d76e 100644 --- a/memory/buffer/circular.cpp +++ b/memory/buffer/circular.cpp @@ -17,9 +17,10 @@ #include "./circular.hpp" #include "../system.hpp" +#include "../../debug.hpp" #include "../../except.hpp" -#include "../../raii.hpp" #include "../../maths.hpp" +#include "../../raii.hpp" #include "../../random.hpp" #include diff --git a/quaternion.cpp b/quaternion.cpp index 6002c9dc..fc42e7da 100644 --- a/quaternion.cpp +++ b/quaternion.cpp @@ -17,6 +17,7 @@ #include "quaternion.hpp" +#include "debug.hpp" #include "maths.hpp" From ef0fb30c8a16839d9d0a7274f64783ed96a68ca0 Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Thu, 28 Jul 2016 13:27:39 +1000 Subject: [PATCH 002/100] ascii: add constexpr ascii manipulators --- Makefile.am | 1 + ascii.hpp | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 ascii.hpp diff --git a/Makefile.am b/Makefile.am index a8742402..c9ff4446 100644 --- a/Makefile.am +++ b/Makefile.am @@ -32,6 +32,7 @@ UTIL_FILES = \ alloc/null.hpp \ alloc/stack.cpp \ alloc/stack.hpp \ + ascii.hpp \ backtrace.hpp \ bezier.cpp \ bezier.hpp \ diff --git a/ascii.hpp b/ascii.hpp new file mode 100644 index 00000000..0d1daebf --- /dev/null +++ b/ascii.hpp @@ -0,0 +1,57 @@ +/* + * 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 + */ + +#ifndef __CRUFT_UTIL_ASCII_HPP +#define __CRUFT_UTIL_ASCII_HPP + +namespace util { namespace ascii { + /////////////////////////////////////////////////////////////////////////// + constexpr inline + bool + is_digit (char c) noexcept + { + return c >= '0' && c <= '9'; + } + + + //------------------------------------------------------------------------- + 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'; + } +} } + +#endif From f9fb0873d35b3744629aa4ef1dc79db2100a7f7d Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Thu, 28 Jul 2016 13:31:52 +1000 Subject: [PATCH 003/100] build: tidy system headers --- json/tree.cpp | 1 - test/colour.cpp | 1 + view.cpp | 2 ++ 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/json/tree.cpp b/json/tree.cpp index c05b198d..f7aae124 100644 --- a/json/tree.cpp +++ b/json/tree.cpp @@ -30,7 +30,6 @@ #include #include #include -#include #include #include diff --git a/test/colour.cpp b/test/colour.cpp index 91c22c21..3dc20f4f 100644 --- a/test/colour.cpp +++ b/test/colour.cpp @@ -2,6 +2,7 @@ #include "tap.hpp" + int main (int, char**) { diff --git a/view.cpp b/view.cpp index 4bd11bde..6eea40d4 100644 --- a/view.cpp +++ b/view.cpp @@ -16,6 +16,8 @@ #include "./view.hpp" +#include + /////////////////////////////////////////////////////////////////////////////// #define EQUALITY(A,B) \ From 8cc4c1e82a9e35b651dfc171e694fecf96c391b0 Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Thu, 28 Jul 2016 13:36:23 +1000 Subject: [PATCH 004/100] format: reimplement format rendering requires literal string arrays, and implements more of the specifier specification. does not implement 'n' or '$' specifiers. falls back to snprintf for real arguments. --- debug.hpp | 5 +- debug.ipp | 14 +- format.cpp | 56 ++ format.hpp | 71 ++- format.ipp | 1067 +++++++++++++++++++++++++++++++------- log.hpp | 4 +- log.ipp | 6 +- maths.cpp | 20 - maths.hpp | 49 +- tap.hpp | 44 +- tap.ipp | 84 ++- test/cmdopt.cpp | 4 +- test/colour.cpp | 4 +- test/crypto/arc4.cpp | 5 +- test/crypto/tea.cpp | 13 +- test/crypto/xtea.cpp | 13 +- test/crypto/xxtea.cpp | 13 +- test/fixed.cpp | 20 +- test/format.cpp | 191 ++++++- test/hash/hmac.cpp | 2 +- test/hash/ripemd.cpp | 2 +- test/hash/sha1.cpp | 2 +- test/hash/sha2.cpp | 2 +- test/ip.cpp | 10 +- test/polynomial.cpp | 2 +- test/roots/bisection.cpp | 2 +- test/vector.cpp | 4 +- test/version.cpp | 2 +- 28 files changed, 1301 insertions(+), 410 deletions(-) diff --git a/debug.hpp b/debug.hpp index c9b84114..82e00ffa 100644 --- a/debug.hpp +++ b/debug.hpp @@ -286,8 +286,9 @@ /////////////////////////////////////////////////////////////////////////////// constexpr void panic [[noreturn]] (const char*); -template -constexpr void panic [[noreturn]] (const char *fmt, const Args&...); +template +constexpr +void panic [[noreturn]] (const char (&fmt)[N], const Args&...); /////////////////////////////////////////////////////////////////////////////// diff --git a/debug.ipp b/debug.ipp index 80f97f57..9720bbc1 100644 --- a/debug.ipp +++ b/debug.ipp @@ -28,9 +28,13 @@ namespace util { namespace debug { namespace detail { void panic [[noreturn]] (const char *msg); - template - void panic [[noreturn]] (const char *msg, const Args& ...args) - { panic (util::format::render (msg, args...).c_str ()); } + template + constexpr + 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 unreachable [[noreturn]] (const char *msg); @@ -92,10 +96,10 @@ constexpr void panic [[noreturn]] (const char *msg) //----------------------------------------------------------------------------- -template +template constexpr void -panic [[noreturn]] (const char *fmt, const Args& ...args) +panic [[noreturn]] (const char (&fmt)[N], const Args& ...args) { ! fmt ? panic ("unreachable constexpr panic helper") diff --git a/format.cpp b/format.cpp index 78104472..7c9808e0 100644 --- a/format.cpp +++ b/format.cpp @@ -17,3 +17,59 @@ #include "format.hpp" #include + + +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 << + " }"; + } +} } } diff --git a/format.hpp b/format.hpp index 3947a18e..7828d009 100644 --- a/format.hpp +++ b/format.hpp @@ -11,7 +11,7 @@ * See the License for the specific language governing permissions and * limitations under the License. * - * Copyright 2015-2016 Danny Robson + * Copyright 2016 Danny Robson */ #ifndef __UTIL_FORMAT_HPP @@ -20,41 +20,56 @@ #include #include -namespace util { - namespace format { - template - std::string - render (const std::string &fmt, Args&&...); +namespace util { namespace format { + //------------------------------------------------------------------------- + // 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 + std::string + render (const char (&fmt)[N], const Args&...); - class error : public std::runtime_error - { using runtime_error::runtime_error; }; + //------------------------------------------------------------------------- + class error : public std::runtime_error + { using runtime_error::runtime_error; }; - // value-specifier mismatch - class value_error : public error - { using error::error; }; + // value-specifier mismatch + class value_error : public error + { using error::error; }; - // malformed format specifier - class format_error : public error - { using error::error; }; + struct conversion_error : public error + { using error::error; }; - template - class invalid_specifier : public format_error { - public: - using value_type = ValueT; + struct length_error : public error + { using error::error; }; - invalid_specifier (char specifier); + // malformed format specifier + class syntax_error : public error + { using error::error; }; - char specifier (void) const; + template + class invalid_specifier : error { + public: + using value_type = ValueT; - private: - char m_specifier; - }; + invalid_specifier (char specifier); - // missing format specifier - class missing_error : public error - { using error::error; }; - } -} + char specifier (void) const; + + private: + char m_specifier; + }; + + // missing format specifier + class missing_error : public error + { + public: + missing_error (): + error ("missing argument for specifier") + { ; } + }; +} } #include "format.ipp" diff --git a/format.ipp b/format.ipp index 3394a228..c740e1c8 100644 --- a/format.ipp +++ b/format.ipp @@ -14,207 +14,900 @@ * Copyright 2015-2016 Danny Robson */ -#if defined(__UTIL_FORMAT_IPP) -#error -#endif -#define __UTIL_FORMAT_IPP +#include "./ascii.hpp" +#include "./debug.hpp" +#include "./maths.hpp" -#include "debug.hpp" - -#include +#include +#include #include -#include -#include -#include - -namespace util { - namespace detail { namespace format { - /////////////////////////////////////////////////////////////////////// - template - inline bool - is_type_specifier (const char*) - { return false; } - //--------------------------------------------------------------------- - template <> - inline bool - is_type_specifier (const char *s) - { return *s == 'c'; } +namespace util { namespace format { namespace detail { + /////////////////////////////////////////////////////////////////////////// + // GCC: workaround which allows a throw to appear in constexpr codepaths + // that do not execute at compile time. See gcc#67371 + template + constexpr void + constexpr_throw [[noreturn]] (Args&& ...args) + { + ! true + ? constexpr_throw (std::forward (args)...) + : throw ExceptT (std::forward (args)...); + } - //--------------------------------------------------------------------- - template <> - inline bool - is_type_specifier (const char *s) - { return *s == 's'; } - - - //--------------------------------------------------------------------- - template <> - inline bool - is_type_specifier (const char *s) - { return *s == 's'; } - - - //--------------------------------------------------------------------- - template <> - inline bool - is_type_specifier (const char *s) - { return *s == 's'; } - - - //--------------------------------------------------------------------- - template <> - inline bool - is_type_specifier (const char *s) - { return *s == 's'; } - - - //--------------------------------------------------------------------- - template <> - inline bool - is_type_specifier (const char *s) - { return *s == 'u' || *s == 'x'; } - - - //--------------------------------------------------------------------- - template <> - inline bool - is_type_specifier (const char *s) - { return *s == 'u' || *s == 'x'; } - - - //--------------------------------------------------------------------- - template <> - inline bool - is_type_specifier (const char *s) - { - return *s == 'i' || *s == 'd' || *s == 'x'; - } - - - //--------------------------------------------------------------------- - template <> - inline bool - is_type_specifier (const char *s) - { - switch (*s) { - case 'e': - case 'E': - case 'f': - case 'F': - case 'g': - case 'G': - case 'a': - case 'A': - return true; - - default: - return false; - } - } - - - /////////////////////////////////////////////////////////////////////// - template - inline bool - is_valid_specifier (const char *s) - { - return *s == '!' || is_type_specifier (s); - } - - - /////////////////////////////////////////////////////////////////////// - template - void - render (InputIt first, - InputIt last, - std::ostringstream &dest) - { - static const char DELIMITER = '%'; - if (std::find (first, last, DELIMITER) != last) - throw util::format::missing_error ("format specifier without value"); - - std::copy (first, last, std::ostream_iterator (dest)); - } - - - //--------------------------------------------------------------------- - template - void - render (InputIt first, - InputIt last, - std::ostringstream &dest, - const ValueT& val, - Args&& ...args) - { - CHECK (first <= last); - - using namespace std::literals; - - static const char DELIMITER = '%'; - auto cursor = std::find (first, last, DELIMITER); - std::copy (first, cursor, std::ostream_iterator (dest)); - - if (cursor == last) - return; - - auto spec = cursor + 1; - if (spec == last) - throw util::format::format_error ("missing format specifier"s); - - if (!is_valid_specifier::type> (&*spec)) - throw util::format::invalid_specifier (*spec); - - if (*spec == 'x') { - dest << std::hex << val << std::dec; - } else - dest << val; - - render (spec + 1, last, dest, std::forward (args)...); - } - } } - /////////////////////////////////////////////////////////////////////////// - namespace format { - template - std::string - render (const std::string &fmt, Args&&... args) - { - std::ostringstream out; + // record all formatting information for a specifier. + // + // does not record redundant/unneeded information, and will default values + // like width and precision, so may not guarantee round-trip to/from + // string specifiers. + struct specifier { + bool alternate_form = false; + bool left_adjusted = false; + bool thousands_grouping = false; - util::detail::format::render ( - fmt.begin (), - fmt.end (), - out, - std::forward (args)... - ); + char padding_char = ' '; + char positive_char = '\0'; - return out.str (); + bool uppercase = false; + + // the rendered base for the value. + // 8 for octal + // 16 for hex + // 10 for decimal + // + // other values are theoretically supportable, but do not form part of + // the printf specification. + unsigned base = 10; + + enum class repr { + FIXED, + SCIENTIFIC, + AUTO + } r = repr::AUTO; + + enum class kind { + UNSIGNED, + SIGNED, + REAL, + + STRING, + POINTER, + CHARACTER, + ESCAPE, + + OSTREAM + } k; + + unsigned width = 0; // field width, ie: how many characters + int precision = -1; // how many digits after the decimal + + size_t length = 0; // bytesize of underlying type + }; + + + /////////////////////////////////////////////////////////////////////////// + // provides the kind, a conversion specifier, and expected length for a + // given type. + // + // the conversion specifier is only one valid specifier. there may be + // multiple valid values, eg 'd' and 'i' for signed integers; or 'e', 'f', + // 'g', and 'a' for reals. + template + struct specifier_traits { + static constexpr specifier::kind kind = specifier::kind::OSTREAM; + static constexpr char conversion = '!'; + static constexpr unsigned length = sizeof (T); + }; + + #define MAKE_SPECIFIER_TRAIT(NATIVE,KIND,CONV) \ + template <> \ + struct specifier_traits { \ + static constexpr specifier::kind kind = specifier::kind:: KIND; \ + static constexpr char conversion = CONV; \ + static constexpr unsigned length = sizeof (NATIVE); \ + }; + + MAKE_SPECIFIER_TRAIT(uint8_t, UNSIGNED,'u'); + MAKE_SPECIFIER_TRAIT(uint16_t,UNSIGNED,'u'); + MAKE_SPECIFIER_TRAIT(uint32_t,UNSIGNED,'u'); + MAKE_SPECIFIER_TRAIT(uint64_t,UNSIGNED,'u'); + + MAKE_SPECIFIER_TRAIT(int8_t, SIGNED,'i'); + MAKE_SPECIFIER_TRAIT(int16_t,SIGNED,'i'); + MAKE_SPECIFIER_TRAIT(int32_t,SIGNED,'i'); + MAKE_SPECIFIER_TRAIT(int64_t,SIGNED,'i'); + + MAKE_SPECIFIER_TRAIT(float,REAL,'g'); + MAKE_SPECIFIER_TRAIT(double,REAL,'g'); + + MAKE_SPECIFIER_TRAIT(char*,STRING,'s'); + MAKE_SPECIFIER_TRAIT(const char*,STRING,'s'); + MAKE_SPECIFIER_TRAIT(const unsigned char*,STRING,'s'); + + MAKE_SPECIFIER_TRAIT(char,CHARACTER,'c'); + MAKE_SPECIFIER_TRAIT(void*,POINTER,'p'); + + template + struct specifier_traits { + static constexpr specifier::kind kind = specifier::kind::STRING; + static constexpr char conversion = 's'; + static constexpr unsigned length = sizeof (const char*); + }; + + #undef MAKE_SPECIFIER_TRAIT + + + /////////////////////////////////////////////////////////////////////////// + static constexpr + specifier::kind + to_kind (const char c) + { + switch (c) { + case 'd': + case 'i': + return specifier::kind::SIGNED; + + case 'u': + case 'o': + case 'x': + case 'X': + return specifier::kind::UNSIGNED; + + case 'e': + case 'E': + case 'f': + case 'F': + case 'g': + case 'G': + case 'a': + case 'A': + return specifier::kind::REAL; + + case 'c': + case 'C': + return specifier::kind::CHARACTER; + + case 's': + case 'S': + return specifier::kind::STRING; + + case 'p': + return specifier::kind::POINTER; + + case '%': + return specifier::kind::ESCAPE; + + case '!': + return specifier::kind::OSTREAM; + } + + constexpr_throw ("invalid conversion specifier"); + } + + + //------------------------------------------------------------------------- + inline constexpr + size_t + length (specifier::kind k) + { + switch (k) { + case specifier::kind::SIGNED: return sizeof (int); + case specifier::kind::UNSIGNED: return sizeof (unsigned); + case specifier::kind::REAL: return sizeof (double); + case specifier::kind::CHARACTER: return sizeof (char); + case specifier::kind::STRING: return sizeof (const char*); + case specifier::kind::POINTER: return sizeof (void*); + case specifier::kind::ESCAPE: return 0; + case specifier::kind::OSTREAM: return 0; + } + + unreachable (); + } + + + //------------------------------------------------------------------------- + inline constexpr + int + precision (specifier &s) + { + switch (s.k) { + case specifier::kind::SIGNED: + case specifier::kind::UNSIGNED: + return 1; + + case specifier::kind::REAL: + if (s.base != 16) + return 6; + else + return -1; + + case specifier::kind::STRING: + return std::numeric_limits::max (); + + case specifier::kind::POINTER: + case specifier::kind::CHARACTER: + case specifier::kind::ESCAPE: + case specifier::kind::OSTREAM: + return 0; + } + + unreachable (); + } + + + //------------------------------------------------------------------------- + inline constexpr + specifier::repr + repr (const char c) + { + switch (c) { + case 'e': + case 'E': + return specifier::repr::SCIENTIFIC; + + case 'f': + case 'F': + return specifier::repr::FIXED; + + default: + return specifier::repr::AUTO; + } + } + + + //------------------------------------------------------------------------- + inline constexpr + unsigned + base (const char c) + { + switch (c) { + case 'o': + return 8; + + case 'x': + case 'X': + case 'a': + case 'A': + return 16; + + default: + return 10; } } /////////////////////////////////////////////////////////////////////////// - // TODO: we'd like to use typeid here for type naming, but we don't allow - // RTTI. revisit this when introspection is more advanced. - template - format::invalid_specifier::invalid_specifier (char _specifier): - format_error ( - format::render ("invalid specifier '%c' for type '%s'", - _specifier, - "unimplemented") - ), - m_specifier (_specifier) - { ; } + // returns the count of specifiers within the range. + // + // if the string is not a valid format string the count may be slightly high; + // particularly in cases of truncation. + inline constexpr + size_t + specifier_count (const char *first, const char *last) + { + size_t count = 0; + + for (auto cursor = first; cursor != last; ++cursor) { + if (*cursor != '%') + continue; + + ++cursor; + if (cursor == last) + return 1; + + ++count; + } + + return count; + } //------------------------------------------------------------------------- - template - char - format::invalid_specifier::specifier (void) const - { return m_specifier; } -} + template + inline constexpr + size_t + specifier_count (const char (&fmt)[N]) + { + return specifier_count (fmt, fmt + N); + } + + + + /////////////////////////////////////////////////////////////////////////// + // parses a format specifier into the details struct + // + // * first:last must form a contiguous range + // * first must be the first character of a specifier, ie a % + // + // returns the character after the last character of the specifier + // + // throws on an invalid specifier (including a truncated specifier) + constexpr + const char* + parse (const char *first, const char *last, specifier &spec) + { + if (last - first < 2) + constexpr_throw ("specifiers require at least two characters"); + + if (*first != '%') + constexpr_throw ("specifiers must start with %"); + + auto cursor = first + 1; + + // read the format flags + for (bool more_flags = true; more_flags; ) { + switch (*cursor) { + case '#': spec.alternate_form = true; ++cursor; break; + case '0': spec.padding_char = '0'; ++cursor; break; + case '-': spec.left_adjusted = true; ++cursor; break; + case ' ': spec.positive_char = ' '; ++cursor; break; + case '+': spec.positive_char = '+'; ++cursor; break; + // ''', thousands grouping + + default: + more_flags = false; + break; + } + } + + // read the width + spec.width = 0; + while (1) { + if (!ascii::is_digit (*cursor)) + break; + + spec.width *= 10; + spec.width += *cursor - '0'; + ++cursor; + } + + // read the precision + if (*cursor == '.') { + ++cursor; + spec.precision = 0; + + while (1) { + if (!ascii::is_digit (*cursor)) + break; + + spec.precision *= 10; + spec.precision += *cursor - '0'; + ++cursor; + } + } + + // read the length modifiers + // TODO: ensure these values make sense given the conversion + // specifier about to come. + switch (*cursor) { + case 'h': { + spec.length = sizeof (short); + ++cursor; + + if (*cursor == 'h') { + spec.length = sizeof (char); + ++cursor; + } + + break; + } + + case 'l': { + spec.length = sizeof (long); + ++cursor; + + if (*cursor == 'l') { + spec.length = sizeof (long long); + ++cursor; + } + + break; + } + + case 'L': spec.length = sizeof (long double); ++cursor; break; + case 'j': spec.length = sizeof (uintmax_t); ++cursor; break; + case 'z': spec.length = sizeof (size_t); ++cursor; break; + case 't': spec.length = sizeof (ptrdiff_t); ++cursor; break; + default: + break; + } + + // read the conversion specifier + auto conv = *cursor++; + spec.k = to_kind (conv); + spec.length = spec.length ?: length (spec.k); + spec.uppercase = ascii::is_upper (conv); + spec.base = base (conv); + spec.r = repr (conv); + if (spec.precision < 0) + spec.precision = precision (spec); + + return cursor; + } + + + //------------------------------------------------------------------------- + template + constexpr + auto + parse (const char (&fmt)[N], specifier &spec) + { + return parse (fmt, fmt + N, spec); + } + + + + /////////////////////////////////////////////////////////////////////////// + template + struct conversion_traits; + + #define CONVERSION_TRAITS(VALUE,TYPE,UPPER) \ + template <> struct conversion_traits { \ + using value_type = TYPE; \ + static constexpr bool is_upper = UPPER; \ + }; + + CONVERSION_TRAITS ('d', int, false) + CONVERSION_TRAITS ('i', int, false) + + CONVERSION_TRAITS ('u', unsigned, false) + CONVERSION_TRAITS ('o', unsigned, false) + CONVERSION_TRAITS ('x', unsigned, false) + CONVERSION_TRAITS ('X', unsigned, true) + + CONVERSION_TRAITS ('e', double, false) + CONVERSION_TRAITS ('E', double, true) + CONVERSION_TRAITS ('f', double, false) + CONVERSION_TRAITS ('F', double, true) + CONVERSION_TRAITS ('g', double, false) + CONVERSION_TRAITS ('G', double, true) + CONVERSION_TRAITS ('a', double, false) + CONVERSION_TRAITS ('A', double, true) + + CONVERSION_TRAITS ('c', char, false) + + CONVERSION_TRAITS ('s', char*, false) + CONVERSION_TRAITS ('p', void*, false) + + CONVERSION_TRAITS ('%', void, false) + + + /////////////////////////////////////////////////////////////////////////// + // calculates the length of a fully rendered specifier/value, or format + // string and parameters. does not include any trailing null. + template + std::enable_if_t::value, size_t> + format_length (const specifier &s, const T &t) + { + return digits (t, s.base); + } + + + //------------------------------------------------------------------------- + inline constexpr + size_t + format_length (const specifier&, const char *str) + { + auto cursor = str; + while (*cursor != '\0') + ++cursor; + + return cursor - str; + } + + + //------------------------------------------------------------------------- + inline + size_t + format_length (const char *first, const char *last) + { + size_t length = 0; + + for (auto cursor = first; cursor != last; ++cursor) { + if (*cursor != '%') { + ++length; + continue; + } + + specifier spec {}; + cursor = parse (cursor, last, spec); + + if (spec.k != specifier::kind::ESCAPE) + unreachable (); + + ++length; + } + + return length; + } + + + //------------------------------------------------------------------------- + template + inline + size_t + format_length (const char *first, const char *last, ValueT value, Args&& ...args) + { + size_t length = 0; + + for (auto cursor = first; cursor != last; ++cursor) { + if (*cursor != '%') { + ++length; + continue; + } + + specifier spec {}; + cursor = parse (cursor, last, spec); + + return + length + + format_length (spec, value) + ( + (spec.k == specifier::kind::ESCAPE) ? + format_length (cursor, last, value, std::forward (args)...) : + format_length (cursor, last, std::forward (args)...) + ); + } + + return length; + } + + + //------------------------------------------------------------------------- + template + inline + size_t + format_length (const char (&fmt)[N], const Args& ...args) + { + if (N <= 1) + return 0; + + return format_length (fmt, fmt + N - 1, args...); + } + + + //------------------------------------------------------------------------- + template + inline + size_t + format_length (const char (&fmt)[N]) + { + if (N <= 1) + return 0; + + return format_length (fmt, fmt + N - 1); + } + + + /////////////////////////////////////////////////////////////////////////// + // render a single value to an ostream given the parsed specifier + + //------------------------------------------------------------------------- + // without a provided value we can only write escaped % characters + template + OutputT + write (OutputT os, const specifier s) + { + if (s.k != specifier::kind::ESCAPE) + throw missing_error (); + + *os = '%'; + return ++os; + } + + + //------------------------------------------------------------------------- + template + OutputT + write (OutputT os, const specifier spec, const char *t) + { + if (spec.k != specifier::kind::STRING) + throw conversion_error ("invalid specifier kind for string argumetn"); + + const auto len = spec.precision < 0 ? spec.precision : + (size_t)spec.precision < strlen (t) ? spec.precision : + strlen (t); + + // perform left padding + if (spec.width > len && !spec.left_adjusted) + os = std::fill_n (os, spec.width - len, spec.padding_char); + + os = std::copy_n (t, len, os); + + // perform right padding + if (spec.width > len && spec.left_adjusted) + os = std::fill_n (os, spec.width - len, spec.padding_char); + + return os; + } + + + //------------------------------------------------------------------------- + template + OutputT + write (OutputT os, const specifier spec, const std::string &val) + { + return write (os, spec, val.c_str ()); + } + + + //------------------------------------------------------------------------- + template + OutputT + write (OutputT os, const specifier s, const char t) + { + if (s.k != specifier::kind::CHARACTER) + throw conversion_error ("invalid specifier kind for char argument"); + + *os = t; + return ++os; + } + + + //------------------------------------------------------------------------- + // if the value isn't a builtin type then, if we asked for an OSTREAM + // conversion, render to a string and forward as such. + template + std::enable_if_t< + !std::is_fundamental::value && !std::is_pointer::value, + OutputT + > + write (OutputT os, const specifier& spec, const ValueT &val) + { + if (spec.k != specifier::kind::OSTREAM) + throw conversion_error ("invalid conversion specifier for user value"); + + std::ostringstream ss; + ss << val; + + specifier strspec = spec; + strspec.k = specifier::kind::STRING; + strspec.length = specifier_traits::length; + return write (os, strspec, ss.str ()); + } + + + //------------------------------------------------------------------------- + template + std::enable_if_t< + std::is_pointer::value, + OutputT + > + write (OutputT &os, const specifier &spec, const T t) + { + if (spec.k != specifier::kind::POINTER) + throw conversion_error ("invalid conversion specifier for pointer value"); + + // glibc at least uses a special form for null pointers + auto uint = reinterpret_cast (t); + if (!uint) { + static const std::string MSG = "(nil)"; + return std::copy (std::cbegin (MSG), std::cend (MSG), os); + } + + // %p specifiers are an implied %#x or %#lx + specifier uintspec = spec; + uintspec.k = specifier::kind::UNSIGNED; + uintspec.alternate_form = true; + uintspec.length = sizeof (t); + uintspec.base = 16; + + return write (os, uintspec, reinterpret_cast (t)); + } + + + //------------------------------------------------------------------------- + template + OutputT + write (OutputT os, const specifier &spec, std::nullptr_t) + { + return write (os, spec, (void*)0); + } + + + //------------------------------------------------------------------------- + template + std::enable_if_t< + std::is_integral::value, + OutputT + > + write (OutputT os, const specifier spec, ValueT t) + { + if (spec.k == specifier::kind::POINTER && !t) + { + return write (os, spec, reinterpret_cast (t)); + } + + if (spec.k != (std::is_unsigned::value ? specifier::kind::UNSIGNED : specifier::kind::SIGNED)) + throw conversion_error ("invalid conversion specifier for integer value"); + + if (spec.length != sizeof (ValueT)) + throw length_error ("incorrect value size"); + + const auto numerals = digits (t, spec.base); + const auto characters = numerals + (spec.positive_char ? 1 : 0); + + // add any requested positive signifier + if (spec.positive_char) + *os++ = spec.positive_char; + + // perform left padding + if (spec.width > characters && !spec.left_adjusted) + os = std::fill_n (os, spec.width - characters, spec.padding_char); + + // write the base prefix + if (spec.alternate_form) { + switch (spec.base) { + case 8: + *os++ = '0'; + break; + + case 16: + *os++ = '0'; + *os++ = spec.uppercase ? 'X' : 'x'; + break; + + case 10: + break; + } + } + + // actually write the number in the desired base. + // + // as a special case, if the value is zero and precision is zero then the + // output is blank (though space padding/etc is still preserved). + if (t != 0 || spec.precision != 0) { + const char *NUMERALS = spec.uppercase ? + "0123456789ABCDEF" : + "0123456789abcdef"; + + char buffer[numerals]; + for (auto cursor = buffer; t; t /= spec.base) + *cursor++ = NUMERALS[t % spec.base]; + std::reverse_copy (buffer, buffer + numerals, os); + } + + // perform right padding + if (spec.width > characters && spec.left_adjusted) + os = std::fill_n (os, spec.width - characters, spec.padding_char); + + return os; + } + + + //------------------------------------------------------------------------- + template + std::enable_if_t< + std::is_floating_point::value, + OutputT + > + write (OutputT os, const specifier spec, T t) + { + if (spec.k != specifier::kind::REAL) + throw conversion_error ("invalid conversion specifier for real value"); + + static const size_t buffer_len = strlen ("+0x") + std::numeric_limits::digits10 + strlen ("e+999") + 1; + char buffer[buffer_len]; + + static const size_t format_len = strlen ("%0-+99.99lle") + 1; + char format[format_len]; + + { + auto cursor = format; + *cursor++ = '%'; + + if (spec.alternate_form) *cursor++ = '#'; + if (spec.left_adjusted) *cursor++ = '-'; + if (spec.positive_char) *cursor++ = spec.positive_char; + + cursor += sprintf (cursor, "%u", spec.width); + + if (spec.precision >= 0) { + *cursor++ = '.'; + + if (spec.precision) + cursor += sprintf (cursor, "%i", spec.precision); + } + + if (spec.r == specifier::repr::SCIENTIFIC) + *cursor = 'e'; + else if (spec.r == specifier::repr::FIXED) + *cursor = 'f'; + else if (spec.base == 16) + *cursor = 'a'; + else + *cursor = 'g'; + + if (spec.uppercase) + *cursor = ascii::to_upper (*cursor); + ++cursor; + + *cursor++ = '\0'; + } + + auto len = snprintf (buffer, buffer_len, format, t); + if (len < 0) + throw error ("snprintf output error"); + + CHECK_LT ((size_t)len, buffer_len); + return std::copy_n (buffer, len, os); + } + + + ////////////////////////////////////////////////////////////////////////// + template + OutputT + _render (OutputT os, const char *first, const char *last) + { + auto start = std::find (first, last, '%'); + os = std::copy (first, start, os); + if (start == last) + return os; + + specifier spec; + auto cursor = parse (start, last, spec); + + return _render (write (os, spec), cursor, last); + } + + + //------------------------------------------------------------------------ + template + OutputT + _render (OutputT os, const char *first, const char *last, ValueT val, Args&& ...args) + { + auto start = std::find (first, last, '%'); + os = std::copy (first, start, os); + if (start == last) + return os; + + specifier spec; + auto cursor = parse (start, last, spec); + return _render (write (os, spec, val), cursor, last, std::forward (args)...); + } + + + //------------------------------------------------------------------------ + template + OutputT + render (OutputT os, const char (&fmt)[N], ValueT val, Args&& ...args) + { + if (N <= 1) + return os; + + const auto first = fmt; + const auto last = fmt + N - 1; + + return _render (os, first, last, val, std::forward (args)...); + } + + + //------------------------------------------------------------------------ + template + OutputT + render (OutputT os, const char (&fmt)[N]) + { + if (N <= 1) + return os; + + auto first = fmt; + auto last = fmt + N - 1; + + return _render (os, first, last); + } +} } } + + +/////////////////////////////////////////////////////////////////////////////// +namespace util { namespace format { + template + std::string + render (const char (&fmt)[N], const Args& ...args) + { + std::string res; + detail::render (std::back_inserter (res), fmt, args...); + return res; + } +} } diff --git a/log.hpp b/log.hpp index 9005772d..dd2e588c 100644 --- a/log.hpp +++ b/log.hpp @@ -61,8 +61,8 @@ namespace util { /////////////////////////////////////////////////////////////////////////// void log (level_t, const std::string &msg); - template - void log (level_t, const std::string &format, tail&& ..._tail); + template + void log (level_t, const char (&fmt)[N], const Args&...); //------------------------------------------------------------------------- diff --git a/log.ipp b/log.ipp index 6afa260f..6c3cbb16 100644 --- a/log.ipp +++ b/log.ipp @@ -24,11 +24,11 @@ //----------------------------------------------------------------------------- namespace util { - template + template 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)...)); + log (l, format::render (fmt, args...)); } } diff --git a/maths.cpp b/maths.cpp index 7f5dc582..aac72953 100644 --- a/maths.cpp +++ b/maths.cpp @@ -57,26 +57,6 @@ template uint32_t util::log2 (uint32_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 std::enable_if_t< diff --git a/maths.hpp b/maths.hpp index 410d21df..426b5b5e 100644 --- a/maths.hpp +++ b/maths.hpp @@ -17,10 +17,14 @@ #ifndef __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 "./float.hpp" +#include #include #include #include @@ -281,9 +285,40 @@ namespace util { //----------------------------------------------------------------------------- - template + constexpr 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 + constexpr + std::enable_if_t< + std::is_integral::value && std::is_unsigned::value, + unsigned + > + digits (ValueT value, BaseT base) noexcept + { + if (value < 0) + return digits (-value, base); + + unsigned tally = 1; + while (value /= base) + ++tally; + + return tally; + } ///---------------------------------------------------------------------------- @@ -326,8 +361,8 @@ namespace util { constexpr T gcd (T a, T b) { - CHECK_NEZ (a); - CHECK_NEZ (b); + assert (a); + assert (b); while (a != b) { if (a > b) @@ -506,7 +541,7 @@ namespace util { constexpr T limit (const T val, const U lo, const V hi) { - CHECK_LE (lo, hi); + assert (lo <= hi); return val > hi ? hi: val < lo ? lo: @@ -520,7 +555,7 @@ namespace util { T smoothstep (T a, T b, T x) { - CHECK_LE(a, b); + assert (a <= b); x = limit ((x - a) / (b - a), T{0}, T{1}); return x * x * (3 - 2 * x); } diff --git a/tap.hpp b/tap.hpp index bc1c462a..8bb82893 100644 --- a/tap.hpp +++ b/tap.hpp @@ -37,42 +37,42 @@ namespace util { namespace TAP { ~logger (); //--------------------------------------------------------------------- - template - void expect (bool, const std::string &fmt, Args&&...); + template + void expect (bool, const char (&fmt)[N], Args&&...); - template - void expect (const std::function&, Args&&..., const std::string& msg); + template + void expect (const std::function&, Args&&..., const char (&msg)[N]); //--------------------------------------------------------------------- - template - void expect_eq (const T&, const U&, const std::string &fmt, Args&&...); + template + void expect_eq (const T&, const U&, const char (&fmt)[N], Args&&...); - template - void expect_neq (const T&, const U&, const std::string &fmt, Args&&...); + template + void expect_neq (const T&, const U&, const char (&fmt)[N], Args&&...); //--------------------------------------------------------------------- - template - void expect_gt (const T&, const U&, const std::string &fmt, Args&&...); + template + void expect_gt (const T&, const U&, const char (&fmt)[N], Args&&...); - template - void expect_ge (const T&, const U&, const std::string &fmt, Args&&...); + template + void expect_ge (const T&, const U&, const char (&fmt)[N], Args&&...); - template - void expect_lt (const T&, const U&, const std::string &fmt, Args&&...); + template + void expect_lt (const T&, const U&, const char (&fmt)[N], Args&&...); - template - void expect_le (const T&, const U&, const std::string &fmt, Args&&...); + template + void expect_le (const T&, const U&, const char (&fmt)[N], Args&&...); //--------------------------------------------------------------------- - template - void expect_nan (const T&, const std::string &fmt, Args&&...); + template + void expect_nan (const T&, const char (&fmt)[N], Args&&...); //--------------------------------------------------------------------- - template - void expect_nothrow (T&&, const std::string &fmt, Args&&...); + template + void expect_nothrow (T&&, const char (&fmt)[N], Args&&...); - template - void expect_throw (T&&, const std::string &fmt, Args&&...); + template + void expect_throw (T&&, const char (&fmt)[N], Args&&...); //--------------------------------------------------------------------- void skip (const std::string &msg); diff --git a/tap.ipp b/tap.ipp index c0de09b4..8fa4d1d7 100644 --- a/tap.ipp +++ b/tap.ipp @@ -29,9 +29,9 @@ /////////////////////////////////////////////////////////////////////////////// -template +template 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 << " - " @@ -43,61 +43,42 @@ util::TAP::logger::expect (bool test, const std::string &fmt, Args&&... args) //----------------------------------------------------------------------------- -template +template void -util::TAP::logger::expect (const std::function &test, Args&&... args, const std::string &msg) +util::TAP::logger::expect (const std::function &test, Args&&... args, const char (&fmt)[N]) { - expect (test (std::forward (args)...), msg); + expect (test (std::forward (args)...), fmt); +} + + +/////////////////////////////////////////////////////////////////////////////// +template +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)...); } //----------------------------------------------------------------------------- -template +template 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 TEST = [] (const T &t, const U &u) -> bool { - return almost_equal (t, u); - }; - - expect (TEST, a, b, util::format::render (fmt, std::forward (args)...)); + expect (!almost_equal (a, b), fmt, std::forward (args)...); } -//----------------------------------------------------------------------------- -template -void -util::TAP::logger::expect_neq (const T&a, const U &b, const std::string &fmt, Args&&... args) -{ - static const std::function TEST = [] (const T &t, const U &u) -> bool { - return !almost_equal (t, u); - }; - - expect (TEST, a, b, util::format::render (fmt, std::forward (args)...)); -} - - -//----------------------------------------------------------------------------- +/////////////////////////////////////////////////////////////////////////////// #define TAP_TEST(SUFFIX,OP) \ -template \ +template \ void \ util::TAP::logger::expect_ ## SUFFIX (const T &a, \ const U &b, \ - const std::string &fmt, \ + const char (&fmt)[N], \ Args&&... args) \ { \ - static const std::function< \ - bool(const T&,const U&) \ - > TEST = [] (const T&t, const U&u) { return t OP u; }; \ - \ - expect ( \ - TEST, \ - a, b, \ - util::format::render ( \ - fmt, \ - std::forward (args)... \ - ) \ - ); \ + expect ((a) OP (b), fmt, std::forward (args)...); \ } TAP_TEST(gt, > ) @@ -109,23 +90,18 @@ TAP_TEST(le, <=) //----------------------------------------------------------------------------- -template +template 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::function (func), - t, - util::format::render (fmt, std::forward (args)...) - ); + expect (std::isnan (t), fmt, std::forward (args)...); } //----------------------------------------------------------------------------- -template +template 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; @@ -135,14 +111,14 @@ util::TAP::logger::expect_nothrow (T &&t, const std::string &fmt, Args&&... args success = false; } - expect (success, util::format::render (fmt, std::forward (args)...)); + expect (success, fmt, std::forward (args)...); } //----------------------------------------------------------------------------- -template +template 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; @@ -154,5 +130,5 @@ util::TAP::logger::expect_throw (T &&t, const std::string &fmt, Args&&... args) success = false; } - expect (success, util::format::render (fmt, std::forward (args)...)); + expect (success, fmt, std::forward (args)...); } diff --git a/test/cmdopt.cpp b/test/cmdopt.cpp index 8b7432cf..d023ade0 100644 --- a/test/cmdopt.cpp +++ b/test/cmdopt.cpp @@ -86,13 +86,13 @@ test_bool (util::TAP::logger &tap) for (auto i: positive) { argv[2] = i; 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) { argv[2] = i; 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 diff --git a/test/colour.cpp b/test/colour.cpp index 3dc20f4f..15b9d7e8 100644 --- a/test/colour.cpp +++ b/test/colour.cpp @@ -45,8 +45,8 @@ main (int, char**) }; for (auto i: TESTS) { - tap.expect_eq (util::rgb_to_hsv (i.rgb), i.hsv, i.name); - tap.expect_eq (util::hsv_to_rgb (i.hsv), i.rgb, 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, "hsv-to-rgb %s", i.name); } } } diff --git a/test/crypto/arc4.cpp b/test/crypto/arc4.cpp index 9b70293a..6e3c2b1e 100644 --- a/test/crypto/arc4.cpp +++ b/test/crypto/arc4.cpp @@ -2,6 +2,7 @@ #include "tap.hpp" #include "types.hpp" + int main () { @@ -384,8 +385,6 @@ main () success = success && std::equal (std::begin (data), std::end (data), std::begin (t.data[j])); }; - std::ostringstream os; - os << "ARC4: " << i; - tap.expect (success, os.str ()); + tap.expect (success, "ARC4 %zu", i); } } diff --git a/test/crypto/tea.cpp b/test/crypto/tea.cpp index 3eef45ac..ab4bdca9 100644 --- a/test/crypto/tea.cpp +++ b/test/crypto/tea.cpp @@ -50,17 +50,8 @@ main () std::array dec (t.enc); gen.decrypt (dec.data (), dec.size ()); - { - std::ostringstream os; - 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 ()); - } + tap.expect (enc == t.enc, "TEA_enc %zu", i); + tap.expect (dec == t.dec, "TEA_dec %zu", i); } return tap.status (); diff --git a/test/crypto/xtea.cpp b/test/crypto/xtea.cpp index 2263080b..17ca469f 100644 --- a/test/crypto/xtea.cpp +++ b/test/crypto/xtea.cpp @@ -49,17 +49,8 @@ main () std::array dec (t.enc); gen.decrypt (dec.data (), dec.size ()); - { - std::ostringstream os; - 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 ()); - } + tap.expect (enc == t.enc, "XTEA_enc %zu", i); + tap.expect (dec == t.dec, "XTEA_dec %zu", i); } return tap.status (); diff --git a/test/crypto/xxtea.cpp b/test/crypto/xxtea.cpp index 0a4dbb39..a568196c 100644 --- a/test/crypto/xxtea.cpp +++ b/test/crypto/xxtea.cpp @@ -104,17 +104,8 @@ main () std::vector dec (enc); gen.decrypt (dec.data (), dec.size ()); - { - std::ostringstream os; - 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 ()); - } + tap.expect (enc == t.enc, "XXTEA_enc %zu", i); + tap.expect (dec == t.dec, "XXTEA_dec %zu", i); } return tap.status (); diff --git a/test/fixed.cpp b/test/fixed.cpp index 0af75841..03db9675 100644 --- a/test/fixed.cpp +++ b/test/fixed.cpp @@ -16,19 +16,19 @@ test_simple (util::TAP::logger &tap) std::ostringstream os; os << "fixed<" << type_to_string () << ',' << I << ',' << E << '>'; - tap.expect_eq (lo, lo, os.str () + " self equality"); - tap.expect_eq (hi, hi, os.str () + " self equality"); + tap.expect_eq (lo, lo, "%s self equality", os.str ()); + tap.expect_eq (hi, hi, "%s self equality", os.str ()); - tap.expect_neq (hi, lo, os.str () + " inequality"); - tap.expect_neq (lo, hi, os.str () + " inequality"); + tap.expect_neq (hi, lo, "%s inequality", os.str ()); + tap.expect_neq (lo, hi, "%s inequality", os.str ()); - tap.expect_lt (lo, hi, os.str () + " less than"); - tap.expect_le (lo, hi, os.str () + " less than equal"); - tap.expect_le (lo, lo, os.str () + " less than equal"); + tap.expect_lt (lo, hi, "%s less than", os.str ()); + tap.expect_le (lo, hi, "%s less than equal", os.str ()); + tap.expect_le (lo, lo, "%s less than equal", os.str ()); - tap.expect_gt (hi, lo, os.str () + " greater than"); - tap.expect_ge (lo, lo, os.str () + " greater than equal"); - tap.expect_ge (hi, lo, os.str () + " greater than equal"); + tap.expect_gt (hi, lo, "%s greater than", os.str ()); + tap.expect_ge (lo, lo, "%s greater than equal", os.str ()); + tap.expect_ge (hi, lo, "%s greater than equal", os.str ()); } diff --git a/test/format.cpp b/test/format.cpp index c3aa6fb1..b343e33e 100644 --- a/test/format.cpp +++ b/test/format.cpp @@ -5,25 +5,186 @@ int main (void) { - using namespace std::string_literals; - util::TAP::logger tap; - tap.expect_eq (util::format::render ("identity"), "identity"s, "identity literal"); - tap.expect_eq (util::format::render ("%s", "identity"s), "identity"s, "identity string substitution"); - tap.expect_eq (util::format::render ("%s", "identity" ), "identity"s, "identity char[] substitution"); + #define CHECK_RENDER(fmt,res,...) do { \ + auto val = util::format::render (fmt, ##__VA_ARGS__); \ + tap.expect_eq (val, res, "render '%s'", fmt); \ + } while (0) - tap.expect_throw ([] (void) { - util::format::render ("%s"); - }, "missing value"); + CHECK_RENDER ("foo", "foo"); - tap.expect_throw> ([] (void) { - util::format::render ("%<", 42); - }, "invalid specifier"); + CHECK_RENDER ("%i", "1", 1 ); + CHECK_RENDER ("%3i", " 1", 1 ); + CHECK_RENDER ("%03i", "001", 1 ); + CHECK_RENDER ("%.i", "", 0); + CHECK_RENDER ("% .i", " ", 0); // zero precision still requires a space - tap.expect_throw ([] (void) { - util::format::render ("%", 42); - }, "truncated specifier"); + CHECK_RENDER ("%hhi", "1", (signed char)1); + CHECK_RENDER ("%hi", "1", (signed short)1); + 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", "1", (size_t)1); + + 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::infinity ()); + CHECK_RENDER ("%E", "INF", std::numeric_limits::infinity ()); + CHECK_RENDER ("%f", "inf", std::numeric_limits::infinity ()); + CHECK_RENDER ("%F", "INF", std::numeric_limits::infinity ()); + CHECK_RENDER ("%g", "inf", std::numeric_limits::infinity ()); + CHECK_RENDER ("%G", "INF", std::numeric_limits::infinity ()); + CHECK_RENDER ("%a", "inf", std::numeric_limits::infinity ()); + CHECK_RENDER ("%A", "INF", std::numeric_limits::infinity ()); + + CHECK_RENDER ("%e", "nan", std::numeric_limits::quiet_NaN ()); + CHECK_RENDER ("%E", "NAN", std::numeric_limits::quiet_NaN ()); + CHECK_RENDER ("%f", "nan", std::numeric_limits::quiet_NaN ()); + CHECK_RENDER ("%F", "NAN", std::numeric_limits::quiet_NaN ()); + CHECK_RENDER ("%g", "nan", std::numeric_limits::quiet_NaN ()); + CHECK_RENDER ("%G", "NAN", std::numeric_limits::quiet_NaN ()); + CHECK_RENDER ("%a", "nan", std::numeric_limits::quiet_NaN ()); + CHECK_RENDER ("%A", "NAN", std::numeric_limits::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 ("%c", "A", 'A'); + + CHECK_RENDER ("%s", "foo", "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 ("%p", "0x1234567", (void*)0x01234567); + CHECK_RENDER ("%p", "0x1234567", (int*)0x01234567); + CHECK_RENDER ("%p", "(nil)", nullptr); + CHECK_RENDER ("%p", "(nil)", NULL); + + 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::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"); + + CHECK_THROW("%!", conversion_error, 1u); } diff --git a/test/hash/hmac.cpp b/test/hash/hmac.cpp index 47406b49..089d8b28 100644 --- a/test/hash/hmac.cpp +++ b/test/hash/hmac.cpp @@ -274,7 +274,7 @@ main (int, char**) util::TAP::logger tap; 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 (); } diff --git a/test/hash/ripemd.cpp b/test/hash/ripemd.cpp index 6dc1ac44..cc8f4d7c 100644 --- a/test/hash/ripemd.cpp +++ b/test/hash/ripemd.cpp @@ -116,7 +116,7 @@ main(int, char**) { obj.update (reinterpret_cast (i.data), strlen (i.data)); 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 diff --git a/test/hash/sha1.cpp b/test/hash/sha1.cpp index a687245b..5c4ee9b0 100644 --- a/test/hash/sha1.cpp +++ b/test/hash/sha1.cpp @@ -66,7 +66,7 @@ main (int, char**) obj.update (reinterpret_cast (i.input), strlen (i.input)); obj.finish (); - tap.expect_eq (obj.digest (), i.output, i.msg); + tap.expect_eq (obj.digest (), i.output, "%s", i.msg); } return tap.status (); diff --git a/test/hash/sha2.cpp b/test/hash/sha2.cpp index c49b823c..7a01f1c4 100644 --- a/test/hash/sha2.cpp +++ b/test/hash/sha2.cpp @@ -55,7 +55,7 @@ main (int, char **) { obj.update (reinterpret_cast (i.input), strlen (i.input)); obj.finish (); - tap.expect_eq (obj.digest (), i.output, i.msg); + tap.expect_eq (obj.digest (), i.output, "%s", i.msg); } return tap.status (); diff --git a/test/ip.cpp b/test/ip.cpp index dfaa0ac5..2f9c3be0 100644 --- a/test/ip.cpp +++ b/test/ip.cpp @@ -23,9 +23,8 @@ test_good (util::TAP::logger &tap) { "127.0.0.1", { 127, 0, 0, 1 }, "localhost" } }; - for (const auto &i: TESTS) { - tap.expect_eq (ipv4::ip::parse (i.str), i.ip, i.msg); - } + for (const auto &i: TESTS) + 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" } }; - for (const auto &i: TESTS) { - tap.expect_throw ([&] { ipv4::ip::parse (i.str); }, i.msg); - } + for (const auto &i: TESTS) + tap.expect_throw ([&] { ipv4::ip::parse (i.str); }, "%s", i.msg); } diff --git a/test/polynomial.cpp b/test/polynomial.cpp index 3ceba424..a1762c79 100644 --- a/test/polynomial.cpp +++ b/test/polynomial.cpp @@ -52,7 +52,7 @@ main (int, char**) ok = false; } - test.expect (ok, i.name); + test.expect (ok, "%s", i.name); } return 0; diff --git a/test/roots/bisection.cpp b/test/roots/bisection.cpp index 10a5e645..f0e763b7 100644 --- a/test/roots/bisection.cpp +++ b/test/roots/bisection.cpp @@ -33,7 +33,7 @@ main (void) for (const auto &t: TESTS) { constexpr float TOLERANCE = 0.00001f; auto root = util::roots::bisection (t.lo, t.hi, t.func, TOLERANCE); - tap.expect_eq (root, t.root, t.msg); + tap.expect_eq (root, t.root, "%s", t.msg); } return tap.status (); diff --git a/test/vector.cpp b/test/vector.cpp index 62081404..c38a26da 100644 --- a/test/vector.cpp +++ b/test/vector.cpp @@ -47,7 +47,7 @@ test_polar (util::TAP::logger &tap) auto in_cart = t.cartesian; auto to_cart = util::polar_to_cartesian (t.polar); - tap.expect_lt ((in_cart - to_cart).magnitude (), 0.00001f, t.desc); + tap.expect_lt ((in_cart - to_cart).magnitude (), 0.00001f, "%s", t.desc); // Compare polar representations. Make sure to normalise them first. auto in_polar = t.polar; @@ -56,7 +56,7 @@ test_polar (util::TAP::logger &tap) in_polar[1] = std::fmod (in_polar[1], 2 * util::PI); to_polar[1] = std::fmod (to_polar[1], 2 * util::PI); - tap.expect_eq (in_polar, to_polar, t.desc); + tap.expect_eq (in_polar, to_polar, "%s", t.desc); } } diff --git a/test/version.cpp b/test/version.cpp index f54247ad..f8abf25c 100644 --- a/test/version.cpp +++ b/test/version.cpp @@ -52,7 +52,7 @@ main () { for (const auto &i: PARSE_TESTS) { util::version v (i.str); - tap.expect (std::equal (v.begin (), v.end (), i.parts) && v.release == i.release, i.msg); + tap.expect (std::equal (v.begin (), v.end (), i.parts) && v.release == i.release, "%s", i.msg); } From 70170f4205bde27952aeac023ef96fb32426333d Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Thu, 28 Jul 2016 13:38:34 +1000 Subject: [PATCH 005/100] alloc/arena: disallow implicit copy constructor in test obj fixes a build warning under clang --- test/alloc/arena.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/alloc/arena.cpp b/test/alloc/arena.cpp index e4b9ebda..4813ad26 100644 --- a/test/alloc/arena.cpp +++ b/test/alloc/arena.cpp @@ -7,6 +7,8 @@ static char g_backing[1024*1024]; struct setter { + setter (const setter&) = delete; + setter (bool &_target): target (_target) { target = false; } @@ -30,7 +32,7 @@ main (void) // double check our testing object is working, because I'm tired and stupid { - auto val = setter (flag); + setter val (flag); CHECK (!flag); } CHECK (flag); From ed7c466d8dedffe4ad02ff00394ee9bd5a99c6e5 Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Thu, 28 Jul 2016 13:44:17 +1000 Subject: [PATCH 006/100] tap: protect against exceptions in func eval expect --- tap.ipp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tap.ipp b/tap.ipp index c0de09b4..7a0e7584 100644 --- a/tap.ipp +++ b/tap.ipp @@ -47,7 +47,11 @@ template void util::TAP::logger::expect (const std::function &test, Args&&... args, const std::string &msg) { - expect (test (std::forward (args)...), msg); + try { + expect (test (std::forward (args)...), msg); + } catch (...) { + expect (false, msg); + } } From 25a9c6fafcd96e4f6ee596fe9e4a7da7de7d4933 Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Thu, 28 Jul 2016 13:45:09 +1000 Subject: [PATCH 007/100] introspection: rename type_string to type_name --- introspection.cpp | 28 ++++++++++++++-------------- introspection.hpp | 46 ++++++++++++++++++++++------------------------ 2 files changed, 36 insertions(+), 38 deletions(-) diff --git a/introspection.cpp b/introspection.cpp index 6f3f380a..fc14b51c 100644 --- a/introspection.cpp +++ b/introspection.cpp @@ -18,21 +18,21 @@ /////////////////////////////////////////////////////////////////////////////// -constexpr char util::type_string::value[]; +constexpr char util::type_name::value[]; -constexpr char util::type_string< int8_t>::value[]; -constexpr char util::type_string< int16_t>::value[]; -constexpr char util::type_string< int32_t>::value[]; -constexpr char util::type_string< int64_t>::value[]; +constexpr char util::type_name< int8_t>::value[]; +constexpr char util::type_name< int16_t>::value[]; +constexpr char util::type_name< int32_t>::value[]; +constexpr char util::type_name< int64_t>::value[]; -constexpr char util::type_string< uint8_t>::value[]; -constexpr char util::type_string::value[]; -constexpr char util::type_string::value[]; -constexpr char util::type_string::value[]; +constexpr char util::type_name< uint8_t>::value[]; +constexpr char util::type_name::value[]; +constexpr char util::type_name::value[]; +constexpr char util::type_name::value[]; -constexpr char util::type_string::value[]; -constexpr char util::type_string::value[]; +constexpr char util::type_name::value[]; +constexpr char util::type_name::value[]; -constexpr char util::type_string::value[]; -constexpr char util::type_string::value[]; -constexpr char util::type_string::value[]; +constexpr char util::type_name::value[]; +constexpr char util::type_name::value[]; +constexpr char util::type_name::value[]; diff --git a/introspection.hpp b/introspection.hpp index c556ef1b..775f6c27 100644 --- a/introspection.hpp +++ b/introspection.hpp @@ -29,40 +29,38 @@ namespace util { template < typename T > - struct type_string { - // static const std::string value - }; + struct type_name { }; - template <> struct type_string { static constexpr const char value[] = "bool"; }; + template <> struct type_name { static constexpr const char value[] = "bool"; }; - template <> struct type_string { static constexpr const char value[] = "char"; }; - template <> struct type_string { static constexpr const char value[] = "void*"; }; + template <> struct type_name { static constexpr const char value[] = "char"; }; + template <> struct type_name { static constexpr const char value[] = "void*"; }; - template <> struct type_string< int8_t> { static constexpr const char value[] = "int8"; }; - template <> struct type_string< int16_t> { static constexpr const char value[] = "int16"; }; - template <> struct type_string< int32_t> { static constexpr const char value[] = "int32"; }; - template <> struct type_string< int64_t> { static constexpr const char value[] = "int64"; }; + template <> struct type_name< int8_t> { static constexpr const char value[] = "int8"; }; + template <> struct type_name< int16_t> { static constexpr const char value[] = "int16"; }; + template <> struct type_name< int32_t> { static constexpr const char value[] = "int32"; }; + 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_string { static constexpr const char value[] = "uint16"; }; - template <> struct type_string { static constexpr const char value[] = "uint32"; }; - template <> struct type_string { static constexpr const char value[] = "uint64"; }; + template <> struct type_name< uint8_t> { static constexpr const char value[] = "uint8"; }; + template <> struct type_name { static constexpr const char value[] = "uint16"; }; + template <> struct type_name { static constexpr const char value[] = "uint32"; }; + template <> struct type_name { static constexpr const char value[] = "uint64"; }; - template <> struct type_string { static constexpr const char value[] = "float32"; }; - template <> struct type_string { static constexpr const char value[] = "float64"; }; + template <> struct type_name { static constexpr const char value[] = "float32"; }; + template <> struct type_name { static constexpr const char value[] = "float64"; }; - template <> struct type_string { static constexpr const char value[] = "string"; }; - template <> struct type_string { static constexpr const char value[] = "cstring"; }; - template <> struct type_string { static constexpr const char value[] = "cstring"; }; + template <> struct type_name { static constexpr const char value[] = "string"; }; + template <> struct type_name { static constexpr const char value[] = "cstring"; }; + template <> struct type_name { static constexpr const char value[] = "cstring"; }; template constexpr - const char* type_string_v = type_string::value; + const char* type_name_v = type_name::value; template const char* to_string (void) - { return type_string_v; } + { return type_name_v; } /////////////////////////////////////////////////////////////////////////// @@ -107,7 +105,7 @@ namespace util { }; \ \ template <> \ - struct type_string<::NS::E> { \ + struct type_name<::NS::E> { \ static constexpr const char ns[] = #NS; \ static constexpr const char value[] = #E; \ }; \ @@ -134,10 +132,10 @@ namespace util { > util::enum_traits<::NS::E>::names; \ \ constexpr \ - const char util::type_string<::NS::E>::ns[]; \ + const char util::type_name<::NS::E>::ns[]; \ \ constexpr \ - const char util::type_string<::NS::E>::value[]; \ + const char util::type_name<::NS::E>::value[]; \ ///------------------------------------------------------------------------ From fe8bbd1b61c04e468c6f634130f42826322e902f Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Thu, 28 Jul 2016 13:45:44 +1000 Subject: [PATCH 008/100] coord: add forward declarations --- Makefile.am | 1 + coord/fwd.hpp | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 coord/fwd.hpp diff --git a/Makefile.am b/Makefile.am index a8742402..f1898f95 100644 --- a/Makefile.am +++ b/Makefile.am @@ -44,6 +44,7 @@ UTIL_FILES = \ colour.cpp \ colour.hpp \ colour.ipp \ + coord/fwd.hpp \ coord/base.hpp \ coord.hpp \ coord/init.hpp \ diff --git a/coord/fwd.hpp b/coord/fwd.hpp new file mode 100644 index 00000000..782805a8 --- /dev/null +++ b/coord/fwd.hpp @@ -0,0 +1,27 @@ +/* + * 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 + */ + +#ifndef __UTIL_COORD_FWD_HPP +#define __UTIL_COORD_FWD_HPP + +namespace util { + template struct colour; + template struct extent; + template struct point; + template struct vector; +} + +#endif From b44e6b8cd7f24abe3128c820be1e8838e6c534c5 Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Thu, 28 Jul 2016 14:16:42 +1000 Subject: [PATCH 009/100] WIP tap param rename --- tap.ipp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tap.ipp b/tap.ipp index d83507d2..b60055d0 100644 --- a/tap.ipp +++ b/tap.ipp @@ -48,9 +48,9 @@ void util::TAP::logger::expect (const std::function &test, Args&&... args, const char (&fmt)[N]) { try { - expect (test (std::forward (args)...), msg); + expect (test (std::forward (args)...), fmt); } catch (...) { - expect (false, msg); + expect (false, fmt); } } From b4640d64d8d9f15e4599e09f11ffa13406d60ff4 Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Thu, 28 Jul 2016 14:14:15 +1000 Subject: [PATCH 010/100] format: use const-ref over rval-ref for value params --- format.ipp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/format.ipp b/format.ipp index c740e1c8..33d53e65 100644 --- a/format.ipp +++ b/format.ipp @@ -856,7 +856,7 @@ namespace util { namespace format { namespace detail { //------------------------------------------------------------------------ template OutputT - _render (OutputT os, const char *first, const char *last, ValueT val, Args&& ...args) + _render (OutputT os, const char *first, const char *last, const ValueT &val, const Args &...args) { auto start = std::find (first, last, '%'); os = std::copy (first, start, os); @@ -865,14 +865,14 @@ namespace util { namespace format { namespace detail { specifier spec; auto cursor = parse (start, last, spec); - return _render (write (os, spec, val), cursor, last, std::forward (args)...); + return _render (write (os, spec, val), cursor, last, args...); } //------------------------------------------------------------------------ template OutputT - render (OutputT os, const char (&fmt)[N], ValueT val, Args&& ...args) + render (OutputT os, const char (&fmt)[N], const ValueT &val, const Args &...args) { if (N <= 1) return os; @@ -880,7 +880,7 @@ namespace util { namespace format { namespace detail { const auto first = fmt; const auto last = fmt + N - 1; - return _render (os, first, last, val, std::forward (args)...); + return _render (os, first, last, val, args...); } From a40e09ed972afb94490b664f93498cc85f4e2b3e Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Thu, 28 Jul 2016 14:14:59 +1000 Subject: [PATCH 011/100] format: write c_str as %s by default, support c_str as %p --- format.ipp | 8 +++++++- test/format.cpp | 3 +++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/format.ipp b/format.ipp index 33d53e65..6efc8da1 100644 --- a/format.ipp +++ b/format.ipp @@ -603,6 +603,12 @@ namespace util { namespace format { namespace detail { OutputT write (OutputT os, const specifier spec, const char *t) { + // we need to forward to the pointer write function rather than the + // other way around to reduce ambiguity and the potential for + // recursion. + if (spec.k == specifier::kind::POINTER) + return write (os, spec, reinterpret_cast (t)); + if (spec.k != specifier::kind::STRING) throw conversion_error ("invalid specifier kind for string argumetn"); @@ -672,7 +678,7 @@ namespace util { namespace format { namespace detail { //------------------------------------------------------------------------- template std::enable_if_t< - std::is_pointer::value, + std::is_pointer::value && !std::is_same, char>::value, OutputT > write (OutputT &os, const specifier &spec, const T t) diff --git a/test/format.cpp b/test/format.cpp index b343e33e..119d84c0 100644 --- a/test/format.cpp +++ b/test/format.cpp @@ -112,6 +112,8 @@ main (void) CHECK_RENDER ("%c", "A", 'A'); CHECK_RENDER ("%s", "foo", "foo"); + CHECK_RENDER ("%s", "foo", std::string ("foo")); + CHECK_RENDER ("%s", "foo", const_cast ("foo")); CHECK_RENDER ("%.s", "", "foo"); CHECK_RENDER ("%.0s", "", "foo"); CHECK_RENDER ("%.2s", "fo", "foo"); @@ -122,6 +124,7 @@ main (void) 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); From fad81818420e74797b8c22c2c2ac116b2a75536a Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Thu, 28 Jul 2016 16:11:47 +1000 Subject: [PATCH 012/100] format: allow undersize integers for conversion --- format.ipp | 4 ++-- test/format.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/format.ipp b/format.ipp index 6efc8da1..42ac2461 100644 --- a/format.ipp +++ b/format.ipp @@ -729,8 +729,8 @@ namespace util { namespace format { namespace detail { if (spec.k != (std::is_unsigned::value ? specifier::kind::UNSIGNED : specifier::kind::SIGNED)) throw conversion_error ("invalid conversion specifier for integer value"); - if (spec.length != sizeof (ValueT)) - throw length_error ("incorrect value size"); + if (sizeof (ValueT) > spec.length) + throw length_error ("overlength value parameter"); const auto numerals = digits (t, spec.base); const auto characters = numerals + (spec.positive_char ? 1 : 0); diff --git a/test/format.cpp b/test/format.cpp index 119d84c0..0628ea58 100644 --- a/test/format.cpp +++ b/test/format.cpp @@ -167,7 +167,7 @@ main (void) CHECK_THROW("%i", conversion_error, nullptr); CHECK_THROW("%hhi", length_error, (long long)1); - CHECK_THROW("%lli", length_error, (signed char)1); + //CHECK_THROW("%lli", length_error, (signed char)1); CHECK_THROW("%u", conversion_error, 1.); CHECK_THROW("%u", conversion_error, "foo"); @@ -176,7 +176,7 @@ main (void) 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("%llu", length_error, (unsigned char)1); CHECK_THROW("%f", conversion_error, 1u); CHECK_THROW("%f", conversion_error, "foo"); From c26c687912d46401098f3e6f1256f0f937494ddf Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Thu, 28 Jul 2016 16:12:16 +1000 Subject: [PATCH 013/100] format: set ostream precision as if for strings ostream conversions are converted to strings anyway, so we should treat them as such earlier in the process. --- format.ipp | 2 +- test/format.cpp | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/format.ipp b/format.ipp index 42ac2461..d375282b 100644 --- a/format.ipp +++ b/format.ipp @@ -225,12 +225,12 @@ namespace util { namespace format { namespace detail { return -1; case specifier::kind::STRING: + case specifier::kind::OSTREAM: return std::numeric_limits::max (); case specifier::kind::POINTER: case specifier::kind::CHARACTER: case specifier::kind::ESCAPE: - case specifier::kind::OSTREAM: return 0; } diff --git a/test/format.cpp b/test/format.cpp index 0628ea58..4ecf9697 100644 --- a/test/format.cpp +++ b/test/format.cpp @@ -2,6 +2,18 @@ #include "tap.hpp" + +/////////////////////////////////////////////////////////////////////////////// +struct userobj { }; + +static std::ostream& +operator<< (std::ostream &os, const userobj&) +{ + return os << "userobj"; +} + + +/////////////////////////////////////////////////////////////////////////////// int main (void) { @@ -121,6 +133,7 @@ main (void) CHECK_RENDER ("%.64s", "foo", "foo"); CHECK_RENDER ("%3.1s", " f", "foo"); CHECK_RENDER ("%-3.1s", "f ", "foo"); + CHECK_RENDER ("%!", "userobj", userobj {}); CHECK_RENDER ("%p", "0x1234567", (void*)0x01234567); CHECK_RENDER ("%p", "0x1234567", (int*)0x01234567); From 453bd1666de247cdb9b4031bc534b9f92bb31c98 Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Sun, 31 Jul 2016 14:23:59 +1000 Subject: [PATCH 014/100] m4: delete unused ax m4 files --- m4/ax_append_compile_flags.m4 | 67 ----- m4/ax_append_link_flags.m4 | 65 ----- m4/ax_check_compile_flag.m4 | 74 ------ m4/ax_check_link_flag.m4 | 74 ------ m4/ax_compiler_vendor.m4 | 87 ------ m4/ax_pthread.m4 | 485 ---------------------------------- m4/ax_require_defined.m4 | 37 --- 7 files changed, 889 deletions(-) delete mode 100644 m4/ax_append_compile_flags.m4 delete mode 100644 m4/ax_append_link_flags.m4 delete mode 100644 m4/ax_check_compile_flag.m4 delete mode 100644 m4/ax_check_link_flag.m4 delete mode 100644 m4/ax_compiler_vendor.m4 delete mode 100644 m4/ax_pthread.m4 delete mode 100644 m4/ax_require_defined.m4 diff --git a/m4/ax_append_compile_flags.m4 b/m4/ax_append_compile_flags.m4 deleted file mode 100644 index 2bb27ef2..00000000 --- a/m4/ax_append_compile_flags.m4 +++ /dev/null @@ -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 -# -# 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 . -# -# 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 diff --git a/m4/ax_append_link_flags.m4 b/m4/ax_append_link_flags.m4 deleted file mode 100644 index fd70fc72..00000000 --- a/m4/ax_append_link_flags.m4 +++ /dev/null @@ -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 -# -# 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 . -# -# 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 diff --git a/m4/ax_check_compile_flag.m4 b/m4/ax_check_compile_flag.m4 deleted file mode 100644 index ca363971..00000000 --- a/m4/ax_check_compile_flag.m4 +++ /dev/null @@ -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 -# Copyright (c) 2011 Maarten Bosmans -# -# 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 . -# -# 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 diff --git a/m4/ax_check_link_flag.m4 b/m4/ax_check_link_flag.m4 deleted file mode 100644 index eb01a6ce..00000000 --- a/m4/ax_check_link_flag.m4 +++ /dev/null @@ -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 -# Copyright (c) 2011 Maarten Bosmans -# -# 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 . -# -# 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 diff --git a/m4/ax_compiler_vendor.m4 b/m4/ax_compiler_vendor.m4 deleted file mode 100644 index 39ca3c0f..00000000 --- a/m4/ax_compiler_vendor.m4 +++ /dev/null @@ -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 -# 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 . -# -# 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` - ]) -]) diff --git a/m4/ax_pthread.m4 b/m4/ax_pthread.m4 deleted file mode 100644 index d218d1af..00000000 --- a/m4/ax_pthread.m4 +++ /dev/null @@ -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 -# Copyright (c) 2011 Daniel Richard G. -# -# 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 . -# -# 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 -# 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 ], - [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 ]], - [[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 diff --git a/m4/ax_require_defined.m4 b/m4/ax_require_defined.m4 deleted file mode 100644 index cae11112..00000000 --- a/m4/ax_require_defined.m4 +++ /dev/null @@ -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 -# -# 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 From 19bf405710994965a4d50fdc1fa04d7961fcc525 Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Sun, 31 Jul 2016 14:31:32 +1000 Subject: [PATCH 015/100] m4/nc: use new NC_SUBPACKAGE argument form --- configure.ac | 2 +- m4/nc | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index de571340..37f26a73 100644 --- a/configure.ac +++ b/configure.ac @@ -126,7 +126,7 @@ AC_SUBST(LIBS) # failure on a clean build AX_APPEND_FLAG([-include config.h]) -NC_SUBPACKAGE([util]) +NC_SUBPACKAGE([cruft-util]) AC_CONFIG_FILES([ Doxyfile diff --git a/m4/nc b/m4/nc index c5615481..5af40e12 160000 --- a/m4/nc +++ b/m4/nc @@ -1 +1 @@ -Subproject commit c5615481949aa6aaedd2c5d221ed17d2e05009b0 +Subproject commit 5af40e12a2b18426a5c595937c71324315a4fbcd From 0b85632c9772d5c7103ce16d6749c9cc7764cb33 Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Mon, 1 Aug 2016 17:22:19 +1000 Subject: [PATCH 016/100] ripemd: panic rather than throw in constexpr calculating the hash should never need to throw; all error cases should be detectable at construction time. we should panic if we detect such an error. this fixes a compilation warning --- hash/ripemd.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hash/ripemd.cpp b/hash/ripemd.cpp index 2d5376bc..73f9c415 100644 --- a/hash/ripemd.cpp +++ b/hash/ripemd.cpp @@ -86,7 +86,7 @@ RIPEMD::update (const void *restrict _data, size_t len) noexcept } if (m_length >> sizeof (m_length) * 8 - 3 != 0) - throw std::length_error ("exceeded maximum message length"); + panic ("exceeded maximum message length"); } From 7d277bb8ff954db5f5605334965af8632ecec5d3 Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Mon, 1 Aug 2016 17:23:53 +1000 Subject: [PATCH 017/100] debug: reduce constexpr tomfoolery where not required don't use compiler fooling tricks where it's not required --- debug.ipp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/debug.ipp b/debug.ipp index 9720bbc1..64287c09 100644 --- a/debug.ipp +++ b/debug.ipp @@ -101,7 +101,5 @@ constexpr void panic [[noreturn]] (const char (&fmt)[N], const Args& ...args) { - ! fmt - ? panic ("unreachable constexpr panic helper") - : util::debug::detail::panic (fmt, args...); + util::debug::detail::panic (fmt, args...); } From 7e0875628b725a923453dd8ceb30c9c45ade85bc Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Mon, 1 Aug 2016 17:24:29 +1000 Subject: [PATCH 018/100] m4/nc: bump for ipa-pta optimsation fixes --- m4/nc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/m4/nc b/m4/nc index 5af40e12..a7a72a44 160000 --- a/m4/nc +++ b/m4/nc @@ -1 +1 @@ -Subproject commit 5af40e12a2b18426a5c595937c71324315a4fbcd +Subproject commit a7a72a4412ca83570de6a12fc15fc52d78083b1b From 5fee69debbd8fe5ba0cda7db583c2de7af64f0e0 Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Tue, 2 Aug 2016 18:49:42 +1000 Subject: [PATCH 019/100] annotation: add likely/unlikely functions --- Makefile.am | 1 + annotation.hpp | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 annotation.hpp diff --git a/Makefile.am b/Makefile.am index 7886b2fd..5690cd00 100644 --- a/Makefile.am +++ b/Makefile.am @@ -32,6 +32,7 @@ UTIL_FILES = \ alloc/null.hpp \ alloc/stack.cpp \ alloc/stack.hpp \ + annotation.hpp \ ascii.hpp \ backtrace.hpp \ bezier.cpp \ diff --git a/annotation.hpp b/annotation.hpp new file mode 100644 index 00000000..7f74fe11 --- /dev/null +++ b/annotation.hpp @@ -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 + */ + +#ifndef __UTIL_ANNOTATION_HPP +#define __UTIL_ANNOTATION_HPP + +template +constexpr inline +bool +likely (T &&t) +{ return __builtin_expect (!!t, true); } + + +template +constexpr inline +bool +unlikely (T &&t) +{ return __builtin_expect (!!t, false); } + +#endif From 3a0f20e68b700deccbc9ca3531876b3149d6b141 Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Tue, 2 Aug 2016 18:50:26 +1000 Subject: [PATCH 020/100] ascii: add is_space --- ascii.hpp | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/ascii.hpp b/ascii.hpp index 0d1daebf..b951ad93 100644 --- a/ascii.hpp +++ b/ascii.hpp @@ -52,6 +52,26 @@ namespace util { namespace ascii { { 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 From c6f483d077abc7ff5c6b1a52fca35583e5980e0f Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Tue, 2 Aug 2016 18:50:35 +1000 Subject: [PATCH 021/100] ascii: add to_integer from ascii to numeric --- ascii.hpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/ascii.hpp b/ascii.hpp index b951ad93..b49cff5b 100644 --- a/ascii.hpp +++ b/ascii.hpp @@ -17,6 +17,11 @@ #ifndef __CRUFT_UTIL_ASCII_HPP #define __CRUFT_UTIL_ASCII_HPP +#include "./annotation.hpp" + +#include +#include + namespace util { namespace ascii { /////////////////////////////////////////////////////////////////////////// constexpr inline @@ -26,6 +31,16 @@ namespace util { namespace ascii { 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 From f9fd156df8af2441da80bf5f66f727574770567a Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Tue, 2 Aug 2016 18:51:04 +1000 Subject: [PATCH 022/100] io_posix: add fd constructors to mapped_file --- io_posix.cpp | 38 +++++++++++++++----------------------- io_posix.hpp | 2 +- 2 files changed, 16 insertions(+), 24 deletions(-) diff --git a/io_posix.cpp b/io_posix.cpp index a3846da3..93d30242 100644 --- a/io_posix.cpp +++ b/io_posix.cpp @@ -26,16 +26,22 @@ using util::detail::posix::mapped_file; ////////////////////////////////////////////////////////////////////////////// -mapped_file::mapped_file (const char *_path, int fflags, int mflags): - m_fd (_path, fflags) +mapped_file::mapped_file (const char *path, int fflags, int mflags): + mapped_file (util::fd (path, fflags), mflags) +{ ; } + + +//----------------------------------------------------------------------------- +mapped_file::mapped_file (const util::fd &src, int mflags) { - try { - load_fd (mflags); - } catch (const errno_error &e) { - // ignore zero length mapping error - if (e.code () == EINVAL && m_size == 0) - return; - } + struct stat meta; + if (fstat (src, &meta) < 0) + throw errno_error (); + + m_size = (size_t)meta.st_size; + m_data = (uint8_t *)mmap (NULL, m_size, mflags, MAP_SHARED, src, 0); + if (m_data == MAP_FAILED) + throw errno_error (); } @@ -47,20 +53,6 @@ mapped_file::~mapped_file () } -//---------------------------------------------------------------------------- -void -mapped_file::load_fd (int mflags) { - struct stat meta; - if (fstat (m_fd, &meta) < 0) - throw errno_error (); - - m_size = (size_t)meta.st_size; - m_data = (uint8_t *)mmap (NULL, m_size, mflags, MAP_SHARED, m_fd, 0); - if (m_data == MAP_FAILED) - throw errno_error (); -} - - //---------------------------------------------------------------------------- size_t mapped_file::size (void) const diff --git a/io_posix.hpp b/io_posix.hpp index c443b3f4..2d505db9 100644 --- a/io_posix.hpp +++ b/io_posix.hpp @@ -31,6 +31,7 @@ namespace util { class mapped_file { public: mapped_file (const char *path, int fflags = O_RDONLY | O_BINARY, int mflags = PROT_READ); + mapped_file (const util::fd&, int mflags = PROT_READ); mapped_file (const mapped_file&) = delete; mapped_file& operator= (const mapped_file&) = delete; @@ -61,7 +62,6 @@ namespace util { as_view () &; private: - fd m_fd; uint8_t *m_data; size_t m_size; From c8d8067af238616deead039c45fdedc49a569baa Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Wed, 3 Aug 2016 18:10:09 +1000 Subject: [PATCH 023/100] format: add unsigned char write method unsigned char sometimes arises from string literals --- format.ipp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/format.ipp b/format.ipp index d375282b..fa5cbbb4 100644 --- a/format.ipp +++ b/format.ipp @@ -630,6 +630,15 @@ namespace util { namespace format { namespace detail { } + //------------------------------------------------------------------------- + template + OutputT + write (OutputT os, const specifier &spec, const unsigned char *t) + { + return write (os, spec, reinterpret_cast (t)); + } + + //------------------------------------------------------------------------- template OutputT From 9270a05a8b03aa857809ca2f866914851b25fc48 Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Wed, 3 Aug 2016 18:11:04 +1000 Subject: [PATCH 024/100] debug: prefer use of the standard __func__ symbol --- debug.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/debug.hpp b/debug.hpp index 82e00ffa..0a3b758b 100644 --- a/debug.hpp +++ b/debug.hpp @@ -59,7 +59,7 @@ /////////////////////////////////////////////////////////////////////////////// #define _CHECK_PANIC(FMT,...) do { \ panic ("%s:%s:%i:%s\n" FMT, \ - PACKAGE, __FILE__, __LINE__, __FUNCTION__, \ + PACKAGE, __FILE__, __LINE__, __func__, \ __VA_ARGS__); \ } while(0) From 74284415a7007729d20aadbd531f638f8018a770 Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Wed, 3 Aug 2016 18:11:29 +1000 Subject: [PATCH 025/100] debug: prefer constref temporaries for CHECK macros --- debug.hpp | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/debug.hpp b/debug.hpp index 0a3b758b..d56a8e22 100644 --- a/debug.hpp +++ b/debug.hpp @@ -87,8 +87,8 @@ /////////////////////////////////////////////////////////////////////////////// #define CHECK_EQ(A,B) do { \ DEBUG_ONLY( \ - const auto __a = (A); \ - const auto __b = (B); \ + const auto &__a = (A); \ + const auto &__b = (B); \ \ if (!util::almost_equal (__a, __b)) { \ _CHECK_PANIC("expected equality\n" \ @@ -104,8 +104,8 @@ /////////////////////////////////////////////////////////////////////////////// #define CHECK_LT(A,B) do { \ DEBUG_ONLY( \ - const auto __a = (A); \ - const auto __b = (B); \ + const auto &__a = (A); \ + const auto &__b = (B); \ \ if (__a >= __b) { \ _CHECK_PANIC("expected less than\n" \ @@ -121,8 +121,8 @@ /////////////////////////////////////////////////////////////////////////////// #define CHECK_LE(A,B) do { \ DEBUG_ONLY( \ - const auto __a = (A); \ - const auto __b = (B); \ + const auto &__a = (A); \ + const auto &__b = (B); \ \ if (__a > __b) { \ _CHECK_PANIC("expected less than or equal\n" \ @@ -138,8 +138,8 @@ /////////////////////////////////////////////////////////////////////////////// #define CHECK_GT(A,B) do { \ DEBUG_ONLY( \ - const auto __a = (A); \ - const auto __b = (B); \ + const auto &__a = (A); \ + const auto &__b = (B); \ \ if (__a <= __b) { \ _CHECK_PANIC ("expected greater than\n" \ @@ -155,8 +155,8 @@ /////////////////////////////////////////////////////////////////////////////// #define CHECK_GE(A,B) do { \ DEBUG_ONLY( \ - const auto __a = (A); \ - const auto __b = (B); \ + const auto &__a = (A); \ + const auto &__b = (B); \ \ if (__a < __b) { \ _CHECK_PANIC ("expected greater or equal\n" \ @@ -172,9 +172,9 @@ /////////////////////////////////////////////////////////////////////////////// #define CHECK_LIMIT(V,L,H) do { \ DEBUG_ONLY( \ - const auto __v = (V); \ - const auto __l = (L); \ - const auto __h = (H); \ + const auto &__v = (V); \ + const auto &__l = (L); \ + const auto &__h = (H); \ \ if (__v < __l || __v > __h) { \ _CHECK_PANIC ("expected limit\n" \ @@ -191,8 +191,8 @@ /////////////////////////////////////////////////////////////////////////////// #define CHECK_NEQ(A,B) do { \ DEBUG_ONLY( \ - const auto __a = (A); \ - const auto __b = (B); \ + const auto &__a = (A); \ + const auto &__b = (B); \ \ if (util::almost_equal (__a, __b)) { \ _CHECK_PANIC ("expected inequality\n" \ @@ -208,7 +208,7 @@ /////////////////////////////////////////////////////////////////////////////// #define CHECK_ZERO(A) do { \ DEBUG_ONLY( \ - const auto __a = (A); \ + const auto &__a = (A); \ \ if (!util::almost_zero (__a)) { \ _CHECK_PANIC ("expected zero\n" \ @@ -222,7 +222,7 @@ /////////////////////////////////////////////////////////////////////////////// #define CHECK_NEZ(A) do { \ DEBUG_ONLY( \ - const auto __a = (A); \ + const auto &__a = (A); \ if (util::exactly_zero (__a)) \ _CHECK_PANIC ("expected zero\n" \ "__a: %s is %!", \ From d0a797d37eb5fea89af6d439e392e7fc11c89ba9 Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Wed, 3 Aug 2016 18:12:05 +1000 Subject: [PATCH 026/100] debug: add CHECK_MOD --- debug.hpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/debug.hpp b/debug.hpp index d56a8e22..21d1694a 100644 --- a/debug.hpp +++ b/debug.hpp @@ -231,6 +231,21 @@ } 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) #define CHECK_ENUM(C, ...) do { \ From 310c01b9d2e313380bd260745e5b4890a7d331a5 Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Thu, 4 Aug 2016 14:14:24 +1000 Subject: [PATCH 027/100] view: instantiate uint8_t ostream operator --- view.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/view.cpp b/view.cpp index 6eea40d4..ebaf035a 100644 --- a/view.cpp +++ b/view.cpp @@ -58,6 +58,8 @@ namespace util { OSTREAM(const char*) OSTREAM(char*) + OSTREAM(unsigned char*) + OSTREAM(const unsigned char*) OSTREAM(std::string::const_iterator) OSTREAM(std::string::iterator) From 116ad04a1f2b72021034c5fe5b44d5488b9e7bf0 Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Thu, 4 Aug 2016 17:42:41 +1000 Subject: [PATCH 028/100] build: use ostream/istream over iostream --- bezier.hpp | 2 +- colour.hpp | 2 +- fixed.hpp | 2 +- geom/aabb.cpp | 2 ++ geom/aabb.hpp | 3 --- geom/iostream.hpp | 10 +++++++++- geom/ray.cpp | 6 ++++-- geom/ray.hpp | 5 +---- json/flat.cpp.rl | 1 + json/flat.hpp | 2 +- json/tree.hpp | 2 +- log.cpp | 6 +++--- log.hpp | 2 +- net/address.hpp | 2 +- range.hpp | 2 +- stats.hpp | 2 +- stream.hpp | 2 +- tools/json-schema.cpp | 5 +++++ version.hpp | 2 +- 19 files changed, 36 insertions(+), 24 deletions(-) diff --git a/bezier.hpp b/bezier.hpp index bafd612c..2253b04e 100644 --- a/bezier.hpp +++ b/bezier.hpp @@ -20,7 +20,7 @@ #include "point.hpp" #include "region.hpp" -#include +#include namespace util { template diff --git a/colour.hpp b/colour.hpp index d0df406e..5cda6a1a 100644 --- a/colour.hpp +++ b/colour.hpp @@ -19,7 +19,7 @@ #include "coord.hpp" -#include +#include namespace util { /// An RGBA colour POD type. diff --git a/fixed.hpp b/fixed.hpp index 9ce3b9c2..5992a43a 100644 --- a/fixed.hpp +++ b/fixed.hpp @@ -20,7 +20,7 @@ #include "types/bits.hpp" #include -#include +#include namespace util { template diff --git a/geom/aabb.cpp b/geom/aabb.cpp index 5145394f..4a1071d2 100644 --- a/geom/aabb.cpp +++ b/geom/aabb.cpp @@ -16,6 +16,8 @@ #include "./aabb.hpp" + +#include "./iostream.hpp" #include "../debug.hpp" using util::geom::AABB; diff --git a/geom/aabb.hpp b/geom/aabb.hpp index 83eb3c4c..bed5e572 100644 --- a/geom/aabb.hpp +++ b/geom/aabb.hpp @@ -65,9 +65,6 @@ namespace util { namespace geom { typedef AABB<3,float> AABB3f; typedef AABB<3,size_t> AABB3u; typedef AABB<3,intmax_t> AABB3i; - - template - std::ostream& operator<< (std::ostream&, AABB); } } #include "aabb.ipp" diff --git a/geom/iostream.hpp b/geom/iostream.hpp index cf533099..c088af94 100644 --- a/geom/iostream.hpp +++ b/geom/iostream.hpp @@ -19,9 +19,17 @@ #include "./fwd.hpp" -#include +#include namespace util { namespace geom { + template + std::ostream& + operator<< (std::ostream&, AABB); + + template + std::ostream& + operator<< (std::ostream&, ray); + template std::ostream& operator<< (std::ostream&, sphere); diff --git a/geom/ray.cpp b/geom/ray.cpp index 5fdf6ae8..84982aab 100644 --- a/geom/ray.cpp +++ b/geom/ray.cpp @@ -14,9 +14,11 @@ * Copyright 2015 Danny Robson */ -#include "ray.hpp" +#include "./ray.hpp" + +#include "./iostream.hpp" +#include "./ops.hpp" -#include "ops.hpp" #include "../debug.hpp" using util::geom::ray; diff --git a/geom/ray.hpp b/geom/ray.hpp index ab00b605..264b1baf 100644 --- a/geom/ray.hpp +++ b/geom/ray.hpp @@ -23,7 +23,7 @@ #include "../vector.hpp" #include "../point.hpp" -#include +#include namespace util { namespace geom { template @@ -50,9 +50,6 @@ namespace util { namespace geom { vector direction; }; - template - std::ostream& operator<< (std::ostream&, ray); - typedef ray<2,float> ray2f; typedef ray<3,float> ray3f; } } diff --git a/json/flat.cpp.rl b/json/flat.cpp.rl index 8394813e..6b78f31a 100644 --- a/json/flat.cpp.rl +++ b/json/flat.cpp.rl @@ -25,6 +25,7 @@ #include "preprocessor.hpp" #include +#include //----------------------------------------------------------------------------- %%{ diff --git a/json/flat.hpp b/json/flat.hpp index b8a58224..5e0bb54a 100644 --- a/json/flat.hpp +++ b/json/flat.hpp @@ -18,7 +18,7 @@ #define __UTIL_JSON_FLAT_HPP #include -#include +#include #include "../view.hpp" diff --git a/json/tree.hpp b/json/tree.hpp index 2170ff0b..e4a99ac7 100644 --- a/json/tree.hpp +++ b/json/tree.hpp @@ -23,7 +23,7 @@ #include "../iterator.hpp" #include "../view.hpp" -#include +#include #include #include #include diff --git a/log.cpp b/log.cpp index 3dc9f6a8..dbd82ae6 100644 --- a/log.cpp +++ b/log.cpp @@ -24,12 +24,12 @@ #include "cast.hpp" #include -#include #include +#include +#include +#include #include #include -#include - /////////////////////////////////////////////////////////////////////////////// static diff --git a/log.hpp b/log.hpp index dd2e588c..7b2e1e4a 100644 --- a/log.hpp +++ b/log.hpp @@ -20,7 +20,7 @@ #include "./nocopy.hpp" #include "./preprocessor.hpp" -#include +#include #include // Windows.h or one of its friends defines a macro 'ERROR'. Screw Microsoft. diff --git a/net/address.hpp b/net/address.hpp index 538ac185..544d9200 100644 --- a/net/address.hpp +++ b/net/address.hpp @@ -24,7 +24,7 @@ #include "ws2tcpip.h" #endif -#include +#include #include diff --git a/range.hpp b/range.hpp index 9b868fc6..d7379884 100644 --- a/range.hpp +++ b/range.hpp @@ -19,7 +19,7 @@ #define __UTIL_RANGE_HPP #include -#include +#include namespace util { /** diff --git a/stats.hpp b/stats.hpp index d9dc8486..9f08f7ab 100644 --- a/stats.hpp +++ b/stats.hpp @@ -17,7 +17,7 @@ #ifndef __UTIL_STATS_HPP #define __UTIL_STATS_HPP -#include +#include namespace util { diff --git a/stream.hpp b/stream.hpp index 3f8ccfbf..4de72a5d 100644 --- a/stream.hpp +++ b/stream.hpp @@ -17,7 +17,7 @@ #ifndef __UTIL_STREAM_HPP #define __UTIL_STREAM_HPP -#include +#include namespace util { namespace stream { diff --git a/tools/json-schema.cpp b/tools/json-schema.cpp index 0fce2853..ebea7d90 100644 --- a/tools/json-schema.cpp +++ b/tools/json-schema.cpp @@ -23,9 +23,13 @@ #include "io.hpp" #include +#include + namespace fs = boost::filesystem; + +/////////////////////////////////////////////////////////////////////////////// enum { ARG_CMD, ARG_SCHEMA, @@ -35,6 +39,7 @@ enum { }; +/////////////////////////////////////////////////////////////////////////////// int main (int argc, char **argv) { if (argc != NUM_ARGS) { diff --git a/version.hpp b/version.hpp index c42749e7..e3097c9c 100644 --- a/version.hpp +++ b/version.hpp @@ -19,7 +19,7 @@ #include #include -#include +#include #include namespace util { From 6ddff9dfde02f7b8474bec045971ce5fcb960fb8 Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Wed, 10 Aug 2016 17:33:45 +1000 Subject: [PATCH 029/100] coord/base: use std::fill for scalar constructor --- coord/base.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coord/base.hpp b/coord/base.hpp index 20c50ac0..42c5abde 100644 --- a/coord/base.hpp +++ b/coord/base.hpp @@ -45,7 +45,7 @@ namespace util { namespace coord { base () = default; 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 &rhs) = default; base& operator= (const base &rhs) = default; From 0b811e636e93255816207c5d2c82744b4cabe751 Mon Sep 17 00:00:00 2001 From: Danny Robson Date: Wed, 10 Aug 2016 17:33:58 +1000 Subject: [PATCH 030/100] coord/base: remove front/back methods --- coord/base.hpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/coord/base.hpp b/coord/base.hpp index 42c5abde..b2b38c08 100644 --- a/coord/base.hpp +++ b/coord/base.hpp @@ -60,12 +60,6 @@ namespace util { namespace coord { auto begin (void) { return std::begin (this->data); } auto end (void) { return std::end (this->data); } - const T& front (void) const { return this->data[0]; } - T& front (void) { return this->data[0]; } - - const T& back (void) const { return this->data[S-1]; } - T& back (void) { return this->data[S-1]; } - /////////////////////////////////////////////////////////////////////// // conversions template