brintos

brintos / llvm-project-archived public Read only

0
0
Text · 7.4 KiB · 1ac04c7 Raw
235 lines · c
1//===-- A simple implementation of the string class -------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_STRING_H10#define LLVM_LIBC_SRC___SUPPORT_CPP_STRING_H11 12#include "hdr/func/free.h"13#include "hdr/func/malloc.h"14#include "hdr/func/realloc.h"15#include "src/__support/CPP/string_view.h"16#include "src/__support/integer_to_string.h" // IntegerToString17#include "src/__support/macros/config.h"18#include "src/string/memory_utils/inline_memcpy.h"19#include "src/string/memory_utils/inline_memset.h"20#include "src/string/string_utils.h" // string_length21 22#include <stddef.h> // size_t23 24namespace LIBC_NAMESPACE_DECL {25namespace cpp {26 27// This class mimics std::string but does not intend to be a full fledged28// implementation. Most notably it does not provide support for character traits29// nor custom allocator.30class string {31private:32  static constexpr char NULL_CHARACTER = '\0';33  static constexpr char *get_empty_string() {34    return const_cast<char *>(&NULL_CHARACTER);35  }36 37  char *buffer_ = get_empty_string();38  size_t size_ = 0;39  size_t capacity_ = 0;40 41  constexpr void reset_no_deallocate() {42    buffer_ = get_empty_string();43    size_ = 0;44    capacity_ = 0;45  }46 47  void set_size_and_add_null_character(size_t size) {48    size_ = size;49    if (buffer_ != get_empty_string())50      buffer_[size_] = NULL_CHARACTER;51  }52 53public:54  LIBC_INLINE constexpr string() {}55  LIBC_INLINE string(const string &other) { this->operator+=(other); }56  LIBC_INLINE constexpr string(string &&other)57      : buffer_(other.buffer_), size_(other.size_), capacity_(other.capacity_) {58    other.reset_no_deallocate();59  }60  LIBC_INLINE string(const char *cstr, size_t count) {61    resize(count);62    inline_memcpy(buffer_, cstr, count);63  }64  LIBC_INLINE string(const string_view &view)65      : string(view.data(), view.size()) {}66  LIBC_INLINE string(const char *cstr)67      : string(cstr, ::LIBC_NAMESPACE::internal::string_length(cstr)) {}68  LIBC_INLINE string(size_t size_, char value) {69    resize(size_);70    static_assert(sizeof(char) == sizeof(uint8_t));71    inline_memset((void *)buffer_, static_cast<uint8_t>(value), size_);72  }73 74  LIBC_INLINE string &operator=(const string &other) {75    resize(0);76    return (*this) += other;77  }78 79  LIBC_INLINE string &operator=(string &&other) {80    buffer_ = other.buffer_;81    size_ = other.size_;82    capacity_ = other.capacity_;83    other.reset_no_deallocate();84    return *this;85  }86 87  LIBC_INLINE string &operator=(const string_view &view) {88    return *this = string(view);89  }90 91  LIBC_INLINE ~string() {92    if (buffer_ != get_empty_string())93      ::free(buffer_);94  }95 96  LIBC_INLINE constexpr size_t capacity() const { return capacity_; }97  LIBC_INLINE constexpr size_t size() const { return size_; }98  LIBC_INLINE constexpr bool empty() const { return size_ == 0; }99 100  LIBC_INLINE constexpr const char *data() const { return buffer_; }101  LIBC_INLINE char *data() { return buffer_; }102 103  LIBC_INLINE constexpr const char *begin() const { return data(); }104  LIBC_INLINE char *begin() { return data(); }105 106  LIBC_INLINE constexpr const char *end() const { return data() + size_; }107  LIBC_INLINE char *end() { return data() + size_; }108 109  LIBC_INLINE constexpr const char &front() const { return data()[0]; }110  LIBC_INLINE char &front() { return data()[0]; }111 112  LIBC_INLINE constexpr const char &back() const { return data()[size_ - 1]; }113  LIBC_INLINE char &back() { return data()[size_ - 1]; }114 115  LIBC_INLINE constexpr const char &operator[](size_t index) const {116    return data()[index];117  }118  LIBC_INLINE char &operator[](size_t index) { return data()[index]; }119 120  LIBC_INLINE const char *c_str() const { return data(); }121 122  LIBC_INLINE operator string_view() const {123    return string_view(buffer_, size_);124  }125 126  LIBC_INLINE void reserve(size_t new_capacity) {127    ++new_capacity; // Accounting for the terminating '\0'128    if (new_capacity <= capacity_)129      return;130    // We extend the capacity to amortize buffer_ reallocations.131    // We choose to augment the value by 11 / 8, this is about +40% and division132    // by 8 is cheap. We guard the extension so the operation doesn't overflow.133    if (new_capacity < SIZE_MAX / 11)134      new_capacity = new_capacity * 11 / 8;135    if (void *Ptr = ::realloc(buffer_ == get_empty_string() ? nullptr : buffer_,136                              new_capacity)) {137      buffer_ = static_cast<char *>(Ptr);138      capacity_ = new_capacity;139    } else {140      __builtin_unreachable(); // out of memory141    }142  }143 144  LIBC_INLINE void resize(size_t size) {145    if (size > capacity_) {146      reserve(size);147      const size_t size_extension = size - size_;148      inline_memset(data() + size_, '\0', size_extension);149    }150    set_size_and_add_null_character(size);151  }152 153  LIBC_INLINE string &operator+=(const string &rhs) {154    const size_t new_size = size_ + rhs.size();155    reserve(new_size);156    inline_memcpy(buffer_ + size_, rhs.data(), rhs.size());157    set_size_and_add_null_character(new_size);158    return *this;159  }160 161  LIBC_INLINE string &operator+=(const char c) {162    const size_t new_size = size_ + 1;163    reserve(new_size);164    buffer_[size_] = c;165    set_size_and_add_null_character(new_size);166    return *this;167  }168};169 170LIBC_INLINE bool operator==(const string &lhs, const string &rhs) {171  return string_view(lhs) == string_view(rhs);172}173LIBC_INLINE bool operator!=(const string &lhs, const string &rhs) {174  return string_view(lhs) != string_view(rhs);175}176LIBC_INLINE bool operator<(const string &lhs, const string &rhs) {177  return string_view(lhs) < string_view(rhs);178}179LIBC_INLINE bool operator<=(const string &lhs, const string &rhs) {180  return string_view(lhs) <= string_view(rhs);181}182LIBC_INLINE bool operator>(const string &lhs, const string &rhs) {183  return string_view(lhs) > string_view(rhs);184}185LIBC_INLINE bool operator>=(const string &lhs, const string &rhs) {186  return string_view(lhs) >= string_view(rhs);187}188 189LIBC_INLINE string operator+(const string &lhs, const string &rhs) {190  string Tmp(lhs);191  return Tmp += rhs;192}193LIBC_INLINE string operator+(const string &lhs, const char *rhs) {194  return lhs + string(rhs);195}196LIBC_INLINE string operator+(const char *lhs, const string &rhs) {197  return string(lhs) + rhs;198}199 200namespace internal {201template <typename T> string to_dec_string(T value) {202  const IntegerToString<T> buffer(value);203  return buffer.view();204}205} // namespace internal206 207LIBC_INLINE string to_string(int value) {208  return internal::to_dec_string<int>(value);209}210LIBC_INLINE string to_string(long value) {211  return internal::to_dec_string<long>(value);212}213LIBC_INLINE string to_string(long long value) {214  return internal::to_dec_string<long long>(value);215}216LIBC_INLINE string to_string(unsigned value) {217  return internal::to_dec_string<unsigned>(value);218}219LIBC_INLINE string to_string(unsigned long value) {220  return internal::to_dec_string<unsigned long>(value);221}222LIBC_INLINE string to_string(unsigned long long value) {223  return internal::to_dec_string<unsigned long long>(value);224}225 226// TODO: Support floating point227// LIBC_INLINE string to_string(float value);228// LIBC_INLINE string to_string(double value);229// LIBC_INLINE string to_string(long double value);230 231} // namespace cpp232} // namespace LIBC_NAMESPACE_DECL233 234#endif // LLVM_LIBC_SRC___SUPPORT_CPP_STRING_H235