mirror of
https://github.com/bsnes-emu/bsnes.git
synced 2025-09-03 07:43:06 +02:00
v108.9
* multi-monitor support * improved pause/frame advance support * added option to disable video dimming when idle
This commit is contained in:
@@ -1,142 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <nall/primitives.hpp>
|
||||
|
||||
namespace nall {
|
||||
|
||||
template<typename Type, uint Bit> struct BooleanBitField {
|
||||
enum : uint { bit = Bit };
|
||||
enum : uint { mask = 1ull << bit };
|
||||
using type = Type;
|
||||
using utype = typename std::make_unsigned<type>::type;
|
||||
static_assert(bit < sizeof(type) * 8, "");
|
||||
|
||||
inline BooleanBitField() = default;
|
||||
inline BooleanBitField(const BooleanBitField& value) { set(value.get()); }
|
||||
template<typename T> inline BooleanBitField(const bool value) { set(value); }
|
||||
|
||||
inline operator bool() const { return get(); }
|
||||
|
||||
inline auto& operator=(const BooleanBitField& value) { return set(value.get()); }
|
||||
inline auto& operator=(const bool value) { return set(value); }
|
||||
|
||||
inline auto& operator&=(const bool value) { return set(get() & value); }
|
||||
inline auto& operator|=(const bool value) { return set(get() | value); }
|
||||
inline auto& operator^=(const bool value) { return set(get() ^ value); }
|
||||
|
||||
inline auto raise() { return get() == 0 ? set(1), true : false; }
|
||||
inline auto lower() { return get() == 1 ? set(0), true : false; }
|
||||
inline auto& invert() { return set(get() ^ 1); }
|
||||
|
||||
private:
|
||||
utype data;
|
||||
|
||||
inline auto get() const -> bool {
|
||||
return data & mask;
|
||||
}
|
||||
|
||||
inline auto set(bool value) -> BooleanBitField& {
|
||||
return data = (data & ~mask) | (value << bit), *this;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Type, uint Lo, uint Hi> struct NaturalBitField {
|
||||
enum : uint { lo = Lo <= Hi ? Lo : Hi };
|
||||
enum : uint { hi = Hi >= Lo ? Hi : Lo };
|
||||
enum : uint { bits = hi - lo + 1 };
|
||||
enum : uint { mask = (~0ull >> (64 - bits)) << lo };
|
||||
using type = Type;
|
||||
using utype = typename std::make_unsigned<type>::type;
|
||||
static_assert(hi < sizeof(type) * 8, "");
|
||||
|
||||
inline NaturalBitField() = default;
|
||||
inline NaturalBitField(const NaturalBitField& value) { set(value.data); }
|
||||
template<typename T> inline NaturalBitField(const T& value) { set(value << lo); }
|
||||
|
||||
inline explicit operator bool() const { return data & mask; }
|
||||
inline operator utype() const { return get(); }
|
||||
|
||||
inline auto& operator=(const NaturalBitField& value) { return set(value.data); }
|
||||
template<typename T> inline auto& operator=(T value) { return set(value << lo); }
|
||||
|
||||
inline auto operator++(int) { utype value = get(); set(data + (1 << lo)); return value; }
|
||||
inline auto operator--(int) { utype value = get(); set(data - (1 << lo)); return value; }
|
||||
|
||||
inline auto& operator++() { return set(data + (1 << lo)); }
|
||||
inline auto& operator--() { return set(data - (1 << lo)); }
|
||||
|
||||
inline auto& operator &=(const utype value) { return set(data & (value << lo)); }
|
||||
inline auto& operator |=(const utype value) { return set(data | (value << lo)); }
|
||||
inline auto& operator ^=(const utype value) { return set(data ^ (value << lo)); }
|
||||
inline auto& operator<<=(const utype value) { return set((data & mask) << value); }
|
||||
inline auto& operator>>=(const utype value) { return set((data & mask) >> value); }
|
||||
inline auto& operator +=(const utype value) { return set(data + (value << lo)); }
|
||||
inline auto& operator -=(const utype value) { return set(data - (value << lo)); }
|
||||
inline auto& operator *=(const utype value) { return set((get() * value) << lo); }
|
||||
inline auto& operator /=(const utype value) { return set((get() / value) << lo); }
|
||||
inline auto& operator %=(const utype value) { return set((get() % value) << lo); }
|
||||
|
||||
private:
|
||||
utype data;
|
||||
|
||||
inline auto get() const -> utype {
|
||||
return (data & mask) >> lo;
|
||||
}
|
||||
|
||||
inline auto set(utype value) -> NaturalBitField& {
|
||||
return data = (data & ~mask) | (value & mask), *this;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Type, uint Lo, uint Hi> struct IntegerBitField {
|
||||
enum : uint { lo = Lo <= Hi ? Lo : Hi };
|
||||
enum : uint { hi = Hi >= Lo ? Hi : Lo };
|
||||
enum : uint { bits = hi - lo + 1 };
|
||||
enum : uint { mask = (~0ull >> (64 - bits)) << lo };
|
||||
using type = Type;
|
||||
using stype = typename std::make_signed<type>::type;
|
||||
using utype = typename std::make_unsigned<type>::type;
|
||||
static_assert(hi < sizeof(type) * 8, "");
|
||||
|
||||
inline IntegerBitField() = default;
|
||||
inline IntegerBitField(const IntegerBitField& value) { set(value.get()); }
|
||||
template<typename T> inline IntegerBitField(const T& value) { set(value); }
|
||||
|
||||
inline explicit operator bool() const { return data & mask; }
|
||||
inline operator stype() const { return get(); }
|
||||
|
||||
inline auto& operator=(const IntegerBitField& value) { return set(value.get()); }
|
||||
template<typename T> inline auto& operator=(const T& value) { return set(value); }
|
||||
|
||||
inline auto operator++(int) { stype value = get(); set(value + 1); return value; }
|
||||
inline auto operator--(int) { stype value = get(); set(value - 1); return value; }
|
||||
|
||||
inline auto& operator++() { return set(get() + 1); }
|
||||
inline auto& operator--() { return set(get() - 1); }
|
||||
|
||||
inline auto& operator &=(const stype value) { return set(get() & value); }
|
||||
inline auto& operator |=(const stype value) { return set(get() | value); }
|
||||
inline auto& operator ^=(const stype value) { return set(get() ^ value); }
|
||||
inline auto& operator<<=(const stype value) { return set(get() << value); }
|
||||
inline auto& operator>>=(const stype value) { return set(get() >> value); }
|
||||
inline auto& operator +=(const stype value) { return set(get() + value); }
|
||||
inline auto& operator -=(const stype value) { return set(get() - value); }
|
||||
inline auto& operator *=(const stype value) { return set(get() * value); }
|
||||
inline auto& operator /=(const stype value) { return set(get() / value); }
|
||||
inline auto& operator %=(const stype value) { return set(get() % value); }
|
||||
|
||||
private:
|
||||
utype data;
|
||||
|
||||
inline auto get() const -> stype {
|
||||
enum : utype { b = 1ull << (bits - 1) };
|
||||
enum : utype { m = b * 2 - 1 };
|
||||
return ((((data & mask) >> lo) & m) ^ b) - b;
|
||||
}
|
||||
|
||||
inline auto set(utype value) -> IntegerBitField& {
|
||||
return data = (data & ~mask) | ((value << lo) & mask), *this;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
@@ -1,119 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <nall/memory.hpp>
|
||||
|
||||
namespace nall {
|
||||
|
||||
struct bitvector {
|
||||
bitvector() = default;
|
||||
bitvector(uint size) { resize(size); }
|
||||
bitvector(const bitvector& source) { operator=(source); }
|
||||
bitvector(bitvector&& source) { operator=(move(source)); }
|
||||
~bitvector() { reset(); }
|
||||
|
||||
auto operator=(const bitvector& source) -> bitvector& {
|
||||
bits = source.bits;
|
||||
pool = memory::resize<uint8_t>(pool, bytes());
|
||||
memory::copy(pool, source.pool, bytes());
|
||||
return *this;
|
||||
}
|
||||
|
||||
auto operator=(bitvector&& source) -> bitvector& {
|
||||
pool = source.pool;
|
||||
bits = source.bits;
|
||||
source.pool = nullptr;
|
||||
source.bits = 0;
|
||||
return *this;
|
||||
}
|
||||
|
||||
explicit operator bool() const { return bits > 0; }
|
||||
auto size() const -> uint { return bits; }
|
||||
auto bytes() const -> uint { return (bits + 7) / 8; }
|
||||
auto data() -> uint8_t* { return pool; }
|
||||
auto data() const -> const uint8_t* { return pool; }
|
||||
|
||||
auto reset() -> void {
|
||||
if(pool) free(pool);
|
||||
pool = nullptr;
|
||||
bits = 0;
|
||||
}
|
||||
|
||||
auto resize(uint size) -> void {
|
||||
uint from = bits;
|
||||
bits = size;
|
||||
for(uint n = size; n < from; n++) clear(n); //on reduce
|
||||
pool = memory::resize<uint8_t>(pool, bytes());
|
||||
for(uint n = from; n < size; n++) clear(n); //on expand
|
||||
}
|
||||
|
||||
auto get(uint position) const -> bool {
|
||||
#ifdef DEBUG
|
||||
struct out_of_bounds {};
|
||||
if(position >= bits) throw out_of_bounds{};
|
||||
#endif
|
||||
return pool[position >> 3] & (0x80 >> (position & 7));
|
||||
}
|
||||
|
||||
auto clear() -> void {
|
||||
memory::fill<uint8_t>(pool, bytes(), 0x00);
|
||||
}
|
||||
|
||||
auto set() -> void {
|
||||
memory::fill<uint8_t>(pool, bytes(), 0xff);
|
||||
for(uint n = bits; n < bytes() * 8; n++) clear(n);
|
||||
}
|
||||
|
||||
auto clear(uint position) -> void {
|
||||
pool[position >> 3] &= ~(0x80 >> (position & 7));
|
||||
}
|
||||
|
||||
auto set(uint position) -> void {
|
||||
pool[position >> 3] |= (0x80 >> (position & 7));
|
||||
}
|
||||
|
||||
auto invert(uint position) -> void {
|
||||
get(position) ? clear(position) : set(position);
|
||||
}
|
||||
|
||||
auto set(uint position, bool value) -> void {
|
||||
value ? set(position) : clear(position);
|
||||
}
|
||||
|
||||
struct reference {
|
||||
reference(bitvector& self, uint position) : self(self), position(position) {}
|
||||
operator bool() const { return self.get(position); }
|
||||
auto operator=(bool value) -> reference& { self.set(position, value); return *this; }
|
||||
|
||||
protected:
|
||||
bitvector& self;
|
||||
uint position;
|
||||
};
|
||||
|
||||
auto operator[](uint position) -> reference {
|
||||
return reference(*this, position);
|
||||
}
|
||||
|
||||
auto operator[](uint position) const -> bool {
|
||||
return get(position);
|
||||
}
|
||||
|
||||
struct iterator {
|
||||
iterator(bitvector& self, uint position) : self(self), position(position) {}
|
||||
auto operator!=(const iterator& source) const -> bool { return position != source.position; }
|
||||
auto operator++() -> iterator& { position++; return *this; }
|
||||
auto operator*() -> reference { return self.operator[](position); }
|
||||
|
||||
protected:
|
||||
bitvector& self;
|
||||
uint position;
|
||||
};
|
||||
|
||||
auto begin() -> iterator { return iterator(*this, 0); }
|
||||
auto end() -> iterator { return iterator(*this, bits); }
|
||||
|
||||
protected:
|
||||
uint8_t* pool = nullptr;
|
||||
uint bits = 0;
|
||||
};
|
||||
|
||||
}
|
@@ -77,16 +77,16 @@ struct directory : inode {
|
||||
function<void (const string&, const string&, const string&)>
|
||||
recurse = [&](const string& basename, const string& pathname, const string& pattern) {
|
||||
for(auto& folder : directory::ufolders(pathname)) {
|
||||
contents.append(string{pathname, folder}.trimLeft(basename, 1L));
|
||||
recurse(basename, {pathname, folder}, pattern);
|
||||
contents.append(string{pathname, folder, "/"}.trimLeft(basename, 1L));
|
||||
recurse(basename, {pathname, folder, "/"}, pattern);
|
||||
}
|
||||
for(auto& file : directory::ufiles(pathname, pattern)) {
|
||||
contents.append(string{pathname, file}.trimLeft(basename, 1L));
|
||||
}
|
||||
};
|
||||
for(auto& folder : directory::ufolders(pathname)) {
|
||||
contents.append(folder);
|
||||
recurse(pathname, {pathname, folder}, pattern);
|
||||
contents.append({folder, "/"});
|
||||
recurse(pathname, {pathname, folder, "/"}, pattern);
|
||||
}
|
||||
for(auto& file : directory::ufiles(pathname, pattern)) {
|
||||
contents.append(file);
|
||||
@@ -100,16 +100,16 @@ struct directory : inode {
|
||||
function<void (const string&, const string&, const string&)>
|
||||
recurse = [&](const string& basename, const string& pathname, const string& pattern) {
|
||||
for(auto& folder : directory::ufolders(pathname)) {
|
||||
contents.append(string{pathname, folder}.trimLeft(basename, 1L));
|
||||
recurse(basename, {pathname, folder}, pattern);
|
||||
contents.append(string{pathname, folder, "/"}.trimLeft(basename, 1L));
|
||||
recurse(basename, {pathname, folder, "/"}, pattern);
|
||||
}
|
||||
for(auto& file : directory::ufiles(pathname, pattern)) {
|
||||
contents.append(string{pathname, file}.trimLeft(basename, 1L));
|
||||
}
|
||||
};
|
||||
for(auto& folder : directory::ufolders(pathname)) {
|
||||
contents.append(folder);
|
||||
recurse(pathname, {pathname, folder}, pattern);
|
||||
contents.append({folder, "/"});
|
||||
recurse(pathname, {pathname, folder, "/"}, pattern);
|
||||
}
|
||||
for(auto& file : directory::ufiles(pathname, pattern)) {
|
||||
contents.append(file);
|
||||
|
@@ -180,6 +180,7 @@ auto Response::findContentType(const string& s) const -> string {
|
||||
if(s == ".gz" ) return "application/gzip";
|
||||
if(s == ".htm" ) return "text/html; charset=utf-8";
|
||||
if(s == ".html") return "text/html; charset=utf-8";
|
||||
if(s == ".ico" ) return "image/x-icon";
|
||||
if(s == ".jpg" ) return "image/jpeg";
|
||||
if(s == ".jpeg") return "image/jpeg";
|
||||
if(s == ".js" ) return "application/javascript";
|
||||
|
@@ -10,13 +10,13 @@ namespace nall::HTTP {
|
||||
|
||||
struct Role {
|
||||
struct Settings {
|
||||
int connectionLimit = 1 * 1024; //server
|
||||
int headSizeLimit = 16 * 1024; //client, server
|
||||
int bodySizeLimit = 8192 * 1024; //client, server
|
||||
int chunkSize = 32 * 1024; //client, server
|
||||
int threadStackSize = 128 * 1024; //server
|
||||
int timeoutReceive = 15 * 1000; //server
|
||||
int timeoutSend = 15 * 1000; //server
|
||||
int connectionLimit = 1 * 1024; //server
|
||||
int headSizeLimit = 16 * 1024; //client, server
|
||||
int bodySizeLimit = 65536 * 1024; //client, server
|
||||
int chunkSize = 32 * 1024; //client, server
|
||||
int threadStackSize = 128 * 1024; //server
|
||||
int timeoutReceive = 15 * 1000; //server
|
||||
int timeoutSend = 15 * 1000; //server
|
||||
} settings;
|
||||
|
||||
inline auto configure(const string& parameters) -> bool;
|
||||
|
@@ -29,6 +29,7 @@ namespace nall {
|
||||
constexpr auto compiler() -> Compiler { return Compiler::Clang; }
|
||||
|
||||
#pragma clang diagnostic warning "-Wreturn-type"
|
||||
#pragma clang diagnostic ignored "-Wunused-result"
|
||||
#pragma clang diagnostic ignored "-Wunknown-pragmas"
|
||||
#pragma clang diagnostic ignored "-Wempty-body"
|
||||
#pragma clang diagnostic ignored "-Wparentheses"
|
||||
@@ -36,20 +37,20 @@ namespace nall {
|
||||
#pragma clang diagnostic ignored "-Wswitch-bool"
|
||||
#pragma clang diagnostic ignored "-Wtautological-compare"
|
||||
#pragma clang diagnostic ignored "-Wabsolute-value"
|
||||
#pragma clang diagnostic ignored "-Wunused-result"
|
||||
#pragma clang diagnostic ignored "-Wshift-count-overflow"
|
||||
|
||||
//temporary
|
||||
#pragma clang diagnostic ignored "-Winconsistent-missing-override"
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
//#pragma clang diagnostic error "-Wdeprecated-declarations"
|
||||
#elif defined(__GNUC__)
|
||||
#define COMPILER_GCC
|
||||
constexpr auto compiler() -> Compiler { return Compiler::GCC; }
|
||||
|
||||
#pragma GCC diagnostic warning "-Wreturn-type"
|
||||
#pragma GCC diagnostic ignored "-Wunused-result"
|
||||
#pragma GCC diagnostic ignored "-Wunknown-pragmas"
|
||||
#pragma GCC diagnostic ignored "-Wpragmas"
|
||||
#pragma GCC diagnostic ignored "-Wswitch-bool"
|
||||
#pragma GCC diagnostic ignored "-Wunused-result"
|
||||
#elif defined(_MSC_VER)
|
||||
#define COMPILER_MICROSOFT
|
||||
constexpr auto compiler() -> Compiler { return Compiler::Microsoft; }
|
||||
|
@@ -22,8 +22,6 @@
|
||||
#include <nall/array-view.hpp>
|
||||
#include <nall/atoi.hpp>
|
||||
#include <nall/bit.hpp>
|
||||
#include <nall/bit-field.hpp>
|
||||
#include <nall/bit-vector.hpp>
|
||||
#include <nall/chrono.hpp>
|
||||
#include <nall/directory.hpp>
|
||||
#include <nall/dl.hpp>
|
||||
|
@@ -103,13 +103,13 @@ namespace Math {
|
||||
#endif
|
||||
|
||||
#if defined(COMPILER_CLANG) || defined(COMPILER_GCC)
|
||||
#define neverinline __attribute__((noinline))
|
||||
#define noinline __attribute__((noinline))
|
||||
#define alwaysinline inline __attribute__((always_inline))
|
||||
#elif defined(COMPILER_MICROSOFT)
|
||||
#define neverinline __declspec(noinline)
|
||||
#define noinline __declspec(noinline)
|
||||
#define alwaysinline inline __forceinline
|
||||
#else
|
||||
#define neverinline
|
||||
#define noinline
|
||||
#define alwaysinline inline
|
||||
#endif
|
||||
|
||||
|
@@ -11,6 +11,7 @@ namespace nall {
|
||||
template<uint Precision = 64> struct Real;
|
||||
}
|
||||
|
||||
#include <nall/primitives/bit-field.hpp>
|
||||
#include <nall/primitives/bit-range.hpp>
|
||||
#include <nall/primitives/boolean.hpp>
|
||||
#include <nall/primitives/natural.hpp>
|
||||
|
124
nall/primitives/bit-field.hpp
Normal file
124
nall/primitives/bit-field.hpp
Normal file
@@ -0,0 +1,124 @@
|
||||
#pragma once
|
||||
|
||||
namespace nall {
|
||||
|
||||
template<int...> struct BitField;
|
||||
|
||||
/* static BitField */
|
||||
|
||||
template<int Precision, int Index> struct BitField<Precision, Index> {
|
||||
static_assert(Precision >= 1 && Precision <= 64);
|
||||
enum : uint { bits = Precision };
|
||||
using type =
|
||||
conditional_t<bits <= 8, uint8_t,
|
||||
conditional_t<bits <= 16, uint16_t,
|
||||
conditional_t<bits <= 32, uint32_t,
|
||||
conditional_t<bits <= 64, uint64_t,
|
||||
void>>>>;
|
||||
enum : uint { shift = Index < 0 ? Precision + Index : Index };
|
||||
enum : type { mask = 1ull << shift };
|
||||
|
||||
BitField(const BitField&) = delete;
|
||||
|
||||
inline auto& operator=(const BitField& source) {
|
||||
target = target & ~mask | (bool)source << shift;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T> inline BitField(T* source) : target((type&)*source) {
|
||||
static_assert(sizeof(T) == sizeof(type));
|
||||
}
|
||||
|
||||
inline auto bit() const {
|
||||
return shift;
|
||||
}
|
||||
|
||||
inline operator bool() const {
|
||||
return target & mask;
|
||||
}
|
||||
|
||||
inline auto& operator=(bool source) {
|
||||
target = target & ~mask | source << shift;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline auto& operator&=(bool source) {
|
||||
target = target & (~mask | source << shift);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline auto& operator^=(bool source) {
|
||||
target = target ^ source << shift;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline auto& operator|=(bool source) {
|
||||
target = target | source << shift;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
type& target;
|
||||
};
|
||||
|
||||
/* dynamic BitField */
|
||||
|
||||
template<int Precision> struct BitField<Precision> {
|
||||
static_assert(Precision >= 1 && Precision <= 64);
|
||||
enum : uint { bits = Precision };
|
||||
using type =
|
||||
conditional_t<bits <= 8, uint8_t,
|
||||
conditional_t<bits <= 16, uint16_t,
|
||||
conditional_t<bits <= 32, uint32_t,
|
||||
conditional_t<bits <= 64, uint64_t,
|
||||
void>>>>;
|
||||
|
||||
BitField(const BitField&) = delete;
|
||||
|
||||
inline auto& operator=(const BitField& source) {
|
||||
target = target & ~mask | (bool)source << shift;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T> inline BitField(T* source, int index) : target((type&)*source) {
|
||||
static_assert(sizeof(T) == sizeof(type));
|
||||
if(index < 0) index = Precision + index;
|
||||
mask = 1ull << index;
|
||||
shift = index;
|
||||
}
|
||||
|
||||
inline auto bit() const {
|
||||
return shift;
|
||||
}
|
||||
|
||||
inline operator bool() const {
|
||||
return target & mask;
|
||||
}
|
||||
|
||||
inline auto& operator=(bool source) {
|
||||
target = target & ~mask | source << shift;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline auto& operator&=(bool source) {
|
||||
target = target & (~mask | source << shift);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline auto& operator^=(bool source) {
|
||||
target = target ^ source << shift;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline auto& operator|=(bool source) {
|
||||
target = target | source << shift;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
type& target;
|
||||
type mask;
|
||||
uint shift;
|
||||
};
|
||||
|
||||
}
|
@@ -2,66 +2,254 @@
|
||||
|
||||
namespace nall {
|
||||
|
||||
//warning: so that BitRange can modify the underlying number directly, it must bind a reference.
|
||||
//as a result, auto value = number.bits() will capture by-reference, rather than by-value.
|
||||
template<int...> struct BitRange;
|
||||
|
||||
template<int Precision> struct BitRange {
|
||||
/* static BitRange */
|
||||
|
||||
template<int Precision, int Lo, int Hi> struct BitRange<Precision, Lo, Hi> {
|
||||
static_assert(Precision >= 1 && Precision <= 64);
|
||||
static inline constexpr auto bits() -> uint { return Precision; }
|
||||
using utype =
|
||||
conditional_t<bits() <= 8, uint8_t,
|
||||
conditional_t<bits() <= 16, uint16_t,
|
||||
conditional_t<bits() <= 32, uint32_t,
|
||||
conditional_t<bits() <= 64, uint64_t,
|
||||
enum : uint { bits = Precision };
|
||||
using type =
|
||||
conditional_t<bits <= 8, uint8_t,
|
||||
conditional_t<bits <= 16, uint16_t,
|
||||
conditional_t<bits <= 32, uint32_t,
|
||||
conditional_t<bits <= 64, uint64_t,
|
||||
void>>>>;
|
||||
static inline constexpr auto mask() -> utype { return ~0ull >> 64 - bits(); }
|
||||
enum : uint { lo = Lo < 0 ? Precision + Lo : Lo };
|
||||
enum : uint { hi = Hi < 0 ? Precision + Hi : Hi };
|
||||
enum : type { mask = ~0ull >> 64 - (hi - lo + 1) << lo };
|
||||
enum : uint { shift = lo };
|
||||
|
||||
inline BitRange(utype& source, int lo, int hi) : source(source) {
|
||||
if(lo < 0) lo = Precision + lo;
|
||||
if(hi < 0) hi = Precision + hi;
|
||||
if(lo > hi) swap(lo, hi);
|
||||
this->lo = lo;
|
||||
this->hi = hi;
|
||||
}
|
||||
inline auto& operator=(BitRange& source) { return set(source.get()); }
|
||||
BitRange(const BitRange& source) = delete;
|
||||
|
||||
inline operator utype() const { return get(); }
|
||||
|
||||
inline auto operator++(int) { auto value = get(); set(value + 1); return value; }
|
||||
inline auto operator--(int) { auto value = get(); set(value - 1); return value; }
|
||||
|
||||
inline auto& operator++() { return set(get() + 1); }
|
||||
inline auto& operator--() { return set(get() - 1); }
|
||||
|
||||
template<typename T> inline auto& operator =(const T& value) { return set( value); }
|
||||
template<typename T> inline auto& operator *=(const T& value) { return set(get() * value); }
|
||||
template<typename T> inline auto& operator /=(const T& value) { return set(get() / value); }
|
||||
template<typename T> inline auto& operator %=(const T& value) { return set(get() % value); }
|
||||
template<typename T> inline auto& operator +=(const T& value) { return set(get() + value); }
|
||||
template<typename T> inline auto& operator -=(const T& value) { return set(get() - value); }
|
||||
template<typename T> inline auto& operator<<=(const T& value) { return set(get() << value); }
|
||||
template<typename T> inline auto& operator>>=(const T& value) { return set(get() >> value); }
|
||||
template<typename T> inline auto& operator &=(const T& value) { return set(get() & value); }
|
||||
template<typename T> inline auto& operator ^=(const T& value) { return set(get() ^ value); }
|
||||
template<typename T> inline auto& operator |=(const T& value) { return set(get() | value); }
|
||||
|
||||
private:
|
||||
inline auto get() const -> utype {
|
||||
const utype rangeBits = hi - lo + 1;
|
||||
const utype rangeMask = (1ull << rangeBits) - 1 << lo & mask();
|
||||
return (source & rangeMask) >> lo;
|
||||
}
|
||||
|
||||
inline auto& set(const utype& value) {
|
||||
const utype rangeBits = hi - lo + 1;
|
||||
const utype rangeMask = (1ull << rangeBits) - 1 << lo & mask();
|
||||
source = source & ~rangeMask | value << lo & rangeMask;
|
||||
inline auto& operator=(const BitRange& source) {
|
||||
target = target & ~mask | ((source.target & source.mask) >> source.shift) << shift & mask;
|
||||
return *this;
|
||||
}
|
||||
|
||||
utype& source;
|
||||
uint lo;
|
||||
uint hi;
|
||||
template<typename T> inline BitRange(T* source) : target((type&)*source) {
|
||||
static_assert(sizeof(T) == sizeof(type));
|
||||
}
|
||||
|
||||
inline operator type() const {
|
||||
return (target & mask) >> shift;
|
||||
}
|
||||
|
||||
inline auto operator++(int) {
|
||||
auto value = (target & mask) >> shift;
|
||||
target = target & ~mask | target + (1 << shift) & mask;
|
||||
return value;
|
||||
}
|
||||
|
||||
inline auto operator--(int) {
|
||||
auto value = (target & mask) >> shift;
|
||||
target = target & ~mask | target - (1 << shift) & mask;
|
||||
return value;
|
||||
}
|
||||
|
||||
inline auto& operator++() {
|
||||
target = target & ~mask | target + (1 << shift) & mask;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline auto& operator--() {
|
||||
target = target & ~mask | target - (1 << shift) & mask;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T> inline auto& operator=(const T& source) {
|
||||
target = target & ~mask | source << shift & mask;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T> inline auto& operator*=(const T& source) {
|
||||
auto value = ((target & mask) >> shift) * source;
|
||||
target = target & ~mask | value << shift & mask;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T> inline auto& operator/=(const T& source) {
|
||||
auto value = ((target & mask) >> shift) / source;
|
||||
target = target & ~mask | value << shift & mask;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T> inline auto& operator%=(const T& source) {
|
||||
auto value = ((target & mask) >> shift) % source;
|
||||
target = target & ~mask | value << shift & mask;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T> inline auto& operator+=(const T& source) {
|
||||
auto value = ((target & mask) >> shift) + source;
|
||||
target = target & ~mask | value << shift & mask;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T> inline auto& operator-=(const T& source) {
|
||||
auto value = ((target & mask) >> shift) - source;
|
||||
target = target & ~mask | value << shift & mask;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T> inline auto& operator<<=(const T& source) {
|
||||
auto value = ((target & mask) >> shift) << source;
|
||||
target = target & ~mask | value << shift & mask;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T> inline auto& operator>>=(const T& source) {
|
||||
auto value = ((target & mask) >> shift) >> source;
|
||||
target = target & ~mask | value << shift & mask;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T> inline auto& operator&=(const T& source) {
|
||||
target = target & (~mask | source << shift & mask);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T> inline auto& operator^=(const T& source) {
|
||||
target = target ^ source << shift & mask;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T> inline auto& operator|=(const T& source) {
|
||||
target = target | source << shift & mask;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
type& target;
|
||||
};
|
||||
|
||||
/* dynamic BitRange */
|
||||
|
||||
template<int Precision> struct BitRange<Precision> {
|
||||
static_assert(Precision >= 1 && Precision <= 64);
|
||||
enum : uint { bits = Precision };
|
||||
using type =
|
||||
conditional_t<bits <= 8, uint8_t,
|
||||
conditional_t<bits <= 16, uint16_t,
|
||||
conditional_t<bits <= 32, uint32_t,
|
||||
conditional_t<bits <= 64, uint64_t,
|
||||
void>>>>;
|
||||
|
||||
BitRange(const BitRange& source) = delete;
|
||||
|
||||
inline auto& operator=(const BitRange& source) {
|
||||
target = target & ~mask | ((source.target & source.mask) >> source.shift) << shift & mask;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T> inline BitRange(T* source, int index) : target((type&)*source) {
|
||||
static_assert(sizeof(T) == sizeof(type));
|
||||
if(index < 0) index = Precision + index;
|
||||
mask = 1ull << index;
|
||||
shift = index;
|
||||
}
|
||||
|
||||
template<typename T> inline BitRange(T* source, int lo, int hi) : target((type&)*source) {
|
||||
static_assert(sizeof(T) == sizeof(type));
|
||||
if(lo < 0) lo = Precision + lo;
|
||||
if(hi < 0) hi = Precision + hi;
|
||||
if(lo > hi) swap(lo, hi);
|
||||
mask = ~0ull >> 64 - (hi - lo + 1) << lo;
|
||||
shift = lo;
|
||||
}
|
||||
|
||||
inline operator type() const {
|
||||
return (target & mask) >> shift;
|
||||
}
|
||||
|
||||
inline auto operator++(int) {
|
||||
auto value = (target & mask) >> shift;
|
||||
target = target & ~mask | target + (1 << shift) & mask;
|
||||
return value;
|
||||
}
|
||||
|
||||
inline auto operator--(int) {
|
||||
auto value = (target & mask) >> shift;
|
||||
target = target & ~mask | target - (1 << shift) & mask;
|
||||
return value;
|
||||
}
|
||||
|
||||
inline auto& operator++() {
|
||||
target = target & ~mask | target + (1 << shift) & mask;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline auto& operator--() {
|
||||
target = target & ~mask | target - (1 << shift) & mask;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T> inline auto& operator=(const T& source) {
|
||||
target = target & ~mask | source << shift & mask;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T> inline auto& operator*=(const T& source) {
|
||||
auto value = ((target & mask) >> shift) * source;
|
||||
target = target & ~mask | value << shift & mask;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T> inline auto& operator/=(const T& source) {
|
||||
auto value = ((target & mask) >> shift) / source;
|
||||
target = target & ~mask | value << shift & mask;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T> inline auto& operator%=(const T& source) {
|
||||
auto value = ((target & mask) >> shift) % source;
|
||||
target = target & ~mask | value << shift & mask;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T> inline auto& operator+=(const T& source) {
|
||||
auto value = ((target & mask) >> shift) + source;
|
||||
target = target & ~mask | value << shift & mask;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T> inline auto& operator-=(const T& source) {
|
||||
auto value = ((target & mask) >> shift) - source;
|
||||
target = target & ~mask | value << shift & mask;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T> inline auto& operator<<=(const T& source) {
|
||||
auto value = ((target & mask) >> shift) << source;
|
||||
target = target & ~mask | value << shift & mask;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T> inline auto& operator>>=(const T& source) {
|
||||
auto value = ((target & mask) >> shift) >> source;
|
||||
target = target & ~mask | value << shift & mask;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T> inline auto& operator&=(const T& source) {
|
||||
target = target & (~mask | source << shift & mask);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T> inline auto& operator^=(const T& source) {
|
||||
target = target ^ source << shift & mask;
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename T> inline auto& operator|=(const T& source) {
|
||||
target = target | source << shift & mask;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
type& target;
|
||||
type mask;
|
||||
uint shift;
|
||||
};
|
||||
|
||||
}
|
||||
|
@@ -12,59 +12,62 @@ template<uint Precision> struct Integer {
|
||||
conditional_t<bits() <= 64, int64_t,
|
||||
void>>>>;
|
||||
using utype = typename Natural<Precision>::utype;
|
||||
static inline constexpr auto mask() -> utype { return ~0ull >> 64 - bits(); }
|
||||
static inline constexpr auto mask() -> utype { return ~0ull >> 64 - Precision; }
|
||||
static inline constexpr auto sign() -> utype { return 1ull << Precision - 1; }
|
||||
|
||||
inline Integer() : data(0) {}
|
||||
template<uint Bits> inline Integer(Integer<Bits> value) { data = mask(value); }
|
||||
template<typename T> inline Integer(const T& value) { data = mask(value); }
|
||||
explicit inline Integer(const char* value) { data = mask(toInteger(value)); }
|
||||
template<uint Bits> inline Integer(Integer<Bits> value) { data = cast(value); }
|
||||
template<typename T> inline Integer(const T& value) { data = cast(value); }
|
||||
explicit inline Integer(const char* value) { data = cast(toInteger(value)); }
|
||||
|
||||
inline operator stype() const { return data; }
|
||||
|
||||
inline auto operator++(int) { auto value = *this; data = mask(data + 1); return value; }
|
||||
inline auto operator--(int) { auto value = *this; data = mask(data - 1); return value; }
|
||||
inline auto operator++(int) { auto value = *this; data = cast(data + 1); return value; }
|
||||
inline auto operator--(int) { auto value = *this; data = cast(data - 1); return value; }
|
||||
|
||||
inline auto& operator++() { data = mask(data + 1); return *this; }
|
||||
inline auto& operator--() { data = mask(data - 1); return *this; }
|
||||
inline auto& operator++() { data = cast(data + 1); return *this; }
|
||||
inline auto& operator--() { data = cast(data - 1); return *this; }
|
||||
|
||||
template<typename T> inline auto& operator =(const T& value) { data = mask( value); return *this; }
|
||||
template<typename T> inline auto& operator *=(const T& value) { data = mask(data * value); return *this; }
|
||||
template<typename T> inline auto& operator /=(const T& value) { data = mask(data / value); return *this; }
|
||||
template<typename T> inline auto& operator %=(const T& value) { data = mask(data % value); return *this; }
|
||||
template<typename T> inline auto& operator +=(const T& value) { data = mask(data + value); return *this; }
|
||||
template<typename T> inline auto& operator -=(const T& value) { data = mask(data - value); return *this; }
|
||||
template<typename T> inline auto& operator<<=(const T& value) { data = mask(data << value); return *this; }
|
||||
template<typename T> inline auto& operator>>=(const T& value) { data = mask(data >> value); return *this; }
|
||||
template<typename T> inline auto& operator &=(const T& value) { data = mask(data & value); return *this; }
|
||||
template<typename T> inline auto& operator ^=(const T& value) { data = mask(data ^ value); return *this; }
|
||||
template<typename T> inline auto& operator |=(const T& value) { data = mask(data | value); return *this; }
|
||||
template<typename T> inline auto& operator =(const T& value) { data = cast( value); return *this; }
|
||||
template<typename T> inline auto& operator *=(const T& value) { data = cast(data * value); return *this; }
|
||||
template<typename T> inline auto& operator /=(const T& value) { data = cast(data / value); return *this; }
|
||||
template<typename T> inline auto& operator %=(const T& value) { data = cast(data % value); return *this; }
|
||||
template<typename T> inline auto& operator +=(const T& value) { data = cast(data + value); return *this; }
|
||||
template<typename T> inline auto& operator -=(const T& value) { data = cast(data - value); return *this; }
|
||||
template<typename T> inline auto& operator<<=(const T& value) { data = cast(data << value); return *this; }
|
||||
template<typename T> inline auto& operator>>=(const T& value) { data = cast(data >> value); return *this; }
|
||||
template<typename T> inline auto& operator &=(const T& value) { data = cast(data & value); return *this; }
|
||||
template<typename T> inline auto& operator ^=(const T& value) { data = cast(data ^ value); return *this; }
|
||||
template<typename T> inline auto& operator |=(const T& value) { data = cast(data | value); return *this; }
|
||||
|
||||
inline auto operator()(int index) -> BitRange<Precision> { return {(utype&)data, index, index}; }
|
||||
inline auto operator()(int lo, int hi) -> BitRange<Precision> { return {(utype&)data, lo, hi}; }
|
||||
inline auto bit(int index) -> BitRange<Precision> { return {&data, index}; }
|
||||
inline auto bit(int index) const -> const BitRange<Precision> { return {&data, index}; }
|
||||
|
||||
inline auto operator()(int index) const -> const BitRange<Precision> { return {(utype&)data, index, index}; }
|
||||
inline auto operator()(int lo, int hi) const -> const BitRange<Precision> { return {(utype&)data, lo, hi}; }
|
||||
inline auto bit(int lo, int hi) -> BitRange<Precision> { return {&data, lo, hi}; }
|
||||
inline auto bit(int lo, int hi) const -> const BitRange<Precision> { return {&data, lo, hi}; }
|
||||
|
||||
inline auto bits(int lo, int hi) -> BitRange<Precision> { return {(utype&)data, lo, hi}; }
|
||||
inline auto bit(int index) -> BitRange<Precision> { return {(utype&)data, index, index}; }
|
||||
inline auto byte(int index) -> BitRange<Precision> { return {(utype&)data, index * 8 + 0, index * 8 + 7}; }
|
||||
inline auto byte(int index) -> BitRange<Precision> { return {&data, index * 8 + 0, index * 8 + 7}; }
|
||||
inline auto byte(int index) const -> const BitRange<Precision> { return {&data, index * 8 + 0, index * 8 + 7}; }
|
||||
|
||||
inline auto bits(int lo, int hi) const -> const BitRange<Precision> { return {(utype&)*this, lo, hi}; }
|
||||
inline auto bit(int index) const -> const BitRange<Precision> { return {(utype&)*this, index, index}; }
|
||||
inline auto byte(int index) const -> const BitRange<Precision> { return {(utype&)*this, index * 8 + 0, index * 8 + 7}; }
|
||||
inline auto mask(int index) const -> utype {
|
||||
return data & 1 << index;
|
||||
}
|
||||
|
||||
inline auto mask(int lo, int hi) const -> utype {
|
||||
return data & (~0ull >> 64 - (hi - lo + 1) << lo);
|
||||
}
|
||||
|
||||
inline auto slice(int index) const { return Natural<>{bit(index)}; }
|
||||
inline auto slice(int lo, int hi) const { return Natural<>{bit(lo, hi)}; }
|
||||
|
||||
inline auto clamp(uint bits) -> stype {
|
||||
const int64_t b = 1ull << (bits - 1);
|
||||
const int64_t b = 1ull << bits - 1;
|
||||
const int64_t m = b - 1;
|
||||
return data > m ? m : data < -b ? -b : data;
|
||||
}
|
||||
|
||||
inline auto clip(uint bits) -> stype {
|
||||
const uint64_t b = 1ull << (bits - 1);
|
||||
const uint64_t b = 1ull << bits - 1;
|
||||
const uint64_t m = b * 2 - 1;
|
||||
return (data & m ^ b) - b;
|
||||
}
|
||||
@@ -73,7 +76,7 @@ template<uint Precision> struct Integer {
|
||||
inline auto natural() const -> Natural<Precision>;
|
||||
|
||||
private:
|
||||
inline auto mask(stype value) const -> stype {
|
||||
inline auto cast(stype value) const -> stype {
|
||||
return (value & mask() ^ sign()) - sign();
|
||||
}
|
||||
|
||||
|
@@ -11,58 +11,61 @@ template<uint Precision> struct Natural {
|
||||
conditional_t<bits() <= 32, uint32_t,
|
||||
conditional_t<bits() <= 64, uint64_t,
|
||||
void>>>>;
|
||||
static inline constexpr auto mask() -> utype { return ~0ull >> 64 - bits(); }
|
||||
static inline constexpr auto mask() -> utype { return ~0ull >> 64 - Precision; }
|
||||
|
||||
inline Natural() : data(0) {}
|
||||
template<uint Bits> inline Natural(Natural<Bits> value) { data = mask(value); }
|
||||
template<typename T> inline Natural(const T& value) { data = mask(value); }
|
||||
explicit inline Natural(const char* value) { data = mask(toNatural(value)); }
|
||||
template<uint Bits> inline Natural(Natural<Bits> value) { data = cast(value); }
|
||||
template<typename T> inline Natural(const T& value) { data = cast(value); }
|
||||
explicit inline Natural(const char* value) { data = cast(toNatural(value)); }
|
||||
|
||||
inline operator utype() const { return data; }
|
||||
|
||||
inline auto operator++(int) { auto value = *this; data = mask(data + 1); return value; }
|
||||
inline auto operator--(int) { auto value = *this; data = mask(data - 1); return value; }
|
||||
inline auto operator++(int) { auto value = *this; data = cast(data + 1); return value; }
|
||||
inline auto operator--(int) { auto value = *this; data = cast(data - 1); return value; }
|
||||
|
||||
inline auto& operator++() { data = mask(data + 1); return *this; }
|
||||
inline auto& operator--() { data = mask(data - 1); return *this; }
|
||||
inline auto& operator++() { data = cast(data + 1); return *this; }
|
||||
inline auto& operator--() { data = cast(data - 1); return *this; }
|
||||
|
||||
template<typename T> inline auto& operator =(const T& value) { data = mask( value); return *this; }
|
||||
template<typename T> inline auto& operator *=(const T& value) { data = mask(data * value); return *this; }
|
||||
template<typename T> inline auto& operator /=(const T& value) { data = mask(data / value); return *this; }
|
||||
template<typename T> inline auto& operator %=(const T& value) { data = mask(data % value); return *this; }
|
||||
template<typename T> inline auto& operator +=(const T& value) { data = mask(data + value); return *this; }
|
||||
template<typename T> inline auto& operator -=(const T& value) { data = mask(data - value); return *this; }
|
||||
template<typename T> inline auto& operator<<=(const T& value) { data = mask(data << value); return *this; }
|
||||
template<typename T> inline auto& operator>>=(const T& value) { data = mask(data >> value); return *this; }
|
||||
template<typename T> inline auto& operator &=(const T& value) { data = mask(data & value); return *this; }
|
||||
template<typename T> inline auto& operator ^=(const T& value) { data = mask(data ^ value); return *this; }
|
||||
template<typename T> inline auto& operator |=(const T& value) { data = mask(data | value); return *this; }
|
||||
template<typename T> inline auto& operator =(const T& value) { data = cast( value); return *this; }
|
||||
template<typename T> inline auto& operator *=(const T& value) { data = cast(data * value); return *this; }
|
||||
template<typename T> inline auto& operator /=(const T& value) { data = cast(data / value); return *this; }
|
||||
template<typename T> inline auto& operator %=(const T& value) { data = cast(data % value); return *this; }
|
||||
template<typename T> inline auto& operator +=(const T& value) { data = cast(data + value); return *this; }
|
||||
template<typename T> inline auto& operator -=(const T& value) { data = cast(data - value); return *this; }
|
||||
template<typename T> inline auto& operator<<=(const T& value) { data = cast(data << value); return *this; }
|
||||
template<typename T> inline auto& operator>>=(const T& value) { data = cast(data >> value); return *this; }
|
||||
template<typename T> inline auto& operator &=(const T& value) { data = cast(data & value); return *this; }
|
||||
template<typename T> inline auto& operator ^=(const T& value) { data = cast(data ^ value); return *this; }
|
||||
template<typename T> inline auto& operator |=(const T& value) { data = cast(data | value); return *this; }
|
||||
|
||||
inline auto operator()(int index) -> BitRange<Precision> { return {(utype&)data, index, index}; }
|
||||
inline auto operator()(int lo, int hi) -> BitRange<Precision> { return {(utype&)data, lo, hi}; }
|
||||
inline auto bit(int index) -> BitRange<Precision> { return {&data, index}; }
|
||||
inline auto bit(int index) const -> const BitRange<Precision> { return {&data, index}; }
|
||||
|
||||
inline auto operator()(int index) const -> const BitRange<Precision> { return {(utype&)data, index, index}; }
|
||||
inline auto operator()(int lo, int hi) const -> const BitRange<Precision> { return {(utype&)data, lo, hi}; }
|
||||
inline auto bit(int lo, int hi) -> BitRange<Precision> { return {&data, lo, hi}; }
|
||||
inline auto bit(int lo, int hi) const -> const BitRange<Precision> { return {&data, lo, hi}; }
|
||||
|
||||
inline auto bits(int lo, int hi) -> BitRange<Precision> { return {(utype&)data, lo, hi}; }
|
||||
inline auto bit(int index) -> BitRange<Precision> { return {(utype&)data, index, index}; }
|
||||
inline auto byte(int index) -> BitRange<Precision> { return {(utype&)data, index * 8 + 0, index * 8 + 7}; }
|
||||
inline auto byte(int index) -> BitRange<Precision> { return {&data, index * 8 + 0, index * 8 + 7}; }
|
||||
inline auto byte(int index) const -> const BitRange<Precision> { return {&data, index * 8 + 0, index * 8 + 7}; }
|
||||
|
||||
inline auto bits(int lo, int hi) const -> const BitRange<Precision> { return {(utype&)data, lo, hi}; }
|
||||
inline auto bit(int index) const -> const BitRange<Precision> { return {(utype&)data, index, index}; }
|
||||
inline auto byte(int index) const -> const BitRange<Precision> { return {(utype&)data, index * 8 + 0, index * 8 + 7}; }
|
||||
inline auto mask(int index) const -> utype {
|
||||
return data & 1 << index;
|
||||
}
|
||||
|
||||
inline auto mask(int lo, int hi) const -> utype {
|
||||
return data & (~0ull >> 64 - (hi - lo + 1) << lo);
|
||||
}
|
||||
|
||||
inline auto slice(int index) const { return Natural<>{bit(index)}; }
|
||||
inline auto slice(int lo, int hi) const { return Natural<>{bits(lo, hi)}; }
|
||||
inline auto slice(int lo, int hi) const { return Natural<>{bit(lo, hi)}; }
|
||||
|
||||
inline auto clamp(uint bits) -> utype {
|
||||
const uint64_t b = 1ull << (bits - 1);
|
||||
const uint64_t b = 1ull << bits - 1;
|
||||
const uint64_t m = b * 2 - 1;
|
||||
return data < m ? data : m;
|
||||
}
|
||||
|
||||
inline auto clip(uint bits) -> utype {
|
||||
const uint64_t b = 1ull << (bits - 1);
|
||||
const uint64_t b = 1ull << bits - 1;
|
||||
const uint64_t m = b * 2 - 1;
|
||||
return data & m;
|
||||
}
|
||||
@@ -71,7 +74,7 @@ template<uint Precision> struct Natural {
|
||||
inline auto integer() const -> Integer<Precision>;
|
||||
|
||||
private:
|
||||
inline auto mask(utype value) const -> utype {
|
||||
inline auto cast(utype value) const -> utype {
|
||||
return value & mask();
|
||||
}
|
||||
|
||||
|
@@ -52,7 +52,7 @@ template<typename T> auto string::_prepend(const stringify<T>& source) -> string
|
||||
|
||||
template<typename T, typename... P> auto string::append(const T& value, P&&... p) -> string& {
|
||||
_append(make_string(value));
|
||||
if constexpr(sizeof...(p)) append(forward<P>(p)...);
|
||||
if constexpr(sizeof...(p) > 0) append(forward<P>(p)...);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
@@ -30,6 +30,8 @@ private:
|
||||
string value;
|
||||
};
|
||||
vector<Variable> variables;
|
||||
bool inMedia = false;
|
||||
bool inMediaNode = false;
|
||||
|
||||
auto parseDocument(const string& filedata, const string& pathname, uint depth) -> bool;
|
||||
};
|
||||
@@ -57,7 +59,7 @@ inline auto CML::parseDocument(const string& filedata, const string& pathname, u
|
||||
|
||||
for(auto& block : filedata.split("\n\n")) {
|
||||
auto lines = block.stripRight().split("\n");
|
||||
auto name = lines.takeLeft();
|
||||
auto name = lines.takeFirst();
|
||||
|
||||
if(name.beginsWith("include ")) {
|
||||
name.trimLeft("include ", 1L);
|
||||
@@ -76,7 +78,16 @@ inline auto CML::parseDocument(const string& filedata, const string& pathname, u
|
||||
}
|
||||
|
||||
state.output.append(name, " {\n");
|
||||
inMedia = name.beginsWith("@media");
|
||||
|
||||
for(auto& line : lines) {
|
||||
if(inMedia && !line.find(": ")) {
|
||||
if(inMediaNode) state.output.append(" }\n");
|
||||
state.output.append(line, " {\n");
|
||||
inMediaNode = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
auto data = line.split(":", 1L).strip();
|
||||
auto name = data(0), value = data(1);
|
||||
while(auto offset = value.find("var(")) {
|
||||
@@ -93,9 +104,13 @@ inline auto CML::parseDocument(const string& filedata, const string& pathname, u
|
||||
}
|
||||
if(!found) break;
|
||||
}
|
||||
state.output.append(" ", name, ": ", value, ";\n");
|
||||
state.output.append(inMedia ? " " : " ", name, ": ", value, ";\n");
|
||||
if(name == "box-sizing") vendorAppend(name, value);
|
||||
}
|
||||
if(inMediaNode) {
|
||||
state.output.append(" }\n");
|
||||
inMediaNode = false;
|
||||
}
|
||||
state.output.append("}\n\n");
|
||||
}
|
||||
|
||||
|
@@ -90,12 +90,12 @@ inline auto DML::parseBlock(string& block, const string& pathname, uint depth) -
|
||||
auto content = lines.takeLeft().trimLeft("# ", 1L).split("::", 1L).strip();
|
||||
auto data = markup(content[0]);
|
||||
auto name = escape(content(1, data.hash()));
|
||||
state.output.append("<header id=\"", name, "\">", data);
|
||||
state.output.append("<h1 id=\"", name, "\">", data);
|
||||
for(auto& line : lines) {
|
||||
if(!line.beginsWith("# ")) continue;
|
||||
state.output.append("<span>", line.trimLeft("# ", 1L), "</span>");
|
||||
}
|
||||
state.output.append("</header>\n");
|
||||
state.output.append("</h1>\n");
|
||||
}
|
||||
|
||||
//header
|
||||
@@ -103,13 +103,13 @@ inline auto DML::parseBlock(string& block, const string& pathname, uint depth) -
|
||||
auto content = slice(lines.takeLeft(), depth + 1).split("::", 1L).strip();
|
||||
auto data = markup(content[0]);
|
||||
auto name = escape(content(1, data.hash()));
|
||||
if(depth <= 6) {
|
||||
state.output.append("<h", depth, " id=\"", name, "\">", data);
|
||||
if(depth <= 5) {
|
||||
state.output.append("<h", depth + 1, " id=\"", name, "\">", data);
|
||||
for(auto& line : lines) {
|
||||
if(count(line, '=') != depth) continue;
|
||||
state.output.append("<span>", slice(line, depth + 1), "</span>");
|
||||
}
|
||||
state.output.append("</h", depth, ">\n");
|
||||
state.output.append("</h", depth + 1, ">\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,12 +215,13 @@ inline auto DML::markup(const string& s) -> string {
|
||||
|
||||
natural link, linkBase;
|
||||
natural embed, embedBase;
|
||||
natural iframe, iframeBase;
|
||||
|
||||
for(uint n = 0; n < s.size();) {
|
||||
char a = s[n];
|
||||
char b = s[n + 1];
|
||||
|
||||
if(!link && !embed) {
|
||||
if(!link && !embed && !iframe) {
|
||||
if(a == '*' && b == '*') { t.append(strong.flip() ? "<strong>" : "</strong>"); n += 2; continue; }
|
||||
if(a == '/' && b == '/') { t.append(emphasis.flip() ? "<em>" : "</em>"); n += 2; continue; }
|
||||
if(a == '_' && b == '_') { t.append(insertion.flip() ? "<ins>" : "</ins>"); n += 2; continue; }
|
||||
@@ -229,6 +230,9 @@ inline auto DML::markup(const string& s) -> string {
|
||||
if(a =='\\' && b =='\\') { t.append("<br>"); n += 2; continue; }
|
||||
}
|
||||
|
||||
if(iframe == 0 && a == '<' && b == '<') { t.append("<iframe width='772' height='434' src=\""); iframe = 1; iframeBase = n += 2; continue; }
|
||||
if(iframe != 0 && a == '>' && b == '>') { t.append("\" frameborder='0' allowfullscreen></iframe>"); iframe = 0; n += 2; continue; }
|
||||
|
||||
if(!embed) {
|
||||
if(link == 0 && a == '[' && b == '[') { t.append("<a href=\""); link = 1; linkBase = n += 2; continue; }
|
||||
if(link == 1 && a == ':' && b == ':') { t.append("\">"); link = 2; n += 2; continue; }
|
||||
|
@@ -95,19 +95,8 @@ struct vector_base {
|
||||
auto removeRight(uint64_t length = 1) -> void;
|
||||
auto removeLast(uint64_t length = 1) -> void { return removeRight(length); }
|
||||
auto remove(uint64_t offset, uint64_t length = 1) -> void;
|
||||
struct RemoveWhere {
|
||||
RemoveWhere(type& source) : self(source) {}
|
||||
auto operator==(const T& value) -> type&;
|
||||
auto operator!=(const T& value) -> type&;
|
||||
auto operator< (const T& value) -> type&;
|
||||
auto operator<=(const T& value) -> type&;
|
||||
auto operator> (const T& value) -> type&;
|
||||
auto operator>=(const T& value) -> type&;
|
||||
private:
|
||||
type& self;
|
||||
template<typename Compare> auto remove(const T& value) -> type&;
|
||||
};
|
||||
auto removeWhere() -> RemoveWhere { return RemoveWhere{*this}; }
|
||||
auto removeByIndex(uint64_t offset) -> bool;
|
||||
auto removeByValue(const T& value) -> bool;
|
||||
|
||||
auto takeLeft() -> T;
|
||||
auto takeFirst() -> T { return move(takeLeft()); }
|
||||
@@ -135,32 +124,6 @@ struct vector_base {
|
||||
auto find(const function<bool (const T& lhs)>& comparator) -> maybe<uint64_t>;
|
||||
auto find(const T& value) const -> maybe<uint64_t>;
|
||||
auto findSorted(const T& value) const -> maybe<uint64_t>;
|
||||
struct FindWhere {
|
||||
FindWhere(type& source) : self(source) {}
|
||||
auto operator==(const T& value) -> vector_base<iterator<T>>;
|
||||
auto operator!=(const T& value) -> vector_base<iterator<T>>;
|
||||
auto operator< (const T& value) -> vector_base<iterator<T>>;
|
||||
auto operator<=(const T& value) -> vector_base<iterator<T>>;
|
||||
auto operator> (const T& value) -> vector_base<iterator<T>>;
|
||||
auto operator>=(const T& value) -> vector_base<iterator<T>>;
|
||||
private:
|
||||
type& self;
|
||||
template<typename Compare> auto find(const T& value) -> vector_base<iterator<T>>;
|
||||
};
|
||||
auto findWhere() { return FindWhere{*this}; }
|
||||
struct FindWhereConst {
|
||||
FindWhereConst(const type& source) : self(source) {}
|
||||
auto operator==(const T& value) const -> vector_base<iterator_const<T>>;
|
||||
auto operator!=(const T& value) const -> vector_base<iterator_const<T>>;
|
||||
auto operator< (const T& value) const -> vector_base<iterator_const<T>>;
|
||||
auto operator<=(const T& value) const -> vector_base<iterator_const<T>>;
|
||||
auto operator> (const T& value) const -> vector_base<iterator_const<T>>;
|
||||
auto operator>=(const T& value) const -> vector_base<iterator_const<T>>;
|
||||
private:
|
||||
const type& self;
|
||||
template<typename Compare> auto find(const T& value) const -> vector_base<iterator_const<T>>;
|
||||
};
|
||||
auto findWhere() const { return FindWhereConst{*this}; }
|
||||
auto foreach(const function<void (const T&)>& callback) -> void;
|
||||
auto foreach(const function<void (uint, const T&)>& callback) -> void;
|
||||
|
||||
@@ -171,10 +134,6 @@ protected:
|
||||
uint64_t _right = 0; //number of allocated elements free on the right of pool
|
||||
};
|
||||
|
||||
template<typename T> auto removeWhere(vector_base<T>& source) { return source.removeWhere(); }
|
||||
template<typename T> auto findWhere(vector_base<T>& source) { return source.findWhere(); }
|
||||
template<typename T> auto findWhere(const vector_base<T>& source) { return source.findWhere(); }
|
||||
|
||||
}
|
||||
|
||||
#define vector vector_base
|
||||
|
@@ -101,23 +101,14 @@ template<typename T> auto vector<T>::remove(uint64_t offset, uint64_t length) ->
|
||||
_size -= length;
|
||||
}
|
||||
|
||||
template<typename T> auto vector<T>::RemoveWhere::operator==(const T& value) -> type& { return remove<std::equal_to<T>>(value); }
|
||||
template<typename T> auto vector<T>::RemoveWhere::operator!=(const T& value) -> type& { return remove<std::not_equal_to<T>>(value); }
|
||||
template<typename T> auto vector<T>::RemoveWhere::operator< (const T& value) -> type& { return remove<std::less<T>>(value); }
|
||||
template<typename T> auto vector<T>::RemoveWhere::operator<=(const T& value) -> type& { return remove<std::less_equal<T>>(value); }
|
||||
template<typename T> auto vector<T>::RemoveWhere::operator> (const T& value) -> type& { return remove<std::greater<T>>(value); }
|
||||
template<typename T> auto vector<T>::RemoveWhere::operator>=(const T& value) -> type& { return remove<std::greater_equal<T>>(value); }
|
||||
template<typename T> auto vector<T>::removeByIndex(uint64_t index) -> bool {
|
||||
if(index < size()) return remove(index), true;
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename T> template<typename Compare> auto vector<T>::RemoveWhere::remove(const T& value) -> type& {
|
||||
auto source = self.begin();
|
||||
auto target = self.begin();
|
||||
while(source != self.end()) {
|
||||
if(source != target) *target = move(*source);
|
||||
if(!Compare()(*target, value)) ++target;
|
||||
++source;
|
||||
}
|
||||
self.resize(target.offset());
|
||||
return self;
|
||||
template<typename T> auto vector<T>::removeByValue(const T& value) -> bool {
|
||||
if(auto index = find(value)) return remove(*index), true;
|
||||
return false;
|
||||
}
|
||||
|
||||
//
|
||||
|
@@ -36,36 +36,6 @@ template<typename T> auto vector<T>::findSorted(const T& value) const -> maybe<u
|
||||
return nothing;
|
||||
}
|
||||
|
||||
template<typename T> auto vector<T>::FindWhere::operator==(const T& value) -> vector<iterator<T>> { return move(find<std::equal_to<T>>(value)); }
|
||||
template<typename T> auto vector<T>::FindWhere::operator!=(const T& value) -> vector<iterator<T>> { return move(find<std::not_equal_to<T>>(value)); }
|
||||
template<typename T> auto vector<T>::FindWhere::operator< (const T& value) -> vector<iterator<T>> { return move(find<std::less<T>>(value)); }
|
||||
template<typename T> auto vector<T>::FindWhere::operator<=(const T& value) -> vector<iterator<T>> { return move(find<std::less_equal<T>>(value)); }
|
||||
template<typename T> auto vector<T>::FindWhere::operator> (const T& value) -> vector<iterator<T>> { return move(find<std::greater<T>>(value)); }
|
||||
template<typename T> auto vector<T>::FindWhere::operator>=(const T& value) -> vector<iterator<T>> { return move(find<std::greater_equal<T>>(value)); }
|
||||
|
||||
template<typename T> template<typename Compare> auto vector<T>::FindWhere::find(const T& value) -> vector<iterator<T>> {
|
||||
vector<iterator<T>> found;
|
||||
for(auto iterator = self.begin(); iterator != self.end(); ++iterator) {
|
||||
if(Compare()(*iterator, value)) found.append(iterator);
|
||||
}
|
||||
return move(found);
|
||||
}
|
||||
|
||||
template<typename T> auto vector<T>::FindWhereConst::operator==(const T& value) const -> vector<iterator_const<T>> { return move(find<std::equal_to<T>>(value)); }
|
||||
template<typename T> auto vector<T>::FindWhereConst::operator!=(const T& value) const -> vector<iterator_const<T>> { return move(find<std::not_equal_to<T>>(value)); }
|
||||
template<typename T> auto vector<T>::FindWhereConst::operator< (const T& value) const -> vector<iterator_const<T>> { return move(find<std::less<T>>(value)); }
|
||||
template<typename T> auto vector<T>::FindWhereConst::operator<=(const T& value) const -> vector<iterator_const<T>> { return move(find<std::less_equal<T>>(value)); }
|
||||
template<typename T> auto vector<T>::FindWhereConst::operator> (const T& value) const -> vector<iterator_const<T>> { return move(find<std::greater<T>>(value)); }
|
||||
template<typename T> auto vector<T>::FindWhereConst::operator>=(const T& value) const -> vector<iterator_const<T>> { return move(find<std::greater_equal<T>>(value)); }
|
||||
|
||||
template<typename T> template<typename Compare> auto vector<T>::FindWhereConst::find(const T& value) const -> vector<iterator_const<T>> {
|
||||
vector<iterator_const<T>> found;
|
||||
for(auto iterator = self.begin(); iterator != self.end(); ++iterator) {
|
||||
if(Compare()(*iterator, value)) found.append(iterator);
|
||||
}
|
||||
return move(found);
|
||||
}
|
||||
|
||||
template<typename T> auto vector<T>::foreach(const function<void (const T&)>& callback) -> void {
|
||||
for(uint64_t n : range(size())) callback(_pool[n]);
|
||||
}
|
||||
|
@@ -5,7 +5,7 @@
|
||||
namespace nall::vfs::fs {
|
||||
|
||||
struct file : vfs::file {
|
||||
static auto open(string location_, mode mode_) -> vfs::shared::file {
|
||||
static auto open(string location_, mode mode_) -> shared_pointer<vfs::file> {
|
||||
auto instance = shared_pointer<file>{new file};
|
||||
if(!instance->_open(location_, mode_)) return {};
|
||||
return instance;
|
||||
|
@@ -8,7 +8,7 @@ namespace nall::vfs::memory {
|
||||
struct file : vfs::file {
|
||||
~file() { delete[] _data; }
|
||||
|
||||
static auto open(const void* data, uintmax size) -> vfs::shared::file {
|
||||
static auto open(const void* data, uintmax size) -> shared_pointer<vfs::file> {
|
||||
auto instance = shared_pointer<file>{new file};
|
||||
instance->_open((const uint8_t*)data, size);
|
||||
return instance;
|
||||
|
@@ -67,9 +67,5 @@ struct file {
|
||||
|
||||
}
|
||||
|
||||
namespace nall::vfs::shared {
|
||||
using file = shared_pointer<vfs::file>;
|
||||
}
|
||||
|
||||
#include <nall/vfs/fs/file.hpp>
|
||||
#include <nall/vfs/memory/file.hpp>
|
||||
|
@@ -2,23 +2,23 @@
|
||||
#define NALL_XORG_GUARD_HPP
|
||||
|
||||
#define Atom XlibAtom
|
||||
#define Bool XlibBool
|
||||
#define Display XlibDisplay
|
||||
#define Font XlibFont
|
||||
#define Screen XlibScreen
|
||||
#define Window XlibWindow
|
||||
#define Above XlibAbove
|
||||
#define Below XlibBelow
|
||||
|
||||
#else
|
||||
#undef NALL_XORG_GUARD_HPP
|
||||
|
||||
#undef Atom
|
||||
#undef Bool
|
||||
#undef Display
|
||||
#undef Font
|
||||
#undef Screen
|
||||
#undef Window
|
||||
|
||||
#undef Above
|
||||
#undef Below
|
||||
#undef Bool
|
||||
|
||||
#ifndef NALL_XORG_GUARD_CONSTANTS
|
||||
#define NALL_XORG_GUARD_CONSTANTS
|
||||
|
Reference in New Issue
Block a user