OpenClonk
StdMeshLoaderDataStream.h
Go to the documentation of this file.
1 /*
2  * OpenClonk, http://www.openclonk.org
3  *
4  * Copyright (c) 2010-2016, The OpenClonk Team and contributors
5  *
6  * Distributed under the terms of the ISC license; see accompanying file
7  * "COPYING" for details.
8  *
9  * "Clonk" is a registered trademark of Matthes Bender, used with permission.
10  * See accompanying file "TRADEMARK" for details.
11  *
12  * To redistribute this file separately, substitute the full license texts
13  * for the above references.
14  */
15 
16 #ifndef INC_StdMeshLoaderDataStream
17 #define INC_StdMeshLoaderDataStream
18 
19 #include "lib/StdMeshLoader.h"
20 
21 namespace Ogre
22 {
23  class DataStream
24  {
25  const char *begin, *cursor, *end;
26  public:
27  DataStream(const char *src, size_t length)
28  {
29  begin = cursor = src;
30  end = cursor + length;
31  }
32 
33  // non-copyable
34  DataStream(const DataStream&) = delete;
35  DataStream& operator=(const DataStream&) = delete;
36 
37  bool AtEof() const { return cursor == end; }
38  size_t GetRemainingBytes() const { return end - cursor; }
39  void Rewind() { cursor = begin; }
40  void Seek(ptrdiff_t offset)
41  {
42  if (offset > 0 && GetRemainingBytes() < static_cast<size_t>(offset))
43  throw InsufficientData();
44  if (cursor - begin < -offset)
45  throw InsufficientData();
46  cursor += offset;
47  }
48 
49  // Only read directly into T when T is trivially copyable (i.e., allows bit-wise copy)
50  template<class T>
51  typename std::enable_if<std::is_pod<T>::value && !std::is_pointer<T>::value, T>::type
52  Peek() const
53  {
54  if (GetRemainingBytes() < sizeof(T))
55  throw InsufficientData();
56  T temp;
57  std::memcpy(reinterpret_cast<char*>(&temp), cursor, sizeof(T));
58  return temp;
59  }
60 
61  // declaration for non-trivially copyable types
62  template<class T> typename std::enable_if<!std::is_pod<T>::value, T>::type
63  Peek() const;
64 
65  template<class T> T Read()
66  {
67  T temp = Peek<T>();
68  Seek(sizeof(T));
69  return temp;
70  }
71  void Peek(void *dest, size_t size) const
72  {
73  if (GetRemainingBytes() < size)
74  throw InsufficientData();
75  std::memcpy(dest, cursor, size);
76  }
77  void Read(void *dest, size_t size)
78  {
79  Peek(dest, size);
80  cursor += size;
81  }
82  };
83 
84  template<> inline bool DataStream::Peek<bool>() const
85  {
86  if (GetRemainingBytes() < 1)
87  throw InsufficientData();
88  return *cursor != '\0';
89  }
90 
91  template<> inline std::string DataStream::Peek<std::string>() const
92  {
93  // Ogre terminates strings with \n
94  const char *terminator = static_cast<const char*>(std::memchr(cursor, '\n', GetRemainingBytes()));
95  if (!terminator)
96  throw InsufficientData("Unterminated string");
97  return std::string(cursor, terminator);
98  }
99 
100  template<> inline std::string DataStream::Read<std::string>()
101  {
102  std::string temp = Peek<std::string>();
103  Seek(temp.size() + 1);
104  return temp;
105  }
106 
107 }
108 
109 #endif
std::enable_if<!std::is_pod< T >::value, T >::type Peek() const
DataStream(const DataStream &)=delete
size_t GetRemainingBytes() const
void Read(void *dest, size_t size)
void Seek(ptrdiff_t offset)
DataStream & operator=(const DataStream &)=delete
DataStream(const char *src, size_t length)
void Peek(void *dest, size_t size) const
std::enable_if< std::is_pod< T >::value &&!std::is_pointer< T >::value, T >::type Peek() const