Coverage Report

Created: 2026-07-20 07:04

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libpagemaker/src/lib/libpagemaker_utils.cpp
Line
Count
Source
1
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2
/*
3
 * This file is part of the libpagemaker project.
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
10
#include "libpagemaker_utils.h"
11
12
#include <cassert>
13
#include <cstdarg>
14
15
namespace libpagemaker
16
{
17
18
namespace
19
{
20
21
void checkStream(const RVNGInputStreamPtr &input)
22
1.72M
{
23
1.72M
  if (!input || input->isEnd())
24
0
    throw EndOfStreamException();
25
1.72M
}
26
27
struct SeekFailedException : public PMDStreamException {};
28
29
}
30
31
#ifdef DEBUG
32
void debugPrint(const char *const format, ...)
33
{
34
  va_list args;
35
  va_start(args, format);
36
  std::vfprintf(stderr, format, args);
37
  va_end(args);
38
}
39
#endif
40
41
uint8_t readU8(const RVNGInputStreamPtr &input, bool /* bigEndian */)
42
69
{
43
69
  checkStream(input);
44
45
69
  unsigned long numBytesRead;
46
69
  uint8_t const *p = input->read(sizeof(uint8_t), numBytesRead);
47
48
69
  if (p && numBytesRead == sizeof(uint8_t))
49
69
    return *(uint8_t const *)(p);
50
0
  throw EndOfStreamException();
51
69
}
52
53
int8_t readS8(const RVNGInputStreamPtr &input, bool /* bigEndian */)
54
0
{
55
0
  return static_cast<int8_t>(readU8(input));
56
0
}
57
58
uint16_t readU16(const RVNGInputStreamPtr &input, bool bigEndian)
59
1.03M
{
60
1.03M
  checkStream(input);
61
62
1.03M
  unsigned long numBytesRead;
63
1.03M
  uint8_t const *p = input->read(sizeof(uint16_t), numBytesRead);
64
65
1.03M
  if (p && numBytesRead == sizeof(uint16_t))
66
1.03M
  {
67
1.03M
    if (bigEndian)
68
1.03M
      return static_cast<uint16_t>((uint16_t)p[1]|((uint16_t)p[0]<<8));
69
3
    return static_cast<uint16_t>((uint16_t)p[0]|((uint16_t)p[1]<<8));
70
1.03M
  }
71
0
  throw EndOfStreamException();
72
1.03M
}
73
74
int16_t readS16(const RVNGInputStreamPtr &input, const bool bigEndian)
75
1.03M
{
76
1.03M
  return static_cast<int16_t>(readU16(input, bigEndian));
77
1.03M
}
78
79
uint32_t readU32(const RVNGInputStreamPtr &input, bool bigEndian)
80
516k
{
81
516k
  checkStream(input);
82
83
516k
  unsigned long numBytesRead;
84
516k
  uint8_t const *p = input->read(sizeof(uint32_t), numBytesRead);
85
86
516k
  if (p && numBytesRead == sizeof(uint32_t))
87
516k
  {
88
516k
    if (bigEndian)
89
516k
      return (uint32_t)p[3]|((uint32_t)p[2]<<8)|((uint32_t)p[1]<<16)|((uint32_t)p[0]<<24);
90
0
    return (uint32_t)p[0]|((uint32_t)p[1]<<8)|((uint32_t)p[2]<<16)|((uint32_t)p[3]<<24);
91
516k
  }
92
0
  throw EndOfStreamException();
93
516k
}
94
95
int32_t readS32(const RVNGInputStreamPtr &input, const bool bigEndian)
96
0
{
97
0
  return static_cast<int32_t>(readU32(input, bigEndian));
98
0
}
99
100
uint64_t readU64(const RVNGInputStreamPtr &input, bool bigEndian)
101
0
{
102
0
  checkStream(input);
103
104
0
  unsigned long numBytesRead;
105
0
  uint8_t const *p = input->read(sizeof(uint64_t), numBytesRead);
106
107
0
  if (p && numBytesRead == sizeof(uint64_t))
108
0
  {
109
0
    if (bigEndian)
110
0
      return (uint64_t)p[7]|((uint64_t)p[6]<<8)|((uint64_t)p[5]<<16)|((uint64_t)p[4]<<24)|((uint64_t)p[3]<<32)|((uint64_t)p[2]<<40)|((uint64_t)p[1]<<48)|((uint64_t)p[0]<<56);
111
0
    return (uint64_t)p[0]|((uint64_t)p[1]<<8)|((uint64_t)p[2]<<16)|((uint64_t)p[3]<<24)|((uint64_t)p[4]<<32)|((uint64_t)p[5]<<40)|((uint64_t)p[6]<<48)|((uint64_t)p[7]<<56);
112
0
  }
113
0
  throw EndOfStreamException();
114
0
}
115
116
int64_t readS64(const RVNGInputStreamPtr &input, const bool bigEndian)
117
0
{
118
0
  return static_cast<int64_t>(readU64(input, bigEndian));
119
0
}
120
121
const unsigned char *readNBytes(const RVNGInputStreamPtr &input, const unsigned long numBytes)
122
0
{
123
0
  checkStream(input);
124
125
0
  unsigned long readBytes = 0;
126
0
  const unsigned char *const s = input->read(numBytes, readBytes);
127
128
0
  if (numBytes != readBytes)
129
0
    throw EndOfStreamException();
130
131
0
  return s;
132
0
}
133
134
void skip(const RVNGInputStreamPtr &input, unsigned long numBytes)
135
172k
{
136
172k
  checkStream(input);
137
138
172k
  seekRelative(input, static_cast<long>(numBytes));
139
172k
}
140
141
void seek(const RVNGInputStreamPtr &input, const unsigned long pos)
142
172k
{
143
172k
  if (!input)
144
0
    throw EndOfStreamException();
145
146
172k
  if (0 != input->seek(static_cast<long>(pos), librevenge::RVNG_SEEK_SET))
147
6
    throw SeekFailedException();
148
172k
}
149
150
void seekRelative(const RVNGInputStreamPtr &input, const long pos)
151
172k
{
152
172k
  if (!input)
153
0
    throw EndOfStreamException();
154
155
172k
  if (0 != input->seek(pos, librevenge::RVNG_SEEK_CUR))
156
0
    throw SeekFailedException();
157
172k
}
158
159
unsigned long getLength(const RVNGInputStreamPtr &input)
160
4
{
161
4
  if (!input)
162
1
    throw EndOfStreamException();
163
164
3
  const long orig = input->tell();
165
3
  unsigned long end = 0;
166
167
3
  if (0 == input->seek(0, librevenge::RVNG_SEEK_END))
168
3
    end = static_cast<unsigned long>(input->tell());
169
0
  else
170
0
  {
171
    // RVNG_SEEK_END does not work. Use the harder way.
172
0
    seek(input, 0);
173
0
    while (!input->isEnd())
174
0
    {
175
0
      readU8(input);
176
0
      ++end;
177
0
    }
178
0
  }
179
180
3
  seek(input, orig);
181
182
3
  return end;
183
4
}
184
185
EndOfStreamException::EndOfStreamException()
186
1
{
187
1
}
188
189
}
190
191
/* vim:set shiftwidth=2 softtabstop=2 expandtab: */