Coverage Report

Created: 2026-09-06 07:18

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libfreehand/src/lib/libfreehand_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 libfreehand 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 <cstdarg>
11
#include <cstdio>
12
13
#include <unicode/utf8.h>
14
#include <unicode/utf16.h>
15
#include "libfreehand_utils.h"
16
17
namespace
18
{
19
20
static const unsigned _macRomanCharacterMap[] =
21
{
22
  0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027,
23
  0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
24
  0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037,
25
  0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
26
  0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047,
27
  0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
28
  0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057,
29
  0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
30
  0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067,
31
  0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
32
  0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077,
33
  0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x0020,
34
  0x00c4, 0x00c5, 0x00c7, 0x00c9, 0x00d1, 0x00d6, 0x00dc, 0x00e1,
35
  0x00e0, 0x00e2, 0x00e4, 0x00e3, 0x00e5, 0x00e7, 0x00e9, 0x00e8,
36
  0x00ea, 0x00eb, 0x00ed, 0x00ec, 0x00ee, 0x00ef, 0x00f1, 0x00f3,
37
  0x00f2, 0x00f4, 0x00f6, 0x00f5, 0x00fa, 0x00f9, 0x00fb, 0x00fc,
38
  0x2020, 0x00b0, 0x00a2, 0x00a3, 0x00a7, 0x2022, 0x00b6, 0x00df,
39
  0x00ae, 0x00a9, 0x2122, 0x00b4, 0x00a8, 0x2260, 0x00c6, 0x00d8,
40
  0x221e, 0x00b1, 0x2264, 0x2265, 0x00a5, 0x00b5, 0x2202, 0x2211,
41
  0x220f, 0x03c0, 0x222b, 0x00aa, 0x00ba, 0x03a9, 0x00e6, 0x00f8,
42
  0x00bf, 0x00a1, 0x00ac, 0x221a, 0x0192, 0x2248, 0x2206, 0x00ab,
43
  0x00bb, 0x2026, 0x00a0, 0x00c0, 0x00c3, 0x00d5, 0x0152, 0x0153,
44
  0x2013, 0x2014, 0x201c, 0x201d, 0x2018, 0x2019, 0x00f7, 0x25ca,
45
  0x00ff, 0x0178, 0x2044, 0x20ac, 0x2039, 0x203a, 0xfb01, 0xfb02,
46
  0x2021, 0x00b7, 0x201a, 0x201e, 0x2030, 0x00c2, 0x00ca, 0x00c1,
47
  0x00cb, 0x00c8, 0x00cd, 0x00ce, 0x00cf, 0x00cc, 0x00d3, 0x00d4,
48
  0xf8ff, 0x00d2, 0x00da, 0x00db, 0x00d9, 0x0131, 0x02c6, 0x02dc,
49
  0x00af, 0x02d8, 0x02d9, 0x02da, 0x00b8, 0x02dd, 0x02db, 0x02c7
50
};
51
52
}
53
54
#ifdef DEBUG
55
void libfreehand::debugPrint(const char *format, ...)
56
{
57
  va_list args;
58
  va_start(args, format);
59
  std::vfprintf(stderr, format, args);
60
  va_end(args);
61
}
62
#endif
63
64
uint8_t libfreehand::readU8(librevenge::RVNGInputStream *input)
65
15.5M
{
66
15.5M
  if (!input || input->isEnd())
67
326
  {
68
326
    FH_DEBUG_MSG(("Throwing EndOfStreamException\n"));
69
326
    throw EndOfStreamException();
70
326
  }
71
15.5M
  unsigned long numBytesRead;
72
15.5M
  uint8_t const *p = input->read(sizeof(uint8_t), numBytesRead);
73
74
15.5M
  if (p && numBytesRead == sizeof(uint8_t))
75
15.5M
    return *(uint8_t const *)(p);
76
0
  FH_DEBUG_MSG(("Throwing EndOfStreamException\n"));
77
0
  throw EndOfStreamException();
78
15.5M
}
79
80
int8_t libfreehand::readS8(librevenge::RVNGInputStream *input)
81
0
{
82
0
  return (int8_t)readU8(input);
83
0
}
84
85
uint16_t libfreehand::readU16(librevenge::RVNGInputStream *input)
86
93.0M
{
87
93.0M
  if (!input || input->isEnd())
88
2.52k
  {
89
2.52k
    FH_DEBUG_MSG(("Throwing EndOfStreamException\n"));
90
2.52k
    throw EndOfStreamException();
91
2.52k
  }
92
93.0M
  unsigned long numBytesRead;
93
93.0M
  uint8_t const *p = input->read(sizeof(uint16_t), numBytesRead);
94
95
93.0M
  if (p && numBytesRead == sizeof(uint16_t))
96
93.0M
    return (uint16_t)p[1]|((uint16_t)p[0]<<8);
97
98
816
  FH_DEBUG_MSG(("Throwing EndOfStreamException\n"));
99
816
  throw EndOfStreamException();
100
93.0M
}
101
102
int16_t libfreehand::readS16(librevenge::RVNGInputStream *input)
103
0
{
104
0
  return (int16_t)readU16(input);
105
0
}
106
107
uint32_t libfreehand::readU32(librevenge::RVNGInputStream *input)
108
22.2M
{
109
22.2M
  if (!input || input->isEnd())
110
535
  {
111
535
    FH_DEBUG_MSG(("Throwing EndOfStreamException\n"));
112
535
    throw EndOfStreamException();
113
535
  }
114
22.2M
  unsigned long numBytesRead;
115
22.2M
  uint8_t const *p = input->read(sizeof(uint32_t), numBytesRead);
116
117
22.2M
  if (p && numBytesRead == sizeof(uint32_t))
118
22.2M
    return (uint32_t)p[3]|((uint32_t)p[2]<<8)
119
22.2M
           |((uint32_t)p[1]<<16)|((uint32_t)p[0]<<24);
120
121
470
  FH_DEBUG_MSG(("Throwing EndOfStreamException\n"));
122
470
  throw EndOfStreamException();
123
22.2M
}
124
125
int32_t libfreehand::readS32(librevenge::RVNGInputStream *input)
126
17.4M
{
127
17.4M
  return (int32_t)readU32(input);
128
17.4M
}
129
130
unsigned long libfreehand::getRemainingLength(librevenge::RVNGInputStream *const input)
131
250k
{
132
250k
  if (!input || input->tell() < 0)
133
0
    throw EndOfStreamException();
134
135
250k
  const long begin = input->tell();
136
137
250k
  if (input->seek(0, librevenge::RVNG_SEEK_END) != 0)
138
0
  {
139
    // librevenge::RVNG_SEEK_END does not work. Use the harder way.
140
0
    while (!input->isEnd())
141
0
      readU8(input);
142
0
  }
143
250k
  const long end = input->tell();
144
145
250k
  if (input->seek(begin, librevenge::RVNG_SEEK_SET) != 0)
146
0
    throw EndOfStreamException();
147
148
250k
  if (end < begin)
149
0
    throw EndOfStreamException();
150
250k
  return static_cast<unsigned long>(end - begin);
151
250k
}
152
153
void libfreehand::_appendUTF16(librevenge::RVNGString &text, std::vector<unsigned short> &characters)
154
58.0k
{
155
58.0k
  if (characters.empty())
156
6.95k
    return;
157
158
51.0k
  const unsigned short *s = &characters[0];
159
51.0k
  int j = 0;
160
51.0k
  int length = characters.size();
161
162
1.70M
  while (j < length)
163
1.65M
  {
164
1.65M
    UChar32 c;
165
1.65M
    U16_NEXT(s, j, length, c);
166
1.65M
    unsigned char outbuf[U8_MAX_LENGTH+1];
167
1.65M
    int i = 0;
168
1.65M
    U8_APPEND_UNSAFE(&outbuf[0], i, c);
169
1.65M
    outbuf[i] = 0;
170
171
1.65M
    text.append((char *)outbuf);
172
1.65M
  }
173
51.0k
}
174
175
void libfreehand::writeU16(librevenge::RVNGBinaryData &buffer, const int value)
176
5.82k
{
177
5.82k
  buffer.append((unsigned char)(value & 0xFF));
178
5.82k
  buffer.append((unsigned char)((value >> 8) & 0xFF));
179
5.82k
}
180
181
void libfreehand::writeU32(librevenge::RVNGBinaryData &buffer, const int value)
182
87.3k
{
183
87.3k
  buffer.append((unsigned char)(value & 0xFF));
184
87.3k
  buffer.append((unsigned char)((value >> 8) & 0xFF));
185
87.3k
  buffer.append((unsigned char)((value >> 16) & 0xFF));
186
87.3k
  buffer.append((unsigned char)((value >> 24) & 0xFF));
187
87.3k
}
188
189
void libfreehand::_appendMacRoman(librevenge::RVNGString &text, unsigned char character)
190
1.74M
{
191
1.74M
  if (character < 0x20)
192
178k
    text.append((char)character);
193
1.56M
  else
194
1.56M
  {
195
    /* Mapping of Apple's MacRoman character set in Unicode */
196
197
1.56M
    UChar32 c = _macRomanCharacterMap[character - 0x20];
198
1.56M
    unsigned char outbuf[U8_MAX_LENGTH+1];
199
1.56M
    int i = 0;
200
1.56M
    U8_APPEND_UNSAFE(&outbuf[0], i, c);
201
1.56M
    outbuf[i] = 0;
202
203
1.56M
    text.append((char *)outbuf);
204
1.56M
  }
205
1.74M
}
206
207
208
/* vim:set shiftwidth=2 softtabstop=2 expandtab: */