mirror of https://github.com/bsnes-emu/bsnes.git
Update to v092r10 release.
byuu says: Changelog: - you can now drop game folders (not game files, sorry) onto higan's main window to load them - audio buffer will clear on Windows when entering modal loop (entering menu, moving or resizing window) - this prevents DirectSound driver's audio repetition - ruby defaults to the optimal driver for each platform, rather than the safest driver, now - added Cydrak's gl_Position.zw change to ruby - added fixes for all the changes to nall, ruby, phoenix over the past three months
This commit is contained in:
parent
29ea5bd599
commit
c74865e171
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
namespace Emulator {
|
namespace Emulator {
|
||||||
static const char Name[] = "higan";
|
static const char Name[] = "higan";
|
||||||
static const char Version[] = "092.09";
|
static const char Version[] = "092.10";
|
||||||
static const char Author[] = "byuu";
|
static const char Author[] = "byuu";
|
||||||
static const char License[] = "GPLv3";
|
static const char License[] = "GPLv3";
|
||||||
static const char Website[] = "http://byuu.org/";
|
static const char Website[] = "http://byuu.org/";
|
||||||
|
|
|
@ -28,7 +28,7 @@ bool Cheat::decode(string code_, unsigned& addr, unsigned& data, unsigned& comp)
|
||||||
code.upper();
|
code.upper();
|
||||||
unsigned length = code.length(), bits = 0;
|
unsigned length = code.length(), bits = 0;
|
||||||
|
|
||||||
if(code.wildcard("????:??")) {
|
if(code.match("????:??")) {
|
||||||
code = {substr(code, 0, 4), substr(code, 5, 2)};
|
code = {substr(code, 0, 4), substr(code, 5, 2)};
|
||||||
for(unsigned n = 0; n < 6; n++) if(mapProActionReplay[code[n]] > 15) return false;
|
for(unsigned n = 0; n < 6; n++) if(mapProActionReplay[code[n]] > 15) return false;
|
||||||
bits = hex(code);
|
bits = hex(code);
|
||||||
|
@ -38,7 +38,7 @@ bool Cheat::decode(string code_, unsigned& addr, unsigned& data, unsigned& comp)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(code.wildcard("????:??:??")) {
|
if(code.match("????:??:??")) {
|
||||||
code = {substr(code, 0, 4), substr(code, 5, 2), substr(code, 8, 2)};
|
code = {substr(code, 0, 4), substr(code, 5, 2), substr(code, 8, 2)};
|
||||||
for(unsigned n = 0; n < 8; n++) if(mapProActionReplay[code[n]] > 15) return false;
|
for(unsigned n = 0; n < 8; n++) if(mapProActionReplay[code[n]] > 15) return false;
|
||||||
bits = hex(code);
|
bits = hex(code);
|
||||||
|
|
|
@ -28,7 +28,7 @@ bool Cheat::decode(string code_, unsigned& addr, unsigned& data, unsigned& comp)
|
||||||
code.upper();
|
code.upper();
|
||||||
unsigned length = code.length(), bits = 0;
|
unsigned length = code.length(), bits = 0;
|
||||||
|
|
||||||
if(code.wildcard("????:??")) {
|
if(code.match("????:??")) {
|
||||||
code = {substr(code, 0, 4), substr(code, 5, 2)};
|
code = {substr(code, 0, 4), substr(code, 5, 2)};
|
||||||
for(unsigned n = 0; n < 6; n++) if(mapProActionReplay[code[n]] > 15) return false;
|
for(unsigned n = 0; n < 6; n++) if(mapProActionReplay[code[n]] > 15) return false;
|
||||||
bits = hex(code);
|
bits = hex(code);
|
||||||
|
@ -38,7 +38,7 @@ bool Cheat::decode(string code_, unsigned& addr, unsigned& data, unsigned& comp)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(code.wildcard("????:??:??")) {
|
if(code.match("????:??:??")) {
|
||||||
code = {substr(code, 0, 4), substr(code, 5, 2), substr(code, 8, 2)};
|
code = {substr(code, 0, 4), substr(code, 5, 2), substr(code, 8, 2)};
|
||||||
for(unsigned n = 0; n < 8; n++) if(mapProActionReplay[code[n]] > 15) return false;
|
for(unsigned n = 0; n < 8; n++) if(mapProActionReplay[code[n]] > 15) return false;
|
||||||
bits = hex(code);
|
bits = hex(code);
|
||||||
|
@ -48,7 +48,7 @@ bool Cheat::decode(string code_, unsigned& addr, unsigned& data, unsigned& comp)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(code.wildcard("???" "-" "???")) {
|
if(code.match("???" "-" "???")) {
|
||||||
code = {substr(code, 0, 3), substr(code, 4, 3)};
|
code = {substr(code, 0, 3), substr(code, 4, 3)};
|
||||||
for(unsigned n = 0; n < 6; n++) if(mapGameGenie[code[n]] > 15) return false;
|
for(unsigned n = 0; n < 6; n++) if(mapGameGenie[code[n]] > 15) return false;
|
||||||
for(unsigned n = 0; n < 6; n++) bits |= mapGameGenie[code[n]] << (20 - n * 4);
|
for(unsigned n = 0; n < 6; n++) bits |= mapGameGenie[code[n]] << (20 - n * 4);
|
||||||
|
@ -62,7 +62,7 @@ bool Cheat::decode(string code_, unsigned& addr, unsigned& data, unsigned& comp)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(code.wildcard("???" "-" "???" "-" "???")) {
|
if(code.match("???" "-" "???" "-" "???")) {
|
||||||
code = {substr(code, 0, 3), substr(code, 4, 3), substr(code, 8, 1), substr(code, 10, 1)};
|
code = {substr(code, 0, 3), substr(code, 4, 3), substr(code, 8, 1), substr(code, 10, 1)};
|
||||||
for(unsigned n = 0; n < 8; n++) if(mapGameGenie[code[n]] > 15) return false;
|
for(unsigned n = 0; n < 8; n++) if(mapGameGenie[code[n]] > 15) return false;
|
||||||
for(unsigned n = 0; n < 8; n++) bits |= mapGameGenie[code[n]] << (28 - n * 4);
|
for(unsigned n = 0; n < 8; n++) bits |= mapGameGenie[code[n]] << (28 - n * 4);
|
||||||
|
|
|
@ -8,7 +8,11 @@ namespace nall {
|
||||||
|
|
||||||
struct any {
|
struct any {
|
||||||
bool empty() const { return container; }
|
bool empty() const { return container; }
|
||||||
const std::type_info& type() const { return container ? container->type() : typeid(void); }
|
void reset() { if(container) { delete container; container = nullptr; } }
|
||||||
|
|
||||||
|
const std::type_info& type() const {
|
||||||
|
return container ? container->type() : typeid(void);
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T> any& operator=(const T& value) {
|
template<typename T> any& operator=(const T& value) {
|
||||||
typedef typename type_if<
|
typedef typename type_if<
|
||||||
|
@ -27,20 +31,37 @@ struct any {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
any& operator=(const any& source) {
|
||||||
|
if(container) { delete container; container = nullptr; }
|
||||||
|
if(source.container) container = source.container->copy();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
any& operator=(any&& source) {
|
||||||
|
if(container) delete container;
|
||||||
|
container = source.container;
|
||||||
|
source.container = nullptr;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
any() = default;
|
any() = default;
|
||||||
|
any(const any& source) { operator=(source); }
|
||||||
|
any(any&& source) { operator=(std::move(source)); }
|
||||||
template<typename T> any(const T& value) { operator=(value); }
|
template<typename T> any(const T& value) { operator=(value); }
|
||||||
~any() { if(container) delete container; }
|
~any() { reset(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct placeholder {
|
struct placeholder {
|
||||||
virtual const std::type_info& type() const = 0;
|
virtual const std::type_info& type() const = 0;
|
||||||
|
virtual placeholder* copy() const = 0;
|
||||||
|
virtual ~placeholder() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
placeholder* container = nullptr;
|
placeholder* container = nullptr;
|
||||||
|
|
||||||
template<typename T> struct holder : placeholder {
|
template<typename T> struct holder : placeholder {
|
||||||
T value;
|
T value;
|
||||||
const std::type_info& type() const { return typeid(T); }
|
const std::type_info& type() const { return typeid(T); }
|
||||||
|
placeholder* copy() const { return new holder(value); }
|
||||||
holder(const T& value) : value(value) {}
|
holder(const T& value) : value(value) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -48,6 +48,8 @@ constexpr inline uintmax_t binary(const char* s) {
|
||||||
|
|
||||||
constexpr inline uintmax_t octal(const char* s) {
|
constexpr inline uintmax_t octal(const char* s) {
|
||||||
return (
|
return (
|
||||||
|
*s == '0' && *(s + 1) == 'O' ? octal_(s + 2) :
|
||||||
|
*s == '0' && *(s + 1) == 'o' ? octal_(s + 2) :
|
||||||
octal_(s)
|
octal_(s)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -88,7 +90,7 @@ constexpr inline intmax_t numeral(const char* s) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline double fp(const char* s) {
|
inline double real(const char* s) {
|
||||||
return atof(s);
|
return atof(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,7 @@ struct beatArchive : beatBase {
|
||||||
while(fp.offset() < fp.size() - 4) {
|
while(fp.offset() < fp.size() - 4) {
|
||||||
unsigned data = readNumber();
|
unsigned data = readNumber();
|
||||||
string name = readString((data >> 1) + 1);
|
string name = readString((data >> 1) + 1);
|
||||||
if(name.position("\\") || name.position("../")) return false; //block path exploits
|
if(name.find("\\") || name.find("../")) return false; //block path exploits
|
||||||
|
|
||||||
if((data & 1) == 0) {
|
if((data & 1) == 0) {
|
||||||
directory::create({pathname, name});
|
directory::create({pathname, name});
|
||||||
|
|
|
@ -35,7 +35,7 @@ struct Node {
|
||||||
case Type::Bool: *(bool*)data = (value == "true"); break;
|
case Type::Bool: *(bool*)data = (value == "true"); break;
|
||||||
case Type::Signed: *(signed*)data = integer(value); break;
|
case Type::Signed: *(signed*)data = integer(value); break;
|
||||||
case Type::Unsigned: *(unsigned*)data = decimal(value); break;
|
case Type::Unsigned: *(unsigned*)data = decimal(value); break;
|
||||||
case Type::Double: *(double*)data = fp(value); break;
|
case Type::Double: *(double*)data = real(value); break;
|
||||||
case Type::String: *(string*)data = value; break;
|
case Type::String: *(string*)data = value; break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -112,14 +112,14 @@ private:
|
||||||
if(wcscmp(data.cFileName, L".") && wcscmp(data.cFileName, L"..")) {
|
if(wcscmp(data.cFileName, L".") && wcscmp(data.cFileName, L"..")) {
|
||||||
if(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
if(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
||||||
string name = (const char*)utf8_t(data.cFileName);
|
string name = (const char*)utf8_t(data.cFileName);
|
||||||
if(wildcard(name, pattern)) list.append(name);
|
if(name.match(pattern)) list.append(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
while(FindNextFile(handle, &data) != false) {
|
while(FindNextFile(handle, &data) != false) {
|
||||||
if(wcscmp(data.cFileName, L".") && wcscmp(data.cFileName, L"..")) {
|
if(wcscmp(data.cFileName, L".") && wcscmp(data.cFileName, L"..")) {
|
||||||
if(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
if(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
||||||
string name = (const char*)utf8_t(data.cFileName);
|
string name = (const char*)utf8_t(data.cFileName);
|
||||||
if(wildcard(name, pattern)) list.append(name);
|
if(name.match(pattern)) list.append(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -141,12 +141,12 @@ private:
|
||||||
if(handle != INVALID_HANDLE_VALUE) {
|
if(handle != INVALID_HANDLE_VALUE) {
|
||||||
if((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) {
|
if((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) {
|
||||||
string name = (const char*)utf8_t(data.cFileName);
|
string name = (const char*)utf8_t(data.cFileName);
|
||||||
if(wildcard(name, pattern)) list.append(name);
|
if(name.match(pattern)) list.append(name);
|
||||||
}
|
}
|
||||||
while(FindNextFile(handle, &data) != false) {
|
while(FindNextFile(handle, &data) != false) {
|
||||||
if((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) {
|
if((data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0) {
|
||||||
string name = (const char*)utf8_t(data.cFileName);
|
string name = (const char*)utf8_t(data.cFileName);
|
||||||
if(wildcard(name, pattern)) list.append(name);
|
if(name.match(pattern)) list.append(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FindClose(handle);
|
FindClose(handle);
|
||||||
|
@ -190,8 +190,14 @@ private:
|
||||||
while(ep = readdir(dp)) {
|
while(ep = readdir(dp)) {
|
||||||
if(!strcmp(ep->d_name, ".")) continue;
|
if(!strcmp(ep->d_name, ".")) continue;
|
||||||
if(!strcmp(ep->d_name, "..")) continue;
|
if(!strcmp(ep->d_name, "..")) continue;
|
||||||
if(ep->d_type & DT_DIR) {
|
bool is_directory = ep->d_type & DT_DIR;
|
||||||
if(wildcard(ep->d_name, pattern)) list.append(ep->d_name);
|
if(ep->d_type & DT_UNKNOWN) {
|
||||||
|
struct stat sp = {0};
|
||||||
|
stat(string{pathname, ep->d_name}, &sp);
|
||||||
|
is_directory = S_ISDIR(sp.st_mode);
|
||||||
|
}
|
||||||
|
if(is_directory) {
|
||||||
|
if(strmatch(ep->d_name, pattern)) list.append(ep->d_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
closedir(dp);
|
closedir(dp);
|
||||||
|
@ -210,7 +216,7 @@ private:
|
||||||
if(!strcmp(ep->d_name, ".")) continue;
|
if(!strcmp(ep->d_name, ".")) continue;
|
||||||
if(!strcmp(ep->d_name, "..")) continue;
|
if(!strcmp(ep->d_name, "..")) continue;
|
||||||
if((ep->d_type & DT_DIR) == 0) {
|
if((ep->d_type & DT_DIR) == 0) {
|
||||||
if(wildcard(ep->d_name, pattern)) list.append(ep->d_name);
|
if(strmatch(ep->d_name, pattern)) list.append(ep->d_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
closedir(dp);
|
closedir(dp);
|
||||||
|
|
|
@ -0,0 +1,137 @@
|
||||||
|
#ifndef NALL_HASHSET_HPP
|
||||||
|
#define NALL_HASHSET_HPP
|
||||||
|
|
||||||
|
//hashset
|
||||||
|
//
|
||||||
|
//search: O(1) average; O(n) worst
|
||||||
|
//insert: O(1) average; O(n) worst
|
||||||
|
//remove: O(1) average; O(n) worst
|
||||||
|
//
|
||||||
|
//requirements:
|
||||||
|
// unsigned T::hash() const;
|
||||||
|
// bool T::operator==(const T&) const;
|
||||||
|
|
||||||
|
namespace nall {
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct hashset {
|
||||||
|
protected:
|
||||||
|
T** pool = nullptr;
|
||||||
|
unsigned length = 8; //length of pool
|
||||||
|
unsigned count = 0; //number of objects inside of the pool
|
||||||
|
|
||||||
|
public:
|
||||||
|
hashset() {}
|
||||||
|
hashset(unsigned length) : length(bit::round(length)) {}
|
||||||
|
hashset(const hashset& source) { operator=(source); }
|
||||||
|
hashset(hashset&& source) { operator=(std::move(source)); }
|
||||||
|
~hashset() { reset(); }
|
||||||
|
|
||||||
|
hashset& operator=(const hashset& source) {
|
||||||
|
reset();
|
||||||
|
if(source.pool) {
|
||||||
|
for(unsigned n = 0; n < source.count; n++) {
|
||||||
|
insert(*source.pool[n]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
hashset& operator=(hashset&& source) {
|
||||||
|
reset();
|
||||||
|
pool = source.pool;
|
||||||
|
length = source.length;
|
||||||
|
count = source.count;
|
||||||
|
source.pool = nullptr;
|
||||||
|
source.length = 8;
|
||||||
|
source.count = 0;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned capacity() const { return length; }
|
||||||
|
unsigned size() const { return count; }
|
||||||
|
bool empty() const { return count == 0; }
|
||||||
|
|
||||||
|
void reset() {
|
||||||
|
if(pool) {
|
||||||
|
for(unsigned n = 0; n < length; n++) {
|
||||||
|
if(pool[n]) {
|
||||||
|
delete pool[n];
|
||||||
|
pool[n] = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete pool;
|
||||||
|
pool = nullptr;
|
||||||
|
}
|
||||||
|
length = 8;
|
||||||
|
count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reserve(unsigned size) {
|
||||||
|
//ensure all items will fit into pool (with <= 50% load) and amortize growth
|
||||||
|
size = bit::round(max(size, count << 1));
|
||||||
|
T** copy = new T*[size]();
|
||||||
|
|
||||||
|
if(pool) {
|
||||||
|
for(unsigned n = 0; n < length; n++) {
|
||||||
|
if(pool[n]) {
|
||||||
|
unsigned hash = (*pool[n]).hash() & (size - 1);
|
||||||
|
while(copy[hash]) if(++hash >= size) hash = 0;
|
||||||
|
copy[hash] = pool[n];
|
||||||
|
pool[n] = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
delete pool;
|
||||||
|
pool = copy;
|
||||||
|
length = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
optional<T&> find(const T& value) {
|
||||||
|
if(!pool) return false;
|
||||||
|
|
||||||
|
unsigned hash = value.hash() & (length - 1);
|
||||||
|
while(pool[hash]) {
|
||||||
|
if(value == *pool[hash]) return {true, *pool[hash]};
|
||||||
|
if(++hash >= length) hash = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
optional<T&> insert(const T& value) {
|
||||||
|
if(!pool) pool = new T*[length]();
|
||||||
|
|
||||||
|
//double pool size when load is >= 50%
|
||||||
|
if(count >= (length >> 1)) reserve(length << 1);
|
||||||
|
count++;
|
||||||
|
|
||||||
|
unsigned hash = value.hash() & (length - 1);
|
||||||
|
while(pool[hash]) if(++hash >= length) hash = 0;
|
||||||
|
pool[hash] = new T(value);
|
||||||
|
|
||||||
|
return {true, *pool[hash]};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool remove(const T& value) {
|
||||||
|
if(!pool) return false;
|
||||||
|
|
||||||
|
unsigned hash = value.hash() & (length - 1);
|
||||||
|
while(pool[hash]) {
|
||||||
|
if(value == *pool[hash]) {
|
||||||
|
delete pool[hash];
|
||||||
|
pool[hash] = nullptr;
|
||||||
|
count--;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if(++hash >= length) hash = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -100,7 +100,7 @@ struct http {
|
||||||
inline void downloadContent(uint8_t*& data, unsigned& size) {
|
inline void downloadContent(uint8_t*& data, unsigned& size) {
|
||||||
unsigned capacity = 0;
|
unsigned capacity = 0;
|
||||||
|
|
||||||
if(header.iposition("\r\nTransfer-Encoding: chunked\r\n")) {
|
if(header.ifind("\r\nTransfer-Encoding: chunked\r\n")) {
|
||||||
while(true) {
|
while(true) {
|
||||||
unsigned length = hex(downloadChunkLength());
|
unsigned length = hex(downloadChunkLength());
|
||||||
if(length == 0) break;
|
if(length == 0) break;
|
||||||
|
@ -116,7 +116,7 @@ struct http {
|
||||||
length -= packetlength;
|
length -= packetlength;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if(auto position = header.iposition("\r\nContent-Length: ")) {
|
} else if(auto position = header.ifind("\r\nContent-Length: ")) {
|
||||||
unsigned length = decimal((const char*)header + position() + 18);
|
unsigned length = decimal((const char*)header + position() + 18);
|
||||||
while(length) {
|
while(length) {
|
||||||
char buffer[256];
|
char buffer[256];
|
||||||
|
|
|
@ -22,7 +22,7 @@ namespace nall {
|
||||||
|
|
||||||
template<typename... Args> inline void invoke(const string& name, Args&&... args) {
|
template<typename... Args> inline void invoke(const string& name, Args&&... args) {
|
||||||
lstring argl(std::forward<Args>(args)...);
|
lstring argl(std::forward<Args>(args)...);
|
||||||
for(auto& arg : argl) if(arg.position(" ")) arg = {"\"", arg, "\""};
|
for(auto& arg : argl) if(arg.find(" ")) arg = {"\"", arg, "\""};
|
||||||
string arguments = argl.concatenate(" ");
|
string arguments = argl.concatenate(" ");
|
||||||
ShellExecuteW(NULL, NULL, utf16_t(name), utf16_t(arguments), NULL, SW_SHOWNORMAL);
|
ShellExecuteW(NULL, NULL, utf16_t(name), utf16_t(arguments), NULL, SW_SHOWNORMAL);
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,9 +47,8 @@ struct context {
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned eval(const string& expression) {
|
unsigned eval(const string& expression) {
|
||||||
intmax_t result;
|
if(auto result = Eval::integer(expression)) return result();
|
||||||
if(fixedpoint::eval(expression, result) == false) return 0u;
|
return 0u;
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void eval(vector<unsigned>& buffer, const string& expression_) {
|
void eval(vector<unsigned>& buffer, const string& expression_) {
|
||||||
|
@ -64,7 +63,7 @@ struct context {
|
||||||
lstring list = expression.split(",");
|
lstring list = expression.split(",");
|
||||||
for(auto& item : list) {
|
for(auto& item : list) {
|
||||||
item.trim();
|
item.trim();
|
||||||
if(item.wildcard("f(?*) ?*")) {
|
if(item.match("f(?*) ?*")) {
|
||||||
item.ltrim<1>("f(");
|
item.ltrim<1>("f(");
|
||||||
lstring part = item.split<1>(") ");
|
lstring part = item.split<1>(") ");
|
||||||
lstring args = part[0].split<3>(";");
|
lstring args = part[0].split<3>(";");
|
||||||
|
@ -85,10 +84,10 @@ struct context {
|
||||||
buffer[offset] = eval(fn);
|
buffer[offset] = eval(fn);
|
||||||
offset += stride;
|
offset += stride;
|
||||||
}
|
}
|
||||||
} else if(item.wildcard("base64*")) {
|
} else if(item.match("base64*")) {
|
||||||
unsigned offset = 0;
|
unsigned offset = 0;
|
||||||
item.ltrim<1>("base64");
|
item.ltrim<1>("base64");
|
||||||
if(item.wildcard("(?*) *")) {
|
if(item.match("(?*) *")) {
|
||||||
item.ltrim<1>("(");
|
item.ltrim<1>("(");
|
||||||
lstring part = item.split<1>(") ");
|
lstring part = item.split<1>(") ");
|
||||||
offset = eval(part[0]);
|
offset = eval(part[0]);
|
||||||
|
@ -102,7 +101,7 @@ struct context {
|
||||||
if(c == '-') buffer.append(offset + 62);
|
if(c == '-') buffer.append(offset + 62);
|
||||||
if(c == '_') buffer.append(offset + 63);
|
if(c == '_') buffer.append(offset + 63);
|
||||||
}
|
}
|
||||||
} else if(item.wildcard("file *")) {
|
} else if(item.match("file *")) {
|
||||||
item.ltrim<1>("file ");
|
item.ltrim<1>("file ");
|
||||||
item.trim();
|
item.trim();
|
||||||
//...
|
//...
|
||||||
|
@ -159,8 +158,8 @@ struct context {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool load(const string& filename) {
|
bool load(const string& filename) {
|
||||||
string filedata;
|
string filedata = string::read(filename);
|
||||||
if(filedata.readfile(filename) == false) return false;
|
if(filedata.empty()) return false;
|
||||||
parse(filedata);
|
parse(filedata);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include <nall/function.hpp>
|
#include <nall/function.hpp>
|
||||||
#include <nall/group.hpp>
|
#include <nall/group.hpp>
|
||||||
#include <nall/gzip.hpp>
|
#include <nall/gzip.hpp>
|
||||||
|
#include <nall/hashset.hpp>
|
||||||
#include <nall/http.hpp>
|
#include <nall/http.hpp>
|
||||||
#include <nall/image.hpp>
|
#include <nall/image.hpp>
|
||||||
#include <nall/inflate.hpp>
|
#include <nall/inflate.hpp>
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
//=========================
|
//=========================
|
||||||
|
|
||||||
#include <limits>
|
#include <limits>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
//
|
//
|
||||||
//caveats:
|
//caveats:
|
||||||
//- only plain-old-data can be stored. complex classes must provide serialize(serializer&);
|
//- only plain-old-data can be stored. complex classes must provide serialize(serializer&);
|
||||||
//- floating-point usage is not portable across platforms
|
//- floating-point usage is not portable across different implementations
|
||||||
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
@ -19,122 +19,130 @@
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
|
|
||||||
|
struct serializer;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
struct has_serialize {
|
||||||
|
template<typename C> static char test(decltype(std::declval<C>().serialize(std::declval<serializer&>()))*);
|
||||||
|
template<typename C> static long test(...);
|
||||||
|
static const bool value = sizeof(test<T>(0)) == sizeof(char);
|
||||||
|
};
|
||||||
|
|
||||||
struct serializer {
|
struct serializer {
|
||||||
enum mode_t { Load, Save, Size };
|
enum mode_t { Load, Save, Size };
|
||||||
|
|
||||||
mode_t mode() const {
|
mode_t mode() const {
|
||||||
return imode;
|
return _mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
const uint8_t* data() const {
|
const uint8_t* data() const {
|
||||||
return idata;
|
return _data;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned size() const {
|
unsigned size() const {
|
||||||
return isize;
|
return _size;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned capacity() const {
|
unsigned capacity() const {
|
||||||
return icapacity;
|
return _capacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> void floatingpoint(T& value) {
|
template<typename T> serializer& floatingpoint(T& value) {
|
||||||
enum { size = sizeof(T) };
|
enum { size = sizeof(T) };
|
||||||
//this is rather dangerous, and not cross-platform safe;
|
//this is rather dangerous, and not cross-platform safe;
|
||||||
//but there is no standardized way to export FP-values
|
//but there is no standardized way to export FP-values
|
||||||
uint8_t* p = (uint8_t*)&value;
|
uint8_t* p = (uint8_t*)&value;
|
||||||
if(imode == Save) {
|
if(_mode == Save) {
|
||||||
for(unsigned n = 0; n < size; n++) idata[isize++] = p[n];
|
for(unsigned n = 0; n < size; n++) _data[_size++] = p[n];
|
||||||
} else if(imode == Load) {
|
} else if(_mode == Load) {
|
||||||
for(unsigned n = 0; n < size; n++) p[n] = idata[isize++];
|
for(unsigned n = 0; n < size; n++) p[n] = _data[_size++];
|
||||||
} else {
|
} else {
|
||||||
isize += size;
|
_size += size;
|
||||||
}
|
}
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> void integer(T& value) {
|
template<typename T> serializer& integer(T& value) {
|
||||||
enum { size = std::is_same<bool, T>::value ? 1 : sizeof(T) };
|
enum { size = std::is_same<bool, T>::value ? 1 : sizeof(T) };
|
||||||
if(imode == Save) {
|
if(_mode == Save) {
|
||||||
for(unsigned n = 0; n < size; n++) idata[isize++] = (uintmax_t)value >> (n << 3);
|
for(unsigned n = 0; n < size; n++) _data[_size++] = (uintmax_t)value >> (n << 3);
|
||||||
} else if(imode == Load) {
|
} else if(_mode == Load) {
|
||||||
value = 0;
|
value = 0;
|
||||||
for(unsigned n = 0; n < size; n++) value |= (uintmax_t)idata[isize++] << (n << 3);
|
for(unsigned n = 0; n < size; n++) value |= (uintmax_t)_data[_size++] << (n << 3);
|
||||||
} else if(imode == Size) {
|
} else if(_mode == Size) {
|
||||||
isize += size;
|
_size += size;
|
||||||
}
|
}
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> void array(T& array) {
|
template<typename T, int N> serializer& array(T (&array)[N]) {
|
||||||
enum { size = sizeof(T) / sizeof(typename std::remove_extent<T>::type) };
|
for(unsigned n = 0; n < N; n++) operator()(array[n]);
|
||||||
for(unsigned n = 0; n < size; n++) integer(array[n]);
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> void array(T array, unsigned size) {
|
template<typename T> serializer& array(T array, unsigned size) {
|
||||||
for(unsigned n = 0; n < size; n++) integer(array[n]);
|
for(unsigned n = 0; n < size; n++) operator()(array[n]);
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
//copy
|
template<typename T> serializer& operator()(T& value, typename std::enable_if<has_serialize<T>::value>::type* = 0) { value.serialize(*this); return *this; }
|
||||||
|
template<typename T> serializer& operator()(T& value, typename std::enable_if<std::is_integral<T>::value>::type* = 0) { return integer(value); }
|
||||||
|
template<typename T> serializer& operator()(T& value, typename std::enable_if<std::is_floating_point<T>::value>::type* = 0) { return floatingpoint(value); }
|
||||||
|
template<typename T> serializer& operator()(T& value, typename std::enable_if<std::is_array<T>::value>::type* = 0) { return array(value); }
|
||||||
|
template<typename T> serializer& operator()(T& value, unsigned size, typename std::enable_if<std::is_pointer<T>::value>::type* = 0) { return array(value, size); }
|
||||||
|
|
||||||
serializer& operator=(const serializer& s) {
|
serializer& operator=(const serializer& s) {
|
||||||
if(idata) delete[] idata;
|
if(_data) delete[] _data;
|
||||||
|
|
||||||
imode = s.imode;
|
_mode = s._mode;
|
||||||
idata = new uint8_t[s.icapacity];
|
_data = new uint8_t[s._capacity];
|
||||||
isize = s.isize;
|
_size = s._size;
|
||||||
icapacity = s.icapacity;
|
_capacity = s._capacity;
|
||||||
|
|
||||||
memcpy(idata, s.idata, s.icapacity);
|
memcpy(_data, s._data, s._capacity);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
serializer(const serializer& s) {
|
|
||||||
operator=(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
//move
|
|
||||||
serializer& operator=(serializer&& s) {
|
serializer& operator=(serializer&& s) {
|
||||||
if(idata) delete[] idata;
|
if(_data) delete[] _data;
|
||||||
|
|
||||||
imode = s.imode;
|
_mode = s._mode;
|
||||||
idata = s.idata;
|
_data = s._data;
|
||||||
isize = s.isize;
|
_size = s._size;
|
||||||
icapacity = s.icapacity;
|
_capacity = s._capacity;
|
||||||
|
|
||||||
s.idata = nullptr;
|
s._data = nullptr;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
serializer(serializer&& s) {
|
|
||||||
operator=(std::move(s));
|
|
||||||
}
|
|
||||||
|
|
||||||
//construction
|
|
||||||
serializer() = default;
|
serializer() = default;
|
||||||
|
serializer(const serializer& s) { operator=(s); }
|
||||||
|
serializer(serializer&& s) { operator=(std::move(s)); }
|
||||||
|
|
||||||
serializer(unsigned capacity) {
|
serializer(unsigned capacity) {
|
||||||
imode = Save;
|
_mode = Save;
|
||||||
idata = new uint8_t[capacity]();
|
_data = new uint8_t[capacity]();
|
||||||
isize = 0;
|
_size = 0;
|
||||||
icapacity = capacity;
|
_capacity = capacity;
|
||||||
}
|
}
|
||||||
|
|
||||||
serializer(const uint8_t* data, unsigned capacity) {
|
serializer(const uint8_t* data, unsigned capacity) {
|
||||||
imode = Load;
|
_mode = Load;
|
||||||
idata = new uint8_t[capacity];
|
_data = new uint8_t[capacity];
|
||||||
isize = 0;
|
_size = 0;
|
||||||
icapacity = capacity;
|
_capacity = capacity;
|
||||||
memcpy(idata, data, capacity);
|
memcpy(_data, data, capacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
//destruction
|
|
||||||
~serializer() {
|
~serializer() {
|
||||||
if(idata) delete[] idata;
|
if(_data) delete[] _data;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
mode_t imode = Size;
|
mode_t _mode = Size;
|
||||||
uint8_t* idata = nullptr;
|
uint8_t* _data = nullptr;
|
||||||
unsigned isize = 0;
|
unsigned _size = 0;
|
||||||
unsigned icapacity = 0;
|
unsigned _capacity = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,9 +3,14 @@
|
||||||
|
|
||||||
//set
|
//set
|
||||||
//implementation: red-black tree
|
//implementation: red-black tree
|
||||||
|
//
|
||||||
//search: O(log n) average; O(log n) worst
|
//search: O(log n) average; O(log n) worst
|
||||||
//insert: O(log n) average; O(log n) worst
|
//insert: O(log n) average; O(log n) worst
|
||||||
//remove: O(log n) average; O(log n) worst
|
//remove: O(log n) average; O(log n) worst
|
||||||
|
//
|
||||||
|
//requirements:
|
||||||
|
// bool T::operator==(const T&) const;
|
||||||
|
// bool T::operator< (const T&) const;
|
||||||
|
|
||||||
#include <nall/utility.hpp>
|
#include <nall/utility.hpp>
|
||||||
#include <nall/vector.hpp>
|
#include <nall/vector.hpp>
|
||||||
|
@ -50,16 +55,18 @@ template<typename T> struct set {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool insert(const T& value) {
|
optional<T&> insert(const T& value) {
|
||||||
unsigned count = size();
|
unsigned count = size();
|
||||||
insert(root, value);
|
node_t* v = insert(root, value);
|
||||||
root->red = 0;
|
root->red = 0;
|
||||||
return size() > count;
|
if(size() == count) return false;
|
||||||
|
return {true, v->value};
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename... Args> bool insert(const T& value, Args&&... args) {
|
template<typename... Args> bool insert(const T& value, Args&&... args) {
|
||||||
bool result = insert(value);
|
bool result = insert(value);
|
||||||
return insert(std::forward<Args>(args)...) | result;
|
insert(std::forward<Args>(args)...) | result;
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool remove(const T& value) {
|
bool remove(const T& value) {
|
||||||
|
@ -175,13 +182,13 @@ private:
|
||||||
rotate(node, dir);
|
rotate(node, dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
void insert(node_t*& node, const T& value) {
|
node_t* insert(node_t*& node, const T& value) {
|
||||||
if(!node) { nodes++; node = new node_t(value); return; }
|
if(!node) { nodes++; node = new node_t(value); return node; }
|
||||||
if(node->value == value) { node->value = value; return; } //prevent duplicate entries
|
if(node->value == value) { node->value = value; return node; } //prevent duplicate entries
|
||||||
|
|
||||||
bool dir = node->value < value;
|
bool dir = node->value < value;
|
||||||
insert(node->link[dir], value);
|
node_t* v = insert(node->link[dir], value);
|
||||||
if(black(node->link[dir])) return;
|
if(black(node->link[dir])) return v;
|
||||||
|
|
||||||
if(red(node->link[!dir])) {
|
if(red(node->link[!dir])) {
|
||||||
node->red = 1;
|
node->red = 1;
|
||||||
|
@ -192,6 +199,8 @@ private:
|
||||||
} else if(red(node->link[dir]->link[!dir])) {
|
} else if(red(node->link[dir]->link[!dir])) {
|
||||||
rotateTwice(node, !dir);
|
rotateTwice(node, !dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
void balance(node_t*& node, bool dir, bool& done) {
|
void balance(node_t*& node, bool dir, bool& done) {
|
||||||
|
|
|
@ -19,7 +19,7 @@ struct zipstream : memorystream {
|
||||||
delete[] data;
|
delete[] data;
|
||||||
|
|
||||||
for(auto& file : archive.file) {
|
for(auto& file : archive.file) {
|
||||||
if(file.name.wildcard(filter)) {
|
if(file.name.match(filter)) {
|
||||||
auto buffer = archive.extract(file);
|
auto buffer = archive.extract(file);
|
||||||
psize = buffer.size();
|
psize = buffer.size();
|
||||||
pdata = buffer.move();
|
pdata = buffer.move();
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
|
|
||||||
#include <nall/platform.hpp>
|
#include <nall/platform.hpp>
|
||||||
#include <nall/atoi.hpp>
|
#include <nall/atoi.hpp>
|
||||||
|
#include <nall/crc32.hpp>
|
||||||
#include <nall/function.hpp>
|
#include <nall/function.hpp>
|
||||||
#include <nall/intrinsics.hpp>
|
#include <nall/intrinsics.hpp>
|
||||||
#include <nall/sha256.hpp>
|
#include <nall/sha256.hpp>
|
||||||
|
@ -39,6 +40,10 @@
|
||||||
#include <nall/string/utility.hpp>
|
#include <nall/string/utility.hpp>
|
||||||
#include <nall/string/variadic.hpp>
|
#include <nall/string/variadic.hpp>
|
||||||
#include <nall/string/wrapper.hpp>
|
#include <nall/string/wrapper.hpp>
|
||||||
|
#include <nall/string/eval/node.hpp>
|
||||||
|
#include <nall/string/eval/literal.hpp>
|
||||||
|
#include <nall/string/eval/parser.hpp>
|
||||||
|
#include <nall/string/eval/evaluator.hpp>
|
||||||
#include <nall/string/markup/node.hpp>
|
#include <nall/string/markup/node.hpp>
|
||||||
#include <nall/string/markup/bml.hpp>
|
#include <nall/string/markup/bml.hpp>
|
||||||
#include <nall/string/markup/xml.hpp>
|
#include <nall/string/markup/xml.hpp>
|
||||||
|
|
|
@ -0,0 +1,98 @@
|
||||||
|
#ifdef NALL_STRING_INTERNAL_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
copy on write (COW) allocator
|
||||||
|
sizeof(string) == 24 (amd64)
|
||||||
|
|
||||||
|
utilizes a shared_ptr to reference count strings
|
||||||
|
allows string copies to execute as fast as string moves
|
||||||
|
requires extra computations, which will be slower for all string sizes
|
||||||
|
|
||||||
|
pros:
|
||||||
|
* lower memory usage
|
||||||
|
* pass-by-value does not require heap allocation; obviates pass-by-const-reference
|
||||||
|
|
||||||
|
cons:
|
||||||
|
* added overhead to fetch data()
|
||||||
|
* added heap allocation for reference-count pool
|
||||||
|
* no potential for in-place resize (always copies)
|
||||||
|
* larger sizeof(string)
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace nall {
|
||||||
|
|
||||||
|
char* string::data() {
|
||||||
|
if(!_data.unique()) _copy();
|
||||||
|
return _data.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* string::data() const {
|
||||||
|
if(!_data) return "";
|
||||||
|
return _data.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
//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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
|
@ -0,0 +1,107 @@
|
||||||
|
#ifdef NALL_STRING_INTERNAL_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
small string optimization (SSO) allocator
|
||||||
|
sizeof(string) == 16 (amd64)
|
||||||
|
|
||||||
|
utilizes a union to store small strings directly into text pointer
|
||||||
|
bypasses the need to allocate heap memory for small strings
|
||||||
|
requires extra computations, which can be slower for large strings
|
||||||
|
|
||||||
|
pros:
|
||||||
|
* potential for in-place resize
|
||||||
|
* no heap allocation when (capacity < 8)
|
||||||
|
|
||||||
|
cons:
|
||||||
|
* added overhead to fetch data()
|
||||||
|
* 32-bit platforms limited to (capacity < 4)
|
||||||
|
* pass-by-value requires heap allocation
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace nall {
|
||||||
|
|
||||||
|
char* string::data() {
|
||||||
|
if(_capacity < SSO) return _text;
|
||||||
|
return _data;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* string::data() const {
|
||||||
|
if(_capacity < SSO) return _text;
|
||||||
|
return _data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void string::reserve(unsigned capacity) {
|
||||||
|
if(capacity > _capacity) {
|
||||||
|
if(capacity >= SSO) {
|
||||||
|
capacity = bit::round(capacity + 1) - 1;
|
||||||
|
if(_capacity < SSO) {
|
||||||
|
char temp[SSO];
|
||||||
|
memcpy(temp, _text, SSO);
|
||||||
|
_data = (char*)malloc(capacity + 1);
|
||||||
|
memcpy(_data, temp, SSO);
|
||||||
|
} else {
|
||||||
|
_data = (char*)realloc(_data, capacity + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_capacity = capacity;
|
||||||
|
data()[_capacity] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void string::resize(unsigned size) {
|
||||||
|
reserve(size);
|
||||||
|
data()[_size = size] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void string::reset() {
|
||||||
|
if(_capacity >= SSO) free(_data);
|
||||||
|
_data = nullptr;
|
||||||
|
_capacity = SSO - 1;
|
||||||
|
_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
string& string::operator=(const string& source) {
|
||||||
|
if(&source == this) return *this;
|
||||||
|
if(source._capacity >= SSO) {
|
||||||
|
_data = (char*)malloc(source._capacity + 1);
|
||||||
|
_capacity = source._capacity;
|
||||||
|
_size = source._size;
|
||||||
|
memcpy(_data, source.data(), source.size() + 1);
|
||||||
|
} else {
|
||||||
|
memcpy(_text, source._text, SSO);
|
||||||
|
_capacity = SSO - 1;
|
||||||
|
_size = strlen(_text);
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
string& string::operator=(string&& source) {
|
||||||
|
if(&source == this) return *this;
|
||||||
|
memcpy(this, &source, sizeof(string));
|
||||||
|
source._data = nullptr;
|
||||||
|
source._capacity = SSO - 1;
|
||||||
|
source._size = 0;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename... Args> string::string(T&& source, Args&&... args) {
|
||||||
|
_data = nullptr;
|
||||||
|
_capacity = SSO - 1;
|
||||||
|
_size = 0;
|
||||||
|
sprint(*this, std::forward<T>(source), std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
string::string() {
|
||||||
|
_data = nullptr;
|
||||||
|
_capacity = SSO - 1;
|
||||||
|
_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
string::~string() {
|
||||||
|
if(_capacity >= SSO) free(_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,90 @@
|
||||||
|
#ifdef NALL_STRING_INTERNAL_HPP
|
||||||
|
|
||||||
|
/*
|
||||||
|
vector allocator
|
||||||
|
sizeof(string) == 16 (amd64)
|
||||||
|
|
||||||
|
utilizes a raw string pointer
|
||||||
|
always allocates memory onto the heap when string is not empty
|
||||||
|
|
||||||
|
pros:
|
||||||
|
* potential for in-place resize
|
||||||
|
* simplicity
|
||||||
|
|
||||||
|
cons:
|
||||||
|
* always allocates heap memory on (capacity > 0)
|
||||||
|
* pass-by-value requires heap allocation
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace nall {
|
||||||
|
|
||||||
|
char* string::data() {
|
||||||
|
if(_capacity == 0) reserve(1);
|
||||||
|
return _data;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* string::data() const {
|
||||||
|
if(_capacity == 0) return "";
|
||||||
|
return _data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void string::reserve(unsigned capacity) {
|
||||||
|
if(capacity > _capacity) {
|
||||||
|
_capacity = bit::round(capacity + 1) - 1;
|
||||||
|
_data = (char*)realloc(_data, _capacity + 1);
|
||||||
|
_data[_capacity] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void string::resize(unsigned size) {
|
||||||
|
reserve(size);
|
||||||
|
data()[_size = size] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void string::reset() {
|
||||||
|
if(_data) { free(_data); _data = nullptr; }
|
||||||
|
_capacity = 0;
|
||||||
|
_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
string& string::operator=(const string& source) {
|
||||||
|
if(&source == this) return *this;
|
||||||
|
_data = (char*)malloc(source._size + 1);
|
||||||
|
_capacity = source._size;
|
||||||
|
_size = source._size;
|
||||||
|
memcpy(_data, source.data(), source.size() + 1);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
string& string::operator=(string&& source) {
|
||||||
|
if(&source == this) return *this;
|
||||||
|
_data = source._data;
|
||||||
|
_capacity = source._capacity;
|
||||||
|
_size = source._size;
|
||||||
|
source._data = nullptr;
|
||||||
|
source._capacity = 0;
|
||||||
|
source._size = 0;
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T, typename... Args> string::string(T&& source, Args&&... args) {
|
||||||
|
_data = nullptr;
|
||||||
|
_capacity = 0;
|
||||||
|
_size = 0;
|
||||||
|
sprint(*this, std::forward<T>(source), std::forward<Args>(args)...);
|
||||||
|
}
|
||||||
|
|
||||||
|
string::string() {
|
||||||
|
_data = nullptr;
|
||||||
|
_capacity = 0;
|
||||||
|
_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
string::~string() {
|
||||||
|
if(_data) free(_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -7,9 +7,29 @@ struct stringref;
|
||||||
struct lstring;
|
struct lstring;
|
||||||
typedef const stringref& rstring;
|
typedef const stringref& rstring;
|
||||||
|
|
||||||
|
//#define NALL_STRING_ALLOCATOR_COPY_ON_WRITE
|
||||||
|
#define NALL_STRING_ALLOCATOR_SMALL_STRING_OPTIMIZATION
|
||||||
|
//#define NALL_STRING_ALLOCATOR_VECTOR
|
||||||
|
|
||||||
struct string {
|
struct string {
|
||||||
protected:
|
protected:
|
||||||
|
#if defined(NALL_STRING_ALLOCATOR_COPY_ON_WRITE)
|
||||||
|
inline void _copy();
|
||||||
std::shared_ptr<char> _data;
|
std::shared_ptr<char> _data;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(NALL_STRING_ALLOCATOR_SMALL_STRING_OPTIMIZATION)
|
||||||
|
enum : unsigned { SSO = 24 };
|
||||||
|
union {
|
||||||
|
char* _data;
|
||||||
|
char _text[SSO];
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(NALL_STRING_ALLOCATOR_VECTOR)
|
||||||
|
char* _data;
|
||||||
|
#endif
|
||||||
|
|
||||||
unsigned _capacity;
|
unsigned _capacity;
|
||||||
unsigned _size;
|
unsigned _size;
|
||||||
|
|
||||||
|
@ -27,12 +47,13 @@ public:
|
||||||
inline void resize(unsigned);
|
inline void resize(unsigned);
|
||||||
inline void clear(char);
|
inline void clear(char);
|
||||||
|
|
||||||
|
inline unsigned hash() const;
|
||||||
|
|
||||||
template<typename... Args> inline string& assign(Args&&... args);
|
template<typename... Args> inline string& assign(Args&&... args);
|
||||||
template<typename... Args> inline string& append(Args&&... args);
|
template<typename... Args> inline string& append(Args&&... args);
|
||||||
|
|
||||||
//file.hpp
|
//file.hpp
|
||||||
inline static string read(rstring filename);
|
inline static string read(const string& filename);
|
||||||
inline bool readfile(rstring);
|
|
||||||
|
|
||||||
//datetime.hpp
|
//datetime.hpp
|
||||||
inline static string date();
|
inline static string date();
|
||||||
|
@ -51,17 +72,22 @@ public:
|
||||||
template<unsigned Limit = 0> inline lstring qsplit(rstring) const;
|
template<unsigned Limit = 0> inline lstring qsplit(rstring) const;
|
||||||
template<unsigned Limit = 0> inline lstring iqsplit(rstring) const;
|
template<unsigned Limit = 0> inline lstring iqsplit(rstring) const;
|
||||||
|
|
||||||
|
inline signed compare(rstring) const;
|
||||||
|
inline signed icompare(rstring) const;
|
||||||
|
|
||||||
inline bool equals(rstring) const;
|
inline bool equals(rstring) const;
|
||||||
inline bool iequals(rstring) const;
|
inline bool iequals(rstring) const;
|
||||||
|
|
||||||
inline bool wildcard(rstring) const;
|
inline bool match(rstring) const;
|
||||||
inline bool iwildcard(rstring) const;
|
inline bool imatch(rstring) const;
|
||||||
|
|
||||||
inline bool beginswith(rstring) const;
|
inline bool beginswith(rstring) const;
|
||||||
inline bool ibeginswith(rstring) const;
|
inline bool ibeginswith(rstring) const;
|
||||||
inline bool endswith(rstring) const;
|
inline bool endswith(rstring) const;
|
||||||
inline bool iendswith(rstring) const;
|
inline bool iendswith(rstring) const;
|
||||||
|
|
||||||
|
inline string slice(unsigned offset, unsigned length = ~0u) const;
|
||||||
|
|
||||||
inline string& lower();
|
inline string& lower();
|
||||||
inline string& upper();
|
inline string& upper();
|
||||||
inline string& qlower();
|
inline string& qlower();
|
||||||
|
@ -69,21 +95,28 @@ public:
|
||||||
inline string& transform(rstring before, rstring after);
|
inline string& transform(rstring before, rstring after);
|
||||||
inline string& reverse();
|
inline string& reverse();
|
||||||
|
|
||||||
template<unsigned limit = 0> inline string& ltrim(rstring key = " ");
|
template<unsigned limit = 0> inline string& ltrim() { return ltrim<limit>(" "); }
|
||||||
template<unsigned limit = 0> inline string& rtrim(rstring key = " ");
|
template<unsigned limit = 0> inline string& ltrim(rstring key);
|
||||||
template<unsigned limit = 0> inline string& trim(rstring key = " ", rstring rkey = "");
|
|
||||||
|
template<unsigned limit = 0> inline string& rtrim() { return rtrim<limit>(" "); }
|
||||||
|
template<unsigned limit = 0> inline string& rtrim(rstring key);
|
||||||
|
|
||||||
|
template<unsigned limit = 0> inline string& trim() { return trim<limit>(" "); }
|
||||||
|
template<unsigned limit = 0> inline string& trim(rstring key);
|
||||||
|
template<unsigned limit = 0> inline string& trim(rstring key, rstring rkey);
|
||||||
|
|
||||||
inline string& strip();
|
inline string& strip();
|
||||||
|
|
||||||
inline optional<unsigned> position(rstring key) const;
|
inline optional<unsigned> find(rstring key) const;
|
||||||
inline optional<unsigned> iposition(rstring key) const;
|
inline optional<unsigned> ifind(rstring key) const;
|
||||||
inline optional<unsigned> qposition(rstring key) const;
|
inline optional<unsigned> qfind(rstring key) const;
|
||||||
inline optional<unsigned> iqposition(rstring key) const;
|
inline optional<unsigned> iqfind(rstring key) const;
|
||||||
|
|
||||||
//core.hpp
|
//core.hpp
|
||||||
inline explicit operator bool() const;
|
inline explicit operator bool() const;
|
||||||
inline operator const char*() const;
|
inline operator const char*() const;
|
||||||
inline char& operator[](unsigned);
|
inline char& operator[](signed);
|
||||||
inline const char& operator[](unsigned) const;
|
inline const char& operator[](signed) const;
|
||||||
|
|
||||||
inline bool operator==(const char*) const;
|
inline bool operator==(const char*) const;
|
||||||
inline bool operator!=(const char*) const;
|
inline bool operator!=(const char*) const;
|
||||||
|
@ -109,8 +142,6 @@ public:
|
||||||
//protected:
|
//protected:
|
||||||
struct exception_out_of_bounds{};
|
struct exception_out_of_bounds{};
|
||||||
template<unsigned Limit, bool Insensitive, bool Quoted> inline string& ureplace(rstring, rstring);
|
template<unsigned Limit, bool Insensitive, bool Quoted> inline string& ureplace(rstring, rstring);
|
||||||
inline void _unique();
|
|
||||||
inline void _copy();
|
|
||||||
inline string& _append(const char*);
|
inline string& _append(const char*);
|
||||||
|
|
||||||
#if defined(QSTRING_H)
|
#if defined(QSTRING_H)
|
||||||
|
@ -179,8 +210,8 @@ inline bool tokenize(lstring& list, const char* s, const char* p);
|
||||||
inline char* integer(char* result, intmax_t value);
|
inline char* integer(char* result, intmax_t value);
|
||||||
inline char* decimal(char* result, uintmax_t value);
|
inline char* decimal(char* result, uintmax_t value);
|
||||||
|
|
||||||
inline unsigned fp(char* str, long double value);
|
inline unsigned real(char* str, long double value);
|
||||||
inline string fp(long double value);
|
inline string real(long double value);
|
||||||
|
|
||||||
//variadic.hpp
|
//variadic.hpp
|
||||||
inline void sprint(string& output);
|
inline void sprint(string& output);
|
||||||
|
|
|
@ -101,19 +101,19 @@ template<unsigned bits> struct stringify<uint_t<bits>> {
|
||||||
template<> struct stringify<float> {
|
template<> struct stringify<float> {
|
||||||
char data[256];
|
char data[256];
|
||||||
operator const char*() const { return data; }
|
operator const char*() const { return data; }
|
||||||
stringify(float value) { fp(data, value); }
|
stringify(float value) { real(data, value); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template<> struct stringify<double> {
|
template<> struct stringify<double> {
|
||||||
char data[256];
|
char data[256];
|
||||||
operator const char*() const { return data; }
|
operator const char*() const { return data; }
|
||||||
stringify(double value) { fp(data, value); }
|
stringify(double value) { real(data, value); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template<> struct stringify<long double> {
|
template<> struct stringify<long double> {
|
||||||
char data[256];
|
char data[256];
|
||||||
operator const char*() const { return data; }
|
operator const char*() const { return data; }
|
||||||
stringify(long double value) { fp(data, value); }
|
stringify(long double value) { real(data, value); }
|
||||||
};
|
};
|
||||||
|
|
||||||
// arrays
|
// arrays
|
||||||
|
|
|
@ -3,13 +3,11 @@
|
||||||
#include <nall/string/char/base.hpp>
|
#include <nall/string/char/base.hpp>
|
||||||
#include <nall/string/char/compare.hpp>
|
#include <nall/string/char/compare.hpp>
|
||||||
#include <nall/string/char/convert.hpp>
|
#include <nall/string/char/convert.hpp>
|
||||||
#include <nall/string/char/math-fixed-point.hpp>
|
#include <nall/string/char/match.hpp>
|
||||||
#include <nall/string/char/math-floating-point.hpp>
|
|
||||||
#include <nall/string/char/strm.hpp>
|
#include <nall/string/char/strm.hpp>
|
||||||
#include <nall/string/char/strpos.hpp>
|
#include <nall/string/char/strpos.hpp>
|
||||||
#include <nall/string/char/trim.hpp>
|
#include <nall/string/char/trim.hpp>
|
||||||
#include <nall/string/char/utf8.hpp>
|
#include <nall/string/char/utf8.hpp>
|
||||||
#include <nall/string/char/utility.hpp>
|
#include <nall/string/char/utility.hpp>
|
||||||
#include <nall/string/char/wildcard.hpp>
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -23,21 +23,10 @@ inline char* qstrlower(char* str);
|
||||||
inline char* qstrupper(char* str);
|
inline char* qstrupper(char* str);
|
||||||
inline char* strtr(char* dest, const char* before, const char* after);
|
inline char* strtr(char* dest, const char* before, const char* after);
|
||||||
|
|
||||||
//math-fixed-point.hpp
|
//match.hpp
|
||||||
namespace fixedpoint {
|
inline bool strmatch(const char* str, const char* pattern);
|
||||||
inline intmax_t eval_integer(const char*& s);
|
inline bool istrmatch(const char* str, const char* pattern);
|
||||||
inline intmax_t eval(const char*& s, int depth = 0);
|
inline bool tokenize(const char* s, const char* p);
|
||||||
inline bool eval(const char* s, intmax_t& result);
|
|
||||||
inline intmax_t parse(const char* s);
|
|
||||||
}
|
|
||||||
|
|
||||||
//math-floating-point.hpp
|
|
||||||
namespace floatingpoint {
|
|
||||||
inline double eval_integer(const char*& s);
|
|
||||||
inline double eval(const char*& s, int depth = 0);
|
|
||||||
inline bool eval(const char* s, double& result);
|
|
||||||
inline double parse(const char* s);
|
|
||||||
}
|
|
||||||
|
|
||||||
//strm.hpp
|
//strm.hpp
|
||||||
inline unsigned strmcpy(char* target, const char* source, unsigned length);
|
inline unsigned strmcpy(char* target, const char* source, unsigned length);
|
||||||
|
@ -56,7 +45,8 @@ template<bool Insensitive = false, bool Quoted = false> inline optional<unsigned
|
||||||
//trim.hpp
|
//trim.hpp
|
||||||
template<unsigned Limit = 0> inline char* ltrim(char* str, const char* key = " ");
|
template<unsigned Limit = 0> inline char* ltrim(char* str, const char* key = " ");
|
||||||
template<unsigned Limit = 0> inline char* rtrim(char* str, const char* key = " ");
|
template<unsigned Limit = 0> inline char* rtrim(char* str, const char* key = " ");
|
||||||
template<unsigned Limit = 0> inline char* trim(char* str, const char* key = " ", const char* rkey = nullptr);
|
template<unsigned Limit = 0> inline char* trim(char* str, const char* key = " ");
|
||||||
|
template<unsigned Limit = 0> inline char* trim(char* str, const char* lkey, const char* rkey);
|
||||||
inline char* strip(char* s);
|
inline char* strip(char* s);
|
||||||
|
|
||||||
//utf8.hpp
|
//utf8.hpp
|
||||||
|
@ -73,11 +63,6 @@ template<bool Insensitive> alwaysinline bool chrequal(char x, char y);
|
||||||
template<bool Quoted, typename T> alwaysinline bool quoteskip(T*& p);
|
template<bool Quoted, typename T> alwaysinline bool quoteskip(T*& p);
|
||||||
template<bool Quoted, typename T> alwaysinline bool quotecopy(char*& t, T*& p);
|
template<bool Quoted, typename T> alwaysinline bool quotecopy(char*& t, T*& p);
|
||||||
|
|
||||||
//wildcard.hpp
|
|
||||||
inline bool wildcard(const char* str, const char* pattern);
|
|
||||||
inline bool iwildcard(const char* str, const char* pattern);
|
|
||||||
inline bool tokenize(const char* s, const char* p);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
|
|
||||||
bool wildcard(const char* s, const char* p) {
|
bool strmatch(const char* s, const char* p) {
|
||||||
const char* cp = nullptr;
|
const char* cp = nullptr;
|
||||||
const char* mp = nullptr;
|
const char* mp = nullptr;
|
||||||
while(*s && *p != '*') {
|
while(*s && *p != '*') {
|
||||||
|
@ -23,7 +23,7 @@ bool wildcard(const char* s, const char* p) {
|
||||||
return !*p;
|
return !*p;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool iwildcard(const char* s, const char* p) {
|
bool istrmatch(const char* s, const char* p) {
|
||||||
const char* cp = nullptr;
|
const char* cp = nullptr;
|
||||||
const char* mp = nullptr;
|
const char* mp = nullptr;
|
||||||
while(*s && *p != '*') {
|
while(*s && *p != '*') {
|
|
@ -1,168 +0,0 @@
|
||||||
#ifdef NALL_STRING_INTERNAL_HPP
|
|
||||||
|
|
||||||
namespace nall {
|
|
||||||
namespace fixedpoint {
|
|
||||||
|
|
||||||
static nall::function<intmax_t (const char*&)> eval_fallback;
|
|
||||||
|
|
||||||
intmax_t eval_integer(const char*& s) {
|
|
||||||
if(!*s) throw "unrecognized integer";
|
|
||||||
intmax_t value = 0, x = *s, y = *(s + 1);
|
|
||||||
|
|
||||||
//hexadecimal
|
|
||||||
if(x == '0' && (y == 'X' || y == 'x')) {
|
|
||||||
s += 2;
|
|
||||||
while(true) {
|
|
||||||
if(*s >= '0' && *s <= '9') { value = value * 16 + (*s++ - '0'); continue; }
|
|
||||||
if(*s >= 'A' && *s <= 'F') { value = value * 16 + (*s++ - 'A' + 10); continue; }
|
|
||||||
if(*s >= 'a' && *s <= 'f') { value = value * 16 + (*s++ - 'a' + 10); continue; }
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//binary
|
|
||||||
if(x == '0' && (y == 'B' || y == 'b')) {
|
|
||||||
s += 2;
|
|
||||||
while(true) {
|
|
||||||
if(*s == '0' || *s == '1') { value = value * 2 + (*s++ - '0'); continue; }
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//octal (or decimal '0')
|
|
||||||
if(x == '0') {
|
|
||||||
s += 1;
|
|
||||||
while(true) {
|
|
||||||
if(*s >= '0' && *s <= '7') { value = value * 8 + (*s++ - '0'); continue; }
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//decimal
|
|
||||||
if(x >= '0' && x <= '9') {
|
|
||||||
while(true) {
|
|
||||||
if(*s >= '0' && *s <= '9') { value = value * 10 + (*s++ - '0'); continue; }
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//char
|
|
||||||
if(x == '\'' && y != '\'') {
|
|
||||||
s += 1;
|
|
||||||
while(true) {
|
|
||||||
value = value * 256 + *s++;
|
|
||||||
if(*s == '\'') { s += 1; return value; }
|
|
||||||
if(!*s) throw "mismatched char";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw "unrecognized integer";
|
|
||||||
}
|
|
||||||
|
|
||||||
intmax_t eval(const char*& s, int depth) {
|
|
||||||
while(*s == ' ' || *s == '\t') s++; //trim whitespace
|
|
||||||
if(!*s) throw "unrecognized token";
|
|
||||||
intmax_t value = 0, x = *s, y = *(s + 1);
|
|
||||||
|
|
||||||
if(*s == '(') {
|
|
||||||
value = eval(++s, 1);
|
|
||||||
if(*s++ != ')') throw "mismatched group";
|
|
||||||
}
|
|
||||||
|
|
||||||
else if(x == '!') value = !eval(++s, 13);
|
|
||||||
else if(x == '~') value = ~eval(++s, 13);
|
|
||||||
else if(x == '+') value = +eval(++s, 13);
|
|
||||||
else if(x == '-') value = -eval(++s, 13);
|
|
||||||
|
|
||||||
else if((x >= '0' && x <= '9') || x == '\'') value = eval_integer(s);
|
|
||||||
|
|
||||||
else if(eval_fallback) value = eval_fallback(s); //optional user-defined syntax parsing
|
|
||||||
|
|
||||||
else throw "unrecognized token";
|
|
||||||
|
|
||||||
while(true) {
|
|
||||||
while(*s == ' ' || *s == '\t') s++; //trim whitespace
|
|
||||||
if(!*s) break;
|
|
||||||
x = *s, y = *(s + 1);
|
|
||||||
|
|
||||||
if(depth >= 13) break;
|
|
||||||
if(x == '*') { value *= eval(++s, 13); continue; }
|
|
||||||
if(x == '/') { intmax_t result = eval(++s, 13); if(result == 0) throw "division by zero"; value /= result; continue; }
|
|
||||||
if(x == '%') { intmax_t result = eval(++s, 13); if(result == 0) throw "division by zero"; value %= result; continue; }
|
|
||||||
|
|
||||||
if(depth >= 12) break;
|
|
||||||
if(x == '+') { value += eval(++s, 12); continue; }
|
|
||||||
if(x == '-') { value -= eval(++s, 12); continue; }
|
|
||||||
|
|
||||||
if(depth >= 11) break;
|
|
||||||
if(x == '<' && y == '<') { value <<= eval(++++s, 11); continue; }
|
|
||||||
if(x == '>' && y == '>') { value >>= eval(++++s, 11); continue; }
|
|
||||||
|
|
||||||
if(depth >= 10) break;
|
|
||||||
if(x == '<' && y == '=') { value = value <= eval(++++s, 10); continue; }
|
|
||||||
if(x == '>' && y == '=') { value = value >= eval(++++s, 10); continue; }
|
|
||||||
if(x == '<') { value = value < eval(++s, 10); continue; }
|
|
||||||
if(x == '>') { value = value > eval(++s, 10); continue; }
|
|
||||||
|
|
||||||
if(depth >= 9) break;
|
|
||||||
if(x == '=' && y == '=') { value = value == eval(++++s, 9); continue; }
|
|
||||||
if(x == '!' && y == '=') { value = value != eval(++++s, 9); continue; }
|
|
||||||
|
|
||||||
if(depth >= 8) break;
|
|
||||||
if(x == '&' && y != '&') { value = value & eval(++s, 8); continue; }
|
|
||||||
|
|
||||||
if(depth >= 7) break;
|
|
||||||
if(x == '^' && y != '^') { value = value ^ eval(++s, 7); continue; }
|
|
||||||
|
|
||||||
if(depth >= 6) break;
|
|
||||||
if(x == '|' && y != '|') { value = value | eval(++s, 6); continue; }
|
|
||||||
|
|
||||||
if(depth >= 5) break;
|
|
||||||
if(x == '&' && y == '&') { value = eval(++++s, 5) && value; continue; }
|
|
||||||
|
|
||||||
if(depth >= 4) break;
|
|
||||||
if(x == '^' && y == '^') { value = (!eval(++++s, 4) != !value); continue; }
|
|
||||||
|
|
||||||
if(depth >= 3) break;
|
|
||||||
if(x == '|' && y == '|') { value = eval(++++s, 3) || value; continue; }
|
|
||||||
|
|
||||||
if(x == '?') {
|
|
||||||
intmax_t lhs = eval(++s, 2);
|
|
||||||
if(*s != ':') throw "mismatched ternary";
|
|
||||||
intmax_t rhs = eval(++s, 2);
|
|
||||||
value = value ? lhs : rhs;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if(depth >= 2) break;
|
|
||||||
|
|
||||||
if(depth > 0 && x == ')') break;
|
|
||||||
|
|
||||||
throw "unrecognized token";
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool eval(const char* s, intmax_t& result) {
|
|
||||||
try {
|
|
||||||
result = eval(s);
|
|
||||||
return true;
|
|
||||||
} catch(const char*) {
|
|
||||||
result = 0;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
intmax_t parse(const char* s) {
|
|
||||||
try {
|
|
||||||
intmax_t result = eval(s);
|
|
||||||
return result;
|
|
||||||
} catch(const char*) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -1,160 +0,0 @@
|
||||||
#ifdef NALL_STRING_INTERNAL_HPP
|
|
||||||
|
|
||||||
namespace nall {
|
|
||||||
namespace floatingpoint {
|
|
||||||
|
|
||||||
static nall::function<double (const char*&)> eval_fallback;
|
|
||||||
|
|
||||||
double eval_integer(const char*& s) {
|
|
||||||
if(!*s) throw "unrecognized integer";
|
|
||||||
intmax_t value = 0, radix = 0, x = *s, y = *(s + 1);
|
|
||||||
|
|
||||||
//hexadecimal
|
|
||||||
if(x == '0' && (y == 'X' || y == 'x')) {
|
|
||||||
s += 2;
|
|
||||||
while(true) {
|
|
||||||
if(*s >= '0' && *s <= '9') { value = value * 16 + (*s++ - '0'); continue; }
|
|
||||||
if(*s >= 'A' && *s <= 'F') { value = value * 16 + (*s++ - 'A' + 10); continue; }
|
|
||||||
if(*s >= 'a' && *s <= 'f') { value = value * 16 + (*s++ - 'a' + 10); continue; }
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//binary
|
|
||||||
if(x == '0' && (y == 'B' || y == 'b')) {
|
|
||||||
s += 2;
|
|
||||||
while(true) {
|
|
||||||
if(*s == '0' || *s == '1') { value = value * 2 + (*s++ - '0'); continue; }
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//octal (or decimal '0')
|
|
||||||
if(x == '0' && y != '.') {
|
|
||||||
s += 1;
|
|
||||||
while(true) {
|
|
||||||
if(*s >= '0' && *s <= '7') { value = value * 8 + (*s++ - '0'); continue; }
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//decimal
|
|
||||||
if(x >= '0' && x <= '9') {
|
|
||||||
while(true) {
|
|
||||||
if(*s >= '0' && *s <= '9') { value = value * 10 + (*s++ - '0'); continue; }
|
|
||||||
if(*s == '.') { s++; break; }
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
//floating-point
|
|
||||||
unsigned divisor = 1;
|
|
||||||
while(true) {
|
|
||||||
if(*s >= '0' && *s <= '9') { radix = radix * 10 + (*s++ - '0'); divisor *= 10; continue; }
|
|
||||||
return (double)value + (double)radix / (double)divisor;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//char
|
|
||||||
if(x == '\'' && y != '\'') {
|
|
||||||
s += 1;
|
|
||||||
while(true) {
|
|
||||||
value = value * 256 + *s++;
|
|
||||||
if(*s == '\'') { s += 1; return value; }
|
|
||||||
if(!*s) throw "mismatched char";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
throw "unrecognized integer";
|
|
||||||
}
|
|
||||||
|
|
||||||
double eval(const char*& s, int depth) {
|
|
||||||
while(*s == ' ' || *s == '\t') s++; //trim whitespace
|
|
||||||
if(!*s) throw "unrecognized token";
|
|
||||||
double value = 0, x = *s, y = *(s + 1);
|
|
||||||
|
|
||||||
if(*s == '(') {
|
|
||||||
value = eval(++s, 1);
|
|
||||||
if(*s++ != ')') throw "mismatched group";
|
|
||||||
}
|
|
||||||
|
|
||||||
else if(x == '!') value = !eval(++s, 9);
|
|
||||||
else if(x == '+') value = +eval(++s, 9);
|
|
||||||
else if(x == '-') value = -eval(++s, 9);
|
|
||||||
|
|
||||||
else if((x >= '0' && x <= '9') || x == '\'') value = eval_integer(s);
|
|
||||||
|
|
||||||
else if(eval_fallback) value = eval_fallback(s); //optional user-defined syntax parsing
|
|
||||||
|
|
||||||
else throw "unrecognized token";
|
|
||||||
|
|
||||||
while(true) {
|
|
||||||
while(*s == ' ' || *s == '\t') s++; //trim whitespace
|
|
||||||
if(!*s) break;
|
|
||||||
x = *s, y = *(s + 1);
|
|
||||||
|
|
||||||
if(depth >= 9) break;
|
|
||||||
if(x == '*') { value *= eval(++s, 9); continue; }
|
|
||||||
if(x == '/') { double result = eval(++s, 9); if(result == 0.0) throw "division by zero"; value /= result; continue; }
|
|
||||||
|
|
||||||
if(depth >= 8) break;
|
|
||||||
if(x == '+') { value += eval(++s, 8); continue; }
|
|
||||||
if(x == '-') { value -= eval(++s, 8); continue; }
|
|
||||||
|
|
||||||
if(depth >= 7) break;
|
|
||||||
if(x == '<' && y == '=') { value = value <= eval(++++s, 7); continue; }
|
|
||||||
if(x == '>' && y == '=') { value = value >= eval(++++s, 7); continue; }
|
|
||||||
if(x == '<') { value = value < eval(++s, 7); continue; }
|
|
||||||
if(x == '>') { value = value > eval(++s, 7); continue; }
|
|
||||||
|
|
||||||
if(depth >= 6) break;
|
|
||||||
if(x == '=' && y == '=') { value = value == eval(++++s, 6); continue; }
|
|
||||||
if(x == '!' && y == '=') { value = value != eval(++++s, 6); continue; }
|
|
||||||
|
|
||||||
if(depth >= 5) break;
|
|
||||||
if(x == '&' && y == '&') { value = eval(++++s, 5) && value; continue; }
|
|
||||||
|
|
||||||
if(depth >= 4) break;
|
|
||||||
if(x == '^' && y == '^') { value = (!eval(++++s, 4) != !value); continue; }
|
|
||||||
|
|
||||||
if(depth >= 3) break;
|
|
||||||
if(x == '|' && y == '|') { value = eval(++++s, 3) || value; continue; }
|
|
||||||
|
|
||||||
if(x == '?') {
|
|
||||||
double lhs = eval(++s, 2);
|
|
||||||
if(*s != ':') throw "mismatched ternary";
|
|
||||||
double rhs = eval(++s, 2);
|
|
||||||
value = value ? lhs : rhs;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if(depth >= 2) break;
|
|
||||||
|
|
||||||
if(depth > 0 && x == ')') break;
|
|
||||||
|
|
||||||
throw "unrecognized token";
|
|
||||||
}
|
|
||||||
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool eval(const char* s, double& result) {
|
|
||||||
try {
|
|
||||||
result = eval(s);
|
|
||||||
return true;
|
|
||||||
} catch(const char*) {
|
|
||||||
result = 0;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
double parse(const char* s) {
|
|
||||||
try {
|
|
||||||
double result = eval(s);
|
|
||||||
return result;
|
|
||||||
} catch(const char*) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
|
@ -29,11 +29,14 @@ template<unsigned Limit> char* rtrim(char* str, const char* key) {
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<unsigned limit> char* trim(char* str, const char* key, const char* rkey) {
|
template<unsigned limit> char* trim(char* str, const char* key) {
|
||||||
if(rkey) return ltrim<limit>(rtrim<limit>(str, rkey), key);
|
|
||||||
return ltrim<limit>(rtrim<limit>(str, key), key);
|
return ltrim<limit>(rtrim<limit>(str, key), key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<unsigned limit> char* trim(char* str, const char* lkey, const char* rkey) {
|
||||||
|
return ltrim<limit>(rtrim<limit>(str, rkey), lkey);
|
||||||
|
}
|
||||||
|
|
||||||
//remove whitespace characters from both left and right sides of string
|
//remove whitespace characters from both left and right sides of string
|
||||||
char* strip(char* s) {
|
char* strip(char* s) {
|
||||||
if(!s) return nullptr;
|
if(!s) return nullptr;
|
||||||
|
|
|
@ -1,59 +1,36 @@
|
||||||
#ifdef NALL_STRING_INTERNAL_HPP
|
#ifdef NALL_STRING_INTERNAL_HPP
|
||||||
|
|
||||||
//core functionality
|
//only allocators may access _data or modify _size and _capacity
|
||||||
//only this header file may access _data, _size, _capacity directly
|
//all other functions must use data(), size(), capacity()
|
||||||
//all other headers must use data(), size(), capacity()
|
|
||||||
|
#if defined(NALL_STRING_ALLOCATOR_COPY_ON_WRITE)
|
||||||
|
#include <nall/string/allocator/copy-on-write.hpp>
|
||||||
|
#elif defined(NALL_STRING_ALLOCATOR_SMALL_STRING_OPTIMIZATION)
|
||||||
|
#include <nall/string/allocator/small-string-optimization.hpp>
|
||||||
|
#elif defined(NALL_STRING_ALLOCATOR_VECTOR)
|
||||||
|
#include <nall/string/allocator/vector.hpp>
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace nall {
|
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::length() const { return strlen(data()); }
|
||||||
unsigned string::size() const { return _size; }
|
unsigned string::size() const { return _size; }
|
||||||
unsigned string::capacity() const { return _capacity; }
|
unsigned string::capacity() const { return _capacity; }
|
||||||
bool string::empty() const { return size() == 0; }
|
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) {
|
void string::clear(char c) {
|
||||||
for(unsigned n = 0; n < size(); n++) data()[n] = c;
|
for(unsigned n = 0; n < size(); n++) data()[n] = c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned string::hash() const {
|
||||||
|
const char* p = data();
|
||||||
|
unsigned result = 5381;
|
||||||
|
while(*p) result = (result << 5) + result + *p++;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename... Args> string& string::assign(Args&&... args) {
|
template<typename... Args> string& string::assign(Args&&... args) {
|
||||||
reset();
|
resize(0);
|
||||||
sprint(*this, std::forward<Args>(args)...);
|
sprint(*this, std::forward<Args>(args)...);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -80,12 +57,12 @@ string::operator const char*() const {
|
||||||
return data();
|
return data();
|
||||||
}
|
}
|
||||||
|
|
||||||
char& string::operator[](unsigned position) {
|
char& string::operator[](signed position) {
|
||||||
if(position > size() + 1) throw exception_out_of_bounds{};
|
if(position > size() + 1) throw exception_out_of_bounds{};
|
||||||
return data()[position];
|
return data()[position];
|
||||||
}
|
}
|
||||||
|
|
||||||
const char& string::operator[](unsigned position) const {
|
const char& string::operator[](signed position) const {
|
||||||
if(position > size() + 1) throw exception_out_of_bounds{};
|
if(position > size() + 1) throw exception_out_of_bounds{};
|
||||||
return data()[position];
|
return data()[position];
|
||||||
}
|
}
|
||||||
|
@ -97,24 +74,6 @@ 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) {
|
string::string(const string& source) {
|
||||||
operator=(source);
|
operator=(source);
|
||||||
}
|
}
|
||||||
|
@ -123,20 +82,6 @@ string::string(string&& source) {
|
||||||
operator=(std::move(source));
|
operator=(std::move(source));
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
#endif
|
||||||
|
|
|
@ -0,0 +1,150 @@
|
||||||
|
#ifdef NALL_STRING_INTERNAL_HPP
|
||||||
|
|
||||||
|
namespace nall {
|
||||||
|
namespace Eval {
|
||||||
|
|
||||||
|
inline string evaluateExpression(Node* node) {
|
||||||
|
#define p(n) evaluateExpression(node->link[n])
|
||||||
|
switch(node->type) {
|
||||||
|
case Node::Type::Null: return "Null";
|
||||||
|
case Node::Type::Literal: return {"Literal:", node->literal};
|
||||||
|
case Node::Type::Function: return {"Function(0:", p(0), ", 1:", p(1), ")"};
|
||||||
|
case Node::Type::Subscript: return {"Subscript(0:", p(0), ", 1:", p(1), ")"};
|
||||||
|
case Node::Type::Member: return {"Member(0:", p(0), ", 1:", p(1), ")"};
|
||||||
|
case Node::Type::SuffixIncrement: return {"SuffixIncrement(0:", p(0), ")"};
|
||||||
|
case Node::Type::SuffixDecrement: return {"SuffixDecrement(0:", p(0), ")"};
|
||||||
|
case Node::Type::Reference: return {"Reference(0:", p(0), ")"};
|
||||||
|
case Node::Type::Dereference: return {"Dereference(0:", p(0), ")"};
|
||||||
|
case Node::Type::BitwiseNot: return {"Complement(0:", p(0), ")"};
|
||||||
|
case Node::Type::PrefixIncrement: return {"PrefixIncrement(0:", p(0), ")"};
|
||||||
|
case Node::Type::PrefixDecrement: return {"PrefixDecrement(0:", p(0), ")"};
|
||||||
|
case Node::Type::Add: return {"Add(0:", p(0), ", 1:", p(1), ")"};
|
||||||
|
case Node::Type::Multiply: return {"Multiply(0:", p(0), ", 1:", p(1), ")"};
|
||||||
|
case Node::Type::Concatenate: return {"Concatenate(0:", p(0), ", ", p(1), ")"};
|
||||||
|
case Node::Type::Coalesce: return {"Coalesce(0:", p(0), ", ", p(1), ")"};
|
||||||
|
case Node::Type::Condition: return {"Condition(0:", p(0), ", ", p(1), ", ", p(2), ")"};
|
||||||
|
case Node::Type::Assign: return {"Assign(0:", p(0), ", ", p(1), ")"};
|
||||||
|
case Node::Type::Separator: {
|
||||||
|
string result = "Separator(";
|
||||||
|
for(auto& link : node->link) {
|
||||||
|
result.append(evaluateExpression(link), ", ");
|
||||||
|
}
|
||||||
|
return result.rtrim<1>(", ").append(")");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#undef p
|
||||||
|
|
||||||
|
throw "invalid operator";
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int64_t evaluateInteger(Node* node) {
|
||||||
|
if(node->type == Node::Type::Literal) return nall::integer(node->literal);
|
||||||
|
|
||||||
|
#define p(n) evaluateInteger(node->link[n])
|
||||||
|
switch(node->type) {
|
||||||
|
case Node::Type::SuffixIncrement: return p(0);
|
||||||
|
case Node::Type::SuffixDecrement: return p(0);
|
||||||
|
case Node::Type::LogicalNot: return !p(0);
|
||||||
|
case Node::Type::BitwiseNot: return ~p(0);
|
||||||
|
case Node::Type::Positive: return +p(0);
|
||||||
|
case Node::Type::Negative: return -p(0);
|
||||||
|
case Node::Type::PrefixIncrement: return p(0) + 1;
|
||||||
|
case Node::Type::PrefixDecrement: return p(0) - 1;
|
||||||
|
case Node::Type::Multiply: return p(0) * p(1);
|
||||||
|
case Node::Type::Divide: return p(0) / p(1);
|
||||||
|
case Node::Type::Modulo: return p(0) % p(1);
|
||||||
|
case Node::Type::Add: return p(0) + p(1);
|
||||||
|
case Node::Type::Subtract: return p(0) - p(1);
|
||||||
|
case Node::Type::ShiftLeft: return p(0) << p(1);
|
||||||
|
case Node::Type::ShiftRight: return p(0) >> p(1);
|
||||||
|
case Node::Type::BitwiseAnd: return p(0) & p(1);
|
||||||
|
case Node::Type::BitwiseOr: return p(0) | p(1);
|
||||||
|
case Node::Type::BitwiseXor: return p(0) ^ p(1);
|
||||||
|
case Node::Type::Equal: return p(0) == p(1);
|
||||||
|
case Node::Type::NotEqual: return p(0) != p(1);
|
||||||
|
case Node::Type::LessThanEqual: return p(0) <= p(1);
|
||||||
|
case Node::Type::GreaterThanEqual: return p(0) >= p(1);
|
||||||
|
case Node::Type::LessThan: return p(0) < p(1);
|
||||||
|
case Node::Type::GreaterThan: return p(0) > p(1);
|
||||||
|
case Node::Type::LogicalAnd: return p(0) && p(1);
|
||||||
|
case Node::Type::LogicalOr: return p(0) || p(1);
|
||||||
|
case Node::Type::Condition: return p(0) ? p(1) : p(2);
|
||||||
|
case Node::Type::Assign: return p(1);
|
||||||
|
case Node::Type::AssignMultiply: return p(0) * p(1);
|
||||||
|
case Node::Type::AssignDivide: return p(0) / p(1);
|
||||||
|
case Node::Type::AssignModulo: return p(0) % p(1);
|
||||||
|
case Node::Type::AssignAdd: return p(0) + p(1);
|
||||||
|
case Node::Type::AssignSubtract: return p(0) - p(1);
|
||||||
|
case Node::Type::AssignShiftLeft: return p(0) << p(1);
|
||||||
|
case Node::Type::AssignShiftRight: return p(0) >> p(1);
|
||||||
|
case Node::Type::AssignBitwiseAnd: return p(0) & p(1);
|
||||||
|
case Node::Type::AssignBitwiseOr: return p(0) | p(1);
|
||||||
|
case Node::Type::AssignBitwiseXor: return p(0) ^ p(1);
|
||||||
|
}
|
||||||
|
#undef p
|
||||||
|
|
||||||
|
throw "invalid operator";
|
||||||
|
}
|
||||||
|
|
||||||
|
inline optional<int64_t> integer(const string& expression) {
|
||||||
|
try {
|
||||||
|
auto tree = new Node;
|
||||||
|
const char* p = expression;
|
||||||
|
parse(tree, p, 0);
|
||||||
|
auto result = evaluateInteger(tree);
|
||||||
|
delete tree;
|
||||||
|
return {true, result};
|
||||||
|
} catch(const char*) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline long double evaluateReal(Node* node) {
|
||||||
|
if(node->type == Node::Type::Literal) return nall::real(node->literal);
|
||||||
|
|
||||||
|
#define p(n) evaluateReal(node->link[n])
|
||||||
|
switch(node->type) {
|
||||||
|
case Node::Type::LogicalNot: return !p(0);
|
||||||
|
case Node::Type::Positive: return +p(0);
|
||||||
|
case Node::Type::Negative: return -p(0);
|
||||||
|
case Node::Type::Multiply: return p(0) * p(1);
|
||||||
|
case Node::Type::Divide: return p(0) / p(1);
|
||||||
|
case Node::Type::Add: return p(0) + p(1);
|
||||||
|
case Node::Type::Subtract: return p(0) - p(1);
|
||||||
|
case Node::Type::Equal: return p(0) == p(1);
|
||||||
|
case Node::Type::NotEqual: return p(0) != p(1);
|
||||||
|
case Node::Type::LessThanEqual: return p(0) <= p(1);
|
||||||
|
case Node::Type::GreaterThanEqual: return p(0) >= p(1);
|
||||||
|
case Node::Type::LessThan: return p(0) < p(1);
|
||||||
|
case Node::Type::GreaterThan: return p(0) > p(1);
|
||||||
|
case Node::Type::LogicalAnd: return p(0) && p(1);
|
||||||
|
case Node::Type::LogicalOr: return p(0) || p(1);
|
||||||
|
case Node::Type::Condition: return p(0) ? p(1) : p(2);
|
||||||
|
case Node::Type::Assign: return p(1);
|
||||||
|
case Node::Type::AssignMultiply: return p(0) * p(1);
|
||||||
|
case Node::Type::AssignDivide: return p(0) / p(1);
|
||||||
|
case Node::Type::AssignAdd: return p(0) + p(1);
|
||||||
|
case Node::Type::AssignSubtract: return p(0) - p(1);
|
||||||
|
}
|
||||||
|
#undef p
|
||||||
|
|
||||||
|
throw "invalid operator";
|
||||||
|
}
|
||||||
|
|
||||||
|
inline optional<long double> real(const string& expression) {
|
||||||
|
try {
|
||||||
|
auto tree = new Node;
|
||||||
|
const char* p = expression;
|
||||||
|
parse(tree, p, 0);
|
||||||
|
auto result = evaluateReal(tree);
|
||||||
|
delete tree;
|
||||||
|
return {true, result};
|
||||||
|
} catch(const char*) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,97 @@
|
||||||
|
#ifdef NALL_STRING_INTERNAL_HPP
|
||||||
|
|
||||||
|
namespace nall {
|
||||||
|
namespace Eval {
|
||||||
|
|
||||||
|
inline bool isLiteral(const char*& s) {
|
||||||
|
char n = s[0];
|
||||||
|
return (n >= 'A' && n <= 'Z')
|
||||||
|
|| (n >= 'a' && n <= 'z')
|
||||||
|
|| (n >= '0' && n <= '9')
|
||||||
|
|| n == '_' || n == '\"';
|
||||||
|
}
|
||||||
|
|
||||||
|
inline string literalNumber(const char*& s) {
|
||||||
|
const char* p = s;
|
||||||
|
|
||||||
|
//binary
|
||||||
|
if(p[0] == '0' && p[1] == 'b') {
|
||||||
|
p += 2;
|
||||||
|
while(p[0] == '0' || p[0] == '1') p++;
|
||||||
|
if(p - s < 3) throw "invalid binary literal";
|
||||||
|
string result = substr(s, 0, p - s);
|
||||||
|
s = p;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
//octal
|
||||||
|
if(p[0] == '0' && p[1] == 'o') {
|
||||||
|
p += 2;
|
||||||
|
while(p[0] >= '0' && p[0] <= '7') p++;
|
||||||
|
if(p - s < 3) throw "invalid octal literal";
|
||||||
|
string result = substr(s, 0, p - s);
|
||||||
|
s = p;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
//hex
|
||||||
|
if(p[0] == '0' && p[1] == 'x') {
|
||||||
|
p += 2;
|
||||||
|
while((p[0] >= '0' && p[0] <= '9') || (p[0] >= 'A' && p[0] <= 'F') || (p[0] >= 'a' && p[0] <= 'f')) p++;
|
||||||
|
if(p - s < 3) throw "invalid hex literal";
|
||||||
|
string result = substr(s, 0, p - s);
|
||||||
|
s = p;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
//decimal
|
||||||
|
while(p[0] >= '0' && p[0] <= '9') p++;
|
||||||
|
if(p[0] != '.') {
|
||||||
|
string result = substr(s, 0, p - s);
|
||||||
|
s = p;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
//floating-point
|
||||||
|
p++;
|
||||||
|
while(p[0] >= '0' && p[0] <= '9') p++;
|
||||||
|
string result = substr(s, 0, p - s);
|
||||||
|
s = p;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline string literalString(const char*& s) {
|
||||||
|
const char* p = s + 1;
|
||||||
|
|
||||||
|
while(p[0] && p[0] != '\"') p++;
|
||||||
|
if(*p++ != '\"') throw "unclosed string literal";
|
||||||
|
|
||||||
|
string result = substr(s, 0, p - s);
|
||||||
|
s = p;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline string literalVariable(const char*& s) {
|
||||||
|
const char* p = s;
|
||||||
|
|
||||||
|
while(p[0] == '_' || (p[0] >= 'A' && p[0] <= 'Z') || (p[0] >= 'a' && p[0] <= 'z') || (p[0] >= '0' && p[0] <= '9')) p++;
|
||||||
|
|
||||||
|
string result = substr(s, 0, p - s);
|
||||||
|
s = p;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline string literal(const char*& s) {
|
||||||
|
const char* p = s;
|
||||||
|
|
||||||
|
if(p[0] >= '0' && p[0] <= '9') return literalNumber(s);
|
||||||
|
if(p[0] == '\"') return literalString(s);
|
||||||
|
if(p[0] == '_' || (p[0] >= 'A' && p[0] <= 'Z') || (p[0] >= 'a' && p[0] <= 'z')) return literalVariable(s);
|
||||||
|
|
||||||
|
throw "invalid literal";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,41 @@
|
||||||
|
#ifdef NALL_STRING_INTERNAL_HPP
|
||||||
|
|
||||||
|
namespace nall {
|
||||||
|
namespace Eval {
|
||||||
|
|
||||||
|
struct Node {
|
||||||
|
enum class Type : unsigned {
|
||||||
|
Null,
|
||||||
|
Literal,
|
||||||
|
Function, Subscript, Member, SuffixIncrement, SuffixDecrement,
|
||||||
|
Reference, Dereference, LogicalNot, BitwiseNot, Positive, Negative, PrefixIncrement, PrefixDecrement,
|
||||||
|
Multiply, Divide, Modulo,
|
||||||
|
Add, Subtract,
|
||||||
|
RotateLeft, RotateRight, ShiftLeft, ShiftRight,
|
||||||
|
BitwiseAnd, BitwiseOr, BitwiseXor,
|
||||||
|
Concatenate,
|
||||||
|
Equal, NotEqual, LessThanEqual, GreaterThanEqual, LessThan, GreaterThan,
|
||||||
|
LogicalAnd, LogicalOr,
|
||||||
|
Coalesce, Condition,
|
||||||
|
Assign, Create, //all assignment operators have the same precedence
|
||||||
|
AssignMultiply, AssignDivide, AssignModulo,
|
||||||
|
AssignAdd, AssignSubtract,
|
||||||
|
AssignRotateLeft, AssignRotateRight, AssignShiftLeft, AssignShiftRight,
|
||||||
|
AssignBitwiseAnd, AssignBitwiseOr, AssignBitwiseXor,
|
||||||
|
AssignConcatenate,
|
||||||
|
Separator,
|
||||||
|
};
|
||||||
|
|
||||||
|
Type type;
|
||||||
|
string literal;
|
||||||
|
vector<Node*> link;
|
||||||
|
|
||||||
|
Node() : type(Type::Null) {}
|
||||||
|
Node(Type type) : type(type) {}
|
||||||
|
~Node() { for(auto& node : link) delete node; }
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,168 @@
|
||||||
|
#ifdef NALL_STRING_INTERNAL_HPP
|
||||||
|
|
||||||
|
namespace nall {
|
||||||
|
namespace Eval {
|
||||||
|
|
||||||
|
inline bool whitespace(char n) {
|
||||||
|
return n == ' ' || n == '\t' || n == '\r' || n == '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void parse(Node*& node, const char*& s, unsigned depth) {
|
||||||
|
auto unaryPrefix = [&](Node::Type type, unsigned seek, unsigned depth) {
|
||||||
|
auto parent = new Node(type);
|
||||||
|
parse(parent->link(0) = new Node, s += seek, depth);
|
||||||
|
node = parent;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto unarySuffix = [&](Node::Type type, unsigned seek, unsigned depth) {
|
||||||
|
auto parent = new Node(type);
|
||||||
|
parent->link(0) = node;
|
||||||
|
parse(parent, s += seek, depth);
|
||||||
|
node = parent;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto binary = [&](Node::Type type, unsigned seek, unsigned depth) {
|
||||||
|
auto parent = new Node(type);
|
||||||
|
parent->link(0) = node;
|
||||||
|
parse(parent->link(1) = new Node, s += seek, depth);
|
||||||
|
node = parent;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto ternary = [&](Node::Type type, unsigned seek, unsigned depth) {
|
||||||
|
auto parent = new Node(type);
|
||||||
|
parent->link(0) = node;
|
||||||
|
parse(parent->link(1) = new Node, s += seek, depth);
|
||||||
|
if(s[0] != ':') throw "mismatched ternary";
|
||||||
|
parse(parent->link(2) = new Node, s += seek, depth);
|
||||||
|
node = parent;
|
||||||
|
};
|
||||||
|
|
||||||
|
auto separator = [&](Node::Type type, unsigned seek, unsigned depth) {
|
||||||
|
if(node->type != Node::Type::Separator) return binary(type, seek, depth);
|
||||||
|
unsigned n = node->link.size();
|
||||||
|
parse(node->link(n) = new Node, s += seek, depth);
|
||||||
|
};
|
||||||
|
|
||||||
|
while(whitespace(s[0])) s++;
|
||||||
|
if(!s[0]) return;
|
||||||
|
|
||||||
|
if(s[0] == '(' && node->link.empty()) {
|
||||||
|
parse(node, s += 1, 1);
|
||||||
|
if(*s++ != ')') throw "mismatched group";
|
||||||
|
}
|
||||||
|
|
||||||
|
if(isLiteral(s)) {
|
||||||
|
node->type = Node::Type::Literal;
|
||||||
|
node->literal = literal(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define p() (node->literal.empty() && node->link.empty())
|
||||||
|
while(true) {
|
||||||
|
while(whitespace(s[0])) s++;
|
||||||
|
if(!s[0]) return;
|
||||||
|
|
||||||
|
if(depth >= 13) break;
|
||||||
|
if(s[0] == '(' && !p()) {
|
||||||
|
binary(Node::Type::Function, 1, 1);
|
||||||
|
if(*s++ != ')') throw "mismatched function";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(s[0] == '[') {
|
||||||
|
binary(Node::Type::Subscript, 1, 1);
|
||||||
|
if(*s++ != ']') throw "mismatched subscript";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(s[0] == '.') { binary(Node::Type::Member, 1, 13); continue; }
|
||||||
|
if(s[0] == '+' && s[1] == '+' && !p()) { unarySuffix(Node::Type::SuffixIncrement, 2, 13); continue; }
|
||||||
|
if(s[0] == '-' && s[1] == '-' && !p()) { unarySuffix(Node::Type::SuffixDecrement, 2, 13); continue; }
|
||||||
|
|
||||||
|
if(s[0] == '&' && p()) { unaryPrefix(Node::Type::Reference, 1, 12); continue; }
|
||||||
|
if(s[0] == '*' && p()) { unaryPrefix(Node::Type::Dereference, 1, 12); continue; }
|
||||||
|
if(s[0] == '!' && p()) { unaryPrefix(Node::Type::LogicalNot, 1, 12); continue; }
|
||||||
|
if(s[0] == '~' && p()) { unaryPrefix(Node::Type::BitwiseNot, 1, 12); continue; }
|
||||||
|
if(s[0] == '+' && s[1] != '+' && p()) { unaryPrefix(Node::Type::Positive, 1, 12); continue; }
|
||||||
|
if(s[0] == '-' && s[1] != '-' && p()) { unaryPrefix(Node::Type::Negative, 1, 12); continue; }
|
||||||
|
if(s[0] == '+' && s[1] == '+' && p()) { unaryPrefix(Node::Type::PrefixIncrement, 2, 12); continue; }
|
||||||
|
if(s[0] == '-' && s[1] == '-' && p()) { unaryPrefix(Node::Type::PrefixDecrement, 2, 12); continue; }
|
||||||
|
if(depth >= 12) break;
|
||||||
|
|
||||||
|
if(depth >= 11) break;
|
||||||
|
if(s[0] == '*' && s[1] != '=') { binary(Node::Type::Multiply, 1, 11); continue; }
|
||||||
|
if(s[0] == '/' && s[1] != '=') { binary(Node::Type::Divide, 1, 11); continue; }
|
||||||
|
if(s[0] == '%' && s[1] != '=') { binary(Node::Type::Modulo, 1, 11); continue; }
|
||||||
|
|
||||||
|
if(depth >= 10) break;
|
||||||
|
if(s[0] == '+' && s[1] != '=') { binary(Node::Type::Add, 1, 10); continue; }
|
||||||
|
if(s[0] == '-' && s[1] != '=') { binary(Node::Type::Subtract, 1, 10); continue; }
|
||||||
|
|
||||||
|
if(depth >= 9) break;
|
||||||
|
if(s[0] == '<' && s[1] == '<' && s[2] == '<' && s[3] != '=') { binary(Node::Type::RotateLeft, 3, 9); continue; }
|
||||||
|
if(s[0] == '>' && s[1] == '>' && s[2] == '>' && s[3] != '=') { binary(Node::Type::RotateRight, 3, 9); continue; }
|
||||||
|
if(s[0] == '<' && s[1] == '<' && s[2] != '=') { binary(Node::Type::ShiftLeft, 2, 9); continue; }
|
||||||
|
if(s[0] == '>' && s[1] == '>' && s[2] != '=') { binary(Node::Type::ShiftRight, 2, 9); continue; }
|
||||||
|
|
||||||
|
if(depth >= 8) break;
|
||||||
|
if(s[0] == '&' && s[1] != '&' && s[1] != '=') { binary(Node::Type::BitwiseAnd, 1, 8); continue; }
|
||||||
|
if(s[0] == '|' && s[1] != '|' && s[1] != '=') { binary(Node::Type::BitwiseOr, 1, 8); continue; }
|
||||||
|
if(s[0] == '^' && s[1] != '^' && s[1] != '=') { binary(Node::Type::BitwiseXor, 1, 8); continue; }
|
||||||
|
|
||||||
|
if(depth >= 7) break;
|
||||||
|
if(s[0] == '~' && s[1] != '=') { binary(Node::Type::Concatenate, 1, 7); continue; }
|
||||||
|
|
||||||
|
if(depth >= 6) break;
|
||||||
|
if(s[0] == '=' && s[1] == '=') { binary(Node::Type::Equal, 2, 6); continue; }
|
||||||
|
if(s[0] == '!' && s[1] == '=') { binary(Node::Type::NotEqual, 2, 6); continue; }
|
||||||
|
if(s[0] == '<' && s[1] == '=') { binary(Node::Type::LessThanEqual, 2, 6); continue; }
|
||||||
|
if(s[0] == '>' && s[1] == '=') { binary(Node::Type::GreaterThanEqual, 2, 6); continue; }
|
||||||
|
if(s[0] == '<') { binary(Node::Type::LessThan, 1, 6); continue; }
|
||||||
|
if(s[0] == '>') { binary(Node::Type::GreaterThan, 1, 6); continue; }
|
||||||
|
|
||||||
|
if(depth >= 5) break;
|
||||||
|
if(s[0] == '&' && s[1] == '&') { binary(Node::Type::LogicalAnd, 2, 5); continue; }
|
||||||
|
if(s[0] == '|' && s[1] == '|') { binary(Node::Type::LogicalOr, 2, 5); continue; }
|
||||||
|
|
||||||
|
if(s[0] == '?' && s[1] == '?') { binary(Node::Type::Coalesce, 2, 4); continue; }
|
||||||
|
if(s[0] == '?' && s[1] != '?') { ternary(Node::Type::Condition, 1, 4); continue; }
|
||||||
|
if(depth >= 4) break;
|
||||||
|
|
||||||
|
if(s[0] == '=') { binary(Node::Type::Assign, 1, 3); continue; }
|
||||||
|
if(s[0] == ':' && s[1] == '=') { binary(Node::Type::Create, 2, 3); continue; }
|
||||||
|
if(s[0] == '*' && s[1] == '=') { binary(Node::Type::AssignMultiply, 2, 3); continue; }
|
||||||
|
if(s[0] == '/' && s[1] == '=') { binary(Node::Type::AssignDivide, 2, 3); continue; }
|
||||||
|
if(s[0] == '%' && s[1] == '=') { binary(Node::Type::AssignModulo, 2, 3); continue; }
|
||||||
|
if(s[0] == '+' && s[1] == '=') { binary(Node::Type::AssignAdd, 2, 3); continue; }
|
||||||
|
if(s[0] == '-' && s[1] == '=') { binary(Node::Type::AssignSubtract, 2, 3); continue; }
|
||||||
|
if(s[0] == '<' && s[1] == '<' && s[2] == '<' && s[3] == '=') { binary(Node::Type::AssignRotateLeft, 4, 3); continue; }
|
||||||
|
if(s[0] == '>' && s[1] == '>' && s[2] == '>' && s[3] == '=') { binary(Node::Type::AssignRotateRight, 4, 3); continue; }
|
||||||
|
if(s[0] == '<' && s[1] == '<' && s[2] == '=') { binary(Node::Type::AssignShiftLeft, 3, 3); continue; }
|
||||||
|
if(s[0] == '>' && s[1] == '>' && s[2] == '=') { binary(Node::Type::AssignShiftRight, 3, 3); continue; }
|
||||||
|
if(s[0] == '&' && s[1] == '=') { binary(Node::Type::AssignBitwiseAnd, 2, 3); continue; }
|
||||||
|
if(s[0] == '|' && s[1] == '=') { binary(Node::Type::AssignBitwiseOr, 2, 3); continue; }
|
||||||
|
if(s[0] == '^' && s[1] == '=') { binary(Node::Type::AssignBitwiseXor, 2, 3); continue; }
|
||||||
|
if(s[0] == '~' && s[1] == '=') { binary(Node::Type::AssignConcatenate, 2, 3); continue; }
|
||||||
|
if(depth >= 3) break;
|
||||||
|
|
||||||
|
if(depth >= 2) break;
|
||||||
|
if(s[0] == ',') { separator(Node::Type::Separator, 1, 2); continue; }
|
||||||
|
|
||||||
|
if(depth >= 1 && (s[0] == ')' || s[0] == ']')) break;
|
||||||
|
|
||||||
|
while(whitespace(s[0])) s++;
|
||||||
|
if(!s[0]) break;
|
||||||
|
|
||||||
|
throw "unrecognized terminal";
|
||||||
|
}
|
||||||
|
#undef p
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Node* parse(const string& expression) {
|
||||||
|
auto result = new Node;
|
||||||
|
const char* p = expression;
|
||||||
|
parse(result, p, 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -2,34 +2,28 @@
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
|
|
||||||
bool string::readfile(rstring filename) {
|
string string::read(const string& filename) {
|
||||||
reset();
|
string result;
|
||||||
|
|
||||||
#if !defined(_WIN32)
|
#if !defined(_WIN32)
|
||||||
FILE* fp = fopen(filename, "rb");
|
FILE* fp = fopen(filename, "rb");
|
||||||
#else
|
#else
|
||||||
FILE* fp = _wfopen(utf16_t(filename), L"rb");
|
FILE* fp = _wfopen(utf16_t(filename), L"rb");
|
||||||
#endif
|
#endif
|
||||||
if(!fp) return false;
|
if(!fp) return result;
|
||||||
|
|
||||||
fseek(fp, 0, SEEK_END);
|
fseek(fp, 0, SEEK_END);
|
||||||
unsigned fsize = ftell(fp);
|
unsigned fsize = ftell(fp);
|
||||||
rewind(fp);
|
rewind(fp);
|
||||||
char *fdata = new char[fsize + 1];
|
char* fdata = new char[fsize + 1];
|
||||||
unsigned unused = fread(fdata, 1, fsize, fp);
|
unsigned unused = fread(fdata, 1, fsize, fp);
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
fdata[fsize] = 0;
|
fdata[fsize] = 0;
|
||||||
resize(fsize);
|
result.resize(fsize);
|
||||||
memcpy(data(), fdata, fsize);
|
memcpy(result.data(), fdata, fsize);
|
||||||
delete[] fdata;
|
delete[] fdata;
|
||||||
|
|
||||||
return true;
|
return result;
|
||||||
}
|
|
||||||
|
|
||||||
string string::read(rstring filename) {
|
|
||||||
string data;
|
|
||||||
data.readfile(filename);
|
|
||||||
return data;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ template<signed precision, char padchar> string hex(uintmax_t value) {
|
||||||
buffer[size++] = n < 10 ? '0' + n : 'a' + n - 10;
|
buffer[size++] = n < 10 ? '0' + n : 'a' + n - 10;
|
||||||
value >>= 4;
|
value >>= 4;
|
||||||
} while(value);
|
} while(value);
|
||||||
buffer[size] = 0;
|
buffer.resize(size);
|
||||||
buffer.reverse();
|
buffer.reverse();
|
||||||
|
|
||||||
return format<precision, padchar>(buffer);
|
return format<precision, padchar>(buffer);
|
||||||
|
@ -46,7 +46,7 @@ template<signed precision, char padchar> string octal(uintmax_t value) {
|
||||||
buffer[size++] = '0' + (value & 7);
|
buffer[size++] = '0' + (value & 7);
|
||||||
value >>= 3;
|
value >>= 3;
|
||||||
} while(value);
|
} while(value);
|
||||||
buffer[size] = 0;
|
buffer.resize(size);
|
||||||
buffer.reverse();
|
buffer.reverse();
|
||||||
|
|
||||||
return format<precision, padchar>(buffer);
|
return format<precision, padchar>(buffer);
|
||||||
|
@ -61,7 +61,7 @@ template<signed precision, char padchar> string binary(uintmax_t value) {
|
||||||
buffer[size++] = '0' + (value & 1);
|
buffer[size++] = '0' + (value & 1);
|
||||||
value >>= 1;
|
value >>= 1;
|
||||||
} while(value);
|
} while(value);
|
||||||
buffer[size] = 0;
|
buffer.resize(size);
|
||||||
buffer.reverse();
|
buffer.reverse();
|
||||||
|
|
||||||
return format<precision, padchar>(buffer);
|
return format<precision, padchar>(buffer);
|
||||||
|
|
|
@ -39,12 +39,12 @@ struct Node {
|
||||||
for(auto& rule : rules) {
|
for(auto& rule : rules) {
|
||||||
enum class Comparator : unsigned { ID, EQ, NE, LT, LE, GT, GE };
|
enum class Comparator : unsigned { ID, EQ, NE, LT, LE, GT, GE };
|
||||||
auto comparator = Comparator::ID;
|
auto comparator = Comparator::ID;
|
||||||
if(rule.wildcard("*!=*")) comparator = Comparator::NE;
|
if(rule.match("*!=*")) comparator = Comparator::NE;
|
||||||
else if(rule.wildcard("*<=*")) comparator = Comparator::LE;
|
else if(rule.match("*<=*")) comparator = Comparator::LE;
|
||||||
else if(rule.wildcard("*>=*")) comparator = Comparator::GE;
|
else if(rule.match("*>=*")) comparator = Comparator::GE;
|
||||||
else if(rule.wildcard ("*=*")) comparator = Comparator::EQ;
|
else if(rule.match ("*=*")) comparator = Comparator::EQ;
|
||||||
else if(rule.wildcard ("*<*")) comparator = Comparator::LT;
|
else if(rule.match ("*<*")) comparator = Comparator::LT;
|
||||||
else if(rule.wildcard ("*>*")) comparator = Comparator::GT;
|
else if(rule.match ("*>*")) comparator = Comparator::GT;
|
||||||
|
|
||||||
if(comparator == Comparator::ID) {
|
if(comparator == Comparator::ID) {
|
||||||
if(find(rule).size()) continue;
|
if(find(rule).size()) continue;
|
||||||
|
@ -69,8 +69,8 @@ struct Node {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch(comparator) {
|
switch(comparator) {
|
||||||
case Comparator::EQ: if(data.wildcard(side(1)) == true) continue; break;
|
case Comparator::EQ: if(data.match(side(1)) == true) continue; break;
|
||||||
case Comparator::NE: if(data.wildcard(side(1)) == false) continue; break;
|
case Comparator::NE: if(data.match(side(1)) == false) continue; break;
|
||||||
case Comparator::LT: if(numeral(data) < numeral(side(1))) continue; break;
|
case Comparator::LT: if(numeral(data) < numeral(side(1))) continue; break;
|
||||||
case Comparator::LE: if(numeral(data) <= numeral(side(1))) continue; break;
|
case Comparator::LE: if(numeral(data) <= numeral(side(1))) continue; break;
|
||||||
case Comparator::GT: if(numeral(data) > numeral(side(1))) continue; break;
|
case Comparator::GT: if(numeral(data) > numeral(side(1))) continue; break;
|
||||||
|
@ -90,7 +90,7 @@ struct Node {
|
||||||
string name = path.take(0), rule;
|
string name = path.take(0), rule;
|
||||||
unsigned lo = 0u, hi = ~0u;
|
unsigned lo = 0u, hi = ~0u;
|
||||||
|
|
||||||
if(name.wildcard("*[*]")) {
|
if(name.match("*[*]")) {
|
||||||
lstring side = name.split<1>("[");
|
lstring side = name.split<1>("[");
|
||||||
name = side(0);
|
name = side(0);
|
||||||
side = side(1).rtrim<1>("]").split<1>("-");
|
side = side(1).rtrim<1>("]").split<1>("-");
|
||||||
|
@ -98,7 +98,7 @@ struct Node {
|
||||||
hi = side(1).empty() ? ~0u : numeral(side(1));
|
hi = side(1).empty() ? ~0u : numeral(side(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
if(name.wildcard("*(*)")) {
|
if(name.match("*(*)")) {
|
||||||
lstring side = name.split<1>("(");
|
lstring side = name.split<1>("(");
|
||||||
name = side(0);
|
name = side(0);
|
||||||
rule = side(1).rtrim<1>(")");
|
rule = side(1).rtrim<1>(")");
|
||||||
|
@ -106,7 +106,7 @@ struct Node {
|
||||||
|
|
||||||
unsigned position = 0;
|
unsigned position = 0;
|
||||||
for(auto& node : children) {
|
for(auto& node : children) {
|
||||||
if(node.name.wildcard(name) == false) continue;
|
if(node.name.match(name) == false) continue;
|
||||||
if(node.evaluate(rule) == false) continue;
|
if(node.evaluate(rule) == false) continue;
|
||||||
|
|
||||||
bool inrange = position >= lo && position <= hi;
|
bool inrange = position >= lo && position <= hi;
|
||||||
|
|
|
@ -13,8 +13,8 @@ struct stringref {
|
||||||
|
|
||||||
unsigned size() const {
|
unsigned size() const {
|
||||||
if(!_initialized) {
|
if(!_initialized) {
|
||||||
|
_initialized = true;
|
||||||
_size = strlen(_data);
|
_size = strlen(_data);
|
||||||
_initialized = 1;
|
|
||||||
}
|
}
|
||||||
return _size;
|
return _size;
|
||||||
}
|
}
|
||||||
|
@ -23,45 +23,21 @@ struct stringref {
|
||||||
stringref(const stringref& source) = delete;
|
stringref(const stringref& source) = delete;
|
||||||
stringref(stringref&& source) = delete;
|
stringref(stringref&& source) = delete;
|
||||||
|
|
||||||
template<typename T, typename... Args>
|
stringref(const char* source) {
|
||||||
stringref(T&& source, Args&&... args) {
|
_data = source;
|
||||||
if(sizeof...(Args) == 0) { construct(std::forward<T>(source)); _string = nullptr; return; }
|
_initialized = false;
|
||||||
_string = new string(std::forward<T>(source), std::forward<Args>(args)...);
|
|
||||||
_data = _string->data();
|
|
||||||
_size = _string->size();
|
|
||||||
_initialized = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
~stringref() {
|
stringref(const string& source) {
|
||||||
if(_string) delete _string;
|
_data = source.data();
|
||||||
|
_size = source.size();
|
||||||
|
_initialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
const char* _data;
|
const char* _data;
|
||||||
string* _string;
|
|
||||||
mutable unsigned _size;
|
mutable unsigned _size;
|
||||||
mutable bool _initialized;
|
mutable bool _initialized;
|
||||||
|
|
||||||
template<int size>
|
|
||||||
void construct(const char (&source)[size]) {
|
|
||||||
_data = source;
|
|
||||||
_size = size - 1;
|
|
||||||
_initialized = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T, typename = typename std::enable_if<std::is_same<T, char>::value>::type>
|
|
||||||
void construct(const T* source) {
|
|
||||||
_data = source;
|
|
||||||
_size = 0;
|
|
||||||
_initialized = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T, typename = typename std::enable_if<std::is_same<T, string>::value>::type>
|
|
||||||
void construct(const T& source) {
|
|
||||||
_data = source.data();
|
|
||||||
_size = source.size();
|
|
||||||
_initialized = 1;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,7 +79,7 @@ char* decimal(char* result, uintmax_t value) {
|
||||||
//using sprintf is certainly not the most ideal method to convert
|
//using sprintf is certainly not the most ideal method to convert
|
||||||
//a double to a string ... but attempting to parse a double by
|
//a double to a string ... but attempting to parse a double by
|
||||||
//hand, digit-by-digit, results in subtle rounding errors.
|
//hand, digit-by-digit, results in subtle rounding errors.
|
||||||
unsigned fp(char* str, long double value) {
|
unsigned real(char* str, long double value) {
|
||||||
char buffer[256];
|
char buffer[256];
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
//Windows C-runtime does not support long double via sprintf()
|
//Windows C-runtime does not support long double via sprintf()
|
||||||
|
@ -105,10 +105,10 @@ unsigned fp(char* str, long double value) {
|
||||||
return length + 1;
|
return length + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
string fp(long double value) {
|
string real(long double value) {
|
||||||
string temp;
|
string temp;
|
||||||
temp.reserve(fp(nullptr, value));
|
temp.resize(real(nullptr, value));
|
||||||
fp(temp.data(), value);
|
real(temp.data(), value);
|
||||||
return temp;
|
return temp;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,17 +7,25 @@ template<unsigned limit> lstring string::isplit(rstring key) const { lstring res
|
||||||
template<unsigned limit> lstring string::qsplit(rstring key) const { lstring result; result.qsplit<limit>(key, data()); return result; }
|
template<unsigned limit> lstring string::qsplit(rstring key) const { lstring result; result.qsplit<limit>(key, data()); return result; }
|
||||||
template<unsigned limit> lstring string::iqsplit(rstring key) const { lstring result; result.iqsplit<limit>(key, data()); return result; }
|
template<unsigned limit> lstring string::iqsplit(rstring key) const { lstring result; result.iqsplit<limit>(key, data()); return result; }
|
||||||
|
|
||||||
bool string::wildcard(rstring source) const { return nall::wildcard(data(), source); }
|
bool string::match(rstring source) const { return nall::strmatch(data(), source); }
|
||||||
bool string::iwildcard(rstring source) const { return nall::iwildcard(data(), source); }
|
bool string::imatch(rstring source) const { return nall::istrmatch(data(), source); }
|
||||||
|
|
||||||
|
signed string::compare(rstring source) const {
|
||||||
|
return strcmp(data(), source.data());
|
||||||
|
}
|
||||||
|
|
||||||
|
signed string::icompare(rstring source) const {
|
||||||
|
return istrcmp(data(), source.data());
|
||||||
|
}
|
||||||
|
|
||||||
bool string::equals(rstring source) const {
|
bool string::equals(rstring source) const {
|
||||||
if(size() != source.size()) return false;
|
if(size() != source.size()) return false;
|
||||||
return memcmp(data(), source.data(), source.size()) == 0;
|
return compare(source) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool string::iequals(rstring source) const {
|
bool string::iequals(rstring source) const {
|
||||||
if(size() != source.size()) return false;
|
if(size() != source.size()) return false;
|
||||||
return imemcmp(data(), source.data(), source.size()) == 0;
|
return icompare(source) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool string::beginswith(rstring source) const {
|
bool string::beginswith(rstring source) const {
|
||||||
|
@ -40,6 +48,12 @@ bool string::iendswith(rstring source) const {
|
||||||
return imemcmp(data() + size() - source.size(), source.data(), source.size()) == 0;
|
return imemcmp(data() + size() - source.size(), source.data(), source.size()) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
string string::slice(unsigned offset, unsigned length) const {
|
||||||
|
if(offset >= size()) return "";
|
||||||
|
if(length == ~0u) length = size() - offset;
|
||||||
|
return substr(data(), offset, length);
|
||||||
|
}
|
||||||
|
|
||||||
string& string::lower() { nall::strlower(data()); return *this; }
|
string& string::lower() { nall::strlower(data()); return *this; }
|
||||||
string& string::upper() { nall::strupper(data()); return *this; }
|
string& string::upper() { nall::strupper(data()); return *this; }
|
||||||
string& string::qlower() { nall::qstrlower(data()); return *this; }
|
string& string::qlower() { nall::qstrlower(data()); return *this; }
|
||||||
|
@ -82,9 +96,16 @@ template<unsigned Limit> string& string::rtrim(rstring key) {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<unsigned limit> string& string::trim(rstring key, rstring rkey) {
|
template<unsigned Limit> string& string::trim(rstring key) {
|
||||||
rtrim(rkey.size() ? rkey : key);
|
rtrim<Limit>(key);
|
||||||
return ltrim(key);
|
ltrim<Limit>(key);
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<unsigned Limit> string& string::trim(rstring lkey, rstring rkey) {
|
||||||
|
rtrim<Limit>(rkey);
|
||||||
|
ltrim<Limit>(lkey);
|
||||||
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
string& string::strip() {
|
string& string::strip() {
|
||||||
|
@ -93,10 +114,10 @@ string& string::strip() {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<unsigned> string::position(rstring key) const { return strpos(data(), key); }
|
optional<unsigned> string::find(rstring key) const { return strpos(data(), key); }
|
||||||
optional<unsigned> string::iposition(rstring key) const { return istrpos(data(), key); }
|
optional<unsigned> string::ifind(rstring key) const { return istrpos(data(), key); }
|
||||||
optional<unsigned> string::qposition(rstring key) const { return qstrpos(data(), key); }
|
optional<unsigned> string::qfind(rstring key) const { return qstrpos(data(), key); }
|
||||||
optional<unsigned> string::iqposition(rstring key) const { return iqstrpos(data(), key); }
|
optional<unsigned> string::iqfind(rstring key) const { return iqstrpos(data(), key); }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <nall/any.hpp>
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
|
|
||||||
|
@ -11,6 +12,22 @@ template<typename T> struct base_from_member {
|
||||||
base_from_member(T value) : value(value) {}
|
base_from_member(T value) : value(value) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename T> struct ref {
|
||||||
|
T& operator*() {
|
||||||
|
if(type == Type::Reference) return *any_cast<T*>(value);
|
||||||
|
return any_cast<T&>(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
operator T&() { return operator*(); }
|
||||||
|
|
||||||
|
ref(T& value) : type(Type::Reference), value(&value) {}
|
||||||
|
ref(T&& value) : type(Type::Temporary), value(value) {}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
enum class Type : unsigned { Reference, Temporary } type;
|
||||||
|
any value;
|
||||||
|
};
|
||||||
|
|
||||||
template<typename TT> struct optional {
|
template<typename TT> struct optional {
|
||||||
typedef typename std::remove_reference<TT>::type T;
|
typedef typename std::remove_reference<TT>::type T;
|
||||||
static const bool isConst = std::is_const<TT>::value;
|
static const bool isConst = std::is_const<TT>::value;
|
||||||
|
@ -30,12 +47,23 @@ template<typename TT> struct optional {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename = typename std::enable_if<!isConst>::type>
|
||||||
|
T& operator*() {
|
||||||
|
if(!valid) throw optional_value_not_valid{};
|
||||||
|
return *value;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename = typename std::enable_if<!isConst>::type>
|
template<typename = typename std::enable_if<!isConst>::type>
|
||||||
T& operator()() {
|
T& operator()() {
|
||||||
if(!valid) throw optional_value_not_valid{};
|
if(!valid) throw optional_value_not_valid{};
|
||||||
return *value;
|
return *value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const T& operator*() const {
|
||||||
|
if(!valid) throw optional_value_not_valid{};
|
||||||
|
return *value;
|
||||||
|
}
|
||||||
|
|
||||||
const T& operator()() const {
|
const T& operator()() const {
|
||||||
if(!valid) throw optional_value_not_valid{};
|
if(!valid) throw optional_value_not_valid{};
|
||||||
return *value;
|
return *value;
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
#define NALL_VARINT_HPP
|
#define NALL_VARINT_HPP
|
||||||
|
|
||||||
#include <nall/bit.hpp>
|
#include <nall/bit.hpp>
|
||||||
|
#include <nall/serializer.hpp>
|
||||||
#include <nall/traits.hpp>
|
#include <nall/traits.hpp>
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
|
@ -34,6 +35,8 @@ public:
|
||||||
|
|
||||||
template<unsigned s> inline type_t operator=(const uint_t<s> &i) { return data = uclip<bits>((type_t)i); }
|
template<unsigned s> inline type_t operator=(const uint_t<s> &i) { return data = uclip<bits>((type_t)i); }
|
||||||
template<unsigned s> inline uint_t(const uint_t<s> &i) : data(uclip<bits>(i)) {}
|
template<unsigned s> inline uint_t(const uint_t<s> &i) : data(uclip<bits>(i)) {}
|
||||||
|
|
||||||
|
void serialize(serializer& s) { s(data); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template<unsigned bits> struct int_t {
|
template<unsigned bits> struct int_t {
|
||||||
|
@ -64,6 +67,8 @@ public:
|
||||||
|
|
||||||
template<unsigned s> inline type_t operator=(const int_t<s> &i) { return data = sclip<bits>((type_t)i); }
|
template<unsigned s> inline type_t operator=(const int_t<s> &i) { return data = sclip<bits>((type_t)i); }
|
||||||
template<unsigned s> inline int_t(const int_t<s> &i) : data(sclip<bits>(i)) {}
|
template<unsigned s> inline int_t(const int_t<s> &i) : data(sclip<bits>(i)) {}
|
||||||
|
|
||||||
|
void serialize(serializer& s) { s(data); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename type_t> struct varuint_t {
|
template<typename type_t> struct varuint_t {
|
||||||
|
@ -92,6 +97,8 @@ public:
|
||||||
inline void bits(type_t bits) { mask = (1ull << (bits - 1)) + ((1ull << (bits - 1)) - 1); data &= mask; }
|
inline void bits(type_t bits) { mask = (1ull << (bits - 1)) + ((1ull << (bits - 1)) - 1); data &= mask; }
|
||||||
inline varuint_t() : data(0ull), mask((type_t)~0ull) {}
|
inline varuint_t() : data(0ull), mask((type_t)~0ull) {}
|
||||||
inline varuint_t(const type_t i) : data(i), mask((type_t)~0ull) {}
|
inline varuint_t(const type_t i) : data(i), mask((type_t)~0ull) {}
|
||||||
|
|
||||||
|
void serialize(serializer& s) { s(data); s(mask); }
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -77,7 +77,7 @@ public:
|
||||||
prepend(data);
|
prepend(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void prepend(const T& data) {
|
T& prepend(const T& data) {
|
||||||
reserve(objectsize + 1);
|
reserve(objectsize + 1);
|
||||||
if(poolbase == 0) {
|
if(poolbase == 0) {
|
||||||
unsigned available = poolsize - objectsize;
|
unsigned available = poolsize - objectsize;
|
||||||
|
@ -88,6 +88,7 @@ public:
|
||||||
}
|
}
|
||||||
new(pool + --poolbase) T(data);
|
new(pool + --poolbase) T(data);
|
||||||
objectsize++;
|
objectsize++;
|
||||||
|
return first();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename... Args> void append(const T& data, Args&&... args) {
|
template<typename... Args> void append(const T& data, Args&&... args) {
|
||||||
|
@ -95,9 +96,10 @@ public:
|
||||||
append(std::forward<Args>(args)...);
|
append(std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
void append(const T& data) {
|
T& append(const T& data) {
|
||||||
reserve(poolbase + objectsize + 1);
|
reserve(poolbase + objectsize + 1);
|
||||||
new(pool + poolbase + objectsize++) T(data);
|
new(pool + poolbase + objectsize++) T(data);
|
||||||
|
return last();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool appendonce(const T& data) {
|
bool appendonce(const T& data) {
|
||||||
|
|
|
@ -33,7 +33,7 @@ void pCheckItem::setChecked(bool checked) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pCheckItem::setText(const string& text) {
|
void pCheckItem::setText(string text) {
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
[cocoaAction setTitle:[NSString stringWithUTF8String:text]];
|
[cocoaAction setTitle:[NSString stringWithUTF8String:text]];
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ struct pCheckItem : public pAction {
|
||||||
|
|
||||||
bool checked();
|
bool checked();
|
||||||
void setChecked(bool checked);
|
void setChecked(bool checked);
|
||||||
void setText(const string& text);
|
void setText(string text);
|
||||||
|
|
||||||
pCheckItem(CheckItem& checkItem) : pAction(checkItem), checkItem(checkItem) {}
|
pCheckItem(CheckItem& checkItem) : pAction(checkItem), checkItem(checkItem) {}
|
||||||
void constructor();
|
void constructor();
|
||||||
|
|
|
@ -24,7 +24,7 @@ void pItem::setImage(const image& image) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pItem::setText(const string& text) {
|
void pItem::setText(string text) {
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
[cocoaAction setTitle:[NSString stringWithUTF8String:text]];
|
[cocoaAction setTitle:[NSString stringWithUTF8String:text]];
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,7 +13,7 @@ struct pItem : public pAction {
|
||||||
CocoaItem* cocoaItem = nullptr;
|
CocoaItem* cocoaItem = nullptr;
|
||||||
|
|
||||||
void setImage(const image& image);
|
void setImage(const image& image);
|
||||||
void setText(const string& text);
|
void setText(string text);
|
||||||
|
|
||||||
pItem(Item& item) : pAction(item), item(item) {}
|
pItem(Item& item) : pAction(item), item(item) {}
|
||||||
void constructor();
|
void constructor();
|
||||||
|
|
|
@ -37,7 +37,7 @@ void pMenu::setImage(const image& image) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pMenu::setText(const string& text) {
|
void pMenu::setText(string text) {
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
[[cocoaAction cocoaMenu] setTitle:[NSString stringWithUTF8String:text]];
|
[[cocoaAction cocoaMenu] setTitle:[NSString stringWithUTF8String:text]];
|
||||||
[cocoaAction setTitle:[NSString stringWithUTF8String:text]];
|
[cocoaAction setTitle:[NSString stringWithUTF8String:text]];
|
||||||
|
|
|
@ -16,7 +16,7 @@ struct pMenu : public pAction {
|
||||||
void append(Action& action);
|
void append(Action& action);
|
||||||
void remove(Action& action);
|
void remove(Action& action);
|
||||||
void setImage(const image& image);
|
void setImage(const image& image);
|
||||||
void setText(const string& text);
|
void setText(string text);
|
||||||
|
|
||||||
pMenu(Menu& menu) : pAction(menu), menu(menu) {}
|
pMenu(Menu& menu) : pAction(menu), menu(menu) {}
|
||||||
void constructor();
|
void constructor();
|
||||||
|
|
|
@ -37,7 +37,7 @@ void pRadioItem::setChecked() {
|
||||||
void pRadioItem::setGroup(const group<RadioItem>& group) {
|
void pRadioItem::setGroup(const group<RadioItem>& group) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void pRadioItem::setText(const string& text) {
|
void pRadioItem::setText(string text) {
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
[cocoaAction setTitle:[NSString stringWithUTF8String:text]];
|
[cocoaAction setTitle:[NSString stringWithUTF8String:text]];
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ struct pRadioItem : public pAction {
|
||||||
bool checked();
|
bool checked();
|
||||||
void setChecked();
|
void setChecked();
|
||||||
void setGroup(const group<RadioItem>& group);
|
void setGroup(const group<RadioItem>& group);
|
||||||
void setText(const string& text);
|
void setText(string text);
|
||||||
|
|
||||||
pRadioItem(RadioItem& radioItem) : pAction(radioItem), radioItem(radioItem) {}
|
pRadioItem(RadioItem& radioItem) : pAction(radioItem), radioItem(radioItem) {}
|
||||||
void constructor();
|
void constructor();
|
||||||
|
|
|
@ -50,7 +50,7 @@ string pBrowserWindow::save(BrowserWindow::State& state) {
|
||||||
NSMutableArray* filters = [[NSMutableArray alloc] init];
|
NSMutableArray* filters = [[NSMutableArray alloc] init];
|
||||||
for(auto& rule : state.filters) {
|
for(auto& rule : state.filters) {
|
||||||
string pattern = rule.split<1>("(")(1).rtrim<1>(")");
|
string pattern = rule.split<1>("(")(1).rtrim<1>(")");
|
||||||
if(!pattern.empty()) [filters addObjects:[NSString stringWithUTF8String:pattern]];
|
if(!pattern.empty()) [filters addObject:[NSString stringWithUTF8String:pattern]];
|
||||||
}
|
}
|
||||||
NSSavePanel* panel = [NSSavePanel savePanel];
|
NSSavePanel* panel = [NSSavePanel savePanel];
|
||||||
if(state.title) [panel setTitle:[NSString stringWithUTF8String:state.title]];
|
if(state.title) [panel setTitle:[NSString stringWithUTF8String:state.title]];
|
||||||
|
|
|
@ -18,7 +18,7 @@ string pFont::monospace(unsigned size, string style) {
|
||||||
return {"Menlo, ", size, ", ", style};
|
return {"Menlo, ", size, ", ", style};
|
||||||
}
|
}
|
||||||
|
|
||||||
Size pFont::size(const string& font, const string& text) {
|
Size pFont::size(string font, string text) {
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
if(NSFont* nsFont = cocoaFont(font)) {
|
if(NSFont* nsFont = cocoaFont(font)) {
|
||||||
return size(nsFont, text);
|
return size(nsFont, text);
|
||||||
|
@ -27,27 +27,26 @@ Size pFont::size(const string& font, const string& text) {
|
||||||
return {0, 0};
|
return {0, 0};
|
||||||
}
|
}
|
||||||
|
|
||||||
NSFont* pFont::cocoaFont(const string& description) {
|
NSFont* pFont::cocoaFont(string description) {
|
||||||
lstring part = description.split<2>(",");
|
lstring part = description.split<2>(",").strip();
|
||||||
for(auto& item : part) item.strip();
|
|
||||||
|
|
||||||
NSString* family = @"Lucida Grande";
|
NSString* family = @"Lucida Grande";
|
||||||
NSFontTraitMask traits = 0;
|
NSFontTraitMask traits = 0;
|
||||||
CGFloat size = 12;
|
CGFloat size = 12;
|
||||||
|
|
||||||
if(!part(0).empty()) family = [NSString stringWithUTF8String:part(0)];
|
if(!part(0).empty()) family = [NSString stringWithUTF8String:part(0)];
|
||||||
if(!part(1).empty()) size = fp(part(1));
|
if(!part(1).empty()) size = real(part(1));
|
||||||
if(part(2).iposition("bold")) traits |= NSBoldFontMask;
|
if(part(2).ifind("bold")) traits |= NSBoldFontMask;
|
||||||
if(part(2).iposition("italic")) traits |= NSItalicFontMask;
|
if(part(2).ifind("italic")) traits |= NSItalicFontMask;
|
||||||
if(part(2).iposition("narrow")) traits |= NSNarrowFontMask;
|
if(part(2).ifind("narrow")) traits |= NSNarrowFontMask;
|
||||||
if(part(2).iposition("expanded")) traits |= NSExpandedFontMask;
|
if(part(2).ifind("expanded")) traits |= NSExpandedFontMask;
|
||||||
if(part(2).iposition("condensed")) traits |= NSCondensedFontMask;
|
if(part(2).ifind("condensed")) traits |= NSCondensedFontMask;
|
||||||
if(part(2).iposition("smallcaps")) traits |= NSSmallCapsFontMask;
|
if(part(2).ifind("smallcaps")) traits |= NSSmallCapsFontMask;
|
||||||
|
|
||||||
return [[NSFontManager sharedFontManager] fontWithFamily:family traits:traits weight:5 size:size];
|
return [[NSFontManager sharedFontManager] fontWithFamily:family traits:traits weight:5 size:size];
|
||||||
}
|
}
|
||||||
|
|
||||||
Size pFont::size(NSFont* font, const string& text) {
|
Size pFont::size(NSFont* font, string text) {
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
NSString* cocoaText = [NSString stringWithUTF8String:text];
|
NSString* cocoaText = [NSString stringWithUTF8String:text];
|
||||||
NSDictionary* fontAttributes = [NSDictionary dictionaryWithObjectsAndKeys:font, NSFontAttributeName, nil];
|
NSDictionary* fontAttributes = [NSDictionary dictionaryWithObjectsAndKeys:font, NSFontAttributeName, nil];
|
||||||
|
|
|
@ -4,10 +4,10 @@ struct pFont {
|
||||||
static string serif(unsigned size, string style);
|
static string serif(unsigned size, string style);
|
||||||
static string sans(unsigned size, string style);
|
static string sans(unsigned size, string style);
|
||||||
static string monospace(unsigned size, string style);
|
static string monospace(unsigned size, string style);
|
||||||
static Size size(const string& font, const string& text);
|
static Size size(string font, string text);
|
||||||
|
|
||||||
static NSFont* cocoaFont(const string& description);
|
static NSFont* cocoaFont(string description);
|
||||||
static Size size(NSFont* font, const string& text);
|
static Size size(NSFont* font, string text);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,3 +15,27 @@ NSImage* NSMakeImage(nall::image image, unsigned width = 0, unsigned height = 0)
|
||||||
[cocoaImage addRepresentation:bitmap];
|
[cocoaImage addRepresentation:bitmap];
|
||||||
return cocoaImage;
|
return cocoaImage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NSDragOperation DropPathsOperation(id<NSDraggingInfo> sender) {
|
||||||
|
NSPasteboard* pboard = [sender draggingPasteboard];
|
||||||
|
if([[pboard types] containsObject:NSFilenamesPboardType]) {
|
||||||
|
if([sender draggingSourceOperationMask] & NSDragOperationGeneric) {
|
||||||
|
return NSDragOperationGeneric;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return NSDragOperationNone;
|
||||||
|
}
|
||||||
|
|
||||||
|
lstring DropPaths(id<NSDraggingInfo> sender) {
|
||||||
|
lstring paths;
|
||||||
|
NSPasteboard* pboard = [sender draggingPasteboard];
|
||||||
|
if([[pboard types] containsObject:NSFilenamesPboardType]) {
|
||||||
|
NSArray* files = [pboard propertyListForType:NSFilenamesPboardType];
|
||||||
|
for(unsigned n = 0; n < [files count]; n++) {
|
||||||
|
string path = [[files objectAtIndex:n] UTF8String];
|
||||||
|
if(directory::exists(path) && !path.endswith("/")) path.append("/");
|
||||||
|
paths.append(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return paths;
|
||||||
|
}
|
||||||
|
|
|
@ -35,7 +35,7 @@ Size pButton::minimumSize() {
|
||||||
return {size.width + 20, size.height + 4};
|
return {size.width + 20, size.height + 4};
|
||||||
}
|
}
|
||||||
|
|
||||||
void pButton::setGeometry(const Geometry& geometry) {
|
void pButton::setGeometry(Geometry geometry) {
|
||||||
pWidget::setGeometry({
|
pWidget::setGeometry({
|
||||||
geometry.x - 2, geometry.y - 2,
|
geometry.x - 2, geometry.y - 2,
|
||||||
geometry.width + 4, geometry.height + 4
|
geometry.width + 4, geometry.height + 4
|
||||||
|
@ -56,7 +56,7 @@ void pButton::setImage(const image& image, Orientation orientation) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pButton::setText(const string& text) {
|
void pButton::setText(string text) {
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
[cocoaView setTitle:[NSString stringWithUTF8String:text]];
|
[cocoaView setTitle:[NSString stringWithUTF8String:text]];
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,9 +13,9 @@ struct pButton : public pWidget {
|
||||||
CocoaButton* cocoaButton = nullptr;
|
CocoaButton* cocoaButton = nullptr;
|
||||||
|
|
||||||
Size minimumSize();
|
Size minimumSize();
|
||||||
void setGeometry(const Geometry& geometry);
|
void setGeometry(Geometry geometry);
|
||||||
void setImage(const image& image, Orientation orientation);
|
void setImage(const image& image, Orientation orientation);
|
||||||
void setText(const string& text);
|
void setText(string text);
|
||||||
|
|
||||||
pButton(Button& button) : pWidget(button), button(button) {}
|
pButton(Button& button) : pWidget(button), button(button) {}
|
||||||
void constructor();
|
void constructor();
|
||||||
|
|
|
@ -13,6 +13,17 @@
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-(NSDragOperation) draggingEntered:(id<NSDraggingInfo>)sender {
|
||||||
|
return DropPathsOperation(sender);
|
||||||
|
}
|
||||||
|
|
||||||
|
-(BOOL) performDragOperation:(id<NSDraggingInfo>)sender {
|
||||||
|
lstring paths = DropPaths(sender);
|
||||||
|
if(paths.empty()) return NO;
|
||||||
|
if(canvas->onDrop) canvas->onDrop(paths);
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
-(void) mouseButton:(NSEvent*)event down:(BOOL)isDown {
|
-(void) mouseButton:(NSEvent*)event down:(BOOL)isDown {
|
||||||
if(auto &callback = isDown ? canvas->onMousePress : canvas->onMouseRelease) {
|
if(auto &callback = isDown ? canvas->onMousePress : canvas->onMouseRelease) {
|
||||||
switch([event buttonNumber]) {
|
switch([event buttonNumber]) {
|
||||||
|
@ -73,7 +84,17 @@
|
||||||
|
|
||||||
namespace phoenix {
|
namespace phoenix {
|
||||||
|
|
||||||
void pCanvas::setSize(const Size& size) {
|
void pCanvas::setDroppable(bool droppable) {
|
||||||
|
@autoreleasepool {
|
||||||
|
if(droppable) {
|
||||||
|
[cocoaCanvas registerForDraggedTypes:[NSArray arrayWithObject:NSFilenamesPboardType]];
|
||||||
|
} else {
|
||||||
|
[cocoaCanvas unregisterDraggedTypes];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void pCanvas::setSize(Size size) {
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
NSImage* image = [[[NSImage alloc] initWithSize:NSMakeSize(size.width, size.height)] autorelease];
|
NSImage* image = [[[NSImage alloc] initWithSize:NSMakeSize(size.width, size.height)] autorelease];
|
||||||
NSBitmapImageRep* bitmap = [[[NSBitmapImageRep alloc]
|
NSBitmapImageRep* bitmap = [[[NSBitmapImageRep alloc]
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
phoenix::Canvas* canvas;
|
phoenix::Canvas* canvas;
|
||||||
}
|
}
|
||||||
-(id) initWith:(phoenix::Canvas&)canvas;
|
-(id) initWith:(phoenix::Canvas&)canvas;
|
||||||
|
-(NSDragOperation) draggingEntered:(id<NSDraggingInfo>)sender;
|
||||||
|
-(BOOL) performDragOperation:(id<NSDraggingInfo>)sender;
|
||||||
-(void) mouseButton:(NSEvent*)event down:(BOOL)isDown;
|
-(void) mouseButton:(NSEvent*)event down:(BOOL)isDown;
|
||||||
-(void) mouseExited:(NSEvent*)event;
|
-(void) mouseExited:(NSEvent*)event;
|
||||||
-(void) mouseMove:(NSEvent*)event;
|
-(void) mouseMove:(NSEvent*)event;
|
||||||
|
@ -23,7 +25,8 @@ struct pCanvas : public pWidget {
|
||||||
Canvas& canvas;
|
Canvas& canvas;
|
||||||
CocoaCanvas* cocoaCanvas = nullptr;
|
CocoaCanvas* cocoaCanvas = nullptr;
|
||||||
|
|
||||||
void setSize(const Size& size);
|
void setDroppable(bool droppable);
|
||||||
|
void setSize(Size size);
|
||||||
void update();
|
void update();
|
||||||
|
|
||||||
pCanvas(Canvas& canvas) : pWidget(canvas), canvas(canvas) {}
|
pCanvas(Canvas& canvas) : pWidget(canvas), canvas(canvas) {}
|
||||||
|
|
|
@ -37,14 +37,14 @@ void pCheckButton::setChecked(bool checked) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pCheckButton::setGeometry(const Geometry& geometry) {
|
void pCheckButton::setGeometry(Geometry geometry) {
|
||||||
pWidget::setGeometry({
|
pWidget::setGeometry({
|
||||||
geometry.x - 2, geometry.y,
|
geometry.x - 2, geometry.y,
|
||||||
geometry.width + 4, geometry.height
|
geometry.width + 4, geometry.height
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void pCheckButton::setText(const string& text) {
|
void pCheckButton::setText(string text) {
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
[cocoaView setTitle:[NSString stringWithUTF8String:text]];
|
[cocoaView setTitle:[NSString stringWithUTF8String:text]];
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,8 +15,8 @@ struct pCheckButton : public pWidget {
|
||||||
bool checked();
|
bool checked();
|
||||||
Size minimumSize();
|
Size minimumSize();
|
||||||
void setChecked(bool checked);
|
void setChecked(bool checked);
|
||||||
void setGeometry(const Geometry& geometry);
|
void setGeometry(Geometry geometry);
|
||||||
void setText(const string& text);
|
void setText(string text);
|
||||||
|
|
||||||
pCheckButton(CheckButton& checkButton) : pWidget(checkButton), checkButton(checkButton) {}
|
pCheckButton(CheckButton& checkButton) : pWidget(checkButton), checkButton(checkButton) {}
|
||||||
void constructor();
|
void constructor();
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
namespace phoenix {
|
namespace phoenix {
|
||||||
|
|
||||||
void pComboButton::append(const string& text) {
|
void pComboButton::append(string text) {
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
[cocoaView addItemWithTitle:[NSString stringWithUTF8String:text]];
|
[cocoaView addItemWithTitle:[NSString stringWithUTF8String:text]];
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ Size pComboButton::minimumSize() {
|
||||||
return {maximumWidth + 36, size.height + 6};
|
return {maximumWidth + 36, size.height + 6};
|
||||||
}
|
}
|
||||||
|
|
||||||
void pComboButton::modify(unsigned row, const string& text) {
|
void pComboButton::modify(unsigned row, string text) {
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
[[cocoaView itemAtIndex:row] setTitle:[NSString stringWithUTF8String:text]];
|
[[cocoaView itemAtIndex:row] setTitle:[NSString stringWithUTF8String:text]];
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ unsigned pComboButton::selection() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pComboButton::setGeometry(const Geometry& geometry) {
|
void pComboButton::setGeometry(Geometry geometry) {
|
||||||
pWidget::setGeometry({
|
pWidget::setGeometry({
|
||||||
geometry.x - 2, geometry.y,
|
geometry.x - 2, geometry.y,
|
||||||
geometry.width + 4, geometry.height
|
geometry.width + 4, geometry.height
|
||||||
|
|
|
@ -12,13 +12,13 @@ struct pComboButton : public pWidget {
|
||||||
ComboButton& comboButton;
|
ComboButton& comboButton;
|
||||||
CocoaComboButton* cocoaComboButton = nullptr;
|
CocoaComboButton* cocoaComboButton = nullptr;
|
||||||
|
|
||||||
void append(const string& text);
|
void append(string text);
|
||||||
Size minimumSize();
|
Size minimumSize();
|
||||||
void modify(unsigned row, const string& text);
|
void modify(unsigned row, string text);
|
||||||
void remove(unsigned row);
|
void remove(unsigned row);
|
||||||
void reset();
|
void reset();
|
||||||
unsigned selection();
|
unsigned selection();
|
||||||
void setGeometry(const Geometry& geometry);
|
void setGeometry(Geometry geometry);
|
||||||
void setSelection(unsigned row);
|
void setSelection(unsigned row);
|
||||||
|
|
||||||
pComboButton(ComboButton& comboButton) : pWidget(comboButton), comboButton(comboButton) {}
|
pComboButton(ComboButton& comboButton) : pWidget(comboButton), comboButton(comboButton) {}
|
||||||
|
|
|
@ -30,7 +30,7 @@ unsigned pHorizontalSlider::position() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pHorizontalSlider::setGeometry(const Geometry& geometry) {
|
void pHorizontalSlider::setGeometry(Geometry geometry) {
|
||||||
pWidget::setGeometry({
|
pWidget::setGeometry({
|
||||||
geometry.x - 2, geometry.y,
|
geometry.x - 2, geometry.y,
|
||||||
geometry.width + 4, geometry.height
|
geometry.width + 4, geometry.height
|
||||||
|
|
|
@ -14,7 +14,7 @@ struct pHorizontalSlider : public pWidget {
|
||||||
|
|
||||||
Size minimumSize();
|
Size minimumSize();
|
||||||
unsigned position();
|
unsigned position();
|
||||||
void setGeometry(const Geometry& geometry);
|
void setGeometry(Geometry geometry);
|
||||||
void setLength(unsigned length);
|
void setLength(unsigned length);
|
||||||
void setPosition(unsigned position);
|
void setPosition(unsigned position);
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ Size pLabel::minimumSize() {
|
||||||
return {size.width, size.height};
|
return {size.width, size.height};
|
||||||
}
|
}
|
||||||
|
|
||||||
void pLabel::setGeometry(const Geometry& geometry) {
|
void pLabel::setGeometry(Geometry geometry) {
|
||||||
//NSTextField does not support vertical text centering:
|
//NSTextField does not support vertical text centering:
|
||||||
//simulate this by adjusting the geometry placement (reduce height, move view down)
|
//simulate this by adjusting the geometry placement (reduce height, move view down)
|
||||||
unsigned height = Font::size(label.font(), " ").height;
|
unsigned height = Font::size(label.font(), " ").height;
|
||||||
|
@ -40,7 +40,7 @@ void pLabel::setGeometry(const Geometry& geometry) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void pLabel::setText(const string& text) {
|
void pLabel::setText(string text) {
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
[cocoaView setStringValue:[NSString stringWithUTF8String:text]];
|
[cocoaView setStringValue:[NSString stringWithUTF8String:text]];
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,8 +12,8 @@ struct pLabel : public pWidget {
|
||||||
CocoaLabel* cocoaLabel = nullptr;
|
CocoaLabel* cocoaLabel = nullptr;
|
||||||
|
|
||||||
Size minimumSize();
|
Size minimumSize();
|
||||||
void setGeometry(const Geometry& geometry);
|
void setGeometry(Geometry geometry);
|
||||||
void setText(const string& text);
|
void setText(string text);
|
||||||
|
|
||||||
pLabel(Label& label) : pWidget(label), label(label) {}
|
pLabel(Label& label) : pWidget(label), label(label) {}
|
||||||
void constructor();
|
void constructor();
|
||||||
|
|
|
@ -37,7 +37,7 @@ void pLineEdit::setEditable(bool editable) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pLineEdit::setText(const string& text) {
|
void pLineEdit::setText(string text) {
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
[cocoaView setStringValue:[NSString stringWithUTF8String:text]];
|
[cocoaView setStringValue:[NSString stringWithUTF8String:text]];
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ struct pLineEdit : public pWidget {
|
||||||
|
|
||||||
Size minimumSize();
|
Size minimumSize();
|
||||||
void setEditable(bool editable);
|
void setEditable(bool editable);
|
||||||
void setText(const string& text);
|
void setText(string text);
|
||||||
string text();
|
string text();
|
||||||
|
|
||||||
pLineEdit(LineEdit& lineEdit) : pWidget(lineEdit), lineEdit(lineEdit) {}
|
pLineEdit(LineEdit& lineEdit) : pWidget(lineEdit), lineEdit(lineEdit) {}
|
||||||
|
|
|
@ -285,7 +285,7 @@ void pListView::setChecked(unsigned row, bool checked) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pListView::setFont(const string& font) {
|
void pListView::setFont(string font) {
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
[cocoaView setFont:pFont::cocoaFont(font)];
|
[cocoaView setFont:pFont::cocoaFont(font)];
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,7 +50,7 @@ struct pListView : public pWidget {
|
||||||
unsigned selection();
|
unsigned selection();
|
||||||
void setCheckable(bool checkable);
|
void setCheckable(bool checkable);
|
||||||
void setChecked(unsigned row, bool checked);
|
void setChecked(unsigned row, bool checked);
|
||||||
void setFont(const string& font);
|
void setFont(string font);
|
||||||
void setHeaderText(const lstring& text);
|
void setHeaderText(const lstring& text);
|
||||||
void setHeaderVisible(bool visible);
|
void setHeaderVisible(bool visible);
|
||||||
void setImage(unsigned row, unsigned column, const image& image);
|
void setImage(unsigned row, unsigned column, const image& image);
|
||||||
|
|
|
@ -40,7 +40,7 @@ void pRadioButton::setChecked() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pRadioButton::setGeometry(const Geometry& geometry) {
|
void pRadioButton::setGeometry(Geometry geometry) {
|
||||||
pWidget::setGeometry({
|
pWidget::setGeometry({
|
||||||
geometry.x - 1, geometry.y,
|
geometry.x - 1, geometry.y,
|
||||||
geometry.width + 2, geometry.height
|
geometry.width + 2, geometry.height
|
||||||
|
@ -50,7 +50,7 @@ void pRadioButton::setGeometry(const Geometry& geometry) {
|
||||||
void pRadioButton::setGroup(const group<RadioButton>& group) {
|
void pRadioButton::setGroup(const group<RadioButton>& group) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void pRadioButton::setText(const string& text) {
|
void pRadioButton::setText(string text) {
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
[cocoaView setTitle:[NSString stringWithUTF8String:text]];
|
[cocoaView setTitle:[NSString stringWithUTF8String:text]];
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,9 +15,9 @@ struct pRadioButton : public pWidget {
|
||||||
bool checked();
|
bool checked();
|
||||||
Size minimumSize();
|
Size minimumSize();
|
||||||
void setChecked();
|
void setChecked();
|
||||||
void setGeometry(const Geometry& geometry);
|
void setGeometry(Geometry geometry);
|
||||||
void setGroup(const group<RadioButton>& group);
|
void setGroup(const group<RadioButton>& group);
|
||||||
void setText(const string& text);
|
void setText(string text);
|
||||||
|
|
||||||
pRadioButton(RadioButton& radioButton) : pWidget(radioButton), radioButton(radioButton) {}
|
pRadioButton(RadioButton& radioButton) : pWidget(radioButton), radioButton(radioButton) {}
|
||||||
void constructor();
|
void constructor();
|
||||||
|
|
|
@ -57,13 +57,13 @@ void pTextEdit::setEditable(bool editable) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pTextEdit::setFont(const string& font) {
|
void pTextEdit::setFont(string font) {
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
[[cocoaView content] setFont:pFont::cocoaFont(font)];
|
[[cocoaView content] setFont:pFont::cocoaFont(font)];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pTextEdit::setText(const string& text) {
|
void pTextEdit::setText(string text) {
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
[[cocoaView content] setString:[NSString stringWithUTF8String:text]];
|
[[cocoaView content] setString:[NSString stringWithUTF8String:text]];
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,8 +17,8 @@ struct pTextEdit : public pWidget {
|
||||||
|
|
||||||
void setCursorPosition(unsigned position);
|
void setCursorPosition(unsigned position);
|
||||||
void setEditable(bool editable);
|
void setEditable(bool editable);
|
||||||
void setFont(const string& font);
|
void setFont(string font);
|
||||||
void setText(const string& text);
|
void setText(string text);
|
||||||
void setWordWrap(bool wordWrap);
|
void setWordWrap(bool wordWrap);
|
||||||
string text();
|
string text();
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@ unsigned pVerticalSlider::position() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pVerticalSlider::setGeometry(const Geometry& geometry) {
|
void pVerticalSlider::setGeometry(Geometry geometry) {
|
||||||
pWidget::setGeometry({
|
pWidget::setGeometry({
|
||||||
geometry.x, geometry.y - 2,
|
geometry.x, geometry.y - 2,
|
||||||
geometry.width, geometry.height + 4
|
geometry.width, geometry.height + 4
|
||||||
|
|
|
@ -14,7 +14,7 @@ struct pVerticalSlider : public pWidget {
|
||||||
|
|
||||||
Size minimumSize();
|
Size minimumSize();
|
||||||
unsigned position();
|
unsigned position();
|
||||||
void setGeometry(const Geometry& geometry);
|
void setGeometry(Geometry geometry);
|
||||||
void setLength(unsigned length);
|
void setLength(unsigned length);
|
||||||
void setPosition(unsigned position);
|
void setPosition(unsigned position);
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,17 @@
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-(NSDragOperation) draggingEntered:(id<NSDraggingInfo>)sender {
|
||||||
|
return DropPathsOperation(sender);
|
||||||
|
}
|
||||||
|
|
||||||
|
-(BOOL) performDragOperation:(id<NSDraggingInfo>)sender {
|
||||||
|
lstring paths = DropPaths(sender);
|
||||||
|
if(paths.empty()) return NO;
|
||||||
|
if(viewport->onDrop) viewport->onDrop(paths);
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
-(void) keyDown:(NSEvent*)event {
|
-(void) keyDown:(NSEvent*)event {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,6 +41,16 @@ uintptr_t pViewport::handle() {
|
||||||
return (uintptr_t)cocoaViewport;
|
return (uintptr_t)cocoaViewport;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pViewport::setDroppable(bool droppable) {
|
||||||
|
@autoreleasepool {
|
||||||
|
if(droppable) {
|
||||||
|
[cocoaViewport registerForDraggedTypes:[NSArray arrayWithObject:NSFilenamesPboardType]];
|
||||||
|
} else {
|
||||||
|
[cocoaViewport unregisterDraggedTypes];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void pViewport::constructor() {
|
void pViewport::constructor() {
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
cocoaView = cocoaViewport = [[CocoaViewport alloc] initWith:viewport];
|
cocoaView = cocoaViewport = [[CocoaViewport alloc] initWith:viewport];
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
-(id) initWith:(phoenix::Viewport&)viewport;
|
-(id) initWith:(phoenix::Viewport&)viewport;
|
||||||
-(void) drawRect:(NSRect)rect;
|
-(void) drawRect:(NSRect)rect;
|
||||||
-(BOOL) acceptsFirstResponder;
|
-(BOOL) acceptsFirstResponder;
|
||||||
|
-(NSDragOperation) draggingEntered:(id<NSDraggingInfo>)sender;
|
||||||
|
-(BOOL) performDragOperation:(id<NSDraggingInfo>)sender;
|
||||||
-(void) keyDown:(NSEvent*)event;
|
-(void) keyDown:(NSEvent*)event;
|
||||||
-(void) keyUp:(NSEvent*)event;
|
-(void) keyUp:(NSEvent*)event;
|
||||||
@end
|
@end
|
||||||
|
@ -16,6 +18,7 @@ struct pViewport : public pWidget {
|
||||||
CocoaViewport* cocoaViewport = nullptr;
|
CocoaViewport* cocoaViewport = nullptr;
|
||||||
|
|
||||||
uintptr_t handle();
|
uintptr_t handle();
|
||||||
|
void setDroppable(bool droppable);
|
||||||
|
|
||||||
pViewport(Viewport& viewport) : pWidget(viewport), viewport(viewport) {}
|
pViewport(Viewport& viewport) : pWidget(viewport), viewport(viewport) {}
|
||||||
void constructor();
|
void constructor();
|
||||||
|
|
|
@ -33,7 +33,7 @@ void pWidget::setFocused() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pWidget::setFont(const string& font) {
|
void pWidget::setFont(string font) {
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
if([cocoaView respondsToSelector:@selector(setFont:)]) {
|
if([cocoaView respondsToSelector:@selector(setFont:)]) {
|
||||||
[cocoaView setFont:pFont::cocoaFont(font)];
|
[cocoaView setFont:pFont::cocoaFont(font)];
|
||||||
|
@ -41,7 +41,7 @@ void pWidget::setFont(const string& font) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pWidget::setGeometry(const Geometry& geometry) {
|
void pWidget::setGeometry(Geometry geometry) {
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
CGFloat windowHeight = [[cocoaView superview] frame].size.height;
|
CGFloat windowHeight = [[cocoaView superview] frame].size.height;
|
||||||
[cocoaView setFrame:NSMakeRect(geometry.x, windowHeight - geometry.y - geometry.height, geometry.width, geometry.height)];
|
[cocoaView setFrame:NSMakeRect(geometry.x, windowHeight - geometry.y - geometry.height, geometry.width, geometry.height)];
|
||||||
|
|
|
@ -9,8 +9,8 @@ struct pWidget : public pSizable {
|
||||||
virtual Size minimumSize();
|
virtual Size minimumSize();
|
||||||
void setEnabled(bool enabled);
|
void setEnabled(bool enabled);
|
||||||
void setFocused();
|
void setFocused();
|
||||||
virtual void setFont(const string& font);
|
virtual void setFont(string font);
|
||||||
virtual void setGeometry(const Geometry& geometry);
|
virtual void setGeometry(Geometry geometry);
|
||||||
void setVisible(bool visible);
|
void setVisible(bool visible);
|
||||||
|
|
||||||
pWidget(Widget& widget) : pSizable(widget), widget(widget) {}
|
pWidget(Widget& widget) : pSizable(widget), widget(widget) {}
|
||||||
|
|
|
@ -105,6 +105,17 @@
|
||||||
return NO;
|
return NO;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-(NSDragOperation) draggingEntered:(id<NSDraggingInfo>)sender {
|
||||||
|
return DropPathsOperation(sender);
|
||||||
|
}
|
||||||
|
|
||||||
|
-(BOOL) performDragOperation:(id<NSDraggingInfo>)sender {
|
||||||
|
lstring paths = DropPaths(sender);
|
||||||
|
if(paths.empty()) return NO;
|
||||||
|
if(window->onDrop) window->onDrop(paths);
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
-(NSMenu*) menuBar {
|
-(NSMenu*) menuBar {
|
||||||
return menuBar;
|
return menuBar;
|
||||||
}
|
}
|
||||||
|
@ -217,7 +228,7 @@ void pWindow::remove(Widget& widget) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pWindow::setBackgroundColor(const Color& color) {
|
void pWindow::setBackgroundColor(Color color) {
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
[cocoaWindow
|
[cocoaWindow
|
||||||
setBackgroundColor:[NSColor
|
setBackgroundColor:[NSColor
|
||||||
|
@ -230,6 +241,16 @@ void pWindow::setBackgroundColor(const Color& color) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pWindow::setDroppable(bool droppable) {
|
||||||
|
@autoreleasepool {
|
||||||
|
if(droppable) {
|
||||||
|
[cocoaWindow registerForDraggedTypes:[NSArray arrayWithObject:NSFilenamesPboardType]];
|
||||||
|
} else {
|
||||||
|
[cocoaWindow unregisterDraggedTypes];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void pWindow::setFocused() {
|
void pWindow::setFocused() {
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
[cocoaWindow makeKeyAndOrderFront:nil];
|
[cocoaWindow makeKeyAndOrderFront:nil];
|
||||||
|
@ -250,7 +271,7 @@ void pWindow::setFullScreen(bool fullScreen) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pWindow::setGeometry(const Geometry& geometry) {
|
void pWindow::setGeometry(Geometry geometry) {
|
||||||
locked = true;
|
locked = true;
|
||||||
|
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
|
@ -276,7 +297,7 @@ void pWindow::setGeometry(const Geometry& geometry) {
|
||||||
locked = false;
|
locked = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pWindow::setMenuFont(const string& font) {
|
void pWindow::setMenuFont(string font) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void pWindow::setMenuVisible(bool visible) {
|
void pWindow::setMenuVisible(bool visible) {
|
||||||
|
@ -302,14 +323,14 @@ void pWindow::setResizable(bool resizable) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pWindow::setStatusFont(const string& font) {
|
void pWindow::setStatusFont(string font) {
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
[[cocoaWindow statusBar] setFont:pFont::cocoaFont(font)];
|
[[cocoaWindow statusBar] setFont:pFont::cocoaFont(font)];
|
||||||
}
|
}
|
||||||
statusBarReposition();
|
statusBarReposition();
|
||||||
}
|
}
|
||||||
|
|
||||||
void pWindow::setStatusText(const string& text) {
|
void pWindow::setStatusText(string text) {
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
[[cocoaWindow statusBar] setStringValue:[NSString stringWithUTF8String:text]];
|
[[cocoaWindow statusBar] setStringValue:[NSString stringWithUTF8String:text]];
|
||||||
}
|
}
|
||||||
|
@ -322,7 +343,7 @@ void pWindow::setStatusVisible(bool visible) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pWindow::setTitle(const string& text) {
|
void pWindow::setTitle(string text) {
|
||||||
@autoreleasepool {
|
@autoreleasepool {
|
||||||
[cocoaWindow setTitle:[NSString stringWithUTF8String:text]];
|
[cocoaWindow setTitle:[NSString stringWithUTF8String:text]];
|
||||||
}
|
}
|
||||||
|
@ -335,7 +356,7 @@ void pWindow::setVisible(bool visible) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pWindow::setWidgetFont(const string& font) {
|
void pWindow::setWidgetFont(string font) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void pWindow::constructor() {
|
void pWindow::constructor() {
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
-(void) windowDidMove:(NSNotification*)notification;
|
-(void) windowDidMove:(NSNotification*)notification;
|
||||||
-(void) windowDidResize:(NSNotification*)notification;
|
-(void) windowDidResize:(NSNotification*)notification;
|
||||||
-(BOOL) windowShouldClose:(id)sender;
|
-(BOOL) windowShouldClose:(id)sender;
|
||||||
|
-(NSDragOperation) draggingEntered:(id<NSDraggingInfo>)sender;
|
||||||
|
-(BOOL) performDragOperation:(id<NSDraggingInfo>)sender;
|
||||||
-(NSMenu*) menuBar;
|
-(NSMenu*) menuBar;
|
||||||
-(void) menuAbout;
|
-(void) menuAbout;
|
||||||
-(void) menuPreferences;
|
-(void) menuPreferences;
|
||||||
|
@ -37,20 +39,21 @@ struct pWindow : public pObject {
|
||||||
void remove(Layout& layout);
|
void remove(Layout& layout);
|
||||||
void remove(Menu& menu);
|
void remove(Menu& menu);
|
||||||
void remove(Widget& widget);
|
void remove(Widget& widget);
|
||||||
void setBackgroundColor(const Color& color);
|
void setBackgroundColor(Color color);
|
||||||
|
void setDroppable(bool droppable);
|
||||||
void setFocused();
|
void setFocused();
|
||||||
void setFullScreen(bool fullScreen);
|
void setFullScreen(bool fullScreen);
|
||||||
void setGeometry(const Geometry& geometry);
|
void setGeometry(Geometry geometry);
|
||||||
void setMenuFont(const string& font);
|
void setMenuFont(string font);
|
||||||
void setMenuVisible(bool visible);
|
void setMenuVisible(bool visible);
|
||||||
void setModal(bool modal);
|
void setModal(bool modal);
|
||||||
void setResizable(bool resizable);
|
void setResizable(bool resizable);
|
||||||
void setStatusFont(const string& font);
|
void setStatusFont(string font);
|
||||||
void setStatusText(const string& text);
|
void setStatusText(string text);
|
||||||
void setStatusVisible(bool visible);
|
void setStatusVisible(bool visible);
|
||||||
void setTitle(const string& text);
|
void setTitle(string text);
|
||||||
void setVisible(bool visible);
|
void setVisible(bool visible);
|
||||||
void setWidgetFont(const string& font);
|
void setWidgetFont(string font);
|
||||||
|
|
||||||
pWindow(Window& window) : pObject(window), window(window) {}
|
pWindow(Window& window) : pObject(window), window(window) {}
|
||||||
void constructor();
|
void constructor();
|
||||||
|
|
|
@ -39,6 +39,9 @@ namespace phoenix {
|
||||||
|
|
||||||
function<void ()> Application::main;
|
function<void ()> Application::main;
|
||||||
|
|
||||||
|
function<void ()> Application::Windows::onModalBegin;
|
||||||
|
function<void ()> Application::Windows::onModalEnd;
|
||||||
|
|
||||||
function<void ()> Application::Cocoa::onAbout;
|
function<void ()> Application::Cocoa::onAbout;
|
||||||
function<void ()> Application::Cocoa::onActivate;
|
function<void ()> Application::Cocoa::onActivate;
|
||||||
function<void ()> Application::Cocoa::onPreferences;
|
function<void ()> Application::Cocoa::onPreferences;
|
||||||
|
@ -377,13 +380,18 @@ void Window::remove_(Widget& widget) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::setBackgroundColor(const Color& color) {
|
void Window::setBackgroundColor(Color color) {
|
||||||
state.backgroundColorOverride = true;
|
state.backgroundColorOverride = true;
|
||||||
state.backgroundColor = color;
|
state.backgroundColor = color;
|
||||||
return p.setBackgroundColor(color);
|
return p.setBackgroundColor(color);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::setFrameGeometry(const Geometry& geometry) {
|
void Window::setDroppable(bool droppable) {
|
||||||
|
state.droppable = droppable;
|
||||||
|
return p.setDroppable(droppable);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Window::setFrameGeometry(Geometry geometry) {
|
||||||
Geometry margin = p.frameMargin();
|
Geometry margin = p.frameMargin();
|
||||||
return setGeometry({
|
return setGeometry({
|
||||||
geometry.x + margin.x, geometry.y + margin.y,
|
geometry.x + margin.x, geometry.y + margin.y,
|
||||||
|
@ -400,7 +408,7 @@ void Window::setFullScreen(bool fullScreen) {
|
||||||
return p.setFullScreen(fullScreen);
|
return p.setFullScreen(fullScreen);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::setGeometry(const Geometry& geometry) {
|
void Window::setGeometry(Geometry geometry) {
|
||||||
state.geometry = geometry;
|
state.geometry = geometry;
|
||||||
return p.setGeometry(geometry);
|
return p.setGeometry(geometry);
|
||||||
}
|
}
|
||||||
|
@ -425,7 +433,7 @@ void Window::setResizable(bool resizable) {
|
||||||
return p.setResizable(resizable);
|
return p.setResizable(resizable);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Window::setSmartGeometry(const Geometry& geometry) {
|
void Window::setSmartGeometry(Geometry geometry) {
|
||||||
Geometry margin = p.frameMargin();
|
Geometry margin = p.frameMargin();
|
||||||
return setGeometry({
|
return setGeometry({
|
||||||
geometry.x + margin.x, geometry.y + margin.y,
|
geometry.x + margin.x, geometry.y + margin.y,
|
||||||
|
@ -790,7 +798,7 @@ void Widget::setFont(string font) {
|
||||||
return p.setFont(font);
|
return p.setFont(font);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Widget::setGeometry(const Geometry& geometry) {
|
void Widget::setGeometry(Geometry geometry) {
|
||||||
state.geometry = geometry;
|
state.geometry = geometry;
|
||||||
return p.setGeometry(geometry);
|
return p.setGeometry(geometry);
|
||||||
}
|
}
|
||||||
|
@ -860,6 +868,11 @@ uint32_t* Canvas::data() {
|
||||||
return state.data;
|
return state.data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Canvas::setDroppable(bool droppable) {
|
||||||
|
state.droppable = droppable;
|
||||||
|
return p.setDroppable(droppable);
|
||||||
|
}
|
||||||
|
|
||||||
bool Canvas::setImage(const nall::image& image) {
|
bool Canvas::setImage(const nall::image& image) {
|
||||||
if(image.data == nullptr || image.width == 0 || image.height == 0) return false;
|
if(image.data == nullptr || image.width == 0 || image.height == 0) return false;
|
||||||
state.width = image.width;
|
state.width = image.width;
|
||||||
|
@ -869,7 +882,7 @@ bool Canvas::setImage(const nall::image& image) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Canvas::setSize(const Size& size) {
|
void Canvas::setSize(Size size) {
|
||||||
state.width = size.width;
|
state.width = size.width;
|
||||||
state.height = size.height;
|
state.height = size.height;
|
||||||
delete[] state.data;
|
delete[] state.data;
|
||||||
|
@ -1416,7 +1429,13 @@ uintptr_t Viewport::handle() {
|
||||||
return p.handle();
|
return p.handle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Viewport::setDroppable(bool droppable) {
|
||||||
|
state.droppable = droppable;
|
||||||
|
return p.setDroppable(droppable);
|
||||||
|
}
|
||||||
|
|
||||||
Viewport::Viewport():
|
Viewport::Viewport():
|
||||||
|
state(*new State),
|
||||||
base_from_member<pViewport&>(*new pViewport(*this)),
|
base_from_member<pViewport&>(*new pViewport(*this)),
|
||||||
Widget(base_from_member<pViewport&>::value),
|
Widget(base_from_member<pViewport&>::value),
|
||||||
p(base_from_member<pViewport&>::value) {
|
p(base_from_member<pViewport&>::value) {
|
||||||
|
@ -1425,6 +1444,7 @@ p(base_from_member<pViewport&>::value) {
|
||||||
|
|
||||||
Viewport::~Viewport() {
|
Viewport::~Viewport() {
|
||||||
p.destructor();
|
p.destructor();
|
||||||
|
delete &state;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,6 +64,11 @@ struct Application {
|
||||||
struct State;
|
struct State;
|
||||||
static void initialize();
|
static void initialize();
|
||||||
|
|
||||||
|
struct Windows {
|
||||||
|
static nall::function<void ()> onModalBegin;
|
||||||
|
static nall::function<void ()> onModalEnd;
|
||||||
|
};
|
||||||
|
|
||||||
struct Cocoa {
|
struct Cocoa {
|
||||||
static nall::function<void ()> onAbout;
|
static nall::function<void ()> onAbout;
|
||||||
static nall::function<void ()> onActivate;
|
static nall::function<void ()> onActivate;
|
||||||
|
@ -72,8 +77,6 @@ struct Application {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef Application App;
|
|
||||||
|
|
||||||
enum : unsigned {
|
enum : unsigned {
|
||||||
MaximumSize = ~0u,
|
MaximumSize = ~0u,
|
||||||
MinimumSize = 0u,
|
MinimumSize = 0u,
|
||||||
|
@ -106,7 +109,7 @@ struct Geometry {
|
||||||
Size size() const;
|
Size size() const;
|
||||||
nall::string text() const;
|
nall::string text() const;
|
||||||
inline Geometry() : x(0), y(0), width(0), height(0) {}
|
inline Geometry() : x(0), y(0), width(0), height(0) {}
|
||||||
inline Geometry(const Position& position, const Size& size) : x(position.x), y(position.y), width(size.width), height(size.height) {}
|
inline Geometry(Position position, Size size) : x(position.x), y(position.y), width(size.width), height(size.height) {}
|
||||||
template<typename X, typename Y, typename W, typename H> inline Geometry(X x, Y y, W width, H height) : x(x), y(y), width(width), height(height) {}
|
template<typename X, typename Y, typename W, typename H> inline Geometry(X x, Y y, W width, H height) : x(x), y(y), width(width), height(height) {}
|
||||||
Geometry(nall::string text);
|
Geometry(nall::string text);
|
||||||
};
|
};
|
||||||
|
@ -212,6 +215,7 @@ struct Timer : private nall::base_from_member<pTimer&>, Object {
|
||||||
|
|
||||||
struct Window : private nall::base_from_member<pWindow&>, Object {
|
struct Window : private nall::base_from_member<pWindow&>, Object {
|
||||||
nall::function<void ()> onClose;
|
nall::function<void ()> onClose;
|
||||||
|
nall::function<void (nall::lstring)> onDrop;
|
||||||
nall::function<void (Keyboard::Keycode)> onKeyPress;
|
nall::function<void (Keyboard::Keycode)> onKeyPress;
|
||||||
nall::function<void (Keyboard::Keycode)> onKeyRelease;
|
nall::function<void (Keyboard::Keycode)> onKeyRelease;
|
||||||
nall::function<void ()> onMove;
|
nall::function<void ()> onMove;
|
||||||
|
@ -236,16 +240,17 @@ struct Window : private nall::base_from_member<pWindow&>, Object {
|
||||||
void remove_(Layout& layout);
|
void remove_(Layout& layout);
|
||||||
void remove_(Menu& menu);
|
void remove_(Menu& menu);
|
||||||
void remove_(Widget& widget);
|
void remove_(Widget& widget);
|
||||||
void setBackgroundColor(const Color& color);
|
void setBackgroundColor(Color color);
|
||||||
void setFrameGeometry(const Geometry& geometry);
|
void setDroppable(bool droppable = true);
|
||||||
|
void setFrameGeometry(Geometry geometry);
|
||||||
void setFocused();
|
void setFocused();
|
||||||
void setFullScreen(bool fullScreen = true);
|
void setFullScreen(bool fullScreen = true);
|
||||||
void setGeometry(const Geometry& geometry);
|
void setGeometry(Geometry geometry);
|
||||||
void setMenuFont(nall::string font);
|
void setMenuFont(nall::string font);
|
||||||
void setMenuVisible(bool visible = true);
|
void setMenuVisible(bool visible = true);
|
||||||
void setModal(bool modal = true);
|
void setModal(bool modal = true);
|
||||||
void setResizable(bool resizable = true);
|
void setResizable(bool resizable = true);
|
||||||
void setSmartGeometry(const Geometry& geometry);
|
void setSmartGeometry(Geometry geometry);
|
||||||
void setStatusFont(nall::string font);
|
void setStatusFont(nall::string font);
|
||||||
void setStatusText(nall::string text);
|
void setStatusText(nall::string text);
|
||||||
void setStatusVisible(bool visible = true);
|
void setStatusVisible(bool visible = true);
|
||||||
|
@ -348,7 +353,7 @@ struct Sizable : Object {
|
||||||
Layout* layout();
|
Layout* layout();
|
||||||
virtual Size minimumSize() = 0;
|
virtual Size minimumSize() = 0;
|
||||||
virtual void setEnabled(bool enabled = true) = 0;
|
virtual void setEnabled(bool enabled = true) = 0;
|
||||||
virtual void setGeometry(const Geometry& geometry) = 0;
|
virtual void setGeometry(Geometry geometry) = 0;
|
||||||
virtual void setVisible(bool visible = true) = 0;
|
virtual void setVisible(bool visible = true) = 0;
|
||||||
virtual bool visible() = 0;
|
virtual bool visible() = 0;
|
||||||
Window* window();
|
Window* window();
|
||||||
|
@ -383,7 +388,7 @@ struct Widget : private nall::base_from_member<pWidget&>, Sizable {
|
||||||
void setEnabled(bool enabled = true);
|
void setEnabled(bool enabled = true);
|
||||||
void setFocused();
|
void setFocused();
|
||||||
void setFont(nall::string font);
|
void setFont(nall::string font);
|
||||||
void setGeometry(const Geometry& geometry);
|
void setGeometry(Geometry geometry);
|
||||||
void setVisible(bool visible = true);
|
void setVisible(bool visible = true);
|
||||||
bool visible();
|
bool visible();
|
||||||
|
|
||||||
|
@ -409,14 +414,16 @@ struct Button : private nall::base_from_member<pButton&>, Widget {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Canvas : private nall::base_from_member<pCanvas&>, Widget {
|
struct Canvas : private nall::base_from_member<pCanvas&>, Widget {
|
||||||
|
nall::function<void (nall::lstring)> onDrop;
|
||||||
nall::function<void ()> onMouseLeave;
|
nall::function<void ()> onMouseLeave;
|
||||||
nall::function<void (Position)> onMouseMove;
|
nall::function<void (Position)> onMouseMove;
|
||||||
nall::function<void (Mouse::Button)> onMousePress;
|
nall::function<void (Mouse::Button)> onMousePress;
|
||||||
nall::function<void (Mouse::Button)> onMouseRelease;
|
nall::function<void (Mouse::Button)> onMouseRelease;
|
||||||
|
|
||||||
uint32_t* data();
|
uint32_t* data();
|
||||||
|
void setDroppable(bool droppable = true);
|
||||||
bool setImage(const nall::image& image);
|
bool setImage(const nall::image& image);
|
||||||
void setSize(const Size& size);
|
void setSize(Size size);
|
||||||
Size size();
|
Size size();
|
||||||
void update();
|
void update();
|
||||||
|
|
||||||
|
@ -641,15 +648,19 @@ struct VerticalSlider : private nall::base_from_member<pVerticalSlider&>, Widget
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Viewport : private nall::base_from_member<pViewport&>, Widget {
|
struct Viewport : private nall::base_from_member<pViewport&>, Widget {
|
||||||
|
nall::function<void (nall::lstring)> onDrop;
|
||||||
nall::function<void ()> onMouseLeave;
|
nall::function<void ()> onMouseLeave;
|
||||||
nall::function<void (Position)> onMouseMove;
|
nall::function<void (Position)> onMouseMove;
|
||||||
nall::function<void (Mouse::Button)> onMousePress;
|
nall::function<void (Mouse::Button)> onMousePress;
|
||||||
nall::function<void (Mouse::Button)> onMouseRelease;
|
nall::function<void (Mouse::Button)> onMouseRelease;
|
||||||
|
|
||||||
uintptr_t handle();
|
uintptr_t handle();
|
||||||
|
void setDroppable(bool droppable = true);
|
||||||
|
|
||||||
Viewport();
|
Viewport();
|
||||||
~Viewport();
|
~Viewport();
|
||||||
|
struct State;
|
||||||
|
State& state;
|
||||||
pViewport& p;
|
pViewport& p;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
void FixedLayout::append(Sizable& sizable, const Geometry& geometry) {
|
void FixedLayout::append(Sizable& sizable, Geometry geometry) {
|
||||||
children.append({&sizable, geometry});
|
children.append({&sizable, geometry});
|
||||||
synchronizeLayout();
|
synchronizeLayout();
|
||||||
if(window()) window()->synchronizeLayout();
|
if(window()) window()->synchronizeLayout();
|
||||||
|
@ -48,7 +48,7 @@ void FixedLayout::setEnabled(bool enabled) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void FixedLayout::setGeometry(const Geometry& geometry) {
|
void FixedLayout::setGeometry(Geometry geometry) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void FixedLayout::setVisible(bool visible) {
|
void FixedLayout::setVisible(bool visible) {
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
struct FixedLayout : Layout {
|
struct FixedLayout : Layout {
|
||||||
void append(Sizable& sizable, const Geometry& geometry);
|
void append(Sizable& sizable, Geometry geometry);
|
||||||
void append(Sizable& sizable);
|
void append(Sizable& sizable);
|
||||||
bool enabled();
|
bool enabled();
|
||||||
Size minimumSize();
|
Size minimumSize();
|
||||||
void remove(Sizable& sizable);
|
void remove(Sizable& sizable);
|
||||||
void reset();
|
void reset();
|
||||||
void setEnabled(bool enabled = true);
|
void setEnabled(bool enabled = true);
|
||||||
void setGeometry(const Geometry& geometry);
|
void setGeometry(Geometry geometry);
|
||||||
void setVisible(bool visible = true);
|
void setVisible(bool visible = true);
|
||||||
void synchronizeLayout();
|
void synchronizeLayout();
|
||||||
bool visible();
|
bool visible();
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
void HorizontalLayout::append(Sizable& sizable, const Size& size, unsigned spacing) {
|
void HorizontalLayout::append(Sizable& sizable, Size size, unsigned spacing) {
|
||||||
for(auto& child : children) if(child.sizable == &sizable) return;
|
for(auto& child : children) if(child.sizable == &sizable) return;
|
||||||
children.append({&sizable, size.width, size.height, spacing});
|
children.append({&sizable, size.width, size.height, spacing});
|
||||||
synchronizeLayout();
|
synchronizeLayout();
|
||||||
|
@ -72,7 +72,7 @@ void HorizontalLayout::setEnabled(bool enabled) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HorizontalLayout::setGeometry(const Geometry& containerGeometry) {
|
void HorizontalLayout::setGeometry(Geometry containerGeometry) {
|
||||||
auto children = this->children;
|
auto children = this->children;
|
||||||
for(auto& child : children) {
|
for(auto& child : children) {
|
||||||
if(child.width == MinimumSize) child.width = child.sizable->minimumSize().width;
|
if(child.width == MinimumSize) child.width = child.sizable->minimumSize().width;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
struct HorizontalLayout : public Layout {
|
struct HorizontalLayout : public Layout {
|
||||||
void append(Sizable& sizable, const Size& size, unsigned spacing = 0);
|
void append(Sizable& sizable, Size size, unsigned spacing = 0);
|
||||||
void append(Sizable& sizable);
|
void append(Sizable& sizable);
|
||||||
bool enabled();
|
bool enabled();
|
||||||
Size minimumSize();
|
Size minimumSize();
|
||||||
|
@ -7,7 +7,7 @@ struct HorizontalLayout : public Layout {
|
||||||
void reset();
|
void reset();
|
||||||
void setAlignment(double alignment);
|
void setAlignment(double alignment);
|
||||||
void setEnabled(bool enabled = true);
|
void setEnabled(bool enabled = true);
|
||||||
void setGeometry(const Geometry& geometry);
|
void setGeometry(Geometry geometry);
|
||||||
void setMargin(unsigned margin);
|
void setMargin(unsigned margin);
|
||||||
void setVisible(bool visible = true);
|
void setVisible(bool visible = true);
|
||||||
void synchronizeLayout();
|
void synchronizeLayout();
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
void VerticalLayout::append(Sizable& sizable, const Size& size, unsigned spacing) {
|
void VerticalLayout::append(Sizable& sizable, Size size, unsigned spacing) {
|
||||||
for(auto& child : children) if(child.sizable == &sizable) return;
|
for(auto& child : children) if(child.sizable == &sizable) return;
|
||||||
children.append({&sizable, size.width, size.height, spacing});
|
children.append({&sizable, size.width, size.height, spacing});
|
||||||
synchronizeLayout();
|
synchronizeLayout();
|
||||||
|
@ -72,7 +72,7 @@ void VerticalLayout::setEnabled(bool enabled) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VerticalLayout::setGeometry(const Geometry& containerGeometry) {
|
void VerticalLayout::setGeometry(Geometry containerGeometry) {
|
||||||
auto children = this->children;
|
auto children = this->children;
|
||||||
for(auto& child : children) {
|
for(auto& child : children) {
|
||||||
if(child.width == MinimumSize) child.width = child.sizable->minimumSize().width;
|
if(child.width == MinimumSize) child.width = child.sizable->minimumSize().width;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
struct VerticalLayout : public Layout {
|
struct VerticalLayout : public Layout {
|
||||||
void append(Sizable& sizable, const Size& size, unsigned spacing = 0);
|
void append(Sizable& sizable, Size size, unsigned spacing = 0);
|
||||||
void append(Sizable& sizable);
|
void append(Sizable& sizable);
|
||||||
bool enabled();
|
bool enabled();
|
||||||
Size minimumSize();
|
Size minimumSize();
|
||||||
|
@ -7,7 +7,7 @@ struct VerticalLayout : public Layout {
|
||||||
void reset();
|
void reset();
|
||||||
void setAlignment(double alignment);
|
void setAlignment(double alignment);
|
||||||
void setEnabled(bool enabled = true);
|
void setEnabled(bool enabled = true);
|
||||||
void setGeometry(const Geometry& geometry);
|
void setGeometry(Geometry geometry);
|
||||||
void setMargin(unsigned margin);
|
void setMargin(unsigned margin);
|
||||||
void setVisible(bool visible = true);
|
void setVisible(bool visible = true);
|
||||||
void synchronizeLayout();
|
void synchronizeLayout();
|
||||||
|
|
|
@ -25,6 +25,7 @@ struct MessageWindow::State {
|
||||||
struct Window::State {
|
struct Window::State {
|
||||||
bool backgroundColorOverride = false;
|
bool backgroundColorOverride = false;
|
||||||
Color backgroundColor = {0, 0, 0, 255};
|
Color backgroundColor = {0, 0, 0, 255};
|
||||||
|
bool droppable = false;
|
||||||
bool fullScreen = false;
|
bool fullScreen = false;
|
||||||
Geometry geometry = {128, 128, 256, 256};
|
Geometry geometry = {128, 128, 256, 256};
|
||||||
group<Layout> layout;
|
group<Layout> layout;
|
||||||
|
@ -95,6 +96,7 @@ struct Button::State {
|
||||||
|
|
||||||
struct Canvas::State {
|
struct Canvas::State {
|
||||||
uint32_t* data = nullptr;
|
uint32_t* data = nullptr;
|
||||||
|
bool droppable = false;
|
||||||
unsigned width = 256;
|
unsigned width = 256;
|
||||||
unsigned height = 256;
|
unsigned height = 256;
|
||||||
};
|
};
|
||||||
|
@ -172,3 +174,7 @@ struct VerticalSlider::State {
|
||||||
unsigned length = 101;
|
unsigned length = 101;
|
||||||
unsigned position = 0;
|
unsigned position = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Viewport::State {
|
||||||
|
bool droppable = false;
|
||||||
|
};
|
||||||
|
|
|
@ -24,7 +24,7 @@ string pAction::mnemonic(string text) {
|
||||||
return text;
|
return text;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pAction::setFont(const string& font) {
|
void pAction::setFont(string font) {
|
||||||
pFont::setFont(widget, font);
|
pFont::setFont(widget, font);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,8 +36,8 @@ PangoFontDescription* pFont::create(string description) {
|
||||||
|
|
||||||
if(part[0] != "") family = part[0];
|
if(part[0] != "") family = part[0];
|
||||||
if(part.size() >= 2) size = decimal(part[1]);
|
if(part.size() >= 2) size = decimal(part[1]);
|
||||||
if(part.size() >= 3) bold = part[2].position("Bold");
|
if(part.size() >= 3) bold = part[2].find("Bold");
|
||||||
if(part.size() >= 3) italic = part[2].position("Italic");
|
if(part.size() >= 3) italic = part[2].find("Italic");
|
||||||
|
|
||||||
PangoFontDescription* font = pango_font_description_new();
|
PangoFontDescription* font = pango_font_description_new();
|
||||||
pango_font_description_set_family(font, family);
|
pango_font_description_set_family(font, family);
|
||||||
|
|
|
@ -124,10 +124,11 @@ struct pWindow : public pObject {
|
||||||
void remove(Layout& layout);
|
void remove(Layout& layout);
|
||||||
void remove(Menu& menu);
|
void remove(Menu& menu);
|
||||||
void remove(Widget& widget);
|
void remove(Widget& widget);
|
||||||
void setBackgroundColor(const Color& color);
|
void setBackgroundColor(Color color);
|
||||||
|
void setDroppable(bool droppable);
|
||||||
void setFocused();
|
void setFocused();
|
||||||
void setFullScreen(bool fullScreen);
|
void setFullScreen(bool fullScreen);
|
||||||
void setGeometry(const Geometry& geometry);
|
void setGeometry(Geometry geometry);
|
||||||
void setMenuFont(string font);
|
void setMenuFont(string font);
|
||||||
void setMenuVisible(bool visible);
|
void setMenuVisible(bool visible);
|
||||||
void setModal(bool modal);
|
void setModal(bool modal);
|
||||||
|
@ -156,7 +157,7 @@ struct pAction : public pObject {
|
||||||
void constructor();
|
void constructor();
|
||||||
virtual void orphan();
|
virtual void orphan();
|
||||||
string mnemonic(string text);
|
string mnemonic(string text);
|
||||||
virtual void setFont(const string &font);
|
virtual void setFont(string font);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct pMenu : public pAction {
|
struct pMenu : public pAction {
|
||||||
|
@ -245,7 +246,7 @@ struct pWidget : public pSizable {
|
||||||
void setEnabled(bool enabled);
|
void setEnabled(bool enabled);
|
||||||
virtual void setFocused();
|
virtual void setFocused();
|
||||||
virtual void setFont(string font);
|
virtual void setFont(string font);
|
||||||
virtual void setGeometry(const Geometry& geometry);
|
virtual void setGeometry(Geometry geometry);
|
||||||
void setVisible(bool visible);
|
void setVisible(bool visible);
|
||||||
|
|
||||||
pWidget(Widget& widget) : pSizable(widget), widget(widget) {}
|
pWidget(Widget& widget) : pSizable(widget), widget(widget) {}
|
||||||
|
@ -271,7 +272,8 @@ struct pCanvas : public pWidget {
|
||||||
Canvas& canvas;
|
Canvas& canvas;
|
||||||
cairo_surface_t* surface;
|
cairo_surface_t* surface;
|
||||||
|
|
||||||
void setSize(const Size& size);
|
void setDroppable(bool droppable);
|
||||||
|
void setSize(Size size);
|
||||||
void update();
|
void update();
|
||||||
|
|
||||||
pCanvas(Canvas& canvas) : pWidget(canvas), canvas(canvas) {}
|
pCanvas(Canvas& canvas) : pWidget(canvas), canvas(canvas) {}
|
||||||
|
@ -510,6 +512,7 @@ struct pViewport : public pWidget {
|
||||||
Viewport& viewport;
|
Viewport& viewport;
|
||||||
|
|
||||||
uintptr_t handle();
|
uintptr_t handle();
|
||||||
|
void setDroppable(bool droppable);
|
||||||
|
|
||||||
pViewport(Viewport& viewport) : pWidget(viewport), viewport(viewport) {}
|
pViewport(Viewport& viewport) : pWidget(viewport), viewport(viewport) {}
|
||||||
void constructor();
|
void constructor();
|
||||||
|
|
|
@ -18,6 +18,25 @@ static GtkImage* CreateImage(const nall::image& image, bool scale = false) {
|
||||||
return gtkImage;
|
return gtkImage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static lstring DropPaths(GtkSelectionData* data) {
|
||||||
|
gchar** uris = gtk_selection_data_get_uris(data);
|
||||||
|
if(uris == nullptr) return {};
|
||||||
|
|
||||||
|
lstring paths;
|
||||||
|
for(unsigned n = 0; uris[n] != nullptr; n++) {
|
||||||
|
gchar* pathname = g_filename_from_uri(uris[n], nullptr, nullptr);
|
||||||
|
if(pathname == nullptr) continue;
|
||||||
|
|
||||||
|
string path = pathname;
|
||||||
|
g_free(pathname);
|
||||||
|
if(directory::exists(path) && !path.endswith("/")) path.append("/");
|
||||||
|
paths.append(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_strfreev(uris);
|
||||||
|
return paths;
|
||||||
|
}
|
||||||
|
|
||||||
static Keyboard::Keycode Keysym(unsigned keysym) {
|
static Keyboard::Keycode Keysym(unsigned keysym) {
|
||||||
switch(keysym) {
|
switch(keysym) {
|
||||||
case GDK_Escape: return Keyboard::Keycode::Escape;
|
case GDK_Escape: return Keyboard::Keycode::Escape;
|
||||||
|
|
|
@ -8,6 +8,14 @@ static gboolean Canvas_expose(GtkWidget* widget, GdkEvent* event, pCanvas* self)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void Canvas_dropEvent(GtkWidget* widget, GdkDragContext* context, gint x, gint y,
|
||||||
|
GtkSelectionData* data, guint type, guint timestamp, Canvas* canvas) {
|
||||||
|
if(canvas->state.droppable == false) return;
|
||||||
|
lstring paths = DropPaths(data);
|
||||||
|
if(paths.empty()) return;
|
||||||
|
if(canvas->onDrop) canvas->onDrop(paths);
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean Canvas_mouseLeave(GtkWidget* widget, GdkEventButton* event, pCanvas* self) {
|
static gboolean Canvas_mouseLeave(GtkWidget* widget, GdkEventButton* event, pCanvas* self) {
|
||||||
if(self->canvas.onMouseLeave) self->canvas.onMouseLeave();
|
if(self->canvas.onMouseLeave) self->canvas.onMouseLeave();
|
||||||
return true;
|
return true;
|
||||||
|
@ -36,7 +44,12 @@ static gboolean Canvas_mouseRelease(GtkWidget* widget, GdkEventButton* event, pC
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pCanvas::setSize(const Size& size) {
|
void pCanvas::setDroppable(bool droppable) {
|
||||||
|
gtk_drag_dest_set(gtkWidget, GTK_DEST_DEFAULT_ALL, nullptr, 0, GDK_ACTION_COPY);
|
||||||
|
if(droppable) gtk_drag_dest_add_uri_targets(gtkWidget);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pCanvas::setSize(Size size) {
|
||||||
cairo_surface_destroy(surface);
|
cairo_surface_destroy(surface);
|
||||||
surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, canvas.state.width, canvas.state.height);
|
surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, canvas.state.width, canvas.state.height);
|
||||||
}
|
}
|
||||||
|
@ -54,6 +67,7 @@ void pCanvas::constructor() {
|
||||||
gtk_widget_set_double_buffered(gtkWidget, false);
|
gtk_widget_set_double_buffered(gtkWidget, false);
|
||||||
gtk_widget_add_events(gtkWidget,
|
gtk_widget_add_events(gtkWidget,
|
||||||
GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_EXPOSURE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_POINTER_MOTION_MASK);
|
GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_EXPOSURE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_POINTER_MOTION_MASK);
|
||||||
|
g_signal_connect(G_OBJECT(gtkWidget), "drag-data-received", G_CALLBACK(Canvas_dropEvent), (gpointer)&canvas);
|
||||||
g_signal_connect(G_OBJECT(gtkWidget), "button_press_event", G_CALLBACK(Canvas_mousePress), (gpointer)this);
|
g_signal_connect(G_OBJECT(gtkWidget), "button_press_event", G_CALLBACK(Canvas_mousePress), (gpointer)this);
|
||||||
g_signal_connect(G_OBJECT(gtkWidget), "button_release_event", G_CALLBACK(Canvas_mouseRelease), (gpointer)this);
|
g_signal_connect(G_OBJECT(gtkWidget), "button_release_event", G_CALLBACK(Canvas_mouseRelease), (gpointer)this);
|
||||||
g_signal_connect(G_OBJECT(gtkWidget), "expose_event", G_CALLBACK(Canvas_expose), (gpointer)this);
|
g_signal_connect(G_OBJECT(gtkWidget), "expose_event", G_CALLBACK(Canvas_expose), (gpointer)this);
|
||||||
|
|
|
@ -1,5 +1,13 @@
|
||||||
namespace phoenix {
|
namespace phoenix {
|
||||||
|
|
||||||
|
static void Viewport_dropEvent(GtkWidget* widget, GdkDragContext* context, gint x, gint y,
|
||||||
|
GtkSelectionData* data, guint type, guint timestamp, Viewport* viewport) {
|
||||||
|
if(viewport->state.droppable == false) return;
|
||||||
|
lstring paths = DropPaths(data);
|
||||||
|
if(paths.empty()) return;
|
||||||
|
if(viewport->onDrop) viewport->onDrop(paths);
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean Viewport_mouseLeave(GtkWidget* widget, GdkEventButton* event, pViewport* self) {
|
static gboolean Viewport_mouseLeave(GtkWidget* widget, GdkEventButton* event, pViewport* self) {
|
||||||
if(self->viewport.onMouseLeave) self->viewport.onMouseLeave();
|
if(self->viewport.onMouseLeave) self->viewport.onMouseLeave();
|
||||||
return true;
|
return true;
|
||||||
|
@ -32,11 +40,17 @@ uintptr_t pViewport::handle() {
|
||||||
return GDK_WINDOW_XID(gtk_widget_get_window(gtkWidget));
|
return GDK_WINDOW_XID(gtk_widget_get_window(gtkWidget));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pViewport::setDroppable(bool droppable) {
|
||||||
|
gtk_drag_dest_set(gtkWidget, GTK_DEST_DEFAULT_ALL, nullptr, 0, GDK_ACTION_COPY);
|
||||||
|
if(droppable) gtk_drag_dest_add_uri_targets(gtkWidget);
|
||||||
|
}
|
||||||
|
|
||||||
void pViewport::constructor() {
|
void pViewport::constructor() {
|
||||||
gtkWidget = gtk_drawing_area_new();
|
gtkWidget = gtk_drawing_area_new();
|
||||||
//gtk_widget_set_double_buffered(gtkWidget, false);
|
//gtk_widget_set_double_buffered(gtkWidget, false);
|
||||||
gtk_widget_add_events(gtkWidget,
|
gtk_widget_add_events(gtkWidget,
|
||||||
GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_POINTER_MOTION_MASK);
|
GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_POINTER_MOTION_MASK);
|
||||||
|
g_signal_connect(G_OBJECT(gtkWidget), "drag-data-received", G_CALLBACK(Viewport_dropEvent), (gpointer)&viewport);
|
||||||
g_signal_connect(G_OBJECT(gtkWidget), "button_press_event", G_CALLBACK(Viewport_mousePress), (gpointer)this);
|
g_signal_connect(G_OBJECT(gtkWidget), "button_press_event", G_CALLBACK(Viewport_mousePress), (gpointer)this);
|
||||||
g_signal_connect(G_OBJECT(gtkWidget), "button_release_event", G_CALLBACK(Viewport_mouseRelease), (gpointer)this);
|
g_signal_connect(G_OBJECT(gtkWidget), "button_release_event", G_CALLBACK(Viewport_mouseRelease), (gpointer)this);
|
||||||
g_signal_connect(G_OBJECT(gtkWidget), "leave_notify_event", G_CALLBACK(Viewport_mouseLeave), (gpointer)this);
|
g_signal_connect(G_OBJECT(gtkWidget), "leave_notify_event", G_CALLBACK(Viewport_mouseLeave), (gpointer)this);
|
||||||
|
|
|
@ -26,7 +26,7 @@ void pWidget::setFont(string font) {
|
||||||
pFont::setFont(gtkWidget, font);
|
pFont::setFont(gtkWidget, font);
|
||||||
}
|
}
|
||||||
|
|
||||||
void pWidget::setGeometry(const Geometry& geometry) {
|
void pWidget::setGeometry(Geometry geometry) {
|
||||||
if(sizable.window() && sizable.window()->visible()) gtk_fixed_move(GTK_FIXED(sizable.window()->p.formContainer), gtkWidget, geometry.x, geometry.y);
|
if(sizable.window() && sizable.window()->visible()) gtk_fixed_move(GTK_FIXED(sizable.window()->p.formContainer), gtkWidget, geometry.x, geometry.y);
|
||||||
unsigned width = (signed)geometry.width <= 0 ? 1U : geometry.width;
|
unsigned width = (signed)geometry.width <= 0 ? 1U : geometry.width;
|
||||||
unsigned height = (signed)geometry.height <= 0 ? 1U : geometry.height;
|
unsigned height = (signed)geometry.height <= 0 ? 1U : geometry.height;
|
||||||
|
|
|
@ -80,6 +80,14 @@ static gboolean Window_configure(GtkWidget* widget, GdkEvent* event, Window* win
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void Window_dropEvent(GtkWidget* widget, GdkDragContext* context, gint x, gint y,
|
||||||
|
GtkSelectionData* data, guint type, guint timestamp, Window* window) {
|
||||||
|
if(window->state.droppable == false) return;
|
||||||
|
lstring paths = DropPaths(data);
|
||||||
|
if(paths.empty()) return;
|
||||||
|
if(window->onDrop) window->onDrop(paths);
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean Window_keyPressEvent(GtkWidget* widget, GdkEventKey* event, Window* window) {
|
static gboolean Window_keyPressEvent(GtkWidget* widget, GdkEventKey* event, Window* window) {
|
||||||
Keyboard::Keycode key = Keysym(event->keyval);
|
Keyboard::Keycode key = Keysym(event->keyval);
|
||||||
if(key != Keyboard::Keycode::None && window->onKeyPress) window->onKeyPress(key);
|
if(key != Keyboard::Keycode::None && window->onKeyPress) window->onKeyPress(key);
|
||||||
|
@ -203,7 +211,7 @@ void pWindow::remove(Widget& widget) {
|
||||||
widget.p.orphan();
|
widget.p.orphan();
|
||||||
}
|
}
|
||||||
|
|
||||||
void pWindow::setBackgroundColor(const Color& color) {
|
void pWindow::setBackgroundColor(Color color) {
|
||||||
GdkColor gdkColor;
|
GdkColor gdkColor;
|
||||||
gdkColor.pixel = (color.red << 16) | (color.green << 8) | (color.blue << 0);
|
gdkColor.pixel = (color.red << 16) | (color.green << 8) | (color.blue << 0);
|
||||||
gdkColor.red = (color.red << 8) | (color.red << 0);
|
gdkColor.red = (color.red << 8) | (color.red << 0);
|
||||||
|
@ -212,6 +220,11 @@ void pWindow::setBackgroundColor(const Color& color) {
|
||||||
gtk_widget_modify_bg(widget, GTK_STATE_NORMAL, &gdkColor);
|
gtk_widget_modify_bg(widget, GTK_STATE_NORMAL, &gdkColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pWindow::setDroppable(bool droppable) {
|
||||||
|
gtk_drag_dest_set(widget, GTK_DEST_DEFAULT_ALL, nullptr, 0, GDK_ACTION_COPY);
|
||||||
|
if(droppable) gtk_drag_dest_add_uri_targets(widget);
|
||||||
|
}
|
||||||
|
|
||||||
void pWindow::setFocused() {
|
void pWindow::setFocused() {
|
||||||
gtk_window_present(GTK_WINDOW(widget));
|
gtk_window_present(GTK_WINDOW(widget));
|
||||||
}
|
}
|
||||||
|
@ -224,7 +237,7 @@ void pWindow::setFullScreen(bool fullScreen) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void pWindow::setGeometry(const Geometry& geometry) {
|
void pWindow::setGeometry(Geometry geometry) {
|
||||||
Geometry margin = frameMargin();
|
Geometry margin = frameMargin();
|
||||||
gtk_window_move(GTK_WINDOW(widget), geometry.x - margin.x, geometry.y - margin.y);
|
gtk_window_move(GTK_WINDOW(widget), geometry.x - margin.x, geometry.y - margin.y);
|
||||||
|
|
||||||
|
@ -362,6 +375,7 @@ void pWindow::constructor() {
|
||||||
g_signal_connect(G_OBJECT(widget), "delete-event", G_CALLBACK(Window_close), (gpointer)&window);
|
g_signal_connect(G_OBJECT(widget), "delete-event", G_CALLBACK(Window_close), (gpointer)&window);
|
||||||
g_signal_connect(G_OBJECT(widget), "expose-event", G_CALLBACK(Window_expose), (gpointer)&window);
|
g_signal_connect(G_OBJECT(widget), "expose-event", G_CALLBACK(Window_expose), (gpointer)&window);
|
||||||
g_signal_connect(G_OBJECT(widget), "configure-event", G_CALLBACK(Window_configure), (gpointer)&window);
|
g_signal_connect(G_OBJECT(widget), "configure-event", G_CALLBACK(Window_configure), (gpointer)&window);
|
||||||
|
g_signal_connect(G_OBJECT(widget), "drag-data-received", G_CALLBACK(Window_dropEvent), (gpointer)&window);
|
||||||
g_signal_connect(G_OBJECT(widget), "key-press-event", G_CALLBACK(Window_keyPressEvent), (gpointer)&window);
|
g_signal_connect(G_OBJECT(widget), "key-press-event", G_CALLBACK(Window_keyPressEvent), (gpointer)&window);
|
||||||
g_signal_connect(G_OBJECT(widget), "key-release-event", G_CALLBACK(Window_keyPressEvent), (gpointer)&window);
|
g_signal_connect(G_OBJECT(widget), "key-release-event", G_CALLBACK(Window_keyPressEvent), (gpointer)&window);
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue