1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  * This file is part of the LibreOffice 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  * This file incorporates work covered by the following license notice:
10  *
11  *   Licensed to the Apache Software Foundation (ASF) under one or more
12  *   contributor license agreements. See the NOTICE file distributed
13  *   with this work for additional information regarding copyright
14  *   ownership. The ASF licenses this file to you under the Apache
15  *   License, Version 2.0 (the "License"); you may not use this file
16  *   except in compliance with the License. You may obtain a copy of
17  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
18  */
19 
20 #ifndef INCLUDED_SOT_SOURCE_SDSTOR_STGSTRMS_HXX
21 #define INCLUDED_SOT_SOURCE_SDSTOR_STGSTRMS_HXX
22 
23 #include <tools/stream.hxx>
24 #include <o3tl/sorted_vector.hxx>
25 #include <rtl/ref.hxx>
26 #include <vector>
27 #include <memory>
28 
29 class StgIo;
30 class StgStrm;
31 class StgPage;
32 class StgDirEntry;
33 
34 // The FAT class performs FAT operations on an underlying storage stream.
35 // This stream is either the physical FAT stream (bPhys == true ) or a normal
36 // storage stream, which then holds the FAT for small data allocations.
37 
38 class StgFAT
39 {                                       // FAT allocator
40     StgStrm& m_rStrm;                     // underlying stream
41     sal_Int32 m_nMaxPage;                     // highest page allocated so far
42     short m_nPageSize;                    // physical page size
43     short m_nEntries;                     // FAT entries per page
44     short m_nOffset;                      // current offset within page
45     sal_Int32 m_nLimit;                       // search limit recommendation
46     bool  m_bPhys;                        // true: physical FAT
47     rtl::Reference< StgPage > GetPhysPage( sal_Int32 nPage );
48     bool  MakeChain( sal_Int32 nStart, sal_Int32 nPages );
49     bool  InitNew( sal_Int32 nPage1 );
50 public:
51     StgFAT( StgStrm& rStrm, bool bMark );
52     sal_Int32 FindBlock( sal_Int32& nPages );
53     sal_Int32 GetNextPage( sal_Int32 nPg );
54     sal_Int32 AllocPages( sal_Int32 nStart, sal_Int32 nPages );
55     bool  FreePages( sal_Int32 nStart, bool bAll );
GetMaxPage() const56     sal_Int32 GetMaxPage() const { return m_nMaxPage; }
SetLimit(sal_Int32 n)57     void  SetLimit( sal_Int32 n ) { m_nLimit = n; }
58 };
59 
60 // The base stream class provides basic functionality for seeking
61 // and accessing the data on a physical basis. It uses the built-in
62 // FAT class for the page allocations.
63 
64 class StgStrm {                           // base class for all streams
65 private:
66     sal_Int32 m_nPos;                     // current byte position
67     bool m_bBytePosValid;                 // what Pos2Page returns for m_nPos
68 protected:
69     StgIo& m_rIo;                         // I/O system
70     std::unique_ptr<StgFAT> m_pFat;       // FAT stream for allocations
71     StgDirEntry* m_pEntry;                // dir entry (for ownership)
72     sal_Int32 m_nStart;                       // 1st data page
73     sal_Int32 m_nSize;                        // stream size in bytes
74     sal_Int32 m_nPage;                        // current logical page
75     short m_nOffset;                      // offset into current page
76     short m_nPageSize;                    // logical page size
77     std::vector<sal_Int32> m_aPagesCache;
78     o3tl::sorted_vector<sal_Int32> m_aUsedPageNumbers;
79     sal_Int32 scanBuildPageChainCache();
80     bool  Copy( sal_Int32 nFrom, sal_Int32 nBytes );
SetPos(sal_Int32 nPos,bool bValid)81     void SetPos(sal_Int32 nPos, bool bValid) { m_nPos = nPos; m_bBytePosValid = bValid; }
82     explicit StgStrm( StgIo& );
83 public:
84     virtual ~StgStrm();
GetIo()85     StgIo&  GetIo()     { return m_rIo;    }
GetPos() const86     sal_Int32   GetPos() const   { return m_nPos; }
GetStart() const87     sal_Int32   GetStart() const { return m_nStart; }
GetSize() const88     sal_Int32   GetSize() const  { return m_nSize;  }
GetPage() const89     sal_Int32   GetPage() const  { return m_nPage;  }
GetPages() const90     sal_Int32   GetPages() const { return ( m_nSize + m_nPageSize - 1 ) / m_nPageSize;}
GetOffset() const91     short       GetOffset() const { return m_nOffset;}
92     void        SetEntry( StgDirEntry& );
93     virtual bool SetSize( sal_Int32 );
94     virtual bool Pos2Page( sal_Int32 nBytePos );
Read(void *,sal_Int32)95     virtual sal_Int32 Read( void*, sal_Int32 )        { return 0; }
Write(const void *,sal_Int32)96     virtual sal_Int32 Write( const void*, sal_Int32 ) { return 0; }
IsSmallStrm() const97     virtual bool IsSmallStrm() const { return false; }
98 };
99 
100 // The FAT stream class provides physical access to the master FAT.
101 // Since this access is implemented as a StgStrm, we can use the
102 // FAT allocator.
103 
104 class StgFATStrm : public StgStrm {     // the master FAT stream
105     virtual bool Pos2Page( sal_Int32 nBytePos ) override;
106     bool  SetPage( short, sal_Int32 );
107 public:
108     explicit StgFATStrm(StgIo&, sal_Int32 nFatStrmSize);
109     using StgStrm::GetPage;
110     sal_Int32 GetPage(sal_Int32, bool, sal_uInt16 *pnMasterAlloc = nullptr);
111     virtual bool SetSize( sal_Int32 ) override;
112 };
113 
114 // The stream has a size increment which normally is 1, but which can be
115 // set to any value is you want the size to be incremented by certain values.
116 
117 class StgDataStrm : public StgStrm      // a physical data stream
118 {
119     short m_nIncr;                        // size adjust increment
120     void Init( sal_Int32 nBgn, sal_Int32 nLen );
121 public:
122     StgDataStrm( StgIo&, sal_Int32 nBgn, sal_Int32 nLen=-1 );
123     StgDataStrm( StgIo&, StgDirEntry& );
124     void* GetPtr( sal_Int32 nPos, bool bDirty );
SetIncrement(short n)125     void SetIncrement( short n ) { m_nIncr = n ; }
126     virtual bool SetSize( sal_Int32 ) override;
127     virtual sal_Int32 Read( void*, sal_Int32 ) override;
128     virtual sal_Int32 Write( const void*, sal_Int32 ) override;
129 };
130 
131 // The small stream class provides access to streams with a size < 4096 bytes.
132 // This stream is a StgStream containing small pages. The FAT for this stream
133 // is also a StgStream. The start of the FAT is in the header at DataRootPage,
134 // the stream itself is pointed to by the root entry (it holds start & size).
135 
136 class StgSmallStrm : public StgStrm     // a logical data stream
137 {
138     StgStrm* m_pData;                     // the data stream
139     void Init( sal_Int32 nBgn, sal_Int32 nLen );
140 public:
141     StgSmallStrm( StgIo&, sal_Int32 nBgn );
142     StgSmallStrm( StgIo&, StgDirEntry& );
143     virtual sal_Int32 Read( void*, sal_Int32 ) override;
144     virtual sal_Int32 Write( const void*, sal_Int32 ) override;
IsSmallStrm() const145     virtual bool IsSmallStrm() const override { return true; }
146 };
147 
148 class StgTmpStrm : public SvMemoryStream
149 {
150     OUString m_aName;
151     SvFileStream* m_pStrm;
152     using SvMemoryStream::GetData;
153     virtual std::size_t GetData( void* pData, std::size_t nSize ) override;
154     virtual std::size_t PutData( const void* pData, std::size_t nSize ) override;
155     virtual sal_uInt64 SeekPos( sal_uInt64 nPos ) override;
156     virtual void FlushData() override;
157 
158 public:
159     explicit StgTmpStrm( sal_uInt64=16 );
160     virtual ~StgTmpStrm() override;
161     bool Copy( StgTmpStrm& );
162     virtual void SetSize( sal_uInt64 ) override;
163     sal_uInt64 GetSize() const;
164 };
165 
166 #endif
167 
168 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
169