mirror of https://github.com/bsnes-emu/bsnes.git
Update to v092r08 release.
byuu says: Changelog: - fixed cartridge load window focus on Windows - lots of updates to nall, ruby and phoenix - ethos and Emulator::Interface updated from "foo &bar" to "foo& bar" syntax (work-in-progress) Before I had mixed the two ways to declare variables/arguments all over the place, so the goal is to unify them all for consistency. So the changelog for this release will be massive (750KB >.>) due to the syntax change. Yeah, that's what I spent the last three days working on ...
This commit is contained in:
parent
177e222ca7
commit
75dab443b4
|
@ -3,7 +3,7 @@
|
||||||
|
|
||||||
namespace Emulator {
|
namespace Emulator {
|
||||||
static const char Name[] = "higan";
|
static const char Name[] = "higan";
|
||||||
static const char Version[] = "092.07";
|
static const char Version[] = "092.08";
|
||||||
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/";
|
||||||
|
@ -59,11 +59,11 @@ template<typename R, typename... P> struct hook<R (P...)> {
|
||||||
}
|
}
|
||||||
|
|
||||||
hook() {}
|
hook() {}
|
||||||
hook(const hook &hook) { callback = hook.callback; }
|
hook(const hook& hook) { callback = hook.callback; }
|
||||||
hook(void *function) { callback = function; }
|
hook(void* function) { callback = function; }
|
||||||
hook(R (*function)(P...)) { callback = function; }
|
hook(R (*function)(P...)) { callback = function; }
|
||||||
template<typename C> hook(R (C::*function)(P...), C *object) { callback = {function, object}; }
|
template<typename C> hook(R (C::*function)(P...), C* object) { callback = {function, object}; }
|
||||||
template<typename C> hook(R (C::*function)(P...) const, C *object) { callback = {function, object}; }
|
template<typename C> hook(R (C::*function)(P...) const, C* object) { callback = {function, object}; }
|
||||||
template<typename L> hook(const L& function) { callback = function; }
|
template<typename L> hook(const L& function) { callback = function; }
|
||||||
|
|
||||||
hook& operator=(const hook& hook) { callback = hook.callback; return *this; }
|
hook& operator=(const hook& hook) { callback = hook.callback; return *this; }
|
||||||
|
|
|
@ -23,7 +23,6 @@ struct Interface {
|
||||||
string type;
|
string type;
|
||||||
bool bootable; //false for cartridge slots (eg Sufami Turbo cartridges)
|
bool bootable; //false for cartridge slots (eg Sufami Turbo cartridges)
|
||||||
};
|
};
|
||||||
|
|
||||||
vector<Media> media;
|
vector<Media> media;
|
||||||
|
|
||||||
struct Device {
|
struct Device {
|
||||||
|
@ -58,21 +57,22 @@ struct Interface {
|
||||||
virtual unsigned dipSettings(const Markup::Node&) { return 0; }
|
virtual unsigned dipSettings(const Markup::Node&) { return 0; }
|
||||||
virtual string path(unsigned) { return ""; }
|
virtual string path(unsigned) { return ""; }
|
||||||
virtual string server() { return ""; }
|
virtual string server() { return ""; }
|
||||||
virtual void notify(const string &text) { print(text, "\n"); }
|
virtual void notify(const string& text) { print(text, "\n"); }
|
||||||
} *bind;
|
};
|
||||||
|
Bind* bind = nullptr;
|
||||||
|
|
||||||
//callback bindings (provided by user interface)
|
//callback bindings (provided by user interface)
|
||||||
void loadRequest(unsigned id, const string &name, const string &type) { return bind->loadRequest(id, name, type); }
|
void loadRequest(unsigned id, const string& name, const string& type) { return bind->loadRequest(id, name, type); }
|
||||||
void loadRequest(unsigned id, const string &path) { return bind->loadRequest(id, path); }
|
void loadRequest(unsigned id, const string& path) { return bind->loadRequest(id, path); }
|
||||||
void saveRequest(unsigned id, const string &path) { return bind->saveRequest(id, path); }
|
void saveRequest(unsigned id, const string& path) { return bind->saveRequest(id, path); }
|
||||||
uint32_t videoColor(unsigned source, uint16_t red, uint16_t green, uint16_t blue) { return bind->videoColor(source, red, green, blue); }
|
uint32_t videoColor(unsigned source, uint16_t red, uint16_t green, uint16_t blue) { return bind->videoColor(source, red, green, blue); }
|
||||||
void videoRefresh(const uint32_t *data, unsigned pitch, unsigned width, unsigned height) { return bind->videoRefresh(data, pitch, width, height); }
|
void videoRefresh(const uint32_t* data, unsigned pitch, unsigned width, unsigned height) { return bind->videoRefresh(data, pitch, width, height); }
|
||||||
void audioSample(int16_t lsample, int16_t rsample) { return bind->audioSample(lsample, rsample); }
|
void audioSample(int16_t lsample, int16_t rsample) { return bind->audioSample(lsample, rsample); }
|
||||||
int16_t inputPoll(unsigned port, unsigned device, unsigned input) { return bind->inputPoll(port, device, input); }
|
int16_t inputPoll(unsigned port, unsigned device, unsigned input) { return bind->inputPoll(port, device, input); }
|
||||||
unsigned dipSettings(const Markup::Node &node) { return bind->dipSettings(node); }
|
unsigned dipSettings(const Markup::Node& node) { return bind->dipSettings(node); }
|
||||||
string path(unsigned group) { return bind->path(group); }
|
string path(unsigned group) { return bind->path(group); }
|
||||||
string server() { return bind->server(); }
|
string server() { return bind->server(); }
|
||||||
template<typename... Args> void notify(Args&... args) { return bind->notify({std::forward<Args>(args)...}); }
|
template<typename... Args> void notify(Args&&... args) { return bind->notify({std::forward<Args>(args)...}); }
|
||||||
|
|
||||||
//information
|
//information
|
||||||
virtual string title() = 0;
|
virtual string title() = 0;
|
||||||
|
@ -85,8 +85,8 @@ struct Interface {
|
||||||
virtual unsigned group(unsigned id) = 0;
|
virtual unsigned group(unsigned id) = 0;
|
||||||
virtual void load(unsigned id) {}
|
virtual void load(unsigned id) {}
|
||||||
virtual void save() {}
|
virtual void save() {}
|
||||||
virtual void load(unsigned id, const stream &memory) {}
|
virtual void load(unsigned id, const stream& memory) {}
|
||||||
virtual void save(unsigned id, const stream &memory) {}
|
virtual void save(unsigned id, const stream& memory) {}
|
||||||
virtual void unload() {}
|
virtual void unload() {}
|
||||||
|
|
||||||
//system interface
|
//system interface
|
||||||
|
@ -112,8 +112,6 @@ struct Interface {
|
||||||
//debugger functions
|
//debugger functions
|
||||||
virtual bool tracerEnable(bool) { return false; }
|
virtual bool tracerEnable(bool) { return false; }
|
||||||
virtual void exportMemory() {}
|
virtual void exportMemory() {}
|
||||||
|
|
||||||
Interface() : bind(nullptr) {}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,8 +11,12 @@ void CPU::serialize(serializer &s) {
|
||||||
s.integer(status.irq_apu_line);
|
s.integer(status.irq_apu_line);
|
||||||
|
|
||||||
s.integer(status.rdy_line);
|
s.integer(status.rdy_line);
|
||||||
s.integer(status.rdy_addr.valid);
|
bool rdy_addr_valid = status.rdy_addr;
|
||||||
s.integer(status.rdy_addr.value);
|
unsigned rdy_addr_value = 0;
|
||||||
|
if(rdy_addr_valid) rdy_addr_value = status.rdy_addr();
|
||||||
|
s.integer(rdy_addr_valid);
|
||||||
|
s.integer(rdy_addr_value);
|
||||||
|
if(rdy_addr_valid) status.rdy_addr = rdy_addr_value;
|
||||||
|
|
||||||
s.integer(status.oam_dma_pending);
|
s.integer(status.oam_dma_pending);
|
||||||
s.integer(status.oam_dma_page);
|
s.integer(status.oam_dma_page);
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
namespace Famicom {
|
namespace Famicom {
|
||||||
|
|
||||||
Interface *interface = nullptr;
|
Interface* interface = nullptr;
|
||||||
|
|
||||||
string Interface::title() {
|
string Interface::title() {
|
||||||
return cartridge.title();
|
return cartridge.title();
|
||||||
|
@ -42,12 +42,12 @@ void Interface::load(unsigned id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interface::save() {
|
void Interface::save() {
|
||||||
for(auto &memory : cartridge.memory) {
|
for(auto& memory : cartridge.memory) {
|
||||||
saveRequest(memory.id, memory.name);
|
saveRequest(memory.id, memory.name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interface::load(unsigned id, const stream &stream) {
|
void Interface::load(unsigned id, const stream& stream) {
|
||||||
if(id == ID::Manifest) cartridge.information.markup = stream.text();
|
if(id == ID::Manifest) cartridge.information.markup = stream.text();
|
||||||
|
|
||||||
if(id == ID::ProgramROM) {
|
if(id == ID::ProgramROM) {
|
||||||
|
@ -67,7 +67,7 @@ void Interface::load(unsigned id, const stream &stream) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interface::save(unsigned id, const stream &stream) {
|
void Interface::save(unsigned id, const stream& stream) {
|
||||||
if(id == ID::ProgramRAM) {
|
if(id == ID::ProgramRAM) {
|
||||||
stream.write(cartridge.board->prgram.data, cartridge.board->prgram.size);
|
stream.write(cartridge.board->prgram.data, cartridge.board->prgram.size);
|
||||||
}
|
}
|
||||||
|
@ -99,15 +99,15 @@ serializer Interface::serialize() {
|
||||||
return system.serialize();
|
return system.serialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Interface::unserialize(serializer &s) {
|
bool Interface::unserialize(serializer& s) {
|
||||||
return system.unserialize(s);
|
return system.unserialize(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interface::cheatSet(const lstring &list) {
|
void Interface::cheatSet(const lstring& list) {
|
||||||
cheat.reset();
|
cheat.reset();
|
||||||
for(auto &code : list) {
|
for(auto& code : list) {
|
||||||
lstring codelist = code.split("+");
|
lstring codelist = code.split("+");
|
||||||
for(auto &part : codelist) {
|
for(auto& part : codelist) {
|
||||||
unsigned addr, data, comp;
|
unsigned addr, data, comp;
|
||||||
if(Cheat::decode(part, addr, data, comp)) cheat.append({addr, data, comp});
|
if(Cheat::decode(part, addr, data, comp)) cheat.append({addr, data, comp});
|
||||||
}
|
}
|
||||||
|
@ -150,8 +150,8 @@ Interface::Interface() {
|
||||||
port.append({0, "Port 1"});
|
port.append({0, "Port 1"});
|
||||||
port.append({1, "Port 2"});
|
port.append({1, "Port 2"});
|
||||||
|
|
||||||
for(auto &device : this->device) {
|
for(auto& device : this->device) {
|
||||||
for(auto &port : this->port) {
|
for(auto& port : this->port) {
|
||||||
if(device.portmask & (1 << port.id)) {
|
if(device.portmask & (1 << port.id)) {
|
||||||
port.device.append(device);
|
port.device.append(device);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,8 +32,8 @@ struct Interface : Emulator::Interface {
|
||||||
unsigned group(unsigned id);
|
unsigned group(unsigned id);
|
||||||
void load(unsigned id);
|
void load(unsigned id);
|
||||||
void save();
|
void save();
|
||||||
void load(unsigned id, const stream &stream);
|
void load(unsigned id, const stream& stream);
|
||||||
void save(unsigned id, const stream &stream);
|
void save(unsigned id, const stream& stream);
|
||||||
void unload();
|
void unload();
|
||||||
|
|
||||||
void power();
|
void power();
|
||||||
|
@ -53,7 +53,7 @@ private:
|
||||||
vector<Device> device;
|
vector<Device> device;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Interface *interface;
|
extern Interface* interface;
|
||||||
|
|
||||||
#ifndef FC_HPP
|
#ifndef FC_HPP
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
namespace GameBoy {
|
namespace GameBoy {
|
||||||
|
|
||||||
Interface *interface = nullptr;
|
Interface* interface = nullptr;
|
||||||
|
|
||||||
void Interface::lcdScanline() {
|
void Interface::lcdScanline() {
|
||||||
if(hook) hook->lcdScanline();
|
if(hook) hook->lcdScanline();
|
||||||
|
@ -62,7 +62,7 @@ void Interface::save() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interface::load(unsigned id, const stream &stream) {
|
void Interface::load(unsigned id, const stream& stream) {
|
||||||
if(id == ID::GameBoyBootROM) {
|
if(id == ID::GameBoyBootROM) {
|
||||||
stream.read(system.bootROM.dmg, min( 256u, stream.size()));
|
stream.read(system.bootROM.dmg, min( 256u, stream.size()));
|
||||||
}
|
}
|
||||||
|
@ -86,7 +86,7 @@ void Interface::load(unsigned id, const stream &stream) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interface::save(unsigned id, const stream &stream) {
|
void Interface::save(unsigned id, const stream& stream) {
|
||||||
if(id == ID::RAM) {
|
if(id == ID::RAM) {
|
||||||
stream.write(cartridge.ramdata, cartridge.ramsize);
|
stream.write(cartridge.ramdata, cartridge.ramsize);
|
||||||
}
|
}
|
||||||
|
@ -114,15 +114,15 @@ serializer Interface::serialize() {
|
||||||
return system.serialize();
|
return system.serialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Interface::unserialize(serializer &s) {
|
bool Interface::unserialize(serializer& s) {
|
||||||
return system.unserialize(s);
|
return system.unserialize(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interface::cheatSet(const lstring &list) {
|
void Interface::cheatSet(const lstring& list) {
|
||||||
cheat.reset();
|
cheat.reset();
|
||||||
for(auto &code : list) {
|
for(auto& code : list) {
|
||||||
lstring codelist = code.split("+");
|
lstring codelist = code.split("+");
|
||||||
for(auto &part : codelist) {
|
for(auto& part : codelist) {
|
||||||
unsigned addr, data, comp;
|
unsigned addr, data, comp;
|
||||||
if(Cheat::decode(part, addr, data, comp)) cheat.append({addr, data, comp});
|
if(Cheat::decode(part, addr, data, comp)) cheat.append({addr, data, comp});
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,8 @@ struct Interface : Emulator::Interface {
|
||||||
struct Hook {
|
struct Hook {
|
||||||
virtual void lcdScanline() {}
|
virtual void lcdScanline() {}
|
||||||
virtual void joypWrite(bool p15, bool p14) {}
|
virtual void joypWrite(bool p15, bool p14) {}
|
||||||
} *hook;
|
};
|
||||||
|
Hook* hook = nullptr;
|
||||||
|
|
||||||
void lcdScanline();
|
void lcdScanline();
|
||||||
void joypWrite(bool p15, bool p14);
|
void joypWrite(bool p15, bool p14);
|
||||||
|
@ -44,8 +45,8 @@ struct Interface : Emulator::Interface {
|
||||||
unsigned group(unsigned id);
|
unsigned group(unsigned id);
|
||||||
void load(unsigned id);
|
void load(unsigned id);
|
||||||
void save();
|
void save();
|
||||||
void load(unsigned id, const stream &stream);
|
void load(unsigned id, const stream& stream);
|
||||||
void save(unsigned id, const stream &stream);
|
void save(unsigned id, const stream& stream);
|
||||||
void unload();
|
void unload();
|
||||||
|
|
||||||
void power();
|
void power();
|
||||||
|
@ -65,7 +66,7 @@ private:
|
||||||
vector<Device> device;
|
vector<Device> device;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Interface *interface;
|
extern Interface* interface;
|
||||||
|
|
||||||
#ifndef GB_HPP
|
#ifndef GB_HPP
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
namespace GameBoyAdvance {
|
namespace GameBoyAdvance {
|
||||||
|
|
||||||
Interface *interface = nullptr;
|
Interface* interface = nullptr;
|
||||||
|
|
||||||
string Interface::title() {
|
string Interface::title() {
|
||||||
return cartridge.title();
|
return cartridge.title();
|
||||||
|
@ -40,12 +40,12 @@ void Interface::load(unsigned id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interface::save() {
|
void Interface::save() {
|
||||||
for(auto &memory : cartridge.memory) {
|
for(auto& memory : cartridge.memory) {
|
||||||
interface->saveRequest(memory.id, memory.name);
|
interface->saveRequest(memory.id, memory.name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interface::load(unsigned id, const stream &stream) {
|
void Interface::load(unsigned id, const stream& stream) {
|
||||||
if(id == ID::BIOS) {
|
if(id == ID::BIOS) {
|
||||||
stream.read(bios.data, min(bios.size, stream.size()));
|
stream.read(bios.data, min(bios.size, stream.size()));
|
||||||
}
|
}
|
||||||
|
@ -69,7 +69,7 @@ void Interface::load(unsigned id, const stream &stream) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Interface::save(unsigned id, const stream &stream) {
|
void Interface::save(unsigned id, const stream& stream) {
|
||||||
if(id == ID::RAM) {
|
if(id == ID::RAM) {
|
||||||
stream.write(cartridge.ram.data, cartridge.ram.size);
|
stream.write(cartridge.ram.data, cartridge.ram.size);
|
||||||
}
|
}
|
||||||
|
@ -105,7 +105,7 @@ serializer Interface::serialize() {
|
||||||
return system.serialize();
|
return system.serialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Interface::unserialize(serializer &s) {
|
bool Interface::unserialize(serializer& s) {
|
||||||
return system.unserialize(s);
|
return system.unserialize(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,8 +32,8 @@ struct Interface : Emulator::Interface {
|
||||||
unsigned group(unsigned id);
|
unsigned group(unsigned id);
|
||||||
void load(unsigned id);
|
void load(unsigned id);
|
||||||
void save();
|
void save();
|
||||||
void load(unsigned id, const stream &stream);
|
void load(unsigned id, const stream& stream);
|
||||||
void save(unsigned id, const stream &stream);
|
void save(unsigned id, const stream& stream);
|
||||||
void unload();
|
void unload();
|
||||||
|
|
||||||
void power();
|
void power();
|
||||||
|
@ -51,7 +51,7 @@ private:
|
||||||
vector<Device> device;
|
vector<Device> device;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Interface *interface;
|
extern Interface* interface;
|
||||||
|
|
||||||
#ifndef GBA_HPP
|
#ifndef GBA_HPP
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,13 +5,15 @@
|
||||||
#undef max
|
#undef max
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
template<typename T, typename U> T min(const T &t, const U &u) {
|
|
||||||
return t < u ? t : u;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T, typename U> T max(const T &t, const U &u) {
|
template<typename T, typename U> T min(const T& t, const U& u) {
|
||||||
return t > u ? t : u;
|
return t < u ? t : u;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename T, typename U> T max(const T& t, const U& u) {
|
||||||
|
return t > u ? t : u;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -5,69 +5,73 @@
|
||||||
#include <nall/traits.hpp>
|
#include <nall/traits.hpp>
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
struct any {
|
|
||||||
bool empty() const { return container; }
|
|
||||||
const std::type_info& type() const { return container ? container->type() : typeid(void); }
|
|
||||||
|
|
||||||
template<typename T> any& operator=(const T& value_) {
|
struct any {
|
||||||
typedef typename type_if<
|
bool empty() const { return container; }
|
||||||
std::is_array<T>::value,
|
const std::type_info& type() const { return container ? container->type() : typeid(void); }
|
||||||
typename std::remove_extent<typename std::add_const<T>::type>::type*,
|
|
||||||
T
|
|
||||||
>::type auto_t;
|
|
||||||
|
|
||||||
if(type() == typeid(auto_t)) {
|
template<typename T> any& operator=(const T& value) {
|
||||||
static_cast<holder<auto_t>*>(container)->value = (auto_t)value_;
|
typedef typename type_if<
|
||||||
} else {
|
std::is_array<T>::value,
|
||||||
if(container) delete container;
|
typename std::remove_extent<typename std::add_const<T>::type>::type*,
|
||||||
container = new holder<auto_t>((auto_t)value_);
|
T
|
||||||
}
|
>::type auto_t;
|
||||||
|
|
||||||
return *this;
|
if(type() == typeid(auto_t)) {
|
||||||
|
static_cast<holder<auto_t>*>(container)->value = (auto_t)value;
|
||||||
|
} else {
|
||||||
|
if(container) delete container;
|
||||||
|
container = new holder<auto_t>((auto_t)value);
|
||||||
}
|
}
|
||||||
|
|
||||||
any() : container(nullptr) {}
|
return *this;
|
||||||
~any() { if(container) delete container; }
|
}
|
||||||
template<typename T> any(const T& value_) : container(nullptr) { operator=(value_); }
|
|
||||||
|
|
||||||
private:
|
any() = default;
|
||||||
struct placeholder {
|
template<typename T> any(const T& value) { operator=(value); }
|
||||||
virtual const std::type_info& type() const = 0;
|
~any() { if(container) delete container; }
|
||||||
} *container;
|
|
||||||
|
|
||||||
template<typename T> struct holder : placeholder {
|
private:
|
||||||
T value;
|
struct placeholder {
|
||||||
const std::type_info& type() const { return typeid(T); }
|
virtual const std::type_info& type() const = 0;
|
||||||
holder(const T& value_) : value(value_) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T> friend T any_cast(any&);
|
|
||||||
template<typename T> friend T any_cast(const any&);
|
|
||||||
template<typename T> friend T* any_cast(any*);
|
|
||||||
template<typename T> friend const T* any_cast(const any*);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T> T any_cast(any &value) {
|
placeholder* container = nullptr;
|
||||||
typedef typename std::remove_reference<T>::type nonref;
|
|
||||||
if(value.type() != typeid(nonref)) throw;
|
|
||||||
return static_cast<any::holder<nonref>*>(value.container)->value;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T> T any_cast(const any &value) {
|
template<typename T> struct holder : placeholder {
|
||||||
typedef const typename std::remove_reference<T>::type nonref;
|
T value;
|
||||||
if(value.type() != typeid(nonref)) throw;
|
const std::type_info& type() const { return typeid(T); }
|
||||||
return static_cast<any::holder<nonref>*>(value.container)->value;
|
holder(const T& value) : value(value) {}
|
||||||
}
|
};
|
||||||
|
|
||||||
template<typename T> T* any_cast(any *value) {
|
template<typename T> friend T any_cast(any&);
|
||||||
if(!value || value->type() != typeid(T)) return nullptr;
|
template<typename T> friend T any_cast(const any&);
|
||||||
return &static_cast<any::holder<T>*>(value->container)->value;
|
template<typename T> friend T* any_cast(any*);
|
||||||
}
|
template<typename T> friend const T* any_cast(const any*);
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T> T any_cast(any& value) {
|
||||||
|
typedef typename std::remove_reference<T>::type nonref;
|
||||||
|
if(value.type() != typeid(nonref)) throw;
|
||||||
|
return static_cast<any::holder<nonref>*>(value.container)->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T> T any_cast(const any& value) {
|
||||||
|
typedef const typename std::remove_reference<T>::type nonref;
|
||||||
|
if(value.type() != typeid(nonref)) throw;
|
||||||
|
return static_cast<any::holder<nonref>*>(value.container)->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T> T* any_cast(any* value) {
|
||||||
|
if(!value || value->type() != typeid(T)) return nullptr;
|
||||||
|
return &static_cast<any::holder<T>*>(value->container)->value;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T> const T* any_cast(const any* value) {
|
||||||
|
if(!value || value->type() != typeid(T)) return nullptr;
|
||||||
|
return &static_cast<any::holder<T>*>(value->container)->value;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename T> const T* any_cast(const any *value) {
|
|
||||||
if(!value || value->type() != typeid(T)) return nullptr;
|
|
||||||
return &static_cast<any::holder<T>*>(value->container)->value;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -5,34 +5,28 @@
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
|
|
||||||
//note: this header is intended to form the base for user-defined literals;
|
constexpr inline uintmax_t binary_(const char* s, uintmax_t sum = 0) {
|
||||||
//once they are supported by GCC. eg:
|
|
||||||
//unsigned operator "" b(const char *s) { return binary(s); }
|
|
||||||
//-> signed data = 1001b;
|
|
||||||
//(0b1001 is nicer, but is not part of the C++ standard)
|
|
||||||
|
|
||||||
constexpr inline uintmax_t binary_(const char *s, uintmax_t sum = 0) {
|
|
||||||
return (
|
return (
|
||||||
*s == '0' || *s == '1' ? binary_(s + 1, (sum << 1) | *s - '0') :
|
*s == '0' || *s == '1' ? binary_(s + 1, (sum << 1) | *s - '0') :
|
||||||
sum
|
sum
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr inline uintmax_t octal_(const char *s, uintmax_t sum = 0) {
|
constexpr inline uintmax_t octal_(const char* s, uintmax_t sum = 0) {
|
||||||
return (
|
return (
|
||||||
*s >= '0' && *s <= '7' ? octal_(s + 1, (sum << 3) | *s - '0') :
|
*s >= '0' && *s <= '7' ? octal_(s + 1, (sum << 3) | *s - '0') :
|
||||||
sum
|
sum
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr inline uintmax_t decimal_(const char *s, uintmax_t sum = 0) {
|
constexpr inline uintmax_t decimal_(const char* s, uintmax_t sum = 0) {
|
||||||
return (
|
return (
|
||||||
*s >= '0' && *s <= '9' ? decimal_(s + 1, (sum * 10) + *s - '0') :
|
*s >= '0' && *s <= '9' ? decimal_(s + 1, (sum * 10) + *s - '0') :
|
||||||
sum
|
sum
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr inline uintmax_t hex_(const char *s, uintmax_t sum = 0) {
|
constexpr inline uintmax_t hex_(const char* s, uintmax_t sum = 0) {
|
||||||
return (
|
return (
|
||||||
*s >= 'A' && *s <= 'F' ? hex_(s + 1, (sum << 4) | *s - 'A' + 10) :
|
*s >= 'A' && *s <= 'F' ? hex_(s + 1, (sum << 4) | *s - 'A' + 10) :
|
||||||
*s >= 'a' && *s <= 'f' ? hex_(s + 1, (sum << 4) | *s - 'a' + 10) :
|
*s >= 'a' && *s <= 'f' ? hex_(s + 1, (sum << 4) | *s - 'a' + 10) :
|
||||||
|
@ -43,7 +37,7 @@ constexpr inline uintmax_t hex_(const char *s, uintmax_t sum = 0) {
|
||||||
|
|
||||||
//
|
//
|
||||||
|
|
||||||
constexpr inline uintmax_t binary(const char *s) {
|
constexpr inline uintmax_t binary(const char* s) {
|
||||||
return (
|
return (
|
||||||
*s == '0' && *(s + 1) == 'B' ? binary_(s + 2) :
|
*s == '0' && *(s + 1) == 'B' ? binary_(s + 2) :
|
||||||
*s == '0' && *(s + 1) == 'b' ? binary_(s + 2) :
|
*s == '0' && *(s + 1) == 'b' ? binary_(s + 2) :
|
||||||
|
@ -52,13 +46,13 @@ 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 (
|
||||||
octal_(s)
|
octal_(s)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr inline intmax_t integer(const char *s) {
|
constexpr inline intmax_t integer(const char* s) {
|
||||||
return (
|
return (
|
||||||
*s == '+' ? +decimal_(s + 1) :
|
*s == '+' ? +decimal_(s + 1) :
|
||||||
*s == '-' ? -decimal_(s + 1) :
|
*s == '-' ? -decimal_(s + 1) :
|
||||||
|
@ -66,13 +60,13 @@ constexpr inline intmax_t integer(const char *s) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr inline uintmax_t decimal(const char *s) {
|
constexpr inline uintmax_t decimal(const char* s) {
|
||||||
return (
|
return (
|
||||||
decimal_(s)
|
decimal_(s)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr inline uintmax_t hex(const char *s) {
|
constexpr inline uintmax_t hex(const char* s) {
|
||||||
return (
|
return (
|
||||||
*s == '0' && *(s + 1) == 'X' ? hex_(s + 2) :
|
*s == '0' && *(s + 1) == 'X' ? hex_(s + 2) :
|
||||||
*s == '0' && *(s + 1) == 'x' ? hex_(s + 2) :
|
*s == '0' && *(s + 1) == 'x' ? hex_(s + 2) :
|
||||||
|
@ -81,7 +75,7 @@ constexpr inline uintmax_t hex(const char *s) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr inline intmax_t numeral(const char *s) {
|
constexpr inline intmax_t numeral(const char* s) {
|
||||||
return (
|
return (
|
||||||
*s == '0' && *(s + 1) == 'X' ? hex_(s + 2) :
|
*s == '0' && *(s + 1) == 'X' ? hex_(s + 2) :
|
||||||
*s == '0' && *(s + 1) == 'x' ? hex_(s + 2) :
|
*s == '0' && *(s + 1) == 'x' ? hex_(s + 2) :
|
||||||
|
@ -94,7 +88,7 @@ constexpr inline intmax_t numeral(const char *s) {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline double fp(const char *s) {
|
inline double fp(const char* s) {
|
||||||
return atof(s);
|
return atof(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,114 +5,116 @@
|
||||||
#include <nall/string.hpp>
|
#include <nall/string.hpp>
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
struct base64 {
|
|
||||||
static bool encode(char *&output, const uint8_t* input, unsigned inlength) {
|
|
||||||
output = new char[inlength * 8 / 6 + 8]();
|
|
||||||
|
|
||||||
unsigned i = 0, o = 0;
|
struct base64 {
|
||||||
while(i < inlength) {
|
static bool encode(char*& output, const uint8_t* input, unsigned inlength) {
|
||||||
switch(i % 3) {
|
output = new char[inlength * 8 / 6 + 8]();
|
||||||
|
|
||||||
case 0: {
|
unsigned i = 0, o = 0;
|
||||||
output[o++] = enc(input[i] >> 2);
|
while(i < inlength) {
|
||||||
output[o] = enc((input[i] & 3) << 4);
|
switch(i % 3) {
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 1: {
|
case 0: {
|
||||||
uint8_t prev = dec(output[o]);
|
output[o++] = enc(input[i] >> 2);
|
||||||
output[o++] = enc(prev + (input[i] >> 4));
|
output[o] = enc((input[i] & 3) << 4);
|
||||||
output[o] = enc((input[i] & 15) << 2);
|
break;
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 2: {
|
|
||||||
uint8_t prev = dec(output[o]);
|
|
||||||
output[o++] = enc(prev + (input[i] >> 6));
|
|
||||||
output[o++] = enc(input[i] & 63);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
i++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
case 1: {
|
||||||
}
|
uint8_t prev = dec(output[o]);
|
||||||
|
output[o++] = enc(prev + (input[i] >> 4));
|
||||||
static string encode(const string &data) {
|
output[o] = enc((input[i] & 15) << 2);
|
||||||
char *buffer = nullptr;
|
break;
|
||||||
encode(buffer, (const uint8_t*)(const char*)data, data.length());
|
|
||||||
string result = buffer;
|
|
||||||
delete[] buffer;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool decode(uint8_t *&output, unsigned &outlength, const char *input) {
|
|
||||||
unsigned inlength = strlen(input), infix = 0;
|
|
||||||
output = new uint8_t[inlength + 1]();
|
|
||||||
|
|
||||||
unsigned i = 0, o = 0;
|
|
||||||
while(i < inlength) {
|
|
||||||
uint8_t x = dec(input[i]);
|
|
||||||
|
|
||||||
switch(i++ & 3) {
|
|
||||||
|
|
||||||
case 0: {
|
|
||||||
output[o] = x << 2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 1: {
|
|
||||||
output[o++] |= x >> 4;
|
|
||||||
output[o] = (x & 15) << 4;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 2: {
|
|
||||||
output[o++] |= x >> 2;
|
|
||||||
output[o] = (x & 3) << 6;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case 3: {
|
|
||||||
output[o++] |= x;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
outlength = o;
|
case 2: {
|
||||||
return true;
|
uint8_t prev = dec(output[o]);
|
||||||
|
output[o++] = enc(prev + (input[i] >> 6));
|
||||||
|
output[o++] = enc(input[i] & 63);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
static string decode(const string &data) {
|
return true;
|
||||||
uint8_t *buffer = nullptr;
|
}
|
||||||
unsigned size = 0;
|
|
||||||
decode(buffer, size, (const char*)data);
|
static string encode(const string& data) {
|
||||||
string result = (const char*)buffer;
|
char* buffer = nullptr;
|
||||||
delete[] buffer;
|
encode(buffer, (const uint8_t*)(const char*)data, data.length());
|
||||||
return result;
|
string result = buffer;
|
||||||
|
delete[] buffer;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool decode(uint8_t*& output, unsigned& outlength, const char* input) {
|
||||||
|
unsigned inlength = strlen(input), infix = 0;
|
||||||
|
output = new uint8_t[inlength + 1]();
|
||||||
|
|
||||||
|
unsigned i = 0, o = 0;
|
||||||
|
while(i < inlength) {
|
||||||
|
uint8_t x = dec(input[i]);
|
||||||
|
|
||||||
|
switch(i++ & 3) {
|
||||||
|
|
||||||
|
case 0: {
|
||||||
|
output[o] = x << 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 1: {
|
||||||
|
output[o++] |= x >> 4;
|
||||||
|
output[o] = (x & 15) << 4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 2: {
|
||||||
|
output[o++] |= x >> 2;
|
||||||
|
output[o] = (x & 3) << 6;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case 3: {
|
||||||
|
output[o++] |= x;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
outlength = o;
|
||||||
static char enc(uint8_t n) {
|
return true;
|
||||||
//base64 for URL encodings (URL = -_, MIME = +/)
|
}
|
||||||
static char lookup_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
|
||||||
return lookup_table[n & 63];
|
static string decode(const string& data) {
|
||||||
}
|
uint8_t* buffer = nullptr;
|
||||||
|
unsigned size = 0;
|
||||||
|
decode(buffer, size, (const char*)data);
|
||||||
|
string result = (const char*)buffer;
|
||||||
|
delete[] buffer;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
static char enc(uint8_t n) {
|
||||||
|
//base64 for URL encodings (URL = -_, MIME = +/)
|
||||||
|
static char lookup_table[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
||||||
|
return lookup_table[n & 63];
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint8_t dec(char n) {
|
||||||
|
if(n >= 'A' && n <= 'Z') return n - 'A';
|
||||||
|
if(n >= 'a' && n <= 'z') return n - 'a' + 26;
|
||||||
|
if(n >= '0' && n <= '9') return n - '0' + 52;
|
||||||
|
if(n == '-') return 62;
|
||||||
|
if(n == '_') return 63;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
static uint8_t dec(char n) {
|
|
||||||
if(n >= 'A' && n <= 'Z') return n - 'A';
|
|
||||||
if(n >= 'a' && n <= 'z') return n - 'a' + 26;
|
|
||||||
if(n >= '0' && n <= '9') return n - '0' + 52;
|
|
||||||
if(n == '-') return 62;
|
|
||||||
if(n == '_') return 63;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
namespace nall {
|
namespace nall {
|
||||||
|
|
||||||
struct beatArchive : beatBase {
|
struct beatArchive : beatBase {
|
||||||
bool create(const string &beatname, string pathname, const string &metadata = "") {
|
bool create(const string& beatname, string pathname, const string& metadata = "") {
|
||||||
if(fp.open(beatname, file::mode::write) == false) return false;
|
if(fp.open(beatname, file::mode::write) == false) return false;
|
||||||
if(pathname.endswith("/") == false) pathname.append("/");
|
if(pathname.endswith("/") == false) pathname.append("/");
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ struct beatArchive : beatBase {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool unpack(const string &beatname, string pathname) {
|
bool unpack(const string& beatname, string pathname) {
|
||||||
if(fp.open(beatname, file::mode::read) == false) return false;
|
if(fp.open(beatname, file::mode::read) == false) return false;
|
||||||
if(pathname.endswith("/") == false) pathname.append("/");
|
if(pathname.endswith("/") == false) pathname.append("/");
|
||||||
|
|
||||||
|
|
|
@ -8,15 +8,15 @@ protected:
|
||||||
file fp;
|
file fp;
|
||||||
uint32_t checksum;
|
uint32_t checksum;
|
||||||
|
|
||||||
void ls(lstring &list, const string &path, const string &basepath) {
|
void ls(lstring& list, const string& path, const string& basepath) {
|
||||||
lstring paths = directory::folders(path);
|
lstring paths = directory::folders(path);
|
||||||
for(auto &pathname : paths) {
|
for(auto& pathname : paths) {
|
||||||
list.append(string{path, pathname}.ltrim<1>(basepath));
|
list.append(string{path, pathname}.ltrim<1>(basepath));
|
||||||
ls(list, {path, pathname}, basepath);
|
ls(list, {path, pathname}, basepath);
|
||||||
}
|
}
|
||||||
|
|
||||||
lstring files = directory::files(path);
|
lstring files = directory::files(path);
|
||||||
for(auto &filename : files) {
|
for(auto& filename : files) {
|
||||||
list.append(string{path, filename}.ltrim<1>(basepath));
|
list.append(string{path, filename}.ltrim<1>(basepath));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,7 +36,7 @@ protected:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeString(const string &text) {
|
void writeString(const string& text) {
|
||||||
unsigned length = text.length();
|
unsigned length = text.length();
|
||||||
for(unsigned n = 0; n < length; n++) write(text[n]);
|
for(unsigned n = 0; n < length; n++) write(text[n]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,56 +10,56 @@
|
||||||
namespace nall {
|
namespace nall {
|
||||||
|
|
||||||
struct bpsdelta {
|
struct bpsdelta {
|
||||||
inline void source(const uint8_t *data, unsigned size);
|
inline void source(const uint8_t* data, unsigned size);
|
||||||
inline void target(const uint8_t *data, unsigned size);
|
inline void target(const uint8_t* data, unsigned size);
|
||||||
|
|
||||||
inline bool source(const string &filename);
|
inline bool source(const string& filename);
|
||||||
inline bool target(const string &filename);
|
inline bool target(const string& filename);
|
||||||
inline bool create(const string &filename, const string &metadata = "");
|
inline bool create(const string& filename, const string& metadata = "");
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
enum : unsigned { SourceRead, TargetRead, SourceCopy, TargetCopy };
|
enum : unsigned { SourceRead, TargetRead, SourceCopy, TargetCopy };
|
||||||
enum : unsigned { Granularity = 1 };
|
enum : unsigned { Granularity = 1 };
|
||||||
|
|
||||||
struct Node {
|
struct Node {
|
||||||
unsigned offset;
|
unsigned offset = 0;
|
||||||
Node *next;
|
Node* next = nullptr;
|
||||||
inline Node() : offset(0), next(nullptr) {}
|
Node() = default;
|
||||||
inline ~Node() { if(next) delete next; }
|
~Node() { if(next) delete next; }
|
||||||
};
|
};
|
||||||
|
|
||||||
filemap sourceFile;
|
filemap sourceFile;
|
||||||
const uint8_t *sourceData;
|
const uint8_t* sourceData;
|
||||||
unsigned sourceSize;
|
unsigned sourceSize;
|
||||||
|
|
||||||
filemap targetFile;
|
filemap targetFile;
|
||||||
const uint8_t *targetData;
|
const uint8_t* targetData;
|
||||||
unsigned targetSize;
|
unsigned targetSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
void bpsdelta::source(const uint8_t *data, unsigned size) {
|
void bpsdelta::source(const uint8_t* data, unsigned size) {
|
||||||
sourceData = data;
|
sourceData = data;
|
||||||
sourceSize = size;
|
sourceSize = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void bpsdelta::target(const uint8_t *data, unsigned size) {
|
void bpsdelta::target(const uint8_t* data, unsigned size) {
|
||||||
targetData = data;
|
targetData = data;
|
||||||
targetSize = size;
|
targetSize = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool bpsdelta::source(const string &filename) {
|
bool bpsdelta::source(const string& filename) {
|
||||||
if(sourceFile.open(filename, filemap::mode::read) == false) return false;
|
if(sourceFile.open(filename, filemap::mode::read) == false) return false;
|
||||||
source(sourceFile.data(), sourceFile.size());
|
source(sourceFile.data(), sourceFile.size());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool bpsdelta::target(const string &filename) {
|
bool bpsdelta::target(const string& filename) {
|
||||||
if(targetFile.open(filename, filemap::mode::read) == false) return false;
|
if(targetFile.open(filename, filemap::mode::read) == false) return false;
|
||||||
target(targetFile.data(), targetFile.size());
|
target(targetFile.data(), targetFile.size());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool bpsdelta::create(const string &filename, const string &metadata) {
|
bool bpsdelta::create(const string& filename, const string& metadata) {
|
||||||
file modifyFile;
|
file modifyFile;
|
||||||
if(modifyFile.open(filename, file::mode::write) == false) return false;
|
if(modifyFile.open(filename, file::mode::write) == false) return false;
|
||||||
|
|
||||||
|
@ -96,7 +96,8 @@ bool bpsdelta::create(const string &filename, const string &metadata) {
|
||||||
encode(markupSize);
|
encode(markupSize);
|
||||||
for(unsigned n = 0; n < markupSize; n++) write(metadata[n]);
|
for(unsigned n = 0; n < markupSize; n++) write(metadata[n]);
|
||||||
|
|
||||||
Node *sourceTree[65536], *targetTree[65536];
|
Node* sourceTree[65536];
|
||||||
|
Node* targetTree[65536];
|
||||||
for(unsigned n = 0; n < 65536; n++) sourceTree[n] = nullptr, targetTree[n] = nullptr;
|
for(unsigned n = 0; n < 65536; n++) sourceTree[n] = nullptr, targetTree[n] = nullptr;
|
||||||
|
|
||||||
//source tree creation
|
//source tree creation
|
||||||
|
@ -136,7 +137,7 @@ bool bpsdelta::create(const string &filename, const string &metadata) {
|
||||||
}
|
}
|
||||||
|
|
||||||
{ //source copy
|
{ //source copy
|
||||||
Node *node = sourceTree[symbol];
|
Node* node = sourceTree[symbol];
|
||||||
while(node) {
|
while(node) {
|
||||||
unsigned length = 0, x = node->offset, y = outputOffset;
|
unsigned length = 0, x = node->offset, y = outputOffset;
|
||||||
while(x < sourceSize && y < targetSize && sourceData[x++] == targetData[y++]) length++;
|
while(x < sourceSize && y < targetSize && sourceData[x++] == targetData[y++]) length++;
|
||||||
|
@ -146,7 +147,7 @@ bool bpsdelta::create(const string &filename, const string &metadata) {
|
||||||
}
|
}
|
||||||
|
|
||||||
{ //target copy
|
{ //target copy
|
||||||
Node *node = targetTree[symbol];
|
Node* node = targetTree[symbol];
|
||||||
while(node) {
|
while(node) {
|
||||||
unsigned length = 0, x = node->offset, y = outputOffset;
|
unsigned length = 0, x = node->offset, y = outputOffset;
|
||||||
while(y < targetSize && targetData[x++] == targetData[y++]) length++;
|
while(y < targetSize && targetData[x++] == targetData[y++]) length++;
|
||||||
|
|
|
@ -10,49 +10,49 @@
|
||||||
namespace nall {
|
namespace nall {
|
||||||
|
|
||||||
struct bpslinear {
|
struct bpslinear {
|
||||||
inline void source(const uint8_t *data, unsigned size);
|
inline void source(const uint8_t* data, unsigned size);
|
||||||
inline void target(const uint8_t *data, unsigned size);
|
inline void target(const uint8_t* data, unsigned size);
|
||||||
|
|
||||||
inline bool source(const string &filename);
|
inline bool source(const string& filename);
|
||||||
inline bool target(const string &filename);
|
inline bool target(const string& filename);
|
||||||
inline bool create(const string &filename, const string &metadata = "");
|
inline bool create(const string& filename, const string& metadata = "");
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
enum : unsigned { SourceRead, TargetRead, SourceCopy, TargetCopy };
|
enum : unsigned { SourceRead, TargetRead, SourceCopy, TargetCopy };
|
||||||
enum : unsigned { Granularity = 1 };
|
enum : unsigned { Granularity = 1 };
|
||||||
|
|
||||||
filemap sourceFile;
|
filemap sourceFile;
|
||||||
const uint8_t *sourceData;
|
const uint8_t* sourceData;
|
||||||
unsigned sourceSize;
|
unsigned sourceSize;
|
||||||
|
|
||||||
filemap targetFile;
|
filemap targetFile;
|
||||||
const uint8_t *targetData;
|
const uint8_t* targetData;
|
||||||
unsigned targetSize;
|
unsigned targetSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
void bpslinear::source(const uint8_t *data, unsigned size) {
|
void bpslinear::source(const uint8_t* data, unsigned size) {
|
||||||
sourceData = data;
|
sourceData = data;
|
||||||
sourceSize = size;
|
sourceSize = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void bpslinear::target(const uint8_t *data, unsigned size) {
|
void bpslinear::target(const uint8_t* data, unsigned size) {
|
||||||
targetData = data;
|
targetData = data;
|
||||||
targetSize = size;
|
targetSize = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool bpslinear::source(const string &filename) {
|
bool bpslinear::source(const string& filename) {
|
||||||
if(sourceFile.open(filename, filemap::mode::read) == false) return false;
|
if(sourceFile.open(filename, filemap::mode::read) == false) return false;
|
||||||
source(sourceFile.data(), sourceFile.size());
|
source(sourceFile.data(), sourceFile.size());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool bpslinear::target(const string &filename) {
|
bool bpslinear::target(const string& filename) {
|
||||||
if(targetFile.open(filename, filemap::mode::read) == false) return false;
|
if(targetFile.open(filename, filemap::mode::read) == false) return false;
|
||||||
target(targetFile.data(), targetFile.size());
|
target(targetFile.data(), targetFile.size());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool bpslinear::create(const string &filename, const string &metadata) {
|
bool bpslinear::create(const string& filename, const string& metadata) {
|
||||||
file modifyFile;
|
file modifyFile;
|
||||||
if(modifyFile.open(filename, file::mode::write) == false) return false;
|
if(modifyFile.open(filename, file::mode::write) == false) return false;
|
||||||
|
|
||||||
|
|
|
@ -10,8 +10,8 @@
|
||||||
namespace nall {
|
namespace nall {
|
||||||
|
|
||||||
struct bpsmetadata {
|
struct bpsmetadata {
|
||||||
inline bool load(const string &filename);
|
inline bool load(const string& filename);
|
||||||
inline bool save(const string &filename, const string &metadata);
|
inline bool save(const string& filename, const string& metadata);
|
||||||
inline string metadata() const;
|
inline string metadata() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -19,7 +19,7 @@ protected:
|
||||||
string metadataString;
|
string metadataString;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool bpsmetadata::load(const string &filename) {
|
bool bpsmetadata::load(const string& filename) {
|
||||||
if(sourceFile.open(filename, file::mode::read) == false) return false;
|
if(sourceFile.open(filename, file::mode::read) == false) return false;
|
||||||
|
|
||||||
auto read = [&]() -> uint8_t {
|
auto read = [&]() -> uint8_t {
|
||||||
|
@ -53,7 +53,7 @@ bool bpsmetadata::load(const string &filename) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool bpsmetadata::save(const string &filename, const string &metadata) {
|
bool bpsmetadata::save(const string& filename, const string& metadata) {
|
||||||
file targetFile;
|
file targetFile;
|
||||||
if(targetFile.open(filename, file::mode::write) == false) return false;
|
if(targetFile.open(filename, file::mode::write) == false) return false;
|
||||||
if(sourceFile.open() == false) return false;
|
if(sourceFile.open() == false) return false;
|
||||||
|
|
|
@ -20,7 +20,7 @@ struct bpsmulti {
|
||||||
OriginTarget = 1,
|
OriginTarget = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
bool create(const string &patchName, const string &sourcePath, const string &targetPath, bool delta = false, const string &metadata = "") {
|
bool create(const string& patchName, const string& sourcePath, const string& targetPath, bool delta = false, const string& metadata = "") {
|
||||||
if(fp.open()) fp.close();
|
if(fp.open()) fp.close();
|
||||||
fp.open(patchName, file::mode::write);
|
fp.open(patchName, file::mode::write);
|
||||||
checksum = ~0;
|
checksum = ~0;
|
||||||
|
@ -33,7 +33,7 @@ struct bpsmulti {
|
||||||
ls(sourceList, sourcePath, sourcePath);
|
ls(sourceList, sourcePath, sourcePath);
|
||||||
ls(targetList, targetPath, targetPath);
|
ls(targetList, targetPath, targetPath);
|
||||||
|
|
||||||
for(auto &targetName : targetList) {
|
for(auto& targetName : targetList) {
|
||||||
if(targetName.endswith("/")) {
|
if(targetName.endswith("/")) {
|
||||||
targetName.rtrim<1>("/");
|
targetName.rtrim<1>("/");
|
||||||
writeNumber(CreatePath | ((targetName.length() - 1) << 2));
|
writeNumber(CreatePath | ((targetName.length() - 1) << 2));
|
||||||
|
@ -94,7 +94,7 @@ struct bpsmulti {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool apply(const string &patchName, const string &sourcePath, const string &targetPath) {
|
bool apply(const string& patchName, const string& sourcePath, const string& targetPath) {
|
||||||
directory::remove(targetPath); //start with a clean directory
|
directory::remove(targetPath); //start with a clean directory
|
||||||
directory::create(targetPath);
|
directory::create(targetPath);
|
||||||
|
|
||||||
|
@ -157,15 +157,15 @@ protected:
|
||||||
uint32_t checksum;
|
uint32_t checksum;
|
||||||
|
|
||||||
//create() functions
|
//create() functions
|
||||||
void ls(lstring &list, const string &path, const string &basepath) {
|
void ls(lstring& list, const string& path, const string& basepath) {
|
||||||
lstring paths = directory::folders(path);
|
lstring paths = directory::folders(path);
|
||||||
for(auto &pathname : paths) {
|
for(auto& pathname : paths) {
|
||||||
list.append(string{path, pathname}.ltrim<1>(basepath));
|
list.append(string{path, pathname}.ltrim<1>(basepath));
|
||||||
ls(list, {path, pathname}, basepath);
|
ls(list, {path, pathname}, basepath);
|
||||||
}
|
}
|
||||||
|
|
||||||
lstring files = directory::files(path);
|
lstring files = directory::files(path);
|
||||||
for(auto &filename : files) {
|
for(auto& filename : files) {
|
||||||
list.append(string{path, filename}.ltrim<1>(basepath));
|
list.append(string{path, filename}.ltrim<1>(basepath));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -188,7 +188,7 @@ protected:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void writeString(const string &text) {
|
void writeString(const string& text) {
|
||||||
unsigned length = text.length();
|
unsigned length = text.length();
|
||||||
for(unsigned n = 0; n < length; n++) write(text[n]);
|
for(unsigned n = 0; n < length; n++) write(text[n]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,13 +10,13 @@
|
||||||
namespace nall {
|
namespace nall {
|
||||||
|
|
||||||
struct bpspatch {
|
struct bpspatch {
|
||||||
inline bool modify(const uint8_t *data, unsigned size);
|
inline bool modify(const uint8_t* data, unsigned size);
|
||||||
inline void source(const uint8_t *data, unsigned size);
|
inline void source(const uint8_t* data, unsigned size);
|
||||||
inline void target(uint8_t *data, unsigned size);
|
inline void target(uint8_t* data, unsigned size);
|
||||||
|
|
||||||
inline bool modify(const string &filename);
|
inline bool modify(const string& filename);
|
||||||
inline bool source(const string &filename);
|
inline bool source(const string& filename);
|
||||||
inline bool target(const string &filename);
|
inline bool target(const string& filename);
|
||||||
|
|
||||||
inline string metadata() const;
|
inline string metadata() const;
|
||||||
inline unsigned size() const;
|
inline unsigned size() const;
|
||||||
|
@ -39,15 +39,15 @@ protected:
|
||||||
enum : unsigned { SourceRead, TargetRead, SourceCopy, TargetCopy };
|
enum : unsigned { SourceRead, TargetRead, SourceCopy, TargetCopy };
|
||||||
|
|
||||||
filemap modifyFile;
|
filemap modifyFile;
|
||||||
const uint8_t *modifyData;
|
const uint8_t* modifyData;
|
||||||
unsigned modifySize;
|
unsigned modifySize;
|
||||||
|
|
||||||
filemap sourceFile;
|
filemap sourceFile;
|
||||||
const uint8_t *sourceData;
|
const uint8_t* sourceData;
|
||||||
unsigned sourceSize;
|
unsigned sourceSize;
|
||||||
|
|
||||||
filemap targetFile;
|
filemap targetFile;
|
||||||
uint8_t *targetData;
|
uint8_t* targetData;
|
||||||
unsigned targetSize;
|
unsigned targetSize;
|
||||||
|
|
||||||
unsigned modifySourceSize;
|
unsigned modifySourceSize;
|
||||||
|
@ -56,7 +56,7 @@ protected:
|
||||||
string metadataString;
|
string metadataString;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool bpspatch::modify(const uint8_t *data, unsigned size) {
|
bool bpspatch::modify(const uint8_t* data, unsigned size) {
|
||||||
if(size < 19) return false;
|
if(size < 19) return false;
|
||||||
modifyData = data;
|
modifyData = data;
|
||||||
modifySize = size;
|
modifySize = size;
|
||||||
|
@ -86,28 +86,28 @@ bool bpspatch::modify(const uint8_t *data, unsigned size) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void bpspatch::source(const uint8_t *data, unsigned size) {
|
void bpspatch::source(const uint8_t* data, unsigned size) {
|
||||||
sourceData = data;
|
sourceData = data;
|
||||||
sourceSize = size;
|
sourceSize = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void bpspatch::target(uint8_t *data, unsigned size) {
|
void bpspatch::target(uint8_t* data, unsigned size) {
|
||||||
targetData = data;
|
targetData = data;
|
||||||
targetSize = size;
|
targetSize = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool bpspatch::modify(const string &filename) {
|
bool bpspatch::modify(const string& filename) {
|
||||||
if(modifyFile.open(filename, filemap::mode::read) == false) return false;
|
if(modifyFile.open(filename, filemap::mode::read) == false) return false;
|
||||||
return modify(modifyFile.data(), modifyFile.size());
|
return modify(modifyFile.data(), modifyFile.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
bool bpspatch::source(const string &filename) {
|
bool bpspatch::source(const string& filename) {
|
||||||
if(sourceFile.open(filename, filemap::mode::read) == false) return false;
|
if(sourceFile.open(filename, filemap::mode::read) == false) return false;
|
||||||
source(sourceFile.data(), sourceFile.size());
|
source(sourceFile.data(), sourceFile.size());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool bpspatch::target(const string &filename) {
|
bool bpspatch::target(const string& filename) {
|
||||||
file fp;
|
file fp;
|
||||||
if(fp.open(filename, file::mode::write) == false) return false;
|
if(fp.open(filename, file::mode::write) == false) return false;
|
||||||
fp.truncate(modifyTargetSize);
|
fp.truncate(modifyTargetSize);
|
||||||
|
|
|
@ -4,79 +4,77 @@
|
||||||
#include <nall/stdint.hpp>
|
#include <nall/stdint.hpp>
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
template<unsigned bits>
|
|
||||||
inline uintmax_t uclamp(const uintmax_t x) {
|
template<unsigned bits> inline uintmax_t uclamp(const uintmax_t x) {
|
||||||
enum : uintmax_t { b = 1ull << (bits - 1), y = b * 2 - 1 };
|
enum : uintmax_t { b = 1ull << (bits - 1), y = b * 2 - 1 };
|
||||||
return y + ((x - y) & -(x < y)); //min(x, y);
|
return y + ((x - y) & -(x < y)); //min(x, y);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<unsigned bits> inline uintmax_t uclip(const uintmax_t x) {
|
||||||
|
enum : uintmax_t { b = 1ull << (bits - 1), m = b * 2 - 1 };
|
||||||
|
return (x & m);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<unsigned bits> inline intmax_t sclamp(const intmax_t x) {
|
||||||
|
enum : intmax_t { b = 1ull << (bits - 1), m = b - 1 };
|
||||||
|
return (x > m) ? m : (x < -b) ? -b : x;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<unsigned bits> inline intmax_t sclip(const intmax_t x) {
|
||||||
|
enum : uintmax_t { b = 1ull << (bits - 1), m = b * 2 - 1 };
|
||||||
|
return ((x & m) ^ b) - b;
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace bit {
|
||||||
|
constexpr inline uintmax_t mask(const char* s, uintmax_t sum = 0) {
|
||||||
|
return (
|
||||||
|
*s == '0' || *s == '1' ? mask(s + 1, (sum << 1) | 1) :
|
||||||
|
*s == ' ' || *s == '_' ? mask(s + 1, sum) :
|
||||||
|
*s ? mask(s + 1, sum << 1) :
|
||||||
|
sum
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<unsigned bits>
|
constexpr inline uintmax_t test(const char* s, uintmax_t sum = 0) {
|
||||||
inline uintmax_t uclip(const uintmax_t x) {
|
return (
|
||||||
enum : uintmax_t { b = 1ull << (bits - 1), m = b * 2 - 1 };
|
*s == '0' || *s == '1' ? test(s + 1, (sum << 1) | (*s - '0')) :
|
||||||
return (x & m);
|
*s == ' ' || *s == '_' ? test(s + 1, sum) :
|
||||||
|
*s ? test(s + 1, sum << 1) :
|
||||||
|
sum
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<unsigned bits>
|
//lowest(0b1110) == 0b0010
|
||||||
inline intmax_t sclamp(const intmax_t x) {
|
constexpr inline uintmax_t lowest(const uintmax_t x) {
|
||||||
enum : intmax_t { b = 1ull << (bits - 1), m = b - 1 };
|
return x & -x;
|
||||||
return (x > m) ? m : (x < -b) ? -b : x;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<unsigned bits>
|
//clear_lowest(0b1110) == 0b1100
|
||||||
inline intmax_t sclip(const intmax_t x) {
|
constexpr inline uintmax_t clear_lowest(const uintmax_t x) {
|
||||||
enum : uintmax_t { b = 1ull << (bits - 1), m = b * 2 - 1 };
|
return x & (x - 1);
|
||||||
return ((x & m) ^ b) - b;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace bit {
|
//set_lowest(0b0101) == 0b0111
|
||||||
constexpr inline uintmax_t mask(const char *s, uintmax_t sum = 0) {
|
constexpr inline uintmax_t set_lowest(const uintmax_t x) {
|
||||||
return (
|
return x | (x + 1);
|
||||||
*s == '0' || *s == '1' ? mask(s + 1, (sum << 1) | 1) :
|
}
|
||||||
*s == ' ' || *s == '_' ? mask(s + 1, sum) :
|
|
||||||
*s ? mask(s + 1, sum << 1) :
|
|
||||||
sum
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
constexpr inline uintmax_t test(const char *s, uintmax_t sum = 0) {
|
//count number of bits set in a byte
|
||||||
return (
|
inline unsigned count(uintmax_t x) {
|
||||||
*s == '0' || *s == '1' ? test(s + 1, (sum << 1) | (*s - '0')) :
|
unsigned count = 0;
|
||||||
*s == ' ' || *s == '_' ? test(s + 1, sum) :
|
do count += x & 1; while(x >>= 1);
|
||||||
*s ? test(s + 1, sum << 1) :
|
return count;
|
||||||
sum
|
}
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
//lowest(0b1110) == 0b0010
|
//round up to next highest single bit:
|
||||||
constexpr inline uintmax_t lowest(const uintmax_t x) {
|
//round(15) == 16, round(16) == 16, round(17) == 32
|
||||||
return x & -x;
|
inline uintmax_t round(uintmax_t x) {
|
||||||
}
|
if((x & (x - 1)) == 0) return x;
|
||||||
|
while(x & (x - 1)) x &= x - 1;
|
||||||
//clear_lowest(0b1110) == 0b1100
|
return x << 1;
|
||||||
constexpr inline uintmax_t clear_lowest(const uintmax_t x) {
|
|
||||||
return x & (x - 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
//set_lowest(0b0101) == 0b0111
|
|
||||||
constexpr inline uintmax_t set_lowest(const uintmax_t x) {
|
|
||||||
return x | (x + 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
//count number of bits set in a byte
|
|
||||||
inline unsigned count(uintmax_t x) {
|
|
||||||
unsigned count = 0;
|
|
||||||
do count += x & 1; while(x >>= 1);
|
|
||||||
return count;
|
|
||||||
}
|
|
||||||
|
|
||||||
//round up to next highest single bit:
|
|
||||||
//round(15) == 16, round(16) == 16, round(17) == 32
|
|
||||||
inline uintmax_t round(uintmax_t x) {
|
|
||||||
if((x & (x - 1)) == 0) return x;
|
|
||||||
while(x & (x - 1)) x &= x - 1;
|
|
||||||
return x << 1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -9,11 +9,11 @@
|
||||||
namespace nall {
|
namespace nall {
|
||||||
|
|
||||||
struct bmp {
|
struct bmp {
|
||||||
inline static bool read(const string &filename, uint32_t *&data, unsigned &width, unsigned &height);
|
inline static bool read(const string& filename, uint32_t*& data, unsigned& width, unsigned& height);
|
||||||
inline static bool write(const string &filename, const uint32_t *data, unsigned width, unsigned height, unsigned pitch, bool alpha = false);
|
inline static bool write(const string& filename, const uint32_t* data, unsigned width, unsigned height, unsigned pitch, bool alpha = false);
|
||||||
};
|
};
|
||||||
|
|
||||||
bool bmp::read(const string &filename, uint32_t *&data, unsigned &width, unsigned &height) {
|
bool bmp::read(const string& filename, uint32_t*& data, unsigned& width, unsigned& height) {
|
||||||
file fp;
|
file fp;
|
||||||
if(fp.open(filename, file::mode::read) == false) return false;
|
if(fp.open(filename, file::mode::read) == false) return false;
|
||||||
if(fp.size() < 0x36) return false;
|
if(fp.size() < 0x36) return false;
|
||||||
|
@ -43,7 +43,7 @@ bool bmp::read(const string &filename, uint32_t *&data, unsigned &width, unsigne
|
||||||
while(alignedWidth % 4) alignedWidth++, paddingLength++;
|
while(alignedWidth % 4) alignedWidth++, paddingLength++;
|
||||||
|
|
||||||
for(unsigned y = 0; y < height; y++) {
|
for(unsigned y = 0; y < height; y++) {
|
||||||
uint32_t *p = noFlip ? data + y * width : data + (height - 1 - y) * width;
|
uint32_t* p = noFlip ? data + y * width : data + (height - 1 - y) * width;
|
||||||
for(unsigned x = 0; x < width; x++, p++) {
|
for(unsigned x = 0; x < width; x++, p++) {
|
||||||
*p = fp.readl(bytesPerPixel);
|
*p = fp.readl(bytesPerPixel);
|
||||||
if(bytesPerPixel == 3) *p |= 255 << 24;
|
if(bytesPerPixel == 3) *p |= 255 << 24;
|
||||||
|
@ -55,7 +55,7 @@ bool bmp::read(const string &filename, uint32_t *&data, unsigned &width, unsigne
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool bmp::write(const string &filename, const uint32_t *data, unsigned width, unsigned height, unsigned pitch, bool alpha) {
|
bool bmp::write(const string& filename, const uint32_t* data, unsigned width, unsigned height, unsigned pitch, bool alpha) {
|
||||||
file fp;
|
file fp;
|
||||||
if(fp.open(filename, file::mode::write) == false) return false;
|
if(fp.open(filename, file::mode::write) == false) return false;
|
||||||
|
|
||||||
|
@ -86,7 +86,7 @@ bool bmp::write(const string &filename, const uint32_t *data, unsigned width, un
|
||||||
fp.writel(0, 4); //important color count
|
fp.writel(0, 4); //important color count
|
||||||
|
|
||||||
for(unsigned y = 0; y < height; y++) {
|
for(unsigned y = 0; y < height; y++) {
|
||||||
const uint32_t *p = (const uint32_t*)((const uint8_t*)data + y * pitch);
|
const uint32_t* p = (const uint32_t*)((const uint8_t*)data + y * pitch);
|
||||||
for(unsigned x = 0; x < width; x++) fp.writel(*p++, bytesPerPixel);
|
for(unsigned x = 0; x < width; x++) fp.writel(*p++, bytesPerPixel);
|
||||||
if(paddingLength) fp.writel(0, paddingLength);
|
if(paddingLength) fp.writel(0, paddingLength);
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ struct compositor {
|
||||||
//Metacity
|
//Metacity
|
||||||
|
|
||||||
bool compositor::enabled_metacity() {
|
bool compositor::enabled_metacity() {
|
||||||
FILE *fp = popen("gconftool-2 --get /apps/metacity/general/compositing_manager", "r");
|
FILE* fp = popen("gconftool-2 --get /apps/metacity/general/compositing_manager", "r");
|
||||||
if(!fp) return false;
|
if(!fp) return false;
|
||||||
|
|
||||||
char buffer[512];
|
char buffer[512];
|
||||||
|
@ -37,7 +37,7 @@ bool compositor::enabled_metacity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool compositor::enable_metacity(bool status) {
|
bool compositor::enable_metacity(bool status) {
|
||||||
FILE *fp;
|
FILE* fp;
|
||||||
if(status) {
|
if(status) {
|
||||||
fp = popen("gconftool-2 --set --type bool /apps/metacity/general/compositing_manager true", "r");
|
fp = popen("gconftool-2 --set --type bool /apps/metacity/general/compositing_manager true", "r");
|
||||||
} else {
|
} else {
|
||||||
|
@ -51,7 +51,7 @@ bool compositor::enable_metacity(bool status) {
|
||||||
//Xfwm4
|
//Xfwm4
|
||||||
|
|
||||||
bool compositor::enabled_xfwm4() {
|
bool compositor::enabled_xfwm4() {
|
||||||
FILE *fp = popen("xfconf-query -c xfwm4 -p '/general/use_compositing'", "r");
|
FILE* fp = popen("xfconf-query -c xfwm4 -p '/general/use_compositing'", "r");
|
||||||
if(!fp) return false;
|
if(!fp) return false;
|
||||||
|
|
||||||
char buffer[512];
|
char buffer[512];
|
||||||
|
@ -62,7 +62,7 @@ bool compositor::enabled_xfwm4() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool compositor::enable_xfwm4(bool status) {
|
bool compositor::enable_xfwm4(bool status) {
|
||||||
FILE *fp;
|
FILE* fp;
|
||||||
if(status) {
|
if(status) {
|
||||||
fp = popen("xfconf-query -c xfwm4 -p '/general/use_compositing' -t 'bool' -s 'true'", "r");
|
fp = popen("xfconf-query -c xfwm4 -p '/general/use_compositing' -t 'bool' -s 'true'", "r");
|
||||||
} else {
|
} else {
|
||||||
|
@ -78,7 +78,7 @@ bool compositor::enable_xfwm4(bool status) {
|
||||||
compositor::Compositor compositor::detect() {
|
compositor::Compositor compositor::detect() {
|
||||||
Compositor result = Compositor::Unknown;
|
Compositor result = Compositor::Unknown;
|
||||||
|
|
||||||
FILE *fp;
|
FILE* fp;
|
||||||
char buffer[512];
|
char buffer[512];
|
||||||
|
|
||||||
fp = popen("pidof metacity", "r");
|
fp = popen("pidof metacity", "r");
|
||||||
|
|
|
@ -4,22 +4,24 @@
|
||||||
#include <nall/stdint.hpp>
|
#include <nall/stdint.hpp>
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
inline uint16_t crc16_adjust(uint16_t crc16, uint8_t data) {
|
|
||||||
for(unsigned n = 0; n < 8; n++) {
|
|
||||||
if((crc16 & 1) ^ (data & 1)) crc16 = (crc16 >> 1) ^ 0x8408;
|
|
||||||
else crc16 >>= 1;
|
|
||||||
data >>= 1;
|
|
||||||
}
|
|
||||||
return crc16;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline uint16_t crc16_calculate(const uint8_t *data, unsigned length) {
|
inline uint16_t crc16_adjust(uint16_t crc16, uint8_t data) {
|
||||||
uint16_t crc16 = ~0;
|
for(unsigned n = 0; n < 8; n++) {
|
||||||
for(unsigned n = 0; n < length; n++) {
|
if((crc16 & 1) ^ (data & 1)) crc16 = (crc16 >> 1) ^ 0x8408;
|
||||||
crc16 = crc16_adjust(crc16, data[n]);
|
else crc16 >>= 1;
|
||||||
}
|
data >>= 1;
|
||||||
return ~crc16;
|
|
||||||
}
|
}
|
||||||
|
return crc16;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline uint16_t crc16_calculate(const uint8_t* data, unsigned length) {
|
||||||
|
uint16_t crc16 = ~0;
|
||||||
|
for(unsigned n = 0; n < length; n++) {
|
||||||
|
crc16 = crc16_adjust(crc16, data[n]);
|
||||||
|
}
|
||||||
|
return ~crc16;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -4,63 +4,65 @@
|
||||||
#include <nall/stdint.hpp>
|
#include <nall/stdint.hpp>
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
const uint32_t crc32_table[256] = {
|
|
||||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
|
|
||||||
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
|
|
||||||
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
|
|
||||||
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
|
|
||||||
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
|
|
||||||
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
|
|
||||||
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
|
|
||||||
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
|
|
||||||
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
|
|
||||||
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
|
|
||||||
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
|
|
||||||
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
|
|
||||||
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
|
|
||||||
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
|
|
||||||
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
|
|
||||||
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
|
|
||||||
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
|
|
||||||
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
|
|
||||||
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
|
|
||||||
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
|
||||||
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
|
|
||||||
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
|
|
||||||
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
|
|
||||||
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
|
|
||||||
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
|
|
||||||
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
|
|
||||||
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
|
|
||||||
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
|
|
||||||
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
|
|
||||||
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
|
|
||||||
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
|
|
||||||
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
|
|
||||||
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
|
|
||||||
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
|
|
||||||
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
|
|
||||||
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
|
|
||||||
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
|
|
||||||
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
|
|
||||||
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
|
|
||||||
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
|
||||||
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
|
|
||||||
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
|
|
||||||
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
|
|
||||||
};
|
|
||||||
|
|
||||||
inline uint32_t crc32_adjust(uint32_t crc32, uint8_t input) {
|
const uint32_t crc32_table[256] = {
|
||||||
return ((crc32 >> 8) & 0x00ffffff) ^ crc32_table[(crc32 ^ input) & 0xff];
|
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
|
||||||
}
|
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
|
||||||
|
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
|
||||||
|
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
|
||||||
|
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
|
||||||
|
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
|
||||||
|
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
|
||||||
|
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
|
||||||
|
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
|
||||||
|
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
|
||||||
|
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
|
||||||
|
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
|
||||||
|
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
|
||||||
|
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
|
||||||
|
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
|
||||||
|
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
|
||||||
|
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
|
||||||
|
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
|
||||||
|
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
|
||||||
|
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
||||||
|
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
|
||||||
|
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
|
||||||
|
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
|
||||||
|
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
|
||||||
|
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
|
||||||
|
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
|
||||||
|
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
|
||||||
|
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
|
||||||
|
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
|
||||||
|
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
|
||||||
|
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
|
||||||
|
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
|
||||||
|
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
|
||||||
|
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
|
||||||
|
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
|
||||||
|
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
|
||||||
|
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
|
||||||
|
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
|
||||||
|
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
|
||||||
|
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
||||||
|
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
|
||||||
|
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
|
||||||
|
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
|
||||||
|
};
|
||||||
|
|
||||||
inline uint32_t crc32_calculate(const uint8_t *data, unsigned length) {
|
inline uint32_t crc32_adjust(uint32_t crc32, uint8_t input) {
|
||||||
uint32_t crc32 = ~0;
|
return ((crc32 >> 8) & 0x00ffffff) ^ crc32_table[(crc32 ^ input) & 0xff];
|
||||||
for(unsigned i = 0; i < length; i++) {
|
}
|
||||||
crc32 = crc32_adjust(crc32, data[i]);
|
|
||||||
}
|
inline uint32_t crc32_calculate(const uint8_t* data, unsigned length) {
|
||||||
return ~crc32;
|
uint32_t crc32 = ~0;
|
||||||
|
for(unsigned i = 0; i < length; i++) {
|
||||||
|
crc32 = crc32_adjust(crc32, data[i]);
|
||||||
}
|
}
|
||||||
|
return ~crc32;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -18,80 +18,80 @@
|
||||||
namespace nall {
|
namespace nall {
|
||||||
|
|
||||||
struct directory {
|
struct directory {
|
||||||
static bool create(const string &pathname, unsigned permissions = 0755); //recursive
|
static bool create(const string& pathname, unsigned permissions = 0755); //recursive
|
||||||
static bool remove(const string &pathname); //recursive
|
static bool remove(const string& pathname); //recursive
|
||||||
static bool exists(const string &pathname);
|
static bool exists(const string& pathname);
|
||||||
|
|
||||||
static lstring folders(const string &pathname, const string &pattern = "*") {
|
static lstring folders(const string& pathname, const string& pattern = "*") {
|
||||||
lstring folders = directory::ufolders(pathname, pattern);
|
lstring folders = directory::ufolders(pathname, pattern);
|
||||||
folders.sort();
|
folders.sort();
|
||||||
return folders;
|
return folders;
|
||||||
}
|
}
|
||||||
|
|
||||||
static lstring files(const string &pathname, const string &pattern = "*") {
|
static lstring files(const string& pathname, const string& pattern = "*") {
|
||||||
lstring files = directory::ufiles(pathname, pattern);
|
lstring files = directory::ufiles(pathname, pattern);
|
||||||
files.sort();
|
files.sort();
|
||||||
return files;
|
return files;
|
||||||
}
|
}
|
||||||
|
|
||||||
static lstring contents(const string &pathname, const string &pattern = "*") {
|
static lstring contents(const string& pathname, const string& pattern = "*") {
|
||||||
lstring folders = directory::ufolders(pathname); //pattern search of contents should only filter files
|
lstring folders = directory::ufolders(pathname); //pattern search of contents should only filter files
|
||||||
lstring files = directory::ufiles(pathname, pattern);
|
lstring files = directory::ufiles(pathname, pattern);
|
||||||
folders.sort();
|
folders.sort();
|
||||||
files.sort();
|
files.sort();
|
||||||
for(auto &file : files) folders.append(file);
|
for(auto& file : files) folders.append(file);
|
||||||
return folders;
|
return folders;
|
||||||
}
|
}
|
||||||
|
|
||||||
static lstring ifolders(const string &pathname, const string &pattern = "*") {
|
static lstring ifolders(const string& pathname, const string& pattern = "*") {
|
||||||
lstring folders = ufolders(pathname, pattern);
|
lstring folders = ufolders(pathname, pattern);
|
||||||
folders.isort();
|
folders.isort();
|
||||||
return folders;
|
return folders;
|
||||||
}
|
}
|
||||||
|
|
||||||
static lstring ifiles(const string &pathname, const string &pattern = "*") {
|
static lstring ifiles(const string& pathname, const string& pattern = "*") {
|
||||||
lstring files = ufiles(pathname, pattern);
|
lstring files = ufiles(pathname, pattern);
|
||||||
files.isort();
|
files.isort();
|
||||||
return files;
|
return files;
|
||||||
}
|
}
|
||||||
|
|
||||||
static lstring icontents(const string &pathname, const string &pattern = "*") {
|
static lstring icontents(const string& pathname, const string& pattern = "*") {
|
||||||
lstring folders = directory::ufolders(pathname); //pattern search of contents should only filter files
|
lstring folders = directory::ufolders(pathname); //pattern search of contents should only filter files
|
||||||
lstring files = directory::ufiles(pathname, pattern);
|
lstring files = directory::ufiles(pathname, pattern);
|
||||||
folders.isort();
|
folders.isort();
|
||||||
files.isort();
|
files.isort();
|
||||||
for(auto &file : files) folders.append(file);
|
for(auto& file : files) folders.append(file);
|
||||||
return folders;
|
return folders;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//internal functions; these return unsorted lists
|
//internal functions; these return unsorted lists
|
||||||
static lstring ufolders(const string &pathname, const string &pattern = "*");
|
static lstring ufolders(const string& pathname, const string& pattern = "*");
|
||||||
static lstring ufiles(const string &pathname, const string &pattern = "*");
|
static lstring ufiles(const string& pathname, const string& pattern = "*");
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(PLATFORM_WINDOWS)
|
#if defined(PLATFORM_WINDOWS)
|
||||||
inline bool directory::create(const string &pathname, unsigned permissions) {
|
inline bool directory::create(const string& pathname, unsigned permissions) {
|
||||||
string path;
|
string path;
|
||||||
lstring list = string{pathname}.transform("\\", "/").rtrim<1>("/").split("/");
|
lstring list = string{pathname}.transform("\\", "/").rtrim<1>("/").split("/");
|
||||||
bool result = true;
|
bool result = true;
|
||||||
for(auto &part : list) {
|
for(auto& part : list) {
|
||||||
path.append(part, "/");
|
path.append(part, "/");
|
||||||
result &= (_wmkdir(utf16_t(path)) == 0);
|
result &= (_wmkdir(utf16_t(path)) == 0);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool directory::remove(const string &pathname) {
|
inline bool directory::remove(const string& pathname) {
|
||||||
lstring list = directory::contents(pathname);
|
lstring list = directory::contents(pathname);
|
||||||
for(auto &name : list) {
|
for(auto& name : list) {
|
||||||
if(name.endswith("/")) directory::remove({pathname, name});
|
if(name.endswith("/")) directory::remove({pathname, name});
|
||||||
else file::remove({pathname, name});
|
else file::remove({pathname, name});
|
||||||
}
|
}
|
||||||
return _wrmdir(utf16_t(pathname)) == 0;
|
return _wrmdir(utf16_t(pathname)) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool directory::exists(const string &pathname) {
|
inline bool directory::exists(const string& pathname) {
|
||||||
string name = pathname;
|
string name = pathname;
|
||||||
name.trim<1>("\"");
|
name.trim<1>("\"");
|
||||||
DWORD result = GetFileAttributes(utf16_t(name));
|
DWORD result = GetFileAttributes(utf16_t(name));
|
||||||
|
@ -99,7 +99,7 @@ private:
|
||||||
return (result & FILE_ATTRIBUTE_DIRECTORY);
|
return (result & FILE_ATTRIBUTE_DIRECTORY);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline lstring directory::ufolders(const string &pathname, const string &pattern) {
|
inline lstring directory::ufolders(const string& pathname, const string& pattern) {
|
||||||
lstring list;
|
lstring list;
|
||||||
string path = pathname;
|
string path = pathname;
|
||||||
path.transform("/", "\\");
|
path.transform("/", "\\");
|
||||||
|
@ -125,11 +125,11 @@ private:
|
||||||
}
|
}
|
||||||
FindClose(handle);
|
FindClose(handle);
|
||||||
}
|
}
|
||||||
for(auto &name : list) name.append("/"); //must append after sorting
|
for(auto& name : list) name.append("/"); //must append after sorting
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline lstring directory::ufiles(const string &pathname, const string &pattern) {
|
inline lstring directory::ufiles(const string& pathname, const string& pattern) {
|
||||||
lstring list;
|
lstring list;
|
||||||
string path = pathname;
|
string path = pathname;
|
||||||
path.transform("/", "\\");
|
path.transform("/", "\\");
|
||||||
|
@ -154,37 +154,37 @@ private:
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
inline bool directory::create(const string &pathname, unsigned permissions) {
|
inline bool directory::create(const string& pathname, unsigned permissions) {
|
||||||
string path;
|
string path;
|
||||||
lstring list = string{pathname}.rtrim<1>("/").split("/");
|
lstring list = string{pathname}.rtrim<1>("/").split("/");
|
||||||
bool result = true;
|
bool result = true;
|
||||||
for(auto &part : list) {
|
for(auto& part : list) {
|
||||||
path.append(part, "/");
|
path.append(part, "/");
|
||||||
result &= (mkdir(path, permissions) == 0);
|
result &= (mkdir(path, permissions) == 0);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool directory::remove(const string &pathname) {
|
inline bool directory::remove(const string& pathname) {
|
||||||
lstring list = directory::contents(pathname);
|
lstring list = directory::contents(pathname);
|
||||||
for(auto &name : list) {
|
for(auto& name : list) {
|
||||||
if(name.endswith("/")) directory::remove({pathname, name});
|
if(name.endswith("/")) directory::remove({pathname, name});
|
||||||
else file::remove({pathname, name});
|
else file::remove({pathname, name});
|
||||||
}
|
}
|
||||||
return rmdir(pathname) == 0;
|
return rmdir(pathname) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool directory::exists(const string &pathname) {
|
inline bool directory::exists(const string& pathname) {
|
||||||
DIR *dp = opendir(pathname);
|
DIR *dp = opendir(pathname);
|
||||||
if(!dp) return false;
|
if(!dp) return false;
|
||||||
closedir(dp);
|
closedir(dp);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline lstring directory::ufolders(const string &pathname, const string &pattern) {
|
inline lstring directory::ufolders(const string& pathname, const string& pattern) {
|
||||||
lstring list;
|
lstring list;
|
||||||
DIR *dp;
|
DIR* dp;
|
||||||
struct dirent *ep;
|
struct dirent* ep;
|
||||||
dp = opendir(pathname);
|
dp = opendir(pathname);
|
||||||
if(dp) {
|
if(dp) {
|
||||||
while(ep = readdir(dp)) {
|
while(ep = readdir(dp)) {
|
||||||
|
@ -196,14 +196,14 @@ private:
|
||||||
}
|
}
|
||||||
closedir(dp);
|
closedir(dp);
|
||||||
}
|
}
|
||||||
for(auto &name : list) name.append("/"); //must append after sorting
|
for(auto& name : list) name.append("/"); //must append after sorting
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline lstring directory::ufiles(const string &pathname, const string &pattern) {
|
inline lstring directory::ufiles(const string& pathname, const string& pattern) {
|
||||||
lstring list;
|
lstring list;
|
||||||
DIR *dp;
|
DIR* dp;
|
||||||
struct dirent *ep;
|
struct dirent* ep;
|
||||||
dp = opendir(pathname);
|
dp = opendir(pathname);
|
||||||
if(dp) {
|
if(dp) {
|
||||||
while(ep = readdir(dp)) {
|
while(ep = readdir(dp)) {
|
||||||
|
|
|
@ -16,102 +16,104 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
struct library {
|
|
||||||
explicit operator bool() const { return open(); }
|
|
||||||
bool open() const { return handle; }
|
|
||||||
bool open(const char*, const char* = "");
|
|
||||||
bool open_absolute(const char*);
|
|
||||||
void* sym(const char*);
|
|
||||||
void close();
|
|
||||||
|
|
||||||
library() : handle(0) {}
|
struct library {
|
||||||
~library() { close(); }
|
explicit operator bool() const { return open(); }
|
||||||
|
bool open() const { return handle; }
|
||||||
|
bool open(const string&, const string& = "");
|
||||||
|
bool open_absolute(const string&);
|
||||||
|
void* sym(const string&);
|
||||||
|
void close();
|
||||||
|
|
||||||
library& operator=(const library&) = delete;
|
library() = default;
|
||||||
library(const library&) = delete;
|
~library() { close(); }
|
||||||
|
|
||||||
private:
|
library& operator=(const library&) = delete;
|
||||||
uintptr_t handle;
|
library(const library&) = delete;
|
||||||
};
|
|
||||||
|
|
||||||
#if defined(PLATFORM_X)
|
private:
|
||||||
inline bool library::open(const char *name, const char *path) {
|
uintptr_t handle = 0;
|
||||||
if(handle) close();
|
|
||||||
handle = (uintptr_t)dlopen(string(path, *path && !strend(path, "/") ? "/" : "", "lib", name, ".so"), RTLD_LAZY);
|
|
||||||
if(!handle) handle = (uintptr_t)dlopen(string("/usr/local/lib/lib", name, ".so"), RTLD_LAZY);
|
|
||||||
return handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool library::open_absolute(const char *name) {
|
|
||||||
if(handle) close();
|
|
||||||
handle = (uintptr_t)dlopen(name, RTLD_LAZY);
|
|
||||||
return handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void* library::sym(const char *name) {
|
|
||||||
if(!handle) return nullptr;
|
|
||||||
return dlsym((void*)handle, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void library::close() {
|
|
||||||
if(!handle) return;
|
|
||||||
dlclose((void*)handle);
|
|
||||||
handle = 0;
|
|
||||||
}
|
|
||||||
#elif defined(PLATFORM_OSX)
|
|
||||||
inline bool library::open(const char *name, const char *path) {
|
|
||||||
if(handle) close();
|
|
||||||
handle = (uintptr_t)dlopen(string(path, *path && !strend(path, "/") ? "/" : "", "lib", name, ".dylib"), RTLD_LAZY);
|
|
||||||
if(!handle) handle = (uintptr_t)dlopen(string("/usr/local/lib/lib", name, ".dylib"), RTLD_LAZY);
|
|
||||||
return handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool library::open_absolute(const char *name) {
|
|
||||||
if(handle) close();
|
|
||||||
handle = (uintptr_t)dlopen(name, RTLD_LAZY);
|
|
||||||
return handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void* library::sym(const char *name) {
|
|
||||||
if(!handle) return nullptr;
|
|
||||||
return dlsym((void*)handle, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void library::close() {
|
|
||||||
if(!handle) return;
|
|
||||||
dlclose((void*)handle);
|
|
||||||
handle = 0;
|
|
||||||
}
|
|
||||||
#elif defined(PLATFORM_WINDOWS)
|
|
||||||
inline bool library::open(const char *name, const char *path) {
|
|
||||||
if(handle) close();
|
|
||||||
string filepath(path, *path && !strend(path, "/") && !strend(path, "\\") ? "\\" : "", name, ".dll");
|
|
||||||
handle = (uintptr_t)LoadLibraryW(utf16_t(filepath));
|
|
||||||
return handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool library::open_absolute(const char *name) {
|
|
||||||
if(handle) close();
|
|
||||||
handle = (uintptr_t)LoadLibraryW(utf16_t(name));
|
|
||||||
return handle;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void* library::sym(const char *name) {
|
|
||||||
if(!handle) return nullptr;
|
|
||||||
return (void*)GetProcAddress((HMODULE)handle, name);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void library::close() {
|
|
||||||
if(!handle) return;
|
|
||||||
FreeLibrary((HMODULE)handle);
|
|
||||||
handle = 0;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
inline bool library::open(const char*, const char*) { return false; }
|
|
||||||
inline bool library::open_absolute(const char*) { return false; }
|
|
||||||
inline void* library::sym(const char*) { return nullptr; }
|
|
||||||
inline void library::close() {}
|
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if defined(PLATFORM_X)
|
||||||
|
inline bool library::open(const string& name, const string& path) {
|
||||||
|
if(handle) close();
|
||||||
|
handle = (uintptr_t)dlopen(string(path, !path.empty() && !path.endswith("/") ? "/" : "", "lib", name, ".so"), RTLD_LAZY);
|
||||||
|
if(!handle) handle = (uintptr_t)dlopen(string("/usr/local/lib/lib", name, ".so"), RTLD_LAZY);
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool library::open_absolute(const string& name) {
|
||||||
|
if(handle) close();
|
||||||
|
handle = (uintptr_t)dlopen(name, RTLD_LAZY);
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void* library::sym(const string& name) {
|
||||||
|
if(!handle) return nullptr;
|
||||||
|
return dlsym((void*)handle, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void library::close() {
|
||||||
|
if(!handle) return;
|
||||||
|
dlclose((void*)handle);
|
||||||
|
handle = 0;
|
||||||
|
}
|
||||||
|
#elif defined(PLATFORM_OSX)
|
||||||
|
inline bool library::open(const string& name, const string& path) {
|
||||||
|
if(handle) close();
|
||||||
|
handle = (uintptr_t)dlopen(string(path, !path.empty() && !path.endswith("/") ? "/" : "", "lib", name, ".dylib"), RTLD_LAZY);
|
||||||
|
if(!handle) handle = (uintptr_t)dlopen(string("/usr/local/lib/lib", name, ".dylib"), RTLD_LAZY);
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool library::open_absolute(const string& name) {
|
||||||
|
if(handle) close();
|
||||||
|
handle = (uintptr_t)dlopen(name, RTLD_LAZY);
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void* library::sym(const string& name) {
|
||||||
|
if(!handle) return nullptr;
|
||||||
|
return dlsym((void*)handle, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void library::close() {
|
||||||
|
if(!handle) return;
|
||||||
|
dlclose((void*)handle);
|
||||||
|
handle = 0;
|
||||||
|
}
|
||||||
|
#elif defined(PLATFORM_WINDOWS)
|
||||||
|
inline bool library::open(const string& name, const string& path) {
|
||||||
|
if(handle) close();
|
||||||
|
string filepath(path, !path.empty() && !path.endswith("/") && !path.endswith("\\") ? "/" : "", name, ".dll");
|
||||||
|
handle = (uintptr_t)LoadLibraryW(utf16_t(filepath));
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool library::open_absolute(const string& name) {
|
||||||
|
if(handle) close();
|
||||||
|
handle = (uintptr_t)LoadLibraryW(utf16_t(name));
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void* library::sym(const string& name) {
|
||||||
|
if(!handle) return nullptr;
|
||||||
|
return (void*)GetProcAddress((HMODULE)handle, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void library::close() {
|
||||||
|
if(!handle) return;
|
||||||
|
FreeLibrary((HMODULE)handle);
|
||||||
|
handle = 0;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
inline bool library::open(const string&, const string&) { return false; }
|
||||||
|
inline bool library::open_absolute(const string&) { return false; }
|
||||||
|
inline void* library::sym(const string&) { return nullptr; }
|
||||||
|
inline void library::close() {}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#ifdef NALL_DSP_INTERNAL_HPP
|
#ifdef NALL_DSP_INTERNAL_HPP
|
||||||
|
|
||||||
struct Buffer {
|
struct Buffer {
|
||||||
double **sample = nullptr;
|
double** sample = nullptr;
|
||||||
uint16_t rdoffset = 0;
|
uint16_t rdoffset = 0;
|
||||||
uint16_t wroffset = 0;
|
uint16_t wroffset = 0;
|
||||||
unsigned channels = 0;
|
unsigned channels = 0;
|
||||||
|
|
|
@ -12,13 +12,13 @@ namespace nall {
|
||||||
struct DSP;
|
struct DSP;
|
||||||
|
|
||||||
struct Resampler {
|
struct Resampler {
|
||||||
DSP &dsp;
|
DSP& dsp;
|
||||||
real frequency;
|
real frequency;
|
||||||
|
|
||||||
virtual void setFrequency() = 0;
|
virtual void setFrequency() = 0;
|
||||||
virtual void clear() = 0;
|
virtual void clear() = 0;
|
||||||
virtual void sample() = 0;
|
virtual void sample() = 0;
|
||||||
Resampler(DSP &dsp) : dsp(dsp) {}
|
Resampler(DSP& dsp) : dsp(dsp) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DSP {
|
struct DSP {
|
||||||
|
@ -70,7 +70,7 @@ protected:
|
||||||
real intensityInverse;
|
real intensityInverse;
|
||||||
} settings;
|
} settings;
|
||||||
|
|
||||||
Resampler *resampler = nullptr;
|
Resampler* resampler = nullptr;
|
||||||
inline void write(real channel[]);
|
inline void write(real channel[]);
|
||||||
|
|
||||||
#include "buffer.hpp"
|
#include "buffer.hpp"
|
||||||
|
|
|
@ -5,7 +5,7 @@ struct ResampleAverage : Resampler {
|
||||||
inline void clear();
|
inline void clear();
|
||||||
inline void sample();
|
inline void sample();
|
||||||
inline void sampleLinear();
|
inline void sampleLinear();
|
||||||
ResampleAverage(DSP &dsp) : Resampler(dsp) {}
|
ResampleAverage(DSP& dsp) : Resampler(dsp) {}
|
||||||
|
|
||||||
real fraction;
|
real fraction;
|
||||||
real step;
|
real step;
|
||||||
|
|
|
@ -4,7 +4,7 @@ struct ResampleCosine : Resampler {
|
||||||
inline void setFrequency();
|
inline void setFrequency();
|
||||||
inline void clear();
|
inline void clear();
|
||||||
inline void sample();
|
inline void sample();
|
||||||
ResampleCosine(DSP &dsp) : Resampler(dsp) {}
|
ResampleCosine(DSP& dsp) : Resampler(dsp) {}
|
||||||
|
|
||||||
real fraction;
|
real fraction;
|
||||||
real step;
|
real step;
|
||||||
|
|
|
@ -4,7 +4,7 @@ struct ResampleCubic : Resampler {
|
||||||
inline void setFrequency();
|
inline void setFrequency();
|
||||||
inline void clear();
|
inline void clear();
|
||||||
inline void sample();
|
inline void sample();
|
||||||
ResampleCubic(DSP &dsp) : Resampler(dsp) {}
|
ResampleCubic(DSP& dsp) : Resampler(dsp) {}
|
||||||
|
|
||||||
real fraction;
|
real fraction;
|
||||||
real step;
|
real step;
|
||||||
|
|
|
@ -4,7 +4,7 @@ struct ResampleHermite : Resampler {
|
||||||
inline void setFrequency();
|
inline void setFrequency();
|
||||||
inline void clear();
|
inline void clear();
|
||||||
inline void sample();
|
inline void sample();
|
||||||
ResampleHermite(DSP &dsp) : Resampler(dsp) {}
|
ResampleHermite(DSP& dsp) : Resampler(dsp) {}
|
||||||
|
|
||||||
real fraction;
|
real fraction;
|
||||||
real step;
|
real step;
|
||||||
|
|
|
@ -4,7 +4,7 @@ struct ResampleLinear : Resampler {
|
||||||
inline void setFrequency();
|
inline void setFrequency();
|
||||||
inline void clear();
|
inline void clear();
|
||||||
inline void sample();
|
inline void sample();
|
||||||
ResampleLinear(DSP &dsp) : Resampler(dsp) {}
|
ResampleLinear(DSP& dsp) : Resampler(dsp) {}
|
||||||
|
|
||||||
real fraction;
|
real fraction;
|
||||||
real step;
|
real step;
|
||||||
|
|
|
@ -4,7 +4,7 @@ struct ResampleNearest : Resampler {
|
||||||
inline void setFrequency();
|
inline void setFrequency();
|
||||||
inline void clear();
|
inline void clear();
|
||||||
inline void sample();
|
inline void sample();
|
||||||
ResampleNearest(DSP &dsp) : Resampler(dsp) {}
|
ResampleNearest(DSP& dsp) : Resampler(dsp) {}
|
||||||
|
|
||||||
real fraction;
|
real fraction;
|
||||||
real step;
|
real step;
|
||||||
|
|
|
@ -6,11 +6,11 @@ struct ResampleSinc : Resampler {
|
||||||
inline void setFrequency();
|
inline void setFrequency();
|
||||||
inline void clear();
|
inline void clear();
|
||||||
inline void sample();
|
inline void sample();
|
||||||
inline ResampleSinc(DSP &dsp);
|
inline ResampleSinc(DSP& dsp);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline void remakeSinc();
|
inline void remakeSinc();
|
||||||
SincResample *sinc_resampler[8];
|
SincResample* sinc_resampler[8];
|
||||||
};
|
};
|
||||||
|
|
||||||
void ResampleSinc::setFrequency() {
|
void ResampleSinc::setFrequency() {
|
||||||
|
@ -38,7 +38,7 @@ void ResampleSinc::sample() {
|
||||||
dsp.buffer.rdoffset++;
|
dsp.buffer.rdoffset++;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResampleSinc::ResampleSinc(DSP &dsp) : Resampler(dsp) {
|
ResampleSinc::ResampleSinc(DSP& dsp) : Resampler(dsp) {
|
||||||
for(unsigned n = 0; n < 8; n++) sinc_resampler[n] = nullptr;
|
for(unsigned n = 0; n < 8; n++) sinc_resampler[n] = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -83,7 +83,7 @@ static void sigint(int) {
|
||||||
usart_sigint = true;
|
usart_sigint = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char** argv) {
|
||||||
setpriority(PRIO_PROCESS, 0, -20); //requires superuser privileges; otherwise priority = +0
|
setpriority(PRIO_PROCESS, 0, -20); //requires superuser privileges; otherwise priority = +0
|
||||||
signal(SIGINT, sigint);
|
signal(SIGINT, sigint);
|
||||||
|
|
||||||
|
|
|
@ -9,346 +9,348 @@
|
||||||
#include <nall/stream/memory.hpp>
|
#include <nall/stream/memory.hpp>
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
inline FILE* fopen_utf8(const string &utf8_filename, const char *mode) {
|
|
||||||
|
inline FILE* fopen_utf8(const string& filename, const string& mode) {
|
||||||
|
#if !defined(_WIN32)
|
||||||
|
return fopen(filename, mode);
|
||||||
|
#else
|
||||||
|
return _wfopen(utf16_t(filename), utf16_t(mode));
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
struct file {
|
||||||
|
enum class mode : unsigned { read, write, modify, append, readwrite = modify, writeread = append };
|
||||||
|
enum class index : unsigned { absolute, relative };
|
||||||
|
enum class time : unsigned { create, modify, access };
|
||||||
|
|
||||||
|
static bool copy(const string& sourcename, const string& targetname) {
|
||||||
|
file rd, wr;
|
||||||
|
if(rd.open(sourcename, mode::read) == false) return false;
|
||||||
|
if(wr.open(targetname, mode::write) == false) return false;
|
||||||
|
for(unsigned n = 0; n < rd.size(); n++) wr.write(rd.read());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool move(const string& sourcename, const string& targetname) {
|
||||||
#if !defined(_WIN32)
|
#if !defined(_WIN32)
|
||||||
return fopen(utf8_filename, mode);
|
return rename(sourcename, targetname) == 0;
|
||||||
#else
|
#else
|
||||||
return _wfopen(utf16_t(utf8_filename), utf16_t(mode));
|
return _wrename(utf16_t(sourcename), utf16_t(targetname)) == 0;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
struct file {
|
static bool remove(const string& filename) {
|
||||||
enum class mode : unsigned { read, write, modify, append, readwrite = modify, writeread = append };
|
return unlink(filename) == 0;
|
||||||
enum class index : unsigned { absolute, relative };
|
}
|
||||||
enum class time : unsigned { create, modify, access };
|
|
||||||
|
|
||||||
static bool copy(const string &sourcename, const string &targetname) {
|
static bool truncate(const string& filename, unsigned size) {
|
||||||
file rd, wr;
|
#if !defined(_WIN32)
|
||||||
if(rd.open(sourcename, mode::read) == false) return false;
|
return truncate(filename, size) == 0;
|
||||||
if(wr.open(targetname, mode::write) == false) return false;
|
#else
|
||||||
for(unsigned n = 0; n < rd.size(); n++) wr.write(rd.read());
|
bool result = false;
|
||||||
return true;
|
FILE* fp = fopen(filename, "rb+");
|
||||||
}
|
if(fp) {
|
||||||
|
result = _chsize(fileno(fp), size) == 0;
|
||||||
static bool move(const string &sourcename, const string &targetname) {
|
|
||||||
#if !defined(_WIN32)
|
|
||||||
return rename(sourcename, targetname) == 0;
|
|
||||||
#else
|
|
||||||
return _wrename(utf16_t(sourcename), utf16_t(targetname)) == 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool remove(const string &filename) {
|
|
||||||
return unlink(filename) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool truncate(const string &filename, unsigned size) {
|
|
||||||
#if !defined(_WIN32)
|
|
||||||
return truncate(filename, size) == 0;
|
|
||||||
#else
|
|
||||||
bool result = false;
|
|
||||||
FILE *fp = fopen(filename, "rb+");
|
|
||||||
if(fp) {
|
|
||||||
result = _chsize(fileno(fp), size) == 0;
|
|
||||||
fclose(fp);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static vector<uint8_t> read(const string &filename) {
|
|
||||||
vector<uint8_t> memory;
|
|
||||||
file fp;
|
|
||||||
if(fp.open(filename, mode::read)) {
|
|
||||||
memory.resize(fp.size());
|
|
||||||
fp.read(memory.data(), memory.size());
|
|
||||||
}
|
|
||||||
return memory;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool read(const string &filename, uint8_t *data, unsigned size) {
|
|
||||||
file fp;
|
|
||||||
if(fp.open(filename, mode::read) == false) return false;
|
|
||||||
fp.read(data, size);
|
|
||||||
fp.close();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool write(const string &filename, const string &text) {
|
|
||||||
file fp;
|
|
||||||
if(fp.open(filename, mode::write) == false) return false;
|
|
||||||
fp.print(text);
|
|
||||||
fp.close();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool write(const string &filename, const vector<uint8_t> &buffer) {
|
|
||||||
file fp;
|
|
||||||
if(fp.open(filename, mode::write) == false) return false;
|
|
||||||
fp.write(buffer.data(), buffer.size());
|
|
||||||
fp.close();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool write(const string &filename, const uint8_t *data, unsigned size) {
|
|
||||||
file fp;
|
|
||||||
if(fp.open(filename, mode::write) == false) return false;
|
|
||||||
fp.write(data, size);
|
|
||||||
fp.close();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool create(const string &filename) {
|
|
||||||
//create an empty file (will replace existing files)
|
|
||||||
file fp;
|
|
||||||
if(fp.open(filename, mode::write) == false) return false;
|
|
||||||
fp.close();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static string sha256(const string &filename) {
|
|
||||||
auto buffer = read(filename);
|
|
||||||
return nall::sha256(buffer.data(), buffer.size());
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t read() {
|
|
||||||
if(!fp) return 0xff; //file not open
|
|
||||||
if(file_mode == mode::write) return 0xff; //reads not permitted
|
|
||||||
if(file_offset >= file_size) return 0xff; //cannot read past end of file
|
|
||||||
buffer_sync();
|
|
||||||
return buffer[(file_offset++) & buffer_mask];
|
|
||||||
}
|
|
||||||
|
|
||||||
uintmax_t readl(unsigned length = 1) {
|
|
||||||
uintmax_t data = 0;
|
|
||||||
for(int i = 0; i < length; i++) {
|
|
||||||
data |= (uintmax_t)read() << (i << 3);
|
|
||||||
}
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
uintmax_t readm(unsigned length = 1) {
|
|
||||||
uintmax_t data = 0;
|
|
||||||
while(length--) {
|
|
||||||
data <<= 8;
|
|
||||||
data |= read();
|
|
||||||
}
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
void read(uint8_t *buffer, unsigned length) {
|
|
||||||
while(length--) *buffer++ = read();
|
|
||||||
}
|
|
||||||
|
|
||||||
void write(uint8_t data) {
|
|
||||||
if(!fp) return; //file not open
|
|
||||||
if(file_mode == mode::read) return; //writes not permitted
|
|
||||||
buffer_sync();
|
|
||||||
buffer[(file_offset++) & buffer_mask] = data;
|
|
||||||
buffer_dirty = true;
|
|
||||||
if(file_offset > file_size) file_size = file_offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
void writel(uintmax_t data, unsigned length = 1) {
|
|
||||||
while(length--) {
|
|
||||||
write(data);
|
|
||||||
data >>= 8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void writem(uintmax_t data, unsigned length = 1) {
|
|
||||||
for(int i = length - 1; i >= 0; i--) {
|
|
||||||
write(data >> (i << 3));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void write(const uint8_t *buffer, unsigned length) {
|
|
||||||
while(length--) write(*buffer++);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename... Args> void print(Args... args) {
|
|
||||||
string data(args...);
|
|
||||||
const char *p = data;
|
|
||||||
while(*p) write(*p++);
|
|
||||||
}
|
|
||||||
|
|
||||||
void flush() {
|
|
||||||
buffer_flush();
|
|
||||||
fflush(fp);
|
|
||||||
}
|
|
||||||
|
|
||||||
void seek(int offset, index index_ = index::absolute) {
|
|
||||||
if(!fp) return; //file not open
|
|
||||||
buffer_flush();
|
|
||||||
|
|
||||||
uintmax_t req_offset = file_offset;
|
|
||||||
switch(index_) {
|
|
||||||
case index::absolute: req_offset = offset; break;
|
|
||||||
case index::relative: req_offset += offset; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(req_offset < 0) req_offset = 0; //cannot seek before start of file
|
|
||||||
if(req_offset > file_size) {
|
|
||||||
if(file_mode == mode::read) { //cannot seek past end of file
|
|
||||||
req_offset = file_size;
|
|
||||||
} else { //pad file to requested location
|
|
||||||
file_offset = file_size;
|
|
||||||
while(file_size < req_offset) write(0x00);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
file_offset = req_offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned offset() const {
|
|
||||||
if(!fp) return 0; //file not open
|
|
||||||
return file_offset;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned size() const {
|
|
||||||
if(!fp) return 0; //file not open
|
|
||||||
return file_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool truncate(unsigned size) {
|
|
||||||
if(!fp) return false; //file not open
|
|
||||||
#if !defined(_WIN32)
|
|
||||||
return ftruncate(fileno(fp), size) == 0;
|
|
||||||
#else
|
|
||||||
return _chsize(fileno(fp), size) == 0;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
bool end() {
|
|
||||||
if(!fp) return true; //file not open
|
|
||||||
return file_offset >= file_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool exists(const string &filename) {
|
|
||||||
#if !defined(_WIN32)
|
|
||||||
struct stat64 data;
|
|
||||||
if(stat64(filename, &data) != 0) return false;
|
|
||||||
#else
|
|
||||||
struct __stat64 data;
|
|
||||||
if(_wstat64(utf16_t(filename), &data) != 0) return false;
|
|
||||||
#endif
|
|
||||||
//return true if this is a file, and false if this is a directory
|
|
||||||
return !(data.st_mode & S_IFDIR);
|
|
||||||
}
|
|
||||||
|
|
||||||
static uintmax_t size(const string &filename) {
|
|
||||||
#if !defined(_WIN32)
|
|
||||||
struct stat64 data;
|
|
||||||
stat64(filename, &data);
|
|
||||||
#else
|
|
||||||
struct __stat64 data;
|
|
||||||
_wstat64(utf16_t(filename), &data);
|
|
||||||
#endif
|
|
||||||
return S_ISREG(data.st_mode) ? data.st_size : 0u;
|
|
||||||
}
|
|
||||||
|
|
||||||
static time_t timestamp(const string &filename, file::time mode = file::time::create) {
|
|
||||||
#if !defined(_WIN32)
|
|
||||||
struct stat64 data;
|
|
||||||
stat64(filename, &data);
|
|
||||||
#else
|
|
||||||
struct __stat64 data;
|
|
||||||
_wstat64(utf16_t(filename), &data);
|
|
||||||
#endif
|
|
||||||
switch(mode) { default:
|
|
||||||
case file::time::create: return data.st_ctime;
|
|
||||||
case file::time::modify: return data.st_mtime;
|
|
||||||
case file::time::access: return data.st_atime;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool open() const {
|
|
||||||
return fp;
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit operator bool() const {
|
|
||||||
return open();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool open(const string &filename, mode mode_) {
|
|
||||||
if(fp) return false;
|
|
||||||
|
|
||||||
switch(file_mode = mode_) {
|
|
||||||
#if !defined(_WIN32)
|
|
||||||
case mode::read: fp = fopen(filename, "rb" ); break;
|
|
||||||
case mode::write: fp = fopen(filename, "wb+"); break; //need read permission for buffering
|
|
||||||
case mode::readwrite: fp = fopen(filename, "rb+"); break;
|
|
||||||
case mode::writeread: fp = fopen(filename, "wb+"); break;
|
|
||||||
#else
|
|
||||||
case mode::read: fp = _wfopen(utf16_t(filename), L"rb" ); break;
|
|
||||||
case mode::write: fp = _wfopen(utf16_t(filename), L"wb+"); break;
|
|
||||||
case mode::readwrite: fp = _wfopen(utf16_t(filename), L"rb+"); break;
|
|
||||||
case mode::writeread: fp = _wfopen(utf16_t(filename), L"wb+"); break;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
if(!fp) return false;
|
|
||||||
buffer_offset = -1; //invalidate buffer
|
|
||||||
file_offset = 0;
|
|
||||||
fseek(fp, 0, SEEK_END);
|
|
||||||
file_size = ftell(fp);
|
|
||||||
fseek(fp, 0, SEEK_SET);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void close() {
|
|
||||||
if(!fp) return;
|
|
||||||
buffer_flush();
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
fp = nullptr;
|
}
|
||||||
|
return result;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static vector<uint8_t> read(const string& filename) {
|
||||||
|
vector<uint8_t> memory;
|
||||||
|
file fp;
|
||||||
|
if(fp.open(filename, mode::read)) {
|
||||||
|
memory.resize(fp.size());
|
||||||
|
fp.read(memory.data(), memory.size());
|
||||||
|
}
|
||||||
|
return memory;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool read(const string& filename, uint8_t* data, unsigned size) {
|
||||||
|
file fp;
|
||||||
|
if(fp.open(filename, mode::read) == false) return false;
|
||||||
|
fp.read(data, size);
|
||||||
|
fp.close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool write(const string& filename, const string& text) {
|
||||||
|
file fp;
|
||||||
|
if(fp.open(filename, mode::write) == false) return false;
|
||||||
|
fp.print(text);
|
||||||
|
fp.close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool write(const string& filename, const vector<uint8_t>& buffer) {
|
||||||
|
file fp;
|
||||||
|
if(fp.open(filename, mode::write) == false) return false;
|
||||||
|
fp.write(buffer.data(), buffer.size());
|
||||||
|
fp.close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool write(const string& filename, const uint8_t* data, unsigned size) {
|
||||||
|
file fp;
|
||||||
|
if(fp.open(filename, mode::write) == false) return false;
|
||||||
|
fp.write(data, size);
|
||||||
|
fp.close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool create(const string& filename) {
|
||||||
|
//create an empty file (will replace existing files)
|
||||||
|
file fp;
|
||||||
|
if(fp.open(filename, mode::write) == false) return false;
|
||||||
|
fp.close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static string sha256(const string& filename) {
|
||||||
|
auto buffer = read(filename);
|
||||||
|
return nall::sha256(buffer.data(), buffer.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t read() {
|
||||||
|
if(!fp) return 0xff; //file not open
|
||||||
|
if(file_mode == mode::write) return 0xff; //reads not permitted
|
||||||
|
if(file_offset >= file_size) return 0xff; //cannot read past end of file
|
||||||
|
buffer_sync();
|
||||||
|
return buffer[(file_offset++) & buffer_mask];
|
||||||
|
}
|
||||||
|
|
||||||
|
uintmax_t readl(unsigned length = 1) {
|
||||||
|
uintmax_t data = 0;
|
||||||
|
for(int i = 0; i < length; i++) {
|
||||||
|
data |= (uintmax_t)read() << (i << 3);
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
uintmax_t readm(unsigned length = 1) {
|
||||||
|
uintmax_t data = 0;
|
||||||
|
while(length--) {
|
||||||
|
data <<= 8;
|
||||||
|
data |= read();
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
void read(uint8_t* buffer, unsigned length) {
|
||||||
|
while(length--) *buffer++ = read();
|
||||||
|
}
|
||||||
|
|
||||||
|
void write(uint8_t data) {
|
||||||
|
if(!fp) return; //file not open
|
||||||
|
if(file_mode == mode::read) return; //writes not permitted
|
||||||
|
buffer_sync();
|
||||||
|
buffer[(file_offset++) & buffer_mask] = data;
|
||||||
|
buffer_dirty = true;
|
||||||
|
if(file_offset > file_size) file_size = file_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
void writel(uintmax_t data, unsigned length = 1) {
|
||||||
|
while(length--) {
|
||||||
|
write(data);
|
||||||
|
data >>= 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void writem(uintmax_t data, unsigned length = 1) {
|
||||||
|
for(int i = length - 1; i >= 0; i--) {
|
||||||
|
write(data >> (i << 3));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void write(const uint8_t* buffer, unsigned length) {
|
||||||
|
while(length--) write(*buffer++);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... Args> void print(Args... args) {
|
||||||
|
string data(args...);
|
||||||
|
const char* p = data;
|
||||||
|
while(*p) write(*p++);
|
||||||
|
}
|
||||||
|
|
||||||
|
void flush() {
|
||||||
|
buffer_flush();
|
||||||
|
fflush(fp);
|
||||||
|
}
|
||||||
|
|
||||||
|
void seek(int offset, index index_ = index::absolute) {
|
||||||
|
if(!fp) return; //file not open
|
||||||
|
buffer_flush();
|
||||||
|
|
||||||
|
uintmax_t req_offset = file_offset;
|
||||||
|
switch(index_) {
|
||||||
|
case index::absolute: req_offset = offset; break;
|
||||||
|
case index::relative: req_offset += offset; break;
|
||||||
}
|
}
|
||||||
|
|
||||||
file() {
|
if(req_offset < 0) req_offset = 0; //cannot seek before start of file
|
||||||
}
|
if(req_offset > file_size) {
|
||||||
|
if(file_mode == mode::read) { //cannot seek past end of file
|
||||||
file(const string &filename, mode mode_) {
|
req_offset = file_size;
|
||||||
open(filename, mode_);
|
} else { //pad file to requested location
|
||||||
}
|
file_offset = file_size;
|
||||||
|
while(file_size < req_offset) write(0x00);
|
||||||
~file() {
|
|
||||||
close();
|
|
||||||
}
|
|
||||||
|
|
||||||
file& operator=(const file&) = delete;
|
|
||||||
file(const file&) = delete;
|
|
||||||
|
|
||||||
private:
|
|
||||||
enum { buffer_size = 1 << 12, buffer_mask = buffer_size - 1 };
|
|
||||||
char buffer[buffer_size] = {0};
|
|
||||||
int buffer_offset = -1; //invalidate buffer
|
|
||||||
bool buffer_dirty = false;
|
|
||||||
FILE *fp = nullptr;
|
|
||||||
unsigned file_offset = 0;
|
|
||||||
unsigned file_size = 0;
|
|
||||||
mode file_mode = mode::read;
|
|
||||||
|
|
||||||
void buffer_sync() {
|
|
||||||
if(!fp) return; //file not open
|
|
||||||
if(buffer_offset != (file_offset & ~buffer_mask)) {
|
|
||||||
buffer_flush();
|
|
||||||
buffer_offset = file_offset & ~buffer_mask;
|
|
||||||
fseek(fp, buffer_offset, SEEK_SET);
|
|
||||||
unsigned length = (buffer_offset + buffer_size) <= file_size ? buffer_size : (file_size & buffer_mask);
|
|
||||||
if(length) unsigned unused = fread(buffer, 1, length, fp);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void buffer_flush() {
|
file_offset = req_offset;
|
||||||
if(!fp) return; //file not open
|
}
|
||||||
if(file_mode == mode::read) return; //buffer cannot be written to
|
|
||||||
if(buffer_offset < 0) return; //buffer unused
|
unsigned offset() const {
|
||||||
if(buffer_dirty == false) return; //buffer unmodified since read
|
if(!fp) return 0; //file not open
|
||||||
|
return file_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned size() const {
|
||||||
|
if(!fp) return 0; //file not open
|
||||||
|
return file_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool truncate(unsigned size) {
|
||||||
|
if(!fp) return false; //file not open
|
||||||
|
#if !defined(_WIN32)
|
||||||
|
return ftruncate(fileno(fp), size) == 0;
|
||||||
|
#else
|
||||||
|
return _chsize(fileno(fp), size) == 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
bool end() {
|
||||||
|
if(!fp) return true; //file not open
|
||||||
|
return file_offset >= file_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool exists(const string& filename) {
|
||||||
|
#if !defined(_WIN32)
|
||||||
|
struct stat64 data;
|
||||||
|
if(stat64(filename, &data) != 0) return false;
|
||||||
|
#else
|
||||||
|
struct __stat64 data;
|
||||||
|
if(_wstat64(utf16_t(filename), &data) != 0) return false;
|
||||||
|
#endif
|
||||||
|
//return true if this is a file, and false if this is a directory
|
||||||
|
return !(data.st_mode & S_IFDIR);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uintmax_t size(const string& filename) {
|
||||||
|
#if !defined(_WIN32)
|
||||||
|
struct stat64 data;
|
||||||
|
stat64(filename, &data);
|
||||||
|
#else
|
||||||
|
struct __stat64 data;
|
||||||
|
_wstat64(utf16_t(filename), &data);
|
||||||
|
#endif
|
||||||
|
return S_ISREG(data.st_mode) ? data.st_size : 0u;
|
||||||
|
}
|
||||||
|
|
||||||
|
static time_t timestamp(const string& filename, file::time mode = file::time::create) {
|
||||||
|
#if !defined(_WIN32)
|
||||||
|
struct stat64 data;
|
||||||
|
stat64(filename, &data);
|
||||||
|
#else
|
||||||
|
struct __stat64 data;
|
||||||
|
_wstat64(utf16_t(filename), &data);
|
||||||
|
#endif
|
||||||
|
switch(mode) { default:
|
||||||
|
case file::time::create: return data.st_ctime;
|
||||||
|
case file::time::modify: return data.st_mtime;
|
||||||
|
case file::time::access: return data.st_atime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool open() const {
|
||||||
|
return fp;
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit operator bool() const {
|
||||||
|
return open();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool open(const string& filename, mode mode_) {
|
||||||
|
if(fp) return false;
|
||||||
|
|
||||||
|
switch(file_mode = mode_) {
|
||||||
|
#if !defined(_WIN32)
|
||||||
|
case mode::read: fp = fopen(filename, "rb" ); break;
|
||||||
|
case mode::write: fp = fopen(filename, "wb+"); break; //need read permission for buffering
|
||||||
|
case mode::readwrite: fp = fopen(filename, "rb+"); break;
|
||||||
|
case mode::writeread: fp = fopen(filename, "wb+"); break;
|
||||||
|
#else
|
||||||
|
case mode::read: fp = _wfopen(utf16_t(filename), L"rb" ); break;
|
||||||
|
case mode::write: fp = _wfopen(utf16_t(filename), L"wb+"); break;
|
||||||
|
case mode::readwrite: fp = _wfopen(utf16_t(filename), L"rb+"); break;
|
||||||
|
case mode::writeread: fp = _wfopen(utf16_t(filename), L"wb+"); break;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
if(!fp) return false;
|
||||||
|
buffer_offset = -1; //invalidate buffer
|
||||||
|
file_offset = 0;
|
||||||
|
fseek(fp, 0, SEEK_END);
|
||||||
|
file_size = ftell(fp);
|
||||||
|
fseek(fp, 0, SEEK_SET);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void close() {
|
||||||
|
if(!fp) return;
|
||||||
|
buffer_flush();
|
||||||
|
fclose(fp);
|
||||||
|
fp = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
file() {
|
||||||
|
}
|
||||||
|
|
||||||
|
file(const string& filename, mode mode_) {
|
||||||
|
open(filename, mode_);
|
||||||
|
}
|
||||||
|
|
||||||
|
~file() {
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
file& operator=(const file&) = delete;
|
||||||
|
file(const file&) = delete;
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum { buffer_size = 1 << 12, buffer_mask = buffer_size - 1 };
|
||||||
|
char buffer[buffer_size] = {0};
|
||||||
|
int buffer_offset = -1; //invalidate buffer
|
||||||
|
bool buffer_dirty = false;
|
||||||
|
FILE *fp = nullptr;
|
||||||
|
unsigned file_offset = 0;
|
||||||
|
unsigned file_size = 0;
|
||||||
|
mode file_mode = mode::read;
|
||||||
|
|
||||||
|
void buffer_sync() {
|
||||||
|
if(!fp) return; //file not open
|
||||||
|
if(buffer_offset != (file_offset & ~buffer_mask)) {
|
||||||
|
buffer_flush();
|
||||||
|
buffer_offset = file_offset & ~buffer_mask;
|
||||||
fseek(fp, buffer_offset, SEEK_SET);
|
fseek(fp, buffer_offset, SEEK_SET);
|
||||||
unsigned length = (buffer_offset + buffer_size) <= file_size ? buffer_size : (file_size & buffer_mask);
|
unsigned length = (buffer_offset + buffer_size) <= file_size ? buffer_size : (file_size & buffer_mask);
|
||||||
if(length) unsigned unused = fwrite(buffer, 1, length, fp);
|
if(length) unsigned unused = fread(buffer, 1, length, fp);
|
||||||
buffer_offset = -1; //invalidate buffer
|
|
||||||
buffer_dirty = false;
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
|
void buffer_flush() {
|
||||||
|
if(!fp) return; //file not open
|
||||||
|
if(file_mode == mode::read) return; //buffer cannot be written to
|
||||||
|
if(buffer_offset < 0) return; //buffer unused
|
||||||
|
if(buffer_dirty == false) return; //buffer unmodified since read
|
||||||
|
fseek(fp, buffer_offset, SEEK_SET);
|
||||||
|
unsigned length = (buffer_offset + buffer_size) <= file_size ? buffer_size : (file_size & buffer_mask);
|
||||||
|
if(length) unsigned unused = fwrite(buffer, 1, length, fp);
|
||||||
|
buffer_offset = -1; //invalidate buffer
|
||||||
|
buffer_dirty = false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -18,197 +18,198 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
class filemap {
|
|
||||||
public:
|
|
||||||
enum class mode : unsigned { read, write, readwrite, writeread };
|
|
||||||
|
|
||||||
explicit operator bool() const { return open(); }
|
struct filemap {
|
||||||
bool open() const { return p_open(); }
|
enum class mode : unsigned { read, write, readwrite, writeread };
|
||||||
bool open(const char *filename, mode mode_) { return p_open(filename, mode_); }
|
|
||||||
void close() { return p_close(); }
|
|
||||||
unsigned size() const { return p_size; }
|
|
||||||
uint8_t* data() { return p_handle; }
|
|
||||||
const uint8_t* data() const { return p_handle; }
|
|
||||||
filemap() : p_size(0), p_handle(nullptr) { p_ctor(); }
|
|
||||||
filemap(const char *filename, mode mode_) : p_size(0), p_handle(nullptr) { p_ctor(); p_open(filename, mode_); }
|
|
||||||
~filemap() { p_dtor(); }
|
|
||||||
|
|
||||||
private:
|
explicit operator bool() const { return open(); }
|
||||||
unsigned p_size;
|
bool open() const { return p_open(); }
|
||||||
uint8_t *p_handle;
|
bool open(const string& filename, mode mode_) { return p_open(filename, mode_); }
|
||||||
|
void close() { return p_close(); }
|
||||||
|
unsigned size() const { return p_size; }
|
||||||
|
uint8_t* data() { return p_handle; }
|
||||||
|
const uint8_t* data() const { return p_handle; }
|
||||||
|
filemap() { p_ctor(); }
|
||||||
|
filemap(const string& filename, mode mode_) { p_ctor(); p_open(filename, mode_); }
|
||||||
|
~filemap() { p_dtor(); }
|
||||||
|
|
||||||
#if defined(_WIN32)
|
private:
|
||||||
//=============
|
uint8_t *p_handle = nullptr;
|
||||||
//MapViewOfFile
|
unsigned p_size = 0;
|
||||||
//=============
|
|
||||||
|
|
||||||
HANDLE p_filehandle, p_maphandle;
|
#if defined(_WIN32)
|
||||||
|
//=============
|
||||||
|
//MapViewOfFile
|
||||||
|
//=============
|
||||||
|
|
||||||
bool p_open() const {
|
HANDLE p_filehandle, p_maphandle;
|
||||||
return p_handle;
|
|
||||||
|
bool p_open() const {
|
||||||
|
return p_handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool p_open(const string& filename, mode mode_) {
|
||||||
|
if(file::exists(filename) && file::size(filename) == 0) {
|
||||||
|
p_handle = nullptr;
|
||||||
|
p_size = 0;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool p_open(const char *filename, mode mode_) {
|
int desired_access, creation_disposition, flprotect, map_access;
|
||||||
if(file::exists(filename) && file::size(filename) == 0) {
|
|
||||||
p_handle = nullptr;
|
|
||||||
p_size = 0;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int desired_access, creation_disposition, flprotect, map_access;
|
switch(mode_) {
|
||||||
|
default: return false;
|
||||||
switch(mode_) {
|
case mode::read:
|
||||||
default: return false;
|
desired_access = GENERIC_READ;
|
||||||
case mode::read:
|
creation_disposition = OPEN_EXISTING;
|
||||||
desired_access = GENERIC_READ;
|
flprotect = PAGE_READONLY;
|
||||||
creation_disposition = OPEN_EXISTING;
|
map_access = FILE_MAP_READ;
|
||||||
flprotect = PAGE_READONLY;
|
break;
|
||||||
map_access = FILE_MAP_READ;
|
case mode::write:
|
||||||
break;
|
//write access requires read access
|
||||||
case mode::write:
|
desired_access = GENERIC_WRITE;
|
||||||
//write access requires read access
|
creation_disposition = CREATE_ALWAYS;
|
||||||
desired_access = GENERIC_WRITE;
|
flprotect = PAGE_READWRITE;
|
||||||
creation_disposition = CREATE_ALWAYS;
|
map_access = FILE_MAP_ALL_ACCESS;
|
||||||
flprotect = PAGE_READWRITE;
|
break;
|
||||||
map_access = FILE_MAP_ALL_ACCESS;
|
case mode::readwrite:
|
||||||
break;
|
desired_access = GENERIC_READ | GENERIC_WRITE;
|
||||||
case mode::readwrite:
|
creation_disposition = OPEN_EXISTING;
|
||||||
desired_access = GENERIC_READ | GENERIC_WRITE;
|
flprotect = PAGE_READWRITE;
|
||||||
creation_disposition = OPEN_EXISTING;
|
map_access = FILE_MAP_ALL_ACCESS;
|
||||||
flprotect = PAGE_READWRITE;
|
break;
|
||||||
map_access = FILE_MAP_ALL_ACCESS;
|
case mode::writeread:
|
||||||
break;
|
desired_access = GENERIC_READ | GENERIC_WRITE;
|
||||||
case mode::writeread:
|
creation_disposition = CREATE_NEW;
|
||||||
desired_access = GENERIC_READ | GENERIC_WRITE;
|
flprotect = PAGE_READWRITE;
|
||||||
creation_disposition = CREATE_NEW;
|
map_access = FILE_MAP_ALL_ACCESS;
|
||||||
flprotect = PAGE_READWRITE;
|
break;
|
||||||
map_access = FILE_MAP_ALL_ACCESS;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
p_filehandle = CreateFileW(utf16_t(filename), desired_access, FILE_SHARE_READ, nullptr,
|
|
||||||
creation_disposition, FILE_ATTRIBUTE_NORMAL, nullptr);
|
|
||||||
if(p_filehandle == INVALID_HANDLE_VALUE) return false;
|
|
||||||
|
|
||||||
p_size = GetFileSize(p_filehandle, nullptr);
|
|
||||||
|
|
||||||
p_maphandle = CreateFileMapping(p_filehandle, nullptr, flprotect, 0, p_size, nullptr);
|
|
||||||
if(p_maphandle == INVALID_HANDLE_VALUE) {
|
|
||||||
CloseHandle(p_filehandle);
|
|
||||||
p_filehandle = INVALID_HANDLE_VALUE;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
p_handle = (uint8_t*)MapViewOfFile(p_maphandle, map_access, 0, 0, p_size);
|
|
||||||
return p_handle;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void p_close() {
|
p_filehandle = CreateFileW(utf16_t(filename), desired_access, FILE_SHARE_READ, nullptr,
|
||||||
if(p_handle) {
|
creation_disposition, FILE_ATTRIBUTE_NORMAL, nullptr);
|
||||||
UnmapViewOfFile(p_handle);
|
if(p_filehandle == INVALID_HANDLE_VALUE) return false;
|
||||||
p_handle = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(p_maphandle != INVALID_HANDLE_VALUE) {
|
p_size = GetFileSize(p_filehandle, nullptr);
|
||||||
CloseHandle(p_maphandle);
|
|
||||||
p_maphandle = INVALID_HANDLE_VALUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(p_filehandle != INVALID_HANDLE_VALUE) {
|
p_maphandle = CreateFileMapping(p_filehandle, nullptr, flprotect, 0, p_size, nullptr);
|
||||||
CloseHandle(p_filehandle);
|
if(p_maphandle == INVALID_HANDLE_VALUE) {
|
||||||
p_filehandle = INVALID_HANDLE_VALUE;
|
CloseHandle(p_filehandle);
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void p_ctor() {
|
|
||||||
p_filehandle = INVALID_HANDLE_VALUE;
|
p_filehandle = INVALID_HANDLE_VALUE;
|
||||||
p_maphandle = INVALID_HANDLE_VALUE;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void p_dtor() {
|
p_handle = (uint8_t*)MapViewOfFile(p_maphandle, map_access, 0, 0, p_size);
|
||||||
close();
|
return p_handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
void p_close() {
|
||||||
|
if(p_handle) {
|
||||||
|
UnmapViewOfFile(p_handle);
|
||||||
|
p_handle = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
if(p_maphandle != INVALID_HANDLE_VALUE) {
|
||||||
//====
|
CloseHandle(p_maphandle);
|
||||||
//mmap
|
p_maphandle = INVALID_HANDLE_VALUE;
|
||||||
//====
|
|
||||||
|
|
||||||
int p_fd;
|
|
||||||
|
|
||||||
bool p_open() const {
|
|
||||||
return p_handle;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool p_open(const char *filename, mode mode_) {
|
if(p_filehandle != INVALID_HANDLE_VALUE) {
|
||||||
if(file::exists(filename) && file::size(filename) == 0) {
|
CloseHandle(p_filehandle);
|
||||||
p_handle = nullptr;
|
p_filehandle = INVALID_HANDLE_VALUE;
|
||||||
p_size = 0;
|
}
|
||||||
return true;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
int open_flags, mmap_flags;
|
void p_ctor() {
|
||||||
|
p_filehandle = INVALID_HANDLE_VALUE;
|
||||||
|
p_maphandle = INVALID_HANDLE_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
switch(mode_) {
|
void p_dtor() {
|
||||||
default: return false;
|
close();
|
||||||
case mode::read:
|
}
|
||||||
open_flags = O_RDONLY;
|
|
||||||
mmap_flags = PROT_READ;
|
|
||||||
break;
|
|
||||||
case mode::write:
|
|
||||||
open_flags = O_RDWR | O_CREAT; //mmap() requires read access
|
|
||||||
mmap_flags = PROT_WRITE;
|
|
||||||
break;
|
|
||||||
case mode::readwrite:
|
|
||||||
open_flags = O_RDWR;
|
|
||||||
mmap_flags = PROT_READ | PROT_WRITE;
|
|
||||||
break;
|
|
||||||
case mode::writeread:
|
|
||||||
open_flags = O_RDWR | O_CREAT;
|
|
||||||
mmap_flags = PROT_READ | PROT_WRITE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
p_fd = ::open(filename, open_flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
|
#else
|
||||||
if(p_fd < 0) return false;
|
//====
|
||||||
|
//mmap
|
||||||
|
//====
|
||||||
|
|
||||||
struct stat p_stat;
|
int p_fd;
|
||||||
fstat(p_fd, &p_stat);
|
|
||||||
p_size = p_stat.st_size;
|
|
||||||
|
|
||||||
p_handle = (uint8_t*)mmap(nullptr, p_size, mmap_flags, MAP_SHARED, p_fd, 0);
|
bool p_open() const {
|
||||||
if(p_handle == MAP_FAILED) {
|
return p_handle;
|
||||||
p_handle = nullptr;
|
}
|
||||||
::close(p_fd);
|
|
||||||
p_fd = -1;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return p_handle;
|
bool p_open(const string& filename, mode mode_) {
|
||||||
|
if(file::exists(filename) && file::size(filename) == 0) {
|
||||||
|
p_handle = nullptr;
|
||||||
|
p_size = 0;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void p_close() {
|
int open_flags, mmap_flags;
|
||||||
if(p_handle) {
|
|
||||||
munmap(p_handle, p_size);
|
|
||||||
p_handle = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(p_fd >= 0) {
|
switch(mode_) {
|
||||||
::close(p_fd);
|
default: return false;
|
||||||
p_fd = -1;
|
case mode::read:
|
||||||
}
|
open_flags = O_RDONLY;
|
||||||
|
mmap_flags = PROT_READ;
|
||||||
|
break;
|
||||||
|
case mode::write:
|
||||||
|
open_flags = O_RDWR | O_CREAT; //mmap() requires read access
|
||||||
|
mmap_flags = PROT_WRITE;
|
||||||
|
break;
|
||||||
|
case mode::readwrite:
|
||||||
|
open_flags = O_RDWR;
|
||||||
|
mmap_flags = PROT_READ | PROT_WRITE;
|
||||||
|
break;
|
||||||
|
case mode::writeread:
|
||||||
|
open_flags = O_RDWR | O_CREAT;
|
||||||
|
mmap_flags = PROT_READ | PROT_WRITE;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
void p_ctor() {
|
p_fd = ::open(filename, open_flags, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
|
||||||
|
if(p_fd < 0) return false;
|
||||||
|
|
||||||
|
struct stat p_stat;
|
||||||
|
fstat(p_fd, &p_stat);
|
||||||
|
p_size = p_stat.st_size;
|
||||||
|
|
||||||
|
p_handle = (uint8_t*)mmap(nullptr, p_size, mmap_flags, MAP_SHARED, p_fd, 0);
|
||||||
|
if(p_handle == MAP_FAILED) {
|
||||||
|
p_handle = nullptr;
|
||||||
|
::close(p_fd);
|
||||||
|
p_fd = -1;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return p_handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
void p_close() {
|
||||||
|
if(p_handle) {
|
||||||
|
munmap(p_handle, p_size);
|
||||||
|
p_handle = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(p_fd >= 0) {
|
||||||
|
::close(p_fd);
|
||||||
p_fd = -1;
|
p_fd = -1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void p_dtor() {
|
void p_ctor() {
|
||||||
p_close();
|
p_fd = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void p_dtor() {
|
||||||
|
p_close();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -2,59 +2,63 @@
|
||||||
#define NALL_FUNCTION_HPP
|
#define NALL_FUNCTION_HPP
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
template<typename T> class function;
|
|
||||||
|
|
||||||
template<typename R, typename... P> class function<R (P...)> {
|
template<typename T> class function;
|
||||||
struct container {
|
|
||||||
virtual R operator()(P... p) const = 0;
|
|
||||||
virtual container* copy() const = 0;
|
|
||||||
virtual ~container() {}
|
|
||||||
} *callback;
|
|
||||||
|
|
||||||
struct global : container {
|
template<typename R, typename... P> class function<R (P...)> {
|
||||||
R (*function)(P...);
|
struct container {
|
||||||
R operator()(P... p) const { return function(std::forward<P>(p)...); }
|
virtual R operator()(P... p) const = 0;
|
||||||
container* copy() const { return new global(function); }
|
virtual container* copy() const = 0;
|
||||||
global(R (*function)(P...)) : function(function) {}
|
virtual ~container() {}
|
||||||
};
|
|
||||||
|
|
||||||
template<typename C> struct member : container {
|
|
||||||
R (C::*function)(P...);
|
|
||||||
C *object;
|
|
||||||
R operator()(P... p) const { return (object->*function)(std::forward<P>(p)...); }
|
|
||||||
container* copy() const { return new member(function, object); }
|
|
||||||
member(R (C::*function)(P...), C *object) : function(function), object(object) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename L> struct lambda : container {
|
|
||||||
mutable L object;
|
|
||||||
R operator()(P... p) const { return object(std::forward<P>(p)...); }
|
|
||||||
container* copy() const { return new lambda(object); }
|
|
||||||
lambda(const L& object) : object(object) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit operator bool() const { return callback; }
|
|
||||||
R operator()(P... p) const { return (*callback)(std::forward<P>(p)...); }
|
|
||||||
void reset() { if(callback) { delete callback; callback = nullptr; } }
|
|
||||||
|
|
||||||
function& operator=(const function &source) {
|
|
||||||
if(this != &source) {
|
|
||||||
if(callback) { delete callback; callback = nullptr; }
|
|
||||||
if(source.callback) callback = source.callback->copy();
|
|
||||||
}
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
function(const function &source) : callback(nullptr) { operator=(source); }
|
|
||||||
function() : callback(nullptr) {}
|
|
||||||
function(void *function) : callback(nullptr) { if(function) callback = new global((R (*)(P...))function); }
|
|
||||||
function(R (*function)(P...)) { callback = new global(function); }
|
|
||||||
template<typename C> function(R (C::*function)(P...), C *object) { callback = new member<C>(function, object); }
|
|
||||||
template<typename C> function(R (C::*function)(P...) const, C *object) { callback = new member<C>((R (C::*)(P...))function, object); }
|
|
||||||
template<typename L> function(const L& object) { callback = new lambda<L>(object); }
|
|
||||||
~function() { if(callback) delete callback; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
container* callback = nullptr;
|
||||||
|
|
||||||
|
struct global : container {
|
||||||
|
R (*function)(P...);
|
||||||
|
R operator()(P... p) const { return function(std::forward<P>(p)...); }
|
||||||
|
container* copy() const { return new global(function); }
|
||||||
|
global(R (*function)(P...)) : function(function) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename C> struct member : container {
|
||||||
|
R (C::*function)(P...);
|
||||||
|
C* object;
|
||||||
|
R operator()(P... p) const { return (object->*function)(std::forward<P>(p)...); }
|
||||||
|
container* copy() const { return new member(function, object); }
|
||||||
|
member(R (C::*function)(P...), C* object) : function(function), object(object) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename L> struct lambda : container {
|
||||||
|
mutable L object;
|
||||||
|
R operator()(P... p) const { return object(std::forward<P>(p)...); }
|
||||||
|
container* copy() const { return new lambda(object); }
|
||||||
|
lambda(const L& object) : object(object) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit operator bool() const { return callback; }
|
||||||
|
R operator()(P... p) const { return (*callback)(std::forward<P>(p)...); }
|
||||||
|
void reset() { if(callback) { delete callback; callback = nullptr; } }
|
||||||
|
|
||||||
|
function& operator=(const function& source) {
|
||||||
|
if(this != &source) {
|
||||||
|
if(callback) { delete callback; callback = nullptr; }
|
||||||
|
if(source.callback) callback = source.callback->copy();
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
function() = default;
|
||||||
|
function(const function &source) { operator=(source); }
|
||||||
|
function(void* function) { if(function) callback = new global((R (*)(P...))function); }
|
||||||
|
function(R (*function)(P...)) { callback = new global(function); }
|
||||||
|
template<typename C> function(R (C::*function)(P...), C* object) { callback = new member<C>(function, object); }
|
||||||
|
template<typename C> function(R (C::*function)(P...) const, C* object) { callback = new member<C>((R (C::*)(P...))function, object); }
|
||||||
|
template<typename L> function(const L& object) { callback = new lambda<L>(object); }
|
||||||
|
~function() { if(callback) delete callback; }
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,132 +1,62 @@
|
||||||
#ifndef NALL_GROUP_HPP
|
#ifndef NALL_GROUP_HPP
|
||||||
#define NALL_GROUP_HPP
|
#define NALL_GROUP_HPP
|
||||||
|
|
||||||
//group: a vector of unique references
|
//group
|
||||||
|
//vector of unique references
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <nall/vector.hpp>
|
||||||
#include <algorithm>
|
|
||||||
#include <initializer_list>
|
|
||||||
#include <utility>
|
|
||||||
#include <nall/bit.hpp>
|
|
||||||
#include <nall/traits.hpp>
|
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
|
|
||||||
template<typename TR> struct group {
|
template<typename T> struct group : protected vector<T*> {
|
||||||
struct exception_out_of_bounds{};
|
group& operator=(const group& source) { vector<T*>::operator=(source); return *this; }
|
||||||
typedef typename std::remove_reference<TR>::type T;
|
group& operator=(group&& source) { vector<T*>::operator=(std::move(source)); return *this; }
|
||||||
|
template<typename... Args> group(Args&&... args) { construct(std::forward<Args>(args)...); }
|
||||||
|
|
||||||
protected:
|
bool empty() const { return vector<T*>::empty(); }
|
||||||
T** pool = nullptr;
|
unsigned size() const { return vector<T*>::size(); }
|
||||||
unsigned poolsize = 0;
|
void reset() { vector<T*>::reset(); }
|
||||||
unsigned objectsize = 0;
|
|
||||||
|
|
||||||
public:
|
T& first() const { return *vector<T*>::operator[](0); }
|
||||||
unsigned size() const { return objectsize; }
|
|
||||||
unsigned capacity() const { return poolsize; }
|
|
||||||
|
|
||||||
void reset() {
|
//return true if at least one item was appended
|
||||||
if(pool) free(pool);
|
template<typename... Args> bool append(T& value, Args&&... args) {
|
||||||
pool = nullptr;
|
bool result = append(value);
|
||||||
poolsize = 0;
|
return append(std::forward<Args>(args)...) | result;
|
||||||
objectsize = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void reserve(unsigned size) {
|
bool append(T& value) {
|
||||||
if(size == poolsize) return;
|
if(vector<T*>::find(&value)) return false;
|
||||||
pool = (T**)realloc(pool, sizeof(T*) * size);
|
return vector<T*>::append(&value), true;
|
||||||
poolsize = size;
|
|
||||||
objectsize = min(objectsize, size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void resize(unsigned size) {
|
//return true if at least one item was removed
|
||||||
if(size > poolsize) reserve(bit::round(size)); //amortize growth
|
template<typename... Args> bool remove(T& value, Args&&... args) {
|
||||||
objectsize = size;
|
bool result = remove(value);
|
||||||
|
return remove(std::forward<Args>(args)...) | result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool append(T& data) {
|
bool remove(T& value) {
|
||||||
if(find(data)) return false;
|
if(auto position = vector<T*>::find(&value)) return vector<T*>::remove(position()), true;
|
||||||
unsigned offset = objectsize++;
|
|
||||||
if(offset >= poolsize) resize(offset + 1);
|
|
||||||
pool[offset] = &data;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename... Args>
|
|
||||||
bool append(T& data, Args&&... args) {
|
|
||||||
bool result = append(data);
|
|
||||||
append(std::forward<Args>(args)...);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool remove(T& data) {
|
|
||||||
if(auto position = find(data)) {
|
|
||||||
for(signed i = position(); i < objectsize - 1; i++) pool[i] = pool[i + 1];
|
|
||||||
resize(objectsize - 1);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<unsigned> find(const T& data) {
|
struct iterator : protected vector<T*>::const_iterator {
|
||||||
for(unsigned n = 0; n < objectsize; n++) if(pool[n] == &data) return {true, n};
|
T& operator*() const { return *vector<T*>::const_iterator::operator*(); }
|
||||||
return {false, 0u};
|
bool operator!=(const iterator& source) const { return vector<T*>::const_iterator::operator!=(source); }
|
||||||
}
|
iterator& operator++() { vector<T*>::const_iterator::operator++(); return *this; }
|
||||||
|
iterator(const group& source, unsigned position) : vector<T*>::const_iterator(source, position) {}
|
||||||
template<typename... Args> group(Args&&... args) {
|
|
||||||
construct(std::forward<Args>(args)...);
|
|
||||||
}
|
|
||||||
|
|
||||||
~group() {
|
|
||||||
reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
group& operator=(const group& source) {
|
|
||||||
if(&source == this) return *this;
|
|
||||||
reset();
|
|
||||||
reserve(source.poolsize);
|
|
||||||
resize(source.objectsize);
|
|
||||||
memcpy(pool, source.pool, sizeof(T*) * objectsize);
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
group& operator=(const group&& source) {
|
|
||||||
if(&source == this) return *this;
|
|
||||||
reset();
|
|
||||||
pool = source.pool;
|
|
||||||
poolsize = source.poolsize;
|
|
||||||
objectsize = source.objectsize;
|
|
||||||
source.pool = nullptr;
|
|
||||||
source.reset();
|
|
||||||
return *this;
|
|
||||||
}
|
|
||||||
|
|
||||||
T& operator[](unsigned position) const {
|
|
||||||
if(position >= objectsize) throw exception_out_of_bounds();
|
|
||||||
return *pool[position];
|
|
||||||
}
|
|
||||||
|
|
||||||
struct iterator {
|
|
||||||
bool operator!=(const iterator& source) const { return position != source.position; }
|
|
||||||
T& operator*() { return source.operator[](position); }
|
|
||||||
iterator& operator++() { position++; return *this; }
|
|
||||||
iterator(const group& source, unsigned position) : source(source), position(position) {}
|
|
||||||
private:
|
|
||||||
const group& source;
|
|
||||||
unsigned position;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
iterator begin() { return iterator(*this, 0); }
|
|
||||||
iterator end() { return iterator(*this, objectsize); }
|
|
||||||
const iterator begin() const { return iterator(*this, 0); }
|
const iterator begin() const { return iterator(*this, 0); }
|
||||||
const iterator end() const { return iterator(*this, objectsize); }
|
const iterator end() const { return iterator(*this, size()); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void construct() {}
|
void construct() {}
|
||||||
void construct(const group& source) { operator=(source); }
|
void construct(const group& source) { vector<T*>::operator=(source); }
|
||||||
void construct(const group&& source) { operator=(std::move(source)); }
|
void construct(group&& source) { vector<T*>::operator=(std::move(source)); }
|
||||||
template<typename... Args> void construct(T& data, Args&&... args) {
|
template<typename... Args> void construct(T& value, Args&&... args) {
|
||||||
append(data);
|
append(value);
|
||||||
construct(std::forward<Args>(args)...);
|
construct(std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,24 +8,24 @@ namespace nall {
|
||||||
|
|
||||||
struct gzip {
|
struct gzip {
|
||||||
string filename;
|
string filename;
|
||||||
uint8_t *data;
|
uint8_t* data = nullptr;
|
||||||
unsigned size;
|
unsigned size = 0;
|
||||||
|
|
||||||
inline bool decompress(const string &filename);
|
inline bool decompress(const string& filename);
|
||||||
inline bool decompress(const uint8_t *data, unsigned size);
|
inline bool decompress(const uint8_t* data, unsigned size);
|
||||||
|
|
||||||
inline gzip();
|
inline gzip();
|
||||||
inline ~gzip();
|
inline ~gzip();
|
||||||
};
|
};
|
||||||
|
|
||||||
bool gzip::decompress(const string &filename) {
|
bool gzip::decompress(const string& filename) {
|
||||||
if(auto memory = file::read(filename)) {
|
if(auto memory = file::read(filename)) {
|
||||||
return decompress(memory.data(), memory.size());
|
return decompress(memory.data(), memory.size());
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool gzip::decompress(const uint8_t *data, unsigned size) {
|
bool gzip::decompress(const uint8_t* data, unsigned size) {
|
||||||
if(size < 18) return false;
|
if(size < 18) return false;
|
||||||
if(data[0] != 0x1f) return false;
|
if(data[0] != 0x1f) return false;
|
||||||
if(data[1] != 0x8b) return false;
|
if(data[1] != 0x8b) return false;
|
||||||
|
@ -73,7 +73,7 @@ bool gzip::decompress(const uint8_t *data, unsigned size) {
|
||||||
return inflate(this->data, this->size, data + p, size - p - 8);
|
return inflate(this->data, this->size, data + p, size - p - 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
gzip::gzip() : data(nullptr) {
|
gzip::gzip() {
|
||||||
}
|
}
|
||||||
|
|
||||||
gzip::~gzip() {
|
gzip::~gzip() {
|
||||||
|
|
|
@ -19,11 +19,11 @@ namespace nall {
|
||||||
|
|
||||||
struct http {
|
struct http {
|
||||||
string hostname;
|
string hostname;
|
||||||
addrinfo *serverinfo;
|
addrinfo* serverinfo;
|
||||||
int serversocket;
|
int serversocket;
|
||||||
string header;
|
string header;
|
||||||
|
|
||||||
inline void download(const string &path, uint8_t *&data, unsigned &size) {
|
inline void download(const string& path, uint8_t*& data, unsigned& size) {
|
||||||
data = nullptr;
|
data = nullptr;
|
||||||
size = 0;
|
size = 0;
|
||||||
|
|
||||||
|
@ -59,11 +59,11 @@ struct http {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool send(const string &data) {
|
inline bool send(const string& data) {
|
||||||
return send((const uint8_t*)(const char*)data, data.length());
|
return send((const uint8_t*)(const char*)data, data.length());
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool send(const uint8_t *data, unsigned size) {
|
inline bool send(const uint8_t* data, unsigned size) {
|
||||||
while(size) {
|
while(size) {
|
||||||
int length = ::send(serversocket, (const char*)data, size, 0);
|
int length = ::send(serversocket, (const char*)data, size, 0);
|
||||||
if(length == -1) return false;
|
if(length == -1) return false;
|
||||||
|
@ -97,7 +97,7 @@ struct http {
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
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.iposition("\r\nTransfer-Encoding: chunked\r\n")) {
|
||||||
|
|
|
@ -11,67 +11,72 @@
|
||||||
namespace nall {
|
namespace nall {
|
||||||
|
|
||||||
struct image {
|
struct image {
|
||||||
uint8_t *data;
|
uint8_t* data = nullptr;
|
||||||
unsigned width;
|
unsigned width = 0;
|
||||||
unsigned height;
|
unsigned height = 0;
|
||||||
unsigned pitch;
|
unsigned pitch = 0;
|
||||||
|
|
||||||
bool endian; //0 = little, 1 = big
|
bool endian = 0;
|
||||||
unsigned depth;
|
unsigned depth = 32;
|
||||||
unsigned stride;
|
unsigned stride = 4;
|
||||||
|
|
||||||
struct Channel {
|
struct Channel {
|
||||||
uint64_t mask;
|
uint64_t mask;
|
||||||
unsigned depth;
|
unsigned depth;
|
||||||
unsigned shift;
|
unsigned shift;
|
||||||
|
|
||||||
inline bool operator==(const Channel &source) {
|
inline bool operator==(const Channel& source) {
|
||||||
return mask == source.mask && depth == source.depth && shift == source.shift;
|
return mask == source.mask && depth == source.depth && shift == source.shift;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool operator!=(const Channel &source) {
|
inline bool operator!=(const Channel& source) {
|
||||||
return !operator==(source);
|
return !operator==(source);
|
||||||
}
|
}
|
||||||
} alpha, red, green, blue;
|
};
|
||||||
|
|
||||||
|
Channel alpha = {255u << 24, 8u, 24};
|
||||||
|
Channel red = {255u << 16, 8u, 16};
|
||||||
|
Channel green = {255u << 8, 8u, 8};
|
||||||
|
Channel blue = {255u << 0, 8u, 0};
|
||||||
|
|
||||||
typedef double (*interpolation)(double, double, double, double, double);
|
typedef double (*interpolation)(double, double, double, double, double);
|
||||||
static inline unsigned bitDepth(uint64_t color);
|
static inline unsigned bitDepth(uint64_t color);
|
||||||
static inline unsigned bitShift(uint64_t color);
|
static inline unsigned bitShift(uint64_t color);
|
||||||
static inline uint64_t normalize(uint64_t color, unsigned sourceDepth, unsigned targetDepth);
|
static inline uint64_t normalize(uint64_t color, unsigned sourceDepth, unsigned targetDepth);
|
||||||
|
|
||||||
inline bool operator==(const image &source);
|
inline bool operator==(const image& source);
|
||||||
inline bool operator!=(const image &source);
|
inline bool operator!=(const image& source);
|
||||||
|
|
||||||
inline image& operator=(const image &source);
|
inline image& operator=(const image& source);
|
||||||
inline image& operator=(image &&source);
|
inline image& operator=(image&& source);
|
||||||
inline image(const image &source);
|
inline image(const image& source);
|
||||||
inline image(image &&source);
|
inline image(image&& source);
|
||||||
inline image(bool endian, unsigned depth, uint64_t alphaMask, uint64_t redMask, uint64_t greenMask, uint64_t blueMask);
|
inline image(bool endian, unsigned depth, uint64_t alphaMask, uint64_t redMask, uint64_t greenMask, uint64_t blueMask);
|
||||||
inline image(const string &filename);
|
inline image(const string& filename);
|
||||||
inline image(const uint8_t *data, unsigned size);
|
inline image(const uint8_t* data, unsigned size);
|
||||||
inline image();
|
inline image();
|
||||||
inline ~image();
|
inline ~image();
|
||||||
|
|
||||||
inline uint64_t read(const uint8_t *data) const;
|
inline uint64_t read(const uint8_t* data) const;
|
||||||
inline void write(uint8_t *data, uint64_t value) const;
|
inline void write(uint8_t* data, uint64_t value) const;
|
||||||
|
|
||||||
inline void free();
|
inline void free();
|
||||||
inline bool empty() const;
|
inline bool empty() const;
|
||||||
inline void allocate(unsigned width, unsigned height);
|
inline void allocate(unsigned width, unsigned height);
|
||||||
inline void clear(uint64_t color);
|
inline void clear(uint64_t color);
|
||||||
inline bool load(const string &filename);
|
inline bool load(const string& filename);
|
||||||
//inline bool loadBMP(const uint8_t *data, unsigned size);
|
//inline bool loadBMP(const uint8_t* data, unsigned size);
|
||||||
inline bool loadPNG(const uint8_t *data, unsigned size);
|
inline bool loadPNG(const uint8_t* data, unsigned size);
|
||||||
inline void scale(unsigned width, unsigned height, interpolation op);
|
inline void scale(unsigned width, unsigned height, interpolation op);
|
||||||
inline void transform(bool endian, unsigned depth, uint64_t alphaMask, uint64_t redMask, uint64_t greenMask, uint64_t blueMask);
|
inline void transform(bool endian, unsigned depth, uint64_t alphaMask, uint64_t redMask, uint64_t greenMask, uint64_t blueMask);
|
||||||
inline void alphaBlend(uint64_t alphaColor);
|
inline void alphaBlend(uint64_t alphaColor);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
inline uint64_t interpolate(double mu, const uint64_t *s, interpolation op);
|
inline uint64_t interpolate(double mu, const uint64_t* s, interpolation op);
|
||||||
inline void scaleX(unsigned width, interpolation op);
|
inline void scaleX(unsigned width, interpolation op);
|
||||||
inline void scaleY(unsigned height, interpolation op);
|
inline void scaleY(unsigned height, interpolation op);
|
||||||
inline bool loadBMP(const string &filename);
|
inline bool loadBMP(const string& filename);
|
||||||
inline bool loadPNG(const string &filename);
|
inline bool loadPNG(const string& filename);
|
||||||
};
|
};
|
||||||
|
|
||||||
//static
|
//static
|
||||||
|
@ -100,7 +105,7 @@ uint64_t image::normalize(uint64_t color, unsigned sourceDepth, unsigned targetD
|
||||||
|
|
||||||
//public
|
//public
|
||||||
|
|
||||||
bool image::operator==(const image &source) {
|
bool image::operator==(const image& source) {
|
||||||
if(width != source.width) return false;
|
if(width != source.width) return false;
|
||||||
if(height != source.height) return false;
|
if(height != source.height) return false;
|
||||||
if(pitch != source.pitch) return false;
|
if(pitch != source.pitch) return false;
|
||||||
|
@ -116,11 +121,11 @@ bool image::operator==(const image &source) {
|
||||||
return memcmp(data, source.data, width * height * stride) == 0;
|
return memcmp(data, source.data, width * height * stride) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool image::operator!=(const image &source) {
|
bool image::operator!=(const image& source) {
|
||||||
return !operator==(source);
|
return !operator==(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
image& image::operator=(const image &source) {
|
image& image::operator=(const image& source) {
|
||||||
free();
|
free();
|
||||||
|
|
||||||
width = source.width;
|
width = source.width;
|
||||||
|
@ -140,7 +145,7 @@ image& image::operator=(const image &source) {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
image& image::operator=(image &&source) {
|
image& image::operator=(image&& source) {
|
||||||
free();
|
free();
|
||||||
|
|
||||||
width = source.width;
|
width = source.width;
|
||||||
|
@ -160,79 +165,41 @@ image& image::operator=(image &&source) {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
image::image(const image &source) : data(nullptr) {
|
image::image(const image& source) {
|
||||||
operator=(source);
|
operator=(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
image::image(image &&source) : data(nullptr) {
|
image::image(image&& source) {
|
||||||
operator=(std::forward<image>(source));
|
operator=(std::forward<image>(source));
|
||||||
}
|
}
|
||||||
|
|
||||||
image::image(bool endian, unsigned depth, uint64_t alphaMask, uint64_t redMask, uint64_t greenMask, uint64_t blueMask) : data(nullptr) {
|
image::image(bool endian, unsigned depth, uint64_t alphaMask, uint64_t redMask, uint64_t greenMask, uint64_t blueMask) {
|
||||||
width = 0, height = 0, pitch = 0;
|
|
||||||
|
|
||||||
this->endian = endian;
|
this->endian = endian;
|
||||||
this->depth = depth;
|
this->depth = depth;
|
||||||
this->stride = (depth / 8) + ((depth & 7) > 0);
|
this->stride = (depth / 8) + ((depth & 7) > 0);
|
||||||
|
|
||||||
alpha.mask = alphaMask, red.mask = redMask, green.mask = greenMask, blue.mask = blueMask;
|
alpha = {alphaMask, bitDepth(alphaMask), bitShift(alphaMask)};
|
||||||
alpha.depth = bitDepth(alpha.mask), alpha.shift = bitShift(alpha.mask);
|
red = {redMask, bitDepth(redMask), bitShift(redMask)};
|
||||||
red.depth = bitDepth(red.mask), red.shift = bitShift(red.mask);
|
green = {greenMask, bitDepth(greenMask), bitShift(greenMask)};
|
||||||
green.depth = bitDepth(green.mask), green.shift = bitShift(green.mask);
|
blue = {blueMask, bitDepth(blueMask), bitShift(blueMask)};
|
||||||
blue.depth = bitDepth(blue.mask), blue.shift = bitShift(blue.mask);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
image::image(const string &filename) : data(nullptr) {
|
image::image(const string& filename) {
|
||||||
width = 0, height = 0, pitch = 0;
|
|
||||||
|
|
||||||
this->endian = 0;
|
|
||||||
this->depth = 32;
|
|
||||||
this->stride = 4;
|
|
||||||
|
|
||||||
alpha.mask = 255u << 24, red.mask = 255u << 16, green.mask = 255u << 8, blue.mask = 255u << 0;
|
|
||||||
alpha.depth = bitDepth(alpha.mask), alpha.shift = bitShift(alpha.mask);
|
|
||||||
red.depth = bitDepth(red.mask), red.shift = bitShift(red.mask);
|
|
||||||
green.depth = bitDepth(green.mask), green.shift = bitShift(green.mask);
|
|
||||||
blue.depth = bitDepth(blue.mask), blue.shift = bitShift(blue.mask);
|
|
||||||
|
|
||||||
load(filename);
|
load(filename);
|
||||||
}
|
}
|
||||||
|
|
||||||
image::image(const uint8_t *data, unsigned size) : data(nullptr) {
|
image::image(const uint8_t* data, unsigned size) {
|
||||||
width = 0, height = 0, pitch = 0;
|
|
||||||
|
|
||||||
this->endian = 0;
|
|
||||||
this->depth = 32;
|
|
||||||
this->stride = 4;
|
|
||||||
|
|
||||||
alpha.mask = 255u << 24, red.mask = 255u << 16, green.mask = 255u << 8, blue.mask = 255u << 0;
|
|
||||||
alpha.depth = bitDepth(alpha.mask), alpha.shift = bitShift(alpha.mask);
|
|
||||||
red.depth = bitDepth(red.mask), red.shift = bitShift(red.mask);
|
|
||||||
green.depth = bitDepth(green.mask), green.shift = bitShift(green.mask);
|
|
||||||
blue.depth = bitDepth(blue.mask), blue.shift = bitShift(blue.mask);
|
|
||||||
|
|
||||||
loadPNG(data, size);
|
loadPNG(data, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
image::image() : data(nullptr) {
|
image::image() {
|
||||||
width = 0, height = 0, pitch = 0;
|
|
||||||
|
|
||||||
this->endian = 0;
|
|
||||||
this->depth = 32;
|
|
||||||
this->stride = 4;
|
|
||||||
|
|
||||||
alpha.mask = 255u << 24, red.mask = 255u << 16, green.mask = 255u << 8, blue.mask = 255u << 0;
|
|
||||||
alpha.depth = bitDepth(alpha.mask), alpha.shift = bitShift(alpha.mask);
|
|
||||||
red.depth = bitDepth(red.mask), red.shift = bitShift(red.mask);
|
|
||||||
green.depth = bitDepth(green.mask), green.shift = bitShift(green.mask);
|
|
||||||
blue.depth = bitDepth(blue.mask), blue.shift = bitShift(blue.mask);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
image::~image() {
|
image::~image() {
|
||||||
free();
|
free();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t image::read(const uint8_t *data) const {
|
uint64_t image::read(const uint8_t* data) const {
|
||||||
uint64_t result = 0;
|
uint64_t result = 0;
|
||||||
if(endian == 0) {
|
if(endian == 0) {
|
||||||
for(signed n = stride - 1; n >= 0; n--) result = (result << 8) | data[n];
|
for(signed n = stride - 1; n >= 0; n--) result = (result << 8) | data[n];
|
||||||
|
@ -242,7 +209,7 @@ uint64_t image::read(const uint8_t *data) const {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void image::write(uint8_t *data, uint64_t value) const {
|
void image::write(uint8_t* data, uint64_t value) const {
|
||||||
if(endian == 0) {
|
if(endian == 0) {
|
||||||
for(signed n = 0; n < stride; n++) { data[n] = value; value >>= 8; }
|
for(signed n = 0; n < stride; n++) { data[n] = value; value >>= 8; }
|
||||||
} else {
|
} else {
|
||||||
|
@ -278,7 +245,7 @@ void image::clear(uint64_t color) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool image::load(const string &filename) {
|
bool image::load(const string& filename) {
|
||||||
if(loadBMP(filename) == true) return true;
|
if(loadBMP(filename) == true) return true;
|
||||||
if(loadPNG(filename) == true) return true;
|
if(loadPNG(filename) == true) return true;
|
||||||
return false;
|
return false;
|
||||||
|
@ -295,8 +262,8 @@ void image::transform(bool outputEndian, unsigned outputDepth, uint64_t outputAl
|
||||||
|
|
||||||
#pragma omp parallel for
|
#pragma omp parallel for
|
||||||
for(unsigned y = 0; y < height; y++) {
|
for(unsigned y = 0; y < height; y++) {
|
||||||
uint8_t *dp = output.data + output.pitch * y;
|
uint8_t* dp = output.data + output.pitch * y;
|
||||||
uint8_t *sp = data + pitch * y;
|
uint8_t* sp = data + pitch * y;
|
||||||
for(unsigned x = 0; x < width; x++) {
|
for(unsigned x = 0; x < width; x++) {
|
||||||
uint64_t color = read(sp);
|
uint64_t color = read(sp);
|
||||||
sp += stride;
|
sp += stride;
|
||||||
|
@ -326,7 +293,7 @@ void image::alphaBlend(uint64_t alphaColor) {
|
||||||
|
|
||||||
#pragma omp parallel for
|
#pragma omp parallel for
|
||||||
for(unsigned y = 0; y < height; y++) {
|
for(unsigned y = 0; y < height; y++) {
|
||||||
uint8_t *dp = data + pitch * y;
|
uint8_t* dp = data + pitch * y;
|
||||||
for(unsigned x = 0; x < width; x++) {
|
for(unsigned x = 0; x < width; x++) {
|
||||||
uint64_t color = read(dp);
|
uint64_t color = read(dp);
|
||||||
|
|
||||||
|
@ -349,7 +316,7 @@ void image::alphaBlend(uint64_t alphaColor) {
|
||||||
|
|
||||||
//protected
|
//protected
|
||||||
|
|
||||||
uint64_t image::interpolate(double mu, const uint64_t *s, double (*op)(double, double, double, double, double)) {
|
uint64_t image::interpolate(double mu, const uint64_t* s, double (*op)(double, double, double, double, double)) {
|
||||||
uint64_t aa = (s[0] & alpha.mask) >> alpha.shift, ar = (s[0] & red.mask) >> red.shift,
|
uint64_t aa = (s[0] & alpha.mask) >> alpha.shift, ar = (s[0] & red.mask) >> red.shift,
|
||||||
ag = (s[0] & green.mask) >> green.shift, ab = (s[0] & blue.mask) >> blue.shift;
|
ag = (s[0] & green.mask) >> green.shift, ab = (s[0] & blue.mask) >> blue.shift;
|
||||||
uint64_t ba = (s[1] & alpha.mask) >> alpha.shift, br = (s[1] & red.mask) >> red.shift,
|
uint64_t ba = (s[1] & alpha.mask) >> alpha.shift, br = (s[1] & red.mask) >> red.shift,
|
||||||
|
@ -373,18 +340,18 @@ uint64_t image::interpolate(double mu, const uint64_t *s, double (*op)(double, d
|
||||||
}
|
}
|
||||||
|
|
||||||
void image::scaleX(unsigned outputWidth, interpolation op) {
|
void image::scaleX(unsigned outputWidth, interpolation op) {
|
||||||
uint8_t *outputData = new uint8_t[outputWidth * height * stride];
|
uint8_t* outputData = new uint8_t[outputWidth * height * stride];
|
||||||
unsigned outputPitch = outputWidth * stride;
|
unsigned outputPitch = outputWidth * stride;
|
||||||
double step = (double)width / (double)outputWidth;
|
double step = (double)width / (double)outputWidth;
|
||||||
const uint8_t *terminal = data + pitch * height;
|
const uint8_t* terminal = data + pitch * height;
|
||||||
|
|
||||||
#pragma omp parallel for
|
#pragma omp parallel for
|
||||||
for(unsigned y = 0; y < height; y++) {
|
for(unsigned y = 0; y < height; y++) {
|
||||||
uint8_t *dp = outputData + outputPitch * y;
|
uint8_t* dp = outputData + outputPitch * y;
|
||||||
uint8_t *sp = data + pitch * y;
|
uint8_t* sp = data + pitch * y;
|
||||||
|
|
||||||
double fraction = 0.0;
|
double fraction = 0.0;
|
||||||
uint64_t s[4] = { sp < terminal ? read(sp) : 0 }; //B,C (0,1) = center of kernel { 0, 0, 1, 2 }
|
uint64_t s[4] = {sp < terminal ? read(sp) : 0}; //B,C (0,1) = center of kernel { 0, 0, 1, 2 }
|
||||||
s[1] = s[0];
|
s[1] = s[0];
|
||||||
s[2] = sp + stride < terminal ? read(sp += stride) : s[1];
|
s[2] = sp + stride < terminal ? read(sp += stride) : s[1];
|
||||||
s[3] = sp + stride < terminal ? read(sp += stride) : s[2];
|
s[3] = sp + stride < terminal ? read(sp += stride) : s[2];
|
||||||
|
@ -410,17 +377,17 @@ void image::scaleX(unsigned outputWidth, interpolation op) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void image::scaleY(unsigned outputHeight, interpolation op) {
|
void image::scaleY(unsigned outputHeight, interpolation op) {
|
||||||
uint8_t *outputData = new uint8_t[width * outputHeight * stride];
|
uint8_t* outputData = new uint8_t[width * outputHeight * stride];
|
||||||
double step = (double)height / (double)outputHeight;
|
double step = (double)height / (double)outputHeight;
|
||||||
const uint8_t *terminal = data + pitch * height;
|
const uint8_t* terminal = data + pitch * height;
|
||||||
|
|
||||||
#pragma omp parallel for
|
#pragma omp parallel for
|
||||||
for(unsigned x = 0; x < width; x++) {
|
for(unsigned x = 0; x < width; x++) {
|
||||||
uint8_t *dp = outputData + stride * x;
|
uint8_t* dp = outputData + stride * x;
|
||||||
uint8_t *sp = data + stride * x;
|
uint8_t* sp = data + stride * x;
|
||||||
|
|
||||||
double fraction = 0.0;
|
double fraction = 0.0;
|
||||||
uint64_t s[4] = { sp < terminal ? read(sp) : 0 };
|
uint64_t s[4] = {sp < terminal ? read(sp) : 0};
|
||||||
s[1] = s[0];
|
s[1] = s[0];
|
||||||
s[2] = sp + pitch < terminal ? read(sp += pitch) : s[1];
|
s[2] = sp + pitch < terminal ? read(sp += pitch) : s[1];
|
||||||
s[3] = sp + pitch < terminal ? read(sp += pitch) : s[2];
|
s[3] = sp + pitch < terminal ? read(sp += pitch) : s[2];
|
||||||
|
@ -444,14 +411,14 @@ void image::scaleY(unsigned outputHeight, interpolation op) {
|
||||||
height = outputHeight;
|
height = outputHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool image::loadBMP(const string &filename) {
|
bool image::loadBMP(const string& filename) {
|
||||||
uint32_t *outputData;
|
uint32_t* outputData;
|
||||||
unsigned outputWidth, outputHeight;
|
unsigned outputWidth, outputHeight;
|
||||||
if(bmp::read(filename, outputData, outputWidth, outputHeight) == false) return false;
|
if(bmp::read(filename, outputData, outputWidth, outputHeight) == false) return false;
|
||||||
|
|
||||||
allocate(outputWidth, outputHeight);
|
allocate(outputWidth, outputHeight);
|
||||||
const uint32_t *sp = outputData;
|
const uint32_t* sp = outputData;
|
||||||
uint8_t *dp = data;
|
uint8_t* dp = data;
|
||||||
|
|
||||||
for(unsigned y = 0; y < outputHeight; y++) {
|
for(unsigned y = 0; y < outputHeight; y++) {
|
||||||
for(unsigned x = 0; x < outputWidth; x++) {
|
for(unsigned x = 0; x < outputWidth; x++) {
|
||||||
|
@ -469,13 +436,13 @@ bool image::loadBMP(const string &filename) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool image::loadPNG(const uint8_t *pngData, unsigned pngSize) {
|
bool image::loadPNG(const uint8_t* pngData, unsigned pngSize) {
|
||||||
png source;
|
png source;
|
||||||
if(source.decode(pngData, pngSize) == false) return false;
|
if(source.decode(pngData, pngSize) == false) return false;
|
||||||
|
|
||||||
allocate(source.info.width, source.info.height);
|
allocate(source.info.width, source.info.height);
|
||||||
const uint8_t *sp = source.data;
|
const uint8_t* sp = source.data;
|
||||||
uint8_t *dp = data;
|
uint8_t* dp = data;
|
||||||
|
|
||||||
auto decode = [&]() -> uint64_t {
|
auto decode = [&]() -> uint64_t {
|
||||||
uint64_t p, r, g, b, a;
|
uint64_t p, r, g, b, a;
|
||||||
|
@ -528,7 +495,7 @@ bool image::loadPNG(const uint8_t *pngData, unsigned pngSize) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool image::loadPNG(const string &filename) {
|
bool image::loadPNG(const string& filename) {
|
||||||
filemap map;
|
filemap map;
|
||||||
if(map.open(filename, filemap::mode::read) == false) return false;
|
if(map.open(filename, filemap::mode::read) == false) return false;
|
||||||
return loadPNG(map.data(), map.size());
|
return loadPNG(map.data(), map.size());
|
||||||
|
|
|
@ -7,14 +7,14 @@ namespace nall {
|
||||||
|
|
||||||
namespace puff {
|
namespace puff {
|
||||||
inline int puff(
|
inline int puff(
|
||||||
unsigned char *dest, unsigned long *destlen,
|
unsigned char* dest, unsigned long* destlen,
|
||||||
unsigned char *source, unsigned long *sourcelen
|
unsigned char* source, unsigned long* sourcelen
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool inflate(
|
inline bool inflate(
|
||||||
uint8_t *target, unsigned targetLength,
|
uint8_t* target, unsigned targetLength,
|
||||||
const uint8_t *source, unsigned sourceLength
|
const uint8_t* source, unsigned sourceLength
|
||||||
) {
|
) {
|
||||||
unsigned long tl = targetLength, sl = sourceLength;
|
unsigned long tl = targetLength, sl = sourceLength;
|
||||||
int result = puff::puff((unsigned char*)target, &tl, (unsigned char*)source, &sl);
|
int result = puff::puff((unsigned char*)target, &tl, (unsigned char*)source, &sl);
|
||||||
|
@ -23,15 +23,6 @@ inline bool inflate(
|
||||||
|
|
||||||
namespace puff {
|
namespace puff {
|
||||||
|
|
||||||
//zlib/contrib/puff.c
|
|
||||||
//version 2.1*
|
|
||||||
//author: Mark Adler
|
|
||||||
//license: zlib
|
|
||||||
//ported by: byuu
|
|
||||||
|
|
||||||
//* I have corrected a bug in fixed(), where it was accessing uninitialized
|
|
||||||
// memory: calling construct() with lencode prior to initializing lencode.count
|
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
MAXBITS = 15,
|
MAXBITS = 15,
|
||||||
MAXLCODES = 286,
|
MAXLCODES = 286,
|
||||||
|
@ -41,11 +32,11 @@ enum {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct state {
|
struct state {
|
||||||
unsigned char *out;
|
unsigned char* out;
|
||||||
unsigned long outlen;
|
unsigned long outlen;
|
||||||
unsigned long outcnt;
|
unsigned long outcnt;
|
||||||
|
|
||||||
unsigned char *in;
|
unsigned char* in;
|
||||||
unsigned long inlen;
|
unsigned long inlen;
|
||||||
unsigned long incnt;
|
unsigned long incnt;
|
||||||
int bitbuf;
|
int bitbuf;
|
||||||
|
@ -55,11 +46,11 @@ struct state {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct huffman {
|
struct huffman {
|
||||||
short *count;
|
short* count;
|
||||||
short *symbol;
|
short* symbol;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline int bits(state *s, int need) {
|
inline int bits(state* s, int need) {
|
||||||
long val;
|
long val;
|
||||||
|
|
||||||
val = s->bitbuf;
|
val = s->bitbuf;
|
||||||
|
@ -75,7 +66,7 @@ inline int bits(state *s, int need) {
|
||||||
return (int)(val & ((1L << need) - 1));
|
return (int)(val & ((1L << need) - 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int stored(state *s) {
|
inline int stored(state* s) {
|
||||||
unsigned len;
|
unsigned len;
|
||||||
|
|
||||||
s->bitbuf = 0;
|
s->bitbuf = 0;
|
||||||
|
@ -100,9 +91,9 @@ inline int stored(state *s) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int decode(state *s, huffman *h) {
|
inline int decode(state* s, huffman* h) {
|
||||||
int len, code, first, count, index, bitbuf, left;
|
int len, code, first, count, index, bitbuf, left;
|
||||||
short *next;
|
short* next;
|
||||||
|
|
||||||
bitbuf = s->bitbuf;
|
bitbuf = s->bitbuf;
|
||||||
left = s->bitcnt;
|
left = s->bitcnt;
|
||||||
|
@ -135,7 +126,7 @@ inline int decode(state *s, huffman *h) {
|
||||||
return -10;
|
return -10;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int construct(huffman *h, short *length, int n) {
|
inline int construct(huffman* h, short* length, int n) {
|
||||||
int symbol, len, left;
|
int symbol, len, left;
|
||||||
short offs[MAXBITS + 1];
|
short offs[MAXBITS + 1];
|
||||||
|
|
||||||
|
@ -160,7 +151,7 @@ inline int construct(huffman *h, short *length, int n) {
|
||||||
return left;
|
return left;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int codes(state *s, huffman *lencode, huffman *distcode) {
|
inline int codes(state* s, huffman* lencode, huffman* distcode) {
|
||||||
int symbol, len;
|
int symbol, len;
|
||||||
unsigned dist;
|
unsigned dist;
|
||||||
static const short lens[29] = {
|
static const short lens[29] = {
|
||||||
|
@ -222,7 +213,7 @@ inline int codes(state *s, huffman *lencode, huffman *distcode) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int fixed(state *s) {
|
inline int fixed(state* s) {
|
||||||
static int virgin = 1;
|
static int virgin = 1;
|
||||||
static short lencnt[MAXBITS + 1], lensym[FIXLCODES];
|
static short lencnt[MAXBITS + 1], lensym[FIXLCODES];
|
||||||
static short distcnt[MAXBITS + 1], distsym[MAXDCODES];
|
static short distcnt[MAXBITS + 1], distsym[MAXDCODES];
|
||||||
|
@ -252,7 +243,7 @@ inline int fixed(state *s) {
|
||||||
return codes(s, &lencode, &distcode);
|
return codes(s, &lencode, &distcode);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int dynamic(state *s) {
|
inline int dynamic(state* s) {
|
||||||
int nlen, ndist, ncode, index, err;
|
int nlen, ndist, ncode, index, err;
|
||||||
short lengths[MAXCODES];
|
short lengths[MAXCODES];
|
||||||
short lencnt[MAXBITS + 1], lensym[MAXLCODES];
|
short lencnt[MAXBITS + 1], lensym[MAXLCODES];
|
||||||
|
@ -313,8 +304,8 @@ inline int dynamic(state *s) {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline int puff(
|
inline int puff(
|
||||||
unsigned char *dest, unsigned long *destlen,
|
unsigned char* dest, unsigned long* destlen,
|
||||||
unsigned char *source, unsigned long *sourcelen
|
unsigned char* source, unsigned long* sourcelen
|
||||||
) {
|
) {
|
||||||
state s;
|
state s;
|
||||||
int last, type, err;
|
int last, type, err;
|
||||||
|
|
|
@ -88,7 +88,7 @@ struct Keyboard {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint16_t decode(const char *name) {
|
static uint16_t decode(const char* name) {
|
||||||
string s(name);
|
string s(name);
|
||||||
if(!strbegin(name, "KB")) return 0;
|
if(!strbegin(name, "KB")) return 0;
|
||||||
s.ltrim("KB");
|
s.ltrim("KB");
|
||||||
|
@ -110,7 +110,7 @@ struct Keyboard {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return { "KB", ID, "::", KeyboardScancodeName[index] };
|
return {"KB", ID, "::", KeyboardScancodeName[index]};
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t operator[](Scancode code) const { return Base + ID * Size + code; }
|
uint16_t operator[](Scancode code) const { return Base + ID * Size + code; }
|
||||||
|
@ -185,7 +185,7 @@ struct Mouse {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint16_t decode(const char *name) {
|
static uint16_t decode(const char* name) {
|
||||||
string s(name);
|
string s(name);
|
||||||
if(!strbegin(name, "MS")) return 0;
|
if(!strbegin(name, "MS")) return 0;
|
||||||
s.ltrim("MS");
|
s.ltrim("MS");
|
||||||
|
@ -207,7 +207,7 @@ struct Mouse {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return { "MS", ID, "::", MouseScancodeName[index] };
|
return {"MS", ID, "::", MouseScancodeName[index]};
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t operator[](Scancode code) const { return Base + ID * Size + code; }
|
uint16_t operator[](Scancode code) const { return Base + ID * Size + code; }
|
||||||
|
@ -309,7 +309,7 @@ struct Joypad {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint16_t decode(const char *name) {
|
static uint16_t decode(const char* name) {
|
||||||
string s(name);
|
string s(name);
|
||||||
if(!strbegin(name, "JP")) return 0;
|
if(!strbegin(name, "JP")) return 0;
|
||||||
s.ltrim("JP");
|
s.ltrim("JP");
|
||||||
|
@ -330,7 +330,7 @@ struct Joypad {
|
||||||
index = code - (Base + Size * i);
|
index = code - (Base + Size * i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return { "JP", ID, "::", JoypadScancodeName[index] };
|
return {"JP", ID, "::", JoypadScancodeName[index]};
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t operator[](Scancode code) const { return Base + ID * Size + code; }
|
uint16_t operator[](Scancode code) const { return Base + ID * Size + code; }
|
||||||
|
@ -356,7 +356,7 @@ inline Joypad& joypad(unsigned id) {
|
||||||
struct Scancode {
|
struct Scancode {
|
||||||
enum { None = 0, Limit = Joypad::Base + Joypad::Size * Joypad::Count };
|
enum { None = 0, Limit = Joypad::Base + Joypad::Size * Joypad::Count };
|
||||||
|
|
||||||
static uint16_t decode(const char *name) {
|
static uint16_t decode(const char* name) {
|
||||||
uint16_t code;
|
uint16_t code;
|
||||||
code = Keyboard::decode(name);
|
code = Keyboard::decode(name);
|
||||||
if(code) return code;
|
if(code) return code;
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
#ifndef NALL_INTRINSICS_HPP
|
#ifndef NALL_INTRINSICS_HPP
|
||||||
#define NALL_INTRINSICS_HPP
|
#define NALL_INTRINSICS_HPP
|
||||||
|
|
||||||
|
namespace nall {
|
||||||
|
|
||||||
struct Intrinsics {
|
struct Intrinsics {
|
||||||
enum class Compiler : unsigned { Clang, GCC, VisualC, Unknown };
|
enum class Compiler : unsigned { Clang, GCC, VisualC, Unknown };
|
||||||
enum class Platform : unsigned { X, OSX, Windows, Unknown };
|
enum class Platform : unsigned { X, OSX, Windows, Unknown };
|
||||||
|
@ -63,4 +65,6 @@ struct Intrinsics {
|
||||||
Intrinsics::Endian Intrinsics::endian() { return Intrinsics::Endian::Unknown; }
|
Intrinsics::Endian Intrinsics::endian() { return Intrinsics::Endian::Unknown; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -20,21 +20,20 @@ namespace nall {
|
||||||
|
|
||||||
#if defined(PLATFORM_WINDOWS)
|
#if defined(PLATFORM_WINDOWS)
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args> inline void invoke(const string& name, Args&&... 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.position(" ")) 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
#elif defined(PLATFORM_X)
|
#elif defined(PLATFORM_X)
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args> inline void invoke(const string& name, Args&&... args) {
|
||||||
inline void invoke(const string &name, Args&&... args) {
|
|
||||||
pid_t pid = fork();
|
pid_t pid = fork();
|
||||||
if(pid == 0) {
|
if(pid == 0) {
|
||||||
const char *argv[1 + sizeof...(args) + 1], **argp = argv;
|
const char* argv[1 + sizeof...(args) + 1];
|
||||||
|
const char** argp = argv;
|
||||||
lstring argl(std::forward<Args>(args)...);
|
lstring argl(std::forward<Args>(args)...);
|
||||||
*argp++ = (const char*)name;
|
*argp++ = (const char*)name;
|
||||||
for(auto &arg : argl) *argp++ = (const char*)arg;
|
for(auto &arg : argl) *argp++ = (const char*)arg;
|
||||||
|
@ -49,8 +48,7 @@ inline void invoke(const string &name, Args&&... args) {
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
template<typename... Args>
|
template<typename... Args> inline void invoke(const string& name, Args&&... args) {
|
||||||
inline void invoke(const string &name, Args&&... args) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -9,17 +9,17 @@ namespace nall {
|
||||||
|
|
||||||
struct ips {
|
struct ips {
|
||||||
inline bool apply();
|
inline bool apply();
|
||||||
inline void source(const uint8_t *data, unsigned size);
|
inline void source(const uint8_t* data, unsigned size);
|
||||||
inline void modify(const uint8_t *data, unsigned size);
|
inline void modify(const uint8_t* data, unsigned size);
|
||||||
inline ips();
|
inline ips();
|
||||||
inline ~ips();
|
inline ~ips();
|
||||||
|
|
||||||
uint8_t *data;
|
uint8_t* data = nullptr;
|
||||||
unsigned size;
|
unsigned size = 0;
|
||||||
const uint8_t *sourceData;
|
const uint8_t* sourceData = nullptr;
|
||||||
unsigned sourceSize;
|
unsigned sourceSize = 0;
|
||||||
const uint8_t *modifyData;
|
const uint8_t* modifyData = nullptr;
|
||||||
unsigned modifySize;
|
unsigned modifySize = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool ips::apply() {
|
bool ips::apply() {
|
||||||
|
@ -78,15 +78,15 @@ bool ips::apply() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ips::source(const uint8_t *data, unsigned size) {
|
void ips::source(const uint8_t* data, unsigned size) {
|
||||||
sourceData = data, sourceSize = size;
|
sourceData = data, sourceSize = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ips::modify(const uint8_t *data, unsigned size) {
|
void ips::modify(const uint8_t* data, unsigned size) {
|
||||||
modifyData = data, modifySize = size;
|
modifyData = data, modifySize = size;
|
||||||
}
|
}
|
||||||
|
|
||||||
ips::ips() : data(nullptr), sourceData(nullptr), modifyData(nullptr) {
|
ips::ips() {
|
||||||
}
|
}
|
||||||
|
|
||||||
ips::~ips() {
|
ips::~ips() {
|
||||||
|
|
|
@ -1,115 +1,57 @@
|
||||||
#ifndef NALL_MAP_HPP
|
#ifndef NALL_MAP_HPP
|
||||||
#define NALL_MAP_HPP
|
#define NALL_MAP_HPP
|
||||||
|
|
||||||
#include <nall/vector.hpp>
|
#include <nall/set.hpp>
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
|
|
||||||
template<typename LHS, typename RHS>
|
template<typename T, typename U> struct map {
|
||||||
struct map {
|
struct node_t {
|
||||||
struct pair {
|
T key;
|
||||||
LHS name;
|
U value;
|
||||||
RHS data;
|
bool operator< (const node_t& source) const { return key < source.key; }
|
||||||
|
bool operator==(const node_t& source) const { return key == source.key; }
|
||||||
|
node_t() = default;
|
||||||
|
node_t(const T& key) : key(key) {}
|
||||||
|
node_t(const T& key, const U& value) : key(key), value(value) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void reset() {
|
optional<U> find(const T& key) const {
|
||||||
list.reset();
|
if(auto node = root.find({key})) return {true, node().value};
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned size() const {
|
void insert(const T& key, const U& value) { root.insert({key, value}); }
|
||||||
return list.size();
|
void remove(const T& key) { root.remove({key}); }
|
||||||
}
|
unsigned size() const { return root.size(); }
|
||||||
|
void reset() { root.reset(); }
|
||||||
|
|
||||||
//O(log n) find
|
typename set<node_t>::iterator begin() { return root.begin(); }
|
||||||
inline optional<unsigned> find(const LHS &name) const {
|
typename set<node_t>::iterator end() { return root.end(); }
|
||||||
signed first = 0, last = size() - 1;
|
const typename set<node_t>::iterator begin() const { return root.begin(); }
|
||||||
while(first <= last) {
|
const typename set<node_t>::iterator end() const { return root.end(); }
|
||||||
signed middle = (first + last) / 2;
|
|
||||||
if(name < list[middle].name) last = middle - 1; //search lower half
|
|
||||||
else if(list[middle].name < name) first = middle + 1; //search upper half
|
|
||||||
else return { true, (unsigned)middle }; //match found
|
|
||||||
}
|
|
||||||
return { false, 0u };
|
|
||||||
}
|
|
||||||
|
|
||||||
//O(n) insert + O(log n) find
|
|
||||||
inline RHS& insert(const LHS &name, const RHS &data) {
|
|
||||||
if(auto position = find(name)) {
|
|
||||||
list[position()].data = data;
|
|
||||||
return list[position()].data;
|
|
||||||
}
|
|
||||||
signed offset = size();
|
|
||||||
for(unsigned n = 0; n < size(); n++) {
|
|
||||||
if(name < list[n].name) { offset = n; break; }
|
|
||||||
}
|
|
||||||
list.insert(offset, { name, data });
|
|
||||||
return list[offset].data;
|
|
||||||
}
|
|
||||||
|
|
||||||
//O(log n) find
|
|
||||||
inline void modify(const LHS &name, const RHS &data) {
|
|
||||||
if(auto position = find(name)) list[position()].data = data;
|
|
||||||
}
|
|
||||||
|
|
||||||
//O(n) remove + O(log n) find
|
|
||||||
inline void remove(const LHS &name) {
|
|
||||||
if(auto position = find(name)) list.remove(position());
|
|
||||||
}
|
|
||||||
|
|
||||||
//O(log n) find
|
|
||||||
inline RHS& operator[](const LHS &name) {
|
|
||||||
if(auto position = find(name)) return list[position()].data;
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const RHS& operator[](const LHS &name) const {
|
|
||||||
if(auto position = find(name)) return list[position()].data;
|
|
||||||
throw;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline RHS& operator()(const LHS &name) {
|
|
||||||
if(auto position = find(name)) return list[position()].data;
|
|
||||||
return insert(name, RHS());
|
|
||||||
}
|
|
||||||
|
|
||||||
inline const RHS& operator()(const LHS &name, const RHS &data) const {
|
|
||||||
if(auto position = find(name)) return list[position()].data;
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline pair* begin() { return list.begin(); }
|
|
||||||
inline pair* end() { return list.end(); }
|
|
||||||
inline const pair* begin() const { return list.begin(); }
|
|
||||||
inline const pair* end() const { return list.end(); }
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
vector<pair> list;
|
set<node_t> root;
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename LHS, typename RHS>
|
template<typename T, typename U> struct bimap {
|
||||||
struct bidirectional_map {
|
optional<U> find(const T& key) const { return tmap.find(key); }
|
||||||
const map<LHS, RHS> &lhs;
|
optional<T> find(const U& key) const { return umap.find(key); }
|
||||||
const map<RHS, LHS> &rhs;
|
void insert(const T& key, const U& value) { tmap.insert(key, value); umap.insert(value, key); }
|
||||||
|
void remove(const T& key) { if(auto p = tmap.find(key)) { umap.remove(p().value); tmap.remove(key); } }
|
||||||
|
void remove(const U& key) { if(auto p = umap.find(key)) { tmap.remove(p().value); umap.remove(key); } }
|
||||||
|
unsigned size() const { return tmap.size(); }
|
||||||
|
void reset() { tmap.reset(); umap.reset(); }
|
||||||
|
|
||||||
inline void reset() {
|
typename set<typename map<T, U>::node_t>::iterator begin() { return tmap.begin(); }
|
||||||
llist.reset();
|
typename set<typename map<T, U>::node_t>::iterator end() { return tmap.end(); }
|
||||||
rlist.reset();
|
const typename set<typename map<T, U>::node_t>::iterator begin() const { return tmap.begin(); }
|
||||||
}
|
const typename set<typename map<T, U>::node_t>::iterator end() const { return tmap.end(); }
|
||||||
|
|
||||||
inline unsigned size() const {
|
|
||||||
return llist.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void insert(const LHS &ldata, const RHS &rdata) {
|
|
||||||
llist.insert(ldata, rdata);
|
|
||||||
rlist.insert(rdata, ldata);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bidirectional_map() : lhs(llist), rhs(rlist) {}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
map<LHS, RHS> llist;
|
map<T, U> tmap;
|
||||||
map<RHS, LHS> rlist;
|
map<U, T> umap;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,7 @@ namespace nall {
|
||||||
|
|
||||||
namespace Matrix {
|
namespace Matrix {
|
||||||
|
|
||||||
template<typename T>
|
template<typename T> inline void Multiply(T* output, const T* xdata, unsigned xrows, unsigned xcols, const T* ydata, unsigned yrows, unsigned ycols) {
|
||||||
inline void Multiply(T *output, const T *xdata, unsigned xrows, unsigned xcols, const T *ydata, unsigned yrows, unsigned ycols) {
|
|
||||||
if(xcols != yrows) return;
|
if(xcols != yrows) return;
|
||||||
|
|
||||||
for(unsigned y = 0; y < xrows; y++) {
|
for(unsigned y = 0; y < xrows; y++) {
|
||||||
|
@ -20,8 +19,7 @@ inline void Multiply(T *output, const T *xdata, unsigned xrows, unsigned xcols,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
template<typename T> inline vector<T> Multiply(const T* xdata, unsigned xrows, unsigned xcols, const T* ydata, unsigned yrows, unsigned ycols) {
|
||||||
inline vector<T> Multiply(const T *xdata, unsigned xrows, unsigned xcols, const T *ydata, unsigned yrows, unsigned ycols) {
|
|
||||||
vector<T> output;
|
vector<T> output;
|
||||||
output.resize(xrows * ycols);
|
output.resize(xrows * ycols);
|
||||||
Multiply(output.data(), xdata, xrows, xcols, ydata, yrows, ycols);
|
Multiply(output.data(), xdata, xrows, xcols, ydata, yrows, ycols);
|
||||||
|
|
|
@ -5,25 +5,25 @@ namespace mosaic {
|
||||||
|
|
||||||
struct bitstream {
|
struct bitstream {
|
||||||
filemap fp;
|
filemap fp;
|
||||||
uint8_t *data;
|
uint8_t* data = nullptr;
|
||||||
unsigned size;
|
unsigned size = 0;
|
||||||
bool readonly;
|
bool readonly = false;
|
||||||
bool endian;
|
bool endian = 1;
|
||||||
|
|
||||||
inline bool read(uint64_t addr) const {
|
bool read(uint64_t addr) const {
|
||||||
if(data == nullptr || (addr >> 3) >= size) return 0;
|
if(data == nullptr || (addr >> 3) >= size) return 0;
|
||||||
unsigned mask = endian == 0 ? (0x01 << (addr & 7)) : (0x80 >> (addr & 7));
|
unsigned mask = endian == 0 ? (0x01 << (addr & 7)) : (0x80 >> (addr & 7));
|
||||||
return data[addr >> 3] & mask;
|
return data[addr >> 3] & mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void write(uint64_t addr, bool value) {
|
void write(uint64_t addr, bool value) {
|
||||||
if(data == nullptr || readonly == true || (addr >> 3) >= size) return;
|
if(data == nullptr || readonly == true || (addr >> 3) >= size) return;
|
||||||
unsigned mask = endian == 0 ? (0x01 << (addr & 7)) : (0x80 >> (addr & 7));
|
unsigned mask = endian == 0 ? (0x01 << (addr & 7)) : (0x80 >> (addr & 7));
|
||||||
if(value == 0) data[addr >> 3] &= ~mask;
|
if(value == 0) data[addr >> 3] &= ~mask;
|
||||||
if(value == 1) data[addr >> 3] |= mask;
|
if(value == 1) data[addr >> 3] |= mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool open(const string &filename) {
|
bool open(const string& filename) {
|
||||||
readonly = false;
|
readonly = false;
|
||||||
if(fp.open(filename, filemap::mode::readwrite) == false) {
|
if(fp.open(filename, filemap::mode::readwrite) == false) {
|
||||||
readonly = true;
|
readonly = true;
|
||||||
|
@ -36,15 +36,15 @@ struct bitstream {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void close() {
|
void close() {
|
||||||
fp.close();
|
fp.close();
|
||||||
data = nullptr;
|
data = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bitstream() : data(nullptr), endian(1) {
|
bitstream() {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline ~bitstream() {
|
~bitstream() {
|
||||||
close();
|
close();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -36,9 +36,9 @@ struct context {
|
||||||
unsigned paddingColor;
|
unsigned paddingColor;
|
||||||
vector<unsigned> palette;
|
vector<unsigned> palette;
|
||||||
|
|
||||||
inline unsigned objectWidth() const { return blockWidth * tileWidth * mosaicWidth + paddingWidth; }
|
unsigned objectWidth() const { return blockWidth * tileWidth * mosaicWidth + paddingWidth; }
|
||||||
inline unsigned objectHeight() const { return blockHeight * tileHeight * mosaicHeight + paddingHeight; }
|
unsigned objectHeight() const { return blockHeight * tileHeight * mosaicHeight + paddingHeight; }
|
||||||
inline unsigned objectSize() const {
|
unsigned objectSize() const {
|
||||||
unsigned size = blockStride * tileWidth * tileHeight * mosaicWidth * mosaicHeight
|
unsigned size = blockStride * tileWidth * tileHeight * mosaicWidth * mosaicHeight
|
||||||
+ blockOffset * tileHeight * mosaicWidth * mosaicHeight
|
+ blockOffset * tileHeight * mosaicWidth * mosaicHeight
|
||||||
+ tileStride * mosaicWidth * mosaicHeight
|
+ tileStride * mosaicWidth * mosaicHeight
|
||||||
|
@ -46,23 +46,23 @@ struct context {
|
||||||
return max(1u, size);
|
return max(1u, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline unsigned eval(const string &expression) {
|
unsigned eval(const string& expression) {
|
||||||
intmax_t result;
|
intmax_t result;
|
||||||
if(fixedpoint::eval(expression, result) == false) return 0u;
|
if(fixedpoint::eval(expression, result) == false) return 0u;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void eval(vector<unsigned> &buffer, const string &expression_) {
|
void eval(vector<unsigned>& buffer, const string& expression_) {
|
||||||
string expression = expression_;
|
string expression = expression_;
|
||||||
bool function = false;
|
bool function = false;
|
||||||
for(auto &c : expression) {
|
for(auto& c : expression) {
|
||||||
if(c == '(') function = true;
|
if(c == '(') function = true;
|
||||||
if(c == ')') function = false;
|
if(c == ')') function = false;
|
||||||
if(c == ',' && function == true) c = ';';
|
if(c == ',' && function == true) c = ';';
|
||||||
}
|
}
|
||||||
|
|
||||||
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.wildcard("f(?*) ?*")) {
|
||||||
item.ltrim<1>("f(");
|
item.ltrim<1>("f(");
|
||||||
|
@ -95,7 +95,7 @@ struct context {
|
||||||
item = part(1, "");
|
item = part(1, "");
|
||||||
}
|
}
|
||||||
item.trim();
|
item.trim();
|
||||||
for(auto &c : item) {
|
for(auto& c : item) {
|
||||||
if(c >= 'A' && c <= 'Z') buffer.append(offset + c - 'A' + 0);
|
if(c >= 'A' && c <= 'Z') buffer.append(offset + c - 'A' + 0);
|
||||||
if(c >= 'a' && c <= 'z') buffer.append(offset + c - 'a' + 26);
|
if(c >= 'a' && c <= 'z') buffer.append(offset + c - 'a' + 26);
|
||||||
if(c >= '0' && c <= '9') buffer.append(offset + c - '0' + 52);
|
if(c >= '0' && c <= '9') buffer.append(offset + c - '0' + 52);
|
||||||
|
@ -112,11 +112,11 @@ struct context {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void parse(const string &data) {
|
void parse(const string& data) {
|
||||||
reset();
|
reset();
|
||||||
|
|
||||||
lstring lines = data.split("\n");
|
lstring lines = data.split("\n");
|
||||||
for(auto &line : lines) {
|
for(auto& line : lines) {
|
||||||
lstring part = line.split<1>(":");
|
lstring part = line.split<1>(":");
|
||||||
if(part.size() != 2) continue;
|
if(part.size() != 2) continue;
|
||||||
part[0].trim();
|
part[0].trim();
|
||||||
|
@ -158,14 +158,14 @@ struct context {
|
||||||
sanitize();
|
sanitize();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool load(const string &filename) {
|
bool load(const string& filename) {
|
||||||
string filedata;
|
string filedata;
|
||||||
if(filedata.readfile(filename) == false) return false;
|
if(filedata.readfile(filename) == false) return false;
|
||||||
parse(filedata);
|
parse(filedata);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void sanitize() {
|
void sanitize() {
|
||||||
if(depth < 1) depth = 1;
|
if(depth < 1) depth = 1;
|
||||||
if(depth > 24) depth = 24;
|
if(depth > 24) depth = 24;
|
||||||
|
|
||||||
|
@ -179,7 +179,7 @@ struct context {
|
||||||
if(mosaicHeight < 1) mosaicHeight = 1;
|
if(mosaicHeight < 1) mosaicHeight = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void reset() {
|
void reset() {
|
||||||
offset = 0;
|
offset = 0;
|
||||||
width = 0;
|
width = 0;
|
||||||
height = 0;
|
height = 0;
|
||||||
|
@ -213,7 +213,7 @@ struct context {
|
||||||
palette.reset();
|
palette.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline context() {
|
context() {
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -7,14 +7,14 @@ struct parser {
|
||||||
image canvas;
|
image canvas;
|
||||||
|
|
||||||
//export from bitstream to canvas
|
//export from bitstream to canvas
|
||||||
inline void load(bitstream &stream, uint64_t offset, context &ctx, unsigned width, unsigned height) {
|
void load(bitstream& stream, uint64_t offset, context& ctx, unsigned width, unsigned height) {
|
||||||
canvas.allocate(width, height);
|
canvas.allocate(width, height);
|
||||||
canvas.clear(ctx.paddingColor);
|
canvas.clear(ctx.paddingColor);
|
||||||
parse(1, stream, offset, ctx, width, height);
|
parse(1, stream, offset, ctx, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
//import from canvas to bitstream
|
//import from canvas to bitstream
|
||||||
inline bool save(bitstream &stream, uint64_t offset, context &ctx) {
|
bool save(bitstream& stream, uint64_t offset, context& ctx) {
|
||||||
if(stream.readonly) return false;
|
if(stream.readonly) return false;
|
||||||
parse(0, stream, offset, ctx, canvas.width, canvas.height);
|
parse(0, stream, offset, ctx, canvas.width, canvas.height);
|
||||||
return true;
|
return true;
|
||||||
|
@ -24,21 +24,21 @@ struct parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
inline uint32_t read(unsigned x, unsigned y) const {
|
uint32_t read(unsigned x, unsigned y) const {
|
||||||
unsigned addr = y * canvas.width + x;
|
unsigned addr = y * canvas.width + x;
|
||||||
if(addr >= canvas.width * canvas.height) return 0u;
|
if(addr >= canvas.width * canvas.height) return 0u;
|
||||||
uint32_t *buffer = (uint32_t*)canvas.data;
|
uint32_t *buffer = (uint32_t*)canvas.data;
|
||||||
return buffer[addr];
|
return buffer[addr];
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void write(unsigned x, unsigned y, uint32_t data) {
|
void write(unsigned x, unsigned y, uint32_t data) {
|
||||||
unsigned addr = y * canvas.width + x;
|
unsigned addr = y * canvas.width + x;
|
||||||
if(addr >= canvas.width * canvas.height) return;
|
if(addr >= canvas.width * canvas.height) return;
|
||||||
uint32_t *buffer = (uint32_t*)canvas.data;
|
uint32_t *buffer = (uint32_t*)canvas.data;
|
||||||
buffer[addr] = data;
|
buffer[addr] = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void parse(bool load, bitstream &stream, uint64_t offset, context &ctx, unsigned width, unsigned height) {
|
void parse(bool load, bitstream& stream, uint64_t offset, context& ctx, unsigned width, unsigned height) {
|
||||||
stream.endian = ctx.endian;
|
stream.endian = ctx.endian;
|
||||||
unsigned canvasWidth = width / (ctx.mosaicWidth * ctx.tileWidth * ctx.blockWidth + ctx.paddingWidth);
|
unsigned canvasWidth = width / (ctx.mosaicWidth * ctx.tileWidth * ctx.blockWidth + ctx.paddingWidth);
|
||||||
unsigned canvasHeight = height / (ctx.mosaicHeight * ctx.tileHeight * ctx.blockHeight + ctx.paddingHeight);
|
unsigned canvasHeight = height / (ctx.mosaicHeight * ctx.tileHeight * ctx.blockHeight + ctx.paddingHeight);
|
||||||
|
|
|
@ -35,6 +35,7 @@
|
||||||
#include <nall/property.hpp>
|
#include <nall/property.hpp>
|
||||||
#include <nall/random.hpp>
|
#include <nall/random.hpp>
|
||||||
#include <nall/serializer.hpp>
|
#include <nall/serializer.hpp>
|
||||||
|
#include <nall/set.hpp>
|
||||||
#include <nall/sha256.hpp>
|
#include <nall/sha256.hpp>
|
||||||
#include <nall/sort.hpp>
|
#include <nall/sort.hpp>
|
||||||
#include <nall/stdint.hpp>
|
#include <nall/stdint.hpp>
|
||||||
|
|
|
@ -10,16 +10,16 @@
|
||||||
namespace nall {
|
namespace nall {
|
||||||
|
|
||||||
struct png {
|
struct png {
|
||||||
//colorType:
|
|
||||||
//0 = L
|
|
||||||
//2 = R,G,B
|
|
||||||
//3 = P
|
|
||||||
//4 = L,A
|
|
||||||
//6 = R,G,B,A
|
|
||||||
struct Info {
|
struct Info {
|
||||||
unsigned width;
|
unsigned width;
|
||||||
unsigned height;
|
unsigned height;
|
||||||
unsigned bitDepth;
|
unsigned bitDepth;
|
||||||
|
//colorType:
|
||||||
|
//0 = L (luma)
|
||||||
|
//2 = R,G,B
|
||||||
|
//3 = P (palette)
|
||||||
|
//4 = L,A
|
||||||
|
//6 = R,G,B,A
|
||||||
unsigned colorType;
|
unsigned colorType;
|
||||||
unsigned compressionMethod;
|
unsigned compressionMethod;
|
||||||
unsigned filterType;
|
unsigned filterType;
|
||||||
|
@ -31,13 +31,13 @@ struct png {
|
||||||
uint8_t palette[256][3];
|
uint8_t palette[256][3];
|
||||||
} info;
|
} info;
|
||||||
|
|
||||||
uint8_t *data;
|
uint8_t* data = nullptr;
|
||||||
unsigned size;
|
unsigned size = 0;
|
||||||
|
|
||||||
inline bool decode(const string &filename);
|
inline bool decode(const string& filename);
|
||||||
inline bool decode(const uint8_t *sourceData, unsigned sourceSize);
|
inline bool decode(const uint8_t* sourceData, unsigned sourceSize);
|
||||||
inline unsigned readbits(const uint8_t *&data);
|
inline unsigned readbits(const uint8_t*& data);
|
||||||
unsigned bitpos;
|
unsigned bitpos = 0;
|
||||||
|
|
||||||
inline png();
|
inline png();
|
||||||
inline ~png();
|
inline ~png();
|
||||||
|
@ -52,24 +52,24 @@ protected:
|
||||||
|
|
||||||
inline unsigned interlace(unsigned pass, unsigned index);
|
inline unsigned interlace(unsigned pass, unsigned index);
|
||||||
inline unsigned inflateSize();
|
inline unsigned inflateSize();
|
||||||
inline bool deinterlace(const uint8_t *&inputData, unsigned pass);
|
inline bool deinterlace(const uint8_t*& inputData, unsigned pass);
|
||||||
inline bool filter(uint8_t *outputData, const uint8_t *inputData, unsigned width, unsigned height);
|
inline bool filter(uint8_t* outputData, const uint8_t* inputData, unsigned width, unsigned height);
|
||||||
inline unsigned read(const uint8_t *data, unsigned length);
|
inline unsigned read(const uint8_t* data, unsigned length);
|
||||||
};
|
};
|
||||||
|
|
||||||
bool png::decode(const string &filename) {
|
bool png::decode(const string& filename) {
|
||||||
if(auto memory = file::read(filename)) {
|
if(auto memory = file::read(filename)) {
|
||||||
return decode(memory.data(), memory.size());
|
return decode(memory.data(), memory.size());
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool png::decode(const uint8_t *sourceData, unsigned sourceSize) {
|
bool png::decode(const uint8_t* sourceData, unsigned sourceSize) {
|
||||||
if(sourceSize < 8) return false;
|
if(sourceSize < 8) return false;
|
||||||
if(read(sourceData + 0, 4) != 0x89504e47) return false;
|
if(read(sourceData + 0, 4) != 0x89504e47) return false;
|
||||||
if(read(sourceData + 4, 4) != 0x0d0a1a0a) return false;
|
if(read(sourceData + 4, 4) != 0x0d0a1a0a) return false;
|
||||||
|
|
||||||
uint8_t *compressedData = nullptr;
|
uint8_t* compressedData = nullptr;
|
||||||
unsigned compressedSize = 0;
|
unsigned compressedSize = 0;
|
||||||
|
|
||||||
unsigned offset = 8;
|
unsigned offset = 8;
|
||||||
|
@ -102,8 +102,9 @@ bool png::decode(const uint8_t *sourceData, unsigned sourceSize) {
|
||||||
default: return false;
|
default: return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(info.colorType == 2 || info.colorType == 4 || info.colorType == 6)
|
if(info.colorType == 2 || info.colorType == 4 || info.colorType == 6) {
|
||||||
if(info.bitDepth != 8 && info.bitDepth != 16) return false;
|
if(info.bitDepth != 8 && info.bitDepth != 16) return false;
|
||||||
|
}
|
||||||
if(info.colorType == 3 && info.bitDepth == 16) return false;
|
if(info.colorType == 3 && info.bitDepth == 16) return false;
|
||||||
|
|
||||||
info.bytesPerPixel = (info.bytesPerPixel + 7) / 8;
|
info.bytesPerPixel = (info.bytesPerPixel + 7) / 8;
|
||||||
|
@ -200,7 +201,7 @@ unsigned png::inflateSize() {
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool png::deinterlace(const uint8_t *&inputData, unsigned pass) {
|
bool png::deinterlace(const uint8_t*& inputData, unsigned pass) {
|
||||||
unsigned xd = interlace(pass, 0), yd = interlace(pass, 1);
|
unsigned xd = interlace(pass, 0), yd = interlace(pass, 1);
|
||||||
unsigned xo = interlace(pass, 2), yo = interlace(pass, 3);
|
unsigned xo = interlace(pass, 2), yo = interlace(pass, 3);
|
||||||
unsigned width = (info.width + (xd - xo - 1)) / xd;
|
unsigned width = (info.width + (xd - xo - 1)) / xd;
|
||||||
|
@ -208,12 +209,12 @@ bool png::deinterlace(const uint8_t *&inputData, unsigned pass) {
|
||||||
if(width == 0 || height == 0) return true;
|
if(width == 0 || height == 0) return true;
|
||||||
|
|
||||||
unsigned outputSize = width * height * info.bytesPerPixel;
|
unsigned outputSize = width * height * info.bytesPerPixel;
|
||||||
uint8_t *outputData = new uint8_t[outputSize];
|
uint8_t* outputData = new uint8_t[outputSize];
|
||||||
bool result = filter(outputData, inputData, width, height);
|
bool result = filter(outputData, inputData, width, height);
|
||||||
|
|
||||||
const uint8_t *rd = outputData;
|
const uint8_t* rd = outputData;
|
||||||
for(unsigned y = yo; y < info.height; y += yd) {
|
for(unsigned y = yo; y < info.height; y += yd) {
|
||||||
uint8_t *wr = data + y * info.pitch;
|
uint8_t* wr = data + y * info.pitch;
|
||||||
for(unsigned x = xo; x < info.width; x += xd) {
|
for(unsigned x = xo; x < info.width; x += xd) {
|
||||||
for(unsigned b = 0; b < info.bytesPerPixel; b++) {
|
for(unsigned b = 0; b < info.bytesPerPixel; b++) {
|
||||||
wr[x * info.bytesPerPixel + b] = *rd++;
|
wr[x * info.bytesPerPixel + b] = *rd++;
|
||||||
|
@ -226,9 +227,9 @@ bool png::deinterlace(const uint8_t *&inputData, unsigned pass) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool png::filter(uint8_t *outputData, const uint8_t *inputData, unsigned width, unsigned height) {
|
bool png::filter(uint8_t* outputData, const uint8_t* inputData, unsigned width, unsigned height) {
|
||||||
uint8_t *wr = outputData;
|
uint8_t* wr = outputData;
|
||||||
const uint8_t *rd = inputData;
|
const uint8_t* rd = inputData;
|
||||||
int bpp = info.bytesPerPixel, pitch = width * bpp;
|
int bpp = info.bytesPerPixel, pitch = width * bpp;
|
||||||
for(int y = 0; y < height; y++) {
|
for(int y = 0; y < height; y++) {
|
||||||
uint8_t filter = *rd++;
|
uint8_t filter = *rd++;
|
||||||
|
@ -289,13 +290,13 @@ bool png::filter(uint8_t *outputData, const uint8_t *inputData, unsigned width,
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned png::read(const uint8_t *data, unsigned length) {
|
unsigned png::read(const uint8_t* data, unsigned length) {
|
||||||
unsigned result = 0;
|
unsigned result = 0;
|
||||||
while(length--) result = (result << 8) | (*data++);
|
while(length--) result = (result << 8) | (*data++);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned png::readbits(const uint8_t *&data) {
|
unsigned png::readbits(const uint8_t*& data) {
|
||||||
unsigned result = 0;
|
unsigned result = 0;
|
||||||
switch(info.bitDepth) {
|
switch(info.bitDepth) {
|
||||||
case 1:
|
case 1:
|
||||||
|
@ -324,8 +325,7 @@ unsigned png::readbits(const uint8_t *&data) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
png::png() : data(nullptr) {
|
png::png() {
|
||||||
bitpos = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
png::~png() {
|
png::~png() {
|
||||||
|
|
|
@ -7,103 +7,104 @@
|
||||||
#include <nall/utility.hpp>
|
#include <nall/utility.hpp>
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
template<typename type_t> void priority_queue_nocallback(type_t) {}
|
|
||||||
|
|
||||||
//priority queue implementation using binary min-heap array;
|
template<typename type_t> void priority_queue_nocallback(type_t) {}
|
||||||
//does not require normalize() function.
|
|
||||||
//O(1) find (tick)
|
//priority queue implementation using binary min-heap array;
|
||||||
//O(log n) append (enqueue)
|
//does not require normalize() function.
|
||||||
//O(log n) remove (dequeue)
|
//O(1) find (tick)
|
||||||
template<typename type_t> class priority_queue {
|
//O(log n) append (enqueue)
|
||||||
public:
|
//O(log n) remove (dequeue)
|
||||||
inline void tick(unsigned ticks) {
|
template<typename type_t> struct priority_queue {
|
||||||
basecounter += ticks;
|
inline void tick(unsigned ticks) {
|
||||||
while(heapsize && gte(basecounter, heap[0].counter)) callback(dequeue());
|
basecounter += ticks;
|
||||||
|
while(heapsize && gte(basecounter, heap[0].counter)) callback(dequeue());
|
||||||
|
}
|
||||||
|
|
||||||
|
//counter is relative to current time (eg enqueue(64, ...) fires in 64 ticks);
|
||||||
|
//counter cannot exceed std::numeric_limits<unsigned>::max() >> 1.
|
||||||
|
void enqueue(unsigned counter, type_t event) {
|
||||||
|
unsigned child = heapsize++;
|
||||||
|
counter += basecounter;
|
||||||
|
|
||||||
|
while(child) {
|
||||||
|
unsigned parent = (child - 1) >> 1;
|
||||||
|
if(gte(counter, heap[parent].counter)) break;
|
||||||
|
|
||||||
|
heap[child].counter = heap[parent].counter;
|
||||||
|
heap[child].event = heap[parent].event;
|
||||||
|
child = parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
//counter is relative to current time (eg enqueue(64, ...) fires in 64 ticks);
|
heap[child].counter = counter;
|
||||||
//counter cannot exceed std::numeric_limits<unsigned>::max() >> 1.
|
heap[child].event = event;
|
||||||
void enqueue(unsigned counter, type_t event) {
|
}
|
||||||
unsigned child = heapsize++;
|
|
||||||
counter += basecounter;
|
|
||||||
|
|
||||||
while(child) {
|
type_t dequeue() {
|
||||||
unsigned parent = (child - 1) >> 1;
|
type_t event(heap[0].event);
|
||||||
if(gte(counter, heap[parent].counter)) break;
|
unsigned parent = 0;
|
||||||
|
unsigned counter = heap[--heapsize].counter;
|
||||||
|
|
||||||
heap[child].counter = heap[parent].counter;
|
while(true) {
|
||||||
heap[child].event = heap[parent].event;
|
unsigned child = (parent << 1) + 1;
|
||||||
child = parent;
|
if(child >= heapsize) break;
|
||||||
}
|
if(child + 1 < heapsize && gte(heap[child].counter, heap[child + 1].counter)) child++;
|
||||||
|
if(gte(heap[child].counter, counter)) break;
|
||||||
|
|
||||||
heap[child].counter = counter;
|
heap[parent].counter = heap[child].counter;
|
||||||
heap[child].event = event;
|
heap[parent].event = heap[child].event;
|
||||||
|
parent = child;
|
||||||
}
|
}
|
||||||
|
|
||||||
type_t dequeue() {
|
heap[parent].counter = counter;
|
||||||
type_t event(heap[0].event);
|
heap[parent].event = heap[heapsize].event;
|
||||||
unsigned parent = 0;
|
return event;
|
||||||
unsigned counter = heap[--heapsize].counter;
|
}
|
||||||
|
|
||||||
while(true) {
|
void reset() {
|
||||||
unsigned child = (parent << 1) + 1;
|
basecounter = 0;
|
||||||
if(child >= heapsize) break;
|
heapsize = 0;
|
||||||
if(child + 1 < heapsize && gte(heap[child].counter, heap[child + 1].counter)) child++;
|
}
|
||||||
if(gte(heap[child].counter, counter)) break;
|
|
||||||
|
|
||||||
heap[parent].counter = heap[child].counter;
|
void serialize(serializer& s) {
|
||||||
heap[parent].event = heap[child].event;
|
s.integer(basecounter);
|
||||||
parent = child;
|
s.integer(heapsize);
|
||||||
}
|
for(unsigned n = 0; n < heapcapacity; n++) {
|
||||||
|
s.integer(heap[n].counter);
|
||||||
heap[parent].counter = counter;
|
s.integer(heap[n].event);
|
||||||
heap[parent].event = heap[heapsize].event;
|
|
||||||
return event;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void reset() {
|
priority_queue(unsigned size, function<void (type_t)> callback = &priority_queue_nocallback<type_t>)
|
||||||
basecounter = 0;
|
: callback(callback) {
|
||||||
heapsize = 0;
|
heap = new heap_t[size];
|
||||||
}
|
heapcapacity = size;
|
||||||
|
reset();
|
||||||
|
}
|
||||||
|
|
||||||
void serialize(serializer &s) {
|
~priority_queue() {
|
||||||
s.integer(basecounter);
|
delete[] heap;
|
||||||
s.integer(heapsize);
|
}
|
||||||
for(unsigned n = 0; n < heapcapacity; n++) {
|
|
||||||
s.integer(heap[n].counter);
|
|
||||||
s.integer(heap[n].event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
priority_queue(unsigned size, function<void (type_t)> callback_ = &priority_queue_nocallback<type_t>)
|
priority_queue& operator=(const priority_queue&) = delete;
|
||||||
: callback(callback_) {
|
priority_queue(const priority_queue&) = delete;
|
||||||
heap = new heap_t[size];
|
|
||||||
heapcapacity = size;
|
|
||||||
reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
~priority_queue() {
|
private:
|
||||||
delete[] heap;
|
function<void (type_t)> callback;
|
||||||
}
|
unsigned basecounter;
|
||||||
|
unsigned heapsize;
|
||||||
|
unsigned heapcapacity;
|
||||||
|
struct heap_t {
|
||||||
|
unsigned counter;
|
||||||
|
type_t event;
|
||||||
|
} *heap;
|
||||||
|
|
||||||
priority_queue& operator=(const priority_queue&) = delete;
|
//return true if x is greater than or equal to y
|
||||||
priority_queue(const priority_queue&) = delete;
|
inline bool gte(unsigned x, unsigned y) {
|
||||||
|
return x - y < (std::numeric_limits<unsigned>::max() >> 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
|
||||||
function<void (type_t)> callback;
|
|
||||||
unsigned basecounter;
|
|
||||||
unsigned heapsize;
|
|
||||||
unsigned heapcapacity;
|
|
||||||
struct heap_t {
|
|
||||||
unsigned counter;
|
|
||||||
type_t event;
|
|
||||||
} *heap;
|
|
||||||
|
|
||||||
//return true if x is greater than or equal to y
|
|
||||||
inline bool gte(unsigned x, unsigned y) {
|
|
||||||
return x - y < (std::numeric_limits<unsigned>::max() >> 1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,83 +1,44 @@
|
||||||
#ifndef NALL_PROPERTY_HPP
|
#ifndef NALL_PROPERTY_HPP
|
||||||
#define NALL_PROPERTY_HPP
|
#define NALL_PROPERTY_HPP
|
||||||
|
|
||||||
//nall::property implements ownership semantics into container classes
|
|
||||||
//example: property<owner>::readonly<type> implies that only owner has full
|
|
||||||
//access to type; and all other code has readonly access.
|
|
||||||
//
|
|
||||||
//property can be used either of two ways:
|
|
||||||
//struct foo {
|
|
||||||
// property<foo>::readonly<bool> x;
|
|
||||||
// property<foo>::readwrite<int> y;
|
|
||||||
//};
|
|
||||||
//-or-
|
|
||||||
//struct foo : property<foo> {
|
|
||||||
// readonly<bool> x;
|
|
||||||
// readwrite<int> y;
|
|
||||||
//};
|
|
||||||
|
|
||||||
//return types are const T& (byref) instead of T (byval) to avoid major speed
|
|
||||||
//penalties for objects with expensive copy constructors
|
|
||||||
|
|
||||||
//operator-> provides access to underlying object type:
|
|
||||||
//readonly<Object> foo;
|
|
||||||
//foo->bar();
|
|
||||||
//... will call Object::bar();
|
|
||||||
|
|
||||||
//operator='s reference is constant so as to avoid leaking a reference handle
|
|
||||||
//that could bypass access restrictions
|
|
||||||
|
|
||||||
//both constant and non-constant operators are provided, though it may be
|
|
||||||
//necessary to cast first, for instance:
|
|
||||||
//struct foo : property<foo> { readonly<int> bar; } object;
|
|
||||||
//int main() { int value = const_cast<const foo&>(object); }
|
|
||||||
|
|
||||||
//writeonly is useful for objects that have non-const reads, but const writes.
|
|
||||||
//however, to avoid leaking handles, the interface is very restricted. the only
|
|
||||||
//way to write is via operator=, which requires conversion via eg copy
|
|
||||||
//constructor. example:
|
|
||||||
//struct foo {
|
|
||||||
// foo(bool value) { ... }
|
|
||||||
//};
|
|
||||||
//writeonly<foo> bar;
|
|
||||||
//bar = true;
|
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
template<typename C> struct property {
|
|
||||||
template<typename T> struct readonly {
|
|
||||||
const T* operator->() const { return &value; }
|
|
||||||
const T& operator()() const { return value; }
|
|
||||||
operator const T&() const { return value; }
|
|
||||||
private:
|
|
||||||
T* operator->() { return &value; }
|
|
||||||
operator T&() { return value; }
|
|
||||||
const T& operator=(const T& value_) { return value = value_; }
|
|
||||||
T value;
|
|
||||||
friend C;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T> struct writeonly {
|
template<typename C> struct property {
|
||||||
void operator=(const T& value_) { value = value_; }
|
template<typename T> struct readonly {
|
||||||
private:
|
const T* operator->() const { return &value; }
|
||||||
const T* operator->() const { return &value; }
|
const T& operator()() const { return value; }
|
||||||
const T& operator()() const { return value; }
|
operator const T&() const { return value; }
|
||||||
operator const T&() const { return value; }
|
private:
|
||||||
T* operator->() { return &value; }
|
T* operator->() { return &value; }
|
||||||
operator T&() { return value; }
|
operator T&() { return value; }
|
||||||
T value;
|
const T& operator=(const T& value_) { return value = value_; }
|
||||||
friend C;
|
T value;
|
||||||
};
|
friend C;
|
||||||
|
|
||||||
template<typename T> struct readwrite {
|
|
||||||
const T* operator->() const { return &value; }
|
|
||||||
const T& operator()() const { return value; }
|
|
||||||
operator const T&() const { return value; }
|
|
||||||
T* operator->() { return &value; }
|
|
||||||
operator T&() { return value; }
|
|
||||||
const T& operator=(const T& value_) { return value = value_; }
|
|
||||||
T value;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
template<typename T> struct writeonly {
|
||||||
|
void operator=(const T& value_) { value = value_; }
|
||||||
|
private:
|
||||||
|
const T* operator->() const { return &value; }
|
||||||
|
const T& operator()() const { return value; }
|
||||||
|
operator const T&() const { return value; }
|
||||||
|
T* operator->() { return &value; }
|
||||||
|
operator T&() { return value; }
|
||||||
|
T value;
|
||||||
|
friend C;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T> struct readwrite {
|
||||||
|
const T* operator->() const { return &value; }
|
||||||
|
const T& operator()() const { return value; }
|
||||||
|
operator const T&() const { return value; }
|
||||||
|
T* operator->() { return &value; }
|
||||||
|
operator T&() { return value; }
|
||||||
|
const T& operator=(const T& value_) { return value = value_; }
|
||||||
|
T value;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -14,19 +14,21 @@
|
||||||
//Class::Reference may be a function, object or variable
|
//Class::Reference may be a function, object or variable
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
template<typename T, typename T::type... P> struct public_cast;
|
|
||||||
|
|
||||||
template<typename T> struct public_cast<T> {
|
template<typename T, typename T::type... P> struct public_cast;
|
||||||
static typename T::type value;
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename T> typename T::type public_cast<T>::value;
|
template<typename T> struct public_cast<T> {
|
||||||
|
static typename T::type value;
|
||||||
|
};
|
||||||
|
|
||||||
template<typename T, typename T::type P> struct public_cast<T, P> {
|
template<typename T> typename T::type public_cast<T>::value;
|
||||||
static typename T::type value;
|
|
||||||
};
|
template<typename T, typename T::type P> struct public_cast<T, P> {
|
||||||
|
static typename T::type value;
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename T, typename T::type P> typename T::type public_cast<T, P>::value = public_cast<T>::value = P;
|
||||||
|
|
||||||
template<typename T, typename T::type P> typename T::type public_cast<T, P>::value = public_cast<T>::value = P;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,28 +1,32 @@
|
||||||
#ifndef NALL_RANDOM_HPP
|
#ifndef NALL_RANDOM_HPP
|
||||||
#define NALL_RANDOM_HPP
|
#define NALL_RANDOM_HPP
|
||||||
|
|
||||||
|
//pseudo-random number generator
|
||||||
|
//very low-quality, but very fast (based on CRC32 polynomial)
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
//pseudo-random number generator
|
|
||||||
inline unsigned prng() {
|
inline unsigned prng() {
|
||||||
static unsigned n = 0;
|
static unsigned n = 0;
|
||||||
return n = (n >> 1) ^ (((n & 1) - 1) & 0xedb88320);
|
return n = (n >> 1) ^ (((n & 1) - 1) & 0xedb88320);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct random_lfsr {
|
||||||
|
inline void seed(unsigned seed__) {
|
||||||
|
seed_ = seed__;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct random_lfsr {
|
inline unsigned operator()() {
|
||||||
inline void seed(unsigned seed__) {
|
return seed_ = (seed_ >> 1) ^ (((seed_ & 1) - 1) & 0xedb88320);
|
||||||
seed_ = seed__;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
inline unsigned operator()() {
|
random_lfsr() : seed_(0) {
|
||||||
return seed_ = (seed_ >> 1) ^ (((seed_ & 1) - 1) & 0xedb88320);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
random_lfsr() : seed_(0) {
|
private:
|
||||||
}
|
unsigned seed_;
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
|
||||||
unsigned seed_;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,110 +1,118 @@
|
||||||
#ifndef NALL_SERIAL_HPP
|
#ifndef NALL_SERIAL_HPP
|
||||||
#define NALL_SERIAL_HPP
|
#define NALL_SERIAL_HPP
|
||||||
|
|
||||||
|
#include <nall/intrinsics.hpp>
|
||||||
|
#include <nall/stdint.hpp>
|
||||||
|
#include <nall/string.hpp>
|
||||||
|
|
||||||
|
#if !defined(PLATFORM_X) && !defined(PLATFORM_OSX)
|
||||||
|
#error "nall/serial: unsupported platform"
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <nall/stdint.hpp>
|
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
struct serial {
|
|
||||||
bool readable() {
|
struct serial {
|
||||||
if(port_open == false) return false;
|
bool readable() {
|
||||||
fd_set fdset;
|
if(port_open == false) return false;
|
||||||
FD_ZERO(&fdset);
|
fd_set fdset;
|
||||||
FD_SET(port, &fdset);
|
FD_ZERO(&fdset);
|
||||||
timeval timeout;
|
FD_SET(port, &fdset);
|
||||||
timeout.tv_sec = 0;
|
timeval timeout;
|
||||||
timeout.tv_usec = 0;
|
timeout.tv_sec = 0;
|
||||||
int result = select(FD_SETSIZE, &fdset, nullptr, nullptr, &timeout);
|
timeout.tv_usec = 0;
|
||||||
if(result < 1) return false;
|
int result = select(FD_SETSIZE, &fdset, nullptr, nullptr, &timeout);
|
||||||
return FD_ISSET(port, &fdset);
|
if(result < 1) return false;
|
||||||
|
return FD_ISSET(port, &fdset);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-1 on error, otherwise return bytes read
|
||||||
|
int read(uint8_t* data, unsigned length) {
|
||||||
|
if(port_open == false) return -1;
|
||||||
|
return ::read(port, (void*)data, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool writable() {
|
||||||
|
if(port_open == false) return false;
|
||||||
|
fd_set fdset;
|
||||||
|
FD_ZERO(&fdset);
|
||||||
|
FD_SET(port, &fdset);
|
||||||
|
timeval timeout;
|
||||||
|
timeout.tv_sec = 0;
|
||||||
|
timeout.tv_usec = 0;
|
||||||
|
int result = select(FD_SETSIZE, nullptr, &fdset, nullptr, &timeout);
|
||||||
|
if(result < 1) return false;
|
||||||
|
return FD_ISSET(port, &fdset);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-1 on error, otherwise return bytes written
|
||||||
|
int write(const uint8_t* data, unsigned length) {
|
||||||
|
if(port_open == false) return -1;
|
||||||
|
return ::write(port, (void*)data, length);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool open(const string& portname, unsigned rate, bool flowcontrol) {
|
||||||
|
close();
|
||||||
|
|
||||||
|
port = ::open(portname, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK);
|
||||||
|
if(port == -1) return false;
|
||||||
|
|
||||||
|
if(ioctl(port, TIOCEXCL) == -1) { close(); return false; }
|
||||||
|
if(fcntl(port, F_SETFL, 0) == -1) { close(); return false; }
|
||||||
|
if(tcgetattr(port, &original_attr) == -1) { close(); return false; }
|
||||||
|
|
||||||
|
termios attr = original_attr;
|
||||||
|
cfmakeraw(&attr);
|
||||||
|
cfsetspeed(&attr, rate);
|
||||||
|
|
||||||
|
attr.c_lflag &=~ (ECHO | ECHONL | ISIG | ICANON | IEXTEN);
|
||||||
|
attr.c_iflag &=~ (BRKINT | PARMRK | INPCK | ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXOFF | IXANY);
|
||||||
|
attr.c_iflag |= (IGNBRK | IGNPAR);
|
||||||
|
attr.c_oflag &=~ (OPOST);
|
||||||
|
attr.c_cflag &=~ (CSIZE | CSTOPB | PARENB | CLOCAL);
|
||||||
|
attr.c_cflag |= (CS8 | CREAD);
|
||||||
|
if(flowcontrol == false) {
|
||||||
|
attr.c_cflag &= ~CRTSCTS;
|
||||||
|
} else {
|
||||||
|
attr.c_cflag |= CRTSCTS;
|
||||||
}
|
}
|
||||||
|
attr.c_cc[VTIME] = attr.c_cc[VMIN] = 0;
|
||||||
|
|
||||||
//-1 on error, otherwise return bytes read
|
if(tcsetattr(port, TCSANOW, &attr) == -1) { close(); return false; }
|
||||||
int read(uint8_t *data, unsigned length) {
|
return port_open = true;
|
||||||
if(port_open == false) return -1;
|
}
|
||||||
return ::read(port, (void*)data, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool writable() {
|
void close() {
|
||||||
if(port_open == false) return false;
|
if(port != -1) {
|
||||||
fd_set fdset;
|
tcdrain(port);
|
||||||
FD_ZERO(&fdset);
|
if(port_open == true) {
|
||||||
FD_SET(port, &fdset);
|
tcsetattr(port, TCSANOW, &original_attr);
|
||||||
timeval timeout;
|
port_open = false;
|
||||||
timeout.tv_sec = 0;
|
|
||||||
timeout.tv_usec = 0;
|
|
||||||
int result = select(FD_SETSIZE, nullptr, &fdset, nullptr, &timeout);
|
|
||||||
if(result < 1) return false;
|
|
||||||
return FD_ISSET(port, &fdset);
|
|
||||||
}
|
|
||||||
|
|
||||||
//-1 on error, otherwise return bytes written
|
|
||||||
int write(const uint8_t *data, unsigned length) {
|
|
||||||
if(port_open == false) return -1;
|
|
||||||
return ::write(port, (void*)data, length);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool open(const char *portname, unsigned rate, bool flowcontrol) {
|
|
||||||
close();
|
|
||||||
|
|
||||||
port = ::open(portname, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK);
|
|
||||||
if(port == -1) return false;
|
|
||||||
|
|
||||||
if(ioctl(port, TIOCEXCL) == -1) { close(); return false; }
|
|
||||||
if(fcntl(port, F_SETFL, 0) == -1) { close(); return false; }
|
|
||||||
if(tcgetattr(port, &original_attr) == -1) { close(); return false; }
|
|
||||||
|
|
||||||
termios attr = original_attr;
|
|
||||||
cfmakeraw(&attr);
|
|
||||||
cfsetspeed(&attr, rate);
|
|
||||||
|
|
||||||
attr.c_lflag &=~ (ECHO | ECHONL | ISIG | ICANON | IEXTEN);
|
|
||||||
attr.c_iflag &=~ (BRKINT | PARMRK | INPCK | ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXOFF | IXANY);
|
|
||||||
attr.c_iflag |= (IGNBRK | IGNPAR);
|
|
||||||
attr.c_oflag &=~ (OPOST);
|
|
||||||
attr.c_cflag &=~ (CSIZE | CSTOPB | PARENB | CLOCAL);
|
|
||||||
attr.c_cflag |= (CS8 | CREAD);
|
|
||||||
if(flowcontrol == false) {
|
|
||||||
attr.c_cflag &= ~CRTSCTS;
|
|
||||||
} else {
|
|
||||||
attr.c_cflag |= CRTSCTS;
|
|
||||||
}
|
}
|
||||||
attr.c_cc[VTIME] = attr.c_cc[VMIN] = 0;
|
::close(port);
|
||||||
|
|
||||||
if(tcsetattr(port, TCSANOW, &attr) == -1) { close(); return false; }
|
|
||||||
return port_open = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void close() {
|
|
||||||
if(port != -1) {
|
|
||||||
tcdrain(port);
|
|
||||||
if(port_open == true) {
|
|
||||||
tcsetattr(port, TCSANOW, &original_attr);
|
|
||||||
port_open = false;
|
|
||||||
}
|
|
||||||
::close(port);
|
|
||||||
port = -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
serial() {
|
|
||||||
port = -1;
|
port = -1;
|
||||||
port_open = false;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
~serial() {
|
serial() {
|
||||||
close();
|
port = -1;
|
||||||
}
|
port_open = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
~serial() {
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
int port;
|
||||||
|
bool port_open;
|
||||||
|
termios original_attr;
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
|
||||||
int port;
|
|
||||||
bool port_open;
|
|
||||||
termios original_attr;
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,145 +1,141 @@
|
||||||
#ifndef NALL_SERIALIZER_HPP
|
#ifndef NALL_SERIALIZER_HPP
|
||||||
#define NALL_SERIALIZER_HPP
|
#define NALL_SERIALIZER_HPP
|
||||||
|
|
||||||
|
//serializer: a class designed to save and restore the state of classes.
|
||||||
|
//
|
||||||
|
//benefits:
|
||||||
|
//- data() will be portable in size (it is not necessary to specify type sizes.)
|
||||||
|
//- data() will be portable in endianness (always stored internally as little-endian.)
|
||||||
|
//- one serialize function can both save and restore class states.
|
||||||
|
//
|
||||||
|
//caveats:
|
||||||
|
//- only plain-old-data can be stored. complex classes must provide serialize(serializer&);
|
||||||
|
//- floating-point usage is not portable across platforms
|
||||||
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <nall/stdint.hpp>
|
#include <nall/stdint.hpp>
|
||||||
#include <nall/utility.hpp>
|
#include <nall/utility.hpp>
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
//serializer: a class designed to save and restore the state of classes.
|
|
||||||
//
|
|
||||||
//benefits:
|
|
||||||
//- data() will be portable in size (it is not necessary to specify type sizes.)
|
|
||||||
//- data() will be portable in endianness (always stored internally as little-endian.)
|
|
||||||
//- one serialize function can both save and restore class states.
|
|
||||||
//
|
|
||||||
//caveats:
|
|
||||||
//- only plain-old-data can be stored. complex classes must provide serialize(serializer&);
|
|
||||||
//- floating-point usage is not portable across platforms
|
|
||||||
|
|
||||||
class serializer {
|
struct serializer {
|
||||||
public:
|
enum mode_t { Load, Save, Size };
|
||||||
enum mode_t { Load, Save, Size };
|
|
||||||
|
|
||||||
mode_t mode() const {
|
mode_t mode() const {
|
||||||
return imode;
|
return imode;
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint8_t* data() const {
|
||||||
|
return idata;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned size() const {
|
||||||
|
return isize;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned capacity() const {
|
||||||
|
return icapacity;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T> void floatingpoint(T& value) {
|
||||||
|
enum { size = sizeof(T) };
|
||||||
|
//this is rather dangerous, and not cross-platform safe;
|
||||||
|
//but there is no standardized way to export FP-values
|
||||||
|
uint8_t* p = (uint8_t*)&value;
|
||||||
|
if(imode == Save) {
|
||||||
|
for(unsigned n = 0; n < size; n++) idata[isize++] = p[n];
|
||||||
|
} else if(imode == Load) {
|
||||||
|
for(unsigned n = 0; n < size; n++) p[n] = idata[isize++];
|
||||||
|
} else {
|
||||||
|
isize += size;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const uint8_t* data() const {
|
template<typename T> void integer(T& value) {
|
||||||
return idata;
|
enum { size = std::is_same<bool, T>::value ? 1 : sizeof(T) };
|
||||||
|
if(imode == Save) {
|
||||||
|
for(unsigned n = 0; n < size; n++) idata[isize++] = (uintmax_t)value >> (n << 3);
|
||||||
|
} else if(imode == Load) {
|
||||||
|
value = 0;
|
||||||
|
for(unsigned n = 0; n < size; n++) value |= (uintmax_t)idata[isize++] << (n << 3);
|
||||||
|
} else if(imode == Size) {
|
||||||
|
isize += size;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unsigned size() const {
|
template<typename T> void array(T& array) {
|
||||||
return isize;
|
enum { size = sizeof(T) / sizeof(typename std::remove_extent<T>::type) };
|
||||||
}
|
for(unsigned n = 0; n < size; n++) integer(array[n]);
|
||||||
|
}
|
||||||
|
|
||||||
unsigned capacity() const {
|
template<typename T> void array(T array, unsigned size) {
|
||||||
return icapacity;
|
for(unsigned n = 0; n < size; n++) integer(array[n]);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> void floatingpoint(T &value) {
|
//copy
|
||||||
enum { size = sizeof(T) };
|
serializer& operator=(const serializer& s) {
|
||||||
//this is rather dangerous, and not cross-platform safe;
|
if(idata) delete[] idata;
|
||||||
//but there is no standardized way to export FP-values
|
|
||||||
uint8_t *p = (uint8_t*)&value;
|
|
||||||
if(imode == Save) {
|
|
||||||
for(unsigned n = 0; n < size; n++) idata[isize++] = p[n];
|
|
||||||
} else if(imode == Load) {
|
|
||||||
for(unsigned n = 0; n < size; n++) p[n] = idata[isize++];
|
|
||||||
} else {
|
|
||||||
isize += size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T> void integer(T &value) {
|
imode = s.imode;
|
||||||
enum { size = std::is_same<bool, T>::value ? 1 : sizeof(T) };
|
idata = new uint8_t[s.icapacity];
|
||||||
if(imode == Save) {
|
isize = s.isize;
|
||||||
for(unsigned n = 0; n < size; n++) idata[isize++] = (uintmax_t)value >> (n << 3);
|
icapacity = s.icapacity;
|
||||||
} else if(imode == Load) {
|
|
||||||
value = 0;
|
|
||||||
for(unsigned n = 0; n < size; n++) value |= (uintmax_t)idata[isize++] << (n << 3);
|
|
||||||
} else if(imode == Size) {
|
|
||||||
isize += size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T> void array(T &array) {
|
memcpy(idata, s.idata, s.icapacity);
|
||||||
enum { size = sizeof(T) / sizeof(typename std::remove_extent<T>::type) };
|
return *this;
|
||||||
for(unsigned n = 0; n < size; n++) integer(array[n]);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
template<typename T> void array(T array, unsigned size) {
|
serializer(const serializer& s) {
|
||||||
for(unsigned n = 0; n < size; n++) integer(array[n]);
|
operator=(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
//copy
|
//move
|
||||||
serializer& operator=(const serializer &s) {
|
serializer& operator=(serializer&& s) {
|
||||||
if(idata) delete[] idata;
|
if(idata) delete[] idata;
|
||||||
|
|
||||||
imode = s.imode;
|
imode = s.imode;
|
||||||
idata = new uint8_t[s.icapacity];
|
idata = s.idata;
|
||||||
isize = s.isize;
|
isize = s.isize;
|
||||||
icapacity = s.icapacity;
|
icapacity = s.icapacity;
|
||||||
|
|
||||||
memcpy(idata, s.idata, s.icapacity);
|
s.idata = nullptr;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
serializer(const serializer &s) : idata(nullptr) {
|
serializer(serializer&& s) {
|
||||||
operator=(s);
|
operator=(std::move(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
//move
|
//construction
|
||||||
serializer& operator=(serializer &&s) {
|
serializer() = default;
|
||||||
if(idata) delete[] idata;
|
|
||||||
|
|
||||||
imode = s.imode;
|
serializer(unsigned capacity) {
|
||||||
idata = s.idata;
|
imode = Save;
|
||||||
isize = s.isize;
|
idata = new uint8_t[capacity]();
|
||||||
icapacity = s.icapacity;
|
isize = 0;
|
||||||
|
icapacity = capacity;
|
||||||
|
}
|
||||||
|
|
||||||
s.idata = nullptr;
|
serializer(const uint8_t* data, unsigned capacity) {
|
||||||
return *this;
|
imode = Load;
|
||||||
}
|
idata = new uint8_t[capacity];
|
||||||
|
isize = 0;
|
||||||
|
icapacity = capacity;
|
||||||
|
memcpy(idata, data, capacity);
|
||||||
|
}
|
||||||
|
|
||||||
serializer(serializer &&s) {
|
//destruction
|
||||||
operator=(std::move(s));
|
~serializer() {
|
||||||
}
|
if(idata) delete[] idata;
|
||||||
|
}
|
||||||
|
|
||||||
//construction
|
private:
|
||||||
serializer() {
|
mode_t imode = Size;
|
||||||
imode = Size;
|
uint8_t* idata = nullptr;
|
||||||
idata = nullptr;
|
unsigned isize = 0;
|
||||||
isize = 0;
|
unsigned icapacity = 0;
|
||||||
icapacity = 0;
|
};
|
||||||
}
|
|
||||||
|
|
||||||
serializer(unsigned capacity) {
|
|
||||||
imode = Save;
|
|
||||||
idata = new uint8_t[capacity]();
|
|
||||||
isize = 0;
|
|
||||||
icapacity = capacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
serializer(const uint8_t *data, unsigned capacity) {
|
|
||||||
imode = Load;
|
|
||||||
idata = new uint8_t[capacity];
|
|
||||||
isize = 0;
|
|
||||||
icapacity = capacity;
|
|
||||||
memcpy(idata, data, capacity);
|
|
||||||
}
|
|
||||||
|
|
||||||
~serializer() {
|
|
||||||
if(idata) delete[] idata;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
mode_t imode;
|
|
||||||
uint8_t *idata;
|
|
||||||
unsigned isize;
|
|
||||||
unsigned icapacity;
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,258 @@
|
||||||
|
#ifndef NALL_SET_HPP
|
||||||
|
#define NALL_SET_HPP
|
||||||
|
|
||||||
|
//set
|
||||||
|
//implementation: red-black tree
|
||||||
|
//search: 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
|
||||||
|
|
||||||
|
#include <nall/utility.hpp>
|
||||||
|
#include <nall/vector.hpp>
|
||||||
|
|
||||||
|
namespace nall {
|
||||||
|
|
||||||
|
template<typename T> struct set {
|
||||||
|
struct node_t {
|
||||||
|
T value;
|
||||||
|
bool red = 1;
|
||||||
|
node_t* link[2] = {nullptr, nullptr};
|
||||||
|
node_t() = default;
|
||||||
|
node_t(const T& value) : value(value) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
node_t* root = nullptr;
|
||||||
|
unsigned nodes = 0;
|
||||||
|
|
||||||
|
set& operator=(const set& source) { copy(source); return *this; }
|
||||||
|
set& operator=(set&& source) { move(std::move(source)); return *this; }
|
||||||
|
set(const set& source) { operator=(source); }
|
||||||
|
set(set&& source) { operator=(std::move(source)); }
|
||||||
|
set(std::initializer_list<T> list) { for(auto& value : list) insert(value); }
|
||||||
|
set() = default;
|
||||||
|
~set() { reset(); }
|
||||||
|
|
||||||
|
unsigned size() const { return nodes; }
|
||||||
|
bool empty() const { return nodes == 0; }
|
||||||
|
|
||||||
|
void reset() {
|
||||||
|
reset(root);
|
||||||
|
nodes = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
optional<T&> find(const T& value) {
|
||||||
|
if(node_t* node = find(root, value)) return node->value;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
optional<const T&> find(const T& value) const {
|
||||||
|
if(node_t* node = find(root, value)) return node->value;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool insert(const T& value) {
|
||||||
|
unsigned count = size();
|
||||||
|
insert(root, value);
|
||||||
|
root->red = 0;
|
||||||
|
return size() > count;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... Args> bool insert(const T& value, Args&&... args) {
|
||||||
|
bool result = insert(value);
|
||||||
|
return insert(std::forward<Args>(args)...) | result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool remove(const T& value) {
|
||||||
|
unsigned count = size();
|
||||||
|
bool done = 0;
|
||||||
|
remove(root, &value, done);
|
||||||
|
if(root) root->red = 0;
|
||||||
|
return size() < count;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... Args> bool remove(const T& value, Args&&... args) {
|
||||||
|
bool result = remove(value);
|
||||||
|
return remove(std::forward<Args>(args)...) | result;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct base_iterator {
|
||||||
|
bool operator!=(const base_iterator& source) const { return position != source.position; }
|
||||||
|
|
||||||
|
base_iterator& operator++() {
|
||||||
|
if(++position >= source.size()) { position = source.size(); return *this; }
|
||||||
|
|
||||||
|
if(stack.last()->link[1]) {
|
||||||
|
stack.append(stack.last()->link[1]);
|
||||||
|
while(stack.last()->link[0]) stack.append(stack.last()->link[0]);
|
||||||
|
} else {
|
||||||
|
node_t* child;
|
||||||
|
do child = stack.take();
|
||||||
|
while(child == stack.last()->link[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
base_iterator(const set& source, unsigned position) : source(source), position(position) {
|
||||||
|
node_t* node = source.root;
|
||||||
|
while(node) {
|
||||||
|
stack.append(node);
|
||||||
|
node = node->link[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
const set& source;
|
||||||
|
unsigned position;
|
||||||
|
vector<node_t*> stack;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct iterator : base_iterator {
|
||||||
|
T& operator*() const { return base_iterator::stack.last()->value; }
|
||||||
|
iterator(const set& source, unsigned position) : base_iterator(source, position) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
iterator begin() { return iterator(*this, 0); }
|
||||||
|
iterator end() { return iterator(*this, size()); }
|
||||||
|
|
||||||
|
struct const_iterator : base_iterator {
|
||||||
|
const T& operator*() const { return base_iterator::stack.last()->value; }
|
||||||
|
const_iterator(const set& source, unsigned position) : base_iterator(source, position) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
const const_iterator begin() const { return const_iterator(*this, 0); }
|
||||||
|
const const_iterator end() const { return const_iterator(*this, size()); }
|
||||||
|
|
||||||
|
private:
|
||||||
|
void reset(node_t*& node) {
|
||||||
|
if(!node) return;
|
||||||
|
if(node->link[0]) reset(node->link[0]);
|
||||||
|
if(node->link[1]) reset(node->link[1]);
|
||||||
|
delete node;
|
||||||
|
node = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void copy(const set& source) {
|
||||||
|
reset();
|
||||||
|
copy(root, source.root);
|
||||||
|
nodes = source.nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
void copy(node_t*& target, const node_t* source) {
|
||||||
|
if(!source) return;
|
||||||
|
target = new node_t(source->value);
|
||||||
|
target->red = source->red;
|
||||||
|
copy(target->link[0], source->link[0]);
|
||||||
|
copy(target->link[1], source->link[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void move(set&& source) {
|
||||||
|
root = source.root;
|
||||||
|
nodes = source.nodes;
|
||||||
|
source.root = nullptr;
|
||||||
|
source.nodes = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
node_t* find(node_t* node, const T& value) const {
|
||||||
|
if(node == nullptr) return nullptr;
|
||||||
|
if(node->value == value) return node;
|
||||||
|
return find(node->link[node->value < value], value);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool red(node_t* node) const { return node && node->red; }
|
||||||
|
bool black(node_t* node) const { return !red(node); }
|
||||||
|
|
||||||
|
void rotate(node_t*& a, bool dir) {
|
||||||
|
node_t*& b = a->link[!dir];
|
||||||
|
node_t*& c = b->link[dir];
|
||||||
|
a->red = 1, b->red = 0;
|
||||||
|
std::swap(a, b);
|
||||||
|
std::swap(b, c);
|
||||||
|
}
|
||||||
|
|
||||||
|
void rotateTwice(node_t*& node, bool dir) {
|
||||||
|
rotate(node->link[!dir], !dir);
|
||||||
|
rotate(node, dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
void insert(node_t*& node, const T& value) {
|
||||||
|
if(!node) { nodes++; node = new node_t(value); return; }
|
||||||
|
if(node->value == value) { node->value = value; return; } //prevent duplicate entries
|
||||||
|
|
||||||
|
bool dir = node->value < value;
|
||||||
|
insert(node->link[dir], value);
|
||||||
|
if(black(node->link[dir])) return;
|
||||||
|
|
||||||
|
if(red(node->link[!dir])) {
|
||||||
|
node->red = 1;
|
||||||
|
node->link[0]->red = 0;
|
||||||
|
node->link[1]->red = 0;
|
||||||
|
} else if(red(node->link[dir]->link[dir])) {
|
||||||
|
rotate(node, !dir);
|
||||||
|
} else if(red(node->link[dir]->link[!dir])) {
|
||||||
|
rotateTwice(node, !dir);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void balance(node_t*& node, bool dir, bool& done) {
|
||||||
|
node_t* p = node;
|
||||||
|
node_t* s = node->link[!dir];
|
||||||
|
if(!s) return;
|
||||||
|
|
||||||
|
if(red(s)) {
|
||||||
|
rotate(node, dir);
|
||||||
|
s = p->link[!dir];
|
||||||
|
}
|
||||||
|
|
||||||
|
if(black(s->link[0]) && black(s->link[1])) {
|
||||||
|
if(red(p)) done = 1;
|
||||||
|
p->red = 0, s->red = 1;
|
||||||
|
} else {
|
||||||
|
bool save = p->red;
|
||||||
|
bool head = node == p;
|
||||||
|
|
||||||
|
if(red(s->link[!dir])) rotate(p, dir);
|
||||||
|
else rotateTwice(p, dir);
|
||||||
|
|
||||||
|
p->red = save;
|
||||||
|
p->link[0]->red = 0;
|
||||||
|
p->link[1]->red = 0;
|
||||||
|
|
||||||
|
if(head) node = p;
|
||||||
|
else node->link[dir] = p;
|
||||||
|
|
||||||
|
done = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void remove(node_t*& node, const T* value, bool& done) {
|
||||||
|
if(!node) { done = 1; return; }
|
||||||
|
|
||||||
|
if(node->value == *value) {
|
||||||
|
if(!node->link[0] || !node->link[1]) {
|
||||||
|
node_t* save = node->link[!node->link[0]];
|
||||||
|
|
||||||
|
if(red(node)) done = 1;
|
||||||
|
else if(red(save)) save->red = 0, done = 1;
|
||||||
|
|
||||||
|
nodes--;
|
||||||
|
delete node;
|
||||||
|
node = save;
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
node_t* heir = node->link[0];
|
||||||
|
while(heir->link[1]) heir = heir->link[1];
|
||||||
|
node->value = heir->value;
|
||||||
|
value = &heir->value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool dir = node->value < *value;
|
||||||
|
remove(node->link[dir], value, done);
|
||||||
|
if(!done) balance(node, dir, done);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -6,140 +6,142 @@
|
||||||
#include <nall/stdint.hpp>
|
#include <nall/stdint.hpp>
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
#define PTR(t, a) ((t*)(a))
|
|
||||||
|
|
||||||
#define SWAP32(x) ((uint32_t)( \
|
#define PTR(t, a) ((t*)(a))
|
||||||
(((uint32_t)(x) & 0x000000ff) << 24) | \
|
|
||||||
(((uint32_t)(x) & 0x0000ff00) << 8) | \
|
|
||||||
(((uint32_t)(x) & 0x00ff0000) >> 8) | \
|
|
||||||
(((uint32_t)(x) & 0xff000000) >> 24) \
|
|
||||||
))
|
|
||||||
|
|
||||||
#define ST32(a, d) *PTR(uint32_t, a) = (d)
|
#define SWAP32(x) ((uint32_t)( \
|
||||||
#define ST32BE(a, d) ST32(a, SWAP32(d))
|
(((uint32_t)(x) & 0x000000ff) << 24) | \
|
||||||
|
(((uint32_t)(x) & 0x0000ff00) << 8) | \
|
||||||
|
(((uint32_t)(x) & 0x00ff0000) >> 8) | \
|
||||||
|
(((uint32_t)(x) & 0xff000000) >> 24) \
|
||||||
|
))
|
||||||
|
|
||||||
#define LD32(a) *PTR(uint32_t, a)
|
#define ST32(a, d) *PTR(uint32_t, a) = (d)
|
||||||
#define LD32BE(a) SWAP32(LD32(a))
|
#define ST32BE(a, d) ST32(a, SWAP32(d))
|
||||||
|
|
||||||
#define LSL32(x, n) ((uint32_t)(x) << (n))
|
#define LD32(a) *PTR(uint32_t, a)
|
||||||
#define LSR32(x, n) ((uint32_t)(x) >> (n))
|
#define LD32BE(a) SWAP32(LD32(a))
|
||||||
#define ROR32(x, n) (LSR32(x, n) | LSL32(x, 32 - (n)))
|
|
||||||
|
|
||||||
//first 32 bits of the fractional parts of the square roots of the first 8 primes 2..19
|
#define LSL32(x, n) ((uint32_t)(x) << (n))
|
||||||
static const uint32_t T_H[8] = {
|
#define LSR32(x, n) ((uint32_t)(x) >> (n))
|
||||||
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
|
#define ROR32(x, n) (LSR32(x, n) | LSL32(x, 32 - (n)))
|
||||||
};
|
|
||||||
|
|
||||||
//first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311
|
//first 32 bits of the fractional parts of the square roots of the first 8 primes 2..19
|
||||||
static const uint32_t T_K[64] = {
|
static const uint32_t T_H[8] = {
|
||||||
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a, 0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19,
|
||||||
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
};
|
||||||
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
|
||||||
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
|
||||||
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
|
||||||
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
|
||||||
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
|
||||||
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct sha256_ctx {
|
//first 32 bits of the fractional parts of the cube roots of the first 64 primes 2..311
|
||||||
uint8_t in[64];
|
static const uint32_t T_K[64] = {
|
||||||
unsigned inlen;
|
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
|
||||||
|
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
|
||||||
|
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
||||||
|
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
|
||||||
|
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
|
||||||
|
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
||||||
|
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
|
||||||
|
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
|
||||||
|
};
|
||||||
|
|
||||||
uint32_t w[64];
|
struct sha256_ctx {
|
||||||
uint32_t h[8];
|
uint8_t in[64];
|
||||||
uint64_t len;
|
unsigned inlen;
|
||||||
};
|
|
||||||
|
|
||||||
inline void sha256_init(sha256_ctx *p) {
|
uint32_t w[64];
|
||||||
memset(p, 0, sizeof(sha256_ctx));
|
uint32_t h[8];
|
||||||
memcpy(p->h, T_H, sizeof(T_H));
|
uint64_t len;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline void sha256_init(sha256_ctx* p) {
|
||||||
|
memset(p, 0, sizeof(sha256_ctx));
|
||||||
|
memcpy(p->h, T_H, sizeof(T_H));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sha256_block(sha256_ctx* p) {
|
||||||
|
unsigned i;
|
||||||
|
uint32_t s0, s1;
|
||||||
|
uint32_t a, b, c, d, e, f, g, h;
|
||||||
|
uint32_t t1, t2, maj, ch;
|
||||||
|
|
||||||
|
for(i = 0; i < 16; i++) p->w[i] = LD32BE(p->in + i * 4);
|
||||||
|
|
||||||
|
for(i = 16; i < 64; i++) {
|
||||||
|
s0 = ROR32(p->w[i - 15], 7) ^ ROR32(p->w[i - 15], 18) ^ LSR32(p->w[i - 15], 3);
|
||||||
|
s1 = ROR32(p->w[i - 2], 17) ^ ROR32(p->w[i - 2], 19) ^ LSR32(p->w[i - 2], 10);
|
||||||
|
p->w[i] = p->w[i - 16] + s0 + p->w[i - 7] + s1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sha256_block(sha256_ctx *p) {
|
a = p->h[0]; b = p->h[1]; c = p->h[2]; d = p->h[3];
|
||||||
unsigned i;
|
e = p->h[4]; f = p->h[5]; g = p->h[6]; h = p->h[7];
|
||||||
uint32_t s0, s1;
|
|
||||||
uint32_t a, b, c, d, e, f, g, h;
|
|
||||||
uint32_t t1, t2, maj, ch;
|
|
||||||
|
|
||||||
for(i = 0; i < 16; i++) p->w[i] = LD32BE(p->in + i * 4);
|
for(i = 0; i < 64; i++) {
|
||||||
|
s0 = ROR32(a, 2) ^ ROR32(a, 13) ^ ROR32(a, 22);
|
||||||
|
maj = (a & b) ^ (a & c) ^ (b & c);
|
||||||
|
t2 = s0 + maj;
|
||||||
|
s1 = ROR32(e, 6) ^ ROR32(e, 11) ^ ROR32(e, 25);
|
||||||
|
ch = (e & f) ^ (~e & g);
|
||||||
|
t1 = h + s1 + ch + T_K[i] + p->w[i];
|
||||||
|
|
||||||
for(i = 16; i < 64; i++) {
|
h = g; g = f; f = e; e = d + t1;
|
||||||
s0 = ROR32(p->w[i - 15], 7) ^ ROR32(p->w[i - 15], 18) ^ LSR32(p->w[i - 15], 3);
|
d = c; c = b; b = a; a = t1 + t2;
|
||||||
s1 = ROR32(p->w[i - 2], 17) ^ ROR32(p->w[i - 2], 19) ^ LSR32(p->w[i - 2], 10);
|
|
||||||
p->w[i] = p->w[i - 16] + s0 + p->w[i - 7] + s1;
|
|
||||||
}
|
|
||||||
|
|
||||||
a = p->h[0]; b = p->h[1]; c = p->h[2]; d = p->h[3];
|
|
||||||
e = p->h[4]; f = p->h[5]; g = p->h[6]; h = p->h[7];
|
|
||||||
|
|
||||||
for(i = 0; i < 64; i++) {
|
|
||||||
s0 = ROR32(a, 2) ^ ROR32(a, 13) ^ ROR32(a, 22);
|
|
||||||
maj = (a & b) ^ (a & c) ^ (b & c);
|
|
||||||
t2 = s0 + maj;
|
|
||||||
s1 = ROR32(e, 6) ^ ROR32(e, 11) ^ ROR32(e, 25);
|
|
||||||
ch = (e & f) ^ (~e & g);
|
|
||||||
t1 = h + s1 + ch + T_K[i] + p->w[i];
|
|
||||||
|
|
||||||
h = g; g = f; f = e; e = d + t1;
|
|
||||||
d = c; c = b; b = a; a = t1 + t2;
|
|
||||||
}
|
|
||||||
|
|
||||||
p->h[0] += a; p->h[1] += b; p->h[2] += c; p->h[3] += d;
|
|
||||||
p->h[4] += e; p->h[5] += f; p->h[6] += g; p->h[7] += h;
|
|
||||||
|
|
||||||
//next block
|
|
||||||
p->inlen = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void sha256_chunk(sha256_ctx *p, const uint8_t *s, unsigned len) {
|
p->h[0] += a; p->h[1] += b; p->h[2] += c; p->h[3] += d;
|
||||||
unsigned l;
|
p->h[4] += e; p->h[5] += f; p->h[6] += g; p->h[7] += h;
|
||||||
p->len += len;
|
|
||||||
|
|
||||||
while(len) {
|
//next block
|
||||||
l = 64 - p->inlen;
|
p->inlen = 0;
|
||||||
l = (len < l) ? len : l;
|
}
|
||||||
|
|
||||||
memcpy(p->in + p->inlen, s, l);
|
inline void sha256_chunk(sha256_ctx* p, const uint8_t* s, unsigned len) {
|
||||||
s += l;
|
unsigned l;
|
||||||
p->inlen += l;
|
p->len += len;
|
||||||
len -= l;
|
|
||||||
|
|
||||||
if(p->inlen == 64) sha256_block(p);
|
while(len) {
|
||||||
}
|
l = 64 - p->inlen;
|
||||||
|
l = (len < l) ? len : l;
|
||||||
|
|
||||||
|
memcpy(p->in + p->inlen, s, l);
|
||||||
|
s += l;
|
||||||
|
p->inlen += l;
|
||||||
|
len -= l;
|
||||||
|
|
||||||
|
if(p->inlen == 64) sha256_block(p);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
inline void sha256_final(sha256_ctx *p) {
|
inline void sha256_final(sha256_ctx* p) {
|
||||||
uint64_t len;
|
uint64_t len;
|
||||||
p->in[p->inlen++] = 0x80;
|
p->in[p->inlen++] = 0x80;
|
||||||
|
|
||||||
if(p->inlen > 56) {
|
if(p->inlen > 56) {
|
||||||
memset(p->in + p->inlen, 0, 64 - p->inlen);
|
memset(p->in + p->inlen, 0, 64 - p->inlen);
|
||||||
sha256_block(p);
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(p->in + p->inlen, 0, 56 - p->inlen);
|
|
||||||
|
|
||||||
len = p->len << 3;
|
|
||||||
ST32BE(p->in + 56, len >> 32);
|
|
||||||
ST32BE(p->in + 60, len);
|
|
||||||
sha256_block(p);
|
sha256_block(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void sha256_hash(sha256_ctx *p, uint8_t *s) {
|
memset(p->in + p->inlen, 0, 56 - p->inlen);
|
||||||
uint32_t *t = (uint32_t*)s;
|
|
||||||
for(unsigned i = 0; i < 8; i++) ST32BE(t++, p->h[i]);
|
len = p->len << 3;
|
||||||
}
|
ST32BE(p->in + 56, len >> 32);
|
||||||
|
ST32BE(p->in + 60, len);
|
||||||
|
sha256_block(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void sha256_hash(sha256_ctx* p, uint8_t* s) {
|
||||||
|
uint32_t *t = (uint32_t*)s;
|
||||||
|
for(unsigned i = 0; i < 8; i++) ST32BE(t++, p->h[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#undef PTR
|
||||||
|
#undef SWAP32
|
||||||
|
#undef ST32
|
||||||
|
#undef ST32BE
|
||||||
|
#undef LD32
|
||||||
|
#undef LD32BE
|
||||||
|
#undef LSL32
|
||||||
|
#undef LSR32
|
||||||
|
#undef ROR32
|
||||||
|
|
||||||
#undef PTR
|
|
||||||
#undef SWAP32
|
|
||||||
#undef ST32
|
|
||||||
#undef ST32BE
|
|
||||||
#undef LD32
|
|
||||||
#undef LD32BE
|
|
||||||
#undef LSL32
|
|
||||||
#undef LSR32
|
|
||||||
#undef ROR32
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -19,59 +19,59 @@
|
||||||
//#define NALL_SORT_SELECTION
|
//#define NALL_SORT_SELECTION
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
template<typename T, typename Comparator>
|
|
||||||
void sort(T list[], unsigned size, const Comparator &lessthan) {
|
|
||||||
if(size <= 1) return; //nothing to sort
|
|
||||||
|
|
||||||
//use insertion sort to quickly sort smaller blocks
|
template<typename T, typename Comparator> void sort(T list[], unsigned size, const Comparator& lessthan) {
|
||||||
if(size < 64) {
|
if(size <= 1) return; //nothing to sort
|
||||||
#if defined(NALL_SORT_INSERTION)
|
|
||||||
for(signed i = 1, j; i < size; i++) {
|
//use insertion sort to quickly sort smaller blocks
|
||||||
T copy = std::move(list[i]);
|
if(size < 64) {
|
||||||
for(j = i - 1; j >= 0; j--) {
|
#if defined(NALL_SORT_INSERTION)
|
||||||
if(!lessthan(copy, list[j])) break;
|
for(signed i = 1, j; i < size; i++) {
|
||||||
list[j + 1] = std::move(list[j]);
|
T copy = std::move(list[i]);
|
||||||
}
|
for(j = i - 1; j >= 0; j--) {
|
||||||
list[j + 1] = std::move(copy);
|
if(!lessthan(copy, list[j])) break;
|
||||||
|
list[j + 1] = std::move(list[j]);
|
||||||
}
|
}
|
||||||
#elif defined(NALL_SORT_SELECTION)
|
list[j + 1] = std::move(copy);
|
||||||
for(unsigned i = 0; i < size; i++) {
|
|
||||||
unsigned min = i;
|
|
||||||
for(unsigned j = i + 1; j < size; j++) {
|
|
||||||
if(lessthan(list[j], list[min])) min = j;
|
|
||||||
}
|
|
||||||
if(min != i) std::swap(list[i], list[min]);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
#elif defined(NALL_SORT_SELECTION)
|
||||||
//split list in half and recursively sort both
|
for(unsigned i = 0; i < size; i++) {
|
||||||
unsigned middle = size / 2;
|
unsigned min = i;
|
||||||
sort(list, middle, lessthan);
|
for(unsigned j = i + 1; j < size; j++) {
|
||||||
sort(list + middle, size - middle, lessthan);
|
if(lessthan(list[j], list[min])) min = j;
|
||||||
|
|
||||||
//left and right are sorted here; perform merge sort
|
|
||||||
T *buffer = new T[size];
|
|
||||||
unsigned offset = 0, left = 0, right = middle;
|
|
||||||
while(left < middle && right < size) {
|
|
||||||
if(!lessthan(list[right], list[left])) {
|
|
||||||
buffer[offset++] = std::move(list[left++]);
|
|
||||||
} else {
|
|
||||||
buffer[offset++] = std::move(list[right++]);
|
|
||||||
}
|
}
|
||||||
|
if(min != i) std::swap(list[i], list[min]);
|
||||||
}
|
}
|
||||||
while(left < middle) buffer[offset++] = std::move(list[left++]);
|
#endif
|
||||||
while(right < size) buffer[offset++] = std::move(list[right++]);
|
return;
|
||||||
|
|
||||||
for(unsigned i = 0; i < size; i++) list[i] = std::move(buffer[i]);
|
|
||||||
delete[] buffer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
//split list in half and recursively sort both
|
||||||
void sort(T list[], unsigned size) {
|
unsigned middle = size / 2;
|
||||||
return sort(list, size, [](const T &l, const T &r) { return l < r; });
|
sort(list, middle, lessthan);
|
||||||
|
sort(list + middle, size - middle, lessthan);
|
||||||
|
|
||||||
|
//left and right are sorted here; perform merge sort
|
||||||
|
T* buffer = new T[size];
|
||||||
|
unsigned offset = 0, left = 0, right = middle;
|
||||||
|
while(left < middle && right < size) {
|
||||||
|
if(!lessthan(list[right], list[left])) {
|
||||||
|
buffer[offset++] = std::move(list[left++]);
|
||||||
|
} else {
|
||||||
|
buffer[offset++] = std::move(list[right++]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
while(left < middle) buffer[offset++] = std::move(list[left++]);
|
||||||
|
while(right < size) buffer[offset++] = std::move(list[right++]);
|
||||||
|
|
||||||
|
for(unsigned i = 0; i < size; i++) list[i] = std::move(buffer[i]);
|
||||||
|
delete[] buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T> void sort(T list[], unsigned size) {
|
||||||
|
return sort(list, size, [](const T& l, const T& r) { return l < r; });
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -28,15 +28,17 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
static_assert(sizeof(int8_t) == 1, "int8_t is not of the correct size" );
|
|
||||||
static_assert(sizeof(int16_t) == 2, "int16_t is not of the correct size");
|
|
||||||
static_assert(sizeof(int32_t) == 4, "int32_t is not of the correct size");
|
|
||||||
static_assert(sizeof(int64_t) == 8, "int64_t is not of the correct size");
|
|
||||||
|
|
||||||
static_assert(sizeof(uint8_t) == 1, "int8_t is not of the correct size" );
|
static_assert(sizeof(int8_t) == 1, "int8_t is not of the correct size" );
|
||||||
static_assert(sizeof(uint16_t) == 2, "int16_t is not of the correct size");
|
static_assert(sizeof(int16_t) == 2, "int16_t is not of the correct size");
|
||||||
static_assert(sizeof(uint32_t) == 4, "int32_t is not of the correct size");
|
static_assert(sizeof(int32_t) == 4, "int32_t is not of the correct size");
|
||||||
static_assert(sizeof(uint64_t) == 8, "int64_t is not of the correct size");
|
static_assert(sizeof(int64_t) == 8, "int64_t is not of the correct size");
|
||||||
|
|
||||||
|
static_assert(sizeof(uint8_t) == 1, "int8_t is not of the correct size" );
|
||||||
|
static_assert(sizeof(uint16_t) == 2, "int16_t is not of the correct size");
|
||||||
|
static_assert(sizeof(uint32_t) == 4, "int32_t is not of the correct size");
|
||||||
|
static_assert(sizeof(uint64_t) == 8, "int64_t is not of the correct size");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -5,18 +5,18 @@ namespace nall {
|
||||||
|
|
||||||
#define autostream(...) (*makestream(__VA_ARGS__))
|
#define autostream(...) (*makestream(__VA_ARGS__))
|
||||||
|
|
||||||
inline std::unique_ptr<stream> makestream(const string &path) {
|
inline std::unique_ptr<stream> makestream(const string& path) {
|
||||||
if(path.ibeginswith("http://")) return std::unique_ptr<stream>(new httpstream(path, 80));
|
if(path.ibeginswith("http://")) return std::unique_ptr<stream>(new httpstream(path, 80));
|
||||||
if(path.iendswith(".gz")) return std::unique_ptr<stream>(new gzipstream(filestream{path}));
|
if(path.iendswith(".gz")) return std::unique_ptr<stream>(new gzipstream(filestream{path}));
|
||||||
if(path.iendswith(".zip")) return std::unique_ptr<stream>(new zipstream(filestream{path}));
|
if(path.iendswith(".zip")) return std::unique_ptr<stream>(new zipstream(filestream{path}));
|
||||||
return std::unique_ptr<stream>(new mmapstream(path));
|
return std::unique_ptr<stream>(new mmapstream(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::unique_ptr<stream> makestream(uint8_t *data, unsigned size) {
|
inline std::unique_ptr<stream> makestream(uint8_t* data, unsigned size) {
|
||||||
return std::unique_ptr<stream>(new memorystream(data, size));
|
return std::unique_ptr<stream>(new memorystream(data, size));
|
||||||
}
|
}
|
||||||
|
|
||||||
inline std::unique_ptr<stream> makestream(const uint8_t *data, unsigned size) {
|
inline std::unique_ptr<stream> makestream(const uint8_t* data, unsigned size) {
|
||||||
return std::unique_ptr<stream>(new memorystream(data, size));
|
return std::unique_ptr<stream>(new memorystream(data, size));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,13 +21,13 @@ struct filestream : stream {
|
||||||
uint8_t read() const { return pfile.read(); }
|
uint8_t read() const { return pfile.read(); }
|
||||||
void write(uint8_t data) const { pfile.write(data); }
|
void write(uint8_t data) const { pfile.write(data); }
|
||||||
|
|
||||||
filestream(const string &filename) {
|
filestream(const string& filename) {
|
||||||
pfile.open(filename, file::mode::readwrite);
|
pfile.open(filename, file::mode::readwrite);
|
||||||
pwritable = pfile.open();
|
pwritable = pfile.open();
|
||||||
if(!pwritable) pfile.open(filename, file::mode::read);
|
if(!pwritable) pfile.open(filename, file::mode::read);
|
||||||
}
|
}
|
||||||
|
|
||||||
filestream(const string &filename, file::mode mode) {
|
filestream(const string& filename, file::mode mode) {
|
||||||
pfile.open(filename, mode);
|
pfile.open(filename, mode);
|
||||||
pwritable = mode == file::mode::write || mode == file::mode::readwrite;
|
pwritable = mode == file::mode::write || mode == file::mode::readwrite;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ struct gzipstream : memorystream {
|
||||||
using stream::read;
|
using stream::read;
|
||||||
using stream::write;
|
using stream::write;
|
||||||
|
|
||||||
gzipstream(const stream &stream) {
|
gzipstream(const stream& stream) {
|
||||||
unsigned size = stream.size();
|
unsigned size = stream.size();
|
||||||
uint8_t *data = new uint8_t[size];
|
uint8_t *data = new uint8_t[size];
|
||||||
stream.read(data, size);
|
stream.read(data, size);
|
||||||
|
|
|
@ -24,7 +24,7 @@ struct httpstream : stream {
|
||||||
uint8_t read(unsigned offset) const { return pdata[offset]; }
|
uint8_t read(unsigned offset) const { return pdata[offset]; }
|
||||||
void write(unsigned offset, uint8_t data) const { pdata[offset] = data; }
|
void write(unsigned offset, uint8_t data) const { pdata[offset] = data; }
|
||||||
|
|
||||||
httpstream(const string &url, unsigned port) : pdata(nullptr), psize(0), poffset(0) {
|
httpstream(const string& url, unsigned port) : pdata(nullptr), psize(0), poffset(0) {
|
||||||
string uri = url;
|
string uri = url;
|
||||||
uri.ltrim<1>("http://");
|
uri.ltrim<1>("http://");
|
||||||
lstring part = uri.split<1>("/");
|
lstring part = uri.split<1>("/");
|
||||||
|
@ -40,7 +40,7 @@ struct httpstream : stream {
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
mutable uint8_t *pdata;
|
mutable uint8_t* pdata;
|
||||||
mutable unsigned psize, poffset;
|
mutable unsigned psize, poffset;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ struct memorystream : stream {
|
||||||
bool writable() const { return pwritable; }
|
bool writable() const { return pwritable; }
|
||||||
bool randomaccess() const { return true; }
|
bool randomaccess() const { return true; }
|
||||||
|
|
||||||
uint8_t *data() const { return pdata; }
|
uint8_t* data() const { return pdata; }
|
||||||
unsigned size() const { return psize; }
|
unsigned size() const { return psize; }
|
||||||
unsigned offset() const { return poffset; }
|
unsigned offset() const { return poffset; }
|
||||||
void seek(unsigned offset) const { poffset = offset; }
|
void seek(unsigned offset) const { poffset = offset; }
|
||||||
|
@ -27,18 +27,18 @@ struct memorystream : stream {
|
||||||
|
|
||||||
memorystream() : pdata(nullptr), psize(0), poffset(0), pwritable(true) {}
|
memorystream() : pdata(nullptr), psize(0), poffset(0), pwritable(true) {}
|
||||||
|
|
||||||
memorystream(uint8_t *data, unsigned size) {
|
memorystream(uint8_t* data, unsigned size) {
|
||||||
pdata = data, psize = size, poffset = 0;
|
pdata = data, psize = size, poffset = 0;
|
||||||
pwritable = true;
|
pwritable = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
memorystream(const uint8_t *data, unsigned size) {
|
memorystream(const uint8_t* data, unsigned size) {
|
||||||
pdata = (uint8_t*)data, psize = size, poffset = 0;
|
pdata = (uint8_t*)data, psize = size, poffset = 0;
|
||||||
pwritable = false;
|
pwritable = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
mutable uint8_t *pdata;
|
mutable uint8_t* pdata;
|
||||||
mutable unsigned psize, poffset, pwritable;
|
mutable unsigned psize, poffset, pwritable;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ struct mmapstream : stream {
|
||||||
uint8_t read(unsigned offset) const { return pdata[offset]; }
|
uint8_t read(unsigned offset) const { return pdata[offset]; }
|
||||||
void write(unsigned offset, uint8_t data) const { pdata[offset] = data; }
|
void write(unsigned offset, uint8_t data) const { pdata[offset] = data; }
|
||||||
|
|
||||||
mmapstream(const string &filename) {
|
mmapstream(const string& filename) {
|
||||||
pmmap.open(filename, filemap::mode::readwrite);
|
pmmap.open(filename, filemap::mode::readwrite);
|
||||||
pwritable = pmmap.open();
|
pwritable = pmmap.open();
|
||||||
if(!pwritable) pmmap.open(filename, filemap::mode::read);
|
if(!pwritable) pmmap.open(filename, filemap::mode::read);
|
||||||
|
@ -33,7 +33,7 @@ struct mmapstream : stream {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
mutable filemap pmmap;
|
mutable filemap pmmap;
|
||||||
mutable uint8_t *pdata;
|
mutable uint8_t* pdata;
|
||||||
mutable unsigned pwritable, poffset;
|
mutable unsigned pwritable, poffset;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,7 @@ struct stream {
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void read(uint8_t *data, unsigned length) const {
|
void read(uint8_t* data, unsigned length) const {
|
||||||
while(length--) *data++ = read();
|
while(length--) *data++ = read();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,17 +72,17 @@ struct stream {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void write(const uint8_t *data, unsigned length) const {
|
void write(const uint8_t* data, unsigned length) const {
|
||||||
while(length--) write(*data++);
|
while(length--) write(*data++);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct byte {
|
struct byte {
|
||||||
operator uint8_t() const { return s.read(offset); }
|
operator uint8_t() const { return s.read(offset); }
|
||||||
byte& operator=(uint8_t data) { s.write(offset, data); return *this; }
|
byte& operator=(uint8_t data) { s.write(offset, data); return *this; }
|
||||||
byte(const stream &s, unsigned offset) : s(s), offset(offset) {}
|
byte(const stream& s, unsigned offset) : s(s), offset(offset) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const stream &s;
|
const stream& s;
|
||||||
const unsigned offset;
|
const unsigned offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -26,11 +26,11 @@ struct vectorstream : stream {
|
||||||
uint8_t read(unsigned offset) const { return memory[offset]; }
|
uint8_t read(unsigned offset) const { return memory[offset]; }
|
||||||
void write(unsigned offset, uint8_t data) const { memory[offset] = data; }
|
void write(unsigned offset, uint8_t data) const { memory[offset] = data; }
|
||||||
|
|
||||||
vectorstream(vector<uint8_t> &memory) : memory(memory), poffset(0), pwritable(true) {}
|
vectorstream(vector<uint8_t>& memory) : memory(memory), poffset(0), pwritable(true) {}
|
||||||
vectorstream(const vector<uint8_t> &memory) : memory((vector<uint8_t>&)memory), poffset(0), pwritable(false) {}
|
vectorstream(const vector<uint8_t>& memory) : memory((vector<uint8_t>&)memory), poffset(0), pwritable(false) {}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
vector<uint8_t> &memory;
|
vector<uint8_t>& memory;
|
||||||
mutable unsigned poffset, pwritable;
|
mutable unsigned poffset, pwritable;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -9,16 +9,16 @@ struct zipstream : memorystream {
|
||||||
using stream::read;
|
using stream::read;
|
||||||
using stream::write;
|
using stream::write;
|
||||||
|
|
||||||
zipstream(const stream &stream, const string &filter = "*") {
|
zipstream(const stream& stream, const string& filter = "*") {
|
||||||
unsigned size = stream.size();
|
unsigned size = stream.size();
|
||||||
uint8_t *data = new uint8_t[size];
|
uint8_t* data = new uint8_t[size];
|
||||||
stream.read(data, size);
|
stream.read(data, size);
|
||||||
|
|
||||||
unzip archive;
|
unzip archive;
|
||||||
if(archive.open(data, size) == false) return;
|
if(archive.open(data, size) == false) return;
|
||||||
delete[] data;
|
delete[] data;
|
||||||
|
|
||||||
for(auto &file : archive.file) {
|
for(auto& file : archive.file) {
|
||||||
if(file.name.wildcard(filter)) {
|
if(file.name.wildcard(filter)) {
|
||||||
auto buffer = archive.extract(file);
|
auto buffer = archive.extract(file);
|
||||||
psize = buffer.size();
|
psize = buffer.size();
|
||||||
|
|
|
@ -11,19 +11,18 @@ namespace nall {
|
||||||
inline unsigned length() const;
|
inline unsigned length() 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;
|
||||||
inline optional<unsigned> position(const char *key) const;
|
inline optional<unsigned> position(const char* key) const;
|
||||||
inline optional<unsigned> iposition(const char *key) const;
|
inline optional<unsigned> iposition(const char* key) const;
|
||||||
inline cstring& operator=(const char *data);
|
inline cstring& operator=(const char* data);
|
||||||
inline cstring(const char *data);
|
inline cstring(const char* data);
|
||||||
inline cstring();
|
inline cstring();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
const char *data;
|
const char* data;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct string {
|
struct string {
|
||||||
//deprecated: use string text = file::read(filename);
|
inline static string read(const string& filename);
|
||||||
inline static string read(const string &filename);
|
|
||||||
|
|
||||||
inline static string date();
|
inline static string date();
|
||||||
inline static string time();
|
inline static string time();
|
||||||
|
@ -68,18 +67,18 @@ namespace nall {
|
||||||
inline string& upper();
|
inline string& upper();
|
||||||
inline string& qlower();
|
inline string& qlower();
|
||||||
inline string& qupper();
|
inline string& qupper();
|
||||||
inline string& transform(const char *before, const char *after);
|
inline string& transform(const char* before, const char* after);
|
||||||
inline string& reverse();
|
inline string& reverse();
|
||||||
|
|
||||||
template<unsigned limit = 0> inline string& ltrim(const char *key = " ");
|
template<unsigned limit = 0> inline string& ltrim(const char* key = " ");
|
||||||
template<unsigned limit = 0> inline string& rtrim(const char *key = " ");
|
template<unsigned limit = 0> inline string& rtrim(const char* key = " ");
|
||||||
template<unsigned limit = 0> inline string& trim(const char *key = " ", const char *rkey = nullptr);
|
template<unsigned limit = 0> inline string& trim(const char* key = " ", const char* rkey = nullptr);
|
||||||
inline string& strip();
|
inline string& strip();
|
||||||
|
|
||||||
inline optional<unsigned> position(const char *key) const;
|
inline optional<unsigned> position(const char* key) const;
|
||||||
inline optional<unsigned> iposition(const char *key) const;
|
inline optional<unsigned> iposition(const char* key) const;
|
||||||
inline optional<unsigned> qposition(const char *key) const;
|
inline optional<unsigned> qposition(const char* key) const;
|
||||||
inline optional<unsigned> iqposition(const char *key) const;
|
inline optional<unsigned> iqposition(const char* key) const;
|
||||||
|
|
||||||
inline explicit operator bool() const;
|
inline explicit operator bool() const;
|
||||||
inline operator const char*() const;
|
inline operator const char*() const;
|
||||||
|
@ -111,7 +110,7 @@ namespace nall {
|
||||||
inline string& append_(const char*);
|
inline string& append_(const char*);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
char *data;
|
char* data;
|
||||||
unsigned size;
|
unsigned size;
|
||||||
|
|
||||||
template<unsigned Limit, bool Insensitive, bool Quoted> inline string& ureplace(const char*, const char*);
|
template<unsigned Limit, bool Insensitive, bool Quoted> inline string& ureplace(const char*, const char*);
|
||||||
|
@ -125,8 +124,9 @@ namespace nall {
|
||||||
struct lstring : vector<string> {
|
struct lstring : vector<string> {
|
||||||
inline optional<unsigned> find(const char*) const;
|
inline optional<unsigned> find(const char*) const;
|
||||||
inline string concatenate(const char*) const;
|
inline string concatenate(const char*) const;
|
||||||
|
inline lstring& isort();
|
||||||
|
inline lstring& strip();
|
||||||
inline void append() {}
|
inline void append() {}
|
||||||
inline void isort();
|
|
||||||
template<typename... Args> inline void append(const string&, Args&&...);
|
template<typename... Args> inline void append(const string&, Args&&...);
|
||||||
|
|
||||||
template<unsigned Limit = 0> inline lstring& split(const char*, const char*);
|
template<unsigned Limit = 0> inline lstring& split(const char*, const char*);
|
||||||
|
@ -153,81 +153,81 @@ namespace nall {
|
||||||
//compare.hpp
|
//compare.hpp
|
||||||
inline char chrlower(char c);
|
inline char chrlower(char c);
|
||||||
inline char chrupper(char c);
|
inline char chrupper(char c);
|
||||||
inline int istrcmp(const char *str1, const char *str2);
|
inline int istrcmp(const char* str1, const char* str2);
|
||||||
inline bool strbegin(const char *str, const char *key);
|
inline bool strbegin(const char* str, const char* key);
|
||||||
inline bool istrbegin(const char *str, const char *key);
|
inline bool istrbegin(const char* str, const char* key);
|
||||||
inline bool strend(const char *str, const char *key);
|
inline bool strend(const char* str, const char* key);
|
||||||
inline bool istrend(const char *str, const char *key);
|
inline bool istrend(const char* str, const char* key);
|
||||||
|
|
||||||
//convert.hpp
|
//convert.hpp
|
||||||
inline char* strlower(char *str);
|
inline char* strlower(char* str);
|
||||||
inline char* strupper(char *str);
|
inline char* strupper(char* str);
|
||||||
inline char* qstrlower(char *str);
|
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);
|
||||||
|
|
||||||
//format.hpp
|
//format.hpp
|
||||||
template<signed precision = 0, char padchar = ' '> inline string format(const string &value);
|
template<signed precision = 0, char padchar = ' '> inline string format(const string& value);
|
||||||
template<signed precision = 0, char padchar = '0'> inline string hex(uintmax_t value);
|
template<signed precision = 0, char padchar = '0'> inline string hex(uintmax_t value);
|
||||||
template<signed precision = 0, char padchar = '0'> inline string octal(uintmax_t value);
|
template<signed precision = 0, char padchar = '0'> inline string octal(uintmax_t value);
|
||||||
template<signed precision = 0, char padchar = '0'> inline string binary(uintmax_t value);
|
template<signed precision = 0, char padchar = '0'> inline string binary(uintmax_t value);
|
||||||
|
|
||||||
//math.hpp
|
//math.hpp
|
||||||
inline bool strint(const char *str, int &result);
|
inline bool strint(const char* str, int& result);
|
||||||
inline bool strmath(const char *str, int &result);
|
inline bool strmath(const char* str, int& result);
|
||||||
|
|
||||||
//platform.hpp
|
//platform.hpp
|
||||||
inline string activepath();
|
inline string activepath();
|
||||||
inline string realpath(const string &name);
|
inline string realpath(const string& name);
|
||||||
inline string userpath();
|
inline string userpath();
|
||||||
inline string configpath();
|
inline string configpath();
|
||||||
inline string sharedpath();
|
inline string sharedpath();
|
||||||
inline string temppath();
|
inline string temppath();
|
||||||
|
|
||||||
//strm.hpp
|
//strm.hpp
|
||||||
inline unsigned strmcpy(char *target, const char *source, unsigned length);
|
inline unsigned strmcpy(char* target, const char* source, unsigned length);
|
||||||
inline unsigned strmcat(char *target, const char *source, unsigned length);
|
inline unsigned strmcat(char* target, const char* source, unsigned length);
|
||||||
inline bool strccpy(char *target, const char *source, unsigned length);
|
inline bool strccpy(char* target, const char* source, unsigned length);
|
||||||
inline bool strccat(char *target, const char *source, unsigned length);
|
inline bool strccat(char* target, const char* source, unsigned length);
|
||||||
inline void strpcpy(char *&target, const char *source, unsigned &length);
|
inline void strpcpy(char*& target, const char* source, unsigned& length);
|
||||||
|
|
||||||
//strpos.hpp
|
//strpos.hpp
|
||||||
inline optional<unsigned> strpos(const char *str, const char *key);
|
inline optional<unsigned> strpos(const char* str, const char* key);
|
||||||
inline optional<unsigned> istrpos(const char *str, const char *key);
|
inline optional<unsigned> istrpos(const char* str, const char* key);
|
||||||
inline optional<unsigned> qstrpos(const char *str, const char *key);
|
inline optional<unsigned> qstrpos(const char* str, const char* key);
|
||||||
inline optional<unsigned> iqstrpos(const char *str, const char *key);
|
inline optional<unsigned> iqstrpos(const char* str, const char* key);
|
||||||
template<bool Insensitive = false, bool Quoted = false> inline optional<unsigned> ustrpos(const char *str, const char *key);
|
template<bool Insensitive = false, bool Quoted = false> inline optional<unsigned> ustrpos(const char* str, const char* key);
|
||||||
|
|
||||||
//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 = " ", const char* rkey = nullptr);
|
||||||
inline char* strip(char *s);
|
inline char* strip(char* s);
|
||||||
|
|
||||||
//utility.hpp
|
//utility.hpp
|
||||||
template<bool Insensitive> alwaysinline bool chrequal(char x, char y);
|
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);
|
||||||
inline string substr(const char *src, unsigned start = 0, unsigned length = ~0u);
|
inline string substr(const char* src, unsigned start = 0, unsigned length = ~0u);
|
||||||
inline string sha256(const uint8_t *data, unsigned size);
|
inline string sha256(const uint8_t* data, unsigned size);
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
//these functions are deprecated, use format() instead:
|
//these functions are deprecated, use format() instead:
|
||||||
template<unsigned length = 0, char padding = ' '> inline string integer(intmax_t value);
|
template<unsigned length = 0, char padding = ' '> inline string integer(intmax_t value);
|
||||||
template<unsigned length = 0, char padding = ' '> inline string linteger(intmax_t value);
|
template<unsigned length = 0, char padding = ' '> inline string linteger(intmax_t value);
|
||||||
template<unsigned length = 0, char padding = ' '> inline string decimal(uintmax_t value);
|
template<unsigned length = 0, char padding = ' '> inline string decimal(uintmax_t value);
|
||||||
template<unsigned length = 0, char padding = ' '> inline string ldecimal(uintmax_t value);
|
template<unsigned length = 0, char padding = ' '> inline string ldecimal(uintmax_t value);
|
||||||
inline unsigned fp(char *str, long double value);
|
inline unsigned fp(char* str, long double value);
|
||||||
inline string fp(long double value);
|
inline string fp(long double value);
|
||||||
|
|
||||||
//variadic.hpp
|
//variadic.hpp
|
||||||
template<typename... Args> inline void print(Args&&... args);
|
template<typename... Args> inline void print(Args&&... args);
|
||||||
|
|
||||||
//wildcard.hpp
|
//wildcard.hpp
|
||||||
inline bool wildcard(const char *str, const char *pattern);
|
inline bool wildcard(const char* str, const char* pattern);
|
||||||
inline bool iwildcard(const char *str, const char *pattern);
|
inline bool iwildcard(const char* str, const char* pattern);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
namespace nall {
|
namespace nall {
|
||||||
|
|
||||||
struct BSV {
|
struct BSV {
|
||||||
static inline string decode(const char *input) {
|
static inline string decode(const char* input) {
|
||||||
string output;
|
string output;
|
||||||
unsigned offset = 0;
|
unsigned offset = 0;
|
||||||
while(*input) {
|
while(*input) {
|
||||||
|
@ -30,7 +30,7 @@ struct BSV {
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline string encode(const char *input) {
|
static inline string encode(const char* input) {
|
||||||
string output;
|
string output;
|
||||||
unsigned offset = 0;
|
unsigned offset = 0;
|
||||||
while(*input) {
|
while(*input) {
|
||||||
|
|
|
@ -119,7 +119,7 @@ template<> struct stringify<long double> {
|
||||||
// arrays
|
// arrays
|
||||||
|
|
||||||
template<> struct stringify<vector<uint8_t>> {
|
template<> struct stringify<vector<uint8_t>> {
|
||||||
char *text;
|
char* text;
|
||||||
operator const char*() const { return text; }
|
operator const char*() const { return text; }
|
||||||
stringify(vector<uint8_t> value) {
|
stringify(vector<uint8_t> value) {
|
||||||
text = new char[value.size() + 1]();
|
text = new char[value.size() + 1]();
|
||||||
|
@ -131,9 +131,9 @@ template<> struct stringify<vector<uint8_t>> {
|
||||||
};
|
};
|
||||||
|
|
||||||
template<> struct stringify<const vector<uint8_t>&> {
|
template<> struct stringify<const vector<uint8_t>&> {
|
||||||
char *text;
|
char* text;
|
||||||
operator const char*() const { return text; }
|
operator const char*() const { return text; }
|
||||||
stringify(const vector<uint8_t> &value) {
|
stringify(const vector<uint8_t>& value) {
|
||||||
text = new char[value.size() + 1]();
|
text = new char[value.size() + 1]();
|
||||||
memcpy(text, value.data(), value.size());
|
memcpy(text, value.data(), value.size());
|
||||||
}
|
}
|
||||||
|
@ -145,53 +145,53 @@ template<> struct stringify<const vector<uint8_t>&> {
|
||||||
// strings
|
// strings
|
||||||
|
|
||||||
template<> struct stringify<char*> {
|
template<> struct stringify<char*> {
|
||||||
const char *value;
|
const char* value;
|
||||||
operator const char*() const { return value; }
|
operator const char*() const { return value; }
|
||||||
stringify(char *value) : value(value) {}
|
stringify(char* value) : value(value) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<> struct stringify<const char*> {
|
template<> struct stringify<const char*> {
|
||||||
const char *value;
|
const char* value;
|
||||||
operator const char*() const { return value; }
|
operator const char*() const { return value; }
|
||||||
stringify(const char *value) : value(value) {}
|
stringify(const char* value) : value(value) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<> struct stringify<string> {
|
template<> struct stringify<string> {
|
||||||
const string &value;
|
const string& value;
|
||||||
operator const char*() const { return value; }
|
operator const char*() const { return value; }
|
||||||
stringify(const string &value) : value(value) {}
|
stringify(const string& value) : value(value) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<> struct stringify<const string&> {
|
template<> struct stringify<const string&> {
|
||||||
const string &value;
|
const string& value;
|
||||||
operator const char*() const { return value; }
|
operator const char*() const { return value; }
|
||||||
stringify(const string &value) : value(value) {}
|
stringify(const string& value) : value(value) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<> struct stringify<cstring> {
|
template<> struct stringify<cstring> {
|
||||||
const char *value;
|
const char* value;
|
||||||
operator const char*() const { return value; }
|
operator const char*() const { return value; }
|
||||||
stringify(const cstring &value) : value(value) {}
|
stringify(const cstring& value) : value(value) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<> struct stringify<const cstring&> {
|
template<> struct stringify<const cstring&> {
|
||||||
const char *value;
|
const char* value;
|
||||||
operator const char*() const { return value; }
|
operator const char*() const { return value; }
|
||||||
stringify(const cstring &value) : value(value) {}
|
stringify(const cstring& value) : value(value) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(QSTRING_H)
|
#if defined(QSTRING_H)
|
||||||
|
|
||||||
template<> struct stringify<QString> {
|
template<> struct stringify<QString> {
|
||||||
const QString &value;
|
const QString& value;
|
||||||
operator const char*() const { return value.toUtf8().constData(); }
|
operator const char*() const { return value.toUtf8().constData(); }
|
||||||
stringify(const QString &value) : value(value) {}
|
stringify(const QString& value) : value(value) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<> struct stringify<const QString&> {
|
template<> struct stringify<const QString&> {
|
||||||
const QString &value;
|
const QString& value;
|
||||||
operator const char*() const { return value.toUtf8().constData(); }
|
operator const char*() const { return value.toUtf8().constData(); }
|
||||||
stringify(const QString &value) : value(value) {}
|
stringify(const QString& value) : value(value) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
string::operator QString() const {
|
string::operator QString() const {
|
||||||
|
|
|
@ -10,7 +10,7 @@ char chrupper(char c) {
|
||||||
return (c >= 'a' && c <= 'z') ? c - ('a' - 'A') : c;
|
return (c >= 'a' && c <= 'z') ? c - ('a' - 'A') : c;
|
||||||
}
|
}
|
||||||
|
|
||||||
int istrcmp(const char *str1, const char *str2) {
|
int istrcmp(const char* str1, const char* str2) {
|
||||||
while(*str1) {
|
while(*str1) {
|
||||||
if(chrlower(*str1) != chrlower(*str2)) break;
|
if(chrlower(*str1) != chrlower(*str2)) break;
|
||||||
str1++, str2++;
|
str1++, str2++;
|
||||||
|
@ -18,14 +18,14 @@ int istrcmp(const char *str1, const char *str2) {
|
||||||
return (int)chrlower(*str1) - (int)chrlower(*str2);
|
return (int)chrlower(*str1) - (int)chrlower(*str2);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool strbegin(const char *str, const char *key) {
|
bool strbegin(const char* str, const char* key) {
|
||||||
int i, ssl = strlen(str), ksl = strlen(key);
|
int i, ssl = strlen(str), ksl = strlen(key);
|
||||||
|
|
||||||
if(ksl > ssl) return false;
|
if(ksl > ssl) return false;
|
||||||
return (!memcmp(str, key, ksl));
|
return (!memcmp(str, key, ksl));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool istrbegin(const char *str, const char *key) {
|
bool istrbegin(const char* str, const char* key) {
|
||||||
int ssl = strlen(str), ksl = strlen(key);
|
int ssl = strlen(str), ksl = strlen(key);
|
||||||
|
|
||||||
if(ksl > ssl) return false;
|
if(ksl > ssl) return false;
|
||||||
|
@ -41,14 +41,14 @@ bool istrbegin(const char *str, const char *key) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool strend(const char *str, const char *key) {
|
bool strend(const char* str, const char* key) {
|
||||||
int ssl = strlen(str), ksl = strlen(key);
|
int ssl = strlen(str), ksl = strlen(key);
|
||||||
|
|
||||||
if(ksl > ssl) return false;
|
if(ksl > ssl) return false;
|
||||||
return (!memcmp(str + ssl - ksl, key, ksl));
|
return (!memcmp(str + ssl - ksl, key, ksl));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool istrend(const char *str, const char *key) {
|
bool istrend(const char* str, const char* key) {
|
||||||
int ssl = strlen(str), ksl = strlen(key);
|
int ssl = strlen(str), ksl = strlen(key);
|
||||||
|
|
||||||
if(ksl > ssl) return false;
|
if(ksl > ssl) return false;
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
|
|
||||||
char* strlower(char *str) {
|
char* strlower(char* str) {
|
||||||
if(!str) return nullptr;
|
if(!str) return nullptr;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while(str[i]) {
|
while(str[i]) {
|
||||||
|
@ -12,7 +12,7 @@ char* strlower(char *str) {
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* strupper(char *str) {
|
char* strupper(char* str) {
|
||||||
if(!str) return nullptr;
|
if(!str) return nullptr;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
while(str[i]) {
|
while(str[i]) {
|
||||||
|
@ -22,7 +22,7 @@ char* strupper(char *str) {
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* qstrlower(char *s) {
|
char* qstrlower(char* s) {
|
||||||
if(!s) return nullptr;
|
if(!s) return nullptr;
|
||||||
bool quoted = false;
|
bool quoted = false;
|
||||||
while(*s) {
|
while(*s) {
|
||||||
|
@ -32,7 +32,7 @@ char* qstrlower(char *s) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char* qstrupper(char *s) {
|
char* qstrupper(char* s) {
|
||||||
if(!s) return nullptr;
|
if(!s) return nullptr;
|
||||||
bool quoted = false;
|
bool quoted = false;
|
||||||
while(*s) {
|
while(*s) {
|
||||||
|
@ -42,7 +42,7 @@ char* qstrupper(char *s) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char* strtr(char *dest, const char *before, const char *after) {
|
char* strtr(char* dest, const char* before, const char* after) {
|
||||||
if(!dest || !before || !after) return dest;
|
if(!dest || !before || !after) return dest;
|
||||||
int sl = strlen(dest), bsl = strlen(before), asl = strlen(after);
|
int sl = strlen(dest), bsl = strlen(before), asl = strlen(after);
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ static void istring(string &output) {
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename... Args>
|
template<typename T, typename... Args>
|
||||||
static void istring(string &output, const T &value, Args&&... args) {
|
static void istring(string& output, const T& value, Args&&... args) {
|
||||||
output.append_(make_string(value));
|
output.append_(make_string(value));
|
||||||
istring(output, std::forward<Args>(args)...);
|
istring(output, std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
@ -46,14 +46,14 @@ template<typename... Args> string& string::append(Args&&... args) {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
string& string::assign_(const char *s) {
|
string& string::assign_(const char* s) {
|
||||||
unsigned length = strlen(s);
|
unsigned length = strlen(s);
|
||||||
reserve(length);
|
reserve(length);
|
||||||
strcpy(data, s);
|
strcpy(data, s);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
string& string::append_(const char *s) {
|
string& string::append_(const char* s) {
|
||||||
unsigned length = strlen(data) + strlen(s);
|
unsigned length = strlen(data) + strlen(s);
|
||||||
reserve(length);
|
reserve(length);
|
||||||
strcat(data, s);
|
strcat(data, s);
|
||||||
|
@ -77,20 +77,20 @@ char& string::operator[](int index) {
|
||||||
return data[index];
|
return data[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
bool string::operator==(const char *str) const { return strcmp(data, str) == 0; }
|
bool string::operator==(const char* str) const { return strcmp(data, str) == 0; }
|
||||||
bool string::operator!=(const char *str) const { return strcmp(data, str) != 0; }
|
bool string::operator!=(const char* str) const { return strcmp(data, str) != 0; }
|
||||||
bool string::operator< (const char *str) const { return strcmp(data, str) < 0; }
|
bool string::operator< (const char* str) const { return strcmp(data, str) < 0; }
|
||||||
bool string::operator<=(const char *str) const { return strcmp(data, str) <= 0; }
|
bool string::operator<=(const char* str) const { return strcmp(data, str) <= 0; }
|
||||||
bool string::operator> (const char *str) const { return strcmp(data, str) > 0; }
|
bool string::operator> (const char* str) const { return strcmp(data, str) > 0; }
|
||||||
bool string::operator>=(const char *str) const { return strcmp(data, str) >= 0; }
|
bool string::operator>=(const char* str) const { return strcmp(data, str) >= 0; }
|
||||||
|
|
||||||
string& string::operator=(const string &value) {
|
string& string::operator=(const string& value) {
|
||||||
if(&value == this) return *this;
|
if(&value == this) return *this;
|
||||||
assign(value);
|
assign(value);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
string& string::operator=(string &&source) {
|
string& string::operator=(string&& source) {
|
||||||
if(&source == this) return *this;
|
if(&source == this) return *this;
|
||||||
if(data) free(data);
|
if(data) free(data);
|
||||||
size = source.size;
|
size = source.size;
|
||||||
|
@ -107,13 +107,13 @@ template<typename... Args> string::string(Args&&... args) {
|
||||||
istring(*this, std::forward<Args>(args)...);
|
istring(*this, std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
string::string(const string &value) {
|
string::string(const string& value) {
|
||||||
if(&value == this) return;
|
if(&value == this) return;
|
||||||
size = strlen(value);
|
size = strlen(value);
|
||||||
data = strdup(value);
|
data = strdup(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
string::string(string &&source) {
|
string::string(string&& source) {
|
||||||
if(&source == this) return;
|
if(&source == this) return;
|
||||||
size = source.size;
|
size = source.size;
|
||||||
data = source.data;
|
data = source.data;
|
||||||
|
@ -124,7 +124,7 @@ string::~string() {
|
||||||
if(data) free(data);
|
if(data) free(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool string::readfile(const string &filename) {
|
bool string::readfile(const string& filename) {
|
||||||
assign("");
|
assign("");
|
||||||
|
|
||||||
#if !defined(_WIN32)
|
#if !defined(_WIN32)
|
||||||
|
@ -147,14 +147,14 @@ bool string::readfile(const string &filename) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<unsigned> lstring::find(const char *key) const {
|
optional<unsigned> lstring::find(const char* key) const {
|
||||||
for(unsigned i = 0; i < size(); i++) {
|
for(unsigned i = 0; i < size(); i++) {
|
||||||
if(operator[](i) == key) return { true, i };
|
if(operator[](i) == key) return { true, i };
|
||||||
}
|
}
|
||||||
return { false, 0 };
|
return { false, 0 };
|
||||||
}
|
}
|
||||||
|
|
||||||
string lstring::concatenate(const char *separator) const {
|
string lstring::concatenate(const char* separator) const {
|
||||||
string output;
|
string output;
|
||||||
for(unsigned i = 0; i < size(); i++) {
|
for(unsigned i = 0; i < size(); i++) {
|
||||||
output.append(operator[](i), i < size() - 1 ? separator : "");
|
output.append(operator[](i), i < size() - 1 ? separator : "");
|
||||||
|
@ -162,18 +162,26 @@ string lstring::concatenate(const char *separator) const {
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename... Args> void lstring::append(const string &data, Args&&... args) {
|
lstring& lstring::isort() {
|
||||||
|
nall::sort(pool, objectsize, [](const string& x, const string& y) {
|
||||||
|
return istrcmp(x, y) < 0;
|
||||||
|
});
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
lstring& lstring::strip() {
|
||||||
|
for(unsigned n = 0; n < size(); n++) {
|
||||||
|
operator[](n).strip();
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename... Args> void lstring::append(const string& data, Args&&... args) {
|
||||||
vector::append(data);
|
vector::append(data);
|
||||||
append(std::forward<Args>(args)...);
|
append(std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
void lstring::isort() {
|
bool lstring::operator==(const lstring& source) const {
|
||||||
nall::sort(pool, objectsize, [](const string &x, const string &y) {
|
|
||||||
return istrcmp(x, y) < 0;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
bool lstring::operator==(const lstring &source) const {
|
|
||||||
if(this == &source) return true;
|
if(this == &source) return true;
|
||||||
if(size() != source.size()) return false;
|
if(size() != source.size()) return false;
|
||||||
for(unsigned n = 0; n < size(); n++) {
|
for(unsigned n = 0; n < size(); n++) {
|
||||||
|
@ -182,21 +190,21 @@ bool lstring::operator==(const lstring &source) const {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool lstring::operator!=(const lstring &source) const {
|
bool lstring::operator!=(const lstring& source) const {
|
||||||
return !operator==(source);
|
return !operator==(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
lstring& lstring::operator=(const lstring &source) {
|
lstring& lstring::operator=(const lstring& source) {
|
||||||
vector::operator=(source);
|
vector::operator=(source);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
lstring& lstring::operator=(lstring &source) {
|
lstring& lstring::operator=(lstring& source) {
|
||||||
vector::operator=(source);
|
vector::operator=(source);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
lstring& lstring::operator=(lstring &&source) {
|
lstring& lstring::operator=(lstring&& source) {
|
||||||
vector::operator=(std::move(source));
|
vector::operator=(std::move(source));
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
@ -205,15 +213,15 @@ template<typename... Args> lstring::lstring(Args&&... args) {
|
||||||
append(std::forward<Args>(args)...);
|
append(std::forward<Args>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
lstring::lstring(const lstring &source) {
|
lstring::lstring(const lstring& source) {
|
||||||
vector::operator=(source);
|
vector::operator=(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
lstring::lstring(lstring &source) {
|
lstring::lstring(lstring& source) {
|
||||||
vector::operator=(source);
|
vector::operator=(source);
|
||||||
}
|
}
|
||||||
|
|
||||||
lstring::lstring(lstring &&source) {
|
lstring::lstring(lstring&& source) {
|
||||||
vector::operator=(std::move(source));
|
vector::operator=(std::move(source));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,12 +8,12 @@ namespace nall {
|
||||||
|
|
||||||
cstring::operator const char*() const { return data; }
|
cstring::operator const char*() const { return data; }
|
||||||
unsigned cstring::length() const { return strlen(data); }
|
unsigned cstring::length() const { return strlen(data); }
|
||||||
bool cstring::operator==(const char *s) const { return !strcmp(data, s); }
|
bool cstring::operator==(const char* s) const { return !strcmp(data, s); }
|
||||||
bool cstring::operator!=(const char *s) const { return strcmp(data, s); }
|
bool cstring::operator!=(const char* s) const { return strcmp(data, s); }
|
||||||
optional<unsigned> cstring::position (const char *key) const { return strpos(data, key); }
|
optional<unsigned> cstring::position (const char* key) const { return strpos(data, key); }
|
||||||
optional<unsigned> cstring::iposition(const char *key) const { return istrpos(data, key); }
|
optional<unsigned> cstring::iposition(const char* key) const { return istrpos(data, key); }
|
||||||
cstring& cstring::operator=(const char *data) { this->data = data; return *this; }
|
cstring& cstring::operator=(const char* data) { this->data = data; return *this; }
|
||||||
cstring::cstring(const char *data) : data(data) {}
|
cstring::cstring(const char* data) : data(data) {}
|
||||||
cstring::cstring() : data("") {}
|
cstring::cstring() : data("") {}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ namespace nall {
|
||||||
|
|
||||||
string string::date() {
|
string string::date() {
|
||||||
time_t timestamp = ::time(nullptr);
|
time_t timestamp = ::time(nullptr);
|
||||||
tm *info = localtime(×tamp);
|
tm* info = localtime(×tamp);
|
||||||
return {
|
return {
|
||||||
decimal<4, '0'>(1900 + info->tm_year), "-",
|
decimal<4, '0'>(1900 + info->tm_year), "-",
|
||||||
decimal<2, '0'>(1 + info->tm_mon), "-",
|
decimal<2, '0'>(1 + info->tm_mon), "-",
|
||||||
|
@ -14,7 +14,7 @@ string string::date() {
|
||||||
|
|
||||||
string string::time() {
|
string string::time() {
|
||||||
time_t timestamp = ::time(nullptr);
|
time_t timestamp = ::time(nullptr);
|
||||||
tm *info = localtime(×tamp);
|
tm* info = localtime(×tamp);
|
||||||
return {
|
return {
|
||||||
decimal<2, '0'>(info->tm_hour), ":",
|
decimal<2, '0'>(info->tm_hour), ":",
|
||||||
decimal<2, '0'>(info->tm_min), ":",
|
decimal<2, '0'>(info->tm_min), ":",
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
|
|
||||||
template<signed precision, char padchar> string format(const string &value) {
|
template<signed precision, char padchar> string format(const string& value) {
|
||||||
if(precision == 0) return value;
|
if(precision == 0) return value;
|
||||||
|
|
||||||
bool padright = precision >= 0;
|
bool padright = precision >= 0;
|
||||||
|
|
|
@ -14,21 +14,21 @@ protected:
|
||||||
}
|
}
|
||||||
|
|
||||||
//determine indentation level, without incrementing pointer
|
//determine indentation level, without incrementing pointer
|
||||||
unsigned readDepth(const char *p) {
|
unsigned readDepth(const char* p) {
|
||||||
unsigned depth = 0;
|
unsigned depth = 0;
|
||||||
while(p[depth] == '\t' || p[depth] == ' ') depth++;
|
while(p[depth] == '\t' || p[depth] == ' ') depth++;
|
||||||
return depth;
|
return depth;
|
||||||
}
|
}
|
||||||
|
|
||||||
//determine indentation level
|
//determine indentation level
|
||||||
unsigned parseDepth(const char *&p) {
|
unsigned parseDepth(const char*& p) {
|
||||||
unsigned depth = readDepth(p);
|
unsigned depth = readDepth(p);
|
||||||
p += depth;
|
p += depth;
|
||||||
return depth;
|
return depth;
|
||||||
}
|
}
|
||||||
|
|
||||||
//read name
|
//read name
|
||||||
void parseName(const char *&p) {
|
void parseName(const char*& p) {
|
||||||
unsigned length = 0;
|
unsigned length = 0;
|
||||||
while(valid(p[length])) length++;
|
while(valid(p[length])) length++;
|
||||||
if(length == 0) throw "Invalid node name";
|
if(length == 0) throw "Invalid node name";
|
||||||
|
@ -36,7 +36,7 @@ protected:
|
||||||
p += length;
|
p += length;
|
||||||
}
|
}
|
||||||
|
|
||||||
void parseData(const char *&p) {
|
void parseData(const char*& p) {
|
||||||
if(*p == '=' && *(p + 1) == '\"') {
|
if(*p == '=' && *(p + 1) == '\"') {
|
||||||
unsigned length = 2;
|
unsigned length = 2;
|
||||||
while(p[length] && p[length] != '\n' && p[length] != '\"') length++;
|
while(p[length] && p[length] != '\n' && p[length] != '\"') length++;
|
||||||
|
@ -58,7 +58,7 @@ protected:
|
||||||
}
|
}
|
||||||
|
|
||||||
//read all attributes for a node
|
//read all attributes for a node
|
||||||
void parseAttributes(const char *&p) {
|
void parseAttributes(const char*& p) {
|
||||||
while(*p && *p != '\n') {
|
while(*p && *p != '\n') {
|
||||||
if(*p != ' ') throw "Invalid node name";
|
if(*p != ' ') throw "Invalid node name";
|
||||||
while(*p == ' ') p++; //skip excess spaces
|
while(*p == ' ') p++; //skip excess spaces
|
||||||
|
@ -77,8 +77,8 @@ protected:
|
||||||
}
|
}
|
||||||
|
|
||||||
//read a node and all of its child nodes
|
//read a node and all of its child nodes
|
||||||
void parseNode(const lstring &text, unsigned &y) {
|
void parseNode(const lstring& text, unsigned& y) {
|
||||||
const char *p = text[y++];
|
const char* p = text[y++];
|
||||||
level = parseDepth(p);
|
level = parseDepth(p);
|
||||||
parseName(p);
|
parseName(p);
|
||||||
parseData(p);
|
parseData(p);
|
||||||
|
@ -102,8 +102,8 @@ protected:
|
||||||
}
|
}
|
||||||
|
|
||||||
//read top-level nodes
|
//read top-level nodes
|
||||||
void parse(const string &document) {
|
void parse(const string& document) {
|
||||||
lstring text = document.split("\n");
|
lstring text = string{document}.replace("\r", "").split("\n");
|
||||||
|
|
||||||
//remove empty lines and comment lines
|
//remove empty lines and comment lines
|
||||||
for(unsigned y = 0; y < text.size();) {
|
for(unsigned y = 0; y < text.size();) {
|
||||||
|
@ -134,12 +134,12 @@ protected:
|
||||||
struct Document : Node {
|
struct Document : Node {
|
||||||
string error;
|
string error;
|
||||||
|
|
||||||
bool load(const string &document) {
|
bool load(const string& document) {
|
||||||
name = "", data = "";
|
name = "", data = "";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
parse(document);
|
parse(document);
|
||||||
} catch(const char *error) {
|
} catch(const char* error) {
|
||||||
this->error = error;
|
this->error = error;
|
||||||
children.reset();
|
children.reset();
|
||||||
return false;
|
return false;
|
||||||
|
@ -147,7 +147,7 @@ struct Document : Node {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Document(const string &document = "") {
|
Document(const string& document = "") {
|
||||||
load(document);
|
load(document);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
namespace nall {
|
namespace nall {
|
||||||
namespace Markup {
|
namespace Markup {
|
||||||
|
|
||||||
inline Node Document(const string &markup) {
|
inline Node Document(const string& markup) {
|
||||||
if(markup.beginswith("<")) return XML::Document(markup);
|
if(markup.beginswith("<")) return XML::Document(markup);
|
||||||
return BML::Document(markup);
|
return BML::Document(markup);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,11 +32,11 @@ struct Node {
|
||||||
children.reset();
|
children.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool evaluate(const string &query) const {
|
bool evaluate(const string& query) const {
|
||||||
if(query.empty()) return true;
|
if(query.empty()) return true;
|
||||||
lstring rules = string{query}.replace(" ", "").split(",");
|
lstring rules = string{query}.replace(" ", "").split(",");
|
||||||
|
|
||||||
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.wildcard("*!=*")) comparator = Comparator::NE;
|
||||||
|
@ -83,7 +83,7 @@ struct Node {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
vector<Node> find(const string &query) const {
|
vector<Node> find(const string& query) const {
|
||||||
vector<Node> result;
|
vector<Node> result;
|
||||||
|
|
||||||
lstring path = query.split("/");
|
lstring path = query.split("/");
|
||||||
|
@ -105,7 +105,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.wildcard(name) == false) continue;
|
||||||
if(node.evaluate(rule) == false) continue;
|
if(node.evaluate(rule) == false) continue;
|
||||||
|
|
||||||
|
@ -116,22 +116,23 @@ struct Node {
|
||||||
if(path.size() == 0) result.append(node);
|
if(path.size() == 0) result.append(node);
|
||||||
else {
|
else {
|
||||||
auto list = node.find(path.concatenate("/"));
|
auto list = node.find(path.concatenate("/"));
|
||||||
for(auto &item : list) result.append(item);
|
for(auto& item : list) result.append(item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
Node operator[](const string &query) const {
|
Node operator[](const string& query) const {
|
||||||
auto result = find(query);
|
auto result = find(query);
|
||||||
return result(0);
|
return result(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
Node* begin() { return children.begin(); }
|
vector<Node>::iterator begin() { return children.begin(); }
|
||||||
Node* end() { return children.end(); }
|
vector<Node>::iterator end() { return children.end(); }
|
||||||
const Node* begin() const { return children.begin(); }
|
|
||||||
const Node* end() const { return children.end(); }
|
const vector<Node>::const_iterator begin() const { return children.begin(); }
|
||||||
|
const vector<Node>::const_iterator end() const { return children.end(); }
|
||||||
|
|
||||||
Node() : attribute(false), level(0) {}
|
Node() : attribute(false), level(0) {}
|
||||||
|
|
||||||
|
|
|
@ -35,7 +35,7 @@ protected:
|
||||||
}
|
}
|
||||||
|
|
||||||
//copy part of string from source document into target string; decode markup while copying
|
//copy part of string from source document into target string; decode markup while copying
|
||||||
inline void copy(string &target, const char *source, unsigned length) {
|
inline void copy(string& target, const char* source, unsigned length) {
|
||||||
target.reserve(length + 1);
|
target.reserve(length + 1);
|
||||||
|
|
||||||
#if defined(NALL_XML_LITERAL)
|
#if defined(NALL_XML_LITERAL)
|
||||||
|
@ -44,7 +44,7 @@ protected:
|
||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
char *output = target();
|
char* output = target();
|
||||||
while(length) {
|
while(length) {
|
||||||
if(*source == '&') {
|
if(*source == '&') {
|
||||||
if(!memcmp(source, "<", 4)) { *output++ = '<'; source += 4; length -= 4; continue; }
|
if(!memcmp(source, "<", 4)) { *output++ = '<'; source += 4; length -= 4; continue; }
|
||||||
|
@ -77,7 +77,7 @@ protected:
|
||||||
*output = 0;
|
*output = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool parseExpression(const char *&p) {
|
inline bool parseExpression(const char*& p) {
|
||||||
if(*(p + 1) != '!') return false;
|
if(*(p + 1) != '!') return false;
|
||||||
|
|
||||||
//comment
|
//comment
|
||||||
|
@ -112,11 +112,11 @@ protected:
|
||||||
}
|
}
|
||||||
|
|
||||||
//returns true if tag closes itself (<tag/>); false if not (<tag>)
|
//returns true if tag closes itself (<tag/>); false if not (<tag>)
|
||||||
inline bool parseHead(const char *&p) {
|
inline bool parseHead(const char*& p) {
|
||||||
//parse name
|
//parse name
|
||||||
const char *nameStart = ++p; //skip '<'
|
const char* nameStart = ++p; //skip '<'
|
||||||
while(isName(*p)) p++;
|
while(isName(*p)) p++;
|
||||||
const char *nameEnd = p;
|
const char* nameEnd = p;
|
||||||
copy(name, nameStart, nameEnd - nameStart);
|
copy(name, nameStart, nameEnd - nameStart);
|
||||||
if(name.empty()) throw "missing element name";
|
if(name.empty()) throw "missing element name";
|
||||||
|
|
||||||
|
@ -130,9 +130,9 @@ protected:
|
||||||
Node attribute;
|
Node attribute;
|
||||||
attribute.attribute = true;
|
attribute.attribute = true;
|
||||||
|
|
||||||
const char *nameStart = p;
|
const char* nameStart = p;
|
||||||
while(isName(*p)) p++;
|
while(isName(*p)) p++;
|
||||||
const char *nameEnd = p;
|
const char* nameEnd = p;
|
||||||
copy(attribute.name, nameStart, nameEnd - nameStart);
|
copy(attribute.name, nameStart, nameEnd - nameStart);
|
||||||
if(attribute.name.empty()) throw "missing attribute name";
|
if(attribute.name.empty()) throw "missing attribute name";
|
||||||
|
|
||||||
|
@ -140,10 +140,10 @@ protected:
|
||||||
if(*p++ != '=') throw "missing attribute value";
|
if(*p++ != '=') throw "missing attribute value";
|
||||||
char terminal = *p++;
|
char terminal = *p++;
|
||||||
if(terminal != '\'' && terminal != '\"') throw "attribute value not quoted";
|
if(terminal != '\'' && terminal != '\"') throw "attribute value not quoted";
|
||||||
const char *dataStart = p;
|
const char* dataStart = p;
|
||||||
while(*p && *p != terminal) p++;
|
while(*p && *p != terminal) p++;
|
||||||
if(!*p) throw "missing attribute data terminal";
|
if(!*p) throw "missing attribute data terminal";
|
||||||
const char *dataEnd = p++; //skip closing terminal
|
const char* dataEnd = p++; //skip closing terminal
|
||||||
|
|
||||||
copy(attribute.data, dataStart, dataEnd - dataStart);
|
copy(attribute.data, dataStart, dataEnd - dataStart);
|
||||||
children.append(attribute);
|
children.append(attribute);
|
||||||
|
@ -157,27 +157,28 @@ protected:
|
||||||
}
|
}
|
||||||
|
|
||||||
//parse element and all of its child elements
|
//parse element and all of its child elements
|
||||||
inline void parseElement(const char *&p) {
|
inline void parseElement(const char*& p) {
|
||||||
Node node;
|
Node node;
|
||||||
if(node.parseHead(p) == false) node.parse(p);
|
if(node.parseHead(p) == false) node.parse(p);
|
||||||
children.append(node);
|
children.append(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
//return true if </tag> matches this node's name
|
//return true if </tag> matches this node's name
|
||||||
inline bool parseClosureElement(const char *&p) {
|
inline bool parseClosureElement(const char*& p) {
|
||||||
if(p[0] != '<' || p[1] != '/') return false;
|
if(p[0] != '<' || p[1] != '/') return false;
|
||||||
p += 2;
|
p += 2;
|
||||||
const char *nameStart = p;
|
const char* nameStart = p;
|
||||||
while(*p && *p != '>') p++;
|
while(*p && *p != '>') p++;
|
||||||
if(*p != '>') throw "unclosed closure element";
|
if(*p != '>') throw "unclosed closure element";
|
||||||
const char *nameEnd = p++;
|
const char* nameEnd = p++;
|
||||||
if(memcmp(name, nameStart, nameEnd - nameStart)) throw "closure element name mismatch";
|
if(memcmp(name, nameStart, nameEnd - nameStart)) throw "closure element name mismatch";
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//parse contents of an element
|
//parse contents of an element
|
||||||
inline void parse(const char *&p) {
|
inline void parse(const char*& p) {
|
||||||
const char *dataStart = p, *dataEnd = p;
|
const char* dataStart = p;
|
||||||
|
const char* dataEnd = p;
|
||||||
|
|
||||||
while(*p) {
|
while(*p) {
|
||||||
while(*p && *p != '<') p++;
|
while(*p && *p != '<') p++;
|
||||||
|
@ -195,12 +196,12 @@ protected:
|
||||||
struct Document : Node {
|
struct Document : Node {
|
||||||
string error;
|
string error;
|
||||||
|
|
||||||
inline bool load(const char *document) {
|
inline bool load(const char* document) {
|
||||||
if(document == nullptr) return false;
|
if(document == nullptr) return false;
|
||||||
reset();
|
reset();
|
||||||
try {
|
try {
|
||||||
parse(document);
|
parse(document);
|
||||||
} catch(const char *error) {
|
} catch(const char* error) {
|
||||||
reset();
|
reset();
|
||||||
this->error = error;
|
this->error = error;
|
||||||
return false;
|
return false;
|
||||||
|
@ -209,7 +210,7 @@ struct Document : Node {
|
||||||
}
|
}
|
||||||
|
|
||||||
inline Document() {}
|
inline Document() {}
|
||||||
inline Document(const char *document) { load(document); }
|
inline Document(const char* document) { load(document); }
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,9 +2,9 @@
|
||||||
|
|
||||||
namespace fixedpoint {
|
namespace fixedpoint {
|
||||||
|
|
||||||
static nall::function<intmax_t (const char *&)> eval_fallback;
|
static nall::function<intmax_t (const char*&)> eval_fallback;
|
||||||
|
|
||||||
static intmax_t eval_integer(const char *& s) {
|
static intmax_t eval_integer(const char*& s) {
|
||||||
if(!*s) throw "unrecognized integer";
|
if(!*s) throw "unrecognized integer";
|
||||||
intmax_t value = 0, x = *s, y = *(s + 1);
|
intmax_t value = 0, x = *s, y = *(s + 1);
|
||||||
|
|
||||||
|
@ -58,7 +58,7 @@ static intmax_t eval_integer(const char *& s) {
|
||||||
throw "unrecognized integer";
|
throw "unrecognized integer";
|
||||||
}
|
}
|
||||||
|
|
||||||
static intmax_t eval(const char *&s, int depth = 0) {
|
static intmax_t eval(const char*& s, int depth = 0) {
|
||||||
while(*s == ' ' || *s == '\t') s++; //trim whitespace
|
while(*s == ' ' || *s == '\t') s++; //trim whitespace
|
||||||
if(!*s) throw "unrecognized token";
|
if(!*s) throw "unrecognized token";
|
||||||
intmax_t value = 0, x = *s, y = *(s + 1);
|
intmax_t value = 0, x = *s, y = *(s + 1);
|
||||||
|
@ -142,7 +142,7 @@ static intmax_t eval(const char *&s, int depth = 0) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool eval(const char *s, intmax_t &result) {
|
static bool eval(const char* s, intmax_t &result) {
|
||||||
try {
|
try {
|
||||||
result = eval(s);
|
result = eval(s);
|
||||||
return true;
|
return true;
|
||||||
|
@ -152,11 +152,11 @@ static bool eval(const char *s, intmax_t &result) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static intmax_t parse(const char *s) {
|
static intmax_t parse(const char* s) {
|
||||||
try {
|
try {
|
||||||
intmax_t result = eval(s);
|
intmax_t result = eval(s);
|
||||||
return result;
|
return result;
|
||||||
} catch(const char *) {
|
} catch(const char*) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,9 +2,9 @@
|
||||||
|
|
||||||
namespace floatingpoint {
|
namespace floatingpoint {
|
||||||
|
|
||||||
static nall::function<double (const char *&)> eval_fallback;
|
static nall::function<double (const char*&)> eval_fallback;
|
||||||
|
|
||||||
static double eval_integer(const char *&s) {
|
static double eval_integer(const char*& s) {
|
||||||
if(!*s) throw "unrecognized integer";
|
if(!*s) throw "unrecognized integer";
|
||||||
intmax_t value = 0, radix = 0, x = *s, y = *(s + 1);
|
intmax_t value = 0, radix = 0, x = *s, y = *(s + 1);
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ static double eval_integer(const char *&s) {
|
||||||
throw "unrecognized integer";
|
throw "unrecognized integer";
|
||||||
}
|
}
|
||||||
|
|
||||||
static double eval(const char *&s, int depth = 0) {
|
static double eval(const char*& s, int depth = 0) {
|
||||||
while(*s == ' ' || *s == '\t') s++; //trim whitespace
|
while(*s == ' ' || *s == '\t') s++; //trim whitespace
|
||||||
if(!*s) throw "unrecognized token";
|
if(!*s) throw "unrecognized token";
|
||||||
double value = 0, x = *s, y = *(s + 1);
|
double value = 0, x = *s, y = *(s + 1);
|
||||||
|
@ -133,21 +133,21 @@ static double eval(const char *&s, int depth = 0) {
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool eval(const char *s, double &result) {
|
static bool eval(const char* s, double& result) {
|
||||||
try {
|
try {
|
||||||
result = eval(s);
|
result = eval(s);
|
||||||
return true;
|
return true;
|
||||||
} catch(const char*e) {
|
} catch(const char*) {
|
||||||
result = 0;
|
result = 0;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static double parse(const char *s) {
|
static double parse(const char* s) {
|
||||||
try {
|
try {
|
||||||
double result = eval(s);
|
double result = eval(s);
|
||||||
return result;
|
return result;
|
||||||
} catch(const char *) {
|
} catch(const char*) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,7 @@ string activepath() {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
string realpath(const string &name) {
|
string realpath(const string& name) {
|
||||||
string result;
|
string result;
|
||||||
#if defined(PLATFORM_WINDOWS)
|
#if defined(PLATFORM_WINDOWS)
|
||||||
wchar_t path[PATH_MAX] = L"";
|
wchar_t path[PATH_MAX] = L"";
|
||||||
|
|
|
@ -3,11 +3,11 @@
|
||||||
namespace nall {
|
namespace nall {
|
||||||
|
|
||||||
template<unsigned Limit, bool Insensitive, bool Quoted>
|
template<unsigned Limit, bool Insensitive, bool Quoted>
|
||||||
string& string::ureplace(const char *key, const char *token) {
|
string& string::ureplace(const char* key, const char* token) {
|
||||||
if(!key || !*key) return *this;
|
if(!key || !*key) return *this;
|
||||||
enum : unsigned { limit = Limit ? Limit : ~0u };
|
enum : unsigned { limit = Limit ? Limit : ~0u };
|
||||||
|
|
||||||
const char *p = data;
|
const char* p = data;
|
||||||
unsigned counter = 0, keyLength = 0;
|
unsigned counter = 0, keyLength = 0;
|
||||||
|
|
||||||
while(*p) {
|
while(*p) {
|
||||||
|
@ -20,13 +20,14 @@ string& string::ureplace(const char *key, const char *token) {
|
||||||
if(counter == 0) return *this;
|
if(counter == 0) return *this;
|
||||||
if(Limit) counter = min(counter, Limit);
|
if(Limit) counter = min(counter, Limit);
|
||||||
|
|
||||||
char *t = data, *base;
|
char* t = data;
|
||||||
|
char* base;
|
||||||
unsigned tokenLength = strlen(token);
|
unsigned tokenLength = strlen(token);
|
||||||
if(tokenLength > keyLength) {
|
if(tokenLength > keyLength) {
|
||||||
t = base = strdup(data);
|
t = base = strdup(data);
|
||||||
reserve((unsigned)(p - data) + ((tokenLength - keyLength) * counter));
|
reserve((unsigned)(p - data) + ((tokenLength - keyLength) * counter));
|
||||||
}
|
}
|
||||||
char *o = data;
|
char* o = data;
|
||||||
|
|
||||||
while(*t && counter) {
|
while(*t && counter) {
|
||||||
if(quotecopy<Quoted>(o, t)) continue;
|
if(quotecopy<Quoted>(o, t)) continue;
|
||||||
|
@ -41,10 +42,10 @@ string& string::ureplace(const char *key, const char *token) {
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<unsigned Limit> string &string::replace(const char *key, const char *token) { return ureplace<Limit, false, false>(key, token); }
|
template<unsigned Limit> string& string::replace(const char* key, const char* token) { return ureplace<Limit, false, false>(key, token); }
|
||||||
template<unsigned Limit> string &string::ireplace(const char *key, const char *token) { return ureplace<Limit, true, false>(key, token); }
|
template<unsigned Limit> string& string::ireplace(const char* key, const char* token) { return ureplace<Limit, true, false>(key, token); }
|
||||||
template<unsigned Limit> string &string::qreplace(const char *key, const char *token) { return ureplace<Limit, false, true>(key, token); }
|
template<unsigned Limit> string& string::qreplace(const char* key, const char* token) { return ureplace<Limit, false, true>(key, token); }
|
||||||
template<unsigned Limit> string &string::iqreplace(const char *key, const char *token) { return ureplace<Limit, true, true>(key, token); }
|
template<unsigned Limit> string& string::iqreplace(const char* key, const char* token) { return ureplace<Limit, true, true>(key, token); }
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -2,11 +2,11 @@
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
|
|
||||||
template<unsigned Limit, bool Insensitive, bool Quoted> lstring& lstring::usplit(const char *key, const char *base) {
|
template<unsigned Limit, bool Insensitive, bool Quoted> lstring& lstring::usplit(const char* key, const char* base) {
|
||||||
reset();
|
reset();
|
||||||
if(!key || !*key) return *this;
|
if(!key || !*key) return *this;
|
||||||
|
|
||||||
const char *p = base;
|
const char* p = base;
|
||||||
|
|
||||||
while(*p) {
|
while(*p) {
|
||||||
if(Limit) if(size() >= Limit) break;
|
if(Limit) if(size() >= Limit) break;
|
||||||
|
@ -26,10 +26,10 @@ template<unsigned Limit, bool Insensitive, bool Quoted> lstring& lstring::usplit
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<unsigned Limit> lstring& lstring::split(const char *key, const char *src) { return usplit<Limit, false, false>(key, src); }
|
template<unsigned Limit> lstring& lstring::split(const char* key, const char* src) { return usplit<Limit, false, false>(key, src); }
|
||||||
template<unsigned Limit> lstring& lstring::isplit(const char *key, const char *src) { return usplit<Limit, true, false>(key, src); }
|
template<unsigned Limit> lstring& lstring::isplit(const char* key, const char* src) { return usplit<Limit, true, false>(key, src); }
|
||||||
template<unsigned Limit> lstring& lstring::qsplit(const char *key, const char *src) { return usplit<Limit, false, true>(key, src); }
|
template<unsigned Limit> lstring& lstring::qsplit(const char* key, const char* src) { return usplit<Limit, false, true>(key, src); }
|
||||||
template<unsigned Limit> lstring& lstring::iqsplit(const char *key, const char *src) { return usplit<Limit, true, true>(key, src); }
|
template<unsigned Limit> lstring& lstring::iqsplit(const char* key, const char* src) { return usplit<Limit, true, true>(key, src); }
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
|
|
||||||
string string::read(const string &filename) {
|
string string::read(const string& filename) {
|
||||||
string data;
|
string data;
|
||||||
data.readfile(filename);
|
data.readfile(filename);
|
||||||
return data;
|
return data;
|
||||||
|
|
|
@ -2,13 +2,9 @@
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
|
|
||||||
//
|
|
||||||
//strmcpy, strmcat created by byuu
|
|
||||||
//
|
|
||||||
|
|
||||||
//return = strlen(target)
|
//return = strlen(target)
|
||||||
unsigned strmcpy(char *target, const char *source, unsigned length) {
|
unsigned strmcpy(char* target, const char* source, unsigned length) {
|
||||||
const char *origin = target;
|
const char* origin = target;
|
||||||
if(length) {
|
if(length) {
|
||||||
while(*source && --length) *target++ = *source++;
|
while(*source && --length) *target++ = *source++;
|
||||||
*target = 0;
|
*target = 0;
|
||||||
|
@ -17,25 +13,25 @@ unsigned strmcpy(char *target, const char *source, unsigned length) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//return = strlen(target)
|
//return = strlen(target)
|
||||||
unsigned strmcat(char *target, const char *source, unsigned length) {
|
unsigned strmcat(char* target, const char* source, unsigned length) {
|
||||||
const char *origin = target;
|
const char* origin = target;
|
||||||
while(*target && length) target++, length--;
|
while(*target && length) target++, length--;
|
||||||
return (target - origin) + strmcpy(target, source, length);
|
return (target - origin) + strmcpy(target, source, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
//return = true when all of source was copied
|
//return = true when all of source was copied
|
||||||
bool strccpy(char *target, const char *source, unsigned length) {
|
bool strccpy(char* target, const char* source, unsigned length) {
|
||||||
return !source[strmcpy(target, source, length)];
|
return !source[strmcpy(target, source, length)];
|
||||||
}
|
}
|
||||||
|
|
||||||
//return = true when all of source was copied
|
//return = true when all of source was copied
|
||||||
bool strccat(char *target, const char *source, unsigned length) {
|
bool strccat(char* target, const char* source, unsigned length) {
|
||||||
while(*target && length) target++, length--;
|
while(*target && length) target++, length--;
|
||||||
return !source[strmcpy(target, source, length)];
|
return !source[strmcpy(target, source, length)];
|
||||||
}
|
}
|
||||||
|
|
||||||
//return = reserved for future use
|
//return = reserved for future use
|
||||||
void strpcpy(char *&target, const char *source, unsigned &length) {
|
void strpcpy(char*& target, const char* source, unsigned& length) {
|
||||||
unsigned offset = strmcpy(target, source, length);
|
unsigned offset = strmcpy(target, source, length);
|
||||||
target += offset, length -= offset;
|
target += offset, length -= offset;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,26 +7,26 @@
|
||||||
namespace nall {
|
namespace nall {
|
||||||
|
|
||||||
template<bool Insensitive, bool Quoted>
|
template<bool Insensitive, bool Quoted>
|
||||||
optional<unsigned> ustrpos(const char *str, const char *key) {
|
optional<unsigned> ustrpos(const char* str, const char* key) {
|
||||||
const char *base = str;
|
const char* base = str;
|
||||||
|
|
||||||
while(*str) {
|
while(*str) {
|
||||||
if(quoteskip<Quoted>(str)) continue;
|
if(quoteskip<Quoted>(str)) continue;
|
||||||
for(unsigned n = 0;; n++) {
|
for(unsigned n = 0;; n++) {
|
||||||
if(key[n] == 0) return { true, (unsigned)(str - base) };
|
if(key[n] == 0) return {true, (unsigned)(str - base)};
|
||||||
if(str[n] == 0) return { false, 0 };
|
if(str[n] == 0) return false;
|
||||||
if(!chrequal<Insensitive>(str[n], key[n])) break;
|
if(!chrequal<Insensitive>(str[n], key[n])) break;
|
||||||
}
|
}
|
||||||
str++;
|
str++;
|
||||||
}
|
}
|
||||||
|
|
||||||
return { false, 0 };
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
optional<unsigned> strpos(const char *str, const char *key) { return ustrpos<false, false>(str, key); }
|
optional<unsigned> strpos(const char* str, const char* key) { return ustrpos<false, false>(str, key); }
|
||||||
optional<unsigned> istrpos(const char *str, const char *key) { return ustrpos<true, false>(str, key); }
|
optional<unsigned> istrpos(const char* str, const char* key) { return ustrpos<true, false>(str, key); }
|
||||||
optional<unsigned> qstrpos(const char *str, const char *key) { return ustrpos<false, true>(str, key); }
|
optional<unsigned> qstrpos(const char* str, const char* key) { return ustrpos<false, true>(str, key); }
|
||||||
optional<unsigned> iqstrpos(const char *str, const char *key) { return ustrpos<true, true>(str, key); }
|
optional<unsigned> iqstrpos(const char* str, const char* key) { return ustrpos<true, true>(str, key); }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,11 +3,12 @@
|
||||||
namespace nall {
|
namespace nall {
|
||||||
|
|
||||||
//limit defaults to zero, which will underflow on first compare; equivalent to no limit
|
//limit defaults to zero, which will underflow on first compare; equivalent to no limit
|
||||||
template<unsigned Limit> char* ltrim(char *str, const char *key) {
|
template<unsigned Limit> char* ltrim(char* str, const char* key) {
|
||||||
unsigned limit = Limit;
|
unsigned limit = Limit;
|
||||||
if(!key || !*key) return str;
|
if(!key || !*key) return str;
|
||||||
while(strbegin(str, key)) {
|
while(strbegin(str, key)) {
|
||||||
char *dest = str, *src = str + strlen(key);
|
char* dest = str;
|
||||||
|
char* src = str + strlen(key);
|
||||||
while(true) {
|
while(true) {
|
||||||
*dest = *src++;
|
*dest = *src++;
|
||||||
if(!*dest) break;
|
if(!*dest) break;
|
||||||
|
@ -18,7 +19,7 @@ template<unsigned Limit> char* ltrim(char *str, const char *key) {
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<unsigned Limit> char* rtrim(char *str, const char *key) {
|
template<unsigned Limit> char* rtrim(char* str, const char* key) {
|
||||||
unsigned limit = Limit;
|
unsigned limit = Limit;
|
||||||
if(!key || !*key) return str;
|
if(!key || !*key) return str;
|
||||||
while(strend(str, key)) {
|
while(strend(str, key)) {
|
||||||
|
@ -28,13 +29,13 @@ 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, const char* rkey) {
|
||||||
if(rkey) return ltrim<limit>(rtrim<limit>(str, rkey), 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
//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) {
|
||||||
signed n = 0, p = 0;
|
signed n = 0, p = 0;
|
||||||
while(s[n]) {
|
while(s[n]) {
|
||||||
if(s[n] != ' ' && s[n] != '\t' && s[n] != '\r' && s[n] != '\n') break;
|
if(s[n] != ' ' && s[n] != '\t' && s[n] != '\r' && s[n] != '\n') break;
|
||||||
|
|
|
@ -8,7 +8,7 @@ struct UTF8 {
|
||||||
unsigned codepoint; //decoded codepoint
|
unsigned codepoint; //decoded codepoint
|
||||||
};
|
};
|
||||||
|
|
||||||
inline UTF8 utf8_read(const char *s) {
|
inline UTF8 utf8_read(const char* s) {
|
||||||
UTF8 utf8;
|
UTF8 utf8;
|
||||||
|
|
||||||
if((*s & 0xfe) == 0xfc) utf8.size = 6;
|
if((*s & 0xfe) == 0xfc) utf8.size = 6;
|
||||||
|
@ -32,7 +32,7 @@ inline UTF8 utf8_read(const char *s) {
|
||||||
return utf8;
|
return utf8;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void utf8_write(char *s, const UTF8 &utf8) {
|
inline void utf8_write(char* s, const UTF8& utf8) {
|
||||||
for(signed n = utf8.size - 1, shift = 0; n >= 0; n--, shift += 8) {
|
for(signed n = utf8.size - 1, shift = 0; n >= 0; n--, shift += 8) {
|
||||||
s[n] = utf8.data >> shift;
|
s[n] = utf8.data >> shift;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ bool chrequal(char x, char y) {
|
||||||
}
|
}
|
||||||
|
|
||||||
template<bool Quoted, typename T>
|
template<bool Quoted, typename T>
|
||||||
bool quoteskip(T *&p) {
|
bool quoteskip(T*& p) {
|
||||||
if(Quoted == false) return false;
|
if(Quoted == false) return false;
|
||||||
if(*p != '\'' && *p != '\"') return false;
|
if(*p != '\'' && *p != '\"') return false;
|
||||||
|
|
||||||
|
@ -21,7 +21,7 @@ bool quoteskip(T *&p) {
|
||||||
}
|
}
|
||||||
|
|
||||||
template<bool Quoted, typename T>
|
template<bool Quoted, typename T>
|
||||||
bool quotecopy(char *&t, T *&p) {
|
bool quotecopy(char*& t, T*& p) {
|
||||||
if(Quoted == false) return false;
|
if(Quoted == false) return false;
|
||||||
if(*p != '\'' && *p != '\"') return false;
|
if(*p != '\'' && *p != '\"') return false;
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ bool quotecopy(char *&t, T *&p) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
string substr(const char *src, unsigned start, unsigned length) {
|
string substr(const char* src, unsigned start, unsigned length) {
|
||||||
string dest;
|
string dest;
|
||||||
if(length == ~0u) {
|
if(length == ~0u) {
|
||||||
//copy entire string
|
//copy entire string
|
||||||
|
@ -48,7 +48,7 @@ string substr(const char *src, unsigned start, unsigned length) {
|
||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
|
|
||||||
string sha256(const uint8_t *data, unsigned size) {
|
string sha256(const uint8_t* data, unsigned size) {
|
||||||
sha256_ctx sha;
|
sha256_ctx sha;
|
||||||
uint8_t hash[32];
|
uint8_t hash[32];
|
||||||
sha256_init(&sha);
|
sha256_init(&sha);
|
||||||
|
@ -62,7 +62,7 @@ string sha256(const uint8_t *data, unsigned size) {
|
||||||
|
|
||||||
/* cast.hpp arithmetic -> string */
|
/* cast.hpp arithmetic -> string */
|
||||||
|
|
||||||
char* integer(char *result, intmax_t value) {
|
char* integer(char* result, intmax_t value) {
|
||||||
bool negative = value < 0;
|
bool negative = value < 0;
|
||||||
if(negative) value = -value;
|
if(negative) value = -value;
|
||||||
|
|
||||||
|
@ -82,7 +82,7 @@ char* integer(char *result, intmax_t value) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
char* decimal(char *result, uintmax_t value) {
|
char* decimal(char* result, uintmax_t value) {
|
||||||
char buffer[64];
|
char buffer[64];
|
||||||
unsigned size = 0;
|
unsigned size = 0;
|
||||||
|
|
||||||
|
@ -204,7 +204,7 @@ template<unsigned length_, char padding> string ldecimal(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 fp(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()
|
||||||
|
@ -214,9 +214,9 @@ unsigned fp(char *str, long double value) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//remove excess 0's in fraction (2.500000 -> 2.5)
|
//remove excess 0's in fraction (2.500000 -> 2.5)
|
||||||
for(char *p = buffer; *p; p++) {
|
for(char* p = buffer; *p; p++) {
|
||||||
if(*p == '.') {
|
if(*p == '.') {
|
||||||
char *p = buffer + strlen(buffer) - 1;
|
char* p = buffer + strlen(buffer) - 1;
|
||||||
while(*p == '0') {
|
while(*p == '0') {
|
||||||
if(*(p - 1) != '.') *p = 0; //... but not for eg 1.0 -> 1.
|
if(*(p - 1) != '.') *p = 0; //... but not for eg 1.0 -> 1.
|
||||||
p--;
|
p--;
|
||||||
|
|
|
@ -2,8 +2,9 @@
|
||||||
|
|
||||||
namespace nall {
|
namespace nall {
|
||||||
|
|
||||||
bool wildcard(const char *s, const char *p) {
|
bool wildcard(const char* s, const char* p) {
|
||||||
const char *cp = nullptr, *mp = nullptr;
|
const char* cp = nullptr;
|
||||||
|
const char* mp = nullptr;
|
||||||
while(*s && *p != '*') {
|
while(*s && *p != '*') {
|
||||||
if(*p != '?' && *s != *p) return false;
|
if(*p != '?' && *s != *p) return false;
|
||||||
p++, s++;
|
p++, s++;
|
||||||
|
@ -22,8 +23,9 @@ bool wildcard(const char *s, const char *p) {
|
||||||
return !*p;
|
return !*p;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool iwildcard(const char *s, const char *p) {
|
bool iwildcard(const char* s, const char* p) {
|
||||||
const char *cp = nullptr, *mp = nullptr;
|
const char* cp = nullptr;
|
||||||
|
const char* mp = nullptr;
|
||||||
while(*s && *p != '*') {
|
while(*s && *p != '*') {
|
||||||
if(*p != '?' && chrlower(*s) != chrlower(*p)) return false;
|
if(*p != '?' && chrlower(*s) != chrlower(*p)) return false;
|
||||||
p++, s++;
|
p++, s++;
|
||||||
|
@ -42,7 +44,7 @@ bool iwildcard(const char *s, const char *p) {
|
||||||
return !*p;
|
return !*p;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool tokenize(const char *s, const char *p) {
|
inline bool tokenize(const char* s, const char* p) {
|
||||||
while(*s) {
|
while(*s) {
|
||||||
if(*p == '*') {
|
if(*p == '*') {
|
||||||
while(*s) if(tokenize(s++, p + 1)) return true;
|
while(*s) if(tokenize(s++, p + 1)) return true;
|
||||||
|
@ -54,10 +56,10 @@ inline bool tokenize(const char *s, const char *p) {
|
||||||
return !*p;
|
return !*p;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool tokenize(lstring &list, const char *s, const char *p) {
|
inline bool tokenize(lstring &list, const char* s, const char* p) {
|
||||||
while(*s) {
|
while(*s) {
|
||||||
if(*p == '*') {
|
if(*p == '*') {
|
||||||
const char *b = s;
|
const char* b = s;
|
||||||
while(*s) {
|
while(*s) {
|
||||||
if(tokenize(list, s++, p + 1)) {
|
if(tokenize(list, s++, p + 1)) {
|
||||||
list.prepend(substr(b, 0, --s - b));
|
list.prepend(substr(b, 0, --s - b));
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue