Coverage Report

Created: 2026-09-14 06:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libvisio/src/lib/VSDInternalStream.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 libvisio 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 "VSDInternalStream.h"
11
12
#include <string.h>
13
14
VSDInternalStream::VSDInternalStream(librevenge::RVNGInputStream *input, unsigned long size, bool compressed) :
15
9.39M
  librevenge::RVNGInputStream(),
16
9.39M
  m_offset(0),
17
9.39M
  m_buffer()
18
9.39M
{
19
9.39M
  unsigned long tmpNumBytesRead = 0;
20
21
9.39M
  const unsigned char *tmpBuffer = input->read(size, tmpNumBytesRead);
22
23
9.39M
  if (tmpNumBytesRead < 2)
24
7.85M
    return;
25
26
1.54M
  if (!compressed)
27
1.17M
  {
28
1.17M
    m_buffer.assign(tmpBuffer, tmpBuffer + tmpNumBytesRead);
29
1.17M
  }
30
372k
  else
31
372k
  {
32
372k
    unsigned char buffer[4096] = { 0 };
33
372k
    unsigned pos = 0;
34
372k
    unsigned offset = 0;
35
36
161M
    while (offset < tmpNumBytesRead)
37
161M
    {
38
161M
      unsigned flag = tmpBuffer[offset++];
39
161M
      if (offset > tmpNumBytesRead-1)
40
103k
        break;
41
42
161M
      unsigned mask = 1;
43
1.45G
      for (unsigned bit = 0; bit < 8 && offset < tmpNumBytesRead; ++bit)
44
1.28G
      {
45
1.28G
        if (flag & mask)
46
511M
        {
47
511M
          buffer[pos&4095] = tmpBuffer[offset++];
48
511M
          m_buffer.push_back(buffer[pos&4095]);
49
511M
          pos++;
50
511M
        }
51
778M
        else
52
778M
        {
53
778M
          if (offset > tmpNumBytesRead-2)
54
85.3k
            break;
55
778M
          unsigned char addr1 = tmpBuffer[offset++];
56
778M
          unsigned char addr2 = tmpBuffer[offset++];
57
58
778M
          unsigned length = (addr2&15) + 3;
59
778M
          unsigned pointer = (((unsigned)addr2 & 0xF0) << 4) | addr1;
60
778M
          if (pointer > 4078)
61
10.1M
            pointer -= 4078;
62
767M
          else
63
767M
            pointer += 18;
64
65
8.24G
          for (unsigned j = 0; j < length; ++j)
66
7.46G
          {
67
7.46G
            buffer[(pos+j) & 4095] = buffer[(pointer+j) & 4095];
68
7.46G
            m_buffer.push_back(buffer[(pointer+j) & 4095]);
69
7.46G
          }
70
778M
          pos += length;
71
778M
        }
72
1.28G
        mask = mask << 1;
73
1.28G
      }
74
161M
    }
75
372k
  }
76
1.54M
}
77
78
const unsigned char *VSDInternalStream::read(unsigned long numBytes, unsigned long &numBytesRead)
79
1.51G
{
80
1.51G
  numBytesRead = 0;
81
82
1.51G
  if (numBytes == 0)
83
149k
    return nullptr;
84
85
1.51G
  int numBytesToRead;
86
87
1.51G
  if (numBytes < m_buffer.size() - m_offset)
88
1.50G
    numBytesToRead = numBytes;
89
1.13M
  else
90
1.13M
    numBytesToRead = m_buffer.size() - m_offset;
91
92
1.51G
  numBytesRead = numBytesToRead; // about as paranoid as we can be..
93
94
1.51G
  if (numBytesToRead == 0)
95
6.57k
    return nullptr;
96
97
1.51G
  long oldOffset = m_offset;
98
1.51G
  m_offset += numBytesToRead;
99
100
1.51G
  return &m_buffer[oldOffset];
101
1.51G
}
102
103
int VSDInternalStream::seek(long offset, librevenge::RVNG_SEEK_TYPE seekType)
104
75.6M
{
105
75.6M
  if (seekType == librevenge::RVNG_SEEK_CUR)
106
64.9M
    m_offset += offset;
107
10.6M
  else if (seekType == librevenge::RVNG_SEEK_SET)
108
10.4M
    m_offset = offset;
109
255k
  else if (seekType == librevenge::RVNG_SEEK_END)
110
255k
    m_offset = long(static_cast<unsigned long>(m_buffer.size())) + offset;
111
112
75.6M
  if (m_offset < 0)
113
46.0k
  {
114
46.0k
    m_offset = 0;
115
46.0k
    return 1;
116
46.0k
  }
117
75.5M
  if ((long)m_offset > (long)m_buffer.size())
118
1.45M
  {
119
1.45M
    m_offset = m_buffer.size();
120
1.45M
    return 1;
121
1.45M
  }
122
123
74.1M
  return 0;
124
75.5M
}
125
126
long VSDInternalStream::tell()
127
514M
{
128
514M
  return m_offset;
129
514M
}
130
131
bool VSDInternalStream::isEnd()
132
2.11G
{
133
2.11G
  if ((long)m_offset >= (long)m_buffer.size())
134
3.66M
    return true;
135
136
2.11G
  return false;
137
2.11G
}
138
/* vim:set shiftwidth=2 softtabstop=2 expandtab: */