1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2024-11-08 08:47:17 +01:00

Initial draft for I/O streams.

This commit is contained in:
Sandu Liviu Catalin 2021-03-09 00:18:07 +02:00
parent 0675c05fe7
commit 7d7fd44427
4 changed files with 1231 additions and 0 deletions

View File

@ -68,6 +68,7 @@ add_library(SqModule MODULE SqBase.hpp Main.cpp
Library/IO/Buffer.cpp Library/IO/Buffer.hpp Library/IO/Buffer.cpp Library/IO/Buffer.hpp
Library/IO/File.cpp Library/IO/File.hpp Library/IO/File.cpp Library/IO/File.hpp
Library/IO/INI.cpp Library/IO/INI.hpp Library/IO/INI.cpp Library/IO/INI.hpp
Library/IO/Stream.cpp Library/IO/Stream.hpp
Library/MMDB.cpp Library/MMDB.hpp Library/MMDB.cpp Library/MMDB.hpp
Library/Numeric.cpp Library/Numeric.hpp Library/Numeric.cpp Library/Numeric.hpp
Library/Numeric/Long.cpp Library/Numeric/Long.hpp Library/Numeric/Long.cpp Library/Numeric/Long.hpp

View File

@ -6,12 +6,14 @@ namespace SqMod {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
extern void Register_Buffer(HSQUIRRELVM vm); extern void Register_Buffer(HSQUIRRELVM vm);
extern void Register_Stream(HSQUIRRELVM vm);
extern void Register_INI(HSQUIRRELVM vm); extern void Register_INI(HSQUIRRELVM vm);
// ================================================================================================ // ================================================================================================
void Register_IO(HSQUIRRELVM vm) void Register_IO(HSQUIRRELVM vm)
{ {
Register_Buffer(vm); Register_Buffer(vm);
Register_Stream(vm);
Register_INI(vm); Register_INI(vm);
} }

View File

@ -0,0 +1,346 @@
// ------------------------------------------------------------------------------------------------
#include "Library/IO/Stream.hpp"
// ------------------------------------------------------------------------------------------------
#include <sqratConst.h>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
// ------------------------------------------------------------------------------------------------
SQMOD_DECL_TYPENAME(StringStreamTn, _SC("SqStringStream"))
SQMOD_DECL_TYPENAME(FileStreamTn, _SC("SqFileStream"))
SQMOD_DECL_TYPENAME(OStringStreamTn, _SC("SqOStringStream"))
SQMOD_DECL_TYPENAME(OFileStreamTn, _SC("SqOFileStream"))
SQMOD_DECL_TYPENAME(IStringStreamTn, _SC("SqIStringStream"))
SQMOD_DECL_TYPENAME(IFileStreamTn, _SC("SqIFileStream"))
// ------------------------------------------------------------------------------------------------
SQMOD_DECL_TYPENAME(CInStreamTn, _SC("SqCInStream"))
SQMOD_DECL_TYPENAME(COutStreamTn, _SC("SqCOutStream"))
SQMOD_DECL_TYPENAME(CErrStreamTn, _SC("SqCErrStream"))
SQMOD_DECL_TYPENAME(CLogStreamTn, _SC("SqCLogStream"))
// ------------------------------------------------------------------------------------------------
static LightObj FileToString(StackStrF & name)
{
// Open file
std::ifstream t(name.mPtr);
String str;
// Pre-allocate buffer
t.seekg(0, std::ios::end);
str.reserve(t.tellg());
t.seekg(0, std::ios::beg);
// Read contents
str.assign((std::istreambuf_iterator< SQChar >(t)), std::istreambuf_iterator< SQChar >());
// Transform to object
return LightObj(str.data(), static_cast< SQInteger >(str.size()));
}
// ------------------------------------------------------------------------------------------------
static void StringToFile(StackStrF & name, StackStrF & str)
{
// Open file
std::ofstream out(name.mPtr);
// Write contents
out.write(str.mPtr, static_cast< std::streamsize >(str.mLen));
// Close file
out.close();
}
// ------------------------------------------------------------------------------------------------
using StringStream = SqStream< std::stringstream >;
using FileStream = SqStream< std::fstream >;
using OStringStream = SqStream< std::ostringstream >;
using OFileStream = SqStream< std::ofstream >;
using IStringStream = SqStream< std::istringstream >;
using IFileStream = SqStream< std::ifstream >;
// ------------------------------------------------------------------------------------------------
using CInStream = SqStream< SqGlobalStream< CInTag > >;
using COutStream = SqStream< SqGlobalStream< COutTag > >;
using CErrStream = SqStream< SqGlobalStream< CErrTag > >;
using CLogStream = SqStream< SqGlobalStream< CLogTag > >;
/* ================================================================================================
* Utility used to reduce code duplication when registering streams.
*/
template < class T > struct RegisterStream
{
/* --------------------------------------------------------------------------------------------
* Class object to be registered.
*/
Class< T, NoCopy< T > > mCls;
/* --------------------------------------------------------------------------------------------
* Base constructor.
*/
RegisterStream(HSQUIRRELVM vm, const SQChar * tn)
: mCls(vm, tn)
{
}
/* --------------------------------------------------------------------------------------------
* Base members.
*/
template < class Tn > RegisterStream & Base()
{
mCls
// Core Meta-methods
.SquirrelFunc(_SC("_typename"), &Tn::Fn)
// Properties
.Prop(_SC("Flags"), &T::GetFlags, &T::SetFlags)
.Prop(_SC("Width"), &T::GetWidth, &T::SetWidth)
.Prop(_SC("Precision"), &T::GetPrecision, &T::SetPrecision)
.Prop(_SC("Good"), &T::Good)
.Prop(_SC("EOF"), &T::EOF_)
.Prop(_SC("Fail"), &T::Fail)
.Prop(_SC("Bad"), &T::Bad)
.Prop(_SC("Fill"), &T::GetFill, &T::SetFill)
.Prop(_SC("State"), &T::GetState, &T::SetState)
.Prop(_SC("Exceptions"), &T::GetExceptions, &T::SetExceptions)
// Member Methods
.Func(_SC("UnSetF"), &T::UnSetF)
.Func(_SC("SetWidth"), &T::SetWidth)
.Func(_SC("SetPrecision"), &T::SetPrecision)
.Func(_SC("SetFill"), &T::SetFill)
.Func(_SC("AdjustBuffer"), &T::AdjustBuffer)
.Func(_SC("ReclaimBuffer"), &T::ReclaimBuffer)
// Member Overloads
.Overload(_SC("SetF"), &T::SetF)
.Overload(_SC("SetF"), &T::SetF_)
.Overload(_SC("Clear"), &T::Clear)
.Overload(_SC("Clear"), &T::ClearEx)
;
// Allow chaining
return *this;
}
/* --------------------------------------------------------------------------------------------
* Output members.
*/
RegisterStream & Output()
{
mCls
// Member Methods
.Func(_SC("TellP"), &T::TellP)
.Func(_SC("Put"), &T::Put)
.Func(_SC("Flush"), &T::Flush)
.Func(_SC("Write"), &T::WriteString)
.Func(_SC("WriteBuffer"), &T::WriteBuffer)
// Member Overloads
.Overload(_SC("SeekP"), &T::SeekP)
.Overload(_SC("SeekP"), &T::SeekP_)
;
// Allow chaining
return *this;
}
/* --------------------------------------------------------------------------------------------
* Input members.
*/
RegisterStream & Input()
{
mCls
// Properties
.Prop(_SC("GCount"), &T::GCount)
// Member Methods
.Func(_SC("TellG"), &T::TellG)
.Func(_SC("Peek"), &T::Peek)
.Func(_SC("UnGet"), &T::UnGet)
.Func(_SC("PutBack"), &T::PutBack)
.Func(_SC("Read"), &T::ReadString)
.Func(_SC("ReadBuffer"), &T::ReadBuffer)
.Func(_SC("ReadSome"), &T::ReadSomeString)
.Func(_SC("ReadSomeBuffer"), &T::ReadSomeBuffer)
// Member Overloads
.Overload(_SC("SeekG"), &T::SeekG)
.Overload(_SC("SeekG"), &T::SeekG_)
.Overload(_SC("Get"), &T::GetString0)
.Overload(_SC("Get"), &T::GetString1)
.Overload(_SC("Get"), &T::GetString2)
.Overload(_SC("GetBuffer"), &T::GetBuffer1)
.Overload(_SC("GetBuffer"), &T::GetBuffer2)
.Overload(_SC("GetLine"), &T::GetLineString1)
.Overload(_SC("GetLine"), &T::GetLineString2)
.Overload(_SC("GetLineBuffer"), &T::GetLineBuffer1)
.Overload(_SC("GetLineBuffer"), &T::GetLineBuffer2)
.Overload(_SC("Ignore"), &T::Ignore0)
.Overload(_SC("Ignore"), &T::Ignore1)
.Overload(_SC("Ignore"), &T::Ignore2)
;
// Allow chaining
return *this;
}
/* --------------------------------------------------------------------------------------------
* String type members.
*/
RegisterStream & StringType()
{
mCls
// Constructors
.template Ctor()
.template Ctor< SQInteger >()
// Properties
.Prop(_SC("Str"), &T::GetStr, &T::SetStr)
;
// Allow chaining
return *this;
}
/* --------------------------------------------------------------------------------------------
* File type members.
*/
RegisterStream & FileType()
{
mCls
// Constructors
.template Ctor< StackStrF & >()
.template Ctor< SQInteger, StackStrF & >()
// Properties
.Prop(_SC("IsOpen"), &T::IsOpen)
// Member Methods
.Func(_SC("Close"), &T::Close)
// Member Overloads
.Overload(_SC("Open"), &T::Open)
.Overload(_SC("Open"), &T::Open_)
;
// Allow chaining
return *this;
}
/* --------------------------------------------------------------------------------------------
* Global stream type members.
*/
RegisterStream & GlobalType()
{
mCls
// Constructors
.template Ctor()
;
// Allow chaining
return *this;
}
/* --------------------------------------------------------------------------------------------
* Bind the class object to a table.
*/
void Bind(Table & ns, const SQChar * name)
{
ns.Bind(name, mCls);
}
};
// ================================================================================================
void Register_Stream(HSQUIRRELVM vm)
{
Table sns(vm);
// --------------------------------------------------------------------------------------------
RegisterStream< StringStream >(vm, StringStreamTn::Str)
.Base< StringStreamTn >()
.Output()
.Input()
.StringType()
.Bind(sns, "String");
// --------------------------------------------------------------------------------------------
RegisterStream< FileStream >(vm, FileStreamTn::Str)
.Base< FileStreamTn >()
.Output()
.Input()
.FileType()
.Bind(sns, "File");
// --------------------------------------------------------------------------------------------
RegisterStream< OStringStream >(vm, OStringStreamTn::Str)
.Base< OStringStreamTn >()
.Output()
.StringType()
.Bind(sns, "OutputString");
// --------------------------------------------------------------------------------------------
RegisterStream< OFileStream >(vm, OFileStreamTn::Str)
.Base< OFileStreamTn >()
.Output()
.FileType()
.Bind(sns, "OutputFile");
// --------------------------------------------------------------------------------------------
RegisterStream< IStringStream >(vm, IStringStreamTn::Str)
.Base< IStringStreamTn >()
.Input()
.StringType()
.Bind(sns, "InputString");
// --------------------------------------------------------------------------------------------
RegisterStream< IFileStream >(vm, IFileStreamTn::Str)
.Base< IFileStreamTn >()
.Input()
.FileType()
.Bind(sns, "InputFile");
// --------------------------------------------------------------------------------------------
sns.FmtFunc(_SC("FileToString"), FileToString);
sns.FmtFunc(_SC("StringToFile"), StringToFile);
// --------------------------------------------------------------------------------------------
/* This feature is implemented but not enabled because it's rather pointless */
//RegisterStream< CInStream >(vm, CInStreamTn::Str)
// .Base< CInStreamTn >()
// .Input()
// .GlobalType()
// .Bind(sns, "CIn");
// --------------------------------------------------------------------------------------------
//RegisterStream< COutStream >(vm, COutStreamTn::Str)
// .Base< COutStreamTn >()
// .Output()
// .GlobalType()
// .Bind(sns, "COut");
// --------------------------------------------------------------------------------------------
//RegisterStream< CErrStream >(vm, CErrStreamTn::Str)
// .Base< CErrStreamTn >()
// .Output()
// .GlobalType()
// .Bind(sns, "CErr");
// --------------------------------------------------------------------------------------------
//RegisterStream< CLogStream >(vm, CLogStreamTn::Str)
// .Base< CLogStreamTn >()
// .Output()
// .GlobalType()
// .Bind(sns, "CLog");
// --------------------------------------------------------------------------------------------
RootTable(vm).Bind(_SC("SqStream"), sns);
// --------------------------------------------------------------------------------------------
ConstTable(vm).Enum(_SC("SqIoState"), Enumeration(vm)
.Const(_SC("GoodBit"), SQInteger(std::ios_base::goodbit))
.Const(_SC("BadBit"), SQInteger(std::ios_base::badbit))
.Const(_SC("FailBit"), SQInteger(std::ios_base::failbit))
.Const(_SC("EofBit"), SQInteger(std::ios_base::eofbit))
);
// --------------------------------------------------------------------------------------------
ConstTable(vm).Enum(_SC("SqFmtFlags"), Enumeration(vm)
.Const(_SC("Dec"), SQInteger(std::ios_base::dec))
.Const(_SC("Oct"), SQInteger(std::ios_base::oct))
.Const(_SC("Hex"), SQInteger(std::ios_base::hex))
.Const(_SC("BaseField"), SQInteger(std::ios_base::basefield))
.Const(_SC("Left"), SQInteger(std::ios_base::left))
.Const(_SC("Right"), SQInteger(std::ios_base::right))
.Const(_SC("Internal"), SQInteger(std::ios_base::internal))
.Const(_SC("AdjustField"), SQInteger(std::ios_base::adjustfield))
.Const(_SC("Scientific"), SQInteger(std::ios_base::scientific))
.Const(_SC("Fixed"), SQInteger(std::ios_base::fixed))
.Const(_SC("FloatField"), SQInteger(std::ios_base::floatfield))
.Const(_SC("BoolAlpha"), SQInteger(std::ios_base::boolalpha))
.Const(_SC("ShowBase"), SQInteger(std::ios_base::showbase))
.Const(_SC("ShowPoint"), SQInteger(std::ios_base::showpoint))
.Const(_SC("ShowPos"), SQInteger(std::ios_base::showpos))
.Const(_SC("SkipWS"), SQInteger(std::ios_base::skipws))
.Const(_SC("UnitBuf"), SQInteger(std::ios_base::unitbuf))
.Const(_SC("UpperCase"), SQInteger(std::ios_base::uppercase))
);
// --------------------------------------------------------------------------------------------
ConstTable(vm).Enum(_SC("SqOpenMode"), Enumeration(vm)
.Const(_SC("App"), SQInteger(std::ios_base::app))
.Const(_SC("Ate"), SQInteger(std::ios_base::ate))
.Const(_SC("AtEnd"), SQInteger(std::ios_base::ate))
.Const(_SC("Binary"), SQInteger(std::ios_base::binary))
.Const(_SC("In"), SQInteger(std::ios_base::in))
.Const(_SC("Out"), SQInteger(std::ios_base::out))
.Const(_SC("Trunc"), SQInteger(std::ios_base::trunc))
);
// --------------------------------------------------------------------------------------------
ConstTable(vm).Enum(_SC("SqSeekDir"), Enumeration(vm)
.Const(_SC("Beg"), SQInteger(std::ios_base::beg))
.Const(_SC("Beginning"), SQInteger(std::ios_base::beg))
.Const(_SC("Cur"), SQInteger(std::ios_base::cur))
.Const(_SC("Current"), SQInteger(std::ios_base::cur))
.Const(_SC("End"), SQInteger(std::ios_base::end))
);
}
} // Namespace:: SqMod

View File

@ -0,0 +1,882 @@
#pragma once
// ------------------------------------------------------------------------------------------------
#include "Library/IO/Buffer.hpp"
// ------------------------------------------------------------------------------------------------
#include <ios>
#include <sstream>
#include <fstream>
#include <iostream>
#include <streambuf>
// ------------------------------------------------------------------------------------------------
namespace SqMod {
/* ------------------------------------------------------------------------------------------------
* Implements specialized storage for the specified stream type.
*/
template < class T > struct SqStreamStorage
{
using Type = T;
/* --------------------------------------------------------------------------------------------
* Move constructor (disabled).
*/
SqStreamStorage(SqStreamStorage && o) = delete;
/* --------------------------------------------------------------------------------------------
* Copy constructor (disabled).
*/
SqStreamStorage(const SqStreamStorage & o) = delete;
/* --------------------------------------------------------------------------------------------
* Move assignment operator (disabled).
*/
SqStreamStorage & operator = (SqStreamStorage && o) = delete;
/* --------------------------------------------------------------------------------------------
* Copy assignment operator (disabled).
*/
SqStreamStorage & operator = (const SqStreamStorage & o) = delete;
/* --------------------------------------------------------------------------------------------
* Retrieve a reference to the managed stream.
*/
inline Type & Stream()
{
return m_Stream;
}
/* --------------------------------------------------------------------------------------------
* Retrieve a constant reference to the managed stream.
*/
inline const Type & Stream() const
{
return m_Stream;
}
protected:
/* --------------------------------------------------------------------------------------------
* Wrapped stream object.
*/
Type m_Stream;
/* --------------------------------------------------------------------------------------------
* Base constructor.
*/
template < class... Args > SqStreamStorage(Args &&... args) // NOLINT(google-explicit-constructor)
: m_Stream(std::forward< Args >(args)...)
{
}
};
/* ------------------------------------------------------------------------------------------------
* Stream type disambiguation tags.
*/
struct CInTag {
explicit CInTag() = default;
};
struct COutTag {
explicit COutTag() = default;
};
struct CErrTag {
explicit CErrTag() = default;
};
struct CLogTag {
explicit CLogTag() = default;
};
/* ------------------------------------------------------------------------------------------------
* Helper used to select the appropriate global stream.
*/
template < class > struct SqGlobalStream;
/* ------------------------------------------------------------------------------------------------
* Specialization of SqGlobalStream for std::cin.
*/
template < > struct SqGlobalStream< CInTag >
{
/* --------------------------------------------------------------------------------------------
* Type of stream used internally.
*/
using Type = decltype(std::cin);
/* --------------------------------------------------------------------------------------------
* Retrieve the associated global stream object.
*/
static Type & Get() { return std::cin; }
};
/* ------------------------------------------------------------------------------------------------
* Specialization of SqGlobalStream for std::cout.
*/
template < > struct SqGlobalStream< COutTag >
{
/* --------------------------------------------------------------------------------------------
* Type of stream used internally.
*/
using Type = decltype(std::cout);
/* --------------------------------------------------------------------------------------------
* Retrieve the associated global stream object.
*/
static Type & Get() { return std::cout; }
};
/* ------------------------------------------------------------------------------------------------
* Specialization of SqGlobalStream for std::cerr.
*/
template < > struct SqGlobalStream< CErrTag >
{
/* --------------------------------------------------------------------------------------------
* Type of stream used internally.
*/
using Type = decltype(std::cerr);
/* --------------------------------------------------------------------------------------------
* Retrieve the associated global stream object.
*/
static Type & Get() { return std::cerr; }
};
/* ------------------------------------------------------------------------------------------------
* Specialization of SqGlobalStream for std::clog.
*/
template < > struct SqGlobalStream< CLogTag >
{
/* --------------------------------------------------------------------------------------------
* Type of stream used internally.
*/
using Type = decltype(std::clog);
/* --------------------------------------------------------------------------------------------
* Retrieve the associated global stream object.
*/
static Type & Get() { return std::clog; }
};
/* ------------------------------------------------------------------------------------------------
* Implements specialized storage for stream reference.
*/
template < class T > struct SqStreamStorage< SqGlobalStream< T > >
{
using Type = typename SqGlobalStream< T >::Type;
/* --------------------------------------------------------------------------------------------
* Move constructor (disabled).
*/
SqStreamStorage(SqStreamStorage && o) = delete;
/* --------------------------------------------------------------------------------------------
* Copy constructor (disabled).
*/
SqStreamStorage(const SqStreamStorage & o) = delete;
/* --------------------------------------------------------------------------------------------
* Move assignment operator (disabled).
*/
SqStreamStorage & operator = (SqStreamStorage && o) = delete;
/* --------------------------------------------------------------------------------------------
* Copy assignment operator (disabled).
*/
SqStreamStorage & operator = (const SqStreamStorage & o) = delete;
/* --------------------------------------------------------------------------------------------
* Retrieve a reference to the managed stream.
*/
inline Type & Stream()
{
return m_Stream.get();
}
/* --------------------------------------------------------------------------------------------
* Retrieve a constant reference to the managed stream.
*/
inline const Type & Stream() const
{
return m_Stream.get();
}
protected:
/* --------------------------------------------------------------------------------------------
* Wrapped stream object.
*/
std::reference_wrapper< Type > m_Stream;
/* --------------------------------------------------------------------------------------------
* Base constructor.
*/
SqStreamStorage()
: m_Stream(SqGlobalStream< T >::Get())
{
}
};
/* ------------------------------------------------------------------------------------------------
* Stream-based input/output class.
*/
template < class T > struct SqStream : public SqStreamStorage< T >
{
using SqStreamStorage< T >::Stream;
// --------------------------------------------------------------------------------------------
using Type = SqStreamStorage< T >::Type;
/* --------------------------------------------------------------------------------------------
* Default string constructor.
*/
SqStream()
: SqStreamStorage< T >(), m_Buffer()
{
}
/* --------------------------------------------------------------------------------------------
* Explicit string constructor.
*/
explicit SqStream(SQInteger m)
: SqStreamStorage< T >(static_cast< std::ios_base::openmode >(m)), m_Buffer()
{
}
/* --------------------------------------------------------------------------------------------
* Base file constructor.
*/
explicit SqStream(StackStrF & name)
: SqStreamStorage< T >(name.mPtr), m_Buffer()
{
}
/* --------------------------------------------------------------------------------------------
* Explicit file constructor.
*/
SqStream(SQInteger m, StackStrF & name)
: SqStreamStorage< T >(name.mPtr, static_cast< std::ios_base::openmode >(m)), m_Buffer()
{
}
/* --------------------------------------------------------------------------------------------
* Manually pre-allocate the size of the internal buffer.
*/
void AdjustBuffer(SQInteger len)
{
m_Buffer.Adjust(ClampL< SQInteger, Buffer::SzType >(len));
}
/* --------------------------------------------------------------------------------------------
* Reclaim memory from the memory buffer.
*/
void ReclaimBuffer()
{
m_Buffer.Reset();
}
/* --------------------------------------------------------------------------------------------
* Retrieve current formatting setting.
*/
SQMOD_NODISCARD SQInteger GetFlags() const
{
return static_cast< SQInteger >(Stream().flags());
}
/* --------------------------------------------------------------------------------------------
* Modify current settings with given ones.
*/
void SetFlags(SQInteger f)
{
Stream().flags(static_cast< std::ios_base::fmtflags >(f));
}
/* --------------------------------------------------------------------------------------------
* Retrieve current field width.
*/
SQMOD_NODISCARD SQInteger GetWidth() const
{
return static_cast< SQInteger >(Stream().width());
}
/* --------------------------------------------------------------------------------------------
* Modify the field width to the given one. Returns the previous field width.
*/
SQInteger SetWidth(SQInteger w)
{
return static_cast< SQInteger >(Stream().width(static_cast< std::streamsize >(w)));
}
/* --------------------------------------------------------------------------------------------
* Retrieve current precision.
*/
SQMOD_NODISCARD SQInteger GetPrecision() const
{
return static_cast< SQInteger >(Stream().precision());
}
/* --------------------------------------------------------------------------------------------
* Modify the precision to the given one. Returns the previous precision.
*/
SQInteger SetPrecision(SQInteger p)
{
return static_cast< SQInteger >(Stream().precision(static_cast< std::streamsize >(p)));
}
/* --------------------------------------------------------------------------------------------
* Sets the formatting flags identified by `f`.
*/
SqStream & SetF(SQInteger f)
{
Stream().setf(static_cast< std::ios_base::fmtflags >(f));
return *this; // Allow chaining
}
/* --------------------------------------------------------------------------------------------
* Clears the formatting flags under `m`, and sets the cleared flags to those specified by `f`.
*/
SqStream & SetF_(SQInteger f, SQInteger m)
{
Stream().setf(static_cast< std::ios_base::fmtflags >(f), static_cast< std::ios_base::fmtflags >(m));
return *this; // Allow chaining
}
/* --------------------------------------------------------------------------------------------
* Unsets the formatting flags identified by `f`.
*/
SqStream & UnSetF(SQInteger f)
{
Stream().unsetf(static_cast< std::ios_base::fmtflags >(f));
return *this; // Allow chaining
}
/* --------------------------------------------------------------------------------------------
* Returns true if the most recent I/O operation on the stream completed successfully, false otherwise.
*/
SQMOD_NODISCARD bool Good() const
{
return Stream().good();
}
/* --------------------------------------------------------------------------------------------
* Returns true if the associated stream has reached end-of-file, false otherwise.
*/
SQMOD_NODISCARD bool EOF_() const
{
return Stream().eof();
}
/* --------------------------------------------------------------------------------------------
* Returns true if an error has occurred on the associated stream, false otherwise.
*/
SQMOD_NODISCARD bool Fail() const
{
return Stream().fail();
}
/* --------------------------------------------------------------------------------------------
* Returns true if non-recoverable error has occurred on the associated stream.
*/
SQMOD_NODISCARD bool Bad() const
{
return Stream().bad();
}
/* --------------------------------------------------------------------------------------------
* Retrieve the current fill character.
*/
SQMOD_NODISCARD SQChar GetFill() const
{
return Stream().fill();
}
/* --------------------------------------------------------------------------------------------
* Modify the fill character to `c`, returns previous value of the fill character.
*/
SQChar SetFill(SQChar c)
{
return Stream().fill(c);
}
/* --------------------------------------------------------------------------------------------
* Retrieve the current stream error state.
*/
SQMOD_NODISCARD SQInteger GetState() const
{
return static_cast< SQInteger >(Stream().rdstate());
}
/* --------------------------------------------------------------------------------------------
* Modify the stream error flags state in addition to currently set flags.
*/
void SetState(SQInteger f)
{
return Stream().setstate(static_cast< std::ios_base::iostate >(f));
}
/* --------------------------------------------------------------------------------------------
* Retrieve the exception mask.
*/
SQMOD_NODISCARD SQInteger GetExceptions() const
{
return static_cast< SQInteger >(Stream().exceptions());
}
/* --------------------------------------------------------------------------------------------
* Modify the exception mask to except.
*/
void SetExceptions(SQInteger f)
{
Stream().exceptions(static_cast< std::ios_base::iostate >(f));
}
/* --------------------------------------------------------------------------------------------
* Sets the stream error state flags by assigning them the value of `SqIoState.GoodBit`.
*/
SqStream & Clear()
{
Stream().clear();
return *this; // Allow chaining
}
/* --------------------------------------------------------------------------------------------
* Sets the stream error state flags by assigning them the value of `f`.
*/
SqStream & ClearEx(SQInteger f)
{
Stream().clear(static_cast< std::ios_base::iostate >(f));
return *this; // Allow chaining
}
/* --------------------------------------------------------------------------------------------
* Retrieve the output position indicator of the current associated `streambuf` object.
*/
SQMOD_NODISCARD SQInteger TellP()
{
return static_cast< SQInteger >(Stream().tellp());
}
/* --------------------------------------------------------------------------------------------
* Modify the output position indicator of the current associated `streambuf` object.
* Sets the output position indicator to absolute (relative to the beginning of the file) value `p`.
*/
SqStream & SeekP(SQInteger p)
{
Stream().seekp(static_cast< typename Type::pos_type >(p));
return *this; // Allow chaining
}
/* --------------------------------------------------------------------------------------------
* Modify the output position indicator of the current associated `streambuf` object.
* Sets the output position indicator to position `o`, relative to position, defined by `d`.
*/
SqStream & SeekP_(SQInteger o, SQInteger d)
{
Stream().seekp(static_cast< typename Type::off_type >(o), static_cast< typename std::ios_base::seekdir >(d));
return *this; // Allow chaining
}
/* --------------------------------------------------------------------------------------------
* Retrieve input position indicator of the current associated `streambuf` object.
*/
SQMOD_NODISCARD SQInteger TellG()
{
return static_cast< SQInteger >(Stream().tellg());
}
/* --------------------------------------------------------------------------------------------
* Modify input position indicator of the current associated `streambuf` object.
* Sets the input position indicator to absolute (relative to the beginning of the file) value `p`.
*/
SqStream & SeekG(SQInteger p)
{
Stream().seekg(static_cast< typename Type::pos_type >(p));
return *this; // Allow chaining
}
/* --------------------------------------------------------------------------------------------
* Modify input position indicator of the current associated `streambuf` object.
* Sets the input position indicator to position `o`, relative to position, defined by `d`.
*/
SqStream & SeekG_(SQInteger o, SQInteger d)
{
Stream().seekg(static_cast< typename Type::off_type >(o), static_cast< typename std::ios_base::seekdir >(d));
return *this; // Allow chaining
}
/* --------------------------------------------------------------------------------------------
* Write the character `c` to the output stream.
*/
SqStream & Put(SQInteger c)
{
Stream().put(static_cast< typename Type::char_type >(c));
return *this; // Allow chaining
}
/* --------------------------------------------------------------------------------------------
* Write a string to the output stream.
*/
SqStream & WriteString(StackStrF & str)
{
Stream().write(str.mPtr, static_cast< std::streamsize >(str.mLen));
return *this; // Allow chaining
}
/* --------------------------------------------------------------------------------------------
* Write a buffer to the output stream.
*/
SqStream & WriteBuffer(SqBuffer & buf)
{
Stream().write(buf.GetInst().Data(), static_cast< std::streamsize >(buf.GetInst().Position()));
return *this; // Allow chaining
}
/* --------------------------------------------------------------------------------------------
* Write uncommitted changes to the underlying output sequence.
*/
SqStream & Flush()
{
Stream().flush();
return *this; // Allow chaining
}
/* --------------------------------------------------------------------------------------------
* Reads at most num-1 characters and returns them as character string, until `delim` is found.
*/
SQMOD_NODISCARD std::streamsize Get(SQInteger num, SQChar delim)
{
// Prevent negative lengths
if (num < 0)
{
STHROWF("Invalid length: {} < 0", num);
}
// Prevent overflow of Buffer::SzType
else
{
num = static_cast< SQInteger >(ClampL< SQInteger, Buffer::SzType >(num));
}
// Allocate a sufficiently large memory buffer
m_Buffer.Adjust(static_cast< Buffer::SzType >(num));
// Read data from the stream
Stream().get(m_Buffer.Get(), static_cast< std::streamsize >(num), static_cast< typename Type::char_type >(delim));
// Return the number of characters read
return Stream().gcount();
}
/* --------------------------------------------------------------------------------------------
* Read one character and return it if available.
*/
SQMOD_NODISCARD SQInteger GetString0()
{
return static_cast< SQInteger >(Stream().get());
}
/* --------------------------------------------------------------------------------------------
* Reads at most num-1 characters and returns them as character string, until '\n' is found.
*/
SQMOD_NODISCARD LightObj GetString1(SQInteger num)
{
const std::streamsize len = Get(num, Stream().widen('\n'));
// Create a string object and return it
return LightObj(m_Buffer.Get(), static_cast< SQInteger >(len));
}
/* --------------------------------------------------------------------------------------------
* Reads at most num-1 characters and returns them as character string, until `delim` is found.
*/
SQMOD_NODISCARD LightObj GetString2(SQInteger num, SQChar delim)
{
const std::streamsize len = Get(num, delim);
// Create a string object and return it
return LightObj(m_Buffer.Get(), static_cast< SQInteger >(len));
}
/* --------------------------------------------------------------------------------------------
* Reads at most num-1 characters and returns them as character string, until '\n' is found.
*/
SQMOD_NODISCARD LightObj GetBuffer1(SQInteger num)
{
const std::streamsize len = Get(num, Stream().widen('\n'));
// Create a buffer object and return it
return LightObj(SqTypeIdentity< SqBuffer >{}, SqVM(), m_Buffer.Get(), static_cast< Buffer::SzType >(len));
}
/* --------------------------------------------------------------------------------------------
* Reads at most num-1 characters and returns them as character string, until `delim` is found.
*/
SQMOD_NODISCARD LightObj GetBuffer2(SQInteger num, SQChar delim)
{
const std::streamsize len = Get(num, delim);
// Create a buffer object and return it
return LightObj(SqTypeIdentity< SqBuffer >{}, SqVM(), m_Buffer.Get(), static_cast< Buffer::SzType >(len));
}
/* --------------------------------------------------------------------------------------------
* Read the next character from the input stream without extracting it.
*/
SQMOD_NODISCARD SQInteger Peek()
{
return static_cast< SQInteger >(Stream().peek());
}
/* --------------------------------------------------------------------------------------------
* Makes the most recently extracted character available again.
*/
SqStream & UnGet()
{
Stream().unget();
return *this; // Allow chaining
}
/* --------------------------------------------------------------------------------------------
* Puts the character `c` back to the input stream so the next extracted character will be `c`.
*/
SqStream & PutBack(SQInteger c)
{
Stream().putback(static_cast< typename Type::char_type >(c));
return *this; // Allow chaining
}
/* --------------------------------------------------------------------------------------------
* Extracts characters from stream until end of line or the specified delimiter `delim`.
*/
SQMOD_NODISCARD std::streamsize GetLine(SQInteger num, SQChar delim)
{
// Prevent negative lengths
if (num < 0)
{
STHROWF("Invalid length: {} < 0", num);
}
// Prevent overflow of Buffer::SzType
else
{
num = static_cast< SQInteger >(ClampL< SQInteger, Buffer::SzType >(num));
}
// Allocate a sufficiently large memory buffer
m_Buffer.Adjust(static_cast< Buffer::SzType >(num));
// Read data from the stream
Stream().getline(m_Buffer.Get(), static_cast< std::streamsize >(num), static_cast< typename Type::char_type >(delim));
// What actually stopped the reading?
if (Stream().rdstate() & (std::ios_base::eofbit | std::ios_base::failbit))
{
// Either end of file or end of count stopped the reading
return Stream().gcount();
}
else
{
// The delimiter stopped the reading but is only counted towards
// the number of elements. Not actually read and stored in the buffer
return Stream().gcount() > 0 ? (Stream().gcount() - 1) : std::streamsize(0);
}
}
/* --------------------------------------------------------------------------------------------
* Extracts characters from stream until end of line or the specified delimiter '\n'.
*/
SQMOD_NODISCARD LightObj GetLineString1(SQInteger num)
{
const std::streamsize len = GetLine(num, Stream().widen('\n'));
// Create a string object and return it
return LightObj(m_Buffer.Get(), static_cast< SQInteger >(len));
}
/* --------------------------------------------------------------------------------------------
* Extracts characters from stream until end of line or the specified delimiter `delim`.
*/
SQMOD_NODISCARD LightObj GetLineString2(SQInteger num, SQChar delim)
{
const std::streamsize len = GetLine(num, delim);
// Create a string object and return it
return LightObj(m_Buffer.Get(), static_cast< SQInteger >(len));
}
/* --------------------------------------------------------------------------------------------
* Extracts characters from stream until end of line or the specified delimiter '\n'.
*/
SQMOD_NODISCARD LightObj GetLineBuffer1(SQInteger num)
{
const std::streamsize len = GetLine(num, Stream().widen('\n'));
// Create a buffer object and return it
return LightObj(SqTypeIdentity< SqBuffer >{}, SqVM(), m_Buffer.Get(), static_cast< Buffer::SzType >(len));
}
/* --------------------------------------------------------------------------------------------
* Extracts characters from stream until end of line or the specified delimiter `delim`.
*/
SQMOD_NODISCARD LightObj GetLineBuffer2(SQInteger num, SQChar delim)
{
const std::streamsize len = GetLine(num, delim);
// Create a buffer object and return it
return LightObj(SqTypeIdentity< SqBuffer >{}, SqVM(), m_Buffer.Get(), static_cast< Buffer::SzType >(len));
}
/* --------------------------------------------------------------------------------------------
* Extracts and discards one character from the input stream until end of file.
*/
SqStream & Ignore0()
{
Stream().ignore();
return *this; // Allow chaining
}
/* --------------------------------------------------------------------------------------------
* Extracts and discards `num` characters from the input stream until end of file.
*/
SqStream & Ignore1(SQInteger num)
{
Stream().ignore(static_cast< std::streamsize >(num));
return *this; // Allow chaining
}
/* --------------------------------------------------------------------------------------------
* Extracts and discards characters from the input stream until and including `delim`.
*/
SqStream & Ignore2(SQInteger num, SQChar delim)
{
Stream().ignore(static_cast< std::streamsize >(num), static_cast< typename Type::char_type >(delim));
return *this; // Allow chaining
}
/* --------------------------------------------------------------------------------------------
* Extracts characters from stream.
*/
SQMOD_NODISCARD std::streamsize Read(SQInteger num)
{
// Prevent negative lengths
if (num < 0)
{
STHROWF("Invalid length: {} < 0", num);
}
// Prevent overflow of Buffer::SzType
else
{
num = static_cast< SQInteger >(ClampL< SQInteger, Buffer::SzType >(num));
}
// Allocate a sufficiently large memory buffer
m_Buffer.Adjust(static_cast< Buffer::SzType >(num));
// Read data from the stream
Stream().read(m_Buffer.Get(), static_cast< std::streamsize >(num));
// Return the number of characters read
return Stream().gcount();
}
/* --------------------------------------------------------------------------------------------
* Extracts characters from stream.
*/
SQMOD_NODISCARD LightObj ReadString(SQInteger num)
{
const std::streamsize len = Read(num);
// Create a string object and return it
return LightObj(m_Buffer.Get(), static_cast< SQInteger >(len));
}
/* --------------------------------------------------------------------------------------------
* Extracts characters from stream.
*/
SQMOD_NODISCARD LightObj ReadBuffer(SQInteger num)
{
const std::streamsize len = Read(num);
// Create a buffer object and return it
return LightObj(SqTypeIdentity< SqBuffer >{}, SqVM(), m_Buffer.Get(), static_cast< Buffer::SzType >(len));
}
/* --------------------------------------------------------------------------------------------
* Extracts up to `num` immediately available characters from the input stream.
*/
SQMOD_NODISCARD std::streamsize ReadSome(SQInteger num)
{
// Prevent negative lengths
if (num < 0)
{
STHROWF("Invalid length: {} < 0", num);
}
// Prevent overflow of Buffer::SzType
else
{
num = static_cast< SQInteger >(ClampL< SQInteger, Buffer::SzType >(num));
}
// Allocate a sufficiently large memory buffer
m_Buffer.Adjust(static_cast< Buffer::SzType >(num));
// Read data from the stream and return the number of characters read
return Stream().readsome(m_Buffer.Get(), static_cast< std::streamsize >(num));
}
/* --------------------------------------------------------------------------------------------
* Extracts up to `num` immediately available characters from the input stream.
*/
SQMOD_NODISCARD LightObj ReadSomeString(SQInteger num)
{
const std::streamsize len = ReadSome(num);
// Create a string object and return it
return LightObj(m_Buffer.Get(), static_cast< SQInteger >(len));
}
/* --------------------------------------------------------------------------------------------
* Extracts up to `num` immediately available characters from the input stream.
*/
SQMOD_NODISCARD LightObj ReadSomeBuffer(SQInteger num)
{
const std::streamsize len = ReadSome(num);
// Create a buffer object and return it
return LightObj(SqTypeIdentity< SqBuffer >{}, SqVM(), m_Buffer.Get(), static_cast< Buffer::SzType >(len));
}
/* --------------------------------------------------------------------------------------------
* Returns the number of characters extracted by the last unformatted input operation.
*/
SQMOD_NODISCARD SQInteger GCount() const
{
return static_cast< SQInteger >(Stream().gcount());
}
/* --------------------------------------------------------------------------------------------
* Returns a copy of the underlying string.
*/
SQMOD_NODISCARD String GetStr() const
{
return Stream().str();
}
/* --------------------------------------------------------------------------------------------
* Replaces the contents of the underlying string.
*/
void SetStr(StackStrF & s)
{
Stream().str(s.ToStr());
}
/* --------------------------------------------------------------------------------------------
* Check if the file stream has an associated file.
*/
SQMOD_NODISCARD bool IsOpen() const
{
return Stream().is_open();
}
/* --------------------------------------------------------------------------------------------
* Open and associate the file with name `name` with the file stream.
*/
SqStream & Open(StackStrF & name)
{
Stream().open(name.mPtr);
return *this; // Allow chaining
}
/* --------------------------------------------------------------------------------------------
* Open and associate the file with name `name` with the file stream.
*/
SqStream & Open_(SQInteger m, StackStrF & name)
{
Stream().open(name.mPtr, static_cast< std::ios_base::openmode >(m));
return *this; // Allow chaining
}
/* --------------------------------------------------------------------------------------------
* Close the associated file.
*/
SqStream & Close()
{
Stream().close();
return *this; // Allow chaining
}
protected:
/* --------------------------------------------------------------------------------------------
* Reusable memory buffer used internally to avoid having to allocate one repeatedly.
*/
Buffer m_Buffer;
};
} // Namespace:: SqMod