1 /* -*- Mode: C++; c-default-style: "k&r"; indent-tabs-mode: nil; tab-width: 2; c-basic-offset: 2 -*- */
2 
3 /* libstaroffice
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 STOFF_INPUT_STREAM_H
35 #define STOFF_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 "libstaroffice_internal.hxx"
43 
44 /*! \class STOFFInputStream
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 STOFFInputStream
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   STOFFInputStream(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   STOFFInputStream(librevenge::RVNGInputStream *input, bool inverted);
67   //! destructor
68   ~STOFFInputStream();
69 
70   //! returns the basic librevenge::RVNGInputStream
input()71   std::shared_ptr<librevenge::RVNGInputStream> input()
72   {
73     return m_stream;
74   }
75   //! returns a new input stream corresponding to a librevenge::RVNGBinaryData
76   static std::shared_ptr<STOFFInputStream> get(librevenge::RVNGBinaryData const &data, bool inverted);
77 
78   //! returns the endian mode (see constructor)
readInverted() const79   bool readInverted() const
80   {
81     return m_inverseRead;
82   }
83   //! sets the endian mode
setReadInverted(bool newVal)84   void setReadInverted(bool newVal)
85   {
86     m_inverseRead = newVal;
87   }
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    */
95   int seek(long offset, librevenge::RVNG_SEEK_TYPE seekType);
96   //! returns actual offset position
97   long tell();
98   //! returns the stream size
size() const99   long size() const
100   {
101     return m_streamSize;
102   }
103   //! checks if a position is or not a valid file position
checkPosition(long pos) const104   bool checkPosition(long pos) const
105   {
106     if (pos < 0) return false;
107     return pos<=m_streamSize;
108   }
109   //! returns true if we are at the end of the section/file
110   bool isEnd();
111 
112   //
113   // get data
114   //
115 
116   //! returns the value of the next caracters or -1, but does not increment the position counter
117   int peek();
118   //! operator>> for bool
operator >>(bool & res)119   STOFFInputStream &operator>>(bool &res)
120   {
121     res=readULong(1)!=0 ? true : false;
122     return *this;
123   }
124   //! operator>> for uint8_t
operator >>(uint8_t & res)125   STOFFInputStream &operator>>(uint8_t &res)
126   {
127     res=static_cast<uint8_t>(readULong(1));
128     return *this;
129   }
130   //! operator>> for int8_t
operator >>(int8_t & res)131   STOFFInputStream &operator>>(int8_t &res)
132   {
133     res=static_cast<int8_t>(readLong(1));
134     return *this;
135   }
136   //! operator>> for uint16_t
operator >>(uint16_t & res)137   STOFFInputStream &operator>>(uint16_t &res)
138   {
139     res=static_cast<uint16_t>(readULong(2));
140     return *this;
141   }
142   //! operator>> for int16_t
operator >>(int16_t & res)143   STOFFInputStream &operator>>(int16_t &res)
144   {
145     res=static_cast<int16_t>(readLong(2));
146     return *this;
147   }
148   //! operator>> for uint32_t
operator >>(uint32_t & res)149   STOFFInputStream &operator>>(uint32_t &res)
150   {
151     res=static_cast<uint32_t>(readULong(4));
152     return *this;
153   }
154   //! operator>> for int32_t
operator >>(int32_t & res)155   STOFFInputStream &operator>>(int32_t &res)
156   {
157     res=static_cast<int32_t>(readLong(4));
158     return *this;
159   }
160   //! operator>> for double
operator >>(double & res)161   STOFFInputStream &operator>>(double &res)
162   {
163     bool isNan;
164     long pos=tell();
165     if (!readDoubleReverted8(res, isNan)) {
166       STOFF_DEBUG_MSG(("STOFFInputStream::operator>>: can not read a double\n"));
167       seek(pos+8, librevenge::RVNG_SEEK_SET);
168       res=0;
169     }
170     return *this;
171   }
172   //! returns a uint8, uint16, uint32 readed from actualPos
readULong(int num)173   unsigned long readULong(int num)
174   {
175     return readULong(m_stream.get(), num, 0, m_inverseRead);
176   }
177   //! return a int8, int16, int32 readed from actualPos
178   long readLong(int num);
179   //! try to read a color
180   bool readColor(STOFFColor &color);
181   //! read a compressed long (pstm.cxx:ReadCompressed)
182   bool readCompressedLong(long &res);
183   //! read a compressed unsigned long (sw_sw3imp.cxx Sw3IoImp::InULong)
184   bool readCompressedULong(unsigned long &res);
185   //! try to read a double of size 8: 1.5 bytes exponent, 6.5 bytes mantisse
186   bool readDouble8(double &res, bool &isNotANumber);
187   //! try to read a double of size 8: 6.5 bytes mantisse, 1.5 bytes exponent
188   bool readDoubleReverted8(double &res, bool &isNotANumber);
189   //! try to read a double of size 10: 2 bytes exponent, 8 bytes mantisse
190   bool readDouble10(double &res, bool &isNotANumber);
191   /**! reads numbytes data, WITHOUT using any endian or section consideration
192    * \return a pointer to the read elements
193    */
194   const uint8_t *read(size_t numBytes, unsigned long &numBytesRead);
195   /*! \brief internal function used to read num byte,
196    *  - where a is the previous read data
197    */
198   static unsigned long readULong(librevenge::RVNGInputStream *stream, int num, unsigned long a, bool inverseRead);
199 
200   //! reads a librevenge::RVNGBinaryData with a given size in the actual section/file
201   bool readDataBlock(long size, librevenge::RVNGBinaryData &data);
202   //! reads a librevenge::RVNGBinaryData from actPos to the end of the section/file
203   bool readEndDataBlock(librevenge::RVNGBinaryData &data);
204 
205   //
206   // OLE/Zip access
207   //
208 
209   //! return true if the stream is ole
210   bool isStructured();
211   //! returns the number of substream
212   unsigned subStreamCount();
213   //! returns the name of the i^th substream
214   std::string subStreamName(unsigned id);
215 
216   //! return a new stream for a ole zone
217   std::shared_ptr<STOFFInputStream> getSubStreamByName(std::string const &name);
218   //! return a new stream for a ole zone
219   std::shared_ptr<STOFFInputStream> getSubStreamById(unsigned id);
220 
221   //
222   // Resource Fork access
223   //
224 
225   /** returns true if the data fork block exists */
hasDataFork() const226   bool hasDataFork() const
227   {
228     return bool(m_stream);
229   }
230 
231 protected:
232   //! update the stream size ( must be called in the constructor )
233   void updateStreamSize();
234   //! internal function used to read a byte
235   static uint8_t readU8(librevenge::RVNGInputStream *stream);
236 
237 private:
238   STOFFInputStream(STOFFInputStream const &orig);
239   STOFFInputStream &operator=(STOFFInputStream const &orig);
240 
241 protected:
242   //! the initial input
243   std::shared_ptr<librevenge::RVNGInputStream> m_stream;
244   //! the stream size
245   long m_streamSize;
246 
247   //! big or normal endian
248   bool m_inverseRead;
249 };
250 
251 #endif
252 // vim: set filetype=cpp tabstop=2 shiftwidth=2 cindent autoindent smartindent noexpandtab:
253