summaryrefslogtreecommitdiffstats
path: root/sc/source/filter/inc/xerecord.hxx
diff options
context:
space:
mode:
Diffstat (limited to 'sc/source/filter/inc/xerecord.hxx')
-rw-r--r--sc/source/filter/inc/xerecord.hxx421
1 files changed, 421 insertions, 0 deletions
diff --git a/sc/source/filter/inc/xerecord.hxx b/sc/source/filter/inc/xerecord.hxx
new file mode 100644
index 000000000..c6901e7fb
--- /dev/null
+++ b/sc/source/filter/inc/xerecord.hxx
@@ -0,0 +1,421 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#pragma once
+
+#include "xlconst.hxx"
+#include "xestream.hxx"
+#include "xlstream.hxx"
+#include <salhelper/simplereferenceobject.hxx>
+#include <rtl/ref.hxx>
+#include <algorithm>
+
+// Base classes to export Excel records =======================================
+
+/** Base class for all Excel records.
+
+ Derive from this class to implement any functionality performed during
+ saving the records - except really writing a record (i.e. write a list of
+ records contained in the class). Derive from XclExpRecord (instead from
+ this class) to write common records.
+ */
+class XclExpRecordBase : public salhelper::SimpleReferenceObject
+{
+public:
+ XclExpRecordBase() {}
+
+ // this class is stored both ref-counted and by value
+ XclExpRecordBase(XclExpRecordBase const &)
+ : salhelper::SimpleReferenceObject() {}
+ XclExpRecordBase(XclExpRecordBase &&)
+ : salhelper::SimpleReferenceObject() {}
+ XclExpRecordBase& operator=(XclExpRecordBase const &)
+ { return *this; }
+ XclExpRecordBase& operator=(XclExpRecordBase &&) noexcept
+ { return *this; }
+
+ virtual ~XclExpRecordBase();
+
+ /** Overwrite this method to do any operation while saving the record. */
+ virtual void Save( XclExpStream& rStrm );
+ virtual void SaveXml( XclExpXmlStream& rStrm );
+};
+
+/*namespace std
+{
+ template<typename T,
+ typename = typename std::enable_if<
+ std::is_base_of<XclExpRecordBase,T>::value
+ >::type>
+ class shared_ptr
+ {
+ shared_ptr() {}
+ };
+};*/
+
+class XclExpDelegatingRecord : public XclExpRecordBase
+{
+public:
+ XclExpDelegatingRecord( XclExpRecordBase* pRecord );
+ virtual ~XclExpDelegatingRecord() override;
+
+ virtual void SaveXml( XclExpXmlStream& rStrm ) override;
+private:
+ XclExpRecordBase* mpRecord;
+};
+
+class XclExpXmlElementRecord : public XclExpRecordBase
+{
+public:
+ explicit XclExpXmlElementRecord(sal_Int32 nElement);
+ virtual ~XclExpXmlElementRecord() override;
+
+protected:
+ sal_Int32 mnElement;
+};
+
+class XclExpXmlStartElementRecord : public XclExpXmlElementRecord
+{
+public:
+ explicit XclExpXmlStartElementRecord(sal_Int32 nElement);
+ virtual ~XclExpXmlStartElementRecord() override;
+
+ /** Starts the element nElement */
+ virtual void SaveXml( XclExpXmlStream& rStrm ) override;
+};
+
+class XclExpXmlEndElementRecord : public XclExpXmlElementRecord
+{
+public:
+ explicit XclExpXmlEndElementRecord(sal_Int32 nElement);
+ virtual ~XclExpXmlEndElementRecord() override;
+
+ /** Ends the element nElement */
+ virtual void SaveXml( XclExpXmlStream& rStrm ) override;
+};
+
+class XclExpXmlStartSingleElementRecord : public XclExpXmlElementRecord
+{
+public:
+ explicit XclExpXmlStartSingleElementRecord(sal_Int32 nElement);
+ virtual ~XclExpXmlStartSingleElementRecord() override;
+
+ /** Starts the single element nElement */
+ virtual void SaveXml( XclExpXmlStream& rStrm ) override;
+};
+
+class XclExpXmlEndSingleElementRecord : public XclExpRecordBase
+{
+public:
+ XclExpXmlEndSingleElementRecord();
+ virtual ~XclExpXmlEndSingleElementRecord() override;
+
+ /** Ends the single element nElement */
+ virtual void SaveXml( XclExpXmlStream& rStrm ) override;
+};
+
+/** Base class for single records with any content.
+
+ This class handles writing the record header. Derived classes only have to
+ write the record body. Calculating the record size before saving optimizes
+ the write process (the stream does not have to seek back and update the
+ written record size). But it is not required to calculate a valid size
+ (maybe it would be too complex or just impossible until the record is
+ really written).
+ */
+class XclExpRecord : public XclExpRecordBase
+{
+public:
+ /** @param nRecId The record ID of this record. May be set later with SetRecId().
+ @param nRecSize The predicted record size. May be set later with SetRecSize(). */
+ explicit XclExpRecord(
+ sal_uInt16 nRecId = EXC_ID_UNKNOWN,
+ std::size_t nRecSize = 0 );
+
+ XclExpRecord(XclExpRecord const &) = default;
+
+ virtual ~XclExpRecord() override;
+
+ /** Returns the current record ID. */
+ sal_uInt16 GetRecId() const { return mnRecId; }
+ /** Returns the current record size prediction. */
+ std::size_t GetRecSize() const { return mnRecSize; }
+
+ /** Sets a new record ID. */
+ void SetRecId( sal_uInt16 nRecId ) { mnRecId = nRecId; }
+ /** Sets a new record size prediction. */
+ void SetRecSize( std::size_t nRecSize ) { mnRecSize = nRecSize; }
+ /** Adds a size value to the record size prediction. */
+ void AddRecSize( std::size_t nRecSize ) { mnRecSize += nRecSize; }
+ /** Sets record ID and size with one call. */
+ void SetRecHeader( sal_uInt16 nRecId, std::size_t nRecSize );
+
+ /** Writes the record header and calls WriteBody(). */
+ virtual void Save( XclExpStream& rStrm ) override;
+
+protected:
+ /** Writes the body of the record (without record header).
+ @descr Usually this method will be overwritten by derived classes. */
+ virtual void WriteBody( XclExpStream& rStrm );
+
+private:
+ std::size_t mnRecSize; /// The predicted record size.
+ sal_uInt16 mnRecId; /// The record ID.
+};
+
+/** A record without body. Only the record ID and the size 0 will be written. */
+class XclExpEmptyRecord : public XclExpRecord
+{
+public:
+ /** @param nRecId The record ID of this record. */
+ inline explicit XclExpEmptyRecord( sal_uInt16 nRecId );
+};
+
+inline XclExpEmptyRecord::XclExpEmptyRecord( sal_uInt16 nRecId ) :
+ XclExpRecord( nRecId, 0 )
+{
+}
+
+/** A record with a single value of type Type.
+ @descr Requires operator<<( XclExpStream&, const Type& ). */
+template< typename Type >
+class XclExpValueRecord : public XclExpRecord
+{
+public:
+ /** @param nRecId The record ID of this record.
+ @param rValue The value for the record body.
+ @param nSize Record size. Uses sizeof( Type ), if this parameter is omitted. */
+ explicit XclExpValueRecord( sal_uInt16 nRecId, const Type& rValue, std::size_t nSize = sizeof( Type ) ) :
+ XclExpRecord( nRecId, nSize ), maValue( rValue ), mnAttribute( -1 ) {}
+
+ /** Returns the value of the record. */
+ const Type& GetValue() const { return maValue; }
+ /** Sets a new record value. */
+ void SetValue( const Type& rValue ) { maValue = rValue; }
+
+ /** Sets the OOXML attribute this record corresponds to */
+ XclExpValueRecord* SetAttribute( sal_Int32 nId );
+
+ /** Write the OOXML attribute and its value */
+ void SaveXml( XclExpXmlStream& rStrm ) override;
+
+private:
+ /** Writes the body of the record. */
+ virtual void WriteBody( XclExpStream& rStrm ) override { rStrm << maValue; }
+ // inlining prevents warning in wntmsci10
+
+private:
+ Type maValue; /// The record data.
+ sal_Int32 mnAttribute; /// The OOXML attribute Id
+};
+
+template< typename Type >
+void XclExpValueRecord< Type >::SaveXml( XclExpXmlStream& rStrm )
+{
+ if( mnAttribute == -1 )
+ return;
+ rStrm.WriteAttributes(mnAttribute, OUString::number(maValue));
+}
+
+template<>
+void XclExpValueRecord<double>::SaveXml( XclExpXmlStream& rStrm );
+
+template< typename Type >
+XclExpValueRecord< Type >* XclExpValueRecord< Type >::SetAttribute( sal_Int32 nId )
+{
+ mnAttribute = nId;
+ return this;
+}
+
+/** A record containing an unsigned 16-bit value. */
+typedef XclExpValueRecord< sal_uInt16 > XclExpUInt16Record;
+
+/** A record containing a double value. */
+typedef XclExpValueRecord< double > XclExpDoubleRecord;
+
+/** Record which contains a Boolean value.
+ @descr The value is stored as 16-bit value: 0x0000 = sal_False, 0x0001 = TRUE. */
+class XclExpBoolRecord : public XclExpRecord
+{
+public:
+ /** @param nRecId The record ID of this record.
+ @param nValue The value for the record body. */
+ explicit XclExpBoolRecord( sal_uInt16 nRecId, bool bValue, sal_Int32 nAttribute = -1 ) :
+ XclExpRecord( nRecId, 2 ), mbValue( bValue ), mnAttribute( nAttribute ) {}
+
+ /** Returns the Boolean value of the record. */
+ bool GetBool() const { return mbValue; }
+
+ virtual void SaveXml( XclExpXmlStream& rStrm ) override;
+
+private:
+ /** Writes the body of the record. */
+ virtual void WriteBody( XclExpStream& rStrm ) override;
+
+private:
+ bool mbValue; /// The record data.
+ sal_Int32 mnAttribute; /// The attribute to generate within SaveXml()
+};
+
+/** Record which exports a memory data array. */
+class XclExpDummyRecord : public XclExpRecord
+{
+public:
+ /** @param nRecId The record ID of this record.
+ @param pRecData Pointer to the data array representing the record body.
+ @param nRecSize Size of the data array. */
+ explicit XclExpDummyRecord(
+ sal_uInt16 nRecId, const void* pRecData, std::size_t nRecSize );
+
+ /** Sets a data array. */
+ void SetData( const void* pRecData, std::size_t nRecSize );
+
+private:
+ /** Writes the body of the record. */
+ virtual void WriteBody( XclExpStream& rStrm ) override;
+
+private:
+ const void* mpData; /// The record data.
+};
+
+// Future records =============================================================
+
+class XclExpFutureRecord : public XclExpRecord
+{
+public:
+ explicit XclExpFutureRecord( XclFutureRecType eRecType,
+ sal_uInt16 nRecId, std::size_t nRecSize );
+
+ /** Writes the extended record header and calls WriteBody(). */
+ virtual void Save( XclExpStream& rStrm ) override;
+
+private:
+ XclFutureRecType meRecType;
+};
+
+// List of records ============================================================
+
+/** A list of Excel record objects.
+
+ Provides saving the compete list. This class is derived from
+ XclExpRecordBase, so it can be used as record in another record list.
+ Requires RecType::Save( XclExpStream& ).
+ */
+template< typename RecType = XclExpRecordBase >
+class XclExpRecordList : public XclExpRecordBase
+{
+public:
+ typedef rtl::Reference< RecType > RecordRefType;
+
+ bool IsEmpty() const { return maRecs.empty(); }
+ size_t GetSize() const { return maRecs.size(); }
+
+ /** Returns true, if the passed index points to an exiting record. */
+ bool HasRecord( size_t nPos ) const
+ { return nPos < maRecs.size(); }
+ /** Returns reference to an existing record or empty reference on error. */
+ RecType* GetRecord( size_t nPos ) const
+ { return nPos < maRecs.size() ? maRecs[ nPos ].get() : nullptr; }
+ /** Returns reference to the first existing record or empty reference, if list is empty. */
+ RecType* GetFirstRecord() const
+ { return maRecs.empty() ? nullptr : maRecs.front().get(); }
+ /** Returns reference to the last existing record or empty reference, if list is empty. */
+ RecType* GetLastRecord() const
+ { return maRecs.empty() ? nullptr : maRecs.back().get(); }
+
+ /** Inserts a record at the specified position into the list. */
+ void InsertRecord( RecType* pRec, size_t nPos )
+ { assert(pRec); maRecs.insert( maRecs.begin() + ::std::min( nPos, maRecs.size() ), pRec ); }
+ void InsertRecord( RecordRefType pRec, size_t nPos )
+ { assert(pRec); maRecs.insert( maRecs.begin() + ::std::min( nPos, maRecs.size() ), std::move(pRec) ); }
+ /** Appends a record to the list. */
+ void AppendRecord( RecType* pRec )
+ { if (pRec) maRecs.push_back( pRec ); }
+ void AppendRecord( const RecordRefType& xRec )
+ { if (xRec) maRecs.push_back( xRec.get() ); }
+ void AppendRecord( RecordRefType xRec ) &&
+ { if (xRec) maRecs.push_back( std::move(xRec) ); }
+ /** Replaces the record at the specified position from the list with the passed record. */
+ void ReplaceRecord( RecType* pRec, size_t nPos )
+ { if (pRec) maRecs[nPos] = pRec; else RemoveRecord( nPos ); }
+ void ReplaceRecord( RecordRefType const & xRec, size_t nPos )
+ { ReplaceRecord(xRec.get(), nPos); }
+
+ /** Appends a newly created record to the list. */
+ void AppendNewRecord( RecType* pRec )
+ { assert(pRec); maRecs.push_back( pRec ); }
+ void AppendNewRecord( RecordRefType const & xRec )
+ { AppendNewRecord(xRec.get()); }
+ void AppendNewRecord( RecordRefType xRec ) &&
+ { assert(xRec); maRecs.append(std::move(xRec)); }
+
+ /** Removes the record at the specified position from the list. */
+ void RemoveRecord( size_t nPos )
+ { maRecs.erase( maRecs.begin() + nPos ); }
+ /** Removes all records from the list. */
+ void RemoveAllRecords() { maRecs.clear(); }
+
+ /** Writes the complete record list. */
+ virtual void Save( XclExpStream& rStrm ) override
+ {
+ // inlining prevents warning in wntmsci10
+ for( typename RecordVec::iterator aIt = maRecs.begin(), aEnd = maRecs.end(); aIt != aEnd; ++aIt )
+ (*aIt)->Save( rStrm );
+ }
+
+ virtual void SaveXml( XclExpXmlStream& rStrm ) override
+ {
+ // inlining prevents warning in wntmsci10
+ for( typename RecordVec::iterator aIt = maRecs.begin(), aEnd = maRecs.end(); aIt != aEnd; ++aIt )
+ (*aIt)->SaveXml( rStrm );
+ }
+
+ /**
+ Optimization for repeated removal. Since this is internally a vector, repeated RemoveRecord()
+ would repeatedly move all items after the removed position. Instead it's possible to invalidate
+ a record and then call RemoveInvalidatedRecords() at the end (which is necessary, the list is generally
+ not allowed to contain invalid entries).
+ */
+ void InvalidateRecord( size_t nPos ) { maRecs[ nPos ] = nullptr; }
+ void RemoveInvalidatedRecords()
+ {
+ maRecs.erase(
+ std::remove_if( maRecs.begin(), maRecs.end(), [](const RecordRefType& xRec) { return xRec == nullptr; } ),
+ maRecs.end());
+ }
+
+private:
+ typedef ::std::vector< RecordRefType > RecordVec;
+ RecordVec maRecs;
+};
+
+/** Represents a complete substream of records enclosed into a pair of BOF/EOF records. */
+class XclExpSubStream : public XclExpRecordList<>
+{
+public:
+ explicit XclExpSubStream( sal_uInt16 nSubStrmType );
+
+ /** Writes the complete substream, including leading BOF and trailing EOF. */
+ virtual void Save( XclExpStream& rStrm ) override;
+
+private:
+ sal_uInt16 mnSubStrmType; /// Substream type, stored in leading BOF record.
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */