Coverage Report

Created: 2026-06-13 06:44

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libcdr/src/lib/CDRInternalStream.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 libcdr 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 "CDRInternalStream.h"
11
12
#include <zlib.h>
13
#include <string.h>  // for memcpy
14
15
16
33.0k
#define CHUNK 16384
17
18
libcdr::CDRInternalStream::CDRInternalStream(const std::vector<unsigned char> &buffer) :
19
22.3k
  librevenge::RVNGInputStream(),
20
22.3k
  m_offset(0),
21
22.3k
  m_buffer(buffer)
22
22.3k
{
23
22.3k
}
24
25
libcdr::CDRInternalStream::CDRInternalStream(librevenge::RVNGInputStream *input, unsigned long size, bool compressed) :
26
226k
  librevenge::RVNGInputStream(),
27
226k
  m_offset(0),
28
226k
  m_buffer()
29
226k
{
30
226k
  if (!size)
31
3.37k
    return;
32
33
223k
  if (!compressed)
34
213k
  {
35
213k
    unsigned long tmpNumBytesRead = 0;
36
213k
    const unsigned char *tmpBuffer = input->read(size, tmpNumBytesRead);
37
38
213k
    if (size != tmpNumBytesRead)
39
26.5k
      return;
40
41
187k
    m_buffer = std::vector<unsigned char>(size);
42
187k
    memcpy(&m_buffer[0], tmpBuffer, size);
43
187k
  }
44
9.57k
  else
45
9.57k
  {
46
9.57k
    int ret;
47
9.57k
    z_stream strm;
48
9.57k
    unsigned char out[CHUNK];
49
50
    /* allocate inflate state */
51
9.57k
    strm.zalloc = Z_NULL;
52
9.57k
    strm.zfree = Z_NULL;
53
9.57k
    strm.opaque = Z_NULL;
54
9.57k
    strm.avail_in = 0;
55
9.57k
    strm.next_in = Z_NULL;
56
9.57k
    ret = inflateInit(&strm);
57
9.57k
    if (ret != Z_OK)
58
0
      return;
59
60
9.57k
    unsigned long tmpNumBytesRead = 0;
61
9.57k
    const unsigned char *tmpBuffer = input->read(size, tmpNumBytesRead);
62
63
9.57k
    if (size != tmpNumBytesRead)
64
360
    {
65
360
      (void)inflateEnd(&strm);
66
360
      return;
67
360
    }
68
69
9.21k
    strm.avail_in = (uInt)tmpNumBytesRead;
70
9.21k
    strm.next_in = const_cast<Bytef *>(tmpBuffer);
71
72
9.21k
    do
73
18.9k
    {
74
18.9k
      strm.avail_out = CHUNK;
75
18.9k
      strm.next_out = out;
76
18.9k
      ret = inflate(&strm, Z_NO_FLUSH);
77
18.9k
      switch (ret)
78
18.9k
      {
79
5
      case Z_NEED_DICT:
80
4.78k
      case Z_DATA_ERROR:
81
4.78k
      case Z_MEM_ERROR:
82
4.78k
        (void)inflateEnd(&strm);
83
4.78k
        m_buffer.clear();
84
4.78k
        return;
85
14.1k
      default:
86
14.1k
        break;
87
18.9k
      }
88
89
14.1k
      unsigned have = CHUNK - strm.avail_out;
90
91
163M
      for (unsigned long i=0; i<have; i++)
92
163M
        m_buffer.push_back(out[i]);
93
94
14.1k
    }
95
14.1k
    while (strm.avail_out == 0);
96
4.43k
    (void)inflateEnd(&strm);
97
4.43k
  }
98
223k
}
99
100
const unsigned char *libcdr::CDRInternalStream::read(unsigned long numBytes, unsigned long &numBytesRead)
101
6.28M
{
102
6.28M
  numBytesRead = 0;
103
104
6.28M
  if (numBytes == 0)
105
486
    return nullptr;
106
107
6.28M
  if (m_offset < 0)
108
0
    return nullptr;
109
110
6.28M
  const unsigned long bufSize = m_buffer.size();
111
6.28M
  const unsigned long pos = static_cast<unsigned long>(m_offset);
112
6.28M
  const unsigned long remaining = pos < bufSize ? bufSize - pos : 0;
113
6.28M
  const unsigned long numBytesToRead = numBytes < remaining ? numBytes : remaining;
114
115
6.28M
  numBytesRead = numBytesToRead; // about as paranoid as we can be..
116
117
6.28M
  if (numBytesToRead == 0)
118
127
    return nullptr;
119
120
6.28M
  long oldOffset = m_offset;
121
6.28M
  m_offset += numBytesToRead;
122
123
6.28M
  return &m_buffer[oldOffset];
124
6.28M
}
125
126
int libcdr::CDRInternalStream::seek(long offset, librevenge::RVNG_SEEK_TYPE seekType)
127
2.35M
{
128
2.35M
  if (seekType == librevenge::RVNG_SEEK_CUR)
129
993k
    m_offset += offset;
130
1.35M
  else if (seekType == librevenge::RVNG_SEEK_SET)
131
1.09M
    m_offset = offset;
132
263k
  else if (seekType == librevenge::RVNG_SEEK_END)
133
263k
    m_offset = long(static_cast<unsigned long>(m_buffer.size())) + offset;
134
135
2.35M
  if (m_offset < 0)
136
0
  {
137
0
    m_offset = 0;
138
0
    return 1;
139
0
  }
140
2.35M
  if ((long)m_offset > (long)m_buffer.size())
141
447k
  {
142
447k
    m_offset = m_buffer.size();
143
447k
    return 1;
144
447k
  }
145
146
1.90M
  return 0;
147
2.35M
}
148
149
long libcdr::CDRInternalStream::tell()
150
1.52M
{
151
1.52M
  return m_offset;
152
1.52M
}
153
154
bool libcdr::CDRInternalStream::isEnd()
155
9.97M
{
156
9.97M
  if ((long)m_offset >= (long)m_buffer.size())
157
248k
    return true;
158
159
9.72M
  return false;
160
9.97M
}
161
/* vim:set shiftwidth=2 softtabstop=2 expandtab: */