Path: blob/main/contrib/llvm-project/libc/src/__support/CPP/string.h
213799 views
//===-- A simple implementation of the string class -------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#ifndef LLVM_LIBC_SRC___SUPPORT_CPP_STRING_H9#define LLVM_LIBC_SRC___SUPPORT_CPP_STRING_H1011#include "hdr/func/free.h"12#include "hdr/func/malloc.h"13#include "hdr/func/realloc.h"14#include "src/__support/CPP/string_view.h"15#include "src/__support/integer_to_string.h" // IntegerToString16#include "src/__support/macros/config.h"17#include "src/string/memory_utils/inline_memcpy.h"18#include "src/string/memory_utils/inline_memset.h"19#include "src/string/string_utils.h" // string_length2021#include <stddef.h> // size_t2223namespace LIBC_NAMESPACE_DECL {24namespace cpp {2526// This class mimics std::string but does not intend to be a full fledged27// implementation. Most notably it does not provide support for character traits28// nor custom allocator.29class string {30private:31static constexpr char NULL_CHARACTER = '\0';32static constexpr char *get_empty_string() {33return const_cast<char *>(&NULL_CHARACTER);34}3536char *buffer_ = get_empty_string();37size_t size_ = 0;38size_t capacity_ = 0;3940constexpr void reset_no_deallocate() {41buffer_ = get_empty_string();42size_ = 0;43capacity_ = 0;44}4546void set_size_and_add_null_character(size_t size) {47size_ = size;48if (buffer_ != get_empty_string())49buffer_[size_] = NULL_CHARACTER;50}5152public:53LIBC_INLINE constexpr string() {}54LIBC_INLINE string(const string &other) { this->operator+=(other); }55LIBC_INLINE constexpr string(string &&other)56: buffer_(other.buffer_), size_(other.size_), capacity_(other.capacity_) {57other.reset_no_deallocate();58}59LIBC_INLINE string(const char *cstr, size_t count) {60resize(count);61inline_memcpy(buffer_, cstr, count);62}63LIBC_INLINE string(const string_view &view)64: string(view.data(), view.size()) {}65LIBC_INLINE string(const char *cstr)66: string(cstr, ::LIBC_NAMESPACE::internal::string_length(cstr)) {}67LIBC_INLINE string(size_t size_, char value) {68resize(size_);69static_assert(sizeof(char) == sizeof(uint8_t));70inline_memset((void *)buffer_, static_cast<uint8_t>(value), size_);71}7273LIBC_INLINE string &operator=(const string &other) {74resize(0);75return (*this) += other;76}7778LIBC_INLINE string &operator=(string &&other) {79buffer_ = other.buffer_;80size_ = other.size_;81capacity_ = other.capacity_;82other.reset_no_deallocate();83return *this;84}8586LIBC_INLINE string &operator=(const string_view &view) {87return *this = string(view);88}8990LIBC_INLINE ~string() {91if (buffer_ != get_empty_string())92::free(buffer_);93}9495LIBC_INLINE constexpr size_t capacity() const { return capacity_; }96LIBC_INLINE constexpr size_t size() const { return size_; }97LIBC_INLINE constexpr bool empty() const { return size_ == 0; }9899LIBC_INLINE constexpr const char *data() const { return buffer_; }100LIBC_INLINE char *data() { return buffer_; }101102LIBC_INLINE constexpr const char *begin() const { return data(); }103LIBC_INLINE char *begin() { return data(); }104105LIBC_INLINE constexpr const char *end() const { return data() + size_; }106LIBC_INLINE char *end() { return data() + size_; }107108LIBC_INLINE constexpr const char &front() const { return data()[0]; }109LIBC_INLINE char &front() { return data()[0]; }110111LIBC_INLINE constexpr const char &back() const { return data()[size_ - 1]; }112LIBC_INLINE char &back() { return data()[size_ - 1]; }113114LIBC_INLINE constexpr const char &operator[](size_t index) const {115return data()[index];116}117LIBC_INLINE char &operator[](size_t index) { return data()[index]; }118119LIBC_INLINE const char *c_str() const { return data(); }120121LIBC_INLINE operator string_view() const {122return string_view(buffer_, size_);123}124125LIBC_INLINE void reserve(size_t new_capacity) {126++new_capacity; // Accounting for the terminating '\0'127if (new_capacity <= capacity_)128return;129// We extend the capacity to amortize buffer_ reallocations.130// We choose to augment the value by 11 / 8, this is about +40% and division131// by 8 is cheap. We guard the extension so the operation doesn't overflow.132if (new_capacity < SIZE_MAX / 11)133new_capacity = new_capacity * 11 / 8;134if (void *Ptr = ::realloc(buffer_ == get_empty_string() ? nullptr : buffer_,135new_capacity)) {136buffer_ = static_cast<char *>(Ptr);137capacity_ = new_capacity;138} else {139__builtin_unreachable(); // out of memory140}141}142143LIBC_INLINE void resize(size_t size) {144if (size > capacity_) {145reserve(size);146const size_t size_extension = size - size_;147inline_memset(data() + size_, '\0', size_extension);148}149set_size_and_add_null_character(size);150}151152LIBC_INLINE string &operator+=(const string &rhs) {153const size_t new_size = size_ + rhs.size();154reserve(new_size);155inline_memcpy(buffer_ + size_, rhs.data(), rhs.size());156set_size_and_add_null_character(new_size);157return *this;158}159160LIBC_INLINE string &operator+=(const char c) {161const size_t new_size = size_ + 1;162reserve(new_size);163buffer_[size_] = c;164set_size_and_add_null_character(new_size);165return *this;166}167};168169LIBC_INLINE bool operator==(const string &lhs, const string &rhs) {170return string_view(lhs) == string_view(rhs);171}172LIBC_INLINE bool operator!=(const string &lhs, const string &rhs) {173return string_view(lhs) != string_view(rhs);174}175LIBC_INLINE bool operator<(const string &lhs, const string &rhs) {176return string_view(lhs) < string_view(rhs);177}178LIBC_INLINE bool operator<=(const string &lhs, const string &rhs) {179return string_view(lhs) <= string_view(rhs);180}181LIBC_INLINE bool operator>(const string &lhs, const string &rhs) {182return string_view(lhs) > string_view(rhs);183}184LIBC_INLINE bool operator>=(const string &lhs, const string &rhs) {185return string_view(lhs) >= string_view(rhs);186}187188LIBC_INLINE string operator+(const string &lhs, const string &rhs) {189string Tmp(lhs);190return Tmp += rhs;191}192LIBC_INLINE string operator+(const string &lhs, const char *rhs) {193return lhs + string(rhs);194}195LIBC_INLINE string operator+(const char *lhs, const string &rhs) {196return string(lhs) + rhs;197}198199namespace internal {200template <typename T> string to_dec_string(T value) {201const IntegerToString<T> buffer(value);202return buffer.view();203}204} // namespace internal205206LIBC_INLINE string to_string(int value) {207return internal::to_dec_string<int>(value);208}209LIBC_INLINE string to_string(long value) {210return internal::to_dec_string<long>(value);211}212LIBC_INLINE string to_string(long long value) {213return internal::to_dec_string<long long>(value);214}215LIBC_INLINE string to_string(unsigned value) {216return internal::to_dec_string<unsigned>(value);217}218LIBC_INLINE string to_string(unsigned long value) {219return internal::to_dec_string<unsigned long>(value);220}221LIBC_INLINE string to_string(unsigned long long value) {222return internal::to_dec_string<unsigned long long>(value);223}224225// TODO: Support floating point226// LIBC_INLINE string to_string(float value);227// LIBC_INLINE string to_string(double value);228// LIBC_INLINE string to_string(long double value);229230} // namespace cpp231} // namespace LIBC_NAMESPACE_DECL232233#endif // LLVM_LIBC_SRC___SUPPORT_CPP_STRING_H234235236