liblcf
Loading...
Searching...
No Matches
writer_lcf.cpp
Go to the documentation of this file.
1/*
2 * This file is part of liblcf. Copyright (c) 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
14namespace lcf {
15
16LcfWriter::LcfWriter(std::ostream& filestream, EngineVersion engine, std::string encoding)
17 : stream(filestream)
18 , encoder(std::move(encoding))
19 , engine(engine)
20{
21}
22
23void 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
28template <>
29void LcfWriter::Write<int8_t>(int8_t val) {
30 Write(&val, 1, 1);
31}
32
33template <>
34void LcfWriter::Write<uint8_t>(uint8_t val) {
35 Write(&val, 1, 1);
36}
37
38template <>
39void LcfWriter::Write<int16_t>(int16_t val) {
40 SwapByteOrder(val);
41 Write(&val, 2, 1);
42}
43
44template <>
45void LcfWriter::Write<uint32_t>(uint32_t val) {
46 SwapByteOrder(val);
47 Write(&val, 4, 1);
48}
49
50void 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
57void LcfWriter::WriteUInt64(uint64_t value) {
58 for (int i = 56; i >= 0; i -= 7)
59 if (value >= (1ULL << i) || i == 0)
60 Write<uint8_t>((uint8_t)(((value >> i) & 0x7F) | (i > 0 ? 0x80 : 0)));
61}
62
63template <>
64void LcfWriter::Write<int32_t>(int32_t val) {
65 WriteInt(val);
66}
67
68template <>
69void LcfWriter::Write<bool>(bool val) {
70 uint8_t x = val ? 1 : 0;
71 Write(x);
72}
73
74template <>
75void LcfWriter::Write<double>(double val) {
76 SwapByteOrder(val);
77 Write(&val, 8, 1);
78}
79
80template <>
81void LcfWriter::Write<bool>(const std::vector<bool>& buffer) {
82 std::vector<bool>::const_iterator it;
83 for (it = buffer.begin(); it != buffer.end(); it++) {
84 uint8_t val = *it ? 1 : 0;
85 Write(val);
86 }
87}
88
89template <>
90void LcfWriter::Write<uint8_t>(const std::vector<uint8_t>& buffer) {
91 Write(&buffer.front(), 1, buffer.size());
92}
93
94template <>
95void LcfWriter::Write<int16_t>(const std::vector<int16_t>& buffer) {
96 std::vector<int16_t>::const_iterator it;
97 for (it = buffer.begin(); it != buffer.end(); it++)
98 Write(*it);
99}
100
101template <>
102void LcfWriter::Write<int32_t>(const std::vector<int32_t>& buffer) {
103 std::vector<int32_t>::const_iterator it;
104 for (it = buffer.begin(); it != buffer.end(); it++) {
105 int32_t val = *it;
106 SwapByteOrder(val);
107 // Write<int32_t> writes a compressed integer
108 Write(&val, 4, 1);
109 }
110}
111
112template <>
113void LcfWriter::Write<uint32_t>(const std::vector<uint32_t>& buffer) {
114 std::vector<uint32_t>::const_iterator it;
115 for (it = buffer.begin(); it != buffer.end(); it++)
116 Write(*it);
117}
118
119void LcfWriter::Write(const std::string& _str) {
120 std::string str = Decode(_str);
121 if (!str.empty()) {
122 Write(&*str.begin(), 1, str.size());
123 }
124}
125
126void LcfWriter::Write(const DBString& _str) {
127 std::string str = Decode(_str);
128 if (!str.empty()) {
129 Write(&*str.begin(), 1, str.size());
130 }
131}
132
133void LcfWriter::Write(const DBBitArray& bits) {
134 for (auto& b: bits) {
135 Write(static_cast<uint8_t>(b));
136 }
137}
138
139uint32_t LcfWriter::Tell() {
140 return (uint32_t)stream.tellp();
141}
142
143bool LcfWriter::IsOk() const {
144 return stream.good() && encoder.IsOk();
145}
146
147std::string LcfWriter::Decode(std::string_view str) {
148 auto copy = std::string(str);
149 encoder.Decode(copy);
150 return copy;
151}
152
153#ifdef WORDS_BIGENDIAN
154void LcfWriter::SwapByteOrder(uint16_t& us)
155{
156 us = (us >> 8) |
157 (us << 8);
158}
159
160void LcfWriter::SwapByteOrder(uint32_t& ui)
161{
162 ui = (ui >> 24) |
163 ((ui<<8) & 0x00FF0000) |
164 ((ui>>8) & 0x0000FF00) |
165 (ui << 24);
166}
167
168void LcfWriter::SwapByteOrder(double& d)
169{
170 char *p = reinterpret_cast<char*>(&d);
171 std::swap(p[0], p[7]);
172 std::swap(p[1], p[6]);
173 std::swap(p[2], p[5]);
174 std::swap(p[3], p[4]);
175}
176#else
177void LcfWriter::SwapByteOrder(uint16_t& /* us */) {}
178void LcfWriter::SwapByteOrder(uint32_t& /* ui */) {}
179void LcfWriter::SwapByteOrder(double& /* d */) {}
180#endif
181
182void LcfWriter::SwapByteOrder(int16_t& s)
183{
184 SwapByteOrder((uint16_t&) s);
185}
186
187void LcfWriter::SwapByteOrder(int32_t& s)
188{
189 SwapByteOrder((uint32_t&) s);
190}
191
192} //namespace lcf