mirror of
https://github.com/fmtlib/fmt.git
synced 2025-03-01 10:13:27 +00:00
Put stringy stuff together
This commit is contained in:
parent
3eff8f94d2
commit
7e39c7e6f4
@ -205,6 +205,7 @@ template <bool B, class T = void>
|
|||||||
using enable_if_t = typename std::enable_if<B, T>::type;
|
using enable_if_t = typename std::enable_if<B, T>::type;
|
||||||
template <bool B, class T, class F>
|
template <bool B, class T, class F>
|
||||||
using conditional_t = typename std::conditional<B, T, F>::type;
|
using conditional_t = typename std::conditional<B, T, F>::type;
|
||||||
|
template <bool B> using bool_constant = std::integral_constant<bool, B>;
|
||||||
|
|
||||||
// An enable_if helper to be used in template parameters which results in much
|
// An enable_if helper to be used in template parameters which results in much
|
||||||
// shorter symbols: https://godbolt.org/z/sWw4vP. Extra parentheses are needed
|
// shorter symbols: https://godbolt.org/z/sWw4vP. Extra parentheses are needed
|
||||||
@ -239,119 +240,6 @@ FMT_CONSTEXPR typename std::make_unsigned<Int>::type to_unsigned(Int value) {
|
|||||||
FMT_ASSERT(value >= 0, "negative value");
|
FMT_ASSERT(value >= 0, "negative value");
|
||||||
return static_cast<typename std::make_unsigned<Int>::type>(value);
|
return static_cast<typename std::make_unsigned<Int>::type>(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A contiguous memory buffer with an optional growing ability. */
|
|
||||||
template <typename T> class buffer {
|
|
||||||
private:
|
|
||||||
buffer(const buffer&) = delete;
|
|
||||||
void operator=(const buffer&) = delete;
|
|
||||||
|
|
||||||
T* ptr_;
|
|
||||||
std::size_t size_;
|
|
||||||
std::size_t capacity_;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
// Don't initialize ptr_ since it is not accessed to save a few cycles.
|
|
||||||
buffer(std::size_t sz) FMT_NOEXCEPT : size_(sz), capacity_(sz) {}
|
|
||||||
|
|
||||||
buffer(T* p = nullptr, std::size_t sz = 0, std::size_t cap = 0) FMT_NOEXCEPT
|
|
||||||
: ptr_(p),
|
|
||||||
size_(sz),
|
|
||||||
capacity_(cap) {}
|
|
||||||
|
|
||||||
/** Sets the buffer data and capacity. */
|
|
||||||
void set(T* buf_data, std::size_t buf_capacity) FMT_NOEXCEPT {
|
|
||||||
ptr_ = buf_data;
|
|
||||||
capacity_ = buf_capacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Increases the buffer capacity to hold at least *capacity* elements. */
|
|
||||||
virtual void grow(std::size_t capacity) = 0;
|
|
||||||
|
|
||||||
public:
|
|
||||||
using value_type = T;
|
|
||||||
using const_reference = const T&;
|
|
||||||
|
|
||||||
virtual ~buffer() {}
|
|
||||||
|
|
||||||
T* begin() FMT_NOEXCEPT { return ptr_; }
|
|
||||||
T* end() FMT_NOEXCEPT { return ptr_ + size_; }
|
|
||||||
|
|
||||||
/** Returns the size of this buffer. */
|
|
||||||
std::size_t size() const FMT_NOEXCEPT { return size_; }
|
|
||||||
|
|
||||||
/** Returns the capacity of this buffer. */
|
|
||||||
std::size_t capacity() const FMT_NOEXCEPT { return capacity_; }
|
|
||||||
|
|
||||||
/** Returns a pointer to the buffer data. */
|
|
||||||
T* data() FMT_NOEXCEPT { return ptr_; }
|
|
||||||
|
|
||||||
/** Returns a pointer to the buffer data. */
|
|
||||||
const T* data() const FMT_NOEXCEPT { return ptr_; }
|
|
||||||
|
|
||||||
/**
|
|
||||||
Resizes the buffer. If T is a POD type new elements may not be initialized.
|
|
||||||
*/
|
|
||||||
void resize(std::size_t new_size) {
|
|
||||||
reserve(new_size);
|
|
||||||
size_ = new_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Clears this buffer. */
|
|
||||||
void clear() { size_ = 0; }
|
|
||||||
|
|
||||||
/** Reserves space to store at least *capacity* elements. */
|
|
||||||
void reserve(std::size_t new_capacity) {
|
|
||||||
if (new_capacity > capacity_) grow(new_capacity);
|
|
||||||
}
|
|
||||||
|
|
||||||
void push_back(const T& value) {
|
|
||||||
reserve(size_ + 1);
|
|
||||||
ptr_[size_++] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Appends data to the end of the buffer. */
|
|
||||||
template <typename U> void append(const U* begin, const U* end);
|
|
||||||
|
|
||||||
T& operator[](std::size_t index) { return ptr_[index]; }
|
|
||||||
const T& operator[](std::size_t index) const { return ptr_[index]; }
|
|
||||||
};
|
|
||||||
|
|
||||||
// A container-backed buffer.
|
|
||||||
template <typename Container>
|
|
||||||
class container_buffer : public buffer<typename Container::value_type> {
|
|
||||||
private:
|
|
||||||
Container& container_;
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void grow(std::size_t capacity) FMT_OVERRIDE {
|
|
||||||
container_.resize(capacity);
|
|
||||||
this->set(&container_[0], capacity);
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit container_buffer(Container& c)
|
|
||||||
: buffer<typename Container::value_type>(c.size()), container_(c) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Extracts a reference to the container from back_insert_iterator.
|
|
||||||
template <typename Container>
|
|
||||||
inline Container& get_container(std::back_insert_iterator<Container> it) {
|
|
||||||
using bi_iterator = std::back_insert_iterator<Container>;
|
|
||||||
struct accessor : bi_iterator {
|
|
||||||
accessor(bi_iterator iter) : bi_iterator(iter) {}
|
|
||||||
using bi_iterator::container;
|
|
||||||
};
|
|
||||||
return *accessor(it).container;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct error_handler {
|
|
||||||
FMT_CONSTEXPR error_handler() {}
|
|
||||||
FMT_CONSTEXPR error_handler(const error_handler&) {}
|
|
||||||
|
|
||||||
// This function is intentionally not constexpr to give a compile-time error.
|
|
||||||
FMT_API FMT_NORETURN void on_error(const char* message);
|
|
||||||
};
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -503,6 +391,31 @@ FMT_CONSTEXPR basic_string_view<typename S::char_type> to_string_view(
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace internal {
|
||||||
|
struct dummy_string_view {
|
||||||
|
using char_type = void;
|
||||||
|
};
|
||||||
|
dummy_string_view to_string_view(...);
|
||||||
|
using fmt::v5::to_string_view;
|
||||||
|
|
||||||
|
// Specifies whether S is a string type convertible to fmt::basic_string_view.
|
||||||
|
// It should be a constexpr function but MSVC 2017 fails to compile it in
|
||||||
|
// enable_if.
|
||||||
|
template <typename S>
|
||||||
|
struct is_string
|
||||||
|
: bool_constant<
|
||||||
|
!std::is_empty<decltype(to_string_view(std::declval<S>()))>::value> {
|
||||||
|
};
|
||||||
|
|
||||||
|
struct error_handler {
|
||||||
|
FMT_CONSTEXPR error_handler() {}
|
||||||
|
FMT_CONSTEXPR error_handler(const error_handler&) {}
|
||||||
|
|
||||||
|
// This function is intentionally not constexpr to give a compile-time error.
|
||||||
|
FMT_API FMT_NORETURN void on_error(const char* message);
|
||||||
|
};
|
||||||
|
} // namespace internal
|
||||||
|
|
||||||
// Parsing context consisting of a format string range being parsed and an
|
// Parsing context consisting of a format string range being parsed and an
|
||||||
// argument counter for automatic indexing.
|
// argument counter for automatic indexing.
|
||||||
template <typename Char, typename ErrorHandler = internal::error_handler>
|
template <typename Char, typename ErrorHandler = internal::error_handler>
|
||||||
@ -576,6 +489,111 @@ struct convert_to_int
|
|||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
|
/** A contiguous memory buffer with an optional growing ability. */
|
||||||
|
template <typename T> class buffer {
|
||||||
|
private:
|
||||||
|
buffer(const buffer&) = delete;
|
||||||
|
void operator=(const buffer&) = delete;
|
||||||
|
|
||||||
|
T* ptr_;
|
||||||
|
std::size_t size_;
|
||||||
|
std::size_t capacity_;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Don't initialize ptr_ since it is not accessed to save a few cycles.
|
||||||
|
buffer(std::size_t sz) FMT_NOEXCEPT : size_(sz), capacity_(sz) {}
|
||||||
|
|
||||||
|
buffer(T* p = nullptr, std::size_t sz = 0, std::size_t cap = 0) FMT_NOEXCEPT
|
||||||
|
: ptr_(p),
|
||||||
|
size_(sz),
|
||||||
|
capacity_(cap) {}
|
||||||
|
|
||||||
|
/** Sets the buffer data and capacity. */
|
||||||
|
void set(T* buf_data, std::size_t buf_capacity) FMT_NOEXCEPT {
|
||||||
|
ptr_ = buf_data;
|
||||||
|
capacity_ = buf_capacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Increases the buffer capacity to hold at least *capacity* elements. */
|
||||||
|
virtual void grow(std::size_t capacity) = 0;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using value_type = T;
|
||||||
|
using const_reference = const T&;
|
||||||
|
|
||||||
|
virtual ~buffer() {}
|
||||||
|
|
||||||
|
T* begin() FMT_NOEXCEPT { return ptr_; }
|
||||||
|
T* end() FMT_NOEXCEPT { return ptr_ + size_; }
|
||||||
|
|
||||||
|
/** Returns the size of this buffer. */
|
||||||
|
std::size_t size() const FMT_NOEXCEPT { return size_; }
|
||||||
|
|
||||||
|
/** Returns the capacity of this buffer. */
|
||||||
|
std::size_t capacity() const FMT_NOEXCEPT { return capacity_; }
|
||||||
|
|
||||||
|
/** Returns a pointer to the buffer data. */
|
||||||
|
T* data() FMT_NOEXCEPT { return ptr_; }
|
||||||
|
|
||||||
|
/** Returns a pointer to the buffer data. */
|
||||||
|
const T* data() const FMT_NOEXCEPT { return ptr_; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
Resizes the buffer. If T is a POD type new elements may not be initialized.
|
||||||
|
*/
|
||||||
|
void resize(std::size_t new_size) {
|
||||||
|
reserve(new_size);
|
||||||
|
size_ = new_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Clears this buffer. */
|
||||||
|
void clear() { size_ = 0; }
|
||||||
|
|
||||||
|
/** Reserves space to store at least *capacity* elements. */
|
||||||
|
void reserve(std::size_t new_capacity) {
|
||||||
|
if (new_capacity > capacity_) grow(new_capacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
void push_back(const T& value) {
|
||||||
|
reserve(size_ + 1);
|
||||||
|
ptr_[size_++] = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Appends data to the end of the buffer. */
|
||||||
|
template <typename U> void append(const U* begin, const U* end);
|
||||||
|
|
||||||
|
T& operator[](std::size_t index) { return ptr_[index]; }
|
||||||
|
const T& operator[](std::size_t index) const { return ptr_[index]; }
|
||||||
|
};
|
||||||
|
|
||||||
|
// A container-backed buffer.
|
||||||
|
template <typename Container>
|
||||||
|
class container_buffer : public buffer<typename Container::value_type> {
|
||||||
|
private:
|
||||||
|
Container& container_;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
void grow(std::size_t capacity) FMT_OVERRIDE {
|
||||||
|
container_.resize(capacity);
|
||||||
|
this->set(&container_[0], capacity);
|
||||||
|
}
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit container_buffer(Container& c)
|
||||||
|
: buffer<typename Container::value_type>(c.size()), container_(c) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Extracts a reference to the container from back_insert_iterator.
|
||||||
|
template <typename Container>
|
||||||
|
inline Container& get_container(std::back_insert_iterator<Container> it) {
|
||||||
|
using bi_iterator = std::back_insert_iterator<Container>;
|
||||||
|
struct accessor : bi_iterator {
|
||||||
|
accessor(bi_iterator iter) : bi_iterator(iter) {}
|
||||||
|
using bi_iterator::container;
|
||||||
|
};
|
||||||
|
return *accessor(it).container;
|
||||||
|
}
|
||||||
|
|
||||||
template <typename T> struct no_formatter_error : std::false_type {};
|
template <typename T> struct no_formatter_error : std::false_type {};
|
||||||
|
|
||||||
template <typename T, typename Char = char, typename Enable = void>
|
template <typename T, typename Char = char, typename Enable = void>
|
||||||
@ -586,22 +604,6 @@ struct fallback_formatter {
|
|||||||
"an operator<< that should be used");
|
"an operator<< that should be used");
|
||||||
};
|
};
|
||||||
|
|
||||||
struct dummy_string_view {
|
|
||||||
typedef void char_type;
|
|
||||||
};
|
|
||||||
dummy_string_view to_string_view(...);
|
|
||||||
using fmt::v5::to_string_view;
|
|
||||||
|
|
||||||
// Specifies whether S is a string type convertible to fmt::basic_string_view.
|
|
||||||
// It should be a constexpr function but MSVC 2017 fails to compile it in
|
|
||||||
// enable_if.
|
|
||||||
template <typename S>
|
|
||||||
struct is_string
|
|
||||||
: std::integral_constant<
|
|
||||||
bool,
|
|
||||||
!std::is_same<dummy_string_view,
|
|
||||||
decltype(to_string_view(std::declval<S>()))>::value> {};
|
|
||||||
|
|
||||||
template <typename S> struct char_t_impl {
|
template <typename S> struct char_t_impl {
|
||||||
typedef decltype(to_string_view(std::declval<S>())) result;
|
typedef decltype(to_string_view(std::declval<S>())) result;
|
||||||
typedef typename result::char_type type;
|
typedef typename result::char_type type;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user