Commit 7e39c7e6 authored by Victor Zverovich's avatar Victor Zverovich

Put stringy stuff together

parent 3eff8f94
...@@ -205,6 +205,7 @@ template <bool B, class T = void> ...@@ -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) { ...@@ -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( ...@@ -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 ...@@ -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 { ...@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment