1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2025-06-15 22:57:12 +02:00

Migrated the host module to C++ exceptions as well.

Also enabled the latest C++ revision in the project.
Replaced the Random library with the one provided by C++11.
Implemented a simple AES256 encryption class.
Various other fixes and improvements.
This commit is contained in:
Sandu Liviu Catalin
2016-03-10 05:57:13 +02:00
parent 3162221e7f
commit 70e5f0ba21
124 changed files with 14873 additions and 14062 deletions

239
source/Library/Crypt.cpp Normal file
View File

@ -0,0 +1,239 @@
// ------------------------------------------------------------------------------------------------
#include "Library/Crypt.hpp"
#include "Base/Shared.hpp"
// ------------------------------------------------------------------------------------------------
#include <cstdlib>
#include <cstring>
// ------------------------------------------------------------------------------------------------
#include <sqstdstring.h>
// ------------------------------------------------------------------------------------------------
#include <crc32.h>
#include <keccak.h>
#include <md5.h>
#include <sha1.h>
#include <sha256.h>
#include <sha3.h>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
SQInteger AES256::Typename(HSQUIRRELVM vm)
{
static SQChar name[] = _SC("SqAES");
sq_pushstring(vm, name, sizeof(name));
return 1;
}
// ------------------------------------------------------------------------------------------------
AES256::AES256()
: m_Context(), m_Buffer()
{
aes256_done(&m_Context);
}
// ------------------------------------------------------------------------------------------------
AES256::AES256(CSStr key)
: m_Context(), m_Buffer()
{
Init(key);
}
// ------------------------------------------------------------------------------------------------
Int32 AES256::Cmp(const AES256 & o) const
{
return memcmp(m_Buffer, o.m_Buffer, sizeof(m_Buffer));
}
// ------------------------------------------------------------------------------------------------
CSStr AES256::ToString() const
{
return ToStrF("%s", m_Buffer);
}
// ------------------------------------------------------------------------------------------------
CSStr AES256::GetKey() const
{
return reinterpret_cast< CSStr >(m_Buffer);
}
// ------------------------------------------------------------------------------------------------
void AES256::Init(CSStr key)
{
// Clear current key, if any
aes256_done(&m_Context);
// Is the specified key empty?
if (!key || *key == 0)
return; // Leave the context with an empty key
// Obtain the specified key size
const Uint32 size = (strlen(key) * sizeof(SQChar));
// See if the key size is accepted
if (size > sizeof(m_Buffer))
SqThrowF("The specified key is out of bounds: %u > %u", size, sizeof(m_Buffer));
// Initialize the key buffer to 0
memset(m_Buffer, 0, sizeof(m_Buffer));
// Copy the key into the key buffer
memcpy(m_Buffer, key, size);
// Initialize the context with the specified key
aes256_init(&m_Context, m_Buffer);
}
// ------------------------------------------------------------------------------------------------
void AES256::Done()
{
aes256_done(&m_Context);
}
// ------------------------------------------------------------------------------------------------
String AES256::Encrypt(CSStr data)
{
// Is there any data to encrypt?
if (!data || *data == 0)
return String();
// Copy the data into an editable string
String str(data);
// Make sure that we have a size with a multiple of 16
if ((str.size() % 16) != 0)
str.resize(str.size() - (str.size() % 16) + 16);
// Encrypt in chunks of 16 characters
for (Uint32 n = 0; n < str.size(); n += 16)
aes256_encrypt_ecb(&m_Context, reinterpret_cast< Uint8 * >(&str[n]));
// Return ownership of the encrypted string
return std::move(str);
}
// ------------------------------------------------------------------------------------------------
String AES256::Decrypt(CSStr data)
{
// Is there any data to decrypt?
if (!data || *data == 0)
return String();
// Copy the data into an editable string
String str(data);
// Make sure that we have a size with a multiple of 16
if ((str.size() % 16) != 0)
str.resize(str.size() - (str.size() % 16) + 16);
// Decrypt inc chunks of 16 characters
for (Uint32 n = 0; n < str.size(); n += 16)
aes256_decrypt_ecb(&m_Context, reinterpret_cast< Uint8 * >(&str[n]));
// Remove null characters in case the string was not a multiple of 16 when encrypted
while (!str.empty() && str.back() == 0)
str.pop_back();
// Return ownership of the encrypted string
return std::move(str);
}
/* ------------------------------------------------------------------------------------------------
* Utility to avoid creating encoder instances for each call.
*/
template < class T > struct BaseHash
{
static T Algo;
};
// ------------------------------------------------------------------------------------------------
template < class T > T BaseHash< T >::Algo;
/* ------------------------------------------------------------------------------------------------
* Hash the specified value or the result of a formatted string.
*/
template < class T > static SQInteger HashF(HSQUIRRELVM vm)
{
const Int32 top = sq_gettop(vm);
// Was the hash value specified?
if (top <= 1)
return sq_throwerror(vm, "Missing hash value");
// Do we have enough values to call the format function?
else if (top > 2)
{
SStr val = NULL;
SQInteger len = 0;
// Attempt to generate the specified string format
SQRESULT ret = sqstd_format(vm, 2, &len, &val);
// Did the format failed?
if (SQ_FAILED(ret))
return ret; // Propagate the exception
// Hash the resulted string
String str(BaseHash< T >::Algo(val));
// Push the string on the stack
sq_pushstring(vm, str.data(), str.size());
}
else
{
// Attempt to retrieve the value from the stack as a string
Var< CSStr > val(vm, 2);
// See if the obtained value is a valid string
if (!val.value)
return sq_throwerror(vm, "Unable to retrieve the value");
// Hash the resulted string
String str(BaseHash< T >::Algo(val.value));
// Push the string on the stack
sq_pushstring(vm, str.data(), str.size());
}
// At this point we have a valid string on the stack
return 1;
}
// ================================================================================================
template < class T > static void RegisterWrapper(Table & hashns, CCStr cname)
{
typedef HashWrapper< T > Hash;
hashns.Bind(cname, Class< Hash >(hashns.GetVM(), cname)
/* Constructors */
.Ctor()
/* Metamethods */
.Func(_SC("_tostring"), &Hash::ToString)
/* Properties */
.Prop(_SC("Hash"), &Hash::GetHash)
/* Functions */
.Func(_SC("Reset"), &Hash::Reset)
.Func(_SC("Compute"), &Hash::Compute)
.Func(_SC("GetHash"), &Hash::GetHash)
.Func(_SC("Add"), &Hash::AddStr)
.Func(_SC("AddStr"), &Hash::AddStr)
);
}
// ================================================================================================
void Register_Crypt(HSQUIRRELVM vm)
{
Table hashns(vm);
RegisterWrapper< CRC32 >(hashns, _SC("CRC32"));
RegisterWrapper< Keccak >(hashns, _SC("Keccak"));
RegisterWrapper< MD5 >(hashns, _SC("MD5"));
RegisterWrapper< SHA1 >(hashns, _SC("SHA1"));
RegisterWrapper< SHA256 >(hashns, _SC("SHA256"));
RegisterWrapper< SHA3 >(hashns, _SC("SHA3"));
hashns.SquirrelFunc(_SC("GetCRC32"), &HashF< CRC32 >);
hashns.SquirrelFunc(_SC("GetKeccak"), &HashF< Keccak >);
hashns.SquirrelFunc(_SC("GetMD5"), &HashF< MD5 >);
hashns.SquirrelFunc(_SC("GetSHA1"), &HashF< SHA1 >);
hashns.SquirrelFunc(_SC("GetSHA256"), &HashF< SHA256 >);
hashns.SquirrelFunc(_SC("GetSHA3"), &HashF< SHA3 >);
RootTable(vm).Bind(_SC("SqHash"), hashns);
RootTable(vm).Bind("SqAES256", Class< AES256 >(vm, "SqAES256")
/* Constructors */
.Ctor()
.Ctor< CSStr >()
/* Metamethods */
.Func(_SC("_cmp"), &AES256::Cmp)
.SquirrelFunc(_SC("_typename"), &AES256::Typename)
.Func(_SC("_tostring"), &AES256::ToString)
/* Properties */
.Prop(_SC("Key"), &AES256::GetKey)
/* Functions */
.Func(_SC("Init"), &AES256::Init)
.Func(_SC("Done"), &AES256::Done)
.Func(_SC("Encrypt"), &AES256::Encrypt)
.Func(_SC("Decrypt"), &AES256::Decrypt)
);
}
} // Namespace:: SqMod

200
source/Library/Crypt.hpp Normal file
View File

@ -0,0 +1,200 @@
#ifndef _LIBRARY_CRYPT_HPP_
#define _LIBRARY_CRYPT_HPP_
// ------------------------------------------------------------------------------------------------
#include "SqBase.hpp"
// ------------------------------------------------------------------------------------------------
#include <aes256.h>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* Simple class to maintain the state of an encoder.
*/
template < class T > class HashWrapper
{
public:
/* --------------------------------------------------------------------------------------------
* Default constructor.
*/
HashWrapper()
: m_Encoder()
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Copy operator.
*/
HashWrapper(const HashWrapper & o)
: m_Encoder(o.m_Encoder)
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Destructor.
*/
~HashWrapper()
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Copy assignment operator.
*/
HashWrapper & operator = (const HashWrapper & o)
{
m_Encoder = o.m_Encoder;
return *this;
}
/* --------------------------------------------------------------------------------------------
* Used by the script engine to convert an instance of this type to a string.
*/
String ToString()
{
return m_Encoder.getHash();
}
/* --------------------------------------------------------------------------------------------
* Reset the encoder state.
*/
void Reset()
{
m_Encoder.reset();
}
/* --------------------------------------------------------------------------------------------
* Compute the hash of the specified string.
*/
String Compute(const String & str)
{
return m_Encoder(str);
}
/* --------------------------------------------------------------------------------------------
* Retrieve the hash value of the data hashed so far.
*/
String GetHash()
{
return m_Encoder.getHash();
}
/* --------------------------------------------------------------------------------------------
* Add a string value to be hashed.
*/
void AddStr(const String & str)
{
m_Encoder.add(str.data(), str.length() * sizeof(String::value_type));
}
private:
/* --------------------------------------------------------------------------------------------
* The managed encoder state.
*/
T m_Encoder;
};
/* ------------------------------------------------------------------------------------------------
* Simple wrapper around a the AES encryption context.
*/
class AES256
{
public:
/* --------------------------------------------------------------------------------------------
* Default constructor.
*/
AES256();
/* --------------------------------------------------------------------------------------------
* Construct with an explicit key.
*/
AES256(CSStr key);
/* --------------------------------------------------------------------------------------------
* Copy constructor.
*/
AES256(const AES256 & o) = default;
/* --------------------------------------------------------------------------------------------
* Move constructor.
*/
AES256(AES256 && o) = default;
/* --------------------------------------------------------------------------------------------
* Destructor.
*/
~AES256() = default;
/* --------------------------------------------------------------------------------------------
* Copy assignment operator.
*/
AES256 & operator = (const AES256 & o) = default;
/* --------------------------------------------------------------------------------------------
* Move assignment operator.
*/
AES256 & operator = (AES256 && o) = default;
/* --------------------------------------------------------------------------------------------
* Used by the script engine to compare two instances of this type.
*/
Int32 Cmp(const AES256 & o) const;
/* --------------------------------------------------------------------------------------------
* Used by the script engine to convert an instance of this type to a string.
*/
CSStr ToString() const;
/* --------------------------------------------------------------------------------------------
* Used by the script engine to retrieve the name from instances of this type.
*/
static SQInteger Typename(HSQUIRRELVM vm);
/* --------------------------------------------------------------------------------------------
* Retrieve the associated key.
*/
CSStr GetKey() const;
/* --------------------------------------------------------------------------------------------
* Initialize the context key.
*/
void Init(CSStr key);
/* --------------------------------------------------------------------------------------------
* Reset the associated context.
*/
void Done();
/* --------------------------------------------------------------------------------------------
* Encrypt the specified string.
*/
String Encrypt(CSStr data);
/* --------------------------------------------------------------------------------------------
* Decrypt the specified string.
*/
String Decrypt(CSStr data);
private:
/* --------------------------------------------------------------------------------------------
* The managed encryption context.
*/
aes256_context m_Context;
/* --------------------------------------------------------------------------------------------
* The key used to encrypt data.
*/
Uint8 m_Buffer[32]{0};
};
} // Namespace:: SqMod
#endif // _LIBRARY_CRYPT_HPP_

View File

@ -1,103 +0,0 @@
// ------------------------------------------------------------------------------------------------
#include "Library/Hashing.hpp"
#include "Base/Shared.hpp"
// ------------------------------------------------------------------------------------------------
#include <sqstdstring.h>
// ------------------------------------------------------------------------------------------------
#include <crc32.h>
#include <keccak.h>
#include <md5.h>
#include <sha1.h>
#include <sha256.h>
#include <sha3.h>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* ...
*/
template < class T > struct BaseHash
{
static T Algo;
};
// ------------------------------------------------------------------------------------------------
template < class T > T BaseHash< T >::Algo;
// ------------------------------------------------------------------------------------------------
template < class T > static SQInteger HashF(HSQUIRRELVM vm)
{
const Int32 top = sq_gettop(vm);
Object ret;
if (top <= 1)
SqThrow("Missing the hash string");
else if (top == 2 && ((sq_gettype(vm, -1) == OT_STRING) || !SQ_FAILED(sq_tostring(vm, -1))))
{
CCStr str = 0;
if (SQ_FAILED(sq_getstring(vm, -1, &str)))
SqThrow("Unable to retrieve the string");
else
ret = MakeObject(vm, BaseHash< T >::Algo(str));
sq_settop(vm, top);
}
else if (top > 2)
{
CStr str = NULL;
SQInteger len = 0;
if (SQ_FAILED(sqstd_format(vm, 2, &len, &str)))
SqThrow("Unable to generate the string [%s]", Error::Message(vm).c_str());
else
ret = MakeObject(vm, BaseHash< T >::Algo(str));
}
else
SqThrow("Unable to extract the hash string");
Var< Object >::push(vm, ret);
return 1;
}
// ================================================================================================
template < class T > static void RegisterWrapper(Table & hashns, CCStr cname)
{
typedef HashWrapper< T > Hash;
hashns.Bind(cname, Class< Hash >(hashns.GetVM(), cname)
/* Constructors */
.Ctor()
/* Metamethods */
.Func(_SC("_tostring"), &Hash::ToString)
/* Properties */
.Prop(_SC("Hash"), &Hash::GetHash)
/* Functions */
.Func(_SC("Reset"), &Hash::Reset)
.Func(_SC("Compute"), &Hash::Compute)
.Func(_SC("GetHash"), &Hash::GetHash)
.Func(_SC("Add"), &Hash::AddStr)
.Func(_SC("AddStr"), &Hash::AddStr)
);
}
// ================================================================================================
void Register_Hash(HSQUIRRELVM vm)
{
Table hashns(vm);
RegisterWrapper< CRC32 >(hashns, _SC("CRC32"));
RegisterWrapper< Keccak >(hashns, _SC("Keccak"));
RegisterWrapper< MD5 >(hashns, _SC("MD5"));
RegisterWrapper< SHA1 >(hashns, _SC("SHA1"));
RegisterWrapper< SHA256 >(hashns, _SC("SHA256"));
RegisterWrapper< SHA3 >(hashns, _SC("SHA3"));
hashns.SquirrelFunc(_SC("GetCRC32"), &HashF< CRC32 >);
hashns.SquirrelFunc(_SC("GetKeccak"), &HashF< Keccak >);
hashns.SquirrelFunc(_SC("GetMD5"), &HashF< MD5 >);
hashns.SquirrelFunc(_SC("GetSHA1"), &HashF< SHA1 >);
hashns.SquirrelFunc(_SC("GetSHA256"), &HashF< SHA256 >);
hashns.SquirrelFunc(_SC("GetSHA3"), &HashF< SHA3 >);
RootTable(vm).Bind(_SC("SqHash"), hashns);
}
} // Namespace:: SqMod

View File

@ -1,58 +0,0 @@
#ifndef _LIBRARY_HASHING_HPP_
#define _LIBRARY_HASHING_HPP_
// ------------------------------------------------------------------------------------------------
#include "SqBase.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
template < class T > class HashWrapper
{
public:
// --------------------------------------------------------------------------------------------
HashWrapper()
: m_Encoder()
{
}
// --------------------------------------------------------------------------------------------
HashWrapper(const HashWrapper & o)
: m_Encoder(o.m_Encoder)
{
}
// --------------------------------------------------------------------------------------------
~HashWrapper()
{
}
// --------------------------------------------------------------------------------------------
HashWrapper & operator = (const HashWrapper & o)
{
m_Encoder = o.m_Encoder;
return *this;
}
// --------------------------------------------------------------------------------------------
String ToString() { return m_Encoder.getHash(); }
void Reset() { m_Encoder.reset(); }
String Compute(const String & str) { return m_Encoder(str); }
String GetHash() { return m_Encoder.getHash(); }
void AddStr(const String & str)
{ m_Encoder.add(str.data(), str.length() * sizeof(String::value_type)); }
private:
// --------------------------------------------------------------------------------------------
T m_Encoder;
};
} // Namespace:: SqMod
#endif // _LIBRARY_HASHING_HPP_

View File

@ -4,11 +4,12 @@
#include "Base/Buffer.hpp"
// ------------------------------------------------------------------------------------------------
#include <RandomLib/Random.hpp>
#include <ctime>
#include <memory>
#include <random>
#include <cstdlib>
// ------------------------------------------------------------------------------------------------
#include <time.h>
#include <stdlib.h>
#ifdef SQMOD_OS_WINDOWS
#include <process.h>
#else
@ -17,10 +18,45 @@
#endif
// ------------------------------------------------------------------------------------------------
RandomLib::Random g_RGen;
namespace SqMod {
// ------------------------------------------------------------------------------------------------
namespace SqMod {
static std::unique_ptr< std::mt19937 > RG32_MT19937 =
std::unique_ptr< std::mt19937 >(new std::mt19937(GenerateSeed()));
static std::unique_ptr< std::mt19937_64 > RG64_MT19937 =
std::unique_ptr< std::mt19937_64 >(new std::mt19937_64(GenerateSeed()));
// ------------------------------------------------------------------------------------------------
static std::uniform_int_distribution< Int8 > Int8_Dist(std::numeric_limits< Int8 >::min(),
std::numeric_limits< Int8 >::max());
static std::uniform_int_distribution< Uint8 > Uint8_Dist(std::numeric_limits< Uint8 >::min(),
std::numeric_limits< Uint8 >::max());
static std::uniform_int_distribution< Int16 > Int16_Dist(std::numeric_limits< Int16 >::min(),
std::numeric_limits< Int16 >::max());
static std::uniform_int_distribution< Uint16 > Uint16_Dist(std::numeric_limits< Uint16 >::min(),
std::numeric_limits< Uint16 >::max());
static std::uniform_int_distribution< Int32 > Int32_Dist(std::numeric_limits< Int32 >::min(),
std::numeric_limits< Int32 >::max());
static std::uniform_int_distribution< Uint32 > Uint32_Dist(std::numeric_limits< Uint32 >::min(),
std::numeric_limits< Uint32 >::max());
static std::uniform_int_distribution< Int64 > Int64_Dist(std::numeric_limits< Int64 >::min(),
std::numeric_limits< Int64 >::max());
static std::uniform_int_distribution< Uint64 > Uint64_Dist(std::numeric_limits< Uint64 >::min(),
std::numeric_limits< Uint64 >::max());
static std::uniform_real_distribution<Float32> Float32_Dist(std::numeric_limits< Float32 >::min(),
std::numeric_limits< Float32 >::max());
static std::uniform_real_distribution<Float64> Float64_Dist(std::numeric_limits< Float64 >::min(),
std::numeric_limits< Float64 >::max());
// ------------------------------------------------------------------------------------------------
static std::uniform_int_distribution< String::value_type >
String_Dist(std::numeric_limits< String::value_type >::min(),
std::numeric_limits< String::value_type >::max());
// ------------------------------------------------------------------------------------------------
SizeT GenerateSeed()
@ -49,309 +85,296 @@ SizeT GenerateSeed()
// ------------------------------------------------------------------------------------------------
void ReseedRandom()
{
g_RGen.Reseed();
RG32_MT19937.reset(new std::mt19937(GenerateSeed()));
RG64_MT19937.reset(new std::mt19937_64(GenerateSeed()));
}
void ReseedRandom(Uint32 n)
{
g_RGen.Reseed(n);
RG32_MT19937.reset(new std::mt19937(n));
RG64_MT19937.reset(new std::mt19937_64(n));
}
// ------------------------------------------------------------------------------------------------
void ReseedRandom32()
{
RG32_MT19937.reset(new std::mt19937(GenerateSeed()));
}
void ReseedRandom32(Uint32 n)
{
RG32_MT19937.reset(new std::mt19937(n));
}
// ------------------------------------------------------------------------------------------------
void ReseedRandom64()
{
RG64_MT19937.reset(new std::mt19937_64(GenerateSeed()));
}
void ReseedRandom64(Uint32 n)
{
RG64_MT19937.reset(new std::mt19937_64(n));
}
// ------------------------------------------------------------------------------------------------
Int8 GetRandomInt8()
{
return g_RGen.Integer< Int8 >();
return Int8_Dist(*RG32_MT19937);
}
Int8 GetRandomInt8(Int8 n)
{
return g_RGen.Integer< Int8 >(n);
return std::uniform_int_distribution< Int8 >(0, n)(*RG32_MT19937);
}
Int8 GetRandomInt8(Int8 m, Int8 n)
{
return g_RGen.IntegerC< Int8 >(m, n);
return std::uniform_int_distribution< Int8 >(m, n)(*RG32_MT19937);
}
// ------------------------------------------------------------------------------------------------
Uint8 GetRandomUint8()
{
return g_RGen.Integer< Uint8 >();
return Uint8_Dist(*RG32_MT19937);
}
Uint8 GetRandomUint8(Uint8 n)
{
return g_RGen.Integer< Uint8 >(n);
return std::uniform_int_distribution< Uint8 >(0, n)(*RG32_MT19937);
}
Uint8 GetRandomUint8(Uint8 m, Uint8 n)
{
return g_RGen.IntegerC< Uint8 >(m, n);
return std::uniform_int_distribution< Uint8 >(m, n)(*RG32_MT19937);
}
// ------------------------------------------------------------------------------------------------
Int16 GetRandomInt16()
{
return g_RGen.Integer< Int16 >();
return Int16_Dist(*RG32_MT19937);
}
Int16 GetRandomInt16(Int16 n)
{
return g_RGen.Integer< Int16 >(n);
return std::uniform_int_distribution< Int16 >(0, n)(*RG32_MT19937);
}
Int16 GetRandomInt16(Int16 m, Int16 n)
{
return g_RGen.IntegerC< Int16 >(m, n);
return std::uniform_int_distribution< Int16 >(m, n)(*RG32_MT19937);
}
// ------------------------------------------------------------------------------------------------
Uint16 GetRandomUint16()
{
return g_RGen.Integer< Uint16 >();
return Uint16_Dist(*RG32_MT19937);
}
Uint16 GetRandomUint16(Uint16 n)
{
return g_RGen.Integer< Uint16 >(n);
return std::uniform_int_distribution< Uint16 >(0, n)(*RG32_MT19937);
}
Uint16 GetRandomUint16(Uint16 m, Uint16 n)
{
return g_RGen.IntegerC< Uint16 >(m, n);
return std::uniform_int_distribution< Uint16 >(m, n)(*RG32_MT19937);
}
// ------------------------------------------------------------------------------------------------
Int32 GetRandomInt32()
{
return g_RGen.Integer< Int32 >();
return Int32_Dist(*RG32_MT19937);
}
Int32 GetRandomInt32(Int32 n)
{
return g_RGen.Integer< Int32 >(n);
return std::uniform_int_distribution< Int32 >(0, n)(*RG32_MT19937);
}
Int32 GetRandomInt32(Int32 m, Int32 n)
{
return g_RGen.IntegerC< Int32 >(m, n);
return std::uniform_int_distribution< Int32 >(m, n)(*RG32_MT19937);
}
// ------------------------------------------------------------------------------------------------
Uint32 GetRandomUint32()
{
return g_RGen.Integer< Uint32 >();
return Int32_Dist(*RG32_MT19937);
}
Uint32 GetRandomUint32(Uint32 n)
{
return g_RGen.Integer< Uint32 >(n);
return std::uniform_int_distribution< Int32 >(0, n)(*RG32_MT19937);
}
Uint32 GetRandomUint32(Uint32 m, Uint32 n)
{
return g_RGen.IntegerC< Uint32 >(m, n);
return std::uniform_int_distribution< Int32 >(m, n)(*RG32_MT19937);
}
// ------------------------------------------------------------------------------------------------
Int64 GetRandomInt64()
{
return g_RGen.Integer< Int64 >();
return Int64_Dist(*RG64_MT19937);
}
Int64 GetRandomInt64(Int64 n)
{
return g_RGen.Integer< Int64 >(n);
return std::uniform_int_distribution< Int64 >(0, n)(*RG64_MT19937);
}
Int64 GetRandomInt64(Int64 m, Int64 n)
{
return g_RGen.IntegerC< Int64 >(m, n);
return std::uniform_int_distribution< Int64 >(m, n)(*RG64_MT19937);
}
// ------------------------------------------------------------------------------------------------
Uint64 GetRandomUint64()
{
return g_RGen.Integer< Uint64 >();
return Uint64_Dist(*RG64_MT19937);
}
Uint64 GetRandomUint64(Uint64 n)
{
return g_RGen.Integer< Uint64 >(n);
return std::uniform_int_distribution< Uint64 >(0, n)(*RG64_MT19937);
}
Uint64 GetRandomUint64(Uint64 m, Uint64 n)
{
return g_RGen.IntegerC< Uint64 >(m, n);
return std::uniform_int_distribution< Uint64 >(m, n)(*RG64_MT19937);
}
// ------------------------------------------------------------------------------------------------
Float32 GetRandomFloat32()
{
static const Float32 m = NumLimit<Int32>::Min, n = NumLimit<Int32>::Max;
return (n - m) * (Float32(g_RGen.IntegerC< Int16 >(0, NumLimit< Int16 >::Max)) / Float32(RAND_MAX)) + m;
return Float32_Dist(*RG32_MT19937);
}
Float32 GetRandomFloat32(Float32 n)
{
return Float32(g_RGen.IntegerC< Int16 >(0, NumLimit< Int16 >::Max)) / Float32(RAND_MAX/n);
return std::uniform_real_distribution< Float32 >(0, n)(*RG32_MT19937);
}
Float32 GetRandomFloat32(Float32 m, Float32 n)
{
return (n - m) * (Float32(g_RGen.IntegerC< Int16 >(0, NumLimit< Int16 >::Max)) / Float32(RAND_MAX)) + m;
return std::uniform_real_distribution< Float32 >(m, n)(*RG32_MT19937);
}
// ------------------------------------------------------------------------------------------------
Float64 GetRandomFloat64()
{
static const Float64 m = NumLimit<Int32>::Min, n = NumLimit<Int32>::Max;
return (n - m) * (Float64(g_RGen.IntegerC< Int16 >(0, NumLimit< Int16 >::Max)) / Float64(RAND_MAX)) + m;
return Float64_Dist(*RG64_MT19937);
}
Float64 GetRandomFloat64(Float64 n)
{
return Float64(g_RGen.IntegerC< Int16 >(0, NumLimit< Int16 >::Max)) / Float64(RAND_MAX/n);
return std::uniform_real_distribution< Float64 >(0, n)(*RG64_MT19937);
}
Float64 GetRandomFloat64(Float64 m, Float64 n)
{
return (n - m) * (Float64(g_RGen.IntegerC< Int16 >(0, NumLimit< Int16 >::Max)) / Float64(RAND_MAX)) + m;
return std::uniform_real_distribution< Float64 >(m, n)(*RG64_MT19937);
}
// ------------------------------------------------------------------------------------------------
void GetRandomString(String & str, String::size_type len)
{
// Reserve the requested size + the null terminator
str.reserve(len+1);
// Resize to the requested size and fill with 0
str.resize(len);
for (String::iterator itr = str.begin(); itr != str.end(); ++itr)
{
*itr = g_RGen.Integer< String::value_type >();
}
// Generate the requested amount of characters
for (auto & c : str)
c = String_Dist(*RG32_MT19937);
// Append the null terminator
str.push_back(0);
}
void GetRandomString(String & str, String::size_type len, String::value_type n)
{
// Reserve the requested size + the null terminator
str.reserve(len+1);
// Resize to the requested size and fill with 0
str.resize(len);
for (String::iterator itr = str.begin(); itr != str.end(); ++itr)
{
*itr = g_RGen.Integer< String::value_type >(n);
}
// Create the custom distribution
std::uniform_int_distribution< String::value_type > dist(1, n);
// Generate the requested amount of characters
for (auto & c : str)
c = dist(*RG32_MT19937);
// Append the null terminator
str.push_back(0);
}
void GetRandomString(String & str, String::size_type len, String::value_type m, String::value_type n)
{
// Reserve the requested size + the null terminator
str.reserve(len+1);
// Resize to the requested size and fill with 0
str.resize(len);
for (String::iterator itr = str.begin(); itr != str.end(); ++itr)
{
*itr = g_RGen.IntegerC< String::value_type >(m, n);
}
// Create the custom distribution
std::uniform_int_distribution< String::value_type > dist(m, n);
// Generate the requested amount of characters
for (auto & c : str)
c = dist(*RG32_MT19937);
// Append the null terminator
str.push_back(0);
}
// ------------------------------------------------------------------------------------------------
bool GetRandomBool()
{
return g_RGen.Boolean();
return std::bernoulli_distribution()(*RG32_MT19937);
}
bool GetRandomBool(SQFloat p)
{
return std::bernoulli_distribution(p)(*RG32_MT19937);
}
// ------------------------------------------------------------------------------------------------
template < typename T > static T RandomValue()
{
return RandomVal< T >::Get();
}
template < typename T > static T RandomValue(T n)
{
return RandomVal< T >::Get(n);
}
template < typename T > static T RandomValue(T m, T n)
{
return RandomVal< T >::Get(m, n);
}
// ------------------------------------------------------------------------------------------------
static CSStr RandomString(Int32 len)
static String RandomString(Int32 len)
{
// Is there anything to generate?
if (len <= 0)
{
return _SC("");
}
Buffer b(len+1);
SStr s = b.Get< SQChar >();
for (Int32 n = 0; n <= len; ++n, ++s)
{
*s = g_RGen.Integer< SQChar >();
}
b.At< SQChar >(len) = 0;
return b.Get< SQChar >();
// Prepare the string buffer
String str;
// Request the random fill
GetRandomString(str, len);
// Return ownership of the string
return std::move(str);
}
// ------------------------------------------------------------------------------------------------
static CSStr RandomString(Int32 len, SQChar n)
static String RandomString(Int32 len, SQChar n)
{
// Is there anything to generate?
if (len <= 0)
{
return _SC("");
}
Buffer b(len+1);
SStr s = b.Get< SQChar >();
for (Int32 i = 0; i <= len; ++i, ++s)
{
*s = g_RGen.Integer< SQChar >(n);
}
b.At< SQChar >(len) = 0;
return b.Get< SQChar >();
// Prepare the string buffer
String str;
// Request the random fill
GetRandomString(str, len, n);
// Return ownership of the string
return std::move(str);
}
// ------------------------------------------------------------------------------------------------
static CSStr RandomString(Int32 len, SQChar m, SQChar n)
static String RandomString(Int32 len, SQChar m, SQChar n)
{
// Is there anything to generate?
if (len <= 0)
{
return _SC("");
}
Buffer b(len+1);
SStr s = b.Get< SQChar >();
for (Int32 i = 0; i <= len; ++i, ++s)
{
*s = g_RGen.IntegerC< SQChar >(m, n);
}
b.At< SQChar >(len) = 0;
return b.Get< SQChar >();
}
// ------------------------------------------------------------------------------------------------
static bool RandomProbI(SQInteger p)
{
return g_RGen.Prob(p);
}
static bool RandomProbI(SQInteger m, SQInteger n)
{
return g_RGen.Prob(m, n);
}
// ------------------------------------------------------------------------------------------------
static bool RandomProbF(SQFloat p)
{
return g_RGen.Prob(p);
}
static bool RandomProbF(SQFloat m, SQFloat n)
{
return g_RGen.Prob(m, n);
// Prepare the string buffer
String str;
// Request the random fill
GetRandomString(str, len, m, n);
// Return ownership of the string
return std::move(str);
}
// ------------------------------------------------------------------------------------------------
@ -361,20 +384,36 @@ void Register_Random(HSQUIRRELVM vm)
.Func(_SC("GenSeed"), &GenerateSeed)
.Overload< void (*)(void) >(_SC("Reseed"), &ReseedRandom)
.Overload< void (*)(Uint32) >(_SC("Reseed"), &ReseedRandom)
.Overload< SQInteger (*)(void) >(_SC("Integer"), &RandomValue< SQInteger >)
.Overload< SQInteger (*)(SQInteger) >(_SC("Integer"), &RandomValue< SQInteger >)
.Overload< SQInteger (*)(SQInteger, SQInteger) >(_SC("Integer"), &RandomValue< SQInteger >)
.Overload< SQFloat (*)(void) >(_SC("Float"), &RandomValue< SQFloat >)
.Overload< SQFloat (*)(SQFloat) >(_SC("Float"), &RandomValue< SQFloat >)
.Overload< SQFloat (*)(SQFloat, SQFloat) >(_SC("Float"), &RandomValue< SQFloat >)
.Overload< CSStr (*)(Int32) >(_SC("String"), &RandomString)
.Overload< CSStr (*)(Int32, SQChar) >(_SC("String"), &RandomString)
.Overload< CSStr (*)(Int32, SQChar, SQChar) >(_SC("String"), &RandomString)
.Func(_SC("Bool"), &GetRandomBool)
.Overload< bool (*)(SQInteger) >(_SC("ProbI"), &RandomProbI)
.Overload< bool (*)(SQInteger, SQInteger) >(_SC("ProbI"), &RandomProbI)
.Overload< bool (*)(SQFloat) >(_SC("ProbF"), &RandomProbF)
.Overload< bool (*)(SQFloat, SQFloat) >(_SC("ProbF"), &RandomProbF)
.Overload< void (*)(void) >(_SC("Reseed32"), &ReseedRandom32)
.Overload< void (*)(Uint32) >(_SC("Reseed32"), &ReseedRandom32)
.Overload< void (*)(void) >(_SC("Reseed64"), &ReseedRandom64)
.Overload< void (*)(Uint32) >(_SC("Reseed64"), &ReseedRandom64)
#ifdef _SQ64
.Overload< SQInteger (*)(void) >(_SC("Integer"), &GetRandomInt64)
.Overload< SQInteger (*)(SQInteger) >(_SC("Integer"), &GetRandomInt64)
.Overload< SQInteger (*)(SQInteger, SQInteger) >(_SC("Integer"), &GetRandomInt64)
#else
.Overload< SQInteger (*)(void) >(_SC("Integer"), &GetRandomInt32)
.Overload< SQInteger (*)(SQInteger) >(_SC("Integer"), &GetRandomInt32)
.Overload< SQInteger (*)(SQInteger, SQInteger) >(_SC("Integer"), &GetRandomInt32)
#endif // _SQ64
#ifdef SQUSEDOUBLE
.Overload< SQFloat (*)(void) >(_SC("Float"), &GetRandomFloat64)
.Overload< SQFloat (*)(SQFloat) >(_SC("Float"), &GetRandomFloat64)
.Overload< SQFloat (*)(SQFloat, SQFloat) >(_SC("Float"), &GetRandomFloat64)
#else
.Overload< SQFloat (*)(void) >(_SC("Float"), &GetRandomFloat32)
.Overload< SQFloat (*)(SQFloat) >(_SC("Float"), &GetRandomFloat32)
.Overload< SQFloat (*)(SQFloat, SQFloat) >(_SC("Float"), &GetRandomFloat32)
#endif // SQUSEDOUBLE
.Overload< String (*)(Int32) >(_SC("String"), &RandomString)
.Overload< String (*)(Int32, SQChar) >(_SC("String"), &RandomString)
.Overload< String (*)(Int32, SQChar, SQChar) >(_SC("String"), &RandomString)
.Overload< bool (*)(void) >(_SC("Bool"), &GetRandomBool)
.Overload< bool (*)(SQFloat) >(_SC("Bool"), &GetRandomBool)
);
}

View File

@ -7,10 +7,10 @@
#include <sqstdstring.h>
// ------------------------------------------------------------------------------------------------
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cctype>
#include <cstdio>
#include <cstdlib>
#include <cstring>
// ------------------------------------------------------------------------------------------------
#include <algorithm>
@ -21,137 +21,117 @@ namespace SqMod {
// ------------------------------------------------------------------------------------------------
CSStr LeftStr(CSStr t, SQChar f, Uint32 w)
{
// Allocate a buffer with the requested width
Buffer b(w * sizeof(SQChar));
Uint32 n = !t ? 0 : strlen(t);
// Populate the entire buffer with the fill character
memset(b.Data(), f, w * sizeof(SQChar));
// Is the specified width valid?
if (w >= b.Size< SQChar >())
{
SqThrow("Invalid width specified: %d > %d", w, b.Size< SQChar >());
w = 0;
}
if (!w)
return _SC("");
// Allocate a buffer with the requested width
Buffer b(w);
// Is the specified string valid?
else if (n == 0)
{
SqThrow("Invalid string length: %d < 0", n);
}
// Is the specified string within width range?
else if (n > w)
{
SqThrow("String is out of bounds: %d > %d", n, w);
}
// Insert the specified string
if (!t || *t == 0)
// Insert only the fill character
memset(b.Data(), f, w);
else
{
// Calculate the string length
const Uint32 n = strlen(t);
// Insert only the fill character first
memset(b.Data(), f, w);
// Overwrite with the specified string
strncpy(b.Data(), t, n);
}
// End the resulted string
b.At< SQChar >(w) = 0;
b.At(w) = 0;
// Return the resulted string
return b.Get< SQChar >();
}
CSStr LeftStr(CSStr t, SQChar f, Uint32 w, Uint32 o)
{
// Allocate a buffer with the requested width
Buffer b(w * sizeof(SQChar));
Uint32 n = !t ? 0 : strlen(t);
// Populate the entire buffer with the fill character
memset(b.Data(), f, w * sizeof(SQChar));
// Is the specified width valid?
if (w >= b.Size< SQChar >())
{
SqThrow("Invalid width specified: %d > %d", w, b.Size< SQChar >());
w = 0;
}
if (!w)
return _SC("");
// Is the specified offset within width range?
else if (o > w)
SqThrowF("Offset is out of bounds");
// Allocate a buffer with the requested width
Buffer b(w);
// Is the specified string valid?
else if (n == 0)
{
SqThrow("Invalid string length: %d < 0", n);
}
// Is the specified string within width range?
else if ((o+n) > w)
{
SqThrow("String is out of bounds: (%d+%d) > %d", o, n, w);
}
// Insert the specified string
if (!t || *t == 0)
// Insert only the fill character
memset(b.Data(), f, w);
else
{
strncpy(b.Get< SQChar >() + o, t, n);
// Clculate the string length
const Uint32 n = strlen(t);
// Insert the fill character first
memset(b.Data(), f, w);
// Overwrite with the specified string
strncpy(b.Data() + o, t, w - n);
}
// End the resulted string
b.At< SQChar >(w) = 0;
b.At(w) = 0;
// Return the resulted string
return b.Get< SQChar >();
return b.Get();
}
// ------------------------------------------------------------------------------------------------
CSStr RightStr(CSStr t, SQChar f, Uint32 w)
{
// Allocate a buffer with the requested width
Buffer b(w * sizeof(SQChar));
Uint32 n = !t ? 0 : strlen(t);
// Populate the entire buffer with the fill character
memset(b.Data(), f, w * sizeof(SQChar));
// Is the specified width valid?
if (w >= b.Size< SQChar >())
{
SqThrow("Invalid width specified: %d > %d", w, b.Size< SQChar >());
w = 0;
}
if (!w)
return _SC("");
// Allocate a buffer with the requested width
Buffer b(w);
// Is the specified string valid?
else if (n == 0)
{
SqThrow("Invalid string length: %d < 0", n);
}
// Is the specified string within width range?
else if (n > w)
{
SqThrow("String is out of bounds: %d > %d", n, w);
}
// Insert the specified string
if (!t || *t == 0)
// Insert only the fill character
memset(b.Data(), f, w);
else
{
strncpy(b.Get< SQChar >() + (w-n), t, n);
// Calculate the string length
const Uint32 n = strlen(t);
// Insert the fill character first
memset(b.Data(), f, w);
// Overwrite with the specified string
if (n >= w)
strncpy(b.Data(), t, w);
else
strncpy(b.Data() + (w - n), t, n);
}
// End the resulted string
b.At< SQChar >(w) = 0;
b.At(w) = 0;
// Return the resulted string
return b.Get< SQChar >();
}
CSStr RightStr(CSStr t, SQChar f, Uint32 w, Uint32 o)
{
// Allocate a buffer with the requested width
Buffer b(w * sizeof(SQChar));
Uint32 n = !t ? 0 : strlen(t);
// Populate the entire buffer with the fill character
memset(b.Data(), f, w * sizeof(SQChar));
// Is the specified width valid?
if (w >= b.Size< SQChar >())
{
SqThrow("Invalid width specified: %d > %d", w, b.Size< SQChar >());
w = 0;
}
if (!w)
return _SC("");
// Is the specified offset within width range?
else if (o > w)
SqThrowF("Offset is out of bounds");
// Allocate a buffer with the requested width
Buffer b(w);
// Is the specified string valid?
else if (n == 0)
{
SqThrow("Invalid string length: %d < 0", n);
}
// Is the specified string within width range?
else if ((n+o) > w)
{
SqThrow("String is out of bounds: (%d+%d) > %d", n, o, w);
}
// Insert the specified string
if (!t || *t == 0)
// Insert only the fill character
memset(b.Data(), f, w);
else
{
strncpy(b.Get< SQChar >() + ((w-n)-o), t, n);
// Calculate the string length
const Uint32 n = strlen(t);
// Insert the fill character first
memset(b.Data(), f, w);
// Overwrite with the specified string
if (n >= w || (n + o) >= w)
strncpy(b.Data(), t, w - o);
else
strncpy(b.Data() + ((w - n) - o), t, n);
}
// End the resulted string
b.At< SQChar >(w) = 0;
b.At(w) = 0;
// Return the resulted string
return b.Get< SQChar >();
}
@ -159,34 +139,26 @@ CSStr RightStr(CSStr t, SQChar f, Uint32 w, Uint32 o)
// ------------------------------------------------------------------------------------------------
CSStr CenterStr(CSStr t, SQChar f, Uint32 w)
{
// Allocate a buffer with the requested width
Buffer b(w * sizeof(SQChar));
Uint32 n = !t ? 0 : strlen(t);
// Populate the entire buffer with the fill character
memset(b.Data(), f, w * sizeof(SQChar));
// Is the specified width valid?
if (w >= b.Size< SQChar >())
{
SqThrow("Invalid width specified: %d > %d", w, b.Size< SQChar >());
w = 0;
}
if (!w)
return _SC("");
// Allocate a buffer with the requested width
Buffer b(w);
// Is the specified string valid?
else if (n == 0)
{
SqThrow("Invalid string length: %d < 0", n);
}
// Is the specified string within width range?
else if (n > w)
{
SqThrow("String is out of bounds: %d > %d", n, w);
}
// Insert the specified string
if (!t || *t == 0)
// Insert only the fill character
memset(b.Data(), f, w);
else
{
strncpy(b.Get< SQChar >() + (w/2 - n/2), t, n);
// Calculate the string length
const Uint32 n = strlen(t);
// Insert only the fill character first
memset(b.Data(), f, w);
// Overwrite with the specified string
strncpy(b.Data() + ((w/2) - (n/2)), t, n);
}
// End the resulted string
b.At< SQChar >(w) = 0;
b.At(w) = 0;
// Return the resulted string
return b.Get< SQChar >();
}
@ -194,12 +166,11 @@ CSStr CenterStr(CSStr t, SQChar f, Uint32 w)
// ------------------------------------------------------------------------------------------------
CSStr StrJustAlphaNum(CSStr str)
{
Uint32 size = 0;
// See if we actually have something to search for
if(!str || (size = strlen(str)) <= 0)
{
if(!str || *str == 0)
return _SC("");
}
// Calculate the string length
Uint32 size = strlen(str);
// Obtain a temporary buffer
Buffer b(size);
// Resulted string size
@ -211,13 +182,11 @@ CSStr StrJustAlphaNum(CSStr str)
{
// Is this an alpha-numeric character?
if (isalnum(c) != 0)
{
// Save it and move to the next one
b.At< SQChar >(n++) = c;
}
b.At(n++) = c;
}
// End the resulted string
b.At< SQChar >(n) = 0;
b.At(n) = 0;
// Return the string
return b.Get< SQChar >();
}
@ -225,12 +194,11 @@ CSStr StrJustAlphaNum(CSStr str)
// ------------------------------------------------------------------------------------------------
CSStr StrToLowercase(CSStr str)
{
Uint32 size = 0;
// See if we actually have something to search for
if(!str || (size = strlen(str)) <= 0)
{
if(!str || *str == 0)
return _SC("");
}
// Calculate the string length
Uint32 size = strlen(str);
// Obtain a temporary buffer
Buffer b(size);
// Resulted string size
@ -239,12 +207,10 @@ CSStr StrToLowercase(CSStr str)
SQChar c = 0;
// Process characters
while ((c = *(str++)) != 0)
{
// Convert it and move to the next one
b.At< SQChar >(n++) = tolower(c);
}
b.At(n++) = tolower(c);
// End the resulted string
b.At< SQChar >(n) = 0;
b.At(n) = 0;
// Return the string
return b.Get< SQChar >();
}
@ -252,12 +218,11 @@ CSStr StrToLowercase(CSStr str)
// ------------------------------------------------------------------------------------------------
CSStr StrToUppercase(CSStr str)
{
Uint32 size = 0;
// See if we actually have something to search for
if(!str || (size = strlen(str)) <= 0)
{
if(!str || *str == 0)
return _SC("");
}
// Calculate the string length
Uint32 size = strlen(str);
// Obtain a temporary buffer
Buffer b(size);
// Resulted string size
@ -266,12 +231,10 @@ CSStr StrToUppercase(CSStr str)
SQChar c = 0;
// Process characters
while ((c = *(str++)) != 0)
{
// Convert it and move to the next one
b.At< SQChar >(n++) = toupper(c);
}
b.At(n++) = toupper(c);
// End the resulted string
b.At< SQChar >(n) = 0;
b.At(n) = 0;
// Return the string
return b.Get< SQChar >();
}
@ -280,18 +243,16 @@ CSStr StrToUppercase(CSStr str)
static CSStr FromArray(Array & arr)
{
// Determine array size
const Int32 length = (Int32)arr.Length();
const Int32 length = static_cast< Int32 >(arr.Length());
// Obtain a temporary buffer
Buffer b(length * sizeof(Int32));
// Get array elements as integers
arr.GetArray< Int32 >(b.Get< Int32 >(), length);
// Overwrite integers with characters
for (Int32 n = 0; n < length; ++n)
{
b.At< SQChar >(n) = (SQChar)b.At< Int32 >(n);
}
b.At(n) = static_cast< SQChar >(b.At< Int32 >(n));
// Terminate the resulted string
b.At< SQChar >(length) = 0;
b.At(length) = 0;
// Return the string
return b.Get< SQChar >();
}
@ -301,9 +262,14 @@ static SQInteger StdPrintF(HSQUIRRELVM vm)
{
CStr msg = NULL;
SQInteger length = 0;
if(SQ_FAILED(sqstd_format(vm, 2, &length, &msg)))
return -1;
// Attempt to run the specified format and save the result
const SQRESULT res = sqstd_format(vm, 2, &length, &msg);
// Validate the result for errors and propagate them to the VM
if(SQ_FAILED(res))
return res;
// Send the resulted string to console as a user message
LogUsr("%s", msg);
// This function doesn't return anything
return 0;
}