Version 3.6.0.4, tag libreoffice-3.6.0.4
[LibreOffice.git] / store / workben / t_page.cxx
blob33ca80ea81a9a5a4b4a22fe05d725c8d00753c20
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * t_page.cxx
4 */
6 #include "osl/diagnose.h"
7 #include "rtl/alloc.h"
8 #include "rtl/ref.hxx"
10 #include "storbase.hxx"
12 #include "osl/file.h"
13 #include "rtl/ustring.hxx"
15 /*========================================================================
17 * OTest...
19 *======================================================================*/
21 template< class T > void swap (T & lhs, T & rhs)
23 T tmp = rhs; rhs = lhs; lhs = tmp;
26 /*======================================================================*/
28 class SharedCount
30 long * m_pCount;
32 class Allocator
34 rtl_cache_type * m_cache;
36 public:
37 static Allocator & get();
39 long * alloc()
41 return static_cast<long*>(rtl_cache_alloc (m_cache));
43 void free (long * pCount)
45 rtl_cache_free (m_cache, pCount);
48 protected:
49 Allocator();
50 ~Allocator();
53 public:
54 SharedCount()
55 : m_pCount(Allocator::get().alloc())
57 if (m_pCount != 0) (*m_pCount) = 1;
60 ~SharedCount()
62 if (m_pCount != 0)
64 long new_count = --(*m_pCount);
65 if (new_count == 0)
66 Allocator::get().free(m_pCount);
70 bool operator== (long count) const
72 return (m_pCount != 0) ? *m_pCount == count : false;
75 friend void swap<> (SharedCount & lhs, SharedCount & rhs); // nothrow
77 SharedCount (SharedCount const & rhs); // nothrow
78 SharedCount & operator= (SharedCount const & rhs); // nothrow
81 template<>
82 inline void swap (SharedCount & lhs, SharedCount & rhs) // nothrow
84 swap<long*>(lhs.m_pCount, rhs.m_pCount);
87 SharedCount::SharedCount (SharedCount const & rhs) // nothrow
88 : m_pCount (rhs.m_pCount)
90 if (m_pCount != 0) ++(*m_pCount);
93 SharedCount &
94 SharedCount::operator= (SharedCount const & rhs) // nothrow
96 SharedCount tmp(rhs);
97 swap<SharedCount>(tmp, *this);
98 return *this;
101 SharedCount::Allocator &
102 SharedCount::Allocator::get()
104 static Allocator g_aSharedCountAllocator;
105 return g_aSharedCountAllocator;
108 SharedCount::Allocator::Allocator()
110 m_cache = rtl_cache_create (
111 "store_shared_count_cache",
112 sizeof(long),
113 0, // objalign
114 0, // constructor
115 0, // destructor
116 0, // reclaim
117 0, // userarg
118 0, // default source
119 0 // flags
123 SharedCount::Allocator::~Allocator()
125 rtl_cache_destroy (m_cache), m_cache = 0;
128 /*======================================================================*/
130 #if defined(OSL_BIGENDIAN)
131 #define STORE_DWORD(dword) OSL_SWAPDWORD((dword))
132 #else
133 #define STORE_DWORD(dword) (dword)
134 #endif
136 struct PageData
138 typedef store::OStorePageGuard G;
139 typedef store::OStorePageDescriptor D;
140 typedef store::OStorePageLink L;
142 /** Representation.
144 G m_aGuard;
145 D m_aDescr;
146 L m_aMarked;
147 L m_aUnused;
149 /** theSize.
151 static const size_t theSize = sizeof(G) + sizeof(D) + 2 * sizeof(L);
152 static const sal_uInt16 thePageSize = theSize;
153 STORE_STATIC_ASSERT(STORE_MINIMUM_PAGESIZE >= thePageSize);
155 /** type.
157 sal_uInt32 type() const { return m_aGuard.m_nMagic; /* @@@ */ }
159 /** offset.
161 sal_uInt32 offset() const { return m_aDescr.m_nAddr; /* @@@ */ }
162 void offset (sal_uInt32 nOffset) { m_aDescr.m_nAddr = nOffset; }
164 /** size.
166 sal_uInt16 size() const { return m_aDescr.m_nSize; /* @@@ */ }
168 /** Allocation.
170 class Allocator : public rtl::IReference
172 public:
173 template< class T > T * construct()
175 void * page = 0; sal_uInt16 size = 0;
176 if (allocate (&page, &size))
178 return new(page) T(size);
180 return 0;
183 virtual bool allocate (void ** ppPage, sal_uInt16 * pnSize) = 0;
184 virtual void deallocate (void * pPage) = 0;
187 static void * operator new (size_t, void * p) { return p; }
188 static void operator delete (void *, void *) {}
190 /** Construction.
192 explicit PageData (sal_uInt16 nPageSize = thePageSize)
193 : m_aDescr (STORE_PAGE_NULL, nPageSize, thePageSize)
196 /** ...
198 void guard()
201 storeError verify() const
203 return store_E_None;
207 class IPageAllocator
209 public:
210 virtual void deallocate (void * p) = 0;
213 class PageAllocator
215 rtl_cache_type * m_cache;
216 SharedCount m_refcount;
218 public:
219 PageAllocator()
220 : m_cache(0), m_refcount()
223 ~PageAllocator()
225 // NYI
226 if (m_refcount == 1)
231 friend void swap<>(PageAllocator & lhs, PageAllocator & rhs);
233 PageAllocator (PageAllocator const & rhs);
234 PageAllocator & operator= (PageAllocator const & rhs);
237 template<>
238 inline void swap (PageAllocator & lhs, PageAllocator & rhs)
240 swap<rtl_cache_type*>(lhs.m_cache, rhs.m_cache);
241 swap<SharedCount>(lhs.m_refcount, rhs.m_refcount);
244 PageAllocator::PageAllocator (PageAllocator const & rhs)
245 : m_cache (rhs.m_cache),
246 m_refcount (rhs.m_refcount)
250 PageAllocator &
251 PageAllocator::operator= (PageAllocator const & rhs)
253 PageAllocator tmp (rhs);
254 swap<PageAllocator>(tmp, *this);
255 return *this;
258 /*======================================================================*/
260 class PageHolder
262 SharedCount m_refcount;
263 PageData * m_pagedata;
265 typedef rtl::Reference< PageData::Allocator > allocator_type;
266 allocator_type m_allocator;
268 public:
269 explicit PageHolder (PageData * pagedata = 0, allocator_type const & allocator = allocator_type())
270 : m_refcount (),
271 m_pagedata (pagedata),
272 m_allocator(allocator)
275 ~PageHolder()
277 if ((m_refcount == 1) && (m_pagedata != 0) && m_allocator.is())
279 // free pagedata.
280 m_allocator->deallocate (m_pagedata);
284 PageData * get() { return m_pagedata; }
285 PageData const * get() const { return m_pagedata; }
287 PageData * operator->() { return m_pagedata; }
288 PageData const * operator->() const { return m_pagedata; }
290 friend void swap<> (PageHolder & lhs, PageHolder & rhs); // nothrow
292 PageHolder (PageHolder const & rhs); // nothrow
293 PageHolder & operator= (PageHolder const & rhs); // nothrow
296 template<>
297 inline void swap (PageHolder & lhs, PageHolder & rhs) // nothrow
299 swap<SharedCount>(lhs.m_refcount, rhs.m_refcount);
300 swap<PageData*>(lhs.m_pagedata, rhs.m_pagedata);
301 swap<PageHolder::allocator_type>(lhs.m_allocator, rhs.m_allocator);
304 PageHolder::PageHolder (PageHolder const & rhs) // nothrow
305 : m_refcount (rhs.m_refcount),
306 m_pagedata (rhs.m_pagedata),
307 m_allocator(rhs.m_allocator)
310 PageHolder &
311 PageHolder::operator= (PageHolder const & rhs) // nothrow
313 PageHolder tmp (rhs);
314 swap<PageHolder>(tmp, *this);
315 return *this;
318 /*======================================================================*/
320 template< class T >
321 class PageHolderObject
323 protected:
324 /** Representation.
326 PageHolder m_xPage;
328 /** Checked cast.
330 template< class U >
331 static bool isA (PageData const * p)
333 return ((p != 0) && (p->type() == U::theTypeId));
336 template< class U >
337 static U * dynamic_page_cast (PageData * p)
339 return isA<U>(p) ? static_cast<U*>(p) : 0;
342 template< class U >
343 static U const * dynamic_page_cast (PageData const * p)
345 return isA<U>(p) ? static_cast<U const *>(p) : 0;
348 public:
349 static PageHolderObject<T> construct (rtl::Reference< PageData::Allocator > const & rxAllocator)
351 PageHolderObject<T> tmp;
352 if (rxAllocator.is())
354 PageHolder xPage (rxAllocator->construct<T>(), rxAllocator);
355 store::swap<PageHolder>(tmp.m_xPage, xPage);
357 return tmp;
360 explicit PageHolderObject (PageHolder const & rxPage = PageHolder())
361 : m_xPage (rxPage)
364 void swap (PageHolderObject<T> & rhs)
366 store::swap<PageHolder>(m_xPage, rhs.m_xPage);
369 PageHolderObject (PageHolderObject<T> const & rhs)
370 : m_xPage (rhs.m_xPage)
374 PageHolderObject<T> & operator= (PageHolderObject<T> const & rhs)
376 PageHolderObject<T> tmp (rhs);
377 this->swap(tmp);
378 return *this;
381 T * operator->()
383 T * pImpl = dynamic_page_cast<T>(m_xPage.get());
384 OSL_PRECOND(pImpl != 0, "store::PageHolder<T>::operator->(): Null pointer");
385 return pImpl;
387 T const * operator->() const
389 T const * pImpl = dynamic_page_cast<T>(m_xPage.get());
390 OSL_PRECOND(pImpl != 0, "store::PageHolder<T>::operator->(): Null pointer");
391 return pImpl;
394 T & operator*()
396 T * pImpl = dynamic_page_cast<T>(m_xPage.get());
397 OSL_PRECOND(pImpl != 0, "store::PageHolder<T>::operator*(): Null pointer");
398 return *pImpl;
400 T const & operator*() const
402 T const * pImpl = dynamic_page_cast<T>(m_xPage.get());
403 OSL_PRECOND(pImpl != 0, "store::PageHolder<T>::operator*(): Null pointer");
404 return *pImpl;
407 static storeError guard (PageHolder & rxPage)
409 T * pImpl = dynamic_page_cast<T>(rxPage.get());
410 if (pImpl != 0)
411 { pImpl->guard(); return store_E_None; }
412 else if (rxPage.get() != 0)
413 return store_E_WrongVersion;
414 else
415 return store_E_InvalidAccess;
417 static storeError verify (PageHolder const & rxPage)
419 T const * pImpl = dynamic_page_cast<T>(rxPage.get());
420 if (pImpl != 0)
421 return pImpl->verify();
422 else if (rxPage.get() != 0)
423 return store_E_WrongVersion;
424 else
425 return store_E_InvalidAccess;
429 /*======================================================================*/
431 class PageObject
433 public:
434 explicit PageObject (PageHolder const & rxPage = PageHolder())
435 : m_xPage (rxPage)
438 virtual ~PageObject();
440 PageHolder & get() { return m_xPage; }
441 PageHolder const & get() const { return m_xPage; }
443 PageData * operator->()
445 PageData * pImpl = m_xPage.get();
446 OSL_PRECOND(pImpl != 0, "store::PageObject::operator->(): Null pointer");
447 return pImpl;
449 PageData & operator*()
451 PageData * pImpl = m_xPage.get();
452 OSL_PRECOND(pImpl != 0, "store::PageObject::operator*(): Null pointer");
453 return *pImpl;
456 virtual void guard();
457 virtual storeError verify() const;
459 protected:
460 PageHolder m_xPage;
463 PageObject::~PageObject()
465 void PageObject::guard()
467 PageData * p = m_xPage.get();
468 p->guard();
470 storeError PageObject::verify() const
472 PageData const * p = m_xPage.get();
473 return p->verify();
476 /*======================================================================*/
478 template< class T >
479 T * dynamic_page_cast (PageData * pagedata)
481 if ((pagedata != 0) && (pagedata->type() == T::theTypeId))
482 return static_cast<T*>(pagedata);
483 return 0;
486 template< class T >
487 T * dynamic_page_cast (PageData const * pagedata)
489 if ((pagedata != 0) && (pagedata->type() == T::theTypeId))
490 return static_cast<T*>(pagedata);
491 return 0;
494 /*======================================================================*/
496 class TestBIOS
498 public:
499 storeError loadPageAt (PageHolder & rPage, storeError (*pfnVerify)(PageHolder const &))
501 return (pfnVerify)(rPage);
504 storeError allocate (PageHolder & rxPage, ...)
506 // NYI: PageObject.save(nAddr, *this);
507 (void)rxPage; // NYI
508 return store_E_Unknown; // NYI
511 storeError loadAt (PageHolder & rPage, sal_uInt32 nOffset)
513 (void)rPage; // NYI
514 (void)nOffset; // NYI
515 return store_E_Unknown; // NYI
517 storeError saveAt (PageHolder const & rPage, sal_uInt32 nOffset)
519 (void)rPage; // NYI
520 (void)nOffset; // NYI
521 return store_E_Unknown; // NYI
524 template< class T >
525 storeError save (PageHolder & rxPage, sal_uInt32 nOffset)
527 storeError result = PageHolderObject<T>::guard (rxPage);
528 if (result != store_E_None)
529 return result;
530 return saveAt (rxPage, nOffset);
533 storeError lookupAt (PageHolder & rPage, sal_uInt32 nOffset)
535 (void)rPage; // NYI
536 (void)nOffset; // NYI
537 return store_E_NotExists;
539 storeError replaceAt (PageHolder const & rPage, sal_uInt32 nOffset)
541 (void)rPage; // NYI
542 (void)nOffset; // NYI
543 return store_E_None;
547 struct TestDataV1 : public PageData
549 static const sal_uInt32 theTypeId = 6 * 9;
551 struct TestData : public PageData
553 typedef PageData base;
554 typedef TestData self;
556 static const sal_uInt32 theTypeId = 42;
558 void guard()
560 base::guard();
561 // self::m_aGuard = ...;
563 storeError verify() const
565 storeError result = base::verify();
566 if (result != store_E_None)
567 return result;
568 if (!(base::type() == self::theTypeId))
569 return store_E_WrongVersion;
570 return store_E_None;
573 storeError dwim() const
575 return store_E_None;
578 class TestObject : public PageObject
580 typedef PageObject base;
582 public:
584 void dwim()
586 PageHolderObject< TestData > xPage (m_xPage);
587 xPage->guard();
590 virtual void guard()
592 TestData * pagedata = dynamic_page_cast< TestData >(m_xPage.get());
593 if (pagedata != 0)
596 virtual storeError verify() const
598 storeError result = base::verify();
599 if (result != store_E_None)
600 return result;
602 TestData const * pagedata = dynamic_page_cast< TestData const >(m_xPage.get());
603 if (!pagedata)
604 return store_E_WrongVersion;
606 return pagedata->verify();
609 static storeError verify (PageHolder const & rPage)
611 return PageHolderObject< TestData >::verify (rPage);
614 storeError loadAt (sal_uInt32 nOffset, TestBIOS & rBIOS)
616 storeError result = rBIOS.lookupAt (m_xPage, nOffset); // cache lookup
617 if (result == store_E_NotExists)
619 result = rBIOS.loadAt (m_xPage, nOffset);
620 if (result != store_E_None)
621 return result;
623 result = PageHolderObject< TestData >::verify (m_xPage);
624 if (result != store_E_None)
625 return result;
627 result = rBIOS.replaceAt (m_xPage, nOffset); // cache insert
629 return result;
631 storeError saveAt (sal_uInt32 nOffset, TestBIOS & rBIOS)
633 if (!m_xPage.get())
634 return store_E_InvalidAccess;
635 m_xPage->m_aDescr.m_nAddr = store::htonl(nOffset); // m_xPage->location (nOffset);
637 storeError result = PageHolderObject< TestData >::guard (m_xPage);
638 if (result != store_E_None)
639 return result;
641 result = rBIOS.saveAt (m_xPage, nOffset);
642 if (result != store_E_None)
643 return result;
645 return rBIOS.replaceAt (m_xPage, nOffset); // cache update
649 class TestObjectV2 : public PageHolderObject< TestData >
651 typedef PageHolderObject< TestData > base;
653 public:
654 storeError saveAt (sal_uInt32 nOffset, TestBIOS & rBIOS)
656 m_xPage->offset(nOffset);
658 storeError result = PageHolderObject< TestData >::guard (m_xPage);
659 if (result != store_E_None)
660 return result;
662 result = rBIOS.saveAt (m_xPage, nOffset);
663 if (result != store_E_None)
664 return result;
666 return rBIOS.replaceAt (m_xPage, nOffset);
668 #if 1
669 storeError dwim() const
671 TestData const * pImpl1 = operator->();
673 PageHolderObject< TestData > xImpl (m_xPage);
675 TestData const * pImpl2 = &*xImpl;
676 OSL_ASSERT(pImpl1 == pImpl2);
678 return xImpl->dwim();
680 #endif
683 class TestClient
685 public:
686 void dwim(TestBIOS & rBIOS)
688 TestObject aObj;
690 rBIOS.loadPageAt(aObj.get(), aObj.verify);
691 rBIOS.loadPageAt(aObj.get(), TestObject::verify);
692 rBIOS.loadPageAt(aObj.get(), PageHolderObject<TestData>::verify);
694 aObj.loadAt (1024, rBIOS);
696 TestObjectV2 aObj2;
697 aObj2.dwim();
698 aObj2->dwim();
702 /*======================================================================*/
704 class IPageAllocator;
705 class IPageAccess
707 public:
708 virtual storeError initialize (storeAccessMode eAccessMode, sal_uInt16 nPageSize) = 0;
709 virtual IPageAllocator & getAllocator () = 0;
711 public:
712 storeError readPageAt (PageHolder & rPage, sal_uInt32 nOffset)
714 return readPageAt_Impl (rPage, nOffset);
716 storeError writePageAt (PageHolder const & rPage, sal_uInt32 nOffset)
718 // [SECURITY:ValInput]
719 PageData const * pagedata = rPage.get();
720 OSL_PRECOND(!(pagedata == 0), "invalid Page");
721 if (pagedata == 0)
722 return store_E_InvalidParameter;
724 sal_uInt32 const offset = pagedata->offset();
725 OSL_PRECOND(!(nOffset != offset), "inconsistent Offset");
726 if (nOffset != offset)
727 return store_E_InvalidParameter;
729 OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::IPageAccess::writePageAt(): invalid Offset");
730 if (nOffset == STORE_PAGE_NULL)
731 return store_E_CantSeek;
733 return writePageAt_Impl (rPage, nOffset);
736 storeError peekAt (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes)
738 // [SECURITY:ValInput]
739 sal_uInt8 * dst_lo = static_cast<sal_uInt8*>(pBuffer);
740 if (!(dst_lo != 0))
741 return store_E_InvalidParameter;
743 sal_uInt8 * dst_hi = dst_lo + nBytes;
744 if (!(dst_lo < dst_hi))
745 return (dst_lo > dst_hi) ? store_E_InvalidParameter : store_E_None;
747 sal_uInt64 const dst_size = nOffset + nBytes;
748 if (dst_size > SAL_MAX_UINT32)
749 return store_E_CantSeek;
751 return peekAt_Impl (nOffset, dst_lo, (dst_hi - dst_lo));
754 storeError pokeAt (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes)
756 // [SECURITY:ValInput]
757 sal_uInt8 const * src_lo = static_cast<sal_uInt8 const*>(pBuffer);
758 if (!(src_lo != 0))
759 return store_E_InvalidParameter;
761 sal_uInt8 const * src_hi = src_lo + nBytes;
762 if (!(src_lo < src_hi))
763 return (src_lo > src_hi) ? store_E_InvalidParameter : store_E_None;
765 sal_uInt64 const dst_size = nOffset + nBytes;
766 if (dst_size > SAL_MAX_UINT32)
767 return store_E_CantSeek;
769 return pokeAt_Impl (nOffset, src_lo, (src_hi - src_lo));
772 storeError getSize (sal_uInt32 & rnSize)
774 rnSize = 0;
775 return getSize_Impl (rnSize);
778 storeError setSize (sal_uInt32 nSize)
780 return setSize_Impl (nSize);
783 private:
784 virtual storeError readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset) = 0;
785 virtual storeError writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset) = 0;
787 virtual storeError peekAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes) = 0;
788 virtual storeError pokeAt_Impl (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes) = 0;
790 virtual storeError getSize_Impl (sal_uInt32 & rnSize) = 0;
791 virtual storeError setSize_Impl (sal_uInt32 nSize) = 0;
794 /*======================================================================*/
796 template< class T > struct ResourceHolder
798 typedef typename T::destructor_type destructor_type;
800 T m_value;
802 explicit ResourceHolder (T const & value = T()) : m_value (value) {}
803 ~ResourceHolder() { reset(); }
805 T & get() { return m_value; }
806 T const & get() const { return m_value; }
808 void set (T const & value) { m_value = value; }
809 void reset (T const & value = T())
811 T tmp (m_value);
812 if (tmp != value)
813 destructor_type()(tmp);
814 set (value);
816 T release()
818 T tmp (m_value);
819 set (T());
820 return tmp;
823 ResourceHolder (ResourceHolder & rhs)
825 set (rhs.release());
827 ResourceHolder & operator= (ResourceHolder & rhs)
829 reset (rhs.release());
830 return *this;
834 struct FileHandle
836 oslFileHandle m_handle;
838 FileHandle() : m_handle(0) {}
840 operator oslFileHandle() { return m_handle; }
842 bool operator != (FileHandle const & rhs)
844 return (m_handle != rhs.m_handle);
847 oslFileError initialize (rtl_uString * pFilename, sal_uInt32 nFlags)
849 // Verify arguments.
850 if (!pFilename || !nFlags)
851 return osl_File_E_INVAL;
853 // Convert into FileUrl.
854 rtl::OUString aFileUrl;
855 if (osl_getFileURLFromSystemPath (pFilename, &(aFileUrl.pData)) != osl_File_E_None)
857 // Not system path. Maybe a file url, already.
858 rtl_uString_assign (&(aFileUrl.pData), pFilename);
861 // Acquire handle.
862 return osl_openFile (aFileUrl.pData, &m_handle, nFlags);
865 struct CloseFile
867 void operator()(FileHandle & rFile) const
869 if (rFile.m_handle != 0)
871 // Release handle.
872 (void) osl_closeFile (rFile.m_handle);
873 rFile.m_handle = 0;
877 typedef CloseFile destructor_type;
880 struct FileMapping
882 void * m_pAddr;
883 sal_uInt64 m_uSize;
885 FileMapping() : m_pAddr(0), m_uSize(0) {}
887 bool operator != (FileMapping const & rhs) const
889 return ((m_pAddr != rhs.m_pAddr) || (m_uSize != rhs.m_uSize));
892 oslFileError initialize (oslFileHandle hFile)
894 // Determine mapping size.
895 oslFileError result = osl_getFileSize (hFile, &m_uSize);
896 if (result != osl_File_E_None)
897 return result;
898 if (m_uSize > SAL_MAX_UINT32)
899 return osl_File_E_OVERFLOW;
901 // Acquire mapping.
902 return osl_mapFile (hFile, &m_pAddr, m_uSize, 0, 0);
905 struct UnmapFile
907 void operator ()(FileMapping & rMapping) const
909 if ((rMapping.m_pAddr != 0) && (rMapping.m_uSize != 0))
911 // Release mapping.
912 (void) osl_unmapFile (rMapping.m_pAddr, rMapping.m_uSize);
913 rMapping.m_pAddr = 0, rMapping.m_uSize = 0;
917 typedef UnmapFile destructor_type;
920 /*======================================================================*/
922 class FilePageAccess : public IPageAccess
924 oslFileHandle m_hFile;
926 public:
927 static storeError ERROR_FROM_NATIVE (oslFileError eErrno);
928 static sal_uInt32 MODE_TO_NATIVE (storeAccessMode eMode);
930 public:
931 explicit FilePageAccess (oslFileHandle hFile = 0) : m_hFile (hFile) {}
932 virtual storeError initialize (storeAccessMode eAccessMode, sal_uInt16 nPageSize);
934 private:
935 virtual storeError readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset);
936 virtual storeError writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset);
938 /* see @ OFileLockBytes */
939 virtual storeError peekAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes);
940 virtual storeError pokeAt_Impl (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes);
942 virtual storeError getSize_Impl (sal_uInt32 & rnSize);
943 virtual storeError setSize_Impl (sal_uInt32 nSize);
945 protected:
946 virtual ~FilePageAccess();
948 private:
949 /** Not implemented.
951 FilePageAccess (FilePageAccess const &);
952 FilePageAccess & operator= (FilePageAccess const &);
955 storeError FilePageAccess::initialize (storeAccessMode eAccessMode, sal_uInt16 nPageSize)
957 (void) eAccessMode; // UNUSED
958 (void) nPageSize; // UNUSED
959 return store_E_Unknown; // NYI
961 FilePageAccess::~FilePageAccess()
963 if (m_hFile != 0)
964 (void) osl_closeFile (m_hFile);
966 storeError FilePageAccess::readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset)
968 PageHolder page (0/*allocate()*/); /* @@@ construct w/ deallocator argument @@@ */
969 if (!page.get())
970 return store_E_OutOfMemory;
972 swap<PageHolder>(page, rPage);
973 return peekAt (nOffset, rPage.get(), 0/*size*/);
975 storeError FilePageAccess::writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset)
977 return pokeAt (nOffset, rPage.get(), 0/*size*/);
979 storeError FilePageAccess::peekAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes)
981 sal_uInt64 nDone = 0;
982 oslFileError result = osl_readFileAt (m_hFile, nOffset, pBuffer, nBytes, &nDone);
983 if (result != osl_File_E_None)
984 return ERROR_FROM_NATIVE(result);
985 if (nDone != nBytes)
986 return (nDone != 0) ? store_E_CantRead : store_E_NotExists;
987 return store_E_None;
989 storeError FilePageAccess::pokeAt_Impl (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes)
991 sal_uInt64 nDone = 0;
992 oslFileError result = osl_writeFileAt (m_hFile, nOffset, pBuffer, nBytes, &nDone);
993 if (result != osl_File_E_None)
994 return ERROR_FROM_NATIVE(result);
995 if (nDone != nBytes)
996 return store_E_CantWrite;
997 return store_E_None;
999 storeError FilePageAccess::getSize_Impl (sal_uInt32 & rnSize)
1001 sal_uInt64 uSize = 0;
1002 oslFileError result = osl_getFileSize (m_hFile, &uSize);
1003 if (result != osl_File_E_None)
1004 return ERROR_FROM_NATIVE(result);
1005 if (uSize > SAL_MAX_UINT32)
1006 return store_E_CantSeek;
1008 rnSize = sal::static_int_cast<sal_uInt32>(uSize);
1009 return store_E_None;
1011 storeError FilePageAccess::setSize_Impl (sal_uInt32 nSize)
1013 oslFileError result = osl_setFileSize (m_hFile, nSize);
1014 if (result != osl_File_E_None)
1015 return ERROR_FROM_NATIVE(result);
1016 return store_E_None;
1018 storeError FilePageAccess::ERROR_FROM_NATIVE (oslFileError eErrno)
1020 switch (eErrno)
1022 case osl_File_E_None:
1023 return store_E_None;
1025 case osl_File_E_NOENT:
1026 return store_E_NotExists;
1028 case osl_File_E_ACCES:
1029 case osl_File_E_PERM:
1030 return store_E_AccessViolation;
1032 case osl_File_E_AGAIN:
1033 case osl_File_E_DEADLK:
1034 return store_E_LockingViolation;
1036 case osl_File_E_BADF:
1037 return store_E_InvalidHandle;
1039 case osl_File_E_INVAL:
1040 return store_E_InvalidParameter;
1042 case osl_File_E_NOSPC:
1043 return store_E_OutOfSpace;
1045 case osl_File_E_OVERFLOW:
1046 return store_E_CantSeek;
1048 default:
1049 return store_E_Unknown;
1052 sal_uInt32 FilePageAccess::MODE_TO_NATIVE(storeAccessMode eAccessMode)
1054 sal_uInt32 nMode = 0;
1055 switch (eAccessMode)
1057 case store_AccessCreate:
1058 case store_AccessReadCreate:
1059 nMode |= osl_File_OpenFlag_Create;
1060 // fall through
1061 case store_AccessReadWrite:
1062 nMode |= osl_File_OpenFlag_Write;
1063 // fall through
1064 case store_AccessReadOnly:
1065 nMode |= osl_File_OpenFlag_Read;
1066 break;
1067 default:
1068 OSL_PRECOND(0, "store::FilePageAccess: unknown storeAccessMode");
1070 return nMode;
1073 /*===*/
1075 class MemoryPageAccess : public IPageAccess
1077 /** Representation.
1079 sal_uInt8 * m_pData;
1080 sal_uInt32 m_nSize;
1082 /** Callback function to release Representation.
1084 typedef void (*destructor_type)(sal_uInt8 * pData, sal_uInt32 nSize);
1085 destructor_type m_destructor;
1087 /** Default destructor callback.
1089 static void freeMemory (sal_uInt8 * pData, sal_uInt32 nSize);
1091 public:
1092 MemoryPageAccess()
1093 : m_pData (0), m_nSize (0), m_destructor (MemoryPageAccess::freeMemory)
1095 MemoryPageAccess (sal_uInt8 * pData, sal_uInt32 nSize, destructor_type destructor = MemoryPageAccess::freeMemory)
1096 : m_pData (pData), m_nSize (nSize), m_destructor (destructor)
1099 virtual storeError initialize (storeAccessMode eAccessMode, sal_uInt16 nPageSize);
1101 private:
1102 /** Page (size aligned) access.
1104 virtual storeError readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset);
1105 virtual storeError writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset);
1107 /** Low level access.
1109 virtual storeError peekAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes);
1110 virtual storeError pokeAt_Impl (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes);
1112 virtual storeError getSize_Impl (sal_uInt32 & rnSize);
1113 virtual storeError setSize_Impl (sal_uInt32 nSize);
1115 protected:
1116 virtual ~MemoryPageAccess();
1118 private:
1119 /** Not implemented.
1121 MemoryPageAccess (MemoryPageAccess const &);
1122 MemoryPageAccess & operator= (MemoryPageAccess const &);
1125 storeError MemoryPageAccess::initialize (storeAccessMode eAccessMode, sal_uInt16 nPageSize)
1127 (void) eAccessMode; // UNUSED
1128 (void) nPageSize; // UNUSED
1129 return store_E_Unknown; // NYI
1131 MemoryPageAccess::~MemoryPageAccess()
1133 if (m_destructor != 0)
1135 // release resource.
1136 (*m_destructor)(m_pData, m_nSize);
1139 storeError MemoryPageAccess::readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset)
1141 /* OSL_PRECOND(nOffset % size == 0, "Unaligned page read."); */
1142 PageHolder page (reinterpret_cast< PageData* >(m_pData + nOffset));
1143 swap<PageHolder>(page, rPage);
1144 return store_E_None;
1146 storeError MemoryPageAccess::writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset)
1148 PageData const * pagedata = rPage.get();
1149 if (!(pagedata != 0))
1150 return store_E_InvalidParameter;
1152 return pokeAt (nOffset, pagedata, pagedata->size());
1154 storeError MemoryPageAccess::peekAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes)
1156 // [SECURITY:ValInput]
1157 sal_uInt8 * dst_lo = static_cast<sal_uInt8*>(pBuffer);
1158 if (!(dst_lo != 0))
1159 return store_E_InvalidParameter;
1161 sal_uInt8 * dst_hi = dst_lo + nBytes;
1162 if (!(dst_lo <= dst_hi))
1163 return store_E_InvalidParameter;
1165 // ...
1166 sal_uInt8 const * src_lo = m_pData + nOffset;
1167 if (!(src_lo <= m_pData + m_nSize))
1168 return store_E_CantSeek;
1170 sal_uInt8 const * src_hi = src_lo + nBytes;
1171 if (!(src_hi <= m_pData + m_nSize))
1172 return store_E_CantRead;
1174 // copy.
1175 memcpy (pBuffer, src_lo, (src_hi - src_lo));
1176 return store_E_None;
1178 storeError MemoryPageAccess::pokeAt_Impl (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes)
1180 // [SECURITY:ValInput]
1181 sal_uInt8 const * src_lo = static_cast<sal_uInt8 const*>(pBuffer);
1182 if (!(src_lo != 0))
1183 return store_E_InvalidParameter;
1185 sal_uInt8 const * src_hi = src_lo + nBytes;
1186 if (!(src_lo <= src_hi))
1187 return store_E_InvalidParameter;
1189 sal_uInt64 const uSize = nOffset + nBytes;
1190 if (uSize > SAL_MAX_UINT32)
1191 return store_E_CantSeek;
1193 // ...
1194 if (uSize > m_nSize)
1196 // increase size.
1197 storeError eErrCode = setSize (sal::static_int_cast<sal_uInt32>(uSize));
1198 if (eErrCode != store_E_None)
1199 return eErrCode;
1202 sal_uInt8 * dst_lo = m_pData + nOffset;
1203 if (!(dst_lo <= m_pData + m_nSize))
1204 return store_E_CantSeek;
1206 sal_uInt8 * dst_hi = dst_lo + nBytes;
1207 if (!(dst_hi <= m_pData + m_nSize))
1208 return store_E_CantWrite;
1210 // copy.
1211 memcpy (dst_lo, src_lo, (src_hi - src_lo));
1212 return store_E_None;
1214 storeError MemoryPageAccess::getSize_Impl (sal_uInt32 & rnSize)
1216 rnSize = m_nSize;
1217 return store_E_None;
1219 storeError MemoryPageAccess::setSize_Impl (sal_uInt32 nSize)
1221 if (nSize != m_nSize)
1223 sal_uInt8 * pData = static_cast<sal_uInt8*>(rtl_reallocateMemory (m_pData, nSize));
1224 if (pData != 0)
1226 if (nSize > m_nSize)
1227 memset (pData + m_nSize, 0, sal::static_int_cast< size_t >(nSize - m_nSize));
1229 else
1231 if (nSize != 0)
1232 return store_E_OutOfMemory;
1234 m_pData = pData, m_nSize = nSize;
1236 return store_E_None;
1238 void MemoryPageAccess::freeMemory (sal_uInt8 * pData, sal_uInt32 /*nSize*/)
1240 rtl_freeMemory (pData);
1243 /*===*/
1245 class MappedPageAccess : public MemoryPageAccess
1247 /** @see MemoryPageAccess::destructor_type callback function.
1249 static void unmapFile (sal_uInt8 * pData, sal_uInt32 nSize);
1251 public:
1252 MappedPageAccess (sal_uInt8 * pData, sal_uInt32 nSize);
1254 virtual storeError initialize (storeAccessMode eAccessMode, sal_uInt16 nPageSize);
1256 virtual storeError writePageAt (PageHolder const & rPage, sal_uInt32 nOffset);
1258 private:
1259 virtual storeError pokeAt_Impl (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes);
1260 virtual storeError setSize_Impl (sal_uInt32 nSize);
1262 protected:
1263 virtual ~MappedPageAccess() {}
1266 MappedPageAccess::MappedPageAccess (sal_uInt8 * pData, sal_uInt32 nSize)
1267 : MemoryPageAccess (pData, nSize, MappedPageAccess::unmapFile)
1270 storeError MappedPageAccess::initialize (storeAccessMode eAccessMode, sal_uInt16 nPageSize)
1272 OSL_PRECOND(eAccessMode == store_AccessReadOnly, "store::MappedPageAccess: invalid AccessMode");
1273 return MemoryPageAccess::initialize (eAccessMode, nPageSize);
1275 storeError MappedPageAccess::writePageAt (PageHolder const & /*rPage*/, sal_uInt32 /*nOffset*/)
1277 return store_E_AccessViolation;
1279 storeError MappedPageAccess::pokeAt_Impl (sal_uInt32 /*nOffset*/, void const * /*pBuffer*/, sal_uInt32 /*nBytes*/)
1281 return store_E_AccessViolation;
1283 storeError MappedPageAccess::setSize_Impl (sal_uInt32 /*nSize*/)
1285 return store_E_AccessViolation;
1287 void MappedPageAccess::unmapFile (sal_uInt8 * pData, sal_uInt32 nSize)
1289 (void) osl_unmapFile (pData, nSize);
1292 /*========================================================================
1294 * main.
1296 *======================================================================*/
1298 #include <stdio.h>
1300 int SAL_CALL main (int argc, char ** argv)
1302 OSL_PRECOND(argc >= 1, "t_page: error: insufficient number of arguments.");
1303 if (argc < 1)
1304 return 0;
1307 void *a = (void*)1, *b = (void*)2;
1308 swap<void*>(a, b);
1311 PageObject a;
1312 PageObject b (a);
1313 PageObject c;
1315 c = b;
1316 a = a;
1320 TestBIOS aBIOS;
1321 TestClient aClient;
1322 aClient.dwim (aBIOS);
1325 if (argc > 1)
1327 rtl_uString * pFilename = 0;
1328 rtl_uString_newFromAscii (&pFilename, argv[1]);
1329 storeAccessMode eAccessMode = store_AccessReadOnly;
1331 // Acquire file handle.
1332 ResourceHolder<FileHandle> h1;
1333 oslFileError result = h1.get().initialize (pFilename, FilePageAccess::MODE_TO_NATIVE(eAccessMode));
1334 if (result == osl_File_E_None)
1336 ResourceHolder<FileHandle> h2 (h1);
1337 h1 = h2;
1339 if (eAccessMode == store_AccessReadOnly)
1341 ResourceHolder<FileMapping> m1;
1342 result = m1.get().initialize (h1.get());
1344 const sal_uInt32 nSize = sal::static_int_cast<sal_uInt32>(m1.get().m_uSize);
1345 (void) nSize; // UNUSED
1347 ResourceHolder<FileMapping> m2 (m1);
1348 m1 = m2;
1350 result = osl_File_E_None;
1355 return 0;
1358 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */