make copying aware of NULL pointers

This commit is contained in:
David Tardon 2010-12-24 12:33:33 +01:00
parent eb13a88164
commit 9192e5de7d
5 changed files with 98 additions and 13 deletions

View file

@ -0,0 +1,82 @@
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* Version: MPL 1.1 / GPLv3+ / LGPLv3+
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (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.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Initial Developer of the Original Code is
* Red Hat, Inc.
* Portions created by the Initial Developer are Copyright (C) 2010 the
* Initial Developer. All Rights Reserved.
*
* Contributor(s): David Tardon <dtardon@redhat.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 3 or later (the "GPLv3+"), or
* the GNU Lesser General Public License Version 3 or later (the "LGPLv3+"),
* in which case the provisions of the GPLv3+ or the LGPLv3+ are applicable
* instead of those above.
*/
namespace detail
{
template<typename T>
struct has_clone
{
template<typename U, U x>
struct test;
typedef char yes;
typedef struct { char a[2]; } no;
template<typename U>
static yes check_sig(U*, test<U* (U::*)() const, &U::clone>* = 0);
template<typename U>
static no check_sig(...);
static bool const value = sizeof(has_clone<T>::template check_sig<T>(0)) == sizeof(yes);
};
template<typename T, bool HasClone>
struct cloner
{
static T* clone(T* const other)
{
return new T(*other);
}
};
template<typename T>
struct cloner<T, true>
{
static T* clone(T* const other)
{
return other->clone();
}
};
}
/** Creates a new copy of the passed object.
If other is 0, just returns 0. Otherwise, if other has function
named clone with signature T* (T::*)() const, the function is called.
Otherwise, copy constructor is used.
@returns 0 or newly allocated object
*/
template<typename T>
T* clone(T* const other)
{
return other ? detail::cloner<T, detail::has_clone<T>::value>::clone(other) : 0;
}
// vim: set sts=4 sw=4 et:

View file

@ -64,6 +64,7 @@
#include <memory>
#include "clone.hxx"
#include "lwpbreaksoverride.hxx"
#include "lwpobjstrm.hxx"
#include "lwpatomholder.hxx"
@ -78,7 +79,7 @@ LwpBreaksOverride::LwpBreaksOverride(LwpBreaksOverride const& rOther)
: LwpOverride(rOther)
, m_pNextStyle(0)
{
std::auto_ptr<LwpAtomHolder> pNextStyle(new LwpAtomHolder(*rOther.m_pNextStyle));
std::auto_ptr<LwpAtomHolder> pNextStyle(::clone(rOther.m_pNextStyle));
m_pNextStyle = pNextStyle.release();
}

View file

@ -64,6 +64,7 @@
#include <memory>
#include "clone.hxx"
#include "lwpcharborderoverride.hxx"
#include "lwpborderstuff.hxx"
#include "lwpmargins.hxx"
@ -80,8 +81,8 @@ LwpCharacterBorderOverride::LwpCharacterBorderOverride(LwpCharacterBorderOverrid
, m_nAboveWidth(rOther.m_nAboveWidth)
, m_nBelowWidth(rOther.m_nBelowWidth)
{
std::auto_ptr<LwpBorderStuff> pBorderStuff(new LwpBorderStuff(*rOther.m_pBorderStuff));
std::auto_ptr<LwpMargins> pMargins(new LwpMargins(*rOther.m_pMargins));
std::auto_ptr<LwpBorderStuff> pBorderStuff(::clone(rOther.m_pBorderStuff));
std::auto_ptr<LwpMargins> pMargins(::clone(rOther.m_pMargins));
m_pBorderStuff = pBorderStuff.release();
m_pMargins = pMargins.release();
}

View file

@ -64,6 +64,7 @@
#include <memory>
#include "clone.hxx"
#include "lwpoverride.hxx"
#include "lwpfilehdr.hxx"
#include "lwpatomholder.hxx"
@ -387,10 +388,10 @@ LwpSpacingOverride::LwpSpacingOverride(LwpSpacingOverride const& rOther)
, m_pParaSpacingAbove(0)
, m_pParaSpacingBelow(0)
{
std::auto_ptr<LwpSpacingCommonOverride> pSpacing(rOther.m_pSpacing->clone());
std::auto_ptr<LwpSpacingCommonOverride> pAboveLineSpacing(rOther.m_pAboveLineSpacing->clone());
std::auto_ptr<LwpSpacingCommonOverride> pParaSpacingAbove(rOther.m_pParaSpacingAbove->clone());
std::auto_ptr<LwpSpacingCommonOverride> pParaSpacingBelow(rOther.m_pParaSpacingBelow->clone());
std::auto_ptr<LwpSpacingCommonOverride> pSpacing(::clone(rOther.m_pSpacing));
std::auto_ptr<LwpSpacingCommonOverride> pAboveLineSpacing(::clone(rOther.m_pAboveLineSpacing));
std::auto_ptr<LwpSpacingCommonOverride> pParaSpacingAbove(::clone(rOther.m_pParaSpacingAbove));
std::auto_ptr<LwpSpacingCommonOverride> pParaSpacingBelow(::clone(rOther.m_pParaSpacingBelow));
m_pSpacing = pSpacing.release();
m_pAboveLineSpacing = pAboveLineSpacing.release();
m_pParaSpacingAbove = pParaSpacingAbove.release();
@ -469,8 +470,7 @@ LwpAmikakeOverride::LwpAmikakeOverride(LwpAmikakeOverride const& rOther)
, m_pBackgroundStuff(0)
, m_nType(rOther.m_nType)
{
std::auto_ptr<LwpBackgroundStuff> pBackgroundStuff(
new LwpBackgroundStuff(*rOther.m_pBackgroundStuff));
std::auto_ptr<LwpBackgroundStuff> pBackgroundStuff(::clone(rOther.m_pBackgroundStuff));
m_pBackgroundStuff = pBackgroundStuff.release();
}

View file

@ -64,6 +64,7 @@
#include <memory>
#include "clone.hxx"
#include "lwpparaborderoverride.hxx"
#include "lwpborderstuff.hxx"
#include "lwpshadow.hxx"
@ -105,10 +106,10 @@ LwpParaBorderOverride::LwpParaBorderOverride(LwpParaBorderOverride const& rOther
, m_nRightWidth(rOther.m_nRightWidth)
, m_nBetweenMargin(rOther.m_nBetweenMargin)
{
std::auto_ptr<LwpBorderStuff> pBorderStuff(new LwpBorderStuff(*rOther.m_pBorderStuff));
std::auto_ptr<LwpBorderStuff> pBetweenStuff(new LwpBorderStuff(*rOther.m_pBetweenStuff));
std::auto_ptr<LwpShadow> pShadow(new LwpShadow(*rOther.m_pShadow));
std::auto_ptr<LwpMargins> pMargins(new LwpMargins(*rOther.m_pMargins));
std::auto_ptr<LwpBorderStuff> pBorderStuff(::clone(rOther.m_pBorderStuff));
std::auto_ptr<LwpBorderStuff> pBetweenStuff(::clone(rOther.m_pBetweenStuff));
std::auto_ptr<LwpShadow> pShadow(::clone(rOther.m_pShadow));
std::auto_ptr<LwpMargins> pMargins(::clone(rOther.m_pMargins));
m_pBorderStuff = pBorderStuff.release();
m_pBetweenStuff = pBetweenStuff.release();
m_pShadow = pShadow.release();