1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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"
30 #include "rtl/ustring.hxx"
32 template< class T
> void swap (T
& lhs
, T
& rhs
)
34 T tmp
= rhs
; rhs
= lhs
; lhs
= tmp
;
43 rtl_cache_type
* m_cache
;
46 static Allocator
& get();
50 return static_cast<long*>(rtl_cache_alloc (m_cache
));
52 void free (long * pCount
)
54 rtl_cache_free (m_cache
, pCount
);
64 : m_pCount(Allocator::get().alloc())
66 if (m_pCount
!= 0) (*m_pCount
) = 1;
73 long new_count
= --(*m_pCount
);
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
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
);
103 SharedCount::operator= (SharedCount
const & rhs
) // nothrow
105 SharedCount
tmp(rhs
);
106 swap
<SharedCount
>(tmp
, *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",
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))
142 #define STORE_DWORD(dword) (dword)
147 typedef store::OStorePageGuard G
;
148 typedef store::OStorePageDescriptor D
;
149 typedef store::OStorePageLink L
;
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
);
166 sal_uInt32
type() const { return m_aGuard
.m_nMagic
; /* @@@ */ }
170 sal_uInt32
offset() const { return m_aDescr
.m_nAddr
; /* @@@ */ }
171 void offset (sal_uInt32 nOffset
) { m_aDescr
.m_nAddr
= nOffset
; }
175 sal_uInt16
size() const { return m_aDescr
.m_nSize
; /* @@@ */ }
179 class Allocator
: public rtl::IReference
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
);
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 *) {}
201 explicit PageData (sal_uInt16 nPageSize
= thePageSize
)
202 : m_aDescr (STORE_PAGE_NULL
, nPageSize
, thePageSize
)
210 storeError
verify() const
218 rtl_cache_type
* m_cache
;
219 SharedCount m_refcount
;
223 : m_cache(0), m_refcount()
234 friend void swap
<>(PageAllocator
& lhs
, PageAllocator
& rhs
);
236 PageAllocator (PageAllocator
const & rhs
);
237 PageAllocator
& operator= (PageAllocator
const & rhs
);
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
)
254 PageAllocator::operator= (PageAllocator
const & rhs
)
256 PageAllocator
tmp (rhs
);
257 swap
<PageAllocator
>(tmp
, *this);
261 /*======================================================================*/
265 SharedCount m_refcount
;
266 PageData
* m_pagedata
;
268 typedef rtl::Reference
< PageData::Allocator
> allocator_type
;
269 allocator_type m_allocator
;
272 explicit PageHolder (PageData
* pagedata
= 0, allocator_type
const & allocator
= allocator_type())
274 m_pagedata (pagedata
),
275 m_allocator(allocator
)
280 if ((m_refcount
== 1) && (m_pagedata
!= 0) && m_allocator
.is())
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
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
)
314 PageHolder::operator= (PageHolder
const & rhs
) // nothrow
316 PageHolder
tmp (rhs
);
317 swap
<PageHolder
>(tmp
, *this);
321 /*======================================================================*/
324 class PageHolderObject
334 static bool isA (PageData
const * p
)
336 return ((p
!= 0) && (p
->type() == U::theTypeId
));
340 static U
* dynamic_page_cast (PageData
* p
)
342 return isA
<U
>(p
) ? static_cast<U
*>(p
) : 0;
346 static U
const * dynamic_page_cast (PageData
const * p
)
348 return isA
<U
>(p
) ? static_cast<U
const *>(p
) : 0;
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
);
363 explicit PageHolderObject (PageHolder
const & rxPage
= PageHolder())
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
);
386 T
* pImpl
= dynamic_page_cast
<T
>(m_xPage
.get());
387 OSL_PRECOND(pImpl
!= 0, "store::PageHolder<T>::operator->(): Null pointer");
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");
399 T
* pImpl
= dynamic_page_cast
<T
>(m_xPage
.get());
400 OSL_PRECOND(pImpl
!= 0, "store::PageHolder<T>::operator*(): Null pointer");
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");
410 static storeError
guard (PageHolder
& rxPage
)
412 T
* pImpl
= dynamic_page_cast
<T
>(rxPage
.get());
414 { pImpl
->guard(); return store_E_None
; }
415 else if (rxPage
.get() != 0)
416 return store_E_WrongVersion
;
418 return store_E_InvalidAccess
;
420 static storeError
verify (PageHolder
const & rxPage
)
422 T
const * pImpl
= dynamic_page_cast
<T
>(rxPage
.get());
424 return pImpl
->verify();
425 else if (rxPage
.get() != 0)
426 return store_E_WrongVersion
;
428 return store_E_InvalidAccess
;
432 /*======================================================================*/
437 explicit PageObject (PageHolder
const & rxPage
= PageHolder())
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");
452 PageData
& operator*()
454 PageData
* pImpl
= m_xPage
.get();
455 OSL_PRECOND(pImpl
!= 0, "store::PageObject::operator*(): Null pointer");
459 virtual void guard();
460 virtual storeError
verify() const;
466 PageObject::~PageObject()
468 void PageObject::guard()
470 PageData
* p
= m_xPage
.get();
473 storeError
PageObject::verify() const
475 PageData
const * p
= m_xPage
.get();
479 /*======================================================================*/
482 T
* dynamic_page_cast (PageData
* pagedata
)
484 if ((pagedata
!= 0) && (pagedata
->type() == T::theTypeId
))
485 return static_cast<T
*>(pagedata
);
490 T
* dynamic_page_cast (PageData
const * pagedata
)
492 if ((pagedata
!= 0) && (pagedata
->type() == T::theTypeId
))
493 return static_cast<T
*>(pagedata
);
497 /*======================================================================*/
502 storeError
loadPageAt (PageHolder
& rPage
, storeError (*pfnVerify
)(PageHolder
const &))
504 return (pfnVerify
)(rPage
);
507 storeError
allocate (PageHolder
& rxPage
, ...)
509 // NYI: PageObject.save(nAddr, *this);
511 return store_E_Unknown
; // NYI
514 storeError
loadAt (PageHolder
& rPage
, sal_uInt32 nOffset
)
517 (void)nOffset
; // NYI
518 return store_E_Unknown
; // NYI
520 storeError
saveAt (PageHolder
const & rPage
, sal_uInt32 nOffset
)
523 (void)nOffset
; // NYI
524 return store_E_Unknown
; // NYI
528 storeError
save (PageHolder
& rxPage
, sal_uInt32 nOffset
)
530 storeError result
= PageHolderObject
<T
>::guard (rxPage
);
531 if (result
!= store_E_None
)
533 return saveAt (rxPage
, nOffset
);
536 storeError
lookupAt (PageHolder
& rPage
, sal_uInt32 nOffset
)
539 (void)nOffset
; // NYI
540 return store_E_NotExists
;
542 storeError
replaceAt (PageHolder
const & rPage
, sal_uInt32 nOffset
)
545 (void)nOffset
; // NYI
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;
564 // self::m_aGuard = ...;
566 storeError
verify() const
568 storeError result
= base::verify();
569 if (result
!= store_E_None
)
571 if (!(base::type() == self::theTypeId
))
572 return store_E_WrongVersion
;
576 storeError
dwim() const
581 class TestObject
: public PageObject
583 typedef PageObject base
;
589 PageHolderObject
< TestData
> xPage (m_xPage
);
595 TestData
* pagedata
= dynamic_page_cast
< TestData
>(m_xPage
.get());
599 virtual storeError
verify() const
601 storeError result
= base::verify();
602 if (result
!= store_E_None
)
605 TestData
const * pagedata
= dynamic_page_cast
< TestData
const >(m_xPage
.get());
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
)
626 result
= PageHolderObject
< TestData
>::verify (m_xPage
);
627 if (result
!= store_E_None
)
630 result
= rBIOS
.replaceAt (m_xPage
, nOffset
); // cache insert
634 storeError
saveAt (sal_uInt32 nOffset
, TestBIOS
& rBIOS
)
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
)
644 result
= rBIOS
.saveAt (m_xPage
, nOffset
);
645 if (result
!= store_E_None
)
648 return rBIOS
.replaceAt (m_xPage
, nOffset
); // cache update
652 class TestObjectV2
: public PageHolderObject
< TestData
>
654 typedef PageHolderObject
< TestData
> base
;
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
)
665 result
= rBIOS
.saveAt (m_xPage
, nOffset
);
666 if (result
!= store_E_None
)
669 return rBIOS
.replaceAt (m_xPage
, nOffset
);
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();
689 void dwim(TestBIOS
& rBIOS
)
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
);
705 /*======================================================================*/
710 virtual storeError
initialize (storeAccessMode eAccessMode
, sal_uInt16 nPageSize
) = 0;
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");
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
);
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
);
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
)
776 return getSize_Impl (rnSize
);
779 storeError
setSize (sal_uInt32 nSize
)
781 return setSize_Impl (nSize
);
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
;
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())
814 destructor_type()(tmp
);
824 ResourceHolder (ResourceHolder
& rhs
)
828 ResourceHolder
& operator= (ResourceHolder
& rhs
)
830 reset (rhs
.release());
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
)
851 if (!pFilename
|| !nFlags
)
852 return osl_File_E_INVAL
;
854 // Convert into FileUrl.
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
);
863 return osl_openFile (aFileUrl
.pData
, &m_handle
, nFlags
);
868 void operator()(FileHandle
& rFile
) const
870 if (rFile
.m_handle
!= 0)
873 (void) osl_closeFile (rFile
.m_handle
);
878 typedef CloseFile destructor_type
;
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
)
899 if (m_uSize
> SAL_MAX_UINT32
)
900 return osl_File_E_OVERFLOW
;
903 return osl_mapFile (hFile
, &m_pAddr
, m_uSize
, 0, 0);
908 void operator ()(FileMapping
& rMapping
) const
910 if ((rMapping
.m_pAddr
!= 0) && (rMapping
.m_uSize
!= 0))
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
;
928 static storeError
ERROR_FROM_NATIVE (oslFileError eErrno
);
929 static sal_uInt32
MODE_TO_NATIVE (storeAccessMode eMode
);
932 explicit FilePageAccess (oslFileHandle hFile
= 0) : m_hFile (hFile
) {}
933 virtual storeError
initialize (storeAccessMode eAccessMode
, sal_uInt16 nPageSize
);
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
);
947 virtual ~FilePageAccess();
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()
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 @@@ */
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
);
987 return (nDone
!= 0) ? store_E_CantRead
: store_E_NotExists
;
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
);
997 return store_E_CantWrite
;
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
)
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
;
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
;
1062 case store_AccessReadWrite
:
1063 nMode
|= osl_File_OpenFlag_Write
;
1065 case store_AccessReadOnly
:
1066 nMode
|= osl_File_OpenFlag_Read
;
1069 OSL_PRECOND(0, "store::FilePageAccess: unknown storeAccessMode");
1076 class MemoryPageAccess
: public IPageAccess
1080 sal_uInt8
* m_pData
;
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
);
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
);
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
);
1117 virtual ~MemoryPageAccess();
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
);
1160 return store_E_InvalidParameter
;
1162 sal_uInt8
* dst_hi
= dst_lo
+ nBytes
;
1163 if (!(dst_lo
<= dst_hi
))
1164 return store_E_InvalidParameter
;
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
;
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
);
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
;
1195 if (uSize
> m_nSize
)
1198 storeError eErrCode
= setSize (sal::static_int_cast
<sal_uInt32
>(uSize
));
1199 if (eErrCode
!= store_E_None
)
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
;
1212 memcpy (dst_lo
, src_lo
, (src_hi
- src_lo
));
1213 return store_E_None
;
1215 storeError
MemoryPageAccess::getSize_Impl (sal_uInt32
& rnSize
)
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
));
1227 if (nSize
> m_nSize
)
1228 memset (pData
+ m_nSize
, 0, sal::static_int_cast
< size_t >(nSize
- m_nSize
));
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
);
1246 class MappedPageAccess
: public MemoryPageAccess
1248 /** @see MemoryPageAccess::destructor_type callback function.
1250 static void unmapFile (sal_uInt8
* pData
, sal_uInt32 nSize
);
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
);
1260 virtual storeError
pokeAt_Impl (sal_uInt32 nOffset
, void const * pBuffer
, sal_uInt32 nBytes
);
1261 virtual storeError
setSize_Impl (sal_uInt32 nSize
);
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 /*========================================================================
1297 *======================================================================*/
1301 int SAL_CALL
main (int argc
, char ** argv
)
1303 OSL_PRECOND(argc
>= 1, "t_page: error: insufficient number of arguments.");
1308 void *a
= (void*)1, *b
= (void*)2;
1322 aClient
.dwim (aBIOS
);
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
);
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
);
1357 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */