Update to v101r19 release.

byuu says:

Changelog:

-   added \~130 new PAL games to icarus (courtesy of Smarthuman
    and aquaman)
-   added all three Korean-localized games to icarus
-   sfc: removed SuperDisc emulation (it was going nowhere)
-   sfc: fixed MSU1 regression where the play/repeat flags were not
    being cleared on track select
-   nall: cryptography support added; will be used to sign future
    databases (validation will always be optional)
-   minor shims to fix compilation issues due to nall changes

The real magic is that we now have 25-30% of the PAL SNES library in
icarus!

Signing will be tricky. Obviously if I put the public key inside the
higan archive, then all anyone has to do is change that public key for
their own releases. And if you download from my site (which is now over
HTTPS), then you don't need the signing to verify integrity. I may just
put the public key on my site on my site and leave it at that, we'll
see.
This commit is contained in:
Tim Allen 2016-10-28 08:16:58 +11:00
parent c6fc15f8d2
commit f3e67da937
70 changed files with 4425 additions and 1667 deletions

View File

@ -12,7 +12,7 @@ using namespace nall;
namespace Emulator {
static const string Name = "higan";
static const string Version = "101.18";
static const string Version = "101.19";
static const string Author = "byuu";
static const string License = "GPLv3";
static const string Website = "http://byuu.org/";

View File

@ -29,8 +29,8 @@ auto Cartridge::load() -> bool {
if(!board) return false;
Hash::SHA256 sha;
sha.data(board->prgrom.data, board->prgrom.size);
sha.data(board->chrrom.data, board->chrrom.size);
sha.input(board->prgrom.data, board->prgrom.size);
sha.input(board->chrrom.data, board->chrrom.size);
information.sha256 = sha.digest();
return true;
}

View File

@ -1,3 +1,7 @@
static auto hex(uintmax value, long precision = 0, char padchar = '0') -> string {
return nall::hex(value, precision, padchar);
}
auto LR35902::disassemble(uint16 pc) -> string {
char output[80];
memset(output, ' ', sizeof output);

View File

@ -1,3 +1,7 @@
static auto hex(uintmax value, long precision = 0, char padchar = '0') -> string {
return nall::hex(value, precision, padchar);
}
auto R65816::dreadb(uint24 addr) -> uint8 {
if((addr & 0x40ffff) >= 0x2000 && (addr & 0x40ffff) <= 0x5fff) {
//$00-3f|80-bf:2000-5fff

View File

@ -3,14 +3,13 @@ processors += r65816 spc700 arm gsu hg51b upd96050
objects += sfc-interface sfc-system sfc-controller
objects += sfc-cartridge sfc-memory
objects += sfc-cpu sfc-smp sfc-dsp sfc-ppu
objects += sfc-expansion sfc-satellaview sfc-superdisc
objects += sfc-21fx
objects += sfc-expansion sfc-satellaview sfc-21fx
objects += sfc-icd2 sfc-mcc sfc-nss sfc-event
objects += sfc-sa1 sfc-superfx
objects += sfc-armdsp sfc-hitachidsp sfc-necdsp
objects += sfc-epsonrtc sfc-sharprtc
objects += sfc-spc7110 sfc-sdd1 sfc-obc1
objects += sfc-msu1
objects += sfc-spc7110 sfc-sdd1
objects += sfc-obc1 sfc-msu1
objects += sfc-bsmemory sfc-sufamiturbo
obj/sfc-interface.o: sfc/interface/interface.cpp $(call rwildcard,sfc/interface)
@ -26,7 +25,6 @@ obj/sfc-ppu.o: sfc/ppu/ppu.cpp $(call rwildcard,sfc/ppu/)
obj/sfc-expansion.o: sfc/expansion/expansion.cpp $(call rwildcard,sfc/expansion/)
obj/sfc-satellaview.o: sfc/expansion/satellaview/satellaview.cpp $(call rwildcard,sfc/expansion/satellaview/)
obj/sfc-superdisc.o: sfc/expansion/superdisc/superdisc.cpp $(call rwildcard,sfc/expansion/superdisc/)
obj/sfc-21fx.o: sfc/expansion/21fx/21fx.cpp $(call rwildcard,sfc/expansion/21fx/)
obj/sfc-icd2.o: sfc/coprocessor/icd2/icd2.cpp $(call rwildcard,sfc/coprocessor/icd2/)

View File

@ -52,8 +52,8 @@ auto Cartridge::load() -> bool {
//Sufami Turbo
else if(cartridge.has.SufamiTurboSlots) {
Hash::SHA256 sha;
sha.data(sufamiturboA.rom.data(), sufamiturboA.rom.size());
sha.data(sufamiturboB.rom.data(), sufamiturboB.rom.size());
sha.input(sufamiturboA.rom.data(), sufamiturboA.rom.size());
sha.input(sufamiturboB.rom.data(), sufamiturboB.rom.size());
information.sha256 = sha.digest();
}
@ -61,22 +61,22 @@ auto Cartridge::load() -> bool {
else {
Hash::SHA256 sha;
//hash each ROM image that exists; any with size() == 0 is ignored by sha256_chunk()
sha.data(rom.data(), rom.size());
sha.data(mcc.rom.data(), mcc.rom.size());
sha.data(sa1.rom.data(), sa1.rom.size());
sha.data(superfx.rom.data(), superfx.rom.size());
sha.data(hitachidsp.rom.data(), hitachidsp.rom.size());
sha.data(spc7110.prom.data(), spc7110.prom.size());
sha.data(spc7110.drom.data(), spc7110.drom.size());
sha.data(sdd1.rom.data(), sdd1.rom.size());
sha.input(rom.data(), rom.size());
sha.input(mcc.rom.data(), mcc.rom.size());
sha.input(sa1.rom.data(), sa1.rom.size());
sha.input(superfx.rom.data(), superfx.rom.size());
sha.input(hitachidsp.rom.data(), hitachidsp.rom.size());
sha.input(spc7110.prom.data(), spc7110.prom.size());
sha.input(spc7110.drom.data(), spc7110.drom.size());
sha.input(sdd1.rom.data(), sdd1.rom.size());
//hash all firmware that exists
vector<uint8> buffer;
buffer = armdsp.firmware();
sha.data(buffer.data(), buffer.size());
sha.input(buffer.data(), buffer.size());
buffer = hitachidsp.firmware();
sha.data(buffer.data(), buffer.size());
sha.input(buffer.data(), buffer.size());
buffer = necdsp.firmware();
sha.data(buffer.data(), buffer.size());
sha.input(buffer.data(), buffer.size());
//finalize hash
information.sha256 = sha.digest();
}

View File

@ -116,9 +116,8 @@ auto MSU1::audioOpen() -> void {
auto MSU1::readIO(uint24 addr, uint8) -> uint8 {
cpu.synchronize(*this);
addr = 0x2000 | (addr & 7);
switch(addr) {
switch(0x2000 | (addr & 7)) {
case 0x2000:
return (
Revision << 0
@ -145,9 +144,8 @@ auto MSU1::readIO(uint24 addr, uint8) -> uint8 {
auto MSU1::writeIO(uint24 addr, uint8 data) -> void {
cpu.synchronize(*this);
addr = 0x2000 | (addr & 7);
switch(addr) {
switch(0x2000 | (addr & 7)) {
case 0x2000: io.dataSeekOffset.byte(0) = data; break;
case 0x2001: io.dataSeekOffset.byte(1) = data; break;
case 0x2002: io.dataSeekOffset.byte(2) = data; break;
@ -157,6 +155,8 @@ auto MSU1::writeIO(uint24 addr, uint8 data) -> void {
break;
case 0x2004: io.audioTrack.byte(0) = data; break;
case 0x2005: io.audioTrack.byte(1) = data;
io.audioPlay = false;
io.audioRepeat = false;
io.audioPlayOffset = 8;
if(io.audioTrack == io.audioResumeTrack) {
io.audioPlayOffset = io.audioResumeOffset;

View File

@ -5,5 +5,4 @@ struct Expansion : Thread {
};
#include <sfc/expansion/satellaview/satellaview.hpp>
#include <sfc/expansion/superdisc/superdisc.hpp>
#include <sfc/expansion/21fx/21fx.hpp>

View File

@ -1,202 +0,0 @@
//NEC D75P308GF
//4-bit microcontroller
//CD-player interface
auto SuperDisc::necPollIRQ() -> uint8 {
auto match = [&](const string& compare) -> bool {
if(nec.command.size() != compare.size()) return false;
for(auto n : range(nec.command)) {
char c = compare[n];
if(c == '?') continue;
if(c >= '0' && c <= '9') c -= '0';
if(c >= 'a' && c <= 'f') c -= 'a' - 10;
if(nec.command[n] != c) return false;
}
return true;
};
//access ??/??/??
if(match("b" )) return 0x8f;
if(match("b?" )) return 0x8f;
if(match("b??" )) return 0x8f;
if(match("b???" )) return 0x8f;
if(match("b????" )) return 0x8f;
if(match("b?????" )) return 0x8f;
if(match("b??????" )) return 0x8f;
if(match("b??????f")) {
nec.command.reset();
return 0x8f;
}
//access t??/i??
if(match("c" )) return 0x8f;
if(match("c?" )) return 0x8f;
if(match("c??" )) return 0x8f;
if(match("c???" )) return 0x8f;
if(match("c????" )) return 0x8f;
if(match("c????f")) {
nec.command.reset();
return 0x8f;
}
//d-prefixes
if(match("d" )) return 0x8f;
if(match("d0")) return 0x8f;
if(match("d1")) return 0x8f;
if(match("d4")) return 0x8f;
if(match("d5")) return 0x8f;
//stop
if(match("d01" )) return 0x8f;
if(match("d01f")) {
nec.command.reset();
return 0x8f;
}
//play
if(match("d02" )) return 0x8f;
if(match("d02f")) {
nec.command.reset();
return 0x8f;
}
//pause
if(match("d03" )) return 0x8f;
if(match("d03f")) {
nec.command.reset();
return 0x8f;
}
//open / close
if(match("d04" )) return 0x8f;
if(match("d04f")) {
nec.command.reset();
return 0x8f;
}
//fast forward
if(match("d10" )) return 0x8f;
if(match("d10f")) {
nec.command.reset();
return 0x8f;
}
//fast reverse
if(match("d11" )) return 0x8f;
if(match("d11f")) {
nec.command.reset();
return 0x8f;
}
//forward
if(match("d12" )) return 0x8f;
if(match("d12f")) {
nec.command.reset();
return 0x8f;
}
//reverse
if(match("d13" )) return 0x8f;
if(match("d13f")) {
nec.command.reset();
return 0x8f;
}
//key direct
if(match("d40" )) return 0x8f;
if(match("d40f")) {
nec.command.reset();
return 0x8f;
}
//key ignore
if(match("d41" )) return 0x8f;
if(match("d41f")) {
nec.command.reset();
return 0x8f;
}
//continuous play
if(match("d42" )) return 0x8f;
if(match("d42f")) {
nec.command.reset();
return 0x8f;
}
//auto track pause
if(match("d43" )) return 0x8f;
if(match("d43f")) {
nec.command.reset();
return 0x8f;
}
//auto index pause
if(match("d44" )) return 0x8f;
if(match("d44f")) {
nec.command.reset();
return 0x8f;
}
//normal speed
if(match("d45" )) return 0x8f;
if(match("d45f")) {
nec.command.reset();
return 0x8f;
}
//double speed
if(match("d46" )) return 0x8f;
if(match("d46f")) {
nec.command.reset();
return 0x8f;
}
//q-data request
if(match("d50" )) return 0x8f;
if(match("d50f" )) return 0x8f;
if(match("d50f?" )) return 0x80;
if(match("d50f??" )) return 0x80;
if(match("d50f???" )) return 0x80;
if(match("d50f????" )) return 0x80;
if(match("d50f?????" )) return 0x80;
if(match("d50f??????" )) return 0x80;
if(match("d50f???????" )) return 0x80;
if(match("d50f????????" )) return 0x80;
if(match("d50f?????????" )) return 0x80;
if(match("d50f??????????" )) return 0x80;
if(match("d50f???????????" )) return 0x80;
if(match("d50f????????????" )) return 0x80;
if(match("d50f?????????????" )) return 0x80;
if(match("d50f??????????????" )) return 0x80;
if(match("d50f???????????????" )) return 0x80;
if(match("d50f????????????????" )) return 0x80;
if(match("d50f????????????????f")) {
nec.command.reset();
return 0x8f;
}
//status request
if(match("d51" )) return 0x8f;
if(match("d51f" )) return 0x8f;
if(match("d51f0" )) return 0x81;
if(match("d51f01" )) return 0x80;
if(match("d51f012" )) return 0x81;
if(match("d51f0123" )) return 0x80;
if(match("d51f01234" )) return 0x80;
if(match("d51f01234f")) {
nec.command.reset();
return 0x8f;
}
nec.command.reset();
return 0x00;
}
auto SuperDisc::necReadData() -> uint8 {
return nec.data;
}
auto SuperDisc::necWriteCommand(uint4 data) -> void {
if(nec.command.size() >= 32) return;
nec.command.append(data);
}

View File

@ -1,143 +0,0 @@
//Sony CXD1800Q
//CD-ROM decoder
auto SuperDisc::sonyPollIRQ() -> uint8 {
return 0x00;
}
auto SuperDisc::sonyReadData() -> uint8 {
uint8 command = sony.command++;
auto match = [&](const string& compare) -> bool {
char hi = compare[0];
if(hi == '?') hi = 0;
if(hi >= '0' && hi <= '9') hi -= '0';
if(hi >= 'a' && hi <= 'f') hi -= 'a' - 10;
if(hi != '?' && hi != command.bits(4,7)) return false;
char lo = compare[1];
if(lo == '?') lo = 0;
if(lo >= '0' && lo <= '9') lo -= '0';
if(lo >= 'a' && lo <= 'f') lo -= 'a' - 10;
if(lo != '?' && lo != command.bits(0,3)) return false;
return true;
};
//DMA
if(match("00")) return 0x00;
//INST
if(match("01")) return 0x10;
//STS
if(match("02")) return 0x00;
//HFLG
if(match("03")) return 0x00;
//HMIN
if(match("?4")) return 0x00;
//HSEC
if(match("?5")) return 0x00;
//HBLK
if(match("?6")) return 0x00;
//HMOD
if(match("?7")) return 0x00;
//SFIL
if(match("08")) return 0x00;
//SCH
if(match("09")) return 0x00;
//SMOD
if(match("0a")) return 0x00;
//SCI
if(match("0b")) return 0x00;
//CMAD
if(match("0c")) return 0x00;
if(match("0d")) return 0x00;
//MDFM
if(match("?e")) return 0x00;
//ADPC
if(match("?f")) return 0x00;
//DMXF
if(match("18")) return 0x00;
if(match("19")) return 0x00;
//DMAD
if(match("1a")) return 0x00;
if(match("1b")) return 0x00;
//DRAD
if(match("1c")) return 0x00;
if(match("1d")) return 0x00;
return 0x00;
}
auto SuperDisc::sonyWriteCommand(uint8 data) -> void {
sony.command = data;
}
auto SuperDisc::sonyWriteData(uint8 data) -> void {
uint8 command = sony.command++;
auto match = [&](const string& compare) -> bool {
char hi = compare[0];
if(hi == '?') hi = 0;
if(hi >= '0' && hi <= '9') hi -= '0';
if(hi >= 'a' && hi <= 'f') hi -= 'a' - 10;
if(hi != '?' && hi != command.bits(4,7)) return false;
char lo = compare[1];
if(lo == '?') lo = 0;
if(lo >= '0' && lo <= '9') lo -= '0';
if(lo >= 'a' && lo <= 'f') lo -= 'a' - 10;
if(lo != '?' && lo != command.bits(0,3)) return false;
return true;
};
//DRIF
if(match("?1")) return;
//CHCT
if(match("?2")) return;
//DECT
if(match("?3")) return;
//INMS
if(match("?4")) return;
//INCL
if(match("?5")) return;
//CI
if(match("?6")) return;
//DMAD
if(match("?7")) return;
if(match("?8")) return;
//DMXF
if(match("?9")) return;
if(match("?a")) return;
//DRAD
if(match("?b")) return;
if(match("?c")) return;
//PLBA
if(match("0d")) return;
}

View File

@ -1,106 +0,0 @@
#include <sfc/sfc.hpp>
namespace SuperFamicom {
#include "nec.cpp"
#include "sony.cpp"
SuperDisc::SuperDisc() {
create(&SuperDisc::Enter, 75);
bus.map({&SuperDisc::read, this}, {&SuperDisc::write, this}, "00-3f,80-bf:21e0-21e5");
r.irqEnable = 0x00;
nec.command.reset();
nec.data = 0x00;
sony.command = 0x00;
sony.data = 0x00;
}
SuperDisc::~SuperDisc() {
scheduler.remove(*this);
bus.unmap("00-3f,80-bf:21e0-21e5");
}
auto SuperDisc::Enter() -> void {
while(true) scheduler.synchronize(), peripherals.expansionPort->main();
}
auto SuperDisc::main() -> void {
cpu.r.irq = 0;
if(r.irqEnable.bit(3)) {
cpu.r.irq = 1;
nec.data = necPollIRQ();
}
if(r.irqEnable.bit(2)) {
cpu.r.irq = 1;
sony.data = sonyPollIRQ();
}
step(1);
synchronize(cpu);
}
auto SuperDisc::read(uint24 addr, uint8 data) -> uint8 {
addr = 0x21e0 | (addr & 7);
if(addr == 0x21e0) {
data = 0x00;
}
if(addr == 0x21e1) {
cpu.r.irq = 0;
data = necReadData();
}
if(addr == 0x21e2) {
data = 0x00;
}
if(addr == 0x21e3) {
cpu.r.irq = 0;
data = sonyReadData();
}
if(addr == 0x21e4) {
data = r.irqEnable;
}
if(addr == 0x21e5) {
data = 0x00;
}
return data;
}
auto SuperDisc::write(uint24 addr, uint8 data) -> void {
addr = 0x21e0 | (addr & 7);
if(addr == 0x21e0) {
}
if(addr == 0x21e1) {
necWriteCommand(data.bits(0,3));
}
if(addr == 0x21e2) {
sonyWriteCommand(data);
}
if(addr == 0x21e3) {
sonyWriteData(data);
}
if(addr == 0x21e4) {
r.irqEnable = data;
}
if(addr == 0x21e5) {
}
}
}

View File

@ -1,38 +0,0 @@
struct SuperDisc : Expansion {
SuperDisc();
~SuperDisc();
static auto Enter() -> void;
auto main() -> void;
auto read(uint24 addr, uint8 data) -> uint8;
auto write(uint24 addr, uint8 data) -> void;
//nec.cpp
auto necPollIRQ() -> uint8;
auto necReadData() -> uint8;
auto necWriteCommand(uint4 data) -> void;
//sony.cpp
auto sonyPollIRQ() -> uint8;
auto sonyReadData() -> uint8;
auto sonyWriteCommand(uint8 data) -> void;
auto sonyWriteData(uint8 data) -> void;
private:
struct Registers {
uint8 irqEnable;
} r;
//NEC
struct NEC {
vector<uint4> command;
uint8 data;
} nec;
//Sony
struct Sony {
uint8 command;
uint8 data;
} sony;
};

View File

@ -108,10 +108,6 @@ Interface::Interface() {
expansionPort.devices.append(device);
}
{ Device device{ID::Device::SuperDisc, "Super Disc"};
expansionPort.devices.append(device);
}
{ Device device{ID::Device::S21FX, "21fx"};
expansionPort.devices.append(device);
}

View File

@ -28,7 +28,6 @@ struct ID {
Justifiers,
Satellaview,
SuperDisc,
S21FX,
};};
};

View File

@ -52,7 +52,6 @@ auto Peripherals::connect(uint port, uint device) -> void {
switch(device) { default:
case ID::Device::None: expansionPort = new Expansion; break;
case ID::Device::Satellaview: expansionPort = new Satellaview; break;
case ID::Device::SuperDisc: expansionPort = new SuperDisc; break;
case ID::Device::S21FX: expansionPort = new S21FX; break;
}
}

View File

@ -17,26 +17,24 @@ auto pDesktop::workspace() -> Geometry {
#endif
#if defined(DISPLAY_XORG)
XlibDisplay* display = XOpenDisplay(nullptr);
auto display = XOpenDisplay(nullptr);
int screen = DefaultScreen(display);
static Atom atom = XlibNone;
if(atom == XlibNone) atom = XInternAtom(display, "_NET_WORKAREA", True);
int format;
unsigned char* data = nullptr;
unsigned long items, after;
Atom returnAtom;
XlibAtom returnAtom;
int result = XGetWindowProperty(
display, RootWindow(display, screen), atom, 0, 4, False, XA_CARDINAL, &returnAtom, &format, &items, &after, &data
display, RootWindow(display, screen), XInternAtom(display, "_NET_WORKAREA", XlibTrue), 0, 4, XlibFalse,
XInternAtom(display, "CARDINAL", XlibTrue), &returnAtom, &format, &items, &after, &data
);
XCloseDisplay(display);
if(result == Success && returnAtom == XA_CARDINAL && format == 32 && items == 4) {
unsigned long *workarea = (unsigned long*)data;
return {(signed)workarea[0], (signed)workarea[1], (signed)workarea[2], (signed)workarea[3]};
if(result == Success && returnAtom == XInternAtom(display, "CARDINAL", XlibTrue) && format == 32 && items == 4) {
unsigned long* workarea = (unsigned long*)data;
return {(int)workarea[0], (int)workarea[1], (int)workarea[2], (int)workarea[3]};
}
return {

View File

@ -66,10 +66,10 @@ auto pCanvas::_rasterize() -> void {
qtImageHeight = height;
if(!qtImage) qtImage = new QImage(width, height, QImage::Format_ARGB32);
auto buffer = (uint32*)qtImage->bits();
auto buffer = (uint32_t*)qtImage->bits();
if(auto& icon = state().icon) {
memory::copy(buffer, state().icon.data(), width * height * sizeof(uint32));
memory::copy(buffer, state().icon.data(), width * height * sizeof(uint32_t));
} else if(auto& gradient = state().gradient) {
auto& colors = gradient.state.colors;
image fill;
@ -77,7 +77,7 @@ auto pCanvas::_rasterize() -> void {
fill.gradient(colors[0].value(), colors[1].value(), colors[2].value(), colors[3].value());
memory::copy(buffer, fill.data(), fill.size());
} else {
uint32 color = state().color.value();
uint32_t color = state().color.value();
for(auto n : range(width * height)) buffer[n] = color;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -39,7 +39,7 @@ struct any {
}
template<typename T> auto operator=(const T& value) -> any& {
using auto_t = type_if<is_array<T>, typename remove_extent<typename add_const<T>::type>::type*, T>;
using auto_t = typename conditional<is_array<T>::value, typename remove_extent<typename add_const<T>::type>::type*, T>::type;
if(type() == typeid(auto_t)) {
static_cast<holder<auto_t>*>(container)->value = (auto_t)value;

69
nall/arithmetic.hpp Normal file
View File

@ -0,0 +1,69 @@
#pragma once
//multi-precision arithmetic
//warning: each size is quadratically more expensive than the size before it!
#include <nall/stdint.hpp>
#include <nall/string.hpp>
#include <nall/range.hpp>
#include <nall/traits.hpp>
#include <nall/arithmetic/unsigned.hpp>
#if !defined(__SIZEOF_INT128__)
#define PairBits 128
#define TypeBits 64
#define HalfBits 32
#include <nall/arithmetic/natural.hpp>
#undef PairBits
#undef TypeBits
#undef HalfBits
#endif
#define PairBits 256
#define TypeBits 128
#define HalfBits 64
#include <nall/arithmetic/natural.hpp>
#undef PairBits
#undef TypeBits
#undef HalfBits
#define PairBits 512
#define TypeBits 256
#define HalfBits 128
#include <nall/arithmetic/natural.hpp>
#undef PairBits
#undef TypeBits
#undef HalfBits
#define PairBits 1024
#define TypeBits 512
#define HalfBits 256
#include <nall/arithmetic/natural.hpp>
#undef PairBits
#undef TypeBits
#undef HalfBits
#define PairBits 2048
#define TypeBits 1024
#define HalfBits 512
#include <nall/arithmetic/natural.hpp>
#undef PairBits
#undef TypeBits
#undef HalfBits
#define PairBits 4096
#define TypeBits 2048
#define HalfBits 1024
#include <nall/arithmetic/natural.hpp>
#undef PairBits
#undef TypeBits
#undef HalfBits
#define PairBits 8192
#define TypeBits 4096
#define HalfBits 2048
#include <nall/arithmetic/natural.hpp>
#undef PairBits
#undef TypeBits
#undef HalfBits

View File

@ -0,0 +1,21 @@
#pragma once
namespace nall {
struct BarrettReduction {
BarrettReduction(uint256_t modulo) : modulo(modulo), factor((1_u1024 << 512) / modulo) {}
//return = value % modulo
inline auto operator()(uint512_t value) const -> uint256_t {
uint512_t hi, lo;
nall::mul(value, factor, hi, lo);
uint512_t remainder = value - hi * modulo;
return remainder < modulo ? remainder : remainder - modulo;
}
private:
const uint512_t modulo;
const uint512_t factor;
};
}

353
nall/arithmetic/natural.hpp Normal file
View File

@ -0,0 +1,353 @@
#define ConcatenateType(Size) uint##Size##_t
#define DeclareType(Size) ConcatenateType(Size)
#define Pair DeclareType(PairBits)
#define Type DeclareType(TypeBits)
#define Half DeclareType(HalfBits)
//pick the larger of two types to prevent unnecessary data clamping
#define Cast (typename conditional<sizeof(Pair) >= sizeof(T), Pair, T>::type)
namespace nall {
//namespace Arithmetic {
struct Pair {
Pair() = default;
explicit constexpr Pair(const Pair& source) : hi(source.hi), lo(source.lo) {}
template<typename Hi, typename Lo> constexpr Pair(const Hi& hi, const Lo& lo) : hi(hi), lo(lo) {}
template<typename T> Pair(const T& source) { _set(*this, source); }
explicit operator bool() const { return hi | lo; }
template<typename T> operator T() const { T value; _get(*this, value); return value; }
auto operator~() const -> Pair { return {~hi, ~lo}; }
auto operator!() const -> bool { return !(hi || lo); }
auto operator++() -> Pair& { lo++; hi += lo == 0; return *this; }
auto operator--() -> Pair& { hi -= lo == 0; lo--; }
auto operator++(int) -> Pair { Pair r = *this; lo++; hi += lo == 0; return r; }
auto operator--(int) -> Pair { Pair r = *this; hi -= lo == 0; lo--; return r; }
auto operator* (const Pair& rhs) const -> Pair { return mul(*this, rhs); }
auto operator/ (const Pair& rhs) const -> Pair { Pair q, r; div(*this, rhs, q, r); return q; }
auto operator% (const Pair& rhs) const -> Pair { Pair q, r; div(*this, rhs, q, r); return r; }
auto operator+ (const Pair& rhs) const -> Pair { return {hi + rhs.hi + (lo + rhs.lo < lo), lo + rhs.lo}; }
auto operator- (const Pair& rhs) const -> Pair { return {hi - rhs.hi - (lo - rhs.lo > lo), lo - rhs.lo}; }
auto operator<<(const Pair& rhs) const -> Pair { return shl(*this, rhs); }
auto operator>>(const Pair& rhs) const -> Pair { return shr(*this, rhs); }
auto operator& (const Pair& rhs) const -> Pair { return {hi & rhs.hi, lo & rhs.lo}; }
auto operator| (const Pair& rhs) const -> Pair { return {hi | rhs.hi, lo | rhs.lo}; }
auto operator^ (const Pair& rhs) const -> Pair { return {hi ^ rhs.hi, lo ^ rhs.lo}; }
auto operator==(const Pair& rhs) const -> bool { return hi == rhs.hi && lo == rhs.lo; }
auto operator!=(const Pair& rhs) const -> bool { return hi != rhs.hi || lo != rhs.lo; }
auto operator>=(const Pair& rhs) const -> bool { return hi > rhs.hi || (hi == rhs.hi && lo >= rhs.lo); }
auto operator<=(const Pair& rhs) const -> bool { return hi < rhs.hi || (hi == rhs.hi && lo <= rhs.lo); }
auto operator> (const Pair& rhs) const -> bool { return hi > rhs.hi || (hi == rhs.hi && lo > rhs.lo); }
auto operator< (const Pair& rhs) const -> bool { return hi < rhs.hi || (hi == rhs.hi && lo < rhs.lo); }
template<typename T> auto& operator*= (const T& rhs) { return *this = *this * Pair(rhs); }
template<typename T> auto& operator/= (const T& rhs) { return *this = *this / Pair(rhs); }
template<typename T> auto& operator%= (const T& rhs) { return *this = *this % Pair(rhs); }
template<typename T> auto& operator+= (const T& rhs) { return *this = *this + Pair(rhs); }
template<typename T> auto& operator-= (const T& rhs) { return *this = *this - Pair(rhs); }
template<typename T> auto& operator<<=(const T& rhs) { return *this = *this << Pair(rhs); }
template<typename T> auto& operator>>=(const T& rhs) { return *this = *this >> Pair(rhs); }
template<typename T> auto& operator&= (const T& rhs) { return *this = *this & Pair(rhs); }
template<typename T> auto& operator|= (const T& rhs) { return *this = *this | Pair(rhs); }
template<typename T> auto& operator^= (const T& rhs) { return *this = *this ^ Pair(rhs); }
template<typename T> auto operator* (const T& rhs) const { return Cast(*this) * Cast(rhs); }
template<typename T> auto operator/ (const T& rhs) const { return Cast(*this) / Cast(rhs); }
template<typename T> auto operator% (const T& rhs) const { return Cast(*this) % Cast(rhs); }
template<typename T> auto operator+ (const T& rhs) const { return Cast(*this) + Cast(rhs); }
template<typename T> auto operator- (const T& rhs) const { return Cast(*this) - Cast(rhs); }
template<typename T> auto operator<<(const T& rhs) const { return Cast(*this) << Cast(rhs); }
template<typename T> auto operator>>(const T& rhs) const { return Cast(*this) >> Cast(rhs); }
template<typename T> auto operator& (const T& rhs) const { return Cast(*this) & Cast(rhs); }
template<typename T> auto operator| (const T& rhs) const { return Cast(*this) | Cast(rhs); }
template<typename T> auto operator^ (const T& rhs) const { return Cast(*this) ^ Cast(rhs); }
template<typename T> auto operator==(const T& rhs) const -> bool { return Cast(*this) == Cast(rhs); }
template<typename T> auto operator!=(const T& rhs) const -> bool { return Cast(*this) != Cast(rhs); }
template<typename T> auto operator>=(const T& rhs) const -> bool { return Cast(*this) >= Cast(rhs); }
template<typename T> auto operator<=(const T& rhs) const -> bool { return Cast(*this) <= Cast(rhs); }
template<typename T> auto operator> (const T& rhs) const -> bool { return Cast(*this) > Cast(rhs); }
template<typename T> auto operator< (const T& rhs) const -> bool { return Cast(*this) < Cast(rhs); }
explicit Pair(const vector<uint8_t>& value) : hi(0), lo(0) {
for(auto n : rrange(value)) {
operator<<=(8);
operator|=(value[n]);
}
}
private:
Type lo;
Type hi;
friend auto upper(const Pair&) -> Type;
friend auto lower(const Pair&) -> Type;
friend auto bits(Pair) -> uint;
friend auto square(const Pair&) -> Pair;
friend auto square(const Pair&, Pair&, Pair&) -> void;
friend auto mul(const Pair&, const Pair&) -> Pair;
friend auto mul(const Pair&, const Pair&, Pair&, Pair&) -> void;
friend auto div(const Pair&, const Pair&, Pair&, Pair&) -> void;
template<typename T> friend auto shl(const Pair&, const T&) -> Pair;
template<typename T> friend auto shr(const Pair&, const T&) -> Pair;
};
#define ConcatenateUDL(Size) _u##Size
#define DeclareUDL(Size) ConcatenateUDL(Size)
alwaysinline auto operator"" DeclareUDL(PairBits)(const char* s) -> Pair {
Pair p = 0;
if(s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) {
s += 2;
while(*s) {
auto c = *s++;
if(c == '\'');
else if(c >= '0' && c <= '9') p = (p << 4) + (c - '0');
else if(c >= 'a' && c <= 'f') p = (p << 4) + (c - 'a' + 10);
else if(c >= 'A' && c <= 'F') p = (p << 4) + (c - 'A' + 10);
else break;
}
} else {
while(*s) {
auto c = *s++;
if(c == '\'');
else if(c >= '0' && c <= '9') p = (p << 3) + (p << 1) + (c - '0');
else break;
}
}
return p;
}
#undef ConcatenateUDL
#undef DeclareUDL
template<typename T> alwaysinline auto _set(Pair& lhs, const T& rhs) -> enable_if_t<(sizeof(Pair) == sizeof(T))> {
lhs = rhs;
}
template<typename T> alwaysinline auto _set(Pair& lhs, const T& rhs) -> enable_if_t<(sizeof(Pair) > sizeof(T))> {
lhs = {0, rhs};
}
template<typename T> alwaysinline auto _set(Pair& lhs, const T& rhs) -> enable_if_t<(sizeof(Pair) < sizeof(T))> {
lhs = {lower(rhs) >> TypeBits, lower(rhs)};
}
template<typename T> alwaysinline auto _get(const Pair& lhs, T& rhs) -> enable_if_t<(sizeof(T) == sizeof(Pair))> {
rhs = lhs;
}
template<typename T> alwaysinline auto _get(const Pair& lhs, T& rhs) -> enable_if_t<(sizeof(T) > sizeof(Pair))> {
rhs = {0, lhs};
}
template<typename T> alwaysinline auto _get(const Pair& lhs, T& rhs) -> enable_if_t<(sizeof(T) < sizeof(Pair))> {
rhs = lower(lhs);
}
alwaysinline auto upper(const Pair& value) -> Type { return value.hi; }
alwaysinline auto lower(const Pair& value) -> Type { return value.lo; }
alwaysinline auto bits(Pair value) -> uint {
if(value.hi) {
uint bits = TypeBits;
while(value.hi) value.hi >>= 1, bits++;
return bits;
} else {
uint bits = 0;
while(value.lo) value.lo >>= 1, bits++;
return bits;
}
}
//Bits * Bits => Bits
inline auto square(const Pair& lhs) -> Pair {
static const Type Mask = (Type(0) - 1) >> HalfBits;
Type a = lhs.hi >> HalfBits, b = lhs.hi & Mask, c = lhs.lo >> HalfBits, d = lhs.lo & Mask;
Type dd = square(d), dc = d * c, db = d * b, da = d * a;
Type cc = square(c), cb = c * b;
Pair r0 = Pair(dd);
Pair r1 = Pair(dc) + Pair(dc) + Pair(r0 >> HalfBits);
Pair r2 = Pair(db) + Pair(cc) + Pair(db) + Pair(r1 >> HalfBits);
Pair r3 = Pair(da) + Pair(cb) + Pair(cb) + Pair(da) + Pair(r2 >> HalfBits);
return {(r3.lo & Mask) << HalfBits | (r2.lo & Mask), (r1.lo & Mask) << HalfBits | (r0.lo & Mask)};
}
//Bits * Bits => 2 * Bits
inline auto square(const Pair& lhs, Pair& hi, Pair& lo) -> void {
static const Type Mask = (Type(0) - 1) >> HalfBits;
Type a = lhs.hi >> HalfBits, b = lhs.hi & Mask, c = lhs.lo >> HalfBits, d = lhs.lo & Mask;
Type dd = square(d), dc = d * c, db = d * b, da = d * a;
Type cc = square(c), cb = c * b, ca = c * a;
Type bb = square(b), ba = b * a;
Type aa = square(a);
Pair r0 = Pair(dd);
Pair r1 = Pair(dc) + Pair(dc) + Pair(r0 >> HalfBits);
Pair r2 = Pair(db) + Pair(cc) + Pair(db) + Pair(r1 >> HalfBits);
Pair r3 = Pair(da) + Pair(cb) + Pair(cb) + Pair(da) + Pair(r2 >> HalfBits);
Pair r4 = Pair(ca) + Pair(bb) + Pair(ca) + Pair(r3 >> HalfBits);
Pair r5 = Pair(ba) + Pair(ba) + Pair(r4 >> HalfBits);
Pair r6 = Pair(aa) + Pair(r5 >> HalfBits);
Pair r7 = Pair(r6 >> HalfBits);
hi = {(r7.lo & Mask) << HalfBits | (r6.lo & Mask), (r5.lo & Mask) << HalfBits | (r4.lo & Mask)};
lo = {(r3.lo & Mask) << HalfBits | (r2.lo & Mask), (r1.lo & Mask) << HalfBits | (r0.lo & Mask)};
}
//Bits * Bits => Bits
alwaysinline auto mul(const Pair& lhs, const Pair& rhs) -> Pair {
static const Type Mask = (Type(0) - 1) >> HalfBits;
Type a = lhs.hi >> HalfBits, b = lhs.hi & Mask, c = lhs.lo >> HalfBits, d = lhs.lo & Mask;
Type e = rhs.hi >> HalfBits, f = rhs.hi & Mask, g = rhs.lo >> HalfBits, h = rhs.lo & Mask;
Pair r0 = Pair(d * h);
Pair r1 = Pair(c * h) + Pair(d * g) + Pair(r0 >> HalfBits);
Pair r2 = Pair(b * h) + Pair(c * g) + Pair(d * f) + Pair(r1 >> HalfBits);
Pair r3 = Pair(a * h) + Pair(b * g) + Pair(c * f) + Pair(d * e) + Pair(r2 >> HalfBits);
return {(r3.lo & Mask) << HalfBits | (r2.lo & Mask), (r1.lo & Mask) << HalfBits | (r0.lo & Mask)};
}
//Bits * Bits => 2 * Bits
alwaysinline auto mul(const Pair& lhs, const Pair& rhs, Pair& hi, Pair& lo) -> void {
static const Type Mask = (Type(0) - 1) >> HalfBits;
Type a = lhs.hi >> HalfBits, b = lhs.hi & Mask, c = lhs.lo >> HalfBits, d = lhs.lo & Mask;
Type e = rhs.hi >> HalfBits, f = rhs.hi & Mask, g = rhs.lo >> HalfBits, h = rhs.lo & Mask;
Pair r0 = Pair(d * h);
Pair r1 = Pair(c * h) + Pair(d * g) + Pair(r0 >> HalfBits);
Pair r2 = Pair(b * h) + Pair(c * g) + Pair(d * f) + Pair(r1 >> HalfBits);
Pair r3 = Pair(a * h) + Pair(b * g) + Pair(c * f) + Pair(d * e) + Pair(r2 >> HalfBits);
Pair r4 = Pair(a * g) + Pair(b * f) + Pair(c * e) + Pair(r3 >> HalfBits);
Pair r5 = Pair(a * f) + Pair(b * e) + Pair(r4 >> HalfBits);
Pair r6 = Pair(a * e) + Pair(r5 >> HalfBits);
Pair r7 = Pair(r6 >> HalfBits);
hi = {(r7.lo & Mask) << HalfBits | (r6.lo & Mask), (r5.lo & Mask) << HalfBits | (r4.lo & Mask)};
lo = {(r3.lo & Mask) << HalfBits | (r2.lo & Mask), (r1.lo & Mask) << HalfBits | (r0.lo & Mask)};
}
alwaysinline auto div(const Pair& lhs, const Pair& rhs, Pair& quotient, Pair& remainder) -> void {
if(!rhs) throw std::runtime_error("division by zero");
quotient = 0, remainder = lhs;
if(!lhs || lhs < rhs) return;
auto count = bits(lhs) - bits(rhs);
Pair x = rhs << count;
Pair y = Pair(1) << count;
if(x > remainder) x >>= 1, y >>= 1;
while(remainder >= rhs) {
if(remainder >= x) remainder -= x, quotient |= y;
x >>= 1, y >>= 1;
}
}
template<typename T> alwaysinline auto shl(const Pair& lhs, const T& rhs) -> Pair {
if(!rhs) return lhs;
auto shift = (uint)rhs;
if(shift < TypeBits) {
return {lhs.hi << shift | lhs.lo >> (TypeBits - shift), lhs.lo << shift};
} else {
return {lhs.lo << (shift - TypeBits), 0};
}
}
template<typename T> alwaysinline auto shr(const Pair& lhs, const T& rhs) -> Pair {
if(!rhs) return lhs;
auto shift = (uint)rhs;
if(shift < TypeBits) {
return {lhs.hi >> shift, lhs.hi << (TypeBits - shift) | lhs.lo >> shift};
} else {
return {0, lhs.hi >> (shift - TypeBits)};
}
}
template<typename T> alwaysinline auto rol(const Pair& lhs, const T& rhs) -> Pair {
return lhs << rhs | lhs >> (PairBits - rhs);
}
template<typename T> alwaysinline auto ror(const Pair& lhs, const T& rhs) -> Pair {
return lhs >> rhs | lhs << (PairBits - rhs);
}
#define EI enable_if_t<is_integral<T>::value>
template<typename T, EI> auto& operator*= (T& lhs, const Pair& rhs) { return lhs = lhs * T(rhs); }
template<typename T, EI> auto& operator/= (T& lhs, const Pair& rhs) { return lhs = lhs / T(rhs); }
template<typename T, EI> auto& operator%= (T& lhs, const Pair& rhs) { return lhs = lhs % T(rhs); }
template<typename T, EI> auto& operator+= (T& lhs, const Pair& rhs) { return lhs = lhs + T(rhs); }
template<typename T, EI> auto& operator-= (T& lhs, const Pair& rhs) { return lhs = lhs - T(rhs); }
template<typename T, EI> auto& operator<<=(T& lhs, const Pair& rhs) { return lhs = lhs << T(rhs); }
template<typename T, EI> auto& operator>>=(T& lhs, const Pair& rhs) { return lhs = lhs >> T(rhs); }
template<typename T, EI> auto& operator&= (T& lhs, const Pair& rhs) { return lhs = lhs & T(rhs); }
template<typename T, EI> auto& operator|= (T& lhs, const Pair& rhs) { return lhs = lhs | T(rhs); }
template<typename T, EI> auto& operator^= (T& lhs, const Pair& rhs) { return lhs = lhs ^ T(rhs); }
template<typename T, EI> auto operator* (const T& lhs, const Pair& rhs) { return Cast(lhs) * Cast(rhs); }
template<typename T, EI> auto operator/ (const T& lhs, const Pair& rhs) { return Cast(lhs) / Cast(rhs); }
template<typename T, EI> auto operator% (const T& lhs, const Pair& rhs) { return Cast(lhs) % Cast(rhs); }
template<typename T, EI> auto operator+ (const T& lhs, const Pair& rhs) { return Cast(lhs) + Cast(rhs); }
template<typename T, EI> auto operator- (const T& lhs, const Pair& rhs) { return Cast(lhs) - Cast(rhs); }
template<typename T, EI> auto operator<<(const T& lhs, const Pair& rhs) { return Cast(lhs) << Cast(rhs); }
template<typename T, EI> auto operator>>(const T& lhs, const Pair& rhs) { return Cast(lhs) >> Cast(rhs); }
template<typename T, EI> auto operator& (const T& lhs, const Pair& rhs) { return Cast(lhs) & Cast(rhs); }
template<typename T, EI> auto operator| (const T& lhs, const Pair& rhs) { return Cast(lhs) | Cast(rhs); }
template<typename T, EI> auto operator^ (const T& lhs, const Pair& rhs) { return Cast(lhs) ^ Cast(rhs); }
template<typename T, EI> auto operator==(const T& lhs, const Pair& rhs) { return Cast(lhs) == Cast(rhs); }
template<typename T, EI> auto operator!=(const T& lhs, const Pair& rhs) { return Cast(lhs) != Cast(rhs); }
template<typename T, EI> auto operator>=(const T& lhs, const Pair& rhs) { return Cast(lhs) >= Cast(rhs); }
template<typename T, EI> auto operator<=(const T& lhs, const Pair& rhs) { return Cast(lhs) <= Cast(rhs); }
template<typename T, EI> auto operator> (const T& lhs, const Pair& rhs) { return Cast(lhs) > Cast(rhs); }
template<typename T, EI> auto operator< (const T& lhs, const Pair& rhs) { return Cast(lhs) < Cast(rhs); }
#undef EI
template<> struct stringify<Pair> {
stringify(Pair source) {
char _output[1 + sizeof(Pair) * 3];
auto p = (char*)&_output;
do {
Pair quotient, remainder;
div(source, 10, quotient, remainder);
*p++ = '0' + remainder;
source = quotient;
} while(source);
_size = p - _output;
*p = 0;
for(int x = _size - 1, y = 0; x >= 0 && y < _size; x--, y++) _data[x] = _output[y];
}
auto data() const -> const char* { return _data; }
auto size() const -> uint { return _size; }
char _data[1 + sizeof(Pair) * 3];
uint _size;
};
inline auto to_vector(Pair value) -> vector<uint8_t> {
vector<uint8_t> result;
result.resize(PairBits / 8);
for(auto& byte : result) {
byte = value;
value >>= 8;
}
return result;
}
}
#undef ConcatenateType
#undef DeclareType
#undef Pair
#undef Type
#undef Half
#undef Cast

View File

@ -0,0 +1,39 @@
#pragma once
namespace nall {
template<typename T, enable_if_t<is_unsigned<T>::value>> alwaysinline auto upper(T value) -> T {
return value >> sizeof(T) * 4;
}
template<typename T, enable_if_t<is_unsigned<T>::value>> alwaysinline auto lower(T value) -> T {
static const T Mask = T(0) - 1 >> sizeof(T) * 4;
return value & Mask;
}
alwaysinline auto square(uintmax value) -> uintmax {
return value * value;
}
template<typename T, typename U> alwaysinline auto rol(const T& lhs, const U& rhs, enable_if_t<is_unsigned<T>::value>* = 0) -> T {
return lhs << rhs | lhs >> (sizeof(T) * 8 - rhs);
}
template<typename T, typename U> alwaysinline auto ror(const T& lhs, const U& rhs, enable_if_t<is_unsigned<T>::value>* = 0) -> T {
return lhs >> rhs | lhs << (sizeof(T) * 8 - rhs);
}
#if INTMAX_BITS >= 128
inline auto operator"" _u128(const char* s) -> uint128_t {
uint128_t p = 0;
while(*s) {
auto c = *s++;
if(c == '\'') continue;
if(c < '0' || c > '9') break;
p = (p << 3) + (p << 1) + (c - '0');
}
return p;
}
#endif
}

View File

@ -42,14 +42,14 @@ auto Archive::create(const string& beatname, const string& pathname, const strin
auto size = input.size();
beat.writevu(size);
while(size--) beat.write(input.read());
beat.writel(input.checksum.value(), 4);
beat.writel(input.checksum.digest().hex(), 4);
} else {
beat.writevu(0);
beat.writel(0x00000000, 4);
}
}
beat.writel(beat.checksum.value(), 4);
beat.writel(beat.checksum.digest().hex(), 4);
return true;
}
@ -82,11 +82,11 @@ auto Archive::unpack(const string& beatname, const string& pathname) -> bool {
auto size = beat.readvu();
while(size--) output.write(beat.read());
if(beat.readl(4) != output.checksum.value()) return false;
if(beat.readl(4) != output.checksum.digest().hex()) return false;
}
}
uint32_t checksum = beat.checksum.value();
uint32_t checksum = beat.checksum.digest().hex();
return beat.readl(4) == checksum;
}
@ -113,7 +113,7 @@ auto Archive::extract(const string& beatname, const string& filename) -> vector<
result.resize(size);
beat.checksum.reset();
for(auto n : range(size)) result[n] = beat.read();
uint32_t checksum = beat.checksum.value();
uint32_t checksum = beat.checksum.digest().hex();
if(beat.readl(4) != checksum) return {};
return result;
}

View File

@ -67,7 +67,7 @@ auto bpsdelta::create(const string& filename, const string& metadata) -> bool {
auto write = [&](uint8_t data) {
modifyFile.write(data);
modifyChecksum.data(data);
modifyChecksum.input(data);
};
auto encode = [&](uint64_t data) {
@ -102,7 +102,7 @@ auto bpsdelta::create(const string& filename, const string& metadata) -> bool {
//source tree creation
for(uint offset = 0; offset < sourceSize; offset++) {
uint16_t symbol = sourceData[offset + 0];
sourceChecksum.data(symbol);
sourceChecksum.input(symbol);
if(offset < sourceSize - 1) symbol |= sourceData[offset + 1] << 8;
Node *node = new Node;
node->offset = offset;
@ -198,10 +198,10 @@ auto bpsdelta::create(const string& filename, const string& metadata) -> bool {
targetReadFlush();
for(uint n = 0; n < 32; n += 8) write(sourceChecksum.value() >> n);
uint32_t targetChecksum = Hash::CRC32(targetData, targetSize).value();
for(uint n = 0; n < 32; n += 8) write(sourceChecksum.digest().hex() >> n);
uint32_t targetChecksum = Hash::CRC32(targetData, targetSize).digest().hex();
for(uint n = 0; n < 32; n += 8) write(targetChecksum >> n);
uint32_t outputChecksum = modifyChecksum.value();
uint32_t outputChecksum = modifyChecksum.digest().hex();
for(uint n = 0; n < 32; n += 8) write(outputChecksum >> n);
modifyFile.close();

View File

@ -11,12 +11,12 @@ struct File : file {
auto File::read() -> uint8_t {
uint8_t data = file::read();
checksum.data(data);
checksum.input(data);
return data;
}
auto File::write(uint8_t data) -> void {
checksum.data(data);
checksum.input(data);
return file::write(data);
}

View File

@ -59,7 +59,7 @@ auto bpslinear::create(const string& filename, const string& metadata) -> bool {
auto write = [&](uint8_t data) {
modifyFile.write(data);
modifyChecksum.data(data);
modifyChecksum.input(data);
};
auto encode = [&](uint64_t data) {
@ -134,11 +134,11 @@ auto bpslinear::create(const string& filename, const string& metadata) -> bool {
targetReadFlush();
uint32_t sourceChecksum = Hash::CRC32(sourceData, sourceSize).value();
uint32_t sourceChecksum = Hash::CRC32(sourceData, sourceSize).digest().hex();
for(uint n = 0; n < 32; n += 8) write(sourceChecksum >> n);
uint32_t targetChecksum = Hash::CRC32(targetData, targetSize).value();
uint32_t targetChecksum = Hash::CRC32(targetData, targetSize).digest().hex();
for(uint n = 0; n < 32; n += 8) write(targetChecksum >> n);
uint32_t outputChecksum = modifyChecksum.value();
uint32_t outputChecksum = modifyChecksum.digest().hex();
for(uint n = 0; n < 32; n += 8) write(outputChecksum >> n);
modifyFile.close();

View File

@ -77,7 +77,7 @@ auto bpsmetadata::save(const string& filename, const string& metadata) -> bool {
auto write = [&](uint8_t data) {
targetFile.write(data);
checksum.data(data);
checksum.input(data);
};
auto encode = [&](uint64_t data) {
@ -103,7 +103,7 @@ auto bpsmetadata::save(const string& filename, const string& metadata) -> bool {
for(uint n = 0; n < targetLength; n++) write(metadata[n]);
uint length = sourceFile.size() - sourceFile.offset() - 4;
for(uint n = 0; n < length; n++) write(read());
uint32_t outputChecksum = checksum.value();
uint32_t outputChecksum = checksum.digest().hex();
for(uint n = 0; n < 32; n += 8) write(outputChecksum >> n);
targetFile.close();

View File

@ -48,14 +48,14 @@ struct bpsmulti {
for(uint n = 0; n < sp.size(); n++) {
uint8_t byte = sp.read();
if(identical && byte != dp.read()) identical = false;
cksum.data(byte);
cksum.input(byte);
}
if(identical) {
writeNumber(MirrorFile | ((targetName.length() - 1) << 2));
writeString(targetName);
writeNumber(OriginSource);
writeChecksum(cksum.value());
writeChecksum(cksum.digest().hex());
} else {
writeNumber(ModifyFile | ((targetName.length() - 1) << 2));
writeString(targetName);
@ -83,12 +83,12 @@ struct bpsmulti {
auto buffer = file::read({targetPath, targetName});
writeNumber(buffer.size());
for(auto& byte : buffer) write(byte);
writeChecksum(Hash::CRC32(buffer.data(), buffer.size()).value());
writeChecksum(Hash::CRC32(buffer.data(), buffer.size()).digest().hex());
}
}
//checksum
writeChecksum(checksum.value());
writeChecksum(checksum.digest().hex());
fp.close();
return true;
}
@ -141,7 +141,7 @@ struct bpsmulti {
}
}
uint32_t cksum = checksum.value();
uint32_t cksum = checksum.digest().hex();
if(read() != (uint8_t)(cksum >> 0)) return false;
if(read() != (uint8_t)(cksum >> 8)) return false;
if(read() != (uint8_t)(cksum >> 16)) return false;
@ -171,7 +171,7 @@ protected:
auto write(uint8_t data) -> void {
fp.write(data);
checksum.data(data);
checksum.input(data);
}
auto writeNumber(uint64_t data) -> void {
@ -202,7 +202,7 @@ protected:
//apply() functions
auto read() -> uint8_t {
uint8_t data = fp.read();
checksum.data(data);
checksum.input(data);
return data;
}

View File

@ -132,7 +132,7 @@ auto bpspatch::apply() -> result {
auto read = [&]() -> uint8_t {
uint8_t data = modifyData[modifyOffset++];
modifyChecksum.data(data);
modifyChecksum.input(data);
return data;
};
@ -150,7 +150,7 @@ auto bpspatch::apply() -> result {
auto write = [&](uint8_t data) {
targetData[outputOffset++] = data;
targetChecksum.data(data);
targetChecksum.input(data);
};
if(read() != 'B') return result::patch_invalid_header;
@ -199,13 +199,13 @@ auto bpspatch::apply() -> result {
uint32_t modifySourceChecksum = 0, modifyTargetChecksum = 0, modifyModifyChecksum = 0;
for(uint n = 0; n < 32; n += 8) modifySourceChecksum |= read() << n;
for(uint n = 0; n < 32; n += 8) modifyTargetChecksum |= read() << n;
uint32_t checksum = modifyChecksum.value();
uint32_t checksum = modifyChecksum.digest().hex();
for(uint n = 0; n < 32; n += 8) modifyModifyChecksum |= read() << n;
uint32_t sourceChecksum = Hash::CRC32(sourceData, modifySourceSize).value();
uint32_t sourceChecksum = Hash::CRC32(sourceData, modifySourceSize).digest().hex();
if(sourceChecksum != modifySourceChecksum) return result::source_checksum_invalid;
if(targetChecksum.value() != modifyTargetChecksum) return result::target_checksum_invalid;
if(targetChecksum.digest().hex() != modifyTargetChecksum) return result::target_checksum_invalid;
if(checksum != modifyModifyChecksum) return result::patch_checksum_invalid;
return result::success;

View File

@ -1,12 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIByTCCAU6gAwIBAgIJAMGBxB7ujnmaMAoGCCqGSM49BAMDMB4xDTALBgNVBAMM
BGJ5dXUxDTALBgNVBAoMBGJ5dXUwIBcNMTYwOTExMTM1MjE3WhgPMjA5MTA4MjQx
MzUyMTdaMB4xDTALBgNVBAMMBGJ5dXUxDTALBgNVBAoMBGJ5dXUwdjAQBgcqhkjO
PQIBBgUrgQQAIgNiAATgdIzJOkXMo3vfw+wshinYYt76IAox5sRcXYfbkTHZ5dGU
Sf/DlrCe/kTIhXe6mKUI6eUjPH7U5UruvHtwi6I7QILHoar1tp4rVGKp7mB3KuIS
qfuu90JhXMfUcwQp3WOjVjBUMBIGA1UdEwEB/wQIMAYBAf8CAQAwHQYDVR0OBBYE
FKD7mEF6/bmtxOUSu05E0iYjRCrJMB8GA1UdIwQYMBaAFKD7mEF6/bmtxOUSu05E
0iYjRCrJMAoGCCqGSM49BAMDA2kAMGYCMQD3Nv8o4qbHOZUd8GUh4ye6Y08WkJ2w
8BZWTJFzAp+4nP9XZJeROQJd97+kQOCdLAICMQC2DtybVIQXaxefAaGi7IvtYcbL
fAWdtu5/dc7bzMpy9GicQkpw8uluxauX8gdnU/4=
-----END CERTIFICATE-----

View File

@ -1,13 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIB6jCCAXCgAwIBAgIJAOrEeJHQ9mppMAoGCCqGSM49BAMDMB4xDTALBgNVBAMM
BGJ5dXUxDTALBgNVBAoMBGJ5dXUwIBcNMTYwOTExMTM1NDIwWhgPMjA5MTA4MjQx
MzU0MjBaMCIxETAPBgNVBAMMCGJ5dXUubmV0MQ0wCwYDVQQKDARieXV1MHYwEAYH
KoZIzj0CAQYFK4EEACIDYgAEL4l9yJtcslBRuaTr7wHJ/Wc7DIspKGv2S2+LYsxE
k3dZI902+J726IX2yiurWlLUEc3B+ooKs3VmhaW1QsStKdYVJVVGBD29zz3rvD/V
oeWjw63yZrSqNQ5S41qXNcMho3QwcjAMBgNVHRMBAf8EAjAAMCIGA1UdEQEB/wQY
MBaCCGJ5dXUubmV0ggoqLmJ5dXUubmV0MB0GA1UdDgQWBBTeXV7JKLjCikQbk+Um
ayFF8yRiSTAfBgNVHSMEGDAWgBSg+5hBev25rcTlErtORNImI0QqyTAKBggqhkjO
PQQDAwNoADBlAjEAgk0ud6h0OAfWNH6pSvMiyHAWQuh24cvkQY3mUNsZzAy36QEQ
X4UBWewxz1lyaFzLAjACXJZ1rZsMnGIgWXvFAsO2v53A612Ba3vH76naExASKbmx
VafrFb6bHXEc3aH/Xws=
-----END CERTIFICATE-----

View File

@ -1,13 +0,0 @@
-----BEGIN CERTIFICATE-----
MIIB6jCCAXCgAwIBAgIJAOrEeJHQ9mpoMAoGCCqGSM49BAMDMB4xDTALBgNVBAMM
BGJ5dXUxDTALBgNVBAoMBGJ5dXUwIBcNMTYwOTExMTM1MzU1WhgPMjA5MTA4MjQx
MzUzNTVaMCIxETAPBgNVBAMMCGJ5dXUub3JnMQ0wCwYDVQQKDARieXV1MHYwEAYH
KoZIzj0CAQYFK4EEACIDYgAEH+ny1an5De9P1TJ0vmpGlpmrZszuV1lKTPut28Vx
98ieuBdmSNG493sJ+ga+adXPtItkck5M0jITR1NxcWvVlZtJG8L6ctEuVF6smkoy
1dbxzEeTIs+xjRQqaLN4U67ho3QwcjAMBgNVHRMBAf8EAjAAMCIGA1UdEQEB/wQY
MBaCCGJ5dXUub3JnggoqLmJ5dXUub3JnMB0GA1UdDgQWBBRhhKSsc+qUaBUNiyJX
j17UDBFuuTAfBgNVHSMEGDAWgBSg+5hBev25rcTlErtORNImI0QqyTAKBggqhkjO
PQQDAwNoADBlAjEApEbI/wT/cU7DRFvBEmfFMtVDJCJCTz4UEo1lJI9SPOEtgX3x
gJZg4deqeoAEffVGAjB2RWI1UPi/jnpJwTsuw4sp5UqFhY48qfqddPiSO4qlmb8s
1aEdP6gHoji22pHrKbY=
-----END CERTIFICATE-----

78
nall/cipher/chacha20.hpp Normal file
View File

@ -0,0 +1,78 @@
#pragma once
#include <nall/arithmetic.hpp>
namespace nall { namespace Cipher {
struct ChaCha20 {
auto initialize(uint256_t key, uint64_t nonce, uint64_t counter = 0) -> void {
static const uint256_t sigma = 0x6b20657479622d323320646e61707865_u256; //"expand 32-byte k"
input[ 0] = sigma >> 0;
input[ 1] = sigma >> 32;
input[ 2] = sigma >> 64;
input[ 3] = sigma >> 96;
input[ 4] = key >> 0;
input[ 5] = key >> 32;
input[ 6] = key >> 64;
input[ 7] = key >> 96;
input[ 8] = key >> 128;
input[ 9] = key >> 160;
input[10] = key >> 192;
input[11] = key >> 224;
input[12] = counter >> 0;
input[13] = counter >> 32;
input[14] = nonce >> 0;
input[15] = nonce >> 32;
offset = 0;
}
auto encrypt(const uint8_t* input, uint8_t* output, uint64_t length) -> void {
while(length--) {
if(!offset) cipher();
auto byte = offset++;
*output++ = *input++ ^ (block[byte >> 2] >> (byte & 3) * 8);
offset &= 63;
}
}
auto decrypt(const uint8_t* input, uint8_t* output, uint64_t length) -> void {
encrypt(input, output, length); //reciprocal cipher
}
private:
inline auto rol(uint32_t value, uint bits) -> uint32_t {
return value << bits | value >> (32 - bits);
}
auto quarterRound(uint32_t x[16], uint a, uint b, uint c, uint d) -> void {
x[a] += x[b]; x[d] = rol(x[d] ^ x[a], 16);
x[c] += x[d]; x[b] = rol(x[b] ^ x[c], 12);
x[a] += x[b]; x[d] = rol(x[d] ^ x[a], 8);
x[c] += x[d]; x[b] = rol(x[b] ^ x[c], 7);
}
auto cipher() -> void {
memory::copy(block, input, 64);
for(auto n : range(10)) {
quarterRound(block, 0, 4, 8, 12);
quarterRound(block, 1, 5, 9, 13);
quarterRound(block, 2, 6, 10, 14);
quarterRound(block, 3, 7, 11, 15);
quarterRound(block, 0, 5, 10, 15);
quarterRound(block, 1, 6, 11, 12);
quarterRound(block, 2, 7, 8, 13);
quarterRound(block, 3, 4, 9, 14);
}
for(auto n : range(16)) {
block[n] += input[n];
}
if(!++input[12]) ++input[13];
}
uint32_t input[16];
uint32_t block[16];
uint64_t offset;
};
}}

23
nall/decode/base57.hpp Normal file
View File

@ -0,0 +1,23 @@
#pragma once
#include <nall/arithmetic.hpp>
namespace nall { namespace Decode {
template<typename T> inline auto Base57(const string& value) -> T {
T result = 0;
for(auto n : rrange(value.size())) {
auto byte = value[n];
if(byte >= '2' && byte <= '9') byte -= '2' - 0;
else if(byte >= 'A' && byte <= 'H') byte -= 'A' - 8;
else if(byte >= 'J' && byte <= 'N') byte -= 'J' - 16;
else if(byte >= 'P' && byte <= 'Z') byte -= 'P' - 21;
else if(byte >= 'a' && byte <= 'k') byte -= 'a' - 32;
else if(byte >= 'm' && byte <= 'z') byte -= 'm' - 43;
else return 0;
result = result * 57 + byte;
}
return result;
}
}}

View File

@ -5,13 +5,19 @@ namespace nall { namespace Decode {
//returns empty string on malformed content
inline auto URL(const string& input) -> string {
string output;
for(unsigned n = 0; n < input.size();) {
for(uint n = 0; n < input.size();) {
char c = input[n];
//unreserved characters
if(c >= 'A' && c <= 'Z') { output.append(c); n++; continue; }
if(c >= 'a' && c <= 'z') { output.append(c); n++; continue; }
if(c >= '0' && c <= '9') { output.append(c); n++; continue; }
if(c == '-' || c == '_' || c == '.' || c == '~') { output.append(c); n++; continue; }
//special characters
if(c == '+') { output.append(' '); n++; continue; }
//reserved characters
if(c != '%' || n + 2 >= input.size()) return "";
char hi = input[n + 1];
char lo = input[n + 2];

View File

@ -0,0 +1,55 @@
#pragma once
#if defined(EC_REFERENCE)
#include <nall/elliptic-curve/modulo25519-reference.hpp>
#else
#include <nall/elliptic-curve/modulo25519.hpp>
#endif
namespace nall { namespace EllipticCurve {
struct Curve25519 {
auto sharedKey(uint256_t secretKey, uint256_t basepoint = 9) const -> uint256_t {
secretKey &= ((0_u256 - 1) >> 2) - 7;
secretKey |= 1_u256 << 254;
basepoint &= (0_u256 - 1) >> 1;
point p = scalarMultiply(secretKey, modP(basepoint));
return p.x * p.z.reciprocal();
}
private:
using field = Modulo25519;
struct point { field x, z; };
inline auto montgomeryAdd(point p, point q, field b) const -> point {
return {
(p.x * q.x - p.z * q.z).square(),
(p.x * q.z - p.z * q.x).square() * b
};
}
inline auto montgomeryDouble(point p) const -> point {
field a = (p.x + p.z).square();
field b = (p.x - p.z).square();
field c = a - b;
field d = a + c * 121665;
return {a * b, c * d};
}
inline auto scalarMultiply(uint256_t e, field b) const -> point {
point p{1, 0}, q{b, 1};
for(uint n : rrange(255)) {
bool bit = e >> n & 1;
cswap(bit, p.x, q.x);
cswap(bit, p.z, q.z);
q = montgomeryAdd(p, q, b);
p = montgomeryDouble(p);
cswap(bit, p.x, q.x);
cswap(bit, p.z, q.z);
}
return p;
}
};
}}

View File

@ -0,0 +1,164 @@
#pragma once
#include <nall/hash/sha512.hpp>
#if defined(EC_REFERENCE)
#include <nall/elliptic-curve/modulo25519-reference.hpp>
#else
#include <nall/elliptic-curve/modulo25519.hpp>
#endif
namespace nall { namespace EllipticCurve {
struct Ed25519 {
Ed25519() {
field y = field(4) * field(5).reciprocal();
field x = recoverX(y);
point B{x, y, 1, x * y};
for(uint n : range(253)) {
Bscalar[n] = B;
B = edwardsDouble(B);
}
}
auto publicKey(uint256_t privateKey) const -> uint256_t {
auto H = uint512_t{Hash::SHA512(to_vector(privateKey)).output()};
auto a = clamp(H);
auto A = compress(scalarMultiplyB(modL(a)));
return A;
}
auto sign(const vector<uint8_t>& message, uint256_t privateKey) const -> uint512_t {
auto H = uint512_t{Hash::SHA512(to_vector(privateKey)).output()};
auto a = clamp(H);
auto A = compress(scalarMultiplyB(modL(a)));
Hash::SHA512 hash1;
hash1.input(to_vector(upper(H)));
hash1.input(message);
auto r = uint512_t{hash1.output()};
auto R = compress(scalarMultiplyB(modL(r)));
Hash::SHA512 hash2;
hash2.input(to_vector(R));
hash2.input(to_vector(A));
hash2.input(message);
uint512_t k = modL(uint512_t{hash2.output()});
uint256_t S = modL(k * a + r);
return uint512_t(S) << 256 | R;
}
auto verify(const vector<uint8_t>& message, uint512_t signature, uint256_t publicKey) const -> bool {
auto R = decompress(lower(signature));
auto A = decompress(publicKey);
if(!R || !A) return false;
uint256_t S = upper(signature);
Hash::SHA512 hash;
hash.input(to_vector(lower(signature)));
hash.input(to_vector(publicKey));
hash.input(message);
auto r = uint512_t{hash.output()};
auto p = scalarMultiplyB(modL(S));
auto q = edwardsAdd(R(), scalarMultiply(modL(r), A()));
if(!onCurve(p) || !onCurve(q)) return false;
if(p.x * q.z - q.x * p.z) return false;
if(p.y * q.z - q.y * p.z) return false;
return true;
}
private:
using field = Modulo25519;
struct point { field x, y, z, t; };
point Bscalar[253];
const field D = -field(121665) * field(121666).reciprocal();
inline auto clamp(uint256_t p) const -> uint256_t {
p &= ((0_u256 - 1) >> 2) - 7;
p |= 1_u256 << 254;
return p;
}
inline auto recoverX(field y) const -> field {
field y2 = y.square();
field x = ((y2 - 1) * (D * y2 + 1).reciprocal()).squareRoot();
return x() & 1 ? -x : x;
}
inline auto onCurve(point p) const -> bool {
if(!p.z) return false;
if(p.x * p.y != p.z * p.t) return false;
if(p.y.square() - p.x.square() - p.z.square() - p.t.square() * D) return false;
return true;
}
inline auto decompress(uint256_t c) const -> maybe<point> {
field y = c & (1_u256 << 255) - 1;
field x = recoverX(y);
if(c >> 255) x = -x;
point p{x, y, 1, x * y};
if(!onCurve(p)) return nothing;
return p;
}
inline auto compress(point p) const -> uint256_t {
field r = p.z.reciprocal();
field x = p.x * r;
field y = p.y * r;
return (x() & 1) << 255 | (y() & ((0_u256 - 1) >> 1));
}
inline auto edwardsDouble(point p) const -> point {
field a = p.x.square();
field b = p.y.square();
field c = p.z.square();
field d = -a;
field e = (p.x + p.y).square() - a - b;
field g = d + b;
field f = g - (c + c);
field h = d - b;
return {e * f, g * h, f * g, e * h};
}
inline auto edwardsAdd(point p, point q) const -> point {
field a = (p.y - p.x) * (q.y - q.x);
field b = (p.y + p.x) * (q.y + q.x);
field c = (p.t + p.t) * q.t * D;
field d = (p.z + p.z) * q.z;
field e = b - a;
field f = d - c;
field g = d + c;
field h = b + a;
return {e * f, g * h, f * g, e * h};
}
inline auto scalarMultiply(uint512_t e, point q) const -> point {
point p{0, 1, 1, 0}, c;
for(uint n : rrange(253)) {
p = edwardsDouble(p);
c = edwardsAdd(p, q);
bool bit = e >> n & 1;
cmove(bit, p.x, c.x);
cmove(bit, p.y, c.y);
cmove(bit, p.z, c.z);
cmove(bit, p.t, c.t);
}
return p;
}
inline auto scalarMultiplyB(uint512_t e) const -> point {
point p{0, 1, 1, 0}, c;
for(uint n : rrange(253)) {
bool bit = e >> n & 1;
c = edwardsAdd(p, Bscalar[n]);
cmove(bit, p.x, c.x);
cmove(bit, p.y, c.y);
cmove(bit, p.z, c.z);
cmove(bit, p.t, c.t);
}
return p;
}
};
}}

View File

@ -0,0 +1,79 @@
#pragma once
#include <nall/arithmetic/barrett.hpp>
namespace nall { namespace EllipticCurve {
static const uint256_t P = (1_u256 << 255) - 19;
static const uint256_t L = (1_u256 << 252) + 27742317777372353535851937790883648493_u256;
static BarrettReduction modP{P};
static BarrettReduction modL{L};
struct Modulo25519 : uint256_t {
using type = Modulo25519;
using uint256_t::uint256_t;
alwaysinline auto operator()() const -> uint256_t {
return *this;
}
alwaysinline auto operator-() const -> type {
return P.operator-(*this);
}
template<typename T> alwaysinline auto operator+(const T& rhs) const -> type {
auto lhs = (uint512_t)*this + rhs;
if(lhs >= P) lhs -= P;
return lhs;
}
template<typename T> alwaysinline auto operator-(const T& rhs) const -> type {
auto lhs = (uint512_t)*this;
if(lhs < rhs) lhs += P;
return lhs - rhs;
}
template<typename T> alwaysinline auto operator*(const T& rhs) const -> type {
uint256_t hi, lo;
nall::mul(*this, rhs, hi, lo);
return modP(uint512_t{hi, lo});
}
alwaysinline auto square() const -> type {
uint256_t hi, lo;
nall::square(*this, hi, lo);
return modP(uint512_t{hi, lo});
}
inline auto expmod(uint256_t e) const -> type {
type x = 1;
for(auto n : rrange(256)) {
x = x.square();
if(e >> n & 1) x = operator*(x);
}
return x;
}
inline auto reciprocal() const -> type {
return expmod(P - 2);
}
inline auto squareRoot() const -> type {
static const type i = type(2).expmod((P - 1) >> 2); //i = sqrt(-1)
type x = expmod((P + 3) >> 3);
if(operator!=(x.square())) x = x * i;
if(x & 1) x = -x;
return x;
}
};
inline auto cmove(bool bit, Modulo25519& lhs, const Modulo25519& rhs) -> void {
if(bit) lhs = rhs;
}
inline auto cswap(bool bit, Modulo25519& lhs, Modulo25519& rhs) -> void {
if(bit) swap(lhs, rhs);
}
}}

View File

@ -0,0 +1,234 @@
#pragma once
#include <nall/arithmetic/barrett.hpp>
namespace nall { namespace EllipticCurve {
static const uint256_t P = (1_u256 << 255) - 19;
static const uint256_t L = (1_u256 << 252) + 27742317777372353535851937790883648493_u256;
static BarrettReduction modP{P};
static BarrettReduction modL{L};
struct Modulo25519;
auto cmove(bool move, Modulo25519& l, const Modulo25519& r) -> void;
auto cswap(bool swap, Modulo25519& l, Modulo25519& r) -> void;
struct Modulo25519 {
using type = Modulo25519;
#define Mask ((1ull << 51) - 1)
inline Modulo25519() = default;
inline Modulo25519(const Modulo25519&) = default;
inline Modulo25519(uint64_t a, uint64_t b = 0, uint64_t c = 0, uint64_t d = 0, uint64_t e = 0) : l{a, b, c, d, e} {}
inline Modulo25519(uint256_t n) {
l[0] = n >> 0 & Mask;
l[1] = n >> 51 & Mask;
l[2] = n >> 102 & Mask;
l[3] = n >> 153 & Mask;
l[4] = n >> 204 & Mask;
}
inline auto operator()() const -> uint256_t { return operator uint256_t(); }
inline auto& operator[](uint index) { return l[index]; }
inline auto operator[](uint index) const { return l[index]; }
inline explicit operator bool() const {
return operator uint256_t();
}
inline operator uint256_t() const {
type o = *this;
o[1] += (o[0] >> 51); o[0] &= Mask;
o[2] += (o[1] >> 51); o[1] &= Mask;
o[3] += (o[2] >> 51); o[2] &= Mask;
o[4] += (o[3] >> 51); o[3] &= Mask;
o[0] += 19 * (o[4] >> 51); o[4] &= Mask;
o[1] += (o[0] >> 51); o[0] &= Mask;
o[2] += (o[1] >> 51); o[1] &= Mask;
o[3] += (o[2] >> 51); o[2] &= Mask;
o[4] += (o[3] >> 51); o[3] &= Mask;
o[0] += 19 * (o[4] >> 51); o[4] &= Mask;
o[0] += 19;
o[1] += (o[0] >> 51); o[0] &= Mask;
o[2] += (o[1] >> 51); o[1] &= Mask;
o[3] += (o[2] >> 51); o[2] &= Mask;
o[4] += (o[3] >> 51); o[3] &= Mask;
o[0] += 19 * (o[4] >> 51); o[4] &= Mask;
o[0] += Mask - 18;
o[1] += Mask;
o[2] += Mask;
o[3] += Mask;
o[4] += Mask;
o[1] += o[0] >> 51; o[0] &= Mask;
o[2] += o[1] >> 51; o[1] &= Mask;
o[3] += o[2] >> 51; o[2] &= Mask;
o[4] += o[3] >> 51; o[3] &= Mask;
o[4] &= Mask;
return (uint256_t)o[0] << 0 | (uint256_t)o[1] << 51 | (uint256_t)o[2] << 102 | (uint256_t)o[3] << 153 | (uint256_t)o[4] << 204;
}
inline auto operator!=(type r) const -> bool {
bool e = 1;
e &= l[0] == r[0];
e &= l[1] == r[1];
e &= l[2] == r[2];
e &= l[3] == r[3];
e &= l[4] == r[4];
return e == 0;
}
inline auto operator-() const -> type { //P - l
type o;
uint64_t c;
o[0] = 0xfffffffffffda - l[0]; c = o[0] >> 51; o[0] &= Mask;
o[1] = 0xffffffffffffe - l[1] + c; c = o[1] >> 51; o[1] &= Mask;
o[2] = 0xffffffffffffe - l[2] + c; c = o[2] >> 51; o[2] &= Mask;
o[3] = 0xffffffffffffe - l[3] + c; c = o[3] >> 51; o[3] &= Mask;
o[4] = 0xffffffffffffe - l[4] + c; c = o[4] >> 51; o[4] &= Mask;
o[0] += c * 19;
return o;
}
inline auto operator+(type r) const -> type {
type o;
uint64_t c;
o[0] = l[0] + r[0]; c = o[0] >> 51; o[0] &= Mask;
o[1] = l[1] + r[1] + c; c = o[1] >> 51; o[1] &= Mask;
o[2] = l[2] + r[2] + c; c = o[2] >> 51; o[2] &= Mask;
o[3] = l[3] + r[3] + c; c = o[3] >> 51; o[3] &= Mask;
o[4] = l[4] + r[4] + c; c = o[4] >> 51; o[4] &= Mask;
o[0] += c * 19;
return o;
}
inline auto operator-(type r) const -> type {
type o;
uint64_t c;
o[0] = l[0] + 0x1fffffffffffb4 - r[0]; c = o[0] >> 51; o[0] &= Mask;
o[1] = l[1] + 0x1ffffffffffffc - r[1] + c; c = o[1] >> 51; o[1] &= Mask;
o[2] = l[2] + 0x1ffffffffffffc - r[2] + c; c = o[2] >> 51; o[2] &= Mask;
o[3] = l[3] + 0x1ffffffffffffc - r[3] + c; c = o[3] >> 51; o[3] &= Mask;
o[4] = l[4] + 0x1ffffffffffffc - r[4] + c; c = o[4] >> 51; o[4] &= Mask;
o[0] += c * 19;
return o;
}
inline auto operator*(uint64_t scalar) const -> type {
type o;
uint128_t a;
a = (uint128_t)l[0] * scalar; o[0] = a & Mask;
a = (uint128_t)l[1] * scalar + (a >> 51 & Mask); o[1] = a & Mask;
a = (uint128_t)l[2] * scalar + (a >> 51 & Mask); o[2] = a & Mask;
a = (uint128_t)l[3] * scalar + (a >> 51 & Mask); o[3] = a & Mask;
a = (uint128_t)l[4] * scalar + (a >> 51 & Mask); o[4] = a & Mask;
o[0] += (a >> 51) * 19;
return o;
}
inline auto operator*(type r) const -> type {
uint128_t t[] = {
(uint128_t)r[0] * l[0],
(uint128_t)r[0] * l[1] + (uint128_t)r[1] * l[0],
(uint128_t)r[0] * l[2] + (uint128_t)r[1] * l[1] + (uint128_t)r[2] * l[0],
(uint128_t)r[0] * l[3] + (uint128_t)r[1] * l[2] + (uint128_t)r[2] * l[1] + (uint128_t)r[3] * l[0],
(uint128_t)r[0] * l[4] + (uint128_t)r[1] * l[3] + (uint128_t)r[2] * l[2] + (uint128_t)r[3] * l[1] + (uint128_t)r[4] * l[0]
};
r[1] *= 19, r[2] *= 19, r[3] *= 19, r[4] *= 19;
t[0] += (uint128_t)r[4] * l[1] + (uint128_t)r[3] * l[2] + (uint128_t)r[2] * l[3] + (uint128_t)r[1] * l[4];
t[1] += (uint128_t)r[4] * l[2] + (uint128_t)r[3] * l[3] + (uint128_t)r[2] * l[4];
t[2] += (uint128_t)r[4] * l[3] + (uint128_t)r[3] * l[4];
t[3] += (uint128_t)r[4] * l[4];
uint64_t c; r[0] = t[0] & Mask; c = (uint64_t)(t[0] >> 51);
t[1] += c; r[1] = t[1] & Mask; c = (uint64_t)(t[1] >> 51);
t[2] += c; r[2] = t[2] & Mask; c = (uint64_t)(t[2] >> 51);
t[3] += c; r[3] = t[3] & Mask; c = (uint64_t)(t[3] >> 51);
t[4] += c; r[4] = t[4] & Mask; c = (uint64_t)(t[4] >> 51);
r[0] += c * 19; c = r[0] >> 51; r[0] &= Mask;
r[1] += c; c = r[1] >> 51; r[1] &= Mask;
r[2] += c;
return r;
}
inline auto square() const -> type {
type r{*this};
type d{r[0] * 2, r[1] * 2, r[2] * 2 * 19, r[4] * 19, r[4] * 19 * 2};
uint128_t t[5];
t[0] = (uint128_t)r[0] * r[0] + (uint128_t)d[4] * r[1] + (uint128_t)d[2] * r[3];
t[1] = (uint128_t)d[0] * r[1] + (uint128_t)d[4] * r[2] + (uint128_t)r[3] * r[3] * 19;
t[2] = (uint128_t)d[0] * r[2] + (uint128_t)r[1] * r[1] + (uint128_t)d[4] * r[3];
t[3] = (uint128_t)d[0] * r[3] + (uint128_t)d[1] * r[2] + (uint128_t)r[4] * d[3];
t[4] = (uint128_t)d[0] * r[4] + (uint128_t)d[1] * r[3] + (uint128_t)r[2] * r[2];
uint64_t c; r[0] = t[0] & Mask; c = (uint64_t)(t[0] >> 51);
t[1] += c; r[1] = t[1] & Mask; c = (uint64_t)(t[1] >> 51);
t[2] += c; r[2] = t[2] & Mask; c = (uint64_t)(t[2] >> 51);
t[3] += c; r[3] = t[3] & Mask; c = (uint64_t)(t[3] >> 51);
t[4] += c; r[4] = t[4] & Mask; c = (uint64_t)(t[4] >> 51);
r[0] += c * 19; c = r[0] >> 51; r[0] &= Mask;
r[1] += c; c = r[1] >> 51; r[1] &= Mask;
r[2] += c;
return r;
}
inline auto expmod(uint256_t e) const -> type {
type x = 1, y;
for(uint n : rrange(256)) {
x = x.square();
y = operator*(x);
cmove(e >> n & 1, x, y);
}
return x;
}
inline auto reciprocal() const -> type {
return expmod(P - 2);
}
inline auto squareRoot() const -> type {
static const type i = type(2).expmod((P - 1) >> 2); //i == sqrt(-1)
type x = expmod((P + 3) >> 3);
type y = x * i;
cmove(operator!=(x.square()), x, y);
y = -x;
cmove(x() & 1, x, y);
return x;
}
private:
uint64_t l[5]; //51-bits per limb; 255-bits total
#undef Mask
};
inline auto cmove(bool move, Modulo25519& l, const Modulo25519& r) -> void {
uint64_t mask = -move;
l[0] ^= mask & (l[0] ^ r[0]);
l[1] ^= mask & (l[1] ^ r[1]);
l[2] ^= mask & (l[2] ^ r[2]);
l[3] ^= mask & (l[3] ^ r[3]);
l[4] ^= mask & (l[4] ^ r[4]);
}
inline auto cswap(bool swap, Modulo25519& l, Modulo25519& r) -> void {
uint64_t mask = -swap, x;
x = mask & (l[0] ^ r[0]); l[0] ^= x; r[0] ^= x;
x = mask & (l[1] ^ r[1]); l[1] ^= x; r[1] ^= x;
x = mask & (l[2] ^ r[2]); l[2] ^= x; r[2] ^= x;
x = mask & (l[3] ^ r[3]); l[3] ^= x; r[3] ^= x;
x = mask & (l[4] ^ r[4]); l[4] ^= x; r[4] ^= x;
}
}}

19
nall/encode/base57.hpp Normal file
View File

@ -0,0 +1,19 @@
#pragma once
#include <nall/arithmetic.hpp>
namespace nall { namespace Encode {
template<typename T> inline auto Base57(T value) -> string {
static const char lookup[] = "23456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz";
static const uint size = ceil(sizeof(T) * 8 / log2(57));
string result;
for(auto n : range(size)) {
result.append(lookup[value % 57]);
value /= 57;
}
return result;
}
}}

View File

@ -5,13 +5,18 @@ namespace nall { namespace Encode {
inline auto URL(const string& input) -> string {
string output;
for(auto c : input) {
//unreserved characters
if(c >= 'A' && c <= 'Z') { output.append(c); continue; }
if(c >= 'a' && c <= 'z') { output.append(c); continue; }
if(c >= '0' && c <= '9') { output.append(c); continue; }
if(c == '-' || c == '_' || c == '.' || c == '~') { output.append(c); continue; }
//special characters
if(c == ' ') { output.append('+'); continue; }
unsigned hi = (c >> 4) & 15;
unsigned lo = (c >> 0) & 15;
//reserved characters
uint hi = (c >> 4) & 15;
uint lo = (c >> 0) & 15;
output.append('%');
output.append((char)(hi < 10 ? ('0' + hi) : ('a' + hi - 10)));
output.append((char)(lo < 10 ? ('0' + lo) : ('a' + lo - 10)));

View File

@ -20,7 +20,7 @@ struct ZIP {
//append file: append("path/file", data, size);
auto append(string filename, const uint8_t* data = nullptr, unsigned size = 0u) -> void {
filename.transform("\\", "/");
uint32_t checksum = Hash::CRC32(data, size).value();
uint32_t checksum = Hash::CRC32(data, size).digest().hex();
directory.append({filename, checksum, size, fp.offset()});
fp.writel(0x04034b50, 4); //signature

View File

@ -20,7 +20,7 @@ template<typename R, typename... P> struct function<auto (P...) -> R> {
function(auto (*function)(P...) -> R) { callback = new global(function); }
template<typename C> function(auto (C::*function)(P...) -> R, C* object) { callback = new member<C>(function, object); }
template<typename C> function(auto (C::*function)(P...) const -> R, C* object) { callback = new member<C>((auto (C::*)(P...) -> R)function, object); }
template<typename L, typename = enable_if<is_compatible<L>>> function(const L& object) { callback = new lambda<L>(object); }
template<typename L, typename = enable_if_t<is_compatible<L>::value>> function(const L& object) { callback = new lambda<L>(object); }
~function() { if(callback) delete callback; }
explicit operator bool() const { return callback; }

View File

@ -1,45 +1,30 @@
#pragma once
#include <nall/range.hpp>
#include <nall/string.hpp>
#include <nall/hash/hash.hpp>
namespace nall { namespace Hash {
struct CRC16 {
CRC16() { reset(); }
CRC16(const void* values, uint size) : CRC16() { data(values, size); }
CRC16(const vector<uint8_t>& values) : CRC16() { data(values); }
CRC16(const string& values) : CRC16() { data(values); }
struct CRC16 : Hash {
nallHash(CRC16)
auto reset() -> void {
auto reset() -> void override {
checksum = ~0;
}
auto data(uint8_t value) -> void {
auto input(uint8_t value) -> void override {
checksum = (checksum >> 8) ^ table(checksum ^ value);
}
auto data(const void* values, uint size) -> void {
auto p = (const uint8_t*)values;
while(size--) data(*p++);
}
auto data(const vector<uint8_t>& values) -> void {
for(auto value : values) data(value);
}
auto data(const string& values) -> void {
for(auto value : values) data(value);
auto output() const -> vector<uint8_t> override {
vector<uint8_t> result;
for(auto n : rrange(2)) result.append(~checksum >> n * 8);
return result;
}
auto value() const -> uint16_t {
return ~checksum;
}
inline auto digest() const -> string {
return hex(value(), 4L);
}
private:
static auto table(uint8_t index) -> uint16_t {
static uint16_t table[256] = {0};
@ -59,7 +44,7 @@ private:
return table[index];
}
uint16_t checksum;
uint16_t checksum = 0;
};
}}

View File

@ -1,45 +1,30 @@
#pragma once
#include <nall/range.hpp>
#include <nall/string.hpp>
#include <nall/hash/hash.hpp>
namespace nall { namespace Hash {
struct CRC32 {
CRC32() { reset(); }
CRC32(const void* values, uint size) : CRC32() { data(values, size); }
CRC32(const vector<uint8_t>& values) : CRC32() { data(values); }
CRC32(const string& values) : CRC32() { data(values); }
struct CRC32 : Hash {
nallHash(CRC32)
auto reset() -> void {
auto reset() -> void override {
checksum = ~0;
}
auto data(uint8_t value) -> void {
auto input(uint8_t value) -> void override {
checksum = (checksum >> 8) ^ table(checksum ^ value);
}
auto data(const void* values, uint size) -> void {
auto p = (const uint8_t*)values;
while(size--) data(*p++);
}
auto data(const vector<uint8_t>& values) -> void {
for(auto value : values) data(value);
}
auto data(const string& values) -> void {
for(auto value : values) data(value);
auto output() const -> vector<uint8_t> {
vector<uint8_t> result;
for(auto n : rrange(4)) result.append(~checksum >> n * 8);
return result;
}
auto value() const -> uint32_t {
return ~checksum;
}
inline auto digest() const -> string {
return hex(value(), 8L);
}
private:
static auto table(uint8_t index) -> uint32_t {
static uint32_t table[256] = {0};
@ -59,7 +44,7 @@ private:
return table[index];
}
uint32_t checksum;
uint32_t checksum = 0;
};
}}

View File

@ -1,45 +1,30 @@
#pragma once
#include <nall/range.hpp>
#include <nall/string.hpp>
#include <nall/hash/hash.hpp>
namespace nall { namespace Hash {
struct CRC64 {
CRC64() { reset(); }
CRC64(const void* values, uint size) : CRC64() { data(values, size); }
CRC64(const vector<uint8_t>& values) : CRC64() { data(values); }
CRC64(const string& values) : CRC64() { data(values); }
struct CRC64 : Hash {
nallHash(CRC64)
auto reset() -> void {
auto reset() -> void override {
checksum = ~0;
}
auto data(uint8_t value) -> void {
auto input(uint8_t value) -> void override {
checksum = (checksum >> 8) ^ table(checksum ^ value);
}
auto data(const void* values, uint size) -> void {
auto p = (const uint8_t*)values;
while(size--) data(*p++);
}
auto data(const vector<uint8_t>& values) -> void {
for(auto value : values) data(value);
}
auto data(const string& values) -> void {
for(auto value : values) data(value);
auto output() const -> vector<uint8_t> {
vector<uint8_t> result;
for(auto n : rrange(8)) result.append(~checksum >> n * 8);
return result;
}
auto value() const -> uint64_t {
return ~checksum;
}
inline auto digest() const -> string {
return hex(value(), 16L);
}
private:
static auto table(uint8_t index) -> uint64_t {
static uint64_t table[256] = {0};
@ -59,7 +44,7 @@ private:
return table[index];
}
uint64_t checksum;
uint64_t checksum = 0;
};
}}

43
nall/hash/hash.hpp Normal file
View File

@ -0,0 +1,43 @@
#pragma once
#include <nall/arithmetic.hpp>
#include <nall/range.hpp>
#include <nall/string.hpp>
//cannot use constructor inheritance due to needing to call virtual reset();
//instead, define a macro to reduce boilerplate code in every Hash subclass
#define nallHash(Name) \
Name() { reset(); } \
Name(const void* data, uint64_t size) : Name() { input(data, size); } \
Name(const vector<uint8_t>& data) : Name() { input(data); } \
Name(const string& data) : Name() { input(data); } \
using Hash::input; \
namespace nall { namespace Hash {
struct Hash {
virtual auto reset() -> void = 0;
virtual auto input(uint8_t data) -> void = 0;
virtual auto output() const -> vector<uint8_t> = 0;
auto input(const void* data, uint64_t size) -> void {
auto p = (const uint8_t*)data;
while(size--) input(*p++);
}
auto input(const vector<uint8_t>& data) -> void {
for(auto byte : data) input(byte);
}
auto input(const string& data) -> void {
for(auto byte : data) input(byte);
}
auto digest() const -> string {
string result;
for(auto n : output()) result.append(hex(n, 2L));
return result;
}
};
}}

101
nall/hash/sha224.hpp Normal file
View File

@ -0,0 +1,101 @@
#pragma once
#include <nall/hash/hash.hpp>
namespace nall { namespace Hash {
struct SHA224 : Hash {
nallHash(SHA224)
auto reset() -> void override {
for(auto& n : queue) n = 0;
for(auto& n : w) n = 0;
for(auto n : range(8)) h[n] = square(n);
queued = length = 0;
}
auto input(uint8_t value) -> void override {
byte(value);
length++;
}
auto output() const -> vector<uint8_t> override {
SHA224 self(*this);
self.finish();
vector<uint8_t> result;
for(auto h : range(7)) {
for(auto n : rrange(4)) result.append(self.h[h] >> n * 8);
}
return result;
}
auto value() const -> uint256_t {
uint256_t value = 0;
for(auto byte : output()) value = value << 8 | byte;
return value;
}
private:
auto byte(uint8_t value) -> void {
uint32_t shift = (3 - (queued & 3)) * 8;
queue[queued >> 2] &= ~(0xff << shift);
queue[queued >> 2] |= (value << shift);
if(++queued == 64) block(), queued = 0;
}
auto block() -> void {
for(auto n : range(16)) w[n] = queue[n];
for(auto n : range(16, 64)) {
uint32_t a = ror(w[n - 15], 7) ^ ror(w[n - 15], 18) ^ (w[n - 15] >> 3);
uint32_t b = ror(w[n - 2], 17) ^ ror(w[n - 2], 19) ^ (w[n - 2] >> 10);
w[n] = w[n - 16] + w[n - 7] + a + b;
}
uint32_t t[8];
for(auto n : range(8)) t[n] = h[n];
for(auto n : range(64)) {
uint32_t a = ror(t[0], 2) ^ ror(t[0], 13) ^ ror(t[0], 22);
uint32_t b = ror(t[4], 6) ^ ror(t[4], 11) ^ ror(t[4], 25);
uint32_t c = (t[0] & t[1]) ^ (t[0] & t[2]) ^ (t[1] & t[2]);
uint32_t d = (t[4] & t[5]) ^ (~t[4] & t[6]);
uint32_t e = t[7] + w[n] + cube(n) + b + d;
t[7] = t[6]; t[6] = t[5]; t[5] = t[4]; t[4] = t[3] + e;
t[3] = t[2]; t[2] = t[1]; t[1] = t[0]; t[0] = a + c + e;
}
for(auto n : range(8)) h[n] += t[n];
}
auto finish() -> void {
byte(0x80);
while(queued != 56) byte(0x00);
for(auto n : range(8)) byte(length * 8 >> (7 - n) * 8);
}
auto square(uint n) -> uint32_t {
static const uint32_t value[8] = {
0xc1059ed8, 0x367cd507, 0x3070dd17, 0xf70e5939, 0xffc00b31, 0x68581511, 0x64f98fa7, 0xbefa4fa4,
};
return value[n];
}
auto cube(uint n) -> uint32_t {
static const uint32_t value[64] = {
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5,
0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174,
0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147, 0x06ca6351, 0x14292967,
0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13, 0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85,
0xa2bfe8a1, 0xa81a664b, 0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a, 0x5b9cca4f, 0x682e6ff3,
0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208, 0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2,
};
return value[n];
}
uint32_t queue[16] = {0};
uint32_t w[64] = {0};
uint32_t h[8] = {0};
uint32_t queued = 0;
uint64_t length = 0;
};
}}

View File

@ -1,66 +1,50 @@
#pragma once
#include <nall/range.hpp>
#include <nall/string.hpp>
#include <nall/hash/hash.hpp>
namespace nall { namespace Hash {
struct SHA256 {
SHA256() { reset(); }
SHA256(const void* values, uint size) : SHA256() { data(values, size); }
SHA256(const vector<uint8_t>& values) : SHA256() { data(values); }
SHA256(const string& values) : SHA256() { data(values); }
struct SHA256 : Hash {
nallHash(SHA256)
auto reset() -> void {
for(auto n : input) n = 0;
for(auto n : w) n = 0;
auto reset() -> void override {
for(auto& n : queue) n = 0;
for(auto& n : w) n = 0;
for(auto n : range(8)) h[n] = square(n);
queued = length = 0;
}
auto data(uint8_t value) -> void {
auto input(uint8_t value) -> void override {
byte(value);
length++;
}
auto data(const void* values, uint size) -> void {
length += size;
auto p = (const uint8_t*)values;
while(size--) byte(*p++);
}
auto data(const vector<uint8_t>& values) -> void {
for(auto value : values) data(value);
}
auto data(const string& values) -> void {
for(auto value : values) data(value);
}
auto value() const -> vector<uint8_t> {
auto output() const -> vector<uint8_t> override {
SHA256 self(*this);
self.finish();
vector<uint8_t> result;
for(auto n : range(32)) result.append(self.h[n >> 2] >> ((3 - (n & 3)) << 3));
for(auto h : self.h) {
for(auto n : rrange(4)) result.append(h >> n * 8);
}
return result;
}
inline auto digest() const -> string {
string result;
for(auto n : value()) result.append(hex(n, 2L));
return result;
auto value() const -> uint256_t {
uint256_t value = 0;
for(auto byte : output()) value = value << 8 | byte;
return value;
}
private:
auto byte(uint8_t value) -> void {
auto shift = (3 - (queued & 3)) * 8;
input[queued >> 2] &= ~(0xff << shift);
input[queued >> 2] |= (value << shift);
uint32_t shift = (3 - (queued & 3)) * 8;
queue[queued >> 2] &= ~(0xff << shift);
queue[queued >> 2] |= (value << shift);
if(++queued == 64) block(), queued = 0;
}
auto block() -> void {
for(auto n : range(16)) w[n] = input[n];
for(auto n : range(16)) w[n] = queue[n];
for(auto n : range(16, 64)) {
uint32_t a = ror(w[n - 15], 7) ^ ror(w[n - 15], 18) ^ (w[n - 15] >> 3);
uint32_t b = ror(w[n - 2], 17) ^ ror(w[n - 2], 19) ^ (w[n - 2] >> 10);
@ -83,11 +67,7 @@ private:
auto finish() -> void {
byte(0x80);
while(queued != 56) byte(0x00);
for(auto n : range(8)) byte((length << 3) >> ((7 - n) << 3));
}
auto ror(uint32_t x, uint32_t n) -> uint32_t {
return (x >> n) | (x << 32 - n);
for(auto n : range(8)) byte(length * 8 >> (7 - n) * 8);
}
auto square(uint n) -> uint32_t {
@ -111,11 +91,11 @@ private:
return value[n];
}
uint32_t input[16];
uint32_t queued;
uint32_t w[64];
uint32_t h[8];
uint64_t length;
uint32_t queue[16] = {0};
uint32_t w[64] = {0};
uint32_t h[8] = {0};
uint32_t queued = 0;
uint64_t length = 0;
};
}}

114
nall/hash/sha384.hpp Normal file
View File

@ -0,0 +1,114 @@
#pragma once
#include <nall/hash/hash.hpp>
namespace nall { namespace Hash {
struct SHA384 : Hash {
nallHash(SHA384)
auto reset() -> void override {
for(auto& n : queue) n = 0;
for(auto& n : w) n = 0;
for(auto n : range(8)) h[n] = square(n);
queued = length = 0;
}
auto input(uint8_t data) -> void override {
byte(data);
length++;
}
auto output() const -> vector<uint8_t> override {
SHA384 self(*this);
self.finish();
vector<uint8_t> result;
for(auto h : range(6)) {
for(auto n : rrange(8)) result.append(self.h[h] >> n * 8);
}
return result;
}
auto value() const -> uint512_t {
uint512_t value = 0;
for(auto byte : output()) value = value << 8 | byte;
return value;
}
private:
auto byte(uint8_t data) -> void {
uint64_t shift = (7 - (queued & 7)) * 8;
queue[queued >> 3] &=~((uint64_t)0xff << shift);
queue[queued >> 3] |= ((uint64_t)data << shift);
if(++queued == 128) block(), queued = 0;
}
auto block() -> void {
for(auto n : range(16)) w[n] = queue[n];
for(auto n : range(16, 80)) {
uint64_t a = ror(w[n - 15], 1) ^ ror(w[n - 15], 8) ^ (w[n - 15] >> 7);
uint64_t b = ror(w[n - 2], 19) ^ ror(w[n - 2], 61) ^ (w[n - 2] >> 6);
w[n] = w[n - 16] + w[n - 7] + a + b;
}
uint64_t t[8];
for(auto n : range(8)) t[n] = h[n];
for(auto n : range(80)) {
uint64_t a = ror(t[0], 28) ^ ror(t[0], 34) ^ ror(t[0], 39);
uint64_t b = ror(t[4], 14) ^ ror(t[4], 18) ^ ror(t[4], 41);
uint64_t c = (t[0] & t[1]) ^ (t[0] & t[2]) ^ (t[1] & t[2]);
uint64_t d = (t[4] & t[5]) ^ (~t[4] & t[6]);
uint64_t e = t[7] + w[n] + cube(n) + b + d;
t[7] = t[6]; t[6] = t[5]; t[5] = t[4]; t[4] = t[3] + e;
t[3] = t[2]; t[2] = t[1]; t[1] = t[0]; t[0] = a + c + e;
}
for(auto n : range(8)) h[n] += t[n];
}
auto finish() -> void {
byte(0x80);
while(queued != 112) byte(0x00);
for(auto n : range(16)) byte(length * 8 >> (15 - n) * 8);
}
auto square(uint n) -> uint64_t {
static const uint64_t data[8] = {
0xcbbb9d5dc1059ed8, 0x629a292a367cd507, 0x9159015a3070dd17, 0x152fecd8f70e5939,
0x67332667ffc00b31, 0x8eb44a8768581511, 0xdb0c2e0d64f98fa7, 0x47b5481dbefa4fa4,
};
return data[n];
}
auto cube(uint n) -> uint64_t {
static const uint64_t data[80] = {
0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc,
0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118,
0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2,
0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, 0xc19bf174cf692694,
0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65,
0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5,
0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4,
0xc6e00bf33da88fc2, 0xd5a79147930aa725, 0x06ca6351e003826f, 0x142929670a0e6e70,
0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df,
0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b,
0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30,
0xd192e819d6ef5218, 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8,
0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8,
0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3,
0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec,
0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b,
0xca273eceea26619c, 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178,
0x06f067aa72176fba, 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b,
0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c,
0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817,
};
return data[n];
}
uint64_t queue[16] = {0};
uint64_t w[80] = {0};
uint64_t h[8] = {0};
uint64_t queued = 0;
uint128_t length = 0;
};
}}

114
nall/hash/sha512.hpp Normal file
View File

@ -0,0 +1,114 @@
#pragma once
#include <nall/hash/hash.hpp>
namespace nall { namespace Hash {
struct SHA512 : Hash {
nallHash(SHA512)
auto reset() -> void override {
for(auto& n : queue) n = 0;
for(auto& n : w) n = 0;
for(auto n : range(8)) h[n] = square(n);
queued = length = 0;
}
auto input(uint8_t data) -> void override {
byte(data);
length++;
}
auto output() const -> vector<uint8_t> override {
SHA512 self(*this);
self.finish();
vector<uint8_t> result;
for(auto h : self.h) {
for(auto n : rrange(8)) result.append(h >> n * 8);
}
return result;
}
auto value() const -> uint512_t {
uint512_t value = 0;
for(auto byte : output()) value = value << 8 | byte;
return value;
}
private:
auto byte(uint8_t data) -> void {
uint64_t shift = (7 - (queued & 7)) * 8;
queue[queued >> 3] &=~((uint64_t)0xff << shift);
queue[queued >> 3] |= ((uint64_t)data << shift);
if(++queued == 128) block(), queued = 0;
}
auto block() -> void {
for(auto n : range(16)) w[n] = queue[n];
for(auto n : range(16, 80)) {
uint64_t a = ror(w[n - 15], 1) ^ ror(w[n - 15], 8) ^ (w[n - 15] >> 7);
uint64_t b = ror(w[n - 2], 19) ^ ror(w[n - 2], 61) ^ (w[n - 2] >> 6);
w[n] = w[n - 16] + w[n - 7] + a + b;
}
uint64_t t[8];
for(auto n : range(8)) t[n] = h[n];
for(auto n : range(80)) {
uint64_t a = ror(t[0], 28) ^ ror(t[0], 34) ^ ror(t[0], 39);
uint64_t b = ror(t[4], 14) ^ ror(t[4], 18) ^ ror(t[4], 41);
uint64_t c = (t[0] & t[1]) ^ (t[0] & t[2]) ^ (t[1] & t[2]);
uint64_t d = (t[4] & t[5]) ^ (~t[4] & t[6]);
uint64_t e = t[7] + w[n] + cube(n) + b + d;
t[7] = t[6]; t[6] = t[5]; t[5] = t[4]; t[4] = t[3] + e;
t[3] = t[2]; t[2] = t[1]; t[1] = t[0]; t[0] = a + c + e;
}
for(auto n : range(8)) h[n] += t[n];
}
auto finish() -> void {
byte(0x80);
while(queued != 112) byte(0x00);
for(auto n : range(16)) byte(length * 8 >> (15 - n) * 8);
}
auto square(uint n) -> uint64_t {
static const uint64_t data[8] = {
0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1,
0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179,
};
return data[n];
}
auto cube(uint n) -> uint64_t {
static const uint64_t data[80] = {
0x428a2f98d728ae22, 0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f, 0xe9b5dba58189dbbc,
0x3956c25bf348b538, 0x59f111f1b605d019, 0x923f82a4af194f9b, 0xab1c5ed5da6d8118,
0xd807aa98a3030242, 0x12835b0145706fbe, 0x243185be4ee4b28c, 0x550c7dc3d5ffb4e2,
0x72be5d74f27b896f, 0x80deb1fe3b1696b1, 0x9bdc06a725c71235, 0xc19bf174cf692694,
0xe49b69c19ef14ad2, 0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5, 0x240ca1cc77ac9c65,
0x2de92c6f592b0275, 0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4, 0x76f988da831153b5,
0x983e5152ee66dfab, 0xa831c66d2db43210, 0xb00327c898fb213f, 0xbf597fc7beef0ee4,
0xc6e00bf33da88fc2, 0xd5a79147930aa725, 0x06ca6351e003826f, 0x142929670a0e6e70,
0x27b70a8546d22ffc, 0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed, 0x53380d139d95b3df,
0x650a73548baf63de, 0x766a0abb3c77b2a8, 0x81c2c92e47edaee6, 0x92722c851482353b,
0xa2bfe8a14cf10364, 0xa81a664bbc423001, 0xc24b8b70d0f89791, 0xc76c51a30654be30,
0xd192e819d6ef5218, 0xd69906245565a910, 0xf40e35855771202a, 0x106aa07032bbd1b8,
0x19a4c116b8d2d0c8, 0x1e376c085141ab53, 0x2748774cdf8eeb99, 0x34b0bcb5e19b48a8,
0x391c0cb3c5c95a63, 0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373, 0x682e6ff3d6b2b8a3,
0x748f82ee5defb2fc, 0x78a5636f43172f60, 0x84c87814a1f0ab72, 0x8cc702081a6439ec,
0x90befffa23631e28, 0xa4506cebde82bde9, 0xbef9a3f7b2c67915, 0xc67178f2e372532b,
0xca273eceea26619c, 0xd186b8c721c0c207, 0xeada7dd6cde0eb1e, 0xf57d4f7fee6ed178,
0x06f067aa72176fba, 0x0a637dc5a2c898a6, 0x113f9804bef90dae, 0x1b710b35131c471b,
0x28db77f523047d84, 0x32caab7b40c72493, 0x3c9ebe0a15c9bebc, 0x431d67c49c100d4c,
0x4cc5d4becb3e42b6, 0x597f299cfc657e2a, 0x5fcb6fab3ad6faec, 0x6c44198c4a475817,
};
return data[n];
}
uint64_t queue[16] = {0};
uint64_t w[80] = {0};
uint64_t h[8] = {0};
uint64_t queued = 0;
uint128_t length = 0;
};
}}

116
nall/mac/poly1305.hpp Normal file
View File

@ -0,0 +1,116 @@
#pragma once
#include <nall/arithmetic.hpp>
namespace nall { namespace MAC {
struct Poly1305 {
auto initialize(uint256_t key) -> void {
uint64_t t0 = key >> 0;
uint64_t t1 = key >> 64;
pad[0] = key >> 128;
pad[1] = key >> 192;
r[0] = (t0 ) & 0xffc0fffffff;
r[1] = (t0 >> 44 | t1 << 20) & 0xfffffc0ffff;
r[2] = ( t1 >> 24) & 0x00ffffffc0f;
h[0] = 0, h[1] = 0, h[2] = 0;
offset = 0;
}
auto process(const uint8_t* data, uint64_t size) -> void {
while(size--) {
buffer[offset++] = *data++;
if(offset >= 16) {
block();
offset = 0;
}
}
}
auto finish() -> uint128_t {
if(offset) {
buffer[offset++] = 1;
while(offset < 16) buffer[offset++] = 0;
block(true);
}
uint64_t h0 = h[0], h1 = h[1], h2 = h[2];
uint64_t c = h1 >> 44; h1 &= 0xfffffffffff;
h2 += c; c = h2 >> 42; h2 &= 0x3ffffffffff;
h0 += c * 5; c = h0 >> 44; h0 &= 0xfffffffffff;
h1 += c; c = h1 >> 44; h1 &= 0xfffffffffff;
h2 += c; c = h2 >> 42; h2 &= 0x3ffffffffff;
h0 += c * 5; c = h0 >> 44; h0 &= 0xfffffffffff;
h1 += c;
uint64_t g0 = h0 + 5; c = g0 >> 44; g0 &= 0xfffffffffff;
uint64_t g1 = h1 + c; c = g1 >> 44; g1 &= 0xfffffffffff;
uint64_t g2 = h2 + c - (1ull << 42);
c = (g2 >> 63) - 1;
g0 &= c, g1 &= c, g2 &= c;
c = ~c;
h0 = (h0 & c) | g0;
h1 = (h1 & c) | g1;
h2 = (h2 & c) | g2;
uint64_t t0 = pad[0], t1 = pad[1];
h0 += ((t0 ) & 0xfffffffffff) ; c = h0 >> 44; h0 &= 0xfffffffffff;
h1 += ((t0 >> 44 | t1 << 20) & 0xfffffffffff) + c; c = h1 >> 44; h1 &= 0xfffffffffff;
h2 += (( t1 >> 24) & 0x3ffffffffff) + c; h2 &= 0x3ffffffffff;
h0 = (h0 >> 0 | h1 << 44);
h1 = (h1 >> 20 | h2 << 24);
r[0] = 0, r[1] = 0, r[2] = 0;
h[0] = 0, h[1] = 0, h[2] = 0;
pad[0] = 0, pad[1] = 0;
memory::fill(buffer, 16);
offset = 0;
return uint128_t(h1) << 64 | h0;
}
private:
auto block(bool last = false) -> void {
uint64_t r0 = r[0], r1 = r[1], r2 = r[2];
uint64_t h0 = h[0], h1 = h[1], h2 = h[2];
uint64_t s1 = r1 * 20;
uint64_t s2 = r2 * 20;
uint64_t t0 = memory::readl<8>(buffer + 0);
uint64_t t1 = memory::readl<8>(buffer + 8);
h0 += ((t0 ) & 0xfffffffffff);
h1 += ((t0 >> 44 | t1 << 20) & 0xfffffffffff);
h2 += (( t1 >> 24) & 0x3ffffffffff) | (last ? 0 : 1ull << 40);
uint128_t d, d0, d1, d2;
d0 = (uint128_t)h0 * r0; d = (uint128_t)h1 * s2; d0 += d; d = (uint128_t)h2 * s1; d0 += d;
d1 = (uint128_t)h0 * r1; d = (uint128_t)h1 * r0; d1 += d; d = (uint128_t)h2 * s2; d1 += d;
d2 = (uint128_t)h0 * r2; d = (uint128_t)h1 * r1; d2 += d; d = (uint128_t)h2 * r0; d2 += d;
uint64_t c = (uint64_t)(d0 >> 44); h0 = (uint64_t)d0 & 0xfffffffffff;
d1 += c; c = (uint64_t)(d1 >> 44); h1 = (uint64_t)d1 & 0xfffffffffff;
d2 += c; c = (uint64_t)(d2 >> 42); h2 = (uint64_t)d2 & 0x3ffffffffff;
h0 += c * 5; c = h0 >> 44; h0 &= 0xfffffffffff;
h1 += c;
h[0] = h0, h[1] = h1, h[2] = h2;
}
uint64_t r[3];
uint64_t h[3];
uint64_t pad[2];
uint8_t buffer[16];
uint offset;
};
}}

View File

@ -27,6 +27,12 @@ namespace nall { namespace memory {
template<typename T> inline auto assign(T* target) -> void {}
template<typename T, typename U, typename... P> inline auto assign(T* target, const U& value, P&&... p) -> void;
template<uint size, typename T = uint64_t> inline auto readl(const void* source) -> T;
template<uint size, typename T = uint64_t> inline auto readm(const void* source) -> T;
template<uint size, typename T = uint64_t> inline auto writel(void* target, T data) -> void;
template<uint size, typename T = uint64_t> inline auto writem(void* target, T data) -> void;
}}
namespace nall {
@ -130,4 +136,28 @@ auto memory::assign(T* target, const U& value, P&&... p) -> void {
assign(target, forward<P>(p)...);
}
template<uint size, typename T> auto memory::readl(const void* source) -> T {
auto p = (const uint8_t*)source;
T data = 0;
for(uint n = 0; n < size; n++) data |= T(*p++) << n * 8;
return data;
}
template<uint size, typename T> auto memory::readm(const void* source) -> T {
auto p = (const uint8_t*)source;
T data = 0;
for(int n = size - 1; n >= 0; n--) data |= T(*p++) << n * 8;
return data;
}
template<uint size, typename T> auto memory::writel(void* target, T data) -> void {
auto p = (uint8_t*)target;
for(uint n = 0; n < size; n++) *p++ = data >> n * 8;
}
template<uint size, typename T> auto memory::writem(void* target, T data) -> void {
auto p = (uint8_t*)target;
for(int n = size - 1; n >= 0; n--) *p++ = data >> n * 8;
}
}

View File

@ -15,6 +15,7 @@
#include <nall/algorithm.hpp>
#include <nall/any.hpp>
#include <nall/arithmetic.hpp>
#include <nall/array.hpp>
#include <nall/atoi.hpp>
#include <nall/bit.hpp>

View File

@ -104,18 +104,12 @@ namespace Math {
#if defined(COMPILER_CLANG) || defined(COMPILER_GCC)
#define neverinline __attribute__((noinline))
#define alwaysinline inline __attribute__((always_inline))
#if !defined(PLATFORM_MACOSX)
//todo: we want this prefix; but it causes compilation errors
#define deprecated __attribute__((deprecated))
#endif
#elif defined(COMPILER_VISUALCPP)
#define neverinline __declspec(noinline)
#define alwaysinline inline __forceinline
#define deprecated __declspec(deprecated)
#else
#define neverinline
#define alwaysinline inline
#define deprecated
#endif
#if defined(COMPILER_CLANG) || defined(COMPILER_GCC)

View File

@ -24,11 +24,11 @@ private:
template<uint Bits> struct Natural {
using type =
type_if<expression<Bits <= 8>, uint8_t,
type_if<expression<Bits <= 16>, uint16_t,
type_if<expression<Bits <= 32>, uint32_t,
type_if<expression<Bits <= 64>, uint64_t,
void>>>>;
typename conditional<Bits <= 8, uint8_t,
typename conditional<Bits <= 16, uint16_t,
typename conditional<Bits <= 32, uint32_t,
typename conditional<Bits <= 64, uint64_t,
void>::type>::type>::type>::type;
enum : type { Mask = ~0ull >> (64 - Bits) };
@ -127,11 +127,11 @@ private:
template<uint Bits> struct Integer {
using type =
type_if<expression<Bits <= 8>, int8_t,
type_if<expression<Bits <= 16>, int16_t,
type_if<expression<Bits <= 32>, int32_t,
type_if<expression<Bits <= 64>, int64_t,
void>>>>;
typename conditional<Bits <= 8, int8_t,
typename conditional<Bits <= 16, int16_t,
typename conditional<Bits <= 32, int32_t,
typename conditional<Bits <= 64, int64_t,
void>::type>::type>::type>::type;
using utype = typename Natural<Bits>::type;
enum : utype { Mask = ~0ull >> (64 - Bits), Sign = 1ull << (Bits - 1) };
@ -231,10 +231,9 @@ private:
template<uint Bits> struct Real {
using type =
type_if<expression<Bits == 32>, float32_t,
type_if<expression<Bits == 64>, float64_t,
//type_if<expression<Bits == 80>, float80_t,
void>>;
typename conditional<Bits == 32, float32_t,
typename conditional<Bits == 64, float64_t,
void>::type>::type;
inline Real() : data(0.0) {}
template<typename T> inline Real(const T& value) : data((type)value) {}

View File

@ -52,22 +52,22 @@ struct shared_pointer {
operator=(move(source));
}
template<typename U, typename = enable_if<is_compatible<U>>>
template<typename U, typename = enable_if_t<is_compatible<U>::value>>
shared_pointer(const shared_pointer<U>& source) {
operator=<U>(source);
}
template<typename U, typename = enable_if<is_compatible<U>>>
template<typename U, typename = enable_if_t<is_compatible<U>::value>>
shared_pointer(shared_pointer<U>&& source) {
operator=<U>(move(source));
}
template<typename U, typename = enable_if<is_compatible<U>>>
template<typename U, typename = enable_if_t<is_compatible<U>::value>>
shared_pointer(const shared_pointer_weak<U>& source) {
operator=<U>(source);
}
template<typename U, typename = enable_if<is_compatible<U>>>
template<typename U, typename = enable_if_t<is_compatible<U>::value>>
shared_pointer(const shared_pointer<U>& source, T* pointer) {
if((bool)source && (T*)source.manager->pointer == pointer) {
manager = source.manager;
@ -108,7 +108,7 @@ struct shared_pointer {
return *this;
}
template<typename U, typename = enable_if<is_compatible<U>>>
template<typename U, typename = enable_if_t<is_compatible<U>::value>>
auto operator=(const shared_pointer<U>& source) -> shared_pointer& {
if((uintptr)this != (uintptr)&source) {
reset();
@ -120,7 +120,7 @@ struct shared_pointer {
return *this;
}
template<typename U, typename = enable_if<is_compatible<U>>>
template<typename U, typename = enable_if_t<is_compatible<U>::value>>
auto operator=(shared_pointer&& source) -> shared_pointer& {
if((uintptr)this != (uintptr)&source) {
reset();
@ -130,7 +130,7 @@ struct shared_pointer {
return *this;
}
template<typename U, typename = enable_if<is_compatible<U>>>
template<typename U, typename = enable_if_t<is_compatible<U>::value>>
auto operator=(const shared_pointer_weak<U>& source) -> shared_pointer& {
reset();
if((bool)source) {

View File

@ -63,9 +63,9 @@ template<typename T> struct stringify;
template<typename... P> inline auto print(P&&...) -> void;
template<typename... P> inline auto print(FILE*, P&&...) -> void;
template<typename T> inline auto pad(const T& value, long precision = 0, char padchar = ' ') -> string;
inline auto hex(uintmax value, long precision = 0, char padchar = '0') -> string;
inline auto octal(uintmax value, long precision = 0, char padchar = '0') -> string;
inline auto binary(uintmax value, long precision = 0, char padchar = '0') -> string;
template<typename T> inline auto hex(T value, long precision = 0, char padchar = '0') -> string;
template<typename T> inline auto octal(T value, long precision = 0, char padchar = '0') -> string;
template<typename T> inline auto binary(T value, long precision = 0, char padchar = '0') -> string;
template<typename T> inline auto pointer(const T* value, long precision = 0) -> string;
inline auto pointer(uintptr value, long precision = 0) -> string;
@ -75,9 +75,9 @@ inline auto tokenize(string_vector& list, const char* s, const char* p) -> bool;
//utility.hpp
inline auto slice(string_view self, int offset = 0, int length = -1) -> string;
inline auto fromInteger(char* result, intmax value) -> char*;
inline auto fromNatural(char* result, uintmax value) -> char*;
inline auto fromReal(char* str, long double value) -> uint;
template<typename T> inline auto fromInteger(char* result, T value) -> char*;
template<typename T> inline auto fromNatural(char* result, T value) -> char*;
template<typename T> inline auto fromReal(char* str, T value) -> uint;
struct string {
using type = string;
@ -177,6 +177,10 @@ public:
inline auto operator[](int) const -> const char&;
inline auto operator()(int, char) const -> char;
template<typename... P> inline auto assign(P&&...) -> type&;
template<typename T, typename... P> inline auto prepend(const T&, P&&...) -> type&;
template<typename... P> inline auto prepend(const nall::string_format&, P&&...) -> type&;
inline auto prepend() -> type&;
template<typename T> inline auto _prepend(const stringify<T>&) -> string&;
template<typename T, typename... P> inline auto append(const T&, P&&...) -> type&;
template<typename... P> inline auto append(const nall::string_format&, P&&...) -> type&;
inline auto append() -> type&;

View File

@ -67,7 +67,7 @@ template<> struct stringify<signed long long> {
char _data[2 + sizeof(signed long long) * 3];
};
#if INTMAX_BITS >= 128
#if defined(__SIZEOF_INT128__)
template<> struct stringify<int128_t> {
stringify(int128_t source) { fromInteger(_data, source); }
auto data() const -> const char* { return _data; }
@ -120,7 +120,7 @@ template<> struct stringify<unsigned long long> {
char _data[1 + sizeof(unsigned long long) * 3];
};
#if INTMAX_BITS >= 128
#if defined(__SIZEOF_INT128__)
template<> struct stringify<uint128_t> {
stringify(uint128_t source) { fromNatural(_data, source); }
auto data() const -> const char* { return _data; }

View File

@ -30,6 +30,26 @@ template<typename... P> auto string::assign(P&&... p) -> string& {
return append(forward<P>(p)...);
}
template<typename T, typename... P> auto string::prepend(const T& value, P&&... p) -> string& {
prepend(forward<P>(p)...);
return _prepend(make_string(value));
}
template<typename... P> auto string::prepend(const nall::string_format& value, P&&... p) -> string& {
prepend(forward<P>(p)...);
return format(value);
}
auto string::prepend() -> string& {
return *this;
}
template<typename T> auto string::_prepend(const stringify<T>& source) -> string& {
resize(source.size() + size());
memory::move(get() + source.size(), get(), size() - source.size());
memory::copy(get(), source.data(), source.size());
}
template<typename T, typename... P> auto string::append(const T& value, P&&... p) -> string& {
_append(make_string(value));
return append(forward<P>(p)...);

View File

@ -84,9 +84,9 @@ template<typename T> auto pad(const T& value, long precision, char padchar) -> s
return buffer;
}
auto hex(uintmax value, long precision, char padchar) -> string {
template<typename T> auto hex(T value, long precision, char padchar) -> string {
string buffer;
buffer.resize(sizeof(uintmax) * 2);
buffer.resize(sizeof(T) * 2);
char* p = buffer.get();
uint size = 0;
@ -101,9 +101,9 @@ auto hex(uintmax value, long precision, char padchar) -> string {
return buffer;
}
auto octal(uintmax value, long precision, char padchar) -> string {
template<typename T> auto octal(T value, long precision, char padchar) -> string {
string buffer;
buffer.resize(sizeof(uintmax) * 3);
buffer.resize(sizeof(T) * 3);
char* p = buffer.get();
uint size = 0;
@ -117,9 +117,9 @@ auto octal(uintmax value, long precision, char padchar) -> string {
return buffer;
}
auto binary(uintmax value, long precision, char padchar) -> string {
template<typename T> auto binary(T value, long precision, char padchar) -> string {
string buffer;
buffer.resize(sizeof(uintmax) * 8);
buffer.resize(sizeof(T) * 8);
char* p = buffer.get();
uint size = 0;

View File

@ -87,7 +87,7 @@ auto DML::parseBlock(string& block, const string& pathname, uint depth) -> bool
if(state.sections++) state.output.append("</section>");
state.output.append("<section>");
}
auto content = lines.takeLeft().trimLeft("# ", 1L).split("::", 1L);
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);
@ -100,7 +100,7 @@ auto DML::parseBlock(string& block, const string& pathname, uint depth) -> bool
//header
else if(auto depth = count(block, '=')) {
auto content = slice(lines.takeLeft(), depth + 1).split("::", 1L);
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) {
@ -121,7 +121,7 @@ auto DML::parseBlock(string& block, const string& pathname, uint depth) -> bool
if(auto depth = count(line, '-')) {
while(level < depth) level++, state.output.append("<ul>\n");
while(level > depth) level--, state.output.append("</ul>\n");
auto content = slice(line, depth + 1).split("::", 1L);
auto content = slice(line, depth + 1).split("::", 1L).strip();
auto data = markup(content[0]);
auto name = escape(content(1, data.hash()));
state.output.append("<li><a href=\"#", name, "\">", data, "</a></li>\n");
@ -204,69 +204,6 @@ auto DML::escape(const string& text) -> string {
return output;
}
/* //revision 0.03 parser
auto DML::markup(const string& text) -> string {
string output;
char match = 0;
uint offset = 0;
for(uint n = 0; n < text.size();) {
char a = n ? text[n - 1] : 0;
char b = text[n];
char c = text[n++ + 1];
bool d = !a || a == ' ' || a == '\t' || a == '\r' || a == '\n'; //is previous character whitespace?
bool e = !c || c == ' ' || c == '\t' || c == '\r' || c == '\n'; //is next character whitespace?
bool f = (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9'); //is next character alphanumeric?
if(!match && d && !e) {
if(b == '*') { match = '*'; offset = n; continue; }
if(b == '/') { match = '/'; offset = n; continue; }
if(b == '_') { match = '_'; offset = n; continue; }
if(b == '~') { match = '~'; offset = n; continue; }
if(b == '|') { match = '|'; offset = n; continue; }
if(b == '[') { match = ']'; offset = n; continue; }
if(b == '{') { match = '}'; offset = n; continue; }
}
//if we reach the end of the string without a match; force a match so the content is still output
if(match && b != match && !c) { b = match; f = 0; n++; }
if(match && b == match && !f) {
match = 0;
auto content = slice(text, offset, n - offset - 1);
if(b == '*') { output.append("<strong>", escape(content), "</strong>"); continue; }
if(b == '/') { output.append("<em>", escape(content), "</em>"); continue; }
if(b == '_') { output.append("<ins>", escape(content), "</ins>"); continue; }
if(b == '~') { output.append("<del>", escape(content), "</del>"); continue; }
if(b == '|') { output.append("<code>", escape(content), "</code>"); continue; }
if(b == ']') {
auto p = content.split(" => ", 1L);
p[0].replace("@/", settings.host);
output.append("<a href=\"", escape(p[0]), "\">", escape(p(1, p[0])), "</a>");
continue;
}
if(b == '}') {
auto p = content.split(" => ", 1L);
p[0].replace("@/", settings.host);
output.append("<img src=\"", escape(p[0]), "\" alt=\"", escape(p(1, "")), "\">");
continue;
}
continue;
}
if(match) continue;
if(b == '\\' && c) { output.append(c); n++; continue; } //character escaping
if(b == '&') { output.append("&amp;"); continue; } //entity escaping
if(b == '<') { output.append("&lt;"); continue; } //...
if(b == '>') { output.append("&gt;"); continue; } //...
if(b == '"') { output.append("&quot;"); continue; } //...
output.append(b);
}
return output;
} */
auto DML::markup(const string& s) -> string {
string t;

View File

@ -92,11 +92,11 @@ auto slice(string_view self, int offset, int length) -> string {
return result;
}
auto fromInteger(char* result, intmax value) -> char* {
template<typename T> auto fromInteger(char* result, T value) -> char* {
bool negative = value < 0;
if(negative) value = -value;
char buffer[64];
char buffer[1 + sizeof(T) * 3];
uint size = 0;
do {
@ -111,8 +111,8 @@ auto fromInteger(char* result, intmax value) -> char* {
return result;
}
auto fromNatural(char* result, uintmax value) -> char* {
char buffer[64];
template<typename T> auto fromNatural(char* result, T value) -> char* {
char buffer[1 + sizeof(T) * 3];
uint size = 0;
do {
@ -129,13 +129,13 @@ auto fromNatural(char* result, uintmax value) -> char* {
//using sprintf is certainly not the most ideal method to convert
//a double to a string ... but attempting to parse a double by
//hand, digit-by-digit, results in subtle rounding errors.
auto fromReal(char* result, long double value) -> uint {
template<typename T> auto fromReal(char* result, T value) -> uint {
char buffer[256];
#ifdef _WIN32
//Windows C-runtime does not support long double via sprintf()
sprintf(buffer, "%f", (double)value);
#else
sprintf(buffer, "%Lf", value);
sprintf(buffer, "%Lf", (long double)value);
#endif
//remove excess 0's in fraction (2.500000 -> 2.5)

View File

@ -1,12 +1,17 @@
#pragma once
#include <type_traits>
#include <utility>
//pull all type traits used by nall from std namespace into nall namespace
//this removes the requirement to prefix type traits with std:: within nall
namespace nall {
using std::add_const;
using std::conditional;
using std::decay;
using std::declval;
using std::enable_if;
using std::enable_if_t;
using std::false_type;
using std::forward;
using std::initializer_list;
@ -15,6 +20,8 @@ namespace nall {
using std::is_function;
using std::is_integral;
using std::is_same;
using std::is_signed;
using std::is_unsigned;
using std::move;
using std::nullptr_t;
using std::remove_extent;
@ -22,32 +29,3 @@ namespace nall {
using std::swap;
using std::true_type;
}
namespace nall {
template<bool C> struct expression { static constexpr bool value = C; };
}
namespace nall {
namespace traits {
enum class enable_type {};
enum class disable_type {};
template<bool C, typename T = void> struct enable_if { using type = T; };
template<typename T> struct enable_if<false, T> {};
template<bool C, typename T = void> struct disable_if { using type = T; };
template<typename T> struct disable_if<true, T> {};
}
template<typename C, typename T = void> using enable_if = typename traits::enable_if<C::value, T>::type;
template<typename C, typename T = void> using disable_if = typename traits::disable_if<C::value, T>::type;
}
namespace nall {
namespace traits {
template<bool C, typename T, typename F> struct type_if { using type = T; };
template<typename T, typename F> struct type_if<false, T, F> { using type = F; };
}
template<typename C, typename T, typename F> using type_if = typename traits::type_if<C::value, T, F>::type;
}

View File

@ -15,7 +15,7 @@ struct shared_memory {
auto empty() const -> bool { return true; }
auto size() const -> uint { return 0; }
auto acquired() const -> bool { return false; }
auto acquire() -> uint8* { return nullptr; }
auto acquire() -> uint8_t* { return nullptr; }
auto release() -> void {}
auto reset() -> void {}
auto create(const string& name, uint size) -> bool { return false; }

14
nall/xorg/clipboard.hpp Normal file
View File

@ -0,0 +1,14 @@
#pragma once
#include <nall/xorg/xorg.hpp>
namespace nall { namespace Clipboard {
auto clear() -> void {
XDisplay display;
if(auto atom = XInternAtom(display, "CLIPBOARD", XlibTrue)) {
XSetSelectionOwner(display, atom, XlibNone, XlibCurrentTime);
}
}
}}

View File

@ -1,15 +1,8 @@
#ifndef NALL_XORG_GUARD_HPP
#define NALL_XORG_GUARD_HPP
#define None
#undef XlibNone
#define XlibNone 0L
#define Atom XlibAtom
#define Bool XlibBool
#define Button1 XlibButton1
#define Button2 XlibButton2
#define Button3 XlibButton3
#define Button4 XlibButton4
#define Button5 XlibButton5
#define Display XlibDisplay
#define Screen XlibScreen
#define Window XlibWindow
@ -17,15 +10,35 @@
#else
#undef NALL_XORG_GUARD_HPP
#undef None
#undef Atom
#undef Bool
#undef Display
#undef Screen
#undef Window
#ifndef NALL_XORG_GUARD_CONSTANTS
#define NALL_XORG_GUARD_CONSTANTS
enum XlibConstants : int {
XlibButton1 = Button1,
XlibButton2 = Button2,
XlibButton3 = Button3,
XlibButton4 = Button4,
XlibButton5 = Button5,
XlibCurrentTime = CurrentTime,
XlibFalse = False,
XlibNone = None,
XlibTrue = True,
};
#endif
#undef Button1
#undef Button2
#undef Button3
#undef Button4
#undef Button5
#undef Display
#undef Screen
#undef Window
#undef CurrentTime
#undef False
#undef None
#undef True
#endif

View File

@ -7,3 +7,12 @@
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <nall/xorg/guard.hpp>
struct XDisplay {
XDisplay() { _display = XOpenDisplay(nullptr); }
~XDisplay() { XCloseDisplay(_display); }
operator XlibDisplay*() const { return _display; }
private:
XlibDisplay* _display;
};