1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #ifndef _STORE_STORTREE_HXX
21 #define _STORE_STORTREE_HXX
23 #include "sal/config.h"
25 #include "boost/static_assert.hpp"
26 #include "sal/types.h"
28 #include "store/types.h"
30 #include "storbase.hxx"
37 /*========================================================================
41 *======================================================================*/
42 struct OStoreBTreeEntry
44 typedef OStorePageKey K
;
45 typedef OStorePageLink L
;
55 explicit OStoreBTreeEntry (
57 L
const & rLink
= L(),
58 sal_uInt32 nAttrib
= 0)
61 m_nAttrib (store::htonl(nAttrib
))
64 OStoreBTreeEntry (const OStoreBTreeEntry
& rhs
)
65 : m_aKey (rhs
.m_aKey
),
66 m_aLink (rhs
.m_aLink
),
67 m_nAttrib (rhs
.m_nAttrib
)
70 OStoreBTreeEntry
& operator= (const OStoreBTreeEntry
& rhs
)
73 m_aLink
= rhs
.m_aLink
;
74 m_nAttrib
= rhs
.m_nAttrib
;
87 CompareResult
compare (const OStoreBTreeEntry
& rOther
) const
89 if (m_aKey
< rOther
.m_aKey
)
91 else if (m_aKey
== rOther
.m_aKey
)
94 return COMPARE_GREATER
;
98 /*========================================================================
100 * OStoreBTreeNodeData.
102 *======================================================================*/
103 #define STORE_MAGIC_BTREENODE sal_uInt32(0x58190322)
105 struct OStoreBTreeNodeData
: public store::OStorePageData
107 typedef OStorePageData base
;
108 typedef OStoreBTreeNodeData self
;
110 typedef OStorePageGuard G
;
111 typedef OStoreBTreeEntry T
;
120 static const sal_uInt32 theTypeId
= STORE_MAGIC_BTREENODE
;
124 static const size_t theSize
= sizeof(G
);
125 static const sal_uInt16 thePageSize
= base::theSize
+ self::theSize
;
126 BOOST_STATIC_ASSERT(STORE_MINIMUM_PAGESIZE
>= self::thePageSize
);
130 sal_uInt16
capacity (void) const
132 return (store::ntohs(base::m_aDescr
.m_nSize
) - self::thePageSize
);
135 /** capacityCount (must be even).
137 sal_uInt16
capacityCount (void) const
139 return sal_uInt16(capacity() / sizeof(T
));
144 sal_uInt16
usage (void) const
146 return (store::ntohs(base::m_aDescr
.m_nUsed
) - self::thePageSize
);
151 sal_uInt16
usageCount (void) const
153 return sal_uInt16(usage() / sizeof(T
));
155 void usageCount (sal_uInt16 nCount
)
157 size_t const nBytes
= self::thePageSize
+ nCount
* sizeof(T
);
158 base::m_aDescr
.m_nUsed
= store::htons(sal::static_int_cast
< sal_uInt16
>(nBytes
));
163 explicit OStoreBTreeNodeData (sal_uInt16 nPageSize
= self::thePageSize
);
165 /** guard (external representation).
169 sal_uInt32 nCRC32
= 0;
170 nCRC32
= rtl_crc32 (nCRC32
, &m_aGuard
.m_nMagic
, sizeof(sal_uInt32
));
171 nCRC32
= rtl_crc32 (nCRC32
, m_pData
, capacity());
172 m_aGuard
.m_nCRC32
= store::htonl(nCRC32
);
175 /** verify (external representation).
177 storeError
verify() const
179 sal_uInt32 nCRC32
= 0;
180 nCRC32
= rtl_crc32 (nCRC32
, &m_aGuard
.m_nMagic
, sizeof(sal_uInt32
));
181 nCRC32
= rtl_crc32 (nCRC32
, m_pData
, capacity());
182 if (m_aGuard
.m_nCRC32
!= store::htonl(nCRC32
))
183 return store_E_InvalidChecksum
;
190 sal_uInt32
depth (void) const
192 return store::ntohl(self::m_aGuard
.m_nMagic
);
194 void depth (sal_uInt32 nDepth
)
196 self::m_aGuard
.m_nMagic
= store::htonl(nDepth
);
201 sal_Bool
queryMerge (const self
&rPageR
) const
203 return ((usageCount() + rPageR
.usageCount()) <= capacityCount());
208 sal_Bool
querySplit (void) const
210 return (!(usageCount() < capacityCount()));
215 sal_uInt16
find (const T
& t
) const;
216 void insert (sal_uInt16 i
, const T
& t
);
217 void remove (sal_uInt16 i
);
219 /** split (left half copied from right half of left page).
221 void split (const self
& rPageL
);
223 /** truncate (to n elements).
225 void truncate (sal_uInt16 n
);
228 /*========================================================================
230 * OStoreBTreeNodeObject.
232 *======================================================================*/
233 class OStoreBTreeNodeObject
: public store::OStorePageObject
235 typedef OStorePageObject base
;
236 typedef OStoreBTreeNodeObject self
;
237 typedef OStoreBTreeNodeData page
;
239 typedef OStoreBTreeEntry T
;
244 explicit OStoreBTreeNodeObject (PageHolder
const & rxPage
= PageHolder())
245 : OStorePageObject (rxPage
)
248 /** External representation.
250 virtual storeError
guard (sal_uInt32 nAddr
);
251 virtual storeError
verify (sal_uInt32 nAddr
) const;
255 * @param rxPageL [inout] left child to be split
259 PageHolderObject
< page
> & rxPageL
,
260 OStorePageBIOS
& rBIOS
);
262 /** remove (down to leaf node, recursive).
266 OStoreBTreeEntry
& rEntryL
,
267 OStorePageBIOS
& rBIOS
);
270 /*========================================================================
272 * OStoreBTreeRootObject.
274 *======================================================================*/
275 class OStoreBTreeRootObject
: public store::OStoreBTreeNodeObject
277 typedef OStoreBTreeNodeObject base
;
278 typedef OStoreBTreeNodeData page
;
280 typedef OStoreBTreeEntry T
;
285 explicit OStoreBTreeRootObject (PageHolder
const & rxPage
= PageHolder())
286 : OStoreBTreeNodeObject (rxPage
)
289 storeError
loadOrCreate (
291 OStorePageBIOS
& rBIOS
);
293 /** find_lookup (w/o split()).
294 * Precond: root node page loaded.
296 storeError
find_lookup (
297 OStoreBTreeNodeObject
& rNode
, // [out]
298 sal_uInt16
& rIndex
, // [out]
299 OStorePageKey
const & rKey
,
300 OStorePageBIOS
& rBIOS
);
302 /** find_insert (possibly with split()).
303 * Precond: root node page loaded.
305 storeError
find_insert (
306 OStoreBTreeNodeObject
& rNode
,
308 OStorePageKey
const & rKey
,
309 OStorePageBIOS
& rBIOS
);
313 * Precond: root node page loaded.
315 bool testInvariant (char const * message
);
319 * @param rxPageL [out] prev. root (needs split)
322 PageHolderObject
< page
> & rxPageL
,
323 OStorePageBIOS
& rBIOS
);
326 /*========================================================================
330 *======================================================================*/
334 #endif /* !_STORE_STORTREE_HXX */
336 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */