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