vcl: sfx2: LOK: Support per-view popup windows
[LibreOffice.git] / store / source / storlckb.cxx
blob1aaf2cbc0a776f12acce228277f12c515c559899
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 "storlckb.hxx"
22 #include <sal/types.h>
23 #include <rtl/string.h>
24 #include <rtl/ref.hxx>
25 #include <osl/mutex.hxx>
27 #include <store/types.h>
29 #include "storbase.hxx"
30 #include "stordata.hxx"
31 #include "storpage.hxx"
33 using namespace store;
35 /*========================================================================
37 * OStoreLockBytes implementation.
39 *======================================================================*/
40 const sal_uInt32 OStoreLockBytes::m_nTypeId(0x94190310);
43 * OStoreLockBytes.
45 OStoreLockBytes::OStoreLockBytes()
46 : m_xManager (),
47 m_xNode (),
48 m_bWriteable (false)
53 * ~OStoreLockBytes.
55 OStoreLockBytes::~OStoreLockBytes()
57 if (m_xManager.is() && m_xNode.is())
59 m_xManager->releasePage(m_xNode->m_aDescr);
64 * isKindOf.
66 bool OStoreLockBytes::isKindOf (sal_uInt32 nTypeId)
68 return (nTypeId == m_nTypeId);
72 * create.
74 storeError OStoreLockBytes::create (
75 OStorePageManager *pManager,
76 rtl_String const *pPath,
77 rtl_String const *pName,
78 storeAccessMode eMode)
80 rtl::Reference<OStorePageManager> xManager (pManager);
81 if (!xManager.is())
82 return store_E_InvalidAccess;
84 if (!(pPath && pName))
85 return store_E_InvalidParameter;
87 OStoreDirectoryPageObject aPage;
88 storeError eErrCode = xManager->iget (
89 aPage, STORE_ATTRIB_ISFILE,
90 pPath, pName, eMode);
91 if (eErrCode != store_E_None)
92 return eErrCode;
94 if (!(aPage.attrib() & STORE_ATTRIB_ISFILE))
96 // No ISFILE in older versions (backward compatibility).
97 if (aPage.attrib() & STORE_ATTRIB_ISLINK)
98 return store_E_NotFile;
101 inode_holder_type xNode (aPage.get());
102 if (eMode != storeAccessMode::ReadOnly)
103 eErrCode = xManager->acquirePage (xNode->m_aDescr, storeAccessMode::ReadWrite);
104 else
105 eErrCode = xManager->acquirePage (xNode->m_aDescr, storeAccessMode::ReadOnly);
106 if (eErrCode != store_E_None)
107 return eErrCode;
109 m_xManager = xManager;
110 m_xNode = xNode;
111 m_bWriteable = (eMode != storeAccessMode::ReadOnly);
113 // Check for truncation.
114 if (eMode == storeAccessMode::Create)
116 // Truncate to zero length.
117 eErrCode = setSize(0);
119 return eErrCode;
123 * readAt.
125 storeError OStoreLockBytes::readAt (
126 sal_uInt32 nOffset,
127 void *pBuffer,
128 sal_uInt32 nBytes,
129 sal_uInt32 &rnDone)
131 rnDone = 0;
133 if (!m_xManager.is())
134 return store_E_InvalidAccess;
136 if (!pBuffer)
137 return store_E_InvalidParameter;
138 if (!nBytes)
139 return store_E_None;
141 // Acquire exclusive access.
142 osl::MutexGuard aGuard (*m_xManager);
144 // Determine data length.
145 OStoreDirectoryPageObject aPage (m_xNode.get());
147 sal_uInt32 nDataLen = aPage.dataLength();
148 if ((nOffset + nBytes) > nDataLen)
149 nBytes = nDataLen - nOffset;
151 // Read data.
152 OStoreDataPageObject aData;
153 sal_uInt8 *pData = static_cast<sal_uInt8*>(pBuffer);
154 while ((0 < nBytes) && (nOffset < nDataLen))
156 // Determine 'Offset' scope.
157 inode::ChunkScope eScope = m_xNode->scope (nOffset);
158 if (eScope == inode::SCOPE_INTERNAL)
160 // Read from inode page (internal scope).
161 inode::ChunkDescriptor aDescr (
162 nOffset, m_xNode->capacity());
164 sal_uInt32 nLength = sal_uInt32(aDescr.m_nLength);
165 if(nLength > nBytes)
167 nLength = nBytes;
169 memcpy (
170 &pData[rnDone],
171 &m_xNode->m_pData[aDescr.m_nOffset],
172 nLength);
174 // Adjust counters.
175 rnDone += nLength;
176 nOffset += nLength;
177 nBytes -= nLength;
179 else
181 // Read from data page (external scope).
182 inode::ChunkDescriptor aDescr (
183 nOffset - m_xNode->capacity(), OStoreDataPageData::capacity(m_xNode->m_aDescr)); // @@@
185 sal_uInt32 nLength = sal_uInt32(aDescr.m_nLength);
186 if(nLength > nBytes)
188 nLength = nBytes;
191 storeError eErrCode = aPage.read (aDescr.m_nPage, aData, *m_xManager);
192 if (eErrCode != store_E_None)
194 if (eErrCode != store_E_NotExists)
195 return eErrCode;
197 memset (
198 &pData[rnDone],
200 nLength);
202 else
204 PageHolderObject< data > xData (aData.makeHolder<data>());
205 memcpy (
206 &pData[rnDone],
207 &xData->m_pData[aDescr.m_nOffset],
208 nLength);
211 // Adjust counters.
212 rnDone += nLength;
213 nOffset += nLength;
214 nBytes -= nLength;
218 // Done.
219 return store_E_None;
223 * writeAt.
225 storeError OStoreLockBytes::writeAt (
226 sal_uInt32 nOffset,
227 const void *pBuffer,
228 sal_uInt32 nBytes,
229 sal_uInt32 &rnDone)
231 rnDone = 0;
233 if (!m_xManager.is())
234 return store_E_InvalidAccess;
235 if (!m_bWriteable)
236 return store_E_AccessViolation;
238 if (!pBuffer)
239 return store_E_InvalidParameter;
240 if (!nBytes)
241 return store_E_None;
243 // Acquire exclusive access.
244 osl::MutexGuard aGuard (*m_xManager);
246 // Write data.
247 OStoreDirectoryPageObject aPage (m_xNode.get());
248 const sal_uInt8 *pData = static_cast<const sal_uInt8*>(pBuffer);
250 storeError eErrCode = store_E_None;
251 while (nBytes > 0)
253 // Determine 'Offset' scope.
254 inode::ChunkScope eScope = m_xNode->scope (nOffset);
255 if (eScope == inode::SCOPE_INTERNAL)
257 // Write to inode page (internal scope).
258 inode::ChunkDescriptor aDescr (
259 nOffset, m_xNode->capacity());
261 sal_uInt32 nLength = sal_uInt32(aDescr.m_nLength);
262 if(nLength > nBytes)
264 nLength = nBytes;
267 memcpy (
268 &m_xNode->m_pData[aDescr.m_nOffset],
269 &pData[rnDone], nLength);
271 // Mark inode dirty.
272 aPage.touch();
274 // Adjust counters.
275 rnDone += nLength;
276 nOffset += nLength;
277 nBytes -= nLength;
279 // Adjust data length.
280 if (aPage.dataLength() < nOffset)
281 aPage.dataLength (nOffset);
283 else
285 // Write to data page (external scope).
286 OStoreDataPageObject aData;
288 inode::ChunkDescriptor aDescr (
289 nOffset - m_xNode->capacity(), OStoreDataPageData::capacity(m_xNode->m_aDescr)); // @@@
291 sal_uInt32 nLength = sal_uInt32(aDescr.m_nLength);
292 if ((aDescr.m_nOffset > 0) || (nBytes < nLength))
294 // Unaligned. Need to load/create data page.
295 // @@@ loadOrCreate()
296 eErrCode = aPage.read (aDescr.m_nPage, aData, *m_xManager);
297 if (eErrCode != store_E_None)
299 if (eErrCode != store_E_NotExists)
300 return eErrCode;
302 eErrCode = aData.construct<data>(m_xManager->allocator());
303 if (eErrCode != store_E_None)
304 return eErrCode;
308 PageHolderObject< data > xData (aData.makeHolder<data>());
309 if (!xData.is())
311 eErrCode = aData.construct<data>(m_xManager->allocator());
312 if (eErrCode != store_E_None)
313 return eErrCode;
314 xData = aData.makeHolder<data>();
317 // Modify data page.
318 if(nLength > nBytes)
320 nLength = nBytes;
322 memcpy (
323 &xData->m_pData[aDescr.m_nOffset],
324 &pData[rnDone], nLength);
326 // Save data page.
327 eErrCode = aPage.write (aDescr.m_nPage, aData, *m_xManager);
328 if (eErrCode != store_E_None)
329 return eErrCode;
331 // Adjust counters.
332 rnDone += nLength;
333 nOffset += nLength;
334 nBytes -= nLength;
336 // Adjust data length.
337 if (aPage.dataLength() < nOffset)
338 aPage.dataLength (nOffset);
342 // Check for modified inode.
343 if (aPage.dirty())
344 return m_xManager->saveObjectAt (aPage, aPage.location());
345 else
346 return store_E_None;
350 * setSize.
352 storeError OStoreLockBytes::setSize (sal_uInt32 nSize)
354 if (!m_xManager.is())
355 return store_E_InvalidAccess;
356 if (!m_bWriteable)
357 return store_E_AccessViolation;
359 // Acquire exclusive access.
360 osl::MutexGuard aGuard (*m_xManager);
362 // Determine current length.
363 OStoreDirectoryPageObject aPage (m_xNode.get());
364 sal_uInt32 nDataLen = aPage.dataLength();
366 if (nSize == nDataLen)
367 return store_E_None;
369 if (nSize < nDataLen)
371 // Truncate.
372 storeError eErrCode = store_E_None;
374 // Determine 'Size' scope.
375 inode::ChunkScope eSizeScope = m_xNode->scope (nSize);
376 if (eSizeScope == inode::SCOPE_INTERNAL)
378 // Internal 'Size' scope. Determine 'Data' scope.
379 inode::ChunkScope eDataScope = m_xNode->scope (nDataLen);
380 if (eDataScope == inode::SCOPE_EXTERNAL)
382 // External 'Data' scope. Truncate all external data pages.
383 eErrCode = aPage.truncate (0, *m_xManager);
384 if (eErrCode != store_E_None)
385 return eErrCode;
388 // Truncate internal data page.
389 inode::ChunkDescriptor aDescr (nSize, m_xNode->capacity());
390 memset (
391 &(m_xNode->m_pData[aDescr.m_nOffset]),
392 0, aDescr.m_nLength);
394 else
396 // External 'Size' scope. Truncate external data pages.
397 inode::ChunkDescriptor aDescr (
398 nSize - m_xNode->capacity(), OStoreDataPageData::capacity(m_xNode->m_aDescr)); // @@@
400 sal_uInt32 nPage = aDescr.m_nPage;
401 if (aDescr.m_nOffset) nPage += 1;
403 eErrCode = aPage.truncate (nPage, *m_xManager);
404 if (eErrCode != store_E_None)
405 return eErrCode;
409 // Set (extended or truncated) size.
410 aPage.dataLength (nSize);
412 // Save modified inode.
413 return m_xManager->saveObjectAt (aPage, aPage.location());
416 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */