Branch libreoffice-5-0-4
[LibreOffice.git] / store / source / storbase.hxx
blob2eed637365003801d6da8881f6315cbd21eabad8
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 #ifndef INCLUDED_STORE_SOURCE_STORBASE_HXX
21 #define INCLUDED_STORE_SOURCE_STORBASE_HXX
23 #include "sal/config.h"
24 #include "salhelper/simplereferenceobject.hxx"
26 #include "sal/types.h"
28 #include "rtl/alloc.h"
29 #include "rtl/crc.h"
30 #include "rtl/ref.hxx"
32 #include "osl/diagnose.h"
33 #include "osl/endian.h"
35 #include "store/types.h"
37 #include <stddef.h>
38 #include <string.h>
40 /*========================================================================
42 * store common internals.
44 *======================================================================*/
46 #ifndef STORE_IMPL_ISP2
47 #define STORE_IMPL_ISP2(value) (((value) & ((value) - 1)) == 0)
48 #endif
50 #ifndef STORE_IMPL_CONCAT
51 #define STORE_IMPL_CONCAT(x, y) STORE_IMPL_CONCAT2(x,y)
52 #define STORE_IMPL_CONCAT2(x, y) x##y
53 #endif
55 namespace store
58 #ifdef htons
59 #undef htons
60 #endif
61 #ifdef ntohs
62 #undef ntohs
63 #endif
65 #ifdef htonl
66 #undef htonl
67 #endif
68 #ifdef ntohl
69 #undef ntohl
70 #endif
72 #ifdef OSL_BIGENDIAN
73 inline sal_uInt16 htons (sal_uInt16 h) { return OSL_SWAPWORD(h); }
74 inline sal_uInt16 ntohs (sal_uInt16 n) { return OSL_SWAPWORD(n); }
76 inline sal_uInt32 htonl (sal_uInt32 h) { return OSL_SWAPDWORD(h); }
77 inline sal_uInt32 ntohl (sal_uInt32 n) { return OSL_SWAPDWORD(n); }
78 #else
79 inline sal_uInt16 htons (sal_uInt16 h) { return h; }
80 inline sal_uInt16 ntohs (sal_uInt16 n) { return n; }
82 inline sal_uInt32 htonl (sal_uInt32 h) { return h; }
83 inline sal_uInt32 ntohl (sal_uInt32 n) { return n; }
84 #endif /* OSL_BIGENDIAN */
86 /** swap.
88 template< typename T > void swap (T & lhs, T & rhs)
90 T tmp = lhs; lhs = rhs; rhs = tmp;
93 /*========================================================================
95 * SharedCount.
97 *======================================================================*/
98 class SharedCount
100 long * m_pCount;
102 class Allocator
104 rtl_cache_type * m_cache;
106 public:
107 static Allocator & get();
109 long * alloc()
111 return static_cast<long*>(rtl_cache_alloc (m_cache));
113 void free (long * pCount)
115 rtl_cache_free (m_cache, pCount);
118 protected:
119 Allocator();
120 ~Allocator();
123 public:
124 SharedCount()
125 : m_pCount(Allocator::get().alloc())
127 if (m_pCount != 0) (*m_pCount) = 1;
130 ~SharedCount()
132 if (m_pCount != 0)
134 long new_count = --(*m_pCount);
135 if (new_count == 0)
136 Allocator::get().free(m_pCount);
140 void swap (SharedCount & rhs) // nothrow
142 store::swap(m_pCount, rhs.m_pCount);
145 SharedCount (SharedCount const & rhs) // nothrow
146 : m_pCount (rhs.m_pCount)
148 if (m_pCount != 0) ++(*m_pCount);
150 SharedCount & operator= (SharedCount const & rhs) // nothrow
152 SharedCount tmp(rhs);
153 swap(tmp);
154 return *this;
157 bool operator== (long count) const
159 return (m_pCount != 0) && (*m_pCount == count);
163 /*========================================================================
165 * OStorePageGuard.
167 *======================================================================*/
168 struct OStorePageGuard
170 /** Representation.
172 sal_uInt32 m_nMagic;
173 sal_uInt32 m_nCRC32;
175 /** Construction.
177 explicit OStorePageGuard (sal_uInt32 nMagic = 0, sal_uInt32 nCRC32 = 0)
178 : m_nMagic (store::htonl(nMagic)),
179 m_nCRC32 (store::htonl(nCRC32))
182 void swap (OStorePageGuard & rhs)
184 store::swap(m_nMagic, rhs.m_nMagic);
185 store::swap(m_nCRC32, rhs.m_nCRC32);
188 OStorePageGuard (OStorePageGuard const & rhs)
189 : m_nMagic (rhs.m_nMagic),
190 m_nCRC32 (rhs.m_nCRC32)
193 OStorePageGuard& operator= (const OStorePageGuard& rhs)
195 m_nMagic = rhs.m_nMagic;
196 m_nCRC32 = rhs.m_nCRC32;
197 return *this;
200 /** Comparison.
202 bool operator== (const OStorePageGuard& rhs) const
204 return ((m_nMagic == rhs.m_nMagic) &&
205 (m_nCRC32 == rhs.m_nCRC32) );
209 /*========================================================================
211 * OStorePageDescriptor.
213 *======================================================================*/
214 #define STORE_PAGE_NULL ((sal_uInt32)(~0))
216 struct OStorePageDescriptor
218 /** Representation.
220 sal_uInt32 m_nAddr;
221 sal_uInt16 m_nSize;
222 sal_uInt16 m_nUsed;
224 /** Construction.
226 explicit OStorePageDescriptor (
227 sal_uInt32 nAddr = STORE_PAGE_NULL,
228 sal_uInt16 nSize = 0,
229 sal_uInt16 nUsed = 0)
230 : m_nAddr (store::htonl(nAddr)),
231 m_nSize (store::htons(nSize)),
232 m_nUsed (store::htons(nUsed))
235 void swap (OStorePageDescriptor & rhs)
237 store::swap(m_nAddr, rhs.m_nAddr);
238 store::swap(m_nSize, rhs.m_nSize);
239 store::swap(m_nUsed, rhs.m_nUsed);
242 OStorePageDescriptor (const OStorePageDescriptor & rhs)
243 : m_nAddr (rhs.m_nAddr),
244 m_nSize (rhs.m_nSize),
245 m_nUsed (rhs.m_nUsed)
248 OStorePageDescriptor & operator= (const OStorePageDescriptor & rhs)
250 m_nAddr = rhs.m_nAddr;
251 m_nSize = rhs.m_nSize;
252 m_nUsed = rhs.m_nUsed;
253 return *this;
256 /** Comparison.
258 bool operator== (const OStorePageDescriptor & rhs) const
260 return ((m_nAddr == rhs.m_nAddr) &&
261 (m_nSize == rhs.m_nSize) );
264 bool operator<= (const OStorePageDescriptor & rhs) const
266 return ((m_nAddr == rhs.m_nAddr ) &&
267 (store::ntohs(m_nSize) <= store::ntohs(rhs.m_nSize)) );
270 bool operator< (const OStorePageDescriptor & rhs) const
272 if (m_nAddr == rhs.m_nAddr)
273 return (store::ntohs(m_nSize) < store::ntohs(rhs.m_nSize));
274 else
275 return (store::ntohl(m_nAddr) < store::ntohl(rhs.m_nAddr));
279 /*========================================================================
281 * OStorePageKey.
283 *======================================================================*/
284 struct OStorePageKey
286 /** Representation.
288 sal_uInt32 m_nLow;
289 sal_uInt32 m_nHigh;
291 /** Construction.
293 explicit OStorePageKey (sal_uInt32 nLow = 0, sal_uInt32 nHigh = 0)
294 : m_nLow (store::htonl(nLow)),
295 m_nHigh (store::htonl(nHigh))
298 void swap (OStorePageKey & rhs)
300 store::swap(m_nLow, rhs.m_nLow);
301 store::swap(m_nHigh, rhs.m_nHigh);
304 OStorePageKey (const OStorePageKey & rhs)
305 : m_nLow (rhs.m_nLow), m_nHigh (rhs.m_nHigh)
308 OStorePageKey & operator= (const OStorePageKey & rhs)
310 m_nLow = rhs.m_nLow;
311 m_nHigh = rhs.m_nHigh;
312 return *this;
315 /** Comparison.
317 bool operator== (const OStorePageKey & rhs) const
319 return ((m_nLow == rhs.m_nLow ) &&
320 (m_nHigh == rhs.m_nHigh) );
323 bool operator< (const OStorePageKey & rhs) const
325 if (m_nHigh == rhs.m_nHigh)
326 return (store::ntohl(m_nLow) < store::ntohl(rhs.m_nLow));
327 else
328 return (store::ntohl(m_nHigh) < store::ntohl(rhs.m_nHigh));
332 /*========================================================================
334 * OStorePageLink.
336 *======================================================================*/
337 struct OStorePageLink
339 /** Representation.
341 sal_uInt32 m_nAddr;
343 /** Construction.
345 explicit OStorePageLink (sal_uInt32 nAddr = STORE_PAGE_NULL)
346 : m_nAddr (store::htonl(nAddr))
349 void swap (OStorePageLink & rhs)
351 store::swap(m_nAddr, rhs.m_nAddr);
354 OStorePageLink (const OStorePageLink & rhs)
355 : m_nAddr (rhs.m_nAddr)
358 OStorePageLink & operator= (const OStorePageLink & rhs)
360 m_nAddr = rhs.m_nAddr;
361 return *this;
364 OStorePageLink & operator= (sal_uInt32 nAddr)
366 m_nAddr = store::htonl(nAddr);
367 return *this;
370 /** Comparison.
372 bool operator== (const OStorePageLink & rhs) const
374 return (m_nAddr == rhs.m_nAddr);
377 bool operator< (const OStorePageLink& rhs) const
379 return (store::ntohl(m_nAddr) < store::ntohl(rhs.m_nAddr));
382 /** Operation.
384 sal_uInt32 location() const
386 return store::ntohl(m_nAddr);
389 void link (OStorePageLink & rPred)
391 // @@@ swap (rPred); @@@
392 OStorePageLink tmp (rPred);
393 rPred = *this;
394 *this = tmp;
397 void unlink (OStorePageLink& rPred)
399 rPred = *this;
400 *this = OStorePageLink();
404 /*========================================================================
406 * PageData.
408 *======================================================================*/
409 typedef struct PageData OStorePageData; // backward compat.
410 struct PageData
412 typedef OStorePageGuard G;
413 typedef OStorePageDescriptor D;
414 typedef OStorePageLink L;
416 /** Representation.
418 G m_aGuard;
419 D m_aDescr;
420 L m_aMarked;
421 L m_aUnused;
423 /** theSize.
425 static const size_t theSize = sizeof(G) + sizeof(D) + 2 * sizeof(L);
426 static const sal_uInt16 thePageSize = theSize;
427 static_assert(STORE_MINIMUM_PAGESIZE >= thePageSize, "must be at least thePageSize");
429 /** location.
431 sal_uInt32 location() const
433 return store::ntohl(m_aDescr.m_nAddr);
435 void location (sal_uInt32 nAddr)
437 m_aDescr.m_nAddr = store::htonl(nAddr);
440 /** size.
442 sal_uInt16 size() const
444 return store::ntohs(m_aDescr.m_nSize);
447 /** type.
449 sal_uInt32 type() const
451 return store::ntohl(m_aGuard.m_nMagic);
454 /** Allocation.
456 class Allocator_Impl;
457 class Allocator : public virtual salhelper::SimpleReferenceObject
459 public:
460 template< class T > T * construct()
462 void * page = 0; sal_uInt16 size = 0;
463 if (allocate (&page, &size))
465 return new(page) T(size);
467 return 0;
470 bool allocate (void ** ppPage, sal_uInt16 * pnSize)
472 allocate_Impl (ppPage, pnSize);
473 return ((*ppPage != 0) && (*pnSize != 0));
476 void deallocate (void * pPage)
478 if (pPage != 0)
479 deallocate_Impl (pPage);
482 static storeError createInstance (
483 rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize);
485 protected:
486 virtual ~Allocator() {}
488 private:
489 /** Implementation (abstract).
491 virtual void allocate_Impl (void ** ppPage, sal_uInt16 * pnSize) = 0;
492 virtual void deallocate_Impl (void * pPage) = 0;
495 static void* operator new (size_t, void * p) { return p; }
496 static void operator delete (void * , void *) {}
498 /** Construction.
500 explicit PageData (sal_uInt16 nPageSize = thePageSize)
501 : m_aGuard(),
502 m_aDescr(STORE_PAGE_NULL, nPageSize, thePageSize),
503 m_aMarked(),
504 m_aUnused()
507 void swap (PageData & rhs) // nothrow
509 m_aGuard.swap(rhs.m_aGuard);
510 m_aDescr.swap(rhs.m_aDescr);
511 m_aMarked.swap(rhs.m_aMarked);
512 m_aUnused.swap(rhs.m_aUnused);
515 PageData (PageData const & rhs) // nothrow
516 : m_aGuard (rhs.m_aGuard),
517 m_aDescr (rhs.m_aDescr),
518 m_aMarked(rhs.m_aMarked),
519 m_aUnused(rhs.m_aUnused)
522 PageData & operator= (PageData const & rhs) // nothrow
524 PageData tmp (rhs);
525 swap (tmp);
526 return *this;
529 /** guard (external representation).
531 void guard (sal_uInt32 nAddr)
533 sal_uInt32 nCRC32 = 0;
534 nCRC32 = rtl_crc32 (nCRC32, &m_aGuard.m_nMagic, sizeof(sal_uInt32));
535 m_aDescr.m_nAddr = store::htonl(nAddr);
536 nCRC32 = rtl_crc32 (nCRC32, &m_aDescr, theSize - sizeof(G));
537 m_aGuard.m_nCRC32 = store::htonl(nCRC32);
540 /** verify (external representation).
542 storeError verify (sal_uInt32 nAddr) const
544 sal_uInt32 nCRC32 = 0;
545 nCRC32 = rtl_crc32 (nCRC32, &m_aGuard.m_nMagic, sizeof(sal_uInt32));
546 nCRC32 = rtl_crc32 (nCRC32, &m_aDescr, theSize - sizeof(G));
547 if (m_aGuard.m_nCRC32 != store::htonl(nCRC32))
548 return store_E_InvalidChecksum;
549 if (m_aDescr.m_nAddr != store::htonl(nAddr))
550 return store_E_InvalidAccess;
551 return store_E_None;
554 storeError verifyVersion (sal_uInt32 nMagic) const
556 if (m_aGuard.m_nMagic != store::htonl(nMagic))
557 return store_E_WrongVersion;
558 else
559 return store_E_None;
563 /*========================================================================
565 * PageHolder.
567 *======================================================================*/
568 class PageHolder
570 SharedCount m_refcount;
571 PageData * m_pagedata;
573 typedef rtl::Reference< PageData::Allocator > allocator_type;
574 allocator_type m_allocator;
576 public:
577 explicit PageHolder (PageData * pagedata = 0, allocator_type const & allocator = allocator_type())
578 : m_refcount (),
579 m_pagedata (pagedata),
580 m_allocator(allocator)
582 OSL_ENSURE((m_pagedata == 0) || m_allocator.is(), "store::PageHolder::ctor(): pagedata w/o allocator.");
585 ~PageHolder()
587 if ((m_refcount == 1) && (m_pagedata != 0))
589 // free pagedata.
590 OSL_ENSURE(m_allocator.is(), "store::PageHolder::dtor(): pagedata w/o allocator.");
591 m_allocator->deallocate (m_pagedata);
595 void swap (PageHolder & rhs) // nothrow
597 m_refcount.swap(rhs.m_refcount);
598 store::swap(m_pagedata, rhs.m_pagedata);
599 store::swap(m_allocator, rhs.m_allocator);
602 PageHolder (PageHolder const & rhs) // nothrow
603 : m_refcount (rhs.m_refcount),
604 m_pagedata (rhs.m_pagedata),
605 m_allocator(rhs.m_allocator)
608 PageHolder & operator= (PageHolder const & rhs) // nothrow
610 PageHolder tmp (rhs);
611 swap(tmp);
612 return *this;
615 PageData * get() { return m_pagedata; }
616 PageData const * get() const { return m_pagedata; }
618 PageData * operator->()
620 OSL_PRECOND(m_pagedata != 0, "store::PageHolder::operator->(): Null pointer");
621 return m_pagedata;
623 PageData const * operator->() const
625 OSL_PRECOND(m_pagedata != 0, "store::PageHolder::operator->(): Null pointer");
626 return m_pagedata;
629 PageData & operator*()
631 OSL_PRECOND(m_pagedata != 0, "store::PageHolder::operator*(): Null pointer");
632 return *m_pagedata;
634 PageData const & operator*() const
636 OSL_PRECOND(m_pagedata != 0, "store::PageHolder::operator*(): Null pointer");
637 return *m_pagedata;
641 /*========================================================================
643 * PageHolderObject.
645 *======================================================================*/
646 template< class T >
647 class PageHolderObject
649 /** Representation.
651 PageHolder m_xPage;
653 /** Checked cast.
655 template< class U >
656 static bool isA (PageData const * p)
658 return ((p != 0) && (p->type() == U::theTypeId));
661 template< class U >
662 static U * dynamic_page_cast (PageData * p)
664 return isA<U>(p) ? static_cast<U*>(p) : 0;
667 template< class U >
668 static U const * dynamic_page_cast (PageData const * p)
670 return isA<U>(p) ? static_cast<U const *>(p) : 0;
673 public:
674 bool construct (rtl::Reference< PageData::Allocator > const & rxAllocator)
676 if ((m_xPage.get() == 0) && rxAllocator.is())
678 PageHolder tmp (rxAllocator->construct<T>(), rxAllocator);
679 m_xPage.swap (tmp);
681 return (m_xPage.get() != 0);
684 static PageHolderObject<T> createInstance (rtl::Reference< PageData::Allocator > const & rxAllocator)
686 PageHolderObject<T> tmp;
687 (void) tmp.construct (rxAllocator);
688 return tmp;
691 explicit PageHolderObject (PageHolder const & rxPage = PageHolder())
692 : m_xPage (rxPage)
695 void swap (PageHolderObject<T> & rhs)
697 m_xPage.swap (rhs.m_xPage);
700 PageHolderObject (PageHolderObject<T> const & rhs)
701 : m_xPage (rhs.m_xPage)
704 PageHolderObject<T> & operator= (PageHolderObject<T> const & rhs)
706 PageHolderObject<T> tmp (rhs);
707 this->swap (tmp);
708 return *this;
711 bool is() const
713 return (m_xPage.get() != 0);
716 #if 1 /* EXP */
717 PageHolder & get() { return m_xPage; }
718 PageHolder const & get() const { return m_xPage; }
719 #endif /* EXP */
721 T * operator->()
723 T * pImpl = dynamic_page_cast<T>(m_xPage.get());
724 OSL_PRECOND(pImpl != 0, "store::PageHolder<T>::operator*(): Null pointer");
725 return pImpl;
727 T const * operator->() const
729 T const * pImpl = dynamic_page_cast<T>(m_xPage.get());
730 OSL_PRECOND(pImpl != 0, "store::PageHolder<T>::operator*(): Null pointer");
731 return pImpl;
734 T & operator*()
736 T * pImpl = dynamic_page_cast<T>(m_xPage.get());
737 OSL_PRECOND(pImpl != 0, "store::PageHolder<T>::operator*(): Null pointer");
738 return (*pImpl);
740 T const & operator*() const
742 T const * pImpl = dynamic_page_cast<T>(m_xPage.get());
743 OSL_PRECOND(pImpl != 0, "store::PageHolder<T>::operator*(): Null pointer");
744 return (*pImpl);
747 static storeError guard (PageHolder & rxPage, sal_uInt32 nAddr)
749 PageData * pHead = rxPage.get();
750 if (!pHead)
751 return store_E_InvalidAccess;
752 pHead->guard(nAddr);
754 T * pImpl = dynamic_page_cast<T>(pHead);
755 OSL_PRECOND(pImpl != 0, "store::PageHolder<T>::guard(): Null pointer");
756 pImpl->guard();
758 return store_E_None;
760 static storeError verify (PageHolder const & rxPage, sal_uInt32 nAddr)
762 PageData const * pHead = rxPage.get();
763 if (!pHead)
764 return store_E_InvalidAccess;
766 storeError eErrCode = pHead->verify(nAddr);
767 if (eErrCode != store_E_None)
768 return eErrCode;
770 T const * pImpl = dynamic_page_cast<T>(pHead);
771 if (!pImpl)
772 return store_E_WrongVersion;
774 return pImpl->verify();
779 class OStorePageBIOS;
781 class OStorePageObject
783 typedef OStorePageData page;
785 public:
786 /** Allocation.
788 static void * operator new (size_t n)
790 return rtl_allocateMemory (sal_uInt32(n));
792 static void operator delete (void * p)
794 rtl_freeMemory (p);
797 /** State.
799 inline bool dirty() const;
800 inline void clean();
801 inline void touch();
803 /** Location.
805 inline sal_uInt32 location() const;
806 inline void location (sal_uInt32 nAddr);
808 protected:
809 /** Representation.
811 PageHolder m_xPage;
812 bool m_bDirty;
814 /** Construction.
816 explicit OStorePageObject (PageHolder const & rxPage = PageHolder())
817 : m_xPage (rxPage), m_bDirty (false)
820 /** Destruction.
822 virtual ~OStorePageObject();
824 public:
825 template< class U >
826 PageHolderObject<U> makeHolder() const
828 return PageHolderObject<U>(m_xPage);
831 template< class U >
832 storeError construct (rtl::Reference< PageData::Allocator > const & rxAllocator)
834 if (!rxAllocator.is())
835 return store_E_InvalidAccess;
837 PageHolder tmp (rxAllocator->construct<U>(), rxAllocator);
838 if (!tmp.get())
839 return store_E_OutOfMemory;
841 m_xPage.swap (tmp);
842 return store_E_None;
845 PageHolder & get() { return m_xPage; }
846 PageHolder const & get() const { return m_xPage; }
848 virtual storeError guard (sal_uInt32 nAddr) = 0;
849 virtual storeError verify (sal_uInt32 nAddr) const = 0;
852 inline bool OStorePageObject::dirty() const
854 return m_bDirty;
857 inline void OStorePageObject::clean()
859 m_bDirty = false;
862 inline void OStorePageObject::touch()
864 m_bDirty = true;
867 inline sal_uInt32 OStorePageObject::location() const
869 return m_xPage->location();
872 inline void OStorePageObject::location (sal_uInt32 nAddr)
874 m_xPage->location(nAddr);
875 touch();
878 /*========================================================================
880 * The End.
882 *======================================================================*/
884 } // namespace store
886 #endif // INCLUDED_STORE_SOURCE_STORBASE_HXX
888 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */