Gorgon Game Engine
Reader.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <stdexcept>
4 #include <iostream>
5 #include <fstream>
6 #include <map>
7 #include <memory>
8 
9 #include "../Utils/Assert.h"
10 #include "../Filesystem.h"
11 #include "../IO/Stream.h"
12 
13 namespace Gorgon { namespace Resource {
14 
16  class LoadError : public std::runtime_error {
17  public:
18 
20  enum ErrorType {
22  Unknown = 0,
23 
26 
28  Signature = 2,
29 
32 
35 
38 
41 
44 
47  };
48 
51 
52  }
53 
55  LoadError(ErrorType number, const std::string &text) : runtime_error(text), number(number) {
56 
57  }
58 
61 
63  static const std::string ErrorStrings[8];
64  };
65 
70  class Reader {
71  public:
72 
75  class Mark {
76  public:
79  Mark(Reader &reader, unsigned long target) :
80  reader(&reader), target(target) {}
81 
83  Mark(const Mark &) = default;
84 
86  explicit operator bool() const {
87  auto pos=reader->Tell();
88  if(pos<target) return false;
89 
90  ASSERT(pos==target, "Reading operation passed the target.");
91 
92  return true;
93  }
94 
96  unsigned long Tell() const {
97  return target;
98  }
99 
100  private:
101  Reader *reader;
102  unsigned long target;
103  };
104 
105  Reader() {}
106 
107  virtual ~Reader() {}
108 
111  void KeepOpen() {
112  keepopenrequests++;
113  }
114 
118  void NoLongerNeeded() {
119  if(--keepopenrequests) {
120  close();
121  stream=nullptr;
122  }
123  }
124 
126  void Open() {
127  if(!stream) {
128  open(true);
129  }
130 
131  ASSERT(stream, "Reader did not set the stream.");
132  }
133 
135  bool IsOpen() const {
136  return stream;
137  }
138 
140  bool IsGood() const {
141  return stream && stream->good();
142  }
143 
145  bool IsFailed() const {
146  return stream && stream->fail();
147  }
148 
151  bool TryOpen() {
152  if(!stream) {
153  return open(false);
154  }
155 
156  return true;
157  }
158 
159 
161  std::istream &GetStream() {
162  ASSERT(stream, "Reader is not opened.");
163 
164  return *stream;
165  }
166 
168  unsigned long Tell() const {
169  ASSERT(stream, "Reader is not opened.");
170  ASSERT(!IsFailed(), "Reader is failed.");
171 
172  return (unsigned long)stream->tellg();
173  }
174 
176  void Seek(unsigned long pos) {
177  ASSERT(stream, "Reader is not opened.");
178  ASSERT(!IsFailed(), "Reader is failed.");
179 
180  stream->seekg((std::streampos)pos, std::ios::beg);
181  }
182 
184  void Seek(const Mark &pos) {
185  ASSERT(stream, "Reader is not opened.");
186  ASSERT(!IsFailed(), "Reader is failed.");
187 
188  stream->seekg((std::streampos)pos.Tell(), std::ios::beg);
189  }
190 
193  Mark Target(unsigned long delta) {
194  return Mark(*this, Tell()+delta);
195  }
196 
197  bool ReadCommonChunk(Base &self, GID::Type gid, unsigned long size);
198 
205 
207  template<class E_>
208  E_ ReadEnum32() {
209  ASSERT(stream, "Reader is not opened.");
210  ASSERT(IsGood(), "Reader is failed.");
211 
212  return IO::ReadEnum32<E_>(*stream);
213  }
214 
217  long ReadInt32() {
218  ASSERT(stream, "Reader is not opened.");
219  ASSERT(IsGood(), "Reader is failed.");
220 
221  return IO::ReadInt32(*stream);
222  }
223 
226  unsigned long ReadUInt32() {
227  ASSERT(stream, "Reader is not opened.");
228  ASSERT(IsGood(), "Reader is failed.");
229 
230  return IO::ReadUInt32(*stream);
231  }
232 
235  int ReadInt16() {
236  ASSERT(stream, "Reader is not opened.");
237  ASSERT(IsGood(), "Reader is failed.");
238 
239  return IO::ReadInt16(*stream);
240  }
241 
244  unsigned ReadUInt16() {
245  ASSERT(stream, "Reader is not opened.");
246  ASSERT(IsGood(), "Reader is failed.");
247 
248  return IO::ReadUInt16(*stream);
249  }
250 
253  char ReadInt8() {
254  ASSERT(stream, "Reader is not opened.");
255  ASSERT(IsGood(), "Reader is failed.");
256 
257  return IO::ReadInt8(*stream);
258  }
259 
263  ASSERT(stream, "Reader is not opened.");
264  ASSERT(IsGood(), "Reader is failed.");
265 
266  return IO::ReadUInt8(*stream);
267  }
268 
271  float ReadFloat() {
272  ASSERT(stream, "Reader is not opened.");
273  ASSERT(IsGood(), "Reader is failed.");
274 
275  return IO::ReadFloat(*stream);
276  }
277 
280  double ReadDouble() {
281  ASSERT(stream, "Reader is not opened.");
282  ASSERT(IsGood(), "Reader is failed.");
283 
284  return IO::ReadDouble(*stream);
285  }
286 
288  bool ReadBool() {
289  ASSERT(stream, "Reader is not opened.");
290  ASSERT(IsGood(), "Reader is failed.");
291 
292  return IO::ReadBool(*stream);
293  }
294 
297  ASSERT(stream, "Reader is not opened.");
298  ASSERT(IsGood(), "Reader is failed.");
299 
300  return IO::ReadRGBA(*stream);
301  }
302 
305  ASSERT(stream, "Reader is not opened.");
306  ASSERT(IsGood(), "Reader is failed.");
307 
308  return IO::ReadRGBAf(*stream);
309  }
310 
313  std::string ReadString() {
314  ASSERT(stream, "Reader is not opened.");
315  ASSERT(IsGood(), "Reader is failed.");
316 
317  return IO::ReadString(*stream);
318  }
319 
321  std::string ReadString(unsigned long size) {
322  ASSERT(stream, "Reader is not opened.");
323  ASSERT(IsGood(), "Reader is failed.");
324 
325  return IO::ReadString(*stream, size);
326  }
327 
332  template<class T_>
333  void ReadArray(T_ *data, unsigned long size) {
334  ASSERT(stream, "Reader is not opened.");
335  ASSERT(IsGood(), "Reader is failed.");
336 
337  IO::ReadArray<T_>(*stream, data, size);
338  }
339 
342  ASSERT(stream, "Reader is not opened.");
343  ASSERT(IsGood(), "Reader is failed.");
344 
345  return GID::Type(ReadUInt32());
346  }
347 
350  ASSERT(stream, "Reader is not opened.");
351  ASSERT(IsGood(), "Reader is failed.");
352 
353  return IO::ReadGuid(*stream);
354  }
355 
358  ASSERT(stream, "Reader is not opened.");
359  ASSERT(IsGood(), "Reader is failed.");
360 
361  return IO::ReadPoint(*stream);
362  }
363 
366  ASSERT(stream, "Reader is not opened.");
367  ASSERT(IsGood(), "Reader is failed.");
368 
369  return IO::ReadPointf(*stream);
370  }
371 
374  ASSERT(stream, "Reader is not opened.");
375  ASSERT(IsGood(), "Reader is failed.");
376 
377  return IO::ReadSize(*stream);
378  }
379 
381  unsigned long ReadChunkSize() {
382  ASSERT(stream, "Reader is not opened.");
383  ASSERT(IsGood(), "Reader is failed.");
384 
385  return ReadUInt32();
386  }
387 
389  void EatChunk(long size) {
390  ASSERT(stream, "Reader is not opened.");
391  ASSERT(IsGood(), "Reader is failed.");
392 
393  stream->seekg(size, std::ios::cur);
394  }
395 
397  void EatChunk() {
398  ASSERT(stream, "Reader is not opened.");
399  ASSERT(IsGood(), "Reader is failed.");
400 
401  long size=ReadUInt32();
402  stream->seekg(size, std::ios::cur);
403  }
404 
406 
407  protected:
410  virtual void close() = 0;
411 
415  virtual bool open(bool thrw) = 0;
416 
419  std::istream *stream = nullptr;
420 
421  private:
422  int keepopenrequests = 0;
423  };
424 
426  class FileReader : public Reader {
427  public:
429  FileReader(const std::string &filename) : filename(filename) {
430  try {
431  this->filename=Filesystem::Canonical(filename);
432  }
433  catch(...) {}
434  }
435 
436 
437  protected:
438  virtual void close() override {
439  file.close();
440  }
441 
442  virtual bool open(bool thrw) override {
443  file.open(filename, std::ios::binary);
444 
445  if(!file.is_open()) {
446  if(thrw) {
447  throw LoadError(LoadError::FileNotFound, "Cannot open file: "+filename);
448  }
449 
450  return false;
451  }
452 
453  stream = &file;
454  this->filename=Filesystem::Canonical(filename);
455 
456  return true;
457  }
458 
459  private:
460  std::string filename;
461  std::ifstream file;
462  };
463 
464 } }
Gorgon::Resource::FileReader::close
virtual void close() override
This function should close the stream.
Definition: Reader.h:438
Gorgon::Resource::Reader::ReadInt8
char ReadInt8()
Reads an 8-bit integer from the stream.
Definition: Reader.h:253
Gorgon::Graphics::RGBA
This class represents a color information.
Definition: Color.h:91
Gorgon::Resource::Reader::IsFailed
bool IsFailed() const
Checks if the stream is open and it can be read from.
Definition: Reader.h:145
Gorgon::Resource::FileReader
This is a file reader. Allows a Gorgon Resource to be loaded from a file.
Definition: Reader.h:426
Gorgon::Resource::Reader::ReadEnum32
E_ ReadEnum32()
Reads an enumeration as 32-bit integer from the stream.
Definition: Reader.h:208
Gorgon::Resource::Reader::KeepOpen
void KeepOpen()
Request reader to keep reading stream open.
Definition: Reader.h:111
Gorgon::IO::ReadRGBA
Graphics::RGBA ReadRGBA(std::istream &stream)
Reads a RGBA color, R will be read first.
Definition: Stream.h:110
Gorgon::IO::ReadInt8
char ReadInt8(std::istream &stream)
Reads an 8-bit integer from the stream.
Definition: Stream.h:62
Gorgon::Resource::LoadError::VersionMismatch
@ VersionMismatch
Version in the file is not recognized.
Definition: Reader.h:31
Gorgon::Resource::Reader::ReadString
std::string ReadString()
Reads a string from a given stream.
Definition: Reader.h:313
Gorgon::Resource::LoadError::NoFileObject
@ NoFileObject
There is no file object associated with the resource. Generally thrown during late loading.
Definition: Reader.h:43
Gorgon::Resource::LoadError::UnknownNode
@ UnknownNode
There is an unknown node in the file. This is never thrown in release mode.
Definition: Reader.h:37
Gorgon::Resource::Reader::Mark::Mark
Mark(const Mark &)=default
Copy constructor.
Gorgon::Resource::LoadError::FileCannotBeOpened
@ FileCannotBeOpened
Cannot open the given file.
Definition: Reader.h:40
Gorgon::Resource::Reader::ReadRGBAf
Graphics::RGBAf ReadRGBAf()
Reads a RGBAf color, R will be read first.
Definition: Reader.h:304
Gorgon::Resource::Reader::ReadArray
void ReadArray(T_ *data, unsigned long size)
Reads an array from the file.
Definition: Reader.h:333
Gorgon::Resource::LoadError::Containment
@ Containment
There is no containing root folder.
Definition: Reader.h:34
Gorgon::Graphics::RGBAf
Represents a four channel 32 bit float per channel color information.
Definition: Color.h:373
Gorgon::Resource::Reader::ReadUInt8
Byte ReadUInt8()
Reads an 8-bit unsigned integer from the stream.
Definition: Reader.h:262
Gorgon::Resource::Reader::Seek
void Seek(const Mark &pos)
Seeks to the given position.
Definition: Reader.h:184
Gorgon::Resource::Reader::stream
std::istream * stream
This is the stream that will be used to read data from.
Definition: Reader.h:419
Gorgon::Resource::LoadError::UnsupportedCompression
@ UnsupportedCompression
If the compression type in the file is not supported.
Definition: Reader.h:46
Gorgon::IO::ReadRGBAf
Graphics::RGBAf ReadRGBAf(std::istream &stream)
Reads a RGBAf color, R will be read first.
Definition: Stream.h:122
Gorgon::Resource::LoadError::Signature
@ Signature
File does not contain correct signature and is probably not a Gorgon resource.
Definition: Reader.h:28
Gorgon::IO::ReadFloat
float ReadFloat(std::istream &stream)
Reads a 32 bit IEEE floating point number from the stream.
Definition: Stream.h:80
Gorgon::Resource::Reader::ReadFloat
float ReadFloat()
Reads a 32 bit IEEE floating point number from the file.
Definition: Reader.h:271
Gorgon::Resource::Reader::ReadInt32
long ReadInt32()
Reads a 32-bit integer from the stream.
Definition: Reader.h:217
Gorgon::IO::ReadInt32
long ReadInt32(std::istream &stream)
Reads a 32-bit integer from the stream.
Definition: Stream.h:26
Gorgon::Resource::Reader::Tell
unsigned long Tell() const
Tells the current position.
Definition: Reader.h:168
Gorgon::Resource::Reader::ReadString
std::string ReadString(unsigned long size)
Reads a string with the given size.
Definition: Reader.h:321
Gorgon
Root namespace for Gorgon Game Engine.
Definition: Any.h:19
Gorgon::Geometry::basic_Size
This class represents a 2D geometric size.
Definition: Size.h:23
Gorgon::Resource::Reader::ReadGuid
SGuid ReadGuid()
Reads a GUID from the given stream.
Definition: Reader.h:349
Gorgon::Resource::FileReader::FileReader
FileReader(const std::string &filename)
Constructor requires a file to be opened later.
Definition: Reader.h:429
Gorgon::Resource::Reader::ReadDouble
double ReadDouble()
Reads a 64 bit IEEE double precision floating point number from the file.
Definition: Reader.h:280
Gorgon::IO::ReadBool
bool ReadBool(std::istream &stream)
Reads a boolean value. In resource 1.0, booleans are stored as 32bit integers.
Definition: Stream.h:105
Gorgon::Resource::Reader::ReadUInt32
unsigned long ReadUInt32()
Reads a 32-bit unsigned integer from the stream.
Definition: Reader.h:226
Gorgon::Resource::Reader
This class allows resource objects to read data from a stream.
Definition: Reader.h:70
Gorgon::IO::ReadInt16
int ReadInt16(std::istream &stream)
Reads a 16-bit integer from the stream.
Definition: Stream.h:44
Gorgon::IO::ReadUInt32
unsigned long ReadUInt32(std::istream &stream)
Reads a 32-bit unsigned integer from the stream.
Definition: Stream.h:35
ASSERT
#define ASSERT(expression, message,...)
Replaces regular assert to allow messages and backtrace.
Definition: Assert.h:161
Gorgon::Resource::Reader::ReadChunkSize
unsigned long ReadChunkSize()
Reads chunk size from a stream.
Definition: Reader.h:381
Gorgon::Resource::LoadError::LoadError
LoadError(ErrorType number, const std::string &text)
A constructor to allow custom text for the error.
Definition: Reader.h:55
Gorgon::IO::ReadUInt16
unsigned ReadUInt16(std::istream &stream)
Reads a 16-bit unsigned integer from the stream.
Definition: Stream.h:53
Gorgon::Resource::LoadError::ErrorType
ErrorType
Error types.
Definition: Reader.h:20
Gorgon::Resource::Base
This class is the base for all Gorgon Resources.
Definition: Base.h:20
Gorgon::Resource::LoadError::FileNotFound
@ FileNotFound
Cannot find the given file.
Definition: Reader.h:25
Gorgon::Resource::Reader::Mark::Mark
Mark(Reader &reader, unsigned long target)
Constructs a target using a reader and absolute file position.
Definition: Reader.h:79
Gorgon::Resource::Reader::TryOpen
bool TryOpen()
Tries to open the stream, if it fails, this function returns false.
Definition: Reader.h:151
Gorgon::Resource::Reader::Target
Mark Target(unsigned long delta)
Creates mark to the the target that is delta distance from current point in file.
Definition: Reader.h:193
Gorgon::Resource::Reader::EatChunk
void EatChunk(long size)
Removes a chunk of data with the given size from the stream.
Definition: Reader.h:389
Gorgon::Resource::FileReader::open
virtual bool open(bool thrw) override
This function should open the stream and set stream member.
Definition: Reader.h:442
Gorgon::Geometry::basic_Point
This class represents a 2D point.
Definition: Point.h:32
Gorgon::Resource::LoadError::LoadError
LoadError(ErrorType number=Unknown)
Regular constructor, creates error text from error number.
Definition: Reader.h:50
Gorgon::Resource::Reader::~Reader
virtual ~Reader()
Definition: Reader.h:107
Gorgon::Resource::Reader::ReadInt16
int ReadInt16()
Reads a 16-bit integer from the stream.
Definition: Reader.h:235
Gorgon::Resource::Reader::ReadGID
GID::Type ReadGID()
Reads a GID from the given stream.
Definition: Reader.h:341
Gorgon::Resource::LoadError
This class represents a loading error.
Definition: Reader.h:16
Gorgon::Resource::Reader::IsOpen
bool IsOpen() const
Checks if the stream is open.
Definition: Reader.h:135
Gorgon::Byte
unsigned char Byte
Represents smallest cell in memory.
Definition: Types.h:9
Gorgon::Resource::LoadError::number
ErrorType number
The type of loading error occurred.
Definition: Reader.h:60
Gorgon::Resource::Reader::ReadPoint
Geometry::Point ReadPoint()
Reads a Point from the given stream.
Definition: Reader.h:357
Gorgon::Resource::Reader::ReadUInt16
unsigned ReadUInt16()
Reads a 16-bit unsigned integer from the stream.
Definition: Reader.h:244
Gorgon::Resource::Reader::GetStream
std::istream & GetStream()
This should be last resort, use if the actual stream is needed.
Definition: Reader.h:161
Gorgon::Resource::Reader::ReadBool
bool ReadBool()
Reads a boolean value. In resource 1.0, booleans are stored as 32bit integers.
Definition: Reader.h:288
Gorgon::Resource::Reader::EatChunk
void EatChunk()
Removes a chunk of data from the stream, the size will be read from the stream.
Definition: Reader.h:397
Gorgon::Resource::Reader::NoLongerNeeded
void NoLongerNeeded()
Marks that this reader is no longer needed.
Definition: Reader.h:118
Gorgon::GL::UBOBindingPoint::Type
Type
Definition: Shader.h:14
Gorgon::IO::ReadPointf
Geometry::Pointf ReadPointf(std::istream &stream)
Definition: Stream.h:174
Gorgon::Resource::LoadError::ErrorStrings
static const std::string ErrorStrings[8]
Strings for error codes.
Definition: Reader.h:63
Gorgon::Resource::Reader::Reader
Reader()
Definition: Reader.h:105
Gorgon::Resource::GID::Type
Type to store GID information.
Definition: GID.h:23
Gorgon::SGuid
This class represents a short globally unique identifier.
Definition: SGuid.h:22
Gorgon::Resource::Reader::ReadPointf
Geometry::Point ReadPointf()
Reads a Pointf from the given stream.
Definition: Reader.h:365
Gorgon::IO::ReadSize
Geometry::Size ReadSize(std::istream &stream)
Definition: Stream.h:181
Gorgon::Filesystem::Canonical
std::string Canonical(const std::string &path)
Canonicalizes a given relative path.
Definition: Linux.cpp:94
Gorgon::Resource::Reader::Open
void Open()
Opens the reader. If this operation fails, it will throw LoadError.
Definition: Reader.h:126
Gorgon::Resource::Reader::ReadSize
Geometry::Size ReadSize()
Reads a Size from the given stream.
Definition: Reader.h:373
Gorgon::Resource::Reader::Mark
Marks a target position in file.
Definition: Reader.h:75
Gorgon::IO::ReadGuid
SGuid ReadGuid(std::istream &stream)
Reads a GUID from the given stream.
Definition: Stream.h:163
Gorgon::IO::ReadDouble
double ReadDouble(std::istream &stream)
Reads a 64 bit IEEE double precision floating point number from the stream.
Definition: Stream.h:93
Gorgon::Resource::Reader::ReadCommonChunk
bool ReadCommonChunk(Base &self, GID::Type gid, unsigned long size)
Definition: File.cpp:41
Gorgon::IO::ReadPoint
Geometry::Point ReadPoint(std::istream &stream)
Definition: Stream.h:167
Gorgon::Resource::Reader::ReadRGBA
Graphics::RGBA ReadRGBA()
Reads a RGBA color, R will be read first.
Definition: Reader.h:296
Gorgon::Resource::Reader::IsGood
bool IsGood() const
Checks if the stream is open and it can be read from.
Definition: Reader.h:140
Gorgon::Resource::Reader::Seek
void Seek(unsigned long pos)
Seeks to the given position.
Definition: Reader.h:176
Gorgon::Resource::Reader::open
virtual bool open(bool thrw)=0
This function should open the stream and set stream member.
Gorgon::IO::ReadUInt8
Byte ReadUInt8(std::istream &stream)
Reads an 8-bit unsigned integer from the stream.
Definition: Stream.h:71
Gorgon::IO::ReadString
std::string ReadString(std::istream &stream)
Reads a string from a given stream.
Definition: Stream.h:135
Gorgon::Resource::Reader::Mark::Tell
unsigned long Tell() const
Tells the position of this mark.
Definition: Reader.h:96
Gorgon::Resource::LoadError::Unknown
@ Unknown
An unknown error occurred.
Definition: Reader.h:22
Gorgon::Resource::Reader::close
virtual void close()=0
This function should close the stream.