Cleanup string classes
This commit is contained in:
@ -106,7 +106,7 @@ void CGA::show(uint8_t x, uint8_t y, char character, uint8_t attrib) {
|
||||
* n Laenger der Zeichenkette *
|
||||
* attrib Attributbyte fuer alle Zeichen der Zeichenkette *
|
||||
*****************************************************************************/
|
||||
void CGA::print(const String::string_view string, uint8_t attrib) const {
|
||||
void CGA::print(const String::StringView string, uint8_t attrib) const {
|
||||
|
||||
/* Hier muess Code eingefuegt werden */
|
||||
|
||||
|
@ -99,7 +99,7 @@ public:
|
||||
static void show(uint8_t x, uint8_t y, char character, uint8_t attrib = STD_ATTR);
|
||||
|
||||
// Anzeige mehrerer Zeichen ab der aktuellen Cursorposition
|
||||
void print(String::string_view substring, uint8_t attrib = STD_ATTR) const;
|
||||
void print(String::StringView substring, uint8_t attrib = STD_ATTR) const;
|
||||
|
||||
// Verschiebt den Bildschirminhalt um eine Zeile nach oben.
|
||||
// Neue Zeile am unteren Bildrand mit Leerzeichen fuellen
|
||||
|
@ -42,7 +42,7 @@ void SerialOut::write(const char a) {
|
||||
com1.outb(a);
|
||||
}
|
||||
|
||||
void SerialOut::write(const String::string_view a) {
|
||||
void SerialOut::write(const String::StringView a) {
|
||||
for (char current: a) {
|
||||
write(current);
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ public:
|
||||
|
||||
static void write(char a);
|
||||
|
||||
static void write(String::string_view a);
|
||||
static void write(String::StringView a);
|
||||
|
||||
private:
|
||||
static const IOport com1;
|
||||
|
@ -10,7 +10,7 @@ void StringDemo::run() {
|
||||
Util::System::out.clear();
|
||||
|
||||
log.info() << "Allocating new string" << endl;
|
||||
String::string str1 = "This is a dynamically allocated string!";
|
||||
String::String str1 = "This is a dynamically allocated string!";
|
||||
Util::System::out << str1 << endl;
|
||||
|
||||
log.info() << "Reassign string" << endl;
|
||||
@ -25,7 +25,7 @@ void StringDemo::run() {
|
||||
|
||||
Util::System::out << "Hello += World" << endl;
|
||||
log.info() << "Hello += World" << endl;
|
||||
String::string str3 = "Hello";
|
||||
String::String str3 = "Hello";
|
||||
str3 += " World";
|
||||
Util::System::out << str3 << endl;
|
||||
|
||||
@ -40,7 +40,7 @@ void StringDemo::run() {
|
||||
Util::System::out << endl;
|
||||
|
||||
log.info() << "Allocating new string" << endl;
|
||||
String::string str2 = "Hello World";
|
||||
String::String str2 = "Hello World";
|
||||
Util::System::out << "str1 == str2: " << static_cast<int>(str1 == str2) << endl;
|
||||
Util::System::out << "strcmp(Hello, Hello): " << String::strcmp("Hello", "Hello") << endl;
|
||||
|
||||
@ -53,10 +53,10 @@ void StringDemo::run() {
|
||||
arr[2] = 'l';
|
||||
arr[3] = 'l';
|
||||
arr[4] = 'o';
|
||||
Util::System::out << "bse::array<char, 5> to bse::string: " << static_cast<String::string>(arr) << ", size: "
|
||||
<< (String::string(arr)).size() << endl;
|
||||
Util::System::out << "(bse::string)arr (" << static_cast<String::string>(arr) << ") == str2 (" << str2 << "): "
|
||||
<< static_cast<int>(String::string(arr) == str2) << endl;
|
||||
Util::System::out << "bse::array<char, 5> to bse::string: " << static_cast<String::String>(arr) << ", size: "
|
||||
<< (String::String(arr)).size() << endl;
|
||||
Util::System::out << "(bse::string)arr (" << static_cast<String::String>(arr) << ") == str2 (" << str2 << "): "
|
||||
<< static_cast<int>(String::String(arr) == str2) << endl;
|
||||
|
||||
Util::System::out.unlock();
|
||||
auto &schedulerService = Kernel::System::getService<Kernel::SchedulerService>();
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
namespace Memory {
|
||||
|
||||
void memset(char *destination, const char value, std::size_t bytes) {
|
||||
void memset(uint8_t *destination, const uint8_t value, std::size_t bytes) {
|
||||
for (std::size_t byte = 0; byte < bytes; ++byte) {
|
||||
*(destination + byte) = value;
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ void memset(uint8_t *destination, uint8_t value, std::size_t bytes);
|
||||
|
||||
template<typename T>
|
||||
void zero(T *destination) {
|
||||
memset(reinterpret_cast<uint8_t *>(destination), '\0', sizeof(T));
|
||||
memset(reinterpret_cast<uint8_t *>(destination), 0, sizeof(T));
|
||||
}
|
||||
|
||||
} // namespace bse
|
||||
|
@ -14,7 +14,7 @@ constexpr const char *ansi_cyan = "\033[1;36m";
|
||||
constexpr const char *ansi_white = "\033[1;37m";
|
||||
constexpr const char *ansi_default = "\033[0;39m ";
|
||||
|
||||
void Logger::log(const String::string_view message, Device::CGA::color col) const {
|
||||
void Logger::log(const String::StringView message, Device::CGA::color col) const {
|
||||
if (!Logger::serial_enabled) {
|
||||
return;
|
||||
}
|
||||
@ -66,25 +66,25 @@ void Logger::flush() {
|
||||
Logger::unlock();
|
||||
}
|
||||
|
||||
void Logger::trace(const String::string_view message) const {
|
||||
void Logger::trace(const String::StringView message) const {
|
||||
if (Logger::level <= Logger::TRACE) {
|
||||
log(message, Device::CGA::WHITE);
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::debug(const String::string_view message) const {
|
||||
void Logger::debug(const String::StringView message) const {
|
||||
if (Logger::level <= Logger::DEBUG) {
|
||||
log(message, Device::CGA::LIGHT_MAGENTA);
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::error(const String::string_view message) const {
|
||||
void Logger::error(const String::StringView message) const {
|
||||
if (Logger::level <= Logger::ERROR) {
|
||||
log(message, Device::CGA::LIGHT_RED);
|
||||
}
|
||||
}
|
||||
|
||||
void Logger::info(const String::string_view message) const {
|
||||
void Logger::info(const String::StringView message) const {
|
||||
if (Logger::level <= Logger::INFO) {
|
||||
log(message, Device::CGA::LIGHT_BLUE);
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ private:
|
||||
|
||||
static bool serial_enabled;
|
||||
|
||||
void log(String::string_view message, Device::CGA::color col) const;
|
||||
void log(String::StringView message, Device::CGA::color col) const;
|
||||
|
||||
Async::SpinLock sem; // Semaphore would be a cyclic include, also there is just one logger...
|
||||
static void lock() { Logger::instance().sem.acquire(); }
|
||||
@ -46,20 +46,20 @@ public:
|
||||
|
||||
void flush() override;
|
||||
|
||||
void trace(String::string_view message) const;
|
||||
void trace(String::StringView message) const;
|
||||
|
||||
void debug(String::string_view message) const;
|
||||
void debug(String::StringView message) const;
|
||||
|
||||
void error(String::string_view message) const;
|
||||
void error(String::StringView message) const;
|
||||
|
||||
void info(String::string_view message) const;
|
||||
void info(String::StringView message) const;
|
||||
|
||||
// TODO: Make lvl change accessible over menu
|
||||
static void set_level(LogLevel lvl) {
|
||||
Logger::level = lvl;
|
||||
}
|
||||
|
||||
static String::string_view level_to_string(LogLevel lvl) {
|
||||
static String::StringView level_to_string(LogLevel lvl) {
|
||||
switch (lvl) {
|
||||
case Logger::TRACE:
|
||||
return "TRC";
|
||||
|
@ -88,7 +88,7 @@ public:
|
||||
|
||||
// Darstellung einer nullterminierten Zeichenkette
|
||||
template<typename T>
|
||||
friend T &operator<<(T &os, const String::string_view string) {
|
||||
friend T &operator<<(T &os, const String::StringView string) {
|
||||
for (char current: string) {
|
||||
os.put(current);
|
||||
}
|
||||
|
@ -6,172 +6,191 @@
|
||||
|
||||
namespace String {
|
||||
|
||||
// A heap dynamically heap-allocated string (mutable)
|
||||
// Utility functions
|
||||
unsigned int strlen(const char *str);
|
||||
|
||||
unsigned int strlen(const char* str);
|
||||
void strncpy(char* destination, unsigned int n, const char* source);
|
||||
int strcmp(const char* a, const char* b);
|
||||
void strncpy(char *destination, unsigned int n, const char *source);
|
||||
|
||||
class string {
|
||||
private:
|
||||
std::size_t len = 0;
|
||||
char* buf = nullptr;
|
||||
int strcmp(const char *a, const char *b);
|
||||
|
||||
public:
|
||||
using iterator = Container::ContinuousIterator<char>;
|
||||
/**
|
||||
* This class implements a simple heap allocated string.
|
||||
*/
|
||||
class String {
|
||||
using iterator = Container::ContinuousIterator<char>;
|
||||
|
||||
string() = default;
|
||||
public:
|
||||
String() = default;
|
||||
|
||||
string(const char* str) : len(strlen(str)), buf(new char[len + 1]) {
|
||||
strncpy(buf, len + 1, str);
|
||||
/**
|
||||
* Constructor. Implicitly convert string literal to dynamic string.
|
||||
*
|
||||
* @param str The string literal to convert
|
||||
*/
|
||||
String(const char *str) : len(strlen(str)), buf(new char[len + 1]) { // NOLINT(google-explicit-constructor)
|
||||
strncpy(buf, len + 1, str);
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor. Convert a char array to a dynamic string.
|
||||
*
|
||||
* @tparam N The size of the char array
|
||||
* @param arr The char array
|
||||
*/
|
||||
template<std::size_t N>
|
||||
explicit String(const Container::Array<char, N> &arr) : len(N), buf(new char[len + 1]) {
|
||||
for (std::size_t i = 0; i < N; ++i) {
|
||||
buf[i] = arr[i];
|
||||
}
|
||||
buf[N] = '\0';
|
||||
}
|
||||
|
||||
// Convert char array to string
|
||||
template<std::size_t N>
|
||||
explicit string(const Container::Array<char, N>& arr) : len(N), buf(new char[len + 1]) {
|
||||
for (std::size_t i = 0; i < N; ++i) {
|
||||
buf[i] = arr[i];
|
||||
}
|
||||
buf[N] = '\0';
|
||||
}
|
||||
String(const String ©) : len(copy.len), buf(new char[len + 1]) {
|
||||
strncpy(buf, len + 1, copy.buf);
|
||||
}
|
||||
|
||||
string(const string& copy) : len(copy.len), buf(new char[len + 1]) {
|
||||
String &operator=(const String ©) {
|
||||
if (© != this) {
|
||||
len = copy.len;
|
||||
buf = new char[len + 1];
|
||||
strncpy(buf, len + 1, copy.buf);
|
||||
}
|
||||
|
||||
string& operator=(const string& copy) {
|
||||
if (© != this) {
|
||||
len = copy.len;
|
||||
buf = new char[len + 1];
|
||||
strncpy(buf, len + 1, copy.buf);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
return *this;
|
||||
}
|
||||
String(String &&move) noexcept: len(move.len), buf(move.buf) {
|
||||
move.len = 0;
|
||||
move.buf = nullptr;
|
||||
}
|
||||
|
||||
String &operator=(String &&move) noexcept {
|
||||
if (&move != this) {
|
||||
len = move.len;
|
||||
buf = move.buf;
|
||||
|
||||
string(string&& move) noexcept : len(move.len), buf(move.buf) {
|
||||
move.len = 0;
|
||||
move.buf = nullptr;
|
||||
}
|
||||
|
||||
string& operator=(string&& move) noexcept {
|
||||
if (&move != this) {
|
||||
len = move.len;
|
||||
buf = move.buf;
|
||||
return *this;
|
||||
}
|
||||
|
||||
move.len = 0;
|
||||
move.buf = nullptr;
|
||||
}
|
||||
~String() {
|
||||
delete[] buf;
|
||||
}
|
||||
|
||||
return *this;
|
||||
iterator begin() { return {buf}; }
|
||||
|
||||
[[nodiscard]] iterator begin() const { return {buf}; }
|
||||
|
||||
iterator end() { return {&buf[len]}; }
|
||||
|
||||
[[nodiscard]] iterator end() const { return {&buf[len]}; }
|
||||
|
||||
explicit operator char *() { return buf; }
|
||||
|
||||
explicit operator char *() const { return buf; }
|
||||
|
||||
char operator[](std::size_t pos) { return buf[pos]; }
|
||||
|
||||
char operator[](std::size_t pos) const { return buf[pos]; }
|
||||
|
||||
String operator+(const String &other) const {
|
||||
String new_str;
|
||||
new_str.len = len + other.len;
|
||||
new_str.buf = new char[new_str.len + 1];
|
||||
|
||||
strncpy(new_str.buf, len, buf); // Copy this content
|
||||
strncpy(&new_str.buf[len], other.len + 1, other.buf); // Copy other content
|
||||
|
||||
return new_str;
|
||||
}
|
||||
|
||||
String operator+(const char *other) const {
|
||||
std::size_t other_len = strlen(other);
|
||||
|
||||
String new_str;
|
||||
new_str.len = len + other_len;
|
||||
new_str.buf = new char[new_str.len + 1];
|
||||
|
||||
strncpy(new_str.buf, len, buf);
|
||||
strncpy(&new_str.buf[len], other_len + 1, other);
|
||||
|
||||
return new_str;
|
||||
}
|
||||
|
||||
String &operator+=(const String &other) {
|
||||
unsigned int new_len = len + other.size();
|
||||
char *new_buf = new char[new_len + 1];
|
||||
|
||||
strncpy(new_buf, len, buf);
|
||||
strncpy(&new_buf[len], other.size() + 1, other.buf);
|
||||
|
||||
delete[] buf;
|
||||
buf = new_buf;
|
||||
len = new_len;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
String &operator+=(const char *other) {
|
||||
unsigned int other_len = strlen(other);
|
||||
unsigned int new_len = len + other_len;
|
||||
char *new_buf = new char[new_len + 1];
|
||||
|
||||
strncpy(new_buf, len, buf);
|
||||
strncpy(&new_buf[len], other_len + 1, other);
|
||||
|
||||
delete[] buf;
|
||||
buf = new_buf;
|
||||
len = new_len;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
String operator*(unsigned int n) const {
|
||||
String new_str;
|
||||
new_str.len = len * n;
|
||||
new_str.buf = new char[new_str.len];
|
||||
|
||||
for (unsigned int i = 0; i < n; ++i) {
|
||||
strncpy(&new_str.buf[i * len], len, buf);
|
||||
}
|
||||
|
||||
~string() {
|
||||
delete[] buf;
|
||||
return new_str;
|
||||
}
|
||||
|
||||
String &operator*=(unsigned int n) {
|
||||
unsigned int new_len = len * n;
|
||||
char *new_buf = new char[new_len];
|
||||
|
||||
for (unsigned int i = 0; i < n; ++i) {
|
||||
strncpy(&new_buf[i * len], len, buf);
|
||||
}
|
||||
|
||||
iterator begin() { return iterator(buf); }
|
||||
iterator begin() const { return iterator(buf); }
|
||||
iterator end() { return iterator(&buf[len]); }
|
||||
iterator end() const { return iterator(&buf[len]); }
|
||||
delete[] buf;
|
||||
buf = new_buf;
|
||||
len = new_len;
|
||||
return *this;
|
||||
}
|
||||
|
||||
explicit operator char*() { return buf; }
|
||||
explicit operator char*() const { return buf; }
|
||||
bool operator==(const String &other) const {
|
||||
return strcmp(buf, other.buf) == 0;
|
||||
}
|
||||
|
||||
char operator[](std::size_t pos) { return buf[pos]; }
|
||||
char operator[](std::size_t pos) const { return buf[pos]; }
|
||||
bool operator!=(const String &other) const {
|
||||
return strcmp(buf, other.buf) != 0;
|
||||
}
|
||||
|
||||
string operator+(const string& other) const {
|
||||
string new_str;
|
||||
new_str.len = len + other.len;
|
||||
new_str.buf = new char[new_str.len + 1];
|
||||
[[nodiscard]] std::size_t size() const {
|
||||
return len;
|
||||
}
|
||||
|
||||
strncpy(new_str.buf, len, buf); // Copy this content
|
||||
strncpy(&new_str.buf[len], other.len + 1, other.buf); // Copy other content
|
||||
|
||||
return new_str;
|
||||
}
|
||||
|
||||
string operator+(const char* other) const {
|
||||
std::size_t other_len = strlen(other);
|
||||
|
||||
string new_str;
|
||||
new_str.len = len + other_len;
|
||||
new_str.buf = new char[new_str.len + 1];
|
||||
|
||||
strncpy(new_str.buf, len, buf);
|
||||
strncpy(&new_str.buf[len], other_len + 1, other);
|
||||
|
||||
return new_str;
|
||||
}
|
||||
|
||||
string& operator+=(const string& other) {
|
||||
unsigned int new_len = len + other.size();
|
||||
char* new_buf = new char[new_len + 1];
|
||||
|
||||
strncpy(new_buf, len, buf);
|
||||
strncpy(&new_buf[len], other.size() + 1, other.buf);
|
||||
|
||||
delete[] buf;
|
||||
buf = new_buf;
|
||||
len = new_len;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
string& operator+=(const char* other) {
|
||||
unsigned int other_len = strlen(other);
|
||||
unsigned int new_len = len + other_len;
|
||||
char* new_buf = new char[new_len + 1];
|
||||
|
||||
strncpy(new_buf, len, buf);
|
||||
strncpy(&new_buf[len], other_len + 1, other);
|
||||
|
||||
delete[] buf;
|
||||
buf = new_buf;
|
||||
len = new_len;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
string operator*(unsigned int n) const {
|
||||
string new_str;
|
||||
new_str.len = len * n;
|
||||
new_str.buf = new char[new_str.len];
|
||||
|
||||
for (unsigned int i = 0; i < n; ++i) {
|
||||
strncpy(&new_str.buf[i * len], len, buf);
|
||||
}
|
||||
|
||||
return new_str;
|
||||
}
|
||||
|
||||
string& operator*=(unsigned int n) {
|
||||
unsigned int new_len = len * n;
|
||||
char* new_buf = new char[new_len];
|
||||
|
||||
for (unsigned int i = 0; i < n; ++i) {
|
||||
strncpy(&new_buf[i * len], len, buf);
|
||||
}
|
||||
|
||||
delete[] buf;
|
||||
buf = new_buf;
|
||||
len = new_len;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const string& other) const {
|
||||
return strcmp(buf, other.buf) == 0;
|
||||
}
|
||||
|
||||
bool operator!=(const string& other) const {
|
||||
return strcmp(buf, other.buf) != 0;
|
||||
}
|
||||
|
||||
std::size_t size() const {
|
||||
return len;
|
||||
}
|
||||
};
|
||||
private:
|
||||
std::size_t len = 0;
|
||||
char *buf = nullptr;
|
||||
};
|
||||
|
||||
} // namespace bse
|
||||
|
||||
|
@ -2,12 +2,12 @@
|
||||
|
||||
namespace String {
|
||||
|
||||
string_view string_view::substring(std::size_t first, std::size_t last) const {
|
||||
StringView StringView::substring(std::size_t first, std::size_t last) const {
|
||||
if (first < 0 || first > len || last <= first || last > len) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
string_view new_view;
|
||||
StringView new_view;
|
||||
new_view.len = last - first;
|
||||
new_view.buf = &buf[first];
|
||||
return new_view;
|
||||
|
@ -7,34 +7,45 @@
|
||||
|
||||
namespace String {
|
||||
|
||||
class string_view {
|
||||
private:
|
||||
std::size_t len = 0;
|
||||
const char* buf = nullptr;
|
||||
// TODO: Investigate this class
|
||||
|
||||
public:
|
||||
using iterator = Container::ContinuousIterator<char>;
|
||||
/**
|
||||
* This class implements a simple wrapper for usual string literals.
|
||||
*/
|
||||
class StringView {
|
||||
using iterator = Container::ContinuousIterator<char>;
|
||||
|
||||
string_view() = default;
|
||||
public:
|
||||
StringView() = default;
|
||||
|
||||
// Important that char* and string& can be implicitly converted: Only have to provide one
|
||||
// implementation using stringview for everything (OutStream only uses string_view for example)
|
||||
string_view(const char* str) : len(strlen(str)), buf(str) {}
|
||||
string_view(const string& str) : len(str.size()), buf(static_cast<char*>(str)) {}
|
||||
// Important that char* and string& can be implicitly converted: Only have to provide one
|
||||
// implementation using stringview for everything (OutStream only uses StringView for example)
|
||||
StringView(const char *str) : len(strlen(str)), buf(str) {} // NOLINT(google-explicit-constructor)
|
||||
|
||||
iterator begin() const { return iterator(buf); }
|
||||
iterator end() const { return iterator(&buf[len]); }
|
||||
StringView(const String &str) : len(str.size()), // NOLINT(google-explicit-constructor)
|
||||
buf(static_cast<char *>(str)) {}
|
||||
|
||||
explicit operator const char*() const { return buf; }
|
||||
char operator[](std::size_t pos) const { return buf[pos]; }
|
||||
bool operator==(const string_view& other) const { return buf == other.buf; }
|
||||
bool operator!=(const string_view& other) const { return buf != other.buf; }
|
||||
[[nodiscard]] iterator begin() const { return {buf}; }
|
||||
|
||||
std::size_t size() const { return len; }
|
||||
[[nodiscard]] iterator end() const { return {&buf[len]}; }
|
||||
|
||||
string_view substring(std::size_t first, std::size_t last) const;
|
||||
};
|
||||
explicit operator const char *() const { return buf; }
|
||||
|
||||
} // namespace bse
|
||||
char operator[](std::size_t pos) const { return buf[pos]; }
|
||||
|
||||
#endif //C_OS_STRINGVIEW_H
|
||||
bool operator==(const StringView &other) const { return buf == other.buf; }
|
||||
|
||||
bool operator!=(const StringView &other) const { return buf != other.buf; }
|
||||
|
||||
[[nodiscard]] std::size_t size() const { return len; }
|
||||
|
||||
[[nodiscard]] StringView substring(std::size_t first, std::size_t last) const;
|
||||
|
||||
private:
|
||||
std::size_t len = 0;
|
||||
const char *buf = nullptr;
|
||||
};
|
||||
|
||||
} // namespace bse
|
||||
|
||||
#endif //C_OS_STRINGVIEW_H
|
||||
|
Reference in New Issue
Block a user