Version 7.6.3.2-android, tag libreoffice-7.6.3.2-android
[LibreOffice.git] / store / source / storbase.hxx
blobfeac0db9622727af0d4d34f8438af5bdedb9693e
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 #pragma once
22 #include <sal/config.h>
23 #include <salhelper/simplereferenceobject.hxx>
25 #include <sal/types.h>
27 #include <rtl/crc.h>
28 #include <rtl/ref.hxx>
30 #include <osl/diagnose.h>
31 #include <osl/endian.h>
33 #include <store/types.h>
35 #include <memory>
36 #include <utility>
38 /** @file store common internals.
41 namespace store
44 #ifdef htons
45 #undef htons
46 #endif
47 #ifdef ntohs
48 #undef ntohs
49 #endif
51 #ifdef htonl
52 #undef htonl
53 #endif
54 #ifdef ntohl
55 #undef ntohl
56 #endif
58 #ifdef OSL_BIGENDIAN
59 inline sal_uInt16 htons (sal_uInt16 h) { return OSL_SWAPWORD(h); }
60 inline sal_uInt16 ntohs (sal_uInt16 n) { return OSL_SWAPWORD(n); }
62 inline sal_uInt32 htonl (sal_uInt32 h) { return OSL_SWAPDWORD(h); }
63 inline sal_uInt32 ntohl (sal_uInt32 n) { return OSL_SWAPDWORD(n); }
64 #else
65 inline sal_uInt16 htons (sal_uInt16 h) { return h; }
66 inline sal_uInt16 ntohs (sal_uInt16 n) { return n; }
68 inline sal_uInt32 htonl (sal_uInt32 h) { return h; }
69 inline sal_uInt32 ntohl (sal_uInt32 n) { return n; }
70 #endif /* OSL_BIGENDIAN */
72 struct OStorePageGuard
74 /** Representation.
76 sal_uInt32 m_nMagic;
77 sal_uInt32 m_nCRC32;
79 /** Construction.
81 explicit OStorePageGuard (sal_uInt32 nMagic = 0)
82 : m_nMagic (store::htonl(nMagic)),
83 m_nCRC32 (store::htonl(0))
86 void swap (OStorePageGuard & rhs)
88 std::swap(m_nMagic, rhs.m_nMagic);
89 std::swap(m_nCRC32, rhs.m_nCRC32);
92 OStorePageGuard (OStorePageGuard const & rhs)
93 : m_nMagic (rhs.m_nMagic),
94 m_nCRC32 (rhs.m_nCRC32)
97 OStorePageGuard& operator= (const OStorePageGuard& rhs)
99 m_nMagic = rhs.m_nMagic;
100 m_nCRC32 = rhs.m_nCRC32;
101 return *this;
104 /** Comparison.
106 bool operator== (const OStorePageGuard& rhs) const
108 return ((m_nMagic == rhs.m_nMagic) &&
109 (m_nCRC32 == rhs.m_nCRC32) );
113 #define STORE_PAGE_NULL (sal_uInt32(~0))
115 struct OStorePageDescriptor
117 /** Representation.
119 sal_uInt32 m_nAddr;
120 sal_uInt16 m_nSize;
121 sal_uInt16 m_nUsed;
123 /** Construction.
125 explicit OStorePageDescriptor (
126 sal_uInt32 nAddr,
127 sal_uInt16 nSize,
128 sal_uInt16 nUsed)
129 : m_nAddr (store::htonl(nAddr)),
130 m_nSize (store::htons(nSize)),
131 m_nUsed (store::htons(nUsed))
134 void swap (OStorePageDescriptor & rhs)
136 std::swap(m_nAddr, rhs.m_nAddr);
137 std::swap(m_nSize, rhs.m_nSize);
138 std::swap(m_nUsed, rhs.m_nUsed);
141 OStorePageDescriptor (const OStorePageDescriptor & rhs)
142 : m_nAddr (rhs.m_nAddr),
143 m_nSize (rhs.m_nSize),
144 m_nUsed (rhs.m_nUsed)
147 OStorePageDescriptor & operator= (const OStorePageDescriptor & rhs)
149 m_nAddr = rhs.m_nAddr;
150 m_nSize = rhs.m_nSize;
151 m_nUsed = rhs.m_nUsed;
152 return *this;
155 /** Comparison.
157 bool operator== (const OStorePageDescriptor & rhs) const
159 return ((m_nAddr == rhs.m_nAddr) &&
160 (m_nSize == rhs.m_nSize) );
164 struct OStorePageKey
166 /** Representation.
168 sal_uInt32 m_nLow;
169 sal_uInt32 m_nHigh;
171 /** Construction.
173 explicit OStorePageKey (sal_uInt32 nLow = 0, sal_uInt32 nHigh = 0)
174 : m_nLow (store::htonl(nLow)),
175 m_nHigh (store::htonl(nHigh))
178 /** Comparison.
180 bool operator== (const OStorePageKey & rhs) const
182 return ((m_nLow == rhs.m_nLow ) &&
183 (m_nHigh == rhs.m_nHigh) );
186 bool operator< (const OStorePageKey & rhs) const
188 if (m_nHigh == rhs.m_nHigh)
189 return (store::ntohl(m_nLow) < store::ntohl(rhs.m_nLow));
190 else
191 return (store::ntohl(m_nHigh) < store::ntohl(rhs.m_nHigh));
195 struct OStorePageLink
197 /** Representation.
199 sal_uInt32 m_nAddr;
201 /** Construction.
203 explicit OStorePageLink (sal_uInt32 nAddr = STORE_PAGE_NULL)
204 : m_nAddr (store::htonl(nAddr))
207 void swap (OStorePageLink & rhs)
209 std::swap(m_nAddr, rhs.m_nAddr);
212 OStorePageLink & operator= (sal_uInt32 nAddr)
214 m_nAddr = store::htonl(nAddr);
215 return *this;
218 /** Comparison.
220 bool operator== (const OStorePageLink & rhs) const
222 return (m_nAddr == rhs.m_nAddr);
225 /** Operation.
227 sal_uInt32 location() const
229 return store::ntohl(m_nAddr);
234 struct PageData
236 typedef OStorePageGuard G;
237 typedef OStorePageDescriptor D;
238 typedef OStorePageLink L;
240 /** Representation.
242 G m_aGuard;
243 D m_aDescr;
244 L m_aMarked;
245 L m_aUnused;
247 /** theSize.
249 static const size_t theSize = sizeof(G) + sizeof(D) + 2 * sizeof(L);
250 static const sal_uInt16 thePageSize = theSize;
251 static_assert(STORE_MINIMUM_PAGESIZE >= thePageSize, "must be at least thePageSize");
253 /** location.
255 sal_uInt32 location() const
257 return store::ntohl(m_aDescr.m_nAddr);
259 void location (sal_uInt32 nAddr)
261 m_aDescr.m_nAddr = store::htonl(nAddr);
264 /** size.
266 sal_uInt16 size() const
268 return store::ntohs(m_aDescr.m_nSize);
271 /** type.
273 sal_uInt32 type() const
275 return store::ntohl(m_aGuard.m_nMagic);
278 /** Allocation.
280 class Allocator_Impl;
281 class Allocator : public virtual salhelper::SimpleReferenceObject
283 public:
284 template< class T > T * construct()
286 void * page = nullptr;
287 sal_uInt16 nSize = 0;
288 if (allocate (&page, &nSize))
290 return new(page) T(nSize);
292 return nullptr;
295 bool allocate (void ** ppPage, sal_uInt16 * pnSize)
297 allocate_Impl (ppPage, pnSize);
298 return ((*ppPage != nullptr) && (*pnSize != 0));
301 void deallocate (void * pPage)
303 if (pPage != nullptr)
304 deallocate_Impl (pPage);
307 static storeError createInstance (
308 rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize);
310 protected:
311 virtual ~Allocator() override {}
313 private:
314 /** Implementation (abstract).
316 virtual void allocate_Impl (void ** ppPage, sal_uInt16 * pnSize) = 0;
317 virtual void deallocate_Impl (void * pPage) = 0;
320 class Deallocate {
321 public:
322 explicit Deallocate(rtl::Reference<Allocator> allocator):
323 allocator_(std::move(allocator)) {};
325 void operator ()(void * page) const { allocator_->deallocate(page); }
327 private:
328 rtl::Reference<Allocator> allocator_;
331 static void* operator new (size_t, void * p) { return p; }
332 static void operator delete (void * , void *) {}
334 /** Construction.
336 explicit PageData (sal_uInt16 nPageSize = thePageSize)
337 : m_aGuard(),
338 m_aDescr(STORE_PAGE_NULL, nPageSize, thePageSize),
339 m_aMarked(),
340 m_aUnused()
343 void swap (PageData & rhs) // nothrow
345 m_aGuard.swap(rhs.m_aGuard);
346 m_aDescr.swap(rhs.m_aDescr);
347 m_aMarked.swap(rhs.m_aMarked);
348 m_aUnused.swap(rhs.m_aUnused);
351 PageData (PageData const & rhs) // nothrow
352 : m_aGuard (rhs.m_aGuard),
353 m_aDescr (rhs.m_aDescr),
354 m_aMarked(rhs.m_aMarked),
355 m_aUnused(rhs.m_aUnused)
358 PageData & operator= (PageData const & rhs) // nothrow
360 PageData tmp (rhs);
361 swap (tmp);
362 return *this;
365 /** guard (external representation).
367 void guard (sal_uInt32 nAddr)
369 sal_uInt32 nCRC32 = rtl_crc32 (0, &m_aGuard.m_nMagic, sizeof(sal_uInt32));
370 m_aDescr.m_nAddr = store::htonl(nAddr);
371 nCRC32 = rtl_crc32 (nCRC32, &m_aDescr, static_cast<sal_uInt32>(theSize - sizeof(G)));
372 m_aGuard.m_nCRC32 = store::htonl(nCRC32);
375 /** verify (external representation).
377 storeError verify (sal_uInt32 nAddr) const
379 sal_uInt32 nCRC32 = rtl_crc32 (0, &m_aGuard.m_nMagic, sizeof(sal_uInt32));
380 nCRC32 = rtl_crc32 (nCRC32, &m_aDescr, static_cast<sal_uInt32>(theSize - sizeof(G)));
381 if (m_aGuard.m_nCRC32 != store::htonl(nCRC32))
382 return store_E_InvalidChecksum;
383 if (m_aDescr.m_nAddr != store::htonl(nAddr))
384 return store_E_InvalidAccess;
385 return store_E_None;
390 template< class T >
391 class PageHolderObject
393 /** Representation.
395 std::shared_ptr<PageData> m_xPage;
397 /** Checked cast.
399 template< class U >
400 static bool isA (PageData const * p)
402 return ((p != nullptr) && (p->type() == U::theTypeId));
405 template< class U >
406 static U * dynamic_page_cast (PageData * p)
408 return isA<U>(p) ? static_cast<U*>(p) : nullptr;
411 template< class U >
412 static U const * dynamic_page_cast (PageData const * p)
414 return isA<U>(p) ? static_cast<U const *>(p) : nullptr;
417 public:
418 bool construct (rtl::Reference< PageData::Allocator > const & rxAllocator)
420 if (!m_xPage && rxAllocator.is())
422 std::shared_ptr<PageData> tmp (rxAllocator->construct<T>(), PageData::Deallocate(rxAllocator));
423 m_xPage.swap (tmp);
425 return bool(m_xPage);
428 explicit PageHolderObject (std::shared_ptr<PageData> xPage = std::shared_ptr<PageData>())
429 : m_xPage (std::move(xPage))
432 void swap (PageHolderObject<T> & rhs)
434 m_xPage.swap (rhs.m_xPage);
437 PageHolderObject (PageHolderObject<T> const & rhs)
438 : m_xPage (rhs.m_xPage)
441 PageHolderObject<T> & operator= (PageHolderObject<T> const & rhs)
443 PageHolderObject<T> tmp (rhs);
444 this->swap (tmp);
445 return *this;
448 bool is() const
450 return bool(m_xPage);
453 std::shared_ptr<PageData> & get() { return m_xPage; }
454 std::shared_ptr<PageData> const & get() const { return m_xPage; }
456 T * operator->()
458 T * pImpl = dynamic_page_cast<T>(m_xPage.get());
459 OSL_PRECOND(pImpl != nullptr, "store::PageHolder<T>::operator*(): Null pointer");
460 return pImpl;
463 T const * operator->() const
465 T const * pImpl = dynamic_page_cast<T>(m_xPage.get());
466 OSL_PRECOND(pImpl != nullptr, "store::PageHolder<T>::operator*(): Null pointer");
467 return pImpl;
470 T & operator*()
472 T * pImpl = dynamic_page_cast<T>(m_xPage.get());
473 OSL_PRECOND(pImpl != nullptr, "store::PageHolder<T>::operator*(): Null pointer");
474 return (*pImpl);
477 T const & operator*() const
479 T const * pImpl = dynamic_page_cast<T>(m_xPage.get());
480 OSL_PRECOND(pImpl != nullptr, "store::PageHolder<T>::operator*(): Null pointer");
481 return (*pImpl);
484 static storeError guard (std::shared_ptr<PageData> const & rxPage, sal_uInt32 nAddr)
486 PageData * pHead = rxPage.get();
487 if (!pHead)
488 return store_E_InvalidAccess;
489 pHead->guard(nAddr);
491 T * pImpl = dynamic_page_cast<T>(pHead);
492 OSL_PRECOND(pImpl != nullptr, "store::PageHolder<T>::guard(): Null pointer");
493 pImpl->guard();
495 return store_E_None;
498 static storeError verify (std::shared_ptr<PageData> const & rxPage, sal_uInt32 nAddr)
500 PageData const * pHead = rxPage.get();
501 if (!pHead)
502 return store_E_InvalidAccess;
504 storeError eErrCode = pHead->verify(nAddr);
505 if (eErrCode != store_E_None)
506 return eErrCode;
508 T const * pImpl = dynamic_page_cast<T>(pHead);
509 if (!pImpl)
510 return store_E_WrongVersion;
512 return pImpl->verify();
516 class OStorePageObject
518 typedef PageData page;
520 public:
521 /** Allocation.
523 static void * operator new (size_t n)
525 return std::malloc(sal_uInt32(n));
527 static void operator delete (void * p)
529 std::free (p);
532 /** State.
534 inline bool dirty() const;
535 inline void clean();
536 inline void touch();
538 /** Location.
540 inline sal_uInt32 location() const;
542 protected:
543 /** Representation.
545 std::shared_ptr<PageData> m_xPage;
546 bool m_bDirty;
548 /** Construction.
550 explicit OStorePageObject (std::shared_ptr<PageData> rxPage)
551 : m_xPage (std::move(rxPage)), m_bDirty (false)
554 /** Destruction.
556 virtual ~OStorePageObject();
558 public:
559 template< class U >
560 PageHolderObject<U> makeHolder() const
562 return PageHolderObject<U>(m_xPage);
565 template< class U >
566 storeError construct (rtl::Reference< PageData::Allocator > const & rxAllocator)
568 if (!rxAllocator.is())
569 return store_E_InvalidAccess;
571 std::shared_ptr<PageData> tmp (rxAllocator->construct<U>(), PageData::Deallocate(rxAllocator));
572 if (!tmp)
573 return store_E_OutOfMemory;
575 m_xPage.swap (tmp);
576 return store_E_None;
579 std::shared_ptr<PageData> & get() { return m_xPage; }
581 virtual storeError guard (sal_uInt32 nAddr) = 0;
582 virtual storeError verify (sal_uInt32 nAddr) const = 0;
585 inline bool OStorePageObject::dirty() const
587 return m_bDirty;
590 inline void OStorePageObject::clean()
592 m_bDirty = false;
595 inline void OStorePageObject::touch()
597 m_bDirty = true;
600 inline sal_uInt32 OStorePageObject::location() const
602 return m_xPage->location();
605 } // namespace store
607 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */