1 #ifndef GARLIC_CONTAINERS_H
2 #define GARLIC_CONTAINERS_H
22 enum class text_type : uint8_t {
27 template<
typename Ch,
typename SizeType =
unsigned>
28 class basic_string_ref {
34 explicit constexpr basic_string_ref(
const Ch* data) : data_(data) {
38 explicit constexpr basic_string_ref(
const Ch* data, SizeType size) : data_(data), size_(size) {}
40 explicit constexpr basic_string_ref(
41 const std::basic_string_view<Ch>& data) : data_(data.data()), size_(data.size()) {}
43 explicit basic_string_ref(
44 const std::basic_string<Ch>& data) : data_(data.data()), size_(data.size()) {}
46 constexpr basic_string_ref(
const basic_string_ref& value) : data_(value.data_), size_(value.size_) {};
47 constexpr basic_string_ref(basic_string_ref&& value) : data_(value.data_), size_(value.size_) {};
49 constexpr
const Ch* data()
const {
return data_; }
50 constexpr SizeType size()
const {
return size_; }
53 using string_ref = basic_string_ref<char>;
66 template<
typename Ch,
typename SizeType =
unsigned>
69 constexpr
basic_text() : size_(0), type_(text_type::reference) {}
71 constexpr
basic_text(
const Ch* data, text_type type = text_type::reference) : type_(type) {
73 if (type == text_type::copy && size_)
74 data_ = strcpy((Ch*)malloc((size_ + 1) *
sizeof(Ch)), data);
80 const Ch* data, SizeType size,
81 text_type type = text_type::reference) : size_(size), type_(type) {
82 if (type == text_type::copy && size_) {
83 data_ = strncpy((Ch*)malloc((size_ + 1) *
sizeof(Ch)), data, size_ + 1);
90 const std::basic_string<Ch>& value,
91 text_type type = text_type::reference) :
basic_text(value.data(), value.size(), type) {}
94 const std::basic_string_view<Ch>& value,
95 text_type type = text_type::reference) :
basic_text(value.data(), value.size(), type) {}
98 const basic_string_ref<Ch>& value,
99 text_type type = text_type::reference) :
basic_text(value.data(), value.size(), type) {}
103 ) : data_(other.data_), size_(other.size_), type_(text_type::reference) {};
110 static inline basic_text copy(
const Ch* data, SizeType size) {
return basic_text(data, size, text_type::copy); }
111 static inline basic_text copy(
const std::basic_string<Ch>& value) {
return basic_text(value, text_type::copy); }
112 static inline basic_text copy(
const std::basic_string_view<Ch>& value) {
return basic_text(value, text_type::copy); }
114 return basic_text(another.data(), another.size(), text_type::copy);
121 type_ = text_type::reference;
135 return basic_text(data_, size_, text_type::copy);
138 return basic_text(data_, size_, text_type::reference);
140 inline basic_string_ref<Ch> string_ref()
const noexcept {
141 return basic_string_ref<Ch>(data_, size_);
146 inline constexpr
bool operator ==(
const basic_text& another)
const noexcept {
147 return (another.data_ == data_ && another.size_ == size_) || !strncmp(data_, another.data_, size_);
149 inline bool operator ==(
const std::basic_string<Ch>& value)
const noexcept {
150 return !strncmp(data_, value.data(), size_);
152 inline constexpr
bool operator ==(
const std::basic_string_view<Ch>& value)
const noexcept {
153 return !strncmp(data_, value.data(), size_);
156 const Ch* data()
const {
return data_; }
158 inline void pop_back() noexcept {
163 inline constexpr
char back()
const {
return data_[size_ - 1]; }
165 inline constexpr
const Ch* begin()
const {
return data_; }
166 inline constexpr
const Ch* end()
const {
return data_ + size_; }
168 inline constexpr SizeType size()
const noexcept {
return size_; }
169 inline constexpr
bool empty()
const noexcept {
return !size_; }
170 inline constexpr
bool is_view()
const noexcept {
return type_ == text_type::reference; }
172 inline int compare(
const char* value) {
173 return strncmp(value, data_, size_);
177 return strncmp(value.data_, data_, size_);
180 constexpr
static inline basic_text no_text() noexcept {
184 friend inline std::ostream& operator << (std::ostream& output,
const basic_text&
text) {
185 output.write(
text.data(),
text.size());
194 constexpr
inline void destroy() noexcept {
195 if (type_ == text_type::copy && size_)
196 std::free((
void*)data_);
206 template<
typename ValueType,
typename SizeType =
unsigned>
209 using value_type = ValueType;
210 using const_reference =
const ValueType&;
211 using reference = ValueType&;
212 using pointer = ValueType*;
213 using iterator = ValueType*;
216 sequence(SizeType initial_capacity = 8) : capacity_(initial_capacity), size_(0) {
218 items_ =
reinterpret_cast<pointer
>(std::malloc(capacity_ *
sizeof(ValueType)));
222 push_front(list.begin(), list.end());
226 sequence(
sequence&& old) : items_(old.items_), capacity_(old.capacity_), size_(old.size_) {
232 void push_back(value_type&& value) {
234 new (items_ + size_++) ValueType(std::forward<ValueType>(value));
237 void push_back(const_reference value) {
239 new (items_ + size_++) ValueType(value);
244 if (count > capacity_ - size_) {
246 items_ =
reinterpret_cast<pointer
>(std::realloc(items_, capacity_ *
sizeof(ValueType)));
249 memmove(items_ + count, items_, count *
sizeof(ValueType));
250 for (
auto i = 0; i < count; ++i)
new (items_ + i) ValueType(
begin[i]);
258 capacity_ = old.capacity_;
263 reference operator [](SizeType index) {
return items_[index]; }
264 const_reference operator [](SizeType index)
const {
return items_[index]; }
279 inline SizeType
size() const noexcept {
return size_; }
282 inline SizeType
capacity() const noexcept {
return capacity_; }
285 inline bool empty() const noexcept {
return !size_; }
287 constexpr
static inline sequence no_sequence() noexcept {
297 inline void reserve_item() noexcept {
298 if (capacity_ == 0) {
300 items_ =
reinterpret_cast<pointer
>(std::malloc(capacity_ *
sizeof(ValueType)));
303 if (size_ == capacity_) {
304 capacity_ += (capacity_ + 1) / 2;
305 items_ =
reinterpret_cast<pointer
>(std::realloc(items_, capacity_ *
sizeof(ValueType)));
309 inline void destroy() noexcept {
311 for (
auto it = items_; it < (items_ + size_); ++it) it->~ValueType();
320 template<
typename Ch,
typename SizeType>
321 struct hash<garlic::basic_text<Ch, SizeType>> {
323 return hash<std::string_view>()(std::string_view(value.data(), value.size()));