Coverage Report

Created: 2026-07-20 07:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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: */