diff --git a/higan/emulator/emulator.hpp b/higan/emulator/emulator.hpp index a4ac20fc..0dc0dfbd 100644 --- a/higan/emulator/emulator.hpp +++ b/higan/emulator/emulator.hpp @@ -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/"; diff --git a/higan/processor/arm/disassembler.cpp b/higan/processor/arm/disassembler.cpp index 6019b8eb..d139319c 100644 --- a/higan/processor/arm/disassembler.cpp +++ b/higan/processor/arm/disassembler.cpp @@ -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; diff --git a/higan/processor/v30mz/disassembler.cpp b/higan/processor/v30mz/disassembler.cpp index f356c709..dfcfb6fc 100644 --- a/higan/processor/v30mz/disassembler.cpp +++ b/higan/processor/v30mz/disassembler.cpp @@ -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}; diff --git a/higan/target-loki/loki.cpp b/higan/target-loki/loki.cpp index 06c2502f..f2762555 100644 --- a/higan/target-loki/loki.cpp +++ b/higan/target-loki/loki.cpp @@ -5,14 +5,14 @@ unique_pointer 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 diff --git a/higan/target-loki/program/interface.cpp b/higan/target-loki/program/interface.cpp index 17744439..a98ae73a 100644 --- a/higan/target-loki/program/interface.cpp +++ b/higan/target-loki/program/interface.cpp @@ -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(), manifest.output.size()}; return emulator->load(id, stream); } } diff --git a/higan/target-loki/program/media.cpp b/higan/target-loki/program/media.cpp index 27d06013..940feb5f 100644 --- a/higan/target-loki/program/media.cpp +++ b/higan/target-loki/program/media.cpp @@ -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; diff --git a/higan/target-loki/program/program.cpp b/higan/target-loki/program/program.cpp index 919c8168..518896a1 100644 --- a/higan/target-loki/program/program.cpp +++ b/higan/target-loki/program/program.cpp @@ -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/" }; diff --git a/higan/target-tomoko/configuration/configuration.cpp b/higan/target-tomoko/configuration/configuration.cpp index 887cffcb..7d680960 100644 --- a/higan/target-tomoko/configuration/configuration.cpp +++ b/higan/target-tomoko/configuration/configuration.cpp @@ -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()); diff --git a/higan/target-tomoko/presentation/presentation.cpp b/higan/target-tomoko/presentation/presentation.cpp index 2b580513..859ac99e 100644 --- a/higan/target-tomoko/presentation/presentation.cpp +++ b/higan/target-tomoko/presentation/presentation.cpp @@ -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(); }); diff --git a/higan/target-tomoko/program/interface.cpp b/higan/target-tomoko/program/interface.cpp index b0c8ba03..2663ba65 100644 --- a/higan/target-tomoko/program/interface.cpp +++ b/higan/target-tomoko/program/interface.cpp @@ -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(), manifest.output.size()}; return emulator->load(id, stream); } } diff --git a/higan/target-tomoko/program/media.cpp b/higan/target-tomoko/program/media.cpp index 028ab820..2b8eb6bc 100644 --- a/higan/target-tomoko/program/media.cpp +++ b/higan/target-tomoko/program/media.cpp @@ -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; diff --git a/higan/target-tomoko/program/program.cpp b/higan/target-tomoko/program/program.cpp index 85d63154..fe21b9a8 100644 --- a/higan/target-tomoko/program/program.cpp +++ b/higan/target-tomoko/program/program.cpp @@ -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()); } } } diff --git a/higan/target-tomoko/tomoko.cpp b/higan/target-tomoko/tomoko.cpp index ed3997cd..51a0cc89 100644 --- a/higan/target-tomoko/tomoko.cpp +++ b/higan/target-tomoko/tomoko.cpp @@ -5,14 +5,14 @@ unique_pointer 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 diff --git a/hiro/cocoa/browser-window.cpp b/hiro/cocoa/browser-window.cpp index e2e54298..4cc407af 100644 --- a/hiro/cocoa/browser-window.cpp +++ b/hiro/cocoa/browser-window.cpp @@ -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]]; diff --git a/hiro/cocoa/widget/table-view.cpp b/hiro/cocoa/widget/table-view.cpp index 0792c199..cba42034 100644 --- a/hiro/cocoa/widget/table-view.cpp +++ b/hiro/cocoa/widget/table-view.cpp @@ -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]; diff --git a/hiro/components.hpp b/hiro/components.hpp index 147f8376..6efaaf61 100644 --- a/hiro/components.hpp +++ b/hiro/components.hpp @@ -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 diff --git a/hiro/core/core.cpp b/hiro/core/core.cpp index 2946f9a7..f7eea111 100644 --- a/hiro/core/core.cpp +++ b/hiro/core/core.cpp @@ -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" diff --git a/hiro/core/core.hpp b/hiro/core/core.hpp index 9541c4d4..d69bc088 100644 --- a/hiro/core/core.hpp +++ b/hiro/core/core.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -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; + auto onActivate(const function& callback = {}) -> type&; + auto onChange(const function& 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 items; + function onActivate; + function 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) diff --git a/hiro/core/object.cpp b/hiro/core/object.cpp index f92d4cbc..cb29bbd4 100644 --- a/hiro/core/object.cpp +++ b/hiro/core/object.cpp @@ -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(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(parent())) return frame; diff --git a/hiro/core/shared.hpp b/hiro/core/shared.hpp index 9030251e..54e2d5e4 100644 --- a/hiro/core/shared.hpp +++ b/hiro/core/shared.hpp @@ -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& callback = {}) { return self().onActivate(callback), *this; } + auto onChange(const function& 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) diff --git a/hiro/core/widget/combo-edit-item.cpp b/hiro/core/widget/combo-edit-item.cpp new file mode 100644 index 00000000..98bb2ee3 --- /dev/null +++ b/hiro/core/widget/combo-edit-item.cpp @@ -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 diff --git a/hiro/core/widget/combo-edit.cpp b/hiro/core/widget/combo-edit.cpp new file mode 100644 index 00000000..1071cd00 --- /dev/null +++ b/hiro/core/widget/combo-edit.cpp @@ -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 { + vector items; + for(auto& item : state.items) items.append(item); + return items; +} + +auto mComboEdit::onActivate(const function& callback) -> type& { + state.onActivate = callback; + return *this; +} + +auto mComboEdit::onChange(const function& 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 diff --git a/hiro/core/widget/tree-view-item.cpp b/hiro/core/widget/tree-view-item.cpp index 58b879ee..f26e9af9 100644 --- a/hiro/core/widget/tree-view-item.cpp +++ b/hiro/core/widget/tree-view-item.cpp @@ -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 {}; diff --git a/hiro/core/widget/tree-view.cpp b/hiro/core/widget/tree-view.cpp index 8ef17c49..006608c7 100644 --- a/hiro/core/widget/tree-view.cpp +++ b/hiro/core/widget/tree-view.cpp @@ -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 {}; diff --git a/hiro/extension/browser-dialog.cpp b/hiro/extension/browser-dialog.cpp index 4e217cf5..22601081 100644 --- a/hiro/extension/browser-dialog.cpp +++ b/hiro/extension/browser-dialog.cpp @@ -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(); } diff --git a/hiro/gtk/browser-window.cpp b/hiro/gtk/browser-window.cpp index 947feb19..8b49e087 100644 --- a/hiro/gtk/browser-window.cpp +++ b/hiro/gtk/browser-window.cpp @@ -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); } diff --git a/hiro/gtk/platform.cpp b/hiro/gtk/platform.cpp index 912ebd6b..0092d3e9 100644 --- a/hiro/gtk/platform.cpp +++ b/hiro/gtk/platform.cpp @@ -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" diff --git a/hiro/gtk/platform.hpp b/hiro/gtk/platform.hpp index 47a2c2d5..839a2c79 100644 --- a/hiro/gtk/platform.hpp +++ b/hiro/gtk/platform.hpp @@ -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" diff --git a/hiro/gtk/settings.cpp b/hiro/gtk/settings.cpp index 53a03d59..594f127d 100644 --- a/hiro/gtk/settings.cpp +++ b/hiro/gtk/settings.cpp @@ -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"}); } diff --git a/hiro/gtk/widget/combo-button-item.cpp b/hiro/gtk/widget/combo-button-item.cpp index 01ca947b..1e81dbfb 100644 --- a/hiro/gtk/widget/combo-button-item.cpp +++ b/hiro/gtk/widget/combo-button-item.cpp @@ -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); } diff --git a/hiro/gtk/widget/combo-edit-item.cpp b/hiro/gtk/widget/combo-edit-item.cpp new file mode 100644 index 00000000..bfea2bb3 --- /dev/null +++ b/hiro/gtk/widget/combo-edit-item.cpp @@ -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 { + if(auto parent = self().parentComboEdit()) { + if(auto self = parent->self()) return *self; + } + return nothing; +} + +} + +#endif diff --git a/hiro/gtk/widget/combo-edit-item.hpp b/hiro/gtk/widget/combo-edit-item.hpp new file mode 100644 index 00000000..fe7f1cd9 --- /dev/null +++ b/hiro/gtk/widget/combo-edit-item.hpp @@ -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; + + GtkTreeIter gtkIter; +}; + +} + +#endif diff --git a/hiro/gtk/widget/combo-edit.cpp b/hiro/gtk/widget/combo-edit.cpp new file mode 100644 index 00000000..49fe7551 --- /dev/null +++ b/hiro/gtk/widget/combo-edit.cpp @@ -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 diff --git a/hiro/gtk/widget/combo-edit.hpp b/hiro/gtk/widget/combo-edit.hpp new file mode 100644 index 00000000..78808bbc --- /dev/null +++ b/hiro/gtk/widget/combo-edit.hpp @@ -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 diff --git a/hiro/gtk/window.cpp b/hiro/gtk/window.cpp index 5f45d005..4a034f57 100644 --- a/hiro/gtk/window.cpp +++ b/hiro/gtk/window.cpp @@ -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/")); diff --git a/hiro/qt/settings.cpp b/hiro/qt/settings.cpp index cbf2d56e..484ccf31 100644 --- a/hiro/qt/settings.cpp +++ b/hiro/qt/settings.cpp @@ -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"}); } diff --git a/hiro/qt/window.cpp b/hiro/qt/window.cpp index 5ae1120d..fe5fb798 100644 --- a/hiro/qt/window.cpp +++ b/hiro/qt/window.cpp @@ -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 { diff --git a/hiro/windows/browser-window.cpp b/hiro/windows/browser-window.cpp index c439c935..a43bfaf0 100644 --- a/hiro/windows/browser-window.cpp +++ b/hiro/windows/browser-window.cpp @@ -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/"); diff --git a/hiro/windows/widget/tab-frame.cpp b/hiro/windows/widget/tab-frame.cpp index 09c246d6..58abbd26 100644 --- a/hiro/windows/widget/tab-frame.cpp +++ b/hiro/windows/widget/tab-frame.cpp @@ -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); } diff --git a/icarus/core/core.cpp b/icarus/core/core.cpp index aa2ac1f1..d6fdce06 100644 --- a/icarus/core/core.cpp +++ b/icarus/core/core.cpp @@ -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"); diff --git a/icarus/icarus.cpp b/icarus/icarus.cpp index 61374449..92784cc1 100644 --- a/icarus/icarus.cpp +++ b/icarus/icarus.cpp @@ -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" diff --git a/icarus/settings.cpp b/icarus/settings.cpp index d0dab44a..9aaebb73 100644 --- a/icarus/settings.cpp +++ b/icarus/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); diff --git a/icarus/ui/scan-dialog.cpp b/icarus/ui/scan-dialog.cpp index e45d2718..f0c2115f 100644 --- a/icarus/ui/scan-dialog.cpp +++ b/icarus/ui/scan-dialog.cpp @@ -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) { diff --git a/nall/any.hpp b/nall/any.hpp index ed1971e6..239e1002 100644 --- a/nall/any.hpp +++ b/nall/any.hpp @@ -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& { diff --git a/nall/beat/archive.hpp b/nall/beat/archive.hpp index 65be3387..df3d3c4e 100644 --- a/nall/beat/archive.hpp +++ b/nall/beat/archive.hpp @@ -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}); } } diff --git a/nall/beat/delta.hpp b/nall/beat/delta.hpp index 17c98340..b9114b51 100644 --- a/nall/beat/delta.hpp +++ b/nall/beat/delta.hpp @@ -4,6 +4,7 @@ #include #include #include +#include namespace nall { diff --git a/nall/beat/multi.hpp b/nall/beat/multi.hpp index 7fb9add6..342bfcb1 100644 --- a/nall/beat/multi.hpp +++ b/nall/beat/multi.hpp @@ -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)); } } diff --git a/nall/bitvector.hpp b/nall/bitvector.hpp index f968cc36..12fc08fc 100644 --- a/nall/bitvector.hpp +++ b/nall/bitvector.hpp @@ -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; } diff --git a/nall/config.hpp b/nall/config.hpp index 3ceffb8d..a9f9cf6d 100644 --- a/nall/config.hpp +++ b/nall/config.hpp @@ -14,9 +14,7 @@ struct Node { void* data = nullptr; vector 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"); diff --git a/nall/directory.hpp b/nall/directory.hpp index 34ced00b..52c9a5eb 100644 --- a/nall/directory.hpp +++ b/nall/directory.hpp @@ -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, "/"); diff --git a/nall/dl.hpp b/nall/dl.hpp index 46d6a10f..d8c541c6 100644 --- a/nall/dl.hpp +++ b/nall/dl.hpp @@ -3,6 +3,7 @@ //dynamic linking support #include +#include #include #include #include @@ -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; diff --git a/nall/emulation/21fx.hpp b/nall/emulation/21fx.hpp index a43b22b2..c6613f38 100644 --- a/nall/emulation/21fx.hpp +++ b/nall/emulation/21fx.hpp @@ -13,7 +13,8 @@ struct FX { auto write(uint8_t data) -> void; auto read(uint offset, uint length) -> vector; - auto write(uint offset, const vector& buffer) -> void; + auto write(uint offset, const void* buffer, uint length) -> void; + auto write(uint offset, const vector& 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 { write(offset >> 8); write(offset >> 0); write(0x01); - write(length >> 8); - write(length >> 0); + write(length >> 8); + write(length >> 0); write(0x00); vector buffer; @@ -93,9 +94,7 @@ auto FX::read(uint offset, uint length) -> vector { return buffer; } -auto FX::write(uint offset, const vector& 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& 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); } diff --git a/nall/encode/base64.hpp b/nall/encode/base64.hpp index cba70c78..42d6cede 100644 --- a/nall/encode/base64.hpp +++ b/nall/encode/base64.hpp @@ -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 result; char lookup[65]; @@ -61,7 +62,7 @@ inline auto Base64(const vector& 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); } }} diff --git a/nall/hash/crc16.hpp b/nall/hash/crc16.hpp index 6430dbd7..879f31d3 100644 --- a/nall/hash/crc16.hpp +++ b/nall/hash/crc16.hpp @@ -1,8 +1,7 @@ #pragma once #include - -namespace nall { struct string; } +#include 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& 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 { diff --git a/nall/hash/crc32.hpp b/nall/hash/crc32.hpp index d34bcd6f..b1a7b57b 100644 --- a/nall/hash/crc32.hpp +++ b/nall/hash/crc32.hpp @@ -1,8 +1,7 @@ #pragma once #include - -namespace nall { struct string; } +#include 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& 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 { diff --git a/nall/hash/crc64.hpp b/nall/hash/crc64.hpp index d838cb7a..c97de7ff 100644 --- a/nall/hash/crc64.hpp +++ b/nall/hash/crc64.hpp @@ -1,8 +1,7 @@ #pragma once #include - -namespace nall { struct string; } +#include 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& 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 { diff --git a/nall/hash/sha256.hpp b/nall/hash/sha256.hpp index 9365e189..3bc354c1 100644 --- a/nall/hash/sha256.hpp +++ b/nall/hash/sha256.hpp @@ -1,8 +1,7 @@ #pragma once #include - -namespace nall { struct string; } +#include 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& 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 { 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 { diff --git a/nall/hashset.hpp b/nall/hashset.hpp index 7efd057c..d7f75edc 100644 --- a/nall/hashset.hpp +++ b/nall/hashset.hpp @@ -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) { diff --git a/nall/http/request.hpp b/nall/http/request.hpp index 9a6ec087..da81dd7d 100644 --- a/nall/http/request.hpp +++ b/nall/http/request.hpp @@ -50,7 +50,7 @@ auto Request::head(const function& 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& callback) co } output.append("\r\n"); - return callback(output.binary(), output.size()); + return callback(output.data(), 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& callback) co if(!callback) return false; if(_body) { - return callback(_body.binary(), _body.size()); + return callback(_body.data(), _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; diff --git a/nall/http/response.hpp b/nall/http/response.hpp index c8174257..3e4b315a 100644 --- a/nall/http/response.hpp +++ b/nall/http/response.hpp @@ -61,7 +61,7 @@ auto Response::head(const function& 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(), output.size()); } } } @@ -83,15 +83,15 @@ auto Response::head(const function& callback) c } output.append("\r\n"); - return callback(output.binary(), output.size()); + return callback(output.data(), 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& callback) c if(chunked) { string prefix = {hex(findContentLength()), "\r\n"}; - if(!callback(prefix.binary(), prefix.size())) return false; + if(!callback(prefix.data(), prefix.size())) return false; } if(_body) { - if(!callback(_body.binary(), _body.size())) return false; + if(!callback(_body.data(), _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(), text().size())) return false; } else { string response = findResponseType(); - if(!callback(response.binary(), response.size())) return false; + if(!callback(response.data(), 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(), suffix.size())) return false; } return true; diff --git a/nall/image/base.hpp b/nall/image/base.hpp index 83742e9f..9e3ac2e8 100644 --- a/nall/image/base.hpp +++ b/nall/image/base.hpp @@ -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; diff --git a/nall/image/core.hpp b/nall/image/core.hpp index e0189359..8fd61d72 100644 --- a/nall/image/core.hpp +++ b/nall/image/core.hpp @@ -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; diff --git a/nall/main.hpp b/nall/main.hpp index 925e8f48..eecc0050 100644 --- a/nall/main.hpp +++ b/nall/main.hpp @@ -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 diff --git a/nall/mosaic/context.hpp b/nall/mosaic/context.hpp index 32950db8..256d926a 100644 --- a/nall/mosaic/context.hpp +++ b/nall/mosaic/context.hpp @@ -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)); } } diff --git a/nall/nall.hpp b/nall/nall.hpp index aa79a941..cdcb5cbb 100644 --- a/nall/nall.hpp +++ b/nall/nall.hpp @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include diff --git a/nall/string/platform.hpp b/nall/path.hpp similarity index 73% rename from nall/string/platform.hpp rename to nall/path.hpp index 86e38e04..b5e62550 100644 --- a/nall/string/platform.hpp +++ b/nall/path.hpp @@ -1,44 +1,46 @@ #pragma once -namespace nall { +#include -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; } -} +}} diff --git a/nall/posix/shared-memory.hpp b/nall/posix/shared-memory.hpp index c5e2756f..af66563c 100644 --- a/nall/posix/shared-memory.hpp +++ b/nall/posix/shared-memory.hpp @@ -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; } diff --git a/nall/run.hpp b/nall/run.hpp index b12fd1fb..7fcc2243 100644 --- a/nall/run.hpp +++ b/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 inline auto execute(const string& name, P&&... p) -> string { - int fd[2]; - if(pipe(fd) == -1) return ""; +template 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 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 inline auto invoke(const string& name, P&&... p) -> void #elif defined(PLATFORM_WINDOWS) -template inline auto execute(const string& name, P&&... p) -> string { +template inline auto execute(const string& name, P&&... p) -> execute_result_t { lstring argl(name, forward

(p)...); for(auto& arg : argl) if(arg.find(" ")) arg = {"\"", arg, "\""}; string arguments = argl.merge(" "); @@ -91,19 +119,24 @@ template 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 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 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; diff --git a/nall/set.hpp b/nall/set.hpp index 2c3a405b..507db8db 100644 --- a/nall/set.hpp +++ b/nall/set.hpp @@ -49,8 +49,8 @@ template 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 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 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 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); } diff --git a/nall/shared-pointer.hpp b/nall/shared-pointer.hpp index af44bde8..634d02a8 100644 --- a/nall/shared-pointer.hpp +++ b/nall/shared-pointer.hpp @@ -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 { diff --git a/nall/smtp.hpp b/nall/smtp.hpp index f1f60dea..b3bca32b 100644 --- a/nall/smtp.hpp +++ b/nall/smtp.hpp @@ -272,7 +272,7 @@ auto SMTP::contacts(const vector& contacts) -> string { for(auto& contact : contacts) { result.append(this->contact(contact), "; "); } - result.rtrim("; ", 1L); + result.trimRight("; ", 1L); return result; } diff --git a/nall/stream/stream.hpp b/nall/stream/stream.hpp index a9e1a64a..e2d23d92 100644 --- a/nall/stream/stream.hpp +++ b/nall/stream/stream.hpp @@ -29,10 +29,6 @@ struct stream { return size(); } - auto empty() const -> bool { - return size() == 0; - } - auto end() const -> bool { return offset() >= size(); } diff --git a/nall/string.hpp b/nall/string.hpp index b38ba8fe..63e71125 100644 --- a/nall/string.hpp +++ b/nall/string.hpp @@ -20,12 +20,305 @@ #include #include #include -#include -#include -#include -#include -#include +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 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 struct stringify; + +//format.hpp +template inline auto print(P&&...) -> void; +template 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 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 inline auto get() -> T*; + template 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 string(T&& s, P&&... p) : string() { + append(forward(s), forward

(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 inline auto assign(P&&...) -> type&; + template inline auto append(const T&, P&&...) -> type&; + template inline auto append(const nall::format&, P&&...) -> type&; + inline auto append() -> type&; + template inline auto _append(const stringify&) -> 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 inline auto _find(int, string_view) const -> maybe; + + inline auto find(string_view source) const -> maybe; + inline auto ifind(string_view source) const -> maybe; + inline auto qfind(string_view source) const -> maybe; + inline auto iqfind(string_view source) const -> maybe; + + inline auto findFrom(int offset, string_view source) const -> maybe; + inline auto ifindFrom(int offset, string_view source) const -> maybe; + + //format.hpp + inline auto format(const nall::format& params) -> type&; + + //compare.hpp + template 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 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 { + using type = lstring; + + lstring(const lstring& source) { vector::operator=(source); } + lstring(lstring& source) { vector::operator=(source); } + lstring(lstring&& source) { vector::operator=(move(source)); } + template lstring(P&&... p) { append(forward

(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 inline auto append(const string&, P&&...) -> type&; + inline auto append() -> type&; + + inline auto find(string_view source) const -> maybe; + inline auto ifind(string_view source) const -> maybe; + inline auto match(string_view pattern) const -> lstring; + inline auto merge(string_view separator) const -> string; + inline auto strip() -> type&; + + //split.hpp + template inline auto _split(string_view, string_view, long) -> lstring&; +}; + +struct format : vector { + using type = format; + + template format(P&&... p) { reserve(sizeof...(p)); append(forward

(p)...); } + template inline auto append(const T&, P&&... p) -> type&; + inline auto append() -> type&; +}; + +} + #include #include #include @@ -35,11 +328,9 @@ #include #include #include -#include #include #include #include -#include #include #include #include diff --git a/nall/string/allocator/adaptive.hpp b/nall/string/allocator/adaptive.hpp index 224cc154..f919c0bb 100644 --- a/nall/string/allocator/adaptive.hpp +++ b/nall/string/allocator/adaptive.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 +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 +auto string::data() const -> const T* { + if(_capacity < SSO) return (const T*)_text; + return (const T*)_data; } auto string::reset() -> type& { diff --git a/nall/string/base.hpp b/nall/string/base.hpp deleted file mode 100644 index d638f035..00000000 --- a/nall/string/base.hpp +++ /dev/null @@ -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 struct stringify; - -//format.hpp -template 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 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 string(T&& s, P&&... p) : string() { append(forward(s), forward

(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 inline auto assign(P&&...) -> type&; - template inline auto append(const T&, P&&...) -> type&; - template inline auto append(const nall::format&, P&&...) -> type&; - inline auto append() -> type&; - template inline auto _append(const stringify&) -> 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 inline auto _find(int, rstring) const -> maybe; - - inline auto find(rstring source) const -> maybe; - inline auto ifind(rstring source) const -> maybe; - inline auto qfind(rstring source) const -> maybe; - inline auto iqfind(rstring source) const -> maybe; - - inline auto findFrom(int offset, rstring source) const -> maybe; - inline auto ifindFrom(int offset, rstring source) const -> maybe; - - //format.hpp - inline auto format(const nall::format& params) -> type&; - - //compare.hpp - template 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 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 { - using type = lstring; - - lstring(const lstring& source) { vector::operator=(source); } - lstring(lstring& source) { vector::operator=(source); } - lstring(lstring&& source) { vector::operator=(move(source)); } - template lstring(P&&... p) { append(forward

(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 inline auto append(const string&, P&&...) -> type&; - inline auto append() -> type&; - - inline auto find(rstring source) const -> maybe; - inline auto ifind(rstring source) const -> maybe; - inline auto match(rstring pattern) const -> lstring; - inline auto merge(rstring separator) const -> string; - inline auto strip() -> type&; - - //split.hpp - template inline auto _split(rstring, rstring, long) -> lstring&; -}; - -struct format : vector { - using type = format; - - template format(P&&... p) { reserve(sizeof...(p)); append(forward

(p)...); } - template inline auto append(const T&, P&&... p) -> type&; - inline auto append() -> type&; -}; - -} diff --git a/nall/string/cast.hpp b/nall/string/cast.hpp index 2574eca4..2c68071e 100644 --- a/nall/string/cast.hpp +++ b/nall/string/cast.hpp @@ -10,7 +10,7 @@ namespace nall { template<> struct stringify { 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 { template<> struct stringify { 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 { template<> struct stringify { 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 { 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 { 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 { 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 { 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 struct stringify> { template<> struct stringify { 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 { 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 { 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 { 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 { 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 struct stringify> { template<> struct stringify { 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 { 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 { 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> { 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 _text; }; @@ -166,7 +166,7 @@ template<> struct stringify&> { 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 _text; }; @@ -175,14 +175,14 @@ template<> struct stringify&> { template<> struct stringify { 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 { 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 { template<> struct stringify { 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 { 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 { 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 { 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; }; diff --git a/nall/string/compare.hpp b/nall/string/compare.hpp index 0fb933dc..08479ba2 100644 --- a/nall/string/compare.hpp +++ b/nall/string/compare.hpp @@ -3,54 +3,54 @@ namespace nall { template -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; } diff --git a/nall/string/convert.hpp b/nall/string/convert.hpp index 2b177f44..4c7d4abf 100644 --- a/nall/string/convert.hpp +++ b/nall/string/convert.hpp @@ -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; diff --git a/nall/string/core.hpp b/nall/string/core.hpp index da8c166e..7122c5f6 100644 --- a/nall/string/core.hpp +++ b/nall/string/core.hpp @@ -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 auto string::_append(const stringify& source) -> string& return *this; } -auto string::empty() const -> bool { - return size() == 0; -} - auto string::length() const -> uint { return strlen(data()); } diff --git a/nall/string/eval/evaluator.hpp b/nall/string/eval/evaluator.hpp index 60fc2d1b..184f8eb4 100644 --- a/nall/string/eval/evaluator.hpp +++ b/nall/string/eval/evaluator.hpp @@ -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 diff --git a/nall/string/eval/literal.hpp b/nall/string/eval/literal.hpp index f56078ad..4efd94aa 100644 --- a/nall/string/eval/literal.hpp +++ b/nall/string/eval/literal.hpp @@ -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"; diff --git a/nall/string/find.hpp b/nall/string/find.hpp index 872fece5..d8d9a48c 100644 --- a/nall/string/find.hpp +++ b/nall/string/find.hpp @@ -2,7 +2,7 @@ namespace nall { -template auto string::_find(int offset, rstring source) const -> maybe { +template auto string::_find(int offset, string_view source) const -> maybe { if(source.size() == 0) return nothing; auto p = data(); @@ -15,12 +15,12 @@ template auto string::_find(int offset, rstring s return nothing; } -auto string::find(rstring source) const -> maybe { return _find<0, 0>(0, source); } -auto string::ifind(rstring source) const -> maybe { return _find<1, 0>(0, source); } -auto string::qfind(rstring source) const -> maybe { return _find<0, 1>(0, source); } -auto string::iqfind(rstring source) const -> maybe { return _find<1, 1>(0, source); } +auto string::find(string_view source) const -> maybe { return _find<0, 0>(0, source); } +auto string::ifind(string_view source) const -> maybe { return _find<1, 0>(0, source); } +auto string::qfind(string_view source) const -> maybe { return _find<0, 1>(0, source); } +auto string::iqfind(string_view source) const -> maybe { return _find<1, 1>(0, source); } -auto string::findFrom(int offset, rstring source) const -> maybe { return _find<0, 0>(offset, source); } -auto string::ifindFrom(int offset, rstring source) const -> maybe { return _find<1, 0>(offset, source); } +auto string::findFrom(int offset, string_view source) const -> maybe { return _find<0, 0>(offset, source); } +auto string::ifindFrom(int offset, string_view source) const -> maybe { return _find<1, 0>(offset, source); } } diff --git a/nall/string/format.hpp b/nall/string/format.hpp index 8f8c463e..71c8a1a4 100644 --- a/nall/string/format.hpp +++ b/nall/string/format.hpp @@ -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 auto print(P&&... p) -> void { string s{forward

(p)...}; - fputs(s.data(), stdout); + fwrite(s.data(), 1, s.size(), stdout); +} + +template auto print(FILE* fp, P&&... p) -> void { + string s{forward

(p)...}; + fwrite(s.data(), 1, s.size(), fp); } auto integer(intmax value, long precision, char padchar) -> string { diff --git a/nall/string/hash.hpp b/nall/string/hash.hpp deleted file mode 100644 index 04be44ff..00000000 --- a/nall/string/hash.hpp +++ /dev/null @@ -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(); -} - -} diff --git a/nall/string/list.hpp b/nall/string/list.hpp index e448acb7..ae741722 100644 --- a/nall/string/list.hpp +++ b/nall/string/list.hpp @@ -32,21 +32,21 @@ auto lstring::append() -> lstring& { return *this; } -auto lstring::find(rstring source) const -> maybe { +auto lstring::find(string_view source) const -> maybe { for(uint n = 0; n < size(); n++) { if(operator[](n).equals(source)) return n; } return nothing; } -auto lstring::ifind(rstring source) const -> maybe { +auto lstring::ifind(string_view source) const -> maybe { 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)); diff --git a/nall/string/markup/bml.hpp b/nall/string/markup/bml.hpp index d170d194..550f3e09 100644 --- a/nall/string/markup/bml.hpp +++ b/nall/string/markup/bml.hpp @@ -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"); diff --git a/nall/string/markup/find.hpp b/nall/string/markup/find.hpp index 91dedc17..f4016bab 100644 --- a/nall/string/markup/find.hpp +++ b/nall/string/markup/find.hpp @@ -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 { 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); } diff --git a/nall/string/markup/xml.hpp b/nall/string/markup/xml.hpp index f53090e0..b0d946af 100644 --- a/nall/string/markup/xml.hpp +++ b/nall/string/markup/xml.hpp @@ -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"; diff --git a/nall/string/match.hpp b/nall/string/match.hpp index 80ff7c1c..3d1bebb1 100644 --- a/nall/string/match.hpp +++ b/nall/string/match.hpp @@ -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; }; diff --git a/nall/string/path.hpp b/nall/string/path.hpp index b5903d56..eac881bf 100644 --- a/nall/string/path.hpp +++ b/nall/string/path.hpp @@ -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 } diff --git a/nall/string/replace.hpp b/nall/string/replace.hpp index 0744caf3..d8143a15 100644 --- a/nall/string/replace.hpp +++ b/nall/string/replace.hpp @@ -3,17 +3,17 @@ namespace nall { template -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(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(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(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(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); } }; diff --git a/nall/string/split.hpp b/nall/string/split.hpp index b236e373..ef5b8f31 100644 --- a/nall/string/split.hpp +++ b/nall/string/split.hpp @@ -3,16 +3,16 @@ namespace nall { template -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(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); } } diff --git a/nall/string/transform/cml.hpp b/nall/string/transform/cml.hpp index d00e1fdb..c0e97336 100644 --- a/nall/string/transform/cml.hpp +++ b/nall/string/transform/cml.hpp @@ -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); diff --git a/nall/string/transform/dml.hpp b/nall/string/transform/dml.hpp index 5a603e11..32dcf1d8 100644 --- a/nall/string/transform/dml.hpp +++ b/nall/string/transform/dml.hpp @@ -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("\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(""); state.output.append("

"); } - 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("
", data); for(auto& line : lines) { if(!line.beginsWith("# ")) continue; - state.output.append("", line.ltrim("# ", 1L), ""); + state.output.append("", line.trimLeft("# ", 1L), ""); } state.output.append("
\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("", 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("\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("
  • ", data, "
  • \n"); } } @@ -162,9 +162,9 @@ auto DML::parseBlock(string& block, const string& pathname, uint depth) -> bool state.output.append("
    ");
         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("
    \n"); + state.output.trimRight("\n", 1L).append("\n"); } //divider diff --git a/nall/string/trim.hpp b/nall/string/trim.hpp index 35c5ecec..17823a7d 100644 --- a/nall/string/trim.hpp +++ b/nall/string/trim.hpp @@ -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); diff --git a/nall/string/utility.hpp b/nall/string/utility.hpp index 0faa2be8..00a52966 100644 --- a/nall/string/utility.hpp +++ b/nall/string/utility.hpp @@ -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; diff --git a/nall/string/view.hpp b/nall/string/view.hpp index 2f72337c..0c8a175e 100644 --- a/nall/string/view.hpp +++ b/nall/string/view.hpp @@ -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 - string_view(P&&... p) { - _string = new string{forward

    (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 +string_view::string_view(P&&... p) { + _string = new string{forward

    (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; +} + } diff --git a/nall/vector.hpp b/nall/vector.hpp index 0bdde14c..ad3d0edf 100644 --- a/nall/vector.hpp +++ b/nall/vector.hpp @@ -88,7 +88,7 @@ struct vector { auto end() const { return vector_iterator_const{*this, size()}; } //utility.hpp - auto sort(const function& comparator = {}) -> void; + auto sort(const function& comparator = [](auto& lhs, auto& rhs) { return lhs < rhs; }) -> void; auto find(const T& value) const -> maybe; private: diff --git a/nall/vector/utility.hpp b/nall/vector/utility.hpp index e58948e9..1cb2b6ef 100644 --- a/nall/vector/utility.hpp +++ b/nall/vector/utility.hpp @@ -3,7 +3,6 @@ namespace nall { template auto vector::sort(const function& comparator) -> void { - if(!comparator) return nall::sort(_pool, _size, [](const T& lhs, const T& rhs) { return lhs < rhs; }); nall::sort(_pool, _size, comparator); } diff --git a/nall/windows/detour.hpp b/nall/windows/detour.hpp index 6e57a590..bedb1901 100644 --- a/nall/windows/detour.hpp +++ b/nall/windows/detour.hpp @@ -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; diff --git a/nall/windows/registry.hpp b/nall/windows/registry.hpp index e9a50559..97f3f35b 100644 --- a/nall/windows/registry.hpp +++ b/nall/windows/registry.hpp @@ -75,7 +75,7 @@ struct registry { HKEY rootKey = root(part.takeLeft()); string node = part.takeRight(); string path = part.merge("\\"); - if(node.empty()) return SHDeleteKeyW(rootKey, utf16_t(path)) == ERROR_SUCCESS; + if(!node) return SHDeleteKeyW(rootKey, utf16_t(path)) == ERROR_SUCCESS; return SHDeleteValueW(rootKey, utf16_t(path), utf16_t(node)) == ERROR_SUCCESS; } diff --git a/ruby/video/glx.cpp b/ruby/video/glx.cpp index b462c056..679a9f74 100644 --- a/ruby/video/glx.cpp +++ b/ruby/video/glx.cpp @@ -82,14 +82,14 @@ struct VideoGLX : Video, OpenGL { if(name == Video::Filter && value.is()) { settings.filter = value.get(); - if(settings.shader.empty()) OpenGL::filter = settings.filter ? GL_LINEAR : GL_NEAREST; + if(!settings.shader) OpenGL::filter = settings.filter ? GL_LINEAR : GL_NEAREST; return true; } if(name == Video::Shader && value.is()) { settings.shader = value.get(); OpenGL::shader(settings.shader); - if(settings.shader.empty()) OpenGL::filter = settings.filter ? GL_LINEAR : GL_NEAREST; + if(!settings.shader) OpenGL::filter = settings.filter ? GL_LINEAR : GL_NEAREST; return true; } diff --git a/ruby/video/opengl/main.hpp b/ruby/video/opengl/main.hpp index 6791d5f1..e664fde7 100644 --- a/ruby/video/opengl/main.hpp +++ b/ruby/video/opengl/main.hpp @@ -28,11 +28,11 @@ auto OpenGL::shader(const string& pathname) -> void { for(auto node : document["output"]) { string text = node.text(); if(node.name() == "width") { - if(text.endsWith("%")) relativeWidth = real(text.rtrim("%", 1L)) / 100.0; + if(text.endsWith("%")) relativeWidth = real(text.trimRight("%", 1L)) / 100.0; else absoluteWidth = text.natural(); } if(node.name() == "height") { - if(text.endsWith("%")) relativeHeight = real(text.rtrim("%", 1L)) / 100.0; + if(text.endsWith("%")) relativeHeight = real(text.trimRight("%", 1L)) / 100.0; else absoluteHeight = text.natural(); } } diff --git a/ruby/video/opengl/program.hpp b/ruby/video/opengl/program.hpp index 1d346822..0c2fda64 100644 --- a/ruby/video/opengl/program.hpp +++ b/ruby/video/opengl/program.hpp @@ -4,9 +4,9 @@ auto OpenGLProgram::bind(OpenGL* instance, const Markup::Node& node, const strin modulo = glrModulo(node["modulo"].integer()); string w = node["width"].text(), h = node["height"].text(); - if(w.endsWith("%")) relativeWidth = real(w.rtrim("%", 1L)) / 100.0; + if(w.endsWith("%")) relativeWidth = real(w.trimRight("%", 1L)) / 100.0; else absoluteWidth = w.natural(); - if(h.endsWith("%")) relativeHeight = real(h.rtrim("%", 1L)) / 100.0; + if(h.endsWith("%")) relativeHeight = real(h.trimRight("%", 1L)) / 100.0; else absoluteHeight = h.natural(); format = glrFormat(node["format"].text()); @@ -41,8 +41,8 @@ auto OpenGLProgram::bind(OpenGL* instance, const Markup::Node& node, const strin for(auto& leaf : node.find("pixmap")) { nall::image image({pathname, leaf.text()}); + if(!image) continue; image.transform(); - if(image.empty()) continue; GLuint texture; glGenTextures(1, &texture); @@ -78,7 +78,7 @@ auto OpenGLProgram::parse(OpenGL* instance, string& source) -> void { if(auto position = s.find("//")) s.resize(position()); //strip comments s.strip(); //remove extraneous whitespace if(s.match("#in ?*")) { - s.ltrim("#in ", 1L).strip(); + s.trimLeft("#in ", 1L).strip(); if(auto setting = instance->settings.find({s})) { line = {"#define ", setting().name, " ", setting().value}; } else { diff --git a/ruby/video/wgl.cpp b/ruby/video/wgl.cpp index 703953bd..82fcfb7b 100644 --- a/ruby/video/wgl.cpp +++ b/ruby/video/wgl.cpp @@ -48,7 +48,7 @@ struct VideoWGL : Video, OpenGL { if(wglcontext) { init(); OpenGL::shader(settings.shader); - if(settings.shader.empty()) OpenGL::filter = settings.filter ? GL_LINEAR : GL_NEAREST; + if(!settings.shader) OpenGL::filter = settings.filter ? GL_LINEAR : GL_NEAREST; } } }