1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
|
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* This file incorporates work covered by the following license notice:
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed
* with this work for additional information regarding copyright
* ownership. The ASF licenses this file to you under the Apache
* License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
#ifndef INCLUDED_SOT_SOURCE_SDSTOR_STGCACHE_HXX
#define INCLUDED_SOT_SOURCE_SDSTOR_STGCACHE_HXX
#include <o3tl/safeint.hxx>
#include <osl/endian.h>
#include <rtl/ref.hxx>
#include <tools/stream.hxx>
#include "stgelem.hxx"
#include <salhelper/simplereferenceobject.hxx>
#include <memory>
#include <unordered_map>
class UCBStorageStream;
class StgPage;
class StorageBase;
class StgCache
{
typedef std::unordered_map
<
sal_Int32, rtl::Reference< StgPage >
> IndexToStgPage;
typedef std::vector< rtl::Reference< StgPage > > LRUList;
ErrCode m_nError; // error code
sal_Int32 m_nPages; // size of data area in pages
sal_uInt16 m_nRef; // reference count
IndexToStgPage maDirtyPages; // hash of all dirty pages
int m_nReplaceIdx; // index into maLRUPages to replace next
LRUList maLRUPages; // list of last few non-dirty pages.
short m_nPageSize; // page size of the file
UCBStorageStream* m_pStorageStream; // holds reference to UCB storage stream
void Erase( const rtl::Reference< StgPage >& ); // delete a cache element
rtl::Reference< StgPage > Create( sal_Int32 ); // create a cached page
SvStream* m_pStrm; // physical stream
bool m_bMyStream; // true: delete stream in dtor
protected:
bool m_bFile; // true: file stream
sal_Int32 Page2Pos( sal_Int32 ) const; // page address --> file position
public:
StgCache();
~StgCache();
void IncRef() { m_nRef++; }
sal_uInt16 DecRef() { return --m_nRef; }
void SetPhysPageSize( short );
sal_Int32 GetPhysPages() const { return m_nPages; }
short GetPhysPageSize() const { return m_nPageSize; }
SvStream* GetStrm() { return m_pStrm; }
void SetStrm( SvStream*, bool );
void SetStrm( UCBStorageStream* );
bool Good() const { return m_nError == ERRCODE_NONE; }
ErrCode const & GetError() const { return m_nError; }
void MoveError( StorageBase const & );
void SetError( ErrCode );
void ResetError();
bool Open( const OUString& rName, StreamMode );
void Close();
bool Read( sal_Int32 nPage, void* pBuf );
bool Write( sal_Int32 nPage, void const * pBuf );
// two routines for accessing FAT pages
// Assume that the data is a FAT page and get/put FAT data.
void SetToPage ( const rtl::Reference< StgPage >& rPage, short nOff, sal_Int32 nVal );
static inline sal_Int32 GetFromPage ( const rtl::Reference< StgPage >& rPage, short nOff );
void SetDirty ( const rtl::Reference< StgPage > &rPage );
bool SetSize( sal_Int32 nPages );
rtl::Reference< StgPage > Find( sal_Int32 ); // find a cached page
rtl::Reference< StgPage > Get( sal_Int32, bool ); // get a cached page
rtl::Reference< StgPage > Copy( sal_Int32, sal_Int32=STG_FREE ); // copy a page
bool Commit(); // flush all pages
void Clear(); // clear the cache
};
class StgPage : public salhelper::SimpleReferenceObject
{
const sal_Int32 mnPage; // page index
std::unique_ptr<sal_uInt8[]>
mpData; // nSize bytes
short mnSize; // size of this page
StgPage( short nData, sal_Int32 nPage );
virtual ~StgPage() override;
public:
StgPage(const StgPage&) = delete;
StgPage& operator=(const StgPage&) = delete;
static rtl::Reference< StgPage > Create( short nData, sal_Int32 nPage );
sal_Int32 GetPage() const { return mnPage; }
void* GetData() { return mpData.get(); }
short GetSize() const { return mnSize; }
public:
static bool IsPageGreater( const StgPage *pA, const StgPage *pB );
};
inline sal_Int32 StgCache::GetFromPage ( const rtl::Reference< StgPage >& rPage, short nOff )
{
if( nOff < 0 || ( o3tl::make_unsigned(nOff) >= rPage->GetSize() / sizeof( sal_Int32 ) ) )
return -1;
sal_Int32 n = static_cast<sal_Int32*>(rPage->GetData())[ nOff ];
#ifdef OSL_BIGENDIAN
return OSL_SWAPDWORD(n);
#else
return n;
#endif
}
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|