enum { STRM_ERROR = 0x20, STRM_READ = 0x10, STRM_WRITE = 0x08, STRM_SEEK = 0x04, STRM_LOADING = 0x02, STRM_THROW = 0x01, ERROR_NOT_ENOUGH_SPACE = -1, ERROR_LOADING_FAILED = -2 }; struct StreamError {}; struct LoadingError : StreamError {}; enum EOLenum { EOL }; class Huge; class Stream { protected: int64 pos; byte *buffer; byte *ptr; byte *rdlim; byte *wrlim; unsigned style:6; unsigned errorcode:16; int version = 0; enum { BEGINOFLINE = 0x02, }; virtual void _Put(int w); virtual int _Term(); virtual int _Get(); virtual void _Put(const void *data, dword size); virtual dword _Get(void *data, dword size); private: int _Get8(); int _Get16(); int _Get32(); int64 _Get64(); public: virtual void Seek(int64 pos); virtual int64 GetSize() const; virtual void SetSize(int64 size); virtual void Flush(); virtual void Close(); virtual bool IsOpen() const = 0; Stream(); virtual ~Stream(); word GetStyle() const { return style; } void SetVersion(int ver) { version = ver; } int GetVersion() const { return version; } bool IsError() const { return style & STRM_ERROR; } bool IsOK() const { return !IsError(); } void SetError(int c = 0) { style |= STRM_ERROR; errorcode = c; } #ifdef PLATFORM_WIN32 void SetLastError() { SetError(GetLastError()); } #endif #ifdef PLATFORM_POSIX void SetLastError() { SetError(errno); } #endif int GetError() const { return errorcode; } String GetErrorText() const; void ClearError() { style = style & ~STRM_ERROR; errorcode = 0; } int64 GetPos() const { return dword(ptr - buffer) + pos; } int64 GetLeft() const { return GetSize() - GetPos(); } void SeekEnd(int64 rel = 0) { Seek(GetSize() + rel); } void SeekCur(int64 rel) { Seek(GetPos() + rel); } bool IsEof() { return ptr >= rdlim && _Term() < 0; } void Put(int c) { if(ptr < wrlim) *ptr++ = c; else _Put(c); } int Term() { return ptr < rdlim ? *ptr : _Term(); } int Peek() { return Term(); } int Get() { return ptr < rdlim ? *ptr++ : _Get(); } const byte *PeekPtr(int size = 1){ ASSERT(size > 0); return ptr + size <= rdlim ? ptr : NULL; } const byte *GetPtr(int size = 1) { ASSERT(size > 0); if(ptr + size <= rdlim) { byte *p = ptr; ptr += size; return p; }; return NULL; } byte *PutPtr(int size = 1) { ASSERT(size > 0); if(ptr + size <= wrlim) { byte *p = ptr; ptr += size; return p; }; return NULL; } const byte *GetSzPtr(int& size) { Term(); size = int(rdlim - ptr); byte *p = ptr; ptr += size; return p; } void Put(const void *data, int size) { ASSERT(size >= 0); if(size) { if(ptr && ptr + size <= wrlim) { memcpy8(ptr, data, size); ptr += size; } else _Put(data, size); } } int Get(void *data, int size) { ASSERT(size >= 0); if(ptr && ptr + size <= rdlim) { memcpy8(data, ptr, size); ptr += size; return size; } return _Get(data, size); } void Put(const String& s) { Put((const char *) s, s.GetLength()); } String Get(int size); String GetAll(int size); int Skip(int size); void LoadThrowing() { style |= STRM_THROW; } void LoadError(); bool GetAll(void *data, int size); void Put64(const void *data, int64 size); int64 Get64(void *data, int64 size); bool GetAll64(void *data, int64 size); size_t Get(Huge& h, size_t size); bool GetAll(Huge& h, size_t size); int Get8() { return ptr < rdlim ? *ptr++ : _Get8(); } int Get16() { if(rdlim - ptr <= 1) return _Get16(); int q = Peek16(ptr); ptr += 2; return q; } int Get32() { if(rdlim - ptr <= 3) return _Get32(); int q = Peek32(ptr); ptr += 4; return q; } int64 Get64() { if(rdlim - ptr <= 7) return _Get64(); int64 q = Peek64(ptr); ptr += 8; return q; } int GetUtf8(); String GetLine(); void Put16(word q) { if(wrlim - ptr > 1) { Poke16(ptr, q); ptr += 2; } else Put(&q, 2); } void Put32(dword q) { if(wrlim - ptr > 3) { Poke32(ptr, q); ptr += 4; } else Put(&q, 4); } void Put64(int64 q) { if(wrlim - ptr > 7) { Poke64(ptr, q); ptr += 8; } else Put(&q, 8); } #ifdef CPU_LE int Get16le() { return Get16(); } int Get32le() { return Get32(); } int64 Get64le() { return Get64(); } int Get16be() { return SwapEndian16(Get16()); } int Get32be() { return SwapEndian32(Get32()); } int64 Get64be() { return SwapEndian64(Get64()); } void Put16le(word q) { Put16(q); } void Put32le(dword q) { Put32(q); } void Put64le(int64 q) { Put64(q); } void Put16be(word q) { Put16(SwapEndian16(q)); } void Put32be(dword q) { Put32(SwapEndian32(q)); } void Put64be(int64 q) { Put64(SwapEndian64(q)); } #else int Get16le() { return SwapEndian16(Get16()); } int Get32le() { return SwapEndian32(Get32()); } int64 Get64le() { return SwapEndian64(Get64()); } int Get16be() { return Get16(); } int Get32be() { return Get32(); } int64 Get64be() { return Get64(); } void Put16le(word q) { Put16(SwapEndian16(q)); } void Put32le(dword q) { Put32(SwapEndian32(q)); } void Put64le(int64 q) { Put64(SwapEndian64(q)); } void Put16be(word q) { Put16(q); } void Put32be(dword q) { Put32(q); } void Put64be(int64 q) { Put64(q); } #endif void PutUtf8(int c); void Put(const char *s); void Put(int c, int count); void Put0(int count) { Put(0, count); } void PutCrLf() { Put16(MAKEWORD('\r', '\n')); } #ifdef PLATFORM_WIN32 void PutEol() { PutCrLf(); } #else void PutEol() { Put('\n'); } #endif Stream& operator<<(EOLenum) { PutEol(); return *this; } void PutLine(const char *s); void PutLine(const String& s); void Put(Stream& s, int64 size = INT64_MAX, dword click = 4096); // Stream as serialization streamer void SetLoading() { ASSERT(style & STRM_READ); style |= STRM_LOADING; } void SetStoring() { ASSERT(style & STRM_WRITE); style &= ~STRM_LOADING; } bool IsLoading() const { return style & STRM_LOADING; } bool IsStoring() const { return !IsLoading(); } void SerializeRaw(byte *data, int64 count); void SerializeRaw(word *data, int64 count); void SerializeRaw(int16 *data, int64 count); void SerializeRaw(dword *data, int64 count); void SerializeRaw(int *data, int64 count); void SerializeRaw(uint64 *data, int64 count); void SerializeRaw(float *data, int64 count); void SerializeRaw(double *data, int64 count); String GetAllRLE(int size); void SerializeRLE(byte *data, int count); Stream& SerializeRaw(byte *data) { if(IsLoading()) *data = Get(); else Put(*data); return *this; } Stream& SerializeRaw(word *data) { if(IsLoading()) *data = Get16le(); else Put16le(*data); return *this; } Stream& SerializeRaw(dword *data) { if(IsLoading()) *data = Get32le(); else Put32le(*data); return *this; } Stream& SerializeRaw(uint64 *data) { if(IsLoading()) *data = Get64le(); else Put64le(*data); return *this; } Stream& operator%(bool& d) { byte b; if(IsStoring()) b = d; SerializeRaw(&b); d = !!b; return *this; } Stream& operator%(char& d) { return SerializeRaw((byte *)&d); } Stream& operator%(signed char& d) { return SerializeRaw((byte *)&d); } Stream& operator%(unsigned char& d) { return SerializeRaw((byte *)&d); } Stream& operator%(short& d) { return SerializeRaw((word *)&d); } Stream& operator%(unsigned short& d) { return SerializeRaw((word *)&d); } Stream& operator%(int& d) { return SerializeRaw((dword *)&d); } Stream& operator%(unsigned int& d) { return SerializeRaw((dword *)&d); } Stream& operator%(long& d) { return SerializeRaw((dword *)&d); } Stream& operator%(unsigned long& d) { return SerializeRaw((dword *)&d); } Stream& operator%(float& d) { return SerializeRaw((dword *)&d); } Stream& operator%(double& d) { return SerializeRaw((uint64 *)&d); } Stream& operator%(int64& d) { return SerializeRaw((uint64 *)&d); } Stream& operator%(uint64& d) { return SerializeRaw((uint64 *)&d); } Stream& operator%(String& s); Stream& operator/(String& s); Stream& operator%(WString& s); Stream& operator/(WString& s); void Pack(dword& i); Stream& operator/(int& i); Stream& operator/(unsigned int& i); Stream& operator/(long& i); Stream& operator/(unsigned long& i); Stream& Serialize64(long& d) { uint64 m = d; *this % m; d = (long) m; return *this; } Stream& Serialize64(unsigned long& d) { uint64 m = d; *this % m; d = (unsigned long) m; return *this; } void Magic(dword magic = 0x7d674d7b); void Pack(bool& a, bool& b, bool& c, bool& d, bool& e, bool& f, bool& g, bool& h); void Pack(bool& a, bool& b, bool& c, bool& d, bool& e, bool& f, bool& g); void Pack(bool& a, bool& b, bool& c, bool& d, bool& e, bool& f); void Pack(bool& a, bool& b, bool& c, bool& d, bool& e); void Pack(bool& a, bool& b, bool& c, bool& d); void Pack(bool& a, bool& b, bool& c); void Pack(bool& a, bool& b); #ifdef DEPRECATED int GetW() { return Get16(); } int GetL() { return Get32(); } int GetIW() { return Get16le(); } int GetIL() { return Get32le(); } int GetMW() { return Get16be(); } int GetML() { return Get32be(); } void PutW(int c) { Put16(c); } void PutL(int c) { Put32(c); } void PutIW(int c) { Put16le(c); } void PutIL(int c) { Put32le(c); } void PutMW(int c) { Put16be(c); } void PutML(int c) { Put32be(c); } void PutW(const char16 *s, int count) { Put(s, count * 2); } dword GetW(char16 *s, int count) { return Get(s, count * 2) / 2; } bool GetAllW(char16 *s, int count) { return GetAll(s, count * 2); } #endif private: // No copy Stream(const Stream& s); void operator=(const Stream& s); }; class StringStream : public Stream { protected: virtual void _Put(int w); virtual int _Term(); virtual int _Get(); virtual void _Put(const void *data, dword size); virtual dword _Get(void *data, dword size); public: virtual void Seek(int64 pos); virtual int64 GetSize() const; virtual void SetSize(int64 size); virtual bool IsOpen() const; protected: bool writemode; String data; StringBuffer wdata; dword size; int limit = INT_MAX; void InitReadMode(); void SetWriteBuffer(); void SetReadMode(); void SetWriteMode(); public: void Open(const String& data); void Create(); void Reserve(int n); String GetResult(); operator String() { return GetResult(); } void Limit(int sz) { limit = sz; } struct LimitExc : public StreamError {}; StringStream() { Create(); } StringStream(const String& data) { Open(data); } }; class MemStream : public Stream { protected: virtual void _Put(const void *data, dword size); virtual dword _Get(void *data, dword size); public: virtual void Seek(int64 pos); virtual int64 GetSize() const; virtual bool IsOpen() const; public: void Create(void *data, int64 size); MemStream(); MemStream(void *data, int64 size); }; class MemReadStream : public MemStream { public: void Create(const void *data, int64 size); MemReadStream(const void *data, int64 size); MemReadStream(); }; class BlockStream : public Stream { protected: virtual void _Put(int w); virtual int _Term(); virtual int _Get(); virtual void _Put(const void *data, dword size); virtual dword _Get(void *data, dword size); public: virtual void Seek(int64 pos); virtual int64 GetSize() const; virtual void SetSize(int64 size); virtual void Flush(); private: int pagesize; int64 pagemask; int64 pagepos; bool pagedirty; int64 streamsize; void SetPos(int64 p); void SyncSize(); bool SyncPage(); bool SyncPos(); void ReadData(void *data, int64 at, int size); protected: virtual dword Read(int64 at, void *ptr, dword size); virtual void Write(int64 at, const void *data, dword size); virtual void SetStreamSize(int64 size); public: enum { READ, CREATE, APPEND, READWRITE, MODEMASK = 0x3, NOWRITESHARE = 0x10, SHAREMASK = 0x70, #ifdef DEPRECATED DELETESHARE = 0x20, NOREADSHARE = 0x40, #endif }; dword GetBufferSize() const { return pagesize; } void SetBufferSize(dword newsize); int64 GetStreamSize() const { return streamsize; } BlockStream(); virtual ~BlockStream(); protected: void Reset(); void OpenInit(dword mode, int64 file_size); }; class FileStream : public BlockStream { protected: virtual void SetStreamSize(int64 size); virtual dword Read(int64 at, void *ptr, dword size); virtual void Write(int64 at, const void *data, dword size); public: virtual void Close(); virtual bool IsOpen() const; protected: #ifdef PLATFORM_WIN32 HANDLE handle; static bool OpenHandle(const char *name, dword mode, HANDLE& handle, int64& fsz); #else int handle; static bool OpenHandle(const char *name, dword mode, int& handle, int64& fsz, mode_t tmode); #endif void SetPos(int64 pos); void Init(int64 size); friend class FileMapping; public: operator bool() const { return IsOpen(); } FileTime GetTime() const; #ifdef PLATFORM_WIN32 void SetTime(const FileTime& tm); bool Open(const char *filename, dword mode); FileStream(const char *filename, dword mode); #endif #ifdef PLATFORM_POSIX bool Open(const char *filename, dword mode, mode_t acm = 0644); FileStream(const char *filename, dword mode, mode_t acm = 0644); FileStream(int std_handle); #endif FileStream(); ~FileStream(); #ifdef PLATFORM_WIN32 HANDLE GetHandle() const { return handle; } #endif #ifdef PLATFORM_POSIX int GetHandle() const { return handle; } #endif }; class FileOut : public FileStream { public: #ifdef PLATFORM_POSIX bool Open(const char *fn, mode_t acm = 0644); #endif #ifdef PLATFORM_WIN32 bool Open(const char *fn); #endif FileOut(const char *fn) { Open(fn); } FileOut() {} }; class FileAppend : public FileStream { public: bool Open(const char *fn) { return FileStream::Open(fn, FileStream::APPEND|FileStream::NOWRITESHARE); } FileAppend(const char *fn) { Open(fn); } FileAppend() {} }; class FileIn : public FileStream { public: bool Open(const char *fn) { return FileStream::Open(fn, FileStream::READ); } FileIn(const char *fn) { Open(fn); } FileIn() {} }; class SizeStream : public Stream { protected: virtual void _Put(int w); virtual void _Put(const void *data, dword size); public: virtual int64 GetSize() const; virtual bool IsOpen() const; protected: byte h[256]; public: operator int64() const { return GetSize(); } void Open() { ptr = buffer; ClearError(); } SizeStream(); }; class CompareStream : public Stream { protected: virtual void _Put(int w); virtual void _Put(const void *data, dword size); public: virtual void Seek(int64 pos); virtual int64 GetSize() const; virtual void SetSize(int64 size); virtual void Close(); virtual bool IsOpen() const; virtual void Flush(); private: Stream *stream; bool equal; int64 size; byte h[1024]; void Compare(int64 pos, const void *data, int size); public: void Open(Stream& aStream); bool IsEqual() { Flush(); return equal; } operator bool() { Flush(); return equal; } CompareStream(); CompareStream(Stream& aStream); }; class OutStream : public Stream { byte *h; protected: virtual void _Put(int w); virtual void _Put(const void *data, dword size); virtual bool IsOpen() const; virtual void Out(const void *data, dword size) = 0; public: virtual void Close(); void Flush(); OutStream(); ~OutStream(); }; class TeeStream : public OutStream { protected: virtual void Out(const void *data, dword size); private: Stream& a; Stream& b; public: TeeStream(Stream& a, Stream& b) : a(a), b(b) {} ~TeeStream() { Close(); } }; String LoadStream(Stream& in); bool SaveStream(Stream& out, const String& data); int64 CopyStream(Stream& dest, Stream& src, int64 count = INT64_MAX); void CoutUTF8(); Stream& Cout(); Stream& Cerr(); String ReadStdIn(); String ReadSecret(); void EnableEcho(bool b = true); void DisableEcho(); Stream& NilStream(); String LoadFile(const char *filename); bool SaveFile(const char *filename, const String& data); template inline Stream& operator%(Stream& s, T& x) { x.Serialize(s); return s; } inline Stream& operator<<(Stream& s, const char *x) { s.Put(x); return s; } inline Stream& operator<<(Stream& s, char *x) { s.Put(x); return s; } inline Stream& operator<<(Stream& s, const String &x) { s.Put(x); return s; } inline Stream& operator<<(Stream& s, char x) { s.Put((int) x); return s; } inline Stream& operator<<(Stream& s, const void *x) { s << FormatPtr(x); return s; } inline Stream& operator<<(Stream& s, void *x) { s << FormatPtr(x); return s; } template inline Stream& operator<<(Stream& s, const T& x) { s << AsString(x); return s; } // ------ Stream& Pack16(Stream& s, int& i); Stream& Pack16(Stream& s, int& i1, int& i2); Stream& Pack16(Stream& s, int& i1, int& i2, int& i3); Stream& Pack16(Stream& s, int& i1, int& i2, int& i3, int& i4); Stream& Pack16(Stream& s, int& i1, int& i2, int& i3, int& i4, int& i5); int StreamHeading(Stream& stream, int ver, int minver, int maxver, const char* tag);