-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathrefString.h
More file actions
190 lines (153 loc) · 5.77 KB
/
refString.h
File metadata and controls
190 lines (153 loc) · 5.77 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
#pragma once
#include "Classes\tstring\tstring.h"
namespace refStringConcepts
{
template <class T>
concept IsPODText = std::is_same_v<char, std::remove_cv_t<T>> || std::is_same_v<wchar_t, std::remove_cv_t<T>>;
template <class T>
concept HasDataFunction = std::is_member_function_pointer_v<decltype(&T::data)>;
//template <class T>
//concept IsSameBaseType = requires(T t, T a)
//{
//}
};
// refString<type, size>
// type = char or wchar_t
// size = the size of the buffer already allocated.
//
// NB: NO buffer is allocated, all data MUST be preallocated.
template <refStringConcepts::IsPODText T, size_t N = UINT_MAX>
class refString final
{
static_assert(N > 1, "N Must be > 1");
static_assert(refStringConcepts::IsPODText<T>, "Type must be char or wchar_t");
public:
using value_type = typename T;
using const_value_type = std::add_const_t<value_type>;
using size_type = std::size_t;
using ptrdiff_type = std::ptrdiff_t;
using pointer = std::add_pointer_t<value_type>;
using const_pointer_const = std::add_const_t<std::add_pointer_t<const_value_type>>;
using const_pointer = std::add_const_t<pointer>;
using reference = std::add_lvalue_reference_t<value_type>;
using const_reference = std::add_const_t<reference>;
constexpr refString() noexcept = default;
constexpr refString(const refString<T, N>& other) noexcept = default;
constexpr refString(refString<T, N>&& other) noexcept = default;
constexpr explicit refString(const_pointer other) noexcept
: m_data(other)
{ }
constexpr refString(std::nullptr_t other) noexcept
{
}
~refString() noexcept = default;
const refString<T, N>& operator =(const value_type* const other) const noexcept
{
_ts_strcpyn(m_data, other, N);
return *this;
}
const refString<T, N>& operator =(const value_type& other) const noexcept
{
m_data[0] = other;
m_data[1] = value_type();
return *this;
}
template <typename otherT, typename = std::enable_if_t<std::is_same_v<typename otherT::value_type, value_type>&& std::is_member_function_pointer_v<decltype(&otherT::data)>> >
//template <refStringConcepts::HasDataFunction otherT>
//requires(otherT t)
//{
// std::same_as<otherT:value_type, value_type>;
//}
const refString<T, N>& operator =(const otherT& other) const noexcept
{
_ts_strcpyn(m_data, other.data(), N);
return *this;
}
const refString<T, N>& operator =(const refString<T, N>&& other) const noexcept
{
using std::swap;
swap(m_data, other.m_data);
return *this;
}
const refString<T, N>& operator +=(const value_type* const other) const noexcept
{
const size_type nLen = length();
const size_type nOtherLen = _ts_strlen(other);
const size_type nDiff = N - (nLen + nOtherLen);
if (nDiff > 1U) // > 1 to account for zero char
_ts_strncat(m_data, other, nDiff);
return *this;
}
const refString<T, N>& operator +=(const value_type& other) const noexcept
{
const size_type nLen = length();
const size_type nDiff = N - (nLen + 1);
if (nDiff > 1U)
{
// > 1 to account for zero char
m_data[nLen] = other;
m_data[nLen + 1] = value_type();
}
return *this;
}
template <std::size_t otherSize>
const refString& operator +=(const_value_type(&other)[otherSize]) const noexcept { return (*this += &other[0]); }
template <typename otherT, typename = std::enable_if_t<std::is_same_v<typename otherT::value_type, value_type>&& std::is_member_function_pointer_v<decltype(&otherT::data)>> >
const refString<T, N>& operator +=(const otherT& other) const noexcept
{
const size_type nLen = length();
const size_type nOtherLen = _ts_strlen(other);
const size_type nDiff = N - (nLen + nOtherLen);
if (nDiff > 1U) // > 1 to account for zero char
_ts_strncat(m_data, other.data(), nDiff);
return *this;
}
bool compare(const_pointer_const other) const noexcept {
return (_ts_strncmp(m_data, other, N) == 0);
}
template <std::size_t otherSize>
constexpr bool operator ==(const_value_type(&other)[otherSize]) const noexcept {
return compare(&other[0]);
}
constexpr bool operator ==(const refString<T, N>& other) const noexcept {
return compare(other.data());
}
constexpr bool operator ==(const_pointer other) const noexcept {
return compare(other);
}
//constexpr bool operator ==(const_pointer_const other) const noexcept {
// return compare(other);
//}
template <std::size_t otherSize>
constexpr bool operator !=(const_value_type(&other)[otherSize]) const noexcept {
return !compare(&other[0]);
}
constexpr bool operator !=(const refString<T, N>& other) const noexcept {
return !compare(other.data());
}
constexpr bool operator !=(const_pointer other) const noexcept {
return !compare(other);
}
//constexpr bool operator !=(const_pointer_const other) const noexcept {
// return !compare(other);
//}
constexpr explicit operator bool() const noexcept { return !empty(); }
constexpr operator const_pointer() const noexcept { return m_data; }
constexpr reference operator [](const ptrdiff_type& iOffSet) const noexcept { return m_data[iOffSet]; }
constexpr size_type length() const noexcept { return _ts_strnlen(m_data, N); }
constexpr const size_type size() const noexcept { return N; }
constexpr const_pointer data() const noexcept { return m_data; }
constexpr bool empty() const noexcept { return (m_data == nullptr || m_data[0] == value_type()); }
constexpr void clear() const noexcept { if (!empty()) m_data[0] = value_type(); }
constexpr void assign(const refString<T, N>& other) const noexcept
{
const_cast<refString*>(this)->swap(other);
}
void swap(const refString<T, N>& other) noexcept
{
using std::swap;
swap(m_data, other.m_data);
}
private:
mutable pointer m_data{ nullptr };
};