[Libreoffice-commits] core.git: include/editeng include/o3tl
Noel Grandin (via logerrit)
logerrit at kemper.freedesktop.org
Wed Aug 18 10:09:45 UTC 2021
include/editeng/outlobj.hxx | 90 +++++++++++++++++++++++++++++++++++++++++--
include/o3tl/cow_wrapper.hxx | 27 ++++++++++++
2 files changed, 113 insertions(+), 4 deletions(-)
New commits:
commit 62d11b0e072b2f34b9f52c33a73cbb54d8112307
Author: Noel Grandin <noel.grandin at collabora.co.uk>
AuthorDate: Mon Aug 16 18:47:58 2021 +0200
Commit: Noel Grandin <noel.grandin at collabora.co.uk>
CommitDate: Wed Aug 18 12:09:09 2021 +0200
specialise std::optional for OutlineParaObject
we can re-use the o3tl::wrapper pointer to indicate empty
Change-Id: I26e502a7dacfb2bd3d465e71c8fdd89a6a80969b
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/120553
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin at collabora.co.uk>
diff --git a/include/editeng/outlobj.hxx b/include/editeng/outlobj.hxx
index fac9bed9ffb9..8ba1dedb3f16 100644
--- a/include/editeng/outlobj.hxx
+++ b/include/editeng/outlobj.hxx
@@ -17,8 +17,7 @@
* the License at http://www.apache.org/licenses/LICENSE-2.0 .
*/
-#ifndef INCLUDED_EDITENG_OUTLOBJ_HXX
-#define INCLUDED_EDITENG_OUTLOBJ_HXX
+#pragma once
#include <editeng/paragraphdata.hxx>
#include <editeng/editengdllapi.h>
@@ -26,6 +25,7 @@
#include <svl/poolitem.hxx>
#include <svl/style.hxx>
#include <o3tl/cow_wrapper.hxx>
+#include <stdexcept>
#include <memory>
class EditTextObject;
@@ -36,7 +36,7 @@ enum class TextRotation;
* This is the guts of OutlinerParaObject, refcounted and shared among
* multiple instances of OutlinerParaObject.
*/
-struct OutlinerParaObjData
+struct EDITENG_DLLPUBLIC OutlinerParaObjData
{
// data members
std::unique_ptr<EditTextObject> mpEditTextObject;
@@ -64,8 +64,14 @@ struct OutlinerParaObjData
class EDITENG_DLLPUBLIC OutlinerParaObject
{
+friend class std::optional<OutlinerParaObject>;
::o3tl::cow_wrapper< OutlinerParaObjData > mpImpl;
+ OutlinerParaObject(std::nullopt_t) noexcept
+ : mpImpl(std::nullopt) {}
+ OutlinerParaObject( const OutlinerParaObject& other, std::nullopt_t ) noexcept
+ : mpImpl(other.mpImpl, std::nullopt) {}
+
public:
// constructors/destructor
OutlinerParaObject(std::unique_ptr<EditTextObject>, const ParagraphDataVector&, bool bIsEditDoc);
@@ -117,6 +123,82 @@ public:
void dumpAsXml(xmlTextWriterPtr pWriter) const;
};
-#endif
+namespace std
+{
+ /** Specialise std::optional template for the case where we are wrapping a o3tl::cow_wrapper
+ type, and we can make the pointer inside the cow_wrapper act as an empty value,
+ and save ourselves some storage */
+ template<>
+ class optional<OutlinerParaObject>
+ {
+ public:
+ optional() noexcept : maParaObject(std::nullopt) {}
+ optional(std::nullopt_t) noexcept : maParaObject(std::nullopt) {}
+ optional(const optional& other) :
+ maParaObject(other.maParaObject, std::nullopt) {}
+ optional(optional&& other) noexcept :
+ maParaObject(std::move(other.maParaObject)) {}
+ optional(OutlinerParaObject&& para) noexcept :
+ maParaObject(std::move(para)) {}
+ optional(const OutlinerParaObject& para) noexcept :
+ maParaObject(para) {}
+ template< class... Args >
+ explicit optional( std::in_place_t, Args&&... args ) :
+ maParaObject(std::forward<Args>(args)...) {}
+
+ optional& operator=(optional const & other)
+ {
+ maParaObject = other.maParaObject;
+ return *this;
+ }
+ optional& operator=(optional&& other) noexcept
+ {
+ maParaObject = std::move(other.maParaObject);
+ return *this;
+ }
+ template< class... Args >
+ void emplace(Args&&... args )
+ {
+ maParaObject = OutlinerParaObject(std::forward<Args>(args)...);
+ }
+
+ bool has_value() const noexcept { return !maParaObject.mpImpl.empty(); }
+ explicit operator bool() const noexcept { return !maParaObject.mpImpl.empty(); }
+ void reset() { maParaObject.mpImpl.set_empty(); }
+
+ OutlinerParaObject& value()
+ {
+ throwIfEmpty();
+ return maParaObject;
+ }
+ OutlinerParaObject& operator*()
+ {
+ throwIfEmpty();
+ return maParaObject;
+ }
+ const OutlinerParaObject& operator*() const
+ {
+ throwIfEmpty();
+ return maParaObject;
+ }
+ OutlinerParaObject* operator->()
+ {
+ throwIfEmpty();
+ return &maParaObject;
+ }
+ const OutlinerParaObject* operator->() const
+ {
+ throwIfEmpty();
+ return &maParaObject;
+ }
+ private:
+ void throwIfEmpty() const
+ {
+ if (maParaObject.mpImpl.empty())
+ throw std::logic_error("empty std::optional<OutlinerParaObject>");
+ }
+ OutlinerParaObject maParaObject;
+ };
+};
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/include/o3tl/cow_wrapper.hxx b/include/o3tl/cow_wrapper.hxx
index c05d28699259..ced27c1fda32 100644
--- a/include/o3tl/cow_wrapper.hxx
+++ b/include/o3tl/cow_wrapper.hxx
@@ -22,6 +22,7 @@
#include <osl/interlck.h>
+#include <optional>
#include <utility>
#include <cstddef>
@@ -252,6 +253,20 @@ int cow_wrapper_client::queryUnmodified() const
rSrc.m_pimpl = nullptr;
}
+ // Only intended to be used by std::optional specialisations
+ explicit cow_wrapper( std::nullopt_t ) noexcept :
+ m_pimpl( nullptr )
+ {
+ }
+
+ // Only intended to be used by std::optional specialisations
+ explicit cow_wrapper( const cow_wrapper& rSrc, std::nullopt_t ) : // nothrow
+ m_pimpl( rSrc.m_pimpl )
+ {
+ if (m_pimpl)
+ MTPolicy::incrementCount( m_pimpl->m_ref_count );
+ }
+
~cow_wrapper() // nothrow, if ~T does not throw
{
release();
@@ -325,6 +340,18 @@ int cow_wrapper_client::queryUnmodified() const
return rOther.m_pimpl == m_pimpl;
}
+ // Only intended to be used by std::optional specialisations
+ bool empty() const { return m_pimpl == nullptr; }
+ // Only intended to be used by std::optional specialisations
+ void set_empty()
+ {
+ if (m_pimpl)
+ {
+ release();
+ m_pimpl = nullptr;
+ }
+ }
+
private:
impl_t* m_pimpl;
};
More information about the Libreoffice-commits
mailing list