mirror of
https://github.com/VCMP-SqMod/SqMod.git
synced 2024-11-08 00:37:15 +01:00
Initial draft for I/O streams.
This commit is contained in:
parent
0675c05fe7
commit
7d7fd44427
@ -68,6 +68,7 @@ add_library(SqModule MODULE SqBase.hpp Main.cpp
|
||||
Library/IO/Buffer.cpp Library/IO/Buffer.hpp
|
||||
Library/IO/File.cpp Library/IO/File.hpp
|
||||
Library/IO/INI.cpp Library/IO/INI.hpp
|
||||
Library/IO/Stream.cpp Library/IO/Stream.hpp
|
||||
Library/MMDB.cpp Library/MMDB.hpp
|
||||
Library/Numeric.cpp Library/Numeric.hpp
|
||||
Library/Numeric/Long.cpp Library/Numeric/Long.hpp
|
||||
|
@ -6,12 +6,14 @@ namespace SqMod {
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
extern void Register_Buffer(HSQUIRRELVM vm);
|
||||
extern void Register_Stream(HSQUIRRELVM vm);
|
||||
extern void Register_INI(HSQUIRRELVM vm);
|
||||
|
||||
// ================================================================================================
|
||||
void Register_IO(HSQUIRRELVM vm)
|
||||
{
|
||||
Register_Buffer(vm);
|
||||
Register_Stream(vm);
|
||||
Register_INI(vm);
|
||||
}
|
||||
|
||||
|
346
module/Library/IO/Stream.cpp
Normal file
346
module/Library/IO/Stream.cpp
Normal 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
|
882
module/Library/IO/Stream.hpp
Normal file
882
module/Library/IO/Stream.hpp
Normal 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
|
Loading…
Reference in New Issue
Block a user