xref: /trunk/main/store/source/storbase.hxx (revision cdf0e10c)
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