mirror of https://github.com/bsnes-emu/bsnes.git
Update to v098r10 release.
byuu says: Changelog: - synchronized tomoko, loki, icarus with extensive changes to nall (118KiB diff)
This commit is contained in:
parent
6ae0abe3d3
commit
3ebc77c148
|
@ -8,7 +8,7 @@ using namespace nall;
|
|||
|
||||
namespace Emulator {
|
||||
static const string Name = "higan";
|
||||
static const string Version = "098.09";
|
||||
static const string Version = "098.10";
|
||||
static const string Author = "byuu";
|
||||
static const string License = "GPLv3";
|
||||
static const string Website = "http://byuu.org/";
|
||||
|
|
|
@ -406,7 +406,7 @@ auto ARM::disassemble_arm_instruction(uint32 pc) -> string {
|
|||
output.append(load ? "ldm" : "stm", conditions[condition], indices[index], " ");
|
||||
output.append(registers[rn], writeback ? "!" : "", ",{");
|
||||
for(unsigned n = 0; n < 16; n++) if(list & (1 << n)) output.append(registers[n], ",");
|
||||
output.rtrim(",");
|
||||
output.trimRight(",", 1L);
|
||||
output.append("}", s ? "^" : "");
|
||||
|
||||
return output;
|
||||
|
@ -679,7 +679,7 @@ auto ARM::disassemble_thumb_instruction(uint32 pc) -> string {
|
|||
if(list & (1 << l)) output.append(registers[l], ",");
|
||||
}
|
||||
if(branch) output.append(load == 0 ? "lr," : "pc,");
|
||||
output.rtrim(",");
|
||||
output.trimRight(",", 1L);
|
||||
output.append("}");
|
||||
|
||||
return output;
|
||||
|
@ -696,7 +696,7 @@ auto ARM::disassemble_thumb_instruction(uint32 pc) -> string {
|
|||
for(unsigned l = 0; l < 8; l++) {
|
||||
if(list & (1 << l)) output.append(registers[l], ",");
|
||||
}
|
||||
output.rtrim(",");
|
||||
output.trimRight(",", 1L);
|
||||
output.append("}");
|
||||
|
||||
return output;
|
||||
|
|
|
@ -378,7 +378,7 @@ auto V30MZ::disassemble(uint16 cs, uint16 ip, bool registers, bool bytes) -> str
|
|||
while(bytesRead) {
|
||||
b.append(hex(bytesRead.takeLeft(), 2L), " ");
|
||||
}
|
||||
b.rstrip();
|
||||
b.stripRight();
|
||||
}
|
||||
|
||||
return {hex(ea, 5L), " ", s, l, b};
|
||||
|
|
|
@ -5,14 +5,14 @@ unique_pointer<Input> input;
|
|||
Emulator::Interface* emulator = nullptr;
|
||||
|
||||
auto locate(string name) -> string {
|
||||
string location = {programpath(), name};
|
||||
string location = {Path::program(), name};
|
||||
if(inode::exists(location)) return location;
|
||||
|
||||
location = {configpath(), "loki/", name};
|
||||
location = {Path::config(), "loki/", name};
|
||||
if(inode::exists(location)) return location;
|
||||
|
||||
directory::create({localpath(), "loki/"});
|
||||
return {localpath(), "loki/", name};
|
||||
directory::create({Path::local(), "loki/"});
|
||||
return {Path::local(), "loki/", name};
|
||||
}
|
||||
|
||||
#include <nall/main.hpp>
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
auto Program::loadRequest(uint id, string name, string type, bool required) -> void {
|
||||
string location = BrowserDialog()
|
||||
.setTitle({"Load ", name})
|
||||
.setPath({userpath(), "Emulation/", name})
|
||||
.setPath({Path::user(), "Emulation/", name})
|
||||
.setFilters({string{name, "|*.", type}})
|
||||
.openFolder();
|
||||
if(!directory::exists(location)) return;
|
||||
|
@ -18,7 +18,7 @@ auto Program::loadRequest(uint id, string filename, bool required) -> void {
|
|||
if(filename == "manifest.bml" && pathname && !pathname.endsWith("sys/")) {
|
||||
if(!file::exists(location)) {
|
||||
if(auto manifest = execute("icarus", "--manifest", pathname)) {
|
||||
memorystream stream{(const uint8_t*)manifest.data(), manifest.size()};
|
||||
memorystream stream{manifest.output.data<uint8_t>(), manifest.output.size()};
|
||||
return emulator->load(id, stream);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ auto Program::loadMedia(string location) -> void {
|
|||
if(!location.endsWith("/")) location.append("/");
|
||||
if(!directory::exists(location)) return;
|
||||
|
||||
string type = suffixname(location).ltrim(".", 1L);
|
||||
string type = suffixname(location).trimLeft(".", 1L);
|
||||
for(auto& media : emulator->media) {
|
||||
if(!media.bootable) continue;
|
||||
if(media.type != type) continue;
|
||||
|
|
|
@ -34,7 +34,7 @@ Program::Program(lstring args) {
|
|||
|
||||
string location = args(1, "");
|
||||
if(!directory::exists(location)) location = { //quick testing hack
|
||||
userpath(), "Emulation/Super Famicom/",
|
||||
Path::user(), "Emulation/Super Famicom/",
|
||||
"Legend of Zelda - A Link to the Past, The (USA) (1.0).sfc/"
|
||||
};
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@ Settings::Settings() {
|
|||
|
||||
set("UserInterface/ShowStatusBar", true);
|
||||
|
||||
set("Library/Location", {userpath(), "Emulation/"});
|
||||
set("Library/Location", {Path::user(), "Emulation/"});
|
||||
set("Library/IgnoreManifests", false);
|
||||
|
||||
set("Video/Driver", ruby::Video::optimalDriver());
|
||||
|
|
|
@ -24,12 +24,12 @@ Presentation::Presentation() {
|
|||
}
|
||||
}
|
||||
//add icarus menu options -- but only if icarus binary is present
|
||||
if(execute("icarus", "--name").strip() == "icarus") {
|
||||
if(execute("icarus", "--name").output.strip() == "icarus") {
|
||||
libraryMenu.append(MenuSeparator());
|
||||
libraryMenu.append(MenuItem().setText("Load ROM File ...").onActivate([&] {
|
||||
audio->clear();
|
||||
if(auto location = execute("icarus", "--import")) {
|
||||
program->loadMedia(location.strip());
|
||||
program->loadMedia(location.output.strip());
|
||||
}
|
||||
}));
|
||||
libraryMenu.append(MenuItem().setText("Import ROM Files ...").onActivate([&] {
|
||||
|
@ -279,7 +279,7 @@ auto Presentation::loadShaders() -> void {
|
|||
for(auto shader : directory::folders(pathname, "*.shader")) {
|
||||
if(videoShaders.objectCount() == 2) videoShaderMenu.append(MenuSeparator());
|
||||
MenuRadioItem item{&videoShaderMenu};
|
||||
item.setText(string{shader}.rtrim(".shader/", 1L)).onActivate([=] {
|
||||
item.setText(string{shader}.trimRight(".shader/", 1L)).onActivate([=] {
|
||||
settings["Video/Shader"].setValue({pathname, shader});
|
||||
program->updateVideoShader();
|
||||
});
|
||||
|
|
|
@ -20,7 +20,7 @@ auto Program::loadRequest(uint id, string filename, bool required) -> void {
|
|||
if(filename == "manifest.bml" && pathname && !pathname.endsWith(".sys/")) {
|
||||
if(!file::exists(location) || settings["Library/IgnoreManifests"].boolean()) {
|
||||
if(auto manifest = execute("icarus", "--manifest", pathname)) {
|
||||
memorystream stream{(const uint8_t*)manifest.data(), manifest.size()};
|
||||
memorystream stream{manifest.output.data<uint8_t>(), manifest.output.size()};
|
||||
return emulator->load(id, stream);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ auto Program::loadMedia(string location) -> void {
|
|||
if(!location.endsWith("/")) location.append("/");
|
||||
if(!directory::exists(location)) return;
|
||||
|
||||
string type = suffixname(location).ltrim(".", 1L);
|
||||
string type = suffixname(location).trimLeft(".", 1L);
|
||||
for(auto& emulator : emulators) {
|
||||
for(auto& media : emulator->media) {
|
||||
if(!media.bootable) continue;
|
||||
|
|
|
@ -77,7 +77,7 @@ auto Program::load(string location) -> void {
|
|||
|
||||
//ask icarus to import the game; and play it upon success
|
||||
if(auto result = execute("icarus", "--import", location)) {
|
||||
loadMedia(result.strip());
|
||||
loadMedia(result.output.strip());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,14 +5,14 @@ unique_pointer<Input> input;
|
|||
Emulator::Interface* emulator = nullptr;
|
||||
|
||||
auto locate(string name) -> string {
|
||||
string location = {programpath(), name};
|
||||
string location = {Path::program(), name};
|
||||
if(inode::exists(location)) return location;
|
||||
|
||||
location = {configpath(), "higan/", name};
|
||||
location = {Path::config(), "higan/", name};
|
||||
if(inode::exists(location)) return location;
|
||||
|
||||
directory::create({localpath(), "higan/"});
|
||||
return {localpath(), "higan/", name};
|
||||
directory::create({Path::local(), "higan/"});
|
||||
return {Path::local(), "higan/", name};
|
||||
}
|
||||
|
||||
#include <nall/main.hpp>
|
||||
|
|
|
@ -26,8 +26,8 @@ auto pBrowserWindow::open(BrowserWindow::State& state) -> string {
|
|||
@autoreleasepool {
|
||||
NSMutableArray* filters = [[NSMutableArray alloc] init];
|
||||
for(auto& rule : state.filters) {
|
||||
string pattern = rule.split("(", 1L)(1).rtrim(")", 1L);
|
||||
if(!pattern.empty()) [filters addObject:[NSString stringWithUTF8String:pattern]];
|
||||
string pattern = rule.split("(", 1L)(1).trimRight(")", 1L);
|
||||
if(pattern) [filters addObject:[NSString stringWithUTF8String:pattern]];
|
||||
}
|
||||
NSOpenPanel* panel = [NSOpenPanel openPanel];
|
||||
if(state.title) [panel setTitle:[NSString stringWithUTF8String:state.title]];
|
||||
|
@ -51,8 +51,8 @@ auto pBrowserWindow::save(BrowserWindow::State& state) -> string {
|
|||
@autoreleasepool {
|
||||
NSMutableArray* filters = [[NSMutableArray alloc] init];
|
||||
for(auto& rule : state.filters) {
|
||||
string pattern = rule.split("(", 1L)(1).rtrim(")", 1L);
|
||||
if(!pattern.empty()) [filters addObject:[NSString stringWithUTF8String:pattern]];
|
||||
string pattern = rule.split("(", 1L)(1).trimRight(")", 1L);
|
||||
if(pattern) [filters addObject:[NSString stringWithUTF8String:pattern]];
|
||||
}
|
||||
NSSavePanel* panel = [NSSavePanel savePanel];
|
||||
if(state.title) [panel setTitle:[NSString stringWithUTF8String:state.title]];
|
||||
|
|
|
@ -425,7 +425,7 @@ auto pTableView::autoSizeColumns() -> void {
|
|||
unsigned minimumWidth = pFont::size([[tableColumn headerCell] font], tableView.state.headerText(column)).width + 4;
|
||||
for(unsigned row = 0; row < tableView.state.text.size(); row++) {
|
||||
unsigned width = pFont::size([cocoaView font], tableView.state.text(row)(column)).width + 2;
|
||||
if(tableView.state.image(row)(height).empty() == false) width += height + 2;
|
||||
if(tableView.state.image(row)(height)) width += height + 2;
|
||||
if(width > minimumWidth) minimumWidth = width;
|
||||
}
|
||||
[tableColumn setWidth:minimumWidth];
|
||||
|
|
|
@ -54,6 +54,7 @@
|
|||
#define Hiro_CheckButton
|
||||
#define Hiro_CheckLabel
|
||||
#define Hiro_ComboButton
|
||||
#define Hiro_ComboEdit
|
||||
#define Hiro_Console
|
||||
#define Hiro_Frame
|
||||
#define Hiro_HexEdit
|
||||
|
@ -74,11 +75,10 @@
|
|||
#define Hiro_VerticalSlider
|
||||
#define Hiro_Viewport
|
||||
|
||||
#define Hiro_FixedLayout
|
||||
#define Hiro_HorizontalLayout
|
||||
#define Hiro_VerticalLayout
|
||||
//platform-specific exclusions
|
||||
|
||||
#if defined(HIRO_WINDOWS) || defined(HIRO_COCOA) || defined(HIRO_QT)
|
||||
#undef Hiro_ComboEdit
|
||||
#undef Hiro_Console
|
||||
#undef Hiro_IconView
|
||||
#undef Hiro_SourceEdit
|
||||
|
@ -89,6 +89,12 @@
|
|||
#undef Hiro_HexEdit
|
||||
#endif
|
||||
|
||||
//extensions
|
||||
|
||||
#define Hiro_FixedLayout
|
||||
#define Hiro_HorizontalLayout
|
||||
#define Hiro_VerticalLayout
|
||||
|
||||
#if defined(Hiro_TableView)
|
||||
#define Hiro_ListView
|
||||
#endif
|
||||
|
@ -97,6 +103,6 @@
|
|||
#define Hiro_MessageDialog
|
||||
#endif
|
||||
|
||||
#if defined(Hiro_Button) && defined(Hiro_ComboButton) && defined(Hiro_LineEdit) && defined(Hiro_TableView) && defined(Hiro_MessageDialog)
|
||||
#if defined(Hiro_Button) && defined(Hiro_ComboButton) && defined(Hiro_LineEdit) && defined(Hiro_ListView) && defined(Hiro_MessageDialog)
|
||||
#define Hiro_BrowserDialog
|
||||
#endif
|
||||
|
|
|
@ -77,6 +77,8 @@ namespace hiro {
|
|||
#include "widget/check-label.cpp"
|
||||
#include "widget/combo-button.cpp"
|
||||
#include "widget/combo-button-item.cpp"
|
||||
#include "widget/combo-edit.cpp"
|
||||
#include "widget/combo-edit-item.cpp"
|
||||
#include "widget/console.cpp"
|
||||
#include "widget/frame.cpp"
|
||||
#include "widget/hex-edit.cpp"
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <nall/function.hpp>
|
||||
#include <nall/image.hpp>
|
||||
#include <nall/maybe.hpp>
|
||||
#include <nall/path.hpp>
|
||||
#include <nall/range.hpp>
|
||||
#include <nall/set.hpp>
|
||||
#include <nall/shared-pointer.hpp>
|
||||
|
@ -58,6 +59,8 @@ Declare(CheckButton)
|
|||
Declare(CheckLabel)
|
||||
Declare(ComboButton)
|
||||
Declare(ComboButtonItem)
|
||||
Declare(ComboEdit)
|
||||
Declare(ComboEditItem)
|
||||
Declare(Console)
|
||||
Declare(Frame)
|
||||
Declare(HexEdit)
|
||||
|
@ -572,6 +575,7 @@ struct mObject {
|
|||
auto offset() const -> signed;
|
||||
auto parent() const -> mObject*;
|
||||
auto parentComboButton(bool recursive = false) const -> mComboButton*;
|
||||
auto parentComboEdit(bool recursive = false) const -> mComboEdit*;
|
||||
auto parentFrame(bool recursive = false) const -> mFrame*;
|
||||
auto parentIconView(bool recursive = false) const -> mIconView*;
|
||||
auto parentLayout(bool recursive = false) const -> mLayout*;
|
||||
|
@ -1116,6 +1120,61 @@ struct mComboButtonItem : mObject {
|
|||
};
|
||||
#endif
|
||||
|
||||
#if defined(Hiro_ComboEdit)
|
||||
struct mComboEdit : mWidget {
|
||||
Declare(ComboEdit)
|
||||
using mObject::remove;
|
||||
|
||||
auto append(sComboEditItem item) -> type&;
|
||||
auto backgroundColor() const -> Color;
|
||||
auto doActivate() const -> void;
|
||||
auto doChange() const -> void;
|
||||
auto foregroundColor() const -> Color;
|
||||
auto item(uint position) const -> ComboEditItem;
|
||||
auto itemCount() const -> uint;
|
||||
auto items() const -> vector<ComboEditItem>;
|
||||
auto onActivate(const function<void ()>& callback = {}) -> type&;
|
||||
auto onChange(const function<void ()>& callback = {}) -> type&;
|
||||
auto remove(sComboEditItem item) -> type&;
|
||||
auto reset() -> type&;
|
||||
auto setBackgroundColor(Color color = {}) -> type&;
|
||||
auto setForegroundColor(Color color = {}) -> type&;
|
||||
auto setParent(mObject* parent = nullptr, int offset = -1) -> type& override;
|
||||
auto setText(const string& text = "") -> type&;
|
||||
auto text() const -> string;
|
||||
|
||||
//private:
|
||||
struct State {
|
||||
Color backgroundColor;
|
||||
Color foregroundColor;
|
||||
vector<sComboEditItem> items;
|
||||
function<void ()> onActivate;
|
||||
function<void ()> onChange;
|
||||
string text;
|
||||
} state;
|
||||
|
||||
auto destruct() -> void override;
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(Hiro_ComboEdit)
|
||||
struct mComboEditItem : mObject {
|
||||
Declare(ComboEditItem)
|
||||
|
||||
auto icon() const -> image;
|
||||
auto remove() -> type& override;
|
||||
auto setIcon(const image& icon = {}) -> type&;
|
||||
auto setText(const string& text = "") -> type&;
|
||||
auto text() const -> string;
|
||||
|
||||
//private:
|
||||
struct State {
|
||||
image icon;
|
||||
string text;
|
||||
} state;
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(Hiro_Console)
|
||||
struct mConsole : mWidget {
|
||||
Declare(Console)
|
||||
|
|
|
@ -100,6 +100,16 @@ auto mObject::parentComboButton(bool recursive) const -> mComboButton* {
|
|||
}
|
||||
#endif
|
||||
|
||||
#if defined(Hiro_ComboEdit)
|
||||
auto mObject::parentComboEdit(bool recursive) const -> mComboEdit* {
|
||||
if(auto comboEdit = dynamic_cast<mComboEdit*>(parent())) return comboEdit;
|
||||
if(recursive) {
|
||||
if(auto object = parent()) return object->parentComboEdit(true);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(Hiro_Frame)
|
||||
auto mObject::parentFrame(bool recursive) const -> mFrame* {
|
||||
if(auto frame = dynamic_cast<mFrame*>(parent())) return frame;
|
||||
|
|
|
@ -321,6 +321,42 @@ struct ComboButton : sComboButton {
|
|||
};
|
||||
#endif
|
||||
|
||||
#if defined(Hiro_ComboEdit)
|
||||
struct ComboEditItem : sComboEditItem {
|
||||
DeclareSharedObject(ComboEditItem)
|
||||
using internalType = mComboEditItem;
|
||||
|
||||
auto icon() const { return self().icon(); }
|
||||
auto setIcon(const image& icon = {}) { return self().setIcon(icon), *this; }
|
||||
auto setText(const string& text = "") { return self().setText(text), *this; }
|
||||
auto text() const { return self().text(); }
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(Hiro_ComboEdit)
|
||||
struct ComboEdit : sComboEdit {
|
||||
DeclareSharedWidget(ComboEdit)
|
||||
using internalType = mComboEdit;
|
||||
|
||||
auto append(sComboEditItem item) { return self().append(item), *this; }
|
||||
auto backgroundColor() const { return self().backgroundColor(); }
|
||||
auto doActivate() const { return self().doActivate(); }
|
||||
auto doChange() const { return self().doChange(); }
|
||||
auto foregroundColor() const { return self().foregroundColor(); }
|
||||
auto item(uint position) const { return self().item(position); }
|
||||
auto itemCount() const { return self().itemCount(); }
|
||||
auto items() const { return self().items(); }
|
||||
auto onActivate(const function<void ()>& callback = {}) { return self().onActivate(callback), *this; }
|
||||
auto onChange(const function<void ()>& callback = {}) { return self().onChange(callback), *this; }
|
||||
auto remove(sComboEditItem item) { return self().remove(item), *this; }
|
||||
auto reset() { return self().reset(), *this; }
|
||||
auto setBackgroundColor(Color color = {}) { return self().setBackgroundColor(color), *this; }
|
||||
auto setForegroundColor(Color color = {}) { return self().setForegroundColor(color), *this; }
|
||||
auto setText(const string& text = "") { return self().setText(text), *this; }
|
||||
auto text() const { return self().text(); }
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(Hiro_Console)
|
||||
struct Console : sConsole {
|
||||
DeclareSharedWidget(Console)
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
#if defined(Hiro_ComboEdit)
|
||||
|
||||
auto mComboEditItem::allocate() -> pObject* {
|
||||
return new pComboEditItem(*this);
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
auto mComboEditItem::icon() const -> image {
|
||||
return state.icon;
|
||||
}
|
||||
|
||||
auto mComboEditItem::remove() -> type& {
|
||||
if(auto comboEdit = parentComboEdit()) comboEdit->remove(*this);
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto mComboEditItem::setIcon(const image& icon) -> type& {
|
||||
state.icon = icon;
|
||||
signal(setIcon, icon);
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto mComboEditItem::setText(const string& text) -> type& {
|
||||
state.text = text;
|
||||
signal(setText, text);
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto mComboEditItem::text() const -> string {
|
||||
return state.text;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,107 @@
|
|||
#if defined(Hiro_ComboEdit)
|
||||
|
||||
auto mComboEdit::allocate() -> pObject* {
|
||||
return new pComboEdit(*this);
|
||||
}
|
||||
|
||||
auto mComboEdit::destruct() -> void {
|
||||
mWidget::destruct();
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
auto mComboEdit::append(sComboEditItem item) -> type& {
|
||||
state.items.append(item);
|
||||
item->setParent(this, itemCount() - 1);
|
||||
signal(append, item);
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto mComboEdit::backgroundColor() const -> Color {
|
||||
return state.backgroundColor;
|
||||
}
|
||||
|
||||
auto mComboEdit::doActivate() const -> void {
|
||||
if(state.onActivate) return state.onActivate();
|
||||
}
|
||||
|
||||
auto mComboEdit::doChange() const -> void {
|
||||
if(state.onChange) return state.onChange();
|
||||
}
|
||||
|
||||
auto mComboEdit::foregroundColor() const -> Color {
|
||||
return state.foregroundColor;
|
||||
}
|
||||
|
||||
auto mComboEdit::item(uint position) const -> ComboEditItem {
|
||||
if(position < itemCount()) return state.items[position];
|
||||
return {};
|
||||
}
|
||||
|
||||
auto mComboEdit::itemCount() const -> uint {
|
||||
return state.items.size();
|
||||
}
|
||||
|
||||
auto mComboEdit::items() const -> vector<ComboEditItem> {
|
||||
vector<ComboEditItem> items;
|
||||
for(auto& item : state.items) items.append(item);
|
||||
return items;
|
||||
}
|
||||
|
||||
auto mComboEdit::onActivate(const function<void ()>& callback) -> type& {
|
||||
state.onActivate = callback;
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto mComboEdit::onChange(const function<void ()>& callback) -> type& {
|
||||
state.onChange = callback;
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto mComboEdit::remove(sComboEditItem item) -> type& {
|
||||
signal(remove, item);
|
||||
state.items.remove(item->offset());
|
||||
for(auto n : range(item->offset(), itemCount())) {
|
||||
state.items[n]->adjustOffset(-1);
|
||||
}
|
||||
item->setParent();
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto mComboEdit::reset() -> type& {
|
||||
signal(reset);
|
||||
for(auto& item : state.items) item->setParent();
|
||||
state.items.reset();
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto mComboEdit::setBackgroundColor(Color color) -> type& {
|
||||
state.backgroundColor = color;
|
||||
signal(setBackgroundColor, color);
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto mComboEdit::setForegroundColor(Color color) -> type& {
|
||||
state.foregroundColor = color;
|
||||
signal(setForegroundColor, color);
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto mComboEdit::setParent(mObject* parent, int offset) -> type& {
|
||||
for(auto& item : state.items) item->destruct();
|
||||
mObject::setParent(parent, offset);
|
||||
for(auto& item : state.items) item->setParent(this, item->offset());
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto mComboEdit::setText(const string& text) -> type& {
|
||||
state.text = text;
|
||||
signal(setText, text);
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto mComboEdit::text() const -> string {
|
||||
return state.text;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -57,7 +57,7 @@ auto mTreeViewItem::icon() const -> image {
|
|||
}
|
||||
|
||||
auto mTreeViewItem::item(const string& path) const -> TreeViewItem {
|
||||
if(path.empty()) return {};
|
||||
if(!path) return {};
|
||||
auto paths = path.split("/");
|
||||
unsigned position = paths.takeLeft().natural();
|
||||
if(position >= itemCount()) return {};
|
||||
|
|
|
@ -43,7 +43,7 @@ auto mTreeView::foregroundColor() const -> Color {
|
|||
}
|
||||
|
||||
auto mTreeView::item(const string& path) const -> TreeViewItem {
|
||||
if(path.empty()) return {};
|
||||
if(!path) return {};
|
||||
auto paths = path.split("/");
|
||||
unsigned position = paths.takeLeft().natural();
|
||||
if(position >= itemCount()) return {};
|
||||
|
|
|
@ -18,7 +18,7 @@ private:
|
|||
Button pathRefresh{&pathLayout, Size{0, 0}, 0};
|
||||
Button pathHome{&pathLayout, Size{0, 0}, 0};
|
||||
Button pathUp{&pathLayout, Size{0, 0}, 0};
|
||||
TableView view{&layout, Size{~0, ~0}, 5};
|
||||
ListView view{&layout, Size{~0, ~0}, 5};
|
||||
HorizontalLayout controlLayout{&layout, Size{~0, 0}};
|
||||
ComboButton filterList{&controlLayout, Size{120, 0}, 5};
|
||||
LineEdit fileName{&controlLayout, Size{~0, 0}, 5};
|
||||
|
@ -119,7 +119,7 @@ auto BrowserDialogWindow::run() -> lstring {
|
|||
layout.setMargin(5);
|
||||
pathName.onActivate([&] { setPath(pathName.text()); });
|
||||
pathRefresh.setBordered(false).setIcon(Icon::Action::Refresh).onActivate([&] { setPath(state.path); });
|
||||
pathHome.setBordered(false).setIcon(Icon::Go::Home).onActivate([&] { setPath(userpath()); });
|
||||
pathHome.setBordered(false).setIcon(Icon::Go::Home).onActivate([&] { setPath(Path::user()); });
|
||||
pathUp.setBordered(false).setIcon(Icon::Go::Up).onActivate([&] { setPath(dirname(state.path)); });
|
||||
view.setBatchable(state.action == "openFiles").onActivate([&] { activate(); }).onChange([&] { change(); });
|
||||
filterList.setVisible(state.action != "selectFolder").onChange([&] { setPath(state.path); });
|
||||
|
@ -143,12 +143,10 @@ auto BrowserDialogWindow::run() -> lstring {
|
|||
setPath(state.path);
|
||||
|
||||
window.onClose([&] { window.setModal(false); });
|
||||
window.onSize([&] { view.resizeColumns(); });
|
||||
window.setTitle(state.title);
|
||||
window.setSize({640, 480});
|
||||
window.setCentered(state.parent);
|
||||
window.setVisible();
|
||||
view.resizeColumns();
|
||||
view.setFocused();
|
||||
window.setModal();
|
||||
window.setVisible(false);
|
||||
|
@ -162,35 +160,28 @@ auto BrowserDialogWindow::setPath(string path) -> void {
|
|||
pathName.setText(state.path = path);
|
||||
|
||||
view.reset();
|
||||
view.append(TableViewHeader().setVisible(false)
|
||||
.append(TableViewColumn().setExpandable())
|
||||
);
|
||||
|
||||
auto contents = directory::icontents(path);
|
||||
bool folderMode = state.action == "openFolder";
|
||||
|
||||
for(auto content : contents) {
|
||||
if(!content.endsWith("/")) continue;
|
||||
content.rtrim("/");
|
||||
content.trimRight("/");
|
||||
if(folderMode && isMatch(content)) continue;
|
||||
|
||||
view.append(TableViewItem()
|
||||
.append(TableViewCell().setText(content).setIcon(Icon::Emblem::Folder))
|
||||
);
|
||||
view.append(ListViewItem().setText(content).setIcon(Icon::Emblem::Folder));
|
||||
}
|
||||
|
||||
for(auto content : contents) {
|
||||
if(content.endsWith("/") != folderMode) continue; //file mode shows files; folder mode shows folders
|
||||
content.rtrim("/");
|
||||
content.trimRight("/");
|
||||
if(!isMatch(content)) continue;
|
||||
|
||||
view.append(TableViewItem()
|
||||
.append(TableViewCell().setText(content).setIcon(folderMode ? Icon::Action::Open : Icon::Emblem::File))
|
||||
);
|
||||
view.append(ListViewItem().setText(content).setIcon(folderMode ? Icon::Action::Open : Icon::Emblem::File));
|
||||
}
|
||||
|
||||
Application::processEvents();
|
||||
view.resizeColumns().setFocused().doChange();
|
||||
view.setFocused().doChange();
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -254,7 +245,7 @@ auto BrowserDialog::setTitle(const string& title) -> type& {
|
|||
}
|
||||
|
||||
auto BrowserDialog::_run() -> lstring {
|
||||
if(!state.path) state.path = userpath();
|
||||
if(!state.path) state.path = Path::user();
|
||||
return BrowserDialogWindow(state).run();
|
||||
}
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@ static auto BrowserWindow_addFilters(GtkWidget* dialog, lstring filters) -> void
|
|||
for(auto& filter : filters) {
|
||||
GtkFileFilter* gtkFilter = gtk_file_filter_new();
|
||||
gtk_file_filter_set_name(gtkFilter, filter);
|
||||
lstring patterns = filter.split("(", 1L)(1).rtrim(")", 1L).split(",").strip();
|
||||
lstring patterns = filter.split("(", 1L)(1).trimRight(")", 1L).split(",").strip();
|
||||
for(auto& pattern : patterns) gtk_file_filter_add_pattern(gtkFilter, pattern);
|
||||
gtk_file_chooser_add_filter(GTK_FILE_CHOOSER(dialog), gtkFilter);
|
||||
}
|
||||
|
|
|
@ -35,6 +35,8 @@
|
|||
#include "widget/check-label.cpp"
|
||||
#include "widget/combo-button.cpp"
|
||||
#include "widget/combo-button-item.cpp"
|
||||
#include "widget/combo-edit.cpp"
|
||||
#include "widget/combo-edit-item.cpp"
|
||||
#include "widget/console.cpp"
|
||||
#include "widget/frame.cpp"
|
||||
#include "widget/hex-edit.cpp"
|
||||
|
|
|
@ -46,6 +46,8 @@ namespace hiro {
|
|||
#include "widget/check-label.hpp"
|
||||
#include "widget/combo-button.hpp"
|
||||
#include "widget/combo-button-item.hpp"
|
||||
#include "widget/combo-edit.hpp"
|
||||
#include "widget/combo-edit-item.hpp"
|
||||
#include "widget/console.hpp"
|
||||
#include "widget/frame.hpp"
|
||||
#include "widget/hex-edit.hpp"
|
||||
|
|
|
@ -13,12 +13,12 @@ Settings::Settings() {
|
|||
}
|
||||
|
||||
auto Settings::load() -> void {
|
||||
string path = {configpath(), "hiro/"};
|
||||
string path = {Path::config(), "hiro/"};
|
||||
Configuration::Document::load({path, "gtk.bml"});
|
||||
}
|
||||
|
||||
auto Settings::save() -> void {
|
||||
string path = {configpath(), "hiro/"};
|
||||
string path = {Path::config(), "hiro/"};
|
||||
directory::create(path, 0755);
|
||||
Configuration::Document::save({path, "gtk.bml"});
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@ auto pComboButtonItem::destruct() -> void {
|
|||
|
||||
auto pComboButtonItem::setIcon(const image& icon) -> void {
|
||||
if(auto parent = _parent()) {
|
||||
auto size = pFont::size(self().font(true), " ").height();
|
||||
auto pixbuf = CreatePixbuf(icon, true);
|
||||
gtk_list_store_set(parent->gtkListStore, >kIter, 0, pixbuf, -1);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
#if defined(Hiro_ComboEdit)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
auto pComboEditItem::construct() -> void {
|
||||
}
|
||||
|
||||
auto pComboEditItem::destruct() -> void {
|
||||
}
|
||||
|
||||
auto pComboEditItem::setIcon(const image& icon) -> void {
|
||||
if(auto parent = _parent()) {
|
||||
auto pixbuf = CreatePixbuf(icon, true);
|
||||
gtk_list_store_set(parent->gtkListStore, >kIter, 0, pixbuf, -1);
|
||||
}
|
||||
}
|
||||
|
||||
auto pComboEditItem::setText(const string& text) -> void {
|
||||
if(auto parent = _parent()) {
|
||||
gtk_list_store_set(parent->gtkListStore, >kIter, 1, text.data(), -1);
|
||||
}
|
||||
}
|
||||
|
||||
auto pComboEditItem::_parent() -> maybe<pComboEdit&> {
|
||||
if(auto parent = self().parentComboEdit()) {
|
||||
if(auto self = parent->self()) return *self;
|
||||
}
|
||||
return nothing;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,18 @@
|
|||
#if defined(Hiro_ComboEdit)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pComboEditItem : pObject {
|
||||
Declare(ComboEditItem, Object)
|
||||
|
||||
auto setIcon(const image& icon) -> void;
|
||||
auto setText(const string& text) -> void;
|
||||
|
||||
auto _parent() -> maybe<pComboEdit&>;
|
||||
|
||||
GtkTreeIter gtkIter;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,115 @@
|
|||
#if defined(Hiro_ComboEdit)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
static auto ComboEdit_activate(GtkComboBox* comboBox, pComboEdit* p) -> void { p->self().doActivate(); }
|
||||
static auto ComboEdit_change(GtkComboBox* comboBox, pComboEdit* p) -> void { p->_updateText(); }
|
||||
|
||||
auto pComboEdit::construct() -> void {
|
||||
gtkListStore = gtk_list_store_new(2, GDK_TYPE_PIXBUF, G_TYPE_STRING);
|
||||
gtkTreeModel = GTK_TREE_MODEL(gtkListStore);
|
||||
gtkWidget = gtk_combo_box_new_with_model_and_entry(gtkTreeModel);
|
||||
gtkComboBox = GTK_COMBO_BOX(gtkWidget);
|
||||
|
||||
gtk_cell_layout_clear(GTK_CELL_LAYOUT(gtkWidget));
|
||||
gtkCellIcon = gtk_cell_renderer_pixbuf_new();
|
||||
gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(gtkWidget), gtkCellIcon, false);
|
||||
gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(gtkWidget), gtkCellIcon, "pixbuf", 0, nullptr);
|
||||
gtkCellText = gtk_cell_renderer_text_new();
|
||||
gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(gtkWidget), gtkCellText, true);
|
||||
gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(gtkWidget), gtkCellText, "text", 1, nullptr);
|
||||
|
||||
//we must call gtk_combo_box_set_entry_text_column(1) in order for GtkComboBoxEntry to pull text
|
||||
//however, this API call throws a Gtk-CRITICAL assertion that column 1 is not a cell renderer
|
||||
//this is, however, incorrect. it *is* a renderer, and the API call works as expected
|
||||
//so in order to suppress the error message, we redirect stderr to /dev/null temporarily
|
||||
int stdErr = dup(STDERR_FILENO);
|
||||
int devNull = open("/dev/null", 0);
|
||||
dup2(devNull, STDERR_FILENO);
|
||||
gtk_combo_box_set_entry_text_column(gtkComboBox, 1);
|
||||
dup2(stdErr, STDERR_FILENO);
|
||||
close(devNull);
|
||||
close(stdErr);
|
||||
|
||||
setBackgroundColor(state().backgroundColor);
|
||||
setForegroundColor(state().foregroundColor);
|
||||
for(auto& item : state().items) append(item);
|
||||
|
||||
g_signal_connect(G_OBJECT(gtk_bin_get_child(GTK_BIN(gtkComboBox))), "activate", G_CALLBACK(ComboEdit_activate), (gpointer)this);
|
||||
g_signal_connect(G_OBJECT(gtkWidget), "changed", G_CALLBACK(ComboEdit_change), (gpointer)this);
|
||||
|
||||
pWidget::construct();
|
||||
}
|
||||
|
||||
auto pComboEdit::destruct() -> void {
|
||||
gtk_widget_destroy(gtkWidget);
|
||||
}
|
||||
|
||||
auto pComboEdit::append(sComboEditItem item) -> void {
|
||||
lock();
|
||||
if(auto self = item->self()) {
|
||||
gtk_list_store_append(gtkListStore, &self->gtkIter);
|
||||
self->setIcon(item->state.icon);
|
||||
self->setText(item->state.text);
|
||||
}
|
||||
unlock();
|
||||
}
|
||||
|
||||
auto pComboEdit::minimumSize() const -> Size {
|
||||
auto font = self().font(true);
|
||||
int maximumWidth = 0;
|
||||
for(auto& item : state().items) {
|
||||
maximumWidth = max(maximumWidth,
|
||||
(item->state.icon ? pFont::size(font, " ").height() + 2 : 0)
|
||||
+ pFont::size(font, item->state.text).width()
|
||||
);
|
||||
}
|
||||
return {maximumWidth + 40, pFont::size(font, " ").height() + 12};
|
||||
}
|
||||
|
||||
auto pComboEdit::remove(sComboEditItem item) -> void {
|
||||
lock();
|
||||
if(auto delegate = item->self()) {
|
||||
gtk_list_store_remove(gtkListStore, &delegate->gtkIter);
|
||||
}
|
||||
unlock();
|
||||
}
|
||||
|
||||
auto pComboEdit::reset() -> void {
|
||||
lock();
|
||||
gtk_list_store_clear(gtkListStore);
|
||||
unlock();
|
||||
}
|
||||
|
||||
auto pComboEdit::setBackgroundColor(Color color) -> void {
|
||||
GdkColor gdkColor = CreateColor(color);
|
||||
gtk_widget_modify_base(gtk_bin_get_child(GTK_BIN(gtkComboBox)), GTK_STATE_NORMAL, color ? &gdkColor : nullptr);
|
||||
}
|
||||
|
||||
auto pComboEdit::setForegroundColor(Color color) -> void {
|
||||
GdkColor gdkColor = CreateColor(color);
|
||||
gtk_widget_modify_text(gtk_bin_get_child(GTK_BIN(gtkComboBox)), GTK_STATE_NORMAL, color ? &gdkColor : nullptr);
|
||||
}
|
||||
|
||||
auto pComboEdit::setFont(const Font& font) -> void {
|
||||
pWidget::setFont(font);
|
||||
auto fontDescription = pFont::create(font);
|
||||
g_object_set(G_OBJECT(gtkCellText), "font-desc", fontDescription, nullptr);
|
||||
}
|
||||
|
||||
auto pComboEdit::setText(const string& text) -> void {
|
||||
lock();
|
||||
gtk_entry_set_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(gtkComboBox))), text);
|
||||
unlock();
|
||||
}
|
||||
|
||||
auto pComboEdit::_updateText() -> void {
|
||||
string text = gtk_entry_get_text(GTK_ENTRY(gtk_bin_get_child(GTK_BIN(gtkComboBox))));
|
||||
if(text == state().text) return;
|
||||
state().text = text;
|
||||
if(!locked()) self().doChange();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,28 @@
|
|||
#if defined(Hiro_ComboEdit)
|
||||
|
||||
namespace hiro {
|
||||
|
||||
struct pComboEdit : pWidget {
|
||||
Declare(ComboEdit, Widget)
|
||||
|
||||
auto append(sComboEditItem item) -> void;
|
||||
auto minimumSize() const -> Size override;
|
||||
auto remove(sComboEditItem item) -> void;
|
||||
auto reset() -> void;
|
||||
auto setBackgroundColor(Color color) -> void;
|
||||
auto setForegroundColor(Color color) -> void;
|
||||
auto setFont(const Font& font) -> void override;
|
||||
auto setText(const string& text) -> void;
|
||||
|
||||
auto _updateText() -> void;
|
||||
|
||||
GtkListStore* gtkListStore = nullptr;
|
||||
GtkTreeModel* gtkTreeModel = nullptr;
|
||||
GtkComboBox* gtkComboBox = nullptr;
|
||||
GtkCellRenderer* gtkCellIcon = nullptr;
|
||||
GtkCellRenderer* gtkCellText = nullptr;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
|
@ -136,7 +136,7 @@ auto pWindow::construct() -> void {
|
|||
|
||||
//if program was given a name, try and set the window taskbar icon from one of the pixmaps folders
|
||||
if(!Application::state.name);
|
||||
else if(_setIcon({userpath(), ".local/share/icons/"}));
|
||||
else if(_setIcon({Path::user(), ".local/share/icons/"}));
|
||||
else if(_setIcon("/usr/local/share/pixmaps/"));
|
||||
else if(_setIcon("/usr/share/pixmaps/"));
|
||||
|
||||
|
|
|
@ -13,12 +13,12 @@ Settings::Settings() {
|
|||
}
|
||||
|
||||
auto Settings::load() -> void {
|
||||
string path{configpath(), "hiro/"};
|
||||
string path{Path::config(), "hiro/"};
|
||||
Configuration::Document::load({path, "qt.bml"});
|
||||
}
|
||||
|
||||
auto Settings::save() -> void {
|
||||
string path{configpath(), "hiro/"};
|
||||
string path{Path::config(), "hiro/"};
|
||||
directory::create(path, 0755);
|
||||
Configuration::Document::save({path, "qt.bml"});
|
||||
}
|
||||
|
|
|
@ -8,8 +8,8 @@ auto pWindow::construct() -> void {
|
|||
|
||||
//if program was given a name, try and set the window taskbar icon to a matching pixmap image
|
||||
if(auto name = Application::state.name) {
|
||||
if(file::exists({userpath(), ".local/share/icons/", name, ".png"})) {
|
||||
qtWindow->setWindowIcon(QIcon(QString::fromUtf8(string{userpath(), ".local/share/icons/", name, ".png"})));
|
||||
if(file::exists({Path::user(), ".local/share/icons/", name, ".png"})) {
|
||||
qtWindow->setWindowIcon(QIcon(QString::fromUtf8(string{Path::user(), ".local/share/icons/", name, ".png"})));
|
||||
} else if(file::exists({"/usr/local/share/pixmaps/", name, ".png"})) {
|
||||
qtWindow->setWindowIcon(QIcon(QString::fromUtf8(string{"/usr/local/share/pixmaps/", name, ".png"})));
|
||||
} else if(file::exists({"/usr/share/pixmaps/", name, ".png"})) {
|
||||
|
@ -195,10 +195,10 @@ auto pWindow::setVisible(bool visible) -> void {
|
|||
}
|
||||
|
||||
/*
|
||||
if(widget.font().empty() && !window.state.widgetFont.empty()) {
|
||||
if(!widget.font() && window.state.widgetFont) {
|
||||
widget.setFont(window.state.widgetFont);
|
||||
}
|
||||
if(widget.font().empty()) widget.p.setFont(Font::sans(8));
|
||||
if(!widget.font()) widget.p.setFont(Font::sans(8));
|
||||
if(GetParentWidget(&widget)) {
|
||||
widget.p.qtWidget->setParent(GetParentWidget(&widget)->p.container(widget));
|
||||
} else {
|
||||
|
|
|
@ -21,7 +21,7 @@ static auto BrowserWindow_fileDialog(bool save, BrowserWindow::State& state) ->
|
|||
for(auto& filter : state.filters) {
|
||||
lstring part = filter.split("(");
|
||||
if(part.size() != 2) continue;
|
||||
part[1].rtrim(")", 1L);
|
||||
part[1].trimRight(")", 1L);
|
||||
part[1].replace(" ", "");
|
||||
part[1].transform(",", ";");
|
||||
filters.append(filter, "\t", part[1], "\t");
|
||||
|
@ -38,7 +38,7 @@ static auto BrowserWindow_fileDialog(bool save, BrowserWindow::State& state) ->
|
|||
p++;
|
||||
}
|
||||
|
||||
if(path.empty() == false) {
|
||||
if(path) {
|
||||
//clear COMDLG32 MRU (most recently used) file list
|
||||
//this is required in order for lpstrInitialDir to be honored in Windows 7 and above
|
||||
registry::remove("HKCU/Software/Microsoft/Windows/CurrentVersion/Explorer/ComDlg32/LastVisitedPidlMRU/");
|
||||
|
|
|
@ -135,7 +135,7 @@ auto pTabFrame::onDrawItem(LPARAM lparam) -> void {
|
|||
string text = tabFrame.state.text[selection];
|
||||
Size size = pFont::size(hfont, text);
|
||||
unsigned width = item->rcItem.right - item->rcItem.left + 1;
|
||||
if(!tabFrame.state.image[selection].empty()) {
|
||||
if(tabFrame.state.image[selection]) {
|
||||
width += size.height + 2;
|
||||
ImageList_Draw(imageList, selection, item->hDC, item->rcItem.left + (width - size.width) / 2 - (size.height + 3), item->rcItem.top + 2, ILD_NORMAL);
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ auto Icarus::failure(string message) -> string {
|
|||
}
|
||||
|
||||
auto Icarus::manifest(string location) -> string {
|
||||
location.transform("\\", "/").rtrim("/").append("/");
|
||||
location.transform("\\", "/").trimRight("/").append("/");
|
||||
if(!directory::exists(location)) return "";
|
||||
|
||||
auto type = suffixname(location).downcase();
|
||||
|
@ -43,7 +43,7 @@ auto Icarus::manifest(string location) -> string {
|
|||
}
|
||||
|
||||
auto Icarus::import(string location) -> string {
|
||||
location.transform("\\", "/").rtrim("/");
|
||||
location.transform("\\", "/").trimRight("/");
|
||||
if(!file::exists(location)) return failure("file does not exist");
|
||||
if(!file::readable(location)) return failure("file is unreadable");
|
||||
|
||||
|
|
|
@ -5,14 +5,14 @@ using namespace nall;
|
|||
using namespace hiro;
|
||||
|
||||
auto locate(string name) -> string {
|
||||
string location = {programpath(), name};
|
||||
string location = {Path::program(), name};
|
||||
if(inode::exists(location)) return location;
|
||||
|
||||
location = {configpath(), "icarus/", name};
|
||||
location = {Path::config(), "icarus/", name};
|
||||
if(inode::exists(location)) return location;
|
||||
|
||||
directory::create({localpath(), "icarus/"});
|
||||
return {localpath(), "icarus/", name};
|
||||
directory::create({Path::local(), "icarus/"});
|
||||
return {Path::local(), "icarus/", name};
|
||||
}
|
||||
|
||||
#include "settings.cpp"
|
||||
|
|
|
@ -11,9 +11,9 @@ Settings::Settings() {
|
|||
if(!operator[](name)) operator()(name).setValue(value);
|
||||
};
|
||||
|
||||
set("Library/Location", {userpath(), "Emulation/"});
|
||||
set("Library/Location", {Path::user(), "Emulation/"});
|
||||
|
||||
set("icarus/Path", userpath());
|
||||
set("icarus/Path", Path::user());
|
||||
set("icarus/CreateManifests", false);
|
||||
set("icarus/UseDatabase", true);
|
||||
set("icarus/UseHeuristics", true);
|
||||
|
|
|
@ -9,7 +9,7 @@ ScanDialog::ScanDialog() {
|
|||
refresh();
|
||||
});
|
||||
homeButton.setIcon(Icon::Go::Home).setBordered(false).onActivate([&] {
|
||||
pathEdit.setText(userpath());
|
||||
pathEdit.setText(Path::user());
|
||||
refresh();
|
||||
});
|
||||
upButton.setIcon(Icon::Go::Up).setBordered(false).onActivate([&] {
|
||||
|
@ -48,7 +48,7 @@ auto ScanDialog::show() -> void {
|
|||
auto ScanDialog::refresh() -> void {
|
||||
scanList.reset();
|
||||
|
||||
auto pathname = pathEdit.text().transform("\\", "/").rtrim("/").append("/");
|
||||
auto pathname = pathEdit.text().transform("\\", "/").trimRight("/").append("/");
|
||||
if(!directory::exists(pathname)) return;
|
||||
|
||||
settings["icarus/Path"].setValue(pathname);
|
||||
|
@ -58,7 +58,7 @@ auto ScanDialog::refresh() -> void {
|
|||
for(auto& name : contents) {
|
||||
if(!name.endsWith("/")) continue;
|
||||
if(gamePakType(suffixname(name))) continue;
|
||||
scanList.append(ListViewItem().setIcon(Icon::Emblem::Folder).setText(name.rtrim("/")));
|
||||
scanList.append(ListViewItem().setIcon(Icon::Emblem::Folder).setText(name.trimRight("/")));
|
||||
}
|
||||
|
||||
for(auto& name : contents) {
|
||||
|
|
|
@ -13,7 +13,6 @@ struct any {
|
|||
~any() { reset(); }
|
||||
|
||||
explicit operator bool() const { return container; }
|
||||
auto empty() const -> bool { return !container; }
|
||||
auto reset() -> void { if(container) { delete container; container = nullptr; } }
|
||||
|
||||
auto type() const -> const std::type_info& {
|
||||
|
|
|
@ -31,7 +31,7 @@ auto Archive::create(const string& beatname, const string& pathname, const strin
|
|||
bool directory = name.endsWith("/");
|
||||
bool writable = inode::writable(location);
|
||||
bool executable = inode::executable(location);
|
||||
uint info = directory << 0 | writable << 1 | executable << 2 | (name.rtrim("/").size() - 1) << 3;
|
||||
uint info = directory << 0 | writable << 1 | executable << 2 | (name.trimRight("/").size() - 1) << 3;
|
||||
|
||||
beat.writevu(info);
|
||||
beat.writes(name);
|
||||
|
@ -123,7 +123,7 @@ auto Archive::extract(const string& beatname, const string& filename) -> vector<
|
|||
|
||||
auto Archive::scan(lstring& result, const string& basename, const string& pathname) -> void {
|
||||
for(auto& name : directory::contents(pathname)) {
|
||||
result.append(string{pathname, name}.ltrim(basename, 1L));
|
||||
result.append(string{pathname, name}.trimLeft(basename, 1L));
|
||||
if(name.endsWith("/")) scan(result, basename, {pathname, name});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <nall/filemap.hpp>
|
||||
#include <nall/stdint.hpp>
|
||||
#include <nall/string.hpp>
|
||||
#include <nall/hash/crc32.hpp>
|
||||
|
||||
namespace nall {
|
||||
|
||||
|
|
|
@ -34,7 +34,7 @@ struct bpsmulti {
|
|||
|
||||
for(auto& targetName : targetList) {
|
||||
if(targetName.endsWith("/")) {
|
||||
targetName.rtrim("/");
|
||||
targetName.trimRight("/");
|
||||
writeNumber(CreatePath | ((targetName.length() - 1) << 2));
|
||||
writeString(targetName);
|
||||
} else if(auto position = sourceList.find(targetName)) { //if sourceName == targetName
|
||||
|
@ -65,15 +65,15 @@ struct bpsmulti {
|
|||
bpslinear patch;
|
||||
patch.source({sourcePath, targetName});
|
||||
patch.target({targetPath, targetName});
|
||||
patch.create({temppath(), "temp.bps"});
|
||||
patch.create({Path::temp(), "temp.bps"});
|
||||
} else {
|
||||
bpsdelta patch;
|
||||
patch.source({sourcePath, targetName});
|
||||
patch.target({targetPath, targetName});
|
||||
patch.create({temppath(), "temp.bps"});
|
||||
patch.create({Path::temp(), "temp.bps"});
|
||||
}
|
||||
|
||||
auto buffer = file::read({temppath(), "temp.bps"});
|
||||
auto buffer = file::read({Path::temp(), "temp.bps"});
|
||||
writeNumber(buffer.size());
|
||||
for(auto &byte : buffer) write(byte);
|
||||
}
|
||||
|
@ -159,13 +159,13 @@ protected:
|
|||
auto ls(lstring& list, const string& path, const string& basepath) -> void {
|
||||
lstring paths = directory::folders(path);
|
||||
for(auto& pathname : paths) {
|
||||
list.append(string{path, pathname}.ltrim(basepath, 1L));
|
||||
list.append(string{path, pathname}.trimLeft(basepath, 1L));
|
||||
ls(list, {path, pathname}, basepath);
|
||||
}
|
||||
|
||||
lstring files = directory::files(path);
|
||||
for(auto& filename : files) {
|
||||
list.append(string{path, filename}.ltrim(basepath, 1L));
|
||||
list.append(string{path, filename}.trimLeft(basepath, 1L));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,6 @@ struct bitvector {
|
|||
}
|
||||
|
||||
explicit operator bool() const { return bits > 0; }
|
||||
auto empty() const -> bool { return bits == 0; }
|
||||
auto size() const -> uint { return bits; }
|
||||
auto bytes() const -> uint { return (bits + 7) / 8; }
|
||||
auto data() -> uint8_t* { return pool; }
|
||||
|
|
|
@ -14,9 +14,7 @@ struct Node {
|
|||
void* data = nullptr;
|
||||
vector<Node> children;
|
||||
|
||||
auto empty() const -> bool {
|
||||
return data == nullptr;
|
||||
}
|
||||
explicit operator bool() const { return data; }
|
||||
|
||||
auto get() const -> string {
|
||||
switch(type) {
|
||||
|
@ -70,7 +68,7 @@ struct Node {
|
|||
auto load(Markup::Node path) -> void {
|
||||
for(auto& child : children) {
|
||||
if(auto leaf = path[child.name]) {
|
||||
if(!child.empty()) child.set(leaf.text());
|
||||
if(child) child.set(leaf.text());
|
||||
child.load(leaf);
|
||||
}
|
||||
}
|
||||
|
@ -84,7 +82,7 @@ struct Node {
|
|||
}
|
||||
for(auto n : range(depth)) fp.print(" ");
|
||||
fp.print(child.name);
|
||||
if(!child.empty()) fp.print(": ", child.get());
|
||||
if(child) fp.print(": ", child.get());
|
||||
fp.print("\n");
|
||||
child.save(fp, depth + 1);
|
||||
if(depth == 0) fp.print("\n");
|
||||
|
|
|
@ -73,7 +73,7 @@ private:
|
|||
#if defined(PLATFORM_WINDOWS)
|
||||
inline auto directory::create(const string& pathname, unsigned permissions) -> bool {
|
||||
string path;
|
||||
lstring list = string{pathname}.transform("\\", "/").rtrim("/").split("/");
|
||||
lstring list = string{pathname}.transform("\\", "/").trimRight("/").split("/");
|
||||
bool result = true;
|
||||
for(auto& part : list) {
|
||||
path.append(part, "/");
|
||||
|
@ -168,7 +168,7 @@ private:
|
|||
|
||||
inline auto directory::create(const string& pathname, unsigned permissions) -> bool {
|
||||
string path;
|
||||
lstring list = string{pathname}.rtrim("/").split("/");
|
||||
lstring list = string{pathname}.trimRight("/").split("/");
|
||||
bool result = true;
|
||||
for(auto& part : list) {
|
||||
path.append(part, "/");
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
//dynamic linking support
|
||||
|
||||
#include <nall/intrinsics.hpp>
|
||||
#include <nall/path.hpp>
|
||||
#include <nall/stdint.hpp>
|
||||
#include <nall/string.hpp>
|
||||
#include <nall/utility.hpp>
|
||||
|
@ -38,7 +39,7 @@ private:
|
|||
inline auto library::open(const string& name, const string& path) -> bool {
|
||||
if(handle) close();
|
||||
if(path) handle = (uintptr_t)dlopen(string(path, "lib", name, ".so"), RTLD_LAZY);
|
||||
if(!handle) handle = (uintptr_t)dlopen(string(userpath(), ".local/lib/lib", name, ".so"), RTLD_LAZY);
|
||||
if(!handle) handle = (uintptr_t)dlopen(string(Path::user(), ".local/lib/lib", name, ".so"), RTLD_LAZY);
|
||||
if(!handle) handle = (uintptr_t)dlopen(string("/usr/local/lib/lib", name, ".so"), RTLD_LAZY);
|
||||
if(!handle) handle = (uintptr_t)dlopen(string("lib", name, ".so"), RTLD_LAZY);
|
||||
return handle;
|
||||
|
|
|
@ -13,7 +13,8 @@ struct FX {
|
|||
auto write(uint8_t data) -> void;
|
||||
|
||||
auto read(uint offset, uint length) -> vector<uint8_t>;
|
||||
auto write(uint offset, const vector<uint8_t>& buffer) -> void;
|
||||
auto write(uint offset, const void* buffer, uint length) -> void;
|
||||
auto write(uint offset, const vector<uint8_t>& buffer) -> void { write(offset, buffer.data(), buffer.size()); }
|
||||
auto execute(uint offset) -> void;
|
||||
|
||||
auto read(uint offset) -> uint8_t;
|
||||
|
@ -27,7 +28,7 @@ auto FX::open(lstring& args) -> bool {
|
|||
string name;
|
||||
for(uint n : range(args)) {
|
||||
if(args[n].beginsWith("--device=")) {
|
||||
name = args.take(n).ltrim("--device=", 1L);
|
||||
name = args.take(n).trimLeft("--device=", 1L);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -84,8 +85,8 @@ auto FX::read(uint offset, uint length) -> vector<uint8_t> {
|
|||
write(offset >> 8);
|
||||
write(offset >> 0);
|
||||
write(0x01);
|
||||
write(length >> 8);
|
||||
write(length >> 0);
|
||||
write(length >> 8);
|
||||
write(length >> 0);
|
||||
write(0x00);
|
||||
|
||||
vector<uint8_t> buffer;
|
||||
|
@ -93,9 +94,7 @@ auto FX::read(uint offset, uint length) -> vector<uint8_t> {
|
|||
return buffer;
|
||||
}
|
||||
|
||||
auto FX::write(uint offset, const vector<uint8_t>& buffer) -> void {
|
||||
auto length = buffer.size();
|
||||
|
||||
auto FX::write(uint offset, const void* data, uint length) -> void {
|
||||
write(0x21);
|
||||
write(0x66);
|
||||
write(0x78);
|
||||
|
@ -103,11 +102,12 @@ auto FX::write(uint offset, const vector<uint8_t>& buffer) -> void {
|
|||
write(offset >> 8);
|
||||
write(offset >> 0);
|
||||
write(0x01);
|
||||
write(buffer.size() >> 8);
|
||||
write(buffer.size() >> 0);
|
||||
write(length >> 8);
|
||||
write(length >> 0);
|
||||
write(0x01);
|
||||
|
||||
for(auto data : buffer) write(data);
|
||||
auto buffer = (uint8_t*)data;
|
||||
for(auto n : range(length)) write(buffer[n]);
|
||||
write(0x00);
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
|
||||
namespace nall { namespace Encode {
|
||||
|
||||
inline auto Base64(const uint8_t* data, unsigned size, const string& format = "MIME") -> string {
|
||||
inline auto Base64(const void* vdata, unsigned size, const string& format = "MIME") -> string {
|
||||
auto data = (const uint8_t*)vdata;
|
||||
vector<uint8_t> result;
|
||||
|
||||
char lookup[65];
|
||||
|
@ -61,7 +62,7 @@ inline auto Base64(const vector<uint8_t>& buffer, const string& format = "MIME")
|
|||
}
|
||||
|
||||
inline auto Base64(const string& text, const string& format = "MIME") -> string {
|
||||
return Base64(text.binary(), text.size(), format);
|
||||
return Base64(text.data(), text.size(), format);
|
||||
}
|
||||
|
||||
}}
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <nall/range.hpp>
|
||||
|
||||
namespace nall { struct string; }
|
||||
#include <nall/string.hpp>
|
||||
|
||||
namespace nall { namespace Hash {
|
||||
|
||||
|
@ -10,6 +9,7 @@ struct CRC16 {
|
|||
CRC16() { reset(); }
|
||||
CRC16(const void* values, uint size) : CRC16() { data(values, size); }
|
||||
CRC16(const vector<uint8_t>& values) : CRC16() { data(values); }
|
||||
CRC16(const string& values) : CRC16() { data(values); }
|
||||
|
||||
auto reset() -> void {
|
||||
checksum = ~0;
|
||||
|
@ -28,11 +28,17 @@ struct CRC16 {
|
|||
for(auto value : values) data(value);
|
||||
}
|
||||
|
||||
auto data(const string& values) -> void {
|
||||
for(auto value : values) data(value);
|
||||
}
|
||||
|
||||
auto value() const -> uint16_t {
|
||||
return ~checksum;
|
||||
}
|
||||
|
||||
inline auto digest() const -> string;
|
||||
inline auto digest() const -> string {
|
||||
return hex(value(), 4L);
|
||||
}
|
||||
|
||||
private:
|
||||
static auto table(uint8_t index) -> uint16_t {
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <nall/range.hpp>
|
||||
|
||||
namespace nall { struct string; }
|
||||
#include <nall/string.hpp>
|
||||
|
||||
namespace nall { namespace Hash {
|
||||
|
||||
|
@ -10,6 +9,7 @@ struct CRC32 {
|
|||
CRC32() { reset(); }
|
||||
CRC32(const void* values, uint size) : CRC32() { data(values, size); }
|
||||
CRC32(const vector<uint8_t>& values) : CRC32() { data(values); }
|
||||
CRC32(const string& values) : CRC32() { data(values); }
|
||||
|
||||
auto reset() -> void {
|
||||
checksum = ~0;
|
||||
|
@ -28,11 +28,17 @@ struct CRC32 {
|
|||
for(auto value : values) data(value);
|
||||
}
|
||||
|
||||
auto data(const string& values) -> void {
|
||||
for(auto value : values) data(value);
|
||||
}
|
||||
|
||||
auto value() const -> uint32_t {
|
||||
return ~checksum;
|
||||
}
|
||||
|
||||
inline auto digest() const -> string;
|
||||
inline auto digest() const -> string {
|
||||
return hex(value(), 8L);
|
||||
}
|
||||
|
||||
private:
|
||||
static auto table(uint8_t index) -> uint32_t {
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <nall/range.hpp>
|
||||
|
||||
namespace nall { struct string; }
|
||||
#include <nall/string.hpp>
|
||||
|
||||
namespace nall { namespace Hash {
|
||||
|
||||
|
@ -10,6 +9,7 @@ struct CRC64 {
|
|||
CRC64() { reset(); }
|
||||
CRC64(const void* values, uint size) : CRC64() { data(values, size); }
|
||||
CRC64(const vector<uint8_t>& values) : CRC64() { data(values); }
|
||||
CRC64(const string& values) : CRC64() { data(values); }
|
||||
|
||||
auto reset() -> void {
|
||||
checksum = ~0;
|
||||
|
@ -28,11 +28,17 @@ struct CRC64 {
|
|||
for(auto value : values) data(value);
|
||||
}
|
||||
|
||||
auto data(const string& values) -> void {
|
||||
for(auto value : values) data(value);
|
||||
}
|
||||
|
||||
auto value() const -> uint64_t {
|
||||
return ~checksum;
|
||||
}
|
||||
|
||||
inline auto digest() const -> string;
|
||||
inline auto digest() const -> string {
|
||||
return hex(value(), 16L);
|
||||
}
|
||||
|
||||
private:
|
||||
static auto table(uint8_t index) -> uint64_t {
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
#pragma once
|
||||
|
||||
#include <nall/range.hpp>
|
||||
|
||||
namespace nall { struct string; }
|
||||
#include <nall/string.hpp>
|
||||
|
||||
namespace nall { namespace Hash {
|
||||
|
||||
|
@ -10,6 +9,7 @@ struct SHA256 {
|
|||
SHA256() { reset(); }
|
||||
SHA256(const void* values, uint size) : SHA256() { data(values, size); }
|
||||
SHA256(const vector<uint8_t>& values) : SHA256() { data(values); }
|
||||
SHA256(const string& values) : SHA256() { data(values); }
|
||||
|
||||
auto reset() -> void {
|
||||
for(auto n : input) n = 0;
|
||||
|
@ -33,6 +33,10 @@ struct SHA256 {
|
|||
for(auto value : values) data(value);
|
||||
}
|
||||
|
||||
auto data(const string& values) -> void {
|
||||
for(auto value : values) data(value);
|
||||
}
|
||||
|
||||
auto value() const -> vector<uint8_t> {
|
||||
SHA256 self(*this);
|
||||
self.finish();
|
||||
|
@ -41,7 +45,11 @@ struct SHA256 {
|
|||
return result;
|
||||
}
|
||||
|
||||
inline auto digest() const -> nall::string;
|
||||
inline auto digest() const -> string {
|
||||
string result;
|
||||
for(auto n : value()) result.append(hex(n, 2L));
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
auto byte(uint8_t value) -> void {
|
||||
|
|
|
@ -41,9 +41,9 @@ struct hashset {
|
|||
return *this;
|
||||
}
|
||||
|
||||
explicit operator bool() const { return count; }
|
||||
auto capacity() const -> unsigned { return length; }
|
||||
auto size() const -> unsigned { return count; }
|
||||
auto empty() const -> bool { return count == 0; }
|
||||
|
||||
auto reset() -> void {
|
||||
if(pool) {
|
||||
|
|
|
@ -50,7 +50,7 @@ auto Request::head(const function<bool (const uint8_t*, unsigned)>& callback) co
|
|||
for(auto& variable : get) {
|
||||
request.append(Encode::URL(variable.name()), "=", Encode::URL(variable.value()), "&");
|
||||
}
|
||||
request.rtrim("&", 1L);
|
||||
request.trimRight("&", 1L);
|
||||
}
|
||||
|
||||
switch(requestType()) {
|
||||
|
@ -65,25 +65,25 @@ auto Request::head(const function<bool (const uint8_t*, unsigned)>& callback) co
|
|||
}
|
||||
output.append("\r\n");
|
||||
|
||||
return callback(output.binary(), output.size());
|
||||
return callback(output.data<uint8_t>(), output.size());
|
||||
}
|
||||
|
||||
auto Request::setHead() -> bool {
|
||||
lstring headers = _head.split("\n");
|
||||
string request = headers.takeLeft().rtrim("\r", 1L);
|
||||
string request = headers.takeLeft().trimRight("\r", 1L);
|
||||
string requestHost;
|
||||
|
||||
if(request.iendsWith(" HTTP/1.0")) request.irtrim(" HTTP/1.0", 1L);
|
||||
else if(request.iendsWith(" HTTP/1.1")) request.irtrim(" HTTP/1.1", 1L);
|
||||
if(request.iendsWith(" HTTP/1.0")) request.itrimRight(" HTTP/1.0", 1L);
|
||||
else if(request.iendsWith(" HTTP/1.1")) request.itrimRight(" HTTP/1.1", 1L);
|
||||
else return false;
|
||||
|
||||
if(request.ibeginsWith("HEAD ")) request.iltrim("HEAD ", 1L), setRequestType(RequestType::Head);
|
||||
else if(request.ibeginsWith("GET " )) request.iltrim("GET ", 1L), setRequestType(RequestType::Get );
|
||||
else if(request.ibeginsWith("POST ")) request.iltrim("POST ", 1L), setRequestType(RequestType::Post);
|
||||
if(request.ibeginsWith("HEAD ")) request.itrimLeft("HEAD ", 1L), setRequestType(RequestType::Head);
|
||||
else if(request.ibeginsWith("GET " )) request.itrimLeft("GET ", 1L), setRequestType(RequestType::Get );
|
||||
else if(request.ibeginsWith("POST ")) request.itrimLeft("POST ", 1L), setRequestType(RequestType::Post);
|
||||
else return false;
|
||||
|
||||
//decode absolute URIs
|
||||
request.strip().iltrim("http://", 1L);
|
||||
request.strip().itrimLeft("http://", 1L);
|
||||
if(!request.beginsWith("/")) {
|
||||
lstring components = request.split("/", 1L);
|
||||
requestHost = components(0);
|
||||
|
@ -126,7 +126,7 @@ auto Request::body(const function<bool (const uint8_t*, unsigned)>& callback) co
|
|||
if(!callback) return false;
|
||||
|
||||
if(_body) {
|
||||
return callback(_body.binary(), _body.size());
|
||||
return callback(_body.data<uint8_t>(), _body.size());
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -137,13 +137,13 @@ auto Request::setBody() -> bool {
|
|||
auto contentType = header["Content-Type"].value();
|
||||
if(contentType.iequals("application/x-www-form-urlencoded")) {
|
||||
for(auto& block : _body.split("&")) {
|
||||
auto p = block.rtrim("\r").split("=", 1L);
|
||||
auto p = block.trimRight("\r").split("=", 1L);
|
||||
auto name = Decode::URL(p(0));
|
||||
auto value = Decode::URL(p(1));
|
||||
if(name) post.append(name, value);
|
||||
}
|
||||
} else if(contentType.imatch("multipart/form-data; boundary=?*")) {
|
||||
auto boundary = contentType.iltrim("multipart/form-data; boundary=", 1L).trim("\"", "\"", 1L);
|
||||
auto boundary = contentType.itrimLeft("multipart/form-data; boundary=", 1L).trim("\"", "\"", 1L);
|
||||
auto blocks = _body.split({"--", boundary}, 1024L); //limit blocks to prevent memory exhaustion
|
||||
for(auto& block : blocks) block.trim("\r\n", "\r\n", 1L);
|
||||
if(blocks.size() < 2 || (blocks.takeLeft(), !blocks.takeRight().beginsWith("--"))) return false;
|
||||
|
|
|
@ -61,7 +61,7 @@ auto Response::head(const function<bool (const uint8_t*, unsigned)>& callback) c
|
|||
output.append("HTTP/1.1 304 Not Modified\r\n");
|
||||
output.append("Connection: close\r\n");
|
||||
output.append("\r\n");
|
||||
return callback(output.binary(), output.size());
|
||||
return callback(output.data<uint8_t>(), output.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -83,15 +83,15 @@ auto Response::head(const function<bool (const uint8_t*, unsigned)>& callback) c
|
|||
}
|
||||
output.append("\r\n");
|
||||
|
||||
return callback(output.binary(), output.size());
|
||||
return callback(output.data<uint8_t>(), output.size());
|
||||
}
|
||||
|
||||
auto Response::setHead() -> bool {
|
||||
lstring headers = _head.split("\n");
|
||||
string response = headers.takeLeft().rtrim("\r");
|
||||
string response = headers.takeLeft().trimRight("\r");
|
||||
|
||||
if(response.ibeginsWith("HTTP/1.0 ")) response.iltrim("HTTP/1.0 ", 1L);
|
||||
else if(response.ibeginsWith("HTTP/1.1 ")) response.iltrim("HTTP/1.1 ", 1L);
|
||||
if(response.ibeginsWith("HTTP/1.0 ")) response.itrimLeft("HTTP/1.0 ", 1L);
|
||||
else if(response.ibeginsWith("HTTP/1.1 ")) response.itrimLeft("HTTP/1.1 ", 1L);
|
||||
else return false;
|
||||
|
||||
setResponseType(natural(response));
|
||||
|
@ -113,26 +113,26 @@ auto Response::body(const function<bool (const uint8_t*, unsigned)>& callback) c
|
|||
|
||||
if(chunked) {
|
||||
string prefix = {hex(findContentLength()), "\r\n"};
|
||||
if(!callback(prefix.binary(), prefix.size())) return false;
|
||||
if(!callback(prefix.data<uint8_t>(), prefix.size())) return false;
|
||||
}
|
||||
|
||||
if(_body) {
|
||||
if(!callback(_body.binary(), _body.size())) return false;
|
||||
if(!callback(_body.data<uint8_t>(), _body.size())) return false;
|
||||
} else if(hasData()) {
|
||||
if(!callback(data().data(), data().size())) return false;
|
||||
} else if(hasFile()) {
|
||||
filemap map(file(), filemap::mode::read);
|
||||
if(!callback(map.data(), map.size())) return false;
|
||||
} else if(hasText()) {
|
||||
if(!callback(text().binary(), text().size())) return false;
|
||||
if(!callback(text().data<uint8_t>(), text().size())) return false;
|
||||
} else {
|
||||
string response = findResponseType();
|
||||
if(!callback(response.binary(), response.size())) return false;
|
||||
if(!callback(response.data<uint8_t>(), response.size())) return false;
|
||||
}
|
||||
|
||||
if(chunked) {
|
||||
string suffix = {"\r\n0\r\n\r\n"};
|
||||
if(!callback(suffix.binary(), suffix.size())) return false;
|
||||
if(!callback(suffix.data<uint8_t>(), suffix.size())) return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
|
|
@ -54,7 +54,6 @@ struct image {
|
|||
inline auto write(uint8_t* data, uint64_t value) const -> void;
|
||||
|
||||
inline auto free() -> void;
|
||||
inline auto empty() const -> bool;
|
||||
inline auto load(const string& filename) -> bool;
|
||||
inline auto allocate(unsigned width, unsigned height) -> void;
|
||||
|
||||
|
|
|
@ -86,7 +86,7 @@ auto image::operator=(image&& source) -> image& {
|
|||
}
|
||||
|
||||
image::operator bool() const {
|
||||
return !empty();
|
||||
return _data && _width && _height;
|
||||
}
|
||||
|
||||
auto image::operator==(const image& source) const -> bool {
|
||||
|
@ -137,10 +137,6 @@ auto image::free() -> void {
|
|||
_data = nullptr;
|
||||
}
|
||||
|
||||
auto image::empty() const -> bool {
|
||||
return !_data || !_width || !_height;
|
||||
}
|
||||
|
||||
auto image::load(const string& filename) -> bool {
|
||||
if(loadBMP(filename) == true) return true;
|
||||
if(loadPNG(filename) == true) return true;
|
||||
|
|
|
@ -11,6 +11,9 @@ namespace nall {
|
|||
CoInitialize(0);
|
||||
WSAData wsaData{0};
|
||||
WSAStartup(MAKEWORD(2, 2), &wsaData);
|
||||
_setmode(_fileno(stdin), O_BINARY);
|
||||
_setmode(_fileno(stdout), O_BINARY);
|
||||
_setmode(_fileno(stderr), O_BINARY);
|
||||
utf8_args(argc, argv);
|
||||
#endif
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ struct context {
|
|||
for(auto& item : list) {
|
||||
item.strip();
|
||||
if(item.match("f(?*) ?*")) {
|
||||
item.ltrim("f(", 1L);
|
||||
item.trimLeft("f(", 1L);
|
||||
lstring part = item.split(") ", 1L);
|
||||
lstring args = part[0].split(";", 3L).strip();
|
||||
|
||||
|
@ -90,9 +90,9 @@ struct context {
|
|||
}
|
||||
} else if(item.match("base64*")) {
|
||||
uint offset = 0;
|
||||
item.ltrim("base64", 1L);
|
||||
item.trimLeft("base64", 1L);
|
||||
if(item.match("(?*) *")) {
|
||||
item.ltrim("(", 1L);
|
||||
item.trimLeft("(", 1L);
|
||||
lstring part = item.split(") ", 1L);
|
||||
offset = eval(part[0]);
|
||||
item = part(1, "");
|
||||
|
@ -106,10 +106,10 @@ struct context {
|
|||
if(c == '_') buffer.append(offset + 63);
|
||||
}
|
||||
} else if(item.match("file *")) {
|
||||
item.ltrim("file ", 1L);
|
||||
item.trimLeft("file ", 1L);
|
||||
item.strip();
|
||||
//...
|
||||
} else if(item.empty() == false) {
|
||||
} else if(item) {
|
||||
buffer.append(eval(item));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@
|
|||
#include <nall/matrix.hpp>
|
||||
#include <nall/maybe.hpp>
|
||||
#include <nall/memory.hpp>
|
||||
#include <nall/path.hpp>
|
||||
#include <nall/primitives.hpp>
|
||||
#include <nall/property.hpp>
|
||||
#include <nall/random.hpp>
|
||||
|
|
|
@ -1,44 +1,46 @@
|
|||
#pragma once
|
||||
|
||||
namespace nall {
|
||||
#include <nall/string.hpp>
|
||||
|
||||
auto activepath() -> string {
|
||||
namespace nall { namespace Path {
|
||||
|
||||
inline auto active() -> string {
|
||||
char path[PATH_MAX] = "";
|
||||
auto unused = getcwd(path, PATH_MAX);
|
||||
string result = path;
|
||||
if(!result) result = ".";
|
||||
result.transform("\\", "/");
|
||||
if(result.endsWith("/") == false) result.append("/");
|
||||
if(!result.endsWith("/")) result.append("/");
|
||||
return result;
|
||||
}
|
||||
|
||||
auto realpath(rstring name) -> string {
|
||||
inline auto real(string_view name) -> string {
|
||||
string result;
|
||||
char path[PATH_MAX] = "";
|
||||
if(::realpath(name, path)) result = pathname(string{path}.transform("\\", "/"));
|
||||
if(!result) return activepath();
|
||||
if(!result) return active();
|
||||
result.transform("\\", "/");
|
||||
if(result.endsWith("/") == false) result.append("/");
|
||||
if(!result.endsWith("/")) result.append("/");
|
||||
return result;
|
||||
}
|
||||
|
||||
auto programpath() -> string {
|
||||
inline auto program() -> string {
|
||||
#if defined(PLATFORM_WINDOWS)
|
||||
wchar_t path[PATH_MAX] = L"";
|
||||
GetModuleFileName(nullptr, path, PATH_MAX);
|
||||
string result = (const char*)utf8_t(path);
|
||||
result.transform("\\", "/");
|
||||
return realpath(result);
|
||||
return real(result);
|
||||
#else
|
||||
Dl_info info;
|
||||
dladdr((void*)&programpath, &info);
|
||||
return realpath(info.dli_fname);
|
||||
dladdr((void*)&program, &info);
|
||||
return real(info.dli_fname);
|
||||
#endif
|
||||
}
|
||||
|
||||
// /
|
||||
// c:/
|
||||
auto rootpath() -> string {
|
||||
inline auto root() -> string {
|
||||
#if defined(PLATFORM_WINDOWS)
|
||||
wchar_t path[PATH_MAX] = L"";
|
||||
SHGetFolderPathW(nullptr, CSIDL_WINDOWS | CSIDL_FLAG_CREATE, nullptr, 0, path);
|
||||
|
@ -52,7 +54,7 @@ auto rootpath() -> string {
|
|||
|
||||
// /home/username/
|
||||
// c:/users/username/
|
||||
auto userpath() -> string {
|
||||
inline auto user() -> string {
|
||||
#if defined(PLATFORM_WINDOWS)
|
||||
wchar_t path[PATH_MAX] = L"";
|
||||
SHGetFolderPathW(nullptr, CSIDL_PROFILE | CSIDL_FLAG_CREATE, nullptr, 0, path);
|
||||
|
@ -63,50 +65,50 @@ auto userpath() -> string {
|
|||
string result = userinfo->pw_dir;
|
||||
#endif
|
||||
if(!result) result = ".";
|
||||
if(result.endsWith("/") == false) result.append("/");
|
||||
if(!result.endsWith("/")) result.append("/");
|
||||
return result;
|
||||
}
|
||||
|
||||
// /home/username/.config/
|
||||
// c:/users/username/appdata/roaming/
|
||||
auto configpath() -> string {
|
||||
inline auto config() -> string {
|
||||
#if defined(PLATFORM_WINDOWS)
|
||||
wchar_t path[PATH_MAX] = L"";
|
||||
SHGetFolderPathW(nullptr, CSIDL_APPDATA | CSIDL_FLAG_CREATE, nullptr, 0, path);
|
||||
string result = (const char*)utf8_t(path);
|
||||
result.transform("\\", "/");
|
||||
#elif defined(PLATFORM_MACOSX)
|
||||
string result = {userpath(), "Library/Application Support/"};
|
||||
string result = {user(), "Library/Application Support/"};
|
||||
#else
|
||||
string result = {userpath(), ".config/"};
|
||||
string result = {user(), ".config/"};
|
||||
#endif
|
||||
if(!result) result = ".";
|
||||
if(result.endsWith("/") == false) result.append("/");
|
||||
if(!result.endsWith("/")) result.append("/");
|
||||
return result;
|
||||
}
|
||||
|
||||
// /home/username/.local/share/
|
||||
// c:/users/username/appdata/local/
|
||||
auto localpath() -> string {
|
||||
inline auto local() -> string {
|
||||
#if defined(PLATFORM_WINDOWS)
|
||||
wchar_t path[PATH_MAX] = L"";
|
||||
SHGetFolderPathW(nullptr, CSIDL_LOCAL_APPDATA | CSIDL_FLAG_CREATE, nullptr, 0, path);
|
||||
string result = (const char*)utf8_t(path);
|
||||
result.transform("\\", "/");
|
||||
#elif defined(PLATFORM_MACOSX)
|
||||
string result = {userpath(), "Library/Application Support/"};
|
||||
string result = {user(), "Library/Application Support/"};
|
||||
#else
|
||||
string result = {userpath(), ".local/share/"};
|
||||
string result = {user(), ".local/share/"};
|
||||
#endif
|
||||
if(!result) result = ".";
|
||||
if(result.endsWith("/") == false) result.append("/");
|
||||
if(!result.endsWith("/")) result.append("/");
|
||||
return result;
|
||||
}
|
||||
|
||||
// /usr/share
|
||||
// /Library/Application Support/
|
||||
// c:/ProgramData/
|
||||
auto sharedpath() -> string {
|
||||
inline auto shared() -> string {
|
||||
#if defined(PLATFORM_WINDOWS)
|
||||
wchar_t path[PATH_MAX] = L"";
|
||||
SHGetFolderPathW(nullptr, CSIDL_COMMON_APPDATA | CSIDL_FLAG_CREATE, nullptr, 0, path);
|
||||
|
@ -118,13 +120,13 @@ auto sharedpath() -> string {
|
|||
string result = "/usr/share/";
|
||||
#endif
|
||||
if(!result) result = ".";
|
||||
if(result.endsWith("/") == false) result.append("/");
|
||||
if(!result.endsWith("/")) result.append("/");
|
||||
return result;
|
||||
}
|
||||
|
||||
// /tmp
|
||||
// c:/users/username/AppData/Local/Temp/
|
||||
auto temppath() -> string {
|
||||
inline auto temp() -> string {
|
||||
#if defined(PLATFORM_WINDOWS)
|
||||
wchar_t path[PATH_MAX] = L"";
|
||||
GetTempPathW(PATH_MAX, path);
|
||||
|
@ -135,8 +137,8 @@ auto temppath() -> string {
|
|||
#else
|
||||
string result = "/tmp/";
|
||||
#endif
|
||||
if(result.endsWith("/") == false) result.append("/");
|
||||
if(!result.endsWith("/")) result.append("/");
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
}}
|
|
@ -18,10 +18,6 @@ struct shared_memory {
|
|||
return _mode != mode::inactive;
|
||||
}
|
||||
|
||||
auto empty() const -> bool {
|
||||
return _mode == mode::inactive;
|
||||
}
|
||||
|
||||
auto size() const -> unsigned {
|
||||
return _size;
|
||||
}
|
||||
|
|
110
nall/run.hpp
110
nall/run.hpp
|
@ -16,11 +16,21 @@
|
|||
|
||||
namespace nall {
|
||||
|
||||
struct execute_result_t {
|
||||
explicit operator bool() const { return code == EXIT_SUCCESS; }
|
||||
|
||||
int code = EXIT_FAILURE;
|
||||
string output;
|
||||
string error;
|
||||
};
|
||||
|
||||
#if defined(PLATFORM_MACOSX) || defined(PLATFORM_LINUX) || defined(PLATFORM_BSD)
|
||||
|
||||
template<typename... P> inline auto execute(const string& name, P&&... p) -> string {
|
||||
int fd[2];
|
||||
if(pipe(fd) == -1) return "";
|
||||
template<typename... P> inline auto execute(const string& name, P&&... p) -> execute_result_t {
|
||||
int fdout[2];
|
||||
int fderr[2];
|
||||
if(pipe(fdout) == -1) return {};
|
||||
if(pipe(fderr) == -1) return {};
|
||||
|
||||
pid_t pid = fork();
|
||||
if(pid == 0) {
|
||||
|
@ -31,30 +41,48 @@ template<typename... P> inline auto execute(const string& name, P&&... p) -> str
|
|||
for(auto& arg : argl) *argp++ = (const char*)arg;
|
||||
*argp++ = nullptr;
|
||||
|
||||
dup2(fd[1], STDOUT_FILENO);
|
||||
dup2(fd[1], STDERR_FILENO);
|
||||
close(fd[0]);
|
||||
close(fd[1]);
|
||||
dup2(fdout[1], STDOUT_FILENO);
|
||||
dup2(fderr[1], STDERR_FILENO);
|
||||
close(fdout[0]);
|
||||
close(fderr[0]);
|
||||
close(fdout[1]);
|
||||
close(fderr[1]);
|
||||
execvp(name, (char* const*)argv);
|
||||
//this is called only if execvp fails:
|
||||
//use _exit instead of exit, to avoid destroying key shared file descriptors
|
||||
_exit(0);
|
||||
_exit(EXIT_FAILURE);
|
||||
} else {
|
||||
close(fd[1]);
|
||||
close(fdout[1]);
|
||||
close(fderr[1]);
|
||||
|
||||
char buffer[256];
|
||||
execute_result_t result;
|
||||
|
||||
string result;
|
||||
while(true) {
|
||||
char buffer[256];
|
||||
auto size = read(fd[0], buffer, sizeof(buffer));
|
||||
auto size = read(fdout[0], buffer, sizeof(buffer));
|
||||
if(size <= 0) break;
|
||||
|
||||
auto offset = result.size();
|
||||
result.resize(offset + size);
|
||||
memory::copy(result.get() + offset, buffer, size);
|
||||
auto offset = result.output.size();
|
||||
result.output.resize(offset + size);
|
||||
memory::copy(result.output.get() + offset, buffer, size);
|
||||
}
|
||||
|
||||
close(fd[0]);
|
||||
wait(nullptr);
|
||||
while(true) {
|
||||
auto size = read(fderr[0], buffer, sizeof(buffer));
|
||||
if(size <= 0) break;
|
||||
|
||||
auto offset = result.error.size();
|
||||
result.error.resize(offset + size);
|
||||
memory::copy(result.error.get() + offset, buffer, size);
|
||||
}
|
||||
|
||||
close(fdout[0]);
|
||||
close(fderr[0]);
|
||||
|
||||
int status = 0;
|
||||
waitpid(pid, &status, 0);
|
||||
if(!WIFEXITED(status)) return {};
|
||||
result.code = WEXITSTATUS(status);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -78,7 +106,7 @@ template<typename... P> inline auto invoke(const string& name, P&&... p) -> void
|
|||
|
||||
#elif defined(PLATFORM_WINDOWS)
|
||||
|
||||
template<typename... P> inline auto execute(const string& name, P&&... p) -> string {
|
||||
template<typename... P> inline auto execute(const string& name, P&&... p) -> execute_result_t {
|
||||
lstring argl(name, forward<P>(p)...);
|
||||
for(auto& arg : argl) if(arg.find(" ")) arg = {"\"", arg, "\""};
|
||||
string arguments = argl.merge(" ");
|
||||
|
@ -91,19 +119,24 @@ template<typename... P> inline auto execute(const string& name, P&&... p) -> str
|
|||
|
||||
HANDLE stdoutRead;
|
||||
HANDLE stdoutWrite;
|
||||
if(!CreatePipe(&stdoutRead, &stdoutWrite, &sa, 0)) return "";
|
||||
if(!SetHandleInformation(stdoutRead, HANDLE_FLAG_INHERIT, 0)) return "";
|
||||
if(!CreatePipe(&stdoutRead, &stdoutWrite, &sa, 0)) return {};
|
||||
if(!SetHandleInformation(stdoutRead, HANDLE_FLAG_INHERIT, 0)) return {};
|
||||
|
||||
HANDLE stderrRead;
|
||||
HANDLE stderrWrite;
|
||||
if(!CreatePipe(&stderrRead, &stderrWrite, &sa, 0)) return {};
|
||||
if(!SetHandleInformation(stderrRead, HANDLE_FLAG_INHERIT, 0)) return {};
|
||||
|
||||
HANDLE stdinRead;
|
||||
HANDLE stdinWrite;
|
||||
if(!CreatePipe(&stdinRead, &stdinWrite, &sa, 0)) return "";
|
||||
if(!SetHandleInformation(stdinWrite, HANDLE_FLAG_INHERIT, 0)) return "";
|
||||
if(!CreatePipe(&stdinRead, &stdinWrite, &sa, 0)) return {};
|
||||
if(!SetHandleInformation(stdinWrite, HANDLE_FLAG_INHERIT, 0)) return {};
|
||||
|
||||
STARTUPINFO si;
|
||||
ZeroMemory(&si, sizeof(STARTUPINFO));
|
||||
si.cb = sizeof(STARTUPINFO);
|
||||
si.hStdError = stdoutWrite;
|
||||
si.hStdOutput = stdoutWrite;
|
||||
si.hStdError = stderrWrite;
|
||||
si.hStdInput = stdinRead;
|
||||
si.dwFlags = STARTF_USESTDHANDLES;
|
||||
|
||||
|
@ -114,15 +147,19 @@ template<typename... P> inline auto execute(const string& name, P&&... p) -> str
|
|||
nullptr, utf16_t(arguments),
|
||||
nullptr, nullptr, true, CREATE_NO_WINDOW,
|
||||
nullptr, nullptr, &si, &pi
|
||||
)) return "";
|
||||
)) return {};
|
||||
|
||||
if(WaitForSingleObject(pi.hProcess, INFINITE)) return "";
|
||||
DWORD exitCode = EXIT_FAILURE;
|
||||
if(WaitForSingleObject(pi.hProcess, INFINITE)) return {};
|
||||
if(!GetExitCodeProcess(pi.hProcess, &exitCode)) return {};
|
||||
CloseHandle(pi.hThread);
|
||||
CloseHandle(pi.hProcess);
|
||||
|
||||
string result;
|
||||
char buffer[256];
|
||||
execute_result_t result;
|
||||
result.code = exitCode;
|
||||
|
||||
while(true) {
|
||||
char buffer[256];
|
||||
DWORD read, available, remaining;
|
||||
if(!PeekNamedPipe(stdoutRead, nullptr, sizeof(buffer), &read, &available, &remaining)) break;
|
||||
if(read == 0) break;
|
||||
|
@ -130,9 +167,22 @@ template<typename... P> inline auto execute(const string& name, P&&... p) -> str
|
|||
if(!ReadFile(stdoutRead, buffer, sizeof(buffer), &read, nullptr)) break;
|
||||
if(read == 0) break;
|
||||
|
||||
auto offset = result.size();
|
||||
result.resize(offset + read);
|
||||
memory::copy(result.get() + offset, buffer, read);
|
||||
auto offset = result.output.size();
|
||||
result.output.resize(offset + read);
|
||||
memory::copy(result.output.get() + offset, buffer, read);
|
||||
}
|
||||
|
||||
while(true) {
|
||||
DWORD read, available, remaining;
|
||||
if(!PeekNamedPipe(stderrRead, nullptr, sizeof(buffer), &read, &available, &remaining)) break;
|
||||
if(read == 0) break;
|
||||
|
||||
if(!ReadFile(stderrRead, buffer, sizeof(buffer), &read, nullptr)) break;
|
||||
if(read == 0) break;
|
||||
|
||||
auto offset = result.error.size();
|
||||
result.error.resize(offset + read);
|
||||
memory::copy(result.error.get() + offset, buffer, read);
|
||||
}
|
||||
|
||||
return result;
|
||||
|
|
16
nall/set.hpp
16
nall/set.hpp
|
@ -49,8 +49,8 @@ template<typename T> struct set {
|
|||
return *this;
|
||||
}
|
||||
|
||||
explicit operator bool() const { return nodes; }
|
||||
auto size() const -> unsigned { return nodes; }
|
||||
auto empty() const -> bool { return nodes == 0; }
|
||||
|
||||
auto reset() -> void {
|
||||
reset(root);
|
||||
|
@ -100,13 +100,13 @@ template<typename T> struct set {
|
|||
auto operator++() -> base_iterator& {
|
||||
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]);
|
||||
if(stack.right()->link[1]) {
|
||||
stack.append(stack.right()->link[1]);
|
||||
while(stack.right()->link[0]) stack.append(stack.right()->link[0]);
|
||||
} else {
|
||||
node_t* child;
|
||||
do child = stack.take();
|
||||
while(child == stack.last()->link[1]);
|
||||
do child = stack.takeRight();
|
||||
while(child == stack.right()->link[1]);
|
||||
}
|
||||
|
||||
return *this;
|
||||
|
@ -128,7 +128,7 @@ template<typename T> struct set {
|
|||
|
||||
struct iterator : base_iterator {
|
||||
iterator(const set& source, unsigned position) : base_iterator(source, position) {}
|
||||
auto operator*() const -> T& { return base_iterator::stack.last()->value; }
|
||||
auto operator*() const -> T& { return base_iterator::stack.right()->value; }
|
||||
};
|
||||
|
||||
auto begin() -> iterator { return iterator(*this, 0); }
|
||||
|
@ -136,7 +136,7 @@ template<typename T> struct set {
|
|||
|
||||
struct const_iterator : base_iterator {
|
||||
const_iterator(const set& source, unsigned position) : base_iterator(source, position) {}
|
||||
auto operator*() const -> const T& { return base_iterator::stack.last()->value; }
|
||||
auto operator*() const -> const T& { return base_iterator::stack.right()->value; }
|
||||
};
|
||||
|
||||
auto begin() const -> const const_iterator { return const_iterator(*this, 0); }
|
||||
|
|
|
@ -170,11 +170,7 @@ struct shared_pointer {
|
|||
}
|
||||
|
||||
explicit operator bool() const {
|
||||
return !empty();
|
||||
}
|
||||
|
||||
auto empty() const -> bool {
|
||||
return !manager || !manager->strong;
|
||||
return manager && manager->strong;
|
||||
}
|
||||
|
||||
auto unique() const -> bool {
|
||||
|
@ -242,11 +238,7 @@ struct shared_pointer_weak {
|
|||
}
|
||||
|
||||
explicit operator bool() const {
|
||||
return !empty();
|
||||
}
|
||||
|
||||
auto empty() const -> bool {
|
||||
return !manager || !manager->strong;
|
||||
return manager && manager->strong;
|
||||
}
|
||||
|
||||
auto acquire() const -> shared_pointer<T> {
|
||||
|
|
|
@ -272,7 +272,7 @@ auto SMTP::contacts(const vector<Information::Contact>& contacts) -> string {
|
|||
for(auto& contact : contacts) {
|
||||
result.append(this->contact(contact), "; ");
|
||||
}
|
||||
result.rtrim("; ", 1L);
|
||||
result.trimRight("; ", 1L);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,10 +29,6 @@ struct stream {
|
|||
return size();
|
||||
}
|
||||
|
||||
auto empty() const -> bool {
|
||||
return size() == 0;
|
||||
}
|
||||
|
||||
auto end() const -> bool {
|
||||
return offset() >= size();
|
||||
}
|
||||
|
|
305
nall/string.hpp
305
nall/string.hpp
|
@ -20,12 +20,305 @@
|
|||
#include <nall/utility.hpp>
|
||||
#include <nall/varint.hpp>
|
||||
#include <nall/vector.hpp>
|
||||
#include <nall/hash/crc16.hpp>
|
||||
#include <nall/hash/crc32.hpp>
|
||||
#include <nall/hash/crc64.hpp>
|
||||
#include <nall/hash/sha256.hpp>
|
||||
|
||||
#include <nall/string/base.hpp>
|
||||
namespace nall {
|
||||
|
||||
struct string;
|
||||
struct format;
|
||||
struct lstring;
|
||||
|
||||
struct string_view {
|
||||
inline string_view();
|
||||
inline string_view(const string_view& source);
|
||||
inline string_view(string_view&& source);
|
||||
inline string_view(const char* data);
|
||||
inline string_view(const char* data, uint size);
|
||||
inline string_view(const string& source);
|
||||
template<typename... P> inline string_view(P&&... p);
|
||||
inline ~string_view();
|
||||
|
||||
inline auto operator=(const string_view& source) -> string_view&;
|
||||
inline auto operator=(string_view&& source) -> string_view&;
|
||||
|
||||
inline operator const char*() const;
|
||||
inline auto data() const -> const char*;
|
||||
inline auto size() const -> uint;
|
||||
|
||||
protected:
|
||||
string* _string;
|
||||
const char* _data;
|
||||
mutable int _size;
|
||||
};
|
||||
|
||||
#define NALL_STRING_ALLOCATOR_ADAPTIVE
|
||||
//#define NALL_STRING_ALLOCATOR_COPY_ON_WRITE
|
||||
//#define NALL_STRING_ALLOCATOR_SMALL_STRING_OPTIMIZATION
|
||||
//#define NALL_STRING_ALLOCATOR_VECTOR
|
||||
|
||||
//cast.hpp
|
||||
template<typename T> struct stringify;
|
||||
|
||||
//format.hpp
|
||||
template<typename... P> inline auto print(P&&...) -> void;
|
||||
template<typename... P> inline auto print(FILE*, P&&...) -> void;
|
||||
inline auto integer(intmax value, long precision = 0, char padchar = '0') -> string;
|
||||
inline auto natural(uintmax value, long precision = 0, char padchar = '0') -> string;
|
||||
inline auto hex(uintmax value, long precision = 0, char padchar = '0') -> string;
|
||||
inline auto octal(uintmax value, long precision = 0, char padchar = '0') -> string;
|
||||
inline auto binary(uintmax value, long precision = 0, char padchar = '0') -> string;
|
||||
template<typename T> inline auto pointer(const T* value, long precision = 0) -> string;
|
||||
inline auto pointer(uintptr value, long precision = 0) -> string;
|
||||
inline auto real(long double value) -> string;
|
||||
|
||||
//match.hpp
|
||||
inline auto tokenize(const char* s, const char* p) -> bool;
|
||||
inline auto tokenize(lstring& list, const char* s, const char* p) -> bool;
|
||||
|
||||
//path.hpp
|
||||
inline auto pathname(string_view self) -> string;
|
||||
inline auto filename(string_view self) -> string;
|
||||
|
||||
inline auto dirname(string_view self) -> string;
|
||||
inline auto basename(string_view self) -> string;
|
||||
inline auto prefixname(string_view self) -> string;
|
||||
inline auto suffixname(string_view self) -> string;
|
||||
|
||||
//utility.hpp
|
||||
inline auto slice(string_view self, int offset = 0, int length = -1) -> string;
|
||||
|
||||
inline auto integer(char* result, intmax value) -> char*;
|
||||
inline auto natural(char* result, uintmax value) -> char*;
|
||||
inline auto real(char* str, long double value) -> uint;
|
||||
|
||||
struct string {
|
||||
using type = string;
|
||||
|
||||
protected:
|
||||
#if defined(NALL_STRING_ALLOCATOR_ADAPTIVE)
|
||||
enum : uint { SSO = 24 };
|
||||
union {
|
||||
struct { //copy-on-write
|
||||
char* _data;
|
||||
uint* _refs;
|
||||
};
|
||||
struct { //small-string-optimization
|
||||
char _text[SSO];
|
||||
};
|
||||
};
|
||||
inline auto _allocate() -> void;
|
||||
inline auto _copy() -> void;
|
||||
inline auto _resize() -> void;
|
||||
#endif
|
||||
|
||||
#if defined(NALL_STRING_ALLOCATOR_COPY_ON_WRITE)
|
||||
char* _data;
|
||||
mutable uint* _refs;
|
||||
inline auto _allocate() -> char*;
|
||||
inline auto _copy() -> char*;
|
||||
#endif
|
||||
|
||||
#if defined(NALL_STRING_ALLOCATOR_SMALL_STRING_OPTIMIZATION)
|
||||
enum : uint { SSO = 24 };
|
||||
union {
|
||||
char* _data;
|
||||
char _text[SSO];
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(NALL_STRING_ALLOCATOR_VECTOR)
|
||||
char* _data;
|
||||
#endif
|
||||
|
||||
uint _capacity;
|
||||
uint _size;
|
||||
|
||||
public:
|
||||
inline string();
|
||||
template<typename T = char> inline auto get() -> T*;
|
||||
template<typename T = char> inline auto data() const -> const T*;
|
||||
inline auto reset() -> type&;
|
||||
inline auto reserve(uint) -> type&;
|
||||
inline auto resize(uint) -> type&;
|
||||
inline auto operator=(const string&) -> type&;
|
||||
inline auto operator=(string&&) -> type&;
|
||||
|
||||
template<typename T, typename... P> string(T&& s, P&&... p) : string() {
|
||||
append(forward<T>(s), forward<P>(p)...);
|
||||
}
|
||||
~string() { reset(); }
|
||||
|
||||
explicit operator bool() const { return _size; }
|
||||
operator const char*() const { return (const char*)data(); }
|
||||
|
||||
auto size() const -> uint { return _size; }
|
||||
auto capacity() const -> uint { return _capacity; }
|
||||
|
||||
auto operator==(const string& source) const -> bool {
|
||||
return size() == source.size() && memory::compare(data(), source.data(), size()) == 0;
|
||||
}
|
||||
auto operator!=(const string& source) const -> bool {
|
||||
return size() != source.size() || memory::compare(data(), source.data(), size()) != 0;
|
||||
}
|
||||
|
||||
auto operator==(const char* source) const -> bool { return strcmp(data(), source) == 0; }
|
||||
auto operator!=(const char* source) const -> bool { return strcmp(data(), source) != 0; }
|
||||
|
||||
auto operator==(string_view source) const -> bool { return compare(source) == 0; }
|
||||
auto operator!=(string_view source) const -> bool { return compare(source) != 0; }
|
||||
auto operator< (string_view source) const -> bool { return compare(source) < 0; }
|
||||
auto operator<=(string_view source) const -> bool { return compare(source) <= 0; }
|
||||
auto operator> (string_view source) const -> bool { return compare(source) > 0; }
|
||||
auto operator>=(string_view source) const -> bool { return compare(source) >= 0; }
|
||||
|
||||
string(const string& source) : string() { operator=(source); }
|
||||
string(string&& source) : string() { operator=(move(source)); }
|
||||
|
||||
auto begin() -> char* { return &get()[0]; }
|
||||
auto end() -> char* { return &get()[size()]; }
|
||||
auto begin() const -> const char* { return &data()[0]; }
|
||||
auto end() const -> const char* { return &data()[size()]; }
|
||||
|
||||
//atoi.hpp
|
||||
inline auto integer() const -> intmax;
|
||||
inline auto natural() const -> uintmax;
|
||||
inline auto real() const -> double;
|
||||
|
||||
//core.hpp
|
||||
inline auto operator[](int) const -> const char&;
|
||||
template<typename... P> inline auto assign(P&&...) -> type&;
|
||||
template<typename T, typename... P> inline auto append(const T&, P&&...) -> type&;
|
||||
template<typename... P> inline auto append(const nall::format&, P&&...) -> type&;
|
||||
inline auto append() -> type&;
|
||||
template<typename T> inline auto _append(const stringify<T>&) -> string&;
|
||||
inline auto length() const -> uint;
|
||||
|
||||
//datetime.hpp
|
||||
inline static auto date(time_t = 0) -> string;
|
||||
inline static auto time(time_t = 0) -> string;
|
||||
inline static auto datetime(time_t = 0) -> string;
|
||||
|
||||
//find.hpp
|
||||
template<bool, bool> inline auto _find(int, string_view) const -> maybe<uint>;
|
||||
|
||||
inline auto find(string_view source) const -> maybe<uint>;
|
||||
inline auto ifind(string_view source) const -> maybe<uint>;
|
||||
inline auto qfind(string_view source) const -> maybe<uint>;
|
||||
inline auto iqfind(string_view source) const -> maybe<uint>;
|
||||
|
||||
inline auto findFrom(int offset, string_view source) const -> maybe<uint>;
|
||||
inline auto ifindFrom(int offset, string_view source) const -> maybe<uint>;
|
||||
|
||||
//format.hpp
|
||||
inline auto format(const nall::format& params) -> type&;
|
||||
|
||||
//compare.hpp
|
||||
template<bool> inline static auto _compare(const char*, uint, const char*, uint) -> int;
|
||||
|
||||
inline static auto compare(string_view, string_view) -> int;
|
||||
inline static auto icompare(string_view, string_view) -> int;
|
||||
|
||||
inline auto compare(string_view source) const -> int;
|
||||
inline auto icompare(string_view source) const -> int;
|
||||
|
||||
inline auto equals(string_view source) const -> bool;
|
||||
inline auto iequals(string_view source) const -> bool;
|
||||
|
||||
inline auto beginsWith(string_view source) const -> bool;
|
||||
inline auto ibeginsWith(string_view source) const -> bool;
|
||||
|
||||
inline auto endsWith(string_view source) const -> bool;
|
||||
inline auto iendsWith(string_view source) const -> bool;
|
||||
|
||||
//convert.hpp
|
||||
inline auto downcase() -> type&;
|
||||
inline auto upcase() -> type&;
|
||||
|
||||
inline auto qdowncase() -> type&;
|
||||
inline auto qupcase() -> type&;
|
||||
|
||||
inline auto transform(string_view from, string_view to) -> type&;
|
||||
|
||||
//match.hpp
|
||||
inline auto match(string_view source) const -> bool;
|
||||
inline auto imatch(string_view source) const -> bool;
|
||||
|
||||
//replace.hpp
|
||||
template<bool, bool> inline auto _replace(string_view, string_view, long) -> type&;
|
||||
inline auto replace(string_view from, string_view to, long limit = LONG_MAX) -> type&;
|
||||
inline auto ireplace(string_view from, string_view to, long limit = LONG_MAX) -> type&;
|
||||
inline auto qreplace(string_view from, string_view to, long limit = LONG_MAX) -> type&;
|
||||
inline auto iqreplace(string_view from, string_view to, long limit = LONG_MAX) -> type&;
|
||||
|
||||
//split.hpp
|
||||
inline auto split(string_view key, long limit = LONG_MAX) const -> lstring;
|
||||
inline auto isplit(string_view key, long limit = LONG_MAX) const -> lstring;
|
||||
inline auto qsplit(string_view key, long limit = LONG_MAX) const -> lstring;
|
||||
inline auto iqsplit(string_view key, long limit = LONG_MAX) const -> lstring;
|
||||
|
||||
//trim.hpp
|
||||
inline auto trim(string_view lhs, string_view rhs, long limit = LONG_MAX) -> type&;
|
||||
inline auto trimLeft(string_view lhs, long limit = LONG_MAX) -> type&;
|
||||
inline auto trimRight(string_view rhs, long limit = LONG_MAX) -> type&;
|
||||
|
||||
inline auto itrim(string_view lhs, string_view rhs, long limit = LONG_MAX) -> type&;
|
||||
inline auto itrimLeft(string_view lhs, long limit = LONG_MAX) -> type&;
|
||||
inline auto itrimRight(string_view rhs, long limit = LONG_MAX) -> type&;
|
||||
|
||||
inline auto strip() -> type&;
|
||||
inline auto stripLeft() -> type&;
|
||||
inline auto stripRight() -> type&;
|
||||
|
||||
//utility.hpp
|
||||
inline static auto read(string_view filename) -> string;
|
||||
inline static auto repeat(string_view pattern, uint times) -> string;
|
||||
inline auto fill(char fill = ' ') -> type&;
|
||||
inline auto hash() const -> uint;
|
||||
inline auto remove(uint offset, uint length) -> type&;
|
||||
inline auto reverse() -> type&;
|
||||
inline auto size(int length, char fill = ' ') -> type&;
|
||||
};
|
||||
|
||||
struct lstring : vector<string> {
|
||||
using type = lstring;
|
||||
|
||||
lstring(const lstring& source) { vector::operator=(source); }
|
||||
lstring(lstring& source) { vector::operator=(source); }
|
||||
lstring(lstring&& source) { vector::operator=(move(source)); }
|
||||
template<typename... P> lstring(P&&... p) { append(forward<P>(p)...); }
|
||||
|
||||
//list.hpp
|
||||
inline auto operator==(const lstring&) const -> bool;
|
||||
inline auto operator!=(const lstring&) const -> bool;
|
||||
|
||||
inline auto operator=(const lstring& source) -> type& { return vector::operator=(source), *this; }
|
||||
inline auto operator=(lstring& source) -> type& { return vector::operator=(source), *this; }
|
||||
inline auto operator=(lstring&& source) -> type& { return vector::operator=(move(source)), *this; }
|
||||
|
||||
inline auto isort() -> type&;
|
||||
|
||||
template<typename... P> inline auto append(const string&, P&&...) -> type&;
|
||||
inline auto append() -> type&;
|
||||
|
||||
inline auto find(string_view source) const -> maybe<uint>;
|
||||
inline auto ifind(string_view source) const -> maybe<uint>;
|
||||
inline auto match(string_view pattern) const -> lstring;
|
||||
inline auto merge(string_view separator) const -> string;
|
||||
inline auto strip() -> type&;
|
||||
|
||||
//split.hpp
|
||||
template<bool, bool> inline auto _split(string_view, string_view, long) -> lstring&;
|
||||
};
|
||||
|
||||
struct format : vector<string> {
|
||||
using type = format;
|
||||
|
||||
template<typename... P> format(P&&... p) { reserve(sizeof...(p)); append(forward<P>(p)...); }
|
||||
template<typename T, typename... P> inline auto append(const T&, P&&... p) -> type&;
|
||||
inline auto append() -> type&;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#include <nall/string/view.hpp>
|
||||
#include <nall/string/atoi.hpp>
|
||||
#include <nall/string/cast.hpp>
|
||||
|
@ -35,11 +328,9 @@
|
|||
#include <nall/string/datetime.hpp>
|
||||
#include <nall/string/find.hpp>
|
||||
#include <nall/string/format.hpp>
|
||||
#include <nall/string/hash.hpp>
|
||||
#include <nall/string/list.hpp>
|
||||
#include <nall/string/match.hpp>
|
||||
#include <nall/string/path.hpp>
|
||||
#include <nall/string/platform.hpp>
|
||||
#include <nall/string/replace.hpp>
|
||||
#include <nall/string/split.hpp>
|
||||
#include <nall/string/trim.hpp>
|
||||
|
|
|
@ -22,15 +22,17 @@ namespace nall {
|
|||
string::string() : _data(nullptr), _capacity(SSO - 1), _size(0) {
|
||||
}
|
||||
|
||||
auto string::get() -> char* {
|
||||
if(_capacity < SSO) return _text;
|
||||
template<typename T>
|
||||
auto string::get() -> T* {
|
||||
if(_capacity < SSO) return (T*)_text;
|
||||
if(*_refs > 1) _copy();
|
||||
return _data;
|
||||
return (T*)_data;
|
||||
}
|
||||
|
||||
auto string::data() const -> const char* {
|
||||
if(_capacity < SSO) return _text;
|
||||
return _data;
|
||||
template<typename T>
|
||||
auto string::data() const -> const T* {
|
||||
if(_capacity < SSO) return (const T*)_text;
|
||||
return (const T*)_data;
|
||||
}
|
||||
|
||||
auto string::reset() -> type& {
|
||||
|
|
|
@ -1,294 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
namespace nall {
|
||||
|
||||
struct string_view;
|
||||
struct string;
|
||||
struct format;
|
||||
struct lstring;
|
||||
|
||||
using rstring = const string_view&;
|
||||
using cstring = const string&;
|
||||
|
||||
#define NALL_STRING_ALLOCATOR_ADAPTIVE
|
||||
//#define NALL_STRING_ALLOCATOR_COPY_ON_WRITE
|
||||
//#define NALL_STRING_ALLOCATOR_SMALL_STRING_OPTIMIZATION
|
||||
//#define NALL_STRING_ALLOCATOR_VECTOR
|
||||
|
||||
//cast.hpp
|
||||
template<typename T> struct stringify;
|
||||
|
||||
//format.hpp
|
||||
template<typename... P> inline auto print(P&&...) -> void;
|
||||
inline auto integer(intmax value, long precision = 0, char padchar = '0') -> string;
|
||||
inline auto natural(uintmax value, long precision = 0, char padchar = '0') -> string;
|
||||
inline auto hex(uintmax value, long precision = 0, char padchar = '0') -> string;
|
||||
inline auto octal(uintmax value, long precision = 0, char padchar = '0') -> string;
|
||||
inline auto binary(uintmax value, long precision = 0, char padchar = '0') -> string;
|
||||
template<typename T> inline auto pointer(const T* value, long precision = 0) -> string;
|
||||
inline auto pointer(uintptr value, long precision = 0) -> string;
|
||||
inline auto real(long double value) -> string;
|
||||
|
||||
//hash.hpp
|
||||
inline auto crc16(rstring self) -> string;
|
||||
inline auto crc32(rstring self) -> string;
|
||||
inline auto crc64(rstring self) -> string;
|
||||
inline auto sha256(rstring self) -> string;
|
||||
|
||||
//match.hpp
|
||||
inline auto tokenize(const char* s, const char* p) -> bool;
|
||||
inline auto tokenize(lstring& list, const char* s, const char* p) -> bool;
|
||||
|
||||
//path.hpp
|
||||
inline auto pathname(rstring self) -> string;
|
||||
inline auto filename(rstring self) -> string;
|
||||
|
||||
inline auto dirname(rstring self) -> string;
|
||||
inline auto basename(rstring self) -> string;
|
||||
inline auto prefixname(rstring self) -> string;
|
||||
inline auto suffixname(rstring self) -> string;
|
||||
|
||||
//platform.hpp
|
||||
inline auto activepath() -> string;
|
||||
inline auto realpath(rstring name) -> string;
|
||||
inline auto programpath() -> string;
|
||||
inline auto rootpath() -> string;
|
||||
inline auto userpath() -> string;
|
||||
inline auto configpath() -> string;
|
||||
inline auto localpath() -> string;
|
||||
inline auto sharedpath() -> string;
|
||||
inline auto temppath() -> string;
|
||||
|
||||
//utility.hpp
|
||||
inline auto slice(rstring self, int offset = 0, int length = -1) -> string;
|
||||
|
||||
inline auto integer(char* result, intmax value) -> char*;
|
||||
inline auto natural(char* result, uintmax value) -> char*;
|
||||
inline auto real(char* str, long double value) -> uint;
|
||||
|
||||
struct string {
|
||||
using type = string;
|
||||
struct exception_out_of_bounds{};
|
||||
|
||||
protected:
|
||||
#if defined(NALL_STRING_ALLOCATOR_ADAPTIVE)
|
||||
enum : uint { SSO = 24 };
|
||||
union {
|
||||
struct { //copy-on-write
|
||||
char* _data;
|
||||
uint* _refs;
|
||||
};
|
||||
struct { //small-string-optimization
|
||||
char _text[SSO];
|
||||
};
|
||||
};
|
||||
inline auto _allocate() -> void;
|
||||
inline auto _copy() -> void;
|
||||
inline auto _resize() -> void;
|
||||
#endif
|
||||
|
||||
#if defined(NALL_STRING_ALLOCATOR_COPY_ON_WRITE)
|
||||
char* _data;
|
||||
mutable uint* _refs;
|
||||
inline auto _allocate() -> char*;
|
||||
inline auto _copy() -> char*;
|
||||
#endif
|
||||
|
||||
#if defined(NALL_STRING_ALLOCATOR_SMALL_STRING_OPTIMIZATION)
|
||||
enum : uint { SSO = 24 };
|
||||
union {
|
||||
char* _data;
|
||||
char _text[SSO];
|
||||
};
|
||||
#endif
|
||||
|
||||
#if defined(NALL_STRING_ALLOCATOR_VECTOR)
|
||||
char* _data;
|
||||
#endif
|
||||
|
||||
uint _capacity;
|
||||
uint _size;
|
||||
|
||||
public:
|
||||
inline string();
|
||||
inline auto get() -> char*;
|
||||
inline auto data() const -> const char*;
|
||||
inline auto reset() -> type&;
|
||||
inline auto reserve(uint) -> type&;
|
||||
inline auto resize(uint) -> type&;
|
||||
inline auto operator=(const string&) -> type&;
|
||||
inline auto operator=(string&&) -> type&;
|
||||
|
||||
template<typename T, typename... P> string(T&& s, P&&... p) : string() { append(forward<T>(s), forward<P>(p)...); }
|
||||
~string() { reset(); }
|
||||
|
||||
explicit operator bool() const { return _size; }
|
||||
operator const uint8_t*() const { return (const uint8_t*)data(); }
|
||||
operator const char*() const { return (const char*)data(); }
|
||||
|
||||
auto binary() const -> const uint8_t* { return (const uint8_t*)data(); }
|
||||
auto size() const -> uint { return _size; }
|
||||
auto capacity() const -> uint { return _capacity; }
|
||||
|
||||
auto operator==(const string& source) const -> bool { return size() == source.size() && memory::compare(data(), source.data(), size()) == 0; }
|
||||
auto operator!=(const string& source) const -> bool { return size() != source.size() || memory::compare(data(), source.data(), size()) != 0; }
|
||||
|
||||
auto operator==(const char* source) const -> bool { return strcmp(data(), source) == 0; }
|
||||
auto operator!=(const char* source) const -> bool { return strcmp(data(), source) != 0; }
|
||||
|
||||
auto operator==(rstring source) const -> bool { return compare(source) == 0; }
|
||||
auto operator!=(rstring source) const -> bool { return compare(source) != 0; }
|
||||
auto operator< (rstring source) const -> bool { return compare(source) < 0; }
|
||||
auto operator<=(rstring source) const -> bool { return compare(source) <= 0; }
|
||||
auto operator> (rstring source) const -> bool { return compare(source) > 0; }
|
||||
auto operator>=(rstring source) const -> bool { return compare(source) >= 0; }
|
||||
|
||||
string(const string& source) : string() { operator=(source); }
|
||||
string(string&& source) : string() { operator=(move(source)); }
|
||||
|
||||
auto begin() -> char* { return &get()[0]; }
|
||||
auto end() -> char* { return &get()[size()]; }
|
||||
auto begin() const -> const char* { return &data()[0]; }
|
||||
auto end() const -> const char* { return &data()[size()]; }
|
||||
|
||||
//atoi.hpp
|
||||
inline auto integer() const -> intmax;
|
||||
inline auto natural() const -> uintmax;
|
||||
inline auto real() const -> double;
|
||||
|
||||
//core.hpp
|
||||
inline auto operator[](int) const -> const char&;
|
||||
template<typename... P> inline auto assign(P&&...) -> type&;
|
||||
template<typename T, typename... P> inline auto append(const T&, P&&...) -> type&;
|
||||
template<typename... P> inline auto append(const nall::format&, P&&...) -> type&;
|
||||
inline auto append() -> type&;
|
||||
template<typename T> inline auto _append(const stringify<T>&) -> string&;
|
||||
inline auto empty() const -> bool;
|
||||
inline auto length() const -> uint;
|
||||
|
||||
//datetime.hpp
|
||||
inline static auto date(time_t = 0) -> string;
|
||||
inline static auto time(time_t = 0) -> string;
|
||||
inline static auto datetime(time_t = 0) -> string;
|
||||
|
||||
//find.hpp
|
||||
template<bool, bool> inline auto _find(int, rstring) const -> maybe<uint>;
|
||||
|
||||
inline auto find(rstring source) const -> maybe<unsigned>;
|
||||
inline auto ifind(rstring source) const -> maybe<unsigned>;
|
||||
inline auto qfind(rstring source) const -> maybe<unsigned>;
|
||||
inline auto iqfind(rstring source) const -> maybe<unsigned>;
|
||||
|
||||
inline auto findFrom(int offset, rstring source) const -> maybe<uint>;
|
||||
inline auto ifindFrom(int offset, rstring source) const -> maybe<uint>;
|
||||
|
||||
//format.hpp
|
||||
inline auto format(const nall::format& params) -> type&;
|
||||
|
||||
//compare.hpp
|
||||
template<bool> inline static auto _compare(const char*, uint, const char*, uint) -> signed;
|
||||
|
||||
inline static auto compare(rstring, rstring) -> signed;
|
||||
inline static auto icompare(rstring, rstring) -> signed;
|
||||
|
||||
inline auto compare(rstring source) const -> signed;
|
||||
inline auto icompare(rstring source) const -> signed;
|
||||
|
||||
inline auto equals(rstring source) const -> bool;
|
||||
inline auto iequals(rstring source) const -> bool;
|
||||
|
||||
inline auto beginsWith(rstring source) const -> bool;
|
||||
inline auto ibeginsWith(rstring source) const -> bool;
|
||||
|
||||
inline auto endsWith(rstring source) const -> bool;
|
||||
inline auto iendsWith(rstring source) const -> bool;
|
||||
|
||||
//convert.hpp
|
||||
inline auto downcase() -> type&;
|
||||
inline auto upcase() -> type&;
|
||||
|
||||
inline auto qdowncase() -> type&;
|
||||
inline auto qupcase() -> type&;
|
||||
|
||||
inline auto transform(rstring from, rstring to) -> type&;
|
||||
|
||||
//match.hpp
|
||||
inline auto match(rstring source) const -> bool;
|
||||
inline auto imatch(rstring source) const -> bool;
|
||||
|
||||
//replace.hpp
|
||||
template<bool, bool> inline auto _replace(rstring, rstring, long) -> type&;
|
||||
inline auto replace(rstring from, rstring to, long limit = LONG_MAX) -> type&;
|
||||
inline auto ireplace(rstring from, rstring to, long limit = LONG_MAX) -> type&;
|
||||
inline auto qreplace(rstring from, rstring to, long limit = LONG_MAX) -> type&;
|
||||
inline auto iqreplace(rstring from, rstring to, long limit = LONG_MAX) -> type&;
|
||||
|
||||
//split.hpp
|
||||
inline auto split(rstring key, long limit = LONG_MAX) const -> lstring;
|
||||
inline auto isplit(rstring key, long limit = LONG_MAX) const -> lstring;
|
||||
inline auto qsplit(rstring key, long limit = LONG_MAX) const -> lstring;
|
||||
inline auto iqsplit(rstring key, long limit = LONG_MAX) const -> lstring;
|
||||
|
||||
//trim.hpp
|
||||
inline auto trim(rstring lhs, rstring rhs, long limit = LONG_MAX) -> type&;
|
||||
inline auto ltrim(rstring lhs, long limit = LONG_MAX) -> type&;
|
||||
inline auto rtrim(rstring rhs, long limit = LONG_MAX) -> type&;
|
||||
|
||||
inline auto itrim(rstring lhs, rstring rhs, long limit = LONG_MAX) -> type&;
|
||||
inline auto iltrim(rstring lhs, long limit = LONG_MAX) -> type&;
|
||||
inline auto irtrim(rstring rhs, long limit = LONG_MAX) -> type&;
|
||||
|
||||
inline auto strip() -> type&;
|
||||
inline auto lstrip() -> type&;
|
||||
inline auto rstrip() -> type&;
|
||||
|
||||
//utility.hpp
|
||||
inline static auto read(rstring filename) -> string;
|
||||
inline static auto repeat(rstring pattern, uint times) -> string;
|
||||
inline auto fill(char fill = ' ') -> type&;
|
||||
inline auto hash() const -> uint;
|
||||
inline auto remove(uint offset, uint length) -> type&;
|
||||
inline auto reverse() -> type&;
|
||||
inline auto size(int length, char fill = ' ') -> type&;
|
||||
};
|
||||
|
||||
struct lstring : vector<string> {
|
||||
using type = lstring;
|
||||
|
||||
lstring(const lstring& source) { vector::operator=(source); }
|
||||
lstring(lstring& source) { vector::operator=(source); }
|
||||
lstring(lstring&& source) { vector::operator=(move(source)); }
|
||||
template<typename... P> lstring(P&&... p) { append(forward<P>(p)...); }
|
||||
|
||||
//list.hpp
|
||||
inline auto operator==(const lstring&) const -> bool;
|
||||
inline auto operator!=(const lstring&) const -> bool;
|
||||
|
||||
inline auto operator=(const lstring& source) -> type& { return vector::operator=(source), *this; }
|
||||
inline auto operator=(lstring& source) -> type& { return vector::operator=(source), *this; }
|
||||
inline auto operator=(lstring&& source) -> type& { return vector::operator=(move(source)), *this; }
|
||||
|
||||
inline auto isort() -> type&;
|
||||
|
||||
template<typename... P> inline auto append(const string&, P&&...) -> type&;
|
||||
inline auto append() -> type&;
|
||||
|
||||
inline auto find(rstring source) const -> maybe<uint>;
|
||||
inline auto ifind(rstring source) const -> maybe<uint>;
|
||||
inline auto match(rstring pattern) const -> lstring;
|
||||
inline auto merge(rstring separator) const -> string;
|
||||
inline auto strip() -> type&;
|
||||
|
||||
//split.hpp
|
||||
template<bool, bool> inline auto _split(rstring, rstring, long) -> lstring&;
|
||||
};
|
||||
|
||||
struct format : vector<string> {
|
||||
using type = format;
|
||||
|
||||
template<typename... P> format(P&&... p) { reserve(sizeof...(p)); append(forward<P>(p)...); }
|
||||
template<typename T, typename... P> inline auto append(const T&, P&&... p) -> type&;
|
||||
inline auto append() -> type&;
|
||||
};
|
||||
|
||||
}
|
|
@ -10,7 +10,7 @@ namespace nall {
|
|||
template<> struct stringify<bool> {
|
||||
stringify(bool value) : _value(value) {}
|
||||
auto data() const -> const char* { return _value ? "true" : "false"; }
|
||||
auto size() const -> unsigned { return _value ? 4 : 5; }
|
||||
auto size() const -> uint { return _value ? 4 : 5; }
|
||||
bool _value;
|
||||
};
|
||||
|
||||
|
@ -26,7 +26,7 @@ template<> struct stringify<Boolean> {
|
|||
template<> struct stringify<char> {
|
||||
stringify(char source) { _data[0] = source; _data[1] = 0; }
|
||||
auto data() const -> const char* { return _data; }
|
||||
auto size() const -> unsigned { return 1; }
|
||||
auto size() const -> uint { return 1; }
|
||||
char _data[2];
|
||||
};
|
||||
|
||||
|
@ -35,35 +35,35 @@ template<> struct stringify<char> {
|
|||
template<> struct stringify<signed char> {
|
||||
stringify(signed char source) { integer(_data, source); }
|
||||
auto data() const -> const char* { return _data; }
|
||||
auto size() const -> unsigned { return strlen(_data); }
|
||||
auto size() const -> uint { return strlen(_data); }
|
||||
char _data[2 + sizeof(signed char) * 3];
|
||||
};
|
||||
|
||||
template<> struct stringify<signed short> {
|
||||
stringify(signed short source) { integer(_data, source); }
|
||||
auto data() const -> const char* { return _data; }
|
||||
auto size() const -> unsigned { return strlen(_data); }
|
||||
auto size() const -> uint { return strlen(_data); }
|
||||
char _data[2 + sizeof(signed short) * 3];
|
||||
};
|
||||
|
||||
template<> struct stringify<signed int> {
|
||||
stringify(signed int source) { integer(_data, source); }
|
||||
auto data() const -> const char* { return _data; }
|
||||
auto size() const -> unsigned { return strlen(_data); }
|
||||
auto size() const -> uint { return strlen(_data); }
|
||||
char _data[2 + sizeof(signed int) * 3];
|
||||
};
|
||||
|
||||
template<> struct stringify<signed long> {
|
||||
stringify(signed long source) { integer(_data, source); }
|
||||
auto data() const -> const char* { return _data; }
|
||||
auto size() const -> unsigned { return strlen(_data); }
|
||||
auto size() const -> uint { return strlen(_data); }
|
||||
char _data[2 + sizeof(signed long) * 3];
|
||||
};
|
||||
|
||||
template<> struct stringify<signed long long> {
|
||||
stringify(signed long long source) { integer(_data, source); }
|
||||
auto data() const -> const char* { return _data; }
|
||||
auto size() const -> unsigned { return strlen(_data); }
|
||||
auto size() const -> uint { return strlen(_data); }
|
||||
char _data[2 + sizeof(signed long long) * 3];
|
||||
};
|
||||
|
||||
|
@ -79,35 +79,35 @@ template<uint Bits> struct stringify<Integer<Bits>> {
|
|||
template<> struct stringify<unsigned char> {
|
||||
stringify(unsigned char source) { natural(_data, source); }
|
||||
auto data() const -> const char* { return _data; }
|
||||
auto size() const -> unsigned { return strlen(_data); }
|
||||
auto size() const -> uint { return strlen(_data); }
|
||||
char _data[1 + sizeof(unsigned char) * 3];
|
||||
};
|
||||
|
||||
template<> struct stringify<unsigned short> {
|
||||
stringify(unsigned short source) { natural(_data, source); }
|
||||
auto data() const -> const char* { return _data; }
|
||||
auto size() const -> unsigned { return strlen(_data); }
|
||||
auto size() const -> uint { return strlen(_data); }
|
||||
char _data[1 + sizeof(unsigned short) * 3];
|
||||
};
|
||||
|
||||
template<> struct stringify<unsigned int> {
|
||||
stringify(unsigned int source) { natural(_data, source); }
|
||||
auto data() const -> const char* { return _data; }
|
||||
auto size() const -> unsigned { return strlen(_data); }
|
||||
auto size() const -> uint { return strlen(_data); }
|
||||
char _data[1 + sizeof(unsigned int) * 3];
|
||||
};
|
||||
|
||||
template<> struct stringify<unsigned long> {
|
||||
stringify(unsigned long source) { natural(_data, source); }
|
||||
auto data() const -> const char* { return _data; }
|
||||
auto size() const -> unsigned { return strlen(_data); }
|
||||
auto size() const -> uint { return strlen(_data); }
|
||||
char _data[1 + sizeof(unsigned long) * 3];
|
||||
};
|
||||
|
||||
template<> struct stringify<unsigned long long> {
|
||||
stringify(unsigned long long source) { natural(_data, source); }
|
||||
auto data() const -> const char* { return _data; }
|
||||
auto size() const -> unsigned { return strlen(_data); }
|
||||
auto size() const -> uint { return strlen(_data); }
|
||||
char _data[1 + sizeof(unsigned long long) * 3];
|
||||
};
|
||||
|
||||
|
@ -123,21 +123,21 @@ template<uint Bits> struct stringify<Natural<Bits>> {
|
|||
template<> struct stringify<float> {
|
||||
stringify(float source) { real(_data, source); }
|
||||
auto data() const -> const char* { return _data; }
|
||||
auto size() const -> unsigned { return strlen(_data); }
|
||||
auto size() const -> uint { return strlen(_data); }
|
||||
char _data[256];
|
||||
};
|
||||
|
||||
template<> struct stringify<double> {
|
||||
stringify(double source) { real(_data, source); }
|
||||
auto data() const -> const char* { return _data; }
|
||||
auto size() const -> unsigned { return strlen(_data); }
|
||||
auto size() const -> uint { return strlen(_data); }
|
||||
char _data[256];
|
||||
};
|
||||
|
||||
template<> struct stringify<long double> {
|
||||
stringify(long double source) { real(_data, source); }
|
||||
auto data() const -> const char* { return _data; }
|
||||
auto size() const -> unsigned { return strlen(_data); }
|
||||
auto size() const -> uint { return strlen(_data); }
|
||||
char _data[256];
|
||||
};
|
||||
|
||||
|
@ -156,7 +156,7 @@ template<> struct stringify<vector<uint8_t>> {
|
|||
memory::copy(_text.data(), source.data(), source.size());
|
||||
}
|
||||
auto data() const -> const char* { return _text.data(); }
|
||||
auto size() const -> unsigned { return _text.size(); }
|
||||
auto size() const -> uint { return _text.size(); }
|
||||
vector<char> _text;
|
||||
};
|
||||
|
||||
|
@ -166,7 +166,7 @@ template<> struct stringify<const vector<uint8_t>&> {
|
|||
memory::copy(_text.data(), source.data(), source.size());
|
||||
}
|
||||
auto data() const -> const char* { return _text.data(); }
|
||||
auto size() const -> unsigned { return _text.size(); }
|
||||
auto size() const -> uint { return _text.size(); }
|
||||
vector<char> _text;
|
||||
};
|
||||
|
||||
|
@ -175,14 +175,14 @@ template<> struct stringify<const vector<uint8_t>&> {
|
|||
template<> struct stringify<char*> {
|
||||
stringify(char* source) : _data(source ? source : "") {}
|
||||
auto data() const -> const char* { return _data; }
|
||||
auto size() const -> unsigned { return strlen(_data); }
|
||||
auto size() const -> uint { return strlen(_data); }
|
||||
const char* _data;
|
||||
};
|
||||
|
||||
template<> struct stringify<const char*> {
|
||||
stringify(const char* source) : _data(source ? source : "") {}
|
||||
auto data() const -> const char* { return _data; }
|
||||
auto size() const -> unsigned { return strlen(_data); }
|
||||
auto size() const -> uint { return strlen(_data); }
|
||||
const char* _data;
|
||||
};
|
||||
|
||||
|
@ -191,28 +191,28 @@ template<> struct stringify<const char*> {
|
|||
template<> struct stringify<string> {
|
||||
stringify(const string& source) : _text(source) {}
|
||||
auto data() const -> const char* { return _text.data(); }
|
||||
auto size() const -> unsigned { return _text.size(); }
|
||||
auto size() const -> uint { return _text.size(); }
|
||||
const string& _text;
|
||||
};
|
||||
|
||||
template<> struct stringify<const string&> {
|
||||
stringify(const string& source) : _text(source) {}
|
||||
auto data() const -> const char* { return _text.data(); }
|
||||
auto size() const -> unsigned { return _text.size(); }
|
||||
auto size() const -> uint { return _text.size(); }
|
||||
const string& _text;
|
||||
};
|
||||
|
||||
template<> struct stringify<string_view> {
|
||||
stringify(const string_view& source) : _view(source) {}
|
||||
auto data() const -> const char* { return _view.data(); }
|
||||
auto size() const -> unsigned { return _view.size(); }
|
||||
auto size() const -> uint { return _view.size(); }
|
||||
const string_view& _view;
|
||||
};
|
||||
|
||||
template<> struct stringify<const string_view&> {
|
||||
stringify(const string_view& source) : _view(source) {}
|
||||
auto data() const -> const char* { return _view.data(); }
|
||||
auto size() const -> unsigned { return _view.size(); }
|
||||
auto size() const -> uint { return _view.size(); }
|
||||
const string_view& _view;
|
||||
};
|
||||
|
||||
|
|
|
@ -3,54 +3,54 @@
|
|||
namespace nall {
|
||||
|
||||
template<bool Insensitive>
|
||||
auto string::_compare(const char* target, uint capacity, const char* source, uint size) -> signed {
|
||||
auto string::_compare(const char* target, uint capacity, const char* source, uint size) -> int {
|
||||
if(Insensitive) return memory::icompare(target, capacity, source, size);
|
||||
return memory::compare(target, capacity, source, size);
|
||||
}
|
||||
|
||||
//size() + 1 includes null-terminator; required to properly compare strings of differing lengths
|
||||
auto string::compare(rstring x, rstring y) -> int {
|
||||
auto string::compare(string_view x, string_view y) -> int {
|
||||
return memory::compare(x.data(), x.size() + 1, y.data(), y.size() + 1);
|
||||
}
|
||||
|
||||
auto string::icompare(rstring x, rstring y) -> int {
|
||||
auto string::icompare(string_view x, string_view y) -> int {
|
||||
return memory::icompare(x.data(), x.size() + 1, y.data(), y.size() + 1);
|
||||
}
|
||||
|
||||
auto string::compare(rstring source) const -> int {
|
||||
auto string::compare(string_view source) const -> int {
|
||||
return memory::compare(data(), size() + 1, source.data(), source.size() + 1);
|
||||
}
|
||||
|
||||
auto string::icompare(rstring source) const -> int {
|
||||
auto string::icompare(string_view source) const -> int {
|
||||
return memory::icompare(data(), size() + 1, source.data(), source.size() + 1);
|
||||
}
|
||||
|
||||
auto string::equals(rstring source) const -> bool {
|
||||
auto string::equals(string_view source) const -> bool {
|
||||
if(size() != source.size()) return false;
|
||||
return memory::compare(data(), source.data(), source.size()) == 0;
|
||||
}
|
||||
|
||||
auto string::iequals(rstring source) const -> bool {
|
||||
auto string::iequals(string_view source) const -> bool {
|
||||
if(size() != source.size()) return false;
|
||||
return memory::icompare(data(), source.data(), source.size()) == 0;
|
||||
}
|
||||
|
||||
auto string::beginsWith(rstring source) const -> bool {
|
||||
auto string::beginsWith(string_view source) const -> bool {
|
||||
if(source.size() > size()) return false;
|
||||
return memory::compare(data(), source.data(), source.size()) == 0;
|
||||
}
|
||||
|
||||
auto string::ibeginsWith(rstring source) const -> bool {
|
||||
auto string::ibeginsWith(string_view source) const -> bool {
|
||||
if(source.size() > size()) return false;
|
||||
return memory::icompare(data(), source.data(), source.size()) == 0;
|
||||
}
|
||||
|
||||
auto string::endsWith(rstring source) const -> bool {
|
||||
auto string::endsWith(string_view source) const -> bool {
|
||||
if(source.size() > size()) return false;
|
||||
return memory::compare(data() + size() - source.size(), source.data(), source.size()) == 0;
|
||||
}
|
||||
|
||||
auto string::iendsWith(rstring source) const -> bool {
|
||||
auto string::iendsWith(string_view source) const -> bool {
|
||||
if(source.size() > size()) return false;
|
||||
return memory::icompare(data() + size() - source.size(), source.data(), source.size()) == 0;
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ namespace nall {
|
|||
|
||||
auto string::downcase() -> string& {
|
||||
char* p = get();
|
||||
for(unsigned n = 0; n < size(); n++) {
|
||||
for(uint n = 0; n < size(); n++) {
|
||||
if(p[n] >= 'A' && p[n] <= 'Z') p[n] += 0x20;
|
||||
}
|
||||
return *this;
|
||||
|
@ -12,7 +12,7 @@ auto string::downcase() -> string& {
|
|||
|
||||
auto string::qdowncase() -> string& {
|
||||
char* p = get();
|
||||
for(unsigned n = 0, quoted = 0; n < size(); n++) {
|
||||
for(uint n = 0, quoted = 0; n < size(); n++) {
|
||||
if(p[n] == '\"') quoted ^= 1;
|
||||
if(!quoted && p[n] >= 'A' && p[n] <= 'Z') p[n] += 0x20;
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ auto string::qdowncase() -> string& {
|
|||
|
||||
auto string::upcase() -> string& {
|
||||
char* p = get();
|
||||
for(unsigned n = 0; n < size(); n++) {
|
||||
for(uint n = 0; n < size(); n++) {
|
||||
if(p[n] >= 'a' && p[n] <= 'z') p[n] -= 0x20;
|
||||
}
|
||||
return *this;
|
||||
|
@ -29,18 +29,18 @@ auto string::upcase() -> string& {
|
|||
|
||||
auto string::qupcase() -> string& {
|
||||
char* p = get();
|
||||
for(unsigned n = 0, quoted = 0; n < size(); n++) {
|
||||
for(uint n = 0, quoted = 0; n < size(); n++) {
|
||||
if(p[n] == '\"') quoted ^= 1;
|
||||
if(!quoted && p[n] >= 'a' && p[n] <= 'z') p[n] -= 0x20;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto string::transform(rstring from, rstring to) -> string& {
|
||||
auto string::transform(string_view from, string_view to) -> string& {
|
||||
if(from.size() != to.size() || from.size() == 0) return *this; //patterns must be the same length
|
||||
char* p = get();
|
||||
for(unsigned n = 0; n < size(); n++) {
|
||||
for(unsigned s = 0; s < from.size(); s++) {
|
||||
for(uint n = 0; n < size(); n++) {
|
||||
for(uint s = 0; s < from.size(); s++) {
|
||||
if(p[n] == from[s]) {
|
||||
p[n] = to[s];
|
||||
break;
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
namespace nall {
|
||||
|
||||
auto string::operator[](int position) const -> const char& {
|
||||
if(position > size() + 1) throw exception_out_of_bounds{};
|
||||
//if(position > size() + 1) throw;
|
||||
return data()[position];
|
||||
}
|
||||
|
||||
|
@ -45,10 +45,6 @@ template<typename T> auto string::_append(const stringify<T>& source) -> string&
|
|||
return *this;
|
||||
}
|
||||
|
||||
auto string::empty() const -> bool {
|
||||
return size() == 0;
|
||||
}
|
||||
|
||||
auto string::length() const -> uint {
|
||||
return strlen(data());
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ inline auto evaluateExpression(Node* node) -> string {
|
|||
for(auto& link : node->link) {
|
||||
result.append(evaluateExpression(link), ", ");
|
||||
}
|
||||
return result.rtrim(", ", 1L).append(")");
|
||||
return result.trimRight(", ", 1L).append(")");
|
||||
}
|
||||
}
|
||||
#undef p
|
||||
|
|
|
@ -16,7 +16,7 @@ inline auto literalNumber(const char*& s) -> string {
|
|||
|
||||
//binary
|
||||
if(p[0] == '%' || (p[0] == '0' && p[1] == 'b')) {
|
||||
unsigned prefix = 1 + (p[0] == '0');
|
||||
uint prefix = 1 + (p[0] == '0');
|
||||
p += prefix;
|
||||
while(p[0] == '\'' || p[0] == '0' || p[0] == '1') p++;
|
||||
if(p - s <= prefix) throw "invalid binary literal";
|
||||
|
@ -27,7 +27,7 @@ inline auto literalNumber(const char*& s) -> string {
|
|||
|
||||
//octal
|
||||
if(p[0] == '0' && p[1] == 'o') {
|
||||
unsigned prefix = 1 + (p[0] == '0');
|
||||
uint prefix = 1 + (p[0] == '0');
|
||||
p += prefix;
|
||||
while(p[0] == '\'' || (p[0] >= '0' && p[0] <= '7')) p++;
|
||||
if(p - s <= prefix) throw "invalid octal literal";
|
||||
|
@ -38,7 +38,7 @@ inline auto literalNumber(const char*& s) -> string {
|
|||
|
||||
//hex
|
||||
if(p[0] == '$' || (p[0] == '0' && p[1] == 'x')) {
|
||||
unsigned prefix = 1 + (p[0] == '0');
|
||||
uint prefix = 1 + (p[0] == '0');
|
||||
p += prefix;
|
||||
while(p[0] == '\'' || (p[0] >= '0' && p[0] <= '9') || (p[0] >= 'A' && p[0] <= 'F') || (p[0] >= 'a' && p[0] <= 'f')) p++;
|
||||
if(p - s <= prefix) throw "invalid hex literal";
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace nall {
|
||||
|
||||
template<bool Insensitive, bool Quoted> auto string::_find(int offset, rstring source) const -> maybe<uint> {
|
||||
template<bool Insensitive, bool Quoted> auto string::_find(int offset, string_view source) const -> maybe<uint> {
|
||||
if(source.size() == 0) return nothing;
|
||||
|
||||
auto p = data();
|
||||
|
@ -15,12 +15,12 @@ template<bool Insensitive, bool Quoted> auto string::_find(int offset, rstring s
|
|||
return nothing;
|
||||
}
|
||||
|
||||
auto string::find(rstring source) const -> maybe<uint> { return _find<0, 0>(0, source); }
|
||||
auto string::ifind(rstring source) const -> maybe<uint> { return _find<1, 0>(0, source); }
|
||||
auto string::qfind(rstring source) const -> maybe<uint> { return _find<0, 1>(0, source); }
|
||||
auto string::iqfind(rstring source) const -> maybe<uint> { return _find<1, 1>(0, source); }
|
||||
auto string::find(string_view source) const -> maybe<uint> { return _find<0, 0>(0, source); }
|
||||
auto string::ifind(string_view source) const -> maybe<uint> { return _find<1, 0>(0, source); }
|
||||
auto string::qfind(string_view source) const -> maybe<uint> { return _find<0, 1>(0, source); }
|
||||
auto string::iqfind(string_view source) const -> maybe<uint> { return _find<1, 1>(0, source); }
|
||||
|
||||
auto string::findFrom(int offset, rstring source) const -> maybe<uint> { return _find<0, 0>(offset, source); }
|
||||
auto string::ifindFrom(int offset, rstring source) const -> maybe<uint> { return _find<1, 0>(offset, source); }
|
||||
auto string::findFrom(int offset, string_view source) const -> maybe<uint> { return _find<0, 0>(offset, source); }
|
||||
auto string::ifindFrom(int offset, string_view source) const -> maybe<uint> { return _find<1, 0>(offset, source); }
|
||||
|
||||
}
|
||||
|
|
|
@ -10,11 +10,11 @@ auto string::format(const nall::format& params) -> type& {
|
|||
auto data = (char*)memory::allocate(size);
|
||||
memory::copy(data, this->data(), size);
|
||||
|
||||
signed x = 0;
|
||||
int x = 0;
|
||||
while(x < size - 2) { //2 = minimum tag length
|
||||
if(data[x] != '{') { x++; continue; }
|
||||
|
||||
signed y = x + 1;
|
||||
int y = x + 1;
|
||||
while(y < size - 1) { //-1 avoids going out of bounds on test after this loop
|
||||
if(data[y] != '}') { y++; continue; }
|
||||
break;
|
||||
|
@ -70,7 +70,12 @@ auto format::append() -> format& {
|
|||
|
||||
template<typename... P> auto print(P&&... p) -> void {
|
||||
string s{forward<P>(p)...};
|
||||
fputs(s.data(), stdout);
|
||||
fwrite(s.data(), 1, s.size(), stdout);
|
||||
}
|
||||
|
||||
template<typename... P> auto print(FILE* fp, P&&... p) -> void {
|
||||
string s{forward<P>(p)...};
|
||||
fwrite(s.data(), 1, s.size(), fp);
|
||||
}
|
||||
|
||||
auto integer(intmax value, long precision, char padchar) -> string {
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
#pragma once
|
||||
|
||||
namespace nall {
|
||||
|
||||
namespace Hash {
|
||||
auto CRC16::digest() const -> string {
|
||||
return hex(value(), 4L);
|
||||
}
|
||||
|
||||
auto CRC32::digest() const -> string {
|
||||
return hex(value(), 8L);
|
||||
}
|
||||
|
||||
auto CRC64::digest() const -> string {
|
||||
return hex(value(), 16L);
|
||||
}
|
||||
|
||||
auto SHA256::digest() const -> string {
|
||||
string result;
|
||||
for(auto n : value()) result.append(hex(n, 2L));
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
auto crc16(rstring self) -> string {
|
||||
return Hash::CRC16(self.data(), self.size()).digest();
|
||||
}
|
||||
|
||||
auto crc32(rstring self) -> string {
|
||||
return Hash::CRC32(self.data(), self.size()).digest();
|
||||
}
|
||||
|
||||
auto crc64(rstring self) -> string {
|
||||
return Hash::CRC64(self.data(), self.size()).digest();
|
||||
}
|
||||
|
||||
auto sha256(rstring self) -> string {
|
||||
return Hash::SHA256(self.data(), self.size()).digest();
|
||||
}
|
||||
|
||||
}
|
|
@ -32,21 +32,21 @@ auto lstring::append() -> lstring& {
|
|||
return *this;
|
||||
}
|
||||
|
||||
auto lstring::find(rstring source) const -> maybe<uint> {
|
||||
auto lstring::find(string_view source) const -> maybe<uint> {
|
||||
for(uint n = 0; n < size(); n++) {
|
||||
if(operator[](n).equals(source)) return n;
|
||||
}
|
||||
return nothing;
|
||||
}
|
||||
|
||||
auto lstring::ifind(rstring source) const -> maybe<uint> {
|
||||
auto lstring::ifind(string_view source) const -> maybe<uint> {
|
||||
for(uint n = 0; n < size(); n++) {
|
||||
if(operator[](n).iequals(source)) return n;
|
||||
}
|
||||
return nothing;
|
||||
}
|
||||
|
||||
auto lstring::match(rstring pattern) const -> lstring {
|
||||
auto lstring::match(string_view pattern) const -> lstring {
|
||||
lstring result;
|
||||
for(uint n = 0; n < size(); n++) {
|
||||
if(operator[](n).match(pattern)) result.append(operator[](n));
|
||||
|
@ -54,7 +54,7 @@ auto lstring::match(rstring pattern) const -> lstring {
|
|||
return result;
|
||||
}
|
||||
|
||||
auto lstring::merge(rstring separator) const -> string {
|
||||
auto lstring::merge(string_view separator) const -> string {
|
||||
string output;
|
||||
for(uint n = 0; n < size(); n++) {
|
||||
output.append(operator[](n));
|
||||
|
|
|
@ -74,7 +74,7 @@ protected:
|
|||
if(length == 0) throw "Invalid attribute name";
|
||||
node->_name = slice(p, 0, length);
|
||||
node->parseData(p += length);
|
||||
node->_value.rtrim("\n", 1L);
|
||||
node->_value.trimRight("\n", 1L);
|
||||
_children.append(node);
|
||||
}
|
||||
}
|
||||
|
@ -101,7 +101,7 @@ protected:
|
|||
_children.append(node);
|
||||
}
|
||||
|
||||
_value.rtrim("\n", 1L);
|
||||
_value.trimRight("\n", 1L);
|
||||
}
|
||||
|
||||
//read top-level nodes
|
||||
|
@ -127,7 +127,7 @@ protected:
|
|||
memory::move(output, origin, p - origin);
|
||||
output += p - origin;
|
||||
}
|
||||
document.resize(document.size() - (p - output)).rtrim("\n");
|
||||
document.resize(document.size() - (p - output)).trimRight("\n");
|
||||
if(document.size() == 0) return; //empty document
|
||||
|
||||
auto text = document.split("\n");
|
||||
|
|
|
@ -31,7 +31,7 @@ auto ManagedNode::_evaluate(string query) const -> bool {
|
|||
}
|
||||
|
||||
string data = string{_value}.strip();
|
||||
if(side(0).empty() == false) {
|
||||
if(side(0)) {
|
||||
auto result = _find(side(0));
|
||||
if(result.size() == 0) return false;
|
||||
data = result[0].value();
|
||||
|
@ -60,19 +60,19 @@ auto ManagedNode::_find(const string& query) const -> vector<Node> {
|
|||
uint lo = 0u, hi = ~0u;
|
||||
|
||||
if(name.match("*[*]")) {
|
||||
auto p = name.rtrim("]", 1L).split("[", 1L);
|
||||
auto p = name.trimRight("]", 1L).split("[", 1L);
|
||||
name = p(0);
|
||||
if(p(1).find("-")) {
|
||||
p = p(1).split("-", 1L);
|
||||
lo = p(0).empty() ? 0u : p(0).natural();
|
||||
hi = p(1).empty() ? ~0u : p(1).natural();
|
||||
lo = !p(0) ? 0u : p(0).natural();
|
||||
hi = !p(1) ? ~0u : p(1).natural();
|
||||
} else {
|
||||
lo = hi = p(1).natural();
|
||||
}
|
||||
}
|
||||
|
||||
if(name.match("*(*)")) {
|
||||
auto p = name.rtrim(")", 1L).split("(", 1L);
|
||||
auto p = name.trimRight(")", 1L).split("(", 1L);
|
||||
name = p(0);
|
||||
rule = p(1);
|
||||
}
|
||||
|
|
|
@ -125,7 +125,7 @@ protected:
|
|||
while(isName(*p)) p++;
|
||||
const char* nameEnd = p;
|
||||
copy(_name, nameStart, nameEnd - nameStart);
|
||||
if(_name.empty()) throw "missing element name";
|
||||
if(!_name) throw "missing element name";
|
||||
|
||||
//parse attributes
|
||||
while(*p) {
|
||||
|
@ -141,7 +141,7 @@ protected:
|
|||
while(isName(*p)) p++;
|
||||
const char* nameEnd = p;
|
||||
copy(attribute->_name, nameStart, nameEnd - nameStart);
|
||||
if(attribute->_name.empty()) throw "missing attribute name";
|
||||
if(!attribute->_name) throw "missing attribute name";
|
||||
|
||||
//parse attribute data
|
||||
if(*p++ != '=') throw "missing attribute value";
|
||||
|
|
|
@ -4,7 +4,7 @@ namespace nall {
|
|||
|
||||
//todo: these functions are not binary-safe
|
||||
|
||||
auto string::match(rstring source) const -> bool {
|
||||
auto string::match(string_view source) const -> bool {
|
||||
const char* s = data();
|
||||
const char* p = source.data();
|
||||
|
||||
|
@ -28,7 +28,7 @@ auto string::match(rstring source) const -> bool {
|
|||
return !*p;
|
||||
}
|
||||
|
||||
auto string::imatch(rstring source) const -> bool {
|
||||
auto string::imatch(string_view source) const -> bool {
|
||||
static auto chrlower = [](char c) -> char {
|
||||
return (c >= 'A' && c <= 'Z') ? c + ('a' - 'A') : c;
|
||||
};
|
||||
|
|
|
@ -4,7 +4,7 @@ namespace nall {
|
|||
|
||||
// (/parent/child.type/)
|
||||
// (/parent/child.type/)name.type
|
||||
auto pathname(rstring self) -> string {
|
||||
auto pathname(string_view self) -> string {
|
||||
const char* p = self.data() + self.size() - 1;
|
||||
for(int offset = self.size() - 1; offset >= 0; offset--, p--) {
|
||||
if(*p == '/') return slice(self, 0, offset + 1);
|
||||
|
@ -14,7 +14,7 @@ auto pathname(rstring self) -> string {
|
|||
|
||||
// /parent/child.type/()
|
||||
// /parent/child.type/(name.type)
|
||||
auto filename(rstring self) -> string {
|
||||
auto filename(string_view self) -> string {
|
||||
const char* p = self.data() + self.size() - 1;
|
||||
for(int offset = self.size() - 1; offset >= 0; offset--, p--) {
|
||||
if(*p == '/') return slice(self, offset + 1);
|
||||
|
@ -24,18 +24,18 @@ auto filename(rstring self) -> string {
|
|||
|
||||
// (/parent/)child.type/
|
||||
// (/parent/child.type/)name.type
|
||||
auto dirname(rstring self) -> string {
|
||||
auto dirname(string_view self) -> string {
|
||||
const char* p = self.data() + self.size() - 1, *last = p;
|
||||
for(int offset = self.size() - 1; offset >= 0; offset--, p--) {
|
||||
if(*p == '/' && p == last) continue;
|
||||
if(*p == '/') return slice(self, 0, offset + 1);
|
||||
}
|
||||
return rootpath(); //technically, directory is unknown; must return something
|
||||
return ""; //no path found
|
||||
}
|
||||
|
||||
// /parent/(child.type/)
|
||||
// /parent/child.type/(name.type)
|
||||
auto basename(rstring self) -> string {
|
||||
auto basename(string_view self) -> string {
|
||||
const char* p = self.data() + self.size() - 1, *last = p;
|
||||
for(int offset = self.size() - 1; offset >= 0; offset--, p--) {
|
||||
if(*p == '/' && p == last) continue;
|
||||
|
@ -46,25 +46,25 @@ auto basename(rstring self) -> string {
|
|||
|
||||
// /parent/(child).type/
|
||||
// /parent/child.type/(name).type
|
||||
auto prefixname(rstring self) -> string {
|
||||
auto prefixname(string_view self) -> string {
|
||||
const char* p = self.data() + self.size() - 1, *last = p;
|
||||
for(int offset = self.size() - 1, suffix = -1; offset >= 0; offset--, p--) {
|
||||
if(*p == '/' && p == last) continue;
|
||||
if(*p == '/') return slice(self, offset + 1, suffix >= 0 ? suffix - offset - 1 : 0).rtrim("/");
|
||||
if(*p == '/') return slice(self, offset + 1, suffix >= 0 ? suffix - offset - 1 : 0).trimRight("/");
|
||||
if(*p == '.' && suffix == -1) { suffix = offset; continue; }
|
||||
if(offset == 0) return slice(self, offset, suffix).rtrim("/");
|
||||
if(offset == 0) return slice(self, offset, suffix).trimRight("/");
|
||||
}
|
||||
return ""; //no prefix found
|
||||
}
|
||||
|
||||
// /parent/child(.type)/
|
||||
// /parent/child.type/name(.type)
|
||||
auto suffixname(rstring self) -> string {
|
||||
auto suffixname(string_view self) -> string {
|
||||
const char* p = self.data() + self.size() - 1, *last = p;
|
||||
for(int offset = self.size() - 1; offset >= 0; offset--, p--) {
|
||||
if(*p == '/' && p == last) continue;
|
||||
if(*p == '/') break;
|
||||
if(*p == '.') return slice(self, offset).rtrim("/");
|
||||
if(*p == '.') return slice(self, offset).trimRight("/");
|
||||
}
|
||||
return ""; //no suffix found
|
||||
}
|
||||
|
|
|
@ -3,17 +3,17 @@
|
|||
namespace nall {
|
||||
|
||||
template<bool Insensitive, bool Quoted>
|
||||
auto string::_replace(rstring from, rstring to, long limit) -> string& {
|
||||
auto string::_replace(string_view from, string_view to, long limit) -> string& {
|
||||
if(limit <= 0 || from.size() == 0) return *this;
|
||||
|
||||
signed size = this->size();
|
||||
signed matches = 0;
|
||||
signed quoted = 0;
|
||||
int size = this->size();
|
||||
int matches = 0;
|
||||
int quoted = 0;
|
||||
|
||||
//count matches first, so that we only need to reallocate memory once
|
||||
//(recording matches would also require memory allocation, so this is not done)
|
||||
{ const char* p = data();
|
||||
for(signed n = 0; n <= size - (signed)from.size();) {
|
||||
for(int n = 0; n <= size - (int)from.size();) {
|
||||
if(Quoted) { if(p[n] == '\"') { quoted ^= 1; n++; continue; } if(quoted) { n++; continue; } }
|
||||
if(_compare<Insensitive>(p + n, size - n, from.data(), from.size())) { n++; continue; }
|
||||
|
||||
|
@ -27,7 +27,7 @@ auto string::_replace(rstring from, rstring to, long limit) -> string& {
|
|||
if(to.size() == from.size()) {
|
||||
char* p = get();
|
||||
|
||||
for(signed n = 0, remaining = matches, quoted = 0; n <= size - (signed)from.size();) {
|
||||
for(int n = 0, remaining = matches, quoted = 0; n <= size - (int)from.size();) {
|
||||
if(Quoted) { if(p[n] == '\"') { quoted ^= 1; n++; continue; } if(quoted) { n++; continue; } }
|
||||
if(_compare<Insensitive>(p + n, size - n, from.data(), from.size())) { n++; continue; }
|
||||
|
||||
|
@ -41,10 +41,10 @@ auto string::_replace(rstring from, rstring to, long limit) -> string& {
|
|||
//left-to-right shrink
|
||||
else if(to.size() < from.size()) {
|
||||
char* p = get();
|
||||
signed offset = 0;
|
||||
signed base = 0;
|
||||
int offset = 0;
|
||||
int base = 0;
|
||||
|
||||
for(signed n = 0, remaining = matches, quoted = 0; n <= size - (signed)from.size();) {
|
||||
for(int n = 0, remaining = matches, quoted = 0; n <= size - (int)from.size();) {
|
||||
if(Quoted) { if(p[n] == '\"') { quoted ^= 1; n++; continue; } if(quoted) { n++; continue; } }
|
||||
if(_compare<Insensitive>(p + n, size - n, from.data(), from.size())) { n++; continue; }
|
||||
|
||||
|
@ -66,10 +66,10 @@ auto string::_replace(rstring from, rstring to, long limit) -> string& {
|
|||
resize(size + matches * (to.size() - from.size()));
|
||||
char* p = get();
|
||||
|
||||
signed offset = this->size();
|
||||
signed base = size;
|
||||
int offset = this->size();
|
||||
int base = size;
|
||||
|
||||
for(signed n = size, remaining = matches; n >= (signed)from.size();) { //quoted reused from parent scope since we are iterating backward
|
||||
for(int n = size, remaining = matches; n >= (int)from.size();) { //quoted reused from parent scope since we are iterating backward
|
||||
if(Quoted) { if(p[n] == '\"') { quoted ^= 1; n--; continue; } if(quoted) { n--; continue; } }
|
||||
if(_compare<Insensitive>(p + n - from.size(), size - n + from.size(), from.data(), from.size())) { n--; continue; }
|
||||
|
||||
|
@ -86,9 +86,9 @@ auto string::_replace(rstring from, rstring to, long limit) -> string& {
|
|||
return *this;
|
||||
}
|
||||
|
||||
auto string::replace(rstring from, rstring to, long limit) -> string& { return _replace<0, 0>(from, to, limit); }
|
||||
auto string::ireplace(rstring from, rstring to, long limit) -> string& { return _replace<1, 0>(from, to, limit); }
|
||||
auto string::qreplace(rstring from, rstring to, long limit) -> string& { return _replace<0, 1>(from, to, limit); }
|
||||
auto string::iqreplace(rstring from, rstring to, long limit) -> string& { return _replace<1, 1>(from, to, limit); }
|
||||
auto string::replace(string_view from, string_view to, long limit) -> string& { return _replace<0, 0>(from, to, limit); }
|
||||
auto string::ireplace(string_view from, string_view to, long limit) -> string& { return _replace<1, 0>(from, to, limit); }
|
||||
auto string::qreplace(string_view from, string_view to, long limit) -> string& { return _replace<0, 1>(from, to, limit); }
|
||||
auto string::iqreplace(string_view from, string_view to, long limit) -> string& { return _replace<1, 1>(from, to, limit); }
|
||||
|
||||
};
|
||||
|
|
|
@ -3,16 +3,16 @@
|
|||
namespace nall {
|
||||
|
||||
template<bool Insensitive, bool Quoted>
|
||||
auto lstring::_split(rstring source, rstring find, long limit) -> lstring& {
|
||||
auto lstring::_split(string_view source, string_view find, long limit) -> lstring& {
|
||||
reset();
|
||||
if(limit <= 0 || find.size() == 0) return *this;
|
||||
|
||||
const char* p = source.data();
|
||||
signed size = source.size();
|
||||
signed base = 0;
|
||||
signed matches = 0;
|
||||
int size = source.size();
|
||||
int base = 0;
|
||||
int matches = 0;
|
||||
|
||||
for(signed n = 0, quoted = 0; n <= size - (signed)find.size();) {
|
||||
for(int n = 0, quoted = 0; n <= size - (int)find.size();) {
|
||||
if(Quoted) { if(p[n] == '\"') { quoted ^= 1; n++; continue; } if(quoted) { n++; continue; } }
|
||||
if(string::_compare<Insensitive>(p + n, size - n, find.data(), find.size())) { n++; continue; }
|
||||
if(matches >= limit) break;
|
||||
|
@ -33,9 +33,9 @@ auto lstring::_split(rstring source, rstring find, long limit) -> lstring& {
|
|||
return *this;
|
||||
}
|
||||
|
||||
auto string::split(rstring on, long limit) const -> lstring { return lstring()._split<0, 0>(*this, on, limit); }
|
||||
auto string::isplit(rstring on, long limit) const -> lstring { return lstring()._split<1, 0>(*this, on, limit); }
|
||||
auto string::qsplit(rstring on, long limit) const -> lstring { return lstring()._split<0, 1>(*this, on, limit); }
|
||||
auto string::iqsplit(rstring on, long limit) const -> lstring { return lstring()._split<1, 1>(*this, on, limit); }
|
||||
auto string::split(string_view on, long limit) const -> lstring { return lstring()._split<0, 0>(*this, on, limit); }
|
||||
auto string::isplit(string_view on, long limit) const -> lstring { return lstring()._split<1, 0>(*this, on, limit); }
|
||||
auto string::qsplit(string_view on, long limit) const -> lstring { return lstring()._split<0, 1>(*this, on, limit); }
|
||||
auto string::iqsplit(string_view on, long limit) const -> lstring { return lstring()._split<1, 1>(*this, on, limit); }
|
||||
|
||||
}
|
||||
|
|
|
@ -54,11 +54,11 @@ auto CML::parseDocument(const string& filedata, const string& pathname, uint dep
|
|||
};
|
||||
|
||||
for(auto& block : filedata.split("\n\n")) {
|
||||
lstring lines = block.rstrip().split("\n");
|
||||
lstring lines = block.stripRight().split("\n");
|
||||
string name = lines.takeLeft();
|
||||
|
||||
if(name.beginsWith("include ")) {
|
||||
name.ltrim("include ", 1L);
|
||||
name.trimLeft("include ", 1L);
|
||||
string filename{pathname, name};
|
||||
string document = settings.reader ? settings.reader(filename) : string::read(filename);
|
||||
parseDocument(document, nall::pathname(filename), depth + 1);
|
||||
|
|
|
@ -61,7 +61,7 @@ auto DML::parseDocument(const string& filedata, const string& pathname, uint dep
|
|||
}
|
||||
|
||||
auto DML::parseBlock(string& block, const string& pathname, uint depth) -> bool {
|
||||
if(block.rstrip().empty()) return true;
|
||||
if(!block.stripRight()) return true;
|
||||
auto lines = block.split("\n");
|
||||
|
||||
//include
|
||||
|
@ -75,7 +75,7 @@ auto DML::parseBlock(string& block, const string& pathname, uint depth) -> bool
|
|||
else if(block.beginsWith("<html>\n") && settings.allowHTML) {
|
||||
for(auto n : range(lines)) {
|
||||
if(n == 0 || !lines[n].beginsWith(" ")) continue;
|
||||
state.output.append(lines[n].ltrim(" ", 1L), "\n");
|
||||
state.output.append(lines[n].trimLeft(" ", 1L), "\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -85,13 +85,13 @@ auto DML::parseBlock(string& block, const string& pathname, uint depth) -> bool
|
|||
if(state.sections++) state.output.append("</section>");
|
||||
state.output.append("<section>");
|
||||
}
|
||||
auto content = lines.takeLeft().ltrim("# ", 1L).split(" => ", 1L);
|
||||
auto content = lines.takeLeft().trimLeft("# ", 1L).split(" => ", 1L);
|
||||
auto data = markup(content[0]);
|
||||
auto name = escape(content(1, crc32(data)));
|
||||
auto name = escape(content(1, data.hash()));
|
||||
state.output.append("<header id=\"", name, "\">", data);
|
||||
for(auto& line : lines) {
|
||||
if(!line.beginsWith("# ")) continue;
|
||||
state.output.append("<span>", line.ltrim("# ", 1L), "</span>");
|
||||
state.output.append("<span>", line.trimLeft("# ", 1L), "</span>");
|
||||
}
|
||||
state.output.append("</header>\n");
|
||||
}
|
||||
|
@ -100,7 +100,7 @@ auto DML::parseBlock(string& block, const string& pathname, uint depth) -> bool
|
|||
else if(auto depth = count(block, '=')) {
|
||||
auto content = slice(lines.takeLeft(), depth + 1).split(" => ", 1L);
|
||||
auto data = markup(content[0]);
|
||||
auto name = escape(content(1, crc32(data)));
|
||||
auto name = escape(content(1, data.hash()));
|
||||
if(depth <= 6) {
|
||||
state.output.append("<h", depth, " id=\"", name, "\">", data);
|
||||
for(auto& line : lines) {
|
||||
|
@ -121,7 +121,7 @@ auto DML::parseBlock(string& block, const string& pathname, uint depth) -> bool
|
|||
while(level > depth) level--, state.output.append("</ul>\n");
|
||||
auto content = slice(line, depth + 1).split(" => ", 1L);
|
||||
auto data = markup(content[0]);
|
||||
auto name = escape(content(1, crc32(data)));
|
||||
auto name = escape(content(1, data.hash()));
|
||||
state.output.append("<li><a href=\"#", name, "\">", data, "</a></li>\n");
|
||||
}
|
||||
}
|
||||
|
@ -162,9 +162,9 @@ auto DML::parseBlock(string& block, const string& pathname, uint depth) -> bool
|
|||
state.output.append("<pre>");
|
||||
for(auto& line : lines) {
|
||||
if(!line.beginsWith(" ")) continue;
|
||||
state.output.append(escape(line.ltrim(" ", 1L)), "\n");
|
||||
state.output.append(escape(line.trimLeft(" ", 1L)), "\n");
|
||||
}
|
||||
state.output.rtrim("\n", 1L).append("</pre>\n");
|
||||
state.output.trimRight("\n", 1L).append("</pre>\n");
|
||||
}
|
||||
|
||||
//divider
|
||||
|
|
|
@ -2,19 +2,19 @@
|
|||
|
||||
namespace nall {
|
||||
|
||||
auto string::trim(rstring lhs, rstring rhs, long limit) -> string& {
|
||||
rtrim(rhs, limit);
|
||||
ltrim(lhs, limit);
|
||||
auto string::trim(string_view lhs, string_view rhs, long limit) -> string& {
|
||||
trimRight(rhs, limit);
|
||||
trimLeft(lhs, limit);
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto string::ltrim(rstring lhs, long limit) -> string& {
|
||||
auto string::trimLeft(string_view lhs, long limit) -> string& {
|
||||
if(lhs.size() == 0) return *this;
|
||||
long matches = 0;
|
||||
while(matches < limit) {
|
||||
signed offset = lhs.size() * matches;
|
||||
signed length = (signed)size() - offset;
|
||||
if(length < (signed)lhs.size()) break;
|
||||
int offset = lhs.size() * matches;
|
||||
int length = (int)size() - offset;
|
||||
if(length < (int)lhs.size()) break;
|
||||
if(memory::compare(data() + offset, lhs.data(), lhs.size()) != 0) break;
|
||||
matches++;
|
||||
}
|
||||
|
@ -22,13 +22,13 @@ auto string::ltrim(rstring lhs, long limit) -> string& {
|
|||
return *this;
|
||||
}
|
||||
|
||||
auto string::rtrim(rstring rhs, long limit) -> string& {
|
||||
auto string::trimRight(string_view rhs, long limit) -> string& {
|
||||
if(rhs.size() == 0) return *this;
|
||||
long matches = 0;
|
||||
while(matches < limit) {
|
||||
signed offset = (signed)size() - rhs.size() * (matches + 1);
|
||||
signed length = (signed)size() - offset;
|
||||
if(offset < 0 || length < (signed)rhs.size()) break;
|
||||
int offset = (int)size() - rhs.size() * (matches + 1);
|
||||
int length = (int)size() - offset;
|
||||
if(offset < 0 || length < (int)rhs.size()) break;
|
||||
if(memory::compare(data() + offset, rhs.data(), rhs.size()) != 0) break;
|
||||
matches++;
|
||||
}
|
||||
|
@ -36,19 +36,19 @@ auto string::rtrim(rstring rhs, long limit) -> string& {
|
|||
return *this;
|
||||
}
|
||||
|
||||
auto string::itrim(rstring lhs, rstring rhs, long limit) -> string& {
|
||||
irtrim(rhs, limit);
|
||||
iltrim(lhs, limit);
|
||||
auto string::itrim(string_view lhs, string_view rhs, long limit) -> string& {
|
||||
itrimRight(rhs, limit);
|
||||
itrimLeft(lhs, limit);
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto string::iltrim(rstring lhs, long limit) -> string& {
|
||||
auto string::itrimLeft(string_view lhs, long limit) -> string& {
|
||||
if(lhs.size() == 0) return *this;
|
||||
long matches = 0;
|
||||
while(matches < limit) {
|
||||
signed offset = lhs.size() * matches;
|
||||
signed length = (signed)size() - offset;
|
||||
if(length < (signed)lhs.size()) break;
|
||||
int offset = lhs.size() * matches;
|
||||
int length = (int)size() - offset;
|
||||
if(length < (int)lhs.size()) break;
|
||||
if(memory::icompare(data() + offset, lhs.data(), lhs.size()) != 0) break;
|
||||
matches++;
|
||||
}
|
||||
|
@ -56,13 +56,13 @@ auto string::iltrim(rstring lhs, long limit) -> string& {
|
|||
return *this;
|
||||
}
|
||||
|
||||
auto string::irtrim(rstring rhs, long limit) -> string& {
|
||||
auto string::itrimRight(string_view rhs, long limit) -> string& {
|
||||
if(rhs.size() == 0) return *this;
|
||||
long matches = 0;
|
||||
while(matches < limit) {
|
||||
signed offset = (signed)size() - rhs.size() * (matches + 1);
|
||||
signed length = (signed)size() - offset;
|
||||
if(offset < 0 || length < (signed)rhs.size()) break;
|
||||
int offset = (int)size() - rhs.size() * (matches + 1);
|
||||
int length = (int)size() - offset;
|
||||
if(offset < 0 || length < (int)rhs.size()) break;
|
||||
if(memory::icompare(data() + offset, rhs.data(), rhs.size()) != 0) break;
|
||||
matches++;
|
||||
}
|
||||
|
@ -71,13 +71,13 @@ auto string::irtrim(rstring rhs, long limit) -> string& {
|
|||
}
|
||||
|
||||
auto string::strip() -> string& {
|
||||
rstrip();
|
||||
lstrip();
|
||||
stripRight();
|
||||
stripLeft();
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto string::lstrip() -> string& {
|
||||
unsigned length = 0;
|
||||
auto string::stripLeft() -> string& {
|
||||
uint length = 0;
|
||||
while(length < size()) {
|
||||
char input = operator[](length);
|
||||
if(input != ' ' && input != '\t' && input != '\r' && input != '\n') break;
|
||||
|
@ -87,8 +87,8 @@ auto string::lstrip() -> string& {
|
|||
return *this;
|
||||
}
|
||||
|
||||
auto string::rstrip() -> string& {
|
||||
unsigned length = 0;
|
||||
auto string::stripRight() -> string& {
|
||||
uint length = 0;
|
||||
while(length < size()) {
|
||||
bool matched = false;
|
||||
char input = operator[](size() - length - 1);
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
namespace nall {
|
||||
|
||||
auto string::read(rstring filename) -> string {
|
||||
auto string::read(string_view filename) -> string {
|
||||
#if !defined(_WIN32)
|
||||
FILE* fp = fopen(filename, "rb");
|
||||
#else
|
||||
|
@ -22,7 +22,7 @@ auto string::read(rstring filename) -> string {
|
|||
return fclose(fp), result;
|
||||
}
|
||||
|
||||
auto string::repeat(rstring pattern, uint times) -> string {
|
||||
auto string::repeat(string_view pattern, uint times) -> string {
|
||||
string result;
|
||||
while(times--) result.append(pattern.data());
|
||||
return result;
|
||||
|
@ -33,7 +33,7 @@ auto string::fill(char fill) -> string& {
|
|||
return *this;
|
||||
}
|
||||
|
||||
auto string::hash() const -> unsigned {
|
||||
auto string::hash() const -> uint {
|
||||
const char* p = data();
|
||||
uint length = size();
|
||||
uint result = 5381;
|
||||
|
@ -82,7 +82,7 @@ auto string::size(int length, char fill) -> string& {
|
|||
return *this;
|
||||
}
|
||||
|
||||
auto slice(rstring self, int offset, int length) -> string {
|
||||
auto slice(string_view self, int offset, int length) -> string {
|
||||
string result;
|
||||
if(offset < self.size()) {
|
||||
if(length < 0) length = self.size() - offset;
|
||||
|
|
|
@ -2,87 +2,84 @@
|
|||
|
||||
namespace nall {
|
||||
|
||||
struct string_view {
|
||||
string_view() {
|
||||
_string = nullptr;
|
||||
_data = "";
|
||||
_size = 0;
|
||||
}
|
||||
string_view::string_view() {
|
||||
_string = nullptr;
|
||||
_data = "";
|
||||
_size = 0;
|
||||
}
|
||||
|
||||
string_view(const char* data) {
|
||||
_string = nullptr;
|
||||
_data = data;
|
||||
_size = -1; //defer length calculation, as it is often unnecessary
|
||||
}
|
||||
string_view::string_view(const string_view& source) {
|
||||
if(this == &source) return;
|
||||
_string = nullptr;
|
||||
_data = source._data;
|
||||
_size = source._size;
|
||||
}
|
||||
|
||||
string_view(const char* data, unsigned size) {
|
||||
_string = nullptr;
|
||||
_data = data;
|
||||
_size = size;
|
||||
}
|
||||
string_view::string_view(string_view&& source) {
|
||||
if(this == &source) return;
|
||||
_string = source._string;
|
||||
_data = source._data;
|
||||
_size = source._size;
|
||||
source._string = nullptr;
|
||||
}
|
||||
|
||||
string_view(const string& source) {
|
||||
_string = nullptr;
|
||||
_data = source.data();
|
||||
_size = source.size();
|
||||
}
|
||||
string_view::string_view(const char* data) {
|
||||
_string = nullptr;
|
||||
_data = data;
|
||||
_size = -1; //defer length calculation, as it is often unnecessary
|
||||
}
|
||||
|
||||
template<typename... P>
|
||||
string_view(P&&... p) {
|
||||
_string = new string{forward<P>(p)...};
|
||||
_data = _string->data();
|
||||
_size = _string->size();
|
||||
}
|
||||
string_view::string_view(const char* data, uint size) {
|
||||
_string = nullptr;
|
||||
_data = data;
|
||||
_size = size;
|
||||
}
|
||||
|
||||
~string_view() {
|
||||
if(_string) delete _string;
|
||||
}
|
||||
string_view::string_view(const string& source) {
|
||||
_string = nullptr;
|
||||
_data = source.data();
|
||||
_size = source.size();
|
||||
}
|
||||
|
||||
string_view(const string_view& source) {
|
||||
_string = nullptr;
|
||||
_data = source._data;
|
||||
_size = source._size;
|
||||
}
|
||||
template<typename... P>
|
||||
string_view::string_view(P&&... p) {
|
||||
_string = new string{forward<P>(p)...};
|
||||
_data = _string->data();
|
||||
_size = _string->size();
|
||||
}
|
||||
|
||||
string_view(string_view&& source) {
|
||||
_string = source._string;
|
||||
_data = source._data;
|
||||
_size = source._size;
|
||||
source._string = nullptr;
|
||||
}
|
||||
string_view::~string_view() {
|
||||
if(_string) delete _string;
|
||||
}
|
||||
|
||||
auto operator=(const string_view& source) -> string_view& {
|
||||
_string = nullptr;
|
||||
_data = source._data;
|
||||
_size = source._size;
|
||||
return *this;
|
||||
};
|
||||
|
||||
auto operator=(string_view&& source) -> string_view& {
|
||||
_string = source._string;
|
||||
_data = source._data;
|
||||
_size = source._size;
|
||||
source._string = nullptr;
|
||||
return *this;
|
||||
};
|
||||
|
||||
operator const char*() const {
|
||||
return _data;
|
||||
}
|
||||
|
||||
auto data() const -> const char* {
|
||||
return _data;
|
||||
}
|
||||
|
||||
auto size() const -> unsigned {
|
||||
if(_size < 0) _size = strlen(_data);
|
||||
return _size;
|
||||
}
|
||||
|
||||
protected:
|
||||
string* _string;
|
||||
const char* _data;
|
||||
mutable signed _size;
|
||||
auto string_view::operator=(const string_view& source) -> string_view& {
|
||||
if(this == &source) return *this;
|
||||
_string = nullptr;
|
||||
_data = source._data;
|
||||
_size = source._size;
|
||||
return *this;
|
||||
};
|
||||
|
||||
auto string_view::operator=(string_view&& source) -> string_view& {
|
||||
if(this == &source) return *this;
|
||||
_string = source._string;
|
||||
_data = source._data;
|
||||
_size = source._size;
|
||||
source._string = nullptr;
|
||||
return *this;
|
||||
};
|
||||
|
||||
string_view::operator const char*() const {
|
||||
return _data;
|
||||
}
|
||||
|
||||
auto string_view::data() const -> const char* {
|
||||
return _data;
|
||||
}
|
||||
|
||||
auto string_view::size() const -> uint {
|
||||
if(_size < 0) _size = strlen(_data);
|
||||
return _size;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -88,7 +88,7 @@ struct vector {
|
|||
auto end() const { return vector_iterator_const<T>{*this, size()}; }
|
||||
|
||||
//utility.hpp
|
||||
auto sort(const function<bool (const T& lhs, const T& rhs)>& comparator = {}) -> void;
|
||||
auto sort(const function<bool (const T& lhs, const T& rhs)>& comparator = [](auto& lhs, auto& rhs) { return lhs < rhs; }) -> void;
|
||||
auto find(const T& value) const -> maybe<uint>;
|
||||
|
||||
private:
|
||||
|
|
|
@ -3,7 +3,6 @@
|
|||
namespace nall {
|
||||
|
||||
template<typename T> auto vector<T>::sort(const function<bool (const T& lhs, const T& rhs)>& comparator) -> void {
|
||||
if(!comparator) return nall::sort(_pool, _size, [](const T& lhs, const T& rhs) { return lhs < rhs; });
|
||||
nall::sort(_pool, _size, comparator);
|
||||
}
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@ auto detour::insert(const string& moduleName, const string& functionName, void*&
|
|||
#if 1
|
||||
string output = {"detour::insert(", moduleName, "::", functionName, ") failed: "};
|
||||
for(uint n = 0; n < 16; n++) output.append(hex<2>(sourceData[n]), " ");
|
||||
output.rtrim(" ", 1L);
|
||||
output.trimRight(" ", 1L);
|
||||
MessageBoxA(0, output, "nall::detour", MB_OK);
|
||||
#endif
|
||||
return false;
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue