Coverage Report

Created: 2026-09-14 06:37

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libmwaw/src/lib/MWAWInputStream.hxx
Line
Count
Source
1
/* -*- Mode: C++; c-default-style: "k&r"; indent-tabs-mode: nil; tab-width: 2; c-basic-offset: 2 -*- */
2
3
/* libmwaw
4
* Version: MPL 2.0 / LGPLv2+
5
*
6
* The contents of this file are subject to the Mozilla Public License Version
7
* 2.0 (the "License"); you may not use this file except in compliance with
8
* the License or as specified alternatively below. You may obtain a copy of
9
* the License at http://www.mozilla.org/MPL/
10
*
11
* Software distributed under the License is distributed on an "AS IS" basis,
12
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13
* for the specific language governing rights and limitations under the
14
* License.
15
*
16
* Major Contributor(s):
17
* Copyright (C) 2002 William Lachance (wrlach@gmail.com)
18
* Copyright (C) 2002,2004 Marc Maurer (uwog@uwog.net)
19
* Copyright (C) 2004-2006 Fridrich Strba (fridrich.strba@bluewin.ch)
20
* Copyright (C) 2006, 2007 Andrew Ziem
21
* Copyright (C) 2011, 2012 Alonso Laurent (alonso@loria.fr)
22
*
23
*
24
* All Rights Reserved.
25
*
26
* For minor contributions see the git repository.
27
*
28
* Alternatively, the contents of this file may be used under the terms of
29
* the GNU Lesser General Public License Version 2 or later (the "LGPLv2+"),
30
* in which case the provisions of the LGPLv2+ are applicable
31
* instead of those above.
32
*/
33
34
#ifndef MWAW_INPUT_STREAM_H
35
#define MWAW_INPUT_STREAM_H
36
37
#include <string>
38
#include <vector>
39
40
#include <librevenge/librevenge.h>
41
#include <librevenge-stream/librevenge-stream.h>
42
#include "libmwaw_internal.hxx"
43
44
/*! \class MWAWInputStream
45
 * \brief Internal class used to read the file stream
46
 *  Internal class used to read the file stream,
47
 *    this class adds some usefull functions to the basic librevenge::RVNGInputStream:
48
 *  - read number (int8, int16, int32) in low or end endian
49
 *  - selection of a section of a stream
50
 *  - read block of data
51
 *  - interface with modified librevenge::RVNGOLEStream
52
 */
53
class MWAWInputStream
54
{
55
public:
56
  /*!\brief creates a stream with given endian
57
   * \param input the given input
58
   * \param inverted must be set to true for pc doc and ole part and to false for mac doc
59
   */
60
  MWAWInputStream(std::shared_ptr<librevenge::RVNGInputStream> input, bool inverted);
61
62
  /*!\brief creates a stream with given endian from an existing input
63
   *
64
   * Note: this functions does not delete input
65
   */
66
  MWAWInputStream(librevenge::RVNGInputStream *input, bool inverted, bool checkCompression=false);
67
  //! destructor
68
  ~MWAWInputStream();
69
70
  //! returns the basic librevenge::RVNGInputStream
71
  std::shared_ptr<librevenge::RVNGInputStream> input()
72
189M
  {
73
189M
    return m_stream;
74
189M
  }
75
  //! returns a new input stream corresponding to a librevenge::RVNGBinaryData
76
  static std::shared_ptr<MWAWInputStream> get(librevenge::RVNGBinaryData const &data, bool inverted);
77
78
  //! returns the endian mode (see constructor)
79
  bool readInverted() const
80
1.26M
  {
81
1.26M
    return m_inverseRead;
82
1.26M
  }
83
  //! sets the endian mode
84
  void setReadInverted(bool newVal)
85
6.58M
  {
86
6.58M
    m_inverseRead = newVal;
87
6.58M
  }
88
  //
89
  // Position: access
90
  //
91
92
  /*! \brief seeks to a offset position, from actual, beginning or ending position
93
   * \return 0 if ok
94
   * \sa pushLimit popLimit
95
   */
96
  int seek(long offset, librevenge::RVNG_SEEK_TYPE seekType);
97
  //! returns actual offset position
98
  long tell();
99
  //! returns the stream size
100
  long size() const
101
24.9G
  {
102
24.9G
    return m_streamSize;
103
24.9G
  }
104
  //! checks if a position is or not a valid file position
105
  bool checkPosition(long pos) const
106
973M
  {
107
973M
    if (pos < 0) return false;
108
971M
    if (m_readLimit > 0 && pos > m_readLimit) return false;
109
949M
    return pos<=m_streamSize;
110
971M
  }
111
  //! returns true if we are at the end of the section/file
112
  bool isEnd();
113
114
  /*! \brief defines a new section in the file (from actualPos to newLimit)
115
   * next call of seek, tell, atEos, ... will be restrained to this section
116
   */
117
  void pushLimit(long newLimit)
118
1.89M
  {
119
1.89M
    m_prevLimits.push_back(m_readLimit);
120
1.89M
    m_readLimit = newLimit > m_streamSize ? m_streamSize : newLimit;
121
1.89M
  }
122
  //! pops a section defined by pushLimit
123
  void popLimit()
124
1.89M
  {
125
1.89M
    if (!m_prevLimits.empty()) {
126
1.89M
      m_readLimit = m_prevLimits.back();
127
1.89M
      m_prevLimits.pop_back();
128
1.89M
    }
129
0
    else m_readLimit = -1;
130
1.89M
  }
131
132
  /*! internal: recomputes the stream size, must be called after you modify the data of the main input
133
134
    For instance, if this input stream is created from a MWAWStringStream and you decide to add some data
135
    in the original MWAWStringStream...
136
   */
137
  void recomputeStreamSize();
138
139
  //
140
  // get data
141
  //
142
143
  //! returns a uint8, uint16, uint32 readed from actualPos
144
  unsigned long readULong(int num)
145
62.6G
  {
146
62.6G
    return readULong(m_stream.get(), num, 0, m_inverseRead);
147
62.6G
  }
148
  //! return a int8, int16, int32 readed from actualPos
149
  long readLong(int num);
150
  //! try to read a double of size 8: 1.5 bytes exponent, 6.5 bytes mantisse
151
  bool readDouble8(double &res, bool &isNotANumber);
152
  //! try to read a double of size 8: 6.5 bytes mantisse, 1.5 bytes exponent
153
  bool readDoubleReverted8(double &res, bool &isNotANumber);
154
  //! try to read a double of size 10: 2 bytes exponent, 8 bytes mantisse
155
  bool readDouble10(double &res, bool &isNotANumber);
156
157
  /**! reads numbytes data, WITHOUT using any endian or section consideration
158
   * \return a pointer to the read elements
159
   */
160
  const uint8_t *read(size_t numBytes, unsigned long &numBytesRead);
161
  /*! \brief internal function used to read num byte,
162
   *  - where a is the previous read data
163
   */
164
  static unsigned long readULong(librevenge::RVNGInputStream *stream, int num, unsigned long a, bool inverseRead);
165
166
  //! reads a librevenge::RVNGBinaryData with a given size in the actual section/file
167
  bool readDataBlock(long size, librevenge::RVNGBinaryData &data);
168
  //! reads a librevenge::RVNGBinaryData from actPos to the end of the section/file
169
  bool readEndDataBlock(librevenge::RVNGBinaryData &data);
170
171
  //
172
  // OLE/Zip access
173
  //
174
175
  //! return true if the stream is ole
176
  bool isStructured();
177
  //! returns the number of substream
178
  unsigned subStreamCount();
179
  //! returns the name of the i^th substream
180
  std::string subStreamName(unsigned id);
181
182
  //! return a new stream for a ole zone
183
  std::shared_ptr<MWAWInputStream> getSubStreamByName(std::string const &name);
184
  //! return a new stream for a ole zone
185
  std::shared_ptr<MWAWInputStream> getSubStreamById(unsigned id);
186
187
  //
188
  // Finder Info access
189
  //
190
  /** returns the finder info type and creator (if known) */
191
  bool getFinderInfo(std::string &type, std::string &creator) const
192
1.41M
  {
193
1.41M
    if (!m_fInfoType.length() || !m_fInfoCreator.length()) {
194
1.33M
      type = creator = "";
195
1.33M
      return false;
196
1.33M
    }
197
79.6k
    type = m_fInfoType;
198
79.6k
    creator = m_fInfoCreator;
199
79.6k
    return true;
200
1.41M
  }
201
202
  //
203
  // Resource Fork access
204
  //
205
206
  /** returns true if the data fork block exists */
207
  bool hasDataFork() const
208
41.8G
  {
209
41.8G
    return bool(m_stream);
210
41.8G
  }
211
  /** returns true if the resource fork block exists */
212
  bool hasResourceFork() const
213
1.41M
  {
214
1.41M
    return bool(m_resourceFork);
215
1.41M
  }
216
  /** returns the resource fork if find */
217
  std::shared_ptr<MWAWInputStream> getResourceForkStream()
218
1.44M
  {
219
1.44M
    return m_resourceFork;
220
1.44M
  }
221
222
223
protected:
224
  //! update the stream size ( must be called in the constructor )
225
  void updateStreamSize();
226
  //! internal function used to read a byte
227
  static uint8_t readU8(librevenge::RVNGInputStream *stream);
228
229
  //! unbinhex the data in the file is a BinHex 4.0 file of a mac file
230
  bool unBinHex();
231
  //! unzip the data in the file is a zip file of a mac file
232
  bool unzipStream();
233
  //! check if some stream are in MacMIME format, if so de MacMIME
234
  bool unMacMIME();
235
  //! de MacMIME an input stream
236
  bool unMacMIME(MWAWInputStream *input,
237
                 std::shared_ptr<librevenge::RVNGInputStream> &dataInput,
238
                 std::shared_ptr<librevenge::RVNGInputStream> &rsrcInput) const;
239
  //! check if a stream is an internal merge stream
240
  bool unsplitInternalMergeStream();
241
242
private:
243
  MWAWInputStream(MWAWInputStream const &orig) = delete;
244
  MWAWInputStream &operator=(MWAWInputStream const &orig) = delete;
245
246
protected:
247
  //! the initial input
248
  std::shared_ptr<librevenge::RVNGInputStream> m_stream;
249
  //! the stream size
250
  long m_streamSize;
251
252
  //! actual section limit (-1 if no limit)
253
  long m_readLimit;
254
  //! list of previous limits
255
  std::vector<long> m_prevLimits;
256
257
  //! finder info type
258
  mutable std::string m_fInfoType;
259
  //! finder info type
260
  mutable std::string m_fInfoCreator;
261
  //! the resource fork
262
  std::shared_ptr<MWAWInputStream> m_resourceFork;
263
  //! big or normal endian
264
  bool m_inverseRead;
265
};
266
267
#endif
268
// vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab: