1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
29 #ifndef _STORE_STORBASE_HXX_
30 #define _STORE_STORBASE_HXX_
32 #include "sal/types.h"
34 #include "rtl/alloc.h"
36 #include "rtl/ref.hxx"
38 #include "osl/diagnose.h"
39 #include "osl/endian.h"
41 #include "store/types.h"
43 #ifndef INCLUDED_STDDEF_H
45 #define INCLUDED_STDDEF_H
48 #ifndef INCLUDED_STRING_H
50 #define INCLUDED_STRING_H
53 /*========================================================================
55 * store common internals.
57 *======================================================================*/
59 #ifndef STORE_IMPL_ISP2
60 #define STORE_IMPL_ISP2(value) (((value) & ((value) - 1)) == 0)
63 #ifndef STORE_IMPL_CONCAT
64 #define STORE_IMPL_CONCAT(x, y) STORE_IMPL_CONCAT2(x,y)
65 #define STORE_IMPL_CONCAT2(x, y) x##y
68 #ifndef STORE_STATIC_ASSERT /* Compile time assertion */
71 template< bool x
> struct STATIC_ASSERTION_FAILURE
;
72 template<> struct STATIC_ASSERTION_FAILURE
< true > { enum { value
= 1 }; };
74 template< int x
> struct static_assert_test
{};
77 #define STORE_STATIC_ASSERT(pred) \
79 store::static_assert_test< sizeof( store::STATIC_ASSERTION_FAILURE< (bool)(pred) > ) > \
80 STORE_IMPL_CONCAT(static_assert_typedef_, __LINE__)
82 #endif /* !STORE_STATIC_ASSERT */
102 inline sal_uInt16
htons (sal_uInt16 h
) { return OSL_SWAPWORD(h
); }
103 inline sal_uInt16
ntohs (sal_uInt16 n
) { return OSL_SWAPWORD(n
); }
105 inline sal_uInt32
htonl (sal_uInt32 h
) { return OSL_SWAPDWORD(h
); }
106 inline sal_uInt32
ntohl (sal_uInt32 n
) { return OSL_SWAPDWORD(n
); }
108 inline sal_uInt16
htons (sal_uInt16 h
) { return (h
); }
109 inline sal_uInt16
ntohs (sal_uInt16 n
) { return (n
); }
111 inline sal_uInt32
htonl (sal_uInt32 h
) { return (h
); }
112 inline sal_uInt32
ntohl (sal_uInt32 n
) { return (n
); }
113 #endif /* OSL_BIGENDIAN */
117 template< typename T
> void swap (T
& lhs
, T
& rhs
)
119 T tmp
= lhs
; lhs
= rhs
; rhs
= tmp
;
122 /*========================================================================
126 *======================================================================*/
133 rtl_cache_type
* m_cache
;
136 static Allocator
& get();
140 return static_cast<long*>(rtl_cache_alloc (m_cache
));
142 void free (long * pCount
)
144 rtl_cache_free (m_cache
, pCount
);
154 : m_pCount(Allocator::get().alloc())
156 if (m_pCount
!= 0) (*m_pCount
) = 1;
163 long new_count
= --(*m_pCount
);
165 Allocator::get().free(m_pCount
);
169 void swap (SharedCount
& rhs
) // nothrow
171 store::swap(m_pCount
, rhs
.m_pCount
);
174 SharedCount (SharedCount
const & rhs
) // nothrow
175 : m_pCount (rhs
.m_pCount
)
177 if (m_pCount
!= 0) ++(*m_pCount
);
179 SharedCount
& operator= (SharedCount
const & rhs
) // nothrow
181 SharedCount
tmp(rhs
);
186 bool operator== (long count
) const
188 return (m_pCount
!= 0) ? *m_pCount
== count
: false;
192 /*========================================================================
196 *======================================================================*/
197 struct OStorePageGuard
206 explicit OStorePageGuard (sal_uInt32 nMagic
= 0, sal_uInt32 nCRC32
= 0)
207 : m_nMagic (store::htonl(nMagic
)),
208 m_nCRC32 (store::htonl(nCRC32
))
211 void swap (OStorePageGuard
& rhs
)
213 store::swap(m_nMagic
, rhs
.m_nMagic
);
214 store::swap(m_nCRC32
, rhs
.m_nCRC32
);
217 OStorePageGuard (OStorePageGuard
const & rhs
)
218 : m_nMagic (rhs
.m_nMagic
),
219 m_nCRC32 (rhs
.m_nCRC32
)
222 OStorePageGuard
& operator= (const OStorePageGuard
& rhs
)
224 m_nMagic
= rhs
.m_nMagic
;
225 m_nCRC32
= rhs
.m_nCRC32
;
231 bool operator== (const OStorePageGuard
& rhs
) const
233 return ((m_nMagic
== rhs
.m_nMagic
) &&
234 (m_nCRC32
== rhs
.m_nCRC32
) );
238 /*========================================================================
240 * OStorePageDescriptor.
242 *======================================================================*/
243 #define STORE_PAGE_NULL ((sal_uInt32)(~0))
245 struct OStorePageDescriptor
255 explicit OStorePageDescriptor (
256 sal_uInt32 nAddr
= STORE_PAGE_NULL
,
257 sal_uInt16 nSize
= 0,
258 sal_uInt16 nUsed
= 0)
259 : m_nAddr (store::htonl(nAddr
)),
260 m_nSize (store::htons(nSize
)),
261 m_nUsed (store::htons(nUsed
))
264 void swap (OStorePageDescriptor
& rhs
)
266 store::swap(m_nAddr
, rhs
.m_nAddr
);
267 store::swap(m_nSize
, rhs
.m_nSize
);
268 store::swap(m_nUsed
, rhs
.m_nUsed
);
271 OStorePageDescriptor (const OStorePageDescriptor
& rhs
)
272 : m_nAddr (rhs
.m_nAddr
),
273 m_nSize (rhs
.m_nSize
),
274 m_nUsed (rhs
.m_nUsed
)
277 OStorePageDescriptor
& operator= (const OStorePageDescriptor
& rhs
)
279 m_nAddr
= rhs
.m_nAddr
;
280 m_nSize
= rhs
.m_nSize
;
281 m_nUsed
= rhs
.m_nUsed
;
287 bool operator== (const OStorePageDescriptor
& rhs
) const
289 return ((m_nAddr
== rhs
.m_nAddr
) &&
290 (m_nSize
== rhs
.m_nSize
) );
293 bool operator<= (const OStorePageDescriptor
& rhs
) const
295 return ((m_nAddr
== rhs
.m_nAddr
) &&
296 (store::ntohs(m_nSize
) <= store::ntohs(rhs
.m_nSize
)) );
299 bool operator< (const OStorePageDescriptor
& rhs
) const
301 if (m_nAddr
== rhs
.m_nAddr
)
302 return (store::ntohs(m_nSize
) < store::ntohs(rhs
.m_nSize
));
304 return (store::ntohl(m_nAddr
) < store::ntohl(rhs
.m_nAddr
));
308 /*========================================================================
312 *======================================================================*/
322 explicit OStorePageKey (sal_uInt32 nLow
= 0, sal_uInt32 nHigh
= 0)
323 : m_nLow (store::htonl(nLow
)),
324 m_nHigh (store::htonl(nHigh
))
327 void swap (OStorePageKey
& rhs
)
329 store::swap(m_nLow
, rhs
.m_nLow
);
330 store::swap(m_nHigh
, rhs
.m_nHigh
);
333 OStorePageKey (const OStorePageKey
& rhs
)
334 : m_nLow (rhs
.m_nLow
), m_nHigh (rhs
.m_nHigh
)
337 OStorePageKey
& operator= (const OStorePageKey
& rhs
)
340 m_nHigh
= rhs
.m_nHigh
;
346 bool operator== (const OStorePageKey
& rhs
) const
348 return ((m_nLow
== rhs
.m_nLow
) &&
349 (m_nHigh
== rhs
.m_nHigh
) );
352 bool operator< (const OStorePageKey
& rhs
) const
354 if (m_nHigh
== rhs
.m_nHigh
)
355 return (store::ntohl(m_nLow
) < store::ntohl(rhs
.m_nLow
));
357 return (store::ntohl(m_nHigh
) < store::ntohl(rhs
.m_nHigh
));
361 /*========================================================================
365 *======================================================================*/
366 struct OStorePageLink
374 explicit OStorePageLink (sal_uInt32 nAddr
= STORE_PAGE_NULL
)
375 : m_nAddr (store::htonl(nAddr
))
378 void swap (OStorePageLink
& rhs
)
380 store::swap(m_nAddr
, rhs
.m_nAddr
);
383 OStorePageLink (const OStorePageLink
& rhs
)
384 : m_nAddr (rhs
.m_nAddr
)
387 OStorePageLink
& operator= (const OStorePageLink
& rhs
)
389 m_nAddr
= rhs
.m_nAddr
;
393 OStorePageLink
& operator= (sal_uInt32 nAddr
)
395 m_nAddr
= store::htonl(nAddr
);
401 bool operator== (const OStorePageLink
& rhs
) const
403 return (m_nAddr
== rhs
.m_nAddr
);
406 bool operator< (const OStorePageLink
& rhs
) const
408 return (store::ntohl(m_nAddr
) < store::ntohl(rhs
.m_nAddr
));
413 sal_uInt32
location() const
415 return store::ntohl(m_nAddr
);
418 void link (OStorePageLink
& rPred
)
420 // @@@ swap (rPred); @@@
421 OStorePageLink
tmp (rPred
);
426 void unlink (OStorePageLink
& rPred
)
429 *this = OStorePageLink();
433 /*========================================================================
437 *======================================================================*/
438 typedef struct PageData OStorePageData
; // backward compat.
441 typedef OStorePageGuard G
;
442 typedef OStorePageDescriptor D
;
443 typedef OStorePageLink L
;
454 static const size_t theSize
= sizeof(G
) + sizeof(D
) + 2 * sizeof(L
);
455 static const sal_uInt16 thePageSize
= theSize
;
456 STORE_STATIC_ASSERT(STORE_MINIMUM_PAGESIZE
>= thePageSize
);
460 sal_uInt32
location() const
462 return store::ntohl(m_aDescr
.m_nAddr
);
464 void location (sal_uInt32 nAddr
)
466 m_aDescr
.m_nAddr
= store::htonl(nAddr
);
471 sal_uInt16
size() const
473 return store::ntohs(m_aDescr
.m_nSize
);
478 sal_uInt32
type() const
480 return store::ntohl(m_aGuard
.m_nMagic
);
485 class Allocator_Impl
;
486 class Allocator
: public rtl::IReference
489 template< class T
> T
* construct()
491 void * page
= 0; sal_uInt16 size
= 0;
492 if (allocate (&page
, &size
))
494 return new(page
) T(size
);
499 bool allocate (void ** ppPage
, sal_uInt16
* pnSize
)
501 allocate_Impl (ppPage
, pnSize
);
502 return ((*ppPage
!= 0) && (*pnSize
!= 0));
505 void deallocate (void * pPage
)
508 deallocate_Impl (pPage
);
511 static storeError
createInstance (
512 rtl::Reference
< PageData::Allocator
> & rxAllocator
, sal_uInt16 nPageSize
);
518 /** Implementation (abstract).
520 virtual void allocate_Impl (void ** ppPage
, sal_uInt16
* pnSize
) = 0;
521 virtual void deallocate_Impl (void * pPage
) = 0;
524 static void* operator new (size_t, void * p
) { return p
; }
525 static void operator delete (void * , void *) {}
529 explicit PageData (sal_uInt16 nPageSize
= thePageSize
)
531 m_aDescr(STORE_PAGE_NULL
, nPageSize
, thePageSize
),
536 void swap (PageData
& rhs
) // nothrow
538 m_aGuard
.swap(rhs
.m_aGuard
);
539 m_aDescr
.swap(rhs
.m_aDescr
);
540 m_aMarked
.swap(rhs
.m_aMarked
);
541 m_aUnused
.swap(rhs
.m_aUnused
);
544 PageData (PageData
const & rhs
) // nothrow
545 : m_aGuard (rhs
.m_aGuard
),
546 m_aDescr (rhs
.m_aDescr
),
547 m_aMarked(rhs
.m_aMarked
),
548 m_aUnused(rhs
.m_aUnused
)
551 PageData
& operator= (PageData
const & rhs
) // nothrow
558 /** guard (external representation).
560 void guard (sal_uInt32 nAddr
)
562 sal_uInt32 nCRC32
= 0;
563 nCRC32
= rtl_crc32 (nCRC32
, &m_aGuard
.m_nMagic
, sizeof(sal_uInt32
));
564 m_aDescr
.m_nAddr
= store::htonl(nAddr
);
565 nCRC32
= rtl_crc32 (nCRC32
, &m_aDescr
, theSize
- sizeof(G
));
566 m_aGuard
.m_nCRC32
= store::htonl(nCRC32
);
569 /** verify (external representation).
571 storeError
verify (sal_uInt32 nAddr
) const
573 sal_uInt32 nCRC32
= 0;
574 nCRC32
= rtl_crc32 (nCRC32
, &m_aGuard
.m_nMagic
, sizeof(sal_uInt32
));
575 nCRC32
= rtl_crc32 (nCRC32
, &m_aDescr
, theSize
- sizeof(G
));
576 if (m_aGuard
.m_nCRC32
!= store::htonl(nCRC32
))
577 return store_E_InvalidChecksum
;
578 if (m_aDescr
.m_nAddr
!= store::htonl(nAddr
))
579 return store_E_InvalidAccess
;
583 storeError
verifyVersion (sal_uInt32 nMagic
) const
585 if (m_aGuard
.m_nMagic
!= store::htonl(nMagic
))
586 return store_E_WrongVersion
;
592 /*========================================================================
596 *======================================================================*/
599 SharedCount m_refcount
;
600 PageData
* m_pagedata
;
602 typedef rtl::Reference
< PageData::Allocator
> allocator_type
;
603 allocator_type m_allocator
;
606 explicit PageHolder (PageData
* pagedata
= 0, allocator_type
const & allocator
= allocator_type())
608 m_pagedata (pagedata
),
609 m_allocator(allocator
)
611 OSL_ENSURE((m_pagedata
== 0) || m_allocator
.is(), "store::PageHolder::ctor(): pagedata w/o allocator.");
616 if ((m_refcount
== 1) && (m_pagedata
!= 0))
619 OSL_ENSURE(m_allocator
.is(), "store::PageHolder::dtor(): pagedata w/o allocator.");
620 m_allocator
->deallocate (m_pagedata
);
624 void swap (PageHolder
& rhs
) // nothrow
626 m_refcount
.swap(rhs
.m_refcount
);
627 store::swap(m_pagedata
, rhs
.m_pagedata
);
628 store::swap(m_allocator
, rhs
.m_allocator
);
631 PageHolder (PageHolder
const & rhs
) // nothrow
632 : m_refcount (rhs
.m_refcount
),
633 m_pagedata (rhs
.m_pagedata
),
634 m_allocator(rhs
.m_allocator
)
637 PageHolder
& operator= (PageHolder
const & rhs
) // nothrow
639 PageHolder
tmp (rhs
);
644 PageData
* get() { return m_pagedata
; }
645 PageData
const * get() const { return m_pagedata
; }
647 PageData
* operator->()
649 OSL_PRECOND(m_pagedata
!= 0, "store::PageHolder::operator->(): Null pointer");
652 PageData
const * operator->() const
654 OSL_PRECOND(m_pagedata
!= 0, "store::PageHolder::operator->(): Null pointer");
658 PageData
& operator*()
660 OSL_PRECOND(m_pagedata
!= 0, "store::PageHolder::operator*(): Null pointer");
663 PageData
const & operator*() const
665 OSL_PRECOND(m_pagedata
!= 0, "store::PageHolder::operator*(): Null pointer");
670 /*========================================================================
674 *======================================================================*/
676 class PageHolderObject
685 static bool isA (PageData
const * p
)
687 return ((p
!= 0) && (p
->type() == U::theTypeId
));
691 static U
* dynamic_page_cast (PageData
* p
)
693 return isA
<U
>(p
) ? static_cast<U
*>(p
) : 0;
697 static U
const * dynamic_page_cast (PageData
const * p
)
699 return isA
<U
>(p
) ? static_cast<U
const *>(p
) : 0;
703 bool construct (rtl::Reference
< PageData::Allocator
> const & rxAllocator
)
705 if ((m_xPage
.get() == 0) && rxAllocator
.is())
707 PageHolder
tmp (rxAllocator
->construct
<T
>(), rxAllocator
);
710 return (m_xPage
.get() != 0);
713 static PageHolderObject
<T
> createInstance (rtl::Reference
< PageData::Allocator
> const & rxAllocator
)
715 PageHolderObject
<T
> tmp
;
716 (void) tmp
.construct (rxAllocator
);
720 explicit PageHolderObject (PageHolder
const & rxPage
= PageHolder())
724 void swap (PageHolderObject
<T
> & rhs
)
726 m_xPage
.swap (rhs
.m_xPage
);
729 PageHolderObject (PageHolderObject
<T
> const & rhs
)
730 : m_xPage (rhs
.m_xPage
)
733 PageHolderObject
<T
> & operator= (PageHolderObject
<T
> const & rhs
)
735 PageHolderObject
<T
> tmp (rhs
);
742 return (m_xPage
.get() != 0);
746 PageHolder
& get() { return m_xPage
; }
747 PageHolder
const & get() const { return m_xPage
; }
752 T
* pImpl
= dynamic_page_cast
<T
>(m_xPage
.get());
753 OSL_PRECOND(pImpl
!= 0, "store::PageHolder<T>::operator*(): Null pointer");
756 T
const * operator->() const
758 T
const * pImpl
= dynamic_page_cast
<T
>(m_xPage
.get());
759 OSL_PRECOND(pImpl
!= 0, "store::PageHolder<T>::operator*(): Null pointer");
765 T
* pImpl
= dynamic_page_cast
<T
>(m_xPage
.get());
766 OSL_PRECOND(pImpl
!= 0, "store::PageHolder<T>::operator*(): Null pointer");
769 T
const & operator*() const
771 T
const * pImpl
= dynamic_page_cast
<T
>(m_xPage
.get());
772 OSL_PRECOND(pImpl
!= 0, "store::PageHolder<T>::operator*(): Null pointer");
776 static storeError
guard (PageHolder
& rxPage
, sal_uInt32 nAddr
)
778 PageData
* pHead
= rxPage
.get();
780 return store_E_InvalidAccess
;
783 T
* pImpl
= dynamic_page_cast
<T
>(pHead
);
784 OSL_PRECOND(pImpl
!= 0, "store::PageHolder<T>::guard(): Null pointer");
789 static storeError
verify (PageHolder
const & rxPage
, sal_uInt32 nAddr
)
791 PageData
const * pHead
= rxPage
.get();
793 return store_E_InvalidAccess
;
795 storeError eErrCode
= pHead
->verify(nAddr
);
796 if (eErrCode
!= store_E_None
)
799 T
const * pImpl
= dynamic_page_cast
<T
>(pHead
);
801 return store_E_WrongVersion
;
803 return pImpl
->verify();
807 /*========================================================================
811 *======================================================================*/
816 explicit PageObject (PageHolder
const & rxPage
= PageHolder())
817 : m_xPage (rxPage
), m_bDirty (false)
820 virtual ~PageObject()
823 PageHolder
& get() { return m_xPage
; }
824 PageHolder
const & get() const { return m_xPage
; }
826 void clean() { m_bDirty
= false; }
827 void touch() { m_bDirty
= true; }
829 sal_uInt32
location() const
831 PageData
const * pagedata
= m_xPage
.get();
832 return (pagedata
!= 0) ? pagedata
->location() : STORE_PAGE_NULL
;
834 void location (sal_uInt32 nAddr
)
836 PageData
* pagedata
= m_xPage
.get();
838 pagedata
->location (nAddr
);
845 virtual storeError
guard (sal_uInt32 nAddr
) = 0;
846 virtual storeError
verify (sal_uInt32 nAddr
) const = 0;
850 class OStorePageBIOS
;
852 class OStorePageObject
854 typedef OStorePageData page
;
859 static void * operator new (size_t n
) SAL_THROW(())
861 return rtl_allocateMemory (sal_uInt32(n
));
863 static void operator delete (void * p
) SAL_THROW(())
870 inline bool dirty (void) const;
871 inline void clean (void);
872 inline void touch (void);
876 inline sal_uInt32
location (void) const;
877 inline void location (sal_uInt32 nAddr
);
887 explicit OStorePageObject (PageHolder
const & rxPage
= PageHolder())
888 : m_xPage (rxPage
), m_bDirty (false)
893 virtual ~OStorePageObject (void);
897 PageHolderObject
<U
> makeHolder() const
899 return PageHolderObject
<U
>(m_xPage
);
903 storeError
construct (rtl::Reference
< PageData::Allocator
> const & rxAllocator
)
905 if (!rxAllocator
.is())
906 return store_E_InvalidAccess
;
908 PageHolder
tmp (rxAllocator
->construct
<U
>(), rxAllocator
);
910 return store_E_OutOfMemory
;
917 PageHolder
& get() { return m_xPage
; }
918 PageHolder
const & get() const { return m_xPage
; }
920 virtual storeError
guard (sal_uInt32 nAddr
) = 0;
921 virtual storeError
verify (sal_uInt32 nAddr
) const = 0;
924 inline bool OStorePageObject::dirty (void) const
929 inline void OStorePageObject::clean (void)
934 inline void OStorePageObject::touch (void)
939 inline sal_uInt32
OStorePageObject::location (void) const
941 return m_xPage
->location();
944 inline void OStorePageObject::location (sal_uInt32 nAddr
)
946 m_xPage
->location(nAddr
);
950 /*========================================================================
954 *======================================================================*/
958 #endif /* !_STORE_STORBASE_HXX_ */
960 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */