0
0
Fork 0
mirror of https://github.com/matrix-construct/construct synced 2024-11-29 10:12:39 +01:00

ircd: Split up string_view.h.

This commit is contained in:
Jason Volk 2017-11-15 17:21:26 -08:00
parent c16a6e8baa
commit 832529396c
5 changed files with 368 additions and 138 deletions

129
include/ircd/array_view.h Normal file
View file

@ -0,0 +1,129 @@
/*
* charybdis: 21st Century IRC++d
* util.h: Miscellaneous utilities
*
* Copyright (C) 2016 Charybdis Development Team
* Copyright (C) 2016 Jason Volk <jason@zemos.net>
*
* 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<class T> struct array_view;
}
template<class T>
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<value_type> &list)
:array_view(std::begin(list), std::end(list))
{}
template<class U,
class A>
array_view(const std::vector<U, A> &v)
:array_view(v.data(), v.size())
{}
template<class U,
class A>
array_view(std::vector<U, A> &v)
:array_view(v.data(), v.size())
{}
template<size_t SIZE>
array_view(value_type (&buffer)[SIZE])
:array_view(buffer, SIZE)
{}
template<class U,
size_t SIZE>
array_view(const std::array<U, SIZE> &array)
:array_view(array.data(), array.size())
{}
template<size_t SIZE>
array_view(std::array<value_type, SIZE> &array)
:array_view(array.data(), array.size())
{}
array_view() = default;
};

81
include/ircd/byte_view.h Normal file
View file

@ -0,0 +1,81 @@
/*
* charybdis: 21st Century IRC++d
* util.h: Miscellaneous utilities
*
* Copyright (C) 2016 Charybdis Development Team
* Copyright (C) 2016 Jason Volk <jason@zemos.net>
*
* 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<class T = string_view> struct byte_view;
template<> struct byte_view<string_view>;
}
/// string_view -> bytes
template<class T>
struct ircd::byte_view
{
string_view s;
operator const T &() const
{
if(unlikely(sizeof(T) > s.size()))
throw std::bad_cast();
return *reinterpret_cast<const T *>(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<string_view>{t}}
{}
};
/// bytes -> string_view. A byte_view<string_view> is raw data of byte_view<T>.
///
/// This is an important specialization to take note of. When you see
/// byte_view<string_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<ircd::string_view>
:string_view
{
template<class T,
typename std::enable_if<!std::is_base_of<std::string_view, T>::value, int *>::type = nullptr>
byte_view(const T &t)
:string_view{reinterpret_cast<const char *>(&t), sizeof(T)}
{}
/// string_view -> string_view (completeness)
byte_view(const string_view &t)
:string_view{t}
{}
};

View file

@ -184,6 +184,9 @@ namespace ircd
#include "util.h" #include "util.h"
#include "exception.h" #include "exception.h"
#include "string_view.h" #include "string_view.h"
#include "vector_view.h"
#include "array_view.h"
#include "byte_view.h"
#include "allocator.h" #include "allocator.h"
#include "buffer.h" #include "buffer.h"
#include "date.h" #include "date.h"

View file

@ -30,13 +30,9 @@ namespace ircd
{ {
struct string_view; struct string_view;
template<class T> struct vector_view;
template<class T = string_view> struct byte_view;
template<> struct byte_view<string_view>;
template<int (&test)(int) = std::isprint> auto ctype(const string_view &s); template<int (&test)(int) = std::isprint> auto ctype(const string_view &s);
const char *data(const string_view &);
size_t size(const string_view &); size_t size(const string_view &);
bool empty(const string_view &); bool empty(const string_view &);
bool operator!(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); constexpr string_view operator ""_sv(const char *const literal, const size_t size);
} }
namespace std
{
template<> struct std::hash<ircd::string_view>;
template<> struct std::less<ircd::string_view>;
template<> struct std::equal_to<ircd::string_view>;
}
/// Customized std::string_view (experimental TS / C++17) /// Customized std::string_view (experimental TS / C++17)
/// ///
/// This class adds iterator-based (char*, char*) construction to std::string_view which otherwise /// 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; using std::string_view::string_view;
}; };
/// Specialization for std::hash<> participation
template<>
struct std::hash<ircd::string_view>
:std::hash<std::string_view>
{
using std::hash<std::string_view>::operator();
using std::hash<std::string_view>::hash;
};
/// Specialization for std::less<> participation
template<>
struct std::less<ircd::string_view>
:std::less<std::string_view>
{
using std::less<std::string_view>::operator();
using std::less<std::string_view>::less;
};
/// Specialization for std::equal_to<> participation
template<>
struct std::equal_to<ircd::string_view>
:std::equal_to<std::string_view>
{
using std::equal_to<std::string_view>::operator();
using std::equal_to<std::string_view>::equal_to;
};
/// Compile-time conversion from a string literal into a string_view. /// Compile-time conversion from a string literal into a string_view.
constexpr ircd::string_view constexpr ircd::string_view
ircd::operator ""_sv(const char *const literal, const size_t size) 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}; return string_view{literal, size};
} }
template<class T>
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<T> &list)
:vector_view(std::begin(list), std::end(list))
{}
template<class U,
class A>
vector_view(std::vector<U, A> &v)
:vector_view(v.data(), v.size())
{}
template<size_t SIZE>
vector_view(T (&buffer)[SIZE])
:vector_view(buffer, SIZE)
{}
template<size_t SIZE>
vector_view(std::array<T, SIZE> &array)
:vector_view(array.data(), array.size())
{}
vector_view() = default;
};
/// string_view -> bytes
template<class T>
struct ircd::byte_view
{
string_view s;
operator const T &() const
{
if(unlikely(sizeof(T) > s.size()))
throw std::bad_cast();
return *reinterpret_cast<const T *>(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<string_view>{t}}
{}
};
/// bytes -> string_view. A byte_view<string_view> is raw data of byte_view<T>.
///
/// This is an important specialization to take note of. When you see
/// byte_view<string_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<ircd::string_view>
:string_view
{
template<class T,
typename std::enable_if<!std::is_base_of<std::string_view, T>::value, int *>::type = nullptr>
byte_view(const T &t)
:string_view{reinterpret_cast<const char *>(&t), sizeof(T)}
{}
/// string_view -> string_view (completeness)
byte_view(const string_view &t)
:string_view{t}
{}
};
inline bool inline bool
ircd::operator!(const string_view &str) ircd::operator!(const string_view &str)
{ {
@ -355,6 +252,12 @@ ircd::size(const string_view &str)
return str.size(); return str.size();
} }
inline const char *
ircd::data(const string_view &str)
{
return str.data();
}
template<int (&test)(int)> template<int (&test)(int)>
auto auto
ircd::ctype(const string_view &s) ircd::ctype(const string_view &s)

114
include/ircd/vector_view.h Normal file
View file

@ -0,0 +1,114 @@
/*
* charybdis: 21st Century IRC++d
* util.h: Miscellaneous utilities
*
* Copyright (C) 2016 Charybdis Development Team
* Copyright (C) 2016 Jason Volk <jason@zemos.net>
*
* 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<class T> struct vector_view;
}
template<class T>
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<value_type> &list)
:vector_view(std::begin(list), std::end(list))
{}
template<class U,
class A>
vector_view(const std::vector<U, A> &v)
:vector_view(v.data(), v.size())
{}
template<class U,
class A>
vector_view(std::vector<U, A> &v)
:vector_view(v.data(), v.size())
{}
template<size_t SIZE>
vector_view(value_type (&buffer)[SIZE])
:vector_view(buffer, SIZE)
{}
template<class U,
size_t SIZE>
vector_view(const std::array<U, SIZE> &array)
:vector_view(array.data(), array.size())
{}
template<size_t SIZE>
vector_view(std::array<value_type, SIZE> &array)
:vector_view(array.data(), array.size())
{}
vector_view() = default;
};