diff --git a/include/ircd/array_view.h b/include/ircd/array_view.h new file mode 100644 index 000000000..a697ef03c --- /dev/null +++ b/include/ircd/array_view.h @@ -0,0 +1,129 @@ +/* + * charybdis: 21st Century IRC++d + * util.h: Miscellaneous utilities + * + * Copyright (C) 2016 Charybdis Development Team + * Copyright (C) 2016 Jason Volk + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice is present in all copies. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + */ + +#pragma once +#define HAVE_IRCD_ARRAY_VIEW_H + +namespace ircd +{ + template struct array_view; +} + +template +struct ircd::array_view +{ + using value_type = const T; + using pointer = value_type *; + using reference = value_type &; + using difference_type = size_t; + using iterator = value_type *; + using const_iterator = const value_type *; + + value_type *_data { nullptr }; + value_type *_stop { nullptr }; + + public: + const value_type *data() const { return _data; } + value_type *data() { return _data; } + + size_t size() const { return std::distance(_data, _stop); } + bool empty() const { return !size(); } + + const_iterator begin() const { return data(); } + const_iterator end() const { return _stop; } + const_iterator cbegin() { return data(); } + const_iterator cend() { return _stop; } + iterator begin() { return data(); } + iterator end() { return _stop; } + + const value_type &operator[](const size_t &pos) const + { + return *(data() + pos); + } + + value_type &operator[](const size_t &pos) + { + return *(data() + pos); + } + + const value_type &at(const size_t &pos) const + { + if(unlikely(pos >= size())) + throw std::out_of_range("array_view::range_check"); + + return operator[](pos); + } + + value_type &at(const size_t &pos) + { + if(unlikely(pos >= size())) + throw std::out_of_range("array_view::range_check"); + + return operator[](pos); + } + + array_view(value_type *const &start, value_type *const &stop) + :_data{start} + ,_stop{stop} + {} + + array_view(value_type *const &start, const size_t &size) + :array_view(start, start + size) + {} + + array_view(const std::initializer_list &list) + :array_view(std::begin(list), std::end(list)) + {} + + template + array_view(const std::vector &v) + :array_view(v.data(), v.size()) + {} + + template + array_view(std::vector &v) + :array_view(v.data(), v.size()) + {} + + template + array_view(value_type (&buffer)[SIZE]) + :array_view(buffer, SIZE) + {} + + template + array_view(const std::array &array) + :array_view(array.data(), array.size()) + {} + + template + array_view(std::array &array) + :array_view(array.data(), array.size()) + {} + + array_view() = default; +}; diff --git a/include/ircd/byte_view.h b/include/ircd/byte_view.h new file mode 100644 index 000000000..6d0c3376e --- /dev/null +++ b/include/ircd/byte_view.h @@ -0,0 +1,81 @@ +/* + * charybdis: 21st Century IRC++d + * util.h: Miscellaneous utilities + * + * Copyright (C) 2016 Charybdis Development Team + * Copyright (C) 2016 Jason Volk + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice is present in all copies. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + */ + +#pragma once +#define HAVE_IRCD_BYTE_VIEW_H + +namespace ircd +{ + template struct byte_view; + template<> struct byte_view; +} + +/// string_view -> bytes +template +struct ircd::byte_view +{ + string_view s; + + operator const T &() const + { + if(unlikely(sizeof(T) > s.size())) + throw std::bad_cast(); + + return *reinterpret_cast(s.data()); + } + + byte_view(const string_view &s = {}) + :s{s} + { + if(unlikely(sizeof(T) > s.size())) + throw std::bad_cast(); + } + + // bytes -> bytes (completeness) + byte_view(const T &t) + :s{byte_view{t}} + {} +}; + +/// bytes -> string_view. A byte_view is raw data of byte_view. +/// +/// This is an important specialization to take note of. When you see +/// byte_view know that another type's bytes are being represented +/// by the string_view if that type is not string_view family itself. +template<> +struct ircd::byte_view +:string_view +{ + template::value, int *>::type = nullptr> + byte_view(const T &t) + :string_view{reinterpret_cast(&t), sizeof(T)} + {} + + /// string_view -> string_view (completeness) + byte_view(const string_view &t) + :string_view{t} + {} +}; diff --git a/include/ircd/stdinc.h b/include/ircd/stdinc.h index 7281b4c3a..c9faa914c 100644 --- a/include/ircd/stdinc.h +++ b/include/ircd/stdinc.h @@ -184,6 +184,9 @@ namespace ircd #include "util.h" #include "exception.h" #include "string_view.h" +#include "vector_view.h" +#include "array_view.h" +#include "byte_view.h" #include "allocator.h" #include "buffer.h" #include "date.h" diff --git a/include/ircd/string_view.h b/include/ircd/string_view.h index 5f49759a3..48f757631 100644 --- a/include/ircd/string_view.h +++ b/include/ircd/string_view.h @@ -30,13 +30,9 @@ namespace ircd { struct string_view; - template struct vector_view; - - template struct byte_view; - template<> struct byte_view; - template auto ctype(const string_view &s); + const char *data(const string_view &); size_t size(const string_view &); bool empty(const string_view &); bool operator!(const string_view &); @@ -46,6 +42,13 @@ namespace ircd constexpr string_view operator ""_sv(const char *const literal, const size_t size); } +namespace std +{ + template<> struct std::hash; + template<> struct std::less; + template<> struct std::equal_to; +} + /// Customized std::string_view (experimental TS / C++17) /// /// This class adds iterator-based (char*, char*) construction to std::string_view which otherwise @@ -185,6 +188,33 @@ struct ircd::string_view using std::string_view::string_view; }; +/// Specialization for std::hash<> participation +template<> +struct std::hash +:std::hash +{ + using std::hash::operator(); + using std::hash::hash; +}; + +/// Specialization for std::less<> participation +template<> +struct std::less +:std::less +{ + using std::less::operator(); + using std::less::less; +}; + +/// Specialization for std::equal_to<> participation +template<> +struct std::equal_to +:std::equal_to +{ + using std::equal_to::operator(); + using std::equal_to::equal_to; +}; + /// Compile-time conversion from a string literal into a string_view. constexpr ircd::string_view ircd::operator ""_sv(const char *const literal, const size_t size) @@ -192,139 +222,6 @@ ircd::operator ""_sv(const char *const literal, const size_t size) return string_view{literal, size}; } -template -struct ircd::vector_view -{ - using value_type = T; - using pointer = T *; - using reference = T &; - using difference_type = size_t; - using iterator = T *; - using const_iterator = const T *; - - T *_data { nullptr }; - T *_stop { nullptr }; - - public: - const T *data() const { return _data; } - T *data() { return _data; } - - size_t size() const { return std::distance(_data, _stop); } - bool empty() const { return !size(); } - - const_iterator begin() const { return data(); } - const_iterator end() const { return _stop; } - const_iterator cbegin() { return data(); } - const_iterator cend() { return _stop; } - iterator begin() { return data(); } - iterator end() { return _stop; } - - const T &operator[](const size_t &pos) const - { - return *(data() + pos); - } - - T &operator[](const size_t &pos) - { - return *(data() + pos); - } - - const T &at(const size_t &pos) const - { - if(unlikely(pos >= size())) - throw std::out_of_range("vector_view::range_check"); - - return operator[](pos); - } - - T &at(const size_t &pos) - { - if(unlikely(pos >= size())) - throw std::out_of_range("vector_view::range_check"); - - return operator[](pos); - } - - vector_view(T *const &start, T *const &stop) - :_data{start} - ,_stop{stop} - {} - - vector_view(T *const &start, const size_t &size) - :vector_view(start, start + size) - {} - - vector_view(const std::initializer_list &list) - :vector_view(std::begin(list), std::end(list)) - {} - - template - vector_view(std::vector &v) - :vector_view(v.data(), v.size()) - {} - - template - vector_view(T (&buffer)[SIZE]) - :vector_view(buffer, SIZE) - {} - - template - vector_view(std::array &array) - :vector_view(array.data(), array.size()) - {} - - vector_view() = default; -}; - -/// string_view -> bytes -template -struct ircd::byte_view -{ - string_view s; - - operator const T &() const - { - if(unlikely(sizeof(T) > s.size())) - throw std::bad_cast(); - - return *reinterpret_cast(s.data()); - } - - byte_view(const string_view &s = {}) - :s{s} - { - if(unlikely(sizeof(T) > s.size())) - throw std::bad_cast(); - } - - // bytes -> bytes (completeness) - byte_view(const T &t) - :s{byte_view{t}} - {} -}; - -/// bytes -> string_view. A byte_view is raw data of byte_view. -/// -/// This is an important specialization to take note of. When you see -/// byte_view know that another type's bytes are being represented -/// by the string_view if that type is not string_view family itself. -template<> -struct ircd::byte_view -:string_view -{ - template::value, int *>::type = nullptr> - byte_view(const T &t) - :string_view{reinterpret_cast(&t), sizeof(T)} - {} - - /// string_view -> string_view (completeness) - byte_view(const string_view &t) - :string_view{t} - {} -}; - inline bool ircd::operator!(const string_view &str) { @@ -355,6 +252,12 @@ ircd::size(const string_view &str) return str.size(); } +inline const char * +ircd::data(const string_view &str) +{ + return str.data(); +} + template auto ircd::ctype(const string_view &s) diff --git a/include/ircd/vector_view.h b/include/ircd/vector_view.h new file mode 100644 index 000000000..f14b1bad9 --- /dev/null +++ b/include/ircd/vector_view.h @@ -0,0 +1,114 @@ +/* + * charybdis: 21st Century IRC++d + * util.h: Miscellaneous utilities + * + * Copyright (C) 2016 Charybdis Development Team + * Copyright (C) 2016 Jason Volk + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice is present in all copies. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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. + * + */ + +#pragma once +#define HAVE_IRCD_VECTOR_VIEW_H + +namespace ircd +{ + template struct vector_view; +} + +template +struct ircd::vector_view +{ + using value_type = T; + using pointer = value_type *; + using reference = value_type &; + using difference_type = size_t; + using iterator = value_type *; + using const_iterator = const value_type *; + + value_type *_data { nullptr }; + value_type *_stop { nullptr }; + + public: + value_type *data() const { return _data; } + size_t size() const { return std::distance(_data, _stop); } + bool empty() const { return !size(); } + + const_iterator begin() const { return data(); } + const_iterator end() const { return _stop; } + const_iterator cbegin() { return data(); } + const_iterator cend() { return _stop; } + iterator begin() { return data(); } + iterator end() { return _stop; } + + value_type &operator[](const size_t &pos) const + { + return *(data() + pos); + } + + value_type &at(const size_t &pos) const + { + if(unlikely(pos >= size())) + throw std::out_of_range("vector_view::range_check"); + + return operator[](pos); + } + + vector_view(value_type *const &start, value_type *const &stop) + :_data{start} + ,_stop{stop} + {} + + vector_view(value_type *const &start, const size_t &size) + :vector_view(start, start + size) + {} + + vector_view(const std::initializer_list &list) + :vector_view(std::begin(list), std::end(list)) + {} + + template + vector_view(const std::vector &v) + :vector_view(v.data(), v.size()) + {} + + template + vector_view(std::vector &v) + :vector_view(v.data(), v.size()) + {} + + template + vector_view(value_type (&buffer)[SIZE]) + :vector_view(buffer, SIZE) + {} + + template + vector_view(const std::array &array) + :vector_view(array.data(), array.size()) + {} + + template + vector_view(std::array &array) + :vector_view(array.data(), array.size()) + {} + + vector_view() = default; +};