/*** Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved. File: AuRandomDevice.cpp Date: 2021-9-3 Author: Reece ***/ #include #include "AuRandomDevice.hpp" namespace Aurora::RNG { void RandomDevice::Init(const RandomDef &def) { this->def_ = def; // Gross... if (!def.bSecure) { if (def.seed) { this->fast_ = WELL_SeedRand(def.seed.value()); } else if (def.seed64) { this->fast_ = WELL_SeedRand64(def.seed64.value()); } else if (def.seedMassive) { this->fast_ = WELL_SeedRandBig64(def.seedMassive.value()); } else { this->fast_ = {}; RNG::RngFillArray(this->fast_.state); } } // secure rng requires no init -> we just passthrough to the global ReadSecureRNG function } void RandomDevice::Read(void *pIn, AuUInt32 uLength) { if (!pIn) { SysPushErrorArg(); return; } if (this->def_.bSecure) { ReadSecureRNG(pIn, uLength); } else { WELL_NextBytes(&this->fast_, pIn, uLength); } } AuString RandomDevice::NextString(AuUInt32 uLength, ERngStringCharacters type) { AuString ret(uLength, '\00'); NextString(ret.data(), AuUInt32(ret.size()), type); return ret; } void RandomDevice::NextString(char *pString, AuUInt32 uLength, ERngStringCharacters type) { static AuPair rngSequence[static_cast(ERngStringCharacters::eEnumCount)] = { {"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", 52}, {"abcdefghijklmnopqrstuvwxyz", 26}, {"ABCDEFGHIJKLMNOPQRSTUVWXYZ", 26}, {"1234567890", 10}, {"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890", 62}, {"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890=-+!$%^*.[];:", 75} }; if (!pString) { SysPushErrorArg(); return; } ReadSecureRNG(pString, uLength); if (!ERngStringCharactersIsValid(type)) { SysPushErrorArg("NextString was called with an invalid ERngStringCharacters {}", (AuUInt)type); type = ERngStringCharacters::eAlphaNumericCharacters; // guess we cant just return false } const auto &pair = rngSequence[static_cast(type)]; for (auto i = 0u; i < uLength; i++) { pString[i] = pair.first[reinterpret_cast(pString)[i] % static_cast(pair.second)]; } } AuUInt8 RandomDevice::NextByte() { return NextFillTmpl(); } bool RandomDevice::NextBoolean() { return NextByte() > 127; } AuUInt32 RandomDevice::NextU32() { return NextFillTmpl(); } AuUInt64 RandomDevice::NextU64() { return NextFillTmpl(); } AuInt32 RandomDevice::NextInt(AuInt32 uMin, AuInt32 uMax) { auto range = uMax - uMin; return (NextU64() % range) + uMin; } AuUInt32 RandomDevice::NextU32(AuUInt32 uMin, AuUInt32 uMax) { auto range = uMax - uMin; return (NextU64() % range) + uMin; } double RandomDevice::NextDecimal() { return double(NextU32()) * (double(1.0) / double(AuNumericLimits::max())); } AuUInt32 RandomDevice::NextIndex(AuUInt32 uCount /* = max + 1*/) { return NextU32() % uCount; } float RandomDevice::NextNumber(float min, float max) { auto range = max - min; return NextDecimal() * range + min; } AUKN_SYM IRandomDevice *RandomNew(const Aurora::RNG::RandomDef &def) { auto pDevice = _new RandomDevice(); if (!pDevice) { return nullptr; } pDevice->Init(def); return pDevice; } AUKN_SYM void RandomRelease(IRandomDevice *pStream) { AuSafeDelete(pStream); } }