// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once #include #include "assert.h" namespace Common { /** * @brief A null-terminated string with a fixed maximum length * This class is not meant to be used as a general-purpose string class * It is meant to be used as `char[N]` where memory layout is fixed * @tparam N Maximum length of the string * @tparam T Type of character */ template class CString { T data[N]{}; public: class Iterator; CString() = default; template explicit CString(const CString& other) requires(M <= N) { std::ranges::copy(other.begin(), other.end(), data); } void FromString(const std::basic_string_view& str) { size_t p = str.copy(data, N - 1); data[p] = '\0'; } void Zero() { std::ranges::fill(data, 0); } #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wtautological-undefined-compare" explicit(false) operator std::basic_string_view() const { if (this == nullptr) { return {}; } return std::basic_string_view{data}; } explicit operator std::basic_string() const { if (this == nullptr) { return {}; } return std::basic_string{data}; } std::basic_string to_string() const { if (this == nullptr) { return {}; } return std::basic_string{data}; } std::basic_string_view to_view() const { if (this == nullptr) { return {}; } return std::basic_string_view{data}; } #pragma clang diagnostic pop char* begin() { return data; } const char* begin() const { return data; } char* end() { return data + N; } const char* end() const { return data + N; } T& operator[](size_t idx) { return data[idx]; } const T& operator[](size_t idx) const { return data[idx]; } class Iterator { T* ptr; T* end; public: using difference_type = std::ptrdiff_t; using value_type = T; using pointer = T*; using reference = T&; using iterator_category = std::random_access_iterator_tag; Iterator() = default; explicit Iterator(T* ptr) : ptr(ptr), end(ptr + N) {} Iterator& operator++() { ++ptr; return *this; } Iterator operator++(int) { Iterator tmp = *this; ++ptr; return tmp; } operator T*() { ASSERT_MSG(ptr >= end, "CString iterator out of bounds"); return ptr; } }; }; static_assert(sizeof(CString<13>) == sizeof(char[13])); // Ensure size still matches a simple array static_assert(std::weakly_incrementable::Iterator>); } // namespace Common