xref: /trunk/main/store/source/storbase.hxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #ifndef _STORE_STORBASE_HXX_
29 #define _STORE_STORBASE_HXX_ "$Revision: 1.10.8.4 $"
30 
31 #include "sal/types.h"
32 
33 #include "rtl/alloc.h"
34 #include "rtl/crc.h"
35 #include "rtl/ref.hxx"
36 
37 #include "osl/diagnose.h"
38 #include "osl/endian.h"
39 
40 #include "store/types.h"
41 
42 #ifndef INCLUDED_STDDEF_H
43 #include <stddef.h>
44 #define INCLUDED_STDDEF_H
45 #endif
46 
47 #ifndef INCLUDED_STRING_H
48 #include <string.h>
49 #define INCLUDED_STRING_H
50 #endif
51 
52 /*========================================================================
53  *
54  * store common internals.
55  *
56  *======================================================================*/
57 
58 #ifndef STORE_IMPL_ISP2
59 #define STORE_IMPL_ISP2(value) (((value) & ((value) - 1)) == 0)
60 #endif
61 
62 #ifndef STORE_IMPL_CONCAT
63 #define STORE_IMPL_CONCAT(x, y) STORE_IMPL_CONCAT2(x,y)
64 #define STORE_IMPL_CONCAT2(x, y) x##y
65 #endif
66 
67 #ifndef STORE_STATIC_ASSERT /* Compile time assertion */
68 namespace store
69 {
70     template< bool x > struct STATIC_ASSERTION_FAILURE;
71     template<> struct STATIC_ASSERTION_FAILURE< true > { enum { value = 1 }; };
72 
73     template< int x > struct static_assert_test{};
74 } // namespace store
75 
76 #define STORE_STATIC_ASSERT(pred) \
77 typedef \
78 store::static_assert_test< sizeof( store::STATIC_ASSERTION_FAILURE< (bool)(pred) > ) > \
79 STORE_IMPL_CONCAT(static_assert_typedef_, __LINE__)
80 
81 #endif  /* !STORE_STATIC_ASSERT */
82 
83 namespace store
84 {
85 
86 #ifdef htons
87 #undef htons
88 #endif
89 #ifdef ntohs
90 #undef ntohs
91 #endif
92 
93 #ifdef htonl
94 #undef htonl
95 #endif
96 #ifdef ntohl
97 #undef ntohl
98 #endif
99 
100 #ifdef OSL_BIGENDIAN
101 inline sal_uInt16 htons (sal_uInt16 h) { return OSL_SWAPWORD(h); }
102 inline sal_uInt16 ntohs (sal_uInt16 n) { return OSL_SWAPWORD(n); }
103 
104 inline sal_uInt32 htonl (sal_uInt32 h) { return OSL_SWAPDWORD(h); }
105 inline sal_uInt32 ntohl (sal_uInt32 n) { return OSL_SWAPDWORD(n); }
106 #else
107 inline sal_uInt16 htons (sal_uInt16 h) { return (h); }
108 inline sal_uInt16 ntohs (sal_uInt16 n) { return (n); }
109 
110 inline sal_uInt32 htonl (sal_uInt32 h) { return (h); }
111 inline sal_uInt32 ntohl (sal_uInt32 n) { return (n); }
112 #endif /* OSL_BIGENDIAN */
113 
114 /** swap.
115  */
116 template< typename T > void swap (T & lhs, T & rhs)
117 {
118     T tmp = lhs; lhs = rhs; rhs = tmp;
119 }
120 
121 /*========================================================================
122  *
123  * SharedCount.
124  *
125  *======================================================================*/
126 class SharedCount
127 {
128     long * m_pCount;
129 
130     class Allocator
131     {
132         rtl_cache_type * m_cache;
133 
134     public:
135         static Allocator & get();
136 
137         long * alloc()
138         {
139             return static_cast<long*>(rtl_cache_alloc (m_cache));
140         }
141         void free (long * pCount)
142         {
143             rtl_cache_free (m_cache, pCount);
144         }
145 
146     protected:
147         Allocator();
148         ~Allocator();
149     };
150 
151 public:
152     SharedCount()
153         : m_pCount(Allocator::get().alloc())
154     {
155         if (m_pCount != 0) (*m_pCount) = 1;
156     }
157 
158     ~SharedCount()
159     {
160         if (m_pCount != 0)
161         {
162             long new_count = --(*m_pCount);
163             if (new_count == 0)
164                 Allocator::get().free(m_pCount);
165         }
166     }
167 
168     void swap (SharedCount & rhs) // nothrow
169     {
170         store::swap(m_pCount, rhs.m_pCount);
171     }
172 
173     SharedCount (SharedCount const & rhs) // nothrow
174         : m_pCount (rhs.m_pCount)
175     {
176         if (m_pCount != 0) ++(*m_pCount);
177     }
178     SharedCount & operator= (SharedCount const & rhs) // nothrow
179     {
180         SharedCount tmp(rhs);
181         swap(tmp);
182         return *this;
183     }
184 
185     bool operator== (long count) const
186     {
187         return (m_pCount != 0) ? *m_pCount == count : false;
188     }
189 };
190 
191 /*========================================================================
192  *
193  * OStorePageGuard.
194  *
195  *======================================================================*/
196 struct OStorePageGuard
197 {
198     /** Representation.
199      */
200     sal_uInt32 m_nMagic;
201     sal_uInt32 m_nCRC32;
202 
203     /** Construction.
204      */
205     explicit OStorePageGuard (sal_uInt32 nMagic = 0, sal_uInt32 nCRC32 = 0)
206         : m_nMagic (store::htonl(nMagic)),
207           m_nCRC32 (store::htonl(nCRC32))
208     {}
209 
210     void swap (OStorePageGuard & rhs)
211     {
212         store::swap(m_nMagic, rhs.m_nMagic);
213         store::swap(m_nCRC32, rhs.m_nCRC32);
214     }
215 
216     OStorePageGuard (OStorePageGuard const & rhs)
217         : m_nMagic (rhs.m_nMagic),
218           m_nCRC32 (rhs.m_nCRC32)
219     {}
220 
221     OStorePageGuard& operator= (const OStorePageGuard& rhs)
222     {
223         m_nMagic = rhs.m_nMagic;
224         m_nCRC32 = rhs.m_nCRC32;
225         return *this;
226     }
227 
228     /** Comparison.
229      */
230     bool operator== (const OStorePageGuard& rhs) const
231     {
232         return ((m_nMagic == rhs.m_nMagic) &&
233                 (m_nCRC32 == rhs.m_nCRC32)    );
234     }
235 };
236 
237 /*========================================================================
238  *
239  * OStorePageDescriptor.
240  *
241  *======================================================================*/
242 #define STORE_PAGE_NULL ((sal_uInt32)(~0))
243 
244 struct OStorePageDescriptor
245 {
246     /** Representation.
247      */
248     sal_uInt32 m_nAddr;
249     sal_uInt16 m_nSize;
250     sal_uInt16 m_nUsed;
251 
252     /** Construction.
253      */
254     explicit OStorePageDescriptor (
255         sal_uInt32 nAddr = STORE_PAGE_NULL,
256         sal_uInt16 nSize = 0,
257         sal_uInt16 nUsed = 0)
258         : m_nAddr (store::htonl(nAddr)),
259           m_nSize (store::htons(nSize)),
260           m_nUsed (store::htons(nUsed))
261     {}
262 
263     void swap (OStorePageDescriptor & rhs)
264     {
265         store::swap(m_nAddr, rhs.m_nAddr);
266         store::swap(m_nSize, rhs.m_nSize);
267         store::swap(m_nUsed, rhs.m_nUsed);
268     }
269 
270     OStorePageDescriptor (const OStorePageDescriptor & rhs)
271         : m_nAddr (rhs.m_nAddr),
272           m_nSize (rhs.m_nSize),
273           m_nUsed (rhs.m_nUsed)
274     {}
275 
276     OStorePageDescriptor & operator= (const OStorePageDescriptor & rhs)
277     {
278         m_nAddr = rhs.m_nAddr;
279         m_nSize = rhs.m_nSize;
280         m_nUsed = rhs.m_nUsed;
281         return *this;
282     }
283 
284     /** Comparison.
285      */
286     bool operator== (const OStorePageDescriptor & rhs) const
287     {
288         return ((m_nAddr == rhs.m_nAddr) &&
289                 (m_nSize == rhs.m_nSize)    );
290     }
291 
292     bool operator<= (const OStorePageDescriptor & rhs) const
293     {
294         return ((m_nAddr               == rhs.m_nAddr              ) &&
295                 (store::ntohs(m_nSize) <= store::ntohs(rhs.m_nSize))    );
296     }
297 
298     bool operator< (const OStorePageDescriptor & rhs) const
299     {
300         if (m_nAddr == rhs.m_nAddr)
301             return (store::ntohs(m_nSize) < store::ntohs(rhs.m_nSize));
302         else
303             return (store::ntohl(m_nAddr) < store::ntohl(rhs.m_nAddr));
304     }
305 };
306 
307 /*========================================================================
308  *
309  * OStorePageKey.
310  *
311  *======================================================================*/
312 struct OStorePageKey
313 {
314     /** Representation.
315      */
316     sal_uInt32 m_nLow;
317     sal_uInt32 m_nHigh;
318 
319     /** Construction.
320      */
321     explicit OStorePageKey (sal_uInt32 nLow = 0, sal_uInt32 nHigh = 0)
322         : m_nLow  (store::htonl(nLow)),
323           m_nHigh (store::htonl(nHigh))
324     {}
325 
326     void swap (OStorePageKey & rhs)
327     {
328         store::swap(m_nLow,  rhs.m_nLow);
329         store::swap(m_nHigh, rhs.m_nHigh);
330     }
331 
332     OStorePageKey (const OStorePageKey & rhs)
333         : m_nLow (rhs.m_nLow), m_nHigh (rhs.m_nHigh)
334     {}
335 
336     OStorePageKey & operator= (const OStorePageKey & rhs)
337     {
338         m_nLow  = rhs.m_nLow;
339         m_nHigh = rhs.m_nHigh;
340         return *this;
341     }
342 
343     /** Comparison.
344      */
345     bool operator== (const OStorePageKey & rhs) const
346     {
347         return ((m_nLow  == rhs.m_nLow ) &&
348                 (m_nHigh == rhs.m_nHigh)    );
349     }
350 
351     bool operator< (const OStorePageKey & rhs) const
352     {
353         if (m_nHigh == rhs.m_nHigh)
354             return (store::ntohl(m_nLow) < store::ntohl(rhs.m_nLow));
355         else
356             return (store::ntohl(m_nHigh) < store::ntohl(rhs.m_nHigh));
357     }
358 };
359 
360 /*========================================================================
361  *
362  * OStorePageLink.
363  *
364  *======================================================================*/
365 struct OStorePageLink
366 {
367     /** Representation.
368      */
369     sal_uInt32 m_nAddr;
370 
371     /** Construction.
372      */
373     explicit OStorePageLink (sal_uInt32 nAddr = STORE_PAGE_NULL)
374         : m_nAddr (store::htonl(nAddr))
375     {}
376 
377     void swap (OStorePageLink & rhs)
378     {
379         store::swap(m_nAddr, rhs.m_nAddr);
380     }
381 
382     OStorePageLink (const OStorePageLink & rhs)
383         : m_nAddr (rhs.m_nAddr)
384     {}
385 
386     OStorePageLink & operator= (const OStorePageLink & rhs)
387     {
388         m_nAddr = rhs.m_nAddr;
389         return *this;
390     }
391 
392     OStorePageLink & operator= (sal_uInt32 nAddr)
393     {
394         m_nAddr = store::htonl(nAddr);
395         return *this;
396     }
397 
398     /** Comparison.
399      */
400     bool operator== (const OStorePageLink & rhs) const
401     {
402         return (m_nAddr == rhs.m_nAddr);
403     }
404 
405     bool operator< (const OStorePageLink& rhs) const
406     {
407         return (store::ntohl(m_nAddr) < store::ntohl(rhs.m_nAddr));
408     }
409 
410     /** Operation.
411      */
412     sal_uInt32 location() const
413     {
414         return store::ntohl(m_nAddr);
415     }
416 
417     void link (OStorePageLink & rPred)
418     {
419         // @@@ swap (rPred); @@@
420         OStorePageLink tmp (rPred);
421         rPred = *this;
422         *this = tmp;
423     }
424 
425     void unlink (OStorePageLink& rPred)
426     {
427         rPred = *this;
428         *this = OStorePageLink();
429     }
430 };
431 
432 /*========================================================================
433  *
434  * PageData.
435  *
436  *======================================================================*/
437 typedef struct PageData OStorePageData; // backward compat.
438 struct PageData
439 {
440     typedef OStorePageGuard      G;
441     typedef OStorePageDescriptor D;
442     typedef OStorePageLink       L;
443 
444     /** Representation.
445      */
446     G m_aGuard;
447     D m_aDescr;
448     L m_aMarked;
449     L m_aUnused;
450 
451     /** theSize.
452      */
453     static const size_t     theSize     = sizeof(G) + sizeof(D) + 2 * sizeof(L);
454     static const sal_uInt16 thePageSize = theSize;
455     STORE_STATIC_ASSERT(STORE_MINIMUM_PAGESIZE >= thePageSize);
456 
457     /** location.
458      */
459     sal_uInt32 location() const
460     {
461         return store::ntohl(m_aDescr.m_nAddr);
462     }
463     void location (sal_uInt32 nAddr)
464     {
465         m_aDescr.m_nAddr = store::htonl(nAddr);
466     }
467 
468     /** size.
469      */
470     sal_uInt16 size() const
471     {
472         return store::ntohs(m_aDescr.m_nSize);
473     }
474 
475     /** type.
476      */
477     sal_uInt32 type() const
478     {
479         return store::ntohl(m_aGuard.m_nMagic);
480     }
481 
482     /** Allocation.
483      */
484     class Allocator_Impl;
485     class Allocator : public rtl::IReference
486     {
487     public:
488         template< class T > T * construct()
489         {
490             void * page = 0; sal_uInt16 size = 0;
491             if (allocate (&page, &size))
492             {
493                 return new(page) T(size);
494             }
495             return 0;
496         }
497 
498         bool allocate (void ** ppPage, sal_uInt16 * pnSize)
499         {
500             allocate_Impl (ppPage, pnSize);
501             return ((*ppPage != 0) && (*pnSize != 0));
502         }
503 
504         void deallocate (void * pPage)
505         {
506             if (pPage != 0)
507                 deallocate_Impl (pPage);
508         }
509 
510         static storeError createInstance (
511             rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize);
512 
513     private:
514         /** Implementation (abstract).
515          */
516         virtual void allocate_Impl (void ** ppPage, sal_uInt16 * pnSize) = 0;
517         virtual void deallocate_Impl (void * pPage) = 0;
518     };
519 
520     static void* operator new (size_t, void * p) { return p; }
521     static void  operator delete (void * , void *) {}
522 
523     /** Construction.
524      */
525     explicit PageData (sal_uInt16 nPageSize = thePageSize)
526         : m_aGuard(),
527           m_aDescr(STORE_PAGE_NULL, nPageSize, thePageSize),
528           m_aMarked(),
529           m_aUnused()
530     {}
531 
532     void swap (PageData & rhs) // nothrow
533     {
534         m_aGuard.swap(rhs.m_aGuard);
535         m_aDescr.swap(rhs.m_aDescr);
536         m_aMarked.swap(rhs.m_aMarked);
537         m_aUnused.swap(rhs.m_aUnused);
538     }
539 
540     PageData (PageData const & rhs) // nothrow
541         : m_aGuard (rhs.m_aGuard),
542           m_aDescr (rhs.m_aDescr),
543           m_aMarked(rhs.m_aMarked),
544           m_aUnused(rhs.m_aUnused)
545     {}
546 
547     PageData & operator= (PageData const & rhs) // nothrow
548     {
549         PageData tmp (rhs);
550         swap (tmp);
551         return *this;
552     }
553 
554     /** guard (external representation).
555      */
556     void guard (sal_uInt32 nAddr)
557     {
558         sal_uInt32 nCRC32 = 0;
559         nCRC32 = rtl_crc32 (nCRC32, &m_aGuard.m_nMagic, sizeof(sal_uInt32));
560         m_aDescr.m_nAddr = store::htonl(nAddr);
561         nCRC32 = rtl_crc32 (nCRC32, &m_aDescr, theSize - sizeof(G));
562         m_aGuard.m_nCRC32 = store::htonl(nCRC32);
563     }
564 
565     /** verify (external representation).
566      */
567     storeError verify (sal_uInt32 nAddr) const
568     {
569         sal_uInt32 nCRC32 = 0;
570         nCRC32 = rtl_crc32 (nCRC32, &m_aGuard.m_nMagic, sizeof(sal_uInt32));
571         nCRC32 = rtl_crc32 (nCRC32, &m_aDescr, theSize - sizeof(G));
572         if (m_aGuard.m_nCRC32 != store::htonl(nCRC32))
573             return store_E_InvalidChecksum;
574         if (m_aDescr.m_nAddr != store::htonl(nAddr))
575             return store_E_InvalidAccess;
576         return store_E_None;
577     }
578 
579     storeError verifyVersion (sal_uInt32 nMagic) const
580     {
581         if (m_aGuard.m_nMagic != store::htonl(nMagic))
582             return store_E_WrongVersion;
583         else
584             return store_E_None;
585     }
586 };
587 
588 /*========================================================================
589  *
590  * PageHolder.
591  *
592  *======================================================================*/
593 class PageHolder
594 {
595     SharedCount m_refcount;
596     PageData  * m_pagedata;
597 
598     typedef rtl::Reference< PageData::Allocator > allocator_type;
599     allocator_type m_allocator;
600 
601 public:
602     explicit PageHolder (PageData * pagedata = 0, allocator_type const & allocator = allocator_type())
603         : m_refcount (),
604           m_pagedata (pagedata),
605           m_allocator(allocator)
606     {
607         OSL_ENSURE((m_pagedata == 0) || m_allocator.is(), "store::PageHolder::ctor(): pagedata w/o allocator.");
608     }
609 
610     ~PageHolder()
611     {
612         if ((m_refcount == 1) && (m_pagedata != 0))
613         {
614             // free pagedata.
615             OSL_ENSURE(m_allocator.is(), "store::PageHolder::dtor(): pagedata w/o allocator.");
616             m_allocator->deallocate (m_pagedata);
617         }
618     }
619 
620     void swap (PageHolder & rhs) // nothrow
621     {
622         m_refcount.swap(rhs.m_refcount);
623         store::swap(m_pagedata,  rhs.m_pagedata);
624         store::swap(m_allocator, rhs.m_allocator);
625     }
626 
627     PageHolder (PageHolder const & rhs) // nothrow
628         : m_refcount (rhs.m_refcount),
629           m_pagedata (rhs.m_pagedata),
630           m_allocator(rhs.m_allocator)
631     {}
632 
633     PageHolder & operator= (PageHolder const & rhs) // nothrow
634     {
635         PageHolder tmp (rhs);
636         swap(tmp);
637         return *this;
638     }
639 
640     PageData * get() { return m_pagedata; }
641     PageData const * get() const { return m_pagedata; }
642 
643     PageData * operator->()
644     {
645         OSL_PRECOND(m_pagedata != 0, "store::PageHolder::operator->(): Null pointer");
646         return m_pagedata;
647     }
648     PageData const * operator->() const
649     {
650         OSL_PRECOND(m_pagedata != 0, "store::PageHolder::operator->(): Null pointer");
651         return m_pagedata;
652     }
653 
654     PageData & operator*()
655     {
656         OSL_PRECOND(m_pagedata != 0, "store::PageHolder::operator*(): Null pointer");
657         return *m_pagedata;
658     }
659     PageData const & operator*() const
660     {
661         OSL_PRECOND(m_pagedata != 0, "store::PageHolder::operator*(): Null pointer");
662         return *m_pagedata;
663     }
664 };
665 
666 /*========================================================================
667  *
668  * PageHolderObject.
669  *
670  *======================================================================*/
671 template< class T >
672 class PageHolderObject
673 {
674     /** Representation.
675      */
676     PageHolder m_xPage;
677 
678     /** Checked cast.
679      */
680     template< class U >
681     static bool isA (PageData const * p)
682     {
683         return ((p != 0) && (p->type() == U::theTypeId));
684     }
685 
686     template< class U >
687     static U * dynamic_page_cast (PageData * p)
688     {
689         return isA<U>(p) ? static_cast<U*>(p) : 0;
690     }
691 
692     template< class U >
693     static U const * dynamic_page_cast (PageData const * p)
694     {
695         return isA<U>(p) ? static_cast<U const *>(p) : 0;
696     }
697 
698 public:
699     bool construct (rtl::Reference< PageData::Allocator > const & rxAllocator)
700     {
701         if ((m_xPage.get() == 0) && rxAllocator.is())
702         {
703             PageHolder tmp (rxAllocator->construct<T>(), rxAllocator);
704             m_xPage.swap (tmp);
705         }
706         return (m_xPage.get() != 0);
707     }
708 
709     static PageHolderObject<T> createInstance (rtl::Reference< PageData::Allocator > const & rxAllocator)
710     {
711         PageHolderObject<T> tmp;
712         (void) tmp.construct (rxAllocator);
713         return tmp;
714     }
715 
716     explicit PageHolderObject (PageHolder const & rxPage = PageHolder())
717         : m_xPage (rxPage)
718     {}
719 
720     void swap (PageHolderObject<T> & rhs)
721     {
722         m_xPage.swap (rhs.m_xPage);
723     }
724 
725     PageHolderObject (PageHolderObject<T> const & rhs)
726         : m_xPage (rhs.m_xPage)
727     {}
728 
729     PageHolderObject<T> & operator= (PageHolderObject<T> const & rhs)
730     {
731         PageHolderObject<T> tmp (rhs);
732         this->swap (tmp);
733         return *this;
734     }
735 
736     bool is() const
737     {
738         return (m_xPage.get() != 0);
739     }
740 
741 #if 1  /* EXP */
742     PageHolder & get() { return m_xPage; }
743     PageHolder const & get() const { return m_xPage; }
744 #endif /* EXP */
745 
746     T * operator->()
747     {
748         T * pImpl = dynamic_page_cast<T>(m_xPage.get());
749         OSL_PRECOND(pImpl != 0, "store::PageHolder<T>::operator*(): Null pointer");
750         return pImpl;
751     }
752     T const * operator->() const
753     {
754         T const * pImpl = dynamic_page_cast<T>(m_xPage.get());
755         OSL_PRECOND(pImpl != 0, "store::PageHolder<T>::operator*(): Null pointer");
756         return pImpl;
757     }
758 
759     T & operator*()
760     {
761         T * pImpl = dynamic_page_cast<T>(m_xPage.get());
762         OSL_PRECOND(pImpl != 0, "store::PageHolder<T>::operator*(): Null pointer");
763         return (*pImpl);
764     }
765     T const & operator*() const
766     {
767         T const * pImpl = dynamic_page_cast<T>(m_xPage.get());
768         OSL_PRECOND(pImpl != 0, "store::PageHolder<T>::operator*(): Null pointer");
769         return (*pImpl);
770     }
771 
772     static storeError guard (PageHolder & rxPage, sal_uInt32 nAddr)
773     {
774         PageData * pHead = rxPage.get();
775         if (!pHead)
776             return store_E_InvalidAccess;
777         pHead->guard(nAddr);
778 
779         T * pImpl = dynamic_page_cast<T>(pHead);
780         OSL_PRECOND(pImpl != 0, "store::PageHolder<T>::guard(): Null pointer");
781         pImpl->guard();
782 
783         return store_E_None;
784     }
785     static storeError verify (PageHolder const & rxPage, sal_uInt32 nAddr)
786     {
787         PageData const * pHead = rxPage.get();
788         if (!pHead)
789             return store_E_InvalidAccess;
790 
791         storeError eErrCode = pHead->verify(nAddr);
792         if (eErrCode != store_E_None)
793             return eErrCode;
794 
795         T const * pImpl = dynamic_page_cast<T>(pHead);
796         if (!pImpl)
797             return store_E_WrongVersion;
798 
799         return pImpl->verify();
800     }
801 };
802 
803 /*========================================================================
804  *
805  * PageObject.
806  *
807  *======================================================================*/
808 #if 1  /* EXP */
809 class PageObject
810 {
811 public:
812     explicit PageObject (PageHolder const & rxPage = PageHolder())
813         : m_xPage (rxPage), m_bDirty (false)
814     {}
815 
816     virtual ~PageObject()
817     {}
818 
819     PageHolder & get() { return m_xPage; }
820     PageHolder const & get() const { return m_xPage; }
821 
822     void clean() { m_bDirty = false; }
823     void touch() { m_bDirty = true; }
824 
825     sal_uInt32 location() const
826     {
827         PageData const * pagedata = m_xPage.get();
828         return (pagedata != 0) ? pagedata->location() : STORE_PAGE_NULL;
829     }
830     void location (sal_uInt32 nAddr)
831     {
832         PageData * pagedata = m_xPage.get();
833         if (pagedata != 0)
834             pagedata->location (nAddr);
835     }
836 
837 protected:
838     PageHolder m_xPage;
839     bool       m_bDirty;
840 
841     virtual storeError guard  (sal_uInt32 nAddr) = 0;
842     virtual storeError verify (sal_uInt32 nAddr) const = 0;
843 };
844 #endif /* EXP */
845 
846 class OStorePageBIOS;
847 
848 class OStorePageObject
849 {
850     typedef OStorePageData       page;
851 
852 public:
853     /** Allocation.
854      */
855     static void * operator new (size_t n) SAL_THROW(())
856     {
857         return rtl_allocateMemory (sal_uInt32(n));
858     }
859     static void operator delete (void * p, size_t) SAL_THROW(())
860     {
861         rtl_freeMemory (p);
862     }
863 
864     /** State.
865      */
866     inline bool dirty (void) const;
867     inline void clean (void);
868     inline void touch (void);
869 
870     /** Location.
871      */
872     inline sal_uInt32 location (void) const;
873     inline void       location (sal_uInt32 nAddr);
874 
875 protected:
876     /** Representation.
877      */
878     PageHolder m_xPage;
879     bool       m_bDirty;
880 
881     /** Construction.
882      */
883     explicit OStorePageObject (PageHolder const & rxPage = PageHolder())
884         : m_xPage (rxPage), m_bDirty (false)
885     {}
886 
887     /** Destruction.
888      */
889     virtual ~OStorePageObject (void);
890 
891 public:
892     template< class U >
893     PageHolderObject<U> makeHolder() const
894     {
895         return PageHolderObject<U>(m_xPage);
896     }
897 
898     template< class U >
899     storeError construct (rtl::Reference< PageData::Allocator > const & rxAllocator)
900     {
901         if (!rxAllocator.is())
902             return store_E_InvalidAccess;
903 
904         PageHolder tmp (rxAllocator->construct<U>(), rxAllocator);
905         if (!tmp.get())
906             return store_E_OutOfMemory;
907 
908         m_xPage.swap (tmp);
909         return store_E_None;
910     }
911 
912 
913     PageHolder & get() { return m_xPage; }
914     PageHolder const & get() const { return m_xPage; }
915 
916     virtual storeError guard  (sal_uInt32 nAddr) = 0;
917     virtual storeError verify (sal_uInt32 nAddr) const = 0;
918 };
919 
920 inline bool OStorePageObject::dirty (void) const
921 {
922     return m_bDirty;
923 }
924 
925 inline void OStorePageObject::clean (void)
926 {
927     m_bDirty = false;
928 }
929 
930 inline void OStorePageObject::touch (void)
931 {
932     m_bDirty = true;
933 }
934 
935 inline sal_uInt32 OStorePageObject::location (void) const
936 {
937     return m_xPage->location();
938 }
939 
940 inline void OStorePageObject::location (sal_uInt32 nAddr)
941 {
942     m_xPage->location(nAddr);
943     touch();
944 }
945 
946 /*========================================================================
947  *
948  * The End.
949  *
950  *======================================================================*/
951 
952 } // namespace store
953 
954 #endif /* !_STORE_STORBASE_HXX_ */
955