LibreOffice Module writerperfect (master) 1
WPXSvInputStream.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
10#include <WPXSvInputStream.hxx>
11
12#include <com/sun/star/packages/zip/XZipFileAccess2.hpp>
13#include <com/sun/star/uno/XComponentContext.hpp>
14
17#include <o3tl/safeint.hxx>
18#include <rtl/string.hxx>
19#include <sal/log.hxx>
20
21#include <sot/storage.hxx>
22
23#include <tools/stream.hxx>
26
27#include <climits>
28#include <limits>
29#include <memory>
30#include <string_view>
31#include <unordered_map>
32#include <utility>
33#include <vector>
34
35namespace writerperfect
36{
37using namespace ::com::sun::star::uno;
38using namespace ::com::sun::star::io;
39
42
43namespace
44{
45class PositionHolder
46{
47public:
48 explicit PositionHolder(const Reference<XSeekable>& rxSeekable);
49 ~PositionHolder();
50 PositionHolder(const PositionHolder&) = delete;
51 PositionHolder& operator=(const PositionHolder&) = delete;
52
53private:
54 const Reference<XSeekable> mxSeekable;
55 const sal_uInt64 mnPosition;
56};
57
58PositionHolder::PositionHolder(const Reference<XSeekable>& rxSeekable)
59 : mxSeekable(rxSeekable)
60 , mnPosition(rxSeekable->getPosition())
61{
62}
63
64PositionHolder::~PositionHolder()
65{
66 try
67 {
69 }
70 catch (...)
71 {
72 }
73}
74
75} // anonymous namespace
76
77namespace
78{
79OUString lcl_normalizeSubStreamPath(const OUString& rPath)
80{
81 // accept paths which begin by '/'
82 // TODO: maybe this should do a full normalization
83 if (rPath.startsWith("/") && rPath.getLength() >= 2)
84 return rPath.copy(1);
85 return rPath;
86}
87}
88
89namespace
90{
91OUString concatPath(std::u16string_view lhs, const OUString& rhs)
92{
93 if (lhs.empty())
94 return rhs;
95 return OUString::Concat(lhs) + "/" + rhs;
96}
97
98struct OLEStreamData
99{
100 OLEStreamData(OString aName, OString rvngName);
101
103
109 OString name;
115 OString RVNGname;
116};
117
118typedef std::unordered_map<OUString, std::size_t> NameMap_t;
119typedef std::unordered_map<OUString, tools::SvRef<SotStorage>> OLEStorageMap_t;
120
137struct OLEStorageImpl
138{
139 OLEStorageImpl();
140
141 void initialize(std::unique_ptr<SvStream> pStream);
142
143 tools::SvRef<SotStorageStream> getStream(const OUString& rPath);
144 tools::SvRef<SotStorageStream> const& getStream(std::size_t nId);
145
146private:
147 void traverse(const tools::SvRef<SotStorage>& rStorage, std::u16string_view rPath);
148
149 tools::SvRef<SotStorageStream> createStream(const OUString& rPath);
150
151public:
152 tools::SvRef<SotStorage> mxRootStorage; //< root storage of the OLE2
153 OLEStorageMap_t maStorageMap; //< map of all sub storages by name
154 ::std::vector<OLEStreamData> maStreams; //< list of streams and their names
155 NameMap_t maNameMap; //< map of stream names to indexes (into @c maStreams)
157};
158
159OLEStreamData::OLEStreamData(OString aName, OString rvngName)
160 : name(std::move(aName))
161 , RVNGname(std::move(rvngName))
162{
163}
164
165OLEStorageImpl::OLEStorageImpl()
166 : mbInitialized(false)
167{
168}
169
170void OLEStorageImpl::initialize(std::unique_ptr<SvStream> pStream)
171{
172 if (!pStream)
173 return;
174
175 mxRootStorage = new SotStorage(pStream.release(), true);
176
177 traverse(mxRootStorage, u"");
178
179 mbInitialized = true;
180}
181
182tools::SvRef<SotStorageStream> OLEStorageImpl::getStream(const OUString& rPath)
183{
184 const OUString aPath(lcl_normalizeSubStreamPath(rPath));
185 NameMap_t::iterator aIt = maNameMap.find(aPath);
186
187 // For the while don't return stream in this situation.
188 // Later, given how libcdr's zip stream implementation behaves,
189 // return the first stream in the storage if there is one.
190 if (maNameMap.end() == aIt)
192
193 if (!maStreams[aIt->second].stream.is())
194 maStreams[aIt->second].stream
195 = createStream(OStringToOUString(maStreams[aIt->second].name, RTL_TEXTENCODING_UTF8));
196
197 return maStreams[aIt->second].stream;
198}
199
200tools::SvRef<SotStorageStream> const& OLEStorageImpl::getStream(const std::size_t nId)
201{
202 if (!maStreams[nId].stream.is())
203 maStreams[nId].stream
204 = createStream(OStringToOUString(maStreams[nId].name, RTL_TEXTENCODING_UTF8));
205
206 return maStreams[nId].stream;
207}
208
209void OLEStorageImpl::traverse(const tools::SvRef<SotStorage>& rStorage, std::u16string_view rPath)
210{
211 SvStorageInfoList infos;
212
213 rStorage->FillInfoList(&infos);
214
215 for (const auto& info : infos)
216 {
217 if (info.IsStream())
218 {
219 OUString baseName = info.GetName(), rvngName = baseName;
220 // librevenge::RVNGOLEStream ignores the first character when is a control code, so ...
221 if (!rvngName.isEmpty() && rvngName.toChar() < 32)
222 rvngName = rvngName.copy(1);
223 maStreams.emplace_back(
224 OUStringToOString(concatPath(rPath, baseName), RTL_TEXTENCODING_UTF8),
225 OUStringToOString(concatPath(rPath, rvngName), RTL_TEXTENCODING_UTF8));
226 maNameMap[concatPath(rPath, rvngName)] = maStreams.size() - 1;
227 }
228 else if (info.IsStorage())
229 {
230 const OUString aPath = concatPath(rPath, info.GetName());
232 = rStorage->OpenSotStorage(info.GetName(), StreamMode::STD_READ);
233 maStorageMap[aPath] = aStorage;
234
235 // deep-first traversal
236 traverse(aStorage, aPath);
237 }
238 else
239 {
240 SAL_WARN("writerperfect",
241 "OLEStorageImpl::traverse: invalid storage entry, neither stream nor file");
242 }
243 }
244}
245
246tools::SvRef<SotStorageStream> OLEStorageImpl::createStream(const OUString& rPath)
247{
248 const sal_Int32 nDelim = rPath.lastIndexOf(u'/');
249
250 if (-1 == nDelim)
251 return mxRootStorage->OpenSotStream(rPath, StreamMode::STD_READ);
252
253 const OUString aDir = rPath.copy(0, nDelim);
254 const OUString aName = rPath.copy(nDelim + 1);
255
256 const OLEStorageMap_t::const_iterator aIt = maStorageMap.find(aDir);
257
258 if (maStorageMap.end() == aIt)
259 return nullptr;
260
261 return aIt->second->OpenSotStream(aName, StreamMode::STD_READ);
262}
263}
264
265namespace
266{
267struct ZipStreamData
268{
269 explicit ZipStreamData(OString aName);
270
271 Reference<XInputStream> xStream;
272
278 OString aName;
279};
280
286struct ZipStorageImpl
287{
288 explicit ZipStorageImpl(const Reference<container::XNameAccess>& rxContainer);
289
296 void initialize();
297
298 Reference<XInputStream> getStream(const OUString& rPath);
299 Reference<XInputStream> const& getStream(std::size_t nId);
300
301private:
302 void traverse(const Reference<container::XNameAccess>& rxEnum);
303
304 Reference<XInputStream> createStream(const OUString& rPath);
305
306public:
307 Reference<container::XNameAccess> mxContainer; //< root of the Zip
308 ::std::vector<ZipStreamData> maStreams; //< list of streams and their names
309 NameMap_t maNameMap; //< map of stream names to indexes (into @c maStreams)
310 bool mbInitialized;
311};
312
313ZipStreamData::ZipStreamData(OString _aName)
314 : aName(std::move(_aName))
315{
316}
317
318ZipStorageImpl::ZipStorageImpl(const Reference<container::XNameAccess>& rxContainer)
319 : mxContainer(rxContainer)
320 , mbInitialized(false)
321{
322 assert(mxContainer.is());
323}
324
325void ZipStorageImpl::initialize()
326{
327 traverse(mxContainer);
328
329 mbInitialized = true;
330}
331
332Reference<XInputStream> ZipStorageImpl::getStream(const OUString& rPath)
333{
334 const OUString aPath(lcl_normalizeSubStreamPath(rPath));
335 NameMap_t::iterator aIt = maNameMap.find(aPath);
336
337 // For the while don't return stream in this situation.
338 // Later, given how libcdr's zip stream implementation behaves,
339 // return the first stream in the storage if there is one.
340 if (maNameMap.end() == aIt)
341 return Reference<XInputStream>();
342
343 if (!maStreams[aIt->second].xStream.is())
344 maStreams[aIt->second].xStream = createStream(aPath);
345
346 return maStreams[aIt->second].xStream;
347}
348
349Reference<XInputStream> const& ZipStorageImpl::getStream(const std::size_t nId)
350{
351 if (!maStreams[nId].xStream.is())
352 maStreams[nId].xStream
353 = createStream(OStringToOUString(maStreams[nId].aName, RTL_TEXTENCODING_UTF8));
354
355 return maStreams[nId].xStream;
356}
357
358void ZipStorageImpl::traverse(const Reference<container::XNameAccess>& rxContainer)
359{
360 const Sequence<OUString> lNames = rxContainer->getElementNames();
361
362 maStreams.reserve(lNames.getLength());
363
364 for (const auto& rName : lNames)
365 {
366 if (!rName.endsWith("/")) // skip dirs
367 {
368 maStreams.emplace_back(OUStringToOString(rName, RTL_TEXTENCODING_UTF8));
369 maNameMap[rName] = maStreams.size() - 1;
370 }
371 }
372}
373
374Reference<XInputStream> ZipStorageImpl::createStream(const OUString& rPath)
375{
376 Reference<XInputStream> xStream;
377
378 try
379 {
380 const Reference<XInputStream> xInputStream(mxContainer->getByName(rPath), UNO_QUERY_THROW);
381 const Reference<XSeekable> xSeekable(xInputStream, UNO_QUERY);
382
383 if (xSeekable.is())
384 xStream = xInputStream;
385 else
388 }
389 catch (const Exception&)
390 {
391 // nothing needed
392 }
393
394 return xStream;
395}
396}
397
399{
400public:
401 explicit WPXSvInputStreamImpl(css::uno::Reference<css::io::XInputStream> const& xStream);
402
403 bool isStructured();
404 unsigned subStreamCount();
405 const char* subStreamName(unsigned id);
406 bool existsSubStream(const char* name);
407 librevenge::RVNGInputStream* getSubStreamByName(const char* name);
408 librevenge::RVNGInputStream* getSubStreamById(unsigned id);
409
410 const unsigned char* read(unsigned long numBytes, unsigned long& numBytesRead);
411 int seek(tools::Long offset);
412 tools::Long tell();
413 bool isEnd();
414
415 void invalidateReadBuffer();
416
417private:
418 bool isOLE();
419 void ensureOLEIsInitialized();
420
421 bool isZip();
422 void ensureZipIsInitialized();
423
424 static librevenge::RVNGInputStream*
425 createWPXStream(const tools::SvRef<SotStorageStream>& rxStorage);
426 static librevenge::RVNGInputStream* createWPXStream(const Reference<XInputStream>& rxStream);
427
428private:
429 css::uno::Reference<css::io::XInputStream> mxStream;
430 css::uno::Reference<css::io::XSeekable> mxSeekable;
431 css::uno::Sequence<sal_Int8> maData;
432 std::unique_ptr<OLEStorageImpl> mpOLEStorage;
433 std::unique_ptr<ZipStorageImpl> mpZipStorage;
436
437public:
438 sal_Int64 mnLength;
439 const unsigned char* mpReadBuffer;
440 unsigned long mnReadBufferLength;
441 unsigned long mnReadBufferPos;
442};
443
444WPXSvInputStreamImpl::WPXSvInputStreamImpl(Reference<XInputStream> const& xStream)
445 : mxStream(xStream)
446 , mxSeekable(xStream, UNO_QUERY)
447 , maData(0)
448 , mbCheckedOLE(false)
449 , mbCheckedZip(false)
450 , mnLength(0)
451 , mpReadBuffer(nullptr)
452 , mnReadBufferLength(0)
453 , mnReadBufferPos(0)
454{
455 if (!xStream.is() || !mxStream.is())
456 mnLength = 0;
457 else
458 {
459 if (!mxSeekable.is())
460 mnLength = 0;
461 else
462 {
463 try
464 {
465 mnLength = mxSeekable->getLength();
466 if (0 < mxSeekable->getPosition())
467 mxSeekable->seek(0);
468 }
469 catch (...)
470 {
471 SAL_WARN("writerperfect", "mnLength = mxSeekable->getLength() threw exception");
472 mnLength = 0;
473 }
474 }
475 }
476}
477
478const unsigned char* WPXSvInputStreamImpl::read(unsigned long numBytes, unsigned long& numBytesRead)
479{
480 numBytesRead = 0;
481
482 if (numBytes == 0 || isEnd())
483 return nullptr;
484
485 numBytesRead = mxStream->readSomeBytes(maData, numBytes);
486 if (numBytesRead == 0)
487 return nullptr;
488
489 return reinterpret_cast<const unsigned char*>(maData.getConstArray());
490}
491
493{
494 if ((mnLength == 0) || !mxStream.is() || !mxSeekable.is())
495 return -1;
496 else
497 {
498 const sal_Int64 tmpPosition = mxSeekable->getPosition();
499 if ((tmpPosition < 0) || (tmpPosition > LONG_MAX))
500 return -1;
501 return static_cast<tools::Long>(tmpPosition);
502 }
503}
504
506{
507 if ((mnLength == 0) || !mxStream.is() || !mxSeekable.is())
508 return -1;
509
510 const sal_Int64 tmpPosition = mxSeekable->getPosition();
511 if ((tmpPosition < 0) || (tmpPosition > LONG_MAX))
512 return -1;
513
514 try
515 {
516 mxSeekable->seek(offset);
517 return 0;
518 }
519 catch (...)
520 {
521 SAL_WARN("writerperfect", "mxSeekable->seek(offset) threw exception");
522 return -1;
523 }
524}
525
527{
528 if ((mnLength == 0) || !mxStream.is() || !mxSeekable.is())
529 return true;
530 return (mxSeekable->getPosition() >= mnLength);
531}
532
534{
535 if ((mnLength == 0) || !mxStream.is() || !mxSeekable.is())
536 return false;
537
538 PositionHolder pos(mxSeekable);
539 mxSeekable->seek(0);
540
541 if (isOLE())
542 return true;
543
544 mxSeekable->seek(0);
545
546 return isZip();
547}
548
550{
551 if ((mnLength == 0) || !mxStream.is() || !mxSeekable.is())
552 return 0;
553
554 PositionHolder pos(mxSeekable);
555 mxSeekable->seek(0);
556
557 if (isOLE())
558 {
560
561 return mpOLEStorage->maStreams.size();
562 }
563
564 mxSeekable->seek(0);
565
566 if (isZip())
567 {
569
570 return mpZipStorage->maStreams.size();
571 }
572
573 return 0;
574}
575
576const char* WPXSvInputStreamImpl::subStreamName(const unsigned id)
577{
578 if ((mnLength == 0) || !mxStream.is() || !mxSeekable.is())
579 return nullptr;
580
581 PositionHolder pos(mxSeekable);
582 mxSeekable->seek(0);
583
584 if (isOLE())
585 {
587
588 if (mpOLEStorage->maStreams.size() <= id)
589 return nullptr;
590
591 return mpOLEStorage->maStreams[id].RVNGname.getStr();
592 }
593
594 mxSeekable->seek(0);
595
596 if (isZip())
597 {
599
600 if (mpZipStorage->maStreams.size() <= id)
601 return nullptr;
602
603 return mpZipStorage->maStreams[id].aName.getStr();
604 }
605
606 return nullptr;
607}
608
610{
611 if (!name)
612 return false;
613
614 if ((mnLength == 0) || !mxStream.is() || !mxSeekable.is())
615 return false;
616
617 PositionHolder pos(mxSeekable);
618 mxSeekable->seek(0);
619
620 const OUString aName(OStringToOUString(std::string_view(name), RTL_TEXTENCODING_UTF8));
621
622 if (isOLE())
623 {
625 return mpOLEStorage->maNameMap.end() != mpOLEStorage->maNameMap.find(aName);
626 }
627
628 mxSeekable->seek(0);
629
630 if (isZip())
631 {
633 return mpZipStorage->maNameMap.end() != mpZipStorage->maNameMap.find(aName);
634 }
635
636 return false;
637}
638
639librevenge::RVNGInputStream* WPXSvInputStreamImpl::getSubStreamByName(const char* const name)
640{
641 if (!name)
642 return nullptr;
643
644 if ((mnLength == 0) || !mxStream.is() || !mxSeekable.is())
645 return nullptr;
646
647 PositionHolder pos(mxSeekable);
648 mxSeekable->seek(0);
649
650 const OUString aName(OStringToOUString(std::string_view(name), RTL_TEXTENCODING_UTF8));
651
652 if (isOLE())
653 {
655 return createWPXStream(mpOLEStorage->getStream(aName));
656 }
657
658 mxSeekable->seek(0);
659
660 if (isZip())
661 {
663
664 try
665 {
666 return createWPXStream(mpZipStorage->getStream(aName));
667 }
668 catch (const Exception&)
669 {
670 // nothing needed
671 }
672 }
673
674 return nullptr;
675}
676
677librevenge::RVNGInputStream* WPXSvInputStreamImpl::getSubStreamById(const unsigned id)
678{
679 if ((mnLength == 0) || !mxStream.is() || !mxSeekable.is())
680 return nullptr;
681
682 PositionHolder pos(mxSeekable);
683 mxSeekable->seek(0);
684
685 if (isOLE())
686 {
688
689 if (mpOLEStorage->maStreams.size() <= id)
690 return nullptr;
691
692 return createWPXStream(mpOLEStorage->getStream(id));
693 }
694
695 mxSeekable->seek(0);
696
697 if (isZip())
698 {
700
701 if (mpZipStorage->maStreams.size() <= id)
702 return nullptr;
703
704 try
705 {
706 return createWPXStream(mpZipStorage->getStream(id));
707 }
708 catch (const Exception&)
709 {
710 // nothing needed
711 }
712 }
713 return nullptr;
714}
715
717{
718 if (mpReadBuffer)
719 {
720 seek(tell() + static_cast<tools::Long>(mnReadBufferPos)
721 - static_cast<tools::Long>(mnReadBufferLength));
722 mpReadBuffer = nullptr;
723 mnReadBufferPos = 0;
725 }
726}
727
728librevenge::RVNGInputStream*
730{
731 if (rxStorage.is())
732 {
734 return new WPXSvInputStream(xContents);
735 }
736 return nullptr;
737}
738
739librevenge::RVNGInputStream*
741{
742 if (rxStream.is())
743 return new WPXSvInputStream(rxStream);
744 else
745 return nullptr;
746}
747
749{
750 if (!mbCheckedOLE)
751 {
752 assert(0 == mxSeekable->getPosition());
753
754 std::unique_ptr<SvStream> pStream(utl::UcbStreamHelper::CreateStream(mxStream));
755 if (pStream && SotStorage::IsOLEStorage(pStream.get()))
756 mpOLEStorage.reset(new OLEStorageImpl());
757
758 mbCheckedOLE = true;
759 }
760
761 return bool(mpOLEStorage);
762}
763
765{
766 if (!mbCheckedZip)
767 {
768 assert(0 == mxSeekable->getPosition());
769
770 try
771 {
773 UNO_SET_THROW);
775 xContext->getServiceManager()->createInstanceWithArgumentsAndContext(
776 "com.sun.star.packages.zip.ZipFileAccess", { Any(mxStream) }, xContext),
777 UNO_QUERY_THROW);
778 mpZipStorage.reset(new ZipStorageImpl(xZip));
779 }
780 catch (const Exception&)
781 {
782 // ignore
783 }
784
785 mbCheckedZip = true;
786 }
787
788 return bool(mpZipStorage);
789}
790
792{
793 assert(mpOLEStorage);
794
795 if (!mpOLEStorage->mbInitialized)
797}
798
800{
801 assert(mpZipStorage);
802
803 if (!mpZipStorage->mbInitialized)
804 mpZipStorage->initialize();
805}
806
808 : mpImpl(new WPXSvInputStreamImpl(xStream))
809{
810}
811
813
814#define BUFFER_MAX 65536
815
816const unsigned char* WPXSvInputStream::read(unsigned long numBytes, unsigned long& numBytesRead)
817{
818 numBytesRead = 0;
819
820 if (numBytes == 0 || numBytes > std::numeric_limits<unsigned long>::max() / 2)
821 return nullptr;
822
823 if (mpImpl->mpReadBuffer)
824 {
825 if ((mpImpl->mnReadBufferPos + numBytes > mpImpl->mnReadBufferPos)
826 && (mpImpl->mnReadBufferPos + numBytes <= mpImpl->mnReadBufferLength))
827 {
828 const unsigned char* pTmp = mpImpl->mpReadBuffer + mpImpl->mnReadBufferPos;
829 mpImpl->mnReadBufferPos += numBytes;
830 numBytesRead = numBytes;
831 return pTmp;
832 }
833
834 mpImpl->invalidateReadBuffer();
835 }
836
837 unsigned long curpos = static_cast<unsigned long>(mpImpl->tell());
838 if (curpos == static_cast<unsigned long>(-1)) // returned ERROR
839 return nullptr;
840
841 if ((curpos + numBytes < curpos) /*overflow*/
842 || (curpos + numBytes
843 >= o3tl::make_unsigned(mpImpl->mnLength))) /*reading more than available*/
844 {
845 numBytes = mpImpl->mnLength - curpos;
846 }
847
848 if (numBytes < BUFFER_MAX)
849 {
850 if (BUFFER_MAX < mpImpl->mnLength - curpos)
851 mpImpl->mnReadBufferLength = BUFFER_MAX;
852 else /* BUFFER_MAX >= mpImpl->mnLength - curpos */
853 mpImpl->mnReadBufferLength = mpImpl->mnLength - curpos;
854 }
855 else
856 mpImpl->mnReadBufferLength = numBytes;
857
858 unsigned long tmpNumBytes(0);
859 mpImpl->mpReadBuffer = mpImpl->read(mpImpl->mnReadBufferLength, tmpNumBytes);
860 if (tmpNumBytes != mpImpl->mnReadBufferLength)
861 mpImpl->mnReadBufferLength = tmpNumBytes;
862
863 mpImpl->mnReadBufferPos = 0;
864 if (!mpImpl->mnReadBufferLength)
865 return nullptr;
866
867 if (numBytes <= mpImpl->mnReadBufferLength)
868 numBytesRead = numBytes;
869 else
870 numBytesRead = mpImpl->mnReadBufferLength;
871
872 mpImpl->mnReadBufferPos += numBytesRead;
873 return mpImpl->mpReadBuffer;
874}
875
877{
878 tools::Long retVal = mpImpl->tell();
879 return retVal - static_cast<tools::Long>(mpImpl->mnReadBufferLength)
880 + static_cast<tools::Long>(mpImpl->mnReadBufferPos);
881}
882
883int WPXSvInputStream::seek(long offset, librevenge::RVNG_SEEK_TYPE seekType)
884{
885 sal_Int64 tmpOffset = offset;
886 if (seekType == librevenge::RVNG_SEEK_CUR)
887 tmpOffset += tell();
888 if (seekType == librevenge::RVNG_SEEK_END)
889 tmpOffset += mpImpl->mnLength;
890
891 int retVal = 0;
892 if (tmpOffset < 0)
893 {
894 tmpOffset = 0;
895 retVal = -1;
896 }
897 if (tmpOffset > mpImpl->mnLength)
898 {
899 tmpOffset = mpImpl->mnLength;
900 retVal = -1;
901 }
902
903 if (tmpOffset < mpImpl->tell()
904 && o3tl::make_unsigned(tmpOffset)
905 >= static_cast<unsigned long>(mpImpl->tell()) - mpImpl->mnReadBufferLength)
906 {
907 mpImpl->mnReadBufferPos = static_cast<unsigned long>(
908 tmpOffset + static_cast<tools::Long>(mpImpl->mnReadBufferLength) - mpImpl->tell());
909 return retVal;
910 }
911
912 mpImpl->invalidateReadBuffer();
913
914 if (mpImpl->seek(tmpOffset))
915 return -1;
916 return retVal;
917}
918
920{
921 return mpImpl->isEnd() && mpImpl->mnReadBufferPos == mpImpl->mnReadBufferLength;
922}
923
925{
926 mpImpl->invalidateReadBuffer();
927 return mpImpl->isStructured();
928}
929
931{
932 mpImpl->invalidateReadBuffer();
933 return mpImpl->subStreamCount();
934}
935
936const char* WPXSvInputStream::subStreamName(const unsigned id)
937{
938 mpImpl->invalidateReadBuffer();
939 return mpImpl->subStreamName(id);
940}
941
943{
944 mpImpl->invalidateReadBuffer();
945 return mpImpl->existsSubStream(name);
946}
947
948librevenge::RVNGInputStream* WPXSvInputStream::getSubStreamByName(const char* name)
949{
950 mpImpl->invalidateReadBuffer();
951 return mpImpl->getSubStreamByName(name);
952}
953
954librevenge::RVNGInputStream* WPXSvInputStream::getSubStreamById(const unsigned id)
955{
956 mpImpl->invalidateReadBuffer();
957 return mpImpl->getSubStreamById(id);
958}
959}
960
961/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
OString RVNGname
librevenge name of the stream.
Reference< XInputStream > xStream
OString aName
Name of the stream.
bool mbInitialized
::std::vector< OLEStreamData > maStreams
OString name
Name of the stream.
tools::SvRef< SotStorageStream > stream
Reference< container::XNameAccess > mxContainer
#define BUFFER_MAX
const Reference< XSeekable > mxSeekable
const sal_uInt64 mnPosition
tools::SvRef< SotStorage > mxRootStorage
OLEStorageMap_t maStorageMap
NameMap_t maNameMap
bool IsOLEStorage() const
T * get() const
bool is() const
static std::unique_ptr< SvStream > CreateStream(const OUString &rFileName, StreamMode eOpenMode, css::uno::Reference< css::awt::XWindow > xParentWin=nullptr)
static librevenge::RVNGInputStream * createWPXStream(const tools::SvRef< SotStorageStream > &rxStorage)
const unsigned char * read(unsigned long numBytes, unsigned long &numBytesRead)
librevenge::RVNGInputStream * getSubStreamById(unsigned id)
std::unique_ptr< OLEStorageImpl > mpOLEStorage
css::uno::Reference< css::io::XInputStream > mxStream
std::unique_ptr< ZipStorageImpl > mpZipStorage
librevenge::RVNGInputStream * getSubStreamByName(const char *name)
const char * subStreamName(unsigned id)
css::uno::Reference< css::io::XSeekable > mxSeekable
css::uno::Sequence< sal_Int8 > maData
virtual bool existsSubStream(const char *name) override
virtual bool isStructured() override
virtual WRITERPERFECT_DLLPUBLIC const unsigned char * read(unsigned long numBytes, unsigned long &numBytesRead) override
virtual const char * subStreamName(unsigned id) override
virtual WRITERPERFECT_DLLPUBLIC int seek(long offset, librevenge::RVNG_SEEK_TYPE seekType) override
virtual unsigned subStreamCount() override
std::unique_ptr< WPXSvInputStreamImpl > mpImpl
virtual librevenge::RVNGInputStream * getSubStreamByName(const char *name) override
WRITERPERFECT_DLLPUBLIC WPXSvInputStream(css::uno::Reference< css::io::XInputStream > const &xStream)
virtual librevenge::RVNGInputStream * getSubStreamById(unsigned id) override
virtual WRITERPERFECT_DLLPUBLIC ~WPXSvInputStream() override
const long LONG_MAX
#define SAL_WARN(area, stream)
std::vector< sal_Int8, boost::noinit_adaptor< std::allocator< sal_Int8 > > > maData
@ Exception
Reference< XComponentContext > getProcessComponentContext()
constexpr std::enable_if_t< std::is_signed_v< T >, std::make_unsigned_t< T > > make_unsigned(T value)
OString OUStringToOString(std::u16string_view str, ConnectionSettings const *settings)
long Long
sal_Int16 nId
std::vector< SvStorageInfo > SvStorageInfoList
size_t pos