1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2024-11-09 01:07:16 +01:00
SqMod/module/Library/IO/Stream.hpp
2021-03-09 00:40:16 +02:00

919 lines
34 KiB
C++

#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())
{
}
};
/* ------------------------------------------------------------------------------------------------
* Helper used to extract the string from the constructor to the proper type.
*/
template < class T > struct StreamConstructorStr
{
static auto Get(StackStrF & str)
{
return str.ToStr();
}
};
/* ------------------------------------------------------------------------------------------------
* Specializations of `StreamConstructorStr` that return the raw string pointer instead,
*/
template < > struct StreamConstructorStr< std::fstream >
{
static const SQChar * Get(StackStrF & str)
{
return str.mPtr;
}
};
template < > struct StreamConstructorStr< std::ofstream >
{
static const SQChar * Get(StackStrF & str)
{
return str.mPtr;
}
};
template < > struct StreamConstructorStr< std::ifstream >
{
static const SQChar * Get(StackStrF & str)
{
return str.mPtr;
}
};
/* ------------------------------------------------------------------------------------------------
* Stream-based input/output class.
*/
template < class T > struct SqStream : public SqStreamStorage< T >
{
using SqStreamStorage< T >::Stream;
// --------------------------------------------------------------------------------------------
using Type = typename 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 & str)
: SqStreamStorage< T >(StreamConstructorStr< Type >::Get(str)), m_Buffer()
{
}
/* --------------------------------------------------------------------------------------------
* Explicit file constructor.
*/
SqStream(SQInteger m, StackStrF & str)
: SqStreamStorage< T >(StreamConstructorStr< Type >::Get(str), 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