187 lines
4.6 KiB
C++
187 lines
4.6 KiB
C++
/***
|
|
Copyright (C) 2021 J Reece Wilson (a/k/a "Reece"). All rights reserved.
|
|
|
|
File: AuRandomDevice.cpp
|
|
Date: 2021-9-3
|
|
Author: Reece
|
|
***/
|
|
#include <AuroraRuntime.hpp>
|
|
#include "AuRandomDevice.hpp"
|
|
|
|
namespace Aurora::RNG
|
|
{
|
|
RandomDevice::RandomDevice()
|
|
{
|
|
|
|
}
|
|
|
|
RandomDevice::RandomDevice(const RandomDef &def)
|
|
{
|
|
this->Init(def);
|
|
}
|
|
|
|
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<false>(this->fast_.state);
|
|
}
|
|
}
|
|
// secure rng requires no init -> we just passthrough to the global ReadSecureRNG function
|
|
}
|
|
|
|
void RandomDevice::Read(Memory::MemoryViewWrite view)
|
|
{
|
|
if (!view)
|
|
{
|
|
SysPushErrorArg();
|
|
return;
|
|
}
|
|
|
|
if (this->def_.bSecure)
|
|
{
|
|
ReadSecureRNG(view);
|
|
}
|
|
else
|
|
{
|
|
WELL_NextBytes(&this->fast_, view.ptr, AuUInt32(view.length));
|
|
}
|
|
}
|
|
|
|
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<const char *, int> rngSequence[static_cast<int>(ERngStringCharacters::eEnumCount)] =
|
|
{
|
|
{"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", 52},
|
|
{"abcdefghijklmnopqrstuvwxyz", 26},
|
|
{"ABCDEFGHIJKLMNOPQRSTUVWXYZ", 26},
|
|
{"1234567890", 10},
|
|
{"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890", 62},
|
|
{"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890=-+!$%^*.[];:", 75}
|
|
};
|
|
|
|
if (!pString)
|
|
{
|
|
SysPushErrorArg();
|
|
return;
|
|
}
|
|
|
|
Read(AuMemoryViewWrite { 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<int>(type)];
|
|
|
|
for (auto i = 0u; i < uLength; i++)
|
|
{
|
|
pString[i] = pair.first[reinterpret_cast<const AuUInt8 *>(pString)[i] % static_cast<int>(pair.second)];
|
|
}
|
|
}
|
|
|
|
AuUInt8 RandomDevice::NextByte()
|
|
{
|
|
return NextFillTmpl<AuUInt8>();
|
|
}
|
|
|
|
bool RandomDevice::NextBoolean()
|
|
{
|
|
return NextByte() > 127;
|
|
}
|
|
|
|
AuUInt32 RandomDevice::NextU32()
|
|
{
|
|
return NextFillTmpl<AuUInt32>();
|
|
}
|
|
|
|
AuUInt64 RandomDevice::NextU64()
|
|
{
|
|
return NextFillTmpl<AuUInt64>();
|
|
}
|
|
|
|
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<AuUInt32>::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;
|
|
}
|
|
|
|
AuMemoryViewRead RandomDevice::ToSeed()
|
|
{
|
|
if (this->def_.bSecure)
|
|
{
|
|
return {};
|
|
}
|
|
|
|
return this->fast_.state;
|
|
}
|
|
|
|
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 *pDevice)
|
|
{
|
|
AuSafeDelete<RandomDevice *>(pDevice);
|
|
}
|
|
|
|
AUROXTL_INTERFACE_SOO_SRC(Random, RandomDevice, (const RandomDef &, def))
|
|
} |