liblcf
writer_lcf.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of liblcf. Copyright (c) 2021 liblcf authors.
3  * https://github.com/EasyRPG/liblcf - https://easyrpg.org
4  *
5  * liblcf is Free/Libre Open Source Software, released under the MIT License.
6  * For the full copyright and license information, please view the COPYING
7  * file that was distributed with this source code.
8  */
9 
10 #include <ostream>
11 
12 #include "lcf/writer_lcf.h"
13 
14 namespace lcf {
15 
16 LcfWriter::LcfWriter(std::ostream& filestream, EngineVersion engine, std::string encoding)
17  : stream(filestream)
18  , encoder(std::move(encoding))
19  , engine(engine)
20 {
21 }
22 
23 void LcfWriter::Write(const void *ptr, size_t size, size_t nmemb) {
24  stream.write(reinterpret_cast<const char*>(ptr), size*nmemb);
25  assert(stream.good());
26 }
27 
28 template <>
29 void LcfWriter::Write<int8_t>(int8_t val) {
30  Write(&val, 1, 1);
31 }
32 
33 template <>
34 void LcfWriter::Write<uint8_t>(uint8_t val) {
35  Write(&val, 1, 1);
36 }
37 
38 template <>
39 void LcfWriter::Write<int16_t>(int16_t val) {
40  SwapByteOrder(val);
41  Write(&val, 2, 1);
42 }
43 
44 template <>
45 void LcfWriter::Write<uint32_t>(uint32_t val) {
46  SwapByteOrder(val);
47  Write(&val, 4, 1);
48 }
49 
50 void LcfWriter::WriteInt(int val) {
51  uint32_t value = (uint32_t) val;
52  for (int i = 28; i >= 0; i -= 7)
53  if (value >= (1U << i) || i == 0)
54  Write<uint8_t>((uint8_t)(((value >> i) & 0x7F) | (i > 0 ? 0x80 : 0)));
55 }
56 
57 template <>
58 void LcfWriter::Write<int32_t>(int32_t val) {
59  WriteInt(val);
60 }
61 
62 template <>
63 void LcfWriter::Write<bool>(bool val) {
64  uint8_t x = val ? 1 : 0;
65  Write(x);
66 }
67 
68 template <>
69 void LcfWriter::Write<double>(double val) {
70  SwapByteOrder(val);
71  Write(&val, 8, 1);
72 }
73 
74 template <>
75 void LcfWriter::Write<bool>(const std::vector<bool>& buffer) {
76  std::vector<bool>::const_iterator it;
77  for (it = buffer.begin(); it != buffer.end(); it++) {
78  uint8_t val = *it ? 1 : 0;
79  Write(val);
80  }
81 }
82 
83 template <>
84 void LcfWriter::Write<uint8_t>(const std::vector<uint8_t>& buffer) {
85  Write(&buffer.front(), 1, buffer.size());
86 }
87 
88 template <>
89 void LcfWriter::Write<int16_t>(const std::vector<int16_t>& buffer) {
90  std::vector<int16_t>::const_iterator it;
91  for (it = buffer.begin(); it != buffer.end(); it++)
92  Write(*it);
93 }
94 
95 template <>
96 void LcfWriter::Write<int32_t>(const std::vector<int32_t>& buffer) {
97  std::vector<int32_t>::const_iterator it;
98  for (it = buffer.begin(); it != buffer.end(); it++) {
99  int32_t val = *it;
100  SwapByteOrder(val);
101  // Write<int32_t> writes a compressed integer
102  Write(&val, 4, 1);
103  }
104 }
105 
106 template <>
107 void LcfWriter::Write<uint32_t>(const std::vector<uint32_t>& buffer) {
108  std::vector<uint32_t>::const_iterator it;
109  for (it = buffer.begin(); it != buffer.end(); it++)
110  Write(*it);
111 }
112 
113 void LcfWriter::Write(const std::string& _str) {
114  std::string str = Decode(_str);
115  if (!str.empty()) {
116  Write(&*str.begin(), 1, str.size());
117  }
118 }
119 
120 void LcfWriter::Write(const DBString& _str) {
121  std::string str = Decode(_str);
122  if (!str.empty()) {
123  Write(&*str.begin(), 1, str.size());
124  }
125 }
126 
127 void LcfWriter::Write(const DBBitArray& bits) {
128  for (auto& b: bits) {
129  Write(static_cast<uint8_t>(b));
130  }
131 }
132 
133 uint32_t LcfWriter::Tell() {
134  return (uint32_t)stream.tellp();
135 }
136 
137 bool LcfWriter::IsOk() const {
138  return stream.good() && encoder.IsOk();
139 }
140 
141 std::string LcfWriter::Decode(StringView str) {
142  auto copy = std::string(str);
143  encoder.Decode(copy);
144  return copy;
145 }
146 
147 #ifdef WORDS_BIGENDIAN
148 void LcfWriter::SwapByteOrder(uint16_t& us)
149 {
150  us = (us >> 8) |
151  (us << 8);
152 }
153 
154 void LcfWriter::SwapByteOrder(uint32_t& ui)
155 {
156  ui = (ui >> 24) |
157  ((ui<<8) & 0x00FF0000) |
158  ((ui>>8) & 0x0000FF00) |
159  (ui << 24);
160 }
161 
162 void LcfWriter::SwapByteOrder(double& d)
163 {
164  uint32_t *p = reinterpret_cast<uint32_t *>(&d);
165  SwapByteOrder(p[0]);
166  SwapByteOrder(p[1]);
167  uint32_t tmp = p[0];
168  p[0] = p[1];
169  p[1] = tmp;
170 }
171 #else
172 void LcfWriter::SwapByteOrder(uint16_t& /* us */) {}
173 void LcfWriter::SwapByteOrder(uint32_t& /* ui */) {}
174 void LcfWriter::SwapByteOrder(double& /* d */) {}
175 #endif
176 
177 void LcfWriter::SwapByteOrder(int16_t& s)
178 {
179  SwapByteOrder((uint16_t&) s);
180 }
181 
182 void LcfWriter::SwapByteOrder(int32_t& s)
183 {
184  SwapByteOrder((uint32_t&) s);
185 }
186 
187 } //namespace lcf
Definition: dbarray.cpp:13