xref: /AOO41X/main/store/source/storbase.hxx (revision 1a5fa39be4c30003d60dac254349a6f82563f140)
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
htons(sal_uInt16 h)97 inline sal_uInt16 htons (sal_uInt16 h) { return OSL_SWAPWORD(h); }
ntohs(sal_uInt16 n)98 inline sal_uInt16 ntohs (sal_uInt16 n) { return OSL_SWAPWORD(n); }
99 
htonl(sal_uInt32 h)100 inline sal_uInt32 htonl (sal_uInt32 h) { return OSL_SWAPDWORD(h); }
ntohl(sal_uInt32 n)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  */
swap(T & lhs,T & rhs)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 
alloc()133         long * alloc()
134         {
135             return static_cast<long*>(rtl_cache_alloc (m_cache));
136         }
free(long * pCount)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:
SharedCount()148     SharedCount()
149         : m_pCount(Allocator::get().alloc())
150     {
151         if (m_pCount != 0) (*m_pCount) = 1;
152     }
153 
~SharedCount()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 
swap(SharedCount & rhs)164     void swap (SharedCount & rhs) // nothrow
165     {
166         store::swap(m_pCount, rhs.m_pCount);
167     }
168 
SharedCount(SharedCount const & rhs)169     SharedCount (SharedCount const & rhs) // nothrow
170         : m_pCount (rhs.m_pCount)
171     {
172         if (m_pCount != 0) ++(*m_pCount);
173     }
operator =(SharedCount const & rhs)174     SharedCount & operator= (SharedCount const & rhs) // nothrow
175     {
176         SharedCount tmp(rhs);
177         swap(tmp);
178         return *this;
179     }
180 
operator ==(long count) const181     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      */
OStorePageGuardstore::OStorePageGuard201     explicit OStorePageGuard (sal_uInt32 nMagic = 0, sal_uInt32 nCRC32 = 0)
202         : m_nMagic (store::htonl(nMagic)),
203           m_nCRC32 (store::htonl(nCRC32))
204     {}
205 
swapstore::OStorePageGuard206     void swap (OStorePageGuard & rhs)
207     {
208         store::swap(m_nMagic, rhs.m_nMagic);
209         store::swap(m_nCRC32, rhs.m_nCRC32);
210     }
211 
OStorePageGuardstore::OStorePageGuard212     OStorePageGuard (OStorePageGuard const & rhs)
213         : m_nMagic (rhs.m_nMagic),
214           m_nCRC32 (rhs.m_nCRC32)
215     {}
216 
operator =store::OStorePageGuard217     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      */
operator ==store::OStorePageGuard226     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      */
OStorePageDescriptorstore::OStorePageDescriptor250     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 
swapstore::OStorePageDescriptor259     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 
OStorePageDescriptorstore::OStorePageDescriptor266     OStorePageDescriptor (const OStorePageDescriptor & rhs)
267         : m_nAddr (rhs.m_nAddr),
268           m_nSize (rhs.m_nSize),
269           m_nUsed (rhs.m_nUsed)
270     {}
271 
operator =store::OStorePageDescriptor272     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      */
operator ==store::OStorePageDescriptor282     bool operator== (const OStorePageDescriptor & rhs) const
283     {
284         return ((m_nAddr == rhs.m_nAddr) &&
285                 (m_nSize == rhs.m_nSize)    );
286     }
287 
operator <=store::OStorePageDescriptor288     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 
operator <store::OStorePageDescriptor294     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      */
OStorePageKeystore::OStorePageKey317     explicit OStorePageKey (sal_uInt32 nLow = 0, sal_uInt32 nHigh = 0)
318         : m_nLow  (store::htonl(nLow)),
319           m_nHigh (store::htonl(nHigh))
320     {}
321 
swapstore::OStorePageKey322     void swap (OStorePageKey & rhs)
323     {
324         store::swap(m_nLow,  rhs.m_nLow);
325         store::swap(m_nHigh, rhs.m_nHigh);
326     }
327 
OStorePageKeystore::OStorePageKey328     OStorePageKey (const OStorePageKey & rhs)
329         : m_nLow (rhs.m_nLow), m_nHigh (rhs.m_nHigh)
330     {}
331 
operator =store::OStorePageKey332     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      */
operator ==store::OStorePageKey341     bool operator== (const OStorePageKey & rhs) const
342     {
343         return ((m_nLow  == rhs.m_nLow ) &&
344                 (m_nHigh == rhs.m_nHigh)    );
345     }
346 
operator <store::OStorePageKey347     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      */
OStorePageLinkstore::OStorePageLink369     explicit OStorePageLink (sal_uInt32 nAddr = STORE_PAGE_NULL)
370         : m_nAddr (store::htonl(nAddr))
371     {}
372 
swapstore::OStorePageLink373     void swap (OStorePageLink & rhs)
374     {
375         store::swap(m_nAddr, rhs.m_nAddr);
376     }
377 
OStorePageLinkstore::OStorePageLink378     OStorePageLink (const OStorePageLink & rhs)
379         : m_nAddr (rhs.m_nAddr)
380     {}
381 
operator =store::OStorePageLink382     OStorePageLink & operator= (const OStorePageLink & rhs)
383     {
384         m_nAddr = rhs.m_nAddr;
385         return *this;
386     }
387 
operator =store::OStorePageLink388     OStorePageLink & operator= (sal_uInt32 nAddr)
389     {
390         m_nAddr = store::htonl(nAddr);
391         return *this;
392     }
393 
394     /** Comparison.
395      */
operator ==store::OStorePageLink396     bool operator== (const OStorePageLink & rhs) const
397     {
398         return (m_nAddr == rhs.m_nAddr);
399     }
400 
operator <store::OStorePageLink401     bool operator< (const OStorePageLink& rhs) const
402     {
403         return (store::ntohl(m_nAddr) < store::ntohl(rhs.m_nAddr));
404     }
405 
406     /** Operation.
407      */
locationstore::OStorePageLink408     sal_uInt32 location() const
409     {
410         return store::ntohl(m_nAddr);
411     }
412 
linkstore::OStorePageLink413     void link (OStorePageLink & rPred)
414     {
415         // @@@ swap (rPred); @@@
416         OStorePageLink tmp (rPred);
417         rPred = *this;
418         *this = tmp;
419     }
420 
unlinkstore::OStorePageLink421     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      */
locationstore::PageData455     sal_uInt32 location() const
456     {
457         return store::ntohl(m_aDescr.m_nAddr);
458     }
locationstore::PageData459     void location (sal_uInt32 nAddr)
460     {
461         m_aDescr.m_nAddr = store::htonl(nAddr);
462     }
463 
464     /** size.
465      */
sizestore::PageData466     sal_uInt16 size() const
467     {
468         return store::ntohs(m_aDescr.m_nSize);
469     }
470 
471     /** type.
472      */
typestore::PageData473     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:
construct()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 
allocate(void ** ppPage,sal_uInt16 * pnSize)494         bool allocate (void ** ppPage, sal_uInt16 * pnSize)
495         {
496             allocate_Impl (ppPage, pnSize);
497             return ((*ppPage != 0) && (*pnSize != 0));
498         }
499 
deallocate(void * pPage)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 
operator newstore::PageData516     static void* operator new (size_t, void * p) { return p; }
operator deletestore::PageData517     static void  operator delete (void * , void *) {}
518 
519     /** Construction.
520      */
PageDatastore::PageData521     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 
swapstore::PageData528     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 
PageDatastore::PageData536     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 
operator =store::PageData543     PageData & operator= (PageData const & rhs) // nothrow
544     {
545         PageData tmp (rhs);
546         swap (tmp);
547         return *this;
548     }
549 
550     /** guard (external representation).
551      */
guardstore::PageData552     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      */
verifystore::PageData563     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 
verifyVersionstore::PageData575     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:
PageHolder(PageData * pagedata=0,allocator_type const & allocator=allocator_type ())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 
~PageHolder()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 
swap(PageHolder & rhs)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 
PageHolder(PageHolder const & rhs)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 
operator =(PageHolder const & rhs)629     PageHolder & operator= (PageHolder const & rhs) // nothrow
630     {
631         PageHolder tmp (rhs);
632         swap(tmp);
633         return *this;
634     }
635 
get()636     PageData * get() { return m_pagedata; }
get() const637     PageData const * get() const { return m_pagedata; }
638 
operator ->()639     PageData * operator->()
640     {
641         OSL_PRECOND(m_pagedata != 0, "store::PageHolder::operator->(): Null pointer");
642         return m_pagedata;
643     }
operator ->() const644     PageData const * operator->() const
645     {
646         OSL_PRECOND(m_pagedata != 0, "store::PageHolder::operator->(): Null pointer");
647         return m_pagedata;
648     }
649 
operator *()650     PageData & operator*()
651     {
652         OSL_PRECOND(m_pagedata != 0, "store::PageHolder::operator*(): Null pointer");
653         return *m_pagedata;
654     }
operator *() const655     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 >
isA(PageData const * p)677     static bool isA (PageData const * p)
678     {
679         return ((p != 0) && (p->type() == U::theTypeId));
680     }
681 
682     template< class U >
dynamic_page_cast(PageData * p)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 >
dynamic_page_cast(PageData const * p)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:
construct(rtl::Reference<PageData::Allocator> const & rxAllocator)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 
createInstance(rtl::Reference<PageData::Allocator> const & rxAllocator)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 
PageHolderObject(PageHolder const & rxPage=PageHolder ())712     explicit PageHolderObject (PageHolder const & rxPage = PageHolder())
713         : m_xPage (rxPage)
714     {}
715 
swap(PageHolderObject<T> & rhs)716     void swap (PageHolderObject<T> & rhs)
717     {
718         m_xPage.swap (rhs.m_xPage);
719     }
720 
PageHolderObject(PageHolderObject<T> const & rhs)721     PageHolderObject (PageHolderObject<T> const & rhs)
722         : m_xPage (rhs.m_xPage)
723     {}
724 
operator =(PageHolderObject<T> const & rhs)725     PageHolderObject<T> & operator= (PageHolderObject<T> const & rhs)
726     {
727         PageHolderObject<T> tmp (rhs);
728         this->swap (tmp);
729         return *this;
730     }
731 
is() const732     bool is() const
733     {
734         return (m_xPage.get() != 0);
735     }
736 
737 #if 1  /* EXP */
get()738     PageHolder & get() { return m_xPage; }
get() const739     PageHolder const & get() const { return m_xPage; }
740 #endif /* EXP */
741 
operator ->()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     }
operator ->() const748     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 
operator *()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     }
operator *() const761     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 
guard(PageHolder & rxPage,sal_uInt32 nAddr)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     }
verify(PageHolder const & rxPage,sal_uInt32 nAddr)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:
PageObject(PageHolder const & rxPage=PageHolder ())808     explicit PageObject (PageHolder const & rxPage = PageHolder())
809         : m_xPage (rxPage), m_bDirty (false)
810     {}
811 
~PageObject()812     virtual ~PageObject()
813     {}
814 
get()815     PageHolder & get() { return m_xPage; }
get() const816     PageHolder const & get() const { return m_xPage; }
817 
clean()818     void clean() { m_bDirty = false; }
touch()819     void touch() { m_bDirty = true; }
820 
location() const821     sal_uInt32 location() const
822     {
823         PageData const * pagedata = m_xPage.get();
824         return (pagedata != 0) ? pagedata->location() : STORE_PAGE_NULL;
825     }
location(sal_uInt32 nAddr)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      */
operator new(size_t n)851     static void * operator new (size_t n) SAL_THROW(())
852     {
853         return rtl_allocateMemory (sal_uInt32(n));
854     }
operator delete(void * p,size_t)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      */
OStorePageObject(PageHolder const & rxPage=PageHolder ())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 >
makeHolder() const889     PageHolderObject<U> makeHolder() const
890     {
891         return PageHolderObject<U>(m_xPage);
892     }
893 
894     template< class U >
construct(rtl::Reference<PageData::Allocator> const & rxAllocator)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 
get()909     PageHolder & get() { return m_xPage; }
get() const910     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 
dirty(void) const916 inline bool OStorePageObject::dirty (void) const
917 {
918     return m_bDirty;
919 }
920 
clean(void)921 inline void OStorePageObject::clean (void)
922 {
923     m_bDirty = false;
924 }
925 
touch(void)926 inline void OStorePageObject::touch (void)
927 {
928     m_bDirty = true;
929 }
930 
location(void) const931 inline sal_uInt32 OStorePageObject::location (void) const
932 {
933     return m_xPage->location();
934 }
935 
location(sal_uInt32 nAddr)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