mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-04-22 04:24:44 +00:00
common: Add CString wrapper to handle native null-terminated strings
This commit is contained in:
parent
5e05fecdd0
commit
1de295aa94
2 changed files with 120 additions and 0 deletions
|
@ -349,6 +349,7 @@ set(COMMON src/common/logging/backend.cpp
|
|||
src/common/concepts.h
|
||||
src/common/config.cpp
|
||||
src/common/config.h
|
||||
src/common/cstring.h
|
||||
src/common/debug.h
|
||||
src/common/disassembler.cpp
|
||||
src/common/disassembler.h
|
||||
|
|
119
src/common/cstring.h
Normal file
119
src/common/cstring.h
Normal file
|
@ -0,0 +1,119 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string_view>
|
||||
|
||||
#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 <size_t N, typename T = char>
|
||||
class CString {
|
||||
public:
|
||||
class Iterator;
|
||||
|
||||
T data[N]{};
|
||||
|
||||
public:
|
||||
CString() = default;
|
||||
|
||||
template <size_t M>
|
||||
explicit CString(const CString<M>& other)
|
||||
requires(M <= N)
|
||||
{
|
||||
std::ranges::copy(other.begin(), other.end(), data);
|
||||
}
|
||||
|
||||
void FromString(const std::basic_string_view<T>& str) {
|
||||
size_t p = str.copy(data, N - 1);
|
||||
data[p] = '\0';
|
||||
}
|
||||
|
||||
void Zero() {
|
||||
std::ranges::fill(data, 0);
|
||||
}
|
||||
|
||||
explicit(false) operator std::basic_string_view<T>() const {
|
||||
return std::basic_string_view<T>{data};
|
||||
}
|
||||
|
||||
explicit operator std::basic_string<T>() const {
|
||||
return std::basic_string<T>{data};
|
||||
}
|
||||
|
||||
std::basic_string<T> to_string() const {
|
||||
return std::basic_string<T>{data};
|
||||
}
|
||||
|
||||
std::basic_string_view<T> to_view() const {
|
||||
return std::basic_string_view<T>{data};
|
||||
}
|
||||
|
||||
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<CString<13>::Iterator>);
|
||||
|
||||
} // namespace Common
|
Loading…
Add table
Reference in a new issue