liblcf
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
reader_lcf.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014 liblcf authors
3  * This file is released under the MIT License
4  * http://opensource.org/licenses/MIT
5  */
6 
7 #include <cstdarg>
8 #include "reader_lcf.h"
9 
10 #ifdef NDEBUG
11 # include <stdio.h>
12 #endif
13 
14 // Statics
15 
16 std::string LcfReader::error_str;
17 
18 LcfReader::LcfReader(const char* filename, std::string encoding) :
19  filename(filename),
20  encoding(encoding),
21  stream(fopen(filename, "rb"))
22 {
23 }
24 
25 LcfReader::LcfReader(const std::string& filename, std::string encoding) :
26  filename(filename),
27  encoding(encoding),
28  stream(fopen(filename.c_str(), "rb"))
29 {
30 }
31 
33  Close();
34 }
35 
37  if (stream != NULL)
38  fclose(stream);
39  stream = NULL;
40 }
41 
42 size_t LcfReader::Read0(void *ptr, size_t size, size_t nmemb) {
43  size_t result = fread(ptr, size, nmemb, stream);
44 #ifdef NDEBUG
45  if (result != nmemb && !Eof()) {
46  perror("Reading error: ");
47  }
48 #endif
49  return result;
50 }
51 
52 void LcfReader::Read(void *ptr, size_t size, size_t nmemb) {
53 #ifdef NDEBUG
54  Read0(ptr, size, nmemb);
55 #else
56  assert(Read0(ptr, size, nmemb) == nmemb);
57 #endif
58 }
59 
60 template <>
61 void LcfReader::Read<bool>(bool& ref) {
62  ref = ReadInt() > 0;
63 }
64 
65 template <>
66 void LcfReader::Read<uint8_t>(uint8_t& ref) {
67  Read(&ref, 1, 1);
68 }
69 
70 template <>
71 void LcfReader::Read<int16_t>(int16_t& ref) {
72  Read(&ref, 2, 1);
73  SwapByteOrder(ref);
74 }
75 
76 template <>
77 void LcfReader::Read<uint32_t>(uint32_t& ref) {
78  Read(&ref, 4, 1);
79  SwapByteOrder(ref);
80 }
81 
83  int value = 0;
84  unsigned char temp = 0;
85 
86  do {
87  value <<= 7;
88  if (Read0(&temp, 1, 1) == 0) {
89  assert(value == 0);
90  return 0;
91  }
92  value |= temp & 0x7F;
93  } while (temp & 0x80);
94  return value;
95 }
96 
97 template <>
98 void LcfReader::Read<int>(int& ref) {
99  ref = ReadInt();
100 }
101 
102 template <>
103 void LcfReader::Read<double>(double& ref) {
104  Read(&ref, 8, 1);
105  SwapByteOrder(ref);
106 }
107 
108 template <>
109 void LcfReader::Read<bool>(std::vector<bool> &buffer, size_t size) {
110  buffer.clear();
111 
112  for (unsigned i = 0; i < size; ++i) {
113  uint8_t val;
114  Read(&val, 1, 1);
115  buffer.push_back(val > 0);
116  }
117 }
118 
119 template <>
120 void LcfReader::Read<uint8_t>(std::vector<uint8_t> &buffer, size_t size) {
121  buffer.clear();
122 
123  for (unsigned int i = 0; i < size; ++i) {
124  uint8_t val;
125  Read(&val, 1, 1);
126  buffer.push_back(val);
127  }
128 }
129 
130 template <>
131 void LcfReader::Read<int16_t>(std::vector<int16_t> &buffer, size_t size) {
132  buffer.clear();
133  size_t items = size / 2;
134  for (unsigned int i = 0; i < items; ++i) {
135  int16_t val;
136  Read(&val, 2, 1);
137  SwapByteOrder(val);
138  buffer.push_back(val);
139  }
140  if (size % 2 != 0) {
141  Seek(1, FromCurrent);
142  buffer.push_back(0);
143  }
144 }
145 
146 template <>
147 void LcfReader::Read<uint32_t>(std::vector<uint32_t> &buffer, size_t size) {
148  buffer.clear();
149  size_t items = size / 4;
150  for (unsigned int i = 0; i < items; ++i) {
151  uint32_t val;
152  Read(&val, 4, 1);
153  SwapByteOrder(val);
154  buffer.push_back(val);
155  }
156  if (size % 4 != 0) {
157  Seek(size % 4, FromCurrent);
158  buffer.push_back(0);
159  }
160 }
161 
162 void LcfReader::ReadString(std::string& ref, size_t size) {
163  char* chars = new char[size + 1];
164  chars[size] = '\0';
165  Read(chars, 1, size);
166  ref = Encode(std::string(chars));
167  delete[] chars;
168 }
169 
170 bool LcfReader::IsOk() const {
171  return (stream != NULL && !ferror(stream));
172 }
173 
174 bool LcfReader::Eof() const {
175  return feof(stream) != 0;
176 }
177 
178 void LcfReader::Seek(size_t pos, SeekMode mode) {
179  switch (mode) {
181  fseek(stream, pos, SEEK_SET);
182  break;
184  fseek(stream, pos, SEEK_CUR);
185  break;
186  case LcfReader::FromEnd:
187  fseek(stream, pos, SEEK_END);
188  break;
189  default:
190  assert(false && "Invalid SeekMode");
191  }
192 }
193 
194 uint32_t LcfReader::Tell() {
195  return (uint32_t)ftell(stream);
196 }
197 
198 bool LcfReader::Ungetch(uint8_t ch) {
199  return (ungetc(ch, stream) == ch);
200 }
201 
202 #ifdef _DEBUG
203 void LcfReader::SkipDebug(const struct LcfReader::Chunk& chunk_info, const char* srcfile) {
204  // Dump the Chunk Data in Debug Mode
205 #ifdef _WIN32
206  const char* srcfilename = strrchr(srcfile, '\\');
207 #else
208  const char* srcfilename = strrchr(srcfile, '/');
209 #endif
210  if (srcfilename == NULL) {
211  srcfilename = srcfile;
212  } else {
213  srcfilename++;
214  }
215  fprintf(stderr, "Skipped Chunk %02X (%d byte) in %s at %X (%s)\n",
216  chunk_info.ID, chunk_info.length, filename.c_str(), Tell(),
217  srcfilename);
218  for (uint32_t i = 0; i < chunk_info.length; ++i) {
219  uint8_t byte;
220  LcfReader::Read(byte);
221  fprintf(stderr, "%02X ", byte);
222  if ((i+1) % 16 == 0) {
223  fprintf(stderr, "\n");
224  }
225  }
226  fprintf(stderr, "\n");
227 }
228 #else
229 void LcfReader::Skip(const struct LcfReader::Chunk& chunk_info) {
230  Seek((size_t)chunk_info.length, FromCurrent);
231 }
232 #endif
233 
234 void LcfReader::SetError(const char* fmt, ...) {
235  va_list args;
236  va_start(args, fmt);
237 
238  char str[256];
239  vsprintf(str, fmt, args);
240 
241  error_str = str;
242  //Output::ErrorStr((std::string)str);
243 
244  va_end(args);
245 }
246 
247 const std::string& LcfReader::GetError() {
248  return error_str;
249 }
250 
251 std::string LcfReader::Encode(const std::string& str_to_encode) {
252  return ReaderUtil::Recode(str_to_encode, encoding, "UTF-8");
253 }
254 
255 int LcfReader::IntSize(unsigned int x) {
256  int result = 0;
257  do {
258  x >>= 7;
259  result++;
260  } while (x != 0);
261  return result;
262 }
263 
264 #ifdef WORDS_BIGENDIAN
265 void LcfReader::SwapByteOrder(uint16_t& us)
266 {
267  us = (us >> 8) |
268  (us << 8);
269 }
270 
271 void LcfReader::SwapByteOrder(uint32_t& ui)
272 {
273  ui = (ui >> 24) |
274  ((ui<<8) & 0x00FF0000) |
275  ((ui>>8) & 0x0000FF00) |
276  (ui << 24);
277 }
278 
279 void LcfReader::SwapByteOrder(double& d)
280 {
281  uint32_t *p = reinterpret_cast<uint32_t *>(&d);
282  SwapByteOrder(p[0]);
283  SwapByteOrder(p[1]);
284  uint32_t tmp = p[0];
285  p[0] = p[1];
286  p[1] = tmp;
287 }
288 #else
289 void LcfReader::SwapByteOrder(uint16_t& /* us */) {}
290 void LcfReader::SwapByteOrder(uint32_t& /* ui */) {}
291 void LcfReader::SwapByteOrder(double& /* d */) {}
292 #endif
293 
294 void LcfReader::SwapByteOrder(int16_t& s)
295 {
296  SwapByteOrder((uint16_t&) s);
297 }
void Seek(size_t pos, SeekMode mode=FromStart)
Definition: reader_lcf.cpp:178
void Skip(const struct LcfReader::Chunk &chunk_info)
Definition: reader_lcf.cpp:229
static void SwapByteOrder(int16_t &us)
Definition: reader_lcf.cpp:294
std::string Recode(const std::string &str_to_encode, const std::string &source_encoding)
void Read(void *ptr, size_t size, size_t nmemb)
Definition: reader_lcf.cpp:52
FILE * stream
Definition: reader_lcf.h:233
uint32_t length
Definition: reader_lcf.h:84
LcfReader(const char *filename, std::string encoding="")
Definition: reader_lcf.cpp:18
bool IsOk() const
Definition: reader_lcf.cpp:170
size_t Read0(void *ptr, size_t size, size_t nmemb)
Definition: reader_lcf.cpp:42
std::string Encode(const std::string &str_to_encode)
Definition: reader_lcf.cpp:251
void Close()
Definition: reader_lcf.cpp:36
int ReadInt()
Definition: reader_lcf.cpp:82
static const std::string & GetError()
Definition: reader_lcf.cpp:247
void ReadString(std::string &ref, size_t size)
Definition: reader_lcf.cpp:162
std::string filename
Definition: reader_lcf.h:229
std::vector< RPG::Item > & items
Definition: data.cpp:15
bool Ungetch(uint8_t ch)
Definition: reader_lcf.cpp:198
static int IntSize(unsigned int x)
Definition: reader_lcf.cpp:255
bool Eof() const
Definition: reader_lcf.cpp:174
std::string encoding
Definition: reader_lcf.h:231
static void SetError(const char *fmt,...)
Definition: reader_lcf.cpp:234
uint32_t Tell()
Definition: reader_lcf.cpp:194
static std::string error_str
Definition: reader_lcf.h:235