mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-11-15 01:26:34 +00:00
util::string_view, update pgl for new sf semantics
This commit is contained in:
parent
6467f6f07b
commit
2c485f832c
13 changed files with 448 additions and 70 deletions
|
@ -20,6 +20,6 @@
|
||||||
|
|
||||||
namespace ams::pgl::srv {
|
namespace ams::pgl::srv {
|
||||||
|
|
||||||
void Initialize(ShellInterface *interface, MemoryResource *mr);
|
void Initialize();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,18 +20,16 @@
|
||||||
|
|
||||||
namespace ams::pgl::srv {
|
namespace ams::pgl::srv {
|
||||||
|
|
||||||
class ShellInterface final {
|
class ShellInterface {
|
||||||
NON_COPYABLE(ShellInterface);
|
NON_COPYABLE(ShellInterface);
|
||||||
NON_MOVEABLE(ShellInterface);
|
NON_MOVEABLE(ShellInterface);
|
||||||
private:
|
private:
|
||||||
MemoryResource *memory_resource;
|
using Allocator = ams::sf::ExpHeapAllocator;
|
||||||
|
using ObjectFactory = ams::sf::ObjectFactory<ams::sf::ExpHeapAllocator::Policy>;
|
||||||
|
private:
|
||||||
|
Allocator *m_allocator;
|
||||||
public:
|
public:
|
||||||
constexpr ShellInterface() : memory_resource(nullptr) { /* ... */ }
|
constexpr ShellInterface(Allocator *a) : m_allocator(a) { /* ... */ }
|
||||||
|
|
||||||
void Initialize(MemoryResource *mr) {
|
|
||||||
AMS_ASSERT(this->memory_resource == nullptr);
|
|
||||||
this->memory_resource = mr;
|
|
||||||
}
|
|
||||||
public:
|
public:
|
||||||
/* Interface commands. */
|
/* Interface commands. */
|
||||||
Result LaunchProgram(ams::sf::Out<os::ProcessId> out, const ncm::ProgramLocation &loc, u32 pm_flags, u8 pgl_flags);
|
Result LaunchProgram(ams::sf::Out<os::ProcessId> out, const ncm::ProgramLocation &loc, u32 pm_flags, u8 pgl_flags);
|
||||||
|
|
|
@ -156,7 +156,7 @@ namespace ams::sf {
|
||||||
constexpr virtual void AddReference() override { /* ... */ }
|
constexpr virtual void AddReference() override { /* ... */ }
|
||||||
constexpr virtual void Release() override { /* ... */ }
|
constexpr virtual void Release() override { /* ... */ }
|
||||||
|
|
||||||
constexpr Impl &GetImpl() { return impl::UnmanagedEmplacedImplHolder<Impl>::GetImplPointer(this); }
|
constexpr Impl &GetImpl() { return *impl::UnmanagedEmplacedImplHolder<Impl>::GetImplPointer(this); }
|
||||||
|
|
||||||
constexpr SharedPointer<Interface> GetShared() { return SharedPointer<Interface>(this, false); }
|
constexpr SharedPointer<Interface> GetShared() { return SharedPointer<Interface>(this, false); }
|
||||||
};
|
};
|
||||||
|
|
|
@ -24,17 +24,17 @@ namespace ams::ncm::impl {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PathView::HasPrefix(std::string_view prefix) const {
|
bool PathView::HasPrefix(util::string_view prefix) const {
|
||||||
return this->path.compare(0, prefix.length(), prefix) == 0;
|
return this->path.compare(0, prefix.length(), prefix) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PathView::HasSuffix(std::string_view suffix) const {
|
bool PathView::HasSuffix(util::string_view suffix) const {
|
||||||
return this->path.compare(this->path.length() - suffix.length(), suffix.length(), suffix) == 0;
|
return this->path.compare(this->path.length() - suffix.length(), suffix.length(), suffix) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string_view PathView::GetFileName() const {
|
util::string_view PathView::GetFileName() const {
|
||||||
auto pos = this->path.find_last_of("/");
|
auto pos = this->path.find_last_of("/");
|
||||||
return pos != std::string_view::npos ? this->path.substr(pos + 1) : this->path;
|
return pos != util::string_view::npos ? this->path.substr(pos + 1) : this->path;
|
||||||
}
|
}
|
||||||
|
|
||||||
MountName CreateUniqueMountName() {
|
MountName CreateUniqueMountName() {
|
||||||
|
|
|
@ -22,12 +22,12 @@ namespace ams::ncm::impl {
|
||||||
|
|
||||||
class PathView {
|
class PathView {
|
||||||
private:
|
private:
|
||||||
std::string_view path; /* Nintendo uses util::string_view here. */
|
util::string_view path; /* Nintendo uses util::string_view here. */
|
||||||
public:
|
public:
|
||||||
PathView(std::string_view p) : path(p) { /* ...*/ }
|
PathView(util::string_view p) : path(p) { /* ...*/ }
|
||||||
bool HasPrefix(std::string_view prefix) const;
|
bool HasPrefix(util::string_view prefix) const;
|
||||||
bool HasSuffix(std::string_view suffix) const;
|
bool HasSuffix(util::string_view suffix) const;
|
||||||
std::string_view GetFileName() const;
|
util::string_view GetFileName() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MountName {
|
struct MountName {
|
||||||
|
|
|
@ -18,10 +18,7 @@
|
||||||
|
|
||||||
namespace ams::pgl::srv {
|
namespace ams::pgl::srv {
|
||||||
|
|
||||||
void Initialize(ShellInterface *interface, MemoryResource *mr) {
|
void Initialize() {
|
||||||
/* Set the memory resource for the interface. */
|
|
||||||
interface->Initialize(mr);
|
|
||||||
|
|
||||||
/* Enable extra application threads, if we should. */
|
/* Enable extra application threads, if we should. */
|
||||||
u8 enable_application_extra_thread;
|
u8 enable_application_extra_thread;
|
||||||
const size_t sz = settings::fwdbg::GetSettingsItemValue(std::addressof(enable_application_extra_thread), sizeof(enable_application_extra_thread), "application_extra_thread", "enable_application_extra_thread");
|
const size_t sz = settings::fwdbg::GetSettingsItemValue(std::addressof(enable_application_extra_thread), sizeof(enable_application_extra_thread), "application_extra_thread", "enable_application_extra_thread");
|
||||||
|
|
|
@ -25,16 +25,16 @@ namespace ams::pgl::srv {
|
||||||
static_assert(sizeof(HostPackageMountName) - 1 <= fs::MountNameLengthMax);
|
static_assert(sizeof(HostPackageMountName) - 1 <= fs::MountNameLengthMax);
|
||||||
|
|
||||||
struct CaseInsensitiveCharTraits : public std::char_traits<char> {
|
struct CaseInsensitiveCharTraits : public std::char_traits<char> {
|
||||||
static char to_upper(char c) {
|
static constexpr char to_upper(char c) {
|
||||||
return std::toupper(static_cast<unsigned char>(c));
|
return std::toupper(static_cast<unsigned char>(c));
|
||||||
}
|
}
|
||||||
static bool eq(char c1, char c2) {
|
static constexpr bool eq(char c1, char c2) {
|
||||||
return to_upper(c1) == to_upper(c2);
|
return to_upper(c1) == to_upper(c2);
|
||||||
}
|
}
|
||||||
static bool lt(char c1, char c2) {
|
static constexpr bool lt(char c1, char c2) {
|
||||||
return to_upper(c1) < to_upper(c2);
|
return to_upper(c1) < to_upper(c2);
|
||||||
}
|
}
|
||||||
static int compare(const char *s1, const char *s2, size_t n) {
|
static constexpr int compare(const char *s1, const char *s2, size_t n) {
|
||||||
while ( n-- != 0 ) {
|
while ( n-- != 0 ) {
|
||||||
if ( to_upper(*s1) < to_upper(*s2) ) return -1;
|
if ( to_upper(*s1) < to_upper(*s2) ) return -1;
|
||||||
if ( to_upper(*s1) > to_upper(*s2) ) return 1;
|
if ( to_upper(*s1) > to_upper(*s2) ) return 1;
|
||||||
|
@ -42,7 +42,7 @@ namespace ams::pgl::srv {
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
static const char *find(const char *s, int n, char a) {
|
static constexpr const char *find(const char *s, int n, char a) {
|
||||||
auto const ua (to_upper(a));
|
auto const ua (to_upper(a));
|
||||||
while ( n-- != 0 )
|
while ( n-- != 0 )
|
||||||
{
|
{
|
||||||
|
@ -54,7 +54,7 @@ namespace ams::pgl::srv {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
using PathView = std::basic_string_view<char, CaseInsensitiveCharTraits>;
|
using PathView = util::basic_string_view<char, CaseInsensitiveCharTraits>;
|
||||||
|
|
||||||
enum class ExtensionType {
|
enum class ExtensionType {
|
||||||
None = 0,
|
None = 0,
|
||||||
|
|
|
@ -20,12 +20,6 @@
|
||||||
|
|
||||||
namespace ams::pgl::srv {
|
namespace ams::pgl::srv {
|
||||||
|
|
||||||
namespace {
|
|
||||||
|
|
||||||
using ShellEventObjectFactory = ams::sf::ObjectFactory<ams::sf::MemoryResourceAllocationPolicy>;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
Result ShellInterface::LaunchProgram(ams::sf::Out<os::ProcessId> out, const ncm::ProgramLocation &loc, u32 pm_flags, u8 pgl_flags) {
|
Result ShellInterface::LaunchProgram(ams::sf::Out<os::ProcessId> out, const ncm::ProgramLocation &loc, u32 pm_flags, u8 pgl_flags) {
|
||||||
return pgl::srv::LaunchProgram(out.GetPointer(), loc, pm_flags, pgl_flags);
|
return pgl::srv::LaunchProgram(out.GetPointer(), loc, pm_flags, pgl_flags);
|
||||||
}
|
}
|
||||||
|
@ -76,7 +70,7 @@ namespace ams::pgl::srv {
|
||||||
|
|
||||||
Result ShellInterface::GetShellEventObserver(ams::sf::Out<ams::sf::SharedPointer<pgl::sf::IEventObserver>> out) {
|
Result ShellInterface::GetShellEventObserver(ams::sf::Out<ams::sf::SharedPointer<pgl::sf::IEventObserver>> out) {
|
||||||
/* Allocate a new interface. */
|
/* Allocate a new interface. */
|
||||||
auto session = ShellEventObjectFactory::CreateSharedEmplaced<pgl::sf::IEventObserver, ShellEventObserver>(this->memory_resource);
|
auto session = ObjectFactory::CreateSharedEmplaced<pgl::sf::IEventObserver, ShellEventObserver>(m_allocator);
|
||||||
R_UNLESS(session != nullptr, pgl::ResultOutOfMemory());
|
R_UNLESS(session != nullptr, pgl::ResultOutOfMemory());
|
||||||
|
|
||||||
*out = std::move(session);
|
*out = std::move(session);
|
||||||
|
|
|
@ -40,6 +40,7 @@
|
||||||
#include <vapours/util/util_bounded_map.hpp>
|
#include <vapours/util/util_bounded_map.hpp>
|
||||||
#include <vapours/util/util_overlap.hpp>
|
#include <vapours/util/util_overlap.hpp>
|
||||||
#include <vapours/util/util_string_util.hpp>
|
#include <vapours/util/util_string_util.hpp>
|
||||||
|
#include <vapours/util/util_string_view.hpp>
|
||||||
#include <vapours/util/util_variadic.hpp>
|
#include <vapours/util/util_variadic.hpp>
|
||||||
#include <vapours/util/util_character_encoding.hpp>
|
#include <vapours/util/util_character_encoding.hpp>
|
||||||
#include <vapours/util/util_format_string.hpp>
|
#include <vapours/util/util_format_string.hpp>
|
||||||
|
|
347
libraries/libvapours/include/vapours/util/util_string_view.hpp
Normal file
347
libraries/libvapours/include/vapours/util/util_string_view.hpp
Normal file
|
@ -0,0 +1,347 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2018-2020 Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include <vapours/common.hpp>
|
||||||
|
#include <vapours/assert.hpp>
|
||||||
|
|
||||||
|
namespace ams::util {
|
||||||
|
|
||||||
|
template<class _CharT, class _Traits = std::char_traits<_CharT>>
|
||||||
|
class basic_string_view {
|
||||||
|
static_assert(!std::is_array<_CharT>::value);
|
||||||
|
static_assert(std::is_trivial<_CharT>::value && std::is_standard_layout<_CharT>::value);
|
||||||
|
static_assert(std::same_as<_CharT, typename _Traits::char_type>);
|
||||||
|
public:
|
||||||
|
using traits_type = _Traits;
|
||||||
|
using value_type = _CharT;
|
||||||
|
using pointer = value_type *;
|
||||||
|
using const_pointer = const value_type *;
|
||||||
|
using reference = value_type &;
|
||||||
|
using const_reference = const value_type &;
|
||||||
|
using const_iterator = const value_type *;
|
||||||
|
using iterator = const_iterator;
|
||||||
|
using const_reverse_iterator = std::reverse_iterator<const_iterator>;
|
||||||
|
using reverse_iterator = const_reverse_iterator;
|
||||||
|
using size_type = size_t;
|
||||||
|
using difference_type = ptrdiff_t;
|
||||||
|
static constexpr size_type npos = size_type(-1);
|
||||||
|
private:
|
||||||
|
static constexpr int _s_compare(size_type lhs, size_type rhs) noexcept {
|
||||||
|
const difference_type diff = lhs - rhs;
|
||||||
|
if (diff > std::numeric_limits<int>::max()) {
|
||||||
|
return std::numeric_limits<int>::max();
|
||||||
|
}
|
||||||
|
if (diff < std::numeric_limits<int>::min()) {
|
||||||
|
return std::numeric_limits<int>::min();
|
||||||
|
}
|
||||||
|
return static_cast<int>(diff);
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
const_pointer m_str;
|
||||||
|
size_type m_len;
|
||||||
|
public:
|
||||||
|
constexpr basic_string_view() noexcept : m_str(nullptr), m_len(0) { /* ... */ }
|
||||||
|
constexpr basic_string_view(const _CharT *str, size_type len) noexcept : m_str(str), m_len(len) { /* ... */ }
|
||||||
|
constexpr basic_string_view(const _CharT *str) noexcept : m_str(str), m_len(str ? traits_type::length(str) : 0) { /* ... */ }
|
||||||
|
|
||||||
|
template<std::contiguous_iterator _It, std::sized_sentinel_for<_It> _End> requires std::same_as<std::iter_value_t<_It>, _CharT> && (!std::convertible_to<_End, size_type>)
|
||||||
|
constexpr basic_string_view(_It first, _End last) noexcept : m_str(std::to_address(first)), m_len(last - first) { /* ... */ }
|
||||||
|
|
||||||
|
constexpr basic_string_view(const basic_string_view &) noexcept = default;
|
||||||
|
constexpr basic_string_view &operator=(const basic_string_view &) noexcept = default;
|
||||||
|
|
||||||
|
constexpr const_iterator begin() const noexcept { return m_str; }
|
||||||
|
constexpr const_iterator end() const noexcept { return m_str + m_len; }
|
||||||
|
|
||||||
|
constexpr const_iterator cbegin() const noexcept { return m_str; }
|
||||||
|
constexpr const_iterator cend() const noexcept { return m_str + m_len; }
|
||||||
|
|
||||||
|
constexpr const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(this->end()); }
|
||||||
|
constexpr const_reverse_iterator rend() const noexcept { return const_reverse_iterator(this->begin()); }
|
||||||
|
|
||||||
|
constexpr const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(this->cend()); }
|
||||||
|
constexpr const_reverse_iterator crend() const noexcept { return const_reverse_iterator(this->cbegin()); }
|
||||||
|
|
||||||
|
constexpr size_type size() const noexcept { return m_len; }
|
||||||
|
constexpr size_type length() const noexcept { return m_len; }
|
||||||
|
|
||||||
|
constexpr size_type max_size() const noexcept { return (npos - sizeof(size_type) - sizeof(void *)) / sizeof(value_type) / 4; }
|
||||||
|
|
||||||
|
[[nodiscard]] constexpr bool empty() const noexcept { return m_len == 0; }
|
||||||
|
|
||||||
|
constexpr const_reference operator[](size_type pos) const noexcept {
|
||||||
|
AMS_ASSERT(pos < m_len);
|
||||||
|
return *(m_str + pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr const_reference at(size_type pos) const noexcept {
|
||||||
|
AMS_ASSERT(pos < m_len);
|
||||||
|
AMS_ABORT_UNLESS(pos < m_len);
|
||||||
|
return *(m_str + pos);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr const_reference front() const noexcept {
|
||||||
|
AMS_ASSERT(m_len > 0);
|
||||||
|
return *m_str;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr const_reference back() const noexcept {
|
||||||
|
AMS_ASSERT(m_len > 0);
|
||||||
|
return *(m_str + m_len - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr const_pointer data() const noexcept { return m_str; }
|
||||||
|
|
||||||
|
constexpr void remove_prefix(size_type n) noexcept {
|
||||||
|
AMS_ASSERT(m_len >= n);
|
||||||
|
m_str += n;
|
||||||
|
m_len -= n;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr void remove_suffix(size_type n) noexcept {
|
||||||
|
AMS_ASSERT(m_len >= n);
|
||||||
|
m_len -= n;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr void swap(basic_string_view &rhs) noexcept {
|
||||||
|
auto tmp = *this;
|
||||||
|
*this = rhs;
|
||||||
|
rhs = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr size_type copy(_CharT *str, size_type n, size_type pos = 0) const noexcept {
|
||||||
|
AMS_ASSERT(pos <= this->size());
|
||||||
|
const size_type rlen = std::min(n, m_len - pos);
|
||||||
|
traits_type::copy(str, this->data() + pos, rlen);
|
||||||
|
return rlen;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr basic_string_view substr(size_type pos = 0, size_type n = npos) const noexcept {
|
||||||
|
AMS_ASSERT(pos <= this->size());
|
||||||
|
const size_type rlen = std::min(n, m_len - pos);
|
||||||
|
return basic_string_view{m_str + pos, rlen};
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr int compare(basic_string_view str) const noexcept {
|
||||||
|
const size_type rlen = std::min(m_len, str.m_len);
|
||||||
|
int ret = traits_type::compare(m_str, str.m_str, rlen);
|
||||||
|
if (ret == 0) {
|
||||||
|
ret = _s_compare(m_len, str.m_len);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr int compare(size_type pos, size_type n, basic_string_view str) const noexcept {
|
||||||
|
return this->substr(pos, n).compare(str);
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr int compare(size_type pos1, size_type n1, basic_string_view str, size_type pos2, size_type n2) const {
|
||||||
|
return this->substr(pos1, n1).compare(str.substr(pos2, n2));
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr int compare(const _CharT *str) const noexcept {
|
||||||
|
return this->compare(basic_string_view(str));
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr int compare(size_type pos, size_type n, const _CharT *str) const noexcept {
|
||||||
|
return this->substr(pos, n).compare(basic_string_view(str));
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr int compare(size_type pos, size_type n, const _CharT *str, size_type n2) const noexcept {
|
||||||
|
return this->substr(pos, n).compare(basic_string_view(str, n2));
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr bool starts_with(basic_string_view x) const noexcept { return this->substr(0, x.size()) == x; }
|
||||||
|
constexpr bool starts_with(_CharT x) const noexcept { return !this->empty() && traits_type::eq(this->front(), x); }
|
||||||
|
constexpr bool starts_with(const _CharT *x) const noexcept { return this->starts_with(basic_string_view(x)); }
|
||||||
|
|
||||||
|
constexpr bool ends_with(basic_string_view x) const noexcept { return this->size() >= x.size() && this->compare(this->size() - x.size(), npos, x) == 0; }
|
||||||
|
constexpr bool ends_with(_CharT x) const noexcept { return !this->empty() && traits_type::eq(this->back(), x); }
|
||||||
|
constexpr bool ends_with(const _CharT *x) const noexcept { return this->ends_with(basic_string_view(x)); }
|
||||||
|
|
||||||
|
constexpr size_type find(const _CharT *str, size_type pos, size_type n) const noexcept {
|
||||||
|
if (n == 0) {
|
||||||
|
return pos + m_len ? pos : npos;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (n <= m_len) {
|
||||||
|
for (/* ... */; pos <= m_len - n; ++pos) {
|
||||||
|
if (traits_type::eq(m_str[pos], str[0]) && traits_type::compare(m_str + pos + 1, str + 1, n - 1) == 0) {
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return npos;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr size_type find(_CharT c, size_type pos = 0) const noexcept {
|
||||||
|
size_type ret = npos;
|
||||||
|
if (pos < m_len) {
|
||||||
|
const size_type n = m_len - pos;
|
||||||
|
if (const _CharT *p = traits_type::find(m_str + pos, n, c); p) {
|
||||||
|
ret = p - m_str;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr size_type find(basic_string_view str, size_type pos = 0) const noexcept { return this->find(str.m_str, pos, str.m_len); }
|
||||||
|
|
||||||
|
__attribute__((nonnull(1)))
|
||||||
|
constexpr size_type find(const _CharT *str, size_type pos = 0) const noexcept { return this->find(str, pos, traits_type::length(str)); }
|
||||||
|
|
||||||
|
constexpr size_type rfind(const _CharT *str, size_type pos, size_type n) const noexcept {
|
||||||
|
if (n <= m_len) {
|
||||||
|
pos = std::min(size_type(m_len - n), pos);
|
||||||
|
do {
|
||||||
|
if (traits_type::compare(m_str + pos, str, n) == 0) {
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
} while (pos-- > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return npos;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr size_type rfind(_CharT c, size_type pos = 0) const noexcept {
|
||||||
|
size_type size = m_len;
|
||||||
|
if (size > 0) {
|
||||||
|
if (--size > pos) {
|
||||||
|
size = pos;
|
||||||
|
}
|
||||||
|
for (++size; size-- > 0; /* ... */) {
|
||||||
|
if (traits_type::eq(m_str[size], c)) {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return npos;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr size_type rfind(basic_string_view str, size_type pos = 0) const noexcept { return this->rfind(str.m_str, pos, str.m_len); }
|
||||||
|
|
||||||
|
__attribute__((nonnull(1)))
|
||||||
|
constexpr size_type rfind(const _CharT *str, size_type pos = 0) const noexcept { return this->rfind(str, pos, traits_type::length(str)); }
|
||||||
|
|
||||||
|
constexpr size_type find_first_of(const _CharT *str, size_type pos, size_t n) const noexcept {
|
||||||
|
for (/* ... */; n && pos < m_len; ++pos) {
|
||||||
|
if (const _CharT *p = traits_type::find(str, n, m_str[pos]); p) {
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return npos;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr size_type find_first_of(basic_string_view str, size_type pos = 0) const noexcept { return this->find_first_of(str.m_str, pos, str.m_len); }
|
||||||
|
constexpr size_type find_first_of(_CharT c, size_type pos = 0) const noexcept { return this->find(c, pos); }
|
||||||
|
|
||||||
|
__attribute__((nonnull(1)))
|
||||||
|
constexpr size_type find_first_of(const _CharT *str, size_type pos = 0) const noexcept { return this->find_first_of(str, pos, traits_type::length(str)); }
|
||||||
|
|
||||||
|
constexpr size_type find_last_of(const _CharT *str, size_type pos, size_t n) const noexcept {
|
||||||
|
size_type size = this->size();
|
||||||
|
if (size && n) {
|
||||||
|
if (--size > pos) {
|
||||||
|
size = pos;
|
||||||
|
}
|
||||||
|
do {
|
||||||
|
if (traits_type::find(str, n, m_str[size])) {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
} while (size-- != 0);
|
||||||
|
}
|
||||||
|
return npos;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr size_type find_last_of(basic_string_view str, size_type pos = 0) const noexcept { return this->find_last_of(str.m_str, pos, str.m_len); }
|
||||||
|
constexpr size_type find_last_of(_CharT c, size_type pos = 0) const noexcept { return this->rfind(c, pos); }
|
||||||
|
|
||||||
|
__attribute__((nonnull(1)))
|
||||||
|
constexpr size_type find_last_of(const _CharT *str, size_type pos = 0) const noexcept { return this->find_first_of(str, pos, traits_type::length(str)); }
|
||||||
|
|
||||||
|
constexpr size_type find_first_not_of(const _CharT *str, size_type pos, size_t n) const noexcept {
|
||||||
|
for (/* ... */; pos < m_len; ++pos) {
|
||||||
|
if (!traits_type::find(str, n, m_str[pos])) {
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return npos;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr size_type find_first_not_of(_CharT c, size_type pos = 0) const noexcept {
|
||||||
|
for (/* ... */; pos < m_len; ++pos) {
|
||||||
|
if (!traits_type::eq(m_str[pos], c)) {
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return npos;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr size_type find_first_not_of(basic_string_view str, size_type pos = 0) const noexcept { return this->find_first_not_of(str.m_str, pos, str.m_len); }
|
||||||
|
|
||||||
|
__attribute__((nonnull(1)))
|
||||||
|
constexpr size_type find_first_not_of(const _CharT *str, size_type pos = 0) const noexcept { return this->find_first_not_of(str, pos, traits_type::length(str)); }
|
||||||
|
|
||||||
|
constexpr size_type find_last_not_of(const _CharT *str, size_type pos, size_t n) const noexcept {
|
||||||
|
size_type size = this->size();
|
||||||
|
if (size) {
|
||||||
|
if (--size > pos) {
|
||||||
|
size = pos;
|
||||||
|
}
|
||||||
|
do {
|
||||||
|
if (!traits_type::find(str, n, m_str[size])) {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
} while (size-- != 0);
|
||||||
|
}
|
||||||
|
return npos;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr size_type find_last_not_of(_CharT c, size_type pos = 0) const noexcept {
|
||||||
|
size_type size = this->size();
|
||||||
|
if (size) {
|
||||||
|
if (--size > pos) {
|
||||||
|
size = pos;
|
||||||
|
}
|
||||||
|
do {
|
||||||
|
if (!traits_type::eq(m_str[size], c)) {
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
} while (size-- != 0);
|
||||||
|
}
|
||||||
|
return npos;
|
||||||
|
}
|
||||||
|
|
||||||
|
constexpr size_type find_last_not_of(basic_string_view str, size_type pos = 0) const noexcept { return this->find_last_not_of(str.m_str, pos, str.m_len); }
|
||||||
|
|
||||||
|
__attribute__((nonnull(1)))
|
||||||
|
constexpr size_type find_last_not_of(const _CharT *str, size_type pos = 0) const noexcept { return this->find_last_not_of(str, pos, traits_type::length(str)); }
|
||||||
|
|
||||||
|
constexpr friend bool operator==(const basic_string_view &lhs, const basic_string_view &rhs) noexcept { return lhs.compare(rhs) == 0; }
|
||||||
|
constexpr friend bool operator!=(const basic_string_view &lhs, const basic_string_view &rhs) noexcept { return lhs.compare(rhs) != 0; }
|
||||||
|
constexpr friend bool operator<=(const basic_string_view &lhs, const basic_string_view &rhs) noexcept { return lhs.compare(rhs) <= 0; }
|
||||||
|
constexpr friend bool operator>=(const basic_string_view &lhs, const basic_string_view &rhs) noexcept { return lhs.compare(rhs) >= 0; }
|
||||||
|
constexpr friend bool operator< (const basic_string_view &lhs, const basic_string_view &rhs) noexcept { return lhs.compare(rhs) < 0; }
|
||||||
|
constexpr friend bool operator> (const basic_string_view &lhs, const basic_string_view &rhs) noexcept { return lhs.compare(rhs) > 0; }
|
||||||
|
};
|
||||||
|
|
||||||
|
template<std::contiguous_iterator _It, std::sized_sentinel_for<_It> _End>
|
||||||
|
basic_string_view(_It, _End) -> basic_string_view<std::iter_value_t<_It>>;
|
||||||
|
|
||||||
|
using string_view = basic_string_view<char>;
|
||||||
|
|
||||||
|
}
|
|
@ -210,17 +210,17 @@ namespace ams::mitm::sysupdater {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PathView::HasPrefix(std::string_view prefix) const {
|
bool PathView::HasPrefix(util::string_view prefix) const {
|
||||||
return this->path.compare(0, prefix.length(), prefix) == 0;
|
return this->path.compare(0, prefix.length(), prefix) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PathView::HasSuffix(std::string_view suffix) const {
|
bool PathView::HasSuffix(util::string_view suffix) const {
|
||||||
return this->path.compare(this->path.length() - suffix.length(), suffix.length(), suffix) == 0;
|
return this->path.compare(this->path.length() - suffix.length(), suffix.length(), suffix) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string_view PathView::GetFileName() const {
|
util::string_view PathView::GetFileName() const {
|
||||||
auto pos = this->path.find_last_of("/");
|
auto pos = this->path.find_last_of("/");
|
||||||
return pos != std::string_view::npos ? this->path.substr(pos + 1) : this->path;
|
return pos != util::string_view::npos ? this->path.substr(pos + 1) : this->path;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result MountSdCardContentMeta(const char *mount_name, const char *path) {
|
Result MountSdCardContentMeta(const char *mount_name, const char *path) {
|
||||||
|
|
|
@ -20,12 +20,12 @@ namespace ams::mitm::sysupdater {
|
||||||
|
|
||||||
class PathView {
|
class PathView {
|
||||||
private:
|
private:
|
||||||
std::string_view path; /* Nintendo uses util::string_view here. */
|
util::string_view path; /* Nintendo uses util::string_view here. */
|
||||||
public:
|
public:
|
||||||
PathView(std::string_view p) : path(p) { /* ...*/ }
|
PathView(util::string_view p) : path(p) { /* ...*/ }
|
||||||
bool HasPrefix(std::string_view prefix) const;
|
bool HasPrefix(util::string_view prefix) const;
|
||||||
bool HasSuffix(std::string_view suffix) const;
|
bool HasSuffix(util::string_view suffix) const;
|
||||||
std::string_view GetFileName() const;
|
util::string_view GetFileName() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
Result MountSdCardContentMeta(const char *mount_name, const char *path);
|
Result MountSdCardContentMeta(const char *mount_name, const char *path);
|
||||||
|
|
|
@ -21,7 +21,7 @@ extern "C" {
|
||||||
u32 __nx_applet_type = AppletType_None;
|
u32 __nx_applet_type = AppletType_None;
|
||||||
u32 __nx_fs_num_sessions = 1;
|
u32 __nx_fs_num_sessions = 1;
|
||||||
|
|
||||||
#define INNER_HEAP_SIZE 0x4000
|
#define INNER_HEAP_SIZE 0x0
|
||||||
size_t nx_inner_heap_size = INNER_HEAP_SIZE;
|
size_t nx_inner_heap_size = INNER_HEAP_SIZE;
|
||||||
char nx_inner_heap[INNER_HEAP_SIZE];
|
char nx_inner_heap[INNER_HEAP_SIZE];
|
||||||
|
|
||||||
|
@ -33,6 +33,9 @@ extern "C" {
|
||||||
alignas(16) u8 __nx_exception_stack[ams::os::MemoryPageSize];
|
alignas(16) u8 __nx_exception_stack[ams::os::MemoryPageSize];
|
||||||
u64 __nx_exception_stack_size = sizeof(__nx_exception_stack);
|
u64 __nx_exception_stack_size = sizeof(__nx_exception_stack);
|
||||||
void __libnx_exception_handler(ThreadExceptionDump *ctx);
|
void __libnx_exception_handler(ThreadExceptionDump *ctx);
|
||||||
|
|
||||||
|
void *__libnx_thread_alloc(size_t size);
|
||||||
|
void __libnx_thread_free(void *mem);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace ams {
|
namespace ams {
|
||||||
|
@ -57,41 +60,52 @@ namespace ams::pgl {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
/* pgl. */
|
|
||||||
constexpr size_t NumServers = 1;
|
|
||||||
ams::sf::hipc::ServerManager<NumServers> g_server_manager;
|
|
||||||
|
|
||||||
constexpr sm::ServiceName ShellServiceName = sm::ServiceName::Encode("pgl");
|
|
||||||
constexpr size_t ShellMaxSessions = 8; /* Official maximum is 8. */
|
|
||||||
|
|
||||||
constinit pgl::srv::ShellInterface g_shell_interface;
|
|
||||||
|
|
||||||
void RegisterServiceSession() {
|
|
||||||
R_ABORT_UNLESS((g_server_manager.RegisterServer<pgl::sf::IShellInterface, pgl::srv::ShellInterface>(ShellServiceName, ShellMaxSessions, ams::sf::GetSharedPointerTo<pgl::sf::IShellInterface>(g_shell_interface))));
|
|
||||||
}
|
|
||||||
|
|
||||||
void LoopProcess() {
|
|
||||||
g_server_manager.LoopProcess();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* NOTE: Nintendo reserves only 0x2000 bytes for this heap, which is used "mostly" to allocate shell event observers. */
|
/* NOTE: Nintendo reserves only 0x2000 bytes for this heap, which is used "mostly" to allocate shell event observers. */
|
||||||
/* However, we would like very much for homebrew sysmodules to be able to subscribe to events if they so choose */
|
/* However, we would like very much for homebrew sysmodules to be able to subscribe to events if they so choose */
|
||||||
/* And so we will use a larger heap (32 KB). */
|
/* And so we will use a larger heap (32 KB). */
|
||||||
/* We should have a smaller memory footprint than N in the end, regardless. */
|
/* We should have a smaller memory footprint than N in the end, regardless. */
|
||||||
u8 g_heap_memory[32_KB];
|
constinit u8 g_heap_memory[32_KB];
|
||||||
TYPED_STORAGE(ams::sf::ExpHeapMemoryResource) g_heap_memory_resource;
|
lmem::HeapHandle g_server_heap_handle;
|
||||||
|
constinit ams::sf::ExpHeapAllocator g_server_allocator;
|
||||||
|
|
||||||
void *Allocate(size_t size) {
|
void *Allocate(size_t size) {
|
||||||
return lmem::AllocateFromExpHeap(GetReference(g_heap_memory_resource).GetHandle(), size);
|
return lmem::AllocateFromExpHeap(g_server_heap_handle, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Deallocate(void *p, size_t size) {
|
void Deallocate(void *p, size_t size) {
|
||||||
return lmem::FreeToExpHeap(GetReference(g_heap_memory_resource).GetHandle(), p);
|
return lmem::FreeToExpHeap(g_server_heap_handle, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InitializeHeap() {
|
void InitializeHeap() {
|
||||||
auto heap_handle = lmem::CreateExpHeap(g_heap_memory, sizeof(g_heap_memory), lmem::CreateOption_ThreadSafe);
|
g_server_heap_handle = lmem::CreateExpHeap(g_heap_memory, sizeof(g_heap_memory), lmem::CreateOption_ThreadSafe);
|
||||||
new (GetPointer(g_heap_memory_resource)) ams::sf::ExpHeapMemoryResource(heap_handle);
|
g_server_allocator.Attach(g_server_heap_handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
/* pgl. */
|
||||||
|
enum PortIndex {
|
||||||
|
PortIndex_Shell,
|
||||||
|
PortIndex_Count,
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr sm::ServiceName ShellServiceName = sm::ServiceName::Encode("pgl");
|
||||||
|
constexpr size_t ShellMaxSessions = 8; /* Official maximum is 8. */
|
||||||
|
|
||||||
|
using ServerManager = ams::sf::hipc::ServerManager<PortIndex_Count>;
|
||||||
|
|
||||||
|
ServerManager g_server_manager;
|
||||||
|
|
||||||
|
constinit ams::sf::UnmanagedServiceObject<pgl::sf::IShellInterface, pgl::srv::ShellInterface> g_shell_interface(std::addressof(g_server_allocator));
|
||||||
|
|
||||||
|
void RegisterServiceSession() {
|
||||||
|
R_ABORT_UNLESS(g_server_manager.RegisterObjectForServer(g_shell_interface.GetShared(), ShellServiceName, ShellMaxSessions));
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoopProcess() {
|
||||||
|
g_server_manager.LoopProcess();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -138,6 +152,33 @@ void __appExit(void) {
|
||||||
setExit();
|
setExit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace ams {
|
||||||
|
|
||||||
|
void *Malloc(size_t size) {
|
||||||
|
AMS_ABORT("ams::Malloc was called");
|
||||||
|
}
|
||||||
|
|
||||||
|
void Free(void *ptr) {
|
||||||
|
AMS_ABORT("ams::Free was called");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void *operator new(size_t size) {
|
||||||
|
return pgl::Allocate(size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void operator delete(void *p) {
|
||||||
|
return pgl::Deallocate(p, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void *__libnx_thread_alloc(size_t size) {
|
||||||
|
AMS_ABORT("__libnx_thread_alloc was called");
|
||||||
|
}
|
||||||
|
|
||||||
|
void __libnx_thread_free(void *mem) {
|
||||||
|
AMS_ABORT("__libnx_thread_free was called");
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
@ -152,7 +193,7 @@ int main(int argc, char **argv)
|
||||||
pgl::RegisterServiceSession();
|
pgl::RegisterServiceSession();
|
||||||
|
|
||||||
/* Initialize the server library. */
|
/* Initialize the server library. */
|
||||||
pgl::srv::Initialize(std::addressof(pgl::g_shell_interface), GetPointer(pgl::g_heap_memory_resource));
|
pgl::srv::Initialize();
|
||||||
|
|
||||||
/* Loop forever, servicing our services. */
|
/* Loop forever, servicing our services. */
|
||||||
pgl::LoopProcess();
|
pgl::LoopProcess();
|
||||||
|
|
Loading…
Reference in a new issue