bsnes/higan/nall/string/core.hpp

143 lines
3.5 KiB
C++
Raw Normal View History

#ifdef NALL_STRING_INTERNAL_HPP
//core functionality
//only this header file may access _data, _size, _capacity directly
//all other headers must use data(), size(), capacity()
namespace nall {
char* string::data() { _unique(); return _data.get(); }
const char* string::data() const { if(!_data) return ""; return _data.get(); }
unsigned string::length() const { return strlen(data()); }
unsigned string::size() const { return _size; }
unsigned string::capacity() const { return _capacity; }
bool string::empty() const { return size() == 0; }
//ensure _data is unique
void string::_unique() {
if(_data.unique()) return;
_copy();
}
//copy _data (to make unique or to grow in size)
void string::_copy() {
auto copy = new char[_capacity + 1];
if(_data.get()) memcpy(copy, _data.get(), min(_capacity, _size));
copy[_size] = 0;
copy[_capacity] = 0;
_data.reset(copy);
}
//amortize growth to O(log n)
//allocate one extra byte to always store null-terminator for libc usage
void string::reserve(unsigned capacity) {
if(capacity > _capacity) {
_capacity = bit::round(capacity + 1) - 1;
_copy();
}
}
void string::resize(unsigned size) {
reserve(size);
data()[_size = size] = 0;
}
void string::reset() {
_data.reset();
_capacity = 0;
_size = 0;
}
void string::clear(char c) {
for(unsigned n = 0; n < size(); n++) data()[n] = c;
}
template<typename... Args> string& string::assign(Args&&... args) {
reset();
sprint(*this, std::forward<Args>(args)...);
return *this;
}
template<typename... Args> string& string::append(Args&&... args) {
sprint(*this, std::forward<Args>(args)...);
return *this;
}
string& string::_append(const char* s) {
if(s == nullptr) return *this;
unsigned basesize = size(), length = strlen(s);
reserve(basesize + length);
memcpy(data() + basesize, s, length);
resize(basesize + length);
return *this;
}
string::operator bool() const {
return !empty();
}
string::operator const char*() const {
return data();
}
char& string::operator[](unsigned position) {
if(position > size() + 1) throw exception_out_of_bounds{};
return data()[position];
}
const char& string::operator[](unsigned position) const {
if(position > size() + 1) throw exception_out_of_bounds{};
return data()[position];
}
bool string::operator==(const char* str) const { return strcmp(data(), str) == 0; }
bool string::operator!=(const char* str) const { return strcmp(data(), str) != 0; }
bool string::operator< (const char* str) const { return strcmp(data(), str) < 0; }
bool string::operator<=(const char* str) const { return strcmp(data(), str) <= 0; }
bool string::operator> (const char* str) const { return strcmp(data(), str) > 0; }
bool string::operator>=(const char* str) const { return strcmp(data(), str) >= 0; }
string& string::operator=(const string& source) {
if(&source == this) return *this;
_data = source._data;
_capacity = source._capacity;
_size = source._size;
return *this;
}
string& string::operator=(string&& source) {
if(&source == this) return *this;
_data = std::move(source._data);
_capacity = source._capacity;
_size = source._size;
source._capacity = 0;
source._size = 0;
return *this;
}
string::string(const string& source) {
operator=(source);
}
string::string(string&& source) {
operator=(std::move(source));
Update to higan v091r14 and ananke v00r03 releases. byuu says: higan changelog: - generates title displayed in emulator window by asking the core - core builds title solely from "information/title" ... if it's not there, you don't get a title at all - sub-system load menu is gone ... since there are multiple revisions of the SGB, this never really worked well anyway - to load an SGB, BS-X or ST cartridge, load the base cartridge first - "File->Load Game" moved to "Load->Import Game" ... may cause a bit of confusion to new users, but I don't like having a single-item menu, we'll just have to explain it to new users - browser window redone to look like ananke - home button here goes to ~/Emulation rather than just ~ like ananke, since this is the home of game folders - game folder icon is now the executable icon for the Tango theme (orange diamond), meant to represent a complete game rather than a game file or archive ananke changelog: - outputs GBC games to "Game Boy Color/" instead of "Game Boy/" - adds the file basename to "information/title" Known issues: - using ananke to load a GB game trips the Super Famicom SGB mode and fails (need to make the full-path auto-detection ignore non-bootable systems) - need to dump and test some BS-X media before releasing - ananke lacks BS-X Satellaview cartridge support - v092 isn't going to let you retarget the ananke/higan game folder path of ~/Emulation, you will have to wait for a future version if that bothers you so greatly [Later, after the v092 release, byuu posted this additional changelog: - kill laevateinn - add title() - add bootable, remove load - combine file, library - combine [][][] paths - fix SFC subtype handling XML->BML - update file browser to use buttons - update file browser keyboard handling - update system XML->BML - fix sufami turbo hashing - remove Cartridge::manifest ]
2012-12-25 05:31:55 +00:00
}
template<typename T, typename... Args> string::string(T&& source, Args&&... args) {
_capacity = 0;
_size = 0;
sprint(*this, std::forward<T>(source), std::forward<Args>(args)...);
}
string::string() {
_capacity = 0;
_size = 0;
}
string::~string() {
}
}
#endif