merge the formfield patch from ooo-build
[ooovba.git] / store / source / lockbyte.cxx
bloba03628bfb740d2f3f28b17d1330af278c6a3bd41
1 /*************************************************************************
3 * OpenOffice.org - a multi-platform office productivity suite
5 * $RCSfile: lockbyte.cxx,v $
7 * $Revision: 1.1.2.4 $
9 * last change: $Author: mhu $ $Date: 2008/11/25 15:44:56 $
11 * The Contents of this file are made available subject to
12 * the terms of GNU Lesser General Public License Version 2.1.
15 * GNU Lesser General Public License Version 2.1
16 * =============================================
17 * Copyright 2005 by Sun Microsystems, Inc.
18 * 901 San Antonio Road, Palo Alto, CA 94303, USA
20 * This library is free software; you can redistribute it and/or
21 * modify it under the terms of the GNU Lesser General Public
22 * License version 2.1, as published by the Free Software Foundation.
24 * This library is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27 * Lesser General Public License for more details.
29 * You should have received a copy of the GNU Lesser General Public
30 * License along with this library; if not, write to the Free Software
31 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
32 * MA 02111-1307 USA
34 ************************************************************************/
36 // MARKER(update_precomp.py): autogen include statement, do not remove
37 #include "precompiled_store.hxx"
39 #include "lockbyte.hxx"
41 #include "sal/types.h"
42 #include "osl/diagnose.h"
43 #include "osl/file.h"
44 #include "osl/process.h"
45 #include "rtl/alloc.h"
46 #include "rtl/ustring.hxx"
48 #include "object.hxx"
49 #include "storbase.hxx"
51 #ifndef INCLUDED_STRING_H
52 #include <string.h>
53 #define INCLUDED_STRING_H
54 #endif
56 using namespace store;
58 /*========================================================================
60 * ILockBytes (non-virtual interface) implementation.
62 *======================================================================*/
64 storeError ILockBytes::initialize (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize)
66 OSL_PRECOND((STORE_MINIMUM_PAGESIZE <= nPageSize) && (nPageSize <= STORE_MAXIMUM_PAGESIZE), "invalid PageSize");
67 return initialize_Impl (rxAllocator, nPageSize);
70 storeError ILockBytes::readPageAt (PageHolder & rPage, sal_uInt32 nOffset)
72 OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::ILockBytes::readPageAt(): invalid Offset");
73 if (nOffset == STORE_PAGE_NULL)
74 return store_E_CantSeek;
76 return readPageAt_Impl (rPage, nOffset);
79 storeError ILockBytes::writePageAt (PageHolder const & rPage, sal_uInt32 nOffset)
81 // [SECURITY:ValInput]
82 PageData const * pagedata = rPage.get();
83 OSL_PRECOND(!(pagedata == 0), "store::ILockBytes::writePageAt(): invalid Page");
84 if (pagedata == 0)
85 return store_E_InvalidParameter;
87 sal_uInt32 const offset = pagedata->location();
88 OSL_PRECOND(!(nOffset != offset), "store::ILockBytes::writePageAt(): inconsistent Offset");
89 if (nOffset != offset)
90 return store_E_InvalidParameter;
92 OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::ILockBytes::writePageAt(): invalid Offset");
93 if (nOffset == STORE_PAGE_NULL)
94 return store_E_CantSeek;
96 return writePageAt_Impl (rPage, nOffset);
99 storeError ILockBytes::readAt (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes)
101 // [SECURITY:ValInput]
102 sal_uInt8 * dst_lo = static_cast<sal_uInt8*>(pBuffer);
103 if (!(dst_lo != 0))
104 return store_E_InvalidParameter;
106 sal_uInt8 * dst_hi = dst_lo + nBytes;
107 if (!(dst_lo < dst_hi))
108 return (dst_lo > dst_hi) ? store_E_InvalidParameter : store_E_None;
110 OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::ILockBytes::readAt(): invalid Offset");
111 if (nOffset == STORE_PAGE_NULL)
112 return store_E_CantSeek;
114 sal_uInt64 const src_size = nOffset + nBytes;
115 if (src_size > SAL_MAX_UINT32)
116 return store_E_CantSeek;
118 return readAt_Impl (nOffset, dst_lo, (dst_hi - dst_lo));
121 storeError ILockBytes::writeAt (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes)
123 // [SECURITY:ValInput]
124 sal_uInt8 const * src_lo = static_cast<sal_uInt8 const*>(pBuffer);
125 if (!(src_lo != 0))
126 return store_E_InvalidParameter;
128 sal_uInt8 const * src_hi = src_lo + nBytes;
129 if (!(src_lo < src_hi))
130 return (src_lo > src_hi) ? store_E_InvalidParameter : store_E_None;
132 OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::ILockBytes::writeAt(): invalid Offset");
133 if (nOffset == STORE_PAGE_NULL)
134 return store_E_CantSeek;
136 sal_uInt64 const dst_size = nOffset + nBytes;
137 if (dst_size > SAL_MAX_UINT32)
138 return store_E_CantSeek;
140 return writeAt_Impl (nOffset, src_lo, (src_hi - src_lo));
143 storeError ILockBytes::getSize (sal_uInt32 & rnSize)
145 rnSize = 0;
146 return getSize_Impl (rnSize);
149 storeError ILockBytes::setSize (sal_uInt32 nSize)
151 return setSize_Impl (nSize);
154 storeError ILockBytes::flush()
156 return flush_Impl();
159 storeError ILockBytes::lockRange (sal_uInt32 nOffset, sal_uInt32 nBytes)
161 OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::ILockBytes::lockRange(): invalid Offset");
162 if (nOffset == STORE_PAGE_NULL)
163 return store_E_CantSeek;
165 sal_uInt64 size = nOffset + nBytes;
166 if (size > SAL_MAX_UINT32)
167 return store_E_CantSeek;
169 #ifdef STORE_FEATURE_LOCKING
170 return lockRange_Impl (nOffset, nBytes);
171 #else
172 return store_E_None; // E_Unsupported
173 #endif /* STORE_FEATURE_LOCKING */
176 storeError ILockBytes::unlockRange (sal_uInt32 nOffset, sal_uInt32 nBytes)
178 OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::ILockBytes::unlockRange(): invalid Offset");
179 if (nOffset == STORE_PAGE_NULL)
180 return store_E_CantSeek;
182 sal_uInt64 size = nOffset + nBytes;
183 if (size > SAL_MAX_UINT32)
184 return store_E_CantSeek;
186 #ifdef STORE_FEATURE_LOCKING
187 return unlockRange_Impl (nOffset, nBytes);
188 #else
189 return store_E_None; // E_Unsupported
190 #endif /* STORE_FEATURE_LOCKING */
193 /*========================================================================
195 * FileLockBytes implementation.
197 *======================================================================*/
198 namespace store
201 struct FileHandle
203 oslFileHandle m_handle;
205 FileHandle() : m_handle(0) {}
207 bool operator != (FileHandle const & rhs)
209 return (m_handle != rhs.m_handle);
212 static storeError errorFromNative (oslFileError eErrno)
214 switch (eErrno)
216 case osl_File_E_None:
217 return store_E_None;
219 case osl_File_E_NOENT:
220 return store_E_NotExists;
222 case osl_File_E_ACCES:
223 case osl_File_E_PERM:
224 return store_E_AccessViolation;
226 case osl_File_E_AGAIN:
227 case osl_File_E_DEADLK:
228 return store_E_LockingViolation;
230 case osl_File_E_BADF:
231 return store_E_InvalidHandle;
233 case osl_File_E_INVAL:
234 return store_E_InvalidParameter;
236 case osl_File_E_NOMEM:
237 return store_E_OutOfMemory;
239 case osl_File_E_NOSPC:
240 return store_E_OutOfSpace;
242 case osl_File_E_OVERFLOW:
243 return store_E_CantSeek;
245 default:
246 return store_E_Unknown;
250 static sal_uInt32 modeToNative (storeAccessMode eAccessMode)
252 sal_uInt32 nFlags = 0;
253 switch (eAccessMode)
255 case store_AccessCreate:
256 case store_AccessReadCreate:
257 nFlags |= osl_File_OpenFlag_Create;
258 // fall through
259 case store_AccessReadWrite:
260 nFlags |= osl_File_OpenFlag_Write;
261 // fall through
262 case store_AccessReadOnly:
263 nFlags |= osl_File_OpenFlag_Read;
264 break;
265 default:
266 OSL_PRECOND(0, "store::FileHandle: unknown storeAccessMode");
268 return nFlags;
271 storeError initialize (rtl_uString * pFilename, storeAccessMode eAccessMode)
273 // Verify arguments.
274 sal_uInt32 nFlags = modeToNative (eAccessMode);
275 if (!pFilename || !nFlags)
276 return store_E_InvalidParameter;
278 // Convert into FileUrl.
279 rtl::OUString aFileUrl;
280 if (osl_getFileURLFromSystemPath (pFilename, &(aFileUrl.pData)) != osl_File_E_None)
282 // Not system path. Assume file url.
283 rtl_uString_assign (&(aFileUrl.pData), pFilename);
285 if (aFileUrl.compareToAscii("file://", 7) != 0)
287 // Not file url. Assume relative path.
288 rtl::OUString aCwdUrl;
289 (void) osl_getProcessWorkingDir (&(aCwdUrl.pData));
291 // Absolute file url.
292 (void) osl_getAbsoluteFileURL (aCwdUrl.pData, aFileUrl.pData, &(aFileUrl.pData));
295 // Acquire handle.
296 oslFileError result = osl_openFile (aFileUrl.pData, &m_handle, nFlags);
297 if (result == osl_File_E_EXIST)
299 // Already existing (O_CREAT | O_EXCL).
300 result = osl_openFile (aFileUrl.pData, &m_handle, osl_File_OpenFlag_Read | osl_File_OpenFlag_Write);
301 if ((result == osl_File_E_None) && (eAccessMode == store_AccessCreate))
303 // Truncate existing file.
304 result = osl_setFileSize (m_handle, 0);
307 if (result != osl_File_E_None)
308 return errorFromNative(result);
309 return store_E_None;
312 /** @see FileLockBytes destructor
314 static void closeFile (oslFileHandle hFile)
316 (void) osl_closeFile (hFile);
319 /** @see ResourceHolder<T>::destructor_type
321 struct CloseFile
323 void operator()(FileHandle & rFile) const
325 // Release handle.
326 closeFile (rFile.m_handle);
327 rFile.m_handle = 0;
330 typedef CloseFile destructor_type;
333 class FileLockBytes :
334 public store::OStoreObject,
335 public store::ILockBytes
337 /** Representation.
339 oslFileHandle m_hFile;
340 sal_uInt32 m_nSize;
341 rtl::Reference< PageData::Allocator > m_xAllocator;
343 storeError initSize_Impl (sal_uInt32 & rnSize);
345 /** ILockBytes implementation.
347 virtual storeError initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize);
349 virtual storeError readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset);
350 virtual storeError writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset);
352 virtual storeError readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes);
353 virtual storeError writeAt_Impl (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes);
355 virtual storeError getSize_Impl (sal_uInt32 & rnSize);
356 virtual storeError setSize_Impl (sal_uInt32 nSize);
358 virtual storeError flush_Impl();
360 /** Not implemented.
362 FileLockBytes (FileLockBytes const &);
363 FileLockBytes & operator= (FileLockBytes const &);
365 public:
366 /** Construction.
368 explicit FileLockBytes (FileHandle & rFile);
370 /** Delegate multiple inherited IReference.
372 virtual oslInterlockedCount SAL_CALL acquire();
373 virtual oslInterlockedCount SAL_CALL release();
375 protected:
376 /** Destruction.
378 virtual ~FileLockBytes();
381 } // namespace store
383 FileLockBytes::FileLockBytes (FileHandle & rFile)
384 : m_hFile (rFile.m_handle), m_nSize (SAL_MAX_UINT32), m_xAllocator()
388 FileLockBytes::~FileLockBytes()
390 FileHandle::closeFile (m_hFile);
393 oslInterlockedCount SAL_CALL FileLockBytes::acquire()
395 return OStoreObject::acquire();
398 oslInterlockedCount SAL_CALL FileLockBytes::release()
400 return OStoreObject::release();
403 storeError FileLockBytes::initSize_Impl (sal_uInt32 & rnSize)
405 /* osl_getFileSize() uses slow 'fstat(h, &size)',
406 * instead of fast 'size = lseek(h, 0, SEEK_END)'.
407 * so, init size here, and track changes.
409 sal_uInt64 uSize = 0;
410 oslFileError result = osl_getFileSize (m_hFile, &uSize);
411 if (result != osl_File_E_None)
412 return FileHandle::errorFromNative(result);
413 if (uSize > SAL_MAX_UINT32)
414 return store_E_CantSeek;
416 rnSize = sal::static_int_cast<sal_uInt32>(uSize);
417 return store_E_None;
420 storeError FileLockBytes::initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize)
422 storeError result = initSize_Impl (m_nSize);
423 if (result != store_E_None)
424 return (result);
426 result = PageData::Allocator::createInstance (rxAllocator, nPageSize);
427 if (result != store_E_None)
428 return (result);
430 // @see readPageAt_Impl().
431 m_xAllocator = rxAllocator;
432 return store_E_None;
435 storeError FileLockBytes::readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset)
437 if (m_xAllocator.is())
439 PageHolder page (m_xAllocator->construct<PageData>(), m_xAllocator);
440 page.swap (rPage);
443 if (!m_xAllocator.is())
444 return store_E_InvalidAccess;
445 if (!rPage.get())
446 return store_E_OutOfMemory;
448 PageData * pagedata = rPage.get();
449 return readAt_Impl (nOffset, pagedata, pagedata->size());
452 storeError FileLockBytes::writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset)
454 PageData const * pagedata = rPage.get();
455 OSL_PRECOND(pagedata != 0, "contract violation");
456 return writeAt_Impl (nOffset, pagedata, pagedata->size());
459 storeError FileLockBytes::readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes)
461 sal_uInt64 nDone = 0;
462 oslFileError result = osl_readFileAt (m_hFile, nOffset, pBuffer, nBytes, &nDone);
463 if (result != osl_File_E_None)
464 return FileHandle::errorFromNative(result);
465 if (nDone != nBytes)
466 return (nDone != 0) ? store_E_CantRead : store_E_NotExists;
467 return store_E_None;
470 storeError FileLockBytes::writeAt_Impl (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes)
472 sal_uInt64 nDone = 0;
473 oslFileError result = osl_writeFileAt (m_hFile, nOffset, pBuffer, nBytes, &nDone);
474 if (result != osl_File_E_None)
475 return FileHandle::errorFromNative(result);
476 if (nDone != nBytes)
477 return store_E_CantWrite;
479 sal_uInt64 const uSize = nOffset + nBytes;
480 OSL_PRECOND(uSize < SAL_MAX_UINT32, "store::ILockBytes::writeAt() contract violation");
481 if (uSize > m_nSize)
482 m_nSize = sal::static_int_cast<sal_uInt32>(uSize);
483 return store_E_None;
486 storeError FileLockBytes::getSize_Impl (sal_uInt32 & rnSize)
488 rnSize = m_nSize;
489 return store_E_None;
492 storeError FileLockBytes::setSize_Impl (sal_uInt32 nSize)
494 oslFileError result = osl_setFileSize (m_hFile, nSize);
495 if (result != osl_File_E_None)
496 return FileHandle::errorFromNative(result);
498 m_nSize = nSize;
499 return store_E_None;
502 storeError FileLockBytes::flush_Impl()
504 oslFileError result = osl_syncFile (m_hFile);
505 if (result != osl_File_E_None)
506 return FileHandle::errorFromNative(result);
507 return store_E_None;
510 /*========================================================================
512 * MappedLockBytes implementation.
514 *======================================================================*/
515 namespace store
518 struct FileMapping
520 sal_uInt8 * m_pAddr;
521 sal_uInt32 m_nSize;
523 FileMapping() : m_pAddr(0), m_nSize(0) {}
525 bool operator != (FileMapping const & rhs) const
527 return ((m_pAddr != rhs.m_pAddr) || (m_nSize != rhs.m_nSize));
530 oslFileError initialize (oslFileHandle hFile)
532 // Determine mapping size.
533 sal_uInt64 uSize = 0;
534 oslFileError result = osl_getFileSize (hFile, &uSize);
535 if (result != osl_File_E_None)
536 return result;
538 // [SECURITY:IntOver]
539 if (uSize > SAL_MAX_UINT32)
540 return osl_File_E_OVERFLOW;
541 m_nSize = sal::static_int_cast<sal_uInt32>(uSize);
543 // Acquire mapping.
544 return osl_mapFile (hFile, reinterpret_cast<void**>(&m_pAddr), m_nSize, 0, osl_File_MapFlag_RandomAccess);
547 /** @see MappedLockBytes::destructor.
549 static void unmapFile (sal_uInt8 * pAddr, sal_uInt32 nSize)
551 (void) osl_unmapFile (pAddr, nSize);
554 /** @see ResourceHolder<T>::destructor_type
556 struct UnmapFile
558 void operator ()(FileMapping & rMapping) const
560 // Release mapping.
561 unmapFile (rMapping.m_pAddr, rMapping.m_nSize);
562 rMapping.m_pAddr = 0, rMapping.m_nSize = 0;
565 typedef UnmapFile destructor_type;
568 class MappedLockBytes :
569 public store::OStoreObject,
570 public store::PageData::Allocator,
571 public store::ILockBytes
573 /** Representation.
575 sal_uInt8 * m_pData;
576 sal_uInt32 m_nSize;
577 sal_uInt16 m_nPageSize;
579 /** PageData::Allocator implementation.
581 virtual void allocate_Impl (void ** ppPage, sal_uInt16 * pnSize);
582 virtual void deallocate_Impl (void * pPage);
584 /** ILockBytes implementation.
586 virtual storeError initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize);
588 virtual storeError readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset);
589 virtual storeError writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset);
591 virtual storeError readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes);
592 virtual storeError writeAt_Impl (sal_uInt32 nOffset, const void * pBuffer, sal_uInt32 nBytes);
594 virtual storeError getSize_Impl (sal_uInt32 & rnSize);
595 virtual storeError setSize_Impl (sal_uInt32 nSize);
597 virtual storeError flush_Impl();
599 /** Not implemented.
601 MappedLockBytes (MappedLockBytes const &);
602 MappedLockBytes & operator= (MappedLockBytes const &);
604 public:
605 /** Construction.
607 explicit MappedLockBytes (FileMapping & rMapping);
609 /** Delegate multiple inherited IReference.
611 virtual oslInterlockedCount SAL_CALL acquire();
612 virtual oslInterlockedCount SAL_CALL release();
614 protected:
615 /* Destruction.
617 virtual ~MappedLockBytes();
620 } // namespace store
622 MappedLockBytes::MappedLockBytes (FileMapping & rMapping)
623 : m_pData (rMapping.m_pAddr), m_nSize (rMapping.m_nSize), m_nPageSize(0)
627 MappedLockBytes::~MappedLockBytes()
629 FileMapping::unmapFile (m_pData, m_nSize);
632 oslInterlockedCount SAL_CALL MappedLockBytes::acquire()
634 return OStoreObject::acquire();
637 oslInterlockedCount SAL_CALL MappedLockBytes::release()
639 return OStoreObject::release();
642 void MappedLockBytes::allocate_Impl (void ** ppPage, sal_uInt16 * pnSize)
644 OSL_PRECOND((ppPage != 0) && (pnSize != 0), "contract violation");
645 *ppPage = 0, *pnSize = m_nPageSize;
648 void MappedLockBytes::deallocate_Impl (void * pPage)
650 OSL_PRECOND((m_pData <= pPage) && (pPage < m_pData + m_nSize), "contract violation");
651 (void)pPage; // UNUSED
654 storeError MappedLockBytes::initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize)
656 rxAllocator = this;
657 m_nPageSize = nPageSize;
658 return store_E_None;
661 storeError MappedLockBytes::readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset)
663 sal_uInt8 * src_lo = m_pData + nOffset;
664 if ((m_pData > src_lo) || (src_lo >= m_pData + m_nSize))
665 return store_E_NotExists;
667 sal_uInt8 * src_hi = src_lo + m_nPageSize;
668 if ((m_pData > src_hi) || (src_hi > m_pData + m_nSize))
669 return store_E_CantRead;
671 PageHolder page (reinterpret_cast< PageData* >(src_lo), static_cast< PageData::Allocator* >(this));
672 page.swap (rPage);
674 return store_E_None;
677 storeError MappedLockBytes::writePageAt_Impl (PageHolder const & /*rPage*/, sal_uInt32 /*nOffset*/)
679 return store_E_AccessViolation;
682 storeError MappedLockBytes::readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes)
684 sal_uInt8 const * src_lo = m_pData + nOffset;
685 if ((m_pData > src_lo) || (src_lo >= m_pData + m_nSize))
686 return store_E_NotExists;
688 sal_uInt8 const * src_hi = src_lo + nBytes;
689 if ((m_pData > src_hi) || (src_hi > m_pData + m_nSize))
690 return store_E_CantRead;
692 memcpy (pBuffer, src_lo, (src_hi - src_lo));
693 return store_E_None;
696 storeError MappedLockBytes::writeAt_Impl (sal_uInt32 /*nOffset*/, void const * /*pBuffer*/, sal_uInt32 /*nBytes*/)
698 return store_E_AccessViolation;
701 storeError MappedLockBytes::getSize_Impl (sal_uInt32 & rnSize)
703 rnSize = m_nSize;
704 return store_E_None;
707 storeError MappedLockBytes::setSize_Impl (sal_uInt32 /*nSize*/)
709 return store_E_AccessViolation;
712 storeError MappedLockBytes::flush_Impl()
714 return store_E_None;
717 /*========================================================================
719 * MemoryLockBytes implementation.
721 *======================================================================*/
722 namespace store
725 class MemoryLockBytes :
726 public store::OStoreObject,
727 public store::ILockBytes
729 /** Representation.
731 sal_uInt8 * m_pData;
732 sal_uInt32 m_nSize;
733 rtl::Reference< PageData::Allocator > m_xAllocator;
735 /** ILockBytes implementation.
737 virtual storeError initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize);
739 virtual storeError readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset);
740 virtual storeError writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset);
742 virtual storeError readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes);
743 virtual storeError writeAt_Impl (sal_uInt32 nOffset, const void * pBuffer, sal_uInt32 nBytes);
745 virtual storeError getSize_Impl (sal_uInt32 & rnSize);
746 virtual storeError setSize_Impl (sal_uInt32 nSize);
748 virtual storeError flush_Impl();
750 /** Not implemented.
752 MemoryLockBytes (MemoryLockBytes const &);
753 MemoryLockBytes& operator= (MemoryLockBytes const &);
755 public:
756 /** Construction.
758 MemoryLockBytes();
760 /** Delegate multiple inherited IReference.
762 virtual oslInterlockedCount SAL_CALL acquire();
763 virtual oslInterlockedCount SAL_CALL release();
765 protected:
766 /** Destruction.
768 virtual ~MemoryLockBytes();
771 } // namespace store
773 MemoryLockBytes::MemoryLockBytes()
774 : m_pData (0), m_nSize (0), m_xAllocator()
777 MemoryLockBytes::~MemoryLockBytes()
779 rtl_freeMemory (m_pData);
782 oslInterlockedCount SAL_CALL MemoryLockBytes::acquire (void)
784 return OStoreObject::acquire();
787 oslInterlockedCount SAL_CALL MemoryLockBytes::release (void)
789 return OStoreObject::release();
792 storeError MemoryLockBytes::initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize)
794 storeError result = PageData::Allocator::createInstance (rxAllocator, nPageSize);
795 if (result == store_E_None)
797 // @see readPageAt_Impl().
798 m_xAllocator = rxAllocator;
800 return result;
803 storeError MemoryLockBytes::readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset)
805 if (m_xAllocator.is())
807 PageHolder page (m_xAllocator->construct<PageData>(), m_xAllocator);
808 page.swap (rPage);
811 if (!m_xAllocator.is())
812 return store_E_InvalidAccess;
813 if (!rPage.get())
814 return store_E_OutOfMemory;
816 PageData * pagedata = rPage.get();
817 return readAt_Impl (nOffset, pagedata, pagedata->size());
820 storeError MemoryLockBytes::writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset)
822 PageData const * pagedata = rPage.get();
823 OSL_PRECOND(!(pagedata == 0), "contract violation");
824 return writeAt_Impl (nOffset, pagedata, pagedata->size());
827 storeError MemoryLockBytes::readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes)
829 sal_uInt8 const * src_lo = m_pData + nOffset;
830 if ((m_pData > src_lo) || (src_lo >= m_pData + m_nSize))
831 return store_E_NotExists;
833 sal_uInt8 const * src_hi = src_lo + nBytes;
834 if ((m_pData > src_hi) || (src_hi > m_pData + m_nSize))
835 return store_E_CantRead;
837 memcpy (pBuffer, src_lo, (src_hi - src_lo));
838 return store_E_None;
841 storeError MemoryLockBytes::writeAt_Impl (sal_uInt32 nOffset, const void * pBuffer, sal_uInt32 nBytes)
843 sal_uInt64 const dst_size = nOffset + nBytes;
844 OSL_PRECOND(dst_size < SAL_MAX_UINT32, "store::ILockBytes::writeAt() contract violation");
845 if (dst_size > m_nSize)
847 storeError eErrCode = setSize_Impl (sal::static_int_cast<sal_uInt32>(dst_size));
848 if (eErrCode != store_E_None)
849 return eErrCode;
851 OSL_POSTCOND(dst_size <= m_nSize, "store::MemoryLockBytes::setSize_Impl() contract violation");
853 sal_uInt8 * dst_lo = m_pData + nOffset;
854 if (dst_lo >= m_pData + m_nSize)
855 return store_E_CantSeek;
857 sal_uInt8 * dst_hi = dst_lo + nBytes;
858 if (dst_hi > m_pData + m_nSize)
859 return store_E_CantWrite;
861 memcpy (dst_lo, pBuffer, (dst_hi - dst_lo));
862 return store_E_None;
865 storeError MemoryLockBytes::getSize_Impl (sal_uInt32 & rnSize)
867 rnSize = m_nSize;
868 return store_E_None;
871 storeError MemoryLockBytes::setSize_Impl (sal_uInt32 nSize)
873 if (nSize != m_nSize)
875 sal_uInt8 * pData = reinterpret_cast<sal_uInt8*>(rtl_reallocateMemory (m_pData, nSize));
876 if (pData != 0)
878 if (nSize > m_nSize)
879 memset (pData + m_nSize, 0, sal::static_int_cast<size_t>(nSize - m_nSize));
881 else
883 if (nSize != 0)
884 return store_E_OutOfMemory;
886 m_pData = pData, m_nSize = nSize;
888 return store_E_None;
891 storeError MemoryLockBytes::flush_Impl()
893 return store_E_None;
896 /*========================================================================
898 * ILockBytes factory implementations.
900 *======================================================================*/
901 namespace store
904 template< class T > struct ResourceHolder
906 typedef typename T::destructor_type destructor_type;
908 T m_value;
910 explicit ResourceHolder (T const & value = T()) : m_value (value) {}
911 ~ResourceHolder() { reset(); }
913 T & get() { return m_value; }
914 T const & get() const { return m_value; }
916 void set (T const & value) { m_value = value; }
917 void reset (T const & value = T())
919 T tmp (m_value);
920 if (tmp != value)
921 destructor_type()(tmp);
922 set (value);
924 T release()
926 T tmp (m_value);
927 set (T());
928 return tmp;
931 ResourceHolder (ResourceHolder & rhs)
933 set (rhs.release());
935 ResourceHolder & operator= (ResourceHolder & rhs)
937 reset (rhs.release());
938 return *this;
942 storeError
943 FileLockBytes_createInstance (
944 rtl::Reference< ILockBytes > & rxLockBytes,
945 rtl_uString * pFilename,
946 storeAccessMode eAccessMode
949 // Acquire file handle.
950 ResourceHolder<FileHandle> xFile;
951 storeError result = xFile.get().initialize (pFilename, eAccessMode);
952 if (result != store_E_None)
953 return (result);
955 if (eAccessMode == store_AccessReadOnly)
957 ResourceHolder<FileMapping> xMapping;
958 if (xMapping.get().initialize (xFile.get().m_handle) == osl_File_E_None)
960 rxLockBytes = new MappedLockBytes (xMapping.get());
961 if (!rxLockBytes.is())
962 return store_E_OutOfMemory;
963 (void) xMapping.release();
966 if (!rxLockBytes.is())
968 rxLockBytes = new FileLockBytes (xFile.get());
969 if (!rxLockBytes.is())
970 return store_E_OutOfMemory;
971 (void) xFile.release();
974 return store_E_None;
977 storeError
978 MemoryLockBytes_createInstance (
979 rtl::Reference< ILockBytes > & rxLockBytes
982 rxLockBytes = new MemoryLockBytes();
983 if (!rxLockBytes.is())
984 return store_E_OutOfMemory;
986 return store_E_None;
989 } // namespace store