Branch libreoffice-5-0-4
[LibreOffice.git] / store / source / lockbyte.cxx
blob09925400d0a5f8169a4d2802da85578f54920df3
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 "lockbyte.hxx"
22 #include "boost/noncopyable.hpp"
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"
29 #include "sal/log.hxx"
31 #include "object.hxx"
32 #include "storbase.hxx"
34 #include <string.h>
36 using namespace store;
38 /*========================================================================
40 * ILockBytes (non-virtual interface) implementation.
42 *======================================================================*/
44 storeError ILockBytes::initialize (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize)
46 OSL_PRECOND((STORE_MINIMUM_PAGESIZE <= nPageSize) && (nPageSize <= STORE_MAXIMUM_PAGESIZE), "invalid PageSize");
47 return initialize_Impl (rxAllocator, nPageSize);
50 storeError ILockBytes::readPageAt (PageHolder & rPage, sal_uInt32 nOffset)
52 OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::ILockBytes::readPageAt(): invalid Offset");
53 if (nOffset == STORE_PAGE_NULL)
54 return store_E_CantSeek;
56 return readPageAt_Impl (rPage, nOffset);
59 storeError ILockBytes::writePageAt (PageHolder const & rPage, sal_uInt32 nOffset)
61 // [SECURITY:ValInput]
62 PageData const * pagedata = rPage.get();
63 OSL_PRECOND(!(pagedata == 0), "store::ILockBytes::writePageAt(): invalid Page");
64 if (pagedata == 0)
65 return store_E_InvalidParameter;
67 sal_uInt32 const offset = pagedata->location();
68 OSL_PRECOND(!(nOffset != offset), "store::ILockBytes::writePageAt(): inconsistent Offset");
69 if (nOffset != offset)
70 return store_E_InvalidParameter;
72 OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::ILockBytes::writePageAt(): invalid Offset");
73 if (nOffset == STORE_PAGE_NULL)
74 return store_E_CantSeek;
76 return writePageAt_Impl (rPage, nOffset);
79 storeError ILockBytes::readAt (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes)
81 // [SECURITY:ValInput]
82 sal_uInt8 * dst_lo = static_cast<sal_uInt8*>(pBuffer);
83 if (!(dst_lo != 0))
84 return store_E_InvalidParameter;
86 sal_uInt8 * dst_hi = dst_lo + nBytes;
87 if (!(dst_lo < dst_hi))
88 return (dst_lo > dst_hi) ? store_E_InvalidParameter : store_E_None;
90 OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::ILockBytes::readAt(): invalid Offset");
91 if (nOffset == STORE_PAGE_NULL)
92 return store_E_CantSeek;
94 sal_uInt64 const src_size = static_cast<sal_uInt64>(nOffset) + nBytes;
95 if (src_size > SAL_MAX_UINT32)
96 return store_E_CantSeek;
98 return readAt_Impl (nOffset, dst_lo, (dst_hi - dst_lo));
101 storeError ILockBytes::writeAt (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes)
103 // [SECURITY:ValInput]
104 sal_uInt8 const * src_lo = static_cast<sal_uInt8 const*>(pBuffer);
105 if (!(src_lo != 0))
106 return store_E_InvalidParameter;
108 sal_uInt8 const * src_hi = src_lo + nBytes;
109 if (!(src_lo < src_hi))
110 return (src_lo > src_hi) ? store_E_InvalidParameter : store_E_None;
112 OSL_PRECOND(!(nOffset == STORE_PAGE_NULL), "store::ILockBytes::writeAt(): invalid Offset");
113 if (nOffset == STORE_PAGE_NULL)
114 return store_E_CantSeek;
116 sal_uInt64 const dst_size = static_cast<sal_uInt64>(nOffset) + nBytes;
117 if (dst_size > SAL_MAX_UINT32)
118 return store_E_CantSeek;
120 return writeAt_Impl (nOffset, src_lo, (src_hi - src_lo));
123 storeError ILockBytes::getSize (sal_uInt32 & rnSize)
125 rnSize = 0;
126 return getSize_Impl (rnSize);
129 storeError ILockBytes::setSize (sal_uInt32 nSize)
131 return setSize_Impl (nSize);
134 storeError ILockBytes::flush()
136 return flush_Impl();
139 /*========================================================================
141 * FileLockBytes implementation.
143 *======================================================================*/
144 namespace store
147 struct FileHandle
149 oslFileHandle m_handle;
151 FileHandle() : m_handle(0) {}
153 bool operator != (FileHandle const & rhs)
155 return (m_handle != rhs.m_handle);
158 static storeError errorFromNative (oslFileError eErrno)
160 switch (eErrno)
162 case osl_File_E_None:
163 return store_E_None;
165 case osl_File_E_NOENT:
166 return store_E_NotExists;
168 case osl_File_E_ACCES:
169 case osl_File_E_PERM:
170 return store_E_AccessViolation;
172 case osl_File_E_AGAIN:
173 case osl_File_E_DEADLK:
174 return store_E_LockingViolation;
176 case osl_File_E_BADF:
177 return store_E_InvalidHandle;
179 case osl_File_E_INVAL:
180 return store_E_InvalidParameter;
182 case osl_File_E_NOMEM:
183 return store_E_OutOfMemory;
185 case osl_File_E_NOSPC:
186 return store_E_OutOfSpace;
188 case osl_File_E_OVERFLOW:
189 return store_E_CantSeek;
191 default:
192 return store_E_Unknown;
196 static sal_uInt32 modeToNative (storeAccessMode eAccessMode)
198 sal_uInt32 nFlags = 0;
199 switch (eAccessMode)
201 case store_AccessCreate:
202 case store_AccessReadCreate:
203 nFlags |= osl_File_OpenFlag_Create;
204 // fall through
205 case store_AccessReadWrite:
206 nFlags |= osl_File_OpenFlag_Write;
207 // fall through
208 case store_AccessReadOnly:
209 nFlags |= osl_File_OpenFlag_Read;
210 break;
211 default:
212 OSL_PRECOND(false, "store::FileHandle: unknown storeAccessMode");
214 return nFlags;
217 storeError initialize (rtl_uString * pFilename, storeAccessMode eAccessMode)
219 // Verify arguments.
220 sal_uInt32 nFlags = modeToNative (eAccessMode);
221 if (!pFilename || !nFlags)
222 return store_E_InvalidParameter;
224 // Convert into FileUrl.
225 OUString aFileUrl;
226 if (osl_getFileURLFromSystemPath (pFilename, &(aFileUrl.pData)) != osl_File_E_None)
228 // Not system path. Assume file url.
229 rtl_uString_assign (&(aFileUrl.pData), pFilename);
231 if (!aFileUrl.startsWith("file://"))
233 // Not file url. Assume relative path.
234 OUString aCwdUrl;
235 (void) osl_getProcessWorkingDir (&(aCwdUrl.pData));
237 // Absolute file url.
238 (void) osl_getAbsoluteFileURL (aCwdUrl.pData, aFileUrl.pData, &(aFileUrl.pData));
241 // Acquire handle.
242 oslFileError result = osl_openFile (aFileUrl.pData, &m_handle, nFlags);
243 if (result == osl_File_E_EXIST)
245 // Already existing (O_CREAT | O_EXCL).
246 result = osl_openFile (aFileUrl.pData, &m_handle, osl_File_OpenFlag_Read | osl_File_OpenFlag_Write);
247 if ((result == osl_File_E_None) && (eAccessMode == store_AccessCreate))
249 // Truncate existing file.
250 result = osl_setFileSize (m_handle, 0);
253 if (result != osl_File_E_None)
254 return errorFromNative(result);
255 return store_E_None;
258 /** @see FileLockBytes destructor
260 static void closeFile (oslFileHandle hFile)
262 (void) osl_closeFile (hFile);
265 /** @see ResourceHolder<T>::destructor_type
267 struct CloseFile
269 void operator()(FileHandle & rFile) const
271 // Release handle.
272 closeFile (rFile.m_handle);
273 rFile.m_handle = 0;
276 typedef CloseFile destructor_type;
279 class FileLockBytes :
280 public store::OStoreObject,
281 public store::ILockBytes,
282 private boost::noncopyable
284 /** Representation.
286 oslFileHandle m_hFile;
287 sal_uInt32 m_nSize;
288 rtl::Reference< PageData::Allocator > m_xAllocator;
290 storeError initSize_Impl (sal_uInt32 & rnSize);
292 /** ILockBytes implementation.
294 virtual storeError initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize) SAL_OVERRIDE;
296 virtual storeError readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset) SAL_OVERRIDE;
297 virtual storeError writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset) SAL_OVERRIDE;
299 virtual storeError readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes) SAL_OVERRIDE;
300 virtual storeError writeAt_Impl (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes) SAL_OVERRIDE;
302 virtual storeError getSize_Impl (sal_uInt32 & rnSize) SAL_OVERRIDE;
303 virtual storeError setSize_Impl (sal_uInt32 nSize) SAL_OVERRIDE;
305 virtual storeError flush_Impl() SAL_OVERRIDE;
307 public:
308 /** Construction.
310 explicit FileLockBytes (FileHandle & rFile);
312 protected:
313 /** Destruction.
315 virtual ~FileLockBytes();
318 } // namespace store
320 FileLockBytes::FileLockBytes (FileHandle & rFile)
321 : m_hFile (rFile.m_handle), m_nSize (SAL_MAX_UINT32), m_xAllocator()
325 FileLockBytes::~FileLockBytes()
327 FileHandle::closeFile (m_hFile);
330 storeError FileLockBytes::initSize_Impl (sal_uInt32 & rnSize)
332 /* osl_getFileSize() uses slow 'fstat(h, &size)',
333 * instead of fast 'size = lseek(h, 0, SEEK_END)'.
334 * so, init size here, and track changes.
336 sal_uInt64 uSize = 0;
337 oslFileError result = osl_getFileSize (m_hFile, &uSize);
338 if (result != osl_File_E_None)
339 return FileHandle::errorFromNative(result);
340 if (uSize > SAL_MAX_UINT32)
341 return store_E_CantSeek;
343 rnSize = sal::static_int_cast<sal_uInt32>(uSize);
344 return store_E_None;
347 storeError FileLockBytes::initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize)
349 storeError result = initSize_Impl (m_nSize);
350 if (result != store_E_None)
351 return result;
353 result = PageData::Allocator::createInstance (rxAllocator, nPageSize);
354 if (result != store_E_None)
355 return result;
357 // @see readPageAt_Impl().
358 m_xAllocator = rxAllocator;
359 return store_E_None;
362 storeError FileLockBytes::readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset)
364 if (m_xAllocator.is())
366 PageHolder page (m_xAllocator->construct<PageData>(), m_xAllocator);
367 page.swap (rPage);
370 if (!m_xAllocator.is())
371 return store_E_InvalidAccess;
372 if (!rPage.get())
373 return store_E_OutOfMemory;
375 PageData * pagedata = rPage.get();
376 return readAt_Impl (nOffset, pagedata, pagedata->size());
379 storeError FileLockBytes::writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset)
381 PageData const * pagedata = rPage.get();
382 OSL_PRECOND(pagedata != 0, "contract violation");
383 return writeAt_Impl (nOffset, pagedata, pagedata->size());
386 storeError FileLockBytes::readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes)
388 sal_uInt64 nDone = 0;
389 oslFileError result = osl_readFileAt (m_hFile, nOffset, pBuffer, nBytes, &nDone);
390 if (result != osl_File_E_None)
391 return FileHandle::errorFromNative(result);
392 if (nDone != nBytes)
393 return (nDone != 0) ? store_E_CantRead : store_E_NotExists;
394 return store_E_None;
397 storeError FileLockBytes::writeAt_Impl (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes)
399 sal_uInt64 nDone = 0;
400 oslFileError result = osl_writeFileAt (m_hFile, nOffset, pBuffer, nBytes, &nDone);
401 if (result != osl_File_E_None)
402 return FileHandle::errorFromNative(result);
403 if (nDone != nBytes)
404 return store_E_CantWrite;
406 sal_uInt64 const uSize = nOffset + nBytes;
407 OSL_PRECOND(uSize < SAL_MAX_UINT32, "store::ILockBytes::writeAt() contract violation");
408 if (uSize > m_nSize)
409 m_nSize = sal::static_int_cast<sal_uInt32>(uSize);
410 return store_E_None;
413 storeError FileLockBytes::getSize_Impl (sal_uInt32 & rnSize)
415 rnSize = m_nSize;
416 return store_E_None;
419 storeError FileLockBytes::setSize_Impl (sal_uInt32 nSize)
421 oslFileError result = osl_setFileSize (m_hFile, nSize);
422 if (result != osl_File_E_None)
423 return FileHandle::errorFromNative(result);
425 m_nSize = nSize;
426 return store_E_None;
429 storeError FileLockBytes::flush_Impl()
431 oslFileError result = osl_syncFile (m_hFile);
432 if (result != osl_File_E_None)
433 return FileHandle::errorFromNative(result);
434 return store_E_None;
437 /*========================================================================
439 * MappedLockBytes implementation.
441 *======================================================================*/
442 namespace store
445 struct FileMapping
447 sal_uInt8 * m_pAddr;
448 sal_uInt32 m_nSize;
449 oslFileHandle m_hFile;
451 FileMapping() : m_pAddr(0), m_nSize(0), m_hFile(0) {}
453 bool operator != (FileMapping const & rhs) const
455 return ((m_pAddr != rhs.m_pAddr) || (m_nSize != rhs.m_nSize));
458 oslFileError initialize (oslFileHandle hFile)
460 // Determine mapping size.
461 sal_uInt64 uSize = 0;
462 oslFileError result = osl_getFileSize (hFile, &uSize);
463 if (result != osl_File_E_None)
464 return result;
466 // [SECURITY:IntOver]
467 if (uSize > SAL_MAX_UINT32)
468 return osl_File_E_OVERFLOW;
469 m_nSize = sal::static_int_cast<sal_uInt32>(uSize);
471 m_hFile = hFile;
473 // Acquire mapping.
474 return osl_mapFile (hFile, reinterpret_cast<void**>(&m_pAddr), m_nSize, 0, osl_File_MapFlag_RandomAccess);
477 /** @see MappedLockBytes::destructor.
479 static void unmapFile (oslFileHandle hFile, sal_uInt8 * pAddr, sal_uInt32 nSize)
481 (void) osl_unmapMappedFile (hFile, pAddr, nSize);
482 (void) osl_closeFile (hFile);
485 /** @see ResourceHolder<T>::destructor_type
487 struct UnmapFile
489 void operator ()(FileMapping & rMapping) const
491 // Release mapping.
492 unmapFile (rMapping.m_hFile, rMapping.m_pAddr, rMapping.m_nSize);
493 rMapping.m_pAddr = 0, rMapping.m_nSize = 0;
496 typedef UnmapFile destructor_type;
499 class MappedLockBytes :
500 public store::OStoreObject,
501 public store::PageData::Allocator,
502 public store::ILockBytes,
503 private boost::noncopyable
505 /** Representation.
507 sal_uInt8 * m_pData;
508 sal_uInt32 m_nSize;
509 sal_uInt16 m_nPageSize;
510 oslFileHandle m_hFile;
512 /** PageData::Allocator implementation.
514 virtual void allocate_Impl (void ** ppPage, sal_uInt16 * pnSize) SAL_OVERRIDE;
515 virtual void deallocate_Impl (void * pPage) SAL_OVERRIDE;
517 /** ILockBytes implementation.
519 virtual storeError initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize) SAL_OVERRIDE;
521 virtual storeError readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset) SAL_OVERRIDE;
522 virtual storeError writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset) SAL_OVERRIDE;
524 virtual storeError readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes) SAL_OVERRIDE;
525 virtual storeError writeAt_Impl (sal_uInt32 nOffset, const void * pBuffer, sal_uInt32 nBytes) SAL_OVERRIDE;
527 virtual storeError getSize_Impl (sal_uInt32 & rnSize) SAL_OVERRIDE;
528 virtual storeError setSize_Impl (sal_uInt32 nSize) SAL_OVERRIDE;
530 virtual storeError flush_Impl() SAL_OVERRIDE;
532 public:
533 /** Construction.
535 explicit MappedLockBytes (FileMapping & rMapping);
537 protected:
538 /* Destruction.
540 virtual ~MappedLockBytes();
543 } // namespace store
545 MappedLockBytes::MappedLockBytes (FileMapping & rMapping)
546 : m_pData (rMapping.m_pAddr), m_nSize (rMapping.m_nSize), m_nPageSize(0), m_hFile (rMapping.m_hFile)
550 MappedLockBytes::~MappedLockBytes()
552 FileMapping::unmapFile (m_hFile, m_pData, m_nSize);
555 void MappedLockBytes::allocate_Impl (void ** ppPage, sal_uInt16 * pnSize)
557 OSL_PRECOND((ppPage != 0) && (pnSize != 0), "contract violation");
558 if ((ppPage != 0) && (pnSize != 0))
559 *ppPage = 0, *pnSize = m_nPageSize;
562 void MappedLockBytes::deallocate_Impl (void * pPage)
564 OSL_PRECOND((m_pData <= pPage) && (pPage < m_pData + m_nSize), "contract violation");
565 (void)pPage; // UNUSED
568 storeError MappedLockBytes::initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize)
570 rxAllocator = this;
571 m_nPageSize = nPageSize;
572 return store_E_None;
575 storeError MappedLockBytes::readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset)
577 sal_uInt8 * src_lo = m_pData + nOffset;
578 if ((m_pData > src_lo) || (src_lo >= m_pData + m_nSize))
579 return store_E_NotExists;
581 sal_uInt8 * src_hi = src_lo + m_nPageSize;
582 if ((m_pData > src_hi) || (src_hi > m_pData + m_nSize))
583 return store_E_CantRead;
585 PageHolder page (reinterpret_cast< PageData* >(src_lo), static_cast< PageData::Allocator* >(this));
586 page.swap (rPage);
588 return store_E_None;
591 storeError MappedLockBytes::writePageAt_Impl (PageHolder const & /*rPage*/, sal_uInt32 /*nOffset*/)
593 return store_E_AccessViolation;
596 storeError MappedLockBytes::readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes)
598 sal_uInt8 const * src_lo = m_pData + nOffset;
599 if ((m_pData > src_lo) || (src_lo >= m_pData + m_nSize))
600 return store_E_NotExists;
602 sal_uInt8 const * src_hi = src_lo + nBytes;
603 if ((m_pData > src_hi) || (src_hi > m_pData + m_nSize))
604 return store_E_CantRead;
606 memcpy (pBuffer, src_lo, (src_hi - src_lo));
607 return store_E_None;
610 storeError MappedLockBytes::writeAt_Impl (sal_uInt32 /*nOffset*/, void const * /*pBuffer*/, sal_uInt32 /*nBytes*/)
612 return store_E_AccessViolation;
615 storeError MappedLockBytes::getSize_Impl (sal_uInt32 & rnSize)
617 rnSize = m_nSize;
618 return store_E_None;
621 storeError MappedLockBytes::setSize_Impl (sal_uInt32 /*nSize*/)
623 return store_E_AccessViolation;
626 storeError MappedLockBytes::flush_Impl()
628 return store_E_None;
631 /*========================================================================
633 * MemoryLockBytes implementation.
635 *======================================================================*/
636 namespace store
639 class MemoryLockBytes :
640 public store::OStoreObject,
641 public store::ILockBytes,
642 private boost::noncopyable
644 /** Representation.
646 sal_uInt8 * m_pData;
647 sal_uInt32 m_nSize;
648 rtl::Reference< PageData::Allocator > m_xAllocator;
650 /** ILockBytes implementation.
652 virtual storeError initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize) SAL_OVERRIDE;
654 virtual storeError readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset) SAL_OVERRIDE;
655 virtual storeError writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset) SAL_OVERRIDE;
657 virtual storeError readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes) SAL_OVERRIDE;
658 virtual storeError writeAt_Impl (sal_uInt32 nOffset, const void * pBuffer, sal_uInt32 nBytes) SAL_OVERRIDE;
660 virtual storeError getSize_Impl (sal_uInt32 & rnSize) SAL_OVERRIDE;
661 virtual storeError setSize_Impl (sal_uInt32 nSize) SAL_OVERRIDE;
663 virtual storeError flush_Impl() SAL_OVERRIDE;
665 public:
666 /** Construction.
668 MemoryLockBytes();
670 protected:
671 /** Destruction.
673 virtual ~MemoryLockBytes();
676 } // namespace store
678 MemoryLockBytes::MemoryLockBytes()
679 : m_pData (0), m_nSize (0), m_xAllocator()
682 MemoryLockBytes::~MemoryLockBytes()
684 rtl_freeMemory (m_pData);
687 storeError MemoryLockBytes::initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize)
689 storeError result = PageData::Allocator::createInstance (rxAllocator, nPageSize);
690 if (result == store_E_None)
692 // @see readPageAt_Impl().
693 m_xAllocator = rxAllocator;
695 return result;
698 storeError MemoryLockBytes::readPageAt_Impl (PageHolder & rPage, sal_uInt32 nOffset)
700 if (m_xAllocator.is())
702 PageHolder page (m_xAllocator->construct<PageData>(), m_xAllocator);
703 page.swap (rPage);
706 if (!m_xAllocator.is())
707 return store_E_InvalidAccess;
708 if (!rPage.get())
709 return store_E_OutOfMemory;
711 PageData * pagedata = rPage.get();
712 return readAt_Impl (nOffset, pagedata, pagedata->size());
715 storeError MemoryLockBytes::writePageAt_Impl (PageHolder const & rPage, sal_uInt32 nOffset)
717 PageData const * pagedata = rPage.get();
718 OSL_PRECOND(!(pagedata == 0), "contract violation");
719 return writeAt_Impl (nOffset, pagedata, pagedata->size());
722 storeError MemoryLockBytes::readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes)
724 sal_uInt8 const * src_lo = m_pData + nOffset;
725 if ((m_pData > src_lo) || (src_lo >= m_pData + m_nSize))
726 return store_E_NotExists;
728 sal_uInt8 const * src_hi = src_lo + nBytes;
729 if ((m_pData > src_hi) || (src_hi > m_pData + m_nSize))
730 return store_E_CantRead;
732 memcpy (pBuffer, src_lo, (src_hi - src_lo));
733 return store_E_None;
736 storeError MemoryLockBytes::writeAt_Impl (sal_uInt32 nOffset, const void * pBuffer, sal_uInt32 nBytes)
738 sal_uInt64 const dst_size = nOffset + nBytes;
739 OSL_PRECOND(dst_size < SAL_MAX_UINT32, "store::ILockBytes::writeAt() contract violation");
740 if (dst_size > m_nSize)
742 storeError eErrCode = setSize_Impl (sal::static_int_cast<sal_uInt32>(dst_size));
743 if (eErrCode != store_E_None)
744 return eErrCode;
746 SAL_WARN_IF(dst_size > m_nSize, "store", "store::MemoryLockBytes::setSize_Impl() contract violation");
748 sal_uInt8 * dst_lo = m_pData + nOffset;
749 if (dst_lo >= m_pData + m_nSize)
750 return store_E_CantSeek;
752 sal_uInt8 * dst_hi = dst_lo + nBytes;
753 if (dst_hi > m_pData + m_nSize)
754 return store_E_CantWrite;
756 memcpy (dst_lo, pBuffer, (dst_hi - dst_lo));
757 return store_E_None;
760 storeError MemoryLockBytes::getSize_Impl (sal_uInt32 & rnSize)
762 rnSize = m_nSize;
763 return store_E_None;
766 storeError MemoryLockBytes::setSize_Impl (sal_uInt32 nSize)
768 if (nSize != m_nSize)
770 sal_uInt8 * pData = static_cast<sal_uInt8*>(rtl_reallocateMemory (m_pData, nSize));
771 if (pData != 0)
773 if (nSize > m_nSize)
774 memset (pData + m_nSize, 0, sal::static_int_cast<size_t>(nSize - m_nSize));
776 else
778 if (nSize != 0)
779 return store_E_OutOfMemory;
781 m_pData = pData, m_nSize = nSize;
783 return store_E_None;
786 storeError MemoryLockBytes::flush_Impl()
788 return store_E_None;
791 /*========================================================================
793 * ILockBytes factory implementations.
795 *======================================================================*/
796 namespace store
799 template< class T > struct ResourceHolder
801 typedef typename T::destructor_type destructor_type;
803 T m_value;
805 explicit ResourceHolder (T const & value = T()) : m_value (value) {}
806 ~ResourceHolder() { reset(); }
808 T & get() { return m_value; }
809 T const & get() const { return m_value; }
811 void set (T const & value) { m_value = value; }
812 void reset (T const & value = T())
814 T tmp (m_value);
815 if (tmp != value)
816 destructor_type()(tmp);
817 set (value);
819 T release()
821 T tmp (m_value);
822 set (T());
823 return tmp;
826 ResourceHolder (ResourceHolder & rhs)
828 set (rhs.release());
830 ResourceHolder & operator= (ResourceHolder & rhs)
832 reset (rhs.release());
833 return *this;
837 storeError
838 FileLockBytes_createInstance (
839 rtl::Reference< ILockBytes > & rxLockBytes,
840 rtl_uString * pFilename,
841 storeAccessMode eAccessMode
844 // Acquire file handle.
845 ResourceHolder<FileHandle> xFile;
846 storeError result = xFile.get().initialize (pFilename, eAccessMode);
847 if (result != store_E_None)
848 return result;
850 if (eAccessMode == store_AccessReadOnly)
852 ResourceHolder<FileMapping> xMapping;
853 if (xMapping.get().initialize (xFile.get().m_handle) == osl_File_E_None)
855 rxLockBytes = new MappedLockBytes (xMapping.get());
856 if (!rxLockBytes.is())
857 return store_E_OutOfMemory;
858 (void) xFile.release();
859 (void) xMapping.release();
862 if (!rxLockBytes.is())
864 rxLockBytes = new FileLockBytes (xFile.get());
865 if (!rxLockBytes.is())
866 return store_E_OutOfMemory;
867 (void) xFile.release();
870 return store_E_None;
873 storeError
874 MemoryLockBytes_createInstance (
875 rtl::Reference< ILockBytes > & rxLockBytes
878 rxLockBytes = new MemoryLockBytes();
879 if (!rxLockBytes.is())
880 return store_E_OutOfMemory;
882 return store_E_None;
885 } // namespace store
887 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */