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