1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2025-07-30 20:51:48 +02:00

Rename source to module.

This commit is contained in:
Sandu Liviu Catalin
2020-03-21 23:02:27 +02:00
parent a5c87bae5e
commit c0fd374404
237 changed files with 0 additions and 272718 deletions

309
module/Library/Chrono.cpp Normal file
View File

@@ -0,0 +1,309 @@
// ------------------------------------------------------------------------------------------------
#include "Library/Chrono.hpp"
#include "Library/Chrono/Date.hpp"
#include "Library/Chrono/Datetime.hpp"
#include "Library/Chrono/Time.hpp"
#include "Library/Chrono/Timer.hpp"
#include "Library/Chrono/Timestamp.hpp"
#include "Library/Numeric/LongInt.hpp"
#include "Base/Shared.hpp"
// ------------------------------------------------------------------------------------------------
#ifdef SQMOD_OS_WINDOWS
#if defined(_SQ64) && (_WIN32_WINNT < 0x0600)
// We need this for the GetTickCount64() function
#undef _WIN32_WINNT
#define _WIN32_WINNT 0x0600
#endif // _SQ64
#include <windows.h>
#else
#include <time.h>
#endif // SQMOD_OS_WINDOWS
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
extern void Register_ChronoDate(HSQUIRRELVM vm, Table & cns);
extern void Register_ChronoDatetime(HSQUIRRELVM vm, Table & cns);
extern void Register_ChronoTime(HSQUIRRELVM vm, Table & cns);
extern void Register_ChronoTimer(HSQUIRRELVM vm, Table & cns);
extern void Register_ChronoTimestamp(HSQUIRRELVM vm, Table & cns);
// ------------------------------------------------------------------------------------------------
const Uint8 Chrono::MonthLengths[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
// ------------------------------------------------------------------------------------------------
#ifdef SQMOD_OS_WINDOWS
/* ------------------------------------------------------------------------------------------------
* Used by GetCurrentSysTime to obtain the system frequency on initial call.
*/
inline LARGE_INTEGER GetFrequency()
{
LARGE_INTEGER frequency;
QueryPerformanceFrequency(&frequency);
return frequency;
}
// ------------------------------------------------------------------------------------------------
Int64 Chrono::GetCurrentSysTime()
{
// Force the following code to run on first core
// (see http://msdn.microsoft.com/en-us/library/windows/desktop/ms644904(v=vs.85).aspx)
HANDLE current_thread = GetCurrentThread();
DWORD_PTR previous_mask = SetThreadAffinityMask(current_thread, 1);
// Get the frequency of the performance counter
// (it is constant across the program lifetime)
static const LARGE_INTEGER frequency = GetFrequency();
// Get the current time
LARGE_INTEGER time;
QueryPerformanceCounter(&time);
// Restore the thread affinity
SetThreadAffinityMask(current_thread, previous_mask);
// Return the current time as microseconds
return Int64(1000000LL * time.QuadPart / frequency.QuadPart);
}
// ------------------------------------------------------------------------------------------------
Int64 Chrono::GetEpochTimeMicro()
{
FILETIME ft;
GetSystemTimeAsFileTime(&ft);
// Extract the nanoseconds from the resulted timestamp
Uint64 time = ft.dwHighDateTime;
time <<= 32;
time |= ft.dwLowDateTime;
time /= 10;
time -= 11644473600000000ULL;
// Return the resulted timestamp
return Int64(time);
}
// ------------------------------------------------------------------------------------------------
#ifndef _SQ64
Int64 GetTickCount64()
{
return static_cast< Int64 >(GetTickCount()); // Fall-back to 32 bit?
}
#endif // _SQ64
#else
// ------------------------------------------------------------------------------------------------
Int64 Chrono::GetCurrentSysTime()
{
// POSIX implementation
timespec time;
clock_gettime(CLOCK_MONOTONIC, &time);
return Int64(Uint64(time.tv_sec) * 1000000 + time.tv_nsec / 1000);
}
// ------------------------------------------------------------------------------------------------
Int64 Chrono::GetEpochTimeMicro()
{
// POSIX implementation
timespec time;
clock_gettime(CLOCK_REALTIME, &time);
return Int64(Uint64(time.tv_sec) * 1000000 + time.tv_nsec / 1000);
}
// ------------------------------------------------------------------------------------------------
Uint32 GetTickCount()
{
// POSIX implementation
struct timespec time;
if (clock_gettime(CLOCK_MONOTONIC, &time))
{
return 0;
}
return time.tv_sec * 1000.0 + time.tv_nsec / 1000000.0;
}
// ------------------------------------------------------------------------------------------------
Int64 GetTickCount64()
{
struct timespec time;
if (clock_gettime(CLOCK_MONOTONIC, &time))
{
return 0;
}
return time.tv_sec * 1000.0 + time.tv_nsec / 1000000.0;
}
#endif // SQMOD_OS_WINDOWS
// ------------------------------------------------------------------------------------------------
Int64 Chrono::GetEpochTimeMilli()
{
return (GetEpochTimeMicro() / 1000L);
}
// ------------------------------------------------------------------------------------------------
bool Chrono::ValidDate(Uint16 year, Uint8 month, Uint8 day)
{
// Is this a valid date?
if (year == 0 || month == 0 || day == 0)
{
return false;
}
// Is the month within range?
else if (month > 12)
{
return false;
}
// Return whether the day inside the month
return day <= DaysInMonth(year, month);
}
// ------------------------------------------------------------------------------------------------
Uint8 Chrono::DaysInMonth(Uint16 year, Uint8 month)
{
// Is the specified month within range?
if (month > 12)
{
STHROWF("Month value is out of range: %u > 12", month);
}
// Obtain the days in this month
Uint8 days = *(MonthLengths + month);
// Should we account for January?
if (month == 2 && IsLeapYear(year))
{
++days;
}
// Return the resulted days
return days;
}
// ------------------------------------------------------------------------------------------------
Uint16 Chrono::DayOfYear(Uint16 year, Uint8 month, Uint8 day)
{
// Start with 0 days
Uint16 doy = 0;
// Cumulate the days in months
for (Uint8 m = 1; m < month; ++month)
{
doy += DaysInMonth(year, m);
}
// Add the specified days
doy += day;
// Return the result
return doy;
}
// ------------------------------------------------------------------------------------------------
Date Chrono::ReverseDayOfyear(Uint16 year, Uint16 doy)
{
// The resulted month
Uint8 month = 1;
// Calculate the months till the specified day of year
for (; month < 12; ++month)
{
// Get the number of days in the current month
Uint32 days = DaysInMonth(year, month);
// Can this month fit in the remaining days?
if (days >= doy)
{
break; // The search is complete
}
// Subtract the month days from days of year
doy -= days;
}
// Return the resulted date
return Date(year, month, doy);
}
// ------------------------------------------------------------------------------------------------
Int64 Chrono::DateRangeToSeconds(Uint16 _year, Uint8 _month, Uint8 _day, Uint16 year_, Uint8 month_, Uint8 day_)
{
// Are we within the same year?
if (_year == year_)
{
return std::abs((DayOfYear(_year, _month, _day) - DayOfYear(year_, month_, day_)) * 86400LL);
}
// Is the start year greater than the end year?
else if (_year > year_)
{
std::swap(_year, year_);
std::swap(_month, month_);
std::swap(_day, day_);
}
// Calculate the remaining days from the first year
Int64 num = DaysInYear(_year) - DayOfYear(_year, _month, _day);
// Calculate the days withing the years range
while (++_year < year_)
{
num += DaysInYear(_year);
}
// Calculate the days up to the last day
num += DayOfYear(year_, month_, day_);
// Convert the obtained days in seconds
num *= 86400ULL;
// Return the result
return std::abs(num);
}
// ------------------------------------------------------------------------------------------------
static SLongInt SqGetEpochTimeMicro()
{
return SLongInt(Chrono::GetEpochTimeMicro());
}
// ------------------------------------------------------------------------------------------------
static SLongInt SqGetEpochTimeMilli()
{
return SLongInt(Chrono::GetEpochTimeMilli());
}
// ------------------------------------------------------------------------------------------------
static SLongInt SqGetCurrentSysTime()
{
return SLongInt(Chrono::GetCurrentSysTime());
}
// ------------------------------------------------------------------------------------------------
static SQInteger SqGetTickCount()
{
return ConvTo< SQInteger >::From(GetTickCount());
}
// ------------------------------------------------------------------------------------------------
static SLongInt SqGetTickCount64()
{
return SLongInt(GetTickCount64());
}
// ================================================================================================
void Register_Chrono(HSQUIRRELVM vm)
{
Table cns(vm);
Register_ChronoDate(vm, cns);
Register_ChronoDatetime(vm, cns);
Register_ChronoTime(vm, cns);
Register_ChronoTimer(vm, cns);
Register_ChronoTimestamp(vm, cns);
cns
.Func(_SC("EpochMicro"), &SqGetEpochTimeMicro)
.Func(_SC("EpochMilli"), &SqGetEpochTimeMilli)
.Func(_SC("Current"), &SqGetCurrentSysTime)
.Func(_SC("TickCount"), &SqGetTickCount)
.Func(_SC("TickCount64"), &SqGetTickCount64)
.Func(_SC("IsLeapYear"), &Chrono::IsLeapYear)
.Func(_SC("IsDateValid"), &Chrono::ValidDate)
.Func(_SC("DaysInYear"), &Chrono::DaysInYear)
.Func(_SC("DaysInMonth"), &Chrono::DaysInMonth)
.Func(_SC("DayOfYear"), &Chrono::DayOfYear)
.Func(_SC("ReverseDayOfyear"), &Chrono::ReverseDayOfyear);
RootTable(vm).Bind(_SC("SqChrono"), cns);
}
} // Namespace:: SqMod

116
module/Library/Chrono.hpp Normal file
View File

@@ -0,0 +1,116 @@
#ifndef _LIBRARY_CHRONO_HPP_
#define _LIBRARY_CHRONO_HPP_
// ------------------------------------------------------------------------------------------------
#include "SqBase.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
class Date;
class Time;
class Datetime;
class Timer;
class Timestamp;
/* ------------------------------------------------------------------------------------------------
* Class that offers helpers to work with time related information.
*/
class Chrono
{
public:
// ------------------------------------------------------------------------------------------------
static const Uint8 MonthLengths[12];
/* --------------------------------------------------------------------------------------------
* Default constructor. (disabled)
*/
Chrono() = delete;
/* --------------------------------------------------------------------------------------------
* Copy constructor. (disabled)
*/
Chrono(const Chrono & o) = delete;
/* --------------------------------------------------------------------------------------------
* Move constructor. (disabled)
*/
Chrono(Chrono && o) = delete;
/* --------------------------------------------------------------------------------------------
* Destructor. (disabled)
*/
~Chrono() = delete;
/* --------------------------------------------------------------------------------------------
* Copy assignment operator. (disabled)
*/
Chrono & operator = (const Chrono & o) = delete;
/* --------------------------------------------------------------------------------------------
* Move assignment operator. (disabled)
*/
Chrono & operator = (Chrono && o) = delete;
/* --------------------------------------------------------------------------------------------
* Retrieve the current time as microseconds.
*/
static Int64 GetCurrentSysTime();
/* --------------------------------------------------------------------------------------------
* Retrieve the epoch time as microseconds.
*/
static Int64 GetEpochTimeMicro();
/* --------------------------------------------------------------------------------------------
* Retrieve the epoch time as milliseconds.
*/
static Int64 GetEpochTimeMilli();
/* --------------------------------------------------------------------------------------------
* See whether the specified date is valid.
*/
static bool ValidDate(Uint16 year, Uint8 month, Uint8 day);
/* --------------------------------------------------------------------------------------------
* See whether the specified year is a leap year.
*/
static bool IsLeapYear(Uint16 year)
{
return !(year % 400) || (!(year % 4) && (year % 100));
}
/* --------------------------------------------------------------------------------------------
* retrieve the number of days in the specified year.
*/
static Uint16 DaysInYear(Uint16 year)
{
return IsLeapYear(year) ? 366 : 365;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the number of days in the specified month.
*/
static Uint8 DaysInMonth(Uint16 year, Uint8 month);
/* --------------------------------------------------------------------------------------------
* Retrieve the number/position of the specified day in the specified year and month.
*/
static Uint16 DayOfYear(Uint16 year, Uint8 month, Uint8 day);
/* --------------------------------------------------------------------------------------------
* Convert just the year and day of year to full date.
*/
static Date ReverseDayOfyear(Uint16 year, Uint16 doy);
/* --------------------------------------------------------------------------------------------
* Calculate the number of days in the specified date range.
*/
static Int64 DateRangeToSeconds(Uint16 _year, Uint8 _month, Uint8 _day, Uint16 year_, Uint8 month_, Uint8 day_);
};
} // Namespace:: SqMod
#endif // _LIBRARY_CHRONO_HPP_

View File

@@ -0,0 +1,414 @@
// ------------------------------------------------------------------------------------------------
#include "Library/Chrono/Date.hpp"
#include "Library/Chrono/Time.hpp"
#include "Library/Chrono/Datetime.hpp"
#include "Library/Chrono/Timestamp.hpp"
#include "Base/Shared.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
SQMODE_DECL_TYPENAME(Typename, _SC("SqDate"))
// ------------------------------------------------------------------------------------------------
SQChar Date::Delimiter = '-';
// ------------------------------------------------------------------------------------------------
Int32 Date::Compare(const Date & o) const
{
if (m_Year < o.m_Year)
{
return -1;
}
else if (m_Year > o.m_Year)
{
return 1;
}
else if (m_Month < o.m_Month)
{
return -1;
}
else if (m_Month > o.m_Month)
{
return 1;
}
else if (m_Day < o.m_Day)
{
return -1;
}
else if (m_Day > o.m_Day)
{
return 1;
}
// They're equal
return 0;
}
// ------------------------------------------------------------------------------------------------
Date Date::operator + (const Date & o) const
{
// Add the components individually
return Date(o);
}
// ------------------------------------------------------------------------------------------------
Date Date::operator - (const Date & o) const
{
return Date(o);
}
// ------------------------------------------------------------------------------------------------
Date Date::operator * (const Date & o) const
{
return Date(o);
}
// ------------------------------------------------------------------------------------------------
Date Date::operator / (const Date & o) const
{
return Date(o);
}
// ------------------------------------------------------------------------------------------------
CSStr Date::ToString() const
{
return ToStrF("%04u%c%02u%c%02u", m_Year, m_Delimiter, m_Month, m_Delimiter, m_Day);
}
// ------------------------------------------------------------------------------------------------
void Date::Set(Uint16 year, Uint8 month, Uint8 day)
{
if (!Chrono::ValidDate(year, month, day))
{
STHROWF("Invalid date: %04u%c%02u%c%02u" , m_Year, m_Delimiter, m_Month, m_Delimiter, m_Day);
}
// Assign the specified values
m_Year = year;
m_Month = month;
m_Day = day;
}
// ------------------------------------------------------------------------------------------------
void Date::SetStr(CSStr str)
{
// The format specifications that will be used to scan the string
static SQChar fs[] = _SC(" %u - %u - %u ");
// Is the specified string empty?
if (!str || *str == '\0')
{
// Clear the values
m_Year = 0;
m_Month = 0;
m_Day = 0;
// We're done here
return;
}
// Assign the specified delimiter
fs[4] = m_Delimiter;
fs[9] = m_Delimiter;
// The sscanf function requires at least 32 bit integers
Uint32 year = 0, month = 0, day = 0;
// Attempt to extract the component values from the specified string
sscanf(str, fs, &year, &month, &day);
// Clamp the extracted values to the boundaries of associated type and assign them
Set(ClampL< Uint32, Uint8 >(year),
ClampL< Uint32, Uint8 >(month),
ClampL< Uint32, Uint8 >(day)
);
}
// ------------------------------------------------------------------------------------------------
void Date::SetDayOfYear(Uint16 doy)
{
// Reverse the given day of year to a full date
Date d = Chrono::ReverseDayOfyear(m_Year, doy);
// Set the obtained month
SetMonth(d.m_Month);
// Set the obtained day
SetDay(d.m_Day);
}
// ------------------------------------------------------------------------------------------------
void Date::SetYear(Uint16 year)
{
// Make sure the year is valid
if (!year)
{
STHROWF("Invalid year: %u", year);
}
// Assign the value
m_Year = year;
// Make sure the new date is valid
if (!Chrono::ValidDate(m_Year, m_Month, m_Day))
{
m_Month = 1;
m_Day = 1;
}
}
// ------------------------------------------------------------------------------------------------
void Date::SetMonth(Uint8 month)
{
// Make sure the month is valid
if (month == 0 || month > 12)
{
STHROWF("Invalid month: %u", month);
}
// Assign the value
m_Month = month;
// Make sure the month days are in range
if (m_Day > Chrono::DaysInMonth(m_Year, m_Month))
{
m_Month = 1; // Fall back to the beginning of the month
}
}
// ------------------------------------------------------------------------------------------------
void Date::SetDay(Uint8 day)
{
// Grab the amount of days in the current month
const Uint8 dim = Chrono::DaysInMonth(m_Year, m_Month);
// Make sure the day is valid
if (day == 0)
{
STHROWF("Invalid day: %u", day);
}
else if (day > dim)
{
STHROWF("Day is out of range: %u > %u", day, dim);
}
// Assign the value
m_Day = day;
}
// ------------------------------------------------------------------------------------------------
Date & Date::AddYears(Int32 years)
{
// Do we have a valid amount of years?
if (years)
{
// Add the specified amount of years
SetYear(ConvTo< Uint16 >::From(static_cast< Int32 >(m_Year) + years));
}
// Allow chaining operations
return *this;
}
// ------------------------------------------------------------------------------------------------
Date & Date::AddMonths(Int32 months)
{
// Do we have a valid amount of months?
if (months)
{
// Extract the number of years
Int32 years = static_cast< Int32 >(months / 12);
// Extract the number of months
months = (months % 12) + m_Month;
// Do we have extra months?
if (months >= 12)
{
// Increase the years
++years;
// Subtract one year from months
months %= 12;
}
else if (months < 0)
{
// Decrease the years
--years;
// Add one year to months
months = 12 - months;
}
// Are there any years to add?
if (years)
{
SetYear(ConvTo< Uint16 >::From(static_cast< Int32 >(m_Year) + years));
}
// Add the months
SetMonth(months);
}
// Allow chaining operations
return *this;
}
// ------------------------------------------------------------------------------------------------
Date & Date::AddDays(Int32 days)
{
// Do we have a valid amount of days?
if (days)
{
// Whether the number of days is positive or negative
const Int32 dir = days > 0 ? 1 : -1;
// Grab current year
Int32 year = m_Year;
// Calculate the days in the current year
Int32 diy = Chrono::DaysInYear(year);
// Calculate the day of year
Int32 doy = GetDayOfYear() + days;
// Calculate the resulting years
while (doy > diy || doy < 0)
{
doy -= diy * dir;
year += dir;
diy = Chrono::DaysInYear(year);
}
// Set the obtained year
SetYear(year);
// Set the obtained day of year
SetDayOfYear(doy);
}
// Allow chaining operations
return *this;
}
// ------------------------------------------------------------------------------------------------
Date Date::AndYears(Int32 years)
{
// Do we have a valid amount of years?
if (!years)
{
return Date(*this); // Return the date as is
}
// Replicate the current date
Date d(*this);
// Add the specified amount of years
d.SetYear(ConvTo< Uint16 >::From(static_cast< Int32 >(m_Year) + years));
// Return the resulted date
return d;
}
// ------------------------------------------------------------------------------------------------
Date Date::AndMonths(Int32 months)
{
// Do we have a valid amount of months?
if (!months)
{
return Date(*this); // Return the date as is
}
// Extract the number of years
Int32 years = static_cast< Int32 >(months / 12);
// Extract the number of months
months = (months % 12) + m_Month;
// Do we have extra months?
if (months >= 12)
{
// Increase the years
++years;
// Subtract one year from months
months %= 12;
}
else if (months < 0)
{
// Decrease the years
--years;
// Add one year to months
months = 12 - months;
}
// Replicate the current date
Date d(*this);
// Are there any years to add?
if (years)
{
d.SetYear(ConvTo< Uint16 >::From(static_cast< Int32 >(m_Year) + years));
}
// Add the months
d.SetMonth(months);
// Return the resulted date
return d;
}
// ------------------------------------------------------------------------------------------------
Date Date::AndDays(Int32 days)
{
// Do we have a valid amount of days?
if (!days)
{
return Date(*this); // Return the date as is
}
// Whether the number of days is positive or negative
const Int32 dir = days > 0 ? 1 : -1;
// Grab current year
Int32 year = m_Year;
// Calculate the days in the current year
Int32 diy = Chrono::DaysInYear(year);
// Calculate the day of year
Int32 doy = GetDayOfYear() + days;
// Calculate the resulting years
while (doy > diy || doy < 0)
{
doy -= diy * dir;
year += dir;
diy = Chrono::DaysInYear(year);
}
// Replicate the current date
Date d(*this);
// Set the obtained year
d.SetYear(year);
// Set the obtained day of year
d.SetDayOfYear(doy);
// Return the resulted date
return d;
}
// ------------------------------------------------------------------------------------------------
Timestamp Date::GetTimestamp() const
{
// Calculate the current day of the year
Int32 days = Chrono::DayOfYear(m_Year, m_Month, m_Day);
// Calculate all days till the current year
for (Int32 year = 0; year < m_Year; --year)
{
days += Chrono::DaysInYear(year);
}
// Return the resulted timestamp
return Timestamp(static_cast< Int64 >(days * 86400000000LL));
}
// ================================================================================================
void Register_ChronoDate(HSQUIRRELVM vm, Table & /*cns*/)
{
RootTable(vm).Bind(Typename::Str,
Class< Date >(vm, Typename::Str)
// Constructors
.Ctor()
.Ctor< Uint16 >()
.Ctor< Uint16, Uint8 >()
.Ctor< Uint16, Uint8, Uint8 >()
// Static Properties
.SetStaticValue(_SC("GlobalDelimiter"), &Date::Delimiter)
// Core Meta-methods
.SquirrelFunc(_SC("_typename"), &Typename::Fn)
.Func(_SC("_tostring"), &Date::ToString)
.Func(_SC("cmp"), &Date::Cmp)
// Meta-methods
.Func< Date (Date::*)(const Date &) const >(_SC("_add"), &Date::operator +)
.Func< Date (Date::*)(const Date &) const >(_SC("_sub"), &Date::operator -)
.Func< Date (Date::*)(const Date &) const >(_SC("_mul"), &Date::operator *)
.Func< Date (Date::*)(const Date &) const >(_SC("_div"), &Date::operator /)
// Properties
.Prop(_SC("Delimiter"), &Date::GetDelimiter, &Date::SetDelimiter)
.Prop(_SC("Str"), &Date::GetStr, &Date::SetStr)
.Prop(_SC("DayOfYear"), &Date::GetDayOfYear, &Date::SetDayOfYear)
.Prop(_SC("Year"), &Date::GetYear, &Date::SetYear)
.Prop(_SC("Month"), &Date::GetMonth, &Date::SetMonth)
.Prop(_SC("Day"), &Date::GetDay, &Date::SetDay)
.Prop(_SC("LeapYear"), &Date::IsThisLeapYear)
.Prop(_SC("YearDays"), &Date::GetYearDays)
.Prop(_SC("MonthDays"), &Date::GetMonthDays)
.Prop(_SC("Timestamp"), &Date::GetTimestamp)
// Member Methods
.Func(_SC("AddYears"), &Date::AddYears)
.Func(_SC("AddMonths"), &Date::AddMonths)
.Func(_SC("AddDays"), &Date::AddDays)
.Func(_SC("AndYears"), &Date::AndYears)
.Func(_SC("AndMonths"), &Date::AndMonths)
.Func(_SC("AndDays"), &Date::AndDays)
// Overloaded Methods
.Overload< void (Date::*)(Uint16) >(_SC("Set"), &Date::Set)
.Overload< void (Date::*)(Uint16, Uint8) >(_SC("Set"), &Date::Set)
.Overload< void (Date::*)(Uint16, Uint8, Uint8) >(_SC("Set"), &Date::Set)
);
}
} // Namespace:: SqMod

View File

@@ -0,0 +1,357 @@
#ifndef _LIBRARY_CHRONO_DATE_HPP_
#define _LIBRARY_CHRONO_DATE_HPP_
// ------------------------------------------------------------------------------------------------
#include "Library/Chrono.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* Helper class used to represent a certain date.
*/
class Date
{
public:
// ------------------------------------------------------------------------------------------------
static SQChar Delimiter;
private:
// ------------------------------------------------------------------------------------------------
Uint16 m_Year; // Year
Uint8 m_Month; // Month
Uint8 m_Day; // Day
// ------------------------------------------------------------------------------------------------
SQChar m_Delimiter; // Component delimiter when generating strings.
protected:
/* ------------------------------------------------------------------------------------------------
* Compare the values of two instances.
*/
Int32 Compare(const Date & o) const;
public:
/* ------------------------------------------------------------------------------------------------
* Default constructor.
*/
Date()
: m_Year(1970)
, m_Month(1)
, m_Day(1)
, m_Delimiter(Delimiter)
{
/* ... */
}
/* ------------------------------------------------------------------------------------------------
* Speciffic year constructor.
*/
Date(Uint16 year)
: m_Delimiter(Delimiter)
{
Set(year, 1, 1);
}
/* ------------------------------------------------------------------------------------------------
* Speciffic year and month constructor.
*/
Date(Uint16 year, Uint8 month)
: m_Delimiter(Delimiter)
{
Set(year, month, 1);
}
/* ------------------------------------------------------------------------------------------------
* Speciffic date constructor.
*/
Date(Uint16 year, Uint8 month, Uint8 day)
: m_Delimiter(Delimiter)
{
Set(year, month, day);
}
/* ------------------------------------------------------------------------------------------------
* String constructor.
*/
Date(CSStr str)
: m_Delimiter(Delimiter)
{
SetStr(str);
}
/* ------------------------------------------------------------------------------------------------
* Copy constructor.
*/
Date(const Date & o) = default;
/* ------------------------------------------------------------------------------------------------
* Move constructor.
*/
Date(Date && o) = default;
/* ------------------------------------------------------------------------------------------------
* Destructor.
*/
~Date() = default;
/* ------------------------------------------------------------------------------------------------
* Copy assignment operator.
*/
Date & operator = (const Date & o) = default;
/* ------------------------------------------------------------------------------------------------
* Move assignment operator.
*/
Date & operator = (Date && o) = default;
/* --------------------------------------------------------------------------------------------
* Equality comparison operator.
*/
bool operator == (const Date & o) const
{
return Compare(o) == 0;
}
/* --------------------------------------------------------------------------------------------
* Inequality comparison operator.
*/
bool operator != (const Date & o) const
{
return Compare(o) != 0;
}
/* --------------------------------------------------------------------------------------------
* Less than comparison operator.
*/
bool operator < (const Date & o) const
{
return Compare(o) < 0;
}
/* --------------------------------------------------------------------------------------------
* Greater than comparison operator.
*/
bool operator > (const Date & o) const
{
return Compare(o) > 0;
}
/* --------------------------------------------------------------------------------------------
* Less than or equal comparison operator.
*/
bool operator <= (const Date & o) const
{
return Compare(o) <= 0;
}
/* --------------------------------------------------------------------------------------------
* Greater than or equal comparison operator.
*/
bool operator >= (const Date & o) const
{
return Compare(o) >= 0;
}
/* --------------------------------------------------------------------------------------------
* Addition operator.
*/
Date operator + (const Date & o) const;
/* --------------------------------------------------------------------------------------------
* Subtraction operator.
*/
Date operator - (const Date & o) const;
/* --------------------------------------------------------------------------------------------
* Multiplication operator.
*/
Date operator * (const Date & o) const;
/* --------------------------------------------------------------------------------------------
* Division operator.
*/
Date operator / (const Date & o) const;
/* --------------------------------------------------------------------------------------------
* Used by the script engine to compare two instances of this type.
*/
Int32 Cmp(const Date & o) const
{
return Compare(o);
}
/* --------------------------------------------------------------------------------------------
* Used by the script engine to convert an instance of this type to a string.
*/
CSStr ToString() const;
/* ------------------------------------------------------------------------------------------------
* Assign the specified values.
*/
void Set(Uint16 year)
{
Set(year, m_Month, m_Day);
}
/* ------------------------------------------------------------------------------------------------
* Assign the specified values.
*/
void Set(Uint16 year, Uint8 month)
{
Set(year, month, m_Day);
}
/* ------------------------------------------------------------------------------------------------
* Assign the specified values.
*/
void Set(Uint16 year, Uint8 month, Uint8 day);
/* ------------------------------------------------------------------------------------------------
* Retrieve the local delimiter character.
*/
SQChar GetDelimiter() const
{
return m_Delimiter;
}
/* ------------------------------------------------------------------------------------------------
* Modify the local delimiter character.
*/
void SetDelimiter(SQChar c)
{
m_Delimiter = c;
}
/* ------------------------------------------------------------------------------------------------
* Retrieve the values as a string.
*/
CSStr GetStr() const
{
return ToString();
}
/* ------------------------------------------------------------------------------------------------
* Extract the values from a string.
*/
void SetStr(CSStr str);
/* ------------------------------------------------------------------------------------------------
* Retrieve the day component.
*/
Uint16 GetDayOfYear() const
{
return Chrono::DayOfYear(m_Year, m_Month, m_Day);
}
/* ------------------------------------------------------------------------------------------------
* Modify the day component.
*/
void SetDayOfYear(Uint16 doy);
/* ------------------------------------------------------------------------------------------------
* Retrieve the year component.
*/
Uint16 GetYear() const
{
return m_Year;
}
/* ------------------------------------------------------------------------------------------------
* Modify the year component.
*/
void SetYear(Uint16 year);
/* ------------------------------------------------------------------------------------------------
* Retrieve the month component.
*/
Uint8 GetMonth() const
{
return m_Month;
}
/* ------------------------------------------------------------------------------------------------
* Modify the month component.
*/
void SetMonth(Uint8 month);
/* ------------------------------------------------------------------------------------------------
* Retrieve the day component.
*/
Uint8 GetDay() const
{
return m_Day;
}
/* ------------------------------------------------------------------------------------------------
* Modify the day component.
*/
void SetDay(Uint8 day);
/* ------------------------------------------------------------------------------------------------
* Add the specified amount of years to the current date.
*/
Date & AddYears(Int32 years);
/* ------------------------------------------------------------------------------------------------
* Add the specified amount of months to the current date.
*/
Date & AddMonths(Int32 months);
/* ------------------------------------------------------------------------------------------------
* Add the specified amount of days to the current date.
*/
Date & AddDays(Int32 days);
/* ------------------------------------------------------------------------------------------------
* Add the specified amount of years to obtain a new date.
*/
Date AndYears(Int32 years);
/* ------------------------------------------------------------------------------------------------
* Add the specified amount of months to obtain a new date.
*/
Date AndMonths(Int32 months);
/* ------------------------------------------------------------------------------------------------
* Add the specified amount of days to obtain a new date.
*/
Date AndDays(Int32 days);
/* ------------------------------------------------------------------------------------------------
* See whether the associated year is a leap year.
*/
bool IsThisLeapYear() const
{
return Chrono::IsLeapYear(m_Year);
}
/* ------------------------------------------------------------------------------------------------
* Retrieve the number of days in the associated year.
*/
Uint16 GetYearDays() const
{
return Chrono::DaysInYear(m_Year);
}
/* ------------------------------------------------------------------------------------------------
* Retrieve the number of days in the associated month.
*/
Uint8 GetMonthDays() const
{
return Chrono::DaysInMonth(m_Year, m_Month);
}
/* ------------------------------------------------------------------------------------------------
* Convert this date instance to a time-stamp.
*/
Timestamp GetTimestamp() const;
};
} // Namespace:: SqMod
#endif // _LIBRARY_CHRONO_DATE_HPP_

View File

@@ -0,0 +1,822 @@
// ------------------------------------------------------------------------------------------------
#include "Library/Chrono/Datetime.hpp"
#include "Library/Chrono/Date.hpp"
#include "Library/Chrono/Time.hpp"
#include "Library/Chrono/Timestamp.hpp"
#include "Base/Shared.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
SQMODE_DECL_TYPENAME(Typename, _SC("SqDatetime"))
// ------------------------------------------------------------------------------------------------
SQChar Datetime::Delimiter = ' ';
SQChar Datetime::DateDelim = '-';
SQChar Datetime::TimeDelim = ':';
// ------------------------------------------------------------------------------------------------
Int32 Datetime::Compare(const Datetime & o) const
{
if (m_Year < o.m_Year)
{
return -1;
}
else if (m_Year > o.m_Year)
{
return 1;
}
else if (m_Month < o.m_Month)
{
return -1;
}
else if (m_Month > o.m_Month)
{
return 1;
}
else if (m_Day < o.m_Day)
{
return -1;
}
else if (m_Day > o.m_Day)
{
return 1;
}
else if (m_Hour < o.m_Hour)
{
return -1;
}
else if (m_Hour > o.m_Hour)
{
return 1;
}
else if (m_Minute < o.m_Minute)
{
return -1;
}
else if (m_Minute > o.m_Minute)
{
return 1;
}
else if (m_Second < o.m_Second)
{
return -1;
}
else if (m_Second > o.m_Second)
{
return 1;
}
else if (m_Millisecond < o.m_Millisecond)
{
return -1;
}
else if (m_Millisecond == o.m_Millisecond)
{
return 0;
}
else
{
return 1;
}
}
// ------------------------------------------------------------------------------------------------
Datetime Datetime::operator + (const Datetime & o) const
{
// Add the components individually
return Datetime(o);
}
// ------------------------------------------------------------------------------------------------
Datetime Datetime::operator - (const Datetime & o) const
{
return Datetime(o);
}
// ------------------------------------------------------------------------------------------------
Datetime Datetime::operator * (const Datetime & o) const
{
return Datetime(o);
}
// ------------------------------------------------------------------------------------------------
Datetime Datetime::operator / (const Datetime & o) const
{
return Datetime(o);
}
// ------------------------------------------------------------------------------------------------
CSStr Datetime::ToString() const
{
return ToStrF("%04u%c%02u%c%02u%c%02u%c%02u%c%02u%c%u"
, m_Year, m_DateDelim, m_Month, m_DateDelim, m_Day
, m_Delimiter
, m_Hour, m_TimeDelim, m_Minute, m_TimeDelim, m_Second , m_TimeDelim, m_Millisecond
);
}
// ------------------------------------------------------------------------------------------------
void Datetime::Set(Uint16 year, Uint8 month, Uint8 day, Uint8 hour, Uint8 minute, Uint8 second, Uint16 millisecond)
{
// Validate the specified date
if (!Chrono::ValidDate(year, month, day))
{
STHROWF("Invalid date: %04u%c%02u%c%02u%c%u"
, m_DateDelim, m_Year
, m_DateDelim, m_Month
, m_DateDelim, m_Day
);
}
// Is the specified hour within range?
else if (hour >= 24)
{
STHROWF("Hour value is out of range: %u >= 24", hour);
}
// Is the specified minute within range?
else if (minute >= 60)
{
STHROWF("Minute value is out of range: %u >= 60", minute);
}
// Is the specified second within range?
else if (second >= 60)
{
STHROWF("Second value is out of range: %u >= 60", second);
}
// Is the specified millisecond within range?
else if (millisecond >= 1000)
{
STHROWF("Millisecond value is out of range: %u >= 1000", millisecond);
}
// Assign the specified values
m_Year = year;
m_Month = month;
m_Day = day;
m_Hour = hour;
m_Minute = minute;
m_Second = second;
m_Millisecond = millisecond;
}
// ------------------------------------------------------------------------------------------------
void Datetime::SetStr(CSStr str)
{
// The format specifications that will be used to scan the string
static SQChar fs[] = _SC(" %u - %u - %u %u : %u : %u : %u ");
// Is the specified string empty?
if (!str || *str == '\0')
{
// Clear the values
m_Year = 0;
m_Month = 0;
m_Day = 0;
m_Hour = 0;
m_Minute = 0;
m_Second = 0;
m_Millisecond = 0;
// We're done here
return;
}
// Assign the specified delimiter
fs[4] = m_DateDelim;
fs[9] = m_DateDelim;
fs[14] = m_Delimiter;
fs[19] = m_TimeDelim;
fs[24] = m_TimeDelim;
fs[29] = m_TimeDelim;
// The sscanf function requires at least 32 bit integers
Uint32 year = 0, month = 0, day = 0, hour = 0, minute = 0, second = 0, milli = 0;
// Attempt to extract the component values from the specified string
sscanf(str, fs, &year, &month, &day, &hour, &minute, &second, &milli);
// Clamp the extracted values to the boundaries of associated type and assign them
Set(ClampL< Uint32, Uint8 >(year),
ClampL< Uint32, Uint8 >(month),
ClampL< Uint32, Uint8 >(day),
ClampL< Uint32, Uint8 >(hour),
ClampL< Uint32, Uint8 >(minute),
ClampL< Uint32, Uint8 >(second),
ClampL< Uint32, Uint16 >(milli)
);
}
// ------------------------------------------------------------------------------------------------
void Datetime::SetDayOfYear(Uint16 doy)
{
// Reverse the given day of year to a full date
Date d = Chrono::ReverseDayOfyear(m_Year, doy);
// Set the obtained month
SetMonth(d.GetMonth());
// Set the obtained day
SetDay(d.GetDay());
}
// ------------------------------------------------------------------------------------------------
void Datetime::SetYear(Uint16 year)
{
// Make sure the year is valid
if (!year)
{
STHROWF("Invalid year: %u", year);
}
// Assign the value
m_Year = year;
// Make sure the new date is valid
if (!Chrono::ValidDate(m_Year, m_Month, m_Day))
{
m_Month = 1;
m_Day = 1;
}
}
// ------------------------------------------------------------------------------------------------
void Datetime::SetMonth(Uint8 month)
{
// Make sure the month is valid
if (month == 0 || month > 12)
{
STHROWF("Invalid month: %u", month);
}
// Assign the value
m_Month = month;
// Make sure the month days are in range
if (m_Day > Chrono::DaysInMonth(m_Year, m_Month))
{
m_Month = 1; // Fall back to the beginning of the month
}
}
// ------------------------------------------------------------------------------------------------
void Datetime::SetDay(Uint8 day)
{
// Grab the amount of days in the current month
const Uint8 dim = Chrono::DaysInMonth(m_Year, m_Month);
// Make sure the day is valid
if (day == 0)
{
STHROWF("Invalid day: %u", day);
}
else if (day > dim)
{
STHROWF("Day is out of range: %u > %u", day, dim);
}
// Assign the value
m_Day = day;
}
// ------------------------------------------------------------------------------------------------
void Datetime::SetHour(Uint8 hour)
{
// Is the specified hour within range?
if (hour >= 24)
{
STHROWF("Hour value is out of range: %u >= 24", hour);
}
// Now it's safe to assign the value
m_Hour = hour;
}
// ------------------------------------------------------------------------------------------------
void Datetime::SetMinute(Uint8 minute)
{
// Is the specified minute within range?
if (minute >= 60)
{
STHROWF("Minute value is out of range: %u >= 60", minute);
}
// Now it's safe to assign the value
m_Minute = minute;
}
// ------------------------------------------------------------------------------------------------
void Datetime::SetSecond(Uint8 second)
{
// Is the specified second within range?
if (second >= 60)
{
STHROWF("Second value is out of range: %u >= 60", second);
}
// Now it's safe to assign the value
m_Second = second;
}
// ------------------------------------------------------------------------------------------------
void Datetime::SetMillisecond(Uint16 millisecond)
{
// Is the specified millisecond within range?
if (millisecond >= 1000)
{
STHROWF("Millisecond value is out of range: %u >= 1000", millisecond);
}
// Now it's safe to assign the value
m_Millisecond = millisecond;
}
// ------------------------------------------------------------------------------------------------
Datetime & Datetime::AddYears(Int32 years)
{
// Do we have a valid amount of years?
if (years)
{
// Add the specified amount of years
SetYear(ConvTo< Uint16 >::From(static_cast< Int32 >(m_Year) + years));
}
// Allow chaining operations
return *this;
}
// ------------------------------------------------------------------------------------------------
Datetime & Datetime::AddMonths(Int32 months)
{
// Do we have a valid amount of months?
if (months)
{
// Extract the number of years
Int32 years = static_cast< Int32 >(months / 12);
// Extract the number of months
months = (months % 12) + m_Month;
// Do we have extra months?
if (months >= 12)
{
// Increase the years
++years;
// Subtract one year from months
months %= 12;
}
else if (months < 0)
{
// Decrease the years
--years;
// Add one year to months
months = 12 - months;
}
// Are there any years to add?
if (years)
{
SetYear(ConvTo< Uint16 >::From(static_cast< Int32 >(m_Year) + years));
}
// Add the months
SetMonth(months);
}
// Allow chaining operations
return *this;
}
// ------------------------------------------------------------------------------------------------
Datetime & Datetime::AddDays(Int32 days)
{
// Do we have a valid amount of days?
if (days)
{
// Whether the number of days is positive or negative
const Int32 dir = days > 0 ? 1 : -1;
// Grab current year
Int32 year = m_Year;
// Calculate the days in the current year
Int32 diy = Chrono::DaysInYear(year);
// Calculate the day of year
Int32 doy = GetDayOfYear() + days;
// Calculate the resulting years
while (doy > diy || doy < 0)
{
doy -= diy * dir;
year += dir;
diy = Chrono::DaysInYear(year);
}
// Set the obtained year
SetYear(year);
// Set the obtained day of year
SetDayOfYear(doy);
}
// Allow chaining operations
return *this;
}
// ------------------------------------------------------------------------------------------------
Datetime & Datetime::AddHours(Int32 hours)
{
// Did we even add any hours?
if (hours)
{
// Extract the number of days
Int32 days = static_cast< Int32 >(hours / 24);
// Extract the number of hours
m_Hour += (hours % 24);
// Are the hours overlapping with the next day?
if (m_Hour >= 24)
{
// Increase the days
++days;
// Subtract one day from hours
m_Hour %= 24;
}
// Should we add any days?
if (days)
{
AddDays(days);
}
}
// Allow chaining operations
return *this;
}
// ------------------------------------------------------------------------------------------------
Datetime & Datetime::AddMinutes(Int32 minutes)
{
// Did we even add any minutes?
if (minutes)
{
// Extract the number of hours
Int32 hours = static_cast< Int32 >(minutes / 60);
// Extract the number of minutes
m_Minute += (minutes % 60);
// Are the minutes overlapping with the next hour?
if (m_Minute >= 60)
{
// Increase the hours
++hours;
// Subtract one hour from minutes
m_Minute %= 60;
}
// Should we add any hours?
if (hours)
{
AddHours(hours);
}
}
// Allow chaining operations
return *this;
}
// ------------------------------------------------------------------------------------------------
Datetime & Datetime::AddSeconds(Int32 seconds)
{
// Did we even add any seconds?
if (seconds)
{
// Extract the number of minutes
Int32 minutes = static_cast< Int32 >(seconds / 60);
// Extract the number of seconds
m_Second += (seconds % 60);
// Are the seconds overlapping with the next minute?
if (m_Second >= 60)
{
// Increase the minutes
++minutes;
// Subtract one minute from seconds
m_Second %= 60;
}
// Should we add any minutes?
if (minutes)
{
AddMinutes(minutes);
}
}
// Allow chaining operations
return *this;
}
// ------------------------------------------------------------------------------------------------
Datetime & Datetime::AddMilliseconds(Int32 milliseconds)
{
// Did we even add any milliseconds?
if (milliseconds)
{
// Extract the number of seconds
Int32 seconds = static_cast< Int32 >(milliseconds / 1000);
// Extract the number of milliseconds
m_Millisecond += (milliseconds / 1000);
// Are the milliseconds overlapping with the next second?
if (m_Millisecond >= 1000)
{
// Increase the seconds
++seconds;
// Subtract one second from milliseconds
m_Millisecond %= 1000;
}
// Should we add any seconds?
if (seconds)
{
AddSeconds(seconds);
}
}
// Allow chaining operations
return *this;
}
// ------------------------------------------------------------------------------------------------
Datetime Datetime::AndYears(Int32 years)
{
// Do we have a valid amount of years?
if (!years)
{
return Datetime(*this); // Return the date-time as is
}
// Replicate the current date
Datetime dt(*this);
// Add the specified amount of years
dt.SetYear(ConvTo< Uint16 >::From(static_cast< Int32 >(m_Year) + years));
// Return the resulted date
return dt;
}
// ------------------------------------------------------------------------------------------------
Datetime Datetime::AndMonths(Int32 months)
{
// Do we have a valid amount of months?
if (!months)
{
return Datetime(*this); // Return the date-time as is
}
// Extract the number of years
Int32 years = static_cast< Int32 >(months / 12);
// Extract the number of months
months = (months % 12) + m_Month;
// Do we have extra months?
if (months >= 12)
{
// Increase the years
++years;
// Subtract one year from months
months %= 12;
}
else if (months < 0)
{
// Decrease the years
--years;
// Add one year to months
months = 12 - months;
}
// Replicate the current date
Datetime dt(*this);
// Are there any years to add?
if (years)
{
dt.SetYear(ConvTo< Uint16 >::From(static_cast< Int32 >(m_Year) + years));
}
// Add the months
dt.SetMonth(months);
// Return the resulted date
return dt;
}
// ------------------------------------------------------------------------------------------------
Datetime Datetime::AndDays(Int32 days)
{
// Do we have a valid amount of days?
if (!days)
{
return Datetime(*this); // Return the date-time as is
}
// Whether the number of days is positive or negative
const Int32 dir = days > 0 ? 1 : -1;
// Grab current year
Int32 year = m_Year;
// Calculate the days in the current year
Int32 diy = Chrono::DaysInYear(year);
// Calculate the day of year
Int32 doy = GetDayOfYear() + days;
// Calculate the resulting years
while (doy > diy || doy < 0)
{
doy -= diy * dir;
year += dir;
diy = Chrono::DaysInYear(year);
}
// Replicate the current date
Datetime dt(*this);
// Set the obtained year
dt.SetYear(year);
// Set the obtained day of year
dt.SetDayOfYear(doy);
// Return the resulted date
return dt;
}
// ------------------------------------------------------------------------------------------------
Datetime Datetime::AndHours(Int32 hours)
{
// Did we even add any hours?
if (!hours)
{
return Datetime(*this); // Return the date-time as is
}
// Extract the number of days
Int32 days = static_cast< Int32 >(hours / 24);
// Extract the number of hours
hours = m_Hour + (hours % 24);
// Are the hours overlapping with the next day?
if (hours >= 24)
{
++days; // Increase the days
}
// Replicate the current time
Datetime dt(*this);
// Should we add any days?
if (days)
{
dt.AddDays(days);
}
// Assign the resulted hours
dt.m_Hour = (hours % 24);
// Return the result
return dt;
}
// ------------------------------------------------------------------------------------------------
Datetime Datetime::AndMinutes(Int32 minutes)
{
// Did we even added any minutes?
if (!minutes)
{
return Datetime(*this); // Return the date-time as is
}
// Extract the number of hours
Int32 hours = static_cast< Int32 >(minutes / 60);
// Extract the number of minutes
minutes = m_Minute + (minutes % 60);
// Are the minutes overlapping with the next hour?
if (minutes >= 60)
{
++hours; // Increase hours
}
// Replicate the current time
Datetime dt(*this);
// Should we add any hours?
if (hours)
{
dt.AddHours(hours);
}
// Assign the resulted minutes
dt.m_Minute = (minutes % 60);
// Return the result
return dt;
}
// ------------------------------------------------------------------------------------------------
Datetime Datetime::AndSeconds(Int32 seconds)
{
// Did we even added any seconds?
if (!seconds)
{
return Datetime(*this); // Return the date-time as is
}
// Extract the number of minutes
Int32 minutes = static_cast< Int32 >(seconds / 60);
// Extract the number of seconds
seconds = m_Second + (seconds % 60);
// Are the seconds overlapping with the next minute?
if (seconds >= 60)
{
++minutes; // Increase minutes
}
// Replicate the current time
Datetime dt(*this);
// Should we add any minutes?
if (minutes)
{
dt.AddMinutes(minutes);
}
// Assign the resulted seconds
dt.m_Second = (seconds % 60);
// Return the result
return dt;
}
// ------------------------------------------------------------------------------------------------
Datetime Datetime::AndMilliseconds(Int32 milliseconds)
{
// Did we even added any milliseconds?
if (!milliseconds)
{
return Datetime(*this); // Return the date-time as is
}
// Extract the number of seconds
Int32 seconds = static_cast< Int32 >(milliseconds / 1000);
// Extract the number of milliseconds
milliseconds = m_Millisecond + (milliseconds % 1000);
// Are the milliseconds overlapping with the next second?
if (milliseconds >= 1000)
{
++seconds; // Increase seconds
}
// Replicate the current time
Datetime dt(*this);
// Should we add any seconds?
if (seconds)
{
dt.AddSeconds(seconds);
}
// Assign the resulted milliseconds
dt.m_Millisecond = (milliseconds % 1000);
// Return the result
return dt;
}
// ------------------------------------------------------------------------------------------------
Date Datetime::GetDate() const
{
return Date(m_Year, m_Month, m_Day);
}
// ------------------------------------------------------------------------------------------------
Time Datetime::GetTime() const
{
return Time(m_Hour, m_Minute, m_Second, m_Millisecond);
}
// ------------------------------------------------------------------------------------------------
Timestamp Datetime::GetTimestamp() const
{
// Calculate the current day of the year
Int32 days = Chrono::DayOfYear(m_Year, m_Month, m_Day);
// Calculate all days till the current year
for (Int32 year = 0; year < m_Year; --year)
{
days += Chrono::DaysInYear(year);
}
// Calculate the microseconds in the resulted days
Int64 ms = static_cast< Int64 >(days * 86400000000LL);
// Calculate the microseconds in the current time
ms += static_cast< Int64 >(m_Hour * 3600000000LL);
ms += static_cast< Int64 >(m_Minute * 60000000L);
ms += static_cast< Int64 >(m_Second * 1000000L);
ms += static_cast< Int64 >(m_Millisecond * 1000L);
// Return the resulted timestamp
return Timestamp(ms);
}
// ================================================================================================
void Register_ChronoDatetime(HSQUIRRELVM vm, Table & /*cns*/)
{
RootTable(vm).Bind(Typename::Str,
Class< Datetime >(vm, Typename::Str)
// Constructors
.Ctor()
.Ctor< Uint16 >()
.Ctor< Uint16, Uint8 >()
.Ctor< Uint16, Uint8, Uint8 >()
.Ctor< Uint16, Uint8, Uint8, Uint8 >()
.Ctor< Uint16, Uint8, Uint8, Uint8, Uint8 >()
.Ctor< Uint16, Uint8, Uint8, Uint8, Uint8, Uint8 >()
.Ctor< Uint16, Uint8, Uint8, Uint8, Uint8, Uint8, Uint16 >()
// Static Properties
.SetStaticValue(_SC("GlobalDelimiter"), &Datetime::Delimiter)
.SetStaticValue(_SC("GlobalDateDelim"), &Datetime::DateDelim)
.SetStaticValue(_SC("GlobalTimeDelim"), &Datetime::TimeDelim)
// Core Meta-methods
.SquirrelFunc(_SC("_typename"), &Typename::Fn)
.Func(_SC("_tostring"), &Datetime::ToString)
.Func(_SC("cmp"), &Datetime::Cmp)
// Meta-methods
.Func< Datetime (Datetime::*)(const Datetime &) const >(_SC("_add"), &Datetime::operator +)
.Func< Datetime (Datetime::*)(const Datetime &) const >(_SC("_sub"), &Datetime::operator -)
.Func< Datetime (Datetime::*)(const Datetime &) const >(_SC("_mul"), &Datetime::operator *)
.Func< Datetime (Datetime::*)(const Datetime &) const >(_SC("_div"), &Datetime::operator /)
// Properties
.Prop(_SC("Delimiter"), &Datetime::GetDelimiter, &Datetime::SetDelimiter)
.Prop(_SC("DateDelim"), &Datetime::GetDateDelim, &Datetime::SetDateDelim)
.Prop(_SC("TimeDelim"), &Datetime::GetTimeDelim, &Datetime::SetTimeDelim)
.Prop(_SC("Str"), &Datetime::GetStr, &Datetime::SetStr)
.Prop(_SC("DayOfYear"), &Datetime::GetDayOfYear, &Datetime::SetDayOfYear)
.Prop(_SC("Year"), &Datetime::GetYear, &Datetime::SetYear)
.Prop(_SC("Month"), &Datetime::GetMonth, &Datetime::SetMonth)
.Prop(_SC("Day"), &Datetime::GetDay, &Datetime::SetDay)
.Prop(_SC("Hour"), &Datetime::GetHour, &Datetime::SetHour)
.Prop(_SC("Minute"), &Datetime::GetMinute, &Datetime::SetMinute)
.Prop(_SC("Second"), &Datetime::GetSecond, &Datetime::SetSecond)
.Prop(_SC("Millisecond"), &Datetime::GetMillisecond, &Datetime::SetMillisecond)
.Prop(_SC("LeapYear"), &Datetime::IsThisLeapYear)
.Prop(_SC("YearDays"), &Datetime::GetYearDays)
.Prop(_SC("MonthDays"), &Datetime::GetMonthDays)
.Prop(_SC("Date"), &Datetime::GetDate)
.Prop(_SC("Time"), &Datetime::GetTime)
.Prop(_SC("Timestamp"), &Datetime::GetTimestamp)
// Member Methods
.Func(_SC("AddYears"), &Datetime::AddYears)
.Func(_SC("AddMonths"), &Datetime::AddMonths)
.Func(_SC("AddDays"), &Datetime::AddDays)
.Func(_SC("AddHours"), &Datetime::AddHours)
.Func(_SC("AddMinutes"), &Datetime::AddMinutes)
.Func(_SC("AddSeconds"), &Datetime::AddSeconds)
.Func(_SC("AddMillis"), &Datetime::AddMilliseconds)
.Func(_SC("AddMilliseconds"), &Datetime::AddMilliseconds)
.Func(_SC("AndYears"), &Datetime::AndYears)
.Func(_SC("AndMonths"), &Datetime::AndMonths)
.Func(_SC("AndDays"), &Datetime::AndDays)
.Func(_SC("AndHours"), &Datetime::AndHours)
.Func(_SC("AndMinutes"), &Datetime::AndMinutes)
.Func(_SC("AndSeconds"), &Datetime::AndSeconds)
.Func(_SC("AndMillis"), &Datetime::AndMilliseconds)
.Func(_SC("AndMilliseconds"), &Datetime::AndMilliseconds)
// Overloaded Methods
.Overload< void (Datetime::*)(Uint16) >(_SC("Set"), &Datetime::Set)
.Overload< void (Datetime::*)(Uint16, Uint8) >(_SC("Set"), &Datetime::Set)
.Overload< void (Datetime::*)(Uint16, Uint8, Uint8) >(_SC("Set"), &Datetime::Set)
.Overload< void (Datetime::*)(Uint16, Uint8, Uint8, Uint8) >(_SC("Set"), &Datetime::Set)
.Overload< void (Datetime::*)(Uint16, Uint8, Uint8, Uint8, Uint8) >(_SC("Set"), &Datetime::Set)
.Overload< void (Datetime::*)(Uint16, Uint8, Uint8, Uint8, Uint8, Uint8) >(_SC("Set"), &Datetime::Set)
.Overload< void (Datetime::*)(Uint16, Uint8, Uint8, Uint8, Uint8, Uint8, Uint16) >(_SC("Set"), &Datetime::Set)
);
}
} // Namespace:: SqMod

View File

@@ -0,0 +1,580 @@
#ifndef _LIBRARY_CHRONO_DATETIME_HPP_
#define _LIBRARY_CHRONO_DATETIME_HPP_
// ------------------------------------------------------------------------------------------------
#include "Library/Chrono.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* Helper class used to represent a certain date and time.
*/
class Datetime
{
public:
// ------------------------------------------------------------------------------------------------
static SQChar Delimiter;
static SQChar DateDelim;
static SQChar TimeDelim;
private:
// ------------------------------------------------------------------------------------------------
Uint16 m_Year; // Year
Uint8 m_Month; // Month
Uint8 m_Day; // Day
// ------------------------------------------------------------------------------------------------
Uint8 m_Hour; // Hour
Uint8 m_Minute; // Minute
Uint8 m_Second; // Second
Uint16 m_Millisecond; // Millisecond
// ------------------------------------------------------------------------------------------------
SQChar m_Delimiter; // Date and time delimiter when generating strings.
SQChar m_DateDelim; // Date component delimiter when generating strings.
SQChar m_TimeDelim; // Time component delimiter when generating strings.
protected:
/* ------------------------------------------------------------------------------------------------
* Compare the values of two instances.
*/
Int32 Compare(const Datetime & o) const;
public:
/* ------------------------------------------------------------------------------------------------
* Default constructor.
*/
Datetime()
: m_Year(1970)
, m_Month(1)
, m_Day(1)
, m_Hour(0)
, m_Minute(0)
, m_Second(0)
, m_Millisecond(0)
, m_Delimiter(Delimiter)
, m_DateDelim(DateDelim)
, m_TimeDelim(TimeDelim)
{
/* ... */
}
/* ------------------------------------------------------------------------------------------------
* Speciffic year constructor.
*/
Datetime(Uint16 year)
: m_Delimiter(Delimiter)
, m_DateDelim(DateDelim)
, m_TimeDelim(TimeDelim)
{
Set(year, 1, 1, 0, 0, 0, 0);
}
/* ------------------------------------------------------------------------------------------------
* Speciffic year and month constructor.
*/
Datetime(Uint16 year, Uint8 month)
: m_Delimiter(Delimiter)
, m_DateDelim(DateDelim)
, m_TimeDelim(TimeDelim)
{
Set(year, month, 1, 0, 0, 0, 0);
}
/* ------------------------------------------------------------------------------------------------
* Speciffic date constructor.
*/
Datetime(Uint16 year, Uint8 month, Uint8 day)
: m_Delimiter(Delimiter)
, m_DateDelim(DateDelim)
, m_TimeDelim(TimeDelim)
{
Set(year, month, day, 0, 0, 0, 0);
}
/* ------------------------------------------------------------------------------------------------
* Speciffic date and hour constructor.
*/
Datetime(Uint16 year, Uint8 month, Uint8 day, Uint8 hour)
: m_Delimiter(Delimiter)
, m_DateDelim(DateDelim)
, m_TimeDelim(TimeDelim)
{
Set(year, month, day, hour, 0, 0, 0);
}
/* ------------------------------------------------------------------------------------------------
* Speciffic date, hour and minute constructor.
*/
Datetime(Uint16 year, Uint8 month, Uint8 day, Uint8 hour, Uint8 minute)
: m_Delimiter(Delimiter)
, m_DateDelim(DateDelim)
, m_TimeDelim(TimeDelim)
{
Set(year, month, day, hour, minute, 0, 0);
}
/* ------------------------------------------------------------------------------------------------
* Speciffic date and time constructor.
*/
Datetime(Uint16 year, Uint8 month, Uint8 day, Uint8 hour, Uint8 minute, Uint8 second)
: m_Delimiter(Delimiter)
, m_DateDelim(DateDelim)
, m_TimeDelim(TimeDelim)
{
Set(year, month, day, hour, minute, second, 0);
}
/* ------------------------------------------------------------------------------------------------
* Speciffic date and precise time constructor.
*/
Datetime(Uint16 year, Uint8 month, Uint8 day, Uint8 hour, Uint8 minute, Uint8 second, Uint16 millisecond)
: m_Delimiter(Delimiter)
, m_DateDelim(DateDelim)
, m_TimeDelim(TimeDelim)
{
Set(year, month, day, hour, minute, second, millisecond);
}
/* --------------------------------------------------------------------------------------------
* Copy constructor.
*/
Datetime(const Datetime & o) = default;
/* --------------------------------------------------------------------------------------------
* Move constructor.
*/
Datetime(Datetime && o) = default;
/* --------------------------------------------------------------------------------------------
* Destructor.
*/
~Datetime() = default;
/* --------------------------------------------------------------------------------------------
* Copy assignment operator.
*/
Datetime & operator = (const Datetime & o) = default;
/* --------------------------------------------------------------------------------------------
* Move assignment operator.
*/
Datetime & operator = (Datetime && o) = default;
/* --------------------------------------------------------------------------------------------
* Equality comparison operator.
*/
bool operator == (const Datetime & o) const
{
return Compare(o) == 0;
}
/* --------------------------------------------------------------------------------------------
* Inequality comparison operator.
*/
bool operator != (const Datetime & o) const
{
return Compare(o) != 0;
}
/* --------------------------------------------------------------------------------------------
* Less than comparison operator.
*/
bool operator < (const Datetime & o) const
{
return Compare(o) < 0;
}
/* --------------------------------------------------------------------------------------------
* Greater than comparison operator.
*/
bool operator > (const Datetime & o) const
{
return Compare(o) > 0;
}
/* --------------------------------------------------------------------------------------------
* Less than or equal comparison operator.
*/
bool operator <= (const Datetime & o) const
{
return Compare(o) <= 0;
}
/* --------------------------------------------------------------------------------------------
* Greater than or equal comparison operator.
*/
bool operator >= (const Datetime & o) const
{
return Compare(o) >= 0;
}
/* --------------------------------------------------------------------------------------------
* Addition operator.
*/
Datetime operator + (const Datetime & o) const;
/* --------------------------------------------------------------------------------------------
* Subtraction operator.
*/
Datetime operator - (const Datetime & o) const;
/* --------------------------------------------------------------------------------------------
* Multiplication operator.
*/
Datetime operator * (const Datetime & o) const;
/* --------------------------------------------------------------------------------------------
* Division operator.
*/
Datetime operator / (const Datetime & o) const;
/* --------------------------------------------------------------------------------------------
* Used by the script engine to compare two instances of this type.
*/
Int32 Cmp(const Datetime & o) const
{
return Compare(o);
}
/* --------------------------------------------------------------------------------------------
* Used by the script engine to convert an instance of this type to a string.
*/
CSStr ToString() const;
/* ------------------------------------------------------------------------------------------------
* Assign the specified values.
*/
void Set(Uint16 year)
{
Set(year, m_Month, m_Day, m_Hour, m_Minute, m_Second, m_Millisecond);
}
/* ------------------------------------------------------------------------------------------------
* Assign the specified values.
*/
void Set(Uint16 year, Uint8 month)
{
Set(year, month, m_Day, m_Hour, m_Minute, m_Second, m_Millisecond);
}
/* ------------------------------------------------------------------------------------------------
* Assign the specified values.
*/
void Set(Uint16 year, Uint8 month, Uint8 day)
{
Set(year, month, day, m_Hour, m_Minute, m_Second, m_Millisecond);
}
/* ------------------------------------------------------------------------------------------------
* Assign the specified values.
*/
void Set(Uint16 year, Uint8 month, Uint8 day, Uint8 hour)
{
Set(year, month, day, hour, m_Minute, m_Second, m_Millisecond);
}
/* ------------------------------------------------------------------------------------------------
* Assign the specified values.
*/
void Set(Uint16 year, Uint8 month, Uint8 day, Uint8 hour, Uint8 minute)
{
Set(year, month, day, hour, minute, m_Second, m_Millisecond);
}
/* ------------------------------------------------------------------------------------------------
* Assign the specified values.
*/
void Set(Uint16 year, Uint8 month, Uint8 day, Uint8 hour, Uint8 minute, Uint8 second)
{
Set(year, month, day, hour, minute, second, m_Millisecond);
}
/* ------------------------------------------------------------------------------------------------
* Assign the specified values.
*/
void Set(Uint16 year, Uint8 month, Uint8 day, Uint8 hour, Uint8 minute, Uint8 second, Uint16 millisecond);
/* ------------------------------------------------------------------------------------------------
* Retrieve the local delimiter character.
*/
SQChar GetDelimiter() const
{
return m_Delimiter;
}
/* ------------------------------------------------------------------------------------------------
* Modify the local delimiter character.
*/
void SetDelimiter(SQChar c)
{
m_Delimiter = c;
}
/* ------------------------------------------------------------------------------------------------
* Retrieve the local date delimiter character.
*/
SQChar GetDateDelim() const
{
return m_DateDelim;
}
/* ------------------------------------------------------------------------------------------------
* Modify the local date delimiter character.
*/
void SetDateDelim(SQChar c)
{
m_DateDelim = c;
}
/* ------------------------------------------------------------------------------------------------
* Retrieve the local time delimiter character.
*/
SQChar GetTimeDelim() const
{
return m_TimeDelim;
}
/* ------------------------------------------------------------------------------------------------
* Modify the local time delimiter character.
*/
void SetTimeDelim(SQChar c)
{
m_TimeDelim = c;
}
/* ------------------------------------------------------------------------------------------------
* Retrieve the values as a string.
*/
CSStr GetStr() const
{
return ToString();
}
/* ------------------------------------------------------------------------------------------------
* Extract the values from a string.
*/
void SetStr(CSStr str);
/* ------------------------------------------------------------------------------------------------
* Retrieve the day component.
*/
Uint16 GetDayOfYear() const
{
return Chrono::DayOfYear(m_Year, m_Month, m_Day);
}
/* ------------------------------------------------------------------------------------------------
* Modify the day component.
*/
void SetDayOfYear(Uint16 doy);
/* ------------------------------------------------------------------------------------------------
* Retrieve the year component.
*/
Uint16 GetYear() const
{
return m_Year;
}
/* ------------------------------------------------------------------------------------------------
* Modify the year component.
*/
void SetYear(Uint16 year);
/* ------------------------------------------------------------------------------------------------
* Retrieve the month component.
*/
Uint8 GetMonth() const
{
return m_Month;
}
/* ------------------------------------------------------------------------------------------------
* Modify the month component.
*/
void SetMonth(Uint8 month);
/* ------------------------------------------------------------------------------------------------
* Retrieve the day component.
*/
Uint8 GetDay() const
{
return m_Day;
}
/* ------------------------------------------------------------------------------------------------
* Modify the day component.
*/
void SetDay(Uint8 day);
/* ------------------------------------------------------------------------------------------------
* Retrieve the hour component.
*/
Uint8 GetHour() const
{
return m_Hour;
}
/* ------------------------------------------------------------------------------------------------
* Modify the hour component.
*/
void SetHour(Uint8 hour);
/* ------------------------------------------------------------------------------------------------
* Retrieve the minute component.
*/
Uint8 GetMinute() const
{
return m_Minute;
}
/* ------------------------------------------------------------------------------------------------
* Modify the minute component.
*/
void SetMinute(Uint8 minute);
/* ------------------------------------------------------------------------------------------------
* Retrieve the second component.
*/
Uint8 GetSecond() const
{
return m_Second;
}
/* ------------------------------------------------------------------------------------------------
* Modify the second component.
*/
void SetSecond(Uint8 second);
/* ------------------------------------------------------------------------------------------------
* Retrieve the millisecond component.
*/
Uint16 GetMillisecond() const
{
return m_Millisecond;
}
/* ------------------------------------------------------------------------------------------------
* Modify the millisecond component.
*/
void SetMillisecond(Uint16 millisecond);
/* ------------------------------------------------------------------------------------------------
* Add the specified amount of years to the current date.
*/
Datetime & AddYears(Int32 years);
/* ------------------------------------------------------------------------------------------------
* Add the specified amount of months to the current date.
*/
Datetime & AddMonths(Int32 months);
/* ------------------------------------------------------------------------------------------------
* Add the specified amount of days to the current date.
*/
Datetime & AddDays(Int32 days);
/* ------------------------------------------------------------------------------------------------
* Add the specified amount of hours to the current time.
*/
Datetime & AddHours(Int32 hours);
/* ------------------------------------------------------------------------------------------------
* Add the specified amount of minutes to the current time.
*/
Datetime & AddMinutes(Int32 minutes);
/* ------------------------------------------------------------------------------------------------
* Add the specified amount of seconds to the current time.
*/
Datetime & AddSeconds(Int32 seconds);
/* ------------------------------------------------------------------------------------------------
* Add the specified amount of milliseconds to the current time.
*/
Datetime & AddMilliseconds(Int32 milliseconds);
/* ------------------------------------------------------------------------------------------------
* Add the specified amount of years to obtain a new date.
*/
Datetime AndYears(Int32 years);
/* ------------------------------------------------------------------------------------------------
* Add the specified amount of months to obtain a new date.
*/
Datetime AndMonths(Int32 months);
/* ------------------------------------------------------------------------------------------------
* Add the specified amount of days to obtain a new date.
*/
Datetime AndDays(Int32 days);
/* ------------------------------------------------------------------------------------------------
* Add the specified amount of hours to obtain a new time.
*/
Datetime AndHours(Int32 hours);
/* ------------------------------------------------------------------------------------------------
* Add the specified amount of minutes to obtain a new time.
*/
Datetime AndMinutes(Int32 minutes);
/* ------------------------------------------------------------------------------------------------
* Add the specified amount of seconds to obtain a new time.
*/
Datetime AndSeconds(Int32 seconds);
/* ------------------------------------------------------------------------------------------------
* Add the specified amount of milliseconds to obtain a new time.
*/
Datetime AndMilliseconds(Int32 milliseconds);
/* ------------------------------------------------------------------------------------------------
* See whether the associated year is a leap year.
*/
bool IsThisLeapYear() const
{
return Chrono::IsLeapYear(m_Year);
}
/* ------------------------------------------------------------------------------------------------
* Retrieve the number of days in the associated year.
*/
Uint16 GetYearDays() const
{
return Chrono::DaysInYear(m_Year);
}
/* ------------------------------------------------------------------------------------------------
* Retrieve the number of days in the associated month.
*/
Uint8 GetMonthDays() const
{
return Chrono::DaysInMonth(m_Year, m_Month);
}
/* ------------------------------------------------------------------------------------------------
* Retrieve the date from this date-time instance.
*/
Date GetDate() const;
/* ------------------------------------------------------------------------------------------------
* Retrieve the time from this date-time instance.
*/
Time GetTime() const;
/* ------------------------------------------------------------------------------------------------
* Convert this date-time instance to a time-stamp.
*/
Timestamp GetTimestamp() const;
};
} // Namespace:: SqMod
#endif // _LIBRARY_CHRONO_DATETIME_HPP_

View File

@@ -0,0 +1,464 @@
// ------------------------------------------------------------------------------------------------
#include "Library/Chrono/Time.hpp"
#include "Library/Chrono/Date.hpp"
#include "Library/Chrono/Datetime.hpp"
#include "Library/Chrono/Timestamp.hpp"
#include "Base/Shared.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
SQMODE_DECL_TYPENAME(Typename, _SC("SqTime"))
// ------------------------------------------------------------------------------------------------
SQChar Time::Delimiter = ':';
// ------------------------------------------------------------------------------------------------
Int32 Time::Compare(const Time & o) const
{
if (m_Hour < o.m_Hour)
{
return -1;
}
else if (m_Hour > o.m_Hour)
{
return 1;
}
else if (m_Minute < o.m_Minute)
{
return -1;
}
else if (m_Minute > o.m_Minute)
{
return 1;
}
else if (m_Second < o.m_Second)
{
return -1;
}
else if (m_Second > o.m_Second)
{
return 1;
}
else if (m_Millisecond < o.m_Millisecond)
{
return -1;
}
else if (m_Millisecond == o.m_Millisecond)
{
return 0;
}
else
{
return 1;
}
}
// ------------------------------------------------------------------------------------------------
Time Time::operator + (const Time & o) const
{
return Time(o);
}
// ------------------------------------------------------------------------------------------------
Time Time::operator - (const Time & o) const
{
return Time(o);
}
// ------------------------------------------------------------------------------------------------
Time Time::operator * (const Time & o) const
{
return Time(o);
}
// ------------------------------------------------------------------------------------------------
Time Time::operator / (const Time & o) const
{
return Time(o);
}
// ------------------------------------------------------------------------------------------------
CSStr Time::ToString() const
{
return ToStrF("%02u%c%02u%c%02u%c%u",
m_Hour, m_Delimiter,
m_Minute, m_Delimiter,
m_Second, m_Delimiter,
m_Millisecond);
}
// ------------------------------------------------------------------------------------------------
void Time::Set(Uint8 hour, Uint8 minute, Uint8 second, Uint16 millisecond)
{
// Is the specified hour within range?
if (hour >= 24)
{
STHROWF("Hour value is out of range: %u >= 24", hour);
}
// Is the specified minute within range?
else if (minute >= 60)
{
STHROWF("Minute value is out of range: %u >= 60", minute);
}
// Is the specified second within range?
else if (second >= 60)
{
STHROWF("Second value is out of range: %u >= 60", second);
}
// Is the specified millisecond within range?
else if (millisecond >= 1000)
{
STHROWF("Millisecond value is out of range: %u >= 1000", millisecond);
}
// Now it's safe to assign the values
m_Hour = hour;
m_Minute = minute;
m_Second = second;
m_Millisecond = millisecond;
}
// ------------------------------------------------------------------------------------------------
void Time::SetStr(CSStr str)
{
// The format specifications that will be used to scan the string
static SQChar fs[] = _SC(" %u : %u : %u : %u ");
// Is the specified string empty?
if (!str || *str == '\0')
{
// Clear the values
m_Hour = 0;
m_Minute = 0;
m_Second = 0;
m_Millisecond = 0;
// We're done here
return;
}
// Assign the specified delimiter
fs[4] = m_Delimiter;
fs[9] = m_Delimiter;
fs[14] = m_Delimiter;
// The sscanf function requires at least 32 bit integers
Uint32 hour = 0, minute = 0, second = 0, milli = 0;
// Attempt to extract the component values from the specified string
sscanf(str, fs, &hour, &minute, &second, &milli);
// Clamp the extracted values to the boundaries of associated type and assign them
Set(ClampL< Uint32, Uint8 >(hour),
ClampL< Uint32, Uint8 >(minute),
ClampL< Uint32, Uint8 >(second),
ClampL< Uint32, Uint16 >(milli)
);
}
// ------------------------------------------------------------------------------------------------
void Time::SetHour(Uint8 hour)
{
// Is the specified hour within range?
if (hour >= 24)
{
STHROWF("Hour value is out of range: %u >= 24", hour);
}
// Now it's safe to assign the value
m_Hour = hour;
}
// ------------------------------------------------------------------------------------------------
void Time::SetMinute(Uint8 minute)
{
// Is the specified minute within range?
if (minute >= 60)
{
STHROWF("Minute value is out of range: %u >= 60", minute);
}
// Now it's safe to assign the value
m_Minute = minute;
}
// ------------------------------------------------------------------------------------------------
void Time::SetSecond(Uint8 second)
{
// Is the specified second within range?
if (second >= 60)
{
STHROWF("Second value is out of range: %u >= 60", second);
}
// Now it's safe to assign the value
m_Second = second;
}
// ------------------------------------------------------------------------------------------------
void Time::SetMillisecond(Uint16 millisecond)
{
// Is the specified millisecond within range?
if (millisecond >= 1000)
{
STHROWF("Millisecond value is out of range: %u >= 1000", millisecond);
}
// Now it's safe to assign the value
m_Millisecond = millisecond;
}
// ------------------------------------------------------------------------------------------------
Time & Time::AddHours(Int32 hours)
{
// Did we even add any hours?
if (hours)
{
// Add the specified amount of hours
m_Hour += (hours % 24);
// Make sure the value is within range
m_Hour %= 24;
}
// Allow chaining operations
return *this;
}
// ------------------------------------------------------------------------------------------------
Time & Time::AddMinutes(Int32 minutes)
{
// Did we even add any minutes?
if (minutes)
{
// Extract the number of hours
Int32 hours = static_cast< Int32 >(minutes / 60);
// Extract the number of minutes
m_Minute += (minutes % 60);
// Are the minutes overlapping with the next hour?
if (m_Minute >= 60)
{
// Increase the hours
++hours;
// Subtract one hour from minutes
m_Minute %= 60;
}
// Should we add any hours?
if (hours)
{
AddHours(hours);
}
}
// Allow chaining operations
return *this;
}
// ------------------------------------------------------------------------------------------------
Time & Time::AddSeconds(Int32 seconds)
{
// Did we even add any seconds?
if (seconds)
{
// Extract the number of minutes
Int32 minutes = static_cast< Int32 >(seconds / 60);
// Extract the number of seconds
m_Second += (seconds % 60);
// Are the seconds overlapping with the next minute?
if (m_Second >= 60)
{
// Increase the minutes
++minutes;
// Subtract one minute from seconds
m_Second %= 60;
}
// Should we add any minutes?
if (minutes)
{
AddMinutes(minutes);
}
}
// Allow chaining operations
return *this;
}
// ------------------------------------------------------------------------------------------------
Time & Time::AddMilliseconds(Int32 milliseconds)
{
// Did we even add any milliseconds?
if (milliseconds)
{
// Extract the number of seconds
Int32 seconds = static_cast< Int32 >(milliseconds / 1000);
// Extract the number of milliseconds
m_Millisecond += (milliseconds / 1000);
// Are the milliseconds overlapping with the next second?
if (m_Millisecond >= 1000)
{
// Increase the seconds
++seconds;
// Subtract one second from milliseconds
m_Millisecond %= 1000;
}
// Should we add any seconds?
if (seconds)
{
AddSeconds(seconds);
}
}
// Allow chaining operations
return *this;
}
// ------------------------------------------------------------------------------------------------
Time Time::AndHours(Int32 hours)
{
// Did we even add any hours?
if (hours)
{
return Time((m_Hour + (hours % 24)) % 24, m_Minute, m_Second, m_Millisecond);
}
// Return the time as is
return Time(*this);
}
// ------------------------------------------------------------------------------------------------
Time Time::AndMinutes(Int32 minutes)
{
// Did we even added any minutes?
if (!minutes)
{
return Time(*this); // Return the time as is
}
// Extract the number of hours
Int32 hours = static_cast< Int32 >(minutes / 60);
// Extract the number of minutes
minutes = m_Minute + (minutes % 60);
// Are the minutes overlapping with the next hour?
if (minutes >= 60)
{
++hours; // Increase hours
}
// Replicate the current time
Time t(*this);
// Should we add any hours?
if (hours)
{
t.AddHours(hours);
}
// Assign the resulted minutes
t.m_Minute = (minutes % 60);
// Return the result
return t;
}
// ------------------------------------------------------------------------------------------------
Time Time::AndSeconds(Int32 seconds)
{
// Did we even added any seconds?
if (!seconds)
{
return Time(*this); // Return the time as is
}
// Extract the number of minutes
Int32 minutes = static_cast< Int32 >(seconds / 60);
// Extract the number of seconds
seconds = m_Second + (seconds % 60);
// Are the seconds overlapping with the next minute?
if (seconds >= 60)
{
++minutes; // Increase minutes
}
// Replicate the current time
Time t(*this);
// Should we add any minutes?
if (minutes)
{
t.AddMinutes(minutes);
}
// Assign the resulted seconds
t.m_Second = (seconds % 60);
// Return the result
return t;
}
// ------------------------------------------------------------------------------------------------
Time Time::AndMilliseconds(Int32 milliseconds)
{
// Did we even added any milliseconds?
if (!milliseconds)
{
return Time(*this); // Return the time as is
}
// Extract the number of seconds
Int32 seconds = static_cast< Int32 >(milliseconds / 1000);
// Extract the number of milliseconds
milliseconds = m_Millisecond + (milliseconds % 1000);
// Are the milliseconds overlapping with the next second?
if (milliseconds >= 1000)
{
++seconds; // Increase seconds
}
// Replicate the current time
Time t(*this);
// Should we add any seconds?
if (seconds)
{
t.AddSeconds(seconds);
}
// Assign the resulted milliseconds
t.m_Millisecond = (milliseconds % 1000);
// Return the result
return t;
}
// ------------------------------------------------------------------------------------------------
Timestamp Time::GetTimestamp() const
{
// Calculate the microseconds in the current time
Int64 ms = static_cast< Int64 >(m_Hour * 3600000000LL);
ms += static_cast< Int64 >(m_Minute * 60000000L);
ms += static_cast< Int64 >(m_Second * 1000000L);
ms += static_cast< Int64 >(m_Millisecond * 1000L);
// Return the resulted timestamp
return Timestamp(ms);
}
// ================================================================================================
void Register_ChronoTime(HSQUIRRELVM vm, Table & /*cns*/)
{
RootTable(vm).Bind(Typename::Str,
Class< Time >(vm, Typename::Str)
// Constructors
.Ctor()
.Ctor< Uint8 >()
.Ctor< Uint8, Uint8 >()
.Ctor< Uint8, Uint8, Uint8 >()
.Ctor< Uint8, Uint8, Uint8, Uint16 >()
// Static Properties
.SetStaticValue(_SC("GlobalDelimiter"), &Time::Delimiter)
// Core Meta-methods
.SquirrelFunc(_SC("_typename"), &Typename::Fn)
.Func(_SC("_tostring"), &Time::ToString)
.Func(_SC("cmp"), &Time::Cmp)
// Meta-methods
.Func< Time (Time::*)(const Time &) const >(_SC("_add"), &Time::operator +)
.Func< Time (Time::*)(const Time &) const >(_SC("_sub"), &Time::operator -)
.Func< Time (Time::*)(const Time &) const >(_SC("_mul"), &Time::operator *)
.Func< Time (Time::*)(const Time &) const >(_SC("_div"), &Time::operator /)
// Properties
.Prop(_SC("Delimiter"), &Time::GetDelimiter, &Time::SetDelimiter)
.Prop(_SC("Str"), &Time::GetStr, &Time::SetStr)
.Prop(_SC("Hour"), &Time::GetHour, &Time::SetHour)
.Prop(_SC("Minute"), &Time::GetMinute, &Time::SetMinute)
.Prop(_SC("Second"), &Time::GetSecond, &Time::SetSecond)
.Prop(_SC("Millisecond"), &Time::GetMillisecond, &Time::SetMillisecond)
.Prop(_SC("Timestamp"), &Time::GetTimestamp)
// Member Methods
.Func(_SC("AddHours"), &Time::AddHours)
.Func(_SC("AddMinutes"), &Time::AddMinutes)
.Func(_SC("AddSeconds"), &Time::AddSeconds)
.Func(_SC("AddMillis"), &Time::AddMilliseconds)
.Func(_SC("AddMilliseconds"), &Time::AddMilliseconds)
.Func(_SC("AndHours"), &Time::AndHours)
.Func(_SC("AndMinutes"), &Time::AndMinutes)
.Func(_SC("AndSeconds"), &Time::AndSeconds)
.Func(_SC("AndMillis"), &Time::AndMilliseconds)
.Func(_SC("AndMilliseconds"), &Time::AndMilliseconds)
// Overloaded Methods
.Overload< void (Time::*)(Uint8) >(_SC("Set"), &Time::Set)
.Overload< void (Time::*)(Uint8, Uint8) >(_SC("Set"), &Time::Set)
.Overload< void (Time::*)(Uint8, Uint8, Uint8) >(_SC("Set"), &Time::Set)
.Overload< void (Time::*)(Uint8, Uint8, Uint8, Uint16) >(_SC("Set"), &Time::Set)
);
}
} // Namespace:: SqMod

View File

@@ -0,0 +1,362 @@
#ifndef _LIBRARY_CHRONO_TIME_HPP_
#define _LIBRARY_CHRONO_TIME_HPP_
// ------------------------------------------------------------------------------------------------
#include "Library/Chrono.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* Helper class used to represent a certain time.
*/
class Time
{
public:
// ------------------------------------------------------------------------------------------------
static SQChar Delimiter;
protected:
/* ------------------------------------------------------------------------------------------------
* Compare the values of two instances.
*/
Int32 Compare(const Time & o) const;
private:
// ------------------------------------------------------------------------------------------------
Uint8 m_Hour; // Hour
Uint8 m_Minute; // Minute
Uint8 m_Second; // Second
Uint16 m_Millisecond; // Millisecond
// ------------------------------------------------------------------------------------------------
SQChar m_Delimiter; // Component delimiter when generating strings.
public:
/* ------------------------------------------------------------------------------------------------
* Default constructor.
*/
Time()
: m_Hour(0)
, m_Minute(0)
, m_Second(0)
, m_Millisecond(0)
, m_Delimiter(Delimiter)
{
/* ... */
}
/* ------------------------------------------------------------------------------------------------
* Base constructor.
*/
Time(Uint8 hour)
: m_Delimiter(Delimiter)
{
Set(hour, 0, 0, 0);
}
/* ------------------------------------------------------------------------------------------------
* Base constructor.
*/
Time(Uint8 hour, Uint8 minute)
: m_Delimiter(Delimiter)
{
Set(hour, minute, 0, 0);
}
/* ------------------------------------------------------------------------------------------------
* Base constructor.
*/
Time(Uint8 hour, Uint8 minute, Uint8 second)
: m_Delimiter(Delimiter)
{
Set(hour, minute, second, 0);
}
/* ------------------------------------------------------------------------------------------------
* Base constructor.
*/
Time(Uint8 hour, Uint8 minute, Uint8 second, Uint16 millisecond)
: m_Delimiter(Delimiter)
{
Set(hour, minute, second, millisecond);
}
/* ------------------------------------------------------------------------------------------------
* String constructor.
*/
Time(CSStr str)
: m_Delimiter(Delimiter)
{
SetStr(str);
}
/* ------------------------------------------------------------------------------------------------
* Copy constructor.
*/
Time(const Time & o) = default;
/* ------------------------------------------------------------------------------------------------
* Move constructor.
*/
Time(Time && o) = default;
/* ------------------------------------------------------------------------------------------------
* Destructor.
*/
~Time() = default;
/* ------------------------------------------------------------------------------------------------
* Copy assignment operator.
*/
Time & operator = (const Time & o) = default;
/* ------------------------------------------------------------------------------------------------
* Move assignment operator.
*/
Time & operator = (Time && o) = default;
/* --------------------------------------------------------------------------------------------
* Equality comparison operator.
*/
bool operator == (const Time & o) const
{
return Compare(o) == 0;
}
/* --------------------------------------------------------------------------------------------
* Inequality comparison operator.
*/
bool operator != (const Time & o) const
{
return Compare(o) != 0;
}
/* --------------------------------------------------------------------------------------------
* Less than comparison operator.
*/
bool operator < (const Time & o) const
{
return Compare(o) < 0;
}
/* --------------------------------------------------------------------------------------------
* Greater than comparison operator.
*/
bool operator > (const Time & o) const
{
return Compare(o) > 0;
}
/* --------------------------------------------------------------------------------------------
* Less than or equal comparison operator.
*/
bool operator <= (const Time & o) const
{
return Compare(o) <= 0;
}
/* --------------------------------------------------------------------------------------------
* Greater than or equal comparison operator.
*/
bool operator >= (const Time & o) const
{
return Compare(o) >= 0;
}
/* --------------------------------------------------------------------------------------------
* Addition operator.
*/
Time operator + (const Time & o) const;
/* --------------------------------------------------------------------------------------------
* Subtraction operator.
*/
Time operator - (const Time & o) const;
/* --------------------------------------------------------------------------------------------
* Multiplication operator.
*/
Time operator * (const Time & o) const;
/* --------------------------------------------------------------------------------------------
* Division operator.
*/
Time operator / (const Time & o) const;
/* --------------------------------------------------------------------------------------------
* Used by the script engine to compare two instances of this type.
*/
Int32 Cmp(const Time & o) const
{
return Compare(o);
}
/* --------------------------------------------------------------------------------------------
* Used by the script engine to convert an instance of this type to a string.
*/
CSStr ToString() const;
/* ------------------------------------------------------------------------------------------------
* Assign the specified values.
*/
void Set(Uint8 hour)
{
Set(hour, m_Minute, m_Second, m_Millisecond);
}
/* ------------------------------------------------------------------------------------------------
* Assign the specified values.
*/
void Set(Uint8 hour, Uint8 minute)
{
Set(hour, minute, m_Second, m_Millisecond);
}
/* ------------------------------------------------------------------------------------------------
* Assign the specified values.
*/
void Set(Uint8 hour, Uint8 minute, Uint8 second)
{
Set(hour, minute, second, m_Millisecond);
}
/* ------------------------------------------------------------------------------------------------
* Assign the specified values.
*/
void Set(Uint8 hour, Uint8 minute, Uint8 second, Uint16 millisecond);
/* ------------------------------------------------------------------------------------------------
* Retrieve the local delimiter character.
*/
SQChar GetDelimiter() const
{
return m_Delimiter;
}
/* ------------------------------------------------------------------------------------------------
* Modify the local delimiter character.
*/
void SetDelimiter(SQChar c)
{
m_Delimiter = c;
}
/* ------------------------------------------------------------------------------------------------
* Retrieve the values as a string.
*/
CSStr GetStr() const
{
return ToString();
}
/* ------------------------------------------------------------------------------------------------
* Extract the values from a string.
*/
void SetStr(CSStr str);
/* ------------------------------------------------------------------------------------------------
* Retrieve the hour component.
*/
Uint8 GetHour() const
{
return m_Hour;
}
/* ------------------------------------------------------------------------------------------------
* Modify the hour component.
*/
void SetHour(Uint8 hour);
/* ------------------------------------------------------------------------------------------------
* Retrieve the minute component.
*/
Uint8 GetMinute() const
{
return m_Minute;
}
/* ------------------------------------------------------------------------------------------------
* Modify the minute component.
*/
void SetMinute(Uint8 minute);
/* ------------------------------------------------------------------------------------------------
* Retrieve the second component.
*/
Uint8 GetSecond() const
{
return m_Second;
}
/* ------------------------------------------------------------------------------------------------
* Modify the second component.
*/
void SetSecond(Uint8 second);
/* ------------------------------------------------------------------------------------------------
* Retrieve the millisecond component.
*/
Uint16 GetMillisecond() const
{
return m_Millisecond;
}
/* ------------------------------------------------------------------------------------------------
* Modify the millisecond component.
*/
void SetMillisecond(Uint16 millisecond);
/* ------------------------------------------------------------------------------------------------
* Add the specified amount of hours to the current time.
*/
Time & AddHours(Int32 hours);
/* ------------------------------------------------------------------------------------------------
* Add the specified amount of minutes to the current time.
*/
Time & AddMinutes(Int32 minutes);
/* ------------------------------------------------------------------------------------------------
* Add the specified amount of seconds to the current time.
*/
Time & AddSeconds(Int32 seconds);
/* ------------------------------------------------------------------------------------------------
* Add the specified amount of milliseconds to the current time.
*/
Time & AddMilliseconds(Int32 milliseconds);
/* ------------------------------------------------------------------------------------------------
* Add the specified amount of hours to obtain a new time.
*/
Time AndHours(Int32 hours);
/* ------------------------------------------------------------------------------------------------
* Add the specified amount of minutes to obtain a new time.
*/
Time AndMinutes(Int32 minutes);
/* ------------------------------------------------------------------------------------------------
* Add the specified amount of seconds to obtain a new time.
*/
Time AndSeconds(Int32 seconds);
/* ------------------------------------------------------------------------------------------------
* Add the specified amount of milliseconds to obtain a new time.
*/
Time AndMilliseconds(Int32 milliseconds);
/* ------------------------------------------------------------------------------------------------
* Convert this time instance to a time-stamp.
*/
Timestamp GetTimestamp() const;
};
} // Namespace:: SqMod
#endif // _LIBRARY_CHRONO_TIME_HPP_

View File

@@ -0,0 +1,92 @@
// ------------------------------------------------------------------------------------------------
#include "Library/Chrono/Timer.hpp"
#include "Library/Chrono/Timestamp.hpp"
#include "Base/Shared.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
SQMODE_DECL_TYPENAME(Typename, _SC("SqTimer"))
// ------------------------------------------------------------------------------------------------
Timer::Timer()
: m_Timestamp(Chrono::GetCurrentSysTime())
{
/* ... */
}
// ------------------------------------------------------------------------------------------------
Int32 Timer::Cmp(const Timer & o) const
{
if (m_Timestamp == o.m_Timestamp)
return 0;
else if (m_Timestamp > o.m_Timestamp)
return 1;
else
return -1;
}
// ------------------------------------------------------------------------------------------------
CSStr Timer::ToString() const
{
return ToStrF("%lld", m_Timestamp);
}
// ------------------------------------------------------------------------------------------------
void Timer::Reset()
{
m_Timestamp = Chrono::GetCurrentSysTime();
}
// ------------------------------------------------------------------------------------------------
Timestamp Timer::Restart()
{
const Int64 now = Chrono::GetCurrentSysTime(), elapsed = now - m_Timestamp;
m_Timestamp = now;
return Timestamp(elapsed);
}
// ------------------------------------------------------------------------------------------------
Int64 Timer::RestartRaw()
{
const Int64 now = Chrono::GetCurrentSysTime(), elapsed = now - m_Timestamp;
m_Timestamp = now;
return elapsed;
}
// ------------------------------------------------------------------------------------------------
Timestamp Timer::GetElapsedTime() const
{
return Timestamp(Chrono::GetCurrentSysTime() - m_Timestamp);
}
// ------------------------------------------------------------------------------------------------
Int64 Timer::GetElapsedTimeRaw() const
{
return (Chrono::GetCurrentSysTime() - m_Timestamp);
}
// ================================================================================================
void Register_ChronoTimer(HSQUIRRELVM vm, Table & /*cns*/)
{
RootTable(vm).Bind(Typename::Str,
Class< Timer >(vm, Typename::Str)
// Constructors
.Ctor()
.Ctor< const Timer & >()
// Core Meta-methods
.SquirrelFunc(_SC("_typename"), &Typename::Fn)
.Func(_SC("_tostring"), &Timer::ToString)
.Func(_SC("cmp"), &Timer::Cmp)
// Properties
.Prop(_SC("Elapsed"), &Timer::GetElapsedTime)
.Prop(_SC("ElapsedRaw"), &Timer::GetElapsedTimeRaw)
// Functions
.Func(_SC("Reset"), &Timer::Reset)
.Func(_SC("Restart"), &Timer::Restart)
.Func(_SC("RestartRaw"), &Timer::RestartRaw)
);
}
} // Namespace:: SqMod

View File

@@ -0,0 +1,100 @@
#ifndef _LIBRARY_CHRONO_TIMER_HPP_
#define _LIBRARY_CHRONO_TIMER_HPP_
// ------------------------------------------------------------------------------------------------
#include "Library/Chrono.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
*
*/
class Timer
{
/* --------------------------------------------------------------------------------------------
*
*/
Timer(Int64 t)
: m_Timestamp(t)
{
/* ... */
}
public:
/* --------------------------------------------------------------------------------------------
*
*/
Timer();
/* --------------------------------------------------------------------------------------------
*
*/
Timer(const Timer & o)
: m_Timestamp(o.m_Timestamp)
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
*
*/
~Timer()
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
*
*/
Timer & operator = (const Timer o)
{
m_Timestamp = o.m_Timestamp;
return *this;
}
/* --------------------------------------------------------------------------------------------
* ...
*/
Int32 Cmp(const Timer & b) const;
/* --------------------------------------------------------------------------------------------
* ...
*/
CSStr ToString() const;
/* --------------------------------------------------------------------------------------------
*
*/
void Reset();
/* --------------------------------------------------------------------------------------------
*
*/
Timestamp Restart();
/* --------------------------------------------------------------------------------------------
*
*/
Int64 RestartRaw();
/* --------------------------------------------------------------------------------------------
*
*/
Timestamp GetElapsedTime() const;
/* --------------------------------------------------------------------------------------------
*
*/
Int64 GetElapsedTimeRaw() const;
private:
// --------------------------------------------------------------------------------------------
Int64 m_Timestamp;
};
} // Namespace:: SqMod
#endif // _LIBRARY_CHRONO_TIMER_HPP_

View File

@@ -0,0 +1,180 @@
// ------------------------------------------------------------------------------------------------
#include "Library/Chrono/Timestamp.hpp"
#include "Library/Chrono/Timer.hpp"
#include "Library/Chrono/Date.hpp"
#include "Library/Chrono/Time.hpp"
#include "Library/Chrono/Datetime.hpp"
#include "Library/Numeric/LongInt.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
SQMODE_DECL_TYPENAME(Typename, _SC("SqTimestamp"))
// ------------------------------------------------------------------------------------------------
Timestamp::Timestamp(const SLongInt & t)
: m_Timestamp(t.GetNum())
{
/* ... */
}
// ------------------------------------------------------------------------------------------------
Int32 Timestamp::Cmp(const Timestamp & o) const
{
if (m_Timestamp == o.m_Timestamp)
{
return 0;
}
else if (m_Timestamp > o.m_Timestamp)
{
return 1;
}
else
{
return -1;
}
}
// ------------------------------------------------------------------------------------------------
CSStr Timestamp::ToString() const
{
return ToStrF("%lld", m_Timestamp);
}
// ------------------------------------------------------------------------------------------------
void Timestamp::SetNow()
{
m_Timestamp = Chrono::GetCurrentSysTime();
}
// ------------------------------------------------------------------------------------------------
SLongInt Timestamp::GetMicroseconds() const
{
return SLongInt(m_Timestamp);
}
// ------------------------------------------------------------------------------------------------
void Timestamp::SetMicroseconds(const SLongInt & ammount)
{
m_Timestamp = ammount.GetNum();
}
// ------------------------------------------------------------------------------------------------
SLongInt Timestamp::GetMilliseconds() const
{
return SLongInt(m_Timestamp / 1000L);
}
// ------------------------------------------------------------------------------------------------
void Timestamp::SetMilliseconds(const SLongInt & ammount)
{
m_Timestamp = (ammount.GetNum() * 1000L);
}
// ------------------------------------------------------------------------------------------------
static Timestamp SqGetEpochTimeNow()
{
return Timestamp(Chrono::GetEpochTimeMicro());
}
// ------------------------------------------------------------------------------------------------
static Timestamp SqGetMicrosecondsRaw(Int64 ammount)
{
return Timestamp(ammount);
}
// ------------------------------------------------------------------------------------------------
static Timestamp SqGetMicroseconds(const SLongInt & ammount)
{
return Timestamp(ammount);
}
// ------------------------------------------------------------------------------------------------
static Timestamp SqGetMilliseconds(SQInteger ammount)
{
return Timestamp(Int64(Int64(ammount) * 1000L));
}
// ------------------------------------------------------------------------------------------------
static Timestamp SqGetSeconds(SQFloat ammount)
{
return Timestamp(Int64(Float64(ammount) * 1000000L));
}
// ------------------------------------------------------------------------------------------------
static Timestamp SqGetMinutes(SQFloat ammount)
{
return Timestamp(Int64((Float64(ammount) * 60000000L)));
}
// ------------------------------------------------------------------------------------------------
static Timestamp SqGetHours(SQFloat ammount)
{
return Timestamp(Int64(Float64(ammount) * 3600000000LL));
}
// ------------------------------------------------------------------------------------------------
static Timestamp SqGetDays(SQFloat ammount)
{
return Timestamp(Int64(Float64(ammount) * 86400000000LL));
}
// ------------------------------------------------------------------------------------------------
static Timestamp SqGetYears(SQFloat ammount)
{
return Timestamp(Int64(Float64(ammount) * 31557600000000LL));
}
// ================================================================================================
void Register_ChronoTimestamp(HSQUIRRELVM vm, Table & /*cns*/)
{
RootTable(vm).Bind(Typename::Str,
Class< Timestamp >(vm, Typename::Str)
// Constructors
.Ctor()
.Ctor< const Timestamp & >()
// Core Meta-methods
.SquirrelFunc(_SC("_typename"), &Typename::Fn)
.Func(_SC("_tostring"), &Timestamp::ToString)
.Func(_SC("cmp"), &Timestamp::Cmp)
// Meta-methods
.Func< Timestamp (Timestamp::*)(const Timestamp &) const >(_SC("_add"), &Timestamp::operator +)
.Func< Timestamp (Timestamp::*)(const Timestamp &) const >(_SC("_sub"), &Timestamp::operator -)
.Func< Timestamp (Timestamp::*)(const Timestamp &) const >(_SC("_mul"), &Timestamp::operator *)
.Func< Timestamp (Timestamp::*)(const Timestamp &) const >(_SC("_div"), &Timestamp::operator /)
// Properties
.Prop(_SC("Microseconds"), &Timestamp::GetMicroseconds, &Timestamp::SetMicroseconds)
.Prop(_SC("MicrosecondsRaw"), &Timestamp::GetMicrosecondsRaw, &Timestamp::SetMicrosecondsRaw)
.Prop(_SC("Milliseconds"), &Timestamp::GetMilliseconds, &Timestamp::SetMilliseconds)
.Prop(_SC("MillisecondsRaw"), &Timestamp::GetMillisecondsRaw, &Timestamp::SetMillisecondsRaw)
.Prop(_SC("SecondsF"), &Timestamp::GetSecondsF, &Timestamp::SetSecondsF)
.Prop(_SC("SecondsI"), &Timestamp::GetSecondsI, &Timestamp::SetSecondsI)
.Prop(_SC("MinutesF"), &Timestamp::GetMinutesF, &Timestamp::SetMinutesF)
.Prop(_SC("MinutesI"), &Timestamp::GetMinutesI, &Timestamp::SetMinutesI)
.Prop(_SC("HoursF"), &Timestamp::GetHoursF, &Timestamp::SetHoursF)
.Prop(_SC("HoursI"), &Timestamp::GetHoursI, &Timestamp::SetHoursI)
.Prop(_SC("DaysF"), &Timestamp::GetDaysF, &Timestamp::SetDaysF)
.Prop(_SC("DaysI"), &Timestamp::GetDaysI, &Timestamp::SetDaysI)
.Prop(_SC("YearsF"), &Timestamp::GetYearsF, &Timestamp::SetYearsF)
.Prop(_SC("YearsI"), &Timestamp::GetYearsI, &Timestamp::SetYearsI)
// Member Methods
.Func(_SC("SetNow"), &Timestamp::SetNow)
// Static Functions
.StaticFunc(_SC("GetNow"), &SqGetEpochTimeNow)
.StaticFunc(_SC("GetMicrosRaw"), &SqGetMicrosecondsRaw)
.StaticFunc(_SC("GetMicrosecondsRaw"), &SqGetMicrosecondsRaw)
.StaticFunc(_SC("GetMicros"), &SqGetMicroseconds)
.StaticFunc(_SC("GetMicroseconds"), &SqGetMicroseconds)
.StaticFunc(_SC("GetMillis"), &SqGetMilliseconds)
.StaticFunc(_SC("GetMilliseconds"), &SqGetMilliseconds)
.StaticFunc(_SC("GetSeconds"), &SqGetSeconds)
.StaticFunc(_SC("GetMinutes"), &SqGetMinutes)
.StaticFunc(_SC("GetHours"), &SqGetHours)
.StaticFunc(_SC("GetDays"), &SqGetDays)
.StaticFunc(_SC("GetYears"), &SqGetYears)
);
;
}
} // Namespace:: SqMod

View File

@@ -0,0 +1,347 @@
#ifndef _LIBRARY_CHRONO_TIMESTAMP_HPP_
#define _LIBRARY_CHRONO_TIMESTAMP_HPP_
// ------------------------------------------------------------------------------------------------
#include "Library/Chrono.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
class Timer;
/* ------------------------------------------------------------------------------------------------
*
*/
class Timestamp
{
// --------------------------------------------------------------------------------------------
friend class Timer;
public:
/* --------------------------------------------------------------------------------------------
*
*/
Timestamp()
: m_Timestamp(0)
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
*
*/
Timestamp(Int64 t)
: m_Timestamp(t)
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
*
*/
explicit Timestamp(const SLongInt & t);
/* --------------------------------------------------------------------------------------------
*
*/
Timestamp(const Timestamp & o)
: m_Timestamp(o.m_Timestamp)
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
*
*/
~Timestamp()
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
*
*/
Timestamp & operator = (const Timestamp o)
{
m_Timestamp = o.m_Timestamp;
return *this;
}
/* --------------------------------------------------------------------------------------------
* ...
*/
Timestamp operator + (const Timestamp & o) const
{
return Timestamp(m_Timestamp + o.m_Timestamp);
}
/* --------------------------------------------------------------------------------------------
* ...
*/
Timestamp operator - (const Timestamp & o) const
{
return Timestamp(m_Timestamp - o.m_Timestamp);
}
/* --------------------------------------------------------------------------------------------
* ...
*/
Timestamp operator * (const Timestamp & o) const
{
return Timestamp(m_Timestamp * o.m_Timestamp);
}
/* --------------------------------------------------------------------------------------------
* ...
*/
Timestamp operator / (const Timestamp & o) const
{
return Timestamp(m_Timestamp / o.m_Timestamp);
}
/* --------------------------------------------------------------------------------------------
* ...
*/
Int32 Cmp(const Timestamp & b) const;
/* --------------------------------------------------------------------------------------------
* ...
*/
CSStr ToString() const;
/* --------------------------------------------------------------------------------------------
* ...
*/
void SetNow();
/* --------------------------------------------------------------------------------------------
*
*/
Int64 GetNum() const
{
return m_Timestamp;
}
/* --------------------------------------------------------------------------------------------
*
*/
SLongInt GetMicroseconds() const;
/* --------------------------------------------------------------------------------------------
*
*/
void SetMicroseconds(const SLongInt & ammount);
/* --------------------------------------------------------------------------------------------
*
*/
SQInteger GetMicrosecondsRaw() const
{
return SQInteger(m_Timestamp);
}
/* --------------------------------------------------------------------------------------------
*
*/
void SetMicrosecondsRaw(SQInteger ammount)
{
m_Timestamp = ammount;
}
/* --------------------------------------------------------------------------------------------
*
*/
SLongInt GetMilliseconds() const;
/* --------------------------------------------------------------------------------------------
*
*/
void SetMilliseconds(const SLongInt & ammount);
/* --------------------------------------------------------------------------------------------
*
*/
SQInteger GetMillisecondsRaw() const
{
return SQInteger(m_Timestamp / 1000L);
}
/* --------------------------------------------------------------------------------------------
*
*/
void SetMillisecondsRaw(SQInteger ammount)
{
m_Timestamp = Int64(Int64(ammount) * 1000L);
}
/* --------------------------------------------------------------------------------------------
*
*/
SQFloat GetSecondsF() const
{
return SQFloat(m_Timestamp / 1000000L);
}
/* --------------------------------------------------------------------------------------------
*
*/
void SetSecondsF(SQFloat ammount)
{
m_Timestamp = Int64(Float64(ammount) * 1000000L);
}
/* --------------------------------------------------------------------------------------------
*
*/
SQInteger GetSecondsI() const
{
return SQInteger(m_Timestamp / 1000000L);
}
/* --------------------------------------------------------------------------------------------
*
*/
void SetSecondsI(SQInteger ammount)
{
m_Timestamp = Int64(Int64(ammount) * 1000000L);
}
/* --------------------------------------------------------------------------------------------
*
*/
SQFloat GetMinutesF() const
{
return SQFloat(m_Timestamp / 60000000.0f);
}
/* --------------------------------------------------------------------------------------------
*
*/
void SetMinutesF(SQFloat ammount)
{
m_Timestamp = Int64(Float64(ammount) * 60000000L);
}
/* --------------------------------------------------------------------------------------------
*
*/
SQInteger GetMinutesI() const
{
return SQInteger(m_Timestamp / 60000000L);
}
/* --------------------------------------------------------------------------------------------
*
*/
void SetMinutesI(SQInteger ammount)
{
m_Timestamp = Int64(Int64(ammount) * 60000000L);
}
/* --------------------------------------------------------------------------------------------
*
*/
SQFloat GetHoursF() const
{
return SQFloat(m_Timestamp / 3600000000.0d);
}
/* --------------------------------------------------------------------------------------------
*
*/
void SetHoursF(SQFloat ammount)
{
m_Timestamp = Int64(Float64(ammount) * 3600000000LL);
}
/* --------------------------------------------------------------------------------------------
*
*/
SQInteger GetHoursI() const
{
return SQInteger(m_Timestamp / 3600000000LL);
}
/* --------------------------------------------------------------------------------------------
*
*/
void SetHoursI(SQInteger ammount)
{
m_Timestamp = Int64(Float64(ammount) * 3600000000LL);
}
/* --------------------------------------------------------------------------------------------
*
*/
SQFloat GetDaysF() const
{
return SQFloat(m_Timestamp / 86400000000.0d);
}
/* --------------------------------------------------------------------------------------------
*
*/
void SetDaysF(SQFloat ammount)
{
m_Timestamp = Int64(Float64(ammount) * 86400000000LL);
}
/* --------------------------------------------------------------------------------------------
*
*/
SQInteger GetDaysI() const
{
return SQInteger(m_Timestamp / 86400000000LL);
}
/* --------------------------------------------------------------------------------------------
*
*/
void SetDaysI(SQInteger ammount)
{
m_Timestamp = Int64(Float64(ammount) * 86400000000LL);
}
/* --------------------------------------------------------------------------------------------
*
*/
SQFloat GetYearsF() const
{
return SQFloat(m_Timestamp / 31557600000000.0d);
}
/* --------------------------------------------------------------------------------------------
*
*/
void SetYearsF(SQFloat ammount)
{
m_Timestamp = Int64(Float64(ammount) * 31557600000000LL);
}
/* --------------------------------------------------------------------------------------------
*
*/
SQInteger GetYearsI() const
{
return SQInteger(m_Timestamp / 31557600000000LL);
}
/* --------------------------------------------------------------------------------------------
*
*/
void SetYearsI(SQInteger ammount)
{
m_Timestamp = Int64(Float64(ammount) * 31557600000000LL);
}
private:
// --------------------------------------------------------------------------------------------
Int64 m_Timestamp;
};
} // Namespace:: SqMod
#endif // _LIBRARY_CHRONO_TIMESTAMP_HPP_

23
module/Library/Crypt.cpp Normal file
View File

@@ -0,0 +1,23 @@
// ------------------------------------------------------------------------------------------------
#include "Library/Crypt.hpp"
#include "Base/Shared.hpp"
// ------------------------------------------------------------------------------------------------
#include <cstdlib>
#include <cstring>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
extern void Register_Hash(HSQUIRRELVM vm);
extern void Register_AES(HSQUIRRELVM vm);
// ================================================================================================
void Register_Crypt(HSQUIRRELVM vm)
{
Register_Hash(vm);
Register_AES(vm);
}
} // Namespace:: SqMod

14
module/Library/Crypt.hpp Normal file
View File

@@ -0,0 +1,14 @@
#ifndef _LIBRARY_CRYPT_HPP_
#define _LIBRARY_CRYPT_HPP_
// ------------------------------------------------------------------------------------------------
#include "SqBase.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
} // Namespace:: SqMod
#endif // _LIBRARY_CRYPT_HPP_

View File

@@ -0,0 +1,155 @@
// ------------------------------------------------------------------------------------------------
#include "Library/Crypt/AES.hpp"
#include "Base/Shared.hpp"
// ------------------------------------------------------------------------------------------------
#include <cstdlib>
#include <cstring>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
SQMODE_DECL_TYPENAME(Typename, _SC("SqAES256"))
// ------------------------------------------------------------------------------------------------
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 std::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);
}
// ------------------------------------------------------------------------------------------------
bool AES256::Init(CSStr key)
{
// Clear current key, if any
aes256_done(&m_Context);
// Is the specified key empty?
if (!key || *key == '\0')
{
return false; // Leave the context with an empty key
}
// Obtain the specified key size
const Uint32 size = (std::strlen(key) * sizeof(SQChar));
// See if the key size is accepted
if (size > sizeof(m_Buffer))
{
STHROWF("The specified key is out of bounds: %u > %u", size, sizeof(m_Buffer));
}
// Initialize the key buffer to 0
std::memset(m_Buffer, 0, sizeof(m_Buffer));
// Copy the key into the key buffer
std::memcpy(m_Buffer, key, size);
// Initialize the context with the specified key
aes256_init(&m_Context, m_Buffer);
// This context was successfully initialized
return true;
}
// ------------------------------------------------------------------------------------------------
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);
}
// ================================================================================================
void Register_AES(HSQUIRRELVM vm)
{
RootTable(vm).Bind(Typename::Str,
Class< AES256 >(vm, Typename::Str)
// Constructors
.Ctor()
.Ctor< CSStr >()
// Meta-methods
.SquirrelFunc(_SC("_typename"), &Typename::Fn)
.Func(_SC("_tostring"), &AES256::ToString)
.Func(_SC("cmp"), &AES256::Cmp)
/* 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

View File

@@ -0,0 +1,105 @@
#ifndef _LIBRARY_CRYPT_AES_HPP_
#define _LIBRARY_CRYPT_AES_HPP_
// ------------------------------------------------------------------------------------------------
#include "SqBase.hpp"
// ------------------------------------------------------------------------------------------------
#include <aes256.h>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* 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;
/* --------------------------------------------------------------------------------------------
* Retrieve the associated key.
*/
CSStr GetKey() const;
/* --------------------------------------------------------------------------------------------
* Initialize the context key.
*/
bool 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_AES_HPP_

View File

@@ -0,0 +1,192 @@
// ------------------------------------------------------------------------------------------------
#include "Library/Crypt/Hash.hpp"
#include "Base/Shared.hpp"
// ------------------------------------------------------------------------------------------------
#include <crc32.h>
#include <keccak.h>
#include <md5.h>
#include <sha1.h>
#include <sha256.h>
#include <sha3.h>
#include <b64.h>
#include <whirlpool.h>
// ------------------------------------------------------------------------------------------------
#include <cstdlib>
#include <cstring>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* 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)
{
// Attempt to retrieve the value from the stack as a string
StackStrF val(vm, 2);
// Have we failed to retrieve the string?
if (SQ_FAILED(val.Proc(true)))
{
return val.mRes; // Propagate the error!
}
// Forward the call to the actual implementation and store the string
String str(BaseHash< T >::Algo(val.mPtr));
// 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;
}
/* ------------------------------------------------------------------------------------------------
* Hash the specified value or the result of a formatted string with whirlpool algorithm.
*/
static SQInteger WhirlpoolF(HSQUIRRELVM vm)
{
// Attempt to retrieve the value from the stack as a string
StackStrF val(vm, 2);
// Have we failed to retrieve the string?
if (SQ_FAILED(val.Proc(true)))
{
return val.mRes; // Propagate the error!
}
// Prepare a whirlpool hashing context
whirlpool_ctx ctx;
// Initialize the hashing context
rhash_whirlpool_init(&ctx);
// Update the context with the given string
rhash_whirlpool_update(&ctx, reinterpret_cast< const unsigned char * >(val.mPtr),
val.mLen < 0 ? 0 : static_cast< size_t >(val.mLen));
// Reserve space for the result in binary form
unsigned char raw_hash[whirlpool_block_size];
// Finalize hashing and obtain the result
rhash_whirlpool_final(&ctx, raw_hash);
// Reserve space for the hexadecimal string
char hex_hash[whirlpool_block_size * 2];
// Convert from binary form to hex string
for (int i = 0, p = 0; i < whirlpool_block_size; ++i)
{
static const char dec2hex[16+1] = "0123456789abcdef";
hex_hash[p++] = dec2hex[(raw_hash[i] >> 4) & 15];
hex_hash[p++] = dec2hex[ raw_hash[i] & 15];
}
// Push the string on the stack
sq_pushstring(vm, hex_hash, whirlpool_block_size * 2);
// At this point we have a valid string on the stack
return 1;
}
/* ------------------------------------------------------------------------------------------------
* Encode the specified value or the result of a formatted string with base64 algorithm.
*/
static SQInteger EncodeBase64F(HSQUIRRELVM vm)
{
// Attempt to retrieve the value from the stack as a string
StackStrF val(vm, 2);
// Have we failed to retrieve the string?
if (SQ_FAILED(val.Proc(true)))
{
return val.mRes; // Propagate the error!
}
// Size of the encoded string
size_t enclen = 0;
// Attempt to encode the resulted string
char * result = b64_encode_ex(reinterpret_cast< const unsigned char * >(val.mPtr),
val.mLen < 0 ? 0 : static_cast< size_t >(val.mLen), &enclen);
// Did we fail to allocate memory for it?
if (!result)
{
return sq_throwerror(vm, _SC("Unable to allocate memory for output"));
}
// Push the string on the stack
sq_pushstring(vm, result, ConvTo< SQInteger >::From(enclen));
// At this point we have a valid string on the stack
return 1;
}
/* ------------------------------------------------------------------------------------------------
* Decode the specified value or the result of a formatted string with base64 algorithm.
*/
static SQInteger DecodeBase64F(HSQUIRRELVM vm)
{
// Attempt to retrieve the value from the stack as a string
StackStrF val(vm, 2);
// Have we failed to retrieve the string?
if (SQ_FAILED(val.Proc(true)))
{
return val.mRes; // Propagate the error!
}
// Size of the decoded string
size_t declen = 0;
// Attempt to decode the resulted string
unsigned char * result = b64_decode_ex(val.mPtr, val.mLen < 0 ? 0 : static_cast< size_t >(val.mLen), &declen);
// Did we fail to allocate memory for it?
if (!result)
{
return sq_throwerror(vm, _SC("Unable to allocate memory for output"));
}
// Push the string on the stack
sq_pushstring(vm, reinterpret_cast< CSStr >(result), ConvTo< SQInteger >::From(declen));
// 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()
// Meta-methods
.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 >);
hashns.SquirrelFunc(_SC("GetWhirlpool"), &WhirlpoolF);
hashns.SquirrelFunc(_SC("EncodeBase64"), &EncodeBase64F);
hashns.SquirrelFunc(_SC("DecodeBase64"), &DecodeBase64F);
RootTable(vm).Bind(_SC("SqHash"), hashns);
}
} // Namespace:: SqMod

View File

@@ -0,0 +1,102 @@
#ifndef _LIBRARY_CRYPT_HASH_HPP_
#define _LIBRARY_CRYPT_HASH_HPP_
// ------------------------------------------------------------------------------------------------
#include "SqBase.hpp"
// ------------------------------------------------------------------------------------------------
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;
};
} // Namespace:: SqMod
#endif // _LIBRARY_CRYPT_HASH_HPP_

16
module/Library/IO.cpp Normal file
View File

@@ -0,0 +1,16 @@
// ------------------------------------------------------------------------------------------------
#include "Library/IO.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
extern void Register_INI(HSQUIRRELVM vm);
// ================================================================================================
void Register_IO(HSQUIRRELVM vm)
{
Register_INI(vm);
}
} // Namespace:: SqMod

14
module/Library/IO.hpp Normal file
View File

@@ -0,0 +1,14 @@
#ifndef _LIBRARY_IO_HPP_
#define _LIBRARY_IO_HPP_
// ------------------------------------------------------------------------------------------------
#include "Base/Shared.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
} // Namespace:: SqMod
#endif // _LIBRARY_IO_HPP_

View File

View File

479
module/Library/IO/INI.cpp Normal file
View File

@@ -0,0 +1,479 @@
// ------------------------------------------------------------------------------------------------
#include "Library/IO/INI.hpp"
// ------------------------------------------------------------------------------------------------
#include <cerrno>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
SQMODE_DECL_TYPENAME(ResultTypename, _SC("SqIniResult"))
SQMODE_DECL_TYPENAME(EntriesTypename, _SC("SqIniEntries"))
SQMODE_DECL_TYPENAME(DocumentTypename, _SC("SqIniDocument"))
// ------------------------------------------------------------------------------------------------
void IniResult::Check() const
{
// Identify the error type
switch (m_Result)
{
case SI_FAIL:
STHROWF("Unable to %s. Probably invalid", m_Action.c_str());
break;
case SI_NOMEM:
STHROWF("Unable to %s. Ran out of memory", m_Action.c_str());
break;
case SI_FILE:
STHROWF("Unable to %s. %s", strerror(errno));
break;
case SI_OK:
case SI_UPDATED:
case SI_INSERTED:
break; /* These are not error messahes. */
default:
STHROWF("Unable to %s for some unforeseen reason", m_Action.c_str());
}
}
// ------------------------------------------------------------------------------------------------
void DocumentRef::Validate() const
{
// Is the document handle valid?
if (!m_Ptr)
{
STHROWF("Invalid INI document reference");
}
}
// ------------------------------------------------------------------------------------------------
Int32 Entries::Cmp(const Entries & o) const
{
if (m_Elem == o.m_Elem)
{
return 0;
}
else if (m_List.size() > o.m_List.size())
{
return 1;
}
else
{
return -1;
}
}
// ------------------------------------------------------------------------------------------------
void Entries::Next()
{
// Are there any other elements ahead?
if (!m_List.empty() && m_Elem != m_List.end())
{
++m_Elem; // Go ahead one element
}
}
// ------------------------------------------------------------------------------------------------
void Entries::Prev()
{
// Are there any other elements behind?
if (!m_List.empty() && m_Elem != m_List.begin())
{
--m_Elem; // Go back one element
}
}
// ------------------------------------------------------------------------------------------------
void Entries::Advance(Int32 n)
{
// Are there any other elements ahead?
if (m_List.empty() || m_Elem == m_List.end())
{
return;
}
// Jump as many elements as possible within the specified distance
while ((--n >= 0) && m_Elem != m_List.end())
{
++m_Elem;
}
}
// ------------------------------------------------------------------------------------------------
void Entries::Retreat(Int32 n)
{
// Are there any other elements behind?
if (m_List.empty() || m_Elem == m_List.begin())
{
return;
}
// Jump as many elements as possible within the specified distance
while ((--n >= 0) && m_Elem != m_List.begin())
{
--m_Elem;
}
}
// ------------------------------------------------------------------------------------------------
CSStr Entries::GetItem() const
{
// is the current element valid?
if (m_List.empty() || m_Elem == m_List.end())
{
STHROWF("Invalid INI entry [item]");
}
// Return the requested information
return m_Elem->pItem;
}
// ------------------------------------------------------------------------------------------------
CSStr Entries::GetComment() const
{
// is the current element valid?
if (m_List.empty() || m_Elem == m_List.end())
{
STHROWF("Invalid INI entry [comment]");
}
// Return the requested information
return m_Elem->pComment;
}
// ------------------------------------------------------------------------------------------------
Int32 Entries::GetOrder() const
{
// is the current element valid?
if (m_List.empty() || m_Elem == m_List.end())
{
STHROWF("Invalid INI entry [order]");
}
// Return the requested information
return m_Elem->nOrder;
}
// ------------------------------------------------------------------------------------------------
Int32 Document::Cmp(const Document & o) const
{
if (m_Doc == o.m_Doc)
{
return 0;
}
else if (m_Doc.m_Ptr > o.m_Doc.m_Ptr)
{
return 1;
}
else
{
return -1;
}
}
// ------------------------------------------------------------------------------------------------
IniResult Document::LoadFile(CSStr filepath)
{
// Validate the handle
m_Doc.Validate();
// Attempt to load the file from disk and return the result
return IniResult("load INI file", m_Doc->LoadFile(filepath));
}
// ------------------------------------------------------------------------------------------------
IniResult Document::LoadData(CSStr source, Int32 size)
{
// Validate the handle
m_Doc.Validate();
// Attempt to load the file from memory and return the result
return IniResult("load INI file", m_Doc->LoadData(source, size < 0 ? strlen(source) : size));
}
// ------------------------------------------------------------------------------------------------
IniResult Document::SaveFile(CSStr filepath, bool signature)
{
// Validate the handle
m_Doc.Validate();
// Attempt to save the file to disk and return the result
return IniResult("save INI file", m_Doc->SaveFile(filepath, signature));
}
// ------------------------------------------------------------------------------------------------
Object Document::SaveData(bool signature)
{
// Validate the handle
m_Doc.Validate();
// The string where the content will be saved
String source;
// Attempt to save the data to string
if (m_Doc->Save(source, signature) < 0)
{
STHROWF("Unable to save INI document");
}
// Obtain the initial stack size
const StackGuard sg(DefaultVM::Get());
// Transform it into a script object
sq_pushstring(DefaultVM::Get(), source.c_str(), source.size());
// Get the object from the stack and return it
return Var< Object >(DefaultVM::Get(), -1).value;
}
// ------------------------------------------------------------------------------------------------
Entries Document::GetAllSections() const
{
// Validate the handle
m_Doc.Validate();
// Prepare a container to receive the entries
static Container entries;
// Obtain all sections from the INI document
m_Doc->GetAllSections(entries);
// Return the entries and take over content
return Entries(m_Doc, entries);
}
// ------------------------------------------------------------------------------------------------
Entries Document::GetAllKeys(CSStr section) const
{
// Validate the handle
m_Doc.Validate();
// Prepare a container to receive the entries
static Container entries;
// Obtain all sections from the INI document
m_Doc->GetAllKeys(section, entries);
// Return the entries and take over content
return Entries(m_Doc, entries);
}
// ------------------------------------------------------------------------------------------------
Entries Document::GetAllValues(CSStr section, CSStr key) const
{
// Validate the handle
m_Doc.Validate();
// Prepare a container to receive the entries
static Container entries;
// Obtain all sections from the INI document
m_Doc->GetAllValues(section, key, entries);
// Return the entries and take over content
return Entries(m_Doc, entries);
}
// ------------------------------------------------------------------------------------------------
Int32 Document::GetSectionSize(CSStr section) const
{
// Validate the handle
m_Doc.Validate();
// Return the requested information
return m_Doc->GetSectionSize(section);
}
// ------------------------------------------------------------------------------------------------
bool Document::HasMultipleKeys(CSStr section, CSStr key) const
{
// Validate the handle
m_Doc.Validate();
// Where to retrive whether the key has multiple instances
bool multiple = false;
// Attempt to query the information
if (m_Doc->GetValue(section, key, nullptr, &multiple) == nullptr)
{
return true; // Doesn't exist
}
// Return the result
return multiple;
}
// ------------------------------------------------------------------------------------------------
CCStr Document::GetValue(CSStr section, CSStr key, CSStr def) const
{
// Validate the handle
m_Doc.Validate();
// Attempt to query the information and return it
return m_Doc->GetValue(section, key, def, nullptr);
}
// ------------------------------------------------------------------------------------------------
SQInteger Document::GetInteger(CSStr section, CSStr key, SQInteger def) const
{
// Validate the handle
m_Doc.Validate();
// Attempt to query the information and return it
return static_cast< SQInteger >(m_Doc->GetLongValue(section, key, def, nullptr));
}
// ------------------------------------------------------------------------------------------------
SQFloat Document::GetFloat(CSStr section, CSStr key, SQFloat def) const
{
// Validate the handle
m_Doc.Validate();
// Attempt to query the information and return it
return static_cast< SQFloat >(m_Doc->GetDoubleValue(section, key, def, nullptr));
}
// ------------------------------------------------------------------------------------------------
bool Document::GetBoolean(CSStr section, CSStr key, bool def) const
{
// Validate the handle
m_Doc.Validate();
// Attempt to query the information and return it
return m_Doc->GetBoolValue(section, key, def, nullptr);
}
// ------------------------------------------------------------------------------------------------
IniResult Document::SetValue(CSStr section, CSStr key, CSStr value, bool force, CSStr comment)
{
// Validate the handle
m_Doc.Validate();
// Attempt to apply the specified information and return the result
return IniResult("set INI value", m_Doc->SetValue(section, key, value, comment, force));
}
// ------------------------------------------------------------------------------------------------
IniResult Document::SetInteger(CSStr section, CSStr key, SQInteger value, bool hex, bool force, CSStr comment)
{
// Validate the handle
m_Doc.Validate();
// Attempt to apply the specified information and return the result
return IniResult("set INI integer", m_Doc->SetLongValue(section, key, value, comment, hex, force));
}
// ------------------------------------------------------------------------------------------------
IniResult Document::SetFloat(CSStr section, CSStr key, SQFloat value, bool force, CSStr comment)
{
// Validate the handle
m_Doc.Validate();
// Attempt to apply the specified information and return the result
return IniResult("set INI float", m_Doc->SetDoubleValue(section, key, value, comment, force));
}
// ------------------------------------------------------------------------------------------------
IniResult Document::SetBoolean(CSStr section, CSStr key, bool value, bool force, CSStr comment)
{
// Validate the handle
m_Doc.Validate();
// Attempt to apply the specified information
return IniResult("set INI boolean", m_Doc->SetBoolValue(section, key, value, comment, force));
}
// ------------------------------------------------------------------------------------------------
bool Document::DeleteValue(CSStr section, CSStr key, CSStr value, bool empty)
{
// Validate the handle
m_Doc.Validate();
// Attempt to remove the specified value and return the result
return m_Doc->DeleteValue(section, key, value, empty);
}
// ================================================================================================
void Register_INI(HSQUIRRELVM vm)
{
Table inins(vm);
inins.Bind(_SC("Result"),
Class< IniResult >(vm, ResultTypename::Str)
// Constructors
.Ctor()
.Ctor< CSStr, SQInteger >()
.Ctor< const IniResult & >()
// Core Meta-methods
.SquirrelFunc(_SC("_typename"), &ResultTypename::Fn)
.Func(_SC("_tostring"), &IniResult::ToString)
.Func(_SC("cmp"), &IniResult::Cmp)
// Properties
.Prop(_SC("Valid"), &IniResult::IsValid)
.Prop(_SC("Action"), &IniResult::GetAction)
.Prop(_SC("Result"), &IniResult::GetResult)
// Member Methods
.Func(_SC("Check"), &IniResult::Check)
);
inins.Bind(_SC("Entries"),
Class< Entries >(vm, EntriesTypename::Str)
// Constructors
.Ctor()
.Ctor< const Entries & >()
// Core Meta-methods
.SquirrelFunc(_SC("_typename"), &EntriesTypename::Fn)
.Func(_SC("_tostring"), &Entries::ToString)
.Func(_SC("cmp"), &Entries::Cmp)
// Properties
.Prop(_SC("Valid"), &Entries::IsValid)
.Prop(_SC("Empty"), &Entries::IsEmpty)
.Prop(_SC("References"), &Entries::GetRefCount)
.Prop(_SC("Size"), &Entries::GetSize)
.Prop(_SC("Item"), &Entries::GetItem)
.Prop(_SC("Comment"), &Entries::GetComment)
.Prop(_SC("Order"), &Entries::GetOrder)
// Member Methods
.Func(_SC("Reset"), &Entries::Reset)
.Func(_SC("Next"), &Entries::Next)
.Func(_SC("Prev"), &Entries::Prev)
.Func(_SC("Advance"), &Entries::Advance)
.Func(_SC("Retreat"), &Entries::Retreat)
.Func(_SC("Sort"), &Entries::Sort)
.Func(_SC("SortByKeyOrder"), &Entries::SortByKeyOrder)
.Func(_SC("SortByLoadOrder"), &Entries::SortByLoadOrder)
);
inins.Bind(_SC("Document"),
Class< Document, NoCopy< Document > >(vm, DocumentTypename::Str)
// Constructors
.Ctor()
.Ctor< bool >()
.Ctor< bool, bool >()
.Ctor< bool, bool, bool >()
// Core Meta-methods
.SquirrelFunc(_SC("_typename"), &DocumentTypename::Fn)
.Func(_SC("_tostring"), &Document::ToString)
.Func(_SC("cmp"), &Document::Cmp)
// Properties
.Prop(_SC("Valid"), &Document::IsValid)
.Prop(_SC("Empty"), &Document::IsEmpty)
.Prop(_SC("References"), &Document::GetRefCount)
.Prop(_SC("Unicode"), &Document::GetUnicode, &Document::SetUnicode)
.Prop(_SC("MultiKey"), &Document::GetMultiKey, &Document::SetMultiKey)
.Prop(_SC("MultiLine"), &Document::GetMultiLine, &Document::SetMultiLine)
.Prop(_SC("Spaces"), &Document::GetSpaces, &Document::SetSpaces)
// Member Methods
.Func(_SC("Reset"), &Document::Reset)
.Func(_SC("LoadFile"), &Document::LoadFile)
.Overload< IniResult (Document::*)(CSStr) >(_SC("LoadString"), &Document::LoadData)
.Overload< IniResult (Document::*)(CSStr, Int32) >(_SC("LoadString"), &Document::LoadData)
.Overload< IniResult (Document::*)(CSStr) >(_SC("SaveFile"), &Document::SaveFile)
.Overload< IniResult (Document::*)(CSStr, bool) >(_SC("SaveFile"), &Document::SaveFile)
.Func(_SC("SaveData"), &Document::SaveData)
.Func(_SC("GetSections"), &Document::GetAllSections)
.Func(_SC("GetKeys"), &Document::GetAllKeys)
.Func(_SC("GetValues"), &Document::GetAllValues)
.Func(_SC("GetSectionSize"), &Document::GetSectionSize)
.Func(_SC("HasMultipleKeys"), &Document::HasMultipleKeys)
.Func(_SC("GetValue"), &Document::GetValue)
.Func(_SC("GetInteger"), &Document::GetInteger)
.Func(_SC("GetFloat"), &Document::GetFloat)
.Func(_SC("GetBoolean"), &Document::GetBoolean)
.Overload< IniResult (Document::*)(CSStr, CSStr, CSStr) >(_SC("SetValue"), &Document::SetValue)
.Overload< IniResult (Document::*)(CSStr, CSStr, CSStr, bool) >(_SC("SetValue"), &Document::SetValue)
.Overload< IniResult (Document::*)(CSStr, CSStr, CSStr, bool, CSStr) >(_SC("SetValue"), &Document::SetValue)
.Overload< IniResult (Document::*)(CSStr, CSStr, SQInteger) >(_SC("SetInteger"), &Document::SetInteger)
.Overload< IniResult (Document::*)(CSStr, CSStr, SQInteger, bool) >(_SC("SetInteger"), &Document::SetInteger)
.Overload< IniResult (Document::*)(CSStr, CSStr, SQInteger, bool, bool) >(_SC("SetInteger"), &Document::SetInteger)
.Overload< IniResult (Document::*)(CSStr, CSStr, SQInteger, bool, bool, CSStr) >(_SC("SetInteger"), &Document::SetInteger)
.Overload< IniResult (Document::*)(CSStr, CSStr, SQFloat) >(_SC("SetFloat"), &Document::SetFloat)
.Overload< IniResult (Document::*)(CSStr, CSStr, SQFloat, bool) >(_SC("SetFloat"), &Document::SetFloat)
.Overload< IniResult (Document::*)(CSStr, CSStr, SQFloat, bool, CSStr) >(_SC("SetFloat"), &Document::SetFloat)
.Overload< IniResult (Document::*)(CSStr, CSStr, bool) >(_SC("SetBoolean"), &Document::SetBoolean)
.Overload< IniResult (Document::*)(CSStr, CSStr, bool, bool) >(_SC("SetBoolean"), &Document::SetBoolean)
.Overload< IniResult (Document::*)(CSStr, CSStr, bool, bool, CSStr) >(_SC("SetBoolean"), &Document::SetBoolean)
.Overload< bool (Document::*)(CSStr) >(_SC("DeleteValue"), &Document::DeleteValue)
.Overload< bool (Document::*)(CSStr, CSStr) >(_SC("DeleteValue"), &Document::DeleteValue)
.Overload< bool (Document::*)(CSStr, CSStr, CSStr) >(_SC("DeleteValue"), &Document::DeleteValue)
.Overload< bool (Document::*)(CSStr, CSStr, CSStr, bool) >(_SC("DeleteValue"), &Document::DeleteValue)
);
RootTable(vm).Bind(_SC("SqIni"), inins);
ConstTable(vm).Enum(_SC("SqIniError"), Enumeration(vm)
.Const(_SC("Ok"), Int32(SI_OK))
.Const(_SC("Updated"), Int32(SI_UPDATED))
.Const(_SC("Inserted"), Int32(SI_INSERTED))
.Const(_SC("Fail"), Int32(SI_FAIL))
.Const(_SC("NoMem"), Int32(SI_NOMEM))
.Const(_SC("File"), Int32(SI_FILE))
);
}
} // Namespace:: SqMod

981
module/Library/IO/INI.hpp Normal file
View File

@@ -0,0 +1,981 @@
#ifndef _LIBRARY_IO_INI_HPP_
#define _LIBRARY_IO_INI_HPP_
// ------------------------------------------------------------------------------------------------
#include "Base/Shared.hpp"
// ------------------------------------------------------------------------------------------------
#include <SimpleIni.h>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* Allows the user to inspect the result of certain operations and act accordingly.
*/
class IniResult
{
private:
// --------------------------------------------------------------------------------------------
String m_Action; // The action that was performed.
SQInteger m_Result; // The internal result code.
public:
/* --------------------------------------------------------------------------------------------
* Construct with no specific action or result.
*/
IniResult()
: m_Action("unknown action"), m_Result(SI_OK)
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Construct with no specific result.
*/
explicit IniResult(CSStr action)
: m_Action(!action ? _SC("") : action), m_Result(SI_OK)
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Construct with no specific action.
*/
explicit IniResult(SQInteger result)
: m_Action("unknown action"), m_Result(result)
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Construct with specific action and result.
*/
IniResult(CSStr action, SQInteger result)
: m_Action(!action ? _SC("") : action), m_Result(result)
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Copy constructor.
*/
IniResult(const IniResult & o)
: m_Action(o.m_Action), m_Result(o.m_Result)
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Destructor.
*/
~IniResult()
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Copy assignment operator.
*/
IniResult & operator = (const IniResult & o)
{
m_Action = o.m_Action;
m_Result = o.m_Result;
return *this;
}
/* --------------------------------------------------------------------------------------------
* Perform an equality comparison between two results.
*/
bool operator == (const IniResult & o) const
{
return (m_Result == o.m_Result);
}
/* --------------------------------------------------------------------------------------------
* Perform an inequality comparison between two results.
*/
bool operator != (const IniResult & o) const
{
return (m_Result != o.m_Result);
}
/* --------------------------------------------------------------------------------------------
* Implicit conversion to boolean for use in boolean operations.
*/
operator bool () const
{
return (m_Result >= 0);
}
/* --------------------------------------------------------------------------------------------
* Used by the script engine to compare two instances of this type.
*/
Int32 Cmp(const IniResult & o) const
{
if (m_Result == o.m_Result)
{
return 0;
}
else if (m_Result > o.m_Result)
{
return 1;
}
else
{
return -1;
}
}
/* --------------------------------------------------------------------------------------------
* Used by the script engine to convert an instance of this type to a string.
*/
CSStr ToString() const
{
return m_Action.c_str();
}
/* --------------------------------------------------------------------------------------------
* See whether this instance references a valid INI result.
*/
bool IsValid() const
{
return (m_Result >= 0);
}
/* --------------------------------------------------------------------------------------------
* Retrieve the associated action.
*/
CSStr GetAction() const
{
return m_Action.c_str();
}
/* --------------------------------------------------------------------------------------------
* Retrieve the resulted code.
*/
SQInteger GetResult() const
{
return m_Result;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the resulted code.
*/
void Check() const;
};
/* ------------------------------------------------------------------------------------------------
* Manages a reference counted INI document instance.
*/
class DocumentRef
{
// --------------------------------------------------------------------------------------------
friend class Document;
public:
// --------------------------------------------------------------------------------------------
typedef CSimpleIniA Type; // The managed type.
// --------------------------------------------------------------------------------------------
typedef Type* Pointer; // Pointer to the managed type.
typedef const Type* ConstPtr; // Constant pointer to the managed type.
// --------------------------------------------------------------------------------------------
typedef Type& Reference; // Reference to the managed type.
typedef const Type& ConstRef; // Constant reference to the managed type.
// --------------------------------------------------------------------------------------------
typedef unsigned int Counter; // Reference counter type.
/* --------------------------------------------------------------------------------------------
* Validate the document reference and throw an error if invalid.
*/
void Validate() const;
private:
// --------------------------------------------------------------------------------------------
Pointer m_Ptr; // The document reader, writer and manager instance.
Counter* m_Ref; // Reference count to the managed instance.
/* --------------------------------------------------------------------------------------------
* Grab a strong reference to a document instance.
*/
void Grab()
{
if (m_Ptr)
{
++(*m_Ref);
}
}
/* --------------------------------------------------------------------------------------------
* Drop a strong reference to a document instance.
*/
void Drop()
{
if (m_Ptr && --(*m_Ref) == 0)
{
delete m_Ptr;
delete m_Ref;
m_Ptr = NULL;
m_Ref = NULL;
}
}
/* --------------------------------------------------------------------------------------------
* Base constructor.
*/
DocumentRef(bool utf8, bool multikey, bool multiline)
: m_Ptr(new Type(utf8, multikey, multiline)), m_Ref(new Counter(1))
{
/* ... */
}
public:
/* --------------------------------------------------------------------------------------------
* Default constructor (null).
*/
DocumentRef()
: m_Ptr(NULL), m_Ref(NULL)
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Copy constructor.
*/
DocumentRef(const DocumentRef & o)
: m_Ptr(o.m_Ptr), m_Ref(o.m_Ref)
{
Grab();
}
/* --------------------------------------------------------------------------------------------
* Move constructor.
*/
DocumentRef(DocumentRef && o)
: m_Ptr(o.m_Ptr), m_Ref(o.m_Ref)
{
o.m_Ptr = NULL;
o.m_Ref = NULL;
}
/* --------------------------------------------------------------------------------------------
* Destructor.
*/
~DocumentRef()
{
Drop();
}
/* --------------------------------------------------------------------------------------------
* Copy assignment operator.
*/
DocumentRef & operator = (const DocumentRef & o)
{
if (m_Ptr != o.m_Ptr)
{
Drop();
m_Ptr = o.m_Ptr;
m_Ref = o.m_Ref;
Grab();
}
return *this;
}
/* --------------------------------------------------------------------------------------------
* Move assignment operator.
*/
DocumentRef & operator = (DocumentRef && o)
{
if (m_Ptr != o.m_Ptr)
{
m_Ptr = o.m_Ptr;
m_Ref = o.m_Ref;
o.m_Ptr = NULL;
o.m_Ref = NULL;
}
return *this;
}
/* --------------------------------------------------------------------------------------------
* Perform an equality comparison between two document instances.
*/
bool operator == (const DocumentRef & o) const
{
return (m_Ptr == o.m_Ptr);
}
/* --------------------------------------------------------------------------------------------
* Perform an inequality comparison between two document instances.
*/
bool operator != (const DocumentRef & o) const
{
return (m_Ptr != o.m_Ptr);
}
/* --------------------------------------------------------------------------------------------
* Implicit conversion to boolean for use in boolean operations.
*/
operator bool () const
{
return m_Ptr;
}
/* --------------------------------------------------------------------------------------------
* Implicit conversion to the managed instance pointer.
*/
operator Pointer ()
{
return m_Ptr;
}
/* --------------------------------------------------------------------------------------------
* Implicit conversion to the managed instance pointer.
*/
operator ConstPtr () const
{
return m_Ptr;
}
/* --------------------------------------------------------------------------------------------
* Implicit conversion to the managed instance reference.
*/
operator Reference ()
{
assert(m_Ptr);
return *m_Ptr;
}
/* --------------------------------------------------------------------------------------------
* Implicit conversion to the managed instance reference.
*/
operator ConstRef () const
{
assert(m_Ptr);
return *m_Ptr;
}
/* --------------------------------------------------------------------------------------------
* Member operator for dereferencing the managed pointer.
*/
Pointer operator -> () const
{
assert(m_Ptr);
return m_Ptr;
}
/* --------------------------------------------------------------------------------------------
* Indirection operator for obtaining a reference of the managed pointer.
*/
Reference operator * () const
{
assert(m_Ptr);
return *m_Ptr;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the number of active references to the managed instance.
*/
Counter Count() const
{
return (m_Ptr && m_Ref) ? (*m_Ref) : 0;
}
};
/* ------------------------------------------------------------------------------------------------
* Class that can access and iterate a series of entries in the INI document.
*/
class Entries
{
// --------------------------------------------------------------------------------------------
friend class Document;
protected:
// --------------------------------------------------------------------------------------------
typedef DocumentRef::Type::TNamesDepend Container;
// --------------------------------------------------------------------------------------------
typedef Container::iterator Iterator;
/* --------------------------------------------------------------------------------------------
* Default constructor.
*/
Entries(const DocumentRef & ini, Container & list)
: m_Doc(ini), m_List(), m_Elem()
{
m_List.swap(list);
Reset();
}
private:
// ---------------------------------------------------------------------------------------------
DocumentRef m_Doc; // The document that contains the elements.
Container m_List; // The list of elements to iterate.
Iterator m_Elem; // The currently processed element.
public:
/* --------------------------------------------------------------------------------------------
* Default constructor. (null)
*/
Entries()
: m_Doc(), m_List(), m_Elem(m_List.end())
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Copy constructor.
*/
Entries(const Entries & o)
: m_Doc(o.m_Doc), m_List(o.m_List), m_Elem()
{
Reset();
}
/* --------------------------------------------------------------------------------------------
* Destructor.
*/
~Entries()
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Copy assignment operator.
*/
Entries & operator = (const Entries & o)
{
m_Doc = o.m_Doc;
m_List = o.m_List;
Reset();
return *this;
}
/* --------------------------------------------------------------------------------------------
* Used by the script engine to compare two instances of this type.
*/
Int32 Cmp(const Entries & o) const;
/* --------------------------------------------------------------------------------------------
* Used by the script engine to convert an instance of this type to a string.
*/
CSStr ToString() const
{
return GetItem();
}
/* --------------------------------------------------------------------------------------------
* Return whether the current element is valid and can be accessed.
*/
bool IsValid() const
{
return !(m_List.empty() || m_Elem == m_List.end());
}
/* --------------------------------------------------------------------------------------------
* Return whether the entry list is empty.
*/
bool IsEmpty() const
{
return m_List.empty();
}
/* --------------------------------------------------------------------------------------------
* Return the number of active references to this document instance.
*/
Uint32 GetRefCount() const
{
return m_Doc.Count();
}
/* --------------------------------------------------------------------------------------------
* Return the total entries in the list.
*/
Int32 GetSize() const
{
return static_cast< Int32 >(m_List.size());
}
/* --------------------------------------------------------------------------------------------
* Reset the internal iterator to the first element.
*/
void Reset()
{
if (m_List.empty())
{
m_Elem = m_List.end();
}
else
{
m_Elem = m_List.begin();
}
}
/* --------------------------------------------------------------------------------------------
* Go to the next element.
*/
void Next();
/* --------------------------------------------------------------------------------------------
* Go to the previous element.
*/
void Prev();
/* --------------------------------------------------------------------------------------------
* Advance a certain number of elements.
*/
void Advance(Int32 n);
/* --------------------------------------------------------------------------------------------
* Retreat a certain number of elements.
*/
void Retreat(Int32 n);
/* --------------------------------------------------------------------------------------------
* Sort the entries using the default options.
*/
void Sort()
{
if (!m_List.empty())
{
m_List.sort(DocumentRef::Type::Entry::KeyOrder());
}
}
/* --------------------------------------------------------------------------------------------
* Sort the entries by name of key only.
*/
void SortByKeyOrder()
{
if (!m_List.empty())
{
m_List.sort(DocumentRef::Type::Entry::KeyOrder());
}
}
/* --------------------------------------------------------------------------------------------
* Sort the entries by their load order and then name of key.
*/
void SortByLoadOrder()
{
if (!m_List.empty())
{
m_List.sort(DocumentRef::Type::Entry::LoadOrder());
}
}
/* --------------------------------------------------------------------------------------------
* Retrieve the string value of the current element item.
*/
CSStr GetItem() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the string value of the current element comment.
*/
CSStr GetComment() const;
/* --------------------------------------------------------------------------------------------
* Retrieve the order of the current element.
*/
Int32 GetOrder() const;
};
/* ------------------------------------------------------------------------------------------------
* Class that can read/write and alter the contents of INI files.
*/
class Document
{
protected:
// --------------------------------------------------------------------------------------------
typedef DocumentRef::Type::TNamesDepend Container;
/* --------------------------------------------------------------------------------------------
* Copy constructor. (disabled)
*/
Document(const Document & o);
/* --------------------------------------------------------------------------------------------
* Copy assignment operator. (disabled)
*/
Document & operator = (const Document & o);
private:
// ---------------------------------------------------------------------------------------------
DocumentRef m_Doc; // The main INI document instance.
public:
/* --------------------------------------------------------------------------------------------
* Default constructor.
*/
Document()
: m_Doc(false, false, true)
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Explicit constructor.
*/
Document(bool utf8)
: m_Doc(utf8, false, true)
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Explicit constructor.
*/
Document(bool utf8, bool multikey)
: m_Doc(utf8, multikey, true)
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Explicit constructor.
*/
Document(bool utf8, bool multikey, bool multiline)
: m_Doc(utf8, multikey, multiline)
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Destructor.
*/
~Document()
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Used by the script engine to compare two instances of this type.
*/
Int32 Cmp(const Document & o) const;
/* --------------------------------------------------------------------------------------------
* Used by the script engine to convert an instance of this type to a string.
*/
CSStr ToString() const
{
return _SC("");
}
/* --------------------------------------------------------------------------------------------
* See whether this instance references a valid INI document.
*/
bool IsValid() const
{
return m_Doc;
}
/* --------------------------------------------------------------------------------------------
* Return the number of active references to this document instance.
*/
Uint32 GetRefCount() const
{
return m_Doc.Count();
}
/* --------------------------------------------------------------------------------------------
* See whether any data has been loaded into this document.
*/
bool IsEmpty() const
{
return m_Doc->IsEmpty();
}
/* --------------------------------------------------------------------------------------------
* Deallocate all memory stored by this document.
*/
void Reset() const
{
m_Doc->Reset();
}
/* --------------------------------------------------------------------------------------------
* See whether the INI data is treated as unicode.
*/
bool GetUnicode() const
{
return m_Doc->IsUnicode();
}
/* --------------------------------------------------------------------------------------------
* Set whether the INI data should be treated as unicode.
*/
void SetUnicode(bool toggle)
{
m_Doc->SetUnicode(toggle);
}
/* --------------------------------------------------------------------------------------------
* See whether multiple identical keys be permitted in the file.
*/
bool GetMultiKey() const
{
return m_Doc->IsMultiKey();
}
/* --------------------------------------------------------------------------------------------
* Set whether multiple identical keys be permitted in the file.
*/
void SetMultiKey(bool toggle)
{
m_Doc->SetMultiKey(toggle);
}
/* --------------------------------------------------------------------------------------------
* See whether data values are permitted to span multiple lines in the file.
*/
bool GetMultiLine() const
{
return m_Doc->IsMultiLine();
}
/* --------------------------------------------------------------------------------------------
* Set whether data values are permitted to span multiple lines in the file.
*/
void SetMultiLine(bool toggle)
{
m_Doc->SetMultiLine(toggle);
}
/* --------------------------------------------------------------------------------------------
* See whether spaces are added around the equals sign when writing key/value pairs out.
*/
bool GetSpaces() const
{
return m_Doc->UsingSpaces();
}
/* --------------------------------------------------------------------------------------------
* Set whether spaces are added around the equals sign when writing key/value pairs out.
*/
void SetSpaces(bool toggle)
{
m_Doc->SetSpaces(toggle);
}
/* --------------------------------------------------------------------------------------------
* Load an INI file from disk into memory.
*/
IniResult LoadFile(CSStr filepath);
/* --------------------------------------------------------------------------------------------
* Load INI file data direct from a string. (LoadString collides with the windows api)
*/
IniResult LoadData(CSStr source)
{
return LoadData(source, -1);
}
/* --------------------------------------------------------------------------------------------
* Load INI file data direct from a string. (LoadString collides with the windows api)
*/
IniResult LoadData(CSStr source, Int32 size);
/* --------------------------------------------------------------------------------------------
* Save an INI file from memory to disk.
*/
IniResult SaveFile(CSStr filepath)
{
return SaveFile(filepath, true);
}
/* --------------------------------------------------------------------------------------------
* Save an INI file from memory to disk.
*/
IniResult SaveFile(CSStr filepath, bool signature);
/* --------------------------------------------------------------------------------------------
* Save the INI data to a string.
*/
Object SaveData(bool signature);
/* --------------------------------------------------------------------------------------------
* Retrieve all section names.
*/
Entries GetAllSections() const;
/* --------------------------------------------------------------------------------------------
* Retrieve all unique key names in a section.
*/
Entries GetAllKeys(CSStr section) const;
/* --------------------------------------------------------------------------------------------
* Retrieve all values for a specific key.
*/
Entries GetAllValues(CSStr section, CSStr key) const;
/* --------------------------------------------------------------------------------------------
* Query the number of keys in a specific section.
*/
Int32 GetSectionSize(CSStr section) const;
/* --------------------------------------------------------------------------------------------
* See whether a certain key has multiple instances.
*/
bool HasMultipleKeys(CSStr section, CSStr key) const;
/* --------------------------------------------------------------------------------------------
* Retrieve the value for a specific key.
*/
CCStr GetValue(CSStr section, CSStr key, CSStr def) const;
/* --------------------------------------------------------------------------------------------
* Retrieve a numeric value for a specific key.
*/
SQInteger GetInteger(CSStr section, CSStr key, SQInteger def) const;
/* --------------------------------------------------------------------------------------------
* Retrieve a numeric value for a specific key.
*/
SQFloat GetFloat(CSStr section, CSStr key, SQFloat def) const;
/* --------------------------------------------------------------------------------------------
* Retrieve a boolean value for a specific key.
*/
bool GetBoolean(CSStr section, CSStr key, bool def) const;
/* --------------------------------------------------------------------------------------------
* Add or update a section or value.
*/
IniResult SetValue(CSStr section, CSStr key, CSStr value)
{
return SetValue(section, key, value, false, nullptr);
}
/* --------------------------------------------------------------------------------------------
* Add or update a section or value.
*/
IniResult SetValue(CSStr section, CSStr key, CSStr value, bool force)
{
return SetValue(section, key, value, force, nullptr);
}
/* --------------------------------------------------------------------------------------------
* Add or update a section or value.
*/
IniResult SetValue(CSStr section, CSStr key, CSStr value, bool force, CSStr comment);
/* --------------------------------------------------------------------------------------------
* Add or update a numeric value.
*/
IniResult SetInteger(CSStr section, CSStr key, SQInteger value)
{
return SetInteger(section, key, value, false, false, nullptr);
}
/* --------------------------------------------------------------------------------------------
* Add or update a numeric value.
*/
IniResult SetInteger(CSStr section, CSStr key, SQInteger value, bool hex)
{
return SetInteger(section, key, value, hex, false, nullptr);
}
/* --------------------------------------------------------------------------------------------
* Add or update a numeric value.
*/
IniResult SetInteger(CSStr section, CSStr key, SQInteger value, bool hex, bool force)
{
return SetInteger(section, key, value, hex, force, nullptr);
}
/* --------------------------------------------------------------------------------------------
* Add or update a numeric value.
*/
IniResult SetInteger(CSStr section, CSStr key, SQInteger value, bool hex, bool force, CSStr comment);
/* --------------------------------------------------------------------------------------------
* Add or update a double value.
*/
IniResult SetFloat(CSStr section, CSStr key, SQFloat value)
{
return SetFloat(section, key, value, false, nullptr);
}
/* --------------------------------------------------------------------------------------------
* Add or update a double value.
*/
IniResult SetFloat(CSStr section, CSStr key, SQFloat value, bool force)
{
return SetFloat(section, key, value, force, nullptr);
}
/* --------------------------------------------------------------------------------------------
* Add or update a double value.
*/
IniResult SetFloat(CSStr section, CSStr key, SQFloat value, bool force, CSStr comment);
/* --------------------------------------------------------------------------------------------
* Add or update a double value.
*/
IniResult SetBoolean(CSStr section, CSStr key, bool value)
{
return SetBoolean(section, key, value, false, nullptr);
}
/* --------------------------------------------------------------------------------------------
* Add or update a double value.
*/
IniResult SetBoolean(CSStr section, CSStr key, bool value, bool force)
{
return SetBoolean(section, key, value, force, nullptr);
}
/* --------------------------------------------------------------------------------------------
* Add or update a boolean value.
*/
IniResult SetBoolean(CSStr section, CSStr key, bool value, bool force, CSStr comment);
/* --------------------------------------------------------------------------------------------
* Delete an entire section, or a key from a section.
*/
bool DeleteValue(CSStr section)
{
return DeleteValue(section, nullptr, nullptr, false);
}
/* --------------------------------------------------------------------------------------------
* Delete an entire section, or a key from a section.
*/
bool DeleteValue(CSStr section, CSStr key)
{
return DeleteValue(section, key, nullptr, false);
}
/* --------------------------------------------------------------------------------------------
* Delete an entire section, or a key from a section.
*/
bool DeleteValue(CSStr section, CSStr key, CSStr value)
{
return DeleteValue(section, key, value, false);
}
/* --------------------------------------------------------------------------------------------
* Delete an entire section, or a key from a section.
*/
bool DeleteValue(CSStr section, CSStr key, CSStr value, bool empty);
};
} // Namespace:: SqMod
#endif // _LIBRARY_IO_INI_HPP_

View File

@@ -0,0 +1,20 @@
// ------------------------------------------------------------------------------------------------
#include "Library/Numeric.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
extern void Register_LongInt(HSQUIRRELVM vm);
extern void Register_Math(HSQUIRRELVM vm);
extern void Register_Random(HSQUIRRELVM vm);
// ================================================================================================
void Register_Numeric(HSQUIRRELVM vm)
{
Register_LongInt(vm);
Register_Math(vm);
Register_Random(vm);
}
} // Namespace:: SqMod

View File

@@ -0,0 +1,14 @@
#ifndef _LIBRARY_NUMERIC_HPP_
#define _LIBRARY_NUMERIC_HPP_
// ------------------------------------------------------------------------------------------------
#include "SqBase.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
} // Namespace:: SqMod
#endif // _LIBRARY_NUMERIC_HPP_

View File

@@ -0,0 +1,197 @@
// ------------------------------------------------------------------------------------------------
#include "Library/Numeric/LongInt.hpp"
#include "Library/Numeric/Random.hpp"
#include "Base/Shared.hpp"
#include "Base/DynArg.hpp"
// ------------------------------------------------------------------------------------------------
#include <cstdio>
#include <cerrno>
#include <cstdlib>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
SQMODE_DECL_TYPENAME(TypenameS, _SC("SLongInt"))
SQMODE_DECL_TYPENAME(TypenameU, _SC("ULongInt"))
// ------------------------------------------------------------------------------------------------
LongInt< Int64 >::LongInt(CSStr text)
: m_Data(0), m_Text()
{
m_Data = std::strtoll(text, nullptr, 10);
}
// ------------------------------------------------------------------------------------------------
LongInt< Int64 >::LongInt(CSStr text, Uint32 base)
: m_Data(0), m_Text()
{
m_Data = std::strtoll(text, nullptr, base);
}
// ------------------------------------------------------------------------------------------------
LongInt< Int64 > & LongInt< Int64 >::operator = (CSStr text)
{
m_Data = std::strtoll(text, nullptr, 10);
return *this;
}
// ------------------------------------------------------------------------------------------------
CSStr LongInt< Int64 >::ToString()
{
if (std::snprintf(m_Text, sizeof(m_Text), "%llu", m_Data) < 0)
{
m_Text[0] = 0;
}
return m_Text;
}
// ------------------------------------------------------------------------------------------------
void LongInt< Int64 >::Random()
{
m_Data = GetRandomInt64();
}
// ------------------------------------------------------------------------------------------------
void LongInt< Int64 >::Random(Type n)
{
m_Data = GetRandomInt64(n);
}
// ------------------------------------------------------------------------------------------------
void LongInt< Int64 >::Random(Type m, Type n)
{
m_Data = GetRandomInt64(m, n);
}
// ------------------------------------------------------------------------------------------------
LongInt< Uint64 >::LongInt(CSStr text)
: m_Data(0), m_Text()
{
m_Data = std::strtoull(text, nullptr, 10);
}
// ------------------------------------------------------------------------------------------------
LongInt< Uint64 >::LongInt(CSStr text, Uint32 base)
: m_Data(0), m_Text()
{
m_Data = std::strtoull(text, nullptr, base);
}
// ------------------------------------------------------------------------------------------------
LongInt< Uint64 > & LongInt< Uint64 >::operator = (CSStr text)
{
m_Data = std::strtoull(text, nullptr, 10);
return *this;
}
// ------------------------------------------------------------------------------------------------
CSStr LongInt< Uint64 >::ToString()
{
if (std::snprintf(m_Text, sizeof(m_Text), "%llu", m_Data) < 0)
{
m_Text[0] = 0;
}
return m_Text;
}
// ------------------------------------------------------------------------------------------------
void LongInt< Uint64 >::Random()
{
m_Data = GetRandomUint64();
}
// ------------------------------------------------------------------------------------------------
void LongInt< Uint64 >::Random(Type n)
{
m_Data = GetRandomUint64(n);
}
// ------------------------------------------------------------------------------------------------
void LongInt< Uint64 >::Random(Type m, Type n)
{
m_Data = GetRandomUint64(m, n);
}
// ================================================================================================
void Register_LongInt(HSQUIRRELVM vm)
{
RootTable(vm).Bind(TypenameS::Str,
Class< SLongInt >(vm, TypenameS::Str)
// Constructors
.Ctor()
.Ctor< SLongInt::Type >()
.template Ctor< CCStr, SQInteger >()
// Properties
.Prop(_SC("Str"), &SLongInt::GetCStr, &SLongInt::SetStr)
.Prop(_SC("Num"), &SLongInt::GetSNum, &SLongInt::SetNum)
// Core Meta-methods
.SquirrelFunc(_SC("cmp"), &SqDynArgFwd< SqDynArgCmpFn< SLongInt >, SQInteger, SQFloat, bool, std::nullptr_t, CSStr, SLongInt, ULongInt >)
.SquirrelFunc(_SC("_typename"), &TypenameS::Fn)
.Func(_SC("_tostring"), &SLongInt::ToString)
// Core Functions
.Func(_SC("tointeger"), &SLongInt::ToSqInteger)
.Func(_SC("tofloat"), &SLongInt::ToSqFloat)
.Func(_SC("tostring"), &SLongInt::ToSqString)
.Func(_SC("tobool"), &SLongInt::ToSqBool)
.Func(_SC("tochar"), &SLongInt::ToSqChar)
// Meta-methods
.SquirrelFunc(_SC("_add"), &SqDynArgFwd< SqDynArgAddFn< SLongInt >, SQInteger, SQFloat, bool, std::nullptr_t, CSStr, SLongInt, ULongInt >)
.SquirrelFunc(_SC("_sub"), &SqDynArgFwd< SqDynArgSubFn< SLongInt >, SQInteger, SQFloat, bool, std::nullptr_t, CSStr, SLongInt, ULongInt >)
.SquirrelFunc(_SC("_mul"), &SqDynArgFwd< SqDynArgMulFn< SLongInt >, SQInteger, SQFloat, bool, std::nullptr_t, CSStr, SLongInt, ULongInt >)
.SquirrelFunc(_SC("_div"), &SqDynArgFwd< SqDynArgDivFn< SLongInt >, SQInteger, SQFloat, bool, std::nullptr_t, CSStr, SLongInt, ULongInt >)
.SquirrelFunc(_SC("_modulo"), &SqDynArgFwd< SqDynArgModFn< SLongInt >, SQInteger, SQFloat, bool, std::nullptr_t, CSStr, SLongInt, ULongInt >)
.Func< SLongInt (SLongInt::*)(void) const >(_SC("_unm"), &SLongInt::operator -)
// Functions
.Func(_SC("GetStr"), &SLongInt::GetCStr)
.Func(_SC("SetStr"), &SLongInt::SetStr)
.Func(_SC("GetNum"), &SLongInt::GetSNum)
.Func(_SC("SetNum"), &SLongInt::SetNum)
// Overloads
.Overload< void (SLongInt::*)(void) >(_SC("Random"), &SLongInt::Random)
.Overload< void (SLongInt::*)(SLongInt::Type) >(_SC("Random"), &SLongInt::Random)
.Overload< void (SLongInt::*)(SLongInt::Type, SLongInt::Type) >(_SC("Random"), &SLongInt::Random)
);
RootTable(vm).Bind(TypenameU::Str,
Class< ULongInt >(vm, TypenameU::Str)
// Constructors
.Ctor()
.Ctor< ULongInt::Type >()
.Ctor< CCStr, SQInteger >()
// Properties
.Prop(_SC("Str"), &ULongInt::GetCStr, &ULongInt::SetStr)
.Prop(_SC("Num"), &ULongInt::GetSNum, &ULongInt::SetNum)
// Core Meta-methods
.SquirrelFunc(_SC("cmp"), &SqDynArgFwd< SqDynArgCmpFn< ULongInt >, SQInteger, SQFloat, bool, std::nullptr_t, CSStr, ULongInt, SLongInt >)
.SquirrelFunc(_SC("_typename"), &TypenameU::Fn)
.Func(_SC("_tostring"), &ULongInt::ToString)
// Core Functions
.Func(_SC("tointeger"), &ULongInt::ToSqInteger)
.Func(_SC("tofloat"), &ULongInt::ToSqFloat)
.Func(_SC("tostring"), &ULongInt::ToSqString)
.Func(_SC("tobool"), &ULongInt::ToSqBool)
.Func(_SC("tochar"), &ULongInt::ToSqChar)
// Meta-methods
.SquirrelFunc(_SC("_add"), &SqDynArgFwd< SqDynArgAddFn< ULongInt >, SQInteger, SQFloat, bool, std::nullptr_t, CSStr, ULongInt, SLongInt >)
.SquirrelFunc(_SC("_sub"), &SqDynArgFwd< SqDynArgSubFn< ULongInt >, SQInteger, SQFloat, bool, std::nullptr_t, CSStr, ULongInt, SLongInt >)
.SquirrelFunc(_SC("_mul"), &SqDynArgFwd< SqDynArgMulFn< ULongInt >, SQInteger, SQFloat, bool, std::nullptr_t, CSStr, ULongInt, SLongInt >)
.SquirrelFunc(_SC("_div"), &SqDynArgFwd< SqDynArgDivFn< ULongInt >, SQInteger, SQFloat, bool, std::nullptr_t, CSStr, ULongInt, SLongInt >)
.SquirrelFunc(_SC("_modulo"), &SqDynArgFwd< SqDynArgModFn< ULongInt >, SQInteger, SQFloat, bool, std::nullptr_t, CSStr, ULongInt, SLongInt >)
.Func< ULongInt (ULongInt::*)(void) const >(_SC("_unm"), &ULongInt::operator -)
// Functions
.Func(_SC("GetStr"), &ULongInt::GetCStr)
.Func(_SC("SetStr"), &ULongInt::SetStr)
.Func(_SC("GetNum"), &ULongInt::GetSNum)
.Func(_SC("SetNum"), &ULongInt::SetNum)
// Overloads
.Overload< void (ULongInt::*)(void) >(_SC("Random"), &ULongInt::Random)
.Overload< void (ULongInt::*)(ULongInt::Type) >(_SC("Random"), &ULongInt::Random)
.Overload< void (ULongInt::*)(ULongInt::Type, ULongInt::Type) >(_SC("Random"), &ULongInt::Random)
);
}
} // Namespace:: SqMod

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,14 @@
#ifndef _LIBRARY_NUMERIC_MATH_HPP_
#define _LIBRARY_NUMERIC_MATH_HPP_
// ------------------------------------------------------------------------------------------------
#include "SqBase.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
} // Namespace:: SqMod
#endif // _LIBRARY_NUMERIC_MATH_HPP_

View File

@@ -0,0 +1,444 @@
// ------------------------------------------------------------------------------------------------
#include "Library/Numeric/Random.hpp"
#include "Base/Shared.hpp"
#include "Base/Buffer.hpp"
// ------------------------------------------------------------------------------------------------
#include <ctime>
#include <memory>
#include <random>
#include <cstdlib>
// ------------------------------------------------------------------------------------------------
#ifdef SQMOD_OS_WINDOWS
#include <process.h>
#else
#include <sys/types.h>
#include <unistd.h>
#endif
// ------------------------------------------------------------------------------------------------
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()
{
Ulong a = clock();
Ulong b = time(NULL);
#ifdef SQMOD_OS_WINDOWS
Ulong c = _getpid();
#else
Ulong c = getpid();
#endif
// Mangle
a=a-b; a=a-c; a=a^(c >> 13);
b=b-c; b=b-a; b=b^(a << 8);
c=c-a; c=c-b; c=c^(b >> 13);
a=a-b; a=a-c; a=a^(c >> 12);
b=b-c; b=b-a; b=b^(a << 16);
c=c-a; c=c-b; c=c^(b >> 5);
a=a-b; a=a-c; a=a^(c >> 3);
b=b-c; b=b-a; b=b^(a << 10);
c=c-a; c=c-b; c=c^(b >> 15);
// Return result
return c;
}
// ------------------------------------------------------------------------------------------------
SizeT GenerateSeed2()
{
struct {
std::clock_t c;
std::time_t t;
#ifdef SQMOD_OS_WINDOWS
int p;
#else
pid_t p;
#endif
} data;
data.c = std::clock();
data.t = std::time(nullptr);
#ifdef SQMOD_OS_WINDOWS
data.p = _getpid();
#else
data.p = getpid();
#endif
// Mangle and return result
return FnvHash(reinterpret_cast< const uint8_t * >(&data), sizeof(data));
}
// ------------------------------------------------------------------------------------------------
void ReseedRandom()
{
RG32_MT19937.reset(new std::mt19937(GenerateSeed()));
RG64_MT19937.reset(new std::mt19937_64(GenerateSeed()));
}
void ReseedRandom(Uint32 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 Int8_Dist(*RG32_MT19937);
}
Int8 GetRandomInt8(Int8 n)
{
return std::uniform_int_distribution< Int8 >(0, n)(*RG32_MT19937);
}
Int8 GetRandomInt8(Int8 m, Int8 n)
{
return std::uniform_int_distribution< Int8 >(m, n)(*RG32_MT19937);
}
// ------------------------------------------------------------------------------------------------
Uint8 GetRandomUint8()
{
return Uint8_Dist(*RG32_MT19937);
}
Uint8 GetRandomUint8(Uint8 n)
{
return std::uniform_int_distribution< Uint8 >(0, n)(*RG32_MT19937);
}
Uint8 GetRandomUint8(Uint8 m, Uint8 n)
{
return std::uniform_int_distribution< Uint8 >(m, n)(*RG32_MT19937);
}
// ------------------------------------------------------------------------------------------------
Int16 GetRandomInt16()
{
return Int16_Dist(*RG32_MT19937);
}
Int16 GetRandomInt16(Int16 n)
{
return std::uniform_int_distribution< Int16 >(0, n)(*RG32_MT19937);
}
Int16 GetRandomInt16(Int16 m, Int16 n)
{
return std::uniform_int_distribution< Int16 >(m, n)(*RG32_MT19937);
}
// ------------------------------------------------------------------------------------------------
Uint16 GetRandomUint16()
{
return Uint16_Dist(*RG32_MT19937);
}
Uint16 GetRandomUint16(Uint16 n)
{
return std::uniform_int_distribution< Uint16 >(0, n)(*RG32_MT19937);
}
Uint16 GetRandomUint16(Uint16 m, Uint16 n)
{
return std::uniform_int_distribution< Uint16 >(m, n)(*RG32_MT19937);
}
// ------------------------------------------------------------------------------------------------
Int32 GetRandomInt32()
{
return Int32_Dist(*RG32_MT19937);
}
Int32 GetRandomInt32(Int32 n)
{
return std::uniform_int_distribution< Int32 >(0, n)(*RG32_MT19937);
}
Int32 GetRandomInt32(Int32 m, Int32 n)
{
return std::uniform_int_distribution< Int32 >(m, n)(*RG32_MT19937);
}
// ------------------------------------------------------------------------------------------------
Uint32 GetRandomUint32()
{
return Int32_Dist(*RG32_MT19937);
}
Uint32 GetRandomUint32(Uint32 n)
{
return std::uniform_int_distribution< Int32 >(0, n)(*RG32_MT19937);
}
Uint32 GetRandomUint32(Uint32 m, Uint32 n)
{
return std::uniform_int_distribution< Int32 >(m, n)(*RG32_MT19937);
}
// ------------------------------------------------------------------------------------------------
Int64 GetRandomInt64()
{
return Int64_Dist(*RG64_MT19937);
}
Int64 GetRandomInt64(Int64 n)
{
return std::uniform_int_distribution< Int64 >(0, n)(*RG64_MT19937);
}
Int64 GetRandomInt64(Int64 m, Int64 n)
{
return std::uniform_int_distribution< Int64 >(m, n)(*RG64_MT19937);
}
// ------------------------------------------------------------------------------------------------
Uint64 GetRandomUint64()
{
return Uint64_Dist(*RG64_MT19937);
}
Uint64 GetRandomUint64(Uint64 n)
{
return std::uniform_int_distribution< Uint64 >(0, n)(*RG64_MT19937);
}
Uint64 GetRandomUint64(Uint64 m, Uint64 n)
{
return std::uniform_int_distribution< Uint64 >(m, n)(*RG64_MT19937);
}
// ------------------------------------------------------------------------------------------------
Float32 GetRandomFloat32()
{
return Float32_Dist(*RG32_MT19937);
}
Float32 GetRandomFloat32(Float32 n)
{
return std::uniform_real_distribution< Float32 >(0, n)(*RG32_MT19937);
}
Float32 GetRandomFloat32(Float32 m, Float32 n)
{
return std::uniform_real_distribution< Float32 >(m, n)(*RG32_MT19937);
}
// ------------------------------------------------------------------------------------------------
Float64 GetRandomFloat64()
{
return Float64_Dist(*RG64_MT19937);
}
Float64 GetRandomFloat64(Float64 n)
{
return std::uniform_real_distribution< Float64 >(0, n)(*RG64_MT19937);
}
Float64 GetRandomFloat64(Float64 m, Float64 n)
{
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);
// 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);
// 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);
// 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 std::bernoulli_distribution()(*RG32_MT19937);
}
bool GetRandomBool(SQFloat p)
{
return std::bernoulli_distribution(p)(*RG32_MT19937);
}
// ------------------------------------------------------------------------------------------------
static String RandomString(Int32 len)
{
// Is there anything to generate?
if (len <= 0)
return _SC("");
// Prepare the string buffer
String str;
// Request the random fill
GetRandomString(str, len);
// Return ownership of the string
return std::move(str);
}
// ------------------------------------------------------------------------------------------------
static String RandomString(Int32 len, SQChar n)
{
// Is there anything to generate?
if (len <= 0)
return _SC("");
// Prepare the string buffer
String str;
// Request the random fill
GetRandomString(str, len, n);
// Return ownership of the string
return std::move(str);
}
// ------------------------------------------------------------------------------------------------
static String RandomString(Int32 len, SQChar m, SQChar n)
{
// Is there anything to generate?
if (len <= 0)
return _SC("");
// Prepare the string buffer
String str;
// Request the random fill
GetRandomString(str, len, m, n);
// Return ownership of the string
return std::move(str);
}
// ------------------------------------------------------------------------------------------------
void Register_Random(HSQUIRRELVM vm)
{
RootTable(vm).Bind(_SC("SqRand"), Table(vm)
.Func(_SC("GenSeed"), &GenerateSeed)
.Func(_SC("GenSeed2"), &GenerateSeed2)
.Overload< void (*)(void) >(_SC("Reseed"), &ReseedRandom)
.Overload< void (*)(Uint32) >(_SC("Reseed"), &ReseedRandom)
.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)
);
}
} // Namespace:: SqMod

View File

@@ -0,0 +1,164 @@
#ifndef _LIBRARY_NUMERIC_RANDOM_HPP_
#define _LIBRARY_NUMERIC_RANDOM_HPP_
// ------------------------------------------------------------------------------------------------
#include "SqBase.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* Attempt to generate a moderately unique number to be used as a seed for random numbers.
*/
Uint32 GenerateSeed();
// ------------------------------------------------------------------------------------------------
void ReseedRandom();
void ReseedRandom(Uint32 n);
// ------------------------------------------------------------------------------------------------
Int8 GetRandomInt8();
Int8 GetRandomInt8(Int8 n);
Int8 GetRandomInt8(Int8 m, Int8 n);
// ------------------------------------------------------------------------------------------------
Uint8 GetRandomUint8();
Uint8 GetRandomUint8(Uint8 n);
Uint8 GetRandomUint8(Uint8 m, Uint8 n);
// ------------------------------------------------------------------------------------------------
Int16 GetRandomInt16();
Int16 GetRandomInt16(Int16 n);
Int16 GetRandomInt16(Int16 m, Int16 n);
// ------------------------------------------------------------------------------------------------
Uint16 GetRandomUint16();
Uint16 GetRandomUint16(Uint16 n);
Uint16 GetRandomUint16(Uint16 m, Uint16 n);
// ------------------------------------------------------------------------------------------------
Int32 GetRandomInt32();
Int32 GetRandomInt32(Int32 n);
Int32 GetRandomInt32(Int32 m, Int32 n);
// ------------------------------------------------------------------------------------------------
Uint32 GetRandomUint32();
Uint32 GetRandomUint32(Uint32 n);
Uint32 GetRandomUint32(Uint32 m, Uint32 n);
// ------------------------------------------------------------------------------------------------
Int64 GetRandomInt64();
Int64 GetRandomInt64(Int64 n);
Int64 GetRandomInt64(Int64 m, Int64 n);
// ------------------------------------------------------------------------------------------------
Uint64 GetRandomUint64();
Uint64 GetRandomUint64(Uint64 n);
Uint64 GetRandomUint64(Uint64 m, Uint64 n);
// ------------------------------------------------------------------------------------------------
Float32 GetRandomFloat32();
Float32 GetRandomFloat32(Float32 n);
Float32 GetRandomFloat32(Float32 m, Float32 n);
// ------------------------------------------------------------------------------------------------
Float64 GetRandomFloat64();
Float64 GetRandomFloat64(Float64 n);
Float64 GetRandomFloat64(Float64 m, Float64 n);
// ------------------------------------------------------------------------------------------------
void GetRandomString(String & str, String::size_type len);
void GetRandomString(String & str, String::size_type len, String::value_type n);
void GetRandomString(String & str, String::size_type len, String::value_type m, String::value_type n);
// ------------------------------------------------------------------------------------------------
bool GetRandomBool();
// ------------------------------------------------------------------------------------------------
template <typename T> struct RandomVal
{ /* ... */ };
// ------------------------------------------------------------------------------------------------
template <> struct RandomVal< Int8 >
{
static inline Int8 Get() { return GetRandomInt8(); }
static inline Int8 Get(Int8 n) { return GetRandomInt8(n); }
static inline Int8 Get(Int8 m, Int8 n) { return GetRandomInt8(m, n); }
};
template <> struct RandomVal< Uint8 >
{
static inline Uint8 Get() { return GetRandomUint8(); }
static inline Uint8 Get(Uint8 n) { return GetRandomUint8(n); }
static inline Uint8 Get(Uint8 m, Uint8 n) { return GetRandomUint8(m, n); }
};
// ------------------------------------------------------------------------------------------------
template <> struct RandomVal< Int16 >
{
static inline Int16 Get() { return GetRandomInt16(); }
static inline Int16 Get(Int16 n) { return GetRandomInt16(n); }
static inline Int16 Get(Int16 m, Int16 n) { return GetRandomInt16(m, n); }
};
template <> struct RandomVal< Uint16 >
{
static inline Uint16 Get() { return GetRandomUint16(); }
static inline Uint16 Get(Uint16 n) { return GetRandomUint16(n); }
static inline Uint16 Get(Uint16 m, Uint16 n) { return GetRandomUint16(m, n); }
};
// ------------------------------------------------------------------------------------------------
template <> struct RandomVal< Int32 >
{
static inline Int32 Get() { return GetRandomInt32(); }
static inline Int32 Get(Int32 n) { return GetRandomInt32(n); }
static inline Int32 Get(Int32 m, Int32 n) { return GetRandomInt32(m, n); }
};
template <> struct RandomVal< Uint32 >
{
static inline Uint32 Get() { return GetRandomUint32(); }
static inline Uint32 Get(Uint32 n) { return GetRandomUint32(n); }
static inline Uint32 Get(Uint32 m, Uint32 n) { return GetRandomUint32(m, n); }
};
// ------------------------------------------------------------------------------------------------
template <> struct RandomVal< Int64 >
{
static inline Int64 Get() { return GetRandomInt64(); }
static inline Int64 Get(Int64 n) { return GetRandomInt64(n); }
static inline Int64 Get(Int64 m, Int64 n) { return GetRandomInt64(m, n); }
};
template <> struct RandomVal< Uint64 >
{
static inline Uint64 Get() { return GetRandomUint64(); }
static inline Uint64 Get(Uint64 n) { return GetRandomUint64(n); }
static inline Uint64 Get(Uint64 m, Uint64 n) { return GetRandomUint64(m, n); }
};
// ------------------------------------------------------------------------------------------------
template <> struct RandomVal< Float32 >
{
static inline Float32 Get() { return GetRandomFloat32(); }
static inline Float32 Get(Float32 n) { return GetRandomFloat32(n); }
static inline Float32 Get(Float32 m, Float32 n) { return GetRandomFloat32(m, n); }
};
template <> struct RandomVal< Float64 >
{
static inline Float64 Get() { return GetRandomFloat64(); }
static inline Float64 Get(Float64 n) { return GetRandomFloat64(n); }
static inline Float64 Get(Float64 m, Float64 n) { return GetRandomFloat64(m, n); }
};
// ------------------------------------------------------------------------------------------------
template <> struct RandomVal< bool >
{
static inline bool Get() { return GetRandomBool(); }
};
} // Namespace:: SqMod
#endif // _LIBRARY_NUMERIC_RANDOM_HPP_

973
module/Library/String.cpp Normal file
View File

@@ -0,0 +1,973 @@
// ------------------------------------------------------------------------------------------------
#include "Library/String.hpp"
#include "Base/Shared.hpp"
#include "Base/Buffer.hpp"
// ------------------------------------------------------------------------------------------------
#include <cctype>
#include <cstdio>
#include <cstdlib>
#include <cstring>
// ------------------------------------------------------------------------------------------------
#include <algorithm>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
static LightObj SqLeftStr(SQChar f, Uint32 w, StackStrF & s)
{
// Is the specified width valid?
if (!w)
{
return _SC(""); // Default to an empty string!
}
// Allocate a buffer with the requested width
Buffer b(w + 1); // + null terminator
// Is the specified string valid?
if (!s.mLen)
{
std::memset(b.Data(), f, w); // Insert only the fill character
}
else
{
// Insert only the fill character first
std::memset(b.Data(), f, w);
// Overwrite with the specified string
std::strncpy(b.Data(), s.mPtr, s.mLen);
}
// Obtain the initial stack size
const StackGuard sg(s.mVM);
// Push the string onto the stack
sq_pushstring(s.mVM, b.Data(), w);
// Obtain the object from the stack and return it
return std::move(Var< LightObj >(s.mVM, -1).value);
}
// ------------------------------------------------------------------------------------------------
static LightObj SqLeftOffsetStr(SQChar f, Uint32 w, Uint32 o, StackStrF & s)
{
// Is the specified width valid?
if (!w)
{
return _SC(""); // Default to an empty string!
}
// Is the specified offset within width range?
else if (o > w)
{
STHROWF("Offset is out of bounds");
}
// Allocate a buffer with the requested width
Buffer b(w + 1); // + null terminator
// Is the specified string valid?
if (!s.mLen)
{
std::memset(b.Data(), f, w); // Insert only the fill character
}
else
{
// Calculate the string length
const Uint32 n = ConvTo< Uint32 >::From(s.mLen);
// Insert the fill character first
std::memset(b.Data(), f, w);
// Overwrite with the specified string
if (n > (w - o))
{
std::strncpy(b.Data() + o, s.mPtr, n);
}
else
{
std::memcpy(b.Data() + o, s.mPtr, n * sizeof(SQChar));
}
}
// Obtain the initial stack size
const StackGuard sg(s.mVM);
// Push the string onto the stack
sq_pushstring(s.mVM, b.Data(), w);
// Obtain the object from the stack and return it
return std::move(Var< LightObj >(s.mVM, -1).value);
}
// ------------------------------------------------------------------------------------------------
static LightObj SqRightStr(SQChar f, Uint32 w, StackStrF & s)
{
// Is the specified width valid?
if (!w)
{
return _SC(""); // Default to an empty string!
}
// Allocate a buffer with the requested width
Buffer b(w + 1); // + null terminator
// Is the specified string valid?
if (!s.mLen)
{
std::memset(b.Data(), f, w); // Insert only the fill character
}
else
{
// Calculate the string length
const Uint32 n = ConvTo< Uint32 >::From(s.mLen);
// Insert the fill character first
std::memset(b.Data(), f, w);
// Overwrite with the specified string
if (n >= w)
{
std::strncpy(b.Data(), s.mPtr, w);
}
else
{
std::strncpy(b.Data() + (w - n), s.mPtr, n);
}
}
// Obtain the initial stack size
const StackGuard sg(s.mVM);
// Push the string onto the stack
sq_pushstring(s.mVM, b.Data(), w);
// Obtain the object from the stack and return it
return std::move(Var< LightObj >(s.mVM, -1).value);
}
// ------------------------------------------------------------------------------------------------
static LightObj SqRightOffsetStr(SQChar f, Uint32 w, Uint32 o, StackStrF & s)
{
// Is the specified width valid?
if (!w)
{
return _SC(""); // Default to an empty string!
}
// Is the specified offset within width range?
else if (o > w)
{
STHROWF("Offset is out of bounds");
}
// Allocate a buffer with the requested width
Buffer b(w + 1); // + null terminator
// Is the specified string valid?
if (!s.mLen)
{
std::memset(b.Data(), f, w); // Insert only the fill character
}
else
{
// Calculate the string length
const Uint32 n = ConvTo< Uint32 >::From(s.mLen);
// Insert the fill character first
std::memset(b.Data(), f, w);
// Overwrite with the specified string
if (n >= w || (n + o) >= w)
{
std::strncpy(b.Data(), s.mPtr, w - o);
}
else
{
std::strncpy(b.Data() + ((w - n) - o), s.mPtr, n);
}
}
// Obtain the initial stack size
const StackGuard sg(s.mVM);
// Push the string onto the stack
sq_pushstring(s.mVM, b.Data(), w);
// Obtain the object from the stack and return it
return std::move(Var< LightObj >(s.mVM, -1).value);
}
// ------------------------------------------------------------------------------------------------
static LightObj SqCenterStr(SQChar f, Uint32 w, StackStrF & s)
{
// Is the specified width valid?
if (!w)
{
return _SC(""); // Default to an empty string!
}
// Allocate a buffer with the requested width
Buffer b(w + 1); // + null terminator
// Is the specified string valid?
if (!s.mLen)
{
std::memset(b.Data(), f, w); // Insert only the fill character
}
else
{
// Calculate the insert position
const Int32 p = ((w/2) - (s.mLen/2));
// Insert only the fill character first
std::memset(b.Data(), f, w);
// Overwrite with the specified string
std::strncpy(b.Data() + (p < 0 ? 0 : p), s.mPtr, s.mLen);
}
// Obtain the initial stack size
const StackGuard sg(s.mVM);
// Push the string onto the stack
sq_pushstring(s.mVM, b.Data(), w);
// Obtain the object from the stack and return it
return std::move(Var< LightObj >(s.mVM, -1).value);
}
// ------------------------------------------------------------------------------------------------
static Buffer StrJustAlphaNumImpl(CSStr str, Uint32 len)
{
// See if we actually have something to search for
if(!len)
{
return Buffer(); // Default to an empty buffer!
}
// Obtain a temporary buffer
Buffer b(len + 1); // + null terminator
// Resulted string size
Uint32 n = 0;
// Currently processed character
SQChar c = 0;
// Process characters
while ((c = *(str++)) != '\0')
{
// Is this an alpha-numeric character?
if (std::isalnum(c) != 0)
{
// Save it and move to the next one
b.At(n++) = c;
}
}
// End the resulted string
b.At(n) = '\0';
// Move the cursor to the end
b.Move(n);
// Return ownership of the buffer
return std::move(b);
}
// ------------------------------------------------------------------------------------------------
Buffer StrJustAlphaNumB(CSStr str)
{
// See if we actually have something to search for
if(!str || *str == '\0')
{
return Buffer(); // Default to an empty string!
}
// Attempt to convert and return the result
return StrJustAlphaNumImpl(str, std::strlen(str));
}
// ------------------------------------------------------------------------------------------------
CSStr StrJustAlphaNum(CSStr str)
{
// See if we actually have something to search for
if(!str || *str == '\0')
{
return _SC(""); // Default to an empty string!
}
// Attempt to convert and return the result
return StrJustAlphaNumImpl(str, std::strlen(str)).Get< SQChar >();
}
// ------------------------------------------------------------------------------------------------
static LightObj SqJustAlphaNum(StackStrF & s)
{
const Buffer b(StrJustAlphaNumImpl(s.mPtr, s.mLen));
// Obtain the initial stack size
const StackGuard sg(s.mVM);
// Push the string onto the stack
sq_pushstring(s.mVM, b.Data(), b.Position());
// Obtain the object from the stack and return it
return std::move(Var< LightObj >(s.mVM, -1).value);
}
// ------------------------------------------------------------------------------------------------
static Buffer StrToLowercaseImpl(CSStr str, Uint32 len)
{
// See if we actually have something to search for
if(!len)
{
return Buffer(); // Default to an empty buffer!
}
// Obtain a temporary buffer
Buffer b(len + 1); // + null terminator
// Resulted string size
Uint32 n = 0;
// Process characters
while (*str != '\0')
{
// Convert it and move to the next one
b.At(n++) = std::tolower(*(str++));
}
// End the resulted string
b.At(n) = '\0';
// Move the cursor to the end
b.Move(n);
// Return ownership of the buffer
return std::move(b);
}
// ------------------------------------------------------------------------------------------------
Buffer StrToLowercaseB(CSStr str)
{
// See if we actually have something to search for
if(!str || *str == '\0')
{
return Buffer(); // Default to an empty string!
}
// Attempt to convert and return the result
return StrToLowercaseImpl(str, std::strlen(str));
}
// ------------------------------------------------------------------------------------------------
CSStr StrToLowercase(CSStr str)
{
// See if we actually have something to search for
if(!str || *str == '\0')
{
return _SC(""); // Default to an empty string!
}
// Attempt to convert and return the result
return StrToLowercaseImpl(str, std::strlen(str)).Get< SQChar >();
}
// ------------------------------------------------------------------------------------------------
static LightObj SqToLowercase(StackStrF & s)
{
const Buffer b(StrToLowercaseImpl(s.mPtr, s.mLen));
// Obtain the initial stack size
const StackGuard sg(s.mVM);
// Push the string onto the stack
sq_pushstring(s.mVM, b.Data(), b.Position());
// Obtain the object from the stack and return it
return std::move(Var< LightObj >(s.mVM, -1).value);
}
// ------------------------------------------------------------------------------------------------
static Buffer StrToUppercaseImpl(CSStr str, Uint32 len)
{
// See if we actually have something to search for
if(!len)
{
return Buffer(); // Default to an empty buffer!
}
// Obtain a temporary buffer
Buffer b(len + 1); // + null terminator
// Resulted string size
Uint32 n = 0;
// Process characters
while (*str != '\0')
{
// Convert it and move to the next one
b.At(n++) = std::toupper(*(str++));
}
// End the resulted string
b.At(n) = '\0';
// Move the cursor to the end
b.Move(n);
// Return ownership of the buffer
return std::move(b);
}
// ------------------------------------------------------------------------------------------------
Buffer StrToUppercaseB(CSStr str)
{
// See if we actually have something to search for
if(!str || *str == '\0')
{
return Buffer(); // Default to an empty string!
}
// Attempt to convert and return the result
return StrToUppercaseImpl(str, std::strlen(str));
}
// ------------------------------------------------------------------------------------------------
CSStr StrToUppercase(CSStr str)
{
// See if we actually have something to search for
if(!str || *str == '\0')
{
return _SC(""); // Default to an empty string!
}
// Attempt to convert and return the result
return StrToUppercaseImpl(str, std::strlen(str)).Get< SQChar >();
}
// ------------------------------------------------------------------------------------------------
static LightObj SqToUppercase(StackStrF & s)
{
const Buffer b(StrToUppercaseImpl(s.mPtr, s.mLen));
// Obtain the initial stack size
const StackGuard sg(s.mVM);
// Push the string onto the stack
sq_pushstring(s.mVM, b.Data(), b.Position());
// Obtain the object from the stack and return it
return std::move(Var< LightObj >(s.mVM, -1).value);
}
/* ------------------------------------------------------------------------------------------------
* Checks if all the characters in the specified string are of the specified class or not.
*/
template < int (*Fn)(int) > static bool SqAllChars(StackStrF & s)
{
// See if we actually have something to search for
if (!s.mLen)
{
// Since there are no other different character then
// we count this as all characters being of this type
return true;
}
// Start iterating characters and find the first that doesn't match
for (CSStr itr = s.mPtr; *itr != '\0'; ++itr)
{
// Call the predicate with the current character
if (Fn(*itr) == 0)
{
return false; // This character did not pass the test
}
}
// All characters passed the test
return true;
}
/* ------------------------------------------------------------------------------------------------
* Find the position of the first character that matches the specified class.
*/
template < int (*Fn)(int), bool Neg > static LightObj SqFirstChar(StackStrF & s)
{
// See if we actually have something to search for
if (s.mLen)
{
// Start iterating characters and find the first that doesn't match
for (CSStr itr = s.mPtr; *itr != '\0'; ++itr)
{
// Call the predicate with the current character
if ((Fn(*itr) == 0) == Neg)
{
// Obtain the initial stack size
const StackGuard sg(s.mVM);
// This character passed our test, push it's position
sq_pushinteger(s.mVM, itr - s.mPtr);
// Obtain the object from the stack and return it
return std::move(Var< LightObj >(s.mVM, -1).value);
}
}
}
// Since there are no other different character then
// we count this as all characters being of this type
return LightObj();
}
/* ------------------------------------------------------------------------------------------------
* Find the position of the last character that matches the specified class.
*/
template < int (*Fn)(int), bool Neg > static LightObj SqLastChar(StackStrF & s)
{
// See if we actually have something to search for
if (s.mLen)
{
// Start iterating characters and find the first that doesn't match
for (CSStr itr = (s.mPtr + s.mLen) - 1; itr >= s.mPtr; --itr)
{
// Call the predicate with the current character
if ((Fn(*itr) == 0) == Neg)
{
// Obtain the initial stack size
const StackGuard sg(s.mVM);
// This character passed our test, push it's position
sq_pushinteger(s.mVM, itr - s.mPtr);
// Obtain the object from the stack and return it
return std::move(Var< LightObj >(s.mVM, -1).value);
}
}
}
// Since there are no other different character then
// we count this as all characters being of this type
return LightObj();
}
/* ------------------------------------------------------------------------------------------------
* Split the string into chunks wherever a character matches or not the specified class.
*/
static SQInteger SplitWhereCharImpl(HSQUIRRELVM vm, int(*fn)(int), bool neg)
{
static const SQInteger top = sq_gettop(vm);
// Is there a value to process?
if (top <= 1)
{
return sq_throwerror(vm, "Missing string or value");
}
// Attempt to retrieve the value from the stack as a string
StackStrF val(vm, 2);
// Have we failed to retrieve the string?
if (SQ_FAILED(val.Proc(true)))
{
return val.mRes; // Propagate the error!
}
// Create a new array on the stack
sq_newarray(vm, 0);
// See if we actually have something to search for
if (!(val.mPtr) || *(val.mPtr) == '\0')
{
return 1; // Return an empty array
}
// Remember the position of the last found match
CSStr last = val.mPtr;
// Start iterating characters and slice where a match is found
for (CSStr itr = val.mPtr; *itr != '\0'; ++itr)
{
// Call the predicate with the current character
if ((fn(*itr) == 0) == neg)
{
// Are there any characters before this match?
if ((itr - last) > 0 && (*last != '\0'))
{
// Push this chunk of string on the stack
sq_pushstring(vm, last, itr - last);
// Insert this element into the array on the stack
const SQRESULT r = sq_arrayappend(vm, -2);
// Did we fail to append the element?
if (SQ_FAILED(r))
{
return r; // We're done here
}
}
// Push this character as an integer on the stack
sq_pushinteger(vm, *itr);
// Insert this element into the array on the stack
const SQRESULT r = sq_arrayappend(vm, -2);
// Did we fail to append the element?
if (SQ_FAILED(r))
{
return r; // We're done here
}
// Update the position of the last found match
last = (itr + 1);
}
}
// Push the remaining chunk, if any
if (*last != '\0')
{
// Push this chunk of string on the stack
sq_pushstring(vm, last, -1);
// Insert this element into the array on the stack
const SQRESULT r = sq_arrayappend(vm, -2);
// Did we fail to append the element?
if (SQ_FAILED(r))
{
return r; // We're done here
}
}
// We have a value to return on the stack
return 1;
}
/* ------------------------------------------------------------------------------------------------
* Simple forwarder to minimize templated functions with large body and reduce executable size.
*/
template < int (*Fn)(int), bool Neg > static SQInteger SplitWhereCharProxy(HSQUIRRELVM vm)
{
return SplitWhereCharImpl(vm, Fn, Neg);
}
/* ------------------------------------------------------------------------------------------------
* Checks if the specified character is of the specified class.
*/
template < int (*Fn)(int) > static bool IsCharOfType(int c)
{
return (Fn(c) != 0);
}
// ------------------------------------------------------------------------------------------------
static bool OnlyDelimiter(CSStr str, SQChar chr)
{
while (*str != '\0')
{
// Is this different from the delimiter?
if (*(str++) != chr)
{
// Another character was found
return false;
}
}
// No other character was found
return true;
}
// ------------------------------------------------------------------------------------------------
static SQInteger SqStrExplode(HSQUIRRELVM vm)
{
const Int32 top = sq_gettop(vm);
// Was the delimiter character specified?
if (top <= 1)
{
return sq_throwerror(vm, _SC("Missing delimiter character"));
}
// Was the boolean empty specified?
else if (top <= 2)
{
return sq_throwerror(vm, _SC("Missing boolean empty"));
}
// Was the string value specified?
else if (top <= 3)
{
return sq_throwerror(vm, _SC("Missing string value"));
}
// Attempt to generate the string value
StackStrF val(vm, 4);
// Have we failed to retrieve the string?
if (SQ_FAILED(val.Proc(true)))
{
return val.mRes; // Propagate the error!
}
// The delimiter character and boolean empty
SQChar delim = 0;
bool empty = 0;
// Attempt to retrieve the remaining arguments from the stack
try
{
delim = Var< SQChar >(vm, 2).value;
empty = Var< bool >(vm, 3).value;
}
catch (const Sqrat::Exception & e)
{
return sq_throwerror(vm, e.what());
}
catch (...)
{
return sq_throwerror(vm, _SC("Unable to retrieve arguments"));
}
// Grab the string value to a shorter name
CSStr str = val.mPtr;
// Create an empty array on the stack
sq_newarray(vm, 0);
// See if we actually have something to explode
if(!str || *str == '\0')
{
// Specify that we have an argument on the stack
return 1;
}
// Don't modify the specified string pointer
CSStr itr = str, last = str;
// The number of delimiter occurrences
Uint32 num = 0;
// Pre-count how many delimiters of this type exist
while (*itr != '\0')
{
// Is this our delimiter?
if (*(itr++) == delim)
{
// Are we allowed to include empty elements?
if (empty || (itr - last) > 1)
{
// Increase the count
++num;
}
// Update the last delimiter position
last = itr;
}
}
// Were there no delimiters found and can we include empty elements?
if (num == 0 && !empty && (str[1] == '\0' || OnlyDelimiter(str, delim)))
{
// Specify that we have an argument on the stack
return 1;
}
// Have we found any delimiters?
else if (num == 0)
{
// Test against strings with only delimiters
if (str[1] == '\0' || OnlyDelimiter(str, delim))
{
sq_pushstring(vm, _SC(""), 0); // Add an empty string
}
else
{
sq_pushstring(vm, val.mPtr, val.mLen); // Add the whole string
}
// Append the string on the stack to the array
const SQRESULT r = sq_arrayappend(vm, -2);
// Check the result
if (SQ_FAILED(r))
{
return r; // Propagate the error
}
// Specify that we have an argument on the stack
return 1;
}
// Is there anything after the last delimiter?
if (itr != last && *last != delim)
{
++num; // Add it to the counter
}
SQRESULT r = SQ_OK;
// Pre-allocate an array with the number of found delimiters
r = sq_arrayresize(vm, -1, num);
// Check the result
if (SQ_FAILED(r))
{
return r; // Propagate the error
}
// Don't modify the specified string pointer
itr = str, last = str;
// Reset the counter and use it as the element index
num = 0;
// Process the string again, this time slicing the actual elements
while (*itr != '\0')
{
// Is this our delimiter?
if (*itr++ == delim)
{
// Are we allowed to include empty elements?
if (empty || (itr - last) > 1)
{
// Push the element index on the stack and advance to the next one
sq_pushinteger(vm, num++);
// Push the string portion on the stack
sq_pushstring(vm, last, itr - last - 1);
// Assign the string onto the
r = sq_set(vm, -3);
// Check the result
if (SQ_FAILED(r))
{
return r; // Propagate the error
}
}
// Update the last delimiter position
last = itr;
}
}
// Is there anything after the last delimiter?
if (itr != last && *last != delim)
{
// Push the element index on the stack
sq_pushinteger(vm, num);
// Add the remaining string as an element
sq_pushstring(vm, last, itr - last);
// Assign the string onto the
r = sq_set(vm, -3);
// Check the result
if (SQ_FAILED(r))
{
return r; // Propagate the error
}
}
// Specify that we have an argument on the stack
return 1;
}
// ------------------------------------------------------------------------------------------------
static CSStr StrImplode(SQChar chr, Array & arr)
{
// Determine array size
const Int32 length = static_cast< Int32 >(arr.Length());
// Is there anything to implode?
if (length <= 0)
{
return _SC(""); // Default to an empty string
}
// Obtain a temporary buffer
Buffer b(length * 32);
// Process array elements
for (SQInteger i = 0; i < length; ++i)
{
// Retrieve the element value as string
SharedPtr< String > str = arr.GetValue< String >(i);
// Was there any value retrieved?
if (!!str)
{
// Append the value to the buffer
b.AppendS(str->data(), str->size());
}
// Append the delimiter
b.Push(chr);
}
// Move the cursor back one element
b.Retreat(1);
// Set that as the null character
b.Cursor() = '\0';
// Return the string
return b.Get< SQChar >();
}
// ------------------------------------------------------------------------------------------------
static CSStr FromArray(Array & arr)
{
// Determine array size
const Int32 length = ConvTo< Int32 >::From(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(n) = ConvTo< SQChar >::From(b.At< Int32 >(n * sizeof(Int32)));
}
// Terminate the resulted string
b.At(length) = '\0';
// Return the string
return b.Get< SQChar >();
}
// ------------------------------------------------------------------------------------------------
static SQInteger StdPrintF(HSQUIRRELVM vm)
{
// Attempt to retrieve the value from the stack as a string
StackStrF val(vm, 2);
// Have we failed to retrieve the string?
if (SQ_FAILED(val.Proc(true)))
{
return val.mRes; // Propagate the error!
}
// Send the resulted string to console as a user message
LogUsr("%s", val.mPtr);
// This function doesn't return anything
return 0;
}
// ------------------------------------------------------------------------------------------------
static String StrCharacterSwap(SQInteger a, SQInteger b, StackStrF & val)
{
// Have we failed to retrieve the string?
if (SQ_FAILED(val.Proc(true)))
{
STHROWLASTF("Invalid string");
}
// Is the string empty?
else if (!val.mLen)
{
return String();
}
// Turn it into a string that we can edit
String str(val.mPtr, val.mLen);
// Replace all occurences of the specified character
std::replace(str.begin(), str.end(),
static_cast< String::value_type >(a), static_cast< String::value_type >(b));
// Return the new string
return str;
}
// ================================================================================================
void Register_String(HSQUIRRELVM vm)
{
Table strns(vm);
strns.Func(_SC("FromArray"), &FromArray)
.SquirrelFunc(_SC("Explode"), &SqStrExplode)
.Func(_SC("Implode"), &StrImplode)
.FmtFunc(_SC("Center"), &SqCenterStr)
.FmtFunc(_SC("Left"), &SqLeftStr)
.FmtFunc(_SC("Right"), &SqRightStr)
.FmtFunc(_SC("LeftEx"), &SqLeftOffsetStr)
.FmtFunc(_SC("RightEx"), &SqRightOffsetStr)
.FmtFunc(_SC("ToLower"), &SqToLowercase)
.FmtFunc(_SC("ToUpper"), &SqToUppercase)
.FmtFunc(_SC("CharSwap"), &StrCharacterSwap)
.FmtFunc(_SC("Lowercase"), &SqToLowercase)
.FmtFunc(_SC("Uppercase"), &SqToUppercase)
.FmtFunc(_SC("JustAlnum"), &SqJustAlphaNum)
.FmtFunc(_SC("AreAllSpace"), &SqAllChars< std::isspace >)
.FmtFunc(_SC("AreAllPrint"), &SqAllChars< std::isprint >)
.FmtFunc(_SC("AreAllCntrl"), &SqAllChars< std::iscntrl >)
.FmtFunc(_SC("AreAllUpper"), &SqAllChars< std::isupper >)
.FmtFunc(_SC("AreAllLower"), &SqAllChars< std::islower >)
.FmtFunc(_SC("AreAllAlpha"), &SqAllChars< std::isalpha >)
.FmtFunc(_SC("AreAllDigit"), &SqAllChars< std::isdigit >)
.FmtFunc(_SC("AreAllPunct"), &SqAllChars< std::ispunct >)
.FmtFunc(_SC("AreAllXdigit"), &SqAllChars< std::isxdigit >)
.FmtFunc(_SC("AreAllAlnum"), &SqAllChars< std::isalnum >)
.FmtFunc(_SC("AreAllGraph"), &SqAllChars< std::isgraph >)
.FmtFunc(_SC("AreAllBlank"), &SqAllChars< std::isblank >)
.FmtFunc(_SC("FirstSpace"), &SqFirstChar< std::isspace, false >)
.FmtFunc(_SC("FirstPrint"), &SqFirstChar< std::isprint, false >)
.FmtFunc(_SC("FirstCntrl"), &SqFirstChar< std::iscntrl, false >)
.FmtFunc(_SC("FirstUpper"), &SqFirstChar< std::isupper, false >)
.FmtFunc(_SC("FirstLower"), &SqFirstChar< std::islower, false >)
.FmtFunc(_SC("FirstAlpha"), &SqFirstChar< std::isalpha, false >)
.FmtFunc(_SC("FirstDigit"), &SqFirstChar< std::isdigit, false >)
.FmtFunc(_SC("FirstPunct"), &SqFirstChar< std::ispunct, false >)
.FmtFunc(_SC("FirstXdigit"), &SqFirstChar< std::isxdigit, false >)
.FmtFunc(_SC("FirstAlnum"), &SqFirstChar< std::isalnum, false >)
.FmtFunc(_SC("FirstGraph"), &SqFirstChar< std::isgraph, false >)
.FmtFunc(_SC("FirstBlank"), &SqFirstChar< std::isblank, false >)
.FmtFunc(_SC("FirstNotSpace"), &SqFirstChar< std::isspace, true >)
.FmtFunc(_SC("FirstNotPrint"), &SqFirstChar< std::isprint, true >)
.FmtFunc(_SC("FirstNotCntrl"), &SqFirstChar< std::iscntrl, true >)
.FmtFunc(_SC("FirstNotUpper"), &SqFirstChar< std::isupper, true >)
.FmtFunc(_SC("FirstNotLower"), &SqFirstChar< std::islower, true >)
.FmtFunc(_SC("FirstNotAlpha"), &SqFirstChar< std::isalpha, true >)
.FmtFunc(_SC("FirstNotDigit"), &SqFirstChar< std::isdigit, true >)
.FmtFunc(_SC("FirstNotPunct"), &SqFirstChar< std::ispunct, true >)
.FmtFunc(_SC("FirstNotXdigit"), &SqFirstChar< std::isxdigit, true >)
.FmtFunc(_SC("FirstNotAlnum"), &SqFirstChar< std::isalnum, true >)
.FmtFunc(_SC("FirstNotGraph"), &SqFirstChar< std::isgraph, true >)
.FmtFunc(_SC("FirstNotBlank"), &SqFirstChar< std::isblank, true >)
.FmtFunc(_SC("LastSpace"), &SqLastChar< std::isspace, false >)
.FmtFunc(_SC("LastPrint"), &SqLastChar< std::isprint, false >)
.FmtFunc(_SC("LastCntrl"), &SqLastChar< std::iscntrl, false >)
.FmtFunc(_SC("LastUpper"), &SqLastChar< std::isupper, false >)
.FmtFunc(_SC("LastLower"), &SqLastChar< std::islower, false >)
.FmtFunc(_SC("LastAlpha"), &SqLastChar< std::isalpha, false >)
.FmtFunc(_SC("LastDigit"), &SqLastChar< std::isdigit, false >)
.FmtFunc(_SC("LastPunct"), &SqLastChar< std::ispunct, false >)
.FmtFunc(_SC("LastXdigit"), &SqLastChar< std::isxdigit, false >)
.FmtFunc(_SC("LastAlnum"), &SqLastChar< std::isalnum, false >)
.FmtFunc(_SC("LastGraph"), &SqLastChar< std::isgraph, false >)
.FmtFunc(_SC("LastBlank"), &SqLastChar< std::isblank, false >)
.FmtFunc(_SC("LastNotSpace"), &SqLastChar< std::isspace, true >)
.FmtFunc(_SC("LastNotPrint"), &SqLastChar< std::isprint, true >)
.FmtFunc(_SC("LastNotCntrl"), &SqLastChar< std::iscntrl, true >)
.FmtFunc(_SC("LastNotUpper"), &SqLastChar< std::isupper, true >)
.FmtFunc(_SC("LastNotLower"), &SqLastChar< std::islower, true >)
.FmtFunc(_SC("LastNotAlpha"), &SqLastChar< std::isalpha, true >)
.FmtFunc(_SC("LastNotDigit"), &SqLastChar< std::isdigit, true >)
.FmtFunc(_SC("LastNotPunct"), &SqLastChar< std::ispunct, true >)
.FmtFunc(_SC("LastNotXdigit"), &SqLastChar< std::isxdigit, true >)
.FmtFunc(_SC("LastNotAlnum"), &SqLastChar< std::isalnum, true >)
.FmtFunc(_SC("LastNotGraph"), &SqLastChar< std::isgraph, true >)
.FmtFunc(_SC("LastNotBlank"), &SqLastChar< std::isblank, true >)
.SquirrelFunc(_SC("SplitWhereSpace"), &SplitWhereCharProxy< std::isspace, false >)
.SquirrelFunc(_SC("SplitWherePrint"), &SplitWhereCharProxy< std::isprint, false >)
.SquirrelFunc(_SC("SplitWhereCntrl"), &SplitWhereCharProxy< std::iscntrl, false >)
.SquirrelFunc(_SC("SplitWhereUpper"), &SplitWhereCharProxy< std::isupper, false >)
.SquirrelFunc(_SC("SplitWhereLower"), &SplitWhereCharProxy< std::islower, false >)
.SquirrelFunc(_SC("SplitWhereAlpha"), &SplitWhereCharProxy< std::isalpha, false >)
.SquirrelFunc(_SC("SplitWhereDigit"), &SplitWhereCharProxy< std::isdigit, false >)
.SquirrelFunc(_SC("SplitWherePunct"), &SplitWhereCharProxy< std::ispunct, false >)
.SquirrelFunc(_SC("SplitWhereXdigit"), &SplitWhereCharProxy< std::isxdigit, false >)
.SquirrelFunc(_SC("SplitWhereAlnum"), &SplitWhereCharProxy< std::isalnum, false >)
.SquirrelFunc(_SC("SplitWhereGraph"), &SplitWhereCharProxy< std::isgraph, false >)
.SquirrelFunc(_SC("SplitWhereBlank"), &SplitWhereCharProxy< std::isblank, false >)
.SquirrelFunc(_SC("SplitWhereNotSpace"), &SplitWhereCharProxy< std::isspace, true >)
.SquirrelFunc(_SC("SplitWhereNotPrint"), &SplitWhereCharProxy< std::isprint, true >)
.SquirrelFunc(_SC("SplitWhereNotCntrl"), &SplitWhereCharProxy< std::iscntrl, true >)
.SquirrelFunc(_SC("SplitWhereNotUpper"), &SplitWhereCharProxy< std::isupper, true >)
.SquirrelFunc(_SC("SplitWhereNotLower"), &SplitWhereCharProxy< std::islower, true >)
.SquirrelFunc(_SC("SplitWhereNotAlpha"), &SplitWhereCharProxy< std::isalpha, true >)
.SquirrelFunc(_SC("SplitWhereNotDigit"), &SplitWhereCharProxy< std::isdigit, true >)
.SquirrelFunc(_SC("SplitWhereNotPunct"), &SplitWhereCharProxy< std::ispunct, true >)
.SquirrelFunc(_SC("SplitWhereNotXdigit"), &SplitWhereCharProxy< std::isxdigit, true >)
.SquirrelFunc(_SC("SplitWhereNotAlnum"), &SplitWhereCharProxy< std::isalnum, true >)
.SquirrelFunc(_SC("SplitWhereNotGraph"), &SplitWhereCharProxy< std::isgraph, true >)
.SquirrelFunc(_SC("SplitWhereNotBlank"), &SplitWhereCharProxy< std::isblank, true >);
RootTable(vm).Bind(_SC("SqStr"), strns);
RootTable(vm).SquirrelFunc(_SC("printf"), &StdPrintF);
RootTable(vm)
.Func(_SC("IsSpace"), &IsCharOfType< std::isspace >)
.Func(_SC("IsPrint"), &IsCharOfType< std::isprint >)
.Func(_SC("IsCntrl"), &IsCharOfType< std::iscntrl >)
.Func(_SC("IsUpper"), &IsCharOfType< std::isupper >)
.Func(_SC("IsLower"), &IsCharOfType< std::islower >)
.Func(_SC("IsAlpha"), &IsCharOfType< std::isalpha >)
.Func(_SC("IsDigit"), &IsCharOfType< std::isdigit >)
.Func(_SC("IsPunct"), &IsCharOfType< std::ispunct >)
.Func(_SC("IsXdigit"), &IsCharOfType< std::isxdigit >)
.Func(_SC("IsAlnum"), &IsCharOfType< std::isalnum >)
.Func(_SC("IsGraph"), &IsCharOfType< std::isgraph >)
.Func(_SC("IsBlank"), &IsCharOfType< std::isblank >)
.Func(_SC("ToLower"), &tolower)
.Func(_SC("ToUpper"), &toupper);
}
} // Namespace:: SqMod

30
module/Library/String.hpp Normal file
View File

@@ -0,0 +1,30 @@
#ifndef _LIBRARY_STRING_HPP_
#define _LIBRARY_STRING_HPP_
// ------------------------------------------------------------------------------------------------
#include "SqBase.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* Get a new string with only the alpha numeric characters from the specified string.
*/
CSStr StrJustAlphaNum(CSStr str);
Buffer StrJustAlphaNumB(CSStr str);
/* ------------------------------------------------------------------------------------------------
* Convert the specified string to lowercase.
*/
CSStr StrToLowercase(CSStr str);
Buffer StrToLowercaseB(CSStr str);
/* ------------------------------------------------------------------------------------------------
* Convert the specified string to uppercase.
*/
CSStr StrToUppercase(CSStr str);
Buffer StrToUppercaseB(CSStr str);
} // Namespace:: SqMod
#endif // _LIBRARY_STRING_HPP_

109
module/Library/System.cpp Normal file
View File

@@ -0,0 +1,109 @@
// ------------------------------------------------------------------------------------------------
#include "Library/System.hpp"
#include "Base/Shared.hpp"
#include "Base/Buffer.hpp"
// ------------------------------------------------------------------------------------------------
#include <cstdio>
#include <iostream>
#include <memory>
#include <stdexcept>
#include <string>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
extern void Register_SysDir(HSQUIRRELVM vm);
extern void Register_SysEnv(HSQUIRRELVM vm);
extern void Register_SysPath(HSQUIRRELVM vm);
// ------------------------------------------------------------------------------------------------
static SQInteger SqSysExec(HSQUIRRELVM vm)
{
// Attempt to retrieve the value from the stack as a string
StackStrF val(vm, 2);
// Have we failed to retrieve the string?
if (SQ_FAILED(val.Proc(true)))
{
return val.mRes; // Propagate the error!
}
// Allocate a temp buffer to retrieve chunks from output
char buffer[128];
// Allocate a buffer which will contain the final output
Buffer b(128);
// Attempt to open the specified process
FILE * pipe = popen(val.mPtr, "r");
// The process return status
Int32 status = -1;
// Did we fail to open the process?
if (!pipe)
{
return sq_throwerror(vm, ToStrF("Unable to open process [%s]", val.mPtr));
}
// Attempt to read process output
try
{
while (!std::feof(pipe))
{
if (std::fgets(buffer, 128, pipe) != NULL)
{
b.AppendS(buffer);
}
}
}
catch (...)
{
// Close the process
status = pclose(pipe);
// Now throw the error
return sq_throwerror(vm, ToStrF("Unable read process output [%d]", status));
}
// Close the process and obtain the exit status
status = pclose(pipe);
// Remember the top of the stack
const Int32 top = sq_gettop(vm);
// Create a new table on the stack
sq_newtable(vm);
// Push the element name
sq_pushstring(vm, _SC("Status"), -1);
// Push the element value
sq_pushinteger(vm, status);
// Create the element in the table
SQRESULT res = sq_rawset(vm, -3);
// Check the result
if (SQ_FAILED(res))
{
// Clean the stack
sq_settop(vm, top);
// Return the error
return res;
}
// Push the element name
sq_pushstring(vm, _SC("Output"), -1);
// Push the element value
sq_pushstring(vm, b.Get< SQChar >(), b.Position());
// Create the element in the table
res = sq_rawset(vm, -3);
// Check the result
if (SQ_FAILED(res))
{
// Clean the stack
sq_settop(vm, top);
// Return the error
return res;
}
// Specify that we want to return the table we created
return 1;
}
// ================================================================================================
void Register_System(HSQUIRRELVM vm)
{
Register_SysDir(vm);
Register_SysEnv(vm);
Register_SysPath(vm);
RootTable(vm).SquirrelFunc(_SC("SysExec"), &SqSysExec);
}
} // Namespace:: SqMod

14
module/Library/System.hpp Normal file
View File

@@ -0,0 +1,14 @@
#ifndef _LIBRARY_SYSTEM_HPP_
#define _LIBRARY_SYSTEM_HPP_
// ------------------------------------------------------------------------------------------------
#include "Base/Shared.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
} // Namespace:: SqMod
#endif // _LIBRARY_SYSTEM_HPP_

View File

@@ -0,0 +1,126 @@
// ------------------------------------------------------------------------------------------------
#include "Library/System/Dir.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
SQMODE_DECL_TYPENAME(TypenameD, _SC("SqSysDir"))
SQMODE_DECL_TYPENAME(TypenameF, _SC("SqSysFile"))
// ------------------------------------------------------------------------------------------------
LightObj SysDir::ReadFile() const
{
Validate("read current file");
// Create a file instance
std::unique_ptr< SysFile > mem = std::make_unique< SysFile >();
// Turn it into a script object
LightObj obj(mem.get());
// Will hold the raw object pointer
SysFile * ptr = nullptr;
// Release it if it was taken over by the script engine
if (obj.IsNull())
{
STHROWF("Failed to create a SqSysFile object.");
}
else
{
ptr = mem.release();
}
// The file handle where it will be opened
tinydir_file * handle = ptr->GetOrMake();
// Attempt to read the current file
if (tinydir_readfile(mHandle.get(), handle) == -1)
{
STHROWF("Failed to read current file.");
}
// Return the resulted object
return obj;
}
// ------------------------------------------------------------------------------------------------
LightObj SysDir::ReadFileAt(SQInteger i) const
{
Validate("read scanned file");
// Make sure the specified directory index is valid
if (i < 0)
{
STHROWF("File index (" PRINT_INT_FMT " < 0) our of bounds.", i);
}
if (static_cast< size_t >(i) >= mHandle->n_files)
{
STHROWF("File index (" PRINT_INT_FMT " >= " PRINT_SZ_FMT ") our of bounds.", i, mHandle->n_files);
}
// Create a file instance
std::unique_ptr< SysFile > mem = std::make_unique< SysFile >();
// Turn it into a script object
LightObj obj(mem.get());
// Will hold the raw object pointer
SysFile * ptr = nullptr;
// Release it if it was taken over by the script engine
if (obj.IsNull())
{
STHROWF("Failed to create a SqSysFile object.");
}
else
{
ptr = mem.release();
}
// The file handle where it will be opened
tinydir_file * handle = ptr->GetOrMake();
// Attempt to read the current file
if (tinydir_readfile_n(mHandle.get(), handle, i) == -1)
{
STHROWF("Failed to read file at index (" PRINT_INT_FMT ")", i);
}
// Return the resulted object
return obj;
}
// ================================================================================================
void Register_SysDir(HSQUIRRELVM vm)
{
RootTable(vm).Bind(TypenameD::Str,
Class< SysDir, NoCopy< SysDir > >(vm, TypenameD::Str)
// Constructors
.Ctor()
.Ctor< StackStrF & >()
.Ctor< bool, StackStrF & >()
// Meta-methods
.SquirrelFunc(_SC("_typename"), &TypenameD::Fn)
.Func(_SC("_tostring"), &SysDir::ToString)
// Member Properties
.Prop(_SC("IsValid"), &SysDir::IsValid)
.Prop(_SC("Path"), &SysDir::GetPath)
.Prop(_SC("HasNext"), &SysDir::HasNext)
.Prop(_SC("FileCount"), &SysDir::FileCount)
// Member Methods
.FmtFunc(_SC("Open"), &SysDir::Open)
.FmtFunc(_SC("OpenSorted"), &SysDir::OpenSorted)
.Func(_SC("OpenSubDir"), &SysDir::OpenSubDir)
.Func(_SC("Next"), &SysDir::Next)
.Func(_SC("Close"), &SysDir::Close)
.Func(_SC("ReadFile"), &SysDir::ReadFile)
.Func(_SC("ReadFileAt"), &SysDir::ReadFileAt)
);
RootTable(vm).Bind(TypenameF::Str,
Class< SysFile, NoCopy< SysFile > >(vm, TypenameF::Str)
// Constructors
.Ctor()
.Ctor< StackStrF & >()
// Meta-methods
.SquirrelFunc(_SC("_typename"), &TypenameF::Fn)
.Func(_SC("_tostring"), &SysFile::ToString)
// Member Properties
.Prop(_SC("IsValid"), &SysFile::IsValid)
.Prop(_SC("IsDir"), &SysFile::IsDir)
.Prop(_SC("IsReg"), &SysFile::IsReg)
.Prop(_SC("Path"), &SysFile::GetPath)
.Prop(_SC("Name"), &SysFile::GetName)
.Prop(_SC("Extension"), &SysFile::GetExtension)
// Member Methods
.FmtFunc(_SC("Open"), &SysFile::Open)
);
}
} // Namespace:: SqMod

View File

@@ -0,0 +1,587 @@
#ifndef _LIBRARY_SYSDIR_HPP_
#define _LIBRARY_SYSDIR_HPP_
// ------------------------------------------------------------------------------------------------
#include "Base/Shared.hpp"
// ------------------------------------------------------------------------------------------------
#include <memory>
// ------------------------------------------------------------------------------------------------
#include <tinydir.h>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
typedef std::unique_ptr< tinydir_dir > TinyDir;
typedef std::unique_ptr< tinydir_file > TinyFile;
/* ------------------------------------------------------------------------------------------------
* This class represents file-system directories in a platform-independent manner.
*/
class SysDir
{
// --------------------------------------------------------------------------------------------
TinyDir mHandle; /* Handle to the managed directory. */
public:
/* --------------------------------------------------------------------------------------------
* Make sure a valid handle is being managed before attempting to use it.
*/
void Validate() const
{
if (!mHandle)
{
STHROWF("Invalid directory handle. Please open a directory first.");
}
}
/* --------------------------------------------------------------------------------------------
* Make sure a valid handle is being managed before attempting to use it.
*/
void Validate(CSStr action) const
{
if (!mHandle)
{
STHROWF("Cannot %s. Invalid directory handle.", action);
}
}
/* --------------------------------------------------------------------------------------------
* Defaults to a null handle.
*/
SysDir()
: mHandle()
{
/*...*/
}
/* --------------------------------------------------------------------------------------------
* Opens the directory at the specified path.
*/
SysDir(StackStrF & path)
: SysDir(false, path)
{
/*...*/
}
/* --------------------------------------------------------------------------------------------
* Construct from an existing file handle.
*/
explicit SysDir(tinydir_dir * handle)
: mHandle(handle)
{
/*...*/
}
/* --------------------------------------------------------------------------------------------
* Opens the directory at the specified path.
*/
SysDir(bool sorted, StackStrF & path)
: SysDir()
{
// Should we open this in sorted mode?
if (sorted)
{
OpenSorted(path);
}
else
{
Open(path);
}
}
/* --------------------------------------------------------------------------------------------
* Copy constructor (disabled).
*/
SysDir(const SysDir &) = delete;
/* --------------------------------------------------------------------------------------------
* Move constructor.
*/
SysDir(SysDir && o)
: mHandle(std::forward< TinyDir >(o.mHandle))
{
/*...*/
}
/* --------------------------------------------------------------------------------------------
* Destructor.
*/
~SysDir()
{
// Is there handle being managed?
if (mHandle)
{
tinydir_close(mHandle.get()); // Close it!
}
}
/* --------------------------------------------------------------------------------------------
* Copy assignment operator (disabled).
*/
SysDir & operator = (const SysDir &) = delete;
/* --------------------------------------------------------------------------------------------
* Move assignment operator.
*/
SysDir & operator = (SysDir && o)
{
// Avoid self assignment
if (this != &o)
{
// Is there handle being managed?
if (mHandle)
{
tinydir_close(mHandle.get()); // Close it!
}
// Take ownership of the new handle
mHandle = std::move(o.mHandle);
}
return *this;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the raw managed handle.
*/
tinydir_dir * Get() const
{
return mHandle.get();
}
/* --------------------------------------------------------------------------------------------
* Retrieve the raw managed handle and make one if it doesn't exist already.
*/
tinydir_dir * GetOrMake()
{
// Do we have a handle already?
if (!mHandle)
{
mHandle = std::make_unique< tinydir_dir >(); // Make one
}
// Return it like we promised
return mHandle.get();
}
/* --------------------------------------------------------------------------------------------
* Take ownership of the managed handle.
*/
tinydir_dir * Release()
{
return mHandle.release();
}
/* --------------------------------------------------------------------------------------------
* Release the managed handle.
*/
void Reset()
{
mHandle.reset();
}
/* --------------------------------------------------------------------------------------------
* Used by the script engine to convert an instance of this type to a string.
*/
CSStr ToString() const
{
return mHandle ? mHandle->path : _SC("");
}
/* --------------------------------------------------------------------------------------------
* Check for the presence of a handle.
*/
bool IsValid() const
{
return !!mHandle;
}
/* --------------------------------------------------------------------------------------------
* Open a handle to the directory at the specified path.
*/
void Open(StackStrF & path)
{
// Get the string from the script
if ((SQ_FAILED(path.Proc(true))))
{
STHROWF("Unable to extract the specified path.");
}
// Allocate handle memory, if necessary
if (!mHandle)
{
mHandle = std::make_unique< tinydir_dir >();
}
// If there was a handle open, we close it
// If we just allocated one, we initialize it (win, either way)
tinydir_close(mHandle.get());
// Attempt to open the specified directory
if (tinydir_open(mHandle.get(), path.mPtr) == -1)
{
// Don't keep a bad handle
mHandle.reset();
// Now we can throw the exception
STHROWLASTF("Failed to open directory: %s", path.mPtr);
}
}
/* --------------------------------------------------------------------------------------------
* Open a handle to the directory at the specified path.
*/
void OpenSorted(StackStrF & path)
{
// Get the string from the script
if ((SQ_FAILED(path.Proc(true))))
{
STHROWF("Unable to extract the specified path.");
}
// Allocate handle memory, if necessary
if (!mHandle)
{
mHandle = std::make_unique< tinydir_dir >();
}
// If there was a handle open, we close it
// If we just allocated one, we initialize it (win, either way)
tinydir_close(mHandle.get());
// Attempt to open the specified directory
if (tinydir_open_sorted(mHandle.get(), path.mPtr) == -1)
{
// Don't keep a bad handle
mHandle.reset();
// Now we can throw the exception
STHROWLASTF("Failed to open directory: %s", path.mPtr);
}
}
/* --------------------------------------------------------------------------------------------
* Open a handle to the directory at the specified path.
*/
SysDir & OpenSubDir(SQInteger i)
{
Validate("open sub directory");
// Discard current error number
errno = 0;
// Make sure the specified directory index is valid
if (i < 0)
{
STHROWF("Directory index (" PRINT_INT_FMT " < 0) our of bounds.", i);
}
if (static_cast< size_t >(i) >= mHandle->n_files)
{
STHROWF("Directory index (" PRINT_INT_FMT " >= " PRINT_SZ_FMT ") our of bounds.", i, mHandle->n_files);
}
// Make sure there is a directory at the specified index
else if (!mHandle->_files[i].is_dir)
{
STHROWF("The specified index (" PRINT_INT_FMT ") is not a directory.", i);
}
// Attempt to open the specified sub-directory
if (tinydir_open_subdir_n(mHandle.get(), static_cast< size_t >(i)) == -1)
{
// Don't keep a bad handle
mHandle.reset();
// Now we can throw the exception
STHROWLASTF("Failed to open sub directory (" PRINT_INT_FMT ").", i);
}
// Return self to allow chaining
return *this;
}
/* --------------------------------------------------------------------------------------------
* Advance to the next element in the opened directory.
*/
void Next()
{
Validate("advance to next element");
// See if there is a next element
if (!mHandle->has_next)
{
STHROWF("Nothing left to advance to.");
}
// Discard current error number
errno = 0;
// Perform the requested action
if (tinydir_next(mHandle.get()) == -1)
{
// This particular error number means the directory was closed
if (errno == EIO) mHandle.reset();
// Now the exception can be thrown
STHROWLASTF("Failed to advance to the next element");
}
}
/* --------------------------------------------------------------------------------------------
* Close the currently associated directory handle.
*/
void Close()
{
Validate("close directory");
// Perform the requested action
tinydir_close(mHandle.get());
// Release any associated memory
mHandle.reset();
}
/* --------------------------------------------------------------------------------------------
* Retrieve the opened path.
*/
CSStr GetPath() const
{
Validate("obtain path");
// Return the requested information
return mHandle->path;
}
/* --------------------------------------------------------------------------------------------
* See if there's a next element in the opened directory.
*/
bool HasNext() const
{
Validate("check for next");
// Return the requested information
return static_cast< bool >(mHandle->has_next);
}
/* --------------------------------------------------------------------------------------------
* Retrieve the number of files in the opened directory (only when opened in sorted mode).
*/
SQInteger FileCount() const
{
Validate("obtain file count");
// Return the requested information
return static_cast< SQInteger >(mHandle->n_files);
}
/* --------------------------------------------------------------------------------------------
* Open current file from the specified directory.
*/
LightObj ReadFile() const;
/* --------------------------------------------------------------------------------------------
* Open current file from the specified directory.
*/
LightObj ReadFileAt(SQInteger i) const;
};
/* ------------------------------------------------------------------------------------------------
* This class represents file-system files in a platform-independent manner.
*/
class SysFile
{
// --------------------------------------------------------------------------------------------
TinyFile mHandle; /* Handle to the managed file. */
public:
/* --------------------------------------------------------------------------------------------
* Make sure a valid handle is being managed before attempting to use it.
*/
void Validate() const
{
if (!mHandle)
{
STHROWF("Invalid file handle. Please open a file first.");
}
}
/* --------------------------------------------------------------------------------------------
* Make sure a valid handle is being managed before attempting to use it.
*/
void Validate(CSStr action) const
{
if (!mHandle)
{
STHROWF("Cannot %s. Invalid file handle.", action);
}
}
/* --------------------------------------------------------------------------------------------
* Defaults to a null handle.
*/
SysFile()
: mHandle()
{
/*...*/
}
/* --------------------------------------------------------------------------------------------
* Opens the file at the specified path.
*/
SysFile(StackStrF & path)
: SysFile()
{
Open(path);
}
/* --------------------------------------------------------------------------------------------
* Copy constructor (disabled).
*/
SysFile(const SysFile &) = delete;
/* --------------------------------------------------------------------------------------------
* Move constructor.
*/
SysFile(SysFile && o)
: mHandle(std::forward< TinyFile >(o.mHandle))
{
/*...*/
}
/* --------------------------------------------------------------------------------------------
* Copy assignment operator (disabled).
*/
SysFile & operator = (const SysFile &) = delete;
/* --------------------------------------------------------------------------------------------
* Move assignment operator.
*/
SysFile & operator = (SysFile && o)
{
// Avoid self assignment
if (this != &o)
{
// Take ownership of the new handle
mHandle = std::move(o.mHandle);
}
return *this;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the raw managed handle.
*/
tinydir_file * Get() const
{
return mHandle.get();
}
/* --------------------------------------------------------------------------------------------
* Retrieve the raw managed handle and make one if it doesn't exist already.
*/
tinydir_file * GetOrMake()
{
// Do we have a handle already?
if (!mHandle)
{
mHandle = std::make_unique< tinydir_file >(); // Make one
}
// Return it like we promised
return mHandle.get();
}
/* --------------------------------------------------------------------------------------------
* Take ownership of the managed handle.
*/
tinydir_file * Release()
{
return mHandle.release();
}
/* --------------------------------------------------------------------------------------------
* Release the managed handle.
*/
void Reset()
{
mHandle.reset();
}
/* --------------------------------------------------------------------------------------------
* Used by the script engine to convert an instance of this type to a string.
*/
CSStr ToString() const
{
return mHandle ? mHandle->path : _SC("");
}
/* --------------------------------------------------------------------------------------------
* Check for the presence of a handle.
*/
bool IsValid() const
{
return !!mHandle;
}
/* --------------------------------------------------------------------------------------------
* Open a handle to the file at the specified path.
*/
void Open(StackStrF & path)
{
// Get the string from the script
if ((SQ_FAILED(path.Proc(true))))
{
STHROWF("Unable to extract the specified path.");
}
// Allocate the handle memory
mHandle = std::make_unique< tinydir_file >();
// Discard current error number
errno = 0;
// Attempt to open the specified file
if (tinydir_file_open(mHandle.get(), path.mPtr) == -1)
{
// Don't keep a bad handle
mHandle.reset();
// Now we can throw the exception
if (errno != 0)
{
STHROWF("Failed to open file: %s [%s]", path.mPtr, strerror(errno));
}
else
{
STHROWLASTF("Failed to open file: %s", path.mPtr);
}
}
}
/* --------------------------------------------------------------------------------------------
* Check if the opened element is a directory.
*/
bool IsDir() const
{
Validate("check type");
// Return the requested information
return static_cast< bool >(mHandle->is_dir);
}
/* --------------------------------------------------------------------------------------------
* Check if the opened element is a regular file.
*/
bool IsReg() const
{
Validate("check type");
// Return the requested information
return static_cast< bool >(mHandle->is_reg);
}
/* --------------------------------------------------------------------------------------------
* Retrieve the path of the opened file.
*/
CSStr GetPath() const
{
Validate("retrieve path");
// Return the requested information
return mHandle->path;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the name of the opened file.
*/
CSStr GetName() const
{
Validate("retrieve name");
// Return the requested information
return mHandle->name;
}
/* --------------------------------------------------------------------------------------------
* Retrieve the extension of the opened file.
*/
CSStr GetExtension() const
{
Validate("retrieve extension");
// Return the requested information
return mHandle->extension != nullptr ? mHandle->extension : _SC("");
}
};
} // Namespace:: SqMod
#endif // _LIBRARY_SYSDIR_HPP_

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,316 @@
#ifndef _LIBRARY_SYSENV_HPP_
#define _LIBRARY_SYSENV_HPP_
// ------------------------------------------------------------------------------------------------
#include "Base/Shared.hpp"
#include "Base/Buffer.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* This class provides access to environment variables and some general system information.
*/
struct SysEnv
{
/* --------------------------------------------------------------------------------------------
* Default constructor. (disabled)
*/
SysEnv() = delete;
/* --------------------------------------------------------------------------------------------
* Copy constructor. (disabled)
*/
SysEnv(const SysEnv &) = delete;
/* --------------------------------------------------------------------------------------------
* Move constructor. (disabled)
*/
SysEnv(SysEnv &&) = delete;
/* --------------------------------------------------------------------------------------------
* Destructor. (disabled)
*/
~SysEnv() = delete;
/* --------------------------------------------------------------------------------------------
* Copy assignment operator. (disabled)
*/
SysEnv & operator = (const SysEnv &) = delete;
/* --------------------------------------------------------------------------------------------
* Move assignment operator. (disabled)
*/
SysEnv & operator = (SysEnv &&) = delete;
public:
/* --------------------------------------------------------------------------------------------
* Returns true if an environment variable with the given name is defined.
*/
static bool Has(CCStr name);
/* --------------------------------------------------------------------------------------------
* Returns true if an environment variable with the given name is defined.
*/
static bool Has(const String & name);
/* --------------------------------------------------------------------------------------------
* Returns the value of the environment variable with the given name.
* If the environment variable is undefined, returns fallback value instead.
*/
static void Get(Buffer & b, CCStr name, CCStr fallback);
/* --------------------------------------------------------------------------------------------
* Returns the value of the environment variable with the given name.
*/
static Buffer Get(CCStr name)
{
return Get(name, nullptr);
}
/* --------------------------------------------------------------------------------------------
* Returns the value of the environment variable with the given name.
*/
static Buffer Get(const String & name)
{
return Get(name.c_str(), nullptr);
}
/* --------------------------------------------------------------------------------------------
* Returns the value of the environment variable with the given name.
* If the environment variable is undefined, returns fallback value instead.
*/
static Buffer Get(CCStr name, CCStr fallback);
/* --------------------------------------------------------------------------------------------
* Returns the value of the environment variable with the given name.
* If the environment variable is undefined, returns fallback value instead.
*/
static Buffer Get(CCStr name, const String & fallback)
{
return Get(name, fallback.c_str());
}
/* --------------------------------------------------------------------------------------------
* Returns the value of the environment variable with the given name.
* If the environment variable is undefined, returns fallback value instead.
*/
static Buffer Get(const String & name, CCStr fallback)
{
return Get(name.c_str(), fallback);
}
/* --------------------------------------------------------------------------------------------
* Returns the value of the environment variable with the given name.
* If the environment variable is undefined, returns fallback value instead.
*/
static Buffer Get(const String & name, const String & fallback)
{
return Get(name.c_str(), fallback.c_str());
}
/* --------------------------------------------------------------------------------------------
* Sets the environment variable with the given name to the given value.
*/
static bool Set(CCStr name, CCStr value);
/* --------------------------------------------------------------------------------------------
* Sets the environment variable with the given name to the given value.
*/
static bool Set(const String & name, const String & value);
/* --------------------------------------------------------------------------------------------
* Returns the operating system name.
*/
static String OSName();
/* --------------------------------------------------------------------------------------------
* Returns the operating system name in a more "user-friendly" way. This only affects Windows.
*/
static String OSDisplayName();
/* --------------------------------------------------------------------------------------------
* Returns the operating system version.
*/
static String OSVersion();
/* --------------------------------------------------------------------------------------------
* Returns the operating system architecture.
*/
static String OSArchitecture();
/* --------------------------------------------------------------------------------------------
* Returns the node (or host) name.
*/
static String NodeName();
/* --------------------------------------------------------------------------------------------
* Returns the number of processors installed in the system. If the number of processors
* cannot be determined, returns 1.
*/
static Uint32 ProcessorCount();
protected:
/* --------------------------------------------------------------------------------------------
* Make sure that the path in the specified buffer contains a trailing slash.
*/
static void TerminatePath(Buffer & b);
/* --------------------------------------------------------------------------------------------
* Expands all environment variables contained in the string.
*/
static void ExpandVars(Buffer & b, CCStr pos, CCStr end);
/* --------------------------------------------------------------------------------------------
* Expands all environment variables contained in the path. Uses the Unix variable style.
*/
static void ExpandPath(Buffer & b, CCStr pos, CCStr end);
public:
/* --------------------------------------------------------------------------------------------
* Expands all environment variables contained in the string.
*/
static void ExpandVars(Buffer & b, CCStr str);
/* --------------------------------------------------------------------------------------------
* Expands all environment variables contained in the string.
*/
static void ExpandVars(Buffer & b, const String & str);
/* --------------------------------------------------------------------------------------------
* Expands all environment variables contained in the string.
*/
static Buffer ExpandVars(CCStr str);
/* --------------------------------------------------------------------------------------------
* Expands all environment variables contained in the string.
*/
static Buffer ExpandVars(const String & str);
/* --------------------------------------------------------------------------------------------
* Expands all environment variables contained in the path. Uses the Unix variable style.
*/
static void ExpandPath(Buffer & b, CCStr path);
/* --------------------------------------------------------------------------------------------
* Expands all environment variables contained in the path. Uses the Unix variable style.
*/
static void ExpandPath(Buffer & b, const String & path);
/* --------------------------------------------------------------------------------------------
* Expands all environment variables contained in the path. Uses the Unix variable style.
*/
static Buffer ExpandPath(CCStr path);
/* --------------------------------------------------------------------------------------------
* Expands all environment variables contained in the path. Uses the Unix variable style.
*/
static Buffer ExpandPath(const String & path);
/* --------------------------------------------------------------------------------------------
* Obtain the current working directory within the specified buffer.
*/
static void WorkingDir(Buffer & b);
/* --------------------------------------------------------------------------------------------
* Obtain the current working directory within a buffer and return it.
*/
static Buffer WorkingDir();
/* --------------------------------------------------------------------------------------------
* Obtain the user's home directory within the specified buffer.
*/
static void HomeDir(Buffer & b);
/* --------------------------------------------------------------------------------------------
* Obtain the user's home directory within a buffer and return it.
*/
static Buffer HomeDir();
/* --------------------------------------------------------------------------------------------
* Obtain the user's config directory within the specified buffer.
*/
static void ConfigHomeDir(Buffer & b);
/* --------------------------------------------------------------------------------------------
* Obtain the user's config directory within a buffer and return it.
*/
static Buffer ConfigHomeDir();
/* --------------------------------------------------------------------------------------------
* Obtain the user's data directory within the specified buffer.
*/
static void DataHomeDir(Buffer & b);
/* --------------------------------------------------------------------------------------------
* Obtain the user's data directory within a buffer and return it.
*/
static Buffer DataHomeDir();
/* --------------------------------------------------------------------------------------------
* Obtain the user's temporary directory within the specified buffer.
*/
static void TempHomeDir(Buffer & b);
/* --------------------------------------------------------------------------------------------
* Obtain the user's temporary directory within a buffer and return it.
*/
static Buffer TempHomeDir();
/* --------------------------------------------------------------------------------------------
* Obtain the user's cache directory within the specified buffer.
*/
static void CacheHomeDir(Buffer & b);
/* --------------------------------------------------------------------------------------------
* Obtain the user's cache directory within a buffer and return it.
*/
static Buffer CacheHomeDir();
/* --------------------------------------------------------------------------------------------
* Obtain the temporary directory within the specified buffer.
*/
static void TempDir(Buffer & b);
/* --------------------------------------------------------------------------------------------
* Obtain the temporary directory within a buffer and return it.
*/
static Buffer TempDir();
/* --------------------------------------------------------------------------------------------
* Obtain the systemwide config directory within the specified buffer.
*/
static void ConfigDir(Buffer & b);
/* --------------------------------------------------------------------------------------------
* Obtain the systemwide config directory within a buffer and return it.
*/
static Buffer ConfigDir();
/* --------------------------------------------------------------------------------------------
* Obtain the system directory within the specified buffer.
*/
static void SystemDir(Buffer & b);
/* --------------------------------------------------------------------------------------------
* Obtain the system directory within a buffer and return it.
*/
static Buffer SystemDir();
/* --------------------------------------------------------------------------------------------
* Obtain the null directory within the specified buffer.
*/
static void NullDir(Buffer & b);
/* --------------------------------------------------------------------------------------------
* Obtain the null directory within a buffer and return it.
*/
static Buffer NullDir();
};
} // Namespace:: SqMod
#endif // _LIBRARY_SYSENV_HPP_

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,763 @@
#ifndef _LIBRARY_SYSPATH_HPP_
#define _LIBRARY_SYSPATH_HPP_
// ------------------------------------------------------------------------------------------------
#include "Base/Shared.hpp"
// ------------------------------------------------------------------------------------------------
#include <vector>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* Retrieve the full path of file.
*/
Buffer GetRealFilePath(CSStr path);
/* ------------------------------------------------------------------------------------------------
* This class represents filesystem paths in a platform-independent manner.
*/
class SysPath
{
public:
// --------------------------------------------------------------------------------------------
typedef std::vector< String > StrVec; // Directory list.
/* --------------------------------------------------------------------------------------------
* Styles of directories to expect when parsing or to export.
*/
enum struct Style
{
Unix = 0,
Windows,
Native,
Guess,
Dynamic
};
/* --------------------------------------------------------------------------------------------
* Creates an empty relative path.
*/
SysPath();
/* --------------------------------------------------------------------------------------------
* Creates an empty absolute or relative path.
*/
SysPath(bool absolute);
/* --------------------------------------------------------------------------------------------
* Creates a path in native format from a string.
*/
SysPath(CSStr path);
/* --------------------------------------------------------------------------------------------
* Creates a path from a string.
*/
SysPath(CSStr path, Int32 style);
/* --------------------------------------------------------------------------------------------
* Creates a path from a string.
*/
SysPath(CSStr path, Style style);
/* --------------------------------------------------------------------------------------------
* Creates a path in native format from a string.
*/
SysPath(const Buffer & path, Int32 size = -1);
/* --------------------------------------------------------------------------------------------
* Creates a path from a string.
*/
SysPath(const Buffer & path, Style style, Int32 size = -1);
/* --------------------------------------------------------------------------------------------
* Creates a path in native format from a string.
*/
SysPath(const String & path);
/* --------------------------------------------------------------------------------------------
* Creates a path from a string.
*/
SysPath(const String & path, Style style);
/* --------------------------------------------------------------------------------------------
* Creates a path from a parent path and a file name. The parent path is expected to reference
* a directory.
*/
SysPath(const SysPath & parent, CSStr name);
/* --------------------------------------------------------------------------------------------
* Creates a path from a parent path and a file name. The parent path is expected to reference
* a directory.
*/
SysPath(const SysPath & parent, const String & name);
/* --------------------------------------------------------------------------------------------
* Creates a path from a parent path and a relative path. The parent path is expected
* to reference a directory. The relative path is appended to the parent path.
*/
SysPath(const SysPath & parent, const SysPath & relative);
/* --------------------------------------------------------------------------------------------
* Copy constructor.
*/
SysPath(const SysPath & o);
/* --------------------------------------------------------------------------------------------
* Move constructor.
*/
SysPath(SysPath && o);
/* --------------------------------------------------------------------------------------------
* Destructor.
*/
~SysPath();
/* --------------------------------------------------------------------------------------------
* Copy assignment operator.
*/
SysPath & operator = (const SysPath & o);
/* --------------------------------------------------------------------------------------------
* Move assignment operator.
*/
SysPath & operator = (SysPath && o);
/* --------------------------------------------------------------------------------------------
* Assigns a string containing a path in native format.
*/
SysPath & operator = (CSStr path);
/* --------------------------------------------------------------------------------------------
* Assigns a string containing a path in native format.
*/
SysPath & operator = (const String & path);
/* --------------------------------------------------------------------------------------------
* Equality comparison.
*/
bool operator == (const SysPath & o) const;
/* --------------------------------------------------------------------------------------------
* Inequality comparison.
*/
bool operator != (const SysPath & o) const;
/* --------------------------------------------------------------------------------------------
* Implicit conversion to boolean operator.
*/
operator bool () const;
/* --------------------------------------------------------------------------------------------
* Returns the n'th directory in the directory list. If n == depth(), returns the file name.
*/
const String & operator [] (Uint32 n) const;
/* --------------------------------------------------------------------------------------------
* Used by the script engine to compare two instances of this type.
*/
Int32 Cmp(const SysPath & o) const;
/* --------------------------------------------------------------------------------------------
* Used by the script engine to convert an instance of this type to a string.
*/
Object ToString() const;
/* --------------------------------------------------------------------------------------------
* Swaps the path with another one.
*/
void Swap(SysPath & path);
/* --------------------------------------------------------------------------------------------
* Clears all components.
*/
void Clear();
/* --------------------------------------------------------------------------------------------
* Assigns a string containing a path in native format.
*/
SysPath & Assign(CSStr path);
/* --------------------------------------------------------------------------------------------
* Assigns a string containing a path.
*/
SysPath & Assign(CSStr path, Int32 style);
/* --------------------------------------------------------------------------------------------
* Assigns a string containing a path.
*/
SysPath & Assign(CSStr path, Style style);
/* --------------------------------------------------------------------------------------------
* Assigns a string containing a path in native format.
*/
SysPath & Assign(const Buffer & path, Int32 size = -1);
/* --------------------------------------------------------------------------------------------
* Assigns a string containing a path.
*/
SysPath & Assign(const Buffer & path, Style style, Int32 size = -1);
/* --------------------------------------------------------------------------------------------
* Assigns a string containing a path in native format.
*/
SysPath & Assign(const String & path);
/* --------------------------------------------------------------------------------------------
* Assigns a string containing a path.
*/
SysPath & Assign(const String & path, Style style);
/* --------------------------------------------------------------------------------------------
* Creates a path from a parent path and a file name. The parent path is expected to reference
* a directory.
*/
SysPath & Assign(const SysPath & parent, CSStr name);
/* --------------------------------------------------------------------------------------------
* Creates a path from a parent path and a file name. The parent path is expected to reference
* a directory.
*/
SysPath & Assign(const SysPath & parent, const String & name);
/* --------------------------------------------------------------------------------------------
* Creates a path from a parent path and a relative path. The parent path is expected
* to reference a directory. The relative path is appended to the parent path.
*/
SysPath & Assign(const SysPath & parent, const SysPath & relative);
/* --------------------------------------------------------------------------------------------
* Copy the components from another path.
*/
SysPath & Assign(const SysPath & path);
/* --------------------------------------------------------------------------------------------
* Move the components of another path into this instance.
*/
SysPath & Assign(SysPath && path);
/* --------------------------------------------------------------------------------------------
* The resulting path always refers to a directory and the filename part is empty.
*/
SysPath & AssignDir(CSStr path);
/* --------------------------------------------------------------------------------------------
* The resulting path always refers to a directory and the filename part is empty.
*/
SysPath & AssignDir(CSStr path, Int32 style);
/* --------------------------------------------------------------------------------------------
* The resulting path always refers to a directory and the filename part is empty.
*/
SysPath & AssignDir(CSStr path, Style style);
/* --------------------------------------------------------------------------------------------
* The resulting path always refers to a directory and the filename part is empty.
*/
SysPath & AssignDir(const Buffer & path, Int32 size = -1);
/* --------------------------------------------------------------------------------------------
* The resulting path always refers to a directory and the filename part is empty.
*/
SysPath & AssignDir(const Buffer & path, Style style, Int32 size = -1);
/* --------------------------------------------------------------------------------------------
* The resulting path always refers to a directory and the filename part is empty.
*/
SysPath & AssignDir(const String & path);
/* --------------------------------------------------------------------------------------------
* The resulting path always refers to a directory and the filename part is empty.
*/
SysPath & AssignDir(const String & path, Style style);
/* --------------------------------------------------------------------------------------------
* Returns a string containing the path in native format.
*/
Buffer ToBuffer() const;
/* --------------------------------------------------------------------------------------------
* Returns a string containing the path in the given format.
*/
Buffer ToBuffer(Style style) const;
/* --------------------------------------------------------------------------------------------
* Returns a string containing the path in the given format.
*/
Object ToStr(Int32 style) const;
/* --------------------------------------------------------------------------------------------
* Assigns a string containing a path.
*/
void FromString(CSStr path);
/* --------------------------------------------------------------------------------------------
* See whether the path is absolute.
*/
bool IsAbsolute() const
{
return m_Absolute;
}
/* --------------------------------------------------------------------------------------------
* See whether the path is relative.
*/
bool IsRelative() const
{
return !m_Absolute;
}
/* --------------------------------------------------------------------------------------------
* See whether the path references a directory.
*/
bool IsDirectory() const
{
return m_Name.empty();
}
/* --------------------------------------------------------------------------------------------
* See whether the path references a file.
*/
bool IsFile() const
{
return !m_Name.empty();
}
/* --------------------------------------------------------------------------------------------
* See whether the path Does not contain a drive, directories or file name.
*/
bool Empty() const
{
return (m_Dirs.empty() && m_Name.empty() && m_Drive == 0);
}
/* --------------------------------------------------------------------------------------------
* If the path contains a file name, the file name is appended to the directory list and cleared.
*/
SysPath & MakeDirectory();
/* --------------------------------------------------------------------------------------------
* If the path contains no file name, the last directory becomes the file name.
*/
SysPath & MakeFile();
/* --------------------------------------------------------------------------------------------
* Makes the path refer to its parent.
*/
SysPath & MakeParent();
/* --------------------------------------------------------------------------------------------
* Makes the path absolute if it is relative. The current working directory is taken
* as base directory.
*/
SysPath & MakeAbsolute();
/* --------------------------------------------------------------------------------------------
* Makes the path absolute if it is relative. The given path is taken as base.
*/
SysPath & MakeAbsolute(const SysPath & base);
/* --------------------------------------------------------------------------------------------
* Makes the path absolute if it is relative. The given path is taken as base.
*/
SysPath & MakeAbsolute(SysPath && base);
/* --------------------------------------------------------------------------------------------
* Appends the given path.
*/
SysPath & Append(const SysPath & path);
/* --------------------------------------------------------------------------------------------
* Appends the given path.
*/
SysPath & Append(SysPath && path);
/* --------------------------------------------------------------------------------------------
* Parse the given string and append the resulted path.
*/
SysPath & Append(CSStr path);
/* --------------------------------------------------------------------------------------------
* Parse the given string and append the resulted path.
*/
SysPath & Append(CSStr path, Int32 style);
/* --------------------------------------------------------------------------------------------
* Parse the given string and append the resulted path.
*/
SysPath & Append(CSStr path, Style style);
/* --------------------------------------------------------------------------------------------
* Parse the given string and append the resulted path.
*/
SysPath & Append(const Buffer & path, Int32 size = -1);
/* --------------------------------------------------------------------------------------------
* Parse the given string and append the resulted path.
*/
SysPath & Append(const Buffer & path, Style style, Int32 size = -1);
/* --------------------------------------------------------------------------------------------
* Parse the given string and append the resulted path.
*/
SysPath & Append(const String & path);
/* --------------------------------------------------------------------------------------------
* Parse the given string and append the resulted path.
*/
SysPath & Append(const String & path, Style style);
/* --------------------------------------------------------------------------------------------
* Returns the drive letter.
*/
CharT GetDrive() const
{
return m_Drive;
}
/* --------------------------------------------------------------------------------------------
* Modifies the drive letter.
*/
void SetDrive(CharT drive)
{
m_Drive = drive;
}
/* --------------------------------------------------------------------------------------------
* Returns the number of directories in the directory list.
*/
Uint32 Depth() const
{
return m_Dirs.size();
}
/* --------------------------------------------------------------------------------------------
* Returns the n'th directory in the directory list. If n == depth(), returns the file name.
*/
const String & Directory(Uint32 n) const;
/* --------------------------------------------------------------------------------------------
* Adds a directory to the directory list.
*/
SysPath & Push(CSStr dir);
/* --------------------------------------------------------------------------------------------
* Adds a directory to the directory list.
*/
SysPath & Push(const String & dir);
/* --------------------------------------------------------------------------------------------
* Adds a directory to the directory list.
*/
SysPath & Push(String && dir);
/* --------------------------------------------------------------------------------------------
* Removes the last directory from the directory list.
*/
SysPath & PopBack();
/* --------------------------------------------------------------------------------------------
* Removes the first directory from the directory list.
*/
SysPath & PopFront();
/* --------------------------------------------------------------------------------------------
* Set the specified file name.
*/
SysPath & SetFilename(CSStr name);
/* --------------------------------------------------------------------------------------------
* Set the specified file name.
*/
SysPath & SetFilename(const String & name);
/* --------------------------------------------------------------------------------------------
* Set the specified file name.
*/
SysPath & SetFilename(String && name);
/* --------------------------------------------------------------------------------------------
* Retrieves the file name.
*/
const String & GetFilename() const
{
return m_Name;
}
/* --------------------------------------------------------------------------------------------
* Set the specified file name.
*/
void SqSetFilename(CSStr name)
{
SetFilename(name);
}
/* --------------------------------------------------------------------------------------------
* Sets the basename part of the file name and does not change the extension.
*/
SysPath & SetBasename(CSStr name);
/* --------------------------------------------------------------------------------------------
* Sets the basename part of the file name and does not change the extension.
*/
SysPath & SetBasename(const String & name);
/* --------------------------------------------------------------------------------------------
* Sets the basename part of the file name and does not change the extension.
*/
SysPath & SetBasename(String && name);
/* --------------------------------------------------------------------------------------------
* Returns the basename (the file name without extension) of the path.
*/
String GetBasename() const;
/* --------------------------------------------------------------------------------------------
* Sets the basename part of the file name and does not change the extension.
*/
void SqSetBasename(CSStr name)
{
SetBasename(name);
}
/* --------------------------------------------------------------------------------------------
* Sets the file name extension.
*/
SysPath & SetExtension(CSStr ext);
/* --------------------------------------------------------------------------------------------
* Sets the file name extension.
*/
SysPath & SetExtension(const String & ext);
/* --------------------------------------------------------------------------------------------
* Returns the file name extension.
*/
String GetExtension() const;
/* --------------------------------------------------------------------------------------------
* Sets the file name extension.
*/
void SqSetExtension(CSStr ext)
{
SetExtension(ext);
}
/* --------------------------------------------------------------------------------------------
* Returns a pointer to the internal name string where the extension starts.
*/
CSStr GetExtensionC() const;
/* --------------------------------------------------------------------------------------------
* Returns a path referring to the path's directory.
*/
SysPath Parent() const;
/* --------------------------------------------------------------------------------------------
* Resolves the given path against the current one. If the given path is absolute, it replaces
* the current one. Otherwise, the relative path is appended to the current path.
*/
SysPath & Resolve(const SysPath & path);
protected:
/* --------------------------------------------------------------------------------------------
* Parse a path using the unix standards.
*/
void ParseUnix(CSStr pos, CSStr end);
/* --------------------------------------------------------------------------------------------
* Parse a path using the windows standards.
*/
void ParseWindows(CSStr pos, CSStr end);
/* --------------------------------------------------------------------------------------------
* Parse a path and expect combined windows and unix styles.
*/
void ParseDynamic(CSStr pos, CSStr end);
/* --------------------------------------------------------------------------------------------
* Parse a path and try to detect it's type automatically.
*/
void ParseGuess(CSStr pos, CSStr end);
/* --------------------------------------------------------------------------------------------
* Build a path string using the Unix conventions.
*/
Buffer BuildUnix() const;
/* --------------------------------------------------------------------------------------------
* Build a path string using the Windows conventions.
*/
Buffer BuildWindows() const;
private:
// --------------------------------------------------------------------------------------------
StrVec m_Dirs; /* The list of directories that form the path. */
String m_Name; /* The file name if one was specified. */
CharT m_Drive; /* The drive letter if one was specified. */
bool m_Absolute; /* Whether this path is an absolute path. */
public:
/* --------------------------------------------------------------------------------------------
* Returns the platform's path name separator, which separates the components (names) in a path.
*/
static CharT Separator()
{
#ifdef GMOD_OS_WINDOWS
return '\\';
#else
return '/';
#endif // GMOD_OS_WINDOWS
}
/* --------------------------------------------------------------------------------------------
* Returns the platform's path separator, which separates single paths in a list of paths.
*/
static CharT PathSeparator()
{
#ifdef GMOD_OS_WINDOWS
return ';';
#else
return ':';
#endif // GMOD_OS_WINDOWS
}
/* --------------------------------------------------------------------------------------------
* Creates a path referring to a directory.
*/
static SysPath ForDirectory(CSStr path);
/* --------------------------------------------------------------------------------------------
* Creates a path referring to a directory.
*/
static SysPath ForDirectory(CSStr path, Int32 style);
/* --------------------------------------------------------------------------------------------
* Creates a path referring to a directory.
*/
static SysPath ForDirectory(CSStr path, Style style);
/* --------------------------------------------------------------------------------------------
* Creates a path referring to a directory.
*/
static SysPath ForDirectory(const String & path);
/* --------------------------------------------------------------------------------------------
* Creates a path referring to a directory.
*/
static SysPath ForDirectory(const String & path, Style style);
/* --------------------------------------------------------------------------------------------
* Expands all environment variables contained in the path. On Unix, a tilde as first character
* in the path is replaced with the path to user's home directory.
*/
static SysPath Expand(CSStr path);
/* --------------------------------------------------------------------------------------------
* Expands all environment variables contained in the path.
*/
static SysPath Expand(const String & path)
{
return Expand(path.c_str());
}
/* --------------------------------------------------------------------------------------------
* Returns the user's home directory.
*/
static SysPath Home();
/* --------------------------------------------------------------------------------------------
* Returns the user's config directory.
*/
static SysPath ConfigHome();
/* --------------------------------------------------------------------------------------------
* Returns the user's data directory.
*/
static SysPath DataHome();
/* --------------------------------------------------------------------------------------------
* Returns the user's temp directory.
*/
static SysPath TempHome();
/* --------------------------------------------------------------------------------------------
* Returns the user's temp directory.
*/
static SysPath CacheHome();
/* --------------------------------------------------------------------------------------------
* Returns the current working directory.
*/
static SysPath Working();
/* --------------------------------------------------------------------------------------------
* Returns the temporary directory.
*/
static SysPath Temp();
/* --------------------------------------------------------------------------------------------
* Returns the systemwide config directory.
*/
static SysPath Config();
/* --------------------------------------------------------------------------------------------
* Returns the system directory.
*/
static SysPath System();
/* --------------------------------------------------------------------------------------------
* Returns the name of the null device.
*/
static SysPath Null();
/* --------------------------------------------------------------------------------------------
* Returns the real path to the specified file or directory.
*/
static SysPath Real(CSStr path);
/* --------------------------------------------------------------------------------------------
* Creates a path from a parent path and a file name. The parent path is expected to reference
* a directory.
*/
static SysPath With(const SysPath & parent, CSStr name);
/* --------------------------------------------------------------------------------------------
* Creates a path in unix format from a string.
*/
static SysPath MakeUnix(CSStr path);
/* --------------------------------------------------------------------------------------------
* Creates a path in windows format from a string.
*/
static SysPath MakeWindows(CSStr path);
/* --------------------------------------------------------------------------------------------
* Creates a path in native format from a string.
*/
static SysPath MakeNative(CSStr path);
/* --------------------------------------------------------------------------------------------
* Creates a path in and guess the format from a string.
*/
static SysPath MakeGuess(CSStr path);
/* --------------------------------------------------------------------------------------------
* Creates a path in dynamic format from a string.
*/
static SysPath MakeDynamic(CSStr path);
/* --------------------------------------------------------------------------------------------
* Makes sure all separators from a path are the same.
*/
static String NormalizePath(SQInteger s, StackStrF & val);
};
} // Namespace:: SqMod
#endif // _LIBRARY_SYSPATH_HPP_

98
module/Library/Utils.cpp Normal file
View File

@@ -0,0 +1,98 @@
// ------------------------------------------------------------------------------------------------
#include "Library/Utils.hpp"
// ------------------------------------------------------------------------------------------------
#include <cstdio>
#include <cstdlib>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
extern void Register_Buffer(HSQUIRRELVM vm);
/* ------------------------------------------------------------------------------------------------
* Probably not the best implementation but should cover all sorts of weird cases.
*/
static SQInteger SqExtractIPv4(HSQUIRRELVM vm)
{
// Was the IP address specified?
if (sq_gettop(vm) <= 1)
{
return sq_throwerror(vm, "Missing IP address string");
}
// Attempt to generate the string value
StackStrF val(vm, 2);
// Have we failed to retrieve the string?
if (SQ_FAILED(val.Proc(true)))
{
return val.mRes; // Propagate the error!
}
// Cleansed IP address buffer
SQChar address[16] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
// Counting variables used by loops
Uint32 i = 0, j = 0, k = 0;
// Replicate the necessary characters from the resulted string
for (; (i < static_cast< Uint32 >(val.mLen)) && (j < 16) && (k < 4); ++i)
{
// Is this a digit?
if (std::isdigit(val.mPtr[i]) != 0)
{
address[j++] = val.mPtr[i]; // Just replicate it
}
// Is this a delimiter?
else if (val.mPtr[i] == '.')
{
// Add a dummy component if one was not specified
if (j == 0 || address[j-1] == '.')
{
address[j++] = '0';
}
// Add the actual delimiter
address[j++] = '.';
// Increase the block counter
++k;
}
}
// Complete the address if it wasn't (also count the last block)
while (++k < 4)
{
address[j++] = '0';
address[j++] = '.';
}
// Components of the IP address
Uint32 blocks[4] = {0, 0, 0, 0};
// Attempt to extract the components of the IP address
std::sscanf(address, "%u.%u.%u.%u", &blocks[0], &blocks[1], &blocks[2], &blocks[3]);
// Create a new array on the stack to hold the extracted components
sq_newarray(vm, 4);
// Push the elements into the array
for (i = 0; i < 4; ++i)
{
// Push the element index
sq_pushinteger(vm, i);
// Push the element value
sq_pushinteger(vm, Clamp(blocks[i], 0U, 255U));
// Assign the element
const SQRESULT res = sq_set(vm, -3);
// See if the assignment failed
if (SQ_FAILED(res))
{
return res;
}
}
// Specify that we have a result on the stack
return 1;
}
// ================================================================================================
void Register_Utils(HSQUIRRELVM vm)
{
RootTable(vm).Bind(_SC("SqUtils"), Table(vm)
.SquirrelFunc(_SC("ExtractIPv4"), &SqExtractIPv4)
);
Register_Buffer(vm);
}
} // Namespace:: SqMod

14
module/Library/Utils.hpp Normal file
View File

@@ -0,0 +1,14 @@
#ifndef _LIBRARY_UTILS_HPP_
#define _LIBRARY_UTILS_HPP_
// ------------------------------------------------------------------------------------------------
#include "Base/Shared.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
} // Namespace:: SqMod
#endif // _LIBRARY_UTILS_HPP_

View File

@@ -0,0 +1,477 @@
// ------------------------------------------------------------------------------------------------
#include "Library/Utils/Buffer.hpp"
#include "Library/Numeric/LongInt.hpp"
#include "Base/AABB.hpp"
#include "Base/Circle.hpp"
#include "Base/Color3.hpp"
#include "Base/Color4.hpp"
#include "Base/Quaternion.hpp"
#include "Base/Sphere.hpp"
#include "Base/Vector2.hpp"
#include "Base/Vector2i.hpp"
#include "Base/Vector3.hpp"
#include "Base/Vector4.hpp"
// ------------------------------------------------------------------------------------------------
#include <cstring>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
SQMODE_DECL_TYPENAME(Typename, _SC("SqBuffer"))
// ------------------------------------------------------------------------------------------------
void SqBuffer::WriteInt64(const SLongInt & val)
{
// Validate the managed buffer reference
Validate();
// Perform the requested operation
m_Buffer->Push< Int64 >(val.GetNum());
}
// ------------------------------------------------------------------------------------------------
void SqBuffer::WriteUint64(const ULongInt & val)
{
// Validate the managed buffer reference
Validate();
// Perform the requested operation
m_Buffer->Push< Uint64 >(val.GetNum());
}
// ------------------------------------------------------------------------------------------------
void SqBuffer::WriteString(CSStr val)
{
// Validate the managed buffer reference
Validate();
// Is the given string value even valid?
if (!val)
{
STHROWF("Invalid string argument: null");
}
// Calculate the string length
Uint16 length = ConvTo< Uint16 >::From(std::strlen(val));
// Change the size endianness to big endian
Uint16 size = ((length >> 8) & 0xFF) | ((length & 0xFF) << 8);
// Write the size and then the string contents
m_Buffer->Push< Uint16 >(size);
m_Buffer->AppendS(val, length);
}
// ------------------------------------------------------------------------------------------------
void SqBuffer::WriteRawString(CSStr val)
{
// Validate the managed buffer reference
Validate();
// Is the given string value even valid?
if (!val)
{
STHROWF("Invalid string argument: null");
}
// Calculate the string length
Uint16 length = ConvTo< Uint16 >::From(std::strlen(val));
// Write the the string contents
m_Buffer->AppendS(val, length);
}
// ------------------------------------------------------------------------------------------------
void SqBuffer::WriteAABB(const AABB & val)
{
// Validate the managed buffer reference
Validate();
// Perform the requested operation
m_Buffer->Push< AABB >(val);
}
// ------------------------------------------------------------------------------------------------
void SqBuffer::WriteCircle(const Circle & val)
{
// Validate the managed buffer reference
Validate();
// Perform the requested operation
m_Buffer->Push< Circle >(val);
}
// ------------------------------------------------------------------------------------------------
void SqBuffer::WriteColor3(const Color3 & val)
{
// Validate the managed buffer reference
Validate();
// Perform the requested operation
m_Buffer->Push< Color3 >(val);
}
// ------------------------------------------------------------------------------------------------
void SqBuffer::WriteColor4(const Color4 & val)
{
// Validate the managed buffer reference
Validate();
// Perform the requested operation
m_Buffer->Push< Color4 >(val);
}
// ------------------------------------------------------------------------------------------------
void SqBuffer::WriteQuaternion(const Quaternion & val)
{
// Validate the managed buffer reference
Validate();
// Perform the requested operation
m_Buffer->Push< Quaternion >(val);
}
// ------------------------------------------------------------------------------------------------
void SqBuffer::WriteSphere(const Sphere &val)
{
// Validate the managed buffer reference
Validate();
// Perform the requested operation
m_Buffer->Push< Sphere >(val);
}
// ------------------------------------------------------------------------------------------------
void SqBuffer::WriteVector2(const Vector2 & val)
{
// Validate the managed buffer reference
Validate();
// Perform the requested operation
m_Buffer->Push< Vector2 >(val);
}
// ------------------------------------------------------------------------------------------------
void SqBuffer::WriteVector2i(const Vector2i & val)
{
// Validate the managed buffer reference
Validate();
// Perform the requested operation
m_Buffer->Push< Vector2i >(val);
}
// ------------------------------------------------------------------------------------------------
void SqBuffer::WriteVector3(const Vector3 & val)
{
// Validate the managed buffer reference
Validate();
// Perform the requested operation
m_Buffer->Push< Vector3 >(val);
}
// ------------------------------------------------------------------------------------------------
void SqBuffer::WriteVector4(const Vector4 & val)
{
// Validate the managed buffer reference
Validate();
// Perform the requested operation
m_Buffer->Push< Vector4 >(val);
}
// ------------------------------------------------------------------------------------------------
SLongInt SqBuffer::ReadInt64()
{
// Validate the managed buffer reference
ValidateDeeper();
// Read one element from the buffer
const Int64 value = m_Buffer->Cursor< Int64 >();
// Advance the buffer cursor
m_Buffer->Advance< Int64 >(1);
// Return the requested information
return SLongInt(value);
}
// ------------------------------------------------------------------------------------------------
ULongInt SqBuffer::ReadUint64()
{
// Validate the managed buffer reference
ValidateDeeper();
// Read one element from the buffer
const Uint64 value = m_Buffer->Cursor< Uint64 >();
// Advance the buffer cursor
m_Buffer->Advance< Uint64 >(1);
// Return the requested information
return ULongInt(value);
}
// ------------------------------------------------------------------------------------------------
Object SqBuffer::ReadString()
{
// Validate the managed buffer reference
ValidateDeeper();
// Read one element from the buffer
Uint16 length = m_Buffer->Cursor< Uint16 >();
// Convert the length to little endian
length = ((length >> 8) & 0xFF) | ((length & 0xFF) << 8);
// Validate the obtained length
if ((m_Buffer->Position() + sizeof(Uint16) + length) > m_Buffer->Capacity())
{
STHROWF("String of size (%u) starting at (%u) is out of buffer capacity (%u)",
length, m_Buffer->Position() + sizeof(Uint16), m_Buffer->Capacity());
}
// Advance the buffer to the actual string
m_Buffer->Advance< Uint16 >(1);
// Remember the current stack size
const StackGuard sg;
// Attempt to create the string as an object
sq_pushstring(DefaultVM::Get(), &m_Buffer->Cursor(), length);
// Advance the cursor after the string
m_Buffer->Advance(length);
// Return the resulted object
return Var< Object >(DefaultVM::Get(), -1).value;
}
// ------------------------------------------------------------------------------------------------
Object SqBuffer::ReadRawString(SQInteger length)
{
// Validate the managed buffer reference
ValidateDeeper();
// Start with a length of zero
Uint32 len = 0;
// Should we Identify the string length ourselves?
if (length < 0)
{
// Grab the buffer range to search for
CCStr ptr = &m_Buffer->Cursor(), itr = ptr, end = m_Buffer->End();
// Attempt to look for a string terminator
while (itr != end && *itr != '\0')
{
++itr;
}
// If nothing was found, consider the remaining buffer part of the requested string
len = static_cast< Uint32 >(ptr - itr);
}
else
{
len = ConvTo< Uint32 >::From(length);
}
// Validate the obtained length
if ((m_Buffer->Position() + len) > m_Buffer->Capacity())
{
STHROWF("String of size (%u) starting at (%u) is out of buffer capacity (%u)",
len, m_Buffer->Position(), m_Buffer->Capacity());
}
// Remember the current stack size
const StackGuard sg;
// Attempt to create the string as an object
sq_pushstring(DefaultVM::Get(), &m_Buffer->Cursor(), len);
// Advance the cursor after the string
m_Buffer->Advance(len);
// Return the resulted object
return Var< Object >(DefaultVM::Get(), -1).value;
}
// ------------------------------------------------------------------------------------------------
AABB SqBuffer::ReadAABB()
{
// Validate the managed buffer reference
ValidateDeeper();
// Read one element from the buffer
const AABB & value = m_Buffer->Cursor< AABB >();
// Advance the buffer cursor
m_Buffer->Advance< AABB >(1);
// Return the requested information
return AABB(value);
}
// ------------------------------------------------------------------------------------------------
Circle SqBuffer::ReadCircle()
{
// Validate the managed buffer reference
ValidateDeeper();
// Read one element from the buffer
const Circle & value = m_Buffer->Cursor< Circle >();
// Advance the buffer cursor
m_Buffer->Advance< Circle >(1);
// Return the requested information
return Circle(value);
}
// ------------------------------------------------------------------------------------------------
Color3 SqBuffer::ReadColor3()
{
// Validate the managed buffer reference
ValidateDeeper();
// Read one element from the buffer
const Color3 & value = m_Buffer->Cursor< Color3 >();
// Advance the buffer cursor
m_Buffer->Advance< Color3 >(1);
// Return the requested information
return Color3(value);
}
// ------------------------------------------------------------------------------------------------
Color4 SqBuffer::ReadColor4()
{
// Validate the managed buffer reference
ValidateDeeper();
// Read one element from the buffer
const Color4 & value = m_Buffer->Cursor< Color4 >();
// Advance the buffer cursor
m_Buffer->Advance< Color4 >(1);
// Return the requested information
return Color4(value);
}
// ------------------------------------------------------------------------------------------------
Quaternion SqBuffer::ReadQuaternion()
{
// Validate the managed buffer reference
ValidateDeeper();
// Read one element from the buffer
const Quaternion & value = m_Buffer->Cursor< Quaternion >();
// Advance the buffer cursor
m_Buffer->Advance< Quaternion >(1);
// Return the requested information
return Quaternion(value);
}
// ------------------------------------------------------------------------------------------------
Sphere SqBuffer::ReadSphere()
{
// Validate the managed buffer reference
ValidateDeeper();
// Read one element from the buffer
const Sphere & value = m_Buffer->Cursor< Sphere >();
// Advance the buffer cursor
m_Buffer->Advance< Sphere >(1);
// Return the requested information
return Sphere(value);
}
// ------------------------------------------------------------------------------------------------
Vector2 SqBuffer::ReadVector2()
{
// Validate the managed buffer reference
ValidateDeeper();
// Read one element from the buffer
const Vector2 & value = m_Buffer->Cursor< Vector2 >();
// Advance the buffer cursor
m_Buffer->Advance< Vector2 >(1);
// Return the requested information
return Vector2(value);
}
// ------------------------------------------------------------------------------------------------
Vector2i SqBuffer::ReadVector2i()
{
// Validate the managed buffer reference
ValidateDeeper();
// Read one element from the buffer
const Vector2i & value = m_Buffer->Cursor< Vector2i >();
// Advance the buffer cursor
m_Buffer->Advance< Vector2i >(1);
// Return the requested information
return Vector2i(value);
}
// ------------------------------------------------------------------------------------------------
Vector3 SqBuffer::ReadVector3()
{
// Validate the managed buffer reference
ValidateDeeper();
// Read one element from the buffer
const Vector3 & value = m_Buffer->Cursor< Vector3 >();
// Advance the buffer cursor
m_Buffer->Advance< Vector3 >(1);
// Return the requested information
return Vector3(value);
}
// ------------------------------------------------------------------------------------------------
Vector4 SqBuffer::ReadVector4()
{
// Validate the managed buffer reference
ValidateDeeper();
// Read one element from the buffer
const Vector4 & value = m_Buffer->Cursor< Vector4 >();
// Advance the buffer cursor
m_Buffer->Advance< Vector4 >(1);
// Return the requested information
return Vector4(value);
}
// ================================================================================================
void Register_Buffer(HSQUIRRELVM vm)
{
RootTable(vm).Bind(Typename::Str,
Class< SqBuffer >(vm, Typename::Str)
// Constructors
.Ctor()
.Ctor< SQInteger >()
// Core Meta-methods
.SquirrelFunc(_SC("_typename"), &Typename::Fn)
// Properties
.Prop(_SC("Front"), &SqBuffer::GetFront, &SqBuffer::SetFront)
.Prop(_SC("Next"), &SqBuffer::GetNext, &SqBuffer::SetNext)
.Prop(_SC("Back"), &SqBuffer::GetBack, &SqBuffer::SetBack)
.Prop(_SC("Prev"), &SqBuffer::GetPrev, &SqBuffer::SetPrev)
.Prop(_SC("Cursor"), &SqBuffer::GetCursor, &SqBuffer::SetCursor)
.Prop(_SC("Before"), &SqBuffer::GetBefore, &SqBuffer::SetBefore)
.Prop(_SC("After"), &SqBuffer::GetAfter, &SqBuffer::SetAfter)
.Prop(_SC("Max"), &SqBuffer::GetMax)
.Prop(_SC("Size"), &SqBuffer::GetSize, &SqBuffer::Adjust)
.Prop(_SC("Capacity"), &SqBuffer::GetCapacity, &SqBuffer::Adjust)
.Prop(_SC("Position"), &SqBuffer::GetPosition, &SqBuffer::Move)
.Prop(_SC("Remaining"), &SqBuffer::GetRemaining)
// Member Methods
.Func(_SC("Get"), &SqBuffer::Get)
.Func(_SC("Set"), &SqBuffer::Set)
.Func(_SC("Move"), &SqBuffer::Move)
.Func(_SC("Advance"), &SqBuffer::Advance)
.Func(_SC("Retreat"), &SqBuffer::Retreat)
.Func(_SC("Push"), &SqBuffer::Push)
.Func(_SC("Grow"), &SqBuffer::Grow)
.Func(_SC("Adjust"), &SqBuffer::Adjust)
.Func(_SC("WriteByte"), &SqBuffer::WriteUint8)
.Func(_SC("WriteShort"), &SqBuffer::WriteInt16)
.Func(_SC("WriteInt"), &SqBuffer::WriteInt32)
.Func(_SC("WriteFloat"), &SqBuffer::WriteFloat32)
.Func(_SC("WriteInt8"), &SqBuffer::WriteInt8)
.Func(_SC("WriteUint8"), &SqBuffer::WriteUint8)
.Func(_SC("WriteInt16"), &SqBuffer::WriteInt16)
.Func(_SC("WriteUint16"), &SqBuffer::WriteUint16)
.Func(_SC("WriteInt32"), &SqBuffer::WriteInt32)
.Func(_SC("WriteUint32"), &SqBuffer::WriteUint32)
.Func(_SC("WriteInt64"), &SqBuffer::WriteInt64)
.Func(_SC("WriteUint64"), &SqBuffer::WriteUint64)
.Func(_SC("WriteFloat32"), &SqBuffer::WriteFloat32)
.Func(_SC("WriteFloat64"), &SqBuffer::WriteFloat64)
.Func(_SC("WriteString"), &SqBuffer::WriteString)
.Func(_SC("WriteRawString"), &SqBuffer::WriteRawString)
.Func(_SC("WriteAABB"), &SqBuffer::WriteAABB)
.Func(_SC("WriteCircle"), &SqBuffer::WriteCircle)
.Func(_SC("WriteColor3"), &SqBuffer::WriteColor3)
.Func(_SC("WriteColor4"), &SqBuffer::WriteColor4)
.Func(_SC("WriteQuaternion"), &SqBuffer::WriteQuaternion)
.Func(_SC("WriteSphere"), &SqBuffer::WriteSphere)
.Func(_SC("WriteVector2"), &SqBuffer::WriteVector2)
.Func(_SC("WriteVector2i"), &SqBuffer::WriteVector2i)
.Func(_SC("WriteVector3"), &SqBuffer::WriteVector3)
.Func(_SC("WriteVector4"), &SqBuffer::WriteVector4)
.Func(_SC("ReadByte"), &SqBuffer::ReadUint8)
.Func(_SC("ReadShort"), &SqBuffer::ReadInt16)
.Func(_SC("ReadInt"), &SqBuffer::ReadInt32)
.Func(_SC("ReadFloat"), &SqBuffer::ReadFloat32)
.Func(_SC("ReadInt8"), &SqBuffer::ReadInt8)
.Func(_SC("ReadUint8"), &SqBuffer::ReadUint8)
.Func(_SC("ReadInt16"), &SqBuffer::ReadInt16)
.Func(_SC("ReadUint16"), &SqBuffer::ReadUint16)
.Func(_SC("ReadInt32"), &SqBuffer::ReadInt32)
.Func(_SC("ReadUint32"), &SqBuffer::ReadUint32)
.Func(_SC("ReadInt64"), &SqBuffer::ReadInt64)
.Func(_SC("ReadUint64"), &SqBuffer::ReadUint64)
.Func(_SC("ReadFloat32"), &SqBuffer::ReadFloat32)
.Func(_SC("ReadFloat64"), &SqBuffer::ReadFloat64)
.Func(_SC("ReadString"), &SqBuffer::ReadString)
.Func(_SC("ReadRawString"), &SqBuffer::ReadRawString)
.Func(_SC("ReadAABB"), &SqBuffer::ReadAABB)
.Func(_SC("ReadCircle"), &SqBuffer::ReadCircle)
.Func(_SC("ReadColor3"), &SqBuffer::ReadColor3)
.Func(_SC("ReadColor4"), &SqBuffer::ReadColor4)
.Func(_SC("ReadQuaternion"), &SqBuffer::ReadQuaternion)
.Func(_SC("ReadSphere"), &SqBuffer::ReadSphere)
.Func(_SC("ReadVector2"), &SqBuffer::ReadVector2)
.Func(_SC("ReadVector2i"), &SqBuffer::ReadVector2i)
.Func(_SC("ReadVector3"), &SqBuffer::ReadVector3)
.Func(_SC("ReadVector4"), &SqBuffer::ReadVector4)
);
}
} // Namespace:: SqMod

View File

@@ -0,0 +1,837 @@
#ifndef _LIBRARY_UTILS_BUFFER_HPP_
#define _LIBRARY_UTILS_BUFFER_HPP_
// ------------------------------------------------------------------------------------------------
#include "Base/Shared.hpp"
#include "Base/Buffer.hpp"
// ------------------------------------------------------------------------------------------------
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* Squirrel wrapper for the shared buffer class.
*/
class SqBuffer
{
private:
// --------------------------------------------------------------------------------------------
typedef SharedPtr< Buffer > SRef; // Strong reference type to the managed memory buffer.
typedef WeakPtr< Buffer > WRef; // Weak reference type to the managed memory buffer.
// --------------------------------------------------------------------------------------------
SRef m_Buffer; // The managed memory buffer.
public:
// --------------------------------------------------------------------------------------------
typedef Buffer::Value Value; // The type of value used to represent a byte.
// --------------------------------------------------------------------------------------------
typedef Value & Reference; // A reference to the stored value type.
typedef const Value & ConstRef; // A const reference to the stored value type.
// --------------------------------------------------------------------------------------------
typedef Value * Pointer; // A pointer to the stored value type.
typedef const Value * ConstPtr; // A const pointer to the stored value type.
// --------------------------------------------------------------------------------------------
typedef Buffer::SzType SzType; // The type used to represent size in general.
public:
/* --------------------------------------------------------------------------------------------
* Create a memory buffer with the requested size.
*/
static Object Create(SzType n);
/* --------------------------------------------------------------------------------------------
* Default constructor.
*/
SqBuffer()
: m_Buffer(new Buffer())
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Allocate constructor.
*/
SqBuffer(SQInteger n)
: m_Buffer(new Buffer(ConvTo< SzType >::From(n)))
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Allocate constructor.
*/
SqBuffer(SQInteger n, SQInteger c)
: m_Buffer(new Buffer(ConvTo< SzType >::From(n), ConvTo< SzType >::From(c)))
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Copy constructor.
*/
SqBuffer(ConstPtr p, SQInteger n)
: m_Buffer(new Buffer(p, ConvTo< SzType >::From(n)))
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Copy constructor.
*/
SqBuffer(ConstPtr p, SQInteger n, SQInteger c)
: m_Buffer(new Buffer(p, ConvTo< SzType >::From(n), ConvTo< SzType >::From(c)))
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Reference constructor.
*/
SqBuffer(const SRef & ref)
: m_Buffer(ref)
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Buffer constructor.
*/
SqBuffer(const Buffer & b)
: m_Buffer(new Buffer(b))
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Buffer constructor.
*/
SqBuffer(Buffer && b)
: m_Buffer(new Buffer(std::move(b)))
{
/* ... */
}
/* --------------------------------------------------------------------------------------------
* Copy constructor.
*/
SqBuffer(const SqBuffer & o) = default;
/* --------------------------------------------------------------------------------------------
* Move constructor.
*/
SqBuffer(SqBuffer && o) = default;
/* --------------------------------------------------------------------------------------------
* Destructor.
*/
~SqBuffer() = default;
/* --------------------------------------------------------------------------------------------
* Copy assignment operator.
*/
SqBuffer & operator = (const SqBuffer & o) = default;
/* --------------------------------------------------------------------------------------------
* Move assignment operator.
*/
SqBuffer & operator = (SqBuffer && o) = default;
/* --------------------------------------------------------------------------------------------
* Retrieve a reference to the managed memory buffer.
*/
const SRef & GetRef() const
{
return m_Buffer;
}
/* --------------------------------------------------------------------------------------------
* Validate the managed memory buffer reference.
*/
void Validate() const
{
// Do we even point to a valid buffer?
if (!m_Buffer)
{
STHROWF("Invalid memory buffer reference");
}
}
/* --------------------------------------------------------------------------------------------
* Validate the managed memory buffer reference and the buffer itself.
*/
void ValidateDeeper() const
{
// Do we even point to a valid buffer?
if (!m_Buffer)
{
STHROWF("Invalid memory buffer reference");
}
// Validate the buffer itself
else if (!(*m_Buffer))
{
STHROWF("Invalid memory buffer");
}
}
/* --------------------------------------------------------------------------------------------
* Retrieve a certain element type at the specified position.
*/
Value Get(SQInteger n) const
{
// Validate the managed buffer reference
Validate();
// Return the requested element
return m_Buffer->At(ConvTo< SzType >::From(n));
}
/* --------------------------------------------------------------------------------------------
* Modify a certain element type at the specified position.
*/
void Set(SQInteger n, SQInteger v)
{
// Validate the managed buffer reference
Validate();
// Return the requested element
m_Buffer->At(ConvTo< SzType >::From(n)) = ConvTo< Value >::From(v);
}
/* --------------------------------------------------------------------------------------------
* Retrieve the element at the front of the buffer.
*/
Value GetFront() const
{
// Validate the managed buffer reference
Validate();
// Return the requested element
return m_Buffer->Front();
}
/* --------------------------------------------------------------------------------------------
* Modify the element at the front of the buffer.
*/
void SetFront(SQInteger v)
{
// Validate the managed buffer reference
Validate();
// Return the requested element
m_Buffer->Front() = ConvTo< Value >::From(v);
}
/* --------------------------------------------------------------------------------------------
* Retrieve the element after the first element in the buffer.
*/
Value GetNext() const
{
// Validate the managed buffer reference
Validate();
// Return the requested element
return m_Buffer->Next();
}
/* --------------------------------------------------------------------------------------------
* Modify the element after the first element in the buffer.
*/
void SetNext(SQInteger v)
{
// Validate the managed buffer reference
Validate();
// Return the requested element
m_Buffer->Next() = ConvTo< Value >::From(v);
}
/* --------------------------------------------------------------------------------------------
* Retrieve the element at the back of the buffer.
*/
Value GetBack() const
{
// Validate the managed buffer reference
Validate();
// Return the requested element
return m_Buffer->Back();
}
/* --------------------------------------------------------------------------------------------
* Modify the element at the back of the buffer.
*/
void SetBack(SQInteger v)
{
// Validate the managed buffer reference
Validate();
// Return the requested element
m_Buffer->Back() = ConvTo< Value >::From(v);
}
/* --------------------------------------------------------------------------------------------
* Retrieve the element before the last element in the buffer.
*/
Value GetPrev() const
{
// Validate the managed buffer reference
Validate();
// Return the requested element
return m_Buffer->Prev();
}
/* --------------------------------------------------------------------------------------------
* Modify the element before the last element in the buffer.
*/
void SetPrev(SQInteger v)
{
// Validate the managed buffer reference
Validate();
// Return the requested element
m_Buffer->Prev() = ConvTo< Value >::From(v);
}
/* --------------------------------------------------------------------------------------------
* Reposition the edit cursor to the specified number of elements ahead.
*/
void Advance(SQInteger n)
{
// Validate the managed buffer reference
Validate();
// Perform the requested operation
m_Buffer->Advance(ConvTo< SzType >::From(n));
}
/* --------------------------------------------------------------------------------------------
* Reposition the edit cursor to the specified number of elements behind.
*/
void Retreat(SQInteger n)
{
// Validate the managed buffer reference
Validate();
// Perform the requested operation
m_Buffer->Retreat(ConvTo< SzType >::From(n));
}
/* --------------------------------------------------------------------------------------------
* Reposition the edit cursor to a fixed position within the buffer.
*/
void Move(SQInteger n)
{
// Validate the managed buffer reference
Validate();
// Perform the requested operation
m_Buffer->Move(ConvTo< SzType >::From(n));
}
/* --------------------------------------------------------------------------------------------
* Append a value to the current cursor location and advance the cursor.
*/
void Push(SQInteger v)
{
// Validate the managed buffer reference
Validate();
// Perform the requested operation
m_Buffer->Push(ConvTo< Value >::From(v));
}
/* --------------------------------------------------------------------------------------------
* Retrieve the element at the cursor position.
*/
Value GetCursor() const
{
// Validate the managed buffer reference
Validate();
// Return the requested element
return m_Buffer->Cursor();
}
/* --------------------------------------------------------------------------------------------
* Modify the element at the cursor position.
*/
void SetCursor(SQInteger v)
{
// Validate the managed buffer reference
Validate();
// Return the requested element
m_Buffer->Cursor() = ConvTo< Value >::From(v);
}
/* --------------------------------------------------------------------------------------------
* Retrieve the element before the cursor position.
*/
Value GetBefore() const
{
// Validate the managed buffer reference
Validate();
// Return the requested element
return m_Buffer->Before();
}
/* --------------------------------------------------------------------------------------------
* Modify the element before the cursor position.
*/
void SetBefore(SQInteger v)
{
// Validate the managed buffer reference
Validate();
// Return the requested element
m_Buffer->Before() = ConvTo< Value >::From(v);
}
/* --------------------------------------------------------------------------------------------
* Retrieve the element after the cursor position.
*/
Value GetAfter() const
{
// Validate the managed buffer reference
Validate();
// Return the requested element
return m_Buffer->After();
}
/* --------------------------------------------------------------------------------------------
* Modify the element after the cursor position.
*/
void SetAfter(SQInteger v)
{
// Validate the managed buffer reference
Validate();
// Return the requested element
m_Buffer->After() = ConvTo< Value >::From(v);
}
/* --------------------------------------------------------------------------------------------
* Retrieve maximum elements it can hold for a certain type.
*/
SzType GetMax() const
{
return Buffer::Max();
}
/* --------------------------------------------------------------------------------------------
* Retrieve the current buffer capacity in element count.
*/
SzType GetSize() const
{
// Validate the managed buffer reference
Validate();
// Return the requested information
return m_Buffer->CapacityAs< Value >();
}
/* --------------------------------------------------------------------------------------------
* Retrieve the current buffer capacity in byte count.
*/
SzType GetCapacity() const
{
// Validate the managed buffer reference
Validate();
// Return the requested information
return m_Buffer->Capacity();
}
/* --------------------------------------------------------------------------------------------
* Retrieve the current position of the cursor in the buffer.
*/
SzType GetPosition() const
{
// Validate the managed buffer reference
Validate();
// Return the requested information
return m_Buffer->Position();
}
/* --------------------------------------------------------------------------------------------
* Retrieve the amount of unused buffer after the edit cursor.
*/
SzType GetRemaining() const
{
// Validate the managed buffer reference
Validate();
// Return the requested information
return m_Buffer->Remaining();
}
/* --------------------------------------------------------------------------------------------
* Grow the size of the internal buffer by the specified amount of bytes.
*/
void Grow(SQInteger n)
{
// Validate the managed buffer reference
Validate();
// Perform the requested operation
return m_Buffer->Grow(ConvTo< SzType >::From(n) * sizeof(Value));
}
/* --------------------------------------------------------------------------------------------
* Makes sure there is enough capacity to hold the specified element count.
*/
void Adjust(SQInteger n)
{
// Validate the managed buffer reference
Validate();
// Attempt to perform the requested operation
try
{
Buffer bkp(m_Buffer->Adjust(ConvTo< SzType >::From(n) * sizeof(Value)));
// Copy the data into the new buffer
m_Buffer->Write(0, bkp.Data(), bkp.Capacity());
m_Buffer->Move(bkp.Position());
}
catch (const std::exception & e)
{
STHROWF("%s", e.what()); // Re-package
}
}
/* --------------------------------------------------------------------------------------------
* Write a signed 8 bit integer to the buffer.
*/
void WriteInt8(SQInteger val)
{
// Validate the managed buffer reference
Validate();
// Perform the requested operation
m_Buffer->Push< Int8 >(ConvTo< Int8 >::From(val));
}
/* --------------------------------------------------------------------------------------------
* Write an unsigned 8 bit integer to the buffer.
*/
void WriteUint8(SQInteger val)
{
// Validate the managed buffer reference
Validate();
// Perform the requested operation
m_Buffer->Push< Uint8 >(ConvTo< Uint8 >::From(val));
}
/* --------------------------------------------------------------------------------------------
* Write a signed 16 bit integer to the buffer.
*/
void WriteInt16(SQInteger val)
{
// Validate the managed buffer reference
Validate();
// Perform the requested operation
m_Buffer->Push< Int16 >(ConvTo< Int16 >::From(val));
}
/* --------------------------------------------------------------------------------------------
* Write an unsigned 16 bit integer to the buffer.
*/
void WriteUint16(SQInteger val)
{
// Validate the managed buffer reference
Validate();
// Perform the requested operation
m_Buffer->Push< Uint16 >(ConvTo< Uint16 >::From(val));
}
/* --------------------------------------------------------------------------------------------
* Write a signed 32 bit integer to the buffer.
*/
void WriteInt32(SQInteger val)
{
// Validate the managed buffer reference
Validate();
// Perform the requested operation
m_Buffer->Push< Int32 >(ConvTo< Int32 >::From(val));
}
/* --------------------------------------------------------------------------------------------
* Write an unsigned 32 bit integer to the buffer.
*/
void WriteUint32(SQInteger val)
{
// Validate the managed buffer reference
Validate();
// Perform the requested operation
m_Buffer->Push< Uint32 >(ConvTo< Uint32 >::From(val));
}
/* --------------------------------------------------------------------------------------------
* Write a signed 64 bit integer to the buffer.
*/
void WriteInt64(const SLongInt & val);
/* --------------------------------------------------------------------------------------------
* Write an unsigned 64 bit integer to the buffer.
*/
void WriteUint64(const ULongInt & val);
/* --------------------------------------------------------------------------------------------
* Write a 32 bit float to the buffer.
*/
void WriteFloat32(SQFloat val)
{
// Validate the managed buffer reference
Validate();
// Perform the requested operation
m_Buffer->Push< Float32 >(ConvTo< Float32 >::From(val));
}
/* --------------------------------------------------------------------------------------------
* Write a 64 bit float to the buffer.
*/
void WriteFloat64(SQFloat val)
{
// Validate the managed buffer reference
Validate();
// Perform the requested operation
m_Buffer->Push< Float64 >(ConvTo< Float64 >::From(val));
}
/* --------------------------------------------------------------------------------------------
* Write a string to the buffer.
*/
void WriteString(CSStr val);
/* --------------------------------------------------------------------------------------------
* Write a raw string to the buffer.
*/
void WriteRawString(CSStr val);
/* --------------------------------------------------------------------------------------------
* Write a AABB to the buffer.
*/
void WriteAABB(const AABB & val);
/* --------------------------------------------------------------------------------------------
* Write a Circle to the buffer.
*/
void WriteCircle(const Circle & val);
/* --------------------------------------------------------------------------------------------
* Write a Color3 to the buffer.
*/
void WriteColor3(const Color3 & val);
/* --------------------------------------------------------------------------------------------
* Write a Color4 to the buffer.
*/
void WriteColor4(const Color4 & val);
/* --------------------------------------------------------------------------------------------
* Write a Quaternion to the buffer.
*/
void WriteQuaternion(const Quaternion & val);
/* --------------------------------------------------------------------------------------------
* Write a Sphere to the buffer.
*/
void WriteSphere(const Sphere &val);
/* --------------------------------------------------------------------------------------------
* Write a Vector2 to the buffer.
*/
void WriteVector2(const Vector2 & val);
/* --------------------------------------------------------------------------------------------
* Write a Vector2i to the buffer.
*/
void WriteVector2i(const Vector2i & val);
/* --------------------------------------------------------------------------------------------
* Write a Vector3 to the buffer.
*/
void WriteVector3(const Vector3 & val);
/* --------------------------------------------------------------------------------------------
* Write a Vector4 to the buffer.
*/
void WriteVector4(const Vector4 & val);
/* --------------------------------------------------------------------------------------------
* Write a signed 8 bit integer from the buffer.
*/
SQInteger ReadInt8()
{
// Validate the managed buffer reference
ValidateDeeper();
// Read one element from the buffer
const Int8 value = m_Buffer->Cursor< Int8 >();
// Advance the buffer cursor
m_Buffer->Advance< Int8 >(1);
// Return the requested information
return ConvTo< SQInteger >::From(value);
}
/* --------------------------------------------------------------------------------------------
* Read an unsigned 8 bit integer from the buffer.
*/
SQInteger ReadUint8()
{
// Validate the managed buffer reference
ValidateDeeper();
// Read one element from the buffer
const Uint8 value = m_Buffer->Cursor< Uint8 >();
// Advance the buffer cursor
m_Buffer->Advance< Uint8 >(1);
// Return the requested information
return ConvTo< SQInteger >::From(value);
}
/* --------------------------------------------------------------------------------------------
* Read a signed 16 bit integer from the buffer.
*/
SQInteger ReadInt16()
{
// Validate the managed buffer reference
ValidateDeeper();
// Read one element from the buffer
const Int16 value = m_Buffer->Cursor< Int16 >();
// Advance the buffer cursor
m_Buffer->Advance< Int16 >(1);
// Return the requested information
return ConvTo< SQInteger >::From(value);
}
/* --------------------------------------------------------------------------------------------
* Read an unsigned 16 bit integer from the buffer.
*/
SQInteger ReadUint16()
{
// Validate the managed buffer reference
ValidateDeeper();
// Read one element from the buffer
const Uint16 value = m_Buffer->Cursor< Uint16 >();
// Advance the buffer cursor
m_Buffer->Advance< Uint16 >(1);
// Return the requested information
return ConvTo< SQInteger >::From(value);
}
/* --------------------------------------------------------------------------------------------
* Read a signed 32 bit integer from the buffer.
*/
SQInteger ReadInt32()
{
// Validate the managed buffer reference
ValidateDeeper();
// Read one element from the buffer
const Int32 value = m_Buffer->Cursor< Int32 >();
// Advance the buffer cursor
m_Buffer->Advance< Int32 >(1);
// Return the requested information
return ConvTo< SQInteger >::From(value);
}
/* --------------------------------------------------------------------------------------------
* Read an unsigned 32 bit integer from the buffer.
*/
SQInteger ReadUint32()
{
// Validate the managed buffer reference
ValidateDeeper();
// Read one element from the buffer
const Uint32 value = m_Buffer->Cursor< Uint32 >();
// Advance the buffer cursor
m_Buffer->Advance< Uint32 >(1);
// Return the requested information
return ConvTo< SQInteger >::From(value);
}
/* --------------------------------------------------------------------------------------------
* Read a signed 64 bit integer from the buffer.
*/
SLongInt ReadInt64();
/* --------------------------------------------------------------------------------------------
* Read an unsigned 64 bit integer from the buffer.
*/
ULongInt ReadUint64();
/* --------------------------------------------------------------------------------------------
* Read a 32 bit float from the buffer.
*/
SQFloat ReadFloat32()
{
// Validate the managed buffer reference
ValidateDeeper();
// Read one element from the buffer
const Float32 value = m_Buffer->Cursor< Float32 >();
// Advance the buffer cursor
m_Buffer->Advance< Float32 >(1);
// Return the requested information
return ConvTo< SQFloat >::From(value);
}
/* --------------------------------------------------------------------------------------------
* Read a 64 bit float from the buffer.
*/
SQFloat ReadFloat64()
{
// Validate the managed buffer reference
ValidateDeeper();
// Read one element from the buffer
const Float64 value = m_Buffer->Cursor< Float64 >();
// Advance the buffer cursor
m_Buffer->Advance< Float64 >(1);
// Return the requested information
return ConvTo< SQFloat >::From(value);
}
/* --------------------------------------------------------------------------------------------
* Read a string from the buffer.
*/
Object ReadString();
/* --------------------------------------------------------------------------------------------
* Read a raw string from the buffer.
*/
Object ReadRawString(SQInteger length);
/* --------------------------------------------------------------------------------------------
* Read a AABB from the buffer.
*/
AABB ReadAABB();
/* --------------------------------------------------------------------------------------------
* Read a Circle from the buffer.
*/
Circle ReadCircle();
/* --------------------------------------------------------------------------------------------
* Read a Color3 from the buffer.
*/
Color3 ReadColor3();
/* --------------------------------------------------------------------------------------------
* Read a Color4 from the buffer.
*/
Color4 ReadColor4();
/* --------------------------------------------------------------------------------------------
* Read a Quaternion from the buffer.
*/
Quaternion ReadQuaternion();
/* --------------------------------------------------------------------------------------------
* Read a Sphere from the buffer.
*/
Sphere ReadSphere();
/* --------------------------------------------------------------------------------------------
* Read a Vector2 from the buffer.
*/
Vector2 ReadVector2();
/* --------------------------------------------------------------------------------------------
* Read a Vector2i from the buffer.
*/
Vector2i ReadVector2i();
/* --------------------------------------------------------------------------------------------
* Read a Vector3 from the buffer.
*/
Vector3 ReadVector3();
/* --------------------------------------------------------------------------------------------
* Read a Vector4 from the buffer.
*/
Vector4 ReadVector4();
};
} // Namespace:: SqMod
#endif // _LIBRARY_UTILS_BUFFER_HPP_