bump product version to 4.1.6.2
[LibreOffice.git] / store / workben / t_page.cxx
blob5fa7ca62bc29fe454f78ab0b2bf94d59ebe5eca7
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
20 #include "sal/config.h"
22 #include "boost/static_assert.hpp"
23 #include "osl/diagnose.h"
24 #include "rtl/alloc.h"
25 #include "rtl/ref.hxx"
27 #include "storbase.hxx"
29 #include "osl/file.h"
30 #include "rtl/ustring.hxx"
32 template< class T > void swap (T & lhs, T & rhs)
34 T tmp = rhs; rhs = lhs; lhs = tmp;
37 class SharedCount
39 long * m_pCount;
41 class Allocator
43 rtl_cache_type * m_cache;
45 public:
46 static Allocator & get();
48 long * alloc()
50 return static_cast<long*>(rtl_cache_alloc (m_cache));
52 void free (long * pCount)
54 rtl_cache_free (m_cache, pCount);
57 protected:
58 Allocator();
59 ~Allocator();
62 public:
63 SharedCount()
64 : m_pCount(Allocator::get().alloc())
66 if (m_pCount != 0) (*m_pCount) = 1;
69 ~SharedCount()
71 if (m_pCount != 0)
73 long new_count = --(*m_pCount);
74 if (new_count == 0)
75 Allocator::get().free(m_pCount);
79 bool operator== (long count) const
81 return (m_pCount != 0) ? *m_pCount == count : false;
84 friend void swap<> (SharedCount & lhs, SharedCount & rhs); // nothrow
86 SharedCount (SharedCount const & rhs); // nothrow
87 SharedCount & operator= (SharedCount const & rhs); // nothrow
90 template<>
91 inline void swap (SharedCount & lhs, SharedCount & rhs) // nothrow
93 swap<long*>(lhs.m_pCount, rhs.m_pCount);
96 SharedCount::SharedCount (SharedCount const & rhs) // nothrow
97 : m_pCount (rhs.m_pCount)
99 if (m_pCount != 0) ++(*m_pCount);
102 SharedCount &
103 SharedCount::operator= (SharedCount const & rhs) // nothrow
105 SharedCount tmp(rhs);
106 swap<SharedCount>(tmp, *this);
107 return *this;
110 SharedCount::Allocator &
111 SharedCount::Allocator::get()
113 static Allocator g_aSharedCountAllocator;
114 return g_aSharedCountAllocator;
117 SharedCount::Allocator::Allocator()
119 m_cache = rtl_cache_create (
120 "store_shared_count_cache",
121 sizeof(long),
122 0, // objalign
123 0, // constructor
124 0, // destructor
125 0, // reclaim
126 0, // userarg
127 0, // default source
128 0 // flags
132 SharedCount::Allocator::~Allocator()
134 rtl_cache_destroy (m_cache), m_cache = 0;
137 /*======================================================================*/
139 #if defined(OSL_BIGENDIAN)
140 #define STORE_DWORD(dword) OSL_SWAPDWORD((dword))
141 #else
142 #define STORE_DWORD(dword) (dword)
143 #endif
145 struct PageData
147 typedef store::OStorePageGuard G;
148 typedef store::OStorePageDescriptor D;
149 typedef store::OStorePageLink L;
151 /** Representation.
153 G m_aGuard;
154 D m_aDescr;
155 L m_aMarked;
156 L m_aUnused;
158 /** theSize.
160 static const size_t theSize = sizeof(G) + sizeof(D) + 2 * sizeof(L);
161 static const sal_uInt16 thePageSize = theSize;
162 BOOST_STATIC_ASSERT(STORE_MINIMUM_PAGESIZE >= thePageSize);
164 /** type.
166 sal_uInt32 type() const { return m_aGuard.m_nMagic; /* @@@ */ }
168 /** offset.
170 sal_uInt32 offset() const { return m_aDescr.m_nAddr; /* @@@ */ }
171 void offset (sal_uInt32 nOffset) { m_aDescr.m_nAddr = nOffset; }
173 /** size.
175 sal_uInt16 size() const { return m_aDescr.m_nSize; /* @@@ */ }
177 /** Allocation.
179 class Allocator : public rtl::IReference
181 public:
182 template< class T > T * construct()
184 void * page = 0; sal_uInt16 size = 0;
185 if (allocate (&page, &size))
187 return new(page) T(size);
189 return 0;
192 virtual bool allocate (void ** ppPage, sal_uInt16 * pnSize) = 0;
193 virtual void deallocate (void * pPage) = 0;
196 static void * operator new (size_t, void * p) { return p; }
197 static void operator delete (void *, void *) {}
199 /** Construction.
201 explicit PageData (sal_uInt16 nPageSize = thePageSize)
202 : m_aDescr (STORE_PAGE_NULL, nPageSize, thePageSize)
205 /** ...
207 void guard()
210 storeError verify() const
212 return store_E_None;
216 class PageAllocator
218 rtl_cache_type * m_cache;
219 SharedCount m_refcount;
221 public:
222 PageAllocator()
223 : m_cache(0), m_refcount()
226 ~PageAllocator()
228 // NYI
229 if (m_refcount == 1)
234 friend void swap<>(PageAllocator & lhs, PageAllocator & rhs);
236 PageAllocator (PageAllocator const & rhs);
237 PageAllocator & operator= (PageAllocator const & rhs);
240 template<>
241 inline void swap (PageAllocator & lhs, PageAllocator & rhs)
243 swap<rtl_cache_type*>(lhs.m_cache, rhs.m_cache);
244 swap<SharedCount>(lhs.m_refcount, rhs.m_refcount);
247 PageAllocator::PageAllocator (PageAllocator const & rhs)
248 : m_cache (rhs.m_cache),
249 m_refcount (rhs.m_refcount)
253 PageAllocator &
254 PageAllocator::operator= (PageAllocator const & rhs)
256 PageAllocator tmp (rhs);
257 swap<PageAllocator>(tmp, *this);
258 return *this;
261 /*======================================================================*/
263 class PageHolder
265 SharedCount m_refcount;
266 PageData * m_pagedata;
268 typedef rtl::Reference< PageData::Allocator > allocator_type;
269 allocator_type m_allocator;
271 public:
272 explicit PageHolder (PageData * pagedata = 0, allocator_type const & allocator = allocator_type())
273 : m_refcount (),
274 m_pagedata (pagedata),
275 m_allocator(allocator)
278 ~PageHolder()
280 if ((m_refcount == 1) && (m_pagedata != 0) && m_allocator.is())
282 // free pagedata.
283 m_allocator->deallocate (m_pagedata);
287 PageData * get() { return m_pagedata; }
288 PageData const * get() const { return m_pagedata; }
290 PageData * operator->() { return m_pagedata; }
291 PageData const * operator->() const { return m_pagedata; }
293 friend void swap<> (PageHolder & lhs, PageHolder & rhs); // nothrow
295 PageHolder (PageHolder const & rhs); // nothrow
296 PageHolder & operator= (PageHolder const & rhs); // nothrow
299 template<>
300 inline void swap (PageHolder & lhs, PageHolder & rhs) // nothrow
302 swap<SharedCount>(lhs.m_refcount, rhs.m_refcount);
303 swap<PageData*>(lhs.m_pagedata, rhs.m_pagedata);
304 swap<PageHolder::allocator_type>(lhs.m_allocator, rhs.m_allocator);
307 PageHolder::PageHolder (PageHolder const & rhs) // nothrow
308 : m_refcount (rhs.m_refcount),
309 m_pagedata (rhs.m_pagedata),
310 m_allocator(rhs.m_allocator)
313 PageHolder &
314 PageHolder::operator= (PageHolder const & rhs) // nothrow
316 PageHolder tmp (rhs);
317 swap<PageHolder>(tmp, *this);
318 return *this;
321 /*======================================================================*/
323 template< class T >
324 class PageHolderObject
326 protected:
327 /** Representation.
329 PageHolder m_xPage;
331 /** Checked cast.
333 template< class U >
334 static bool isA (PageData const * p)
336 return ((p != 0) && (p->type() == U::theTypeId));
339 template< class U >
340 static U * dynamic_page_cast (PageData * p)
342 return isA<U>(p) ? static_cast<U*>(p) : 0;
345 template< class U >
346 static U const * dynamic_page_cast (PageData const * p)
348 return isA<U>(p) ? static_cast<U const *>(p) : 0;
351 public:
352 static PageHolderObject<T> construct (rtl::Reference< PageData::Allocator > const & rxAllocator)
354 PageHolderObject<T> tmp;
355 if (rxAllocator.is())
357 PageHolder xPage (rxAllocator->construct<T>(), rxAllocator);
358 store::swap<PageHolder>(tmp.m_xPage, xPage);
360 return tmp;
363 explicit PageHolderObject (PageHolder const & rxPage = PageHolder())
364 : m_xPage (rxPage)
367 void swap (PageHolderObject<T> & rhs)
369 store::swap<PageHolder>(m_xPage, rhs.m_xPage);
372 PageHolderObject (PageHolderObject<T> const & rhs)
373 : m_xPage (rhs.m_xPage)
377 PageHolderObject<T> & operator= (PageHolderObject<T> const & rhs)
379 PageHolderObject<T> tmp (rhs);
380 this->swap(tmp);
381 return *this;
384 T * operator->()
386 T * pImpl = dynamic_page_cast<T>(m_xPage.get());
387 OSL_PRECOND(pImpl != 0, "store::PageHolder<T>::operator->(): Null pointer");
388 return pImpl;
390 T const * operator->() const
392 T const * pImpl = dynamic_page_cast<T>(m_xPage.get());
393 OSL_PRECOND(pImpl != 0, "store::PageHolder<T>::operator->(): Null pointer");
394 return pImpl;
397 T & operator*()
399 T * pImpl = dynamic_page_cast<T>(m_xPage.get());
400 OSL_PRECOND(pImpl != 0, "store::PageHolder<T>::operator*(): Null pointer");
401 return *pImpl;
403 T const & operator*() const
405 T const * pImpl = dynamic_page_cast<T>(m_xPage.get());
406 OSL_PRECOND(pImpl != 0, "store::PageHolder<T>::operator*(): Null pointer");
407 return *pImpl;
410 static storeError guard (PageHolder & rxPage)
412 T * pImpl = dynamic_page_cast<T>(rxPage.get());
413 if (pImpl != 0)
414 { pImpl->guard(); return store_E_None; }
415 else if (rxPage.get() != 0)
416 return store_E_WrongVersion;
417 else
418 return store_E_InvalidAccess;
420 static storeError verify (PageHolder const & rxPage)
422 T const * pImpl = dynamic_page_cast<T>(rxPage.get());
423 if (pImpl != 0)
424 return pImpl->verify();
425 else if (rxPage.get() != 0)
426 return store_E_WrongVersion;
427 else
428 return store_E_InvalidAccess;
432 /*======================================================================*/
434 class PageObject
436 public:
437 explicit PageObject (PageHolder const & rxPage = PageHolder())
438 : m_xPage (rxPage)
441 virtual ~PageObject();
443 PageHolder & get() { return m_xPage; }
444 PageHolder const & get() const { return m_xPage; }
446 PageData * operator->()
448 PageData * pImpl = m_xPage.get();
449 OSL_PRECOND(pImpl != 0, "store::PageObject::operator->(): Null pointer");
450 return pImpl;
452 PageData & operator*()
454 PageData * pImpl = m_xPage.get();
455 OSL_PRECOND(pImpl != 0, "store::PageObject::operator*(): Null pointer");
456 return *pImpl;
459 virtual void guard();
460 virtual storeError verify() const;
462 protected:
463 PageHolder m_xPage;
466 PageObject::~PageObject()
468 void PageObject::guard()
470 PageData * p = m_xPage.get();
471 p->guard();
473 storeError PageObject::verify() const
475 PageData const * p = m_xPage.get();
476 return p->verify();
479 /*======================================================================*/
481 template< class T >
482 T * dynamic_page_cast (PageData * pagedata)
484 if ((pagedata != 0) && (pagedata->type() == T::theTypeId))
485 return static_cast<T*>(pagedata);
486 return 0;
489 template< class T >
490 T * dynamic_page_cast (PageData const * pagedata)
492 if ((pagedata != 0) && (pagedata->type() == T::theTypeId))
493 return static_cast<T*>(pagedata);
494 return 0;
497 /*======================================================================*/
499 class TestBIOS
501 public:
502 storeError loadPageAt (PageHolder & rPage, storeError (*pfnVerify)(PageHolder const &))
504 return (pfnVerify)(rPage);
507 storeError allocate (PageHolder & rxPage, ...)
509 // NYI: PageObject.save(nAddr, *this);
510 (void)rxPage; // NYI
511 return store_E_Unknown; // NYI
514 storeError loadAt (PageHolder & rPage, sal_uInt32 nOffset)
516 (void)rPage; // NYI
517 (void)nOffset; // NYI
518 return store_E_Unknown; // NYI
520 storeError saveAt (PageHolder const & rPage, sal_uInt32 nOffset)
522 (void)rPage; // NYI
523 (void)nOffset; // NYI
524 return store_E_Unknown; // NYI
527 template< class T >
528 storeError save (PageHolder & rxPage, sal_uInt32 nOffset)
530 storeError result = PageHolderObject<T>::guard (rxPage);
531 if (result != store_E_None)
532 return result;
533 return saveAt (rxPage, nOffset);
536 storeError lookupAt (PageHolder & rPage, sal_uInt32 nOffset)
538 (void)rPage; // NYI
539 (void)nOffset; // NYI
540 return store_E_NotExists;
542 storeError replaceAt (PageHolder const & rPage, sal_uInt32 nOffset)
544 (void)rPage; // NYI
545 (void)nOffset; // NYI
546 return store_E_None;
550 struct TestDataV1 : public PageData
552 static const sal_uInt32 theTypeId = 6 * 9;
554 struct TestData : public PageData
556 typedef PageData base;
557 typedef TestData self;
559 static const sal_uInt32 theTypeId = 42;
561 void guard()
563 base::guard();
564 // self::m_aGuard = ...;
566 storeError verify() const
568 storeError result = base::verify();
569 if (result != store_E_None)
570 return result;
571 if (!(base::type() == self::theTypeId))
572 return store_E_WrongVersion;
573 return store_E_None;
576 storeError dwim() const
578 return store_E_None;
581 class TestObject : public PageObject
583 typedef PageObject base;
585 public:
587 void dwim()
589 PageHolderObject< TestData > xPage (m_xPage);
590 xPage->guard();
593 virtual void guard()
595 TestData * pagedata = dynamic_page_cast< TestData >(m_xPage.get());
596 if (pagedata != 0)
599 virtual storeError verify() const
601 storeError result = base::verify();
602 if (result != store_E_None)
603 return result;
605 TestData const * pagedata = dynamic_page_cast< TestData const >(m_xPage.get());
606 if (!pagedata)
607 return store_E_WrongVersion;
609 return pagedata->verify();
612 static storeError verify (PageHolder const & rPage)
614 return PageHolderObject< TestData >::verify (rPage);
617 storeError loadAt (sal_uInt32 nOffset, TestBIOS & rBIOS)
619 storeError result = rBIOS.lookupAt (m_xPage, nOffset); // cache lookup
620 if (result == store_E_NotExists)
622 result = rBIOS.loadAt (m_xPage, nOffset);
623 if (result != store_E_None)
624 return result;
626 result = PageHolderObject< TestData >::verify (m_xPage);
627 if (result != store_E_None)
628 return result;
630 result = rBIOS.replaceAt (m_xPage, nOffset); // cache insert
632 return result;
634 storeError saveAt (sal_uInt32 nOffset, TestBIOS & rBIOS)
636 if (!m_xPage.get())
637 return store_E_InvalidAccess;
638 m_xPage->m_aDescr.m_nAddr = store::htonl(nOffset); // m_xPage->location (nOffset);
640 storeError result = PageHolderObject< TestData >::guard (m_xPage);
641 if (result != store_E_None)
642 return result;
644 result = rBIOS.saveAt (m_xPage, nOffset);
645 if (result != store_E_None)
646 return result;
648 return rBIOS.replaceAt (m_xPage, nOffset); // cache update
652 class TestObjectV2 : public PageHolderObject< TestData >
654 typedef PageHolderObject< TestData > base;
656 public:
657 storeError saveAt (sal_uInt32 nOffset, TestBIOS & rBIOS)
659 m_xPage->offset(nOffset);
661 storeError result = PageHolderObject< TestData >::guard (m_xPage);
662 if (result != store_E_None)
663 return result;
665 result = rBIOS.saveAt (m_xPage, nOffset);
666 if (result != store_E_None)
667 return result;
669 return rBIOS.replaceAt (m_xPage, nOffset);
671 #if 1
672 storeError dwim() const
674 TestData const * pImpl1 = operator->();
676 PageHolderObject< TestData > xImpl (m_xPage);
678 TestData const * pImpl2 = &*xImpl;
679 OSL_ASSERT(pImpl1 == pImpl2);
681 return xImpl->dwim();
683 #endif
686 class TestClient
688 public:
689 void dwim(TestBIOS & rBIOS)
691 TestObject aObj;
693 rBIOS.loadPageAt(aObj.get(), aObj.verify);
694 rBIOS.loadPageAt(aObj.get(), TestObject::verify);
695 rBIOS.loadPageAt(aObj.get(), PageHolderObject<TestData>::verify);
697 aObj.loadAt (1024, rBIOS);
699 TestObjectV2 aObj2;
700 aObj2.dwim();
701 aObj2->dwim();
705 /*======================================================================*/
707 class IPageAccess
709 public:
710 virtual storeError initialize (storeAccessMode eAccessMode, sal_uInt16 nPageSize) = 0;
712 public:
713 storeError readPageAt (PageHolder & rPage, sal_uInt32 nOffset)
715 return readPageAt_Impl (rPage, nOffset);
717 storeError writePageAt (PageHolder const & rPage, sal_uInt32 nOffset)
719 // [SECURITY:ValInput]
720 PageData const * pagedata = rPage.get();
721 OSL_PRECOND(!(pagedata == 0), "invalid Page");
722 if (pagedata == 0)
723 return store_E_InvalidParameter;
725 sal_uInt32 const offset = pagedata->offset();
726 OSL_PRECOND(!(nOffset != offset), "inconsistent Offset");
727 if (nOffset != offset)
728 return store_E_InvalidParameter;
730 OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::IPageAccess::writePageAt(): invalid Offset");
731 if (nOffset == STORE_PAGE_NULL)
732 return store_E_CantSeek;
734 return writePageAt_Impl (rPage, nOffset);
737 storeError peekAt (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes)
739 // [SECURITY:ValInput]
740 sal_uInt8 * dst_lo = static_cast<sal_uInt8*>(pBuffer);
741 if (!(dst_lo != 0))
742 return store_E_InvalidParameter;
744 sal_uInt8 * dst_hi = dst_lo + nBytes;
745 if (!(dst_lo < dst_hi))
746 return (dst_lo > dst_hi) ? store_E_InvalidParameter : store_E_None;
748 sal_uInt64 const dst_size = nOffset + nBytes;
749 if (dst_size > SAL_MAX_UINT32)
750 return store_E_CantSeek;
752 return peekAt_Impl (nOffset, dst_lo, (dst_hi - dst_lo));
755 storeError pokeAt (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes)
757 // [SECURITY:ValInput]
758 sal_uInt8 const * src_lo = static_cast<sal_uInt8 const*>(pBuffer);
759 if (!(src_lo != 0))
760 return store_E_InvalidParameter;
762 sal_uInt8 const * src_hi = src_lo + nBytes;
763 if (!(src_lo < src_hi))
764 return (src_lo > src_hi) ? store_E_InvalidParameter : store_E_None;
766 sal_uInt64 const dst_size = nOffset + nBytes;
767 if (dst_size > SAL_MAX_UINT32)
768 return store_E_CantSeek;
770 return pokeAt_Impl (nOffset, src_lo, (src_hi - src_lo));
773 storeError getSize (sal_uInt32 & rnSize)
775 rnSize = 0;
776 return getSize_Impl (rnSize);
779 storeError setSize (sal_uInt32 nSize)
781 return setSize_Impl (nSize);
784 private:
785 virtual storeError readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset) = 0;
786 virtual storeError writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset) = 0;
788 virtual storeError peekAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes) = 0;
789 virtual storeError pokeAt_Impl (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes) = 0;
791 virtual storeError getSize_Impl (sal_uInt32 & rnSize) = 0;
792 virtual storeError setSize_Impl (sal_uInt32 nSize) = 0;
795 /*======================================================================*/
797 template< class T > struct ResourceHolder
799 typedef typename T::destructor_type destructor_type;
801 T m_value;
803 explicit ResourceHolder (T const & value = T()) : m_value (value) {}
804 ~ResourceHolder() { reset(); }
806 T & get() { return m_value; }
807 T const & get() const { return m_value; }
809 void set (T const & value) { m_value = value; }
810 void reset (T const & value = T())
812 T tmp (m_value);
813 if (tmp != value)
814 destructor_type()(tmp);
815 set (value);
817 T release()
819 T tmp (m_value);
820 set (T());
821 return tmp;
824 ResourceHolder (ResourceHolder & rhs)
826 set (rhs.release());
828 ResourceHolder & operator= (ResourceHolder & rhs)
830 reset (rhs.release());
831 return *this;
835 struct FileHandle
837 oslFileHandle m_handle;
839 FileHandle() : m_handle(0) {}
841 operator oslFileHandle() { return m_handle; }
843 bool operator != (FileHandle const & rhs)
845 return (m_handle != rhs.m_handle);
848 oslFileError initialize (rtl_uString * pFilename, sal_uInt32 nFlags)
850 // Verify arguments.
851 if (!pFilename || !nFlags)
852 return osl_File_E_INVAL;
854 // Convert into FileUrl.
855 OUString aFileUrl;
856 if (osl_getFileURLFromSystemPath (pFilename, &(aFileUrl.pData)) != osl_File_E_None)
858 // Not system path. Maybe a file url, already.
859 rtl_uString_assign (&(aFileUrl.pData), pFilename);
862 // Acquire handle.
863 return osl_openFile (aFileUrl.pData, &m_handle, nFlags);
866 struct CloseFile
868 void operator()(FileHandle & rFile) const
870 if (rFile.m_handle != 0)
872 // Release handle.
873 (void) osl_closeFile (rFile.m_handle);
874 rFile.m_handle = 0;
878 typedef CloseFile destructor_type;
881 struct FileMapping
883 void * m_pAddr;
884 sal_uInt64 m_uSize;
886 FileMapping() : m_pAddr(0), m_uSize(0) {}
888 bool operator != (FileMapping const & rhs) const
890 return ((m_pAddr != rhs.m_pAddr) || (m_uSize != rhs.m_uSize));
893 oslFileError initialize (oslFileHandle hFile)
895 // Determine mapping size.
896 oslFileError result = osl_getFileSize (hFile, &m_uSize);
897 if (result != osl_File_E_None)
898 return result;
899 if (m_uSize > SAL_MAX_UINT32)
900 return osl_File_E_OVERFLOW;
902 // Acquire mapping.
903 return osl_mapFile (hFile, &m_pAddr, m_uSize, 0, 0);
906 struct UnmapFile
908 void operator ()(FileMapping & rMapping) const
910 if ((rMapping.m_pAddr != 0) && (rMapping.m_uSize != 0))
912 // Release mapping.
913 (void) osl_unmapFile (rMapping.m_pAddr, rMapping.m_uSize);
914 rMapping.m_pAddr = 0, rMapping.m_uSize = 0;
918 typedef UnmapFile destructor_type;
921 /*======================================================================*/
923 class FilePageAccess : public IPageAccess
925 oslFileHandle m_hFile;
927 public:
928 static storeError ERROR_FROM_NATIVE (oslFileError eErrno);
929 static sal_uInt32 MODE_TO_NATIVE (storeAccessMode eMode);
931 public:
932 explicit FilePageAccess (oslFileHandle hFile = 0) : m_hFile (hFile) {}
933 virtual storeError initialize (storeAccessMode eAccessMode, sal_uInt16 nPageSize);
935 private:
936 virtual storeError readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset);
937 virtual storeError writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset);
939 /* see @ OFileLockBytes */
940 virtual storeError peekAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes);
941 virtual storeError pokeAt_Impl (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes);
943 virtual storeError getSize_Impl (sal_uInt32 & rnSize);
944 virtual storeError setSize_Impl (sal_uInt32 nSize);
946 protected:
947 virtual ~FilePageAccess();
949 private:
950 /** Not implemented.
952 FilePageAccess (FilePageAccess const &);
953 FilePageAccess & operator= (FilePageAccess const &);
956 storeError FilePageAccess::initialize (storeAccessMode eAccessMode, sal_uInt16 nPageSize)
958 (void) eAccessMode; // UNUSED
959 (void) nPageSize; // UNUSED
960 return store_E_Unknown; // NYI
962 FilePageAccess::~FilePageAccess()
964 if (m_hFile != 0)
965 (void) osl_closeFile (m_hFile);
967 storeError FilePageAccess::readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset)
969 PageHolder page (0/*allocate()*/); /* @@@ construct w/ deallocator argument @@@ */
970 if (!page.get())
971 return store_E_OutOfMemory;
973 swap<PageHolder>(page, rPage);
974 return peekAt (nOffset, rPage.get(), 0/*size*/);
976 storeError FilePageAccess::writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset)
978 return pokeAt (nOffset, rPage.get(), 0/*size*/);
980 storeError FilePageAccess::peekAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes)
982 sal_uInt64 nDone = 0;
983 oslFileError result = osl_readFileAt (m_hFile, nOffset, pBuffer, nBytes, &nDone);
984 if (result != osl_File_E_None)
985 return ERROR_FROM_NATIVE(result);
986 if (nDone != nBytes)
987 return (nDone != 0) ? store_E_CantRead : store_E_NotExists;
988 return store_E_None;
990 storeError FilePageAccess::pokeAt_Impl (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes)
992 sal_uInt64 nDone = 0;
993 oslFileError result = osl_writeFileAt (m_hFile, nOffset, pBuffer, nBytes, &nDone);
994 if (result != osl_File_E_None)
995 return ERROR_FROM_NATIVE(result);
996 if (nDone != nBytes)
997 return store_E_CantWrite;
998 return store_E_None;
1000 storeError FilePageAccess::getSize_Impl (sal_uInt32 & rnSize)
1002 sal_uInt64 uSize = 0;
1003 oslFileError result = osl_getFileSize (m_hFile, &uSize);
1004 if (result != osl_File_E_None)
1005 return ERROR_FROM_NATIVE(result);
1006 if (uSize > SAL_MAX_UINT32)
1007 return store_E_CantSeek;
1009 rnSize = sal::static_int_cast<sal_uInt32>(uSize);
1010 return store_E_None;
1012 storeError FilePageAccess::setSize_Impl (sal_uInt32 nSize)
1014 oslFileError result = osl_setFileSize (m_hFile, nSize);
1015 if (result != osl_File_E_None)
1016 return ERROR_FROM_NATIVE(result);
1017 return store_E_None;
1019 storeError FilePageAccess::ERROR_FROM_NATIVE (oslFileError eErrno)
1021 switch (eErrno)
1023 case osl_File_E_None:
1024 return store_E_None;
1026 case osl_File_E_NOENT:
1027 return store_E_NotExists;
1029 case osl_File_E_ACCES:
1030 case osl_File_E_PERM:
1031 return store_E_AccessViolation;
1033 case osl_File_E_AGAIN:
1034 case osl_File_E_DEADLK:
1035 return store_E_LockingViolation;
1037 case osl_File_E_BADF:
1038 return store_E_InvalidHandle;
1040 case osl_File_E_INVAL:
1041 return store_E_InvalidParameter;
1043 case osl_File_E_NOSPC:
1044 return store_E_OutOfSpace;
1046 case osl_File_E_OVERFLOW:
1047 return store_E_CantSeek;
1049 default:
1050 return store_E_Unknown;
1053 sal_uInt32 FilePageAccess::MODE_TO_NATIVE(storeAccessMode eAccessMode)
1055 sal_uInt32 nMode = 0;
1056 switch (eAccessMode)
1058 case store_AccessCreate:
1059 case store_AccessReadCreate:
1060 nMode |= osl_File_OpenFlag_Create;
1061 // fall through
1062 case store_AccessReadWrite:
1063 nMode |= osl_File_OpenFlag_Write;
1064 // fall through
1065 case store_AccessReadOnly:
1066 nMode |= osl_File_OpenFlag_Read;
1067 break;
1068 default:
1069 OSL_PRECOND(0, "store::FilePageAccess: unknown storeAccessMode");
1071 return nMode;
1074 /*===*/
1076 class MemoryPageAccess : public IPageAccess
1078 /** Representation.
1080 sal_uInt8 * m_pData;
1081 sal_uInt32 m_nSize;
1083 /** Callback function to release Representation.
1085 typedef void (*destructor_type)(sal_uInt8 * pData, sal_uInt32 nSize);
1086 destructor_type m_destructor;
1088 /** Default destructor callback.
1090 static void freeMemory (sal_uInt8 * pData, sal_uInt32 nSize);
1092 public:
1093 MemoryPageAccess()
1094 : m_pData (0), m_nSize (0), m_destructor (MemoryPageAccess::freeMemory)
1096 MemoryPageAccess (sal_uInt8 * pData, sal_uInt32 nSize, destructor_type destructor = MemoryPageAccess::freeMemory)
1097 : m_pData (pData), m_nSize (nSize), m_destructor (destructor)
1100 virtual storeError initialize (storeAccessMode eAccessMode, sal_uInt16 nPageSize);
1102 private:
1103 /** Page (size aligned) access.
1105 virtual storeError readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset);
1106 virtual storeError writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset);
1108 /** Low level access.
1110 virtual storeError peekAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes);
1111 virtual storeError pokeAt_Impl (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes);
1113 virtual storeError getSize_Impl (sal_uInt32 & rnSize);
1114 virtual storeError setSize_Impl (sal_uInt32 nSize);
1116 protected:
1117 virtual ~MemoryPageAccess();
1119 private:
1120 /** Not implemented.
1122 MemoryPageAccess (MemoryPageAccess const &);
1123 MemoryPageAccess & operator= (MemoryPageAccess const &);
1126 storeError MemoryPageAccess::initialize (storeAccessMode eAccessMode, sal_uInt16 nPageSize)
1128 (void) eAccessMode; // UNUSED
1129 (void) nPageSize; // UNUSED
1130 return store_E_Unknown; // NYI
1132 MemoryPageAccess::~MemoryPageAccess()
1134 if (m_destructor != 0)
1136 // release resource.
1137 (*m_destructor)(m_pData, m_nSize);
1140 storeError MemoryPageAccess::readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset)
1142 /* OSL_PRECOND(nOffset % size == 0, "Unaligned page read."); */
1143 PageHolder page (reinterpret_cast< PageData* >(m_pData + nOffset));
1144 swap<PageHolder>(page, rPage);
1145 return store_E_None;
1147 storeError MemoryPageAccess::writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset)
1149 PageData const * pagedata = rPage.get();
1150 if (!(pagedata != 0))
1151 return store_E_InvalidParameter;
1153 return pokeAt (nOffset, pagedata, pagedata->size());
1155 storeError MemoryPageAccess::peekAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes)
1157 // [SECURITY:ValInput]
1158 sal_uInt8 * dst_lo = static_cast<sal_uInt8*>(pBuffer);
1159 if (!(dst_lo != 0))
1160 return store_E_InvalidParameter;
1162 sal_uInt8 * dst_hi = dst_lo + nBytes;
1163 if (!(dst_lo <= dst_hi))
1164 return store_E_InvalidParameter;
1166 // ...
1167 sal_uInt8 const * src_lo = m_pData + nOffset;
1168 if (!(src_lo <= m_pData + m_nSize))
1169 return store_E_CantSeek;
1171 sal_uInt8 const * src_hi = src_lo + nBytes;
1172 if (!(src_hi <= m_pData + m_nSize))
1173 return store_E_CantRead;
1175 // copy.
1176 memcpy (pBuffer, src_lo, (src_hi - src_lo));
1177 return store_E_None;
1179 storeError MemoryPageAccess::pokeAt_Impl (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes)
1181 // [SECURITY:ValInput]
1182 sal_uInt8 const * src_lo = static_cast<sal_uInt8 const*>(pBuffer);
1183 if (!(src_lo != 0))
1184 return store_E_InvalidParameter;
1186 sal_uInt8 const * src_hi = src_lo + nBytes;
1187 if (!(src_lo <= src_hi))
1188 return store_E_InvalidParameter;
1190 sal_uInt64 const uSize = nOffset + nBytes;
1191 if (uSize > SAL_MAX_UINT32)
1192 return store_E_CantSeek;
1194 // ...
1195 if (uSize > m_nSize)
1197 // increase size.
1198 storeError eErrCode = setSize (sal::static_int_cast<sal_uInt32>(uSize));
1199 if (eErrCode != store_E_None)
1200 return eErrCode;
1203 sal_uInt8 * dst_lo = m_pData + nOffset;
1204 if (!(dst_lo <= m_pData + m_nSize))
1205 return store_E_CantSeek;
1207 sal_uInt8 * dst_hi = dst_lo + nBytes;
1208 if (!(dst_hi <= m_pData + m_nSize))
1209 return store_E_CantWrite;
1211 // copy.
1212 memcpy (dst_lo, src_lo, (src_hi - src_lo));
1213 return store_E_None;
1215 storeError MemoryPageAccess::getSize_Impl (sal_uInt32 & rnSize)
1217 rnSize = m_nSize;
1218 return store_E_None;
1220 storeError MemoryPageAccess::setSize_Impl (sal_uInt32 nSize)
1222 if (nSize != m_nSize)
1224 sal_uInt8 * pData = static_cast<sal_uInt8*>(rtl_reallocateMemory (m_pData, nSize));
1225 if (pData != 0)
1227 if (nSize > m_nSize)
1228 memset (pData + m_nSize, 0, sal::static_int_cast< size_t >(nSize - m_nSize));
1230 else
1232 if (nSize != 0)
1233 return store_E_OutOfMemory;
1235 m_pData = pData, m_nSize = nSize;
1237 return store_E_None;
1239 void MemoryPageAccess::freeMemory (sal_uInt8 * pData, sal_uInt32 /*nSize*/)
1241 rtl_freeMemory (pData);
1244 /*===*/
1246 class MappedPageAccess : public MemoryPageAccess
1248 /** @see MemoryPageAccess::destructor_type callback function.
1250 static void unmapFile (sal_uInt8 * pData, sal_uInt32 nSize);
1252 public:
1253 MappedPageAccess (sal_uInt8 * pData, sal_uInt32 nSize);
1255 virtual storeError initialize (storeAccessMode eAccessMode, sal_uInt16 nPageSize);
1257 virtual storeError writePageAt (PageHolder const & rPage, sal_uInt32 nOffset);
1259 private:
1260 virtual storeError pokeAt_Impl (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes);
1261 virtual storeError setSize_Impl (sal_uInt32 nSize);
1263 protected:
1264 virtual ~MappedPageAccess() {}
1267 MappedPageAccess::MappedPageAccess (sal_uInt8 * pData, sal_uInt32 nSize)
1268 : MemoryPageAccess (pData, nSize, MappedPageAccess::unmapFile)
1271 storeError MappedPageAccess::initialize (storeAccessMode eAccessMode, sal_uInt16 nPageSize)
1273 OSL_PRECOND(eAccessMode == store_AccessReadOnly, "store::MappedPageAccess: invalid AccessMode");
1274 return MemoryPageAccess::initialize (eAccessMode, nPageSize);
1276 storeError MappedPageAccess::writePageAt (PageHolder const & /*rPage*/, sal_uInt32 /*nOffset*/)
1278 return store_E_AccessViolation;
1280 storeError MappedPageAccess::pokeAt_Impl (sal_uInt32 /*nOffset*/, void const * /*pBuffer*/, sal_uInt32 /*nBytes*/)
1282 return store_E_AccessViolation;
1284 storeError MappedPageAccess::setSize_Impl (sal_uInt32 /*nSize*/)
1286 return store_E_AccessViolation;
1288 void MappedPageAccess::unmapFile (sal_uInt8 * pData, sal_uInt32 nSize)
1290 (void) osl_unmapFile (pData, nSize);
1293 /*========================================================================
1295 * main.
1297 *======================================================================*/
1299 #include <stdio.h>
1301 int SAL_CALL main (int argc, char ** argv)
1303 OSL_PRECOND(argc >= 1, "t_page: error: insufficient number of arguments.");
1304 if (argc < 1)
1305 return 0;
1308 void *a = (void*)1, *b = (void*)2;
1309 swap<void*>(a, b);
1312 PageObject a;
1313 PageObject b (a);
1314 PageObject c;
1316 c = b;
1317 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 return result;
1354 return 0;
1357 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */