mirror of https://github.com/oxen-io/lokinet
Merge pull request #1124 from jagerman/deabseil-finale
De-abseil finale: no more abseilpull/1051/head^2
commit
1e96347981
@ -1 +0,0 @@
|
||||
Subproject commit aa844899c937bde5d2b24f276b59997e5b668bde
|
@ -0,0 +1 @@
|
||||
Subproject commit 9a0ee2542848ab8625984fc8cdbfb9b5414c0082
|
@ -0,0 +1,321 @@
|
||||
#pragma once
|
||||
#include <array>
|
||||
#include <cstdint>
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
|
||||
#include "../util/meta/traits.hpp"
|
||||
#include "../util/endian.hpp"
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
/// 128-bit unsigned integer. Does *not* support
|
||||
/// multiplication/division/modulus.
|
||||
struct uint128_t
|
||||
{
|
||||
// Swap order on little/big endian so that the first byte of the struct is
|
||||
// always most significant on big endian and least significant on little
|
||||
// endian.
|
||||
#ifdef __BIG_ENDIAN__
|
||||
uint64_t upper, lower;
|
||||
#else
|
||||
uint64_t lower, upper;
|
||||
#endif
|
||||
|
||||
// Initializes with 0s
|
||||
constexpr uint128_t() : uint128_t{0, 0}
|
||||
{
|
||||
}
|
||||
|
||||
// Initializes with least-significant value
|
||||
constexpr uint128_t(uint64_t lower) : uint128_t{0, lower}
|
||||
{
|
||||
}
|
||||
|
||||
// Initializes with upper and lower values
|
||||
constexpr uint128_t(uint64_t upper, uint64_t lower)
|
||||
// clang-format off
|
||||
#ifdef __BIG_ENDIAN__
|
||||
: upper{upper}, lower{lower}
|
||||
#else
|
||||
: lower{lower}, upper{upper}
|
||||
#endif
|
||||
// clang-format on
|
||||
{
|
||||
}
|
||||
|
||||
constexpr uint128_t(const uint128_t&) = default;
|
||||
constexpr uint128_t(uint128_t&&) = default;
|
||||
constexpr uint128_t&
|
||||
operator=(const uint128_t&) = default;
|
||||
constexpr uint128_t&
|
||||
operator=(uint128_t&&) = default;
|
||||
|
||||
// bitwise and
|
||||
constexpr uint128_t&
|
||||
operator&=(const uint128_t& o)
|
||||
{
|
||||
upper &= o.upper;
|
||||
lower &= o.lower;
|
||||
return *this;
|
||||
}
|
||||
constexpr uint128_t operator&(const uint128_t& o) const
|
||||
{
|
||||
uint128_t result = *this;
|
||||
result &= o;
|
||||
return result;
|
||||
}
|
||||
|
||||
// bitwise or
|
||||
constexpr uint128_t&
|
||||
operator|=(const uint128_t& o)
|
||||
{
|
||||
upper |= o.upper;
|
||||
lower |= o.lower;
|
||||
return *this;
|
||||
}
|
||||
constexpr uint128_t
|
||||
operator|(const uint128_t& o) const
|
||||
{
|
||||
uint128_t result = *this;
|
||||
result |= o;
|
||||
return result;
|
||||
}
|
||||
|
||||
// bitwise xor
|
||||
constexpr uint128_t&
|
||||
operator^=(const uint128_t& o)
|
||||
{
|
||||
upper ^= o.upper;
|
||||
lower ^= o.lower;
|
||||
return *this;
|
||||
}
|
||||
constexpr uint128_t
|
||||
operator^(const uint128_t& o) const
|
||||
{
|
||||
uint128_t result = *this;
|
||||
result ^= o;
|
||||
return result;
|
||||
}
|
||||
|
||||
// bitwise not
|
||||
constexpr uint128_t
|
||||
operator~() const
|
||||
{
|
||||
return {~upper, ~lower};
|
||||
}
|
||||
|
||||
// bool: true if any bit set
|
||||
explicit constexpr operator bool() const
|
||||
{
|
||||
return static_cast< bool >(lower) || static_cast< bool >(upper);
|
||||
}
|
||||
|
||||
// Casting to basic unsigned int types: casts away upper bits
|
||||
explicit constexpr operator uint8_t() const
|
||||
{
|
||||
return static_cast< uint8_t >(lower);
|
||||
}
|
||||
explicit constexpr operator uint16_t() const
|
||||
{
|
||||
return static_cast< uint16_t >(lower);
|
||||
}
|
||||
explicit constexpr operator uint32_t() const
|
||||
{
|
||||
return static_cast< uint32_t >(lower);
|
||||
}
|
||||
explicit constexpr operator uint64_t() const
|
||||
{
|
||||
return lower;
|
||||
}
|
||||
|
||||
constexpr bool
|
||||
operator==(const uint128_t& b) const
|
||||
{
|
||||
return lower == b.lower && upper == b.upper;
|
||||
}
|
||||
|
||||
constexpr bool
|
||||
operator!=(const uint128_t& b) const
|
||||
{
|
||||
return lower != b.lower || upper != b.upper;
|
||||
}
|
||||
|
||||
constexpr bool
|
||||
operator<(const uint128_t& b) const
|
||||
{
|
||||
return upper < b.upper || (upper == b.upper && lower < b.lower);
|
||||
}
|
||||
|
||||
constexpr bool
|
||||
operator<=(const uint128_t& b) const
|
||||
{
|
||||
return upper < b.upper || (upper == b.upper && lower <= b.lower);
|
||||
}
|
||||
|
||||
constexpr bool
|
||||
operator>(const uint128_t& b) const
|
||||
{
|
||||
return upper > b.upper || (upper == b.upper && lower > b.lower);
|
||||
}
|
||||
|
||||
constexpr bool
|
||||
operator>=(const uint128_t& b) const
|
||||
{
|
||||
return upper > b.upper || (upper == b.upper && lower >= b.lower);
|
||||
}
|
||||
|
||||
constexpr uint128_t&
|
||||
operator++()
|
||||
{
|
||||
if(++lower == 0)
|
||||
++upper;
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr uint128_t
|
||||
operator++(int)
|
||||
{
|
||||
auto copy = *this;
|
||||
++*this;
|
||||
return copy;
|
||||
}
|
||||
|
||||
constexpr uint128_t&
|
||||
operator+=(const uint128_t& b)
|
||||
{
|
||||
lower += b.lower;
|
||||
if(lower < b.lower)
|
||||
++upper;
|
||||
upper += b.upper;
|
||||
return *this;
|
||||
}
|
||||
constexpr uint128_t
|
||||
operator+(const uint128_t& b) const
|
||||
{
|
||||
uint128_t result = *this;
|
||||
result += b;
|
||||
return result;
|
||||
}
|
||||
|
||||
constexpr uint128_t&
|
||||
operator-=(const uint128_t& b)
|
||||
{
|
||||
if(b.lower > lower)
|
||||
--upper;
|
||||
lower -= b.lower;
|
||||
upper -= b.upper;
|
||||
return *this;
|
||||
}
|
||||
constexpr uint128_t
|
||||
operator-(const uint128_t& b) const
|
||||
{
|
||||
uint128_t result = *this;
|
||||
result -= b;
|
||||
return result;
|
||||
}
|
||||
|
||||
constexpr uint128_t&
|
||||
operator<<=(uint64_t shift)
|
||||
{
|
||||
if(shift == 0)
|
||||
{
|
||||
}
|
||||
else if(shift < 64)
|
||||
{
|
||||
upper = upper << shift | (lower >> (64 - shift));
|
||||
lower <<= shift;
|
||||
}
|
||||
else if(shift == 64)
|
||||
{
|
||||
upper = lower;
|
||||
lower = 0;
|
||||
}
|
||||
else if(shift < 128)
|
||||
{
|
||||
upper = lower << (shift - 64);
|
||||
lower = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
upper = lower = 0;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
constexpr uint128_t
|
||||
operator<<(uint64_t shift) const
|
||||
{
|
||||
uint128_t result = *this;
|
||||
result <<= shift;
|
||||
return result;
|
||||
}
|
||||
|
||||
constexpr uint128_t&
|
||||
operator>>=(uint64_t shift)
|
||||
{
|
||||
if(shift == 0)
|
||||
{
|
||||
}
|
||||
else if(shift < 64)
|
||||
{
|
||||
lower = lower >> shift | upper << (64 - shift);
|
||||
upper >>= shift;
|
||||
}
|
||||
else if(shift == 64)
|
||||
{
|
||||
lower = upper;
|
||||
upper = 0;
|
||||
}
|
||||
else if(shift < 128)
|
||||
{
|
||||
lower = upper >> (shift - 64);
|
||||
upper = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
upper = lower = 0;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
constexpr uint128_t
|
||||
operator>>(uint64_t shift) const
|
||||
{
|
||||
uint128_t result = *this;
|
||||
result >>= shift;
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(sizeof(uint128_t) == 16,
|
||||
"uint128_t has unexpected size (padding?)");
|
||||
|
||||
} // namespace llarp
|
||||
|
||||
namespace std
|
||||
{
|
||||
// Hash function for uint128_t
|
||||
template <>
|
||||
struct hash< llarp::uint128_t >
|
||||
{
|
||||
size_t
|
||||
operator()(const llarp::uint128_t& i) const
|
||||
{
|
||||
size_t h = std::hash< uint64_t >()(i.lower);
|
||||
h ^= std::hash< uint64_t >()(i.upper) + 0x9e3779b9 + (h << 6) + (h >> 2);
|
||||
return h;
|
||||
}
|
||||
};
|
||||
} // namespace std
|
||||
|
||||
inline llarp::uint128_t
|
||||
ntoh128(llarp::uint128_t i)
|
||||
{
|
||||
#ifdef __BIG_ENDIAN__
|
||||
return i;
|
||||
#else
|
||||
const auto loSwapped = htobe64(i.lower);
|
||||
const auto hiSwapped = htobe64(i.upper);
|
||||
return {loSwapped, hiSwapped};
|
||||
#endif
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
#include <util/logging/logger_internal.hpp>
|
||||
|
||||
#include <date/date.h>
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
std::ostream&
|
||||
operator<<(std::ostream& out, const log_timestamp& ts)
|
||||
{
|
||||
std::chrono::milliseconds delta{ts.delta};
|
||||
auto h = std::chrono::duration_cast< std::chrono::hours >(delta);
|
||||
delta -= h;
|
||||
auto m = std::chrono::duration_cast< std::chrono::minutes >(delta);
|
||||
delta -= m;
|
||||
auto s = std::chrono::duration_cast< std::chrono::seconds >(delta);
|
||||
delta -= s;
|
||||
auto ms = delta;
|
||||
std::chrono::time_point< std::chrono::system_clock,
|
||||
std::chrono::milliseconds >
|
||||
now{std::chrono::milliseconds{ts.now}};
|
||||
date::operator<<(out, now) << " UTC [+";
|
||||
auto old_fill = out.fill('0');
|
||||
if(h > 0h)
|
||||
{
|
||||
out << h.count() << 'h';
|
||||
out.width(2); // 0-fill minutes if we have hours
|
||||
}
|
||||
if(h > 0h || m > 0min)
|
||||
{
|
||||
out << m.count() << 'm';
|
||||
out.width(2); // 0-fill seconds if we have minutes
|
||||
}
|
||||
out << s.count() << '.';
|
||||
out.width(3);
|
||||
out << ms.count();
|
||||
out.fill(old_fill);
|
||||
return out << "s]";
|
||||
}
|
||||
} // namespace llarp
|
@ -1,17 +1,221 @@
|
||||
#ifndef LLARP_STRING_VIEW_HPP
|
||||
#define LLARP_STRING_VIEW_HPP
|
||||
|
||||
#include <absl/hash/hash.h>
|
||||
#include <absl/strings/string_view.h>
|
||||
namespace llarp
|
||||
{
|
||||
using string_view = absl::string_view;
|
||||
using string_view_hash = absl::Hash< string_view >;
|
||||
|
||||
static std::string
|
||||
string_view_string(const string_view& v)
|
||||
{
|
||||
return std::string(v);
|
||||
}
|
||||
} // namespace llarp
|
||||
// Copied from loki-mq (with namespaces modified); when we fully import loki-mq
|
||||
// we can just use it directly.
|
||||
|
||||
// To keep this identical to loki-mq's copy (e.g. to be able to diff it):
|
||||
//
|
||||
// clang-format off
|
||||
|
||||
#include <string>
|
||||
|
||||
#ifdef __cpp_lib_string_view
|
||||
|
||||
#include <string_view>
|
||||
namespace llarp { using string_view = std::string_view; }
|
||||
|
||||
#else
|
||||
|
||||
#include <ostream>
|
||||
#include <limits>
|
||||
|
||||
namespace llarp {
|
||||
|
||||
/// Basic implementation of std::string_view (except for std::hash support).
|
||||
class simple_string_view {
|
||||
const char *data_;
|
||||
size_t size_;
|
||||
public:
|
||||
using traits_type = std::char_traits<char>;
|
||||
using value_type = char;
|
||||
using pointer = char*;
|
||||
using const_pointer = const char*;
|
||||
using reference = char&;
|
||||
using const_reference = const char&;
|
||||
using const_iterator = const_pointer;
|
||||
using iterator = const_iterator;
|
||||
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||
using reverse_iterator = const_reverse_iterator;
|
||||
using size_type = std::size_t;
|
||||
using different_type = std::ptrdiff_t;
|
||||
|
||||
static constexpr auto& npos = std::string::npos;
|
||||
|
||||
constexpr simple_string_view() noexcept : data_{nullptr}, size_{0} {}
|
||||
constexpr simple_string_view(const simple_string_view&) noexcept = default;
|
||||
simple_string_view(const std::string& str) : data_{str.data()}, size_{str.size()} {}
|
||||
constexpr simple_string_view(const char* data, size_t size) noexcept : data_{data}, size_{size} {}
|
||||
simple_string_view(const char* data) : data_{data}, size_{traits_type::length(data)} {}
|
||||
simple_string_view& operator=(const simple_string_view&) = default;
|
||||
constexpr const char* data() const noexcept { return data_; }
|
||||
constexpr size_t size() const noexcept { return size_; }
|
||||
constexpr size_t length() const noexcept { return size_; }
|
||||
constexpr size_t max_size() const noexcept { return std::numeric_limits<size_t>::max(); }
|
||||
constexpr bool empty() const noexcept { return size_ == 0; }
|
||||
operator std::string() const { return {data_, size_}; }
|
||||
constexpr const char* begin() const noexcept { return data_; }
|
||||
constexpr const char* cbegin() const noexcept { return data_; }
|
||||
constexpr const char* end() const noexcept { return data_ + size_; }
|
||||
constexpr const char* cend() const noexcept { return data_ + size_; }
|
||||
reverse_iterator rbegin() const { return reverse_iterator{end()}; }
|
||||
reverse_iterator crbegin() const { return reverse_iterator{end()}; }
|
||||
reverse_iterator rend() const { return reverse_iterator{begin()}; }
|
||||
reverse_iterator crend() const { return reverse_iterator{begin()}; }
|
||||
constexpr const char& operator[](size_t pos) const { return data_[pos]; }
|
||||
constexpr const char& front() const { return *data_; }
|
||||
constexpr const char& back() const { return data_[size_ - 1]; }
|
||||
int compare(simple_string_view s) const;
|
||||
constexpr void remove_prefix(size_t n) { data_ += n; size_ -= n; }
|
||||
constexpr void remove_suffix(size_t n) { size_ -= n; }
|
||||
void swap(simple_string_view &s) noexcept { std::swap(data_, s.data_); std::swap(size_, s.size_); }
|
||||
|
||||
#if defined(__clang__) || !defined(__GNUG__) || __GNUC__ >= 6
|
||||
constexpr // GCC 5.x is buggy wrt constexpr throwing
|
||||
#endif
|
||||
const char& at(size_t pos) const {
|
||||
if (pos >= size())
|
||||
throw std::out_of_range{"invalid string_view index"};
|
||||
return data_[pos];
|
||||
};
|
||||
|
||||
size_t copy(char* dest, size_t count, size_t pos = 0) const {
|
||||
if (pos > size()) throw std::out_of_range{"invalid copy pos"};
|
||||
size_t rcount = std::min(count, size_ - pos);
|
||||
traits_type::copy(dest, data_ + pos, rcount);
|
||||
return rcount;
|
||||
}
|
||||
|
||||
#if defined(__clang__) || !defined(__GNUG__) || __GNUC__ >= 6
|
||||
constexpr // GCC 5.x is buggy wrt constexpr throwing
|
||||
#endif
|
||||
simple_string_view substr(size_t pos = 0, size_t count = npos) const {
|
||||
if (pos > size()) throw std::out_of_range{"invalid substr range"};
|
||||
simple_string_view result = *this;
|
||||
if (pos > 0) result.remove_prefix(pos);
|
||||
if (count < result.size()) result.remove_suffix(result.size() - count);
|
||||
return result;
|
||||
}
|
||||
|
||||
size_t find(simple_string_view v, size_t pos = 0) const {
|
||||
if (pos > size_ || v.size_ > size_) return npos;
|
||||
for (const size_t max_pos = size_ - v.size_; pos <= max_pos; ++pos) {
|
||||
if (0 == traits_type::compare(v.data_, data_ + pos, v.size_))
|
||||
return pos;
|
||||
}
|
||||
return npos;
|
||||
}
|
||||
size_t find(char c, size_t pos = 0) const { return find({&c, 1}, pos); }
|
||||
size_t find(const char* c, size_t pos, size_t count) const { return find({c, count}, pos); }
|
||||
size_t find(const char* c, size_t pos = 0) const { return find(simple_string_view(c), pos); }
|
||||
|
||||
size_t rfind(simple_string_view v, size_t pos = npos) const {
|
||||
if (v.size_ > size_) return npos;
|
||||
const size_t max_pos = size_ - v.size_;
|
||||
for (pos = std::min(pos, max_pos); pos <= max_pos; --pos) {
|
||||
if (0 == traits_type::compare(v.data_, data_ + pos, v.size_))
|
||||
return pos;
|
||||
}
|
||||
return npos;
|
||||
}
|
||||
size_t rfind(char c, size_t pos = npos) const { return rfind({&c, 1}, pos); }
|
||||
size_t rfind(const char* c, size_t pos, size_t count) const { return rfind({c, count}, pos); }
|
||||
size_t rfind(const char* c, size_t pos = npos) const { return rfind(simple_string_view(c), pos); }
|
||||
|
||||
constexpr size_t find_first_of(simple_string_view v, size_t pos = 0) const noexcept {
|
||||
for (; pos < size_; ++pos)
|
||||
for (char c : v)
|
||||
if (data_[pos] == c)
|
||||
return pos;
|
||||
return npos;
|
||||
}
|
||||
constexpr size_t find_first_of(char c, size_t pos = 0) const noexcept { return find_first_of({&c, 1}, pos); }
|
||||
constexpr size_t find_first_of(const char* c, size_t pos, size_t count) const { return find_first_of({c, count}, pos); }
|
||||
size_t find_first_of(const char* c, size_t pos = 0) const { return find_first_of(simple_string_view(c), pos); }
|
||||
|
||||
constexpr size_t find_last_of(simple_string_view v, const size_t pos = npos) const noexcept {
|
||||
if (size_ == 0) return npos;
|
||||
const size_t last_pos = std::min(pos, size_-1);
|
||||
for (size_t i = last_pos; i <= last_pos; --i)
|
||||
for (char c : v)
|
||||
if (data_[i] == c)
|
||||
return i;
|
||||
return npos;
|
||||
}
|
||||
constexpr size_t find_last_of(char c, size_t pos = npos) const noexcept { return find_last_of({&c, 1}, pos); }
|
||||
constexpr size_t find_last_of(const char* c, size_t pos, size_t count) const { return find_last_of({c, count}, pos); }
|
||||
size_t find_last_of(const char* c, size_t pos = npos) const { return find_last_of(simple_string_view(c), pos); }
|
||||
|
||||
constexpr size_t find_first_not_of(simple_string_view v, size_t pos = 0) const noexcept {
|
||||
for (; pos < size_; ++pos) {
|
||||
bool none = true;
|
||||
for (char c : v) {
|
||||
if (data_[pos] == c) {
|
||||
none = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (none) return pos;
|
||||
}
|
||||
return npos;
|
||||
}
|
||||
constexpr size_t find_first_not_of(char c, size_t pos = 0) const noexcept { return find_first_not_of({&c, 1}, pos); }
|
||||
constexpr size_t find_first_not_of(const char* c, size_t pos, size_t count) const { return find_first_not_of({c, count}, pos); }
|
||||
size_t find_first_not_of(const char* c, size_t pos = 0) const { return find_first_not_of(simple_string_view(c), pos); }
|
||||
|
||||
constexpr size_t find_last_not_of(simple_string_view v, const size_t pos = npos) const noexcept {
|
||||
if (size_ == 0) return npos;
|
||||
const size_t last_pos = std::min(pos, size_-1);
|
||||
for (size_t i = last_pos; i <= last_pos; --i) {
|
||||
bool none = true;
|
||||
for (char c : v) {
|
||||
if (data_[i] == c) {
|
||||
none = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (none) return i;
|
||||
}
|
||||
return npos;
|
||||
}
|
||||
constexpr size_t find_last_not_of(char c, size_t pos = npos) const noexcept { return find_last_not_of({&c, 1}, pos); }
|
||||
constexpr size_t find_last_not_of(const char* c, size_t pos, size_t count) const { return find_last_not_of({c, count}, pos); }
|
||||
size_t find_last_not_of(const char* c, size_t pos = npos) const { return find_last_not_of(simple_string_view(c), pos); }
|
||||
};
|
||||
inline bool operator==(simple_string_view lhs, simple_string_view rhs) {
|
||||
return lhs.size() == rhs.size() && 0 == std::char_traits<char>::compare(lhs.data(), rhs.data(), lhs.size());
|
||||
};
|
||||
inline bool operator!=(simple_string_view lhs, simple_string_view rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
inline int simple_string_view::compare(simple_string_view s) const {
|
||||
int cmp = std::char_traits<char>::compare(data_, s.data(), std::min(size_, s.size()));
|
||||
if (cmp) return cmp;
|
||||
if (size_ < s.size()) return -1;
|
||||
else if (size_ > s.size()) return 1;
|
||||
return 0;
|
||||
}
|
||||
inline bool operator<(simple_string_view lhs, simple_string_view rhs) {
|
||||
return lhs.compare(rhs) < 0;
|
||||
};
|
||||
inline bool operator<=(simple_string_view lhs, simple_string_view rhs) {
|
||||
return lhs.compare(rhs) <= 0;
|
||||
};
|
||||
inline bool operator>(simple_string_view lhs, simple_string_view rhs) {
|
||||
return lhs.compare(rhs) > 0;
|
||||
};
|
||||
inline bool operator>=(simple_string_view lhs, simple_string_view rhs) {
|
||||
return lhs.compare(rhs) >= 0;
|
||||
};
|
||||
inline std::ostream& operator<<(std::ostream& os, const simple_string_view& s) {
|
||||
os.write(s.data(), s.size());
|
||||
return os;
|
||||
}
|
||||
|
||||
using string_view = simple_string_view;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -1,10 +1,16 @@
|
||||
#ifndef LLARP_TYPES_H
|
||||
#define LLARP_TYPES_H
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
using byte_t = uint8_t;
|
||||
using llarp_proto_version_t = std::uint8_t;
|
||||
using llarp_time_t = std::uint64_t;
|
||||
using llarp_seconds_t = std::uint64_t;
|
||||
|
||||
namespace llarp
|
||||
{
|
||||
using namespace std::literals;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -1,66 +1,71 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <array>
|
||||
#include <absl/types/variant.h>
|
||||
|
||||
#include <catch2/catch.hpp>
|
||||
#include <util/bits.hpp>
|
||||
|
||||
using ArrayUC1 = std::array< unsigned char, 1 >;
|
||||
using ArrayUC20 = std::array< unsigned char, 20 >;
|
||||
using ArrayU1 = std::array< unsigned int, 1 >;
|
||||
using ArrayULL1 = std::array< unsigned long long, 1 >;
|
||||
using namespace llarp::bits;
|
||||
|
||||
using TestType = absl::variant< ArrayUC1, ArrayUC20, ArrayU1, ArrayULL1 >;
|
||||
TEST_CASE("test bit counting, 8-bit", "[bits]") {
|
||||
// Workaround for gcc 5's stdlib; we can drop this crap (and drop all the `T`'s below) once we
|
||||
// stop supporting it.
|
||||
using T = std::tuple<unsigned char, size_t>;
|
||||
auto x = GENERATE(table<unsigned char, size_t>({
|
||||
T{0b00000000, 0},
|
||||
T{0b00000001, 1},
|
||||
T{0b00000010, 1},
|
||||
T{0b00000100, 1},
|
||||
T{0b00001000, 1},
|
||||
T{0b00010000, 1},
|
||||
T{0b00100000, 1},
|
||||
T{0b01000000, 1},
|
||||
T{0b10000000, 1},
|
||||
T{0b11111111, 8},
|
||||
}));
|
||||
std::array<unsigned char, 1> arr{{std::get<0>(x)}};
|
||||
auto expected = std::get<1>(x);
|
||||
REQUIRE( count_array_bits(arr) == expected );
|
||||
}
|
||||
|
||||
struct InputData
|
||||
{
|
||||
TestType data;
|
||||
size_t result;
|
||||
};
|
||||
TEST_CASE("test bit counting, 20 x 8-bit", "[bits]") {
|
||||
std::array<unsigned char, 20> x{{
|
||||
0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
||||
0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
||||
0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
||||
0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000}};
|
||||
REQUIRE( count_array_bits(x) == 0 );
|
||||
|
||||
struct TestBits : public ::testing::TestWithParam< InputData >
|
||||
{
|
||||
};
|
||||
x = {{
|
||||
0b11111111, 0b00000100, 0b00000100, 0b00000100, 0b00000100,
|
||||
0b11111111, 0b00000100, 0b00000100, 0b00000100, 0b00000100,
|
||||
0b11111111, 0b00000100, 0b00000100, 0b00000100, 0b00000100,
|
||||
0b11111111, 0b00000100, 0b00000100, 0b00000100, 0b00000100}};
|
||||
REQUIRE( count_array_bits(x) == 48 );
|
||||
}
|
||||
|
||||
TEST_P(TestBits, bitcount)
|
||||
{
|
||||
auto d = GetParam();
|
||||
ASSERT_EQ(d.result,
|
||||
absl::visit(
|
||||
[](const auto& v) { return llarp::bits::count_array_bits(v); },
|
||||
d.data));
|
||||
TEST_CASE("test bit counting, unsigned int", "[bits]") {
|
||||
using T = std::tuple<unsigned int, size_t>; // gcc 5 workaround
|
||||
auto x = GENERATE(table<unsigned int, size_t>({
|
||||
T{0b00000000000000000000000000000000, 0},
|
||||
T{0b00101010101010101010101010101010, 15},
|
||||
T{0b10101010101010101010101010101010, 16},
|
||||
T{0b01010101010101010101010101010101, 16},
|
||||
T{0b11111111111111111111111111111111, 32},
|
||||
}));
|
||||
|
||||
std::array<unsigned int, 1> arr{{std::get<0>(x)}};
|
||||
auto expected = std::get<1>(x);
|
||||
REQUIRE( llarp::bits::count_array_bits(arr) == expected );
|
||||
}
|
||||
|
||||
// clang-format off
|
||||
static const InputData inputData[] = {
|
||||
{ArrayUC1{{0b00000000}}, 0},
|
||||
{ArrayUC1{{0b00000001}}, 1},
|
||||
{ArrayUC1{{0b00000010}}, 1},
|
||||
{ArrayUC1{{0b00000100}}, 1},
|
||||
{ArrayUC1{{0b00001000}}, 1},
|
||||
{ArrayUC1{{0b00010000}}, 1},
|
||||
{ArrayUC1{{0b00100000}}, 1},
|
||||
{ArrayUC1{{0b01000000}}, 1},
|
||||
{ArrayUC1{{0b10000000}}, 1},
|
||||
{ArrayUC1{{0b11111111}}, 8},
|
||||
{ArrayUC20{{0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
||||
0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
||||
0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000,
|
||||
0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000}}, 0},
|
||||
{ArrayUC20{{0b11111111, 0b00000100, 0b00000100, 0b00000100, 0b00000100,
|
||||
0b11111111, 0b00000100, 0b00000100, 0b00000100, 0b00000100,
|
||||
0b11111111, 0b00000100, 0b00000100, 0b00000100, 0b00000100,
|
||||
0b11111111, 0b00000100, 0b00000100, 0b00000100, 0b00000100}}, 48},
|
||||
{ArrayU1{{0b00000000000000000000000000000000}}, 0},
|
||||
{ArrayU1{{0b00101010101010101010101010101010}}, 15},
|
||||
{ArrayU1{{0b10101010101010101010101010101010}}, 16},
|
||||
{ArrayU1{{0b01010101010101010101010101010101}}, 16},
|
||||
{ArrayU1{{0b11111111111111111111111111111111}}, 32},
|
||||
{ArrayULL1{{0b0000000000000000000000000000000000000000000000000000000000000000}}, 0},
|
||||
{ArrayULL1{{0b0010101010101010101010101010101000101010101010101010101010101010}}, 30},
|
||||
{ArrayULL1{{0b1010101010101010101010101010101010101010101010101010101010101010}}, 32},
|
||||
{ArrayULL1{{0b0101010101010101010101010101010101010101010101010101010101010101}}, 32},
|
||||
{ArrayULL1{{0b1111111111111111111111111111111111111111111111111111111111111111}}, 64},
|
||||
};
|
||||
// clang-format on
|
||||
TEST_CASE("test bit counting, unsigned long long", "[bits]") {
|
||||
using T = std::tuple<unsigned long long, size_t>; // gcc 5 workaround
|
||||
auto x = GENERATE(table<unsigned long long, size_t>({
|
||||
T{0b0000000000000000000000000000000000000000000000000000000000000000, 0},
|
||||
T{0b0010101010101010101010101010101000101010101010101010101010101010, 30},
|
||||
T{0b1010101010101010101010101010101010101010101010101010101010101010, 32},
|
||||
T{0b0101010101010101010101010101010101010101010101010101010101010101, 32},
|
||||
T{0b1111111111111111111111111111111111111111111111111111111111111111, 64},
|
||||
}));
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(TestBits, TestBits, ::testing::ValuesIn(inputData));
|
||||
std::array<unsigned long long, 1> arr{{std::get<0>(x)}};
|
||||
auto expected = std::get<1>(x);
|
||||
REQUIRE( llarp::bits::count_array_bits(arr) == expected );
|
||||
}
|
||||
|
@ -0,0 +1,93 @@
|
||||
#include <util/str.hpp>
|
||||
#include <catch2/catch.hpp>
|
||||
|
||||
using namespace std::literals;
|
||||
|
||||
TEST_CASE("TrimWhitespace -- positive tests", "[str][trim]")
|
||||
{
|
||||
// Test that things that should be trimmed actually get trimmed
|
||||
auto fee = " J a c k"s;
|
||||
auto fi = "\ra\nd"s;
|
||||
auto fo = "\fthe "s;
|
||||
auto fum = " \t\r\n\v\f Beanstalk\n\n\n\t\r\f\v \n\n\r\f\f\f\f\v"s;
|
||||
for (auto* s: {&fee, &fi, &fo, &fum})
|
||||
*s = llarp::TrimWhitespace(*s);
|
||||
|
||||
REQUIRE( fee == "J a c k" );
|
||||
REQUIRE( fi == "a\nd" );
|
||||
REQUIRE( fo == "the" );
|
||||
REQUIRE( fum == "Beanstalk" );
|
||||
}
|
||||
|
||||
TEST_CASE("TrimWhitespace -- negative tests", "[str][trim]")
|
||||
{
|
||||
// Test that things that shouldn't be trimmed don't get trimmed
|
||||
auto c = GENERATE(range(std::numeric_limits<char>::min(), std::numeric_limits<char>::max()));
|
||||
std::string plant = c + "bean"s + c;
|
||||
plant = llarp::TrimWhitespace(plant);
|
||||
if (c == ' ' || c == '\t' || c == '\r' || c == '\n' || c == '\f' || c == '\v')
|
||||
REQUIRE( plant == "bean" );
|
||||
else
|
||||
{
|
||||
REQUIRE( plant.size() == 6 );
|
||||
REQUIRE( plant.substr(1, 4) == "bean" );
|
||||
}
|
||||
}
|
||||
|
||||
TEST_CASE("caseless comparison tests - less than", "[str][lt]") {
|
||||
using namespace llarp;
|
||||
CaselessLessThan lt;
|
||||
// Workaround for gcc 5's stdlib; we can drop this crap (and drop all the `T`'s below) once we
|
||||
// stop supporting it.
|
||||
using T = std::tuple<const char*, const char*>;
|
||||
auto expect_less_than = GENERATE(table<const char*, const char*>({
|
||||
T{"", "1"},
|
||||
T{"1", "11"},
|
||||
T{"abc", "abcd"},
|
||||
T{"ABC", "abcd"},
|
||||
T{"abc", "ABCD"},
|
||||
T{"abc", "Abcd"},
|
||||
T{"abc", "abcD"},
|
||||
T{"abc", "abCd"},
|
||||
T{"abc", "zz"},
|
||||
T{"abc", "zzzz"},
|
||||
T{"abc", "abd"},
|
||||
T{"abc", "aBd"},
|
||||
T{"abc", "abD"},
|
||||
T{"ABC", "abd"},
|
||||
T{"abC", "abd"},
|
||||
}));
|
||||
REQUIRE( lt(std::get<0>(expect_less_than), std::get<1>(expect_less_than)) );
|
||||
REQUIRE( !lt(std::get<1>(expect_less_than), std::get<0>(expect_less_than)) );
|
||||
}
|
||||
|
||||
TEST_CASE("caseless comparison tests - equality", "[str][eq]") {
|
||||
using namespace llarp;
|
||||
CaselessLessThan lt;
|
||||
using T = std::tuple<const char*, const char*>; // gcc 5 workaround
|
||||
auto expect_equal = GENERATE(table<const char*, const char*>({
|
||||
T{"1", "1"},
|
||||
T{"a", "A"},
|
||||
T{"abc", "ABC"},
|
||||
T{"abc", "aBc"},
|
||||
T{"ABC", "abc"},
|
||||
}));
|
||||
REQUIRE( !lt(std::get<0>(expect_equal), std::get<1>(expect_equal)) );
|
||||
REQUIRE( !lt(std::get<1>(expect_equal), std::get<0>(expect_equal)) );
|
||||
}
|
||||
|
||||
TEST_CASE("truthy string values", "[str][truthy]") {
|
||||
auto val = GENERATE("true", "TruE", "yes", "yeS", "yES", "yes", "YES", "1", "on", "oN", "ON");
|
||||
REQUIRE( llarp::IsTrueValue(val) );
|
||||
}
|
||||
|
||||
TEST_CASE("falsey string values", "[str][falsey]") {
|
||||
auto val = GENERATE("false", "FalSe", "no", "NO", "No", "nO", "0", "off", "OFF");
|
||||
REQUIRE( llarp::IsFalseValue(val) );
|
||||
}
|
||||
|
||||
TEST_CASE("neither true nor false string values", "[str][nottruefalse]") {
|
||||
auto val = GENERATE("false y", "maybe", "not on", "2", "yesno", "YESNO", "-1", "default", "OMG");
|
||||
REQUIRE( !llarp::IsTrueValue(val) );
|
||||
REQUIRE( !llarp::IsFalseValue(val) );
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
#include <util/str.hpp>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
#include <gmock/gmock.h>
|
||||
|
||||
using namespace llarp;
|
||||
using namespace ::testing;
|
||||
|
||||
struct CmpTestData
|
||||
{
|
||||
bool lt;
|
||||
std::string lhs;
|
||||
std::string rhs;
|
||||
};
|
||||
|
||||
class CaselessCmpTest : public ::testing::TestWithParam< CmpTestData >
|
||||
{
|
||||
};
|
||||
|
||||
TEST_P(CaselessCmpTest, test)
|
||||
{
|
||||
CaselessCmp cmp;
|
||||
auto d = GetParam();
|
||||
ASSERT_EQ(d.lt, cmp(d.lhs, d.rhs));
|
||||
}
|
||||
|
||||
std::vector< CmpTestData > CMPTESTDATA{
|
||||
{true, "", "1"}, {false, "1", ""}, {true, "abc", "abcd"},
|
||||
{true, "abc", "abd"}, {false, "11", "1"}, {false, "a", "A"},
|
||||
{false, "abc", "aBc"}, {false, "ABC", "abc"}};
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(TestStr, CaselessCmpTest, ValuesIn(CMPTESTDATA));
|
||||
|
||||
using TestData = std::pair< bool, std::string >;
|
||||
|
||||
class TestIsFalseValue : public ::testing::TestWithParam< TestData >
|
||||
{
|
||||
};
|
||||
|
||||
TEST_P(TestIsFalseValue, test)
|
||||
{
|
||||
ASSERT_EQ(GetParam().first, IsFalseValue(GetParam().second));
|
||||
}
|
||||
|
||||
std::vector< TestData > FALSE_DATA{
|
||||
{true, "false"}, {true, "FaLsE"}, {true, "no"}, {true, "nO"},
|
||||
{true, "No"}, {true, "NO"}, {true, "NO"}, {true, "0"},
|
||||
{true, "off"}, {true, "oFF"}, {false, "false y"}, {false, "true"},
|
||||
{false, "tRue"}, {false, "on"}};
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(TestStr, TestIsFalseValue, ValuesIn(FALSE_DATA));
|
||||
|
||||
class TestIsTrueValue : public ::testing::TestWithParam< TestData >
|
||||
{
|
||||
};
|
||||
|
||||
TEST_P(TestIsTrueValue, test)
|
||||
{
|
||||
ASSERT_EQ(GetParam().first, IsTrueValue(GetParam().second));
|
||||
}
|
||||
|
||||
std::vector< TestData > TRUE_DATA{
|
||||
{true, "true"}, {true, "TruE"}, {true, "yes"}, {true, "yeS"},
|
||||
{true, "yES"}, {true, "YES"}, {true, "1"}, {false, "0"},
|
||||
{true, "on"}, {true, "oN"}, {false, "false y"}, {false, "truth"},
|
||||
{false, "false"}, {false, "off"}};
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(TestStr, TestIsTrueValue, ValuesIn(TRUE_DATA));
|
@ -1,85 +0,0 @@
|
||||
environment:
|
||||
matrix:
|
||||
- platform: x86
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
generator: "Visual Studio 14 2015"
|
||||
compiler: msvc
|
||||
configuration: Release
|
||||
|
||||
- platform: x64
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
generator: "Visual Studio 14 2015 Win64"
|
||||
compiler: msvc
|
||||
configuration: Release
|
||||
|
||||
- platform: x86
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
generator: "Visual Studio 15 2017"
|
||||
compiler: msvc
|
||||
configuration: Release
|
||||
|
||||
- platform: x64
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2017
|
||||
generator: "Visual Studio 15 2017 Win64"
|
||||
compiler: msvc
|
||||
configuration: Release
|
||||
|
||||
- platform: x86
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
generator: "Visual Studio 16 2019"
|
||||
compiler: msvc19
|
||||
configuration: Release
|
||||
arch: Win32
|
||||
|
||||
- platform: x64
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2019
|
||||
generator: "Visual Studio 16 2019"
|
||||
compiler: msvc19
|
||||
configuration: Release
|
||||
arch: x64
|
||||
|
||||
- platform: x86
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
generator: "MinGW Makefiles"
|
||||
compiler: mingw
|
||||
TOOLCHAIN_PATH: C:\mingw-w64\i686-6.3.0-posix-dwarf-rt_v5-rev1/mingw32\bin
|
||||
CC: C:/mingw-w64/i686-6.3.0-posix-dwarf-rt_v5-rev1/mingw32/bin/gcc.exe
|
||||
CXX: C:/mingw-w64/i686-6.3.0-posix-dwarf-rt_v5-rev1/mingw32/bin/g++.exe
|
||||
configuration: Release
|
||||
|
||||
- platform: x64
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
|
||||
generator: "MinGW Makefiles"
|
||||
compiler: mingw
|
||||
TOOLCHAIN_PATH: C:\mingw-w64\x86_64-7.2.0-posix-seh-rt_v5-rev1\mingw64\bin
|
||||
CC: C:/mingw-w64/x86_64-7.2.0-posix-seh-rt_v5-rev1/mingw64/bin/gcc.exe
|
||||
CXX: C:/mingw-w64/x86_64-7.2.0-posix-seh-rt_v5-rev1/mingw64/bin/g++.exe
|
||||
configuration: Release
|
||||
|
||||
matrix:
|
||||
fast_finish: false
|
||||
|
||||
init:
|
||||
- cmd: cmake --version
|
||||
- cmd: msbuild /version
|
||||
|
||||
install:
|
||||
- cmd: reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\AppModelUnlock" /t REG_DWORD /f /v "AllowDevelopmentWithoutDevLicense" /d "1"
|
||||
- cmd: ren "C:\Program Files\Git\usr\bin\sh.exe" _sh.exe
|
||||
|
||||
build_script:
|
||||
- mkdir build
|
||||
- cd build
|
||||
- if [%compiler%]==[msvc] cmake -G"%generator%" ..
|
||||
- if [%compiler%]==[msvc19] cmake -G"%generator%" -A "%arch%" ..
|
||||
- if [%compiler%]==[mingw] set PATH=%TOOLCHAIN_PATH%;%PATH%
|
||||
- if [%compiler%]==[mingw] cmake -G"%generator%" -DCMAKE_C_COMPILER=%CC% -DCMAKE_CXX_COMPILER=%CXX% -DCMAKE_SH=CMAKE_SH-NOTFOUND -DCMAKE_BUILD_TYPE=%configuration% ..
|
||||
- cmake --build . --config %configuration%
|
||||
|
||||
test_script:
|
||||
- cd %APPVEYOR_BUILD_FOLDER%\build
|
||||
- set CTEST_OUTPUT_ON_FAILURE=1
|
||||
- ctest -C %configuration%
|
||||
- if exist "test\Release\std_filesystem_test.exe" test\Release\std_filesystem_test.exe & exit 0
|
||||
- cd ..
|
||||
|
@ -1,25 +0,0 @@
|
||||
---
|
||||
Language: Cpp
|
||||
BasedOnStyle: Chromium
|
||||
AccessModifierOffset: '-4'
|
||||
IndentWidth: '4'
|
||||
ColumnLimit: 256
|
||||
BreakBeforeBraces: Custom
|
||||
BraceWrapping:
|
||||
AfterClass: true
|
||||
AfterControlStatement: false
|
||||
AfterFunction: true
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: true
|
||||
AfterStruct: true
|
||||
AfterUnion: true
|
||||
BeforeCatch: true
|
||||
BeforeElse: true
|
||||
IndentBraces: false
|
||||
SplitEmptyFunction: true
|
||||
SplitEmptyRecord: true
|
||||
SplitEmptyNamespace: true
|
||||
BreakConstructorInitializers: BeforeComma
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: false
|
||||
IndentPPDirectives: None
|
||||
...
|
@ -1,17 +0,0 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Create a report to help us improve
|
||||
|
||||
---
|
||||
|
||||
**Describe the bug**
|
||||
A clear and concise description of what the bug is.
|
||||
|
||||
**To Reproduce**
|
||||
Detailed steps to reproduce the behavior.
|
||||
|
||||
**Expected behavior**
|
||||
A clear and concise description of what you expected to happen.
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
@ -1,17 +0,0 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: Suggest an idea for this project
|
||||
|
||||
---
|
||||
|
||||
**Is your feature request related to a problem? Please describe.**
|
||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||
|
||||
**Describe the solution you'd like**
|
||||
A clear and concise description of what you want to happen.
|
||||
|
||||
**Describe alternatives you've considered**
|
||||
A clear and concise description of any alternative solutions or features you've considered.
|
||||
|
||||
**Additional context**
|
||||
Add any other context or screenshots about the feature request here.
|
@ -1,2 +0,0 @@
|
||||
/build*/
|
||||
.vscode/
|
@ -1,104 +0,0 @@
|
||||
language: cpp
|
||||
|
||||
dist: xenial # default distribution
|
||||
os: linux # default os
|
||||
sudo: false
|
||||
|
||||
|
||||
matrix:
|
||||
fast_finish: true
|
||||
include:
|
||||
- env: MATRIX_EVAL="CC=gcc-5 && CXX=g++-5 && GENERATOR='Unix Makefiles' && CONFIG=Release"
|
||||
addons: { apt: { packages: ["g++-5"], sources: ["ubuntu-toolchain-r-test"] } }
|
||||
|
||||
- env: MATRIX_EVAL="CC=gcc-6 && CXX=g++-6 && GENERATOR='Unix Makefiles' && CONFIG=Release"
|
||||
addons: { apt: { packages: ["g++-6"], sources: ["ubuntu-toolchain-r-test"] } }
|
||||
|
||||
- env: MATRIX_EVAL="CC=gcc-7 && CXX=g++-7 && GENERATOR='Unix Makefiles' && CONFIG=Release"
|
||||
addons: { apt: { packages: ["g++-7"], sources: ["ubuntu-toolchain-r-test"] } }
|
||||
|
||||
- env: MATRIX_EVAL="CC=gcc-7 && CXX=g++-7 && GENERATOR='Unix Makefiles' && CONFIG=Debug && GHC_COVERAGE=1"
|
||||
addons: { apt: { packages: ["g++-7", "lcov"], sources: ["ubuntu-toolchain-r-test"] } }
|
||||
|
||||
- env: MATRIX_EVAL="CC=gcc-8 && CXX=g++-8 && GENERATOR='Unix Makefiles' && CONFIG=Release"
|
||||
addons: { apt: { packages: ["g++-8"], sources: ["ubuntu-toolchain-r-test"] } }
|
||||
|
||||
- env: MATRIX_EVAL="CC=gcc-9 && CXX=g++-9 && GENERATOR='Unix Makefiles' && CONFIG=Release"
|
||||
addons: { apt: { packages: ["g++-9"], sources: ["ubuntu-toolchain-r-test"] } }
|
||||
|
||||
- env: MATRIX_EVAL="CC=clang-5.0 && CXX=clang++-5.0 && GENERATOR='Unix Makefiles' && CONFIG=Release"
|
||||
addons: { apt: { packages: ["clang-5.0"] } }
|
||||
|
||||
- env: MATRIX_EVAL="CC=clang-6.0 && CXX=clang++-6.0 && GENERATOR='Unix Makefiles' && CONFIG=Release"
|
||||
addons: { apt: { packages: ["clang-6.0"] } }
|
||||
|
||||
- env: MATRIX_EVAL="CC=clang-7 && CXX=clang++-7 && GENERATOR='Unix Makefiles' && CONFIG=Release"
|
||||
addons: { apt: { packages: ["clang-7", "libc++-7-dev", "libc++abi-7-dev"], sources: ["llvm-toolchain-xenial-7"] } }
|
||||
|
||||
- env: MATRIX_EVAL="CC=clang-8 && CXX=clang++-8 && GENERATOR='Unix Makefiles' && CONFIG=Release"
|
||||
addons: { apt: { packages: ["clang-8", "libc++-8-dev", "libc++abi-8-dev"], sources: ["llvm-toolchain-xenial-8"] } }
|
||||
|
||||
- env: MATRIX_EVAL="CC=clang-9 && CXX=clang++-9 && GENERATOR='Unix Makefiles' && CONFIG=Release"
|
||||
addons: { apt: { packages: ["clang-9", "libc++-9-dev", "libc++abi-9-dev"], sources: [{sourceline: 'deb https://apt.llvm.org/xenial/ llvm-toolchain-xenial-9 main', key_url: 'https://apt.llvm.org/llvm-snapshot.gpg.key'}] } }
|
||||
|
||||
- os: osx
|
||||
env: MATRIX_EVAL="CC=clang && CXX=clang++ && GENERATOR=Xcode && CONFIG=Release"
|
||||
osx_image: xcode9.2
|
||||
|
||||
- os: osx
|
||||
env: MATRIX_EVAL="CC=clang && CXX=clang++ && GENERATOR=Xcode && CONFIG=Release"
|
||||
osx_image: xcode10.1
|
||||
|
||||
- os: osx
|
||||
env: MATRIX_EVAL="CC=clang && CXX=clang++ && GENERATOR=Xcode && CONFIG=Release"
|
||||
osx_image: xcode11.2
|
||||
|
||||
install:
|
||||
- eval "${MATRIX_EVAL}"
|
||||
- |
|
||||
if [ "${TRAVIS_OS_NAME}" = "osx" ]; then
|
||||
brew update
|
||||
fi
|
||||
- |
|
||||
if [ "${GHC_COVERAGE}" = "1" ]; then
|
||||
gem install coveralls-lcov
|
||||
fi
|
||||
- $CC --version
|
||||
- $CXX --version
|
||||
- cmake --version
|
||||
|
||||
before_script:
|
||||
- eval "${MATRIX_EVAL}"
|
||||
- mkdir build
|
||||
- cd build
|
||||
- export VERBOSE=1
|
||||
- |
|
||||
if [ "${CONFIG}" = "Debug" ]; then
|
||||
cmake -G"${GENERATOR}" -DCMAKE_CXX_COMPILER=${CXX} -DCMAKE_C_COMPILER=${CC} -DCMAKE_BUILD_TYPE=${CONFIG} -DGHC_COVERAGE=ON ..
|
||||
else
|
||||
cmake -G"${GENERATOR}" -DCMAKE_CXX_COMPILER=${CXX} -DCMAKE_C_COMPILER=${CC} -DCMAKE_BUILD_TYPE=${CONFIG} ..
|
||||
fi
|
||||
|
||||
script:
|
||||
- export VERBOSE=1
|
||||
- cmake --build . --config ${CONFIG} --target filesystem_test
|
||||
- |
|
||||
if [ "${GHC_COVERAGE}" = "1" ]; then
|
||||
cmake --build . --config ${CONFIG} --target filesystem_test
|
||||
test/filesystem_test
|
||||
else
|
||||
cmake --build . --config ${CONFIG}
|
||||
ctest -C ${CONFIG} -E Windows
|
||||
if [ -f "test/std_filesystem_test" ]; then
|
||||
test/std_filesystem_test || true
|
||||
fi
|
||||
fi
|
||||
|
||||
after_success:
|
||||
- |
|
||||
if [ "${GHC_COVERAGE}" = "1" ]; then
|
||||
lcov --compat-libtool --directory . --capture --output-file coverage_output.info
|
||||
lcov --remove coverage_output.info '/usr/*' '*/c++/*' '*.h' '*/catch.hpp' -o coverage.info
|
||||
sed -i 's|SF:/.*/filesystem/|SF:../|g' coverage.info
|
||||
coveralls-lcov coverage.info
|
||||
fi
|
@ -1,56 +0,0 @@
|
||||
cmake_minimum_required(VERSION 3.7.2)
|
||||
project(ghcfilesystem)
|
||||
|
||||
include(CMakeDependentOption)
|
||||
|
||||
cmake_dependent_option(GHC_FILESYSTEM_BUILD_TESTING
|
||||
"Enable tests" ON
|
||||
"CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR" OFF)
|
||||
cmake_dependent_option(GHC_FILESYSTEM_BUILD_EXAMPLES
|
||||
"Build examples" ON
|
||||
"CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR" OFF)
|
||||
cmake_dependent_option(GHC_FILESYSTEM_WITH_INSTALL
|
||||
"With install target" ON
|
||||
"CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR" OFF)
|
||||
|
||||
if(NOT DEFINED CMAKE_CXX_STANDARD)
|
||||
set(CMAKE_CXX_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
set(CMAKE_CXX_EXTENSIONS OFF)
|
||||
endif()
|
||||
if(CMAKE_CXX_STANDARD LESS 11)
|
||||
message(FATAL_ERROR "CMAKE_CXX_STANDARD is less than 11, ghc::filesystem only works with C++11 and above.")
|
||||
endif()
|
||||
|
||||
add_library(ghc_filesystem INTERFACE)
|
||||
target_include_directories(ghc_filesystem INTERFACE
|
||||
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
|
||||
$<INSTALL_INTERFACE:include>)
|
||||
target_compile_options(ghc_filesystem INTERFACE "$<$<C_COMPILER_ID:MSVC>:/utf-8>")
|
||||
target_compile_options(ghc_filesystem INTERFACE "$<$<CXX_COMPILER_ID:MSVC>:/utf-8>")
|
||||
|
||||
get_directory_property(hasParent PARENT_DIRECTORY)
|
||||
if(NOT hasParent)
|
||||
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/")
|
||||
include(GhcHelper)
|
||||
|
||||
if(GHC_FILESYSTEM_BUILD_TESTING)
|
||||
enable_testing()
|
||||
add_subdirectory(test)
|
||||
endif()
|
||||
|
||||
if(GHC_FILESYSTEM_BUILD_EXAMPLES)
|
||||
add_subdirectory(examples)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(GHC_FILESYSTEM_WITH_INSTALL)
|
||||
include(CMakePackageConfigHelpers)
|
||||
include(GNUInstallDirs)
|
||||
|
||||
install(DIRECTORY include/ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR})
|
||||
install(TARGETS ghc_filesystem EXPORT ghcFilesystemConfig)
|
||||
install(EXPORT ghcFilesystemConfig NAMESPACE ghcFilesystem:: DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/ghcFilesystem)
|
||||
endif()
|
||||
|
@ -1,27 +0,0 @@
|
||||
Copyright (c) 2018, Steffen Schümann <s.schuemann@pobox.com>
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
3. Neither the name of the copyright holder nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software without
|
||||
specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
@ -1,710 +0,0 @@
|
||||
![Supported Platforms](https://img.shields.io/badge/platform-macOS%20%7C%20Linux%20%7C%20Windows-blue.svg)
|
||||
[![Build Status](https://travis-ci.org/gulrak/filesystem.svg?branch=master)](https://travis-ci.org/gulrak/filesystem)
|
||||
[![Build status](https://ci.appveyor.com/api/projects/status/t07wp3k2cddo0hpo/branch/master?svg=true)](https://ci.appveyor.com/project/gulrak/filesystem)
|
||||
[![Coverage Status](https://coveralls.io/repos/github/gulrak/filesystem/badge.svg?branch=master)](https://coveralls.io/github/gulrak/filesystem?branch=master)
|
||||
[![Latest Release Tag](https://img.shields.io/github/tag/gulrak/filesystem.svg)](https://github.com/gulrak/filesystem/tree/v1.2.10)
|
||||
|
||||
# Filesystem
|
||||
|
||||
This is a header-only single-file std::filesystem compatible helper library,
|
||||
based on the C++17 specs, but implemented for C++11, C++14 or C++17 (tightly following
|
||||
the C++17 with very few documented exceptions). It is currently tested on
|
||||
macOS 10.12/10.14, Windows 10, and Ubuntu 18.04 but should work on other versions too, as long as you have a
|
||||
C++11 compatible compiler. It is of course in its own namespace `ghc::filesystem`
|
||||
to not interfere with a regular `std::filesystem` should you use it in a mixed C++17
|
||||
environment.
|
||||
|
||||
*It could still use some polishing, test coverage is above 90%, I didn't benchmark
|
||||
much yet, but I'll try to optimize some parts and refactor others, so I'm striving
|
||||
to improve it as long as it doesn't introduce additional C++17 compatibility
|
||||
issues. Feedback is always welcome. Simply open an issue if you see something missing
|
||||
or wrong or not behaving as expected and I'll comment.*
|
||||
|
||||
|
||||
## Motivation
|
||||
|
||||
I'm often in need of filesystem functionality, mostly `fs::path`, but directory
|
||||
access too, and when beginning to use C++11, I used that language update
|
||||
to try to reduce my third-party dependencies. I could drop most of what
|
||||
I used, but still missed some stuff that I started implementing for the
|
||||
fun of it. Originally I based these helpers on my own coding- and naming
|
||||
conventions. When C++17 was finalized, I wanted to use that interface,
|
||||
but it took a while, to push myself to convert my classes.
|
||||
|
||||
The implementation is closely based on chapter 30.10 from the C++17 standard
|
||||
and a draft close to that version is
|
||||
[Working Draft N4687](https://github.com/cplusplus/draft/raw/master/papers/n4687.pdf).
|
||||
It is from after the standardization of C++17 but it contains the latest filesystem
|
||||
interface changes compared to the
|
||||
[Working Draft N4659](https://github.com/cplusplus/draft/raw/master/papers/n4659.pdf).
|
||||
|
||||
I want to thank the people working on improving C++, I really liked how the language
|
||||
evolved with C++11 and the following standards. Keep on the good work!
|
||||
|
||||
Oh, and if you ask yourself, what `ghc` is standing for, it is simply
|
||||
`gulraks helper classes`, yeah, I know, not very imaginative, but I wanted a
|
||||
short namespace and I use it in some of my private classes (so it has nothing
|
||||
to do with Haskell).
|
||||
|
||||
## Platforms
|
||||
|
||||
`ghc::filesystem` is developed on macOS but tested on Windows and Linux.
|
||||
It should work on any of these with a C++11-capable compiler. I currently
|
||||
don't have a BSD derivate besides macOS, so the preprocessor checks will
|
||||
cry out if you try to use it there, but if there is demand, I can try to
|
||||
help. Also there are some checks to hopefully better work on Android, but
|
||||
as I currently don't test with the Android NDK, I wouldn't call it a
|
||||
supported platform yet. All in all, I don't see it replacing `std::filesystem`
|
||||
where full C++17 is available, it doesn't try to be a "better"
|
||||
`std::filesystem`, just a drop-in if you can't use it (with the exception
|
||||
of the UTF-8 preference on Windows).
|
||||
|
||||
|
||||
Unit tests are currently run with:
|
||||
|
||||
* macOS 10.12: Xcode 9.2 (clang-900.0.39.2), GCC 9.2, Clang 9.0, macOS 10.13: Xcode 10.1, macOS 10.14: Xcode 11.2
|
||||
* Windows: Visual Studio 2017, Visual Studio 2015, Visual Studio 2019, MinGW GCC 6.3 (Win32), GCC 7.2 (Win64)
|
||||
* Linux (Ubuntu): GCC (5.5, 6.5, 7.4, 8.3, 9.2), Clang (5.0, 6.0, 7.1, 8.0, 9.0)
|
||||
|
||||
|
||||
## Tests
|
||||
|
||||
The header comes with a set of unit-tests and uses [CMake](https://cmake.org/)
|
||||
as a build tool and [Catch2](https://github.com/catchorg/Catch2) as test framework.
|
||||
|
||||
All tests agains this implementation should succeed, depending on your environment
|
||||
it might be that there are some warnings, e.g. if you have no rights to create
|
||||
Symlinks on Windows or at least the test thinks so, but these are just informative.
|
||||
|
||||
To build the tests from inside the project directory under macOS or Linux just:
|
||||
|
||||
```cpp
|
||||
mkdir build
|
||||
cd build
|
||||
cmake -DCMAKE_BUILD_TYPE=Debug ..
|
||||
make
|
||||
```
|
||||
|
||||
This generates `filesystem_test`, the binary that runs all tests.
|
||||
|
||||
If the default compiler is a GCC 8 or newer, or Clang 7 or newer, it
|
||||
additionally tries to build a version of the test binary compiled against GCCs/Clangs
|
||||
`std::filesystem` implementation, named `std_filesystem_test`
|
||||
as an additional test of conformance. Ideally all tests should compile and
|
||||
succeed with all filesystem implementations, but in reality, there are
|
||||
some differences in behavior, sometimes due to room for interpretation in
|
||||
in the standard, and there might be issues in these implementations too.
|
||||
|
||||
|
||||
## Usage
|
||||
|
||||
### Downloads
|
||||
|
||||
The latest release version is [v1.2.10](https://github.com/gulrak/filesystem/tree/v1.2.10) and
|
||||
source archives can be found [here](https://github.com/gulrak/filesystem/releases/tag/v1.2.10).
|
||||
|
||||
### Using it as Single-File-Header
|
||||
|
||||
As `ghc::filesystem` is at first a header-only library, it should be enough to copy the header
|
||||
or the `include/ghc` directory into your project folder oder point your include path to this place and
|
||||
simply include the `filesystem.hpp` header (or `ghc/filesystem.hpp` if you use the subdirectory).
|
||||
|
||||
Everything is in the namespace `ghc::filesystem`, so one way to use it only as
|
||||
a fallback could be:
|
||||
|
||||
```cpp
|
||||
#if defined(__cplusplus) && __cplusplus >= 201703L && defined(__has_include)
|
||||
#if __has_include(<filesystem>)
|
||||
#define GHC_USE_STD_FS
|
||||
#include <filesystem>
|
||||
namespace fs = std::filesystem;
|
||||
#endif
|
||||
#endif
|
||||
#ifndef GHC_USE_STD_FS
|
||||
#include <ghc/filesystem.hpp>
|
||||
namespace fs = ghc::filesystem;
|
||||
#endif
|
||||
```
|
||||
|
||||
**Note that this code uses a two-stage preprocessor condition because Visual Studio 2015
|
||||
doesn't like the `(<...>)` syntax, even if it could cut evaluation early before.**
|
||||
|
||||
**Note also, that on MSVC this detection only works starting from version 15.7 on and when setting
|
||||
the `/Zc:__cplusplus` compile switch, as the compiler allways reports `199711L`
|
||||
without that switch ([see](https://blogs.msdn.microsoft.com/vcblog/2018/04/09/msvc-now-correctly-reports-__cplusplus/)).**
|
||||
|
||||
If you want to also use the `fstream` wrapper with `path` support as fallback,
|
||||
you might use:
|
||||
|
||||
```cpp
|
||||
#if defined(__cplusplus) && __cplusplus >= 201703L && defined(__has_include)
|
||||
#if __has_include(<filesystem>)
|
||||
#define GHC_USE_STD_FS
|
||||
#include <filesystem>
|
||||
namespace fs {
|
||||
using namespace std::filesystem;
|
||||
using ifstream = std::ifstream;
|
||||
using ofstream = std::ofstream;
|
||||
using fstream = std::fstream;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#ifndef GHC_USE_STD_FS
|
||||
#include <ghc/filesystem.hpp>
|
||||
namespace fs {
|
||||
using namespace ghc::filesystem;
|
||||
using ifstream = ghc::filesystem::ifstream;
|
||||
using ofstream = ghc::filesystem::ofstream;
|
||||
using fstream = ghc::filesystem::fstream;
|
||||
}
|
||||
#endif
|
||||
```
|
||||
|
||||
Now you have e.g. `fs::ofstream out(somePath);` and it is either the wrapper or
|
||||
the C++17 `std::ofstream`.
|
||||
|
||||
**Be aware, as a header-only library, it is not hiding the fact, that it
|
||||
uses system includes, so they "pollute" your global namespace.**
|
||||
|
||||
:information_source: **Hint:** There is an additional header named `ghc/fs_std.hpp` that implements this
|
||||
dynamic selection of a filesystem implementation, that you can include
|
||||
instead of `ghc/filesystem.hpp` when you want std::filesystem where
|
||||
available and ghc::filesystem where not. It also enables the `wchar_t`
|
||||
support on `ghc::filesystem` on Windows, so the resulting implementation
|
||||
in the `fs` namespace will be compatible.
|
||||
|
||||
|
||||
### Using it as Forwarding-/Implementation-Header
|
||||
|
||||
Alternatively, starting from v1.1.0 `ghc::filesystem` can also be used by
|
||||
including one of two additional wrapper headers. These allow to include
|
||||
a forwarded version in most places (`ghc/fs_fwd.hpp`) while hiding the
|
||||
implementation details in a single cpp that includes `ghc/fs_impl.hpp` to
|
||||
implement the needed code. That way system includes are only visible from
|
||||
inside the cpp, all other places are clean.
|
||||
|
||||
Be aware, that it is currently not supported to hide the implementation
|
||||
into a Windows-DLL, as a DLL interface with C++ standard templates in interfaces
|
||||
is a different beast. If someone is willing to give it a try, I might integrate
|
||||
a PR but currently working on that myself is not a priority.
|
||||
|
||||
If you use the forwarding/implementation approach, you can still use the dynamic
|
||||
switching like this:
|
||||
|
||||
```cpp
|
||||
#if defined(__cplusplus) && __cplusplus >= 201703L && defined(__has_include)
|
||||
#if __has_include(<filesystem>)
|
||||
#define GHC_USE_STD_FS
|
||||
#include <filesystem>
|
||||
namespace fs {
|
||||
using namespace std::filesystem;
|
||||
using ifstream = std::ifstream;
|
||||
using ofstream = std::ofstream;
|
||||
using fstream = std::fstream;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#ifndef GHC_USE_STD_FS
|
||||
#include <ghc/fs-fwd.hpp>
|
||||
namespace fs {
|
||||
using namespace ghc::filesystem;
|
||||
using ifstream = ghc::filesystem::ifstream;
|
||||
using ofstream = ghc::filesystem::ofstream;
|
||||
using fstream = ghc::filesystem::fstream;
|
||||
}
|
||||
#endif
|
||||
```
|
||||
|
||||
and in the implementation hiding cpp, you might use (before any include that includes `ghc/fs_fwd.hpp`
|
||||
to take precedence:
|
||||
|
||||
```cpp
|
||||
#if !(defined(__cplusplus) && __cplusplus >= 201703L && defined(__has_include)
|
||||
#if __has_include(<filesystem>))
|
||||
#include <ghc/fs_impl.hpp>
|
||||
#endif
|
||||
#endif
|
||||
```
|
||||
|
||||
:information_source: **Hint:** There are additional helper headers, named `ghc/fs_std_fwd.hpp` and
|
||||
`ghc/fs_std_impl.hpp` that use this technique, so you can simply include them
|
||||
if you want to dynamically select the filesystem implementation. they also
|
||||
enable the `wchar_t` support on `ghc::filesystem` on Windows, so the resulting
|
||||
implementation in the `fs` namespace will be compatible.
|
||||
|
||||
|
||||
|
||||
### Git Submodule and CMake
|
||||
|
||||
Starting from v1.1.0, it is possible to add `ghc::filesystem`
|
||||
as a git submodule, add the directory to your `CMakeLists.txt` with
|
||||
`add_subdirectory()` and then simply use `target_link_libraries(your-target ghc_filesystem)`
|
||||
to ensure correct include path that allow `#include <ghc/filesystem.hpp>`
|
||||
to work.
|
||||
|
||||
The `CMakeLists.txt` offers a few options to customize its behaviour:
|
||||
|
||||
* `GHC_FILESYSTEM_BUILD_TESTING` - Compile tests, default is `OFF` when used as
|
||||
a submodule, else `ON`.
|
||||
* `GHC_FILESYSTEM_BUILD_EXAMPLES` - Compile the examples, default is `OFF` when used as
|
||||
a submodule, else `ON`.
|
||||
* `GHC_FILESYSTEM_WITH_INSTALL` - Add install target to build, default is `OFF` when used as
|
||||
a submodule, else `ON`.
|
||||
|
||||
### Versioning
|
||||
|
||||
There is a version macro `GHC_FILESYSTEM_VERSION` defined in case future changes
|
||||
might make it needed to react on the version, but I don't plan to break anything.
|
||||
It's the version as decimal number `(major * 10000 + minor * 100 + patch)`.
|
||||
|
||||
**Note:** Starting from v1.0.2 only even patch versions will be used for releases
|
||||
and odd patch version will only be used for in between commits while working on
|
||||
the next version.
|
||||
|
||||
|
||||
## Documentation
|
||||
|
||||
There is almost no documentation in this release, as any `std::filesystem`
|
||||
documentation would work, besides the few differences explained in the next
|
||||
section. So you might head over to https://en.cppreference.com/w/cpp/filesystem
|
||||
for a description of the components of this library.
|
||||
|
||||
The only additions to the standard are documented here:
|
||||
|
||||
|
||||
### `ghc::filesystem::ifstream`, `ghc::filesystem::ofstream`, `ghc::filesystem::fstream`
|
||||
|
||||
These are simple wrappers around `std::ifstream`, `std::ofstream` and `std::fstream`.
|
||||
They simply add an `open()` method and a constuctor with an `ghc::filesystem::path`
|
||||
argument as the `fstream` variants in C++17 have them.
|
||||
|
||||
### `ghc::filesystem::u8arguments`
|
||||
|
||||
This is a helper class that currently checks for UTF-8 encoding on non-Windows platforms but on Windows it
|
||||
fetches the command line arguments als Unicode strings from the OS with
|
||||
|
||||
```cpp
|
||||
::CommandLineToArgvW(::GetCommandLineW(), &argc)
|
||||
```
|
||||
|
||||
and then converts them to UTF-8, and replaces `argc` and `argv`. It is a guard-like
|
||||
class that reverts its changes when going out of scope.
|
||||
|
||||
So basic usage is:
|
||||
|
||||
```cpp
|
||||
namespace fs = ghc::filesystem;
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
fs::u8arguments u8guard(argc, argv);
|
||||
if(!u8guard.valid()) {
|
||||
std::cerr << "Bad encoding, needs UTF-8." << std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// now use argc/argv as usual, they have utf-8 enconding on windows
|
||||
// ...
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
That way `argv` is UTF-8 encoded as long as the scope from `main` is valid.
|
||||
|
||||
**Note:** On macOS, while debugging under Xcode the code currently will return
|
||||
`false` as Xcode starts the application with `US-ASCII` as encoding, no matter what
|
||||
encoding is actually used and even setting `LC_ALL` in the product scheme doesn't
|
||||
change anything. I still need to investigate this.
|
||||
|
||||
|
||||
## Differences
|
||||
|
||||
As this implementation is based on existing code from my private helper
|
||||
classes, it derived some constraints of it, leading to some differences
|
||||
between this and the standard C++17 API.
|
||||
|
||||
|
||||
### LWG Defects
|
||||
|
||||
This implementation has switchable behavior for the LWG defects
|
||||
[#2682](https://wg21.cmeerw.net/lwg/issue2682),
|
||||
[#2935](http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2935) and
|
||||
[#2937](http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2937).
|
||||
The currently selected behavior is following
|
||||
[#2682](https://wg21.cmeerw.net/lwg/issue2682),
|
||||
[#2937](http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2937) but
|
||||
not following [#2935](http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2935),
|
||||
as I feel it is a bug to report no error on a `create_directory()` or `create_directories()`
|
||||
where a regular file of the same name prohibits the creation of a directory and forces
|
||||
the user of those functions to double-check via `fs::is_directory` if it really worked.
|
||||
The more intuitive approach to directory creation of treating a file with that name as an
|
||||
error is also advocated by the newer paper
|
||||
[WG21 P1164R0](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1164r0.pdf), the revison
|
||||
P1161R1 was agreed upon on Kona 2019 meeting [see merge](https://github.com/cplusplus/draft/issues/2703)
|
||||
and GCC by now switched to following its proposal
|
||||
([GCC #86910](https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86910)).
|
||||
|
||||
### Not Implemented on C++ before C++17
|
||||
|
||||
```cpp
|
||||
// methods in ghc::filesystem::path:
|
||||
path& operator+=(basic_string_view<value_type> x);
|
||||
int compare(basic_string_view<value_type> s) const;
|
||||
```
|
||||
|
||||
These are not implemented under C++11 and C++14, as there is no
|
||||
`std::basic_string_view` available and I did want to keep this
|
||||
implementation self-contained and not write a full C++17-upgrade for
|
||||
C++11/14. Starting with v1.1.0 these are supported when compiling
|
||||
ghc::filesystem under C++17.
|
||||
|
||||
|
||||
### Differences in API
|
||||
|
||||
```cpp
|
||||
filesystem::path::string_type
|
||||
filesystem::path::value_type
|
||||
```
|
||||
|
||||
In Windows, an implementation should use `std::wstring` and `wchar_t` as types used
|
||||
for the native representation, but as I'm a big fan of the
|
||||
["UTF-8 Everywhere" philosophy](https://utf8everywhere.org/), I decided
|
||||
agains it for now. If you need to call some Windows API, use the W-variant
|
||||
with the `path::wstring()` member
|
||||
(e.g. `GetFileAttributesW(p.wstring().c_str())`). This gives you the
|
||||
Unicode variant independant of the `UNICODE` macro and makes sharing code
|
||||
between Windows, Linux and macOS easier.
|
||||
|
||||
Starting with v1.2.0 `ghc::filesystem` has the option to select the more
|
||||
standard conforming APi with `wchar_t` and `std::wstring` on Windows by
|
||||
defining `GHC_WIN_WSTRING_STRING_TYPE`. This define has no effect on other
|
||||
platforms and will be set by the helping headers `ghc/fs_std.hpp` and
|
||||
the pair `ghc/fs_std_fwd.hpp`/`ghc/fs_std_impl.hpp` to enhance compatibility.
|
||||
|
||||
|
||||
```cpp
|
||||
const path::string_type& path::native() const /*noexcept*/;
|
||||
const path::value_type *path::c_str() const /*noexcept*/;
|
||||
```
|
||||
|
||||
These two can not be `noexcept` with the current implementation. This due
|
||||
to the fact, that internally path is working on the generic path version
|
||||
only, and the getters need to do a conversion to native path format.
|
||||
|
||||
```cpp
|
||||
const path::string_type& path::generic_string() const;
|
||||
```
|
||||
|
||||
This returns a const reference, instead of a value, because it can. This
|
||||
implementation uses the generic representation for internal workings, so
|
||||
it's "free" to return that.
|
||||
|
||||
|
||||
### Differences in Behavior
|
||||
|
||||
#### fs.path ([ref](https://en.cppreference.com/w/cpp/filesystem/path))
|
||||
|
||||
As the complete inner mechanics of this implementation `fs::path` are working
|
||||
on the generic format, it is the internal representation. So creating any mixed
|
||||
slash `fs::path` object under Windows (e.g. with `"C:\foo/bar"`) will lead to a
|
||||
unified path with `"C:\foo\bar"` via `native()` and `"C:/foo/bar"` via
|
||||
`generic_string()` API.
|
||||
|
||||
Additionally this implementation follows the standards suggestion to handle
|
||||
posix paths of the form `"//host/path"` and USC path on windows also as having
|
||||
a root-name (e.g. `"//host"`). The GCC implementation didn't choose to do that
|
||||
while testing on Ubuntu 18.04 and macOS with GCC 8.1.0 or Clang 7.0.0. This difference
|
||||
will show as warnings under std::filesystem. This leads to a change in the
|
||||
algorithm described in the standard for `operator/=(path& p)` where any path
|
||||
`p` with `p.is_absolute()` will degrade to an assignment, while this implementation
|
||||
has the exception where `*this == *this.root_name()` and `p == preferred_seperator`
|
||||
a normal append will be done, to allow:
|
||||
|
||||
```cpp
|
||||
fs::path p1 = "//host/foo/bar/file.txt";
|
||||
fs::path p2;
|
||||
for (auto p : p1) p2 /= p;
|
||||
ASSERT(p1 == p2);
|
||||
```
|
||||
|
||||
For all non-host-leading paths the behaviour will match the one described by
|
||||
the standard.
|
||||
|
||||
#### fs.op.copy ([ref](https://en.cppreference.com/w/cpp/filesystem/copy))
|
||||
|
||||
Then there is `fs::copy`. The tests in the suite fail partially with C++17 `std::filesystem`
|
||||
on GCC/Clang. They complain about a copy call with `fs::copy_options::recursive` combined
|
||||
with `fs::copy_options::create_symlinks` or `fs::copy_options::create_hard_links` if the
|
||||
source is a directory. There is nothing in the standard that forbids this combination
|
||||
and it is the only way to deep-copy a tree while only create links for the files.
|
||||
There is [LWG #2682](https://wg21.cmeerw.net/lwg/issue2682) that supports this
|
||||
interpretation, but the issue ignores the usefulness of the combination with recursive
|
||||
and part of the justification for the proposed solution is "we did it so for almost two years".
|
||||
But this makes `fs::copy` with `fs::copy_options::create_symlinks` or `fs::copy_options::create_hard_links`
|
||||
just a more complicated syntax for the `fs::create_symlink` or `fs::create_hardlink` operation
|
||||
and I don't want to believe, that this was the intention of the original writing.
|
||||
As there is another issue related to copy, with a different take on the description.
|
||||
|
||||
**Note:** With v1.1.2 I decided to integrate a behavior switch for this and make the LWG #2682
|
||||
the default.
|
||||
|
||||
## Open Issues
|
||||
|
||||
### General Known Issues
|
||||
|
||||
There are still some methods that break the `noexcept` clause, some
|
||||
are related to LWG defects, some are due to my implementation. I
|
||||
work on fixing the later ones, and might in cases where there is no
|
||||
way of implementing the feature without risk of an exception, break
|
||||
conformance and remove the `noexcept`.
|
||||
|
||||
### Windows
|
||||
|
||||
#### Symbolic Links on Windows
|
||||
|
||||
As symbolic links on Windows, while being supported more or less since
|
||||
Windows Vista (with some strict security constraints) and fully since some earlier
|
||||
build of Windows 10, when "Developer Mode" is activated, are at time of writing
|
||||
(2018) rarely used, still they are supported with this implementation.
|
||||
|
||||
#### Permissions
|
||||
|
||||
The Windows ACL permission feature translates badly to the POSIX permission
|
||||
bit mask used in the interface of C++17 filesystem. The permissions returned
|
||||
in the `file_status` are therefore currently synthesized for the `user`-level
|
||||
and copied to the `group`- and `other`-level. There is still some potential
|
||||
for more interaction with the Windows permission system, but currently setting
|
||||
or reading permissions with this implementation will most certainly not lead
|
||||
to the expected behavior.
|
||||
|
||||
|
||||
## Release Notes
|
||||
|
||||
### [v1.2.10](https://github.com/gulrak/filesystem/releases/tag/v1.2.10)
|
||||
|
||||
* The Visual Studio 2019 compiler, GCC 9.2 and Clang 9.0 where added to the
|
||||
CI configuration.
|
||||
* Bugfix for [#39](https://github.com/gulrak/filesystem/issues/39), `fs::rename`
|
||||
on Windows didn't replace an axisting regular file as required by the standard,
|
||||
but gave an error. New tests and a fix as provided in the issue was implemented.
|
||||
* Bugfix for [#39](https://github.com/gulrak/filesystem/issues/39), for the
|
||||
forwarding use via `fs_fwd.hpp` or `fs_std_fwd.hpp` der was a use of
|
||||
`DWORD` in the forwarding part leading to an error if `Windows.h` was not
|
||||
included before the header. The tests were changed to give an error in that
|
||||
case too and the useage of `DWORD` was removed.
|
||||
* Bugfix for [#38](https://github.com/gulrak/filesystem/issues/38), casting the
|
||||
return value of `GetProcAddress` gave a warning with `-Wcast-function-type`
|
||||
on MSYS2 and MinGW GCC 9 builds.
|
||||
|
||||
### [v1.2.8](https://github.com/gulrak/filesystem/releases/tag/v1.2.8)
|
||||
|
||||
* Pull request [#30](https://github.com/gulrak/filesystem/pull/30), the
|
||||
`CMakeLists.txt` will automatically exclude building examples and tests when
|
||||
used as submodule, the configuration options now use a prefixed name to
|
||||
reduce risk of conflicts.
|
||||
* Pull request [#24](https://github.com/gulrak/filesystem/pull/24), install
|
||||
target now creates a `ghcFilesystemConfig.cmake` in
|
||||
`${CMAKE_INSTALL_LIBDIR}/cmake/ghcFilesystem` for `find_package` that
|
||||
exports a target as `ghcFilesystem::ghc_filesystem`.
|
||||
* Pull request [#31](https://github.com/gulrak/filesystem/pull/31), fixes
|
||||
`error: redundant redeclaration of 'constexpr' static data member` deprecation
|
||||
warning in C++17 mode.
|
||||
* Pull request [#32](https://github.com/gulrak/filesystem/pull/32), fixes
|
||||
old-style-cast warnings.
|
||||
* Pull request [#34](https://github.com/gulrak/filesystem/pull/34), fixes
|
||||
[TOCTOU](https://en.wikipedia.org/wiki/Time-of-check_to_time-of-use) situation
|
||||
on `fs::create_directories`, thanks for the PR!
|
||||
* Feature [#35](https://github.com/gulrak/filesystem/issues/35), new CMake
|
||||
option to add an install target `GHC_FILESYSTEM_WITH_INSTALL` that is
|
||||
defaulted to OFF if `ghc::filesystem` is used via `add_subdirectory`.
|
||||
* Bugfix for [#33](https://github.com/gulrak/filesystem/issues/33), fixes
|
||||
an issue with `fs::path::lexically_normal()` that leaves a trailing separator
|
||||
in case of a resulting path ending with `..` as last element.
|
||||
* Bugfix for [#36](https://github.com/gulrak/filesystem/issues/36), warings
|
||||
on Xcode 11.2 due to unhelpfull references in path element iteration.
|
||||
|
||||
### [v1.2.6](https://github.com/gulrak/filesystem/releases/tag/v1.2.6)
|
||||
|
||||
* Pull request [#23](https://github.com/gulrak/filesystem/pull/23), tests and
|
||||
examples can now be disabled in CMake via seting `BUILD_TESTING` and
|
||||
`BUILD_EXAMPLES` to `NO`, `OFF` or `FALSE`.
|
||||
* Pull request [#25](https://github.com/gulrak/filesystem/pull/25),
|
||||
missing specialization for construction from `std::string_view` when
|
||||
available was added.
|
||||
* Additional test case when `std::string_view` is available.
|
||||
* Bugfix for [#27](https://github.com/gulrak/filesystem/issues/27), the
|
||||
`fs::path::preferred_seperator` declaration was not compiling on pre
|
||||
C++17 compilers and no test accessed it, to show the problem. Fixed
|
||||
it to an construction C++11 compiler should accept and added a test that
|
||||
is successful on all combinations tested.
|
||||
* Bugfix for [#29](https://github.com/gulrak/filesystem/issues/29), stricter
|
||||
warning settings where chosen and resulting warnings where fixed.
|
||||
|
||||
### [v1.2.4](https://github.com/gulrak/filesystem/releases/tag/v1.2.4)
|
||||
|
||||
* Enabled stronger warning switches and resulting fixed issues on GCC and MinGW
|
||||
* Bugfix for #22, the `fs::copy_options` where not forwarded from `fs::copy` to
|
||||
`fs::copy_file` in one of the cases.
|
||||
|
||||
### [v1.2.2](https://github.com/gulrak/filesystem/releases/tag/v1.2.2)
|
||||
|
||||
* Fix for ([#21](https://github.com/gulrak/filesystem/pull/21)), when compiling
|
||||
on Alpine Linux with musl instead of glibc, the wrong `strerror_r` signature
|
||||
was expected. The complex preprocessor define mix was dropped in favor of
|
||||
the usual dispatch by overloading a unifying wrapper.
|
||||
|
||||
### [v1.2.0](https://github.com/gulrak/filesystem/releases/tag/v1.2.0)
|
||||
|
||||
* Added MinGW 32/64 and Visual Studio 2015 builds to the CI configuration.
|
||||
* Fixed additional compilation issues on MinGW.
|
||||
* Pull request ([#13](https://github.com/gulrak/filesystem/pull/13)), set
|
||||
minimum required CMake version to 3.7.2 (as in Debian 8).
|
||||
* Pull request ([#14](https://github.com/gulrak/filesystem/pull/14)), added
|
||||
support for a make install target.
|
||||
* Bugfix for ([#15](https://github.com/gulrak/filesystem/issues/15)), the
|
||||
forward/impl way of using `ghc::filesystem` missed a `<vector>` include
|
||||
in the windows case.
|
||||
* Bugfix for ([#16](https://github.com/gulrak/filesystem/issues/16)),
|
||||
VS2019 didn't like the old size dispatching in the utf8 decoder, so it
|
||||
was changed to a sfinae based approach.
|
||||
* New feature ([#17](https://github.com/gulrak/filesystem/issues/17)), optional
|
||||
support for standard conforming `wchar_t/std::wstring` interface when
|
||||
compiling on Windows with defined `GHC_WIN_WSTRING_STRING_TYPE`, this is
|
||||
default when using the `ghc/fs_std*.hpp` header, to enhance compatibility.
|
||||
* New feature ([#18](https://github.com/gulrak/filesystem/issues/18)), optional
|
||||
filesystem exceptions/errors on unicode errors with defined
|
||||
`GHC_RAISE_UNICODE_ERRORS` (instead of replacing invalid code points or
|
||||
UTF-8 encoding errors with the replacement character `U+FFFD`).
|
||||
* Pull request ([#20](https://github.com/gulrak/filesystem/pull/20)), fix for
|
||||
file handle leak in `fs::copy_file`.
|
||||
* Coverage now checked in CI (~95% line coverage).
|
||||
|
||||
### [v1.1.4](https://github.com/gulrak/filesystem/releases/tag/v1.1.4)
|
||||
|
||||
* Additional Bugfix for ([#12](https://github.com/gulrak/filesystem/issues/12)),
|
||||
error in old unified `readdir/readdir_r` code of `fs::directory_iterator`;
|
||||
as `readdir_r` is now depricated, I decided to drop it and the resulting
|
||||
code is much easier, shorter and due to more refactoring faster
|
||||
* Fix for crashing unit tests against MSVC C++17 std::filesystem
|
||||
* Travis-CI now additionally test with Xcode 10.2 on macOS
|
||||
* Some minor refactorings
|
||||
|
||||
### [v1.1.2](https://github.com/gulrak/filesystem/releases/tag/v1.1.2)
|
||||
|
||||
* Bugfix for ([#11](https://github.com/gulrak/filesystem/issues/11)),
|
||||
`fs::path::lexically_normal()` had some issues with `".."`-sequences.
|
||||
* Bugfix for ([#12](https://github.com/gulrak/filesystem/issues/12)),
|
||||
`fs::recursive_directory_iterator` could run into endless loops,
|
||||
the methods depth() and pop() had issues and the copy behaviour and
|
||||
`input_iterator_tag` conformance was broken, added tests
|
||||
* Restructured some CMake code into a macro to ease the support for
|
||||
C++17 std::filesystem builds of tests and examples for interoperability
|
||||
checks.
|
||||
* Some fixes on Windows tests to ease interoperability test runs.
|
||||
* Reduced noise on `fs::weakly_canonical()` tests against `std::fs`
|
||||
* Added simple `du` example showing the `recursive_directory_iterator`
|
||||
used to add the sizes of files in a directory tree.
|
||||
* Added error checking in `fs::file_time_type` test helpers
|
||||
* `fs::copy()` now conforms LWG #2682, disallowing the use of
|
||||
`copy_option::create_symlinks' to be used on directories
|
||||
|
||||
### [v1.1.0](https://github.com/gulrak/filesystem/releases/tag/v1.1.0)
|
||||
|
||||
* Restructuring of the project directory. The header files are now using
|
||||
`hpp` as extension to be marked as c++ and they where moved to
|
||||
`include/ghc/` to be able to include by `<ghc/filesystem.hpp>` as the
|
||||
former include name might have been to generic and conflict with other
|
||||
files.
|
||||
* Better CMake support: `ghc::filesystem` now can be used as a submodul
|
||||
and added with `add_subdirectory` and will export itself as `ghc_filesystem`
|
||||
target. To use it, only `target_link_libraries(your-target ghc_filesystem)`
|
||||
is needed and the include directories will be set so `#include <ghc/filesystem.hpp>`
|
||||
will be a valid directive.
|
||||
Still you can simply only add the header file to you project and include it
|
||||
from there.
|
||||
* Enhancement ([#10](https://github.com/gulrak/filesystem/issues/10)),
|
||||
support for separation of implementation and forwarded api: Two
|
||||
additional simple includes are added, that can be used to forward
|
||||
`ghc::filesystem` declarations (`fs_fwd.hpp`) and to wrap the
|
||||
implementation into a single cpp (`fs_impl.hpp`)
|
||||
* The `std::basic_string_view` variants of the `fs::path` api are
|
||||
now supported when compiling with C++17.
|
||||
* Added CI integration for Travis-CI and Appveyor.
|
||||
* Fixed MinGW compilation issues.
|
||||
* Added long filename support for Windows.
|
||||
|
||||
### [v1.0.10](https://github.com/gulrak/filesystem/releases/tag/v1.0.10)
|
||||
|
||||
* Bugfix for ([#9](https://github.com/gulrak/filesystem/issues/9)), added
|
||||
missing return statement to `ghc::filesystem::path::generic_string()`
|
||||
* Added checks to hopefully better compile against Android NDK. There where
|
||||
no tests run yet, so feedback is needed to actually call this supported.
|
||||
* `filesystem.h` was renamed `filesystem.hpp` to better reflect that it is
|
||||
a c++ language header.
|
||||
|
||||
### [v1.0.8](https://github.com/gulrak/filesystem/releases/tag/v1.0.8)
|
||||
|
||||
* Bugfix for ([#6](https://github.com/gulrak/filesystem/issues/6)), where
|
||||
`ghc::filesystem::remove()` and `ghc::filesystem::remove_all()` both are
|
||||
now able to remove a single file and both will not raise an error if the
|
||||
path doesn't exist.
|
||||
* Merged pull request ([#7](https://github.com/gulrak/filesystem/pull/7)),
|
||||
a typo leading to setting error code instead of comparing it in
|
||||
`ghc::filesystem::remove()` under Windows.
|
||||
* Bugfix for (([#8](https://github.com/gulrak/filesystem/issues/8)), the
|
||||
Windows version of `ghc::filesystem::directory_iterator` now releases
|
||||
resources when reaching `end()` like the POSIX one does.
|
||||
|
||||
|
||||
### [v1.0.6](https://github.com/gulrak/filesystem/releases/tag/v1.0.6)
|
||||
|
||||
* Bugfix for ([#4](https://github.com/gulrak/filesystem/issues/4)), missing error_code
|
||||
propagation in `ghc::filesystem::copy()` and `ghc::filesystem::remove_all` fixed.
|
||||
* Bugfix for ([#5](https://github.com/gulrak/filesystem/issues/5)), added missing std
|
||||
namespace in `ghc::filesystem::recursive_directory_iterator::difference_type`.
|
||||
|
||||
### [v1.0.4](https://github.com/gulrak/filesystem/releases/tag/v1.0.4)
|
||||
|
||||
* Bugfix for ([#3](https://github.com/gulrak/filesystem/issues/3)), fixed missing inlines
|
||||
and added test to ensure including into multiple implementation files works as expected.
|
||||
* Building tests with `-Wall -Wextra -Werror` and fixed resulting issues.
|
||||
|
||||
### [v1.0.2](https://github.com/gulrak/filesystem/releases/tag/v1.0.2)
|
||||
|
||||
* Updated catch2 to v2.4.0.
|
||||
* Refactored `fs.op.permissions` test to work with all tested `std::filesystem`
|
||||
implementations (gcc, clang, msvc++).
|
||||
* Added helper class `ghc::filesystem::u8arguments` as `argv` converter, to
|
||||
help follow the UTF-8 path on windows. Simply instantiate it with `argc` and
|
||||
`argv` and it will fetch the Unicode version of the command line and convert
|
||||
it to UTF-8. The destructor reverts the change.
|
||||
* Added `examples` folder with hopefully some usefull example usage. Examples are
|
||||
tested (and build) with `ghc::filesystem` and C++17 `std::filesystem` when
|
||||
available.
|
||||
* Starting with this version, only even patch level versions will be tagged and
|
||||
odd patch levels mark in-between non-stable wip states.
|
||||
* Tests can now also be run against MS version of std::filesystem for comparison.
|
||||
* Added missing `fstream` include.
|
||||
* Removed non-conforming C99 `timespec`/`timeval` usage.
|
||||
* Fixed some integer type mismatches that could lead to warnings.
|
||||
* Fixed `chrono` conversion issues in test and example on clang 7.0.0.
|
||||
|
||||
### [v1.0.1](https://github.com/gulrak/filesystem/releases/tag/v1.0.1)
|
||||
|
||||
* Bugfix: `ghc::filesystem::canonical` now sees empty path as non-existant and reports
|
||||
an error. Due to this `ghc::filesystem::weakly_canonical` now returns relative
|
||||
paths for non-existant argument paths. ([#1](https://github.com/gulrak/filesystem/issues/1))
|
||||
* Bugfix: `ghc::filesystem::remove_all` now also counts directories removed ([#2](https://github.com/gulrak/filesystem/issues/2))
|
||||
* Bugfix: `recursive_directory_iterator` tests didn't respect equality domain issues
|
||||
and dereferencable constraints, leading to fails on `std::filesystem` tests.
|
||||
* Bugfix: Some `noexcept` tagged methods and functions could indirectly throw exceptions
|
||||
due to UFT-8 decoding issues.
|
||||
* `std_filesystem_test` is now also generated if LLVM/clang 7.0.0 is found.
|
||||
|
||||
|
||||
### [v1.0.0](https://github.com/gulrak/filesystem/releases/tag/v1.0.0)
|
||||
|
||||
This was the first public release version. It implements the full range of
|
||||
C++17 std::filesystem, as far as possible without other C++17 dependencies.
|
||||
|
@ -1,38 +0,0 @@
|
||||
macro(AddExecutableWithStdFS targetName)
|
||||
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" AND (CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 7.0 OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 7.0))
|
||||
if(APPLE)
|
||||
include_directories(/usr/local/opt/llvm/include)
|
||||
link_directories(/usr/local/opt/llvm/lib)
|
||||
endif()
|
||||
add_executable(${targetName} ${ARGN})
|
||||
set_property(TARGET ${targetName} PROPERTY CXX_STANDARD 17)
|
||||
if(APPLE)
|
||||
target_link_libraries(${targetName} -lc++fs)
|
||||
else()
|
||||
target_compile_options(${targetName} PRIVATE "-stdlib=libc++")
|
||||
target_link_libraries(${targetName} -stdlib=libc++ -lc++fs)
|
||||
endif()
|
||||
|
||||
target_link_libraries(${targetName} -lc++fs)
|
||||
target_compile_definitions(${targetName} PRIVATE USE_STD_FS)
|
||||
endif()
|
||||
|
||||
if (CMAKE_COMPILER_IS_GNUCXX AND (CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 8.0 OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 8.0))
|
||||
add_executable(${targetName} ${ARGN})
|
||||
set_property(TARGET ${targetName} PROPERTY CXX_STANDARD 17)
|
||||
if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9.0)
|
||||
target_link_libraries(${targetName} -lstdc++fs)
|
||||
endif()
|
||||
target_compile_definitions(${targetName} PRIVATE USE_STD_FS)
|
||||
endif()
|
||||
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES MSVC AND (CMAKE_CXX_COMPILER_VERSION VERSION_EQUAL 19.15 OR CMAKE_CXX_COMPILER_VERSION VERSION_GREATER 19.15))
|
||||
add_executable(${targetName} ${ARGN})
|
||||
set_property(TARGET ${targetName} PROPERTY CXX_STANDARD 17)
|
||||
set_property(TARGET ${targetName} PROPERTY CXX_STANDARD_REQUIRED ON)
|
||||
target_compile_options(${targetName} PRIVATE "/Zc:__cplusplus")
|
||||
target_compile_definitions(${targetName} PRIVATE USE_STD_FS _CRT_SECURE_NO_WARNINGS)
|
||||
endif()
|
||||
|
||||
endmacro()
|
@ -1,5 +0,0 @@
|
||||
@PACKAGE_INIT@
|
||||
|
||||
set_and_check(ghcfilesystem_INCLUDE_DIRS "@PACKAGE_INCLUDE_INSTALL_DIR@")
|
||||
|
||||
check_required_components(ghcfilesystem)
|
@ -1,12 +0,0 @@
|
||||
|
||||
add_executable(fs_dir dir.cpp)
|
||||
target_link_libraries(fs_dir ghc_filesystem)
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES MSVC)
|
||||
target_compile_definitions(fs_dir PRIVATE _CRT_SECURE_NO_WARNINGS)
|
||||
endif()
|
||||
AddExecutableWithStdFS(std_fs_dir dir.cpp)
|
||||
|
||||
add_executable(fs_du du.cpp)
|
||||
target_link_libraries(fs_du ghc_filesystem)
|
||||
AddExecutableWithStdFS(std_fs_du du.cpp)
|
||||
|
@ -1,60 +0,0 @@
|
||||
#include <chrono>
|
||||
#include <iomanip>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
#if defined(__cplusplus) && __cplusplus >= 201703L && defined(__has_include)
|
||||
#if __has_include(<filesystem>)
|
||||
#define GHC_USE_STD_FS
|
||||
#include <filesystem>
|
||||
namespace fs = std::filesystem;
|
||||
#endif
|
||||
#endif
|
||||
#ifndef GHC_USE_STD_FS
|
||||
#include <ghc/filesystem.hpp>
|
||||
namespace fs = ghc::filesystem;
|
||||
#endif
|
||||
|
||||
template <typename TP>
|
||||
std::time_t to_time_t(TP tp)
|
||||
{
|
||||
// Based on trick from: Nico Josuttis, C++17 - The Complete Guide
|
||||
std::chrono::system_clock::duration dt = std::chrono::duration_cast<std::chrono::system_clock::duration>(tp - TP::clock::now());
|
||||
return std::chrono::system_clock::to_time_t(std::chrono::system_clock::now() + dt);
|
||||
}
|
||||
|
||||
static std::string perm_to_str(fs::perms prms)
|
||||
{
|
||||
std::string result;
|
||||
result.reserve(9);
|
||||
for (int i = 0; i < 9; ++i) {
|
||||
result = ((static_cast<int>(prms) & (1 << i)) ? "xwrxwrxwr"[i] : '-') + result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
#ifdef GHC_FILESYSTEM_VERSION
|
||||
fs::u8arguments u8guard(argc, argv);
|
||||
if (!u8guard.valid()) {
|
||||
std::cerr << "Invalid character encoding, UTF-8 based encoding needed." << std::endl;
|
||||
std::exit(EXIT_FAILURE);
|
||||
}
|
||||
#endif
|
||||
if (argc > 2) {
|
||||
std::cerr << "USAGE: dir <path>" << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
fs::path dir{"."};
|
||||
if (argc == 2) {
|
||||
dir = fs::u8path(argv[1]);
|
||||
}
|
||||
for (auto de : fs::directory_iterator(dir)) {
|
||||
auto ft = to_time_t(de.last_write_time());
|
||||
auto ftm = *std::localtime(&ft);
|
||||
std::cout << (de.is_directory() ? "d" : "-") << perm_to_str(de.symlink_status().permissions()) << " " << std::setw(8) << (de.is_directory() ? "-" : std::to_string(de.file_size())) << " " << std::put_time(&ftm, "%Y-%m-%d %H:%M:%S") << " "
|
||||
<< de.path().filename().string() << std::endl;
|
||||
}
|
||||
return 0;
|
||||
}
|
@ -1,61 +0,0 @@
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include <chrono>
|
||||
|
||||
#if defined(__cplusplus) && __cplusplus >= 201703L && defined(__has_include)
|
||||
#if __has_include(<filesystem>)
|
||||
#define GHC_USE_STD_FS
|
||||
#include <filesystem>
|
||||
namespace fs = std::filesystem;
|
||||
#endif
|
||||
#endif
|
||||
#ifndef GHC_USE_STD_FS
|
||||
#include <ghc/filesystem.hpp>
|
||||
namespace fs = ghc::filesystem;
|
||||
#endif
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
#ifdef GHC_FILESYSTEM_VERSION
|
||||
fs::u8arguments u8guard(argc, argv);
|
||||
if(!u8guard.valid()) {
|
||||
std::cerr << "Invalid character encoding, UTF-8 based encoding needed." << std::endl;
|
||||
std::exit(EXIT_FAILURE);
|
||||
}
|
||||
#endif
|
||||
if(argc > 2) {
|
||||
std::cerr << "USAGE: du <path>" << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
fs::path dir{"."};
|
||||
if(argc == 2) {
|
||||
dir = fs::u8path(argv[1]);
|
||||
}
|
||||
|
||||
uint64_t totalSize = 0;
|
||||
int totalDirs = 0;
|
||||
int totalFiles = 0;
|
||||
int maxDepth = 0;
|
||||
|
||||
try {
|
||||
auto rdi = fs::recursive_directory_iterator(dir);
|
||||
for(auto de : rdi) {
|
||||
if(rdi.depth() > maxDepth) {
|
||||
maxDepth = rdi.depth();
|
||||
}
|
||||
if(de.is_regular_file()) {
|
||||
totalSize += de.file_size();
|
||||
++totalFiles;
|
||||
}
|
||||
else if(de.is_directory()) {
|
||||
++totalDirs;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(fs::filesystem_error fe) {
|
||||
std::cerr << "Error: " << fe.what() << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
std::cout << totalSize << " bytes in " << totalFiles << " files and " << totalDirs << " directories, maximum depth: " << maxDepth << std::endl;
|
||||
return 0;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,46 +0,0 @@
|
||||
//---------------------------------------------------------------------------------------
|
||||
//
|
||||
// ghc::filesystem - A C++17-like filesystem implementation for C++11/C++14
|
||||
//
|
||||
//---------------------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) 2018, Steffen Schümann <s.schuemann@pobox.com>
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this
|
||||
// list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software without
|
||||
// specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//---------------------------------------------------------------------------------------
|
||||
// fs_fwd.hpp - The forwarding header for the header/implementation seperated usage of
|
||||
// ghc::filesystem.
|
||||
// This file can be include at any place, where ghc::filesystem api is needed while
|
||||
// not bleeding implementation details (e.g. system includes) into the global namespace,
|
||||
// as long as one cpp includes fs_impl.hpp to deliver the matching implementations.
|
||||
//---------------------------------------------------------------------------------------
|
||||
#ifndef GHC_FILESYSTEM_FWD_H
|
||||
#define GHC_FILESYSTEM_FWD_H
|
||||
#define GHC_FILESYSTEM_FWD
|
||||
#include <ghc/filesystem.hpp>
|
||||
#endif // GHC_FILESYSTEM_FWD_H
|
@ -1,43 +0,0 @@
|
||||
//---------------------------------------------------------------------------------------
|
||||
//
|
||||
// ghc::filesystem - A C++17-like filesystem implementation for C++11/C++14
|
||||
//
|
||||
//---------------------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) 2018, Steffen Schümann <s.schuemann@pobox.com>
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this
|
||||
// list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software without
|
||||
// specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//---------------------------------------------------------------------------------------
|
||||
// fs_impl.hpp - The implementation header for the header/implementation seperated usage of
|
||||
// ghc::filesystem.
|
||||
// This file can be used to hide the implementation of ghc::filesystem into a single cpp.
|
||||
// The cpp has to include this before including fs_fwd.hpp directly or via a different
|
||||
// header to work.
|
||||
//---------------------------------------------------------------------------------------
|
||||
#define GHC_FILESYSTEM_IMPLEMENTATION
|
||||
#include <ghc/filesystem.hpp>
|
@ -1,64 +0,0 @@
|
||||
//---------------------------------------------------------------------------------------
|
||||
//
|
||||
// ghc::filesystem - A C++17-like filesystem implementation for C++11/C++14
|
||||
//
|
||||
//---------------------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) 2018, Steffen Schümann <s.schuemann@pobox.com>
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this
|
||||
// list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software without
|
||||
// specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//---------------------------------------------------------------------------------------
|
||||
// fs_std.hpp - The dynamic switching header that includes std::filesystem if detected
|
||||
// or ghc::filesystem if not, and makes the resulting API available in the
|
||||
// namespace fs.
|
||||
//---------------------------------------------------------------------------------------
|
||||
#ifndef GHC_FILESYSTEM_STD_H
|
||||
#if defined(__cplusplus) && __cplusplus >= 201703L && defined(__has_include)
|
||||
#if __has_include(<filesystem>)
|
||||
#define GHC_USE_STD_FS
|
||||
#include <filesystem>
|
||||
namespace fs {
|
||||
using namespace std::filesystem;
|
||||
using ifstream = std::ifstream;
|
||||
using ofstream = std::ofstream;
|
||||
using fstream = std::fstream;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#ifndef GHC_USE_STD_FS
|
||||
#define GHC_WIN_WSTRING_STRING_TYPE
|
||||
#include <ghc/filesystem.hpp>
|
||||
namespace fs {
|
||||
using namespace ghc::filesystem;
|
||||
using ifstream = ghc::filesystem::ifstream;
|
||||
using ofstream = ghc::filesystem::ofstream;
|
||||
using fstream = ghc::filesystem::fstream;
|
||||
}
|
||||
#endif
|
||||
#endif // GHC_FILESYSTEM_STD_H
|
||||
|
@ -1,68 +0,0 @@
|
||||
//---------------------------------------------------------------------------------------
|
||||
//
|
||||
// ghc::filesystem - A C++17-like filesystem implementation for C++11/C++14
|
||||
//
|
||||
//---------------------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) 2018, Steffen Schümann <s.schuemann@pobox.com>
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this
|
||||
// list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software without
|
||||
// specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//---------------------------------------------------------------------------------------
|
||||
// fs_std_fwd.hpp - The forwarding header for the header/implementation seperated usage of
|
||||
// ghc::filesystem that uses std::filesystem if it detects it.
|
||||
// This file can be include at any place, where fs::filesystem api is needed while
|
||||
// not bleeding implementation details (e.g. system includes) into the global namespace,
|
||||
// as long as one cpp includes fs_std_impl.hpp to deliver the matching implementations.
|
||||
//---------------------------------------------------------------------------------------
|
||||
#ifndef GHC_FILESYSTEM_STD_FWD_H
|
||||
#define GHC_FILESYSTEM_STD_FWD_H
|
||||
#if defined(__cplusplus) && __cplusplus >= 201703L && defined(__has_include)
|
||||
#if __has_include(<filesystem>)
|
||||
#define GHC_USE_STD_FS
|
||||
#include <filesystem>
|
||||
namespace fs {
|
||||
using namespace std::filesystem;
|
||||
using ifstream = std::ifstream;
|
||||
using ofstream = std::ofstream;
|
||||
using fstream = std::fstream;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
#ifndef GHC_USE_STD_FS
|
||||
#define GHC_WIN_WSTRING_STRING_TYPE
|
||||
#define GHC_FILESYSTEM_FWD
|
||||
#include <ghc/filesystem.hpp>
|
||||
namespace fs {
|
||||
using namespace ghc::filesystem;
|
||||
using ifstream = ghc::filesystem::ifstream;
|
||||
using ofstream = ghc::filesystem::ofstream;
|
||||
using fstream = ghc::filesystem::fstream;
|
||||
}
|
||||
#endif
|
||||
#endif // GHC_FILESYSTEM_STD_FWD_H
|
||||
|
@ -1,51 +0,0 @@
|
||||
//---------------------------------------------------------------------------------------
|
||||
//
|
||||
// ghc::filesystem - A C++17-like filesystem implementation for C++11/C++14
|
||||
//
|
||||
//---------------------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) 2018, Steffen Schümann <s.schuemann@pobox.com>
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this
|
||||
// list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software without
|
||||
// specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//---------------------------------------------------------------------------------------
|
||||
// fs_std_impl.hpp - The implementation header for the header/implementation seperated usage of
|
||||
// ghc::filesystem that does nothing if std::filesystem is detected.
|
||||
// This file can be used to hide the implementation of ghc::filesystem into a single cpp.
|
||||
// The cpp has to include this before including fs_std_fwd.hpp directly or via a different
|
||||
// header to work.
|
||||
//---------------------------------------------------------------------------------------
|
||||
#if defined(__cplusplus) && __cplusplus >= 201703L && defined(__has_include)
|
||||
#if __has_include(<filesystem>)
|
||||
#define GHC_USE_STD_FS
|
||||
#endif
|
||||
#endif
|
||||
#ifndef GHC_USE_STD_FS
|
||||
#define GHC_WIN_WSTRING_STRING_TYPE
|
||||
#define GHC_FILESYSTEM_IMPLEMENTATION
|
||||
#include <ghc/filesystem.hpp>
|
||||
#endif
|
@ -1,54 +0,0 @@
|
||||
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake/")
|
||||
set(PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS ON)
|
||||
include(ParseAndAddCatchTests)
|
||||
|
||||
if(GHC_COVERAGE)
|
||||
message("Generating test runner for coverage run...")
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMCMAKE_EXE_LINKER_FLAGS} --coverage")
|
||||
add_executable(filesystem_test filesystem_test.cpp catch.hpp)
|
||||
if(MINGW)
|
||||
target_compile_options(filesystem_test PUBLIC --coverage "-Wa,-mbig-obj")
|
||||
else()
|
||||
target_compile_options(filesystem_test PUBLIC --coverage)
|
||||
endif()
|
||||
target_link_libraries(filesystem_test PUBLIC ghc_filesystem --coverage)
|
||||
else()
|
||||
message("Generating test runner for normal test...")
|
||||
add_executable(filesystem_test filesystem_test.cpp catch.hpp)
|
||||
target_link_libraries(filesystem_test ghc_filesystem)
|
||||
target_compile_options(filesystem_test PRIVATE
|
||||
$<$<CXX_COMPILER_ID:Clang>:-Wall -Wextra -Wshadow -Wconversion -Wsign-conversion -Wpedantic -Werror>
|
||||
$<$<CXX_COMPILER_ID:GNU>:-Wall -Wextra -Wshadow -Wconversion -Wsign-conversion -Wpedantic -Werror>
|
||||
$<$<CXX_COMPILER_ID:MSVC>:/WX>)
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES MSVC)
|
||||
target_compile_definitions(filesystem_test PRIVATE _CRT_SECURE_NO_WARNINGS)
|
||||
endif()
|
||||
ParseAndAddCatchTests(filesystem_test)
|
||||
AddExecutableWithStdFS(std_filesystem_test filesystem_test.cpp catch.hpp)
|
||||
if(WIN32)
|
||||
add_executable(filesystem_test_wchar filesystem_test.cpp catch.hpp)
|
||||
target_link_libraries(filesystem_test_wchar ghc_filesystem)
|
||||
target_compile_options(filesystem_test_wchar PRIVATE
|
||||
$<$<CXX_COMPILER_ID:Clang>:-Wall -Wextra -Werror>
|
||||
$<$<CXX_COMPILER_ID:GNU>:-Wall -Werror>
|
||||
$<$<CXX_COMPILER_ID:MSVC>:/WX>)
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES MSVC)
|
||||
target_compile_definitions(filesystem_test_wchar PRIVATE _CRT_SECURE_NO_WARNINGS GHC_WIN_WSTRING_STRING_TYPE)
|
||||
else()
|
||||
target_compile_definitions(filesystem_test_wchar PRIVATE GHC_WIN_WSTRING_STRING_TYPE)
|
||||
endif()
|
||||
ParseAndAddCatchTests(filesystem_test_wchar)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
add_executable(multifile_test multi1.cpp multi2.cpp catch.hpp)
|
||||
target_link_libraries(multifile_test ghc_filesystem)
|
||||
add_test(multifile_test multifile_test)
|
||||
|
||||
add_executable(fwd_impl_test fwd_test.cpp impl_test.cpp)
|
||||
target_link_libraries(fwd_impl_test ghc_filesystem)
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES MSVC)
|
||||
target_compile_definitions(fwd_impl_test PRIVATE _CRT_SECURE_NO_WARNINGS)
|
||||
endif()
|
||||
add_test(fwd_impl_test fwd_impl_test)
|
File diff suppressed because it is too large
Load Diff
@ -1,225 +0,0 @@
|
||||
#==================================================================================================#
|
||||
# supported macros #
|
||||
# - TEST_CASE, #
|
||||
# - SCENARIO, #
|
||||
# - TEST_CASE_METHOD, #
|
||||
# - CATCH_TEST_CASE, #
|
||||
# - CATCH_SCENARIO, #
|
||||
# - CATCH_TEST_CASE_METHOD. #
|
||||
# #
|
||||
# Usage #
|
||||
# 1. make sure this module is in the path or add this otherwise: #
|
||||
# set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake.modules/") #
|
||||
# 2. make sure that you've enabled testing option for the project by the call: #
|
||||
# enable_testing() #
|
||||
# 3. add the lines to the script for testing target (sample CMakeLists.txt): #
|
||||
# project(testing_target) #
|
||||
# set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake.modules/") #
|
||||
# enable_testing() #
|
||||
# #
|
||||
# find_path(CATCH_INCLUDE_DIR "catch.hpp") #
|
||||
# include_directories(${INCLUDE_DIRECTORIES} ${CATCH_INCLUDE_DIR}) #
|
||||
# #
|
||||
# file(GLOB SOURCE_FILES "*.cpp") #
|
||||
# add_executable(${PROJECT_NAME} ${SOURCE_FILES}) #
|
||||
# #
|
||||
# include(ParseAndAddCatchTests) #
|
||||
# ParseAndAddCatchTests(${PROJECT_NAME}) #
|
||||
# #
|
||||
# The following variables affect the behavior of the script: #
|
||||
# #
|
||||
# PARSE_CATCH_TESTS_VERBOSE (Default OFF) #
|
||||
# -- enables debug messages #
|
||||
# PARSE_CATCH_TESTS_NO_HIDDEN_TESTS (Default OFF) #
|
||||
# -- excludes tests marked with [!hide], [.] or [.foo] tags #
|
||||
# PARSE_CATCH_TESTS_ADD_FIXTURE_IN_TEST_NAME (Default ON) #
|
||||
# -- adds fixture class name to the test name #
|
||||
# PARSE_CATCH_TESTS_ADD_TARGET_IN_TEST_NAME (Default ON) #
|
||||
# -- adds cmake target name to the test name #
|
||||
# PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS (Default OFF) #
|
||||
# -- causes CMake to rerun when file with tests changes so that new tests will be discovered #
|
||||
# #
|
||||
# One can also set (locally) the optional variable OptionalCatchTestLauncher to precise the way #
|
||||
# a test should be run. For instance to use test MPI, one can write #
|
||||
# set(OptionalCatchTestLauncher ${MPIEXEC} ${MPIEXEC_NUMPROC_FLAG} ${NUMPROC}) #
|
||||
# just before calling this ParseAndAddCatchTests function #
|
||||
# #
|
||||
# The AdditionalCatchParameters optional variable can be used to pass extra argument to the test #
|
||||
# command. For example, to include successful tests in the output, one can write #
|
||||
# set(AdditionalCatchParameters --success) #
|
||||
# #
|
||||
# After the script, the ParseAndAddCatchTests_TESTS property for the target, and for each source #
|
||||
# file in the target is set, and contains the list of the tests extracted from that target, or #
|
||||
# from that file. This is useful, for example to add further labels or properties to the tests. #
|
||||
# #
|
||||
#==================================================================================================#
|
||||
|
||||
if (CMAKE_MINIMUM_REQUIRED_VERSION VERSION_LESS 2.8.8)
|
||||
message(FATAL_ERROR "ParseAndAddCatchTests requires CMake 2.8.8 or newer")
|
||||
endif()
|
||||
|
||||
option(PARSE_CATCH_TESTS_VERBOSE "Print Catch to CTest parser debug messages" OFF)
|
||||
option(PARSE_CATCH_TESTS_NO_HIDDEN_TESTS "Exclude tests with [!hide], [.] or [.foo] tags" OFF)
|
||||
option(PARSE_CATCH_TESTS_ADD_FIXTURE_IN_TEST_NAME "Add fixture class name to the test name" ON)
|
||||
option(PARSE_CATCH_TESTS_ADD_TARGET_IN_TEST_NAME "Add target name to the test name" ON)
|
||||
option(PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS "Add test file to CMAKE_CONFIGURE_DEPENDS property" OFF)
|
||||
|
||||
function(ParseAndAddCatchTests_PrintDebugMessage)
|
||||
if(PARSE_CATCH_TESTS_VERBOSE)
|
||||
message(STATUS "ParseAndAddCatchTests: ${ARGV}")
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
# This removes the contents between
|
||||
# - block comments (i.e. /* ... */)
|
||||
# - full line comments (i.e. // ... )
|
||||
# contents have been read into '${CppCode}'.
|
||||
# !keep partial line comments
|
||||
function(ParseAndAddCatchTests_RemoveComments CppCode)
|
||||
string(ASCII 2 CMakeBeginBlockComment)
|
||||
string(ASCII 3 CMakeEndBlockComment)
|
||||
string(REGEX REPLACE "/\\*" "${CMakeBeginBlockComment}" ${CppCode} "${${CppCode}}")
|
||||
string(REGEX REPLACE "\\*/" "${CMakeEndBlockComment}" ${CppCode} "${${CppCode}}")
|
||||
string(REGEX REPLACE "${CMakeBeginBlockComment}[^${CMakeEndBlockComment}]*${CMakeEndBlockComment}" "" ${CppCode} "${${CppCode}}")
|
||||
string(REGEX REPLACE "\n[ \t]*//+[^\n]+" "\n" ${CppCode} "${${CppCode}}")
|
||||
|
||||
set(${CppCode} "${${CppCode}}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
# Worker function
|
||||
function(ParseAndAddCatchTests_ParseFile SourceFile TestTarget)
|
||||
# If SourceFile is an object library, do not scan it (as it is not a file). Exit without giving a warning about a missing file.
|
||||
if(SourceFile MATCHES "\\\$<TARGET_OBJECTS:.+>")
|
||||
ParseAndAddCatchTests_PrintDebugMessage("Detected OBJECT library: ${SourceFile} this will not be scanned for tests.")
|
||||
return()
|
||||
endif()
|
||||
# According to CMake docs EXISTS behavior is well-defined only for full paths.
|
||||
get_filename_component(SourceFile ${SourceFile} ABSOLUTE)
|
||||
if(NOT EXISTS ${SourceFile})
|
||||
message(WARNING "Cannot find source file: ${SourceFile}")
|
||||
return()
|
||||
endif()
|
||||
ParseAndAddCatchTests_PrintDebugMessage("parsing ${SourceFile}")
|
||||
file(STRINGS ${SourceFile} Contents NEWLINE_CONSUME)
|
||||
|
||||
# Remove block and fullline comments
|
||||
ParseAndAddCatchTests_RemoveComments(Contents)
|
||||
|
||||
# Find definition of test names
|
||||
string(REGEX MATCHALL "[ \t]*(CATCH_)?(TEST_CASE_METHOD|SCENARIO|TEST_CASE)[ \t]*\\([^\)]+\\)+[ \t\n]*{+[ \t]*(//[^\n]*[Tt][Ii][Mm][Ee][Oo][Uu][Tt][ \t]*[0-9]+)*" Tests "${Contents}")
|
||||
|
||||
if(PARSE_CATCH_TESTS_ADD_TO_CONFIGURE_DEPENDS AND Tests)
|
||||
ParseAndAddCatchTests_PrintDebugMessage("Adding ${SourceFile} to CMAKE_CONFIGURE_DEPENDS property")
|
||||
set_property(
|
||||
DIRECTORY
|
||||
APPEND
|
||||
PROPERTY CMAKE_CONFIGURE_DEPENDS ${SourceFile}
|
||||
)
|
||||
endif()
|
||||
|
||||
foreach(TestName ${Tests})
|
||||
# Strip newlines
|
||||
string(REGEX REPLACE "\\\\\n|\n" "" TestName "${TestName}")
|
||||
|
||||
# Get test type and fixture if applicable
|
||||
string(REGEX MATCH "(CATCH_)?(TEST_CASE_METHOD|SCENARIO|TEST_CASE)[ \t]*\\([^,^\"]*" TestTypeAndFixture "${TestName}")
|
||||
string(REGEX MATCH "(CATCH_)?(TEST_CASE_METHOD|SCENARIO|TEST_CASE)" TestType "${TestTypeAndFixture}")
|
||||
string(REGEX REPLACE "${TestType}\\([ \t]*" "" TestFixture "${TestTypeAndFixture}")
|
||||
|
||||
# Get string parts of test definition
|
||||
string(REGEX MATCHALL "\"+([^\\^\"]|\\\\\")+\"+" TestStrings "${TestName}")
|
||||
|
||||
# Strip wrapping quotation marks
|
||||
string(REGEX REPLACE "^\"(.*)\"$" "\\1" TestStrings "${TestStrings}")
|
||||
string(REPLACE "\";\"" ";" TestStrings "${TestStrings}")
|
||||
|
||||
# Validate that a test name and tags have been provided
|
||||
list(LENGTH TestStrings TestStringsLength)
|
||||
if(TestStringsLength GREATER 2 OR TestStringsLength LESS 1)
|
||||
message(FATAL_ERROR "You must provide a valid test name and tags for all tests in ${SourceFile}")
|
||||
endif()
|
||||
|
||||
# Assign name and tags
|
||||
list(GET TestStrings 0 Name)
|
||||
if("${TestType}" STREQUAL "SCENARIO")
|
||||
set(Name "Scenario: ${Name}")
|
||||
endif()
|
||||
if(PARSE_CATCH_TESTS_ADD_FIXTURE_IN_TEST_NAME AND TestFixture)
|
||||
set(CTestName "${TestFixture}:${Name}")
|
||||
else()
|
||||
set(CTestName "${Name}")
|
||||
endif()
|
||||
if(PARSE_CATCH_TESTS_ADD_TARGET_IN_TEST_NAME)
|
||||
set(CTestName "${TestTarget}:${CTestName}")
|
||||
endif()
|
||||
# add target to labels to enable running all tests added from this target
|
||||
set(Labels ${TestTarget})
|
||||
if(TestStringsLength EQUAL 2)
|
||||
list(GET TestStrings 1 Tags)
|
||||
string(TOLOWER "${Tags}" Tags)
|
||||
# remove target from labels if the test is hidden
|
||||
if("${Tags}" MATCHES ".*\\[!?(hide|\\.)\\].*")
|
||||
list(REMOVE_ITEM Labels ${TestTarget})
|
||||
endif()
|
||||
string(REPLACE "]" ";" Tags "${Tags}")
|
||||
string(REPLACE "[" "" Tags "${Tags}")
|
||||
else()
|
||||
# unset tags variable from previous loop
|
||||
unset(Tags)
|
||||
endif()
|
||||
|
||||
list(APPEND Labels ${Tags})
|
||||
|
||||
set(HiddenTagFound OFF)
|
||||
foreach(label ${Labels})
|
||||
string(REGEX MATCH "^!hide|^\\." result ${label})
|
||||
if(result)
|
||||
set(HiddenTagFound ON)
|
||||
break()
|
||||
endif(result)
|
||||
endforeach(label)
|
||||
if(PARSE_CATCH_TESTS_NO_HIDDEN_TESTS AND ${HiddenTagFound} AND ${CMAKE_VERSION} VERSION_LESS "3.9")
|
||||
ParseAndAddCatchTests_PrintDebugMessage("Skipping test \"${CTestName}\" as it has [!hide], [.] or [.foo] label")
|
||||
else()
|
||||
ParseAndAddCatchTests_PrintDebugMessage("Adding test \"${CTestName}\"")
|
||||
if(Labels)
|
||||
ParseAndAddCatchTests_PrintDebugMessage("Setting labels to ${Labels}")
|
||||
endif()
|
||||
|
||||
# Escape commas in the test spec
|
||||
string(REPLACE "," "\\," Name ${Name})
|
||||
|
||||
# Add the test and set its properties
|
||||
add_test(NAME "\"${CTestName}\"" COMMAND ${OptionalCatchTestLauncher} $<TARGET_FILE:${TestTarget}> ${Name} ${AdditionalCatchParameters})
|
||||
# Old CMake versions do not document VERSION_GREATER_EQUAL, so we use VERSION_GREATER with 3.8 instead
|
||||
if(PARSE_CATCH_TESTS_NO_HIDDEN_TESTS AND ${HiddenTagFound} AND ${CMAKE_VERSION} VERSION_GREATER "3.8")
|
||||
ParseAndAddCatchTests_PrintDebugMessage("Setting DISABLED test property")
|
||||
set_tests_properties("\"${CTestName}\"" PROPERTIES DISABLED ON)
|
||||
else()
|
||||
set_tests_properties("\"${CTestName}\"" PROPERTIES FAIL_REGULAR_EXPRESSION "No tests ran"
|
||||
LABELS "${Labels}")
|
||||
endif()
|
||||
set_property(
|
||||
TARGET ${TestTarget}
|
||||
APPEND
|
||||
PROPERTY ParseAndAddCatchTests_TESTS "\"${CTestName}\"")
|
||||
set_property(
|
||||
SOURCE ${SourceFile}
|
||||
APPEND
|
||||
PROPERTY ParseAndAddCatchTests_TESTS "\"${CTestName}\"")
|
||||
endif()
|
||||
|
||||
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
# entry point
|
||||
function(ParseAndAddCatchTests TestTarget)
|
||||
ParseAndAddCatchTests_PrintDebugMessage("Started parsing ${TestTarget}")
|
||||
get_target_property(SourceFiles ${TestTarget} SOURCES)
|
||||
ParseAndAddCatchTests_PrintDebugMessage("Found the following sources: ${SourceFiles}")
|
||||
foreach(SourceFile ${SourceFiles})
|
||||
ParseAndAddCatchTests_ParseFile(${SourceFile} ${TestTarget})
|
||||
endforeach()
|
||||
ParseAndAddCatchTests_PrintDebugMessage("Finished parsing ${TestTarget}")
|
||||
endfunction()
|
File diff suppressed because it is too large
Load Diff
@ -1,7 +0,0 @@
|
||||
// This test file is part of the fwd_test.cpp/impl_test.cpp pair
|
||||
// and used to test the new optional two-part usage of ghc::filesystem
|
||||
// where exactly one cpp includes fs_impl.hpp and all others use
|
||||
// fs_fwd.hpp (to test this with maximum functionality, the unit tests
|
||||
// are included here, signaling they should only include the fs_fwd.hpp)
|
||||
#define GHC_FILESYSTEM_FWD_TEST
|
||||
#include "filesystem_test.cpp"
|
@ -1,9 +0,0 @@
|
||||
// This test file is part of the fwd_test.cpp/impl_test.cpp pair
|
||||
// and used to test the new optional two-part usage of ghc::filesystem
|
||||
// where exactly one cpp includes fs_impl.hpp and all others use
|
||||
// fs_fwd.hpp (to test this with maximum functionality, the unit tests
|
||||
// are included here, signaling they should only include the fs_fwd.hpp)
|
||||
#define NOMINMAX
|
||||
#include <ghc/fs_impl.hpp>
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#include "catch.hpp"
|
@ -1,50 +0,0 @@
|
||||
//---------------------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) 2018, Steffen Schümann <s.schuemann@pobox.com>
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this
|
||||
// list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software without
|
||||
// specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//---------------------------------------------------------------------------------------
|
||||
#define CATCH_CONFIG_MAIN
|
||||
#include "catch.hpp"
|
||||
|
||||
#include <ghc/filesystem.hpp>
|
||||
namespace fs = ghc::filesystem;
|
||||
|
||||
// This test and the one in multi2.cpp doesn't actualy test relevant functionality,
|
||||
// it is just used to check that it is possible to include filesystem.h in multiple
|
||||
// source files.
|
||||
TEST_CASE("Multifile-test 1", "[multi]")
|
||||
{
|
||||
CHECK("/usr/local/bin" == fs::path("/usr/local/bin").generic_string());
|
||||
std::string str = "/usr/local/bin";
|
||||
std::u16string u16str = u"/usr/local/bin";
|
||||
std::u32string u32str = U"/usr/local/bin";
|
||||
CHECK(str == fs::path(str.begin(), str.end()));
|
||||
CHECK(str == fs::path(u16str.begin(), u16str.end()));
|
||||
CHECK(str == fs::path(u32str.begin(), u32str.end()));
|
||||
}
|
@ -1,48 +0,0 @@
|
||||
//---------------------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright (c) 2018, Steffen Schümann <s.schuemann@pobox.com>
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without modification,
|
||||
// are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice, this
|
||||
// list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this list of conditions and the following disclaimer in the documentation
|
||||
// and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its contributors
|
||||
// may be used to endorse or promote products derived from this software without
|
||||
// specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//---------------------------------------------------------------------------------------
|
||||
#include "catch.hpp"
|
||||
#include <ghc/filesystem.hpp>
|
||||
namespace fs = ghc::filesystem;
|
||||
|
||||
// This test and the one in multi1.cpp doesn't actualy test relevant functionality,
|
||||
// it is just used to check that it is possible to include filesystem.h in multiple
|
||||
// source files.
|
||||
TEST_CASE("Multifile-test 2", "[multi]")
|
||||
{
|
||||
CHECK("/usr/local/bin" == fs::path("/usr/local/bin").generic_string());
|
||||
std::string str = "/usr/local/bin";
|
||||
std::u16string u16str = u"/usr/local/bin";
|
||||
std::u32string u32str = U"/usr/local/bin";
|
||||
CHECK(str == fs::path(str.begin(), str.end()));
|
||||
CHECK(str == fs::path(u16str.begin(), u16str.end()));
|
||||
CHECK(str == fs::path(u32str.begin(), u32str.end()));
|
||||
}
|
Loading…
Reference in New Issue