slang-text-io.h
#ifndef SLANG_CORE_TEXT_IO_H
#define SLANG_CORE_TEXT_IO_H
#include "slang-secure-crt.h"
#include "slang-stream.h"
#include "slang-char-encode.h"
namespace Slang
{
using Slang::List;
using Slang::_EndLine;
class TextReader
{
public:
virtual void close(){}
virtual SlangResult readToEnd(String& outString) = 0;
virtual bool isEnd() = 0;
char read()
{
if (m_decodedCharIndex == m_decodedCharSize)
readChar();
if (m_decodedCharIndex < m_decodedCharSize)
return m_decodedChar[m_decodedCharIndex++];
else
return 0;
}
char peek()
{
if (m_decodedCharIndex == m_decodedCharSize)
readChar();
if (m_decodedCharIndex < m_decodedCharSize)
return m_decodedChar[m_decodedCharIndex];
else
return 0;
}
virtual ~TextReader() { close(); }
protected:
char m_decodedChar[5];
Index m_decodedCharIndex = 0;
Index m_decodedCharSize = 0;
virtual void readChar() = 0;
};
class StreamReader : public TextReader
{
public:
virtual SlangResult readToEnd(String& outString) SLANG_OVERRIDE;
virtual bool isEnd() SLANG_OVERRIDE { return m_index == m_buffer.getCount() && m_stream->isEnd(); }
virtual void close() SLANG_OVERRIDE { m_stream->close(); }
void releaseStream() { m_stream.setNull(); }
StreamReader();
SlangResult init(const String& path);
SlangResult init(RefPtr<Stream> stream, CharEncoding* encoding = nullptr);
protected:
virtual void readChar() SLANG_OVERRIDE
{
m_decodedCharIndex = 0;
Char32 codePoint = 0;
switch (m_encodingType)
{
case CharEncodeType::UTF8:
{
codePoint = getUnicodePointFromUTF8([&]() -> Byte {return readBufferChar(); });
break;
}
case CharEncodeType::UTF16:
{
codePoint = getUnicodePointFromUTF16([&]() -> Byte {return readBufferChar(); });
break;
}
case CharEncodeType::UTF16Reversed:
{
codePoint = getUnicodePointFromUTF16Reversed([&]() -> Byte {return readBufferChar(); });
break;
}
case CharEncodeType::UTF32:
{
codePoint = getUnicodePointFromUTF32([&]() -> Byte {return readBufferChar(); });
break;
}
}
m_decodedCharSize = encodeUnicodePointToUTF8(codePoint, m_decodedChar);
}
private:
char readBufferChar();
SlangResult readBuffer();
RefPtr<Stream> m_stream;
List<char> m_buffer;
CharEncodeType m_encodingType = CharEncodeType::UTF8;
CharEncoding* m_encoding = nullptr;
Index m_index = 0; ///< Index into buffer
};
class TextWriter
{
public:
virtual SlangResult writeSlice(const UnownedStringSlice& slice) = 0;
virtual void close(){}
SlangResult write(const UnownedStringSlice& slice) { return writeSlice(slice); }
SlangResult write(const char* str) { return writeSlice(UnownedStringSlice(str)); }
SlangResult write(const String& str) { return writeSlice(str.getUnownedSlice()); }
virtual ~TextWriter() { close(); }
template<typename T>
TextWriter& operator << (const T& val)
{
write(val.ToString());
return *this;
}
TextWriter& operator << (int value)
{
write(String(value));
return *this;
}
TextWriter& operator << (float value)
{
write(String(value));
return *this;
}
TextWriter& operator << (double value)
{
write(String(value));
return *this;
}
TextWriter& operator << (const char* value)
{
writeSlice(UnownedStringSlice(value));
return *this;
}
TextWriter& operator << (const String & val)
{
writeSlice(val.getUnownedSlice());
return *this;
}
TextWriter& operator << (const _EndLine &)
{
#ifdef _WIN32
writeSlice(UnownedStringSlice::fromLiteral("\r\n"));
#else
writeSlice(UnownedStringSlice::fromLiteral("\n"));
#endif
return *this;
}
};
class StreamWriter : public TextWriter
{
public:
// TextWriter
virtual SlangResult writeSlice(const UnownedStringSlice& slice) SLANG_OVERRIDE;
virtual void close() SLANG_OVERRIDE { m_stream->close(); }
void releaseStream() { m_stream.setNull(); }
StreamWriter() {}
SlangResult init(const String& path, CharEncoding* encoding = CharEncoding::UTF8);
SlangResult init(RefPtr<Stream> stream, CharEncoding* encoding = CharEncoding::UTF8);
private:
List<Byte> m_encodingBuffer;
RefPtr<Stream> m_stream;
CharEncoding* m_encoding = nullptr;
};
}
#endif