/src/librevenge/src/lib/RVNGBinaryData.cpp
Line | Count | Source |
1 | | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ |
2 | | /* librevenge |
3 | | * Version: MPL 2.0 / LGPLv2.1+ |
4 | | * |
5 | | * This Source Code Form is subject to the terms of the Mozilla Public |
6 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
7 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. |
8 | | * |
9 | | * Major Contributor(s): |
10 | | * Copyright (C) 2007 Fridrich Strba (fridrich.strba@bluewin.ch) |
11 | | * |
12 | | * For minor contributions see the git repository. |
13 | | * |
14 | | * Alternatively, the contents of this file may be used under the terms |
15 | | * of the GNU Lesser General Public License Version 2.1 or later |
16 | | * (LGPLv2.1+), in which case the provisions of the LGPLv2.1+ are |
17 | | * applicable instead of those above. |
18 | | */ |
19 | | |
20 | | #include <librevenge/librevenge.h> |
21 | | |
22 | | #include <boost/algorithm/string.hpp> |
23 | | #include <boost/archive/iterators/binary_from_base64.hpp> |
24 | | #include <boost/archive/iterators/base64_from_binary.hpp> |
25 | | #include <boost/archive/iterators/remove_whitespace.hpp> |
26 | | #include <boost/archive/iterators/transform_width.hpp> |
27 | | |
28 | | #include <algorithm> |
29 | | #include <iterator> |
30 | | #include <memory> |
31 | | #include <vector> |
32 | | #include <string> |
33 | | #include <stdarg.h> |
34 | | #include <stdio.h> |
35 | | |
36 | | #include "RVNGMemoryStream.h" |
37 | | |
38 | | |
39 | | namespace librevenge |
40 | | { |
41 | | |
42 | | namespace |
43 | | { |
44 | | |
45 | | struct DataImpl |
46 | | { |
47 | 133M | DataImpl() : m_buf(), m_stream() {} |
48 | | |
49 | | std::vector<unsigned char> m_buf; |
50 | | std::unique_ptr<RVNGMemoryInputStream> m_stream; |
51 | | }; |
52 | | |
53 | | void convertFromBase64(std::vector<unsigned char> &result, const std::string &source) |
54 | 10.0k | { |
55 | 10.0k | std::string::const_iterator paddingIter = std::find(source.begin(), source.end(), '='); |
56 | 10.0k | typedef boost::archive::iterators::transform_width< |
57 | 10.0k | boost::archive::iterators::binary_from_base64< |
58 | 10.0k | boost::archive::iterators::remove_whitespace< std::string::const_iterator > >, 8, 6 > base64_decoder; |
59 | | |
60 | 10.0k | std::copy(base64_decoder(source.begin()), base64_decoder(paddingIter), std::back_inserter(result)); |
61 | 10.0k | } |
62 | | |
63 | | void convertToBase64(std::string &result, const std::vector<unsigned char> &source) |
64 | 3.43M | { |
65 | 3.43M | auto numPadding = unsigned((3- (source.size()%3)) %3); |
66 | | |
67 | 3.43M | typedef boost::archive::iterators::base64_from_binary< |
68 | 3.43M | boost::archive::iterators::transform_width<std::vector<unsigned char>::const_iterator, 6, 8 > > base64_encoder; |
69 | | |
70 | | // Encode the buffer and create a string |
71 | 3.43M | result.insert(result.begin(), |
72 | 3.43M | base64_encoder(source.begin()), |
73 | 3.43M | base64_encoder(source.end())); |
74 | | |
75 | 3.43M | result.append(numPadding, '='); // add '=' for each padded character |
76 | 3.43M | } |
77 | | |
78 | | } // anonymous namespace |
79 | | |
80 | | struct RVNGBinaryDataImpl |
81 | | { |
82 | | RVNGBinaryDataImpl(); |
83 | | |
84 | | void makeUnique(); |
85 | | |
86 | | std::shared_ptr<DataImpl> m_ptr; |
87 | | }; |
88 | | |
89 | | RVNGBinaryDataImpl::RVNGBinaryDataImpl() |
90 | 133M | : m_ptr(new DataImpl()) |
91 | 133M | { |
92 | 133M | } |
93 | | |
94 | | void RVNGBinaryDataImpl::makeUnique() |
95 | 3.83G | { |
96 | 3.83G | if (!(m_ptr.use_count() == 1)) |
97 | 89.3k | { |
98 | 89.3k | std::shared_ptr<DataImpl> ptr(new DataImpl()); |
99 | 89.3k | ptr->m_buf = m_ptr->m_buf; |
100 | 89.3k | m_ptr = ptr; |
101 | 89.3k | } |
102 | 3.83G | } |
103 | | |
104 | | RVNGBinaryData::~RVNGBinaryData() |
105 | 133M | { |
106 | 133M | delete m_binaryDataImpl; |
107 | 133M | } |
108 | | |
109 | | RVNGBinaryData::RVNGBinaryData() : |
110 | 85.2M | m_binaryDataImpl(new RVNGBinaryDataImpl) |
111 | 85.2M | { |
112 | 85.2M | } |
113 | | |
114 | | RVNGBinaryData::RVNGBinaryData(const RVNGBinaryData &data) : |
115 | 47.1M | m_binaryDataImpl(new RVNGBinaryDataImpl) |
116 | 47.1M | { |
117 | 47.1M | m_binaryDataImpl->m_ptr = data.m_binaryDataImpl->m_ptr; |
118 | 47.1M | } |
119 | | |
120 | | RVNGBinaryData::RVNGBinaryData(const unsigned char *buffer, const unsigned long bufferSize) : |
121 | 1.16M | m_binaryDataImpl(nullptr) |
122 | 1.16M | { |
123 | 1.16M | std::unique_ptr<RVNGBinaryDataImpl> impl(new RVNGBinaryDataImpl()); |
124 | 1.16M | if (buffer) |
125 | 1.08M | impl->m_ptr->m_buf.assign(buffer, buffer + bufferSize); |
126 | 1.16M | m_binaryDataImpl = impl.release(); |
127 | 1.16M | } |
128 | | |
129 | | RVNGBinaryData::RVNGBinaryData(const RVNGString &base64) : |
130 | 0 | m_binaryDataImpl(nullptr) |
131 | 0 | { |
132 | 0 | std::unique_ptr<RVNGBinaryDataImpl> impl(new RVNGBinaryDataImpl()); |
133 | 0 | std::string base64String(base64.cstr(), base64.size()); |
134 | 0 | boost::trim(base64String); |
135 | 0 | convertFromBase64(impl->m_ptr->m_buf, base64String); |
136 | 0 | m_binaryDataImpl = impl.release(); |
137 | 0 | } |
138 | | |
139 | | RVNGBinaryData::RVNGBinaryData(const char *base64) : |
140 | 6.38k | m_binaryDataImpl(nullptr) |
141 | 6.38k | { |
142 | 6.38k | std::unique_ptr<RVNGBinaryDataImpl> impl(new RVNGBinaryDataImpl()); |
143 | 6.38k | if (base64) |
144 | 6.38k | { |
145 | 6.38k | std::string base64String(base64); |
146 | 6.38k | boost::trim(base64String); |
147 | 6.38k | convertFromBase64(impl->m_ptr->m_buf, base64String); |
148 | 6.38k | } |
149 | 6.38k | m_binaryDataImpl = impl.release(); |
150 | 6.38k | } |
151 | | |
152 | | void RVNGBinaryData::append(const RVNGBinaryData &data) |
153 | 2.05M | { |
154 | 2.05M | m_binaryDataImpl->makeUnique(); |
155 | | |
156 | 2.05M | m_binaryDataImpl->m_ptr->m_buf.insert( |
157 | 2.05M | m_binaryDataImpl->m_ptr->m_buf.end(), |
158 | 2.05M | data.m_binaryDataImpl->m_ptr->m_buf.begin(), |
159 | 2.05M | data.m_binaryDataImpl->m_ptr->m_buf.end()); |
160 | 2.05M | } |
161 | | |
162 | | void RVNGBinaryData::appendBase64Data(const RVNGString &base64) |
163 | 117 | { |
164 | 117 | std::string base64String(base64.cstr(), base64.size()); |
165 | 117 | boost::trim(base64String); |
166 | 117 | std::vector<unsigned char> buffer; |
167 | 117 | convertFromBase64(buffer, base64String); |
168 | 117 | if (!buffer.empty()) |
169 | 94 | append(buffer.data(), buffer.size()); |
170 | 117 | } |
171 | | |
172 | | void RVNGBinaryData::appendBase64Data(const char *base64) |
173 | 3.58k | { |
174 | 3.58k | if (base64) |
175 | 3.58k | { |
176 | 3.58k | std::string base64String(base64); |
177 | 3.58k | boost::trim(base64String); |
178 | 3.58k | std::vector<unsigned char> buffer; |
179 | 3.58k | convertFromBase64(buffer, base64String); |
180 | 3.58k | if (!buffer.empty()) |
181 | 1.10k | append(buffer.data(), buffer.size()); |
182 | 3.58k | } |
183 | 3.58k | } |
184 | | |
185 | | void RVNGBinaryData::append(const unsigned char *buffer, const unsigned long bufferSize) |
186 | 17.6M | { |
187 | 17.6M | if (buffer && bufferSize > 0) |
188 | 17.3M | { |
189 | 17.3M | m_binaryDataImpl->makeUnique(); |
190 | | |
191 | 17.3M | std::vector<unsigned char> &buf = m_binaryDataImpl->m_ptr->m_buf; |
192 | 17.3M | buf.reserve(buf.size() + bufferSize); |
193 | 17.3M | buf.insert(buf.end(), buffer, buffer + bufferSize); |
194 | 17.3M | } |
195 | 17.6M | } |
196 | | |
197 | | void RVNGBinaryData::append(const unsigned char c) |
198 | 3.80G | { |
199 | 3.80G | m_binaryDataImpl->makeUnique(); |
200 | | |
201 | 3.80G | m_binaryDataImpl->m_ptr->m_buf.push_back(c); |
202 | 3.80G | } |
203 | | |
204 | | void RVNGBinaryData::clear() |
205 | 16.3M | { |
206 | 16.3M | m_binaryDataImpl->makeUnique(); |
207 | | |
208 | | // clear and return allocated memory |
209 | 16.3M | std::vector<unsigned char>().swap(m_binaryDataImpl->m_ptr->m_buf); |
210 | 16.3M | } |
211 | | |
212 | | unsigned long RVNGBinaryData::size() const |
213 | 112M | { |
214 | 112M | return (unsigned long)m_binaryDataImpl->m_ptr->m_buf.size(); |
215 | 112M | } |
216 | | bool RVNGBinaryData::empty() const |
217 | 14.3M | { |
218 | 14.3M | return (unsigned long)m_binaryDataImpl->m_ptr->m_buf.empty(); |
219 | 14.3M | } |
220 | | |
221 | | RVNGBinaryData &RVNGBinaryData::operator=(const RVNGBinaryData &dataBuf) |
222 | 39.9M | { |
223 | 39.9M | m_binaryDataImpl->m_ptr = dataBuf.m_binaryDataImpl->m_ptr; |
224 | 39.9M | return *this; |
225 | 39.9M | } |
226 | | |
227 | | const unsigned char *RVNGBinaryData::getDataBuffer() const |
228 | 42.9M | { |
229 | 42.9M | if (m_binaryDataImpl->m_ptr->m_buf.empty()) |
230 | 195 | return nullptr; |
231 | 42.9M | return m_binaryDataImpl->m_ptr->m_buf.data(); |
232 | 42.9M | } |
233 | | |
234 | | const RVNGString RVNGBinaryData::getBase64Data() const |
235 | 3.43M | { |
236 | 3.43M | std::string base64; |
237 | 3.43M | base64.reserve(m_binaryDataImpl->m_ptr->m_buf.size() / 4 * 3); |
238 | 3.43M | convertToBase64(base64, m_binaryDataImpl->m_ptr->m_buf); |
239 | 3.43M | return RVNGString(std::move(base64)); |
240 | 3.43M | } |
241 | | |
242 | | RVNGInputStream *RVNGBinaryData::getDataStream() const |
243 | 6.84M | { |
244 | 6.84M | std::shared_ptr<DataImpl> data = m_binaryDataImpl->m_ptr; |
245 | 6.84M | if (data->m_stream) |
246 | 6 | { |
247 | 6 | data->m_stream.reset(); |
248 | 6 | } |
249 | 6.84M | if (data->m_buf.empty()) |
250 | 37 | return nullptr; |
251 | 6.84M | data->m_stream.reset(new RVNGMemoryInputStream(data->m_buf.data(), data->m_buf.size())); |
252 | 6.84M | return data->m_stream.get(); |
253 | 6.84M | } |
254 | | |
255 | | } |
256 | | |
257 | | /* vim:set shiftwidth=4 softtabstop=4 noexpandtab: */ |