LibreOffice Module oox (master) 1
storagebase.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
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/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
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 .
18 */
19
21
22#include <com/sun/star/io/XStream.hpp>
23#include <osl/diagnose.h>
24#include <rtl/ustrbuf.hxx>
27
28namespace oox {
29
30using namespace ::com::sun::star::embed;
31using namespace ::com::sun::star::io;
32using namespace ::com::sun::star::uno;
33
34namespace {
35
36void lclSplitFirstElement( OUString& orElement, OUString& orRemainder, const OUString& _aFullName )
37{
38 OUString aFullName = _aFullName;
39 sal_Int32 nSlashPos = aFullName.indexOf( '/' );
40
41 // strip leading slashes
42 while( nSlashPos == 0 )
43 {
44 aFullName = aFullName.copy(1);
45 nSlashPos = aFullName.indexOf( '/' );
46 }
47
48 if( (0 <= nSlashPos) && (nSlashPos < aFullName.getLength()) )
49 {
50 orElement = aFullName.copy( 0, nSlashPos );
51 orRemainder = aFullName.copy( nSlashPos + 1 );
52 }
53 else
54 {
55 orElement = aFullName;
56 }
57}
58
59} // namespace
60
61StorageBase::StorageBase( const Reference< XInputStream >& rxInStream, bool bBaseStreamAccess ) :
62 mxInStream( rxInStream ),
63 mbBaseStreamAccess( bBaseStreamAccess ),
64 mbReadOnly( true )
65{
66 OSL_ENSURE( mxInStream.is(), "StorageBase::StorageBase - missing base input stream" );
67}
68
69StorageBase::StorageBase( const Reference< XStream >& rxOutStream, bool bBaseStreamAccess ) :
70 mxOutStream( rxOutStream ),
71 mbBaseStreamAccess( bBaseStreamAccess ),
72 mbReadOnly( false )
73{
74 OSL_ENSURE( mxOutStream.is(), "StorageBase::StorageBase - missing base output stream" );
75}
76
77StorageBase::StorageBase( const StorageBase& rParentStorage, const OUString& rStorageName, bool bReadOnly ) :
78 maParentPath( rParentStorage.getPath() ),
79 maStorageName( rStorageName ),
80 mbBaseStreamAccess( false ),
81 mbReadOnly( bReadOnly )
82{
83}
84
86{
87}
88
90{
91 return implIsStorage();
92}
93
95{
96 return implIsStorage() && maStorageName.isEmpty();
97}
98
99Reference< XStorage > StorageBase::getXStorage() const
100{
101 return implGetXStorage();
102}
103
104OUString StorageBase::getPath() const
105{
106 OUStringBuffer aBuffer( maParentPath );
107 if( !aBuffer.isEmpty() )
108 aBuffer.append( '/' );
109 aBuffer.append( maStorageName );
110 return aBuffer.makeStringAndClear();
111}
112
113void StorageBase::getElementNames( ::std::vector< OUString >& orElementNames ) const
114{
115 orElementNames.clear();
116 implGetElementNames( orElementNames );
117}
118
119StorageRef StorageBase::openSubStorage( const OUString& rStorageName, bool bCreateMissing )
120{
121 StorageRef xSubStorage;
122 OSL_ENSURE( !bCreateMissing || !mbReadOnly, "StorageBase::openSubStorage - cannot create substorage in read-only mode" );
123 if( !bCreateMissing || !mbReadOnly )
124 {
125 OUString aElement, aRemainder;
126 lclSplitFirstElement( aElement, aRemainder, rStorageName );
127 if( !aElement.isEmpty() )
128 xSubStorage = getSubStorage( aElement, bCreateMissing );
129 if( xSubStorage && !aRemainder.isEmpty() )
130 xSubStorage = xSubStorage->openSubStorage( aRemainder, bCreateMissing );
131 }
132 return xSubStorage;
133}
134
135Reference< XInputStream > StorageBase::openInputStream( const OUString& rStreamName )
136{
137 Reference< XInputStream > xInStream;
138 OUString aElement, aRemainder;
139 lclSplitFirstElement( aElement, aRemainder, rStreamName );
140 if( !aElement.isEmpty() )
141 {
142 if( !aRemainder.isEmpty() )
143 {
144 StorageRef xSubStorage = getSubStorage( aElement, false );
145 if( xSubStorage )
146 xInStream = xSubStorage->openInputStream( aRemainder );
147 }
148 else
149 {
150 xInStream = implOpenInputStream( aElement );
151 }
152 }
153 else if( mbBaseStreamAccess )
154 {
155 xInStream = mxInStream;
156 }
157 return xInStream;
158}
159
160Reference< XOutputStream > StorageBase::openOutputStream( const OUString& rStreamName )
161{
162 Reference< XOutputStream > xOutStream;
163 OSL_ENSURE( !mbReadOnly, "StorageBase::openOutputStream - cannot create output stream in read-only mode" );
164 if( !mbReadOnly )
165 {
166 OUString aElement, aRemainder;
167 lclSplitFirstElement( aElement, aRemainder, rStreamName );
168 if( !aElement.isEmpty() )
169 {
170 if( !aRemainder.isEmpty() )
171 {
172 StorageRef xSubStorage = getSubStorage( aElement, true );
173 if( xSubStorage )
174 xOutStream = xSubStorage->openOutputStream( aRemainder );
175 }
176 else
177 {
178 xOutStream = implOpenOutputStream( aElement );
179 }
180 }
181 else if( mbBaseStreamAccess )
182 {
183 xOutStream = mxOutStream->getOutputStream();
184 }
185 }
186 return xOutStream;
187}
188
189void StorageBase::copyToStorage( StorageBase& rDestStrg, const OUString& rElementName )
190{
191 OSL_ENSURE( rDestStrg.isStorage() && !rDestStrg.isReadOnly(), "StorageBase::copyToStorage - invalid destination" );
192 OSL_ENSURE( !rElementName.isEmpty(), "StorageBase::copyToStorage - invalid element name" );
193 if( !rDestStrg.isStorage() || rDestStrg.isReadOnly() || rElementName.isEmpty() )
194 return;
195
196 StorageRef xSubStrg = openSubStorage( rElementName, false );
197 if( xSubStrg )
198 {
199 StorageRef xDestSubStrg = rDestStrg.openSubStorage( rElementName, true );
200 if( xDestSubStrg )
201 xSubStrg->copyStorageToStorage( *xDestSubStrg );
202 }
203 else
204 {
205 Reference< XInputStream > xInStrm = openInputStream( rElementName );
206 if( xInStrm.is() )
207 {
208 Reference< XOutputStream > xOutStrm = rDestStrg.openOutputStream( rElementName );
209 if( xOutStrm.is() )
210 {
211 BinaryXInputStream aInStrm( xInStrm, true );
212 BinaryXOutputStream aOutStrm( xOutStrm, true );
213 aInStrm.copyToStream( aOutStrm );
214 }
215 }
216 }
217}
218
220{
221 OSL_ENSURE( rDestStrg.isStorage() && !rDestStrg.isReadOnly(), "StorageBase::copyToStorage - invalid destination" );
222 if( rDestStrg.isStorage() && !rDestStrg.isReadOnly() )
223 {
224 ::std::vector< OUString > aElements;
225 getElementNames( aElements );
226 for (auto const& elem : aElements)
227 copyToStorage(rDestStrg, elem);
228 }
229}
230
232{
233 OSL_ENSURE( !mbReadOnly, "StorageBase::commit - cannot commit in read-only mode" );
234 if( !mbReadOnly )
235 {
236 // commit all open substorages
237 maSubStorages.forEachMem( &StorageBase::commit );
238 // commit this storage
239 implCommit();
240 }
241}
242
243// private --------------------------------------------------------------------
244
245StorageRef StorageBase::getSubStorage( const OUString& rElementName, bool bCreateMissing )
246{
247 StorageRef& rxSubStrg = maSubStorages[ rElementName ];
248 if( !rxSubStrg )
249 rxSubStrg = implOpenSubStorage( rElementName, bCreateMissing );
250 return rxSubStrg;
251}
252
253} // namespace oox
254
255/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
void copyToStream(BinaryOutputStream &rOutStrm)
Copies bytes from the current position to the passed output stream.
Wraps a UNO input stream and provides convenient access functions.
Wraps a UNO output stream and provides convenient access functions.
Base class for storage access implementations.
Definition: storagebase.hxx:52
virtual css::uno::Reference< css::embed::XStorage > implGetXStorage() const =0
Returns the com.sun.star.embed.XStorage interface of the current storage.
virtual bool implIsStorage() const =0
Returns true, if the object represents a valid storage.
css::uno::Reference< css::embed::XStorage > getXStorage() const
Returns the com.sun.star.embed.XStorage interface of the current storage.
Definition: storagebase.cxx:99
StorageBase(const css::uno::Reference< css::io::XInputStream > &rxInStream, bool bBaseStreamAccess)
OUString getPath() const
Returns the full path of this storage.
bool mbReadOnly
True = storage opened read-only (based on input stream).
css::uno::Reference< css::io::XStream > mxOutStream
Cached base output stream (to keep it alive).
css::uno::Reference< css::io::XInputStream > mxInStream
Cached base input stream (to keep it alive).
bool mbBaseStreamAccess
True = access base streams with empty stream name.
StorageRef getSubStorage(const OUString &rElementName, bool bCreateMissing)
Helper that opens and caches the specified direct substorage.
void getElementNames(::std::vector< OUString > &orElementNames) const
Fills the passed vector with the names of all direct elements of this storage.
void copyToStorage(StorageBase &rDestStrg, const OUString &rElementName)
Copies the specified element from this storage to the passed destination storage.
OUString maStorageName
Name of this storage, if it is a substorage.
css::uno::Reference< css::io::XInputStream > openInputStream(const OUString &rStreamName)
Opens and returns the specified input stream from the storage.
virtual void implCommit() const =0
Commits the current storage.
RefMap< OUString, StorageBase > maSubStorages
Map of direct sub storages.
virtual css::uno::Reference< css::io::XInputStream > implOpenInputStream(const OUString &rElementName)=0
Implementation of opening an input stream element.
void commit()
Commits the changes to the storage and all substorages.
virtual css::uno::Reference< css::io::XOutputStream > implOpenOutputStream(const OUString &rElementName)=0
Implementation of opening an output stream element.
bool isReadOnly() const
Returns true, if the storage operates in read-only mode (based on an input stream).
Definition: storagebase.hxx:72
void copyStorageToStorage(StorageBase &rDestStrg)
Copies all streams of this storage and of all substorages to the passed destination.
virtual StorageRef implOpenSubStorage(const OUString &rElementName, bool bCreate)=0
Implementation of opening a storage element.
bool isStorage() const
Returns true, if the object represents a valid storage.
Definition: storagebase.cxx:89
StorageRef openSubStorage(const OUString &rStorageName, bool bCreateMissing)
Opens and returns the specified sub storage from the storage.
virtual void implGetElementNames(::std::vector< OUString > &orElementNames) const =0
Returns the names of all elements of this storage.
OUString maParentPath
Full path of parent storage.
virtual ~StorageBase()
Definition: storagebase.cxx:85
bool isRootStorage() const
Returns true, if the object represents the root storage.
Definition: storagebase.cxx:94
css::uno::Reference< css::io::XOutputStream > openOutputStream(const OUString &rStreamName)
Opens and returns the specified output stream from the storage.
Reference< XInputStream > mxInStream
Definition: fastparser.cxx:47
bool bReadOnly
std::shared_ptr< StorageBase > StorageRef
Definition: storagebase.hxx:42
std::unique_ptr< char[]> aBuffer