update credits
[LibreOffice.git] / store / source / lockbyte.cxx
blob2c322bacc6d4c7a9f0964fcdd61c173a4bbd9552
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 .
21 #include "lockbyte.hxx"
23 #include "sal/types.h"
24 #include "osl/diagnose.h"
25 #include "osl/file.h"
26 #include "osl/process.h"
27 #include "rtl/alloc.h"
28 #include "rtl/ustring.hxx"
30 #include "object.hxx"
31 #include "storbase.hxx"
33 #include <string.h>
35 using namespace store;
37 /*========================================================================
39 * ILockBytes (non-virtual interface) implementation.
41 *======================================================================*/
43 storeError ILockBytes::initialize (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize)
45 OSL_PRECOND((STORE_MINIMUM_PAGESIZE <= nPageSize) && (nPageSize <= STORE_MAXIMUM_PAGESIZE), "invalid PageSize");
46 return initialize_Impl (rxAllocator, nPageSize);
49 storeError ILockBytes::readPageAt (PageHolder & rPage, sal_uInt32 nOffset)
51 OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::ILockBytes::readPageAt(): invalid Offset");
52 if (nOffset == STORE_PAGE_NULL)
53 return store_E_CantSeek;
55 return readPageAt_Impl (rPage, nOffset);
58 storeError ILockBytes::writePageAt (PageHolder const & rPage, sal_uInt32 nOffset)
60 // [SECURITY:ValInput]
61 PageData const * pagedata = rPage.get();
62 OSL_PRECOND(!(pagedata == 0), "store::ILockBytes::writePageAt(): invalid Page");
63 if (pagedata == 0)
64 return store_E_InvalidParameter;
66 sal_uInt32 const offset = pagedata->location();
67 OSL_PRECOND(!(nOffset != offset), "store::ILockBytes::writePageAt(): inconsistent Offset");
68 if (nOffset != offset)
69 return store_E_InvalidParameter;
71 OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::ILockBytes::writePageAt(): invalid Offset");
72 if (nOffset == STORE_PAGE_NULL)
73 return store_E_CantSeek;
75 return writePageAt_Impl (rPage, nOffset);
78 storeError ILockBytes::readAt (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes)
80 // [SECURITY:ValInput]
81 sal_uInt8 * dst_lo = static_cast<sal_uInt8*>(pBuffer);
82 if (!(dst_lo != 0))
83 return store_E_InvalidParameter;
85 sal_uInt8 * dst_hi = dst_lo + nBytes;
86 if (!(dst_lo < dst_hi))
87 return (dst_lo > dst_hi) ? store_E_InvalidParameter : store_E_None;
89 OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::ILockBytes::readAt(): invalid Offset");
90 if (nOffset == STORE_PAGE_NULL)
91 return store_E_CantSeek;
93 sal_uInt64 const src_size = nOffset + nBytes;
94 if (src_size > SAL_MAX_UINT32)
95 return store_E_CantSeek;
97 return readAt_Impl (nOffset, dst_lo, (dst_hi - dst_lo));
100 storeError ILockBytes::writeAt (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes)
102 // [SECURITY:ValInput]
103 sal_uInt8 const * src_lo = static_cast<sal_uInt8 const*>(pBuffer);
104 if (!(src_lo != 0))
105 return store_E_InvalidParameter;
107 sal_uInt8 const * src_hi = src_lo + nBytes;
108 if (!(src_lo < src_hi))
109 return (src_lo > src_hi) ? store_E_InvalidParameter : store_E_None;
111 OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::ILockBytes::writeAt(): invalid Offset");
112 if (nOffset == STORE_PAGE_NULL)
113 return store_E_CantSeek;
115 sal_uInt64 const dst_size = nOffset + nBytes;
116 if (dst_size > SAL_MAX_UINT32)
117 return store_E_CantSeek;
119 return writeAt_Impl (nOffset, src_lo, (src_hi - src_lo));
122 storeError ILockBytes::getSize (sal_uInt32 & rnSize)
124 rnSize = 0;
125 return getSize_Impl (rnSize);
128 storeError ILockBytes::setSize (sal_uInt32 nSize)
130 return setSize_Impl (nSize);
133 storeError ILockBytes::flush()
135 return flush_Impl();
138 /*========================================================================
140 * FileLockBytes implementation.
142 *======================================================================*/
143 namespace store
146 struct FileHandle
148 oslFileHandle m_handle;
150 FileHandle() : m_handle(0) {}
152 bool operator != (FileHandle const & rhs)
154 return (m_handle != rhs.m_handle);
157 static storeError errorFromNative (oslFileError eErrno)
159 switch (eErrno)
161 case osl_File_E_None:
162 return store_E_None;
164 case osl_File_E_NOENT:
165 return store_E_NotExists;
167 case osl_File_E_ACCES:
168 case osl_File_E_PERM:
169 return store_E_AccessViolation;
171 case osl_File_E_AGAIN:
172 case osl_File_E_DEADLK:
173 return store_E_LockingViolation;
175 case osl_File_E_BADF:
176 return store_E_InvalidHandle;
178 case osl_File_E_INVAL:
179 return store_E_InvalidParameter;
181 case osl_File_E_NOMEM:
182 return store_E_OutOfMemory;
184 case osl_File_E_NOSPC:
185 return store_E_OutOfSpace;
187 case osl_File_E_OVERFLOW:
188 return store_E_CantSeek;
190 default:
191 return store_E_Unknown;
195 static sal_uInt32 modeToNative (storeAccessMode eAccessMode)
197 sal_uInt32 nFlags = 0;
198 switch (eAccessMode)
200 case store_AccessCreate:
201 case store_AccessReadCreate:
202 nFlags |= osl_File_OpenFlag_Create;
203 // fall through
204 case store_AccessReadWrite:
205 nFlags |= osl_File_OpenFlag_Write;
206 // fall through
207 case store_AccessReadOnly:
208 nFlags |= osl_File_OpenFlag_Read;
209 break;
210 default:
211 OSL_PRECOND(0, "store::FileHandle: unknown storeAccessMode");
213 return nFlags;
216 storeError initialize (rtl_uString * pFilename, storeAccessMode eAccessMode)
218 // Verify arguments.
219 sal_uInt32 nFlags = modeToNative (eAccessMode);
220 if (!pFilename || !nFlags)
221 return store_E_InvalidParameter;
223 // Convert into FileUrl.
224 OUString aFileUrl;
225 if (osl_getFileURLFromSystemPath (pFilename, &(aFileUrl.pData)) != osl_File_E_None)
227 // Not system path. Assume file url.
228 rtl_uString_assign (&(aFileUrl.pData), pFilename);
230 if (!aFileUrl.startsWith("file://"))
232 // Not file url. Assume relative path.
233 OUString aCwdUrl;
234 (void) osl_getProcessWorkingDir (&(aCwdUrl.pData));
236 // Absolute file url.
237 (void) osl_getAbsoluteFileURL (aCwdUrl.pData, aFileUrl.pData, &(aFileUrl.pData));
240 // Acquire handle.
241 oslFileError result = osl_openFile (aFileUrl.pData, &m_handle, nFlags);
242 if (result == osl_File_E_EXIST)
244 // Already existing (O_CREAT | O_EXCL).
245 result = osl_openFile (aFileUrl.pData, &m_handle, osl_File_OpenFlag_Read | osl_File_OpenFlag_Write);
246 if ((result == osl_File_E_None) && (eAccessMode == store_AccessCreate))
248 // Truncate existing file.
249 result = osl_setFileSize (m_handle, 0);
252 if (result != osl_File_E_None)
253 return errorFromNative(result);
254 return store_E_None;
257 /** @see FileLockBytes destructor
259 static void closeFile (oslFileHandle hFile)
261 (void) osl_closeFile (hFile);
264 /** @see ResourceHolder<T>::destructor_type
266 struct CloseFile
268 void operator()(FileHandle & rFile) const
270 // Release handle.
271 closeFile (rFile.m_handle);
272 rFile.m_handle = 0;
275 typedef CloseFile destructor_type;
278 class FileLockBytes :
279 public store::OStoreObject,
280 public store::ILockBytes
282 /** Representation.
284 oslFileHandle m_hFile;
285 sal_uInt32 m_nSize;
286 rtl::Reference< PageData::Allocator > m_xAllocator;
288 storeError initSize_Impl (sal_uInt32 & rnSize);
290 /** ILockBytes implementation.
292 virtual storeError initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize);
294 virtual storeError readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset);
295 virtual storeError writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset);
297 virtual storeError readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes);
298 virtual storeError writeAt_Impl (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes);
300 virtual storeError getSize_Impl (sal_uInt32 & rnSize);
301 virtual storeError setSize_Impl (sal_uInt32 nSize);
303 virtual storeError flush_Impl();
305 /** Not implemented.
307 FileLockBytes (FileLockBytes const &);
308 FileLockBytes & operator= (FileLockBytes const &);
310 public:
311 /** Construction.
313 explicit FileLockBytes (FileHandle & rFile);
315 /** Delegate multiple inherited IReference.
317 virtual oslInterlockedCount SAL_CALL acquire();
318 virtual oslInterlockedCount SAL_CALL release();
320 protected:
321 /** Destruction.
323 virtual ~FileLockBytes();
326 } // namespace store
328 FileLockBytes::FileLockBytes (FileHandle & rFile)
329 : m_hFile (rFile.m_handle), m_nSize (SAL_MAX_UINT32), m_xAllocator()
333 FileLockBytes::~FileLockBytes()
335 FileHandle::closeFile (m_hFile);
338 oslInterlockedCount SAL_CALL FileLockBytes::acquire()
340 return OStoreObject::acquire();
343 oslInterlockedCount SAL_CALL FileLockBytes::release()
345 return OStoreObject::release();
348 storeError FileLockBytes::initSize_Impl (sal_uInt32 & rnSize)
350 /* osl_getFileSize() uses slow 'fstat(h, &size)',
351 * instead of fast 'size = lseek(h, 0, SEEK_END)'.
352 * so, init size here, and track changes.
354 sal_uInt64 uSize = 0;
355 oslFileError result = osl_getFileSize (m_hFile, &uSize);
356 if (result != osl_File_E_None)
357 return FileHandle::errorFromNative(result);
358 if (uSize > SAL_MAX_UINT32)
359 return store_E_CantSeek;
361 rnSize = sal::static_int_cast<sal_uInt32>(uSize);
362 return store_E_None;
365 storeError FileLockBytes::initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize)
367 storeError result = initSize_Impl (m_nSize);
368 if (result != store_E_None)
369 return (result);
371 result = PageData::Allocator::createInstance (rxAllocator, nPageSize);
372 if (result != store_E_None)
373 return (result);
375 // @see readPageAt_Impl().
376 m_xAllocator = rxAllocator;
377 return store_E_None;
380 storeError FileLockBytes::readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset)
382 if (m_xAllocator.is())
384 PageHolder page (m_xAllocator->construct<PageData>(), m_xAllocator);
385 page.swap (rPage);
388 if (!m_xAllocator.is())
389 return store_E_InvalidAccess;
390 if (!rPage.get())
391 return store_E_OutOfMemory;
393 PageData * pagedata = rPage.get();
394 return readAt_Impl (nOffset, pagedata, pagedata->size());
397 storeError FileLockBytes::writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset)
399 PageData const * pagedata = rPage.get();
400 OSL_PRECOND(pagedata != 0, "contract violation");
401 return writeAt_Impl (nOffset, pagedata, pagedata->size());
404 storeError FileLockBytes::readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes)
406 sal_uInt64 nDone = 0;
407 oslFileError result = osl_readFileAt (m_hFile, nOffset, pBuffer, nBytes, &nDone);
408 if (result != osl_File_E_None)
409 return FileHandle::errorFromNative(result);
410 if (nDone != nBytes)
411 return (nDone != 0) ? store_E_CantRead : store_E_NotExists;
412 return store_E_None;
415 storeError FileLockBytes::writeAt_Impl (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes)
417 sal_uInt64 nDone = 0;
418 oslFileError result = osl_writeFileAt (m_hFile, nOffset, pBuffer, nBytes, &nDone);
419 if (result != osl_File_E_None)
420 return FileHandle::errorFromNative(result);
421 if (nDone != nBytes)
422 return store_E_CantWrite;
424 sal_uInt64 const uSize = nOffset + nBytes;
425 OSL_PRECOND(uSize < SAL_MAX_UINT32, "store::ILockBytes::writeAt() contract violation");
426 if (uSize > m_nSize)
427 m_nSize = sal::static_int_cast<sal_uInt32>(uSize);
428 return store_E_None;
431 storeError FileLockBytes::getSize_Impl (sal_uInt32 & rnSize)
433 rnSize = m_nSize;
434 return store_E_None;
437 storeError FileLockBytes::setSize_Impl (sal_uInt32 nSize)
439 oslFileError result = osl_setFileSize (m_hFile, nSize);
440 if (result != osl_File_E_None)
441 return FileHandle::errorFromNative(result);
443 m_nSize = nSize;
444 return store_E_None;
447 storeError FileLockBytes::flush_Impl()
449 oslFileError result = osl_syncFile (m_hFile);
450 if (result != osl_File_E_None)
451 return FileHandle::errorFromNative(result);
452 return store_E_None;
455 /*========================================================================
457 * MappedLockBytes implementation.
459 *======================================================================*/
460 namespace store
463 struct FileMapping
465 sal_uInt8 * m_pAddr;
466 sal_uInt32 m_nSize;
467 oslFileHandle m_hFile;
469 FileMapping() : m_pAddr(0), m_nSize(0), m_hFile(0) {}
471 bool operator != (FileMapping const & rhs) const
473 return ((m_pAddr != rhs.m_pAddr) || (m_nSize != rhs.m_nSize));
476 oslFileError initialize (oslFileHandle hFile)
478 // Determine mapping size.
479 sal_uInt64 uSize = 0;
480 oslFileError result = osl_getFileSize (hFile, &uSize);
481 if (result != osl_File_E_None)
482 return result;
484 // [SECURITY:IntOver]
485 if (uSize > SAL_MAX_UINT32)
486 return osl_File_E_OVERFLOW;
487 m_nSize = sal::static_int_cast<sal_uInt32>(uSize);
489 m_hFile = hFile;
491 // Acquire mapping.
492 return osl_mapFile (hFile, reinterpret_cast<void**>(&m_pAddr), m_nSize, 0, osl_File_MapFlag_RandomAccess);
495 /** @see MappedLockBytes::destructor.
497 static void unmapFile (oslFileHandle hFile, sal_uInt8 * pAddr, sal_uInt32 nSize)
499 (void) osl_unmapMappedFile (hFile, pAddr, nSize);
500 (void) osl_closeFile (hFile);
503 /** @see ResourceHolder<T>::destructor_type
505 struct UnmapFile
507 void operator ()(FileMapping & rMapping) const
509 // Release mapping.
510 unmapFile (rMapping.m_hFile, rMapping.m_pAddr, rMapping.m_nSize);
511 rMapping.m_pAddr = 0, rMapping.m_nSize = 0;
514 typedef UnmapFile destructor_type;
517 class MappedLockBytes :
518 public store::OStoreObject,
519 public store::PageData::Allocator,
520 public store::ILockBytes
522 /** Representation.
524 sal_uInt8 * m_pData;
525 sal_uInt32 m_nSize;
526 sal_uInt16 m_nPageSize;
527 oslFileHandle m_hFile;
529 /** PageData::Allocator implementation.
531 virtual void allocate_Impl (void ** ppPage, sal_uInt16 * pnSize);
532 virtual void deallocate_Impl (void * pPage);
534 /** ILockBytes implementation.
536 virtual storeError initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize);
538 virtual storeError readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset);
539 virtual storeError writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset);
541 virtual storeError readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes);
542 virtual storeError writeAt_Impl (sal_uInt32 nOffset, const void * pBuffer, sal_uInt32 nBytes);
544 virtual storeError getSize_Impl (sal_uInt32 & rnSize);
545 virtual storeError setSize_Impl (sal_uInt32 nSize);
547 virtual storeError flush_Impl();
549 /** Not implemented.
551 MappedLockBytes (MappedLockBytes const &);
552 MappedLockBytes & operator= (MappedLockBytes const &);
554 public:
555 /** Construction.
557 explicit MappedLockBytes (FileMapping & rMapping);
559 /** Delegate multiple inherited IReference.
561 virtual oslInterlockedCount SAL_CALL acquire();
562 virtual oslInterlockedCount SAL_CALL release();
564 protected:
565 /* Destruction.
567 virtual ~MappedLockBytes();
570 } // namespace store
572 MappedLockBytes::MappedLockBytes (FileMapping & rMapping)
573 : m_pData (rMapping.m_pAddr), m_nSize (rMapping.m_nSize), m_nPageSize(0), m_hFile (rMapping.m_hFile)
577 MappedLockBytes::~MappedLockBytes()
579 FileMapping::unmapFile (m_hFile, m_pData, m_nSize);
582 oslInterlockedCount SAL_CALL MappedLockBytes::acquire()
584 return OStoreObject::acquire();
587 oslInterlockedCount SAL_CALL MappedLockBytes::release()
589 return OStoreObject::release();
592 void MappedLockBytes::allocate_Impl (void ** ppPage, sal_uInt16 * pnSize)
594 OSL_PRECOND((ppPage != 0) && (pnSize != 0), "contract violation");
595 if ((ppPage != 0) && (pnSize != 0))
596 *ppPage = 0, *pnSize = m_nPageSize;
599 void MappedLockBytes::deallocate_Impl (void * pPage)
601 OSL_PRECOND((m_pData <= pPage) && (pPage < m_pData + m_nSize), "contract violation");
602 (void)pPage; // UNUSED
605 storeError MappedLockBytes::initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize)
607 rxAllocator = this;
608 m_nPageSize = nPageSize;
609 return store_E_None;
612 storeError MappedLockBytes::readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset)
614 sal_uInt8 * src_lo = m_pData + nOffset;
615 if ((m_pData > src_lo) || (src_lo >= m_pData + m_nSize))
616 return store_E_NotExists;
618 sal_uInt8 * src_hi = src_lo + m_nPageSize;
619 if ((m_pData > src_hi) || (src_hi > m_pData + m_nSize))
620 return store_E_CantRead;
622 PageHolder page (reinterpret_cast< PageData* >(src_lo), static_cast< PageData::Allocator* >(this));
623 page.swap (rPage);
625 return store_E_None;
628 storeError MappedLockBytes::writePageAt_Impl (PageHolder const & /*rPage*/, sal_uInt32 /*nOffset*/)
630 return store_E_AccessViolation;
633 storeError MappedLockBytes::readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes)
635 sal_uInt8 const * src_lo = m_pData + nOffset;
636 if ((m_pData > src_lo) || (src_lo >= m_pData + m_nSize))
637 return store_E_NotExists;
639 sal_uInt8 const * src_hi = src_lo + nBytes;
640 if ((m_pData > src_hi) || (src_hi > m_pData + m_nSize))
641 return store_E_CantRead;
643 memcpy (pBuffer, src_lo, (src_hi - src_lo));
644 return store_E_None;
647 storeError MappedLockBytes::writeAt_Impl (sal_uInt32 /*nOffset*/, void const * /*pBuffer*/, sal_uInt32 /*nBytes*/)
649 return store_E_AccessViolation;
652 storeError MappedLockBytes::getSize_Impl (sal_uInt32 & rnSize)
654 rnSize = m_nSize;
655 return store_E_None;
658 storeError MappedLockBytes::setSize_Impl (sal_uInt32 /*nSize*/)
660 return store_E_AccessViolation;
663 storeError MappedLockBytes::flush_Impl()
665 return store_E_None;
668 /*========================================================================
670 * MemoryLockBytes implementation.
672 *======================================================================*/
673 namespace store
676 class MemoryLockBytes :
677 public store::OStoreObject,
678 public store::ILockBytes
680 /** Representation.
682 sal_uInt8 * m_pData;
683 sal_uInt32 m_nSize;
684 rtl::Reference< PageData::Allocator > m_xAllocator;
686 /** ILockBytes implementation.
688 virtual storeError initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize);
690 virtual storeError readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset);
691 virtual storeError writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset);
693 virtual storeError readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes);
694 virtual storeError writeAt_Impl (sal_uInt32 nOffset, const void * pBuffer, sal_uInt32 nBytes);
696 virtual storeError getSize_Impl (sal_uInt32 & rnSize);
697 virtual storeError setSize_Impl (sal_uInt32 nSize);
699 virtual storeError flush_Impl();
701 /** Not implemented.
703 MemoryLockBytes (MemoryLockBytes const &);
704 MemoryLockBytes& operator= (MemoryLockBytes const &);
706 public:
707 /** Construction.
709 MemoryLockBytes();
711 /** Delegate multiple inherited IReference.
713 virtual oslInterlockedCount SAL_CALL acquire();
714 virtual oslInterlockedCount SAL_CALL release();
716 protected:
717 /** Destruction.
719 virtual ~MemoryLockBytes();
722 } // namespace store
724 MemoryLockBytes::MemoryLockBytes()
725 : m_pData (0), m_nSize (0), m_xAllocator()
728 MemoryLockBytes::~MemoryLockBytes()
730 rtl_freeMemory (m_pData);
733 oslInterlockedCount SAL_CALL MemoryLockBytes::acquire (void)
735 return OStoreObject::acquire();
738 oslInterlockedCount SAL_CALL MemoryLockBytes::release (void)
740 return OStoreObject::release();
743 storeError MemoryLockBytes::initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize)
745 storeError result = PageData::Allocator::createInstance (rxAllocator, nPageSize);
746 if (result == store_E_None)
748 // @see readPageAt_Impl().
749 m_xAllocator = rxAllocator;
751 return result;
754 storeError MemoryLockBytes::readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset)
756 if (m_xAllocator.is())
758 PageHolder page (m_xAllocator->construct<PageData>(), m_xAllocator);
759 page.swap (rPage);
762 if (!m_xAllocator.is())
763 return store_E_InvalidAccess;
764 if (!rPage.get())
765 return store_E_OutOfMemory;
767 PageData * pagedata = rPage.get();
768 return readAt_Impl (nOffset, pagedata, pagedata->size());
771 storeError MemoryLockBytes::writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset)
773 PageData const * pagedata = rPage.get();
774 OSL_PRECOND(!(pagedata == 0), "contract violation");
775 return writeAt_Impl (nOffset, pagedata, pagedata->size());
778 storeError MemoryLockBytes::readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes)
780 sal_uInt8 const * src_lo = m_pData + nOffset;
781 if ((m_pData > src_lo) || (src_lo >= m_pData + m_nSize))
782 return store_E_NotExists;
784 sal_uInt8 const * src_hi = src_lo + nBytes;
785 if ((m_pData > src_hi) || (src_hi > m_pData + m_nSize))
786 return store_E_CantRead;
788 memcpy (pBuffer, src_lo, (src_hi - src_lo));
789 return store_E_None;
792 storeError MemoryLockBytes::writeAt_Impl (sal_uInt32 nOffset, const void * pBuffer, sal_uInt32 nBytes)
794 sal_uInt64 const dst_size = nOffset + nBytes;
795 OSL_PRECOND(dst_size < SAL_MAX_UINT32, "store::ILockBytes::writeAt() contract violation");
796 if (dst_size > m_nSize)
798 storeError eErrCode = setSize_Impl (sal::static_int_cast<sal_uInt32>(dst_size));
799 if (eErrCode != store_E_None)
800 return eErrCode;
802 OSL_POSTCOND(dst_size <= m_nSize, "store::MemoryLockBytes::setSize_Impl() contract violation");
804 sal_uInt8 * dst_lo = m_pData + nOffset;
805 if (dst_lo >= m_pData + m_nSize)
806 return store_E_CantSeek;
808 sal_uInt8 * dst_hi = dst_lo + nBytes;
809 if (dst_hi > m_pData + m_nSize)
810 return store_E_CantWrite;
812 memcpy (dst_lo, pBuffer, (dst_hi - dst_lo));
813 return store_E_None;
816 storeError MemoryLockBytes::getSize_Impl (sal_uInt32 & rnSize)
818 rnSize = m_nSize;
819 return store_E_None;
822 storeError MemoryLockBytes::setSize_Impl (sal_uInt32 nSize)
824 if (nSize != m_nSize)
826 sal_uInt8 * pData = reinterpret_cast<sal_uInt8*>(rtl_reallocateMemory (m_pData, nSize));
827 if (pData != 0)
829 if (nSize > m_nSize)
830 memset (pData + m_nSize, 0, sal::static_int_cast<size_t>(nSize - m_nSize));
832 else
834 if (nSize != 0)
835 return store_E_OutOfMemory;
837 m_pData = pData, m_nSize = nSize;
839 return store_E_None;
842 storeError MemoryLockBytes::flush_Impl()
844 return store_E_None;
847 /*========================================================================
849 * ILockBytes factory implementations.
851 *======================================================================*/
852 namespace store
855 template< class T > struct ResourceHolder
857 typedef typename T::destructor_type destructor_type;
859 T m_value;
861 explicit ResourceHolder (T const & value = T()) : m_value (value) {}
862 ~ResourceHolder() { reset(); }
864 T & get() { return m_value; }
865 T const & get() const { return m_value; }
867 void set (T const & value) { m_value = value; }
868 void reset (T const & value = T())
870 T tmp (m_value);
871 if (tmp != value)
872 destructor_type()(tmp);
873 set (value);
875 T release()
877 T tmp (m_value);
878 set (T());
879 return tmp;
882 ResourceHolder (ResourceHolder & rhs)
884 set (rhs.release());
886 ResourceHolder & operator= (ResourceHolder & rhs)
888 reset (rhs.release());
889 return *this;
893 storeError
894 FileLockBytes_createInstance (
895 rtl::Reference< ILockBytes > & rxLockBytes,
896 rtl_uString * pFilename,
897 storeAccessMode eAccessMode
900 // Acquire file handle.
901 ResourceHolder<FileHandle> xFile;
902 storeError result = xFile.get().initialize (pFilename, eAccessMode);
903 if (result != store_E_None)
904 return (result);
906 if (eAccessMode == store_AccessReadOnly)
908 ResourceHolder<FileMapping> xMapping;
909 if (xMapping.get().initialize (xFile.get().m_handle) == osl_File_E_None)
911 rxLockBytes = new MappedLockBytes (xMapping.get());
912 if (!rxLockBytes.is())
913 return store_E_OutOfMemory;
914 (void) xFile.release();
915 (void) xMapping.release();
918 if (!rxLockBytes.is())
920 rxLockBytes = new FileLockBytes (xFile.get());
921 if (!rxLockBytes.is())
922 return store_E_OutOfMemory;
923 (void) xFile.release();
926 return store_E_None;
929 storeError
930 MemoryLockBytes_createInstance (
931 rtl::Reference< ILockBytes > & rxLockBytes
934 rxLockBytes = new MemoryLockBytes();
935 if (!rxLockBytes.is())
936 return store_E_OutOfMemory;
938 return store_E_None;
941 } // namespace store
943 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */