2011-10-02 10:05:45 +00:00
|
|
|
#ifdef NALL_STRING_INTERNAL_HPP
|
2010-08-09 13:28:56 +00:00
|
|
|
|
2013-05-05 09:21:30 +00:00
|
|
|
//core functionality
|
|
|
|
//only this header file may access _data, _size, _capacity directly
|
|
|
|
//all other headers must use data(), size(), capacity()
|
|
|
|
|
2010-08-09 13:28:56 +00:00
|
|
|
namespace nall {
|
|
|
|
|
2013-05-05 09:21:30 +00:00
|
|
|
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();
|
|
|
|
}
|
2011-03-17 10:39:55 +00:00
|
|
|
}
|
|
|
|
|
2013-05-05 09:21:30 +00:00
|
|
|
void string::resize(unsigned size) {
|
|
|
|
reserve(size);
|
|
|
|
data()[_size = size] = 0;
|
2011-03-17 10:39:55 +00:00
|
|
|
}
|
|
|
|
|
2013-04-14 08:52:47 +00:00
|
|
|
void string::reset() {
|
2013-05-05 09:21:30 +00:00
|
|
|
_data.reset();
|
|
|
|
_capacity = 0;
|
|
|
|
_size = 0;
|
2013-01-21 12:27:15 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
void string::clear(char c) {
|
2013-05-05 09:21:30 +00:00
|
|
|
for(unsigned n = 0; n < size(); n++) data()[n] = c;
|
2011-12-12 10:59:53 +00:00
|
|
|
}
|
|
|
|
|
2011-03-17 10:39:55 +00:00
|
|
|
template<typename... Args> string& string::assign(Args&&... args) {
|
2013-05-05 09:21:30 +00:00
|
|
|
reset();
|
|
|
|
sprint(*this, std::forward<Args>(args)...);
|
2011-03-17 10:39:55 +00:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
|
|
|
template<typename... Args> string& string::append(Args&&... args) {
|
2013-05-05 09:21:30 +00:00
|
|
|
sprint(*this, std::forward<Args>(args)...);
|
2010-08-09 13:28:56 +00:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2013-05-05 09:21:30 +00:00
|
|
|
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);
|
2010-08-09 13:28:56 +00:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2013-03-15 13:11:33 +00:00
|
|
|
string::operator bool() const {
|
|
|
|
return !empty();
|
|
|
|
}
|
|
|
|
|
2010-08-09 13:28:56 +00:00
|
|
|
string::operator const char*() const {
|
2013-05-05 09:21:30 +00:00
|
|
|
return data();
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
|
2013-05-05 09:21:30 +00:00
|
|
|
char& string::operator[](unsigned position) {
|
|
|
|
if(position > size() + 1) throw exception_out_of_bounds{};
|
|
|
|
return data()[position];
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
|
2013-05-05 09:21:30 +00:00
|
|
|
const char& string::operator[](unsigned position) const {
|
|
|
|
if(position > size() + 1) throw exception_out_of_bounds{};
|
|
|
|
return data()[position];
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
|
2013-05-05 09:21:30 +00:00
|
|
|
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; }
|
2010-08-09 13:28:56 +00:00
|
|
|
|
2013-05-05 09:21:30 +00:00
|
|
|
string& string::operator=(const string& source) {
|
|
|
|
if(&source == this) return *this;
|
|
|
|
_data = source._data;
|
|
|
|
_capacity = source._capacity;
|
|
|
|
_size = source._size;
|
2010-08-09 13:28:56 +00:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2013-05-02 11:25:45 +00:00
|
|
|
string& string::operator=(string&& source) {
|
2011-09-09 04:16:25 +00:00
|
|
|
if(&source == this) return *this;
|
2013-05-05 09:21:30 +00:00
|
|
|
_data = std::move(source._data);
|
|
|
|
_capacity = source._capacity;
|
|
|
|
_size = source._size;
|
|
|
|
source._capacity = 0;
|
|
|
|
source._size = 0;
|
2010-08-09 13:28:56 +00:00
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2013-05-05 09:21:30 +00:00
|
|
|
string::string(const string& source) {
|
|
|
|
operator=(source);
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
|
2013-05-02 11:25:45 +00:00
|
|
|
string::string(string&& source) {
|
2013-05-05 09:21:30 +00:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2013-05-05 09:21:30 +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)...);
|
2011-09-19 12:34:18 +00:00
|
|
|
}
|
|
|
|
|
2013-05-05 09:21:30 +00:00
|
|
|
string::string() {
|
|
|
|
_capacity = 0;
|
|
|
|
_size = 0;
|
2012-06-18 10:13:51 +00:00
|
|
|
}
|
|
|
|
|
2013-05-05 09:21:30 +00:00
|
|
|
string::~string() {
|
2010-08-09 13:28:56 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|