Seregon/ShadPKG

A tool for deriving PKG packet encryption keys for ps4 written in c++

C++/47.3 KB/No license
common/cstring.h
ShadPKG / common / cstring.h
1// SPDX-FileCopyrightText: Copyright 2024 shadPS4 Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3 
4#pragma once
5 
6#include <string_view>
7 
8#include "assert.h"
9 
10namespace Common {
11 
12#pragma clang diagnostic push
13#pragma clang diagnostic ignored "-Wtautological-undefined-compare"
14 
15/**
16 * @brief A null-terminated string with a fixed maximum length
17 * This class is not meant to be used as a general-purpose string class
18 * It is meant to be used as `char[N]` where memory layout is fixed
19 * @tparam N Maximum length of the string
20 * @tparam T Type of character
21 */
22template <size_t N, typename T = char>
23class CString {
24 T data[N]{};
25 
26public:
27 class Iterator;
28 
29 CString() = default;
30 
31 template <size_t M>
32 explicit CString(const CString<M>& other)
33 requires(M <= N)
34 {
35 if (this == nullptr) {
36 return;
37 }
38 std::ranges::copy(other.begin(), other.end(), data);
39 }
40 
41 void FromString(const std::basic_string_view<T>& str) {
42 if (this == nullptr) {
43 return;
44 }
45 size_t p = str.copy(data, N - 1);
46 data[p] = '\0';
47 }
48 
49 void Zero() {
50 if (this == nullptr) {
51 return;
52 }
53 std::ranges::fill(data, 0);
54 }
55 
56 explicit(false) operator std::basic_string_view<T>() const {
57 if (this == nullptr) {
58 return {};
59 }
60 return std::basic_string_view<T>{data};
61 }
62 
63 explicit operator std::basic_string<T>() const {
64 if (this == nullptr) {
65 return {};
66 }
67 return std::basic_string<T>{data};
68 }
69 
70 std::basic_string<T> to_string() const {
71 if (this == nullptr) {
72 return {};
73 }
74 return std::basic_string<T>{data};
75 }
76 
77 std::basic_string_view<T> to_view() const {
78 if (this == nullptr) {
79 return {};
80 }
81 return std::basic_string_view<T>{data};
82 }
83 
84 T* begin() {
85 if (this == nullptr) {
86 return nullptr;
87 }
88 return data;
89 }
90 
91 const T* begin() const {
92 if (this == nullptr) {
93 return nullptr;
94 }
95 return data;
96 }
97 
98 T* end() {
99 if (this == nullptr) {
100 return nullptr;
101 }
102 return data + N;
103 }
104 
105 const T* end() const {
106 if (this == nullptr) {
107 return nullptr;
108 }
109 return data + N;
110 }
111 
112 constexpr std::size_t capacity() const {
113 return N;
114 }
115 
116 std::size_t size() const {
117 return std::char_traits<T>::length(data);
118 }
119 
120 T& operator[](size_t idx) {
121 return data[idx];
122 }
123 
124 const T& operator[](size_t idx) const {
125 return data[idx];
126 }
127 
128 class Iterator {
129 T* ptr;
130 T* end;
131 
132 public:
133 using difference_type = std::ptrdiff_t;
134 using value_type = T;
135 using pointer = T*;
136 using reference = T&;
137 using iterator_category = std::random_access_iterator_tag;
138 
139 Iterator() = default;
140 explicit Iterator(T* ptr) : ptr(ptr), end(ptr + N) {}
141 
142 Iterator& operator++() {
143 ++ptr;
144 return *this;
145 }
146 
147 Iterator operator++(int) {
148 Iterator tmp = *this;
149 ++ptr;
150 return tmp;
151 }
152 
153 operator T*() {
154 ASSERT_MSG(ptr >= end, "CString iterator out of bounds");
155 return ptr;
156 }
157 };
158};
159 
160static_assert(sizeof(CString<13>) == sizeof(char[13])); // Ensure size still matches a simple array
161static_assert(std::weakly_incrementable<CString<13>::Iterator>);
162 
163template <size_t N>
164using CWString = CString<N, wchar_t>;
165 
166template <size_t N>
167using CU16String = CString<N, char16_t>;
168 
169#pragma clang diagnostic pop
170 
171} // namespace Common