Coverage Report

Created: 2025-07-07 10:01

/src/libreoffice/connectivity/source/inc/dbase/dindexnode.hxx
Line
Count
Source (jump to first uncovered line)
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
#pragma once
20
21
#include <file/fcode.hxx>
22
#include <connectivity/FValue.hxx>
23
#include <memory>
24
25
0
#define NODE_NOTFOUND 0xFFFF
26
0
#define DINDEX_PAGE_SIZE 512
27
28
class SvStream;
29
30
namespace connectivity::dbase
31
{
32
33
    class ONDXNode;
34
    class ODbaseIndex;
35
36
    // Index Key
37
38
    typedef file::OOperand ONDXKey_BASE;
39
    class ONDXKey : public ONDXKey_BASE
40
    {
41
        friend class ONDXNode;
42
        sal_uInt32      nRecord;                /* Record pointer */
43
        ORowSetValue    xValue;                 /* Key values     */
44
45
    public:
46
        ONDXKey();
47
        ONDXKey(ORowSetValue aVal, sal_Int32 eType, sal_uInt32 nRec);
48
        ONDXKey(const OUString& aStr, sal_uInt32 nRec);
49
        ONDXKey(double aVal, sal_uInt32 nRec);
50
51
        inline ONDXKey(const ONDXKey& rKey);
52
53
        inline ONDXKey& operator= (const ONDXKey& rKey);
54
        virtual void setValue(const ORowSetValue& _rVal) override;
55
56
        virtual const ORowSetValue& getValue() const override;
57
58
0
        sal_uInt32 GetRecord() const        { return nRecord;   }
59
0
        void setRecord(sal_uInt32 _nRec)    { nRecord = _nRec;  }
60
0
        void   ResetRecord()            { nRecord = 0;      }
61
62
        bool operator == (const ONDXKey& rKey) const;
63
        bool operator != (const ONDXKey& rKey) const;
64
        bool operator <  (const ONDXKey& rKey) const;
65
        bool operator <= (const ONDXKey& rKey) const;
66
        bool operator >  (const ONDXKey& rKey) const;
67
68
        static bool IsText(sal_Int32 eType);
69
70
    private:
71
        int Compare(const ONDXKey& rKey) const;
72
    };
73
74
75
    class ONDXPage;
76
77
    // Index Page Pointer
78
    // This is  ref-count pointer class
79
    class ONDXPagePtr
80
    {
81
        friend  SvStream& WriteONDXPagePtr(SvStream &rStream, const ONDXPagePtr&);
82
        friend  SvStream& operator >> (SvStream &rStream, ONDXPagePtr&);
83
84
        ONDXPage*   mpPage;
85
        sal_uInt32  nPagePos;       // Position in the index file
86
87
    public:
88
        ONDXPagePtr();
89
        ONDXPagePtr(ONDXPagePtr&& rObj) noexcept;
90
        ONDXPagePtr(ONDXPagePtr const & rRef);
91
        ONDXPagePtr(ONDXPage* pRefPage);
92
        ~ONDXPagePtr();
93
        void Clear();
94
        ONDXPagePtr& operator=(ONDXPagePtr const & rRef);
95
        ONDXPagePtr& operator=(ONDXPagePtr && rRef);
96
0
        bool Is() const { return mpPage != nullptr; }
97
98
0
        ONDXPage * operator ->() const { assert(mpPage != nullptr); return mpPage; }
99
0
        operator ONDXPage *() const { return mpPage; }
100
101
0
        sal_uInt32 GetPagePos() const {return nPagePos;}
102
0
        bool HasPage() const {return nPagePos != 0;}
103
    };
104
105
    // Index Page
106
    // This is a ref-counted class, with re-cycling
107
    class ONDXPage
108
    {
109
        friend class ODbaseIndex;
110
        friend class ONDXPagePtr;
111
112
        friend  SvStream& WriteONDXPage(SvStream &rStream, const ONDXPage&);
113
        friend  SvStream& operator >> (SvStream &rStream, ONDXPage&);
114
115
        // work around a clang 3.5 optimization bug: if the bNoDelete is *first*
116
        // it mis-compiles "if (--nRefCount == 0)" and never deletes any object
117
        unsigned int    nRefCount : 31;
118
        // the only reason this is not bool is because MSVC cannot handle mixed type bitfields
119
        unsigned int    bNoDelete : 1;
120
        sal_uInt32      nPagePos;       // Position in the index file
121
        bool            bModified : 1;
122
        sal_uInt16      nCount;
123
124
        ONDXPagePtr     aParent,            // Parent page
125
                        aChild;             // Pointer to the right child page
126
        ODbaseIndex&    rIndex;
127
        std::unique_ptr<ONDXNode[]>
128
                        ppNodes;             // Array of nodes
129
130
    public:
131
        // Node operations
132
0
        sal_uInt16  Count() const {return nCount;}
133
134
        bool    Insert(ONDXNode& rNode, sal_uInt32 nRowsLeft = 0);
135
        bool    Insert(sal_uInt16 nIndex, ONDXNode& rNode);
136
        bool    Append(ONDXNode& rNode);
137
        void    Delete(sal_uInt16);
138
        void    Remove(sal_uInt16);
139
        void    Release(bool bSave = true);
140
        void    ReleaseFull();
141
142
        // Split and merge
143
        ONDXNode Split(ONDXPage& rPage);
144
        void Merge(sal_uInt16 nParentNodePos, const ONDXPagePtr& xPage);
145
146
        // Access operators
147
        ONDXNode& operator[] (sal_uInt16 nPos);
148
        const ONDXNode& operator[] (sal_uInt16 nPos) const;
149
150
        bool IsRoot() const;
151
        bool IsLeaf() const;
152
        bool IsModified() const;
153
        bool HasParent() const;
154
155
        bool IsFull() const;
156
157
0
        sal_uInt32 GetPagePos() const {return nPagePos;}
158
        ONDXPagePtr& GetChild(ODbaseIndex const * pIndex = nullptr);
159
160
        // Parent does not need to be reloaded
161
        const ONDXPagePtr& GetParent() const;
162
0
        ODbaseIndex& GetIndex() {return rIndex;}
163
0
        const ODbaseIndex& GetIndex() const {return rIndex;}
164
165
        // Setting the child, via reference to retain the PagePos
166
        void SetChild(const ONDXPagePtr& rCh);
167
        void SetParent(const ONDXPagePtr& rPa);
168
169
        sal_uInt16 Search(const ONDXKey& rSearch);
170
        sal_uInt16 Search(const ONDXPage* pPage);
171
        void   SearchAndReplace(const ONDXKey& rSearch, ONDXKey const & rReplace);
172
173
    protected:
174
        ONDXPage(ODbaseIndex& rIndex, sal_uInt32 nPos, ONDXPage*);
175
        ~ONDXPage();
176
177
        void ReleaseRef();
178
        void QueryDelete();
179
        void AddNextRef()
180
0
                {
181
0
                    assert( nRefCount < (1 << 30) && "Do not add refs to dead objects" );
182
0
                    ++nRefCount;
183
0
                }
184
        void AddFirstRef()
185
0
                {
186
0
                    assert( nRefCount < (1 << 30) && "Do not add refs to dead objects" );
187
0
                    if( bNoDelete )
188
0
                        bNoDelete = 0;
189
0
                    ++nRefCount;
190
0
                }
191
192
0
        void SetModified(bool bMod) {bModified = bMod;}
193
0
        void SetPagePos(sal_uInt32 nPage) {nPagePos = nPage;}
194
195
        bool Find(const ONDXKey&);  // Descend recursively
196
        sal_uInt16 FindPos(const ONDXKey& rKey) const;
197
198
#if OSL_DEBUG_LEVEL > 1
199
        void PrintPage();
200
#endif
201
    };
202
203
    SvStream& WriteONDXPagePtr(SvStream &rStream, const ONDXPagePtr&);
204
    SvStream& operator >> (SvStream &rStream, ONDXPagePtr&);
205
206
0
    inline bool ONDXPage::IsRoot() const {return !aParent.Is();}
207
0
    inline bool ONDXPage::IsLeaf() const {return !aChild.HasPage();}
208
0
    inline bool ONDXPage::IsModified() const {return bModified;}
209
0
    inline bool ONDXPage::HasParent() const {return aParent.Is();}
210
0
    inline const ONDXPagePtr& ONDXPage::GetParent() const {return aParent;}
211
212
    inline void ONDXPage::SetParent(const ONDXPagePtr& rPa = ONDXPagePtr())
213
0
    {
214
0
        aParent = rPa;
215
0
    }
216
217
    inline void ONDXPage::SetChild(const ONDXPagePtr& rCh = ONDXPagePtr())
218
0
    {
219
0
        aChild = rCh;
220
0
        if (aChild.Is())
221
0
            aChild->SetParent(this);
222
0
    }
223
    SvStream& operator >> (SvStream &rStream, ONDXPage& rPage);
224
    SvStream& WriteONDXPage(SvStream &rStream, const ONDXPage& rPage);
225
226
227
    // Index Node
228
229
    class ONDXNode
230
    {
231
        friend class ONDXPage;
232
        ONDXPagePtr aChild;             /* Next page reference */
233
        ONDXKey   aKey;
234
235
    public:
236
0
        ONDXNode(){}
237
        ONDXNode(const ONDXKey& rKey)
238
0
                   :aKey(rKey) {}
239
240
        // Does the node point to a page?
241
0
        bool            HasChild() const {return aChild.HasPage();}
242
        // If an index is provided, we may be able to retrieve the page
243
        ONDXPagePtr&    GetChild(ODbaseIndex* pIndex = nullptr, ONDXPage* = nullptr);
244
245
0
        const ONDXKey& GetKey() const   { return aKey;}
246
0
        ONDXKey&       GetKey()         { return aKey;}
247
248
        // Setting the child, via reference to retain the PagePos
249
        void            SetChild(const ONDXPagePtr& rCh = ONDXPagePtr(), ONDXPage* = nullptr);
250
251
        void Write(SvStream &rStream, const ONDXPage& rPage) const;
252
        void Read(SvStream &rStream, ODbaseIndex const &);
253
    };
254
255
    inline ONDXKey::ONDXKey(const ONDXKey& rKey)
256
0
                 : ONDXKey_BASE(rKey.getDBType())
257
0
                 ,nRecord(rKey.nRecord)
258
0
                 ,xValue(rKey.xValue)
259
0
    {
260
0
    }
261
262
    inline ONDXKey& ONDXKey::operator=(const ONDXKey& rKey)
263
0
    {
264
0
        if(&rKey == this)
265
0
            return *this;
266
267
0
        xValue = rKey.xValue;
268
0
        nRecord = rKey.nRecord;
269
0
        m_eDBType = rKey.getDBType();
270
0
        return *this;
271
0
    }
272
273
    inline bool ONDXKey::operator == (const ONDXKey& rKey) const
274
0
    {
275
0
        if(&rKey == this)
276
0
            return true;
277
0
        return Compare(rKey) == 0;
278
0
    }
279
    inline bool ONDXKey::operator != (const ONDXKey& rKey) const
280
0
    {
281
0
        return !operator== (rKey);
282
0
    }
283
    inline bool ONDXKey::operator <  (const ONDXKey& rKey) const
284
0
    {
285
0
        return Compare(rKey) < 0;
286
0
    }
287
    inline bool ONDXKey::operator >  (const ONDXKey& rKey) const
288
0
    {
289
0
        return Compare(rKey) > 0;
290
0
    }
291
    inline bool ONDXKey::operator <= (const ONDXKey& rKey) const
292
0
    {
293
0
        return !operator > (rKey);
294
0
    }
295
296
    inline void ONDXNode::SetChild(const ONDXPagePtr& rCh, ONDXPage* pParent)
297
0
    {
298
0
        aChild = rCh;
299
0
        if (aChild.Is())
300
0
            aChild->SetParent(pParent);
301
0
    }
302
303
}
304
305
306
307
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */