vcl: sfx2: LOK: Support per-view popup windows
[LibreOffice.git] / store / source / lockbyte.cxx
blob139857440dfbdeedee2f7ec69e4f2a705344ecd3
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 <sal/types.h>
23 #include <osl/diagnose.h>
24 #include <osl/file.h>
25 #include <osl/process.h>
26 #include <rtl/ustring.hxx>
27 #include <sal/log.hxx>
29 #include "object.hxx"
30 #include "storbase.hxx"
32 #include <memory>
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 (std::shared_ptr<PageData> & 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 (std::shared_ptr<PageData> const & rPage, sal_uInt32 nOffset)
60 // [SECURITY:ValInput]
61 PageData const * pagedata = rPage.get();
62 OSL_PRECOND(!(pagedata == nullptr), "store::ILockBytes::writePageAt(): invalid Page");
63 if (pagedata == nullptr)
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 == nullptr)
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 = static_cast<sal_uInt64>(nOffset) + nBytes;
94 if (src_size > SAL_MAX_UINT32)
95 return store_E_CantSeek;
97 return readAt_Impl (nOffset, dst_lo, nBytes);
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 == nullptr)
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 = static_cast<sal_uInt64>(nOffset) + nBytes;
116 if (dst_size > SAL_MAX_UINT32)
117 return store_E_CantSeek;
119 return writeAt_Impl (nOffset, src_lo, nBytes);
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 namespace {
148 struct FileHandle
150 oslFileHandle m_handle;
152 FileHandle() : m_handle(nullptr) {}
154 bool operator != (FileHandle const & rhs)
156 return (m_handle != rhs.m_handle);
159 static storeError errorFromNative (oslFileError eErrno)
161 switch (eErrno)
163 case osl_File_E_None:
164 return store_E_None;
166 case osl_File_E_NOENT:
167 return store_E_NotExists;
169 case osl_File_E_ACCES:
170 case osl_File_E_PERM:
171 return store_E_AccessViolation;
173 case osl_File_E_AGAIN:
174 case osl_File_E_DEADLK:
175 return store_E_LockingViolation;
177 case osl_File_E_BADF:
178 return store_E_InvalidHandle;
180 case osl_File_E_INVAL:
181 return store_E_InvalidParameter;
183 case osl_File_E_NOMEM:
184 return store_E_OutOfMemory;
186 case osl_File_E_NOSPC:
187 return store_E_OutOfSpace;
189 case osl_File_E_OVERFLOW:
190 return store_E_CantSeek;
192 default:
193 return store_E_Unknown;
197 static sal_uInt32 modeToNative (storeAccessMode eAccessMode)
199 sal_uInt32 nFlags = 0;
200 switch (eAccessMode)
202 case storeAccessMode::Create:
203 nFlags |= osl_File_OpenFlag_Create;
204 [[fallthrough]];
205 case storeAccessMode::ReadWrite:
206 nFlags |= osl_File_OpenFlag_Write;
207 [[fallthrough]];
208 case storeAccessMode::ReadOnly:
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 == storeAccessMode::Create))
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 = nullptr;
276 typedef CloseFile destructor_type;
279 class FileLockBytes :
280 public store::OStoreObject,
281 public store::ILockBytes
283 /** Representation.
285 oslFileHandle const m_hFile;
286 sal_uInt32 m_nSize;
287 rtl::Reference< PageData::Allocator > m_xAllocator;
289 storeError initSize_Impl (sal_uInt32 & rnSize);
291 /** ILockBytes implementation.
293 virtual storeError initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize) override;
295 virtual storeError readPageAt_Impl (std::shared_ptr<PageData> & rPage, sal_uInt32 nOffset) override;
296 virtual storeError writePageAt_Impl (std::shared_ptr<PageData> const & rPage, sal_uInt32 nOffset) override;
298 virtual storeError readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes) override;
299 virtual storeError writeAt_Impl (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes) override;
301 virtual storeError getSize_Impl (sal_uInt32 & rnSize) override;
302 virtual storeError setSize_Impl (sal_uInt32 nSize) override;
304 virtual storeError flush_Impl() override;
306 public:
307 /** Construction.
309 explicit FileLockBytes (FileHandle const & rFile);
311 FileLockBytes(const FileLockBytes&) = delete;
312 FileLockBytes& operator=(const FileLockBytes&) = delete;
314 protected:
315 /** Destruction.
317 virtual ~FileLockBytes() override;
322 } // namespace store
324 FileLockBytes::FileLockBytes (FileHandle const & rFile)
325 : m_hFile (rFile.m_handle), m_nSize (SAL_MAX_UINT32), m_xAllocator()
329 FileLockBytes::~FileLockBytes()
331 FileHandle::closeFile (m_hFile);
334 storeError FileLockBytes::initSize_Impl (sal_uInt32 & rnSize)
336 /* osl_getFileSize() uses slow 'fstat(h, &size)',
337 * instead of fast 'size = lseek(h, 0, SEEK_END)'.
338 * so, init size here, and track changes.
340 sal_uInt64 uSize = 0;
341 oslFileError result = osl_getFileSize (m_hFile, &uSize);
342 if (result != osl_File_E_None)
343 return FileHandle::errorFromNative(result);
344 if (uSize > SAL_MAX_UINT32)
345 return store_E_CantSeek;
347 rnSize = sal::static_int_cast<sal_uInt32>(uSize);
348 return store_E_None;
351 storeError FileLockBytes::initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize)
353 storeError result = initSize_Impl (m_nSize);
354 if (result != store_E_None)
355 return result;
357 result = PageData::Allocator::createInstance (rxAllocator, nPageSize);
358 if (result != store_E_None)
359 return result;
361 // @see readPageAt_Impl().
362 m_xAllocator = rxAllocator;
363 return store_E_None;
366 storeError FileLockBytes::readPageAt_Impl (std::shared_ptr<PageData> & rPage, sal_uInt32 nOffset)
368 if (m_xAllocator.is())
370 std::shared_ptr<PageData> page (m_xAllocator->construct<PageData>(), PageData::Deallocate(m_xAllocator));
371 page.swap (rPage);
374 if (!m_xAllocator.is())
375 return store_E_InvalidAccess;
376 if (!rPage.get())
377 return store_E_OutOfMemory;
379 PageData * pagedata = rPage.get();
380 return readAt_Impl (nOffset, pagedata, pagedata->size());
383 storeError FileLockBytes::writePageAt_Impl (std::shared_ptr<PageData> const & rPage, sal_uInt32 nOffset)
385 PageData const * pagedata = rPage.get();
386 OSL_PRECOND(pagedata != nullptr, "contract violation");
387 return writeAt_Impl (nOffset, pagedata, pagedata->size());
390 storeError FileLockBytes::readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes)
392 sal_uInt64 nDone = 0;
393 oslFileError result = osl_readFileAt (m_hFile, nOffset, pBuffer, nBytes, &nDone);
394 if (result != osl_File_E_None)
395 return FileHandle::errorFromNative(result);
396 if (nDone != nBytes)
397 return (nDone != 0) ? store_E_CantRead : store_E_NotExists;
398 return store_E_None;
401 storeError FileLockBytes::writeAt_Impl (sal_uInt32 nOffset, void const * pBuffer, sal_uInt32 nBytes)
403 sal_uInt64 nDone = 0;
404 oslFileError result = osl_writeFileAt (m_hFile, nOffset, pBuffer, nBytes, &nDone);
405 if (result != osl_File_E_None)
406 return FileHandle::errorFromNative(result);
407 if (nDone != nBytes)
408 return store_E_CantWrite;
410 sal_uInt64 const uSize = nOffset + nBytes;
411 OSL_PRECOND(uSize < SAL_MAX_UINT32, "store::ILockBytes::writeAt() contract violation");
412 if (uSize > m_nSize)
413 m_nSize = sal::static_int_cast<sal_uInt32>(uSize);
414 return store_E_None;
417 storeError FileLockBytes::getSize_Impl (sal_uInt32 & rnSize)
419 rnSize = m_nSize;
420 return store_E_None;
423 storeError FileLockBytes::setSize_Impl (sal_uInt32 nSize)
425 oslFileError result = osl_setFileSize (m_hFile, nSize);
426 if (result != osl_File_E_None)
427 return FileHandle::errorFromNative(result);
429 m_nSize = nSize;
430 return store_E_None;
433 storeError FileLockBytes::flush_Impl()
435 oslFileError result = osl_syncFile (m_hFile);
436 if (result != osl_File_E_None)
437 return FileHandle::errorFromNative(result);
438 return store_E_None;
441 /*========================================================================
443 * MappedLockBytes implementation.
445 *======================================================================*/
446 namespace store
449 namespace {
451 struct FileMapping
453 sal_uInt8 * m_pAddr;
454 sal_uInt32 m_nSize;
455 oslFileHandle m_hFile;
457 FileMapping() : m_pAddr(nullptr), m_nSize(0), m_hFile(nullptr) {}
459 bool operator != (FileMapping const & rhs) const
461 return ((m_pAddr != rhs.m_pAddr) || (m_nSize != rhs.m_nSize));
464 oslFileError initialize (oslFileHandle hFile)
466 // Determine mapping size.
467 sal_uInt64 uSize = 0;
468 oslFileError result = osl_getFileSize (hFile, &uSize);
469 if (result != osl_File_E_None)
470 return result;
472 // [SECURITY:IntOver]
473 if (uSize > SAL_MAX_UINT32)
474 return osl_File_E_OVERFLOW;
475 m_nSize = sal::static_int_cast<sal_uInt32>(uSize);
477 m_hFile = hFile;
479 // Acquire mapping.
480 return osl_mapFile (hFile, reinterpret_cast<void**>(&m_pAddr), m_nSize, 0, osl_File_MapFlag_RandomAccess);
483 /** @see MappedLockBytes::destructor.
485 static void unmapFile (oslFileHandle hFile, sal_uInt8 * pAddr, sal_uInt32 nSize)
487 (void) osl_unmapMappedFile (hFile, pAddr, nSize);
488 (void) osl_closeFile (hFile);
491 /** @see ResourceHolder<T>::destructor_type
493 struct UnmapFile
495 void operator ()(FileMapping & rMapping) const
497 // Release mapping.
498 unmapFile (rMapping.m_hFile, rMapping.m_pAddr, rMapping.m_nSize);
499 rMapping.m_pAddr = nullptr;
500 rMapping.m_nSize = 0;
503 typedef UnmapFile destructor_type;
506 class MappedLockBytes :
507 public store::OStoreObject,
508 public store::PageData::Allocator,
509 public store::ILockBytes
511 /** Representation.
513 sal_uInt8 * const m_pData;
514 sal_uInt32 const m_nSize;
515 sal_uInt16 m_nPageSize;
516 oslFileHandle const m_hFile;
518 /** PageData::Allocator implementation.
520 virtual void allocate_Impl (void ** ppPage, sal_uInt16 * pnSize) override;
521 virtual void deallocate_Impl (void * pPage) override;
523 /** ILockBytes implementation.
525 virtual storeError initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize) override;
527 virtual storeError readPageAt_Impl (std::shared_ptr<PageData> & rPage, sal_uInt32 nOffset) override;
528 virtual storeError writePageAt_Impl (std::shared_ptr<PageData> const & rPage, sal_uInt32 nOffset) override;
530 virtual storeError readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes) override;
531 virtual storeError writeAt_Impl (sal_uInt32 nOffset, const void * pBuffer, sal_uInt32 nBytes) override;
533 virtual storeError getSize_Impl (sal_uInt32 & rnSize) override;
534 virtual storeError setSize_Impl (sal_uInt32 nSize) override;
536 virtual storeError flush_Impl() override;
538 public:
539 /** Construction.
541 explicit MappedLockBytes (FileMapping const & rMapping);
543 MappedLockBytes(const MappedLockBytes&) = delete;
544 MappedLockBytes& operator=(const MappedLockBytes&) = delete;
546 protected:
547 /* Destruction.
549 virtual ~MappedLockBytes() override;
554 } // namespace store
556 MappedLockBytes::MappedLockBytes (FileMapping const & rMapping)
557 : m_pData (rMapping.m_pAddr), m_nSize (rMapping.m_nSize), m_nPageSize(0), m_hFile (rMapping.m_hFile)
561 MappedLockBytes::~MappedLockBytes()
563 FileMapping::unmapFile (m_hFile, m_pData, m_nSize);
566 void MappedLockBytes::allocate_Impl (void ** ppPage, sal_uInt16 * pnSize)
568 OSL_PRECOND((ppPage != nullptr) && (pnSize != nullptr), "contract violation");
569 if ((ppPage != nullptr) && (pnSize != nullptr))
571 *ppPage = nullptr;
572 *pnSize = m_nPageSize;
576 void MappedLockBytes::deallocate_Impl (void * pPage)
578 OSL_PRECOND((m_pData <= pPage) && (pPage < m_pData + m_nSize), "contract violation");
581 storeError MappedLockBytes::initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize)
583 rxAllocator = this;
584 m_nPageSize = nPageSize;
585 return store_E_None;
588 storeError MappedLockBytes::readPageAt_Impl (std::shared_ptr<PageData> & rPage, sal_uInt32 nOffset)
590 sal_uInt8 * src_lo = m_pData + nOffset;
591 if ((m_pData > src_lo) || (src_lo >= m_pData + m_nSize))
592 return store_E_NotExists;
594 sal_uInt8 * src_hi = src_lo + m_nPageSize;
595 if ((m_pData > src_hi) || (src_hi > m_pData + m_nSize))
596 return store_E_CantRead;
598 std::shared_ptr<PageData> page (reinterpret_cast< PageData* >(src_lo), PageData::Deallocate(static_cast< PageData::Allocator* >(this)));
599 page.swap (rPage);
601 return store_E_None;
604 storeError MappedLockBytes::writePageAt_Impl (std::shared_ptr<PageData> const & /*rPage*/, sal_uInt32 /*nOffset*/)
606 return store_E_AccessViolation;
609 storeError MappedLockBytes::readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes)
611 sal_uInt8 const * src_lo = m_pData + nOffset;
612 if ((m_pData > src_lo) || (src_lo >= m_pData + m_nSize))
613 return store_E_NotExists;
615 sal_uInt8 const * src_hi = src_lo + nBytes;
616 if ((m_pData > src_hi) || (src_hi > m_pData + m_nSize))
617 return store_E_CantRead;
619 memcpy (pBuffer, src_lo, (src_hi - src_lo));
620 return store_E_None;
623 storeError MappedLockBytes::writeAt_Impl (sal_uInt32 /*nOffset*/, void const * /*pBuffer*/, sal_uInt32 /*nBytes*/)
625 return store_E_AccessViolation;
628 storeError MappedLockBytes::getSize_Impl (sal_uInt32 & rnSize)
630 rnSize = m_nSize;
631 return store_E_None;
634 storeError MappedLockBytes::setSize_Impl (sal_uInt32 /*nSize*/)
636 return store_E_AccessViolation;
639 storeError MappedLockBytes::flush_Impl()
641 return store_E_None;
644 /*========================================================================
646 * MemoryLockBytes implementation.
648 *======================================================================*/
649 namespace store
652 namespace {
654 class MemoryLockBytes :
655 public store::OStoreObject,
656 public store::ILockBytes
658 /** Representation.
660 sal_uInt8 * m_pData;
661 sal_uInt32 m_nSize;
662 rtl::Reference< PageData::Allocator > m_xAllocator;
664 /** ILockBytes implementation.
666 virtual storeError initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize) override;
668 virtual storeError readPageAt_Impl (std::shared_ptr<PageData> & rPage, sal_uInt32 nOffset) override;
669 virtual storeError writePageAt_Impl (std::shared_ptr<PageData> const & rPage, sal_uInt32 nOffset) override;
671 virtual storeError readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes) override;
672 virtual storeError writeAt_Impl (sal_uInt32 nOffset, const void * pBuffer, sal_uInt32 nBytes) override;
674 virtual storeError getSize_Impl (sal_uInt32 & rnSize) override;
675 virtual storeError setSize_Impl (sal_uInt32 nSize) override;
677 virtual storeError flush_Impl() override;
679 public:
680 /** Construction.
682 MemoryLockBytes();
684 MemoryLockBytes(const MemoryLockBytes&) = delete;
685 MemoryLockBytes& operator=(const MemoryLockBytes&) = delete;
687 protected:
688 /** Destruction.
690 virtual ~MemoryLockBytes() override;
695 } // namespace store
697 MemoryLockBytes::MemoryLockBytes()
698 : m_pData (nullptr), m_nSize (0), m_xAllocator()
701 MemoryLockBytes::~MemoryLockBytes()
703 std::free (m_pData);
706 storeError MemoryLockBytes::initialize_Impl (rtl::Reference< PageData::Allocator > & rxAllocator, sal_uInt16 nPageSize)
708 storeError result = PageData::Allocator::createInstance (rxAllocator, nPageSize);
709 if (result == store_E_None)
711 // @see readPageAt_Impl().
712 m_xAllocator = rxAllocator;
714 return result;
717 storeError MemoryLockBytes::readPageAt_Impl (std::shared_ptr<PageData> & rPage, sal_uInt32 nOffset)
719 if (m_xAllocator.is())
721 std::shared_ptr<PageData> page (m_xAllocator->construct<PageData>(), PageData::Deallocate(m_xAllocator));
722 page.swap (rPage);
725 if (!m_xAllocator.is())
726 return store_E_InvalidAccess;
727 if (!rPage.get())
728 return store_E_OutOfMemory;
730 PageData * pagedata = rPage.get();
731 return readAt_Impl (nOffset, pagedata, pagedata->size());
734 storeError MemoryLockBytes::writePageAt_Impl (std::shared_ptr<PageData> const & rPage, sal_uInt32 nOffset)
736 PageData const * pagedata = rPage.get();
737 OSL_PRECOND(!(pagedata == nullptr), "contract violation");
738 return writeAt_Impl (nOffset, pagedata, pagedata->size());
741 storeError MemoryLockBytes::readAt_Impl (sal_uInt32 nOffset, void * pBuffer, sal_uInt32 nBytes)
743 sal_uInt8 const * src_lo = m_pData + nOffset;
744 if ((m_pData > src_lo) || (src_lo >= m_pData + m_nSize))
745 return store_E_NotExists;
747 sal_uInt8 const * src_hi = src_lo + nBytes;
748 if ((m_pData > src_hi) || (src_hi > m_pData + m_nSize))
749 return store_E_CantRead;
751 memcpy (pBuffer, src_lo, (src_hi - src_lo));
752 return store_E_None;
755 storeError MemoryLockBytes::writeAt_Impl (sal_uInt32 nOffset, const void * pBuffer, sal_uInt32 nBytes)
757 sal_uInt64 const dst_size = nOffset + nBytes;
758 OSL_PRECOND(dst_size < SAL_MAX_UINT32, "store::ILockBytes::writeAt() contract violation");
759 if (dst_size > m_nSize)
761 storeError eErrCode = setSize_Impl (sal::static_int_cast<sal_uInt32>(dst_size));
762 if (eErrCode != store_E_None)
763 return eErrCode;
765 SAL_WARN_IF(dst_size > m_nSize, "store", "store::MemoryLockBytes::setSize_Impl() contract violation");
767 sal_uInt8 * dst_lo = m_pData + nOffset;
768 if (dst_lo >= m_pData + m_nSize)
769 return store_E_CantSeek;
771 sal_uInt8 * dst_hi = dst_lo + nBytes;
772 if (dst_hi > m_pData + m_nSize)
773 return store_E_CantWrite;
775 memcpy (dst_lo, pBuffer, (dst_hi - dst_lo));
776 return store_E_None;
779 storeError MemoryLockBytes::getSize_Impl (sal_uInt32 & rnSize)
781 rnSize = m_nSize;
782 return store_E_None;
785 storeError MemoryLockBytes::setSize_Impl (sal_uInt32 nSize)
787 if (nSize != m_nSize)
789 sal_uInt8 * pData = static_cast<sal_uInt8*>(std::realloc (m_pData, nSize));
790 if (pData != nullptr)
792 if (nSize > m_nSize)
793 memset (pData + m_nSize, 0, sal::static_int_cast<size_t>(nSize - m_nSize));
795 else
797 if (nSize != 0)
798 return store_E_OutOfMemory;
800 m_pData = pData;
801 m_nSize = nSize;
803 return store_E_None;
806 storeError MemoryLockBytes::flush_Impl()
808 return store_E_None;
811 /*========================================================================
813 * ILockBytes factory implementations.
815 *======================================================================*/
816 namespace store
819 namespace {
821 template< class T > struct ResourceHolder
823 typedef typename T::destructor_type destructor_type;
825 T m_value;
827 explicit ResourceHolder (T const & value = T()) : m_value (value) {}
828 ~ResourceHolder() { reset(T()); }
830 T & get() { return m_value; }
831 T const & get() const { return m_value; }
833 void set (T const & value) { m_value = value; }
834 void reset (T const & value)
836 T tmp (m_value);
837 if (tmp != value)
838 destructor_type()(tmp);
839 set (value);
841 T release()
843 T tmp (m_value);
844 set (T());
845 return tmp;
848 ResourceHolder & operator= (ResourceHolder & rhs)
850 reset (rhs.release());
851 return *this;
857 storeError
858 FileLockBytes_createInstance (
859 rtl::Reference< ILockBytes > & rxLockBytes,
860 rtl_uString * pFilename,
861 storeAccessMode eAccessMode
864 // Acquire file handle.
865 ResourceHolder<FileHandle> xFile;
866 storeError result = xFile.get().initialize (pFilename, eAccessMode);
867 if (result != store_E_None)
868 return result;
870 if (eAccessMode == storeAccessMode::ReadOnly)
872 ResourceHolder<FileMapping> xMapping;
873 if (xMapping.get().initialize (xFile.get().m_handle) == osl_File_E_None)
875 rxLockBytes = new MappedLockBytes (xMapping.get());
876 if (!rxLockBytes.is())
877 return store_E_OutOfMemory;
878 (void) xFile.release();
879 (void) xMapping.release();
882 if (!rxLockBytes.is())
884 rxLockBytes = new FileLockBytes (xFile.get());
885 if (!rxLockBytes.is())
886 return store_E_OutOfMemory;
887 (void) xFile.release();
890 return store_E_None;
893 storeError
894 MemoryLockBytes_createInstance (
895 rtl::Reference< ILockBytes > & rxLockBytes
898 rxLockBytes = new MemoryLockBytes();
899 if (!rxLockBytes.is())
900 return store_E_OutOfMemory;
902 return store_E_None;
905 } // namespace store
907 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */