From 06b8a3a14a89c5e9e33b7232c8646b93466be79a Mon Sep 17 00:00:00 2001 From: Mike Fleetwood Date: Tue, 16 Jun 2015 22:34:59 +0100 Subject: [PATCH] Use pointers to Partitions in PartitionVector class (#759726) The PartitionVector class is now internally using pointers to Partition objects and taking on management of their lifetimes. It therefore has to implement the Big 3: destructor, copy constructor and copy assignment operator [1][2]. This is because the implicitly-defined copy constructor and assignment operator perform memberwise "shallow copying" and the destructor does nothing. This not correct for classes which contain non-class types such as raw pointers. The semantics of the interface still copies each Partition object into the PartitionVector when they are added with push_back() and insert(). Note that a PartitionVector object is explicitly copy assigned in Win_GParted::Refresh_Visual(). They are also implicitly copied when (1) the implementing vector is resized larger to allow it to hold more pointers to Partition objects than it previously had capacity for; and (2) a Partition object is copied including the logicals PartitionVector member. [1] The rule of three/five/zero http://en.cppreference.com/w/cpp/language/rule_of_three [2] Rule of Three https://en.wikipedia.org/wiki/Rule_of_three_%28C%2B%2B_programming%29 Bug 759726 - Implement Partition object polymorphism --- include/PartitionVector.h | 34 ++++++++------- po/POTFILES.in | 1 + src/Makefile.am | 1 + src/PartitionVector.cc | 88 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 108 insertions(+), 16 deletions(-) create mode 100644 src/PartitionVector.cc diff --git a/include/PartitionVector.h b/include/PartitionVector.h index 3a3addf6..f1d6c33e 100644 --- a/include/PartitionVector.h +++ b/include/PartitionVector.h @@ -14,9 +14,9 @@ * along with this program; if not, see . */ -/* Minimal implementation of a class that behaves like a std::vector which can - * be used in it's place with minimal change to the existing GParted code which expects to - * be working with a std::vector. +/* Minimal implementation of a class with some behaviours like a std::vector. + * However internally the class manages pointers to Partition objects allowing for + * Partition object polymorphism. * Reference: * C++ Reference to std::vector * http://www.cplusplus.com/reference/vector/vector/ @@ -44,10 +44,13 @@ class PartitionVector; // mutually recursive classes. class PartitionVector { public: typedef size_t size_type; - typedef std::vector::iterator iterator; + typedef std::vector::iterator iterator; PartitionVector() {}; - ~PartitionVector() {}; + PartitionVector( const PartitionVector & src ); + ~PartitionVector(); + void swap( PartitionVector & other ); + PartitionVector & operator=( PartitionVector rhs ); // Iterators iterator begin() { return v.begin(); }; @@ -56,22 +59,21 @@ public: bool empty() const { return v.empty(); }; // Element access - Partition & operator[]( size_type n ) { return v[n]; }; - const Partition & operator[]( size_type n ) const { return v[n]; }; + Partition & operator[]( size_type n ) { return *v[n]; }; + const Partition & operator[]( size_type n ) const { return *v[n]; }; size_type size() const { return v.size(); }; - const Partition & front() const { return v.front(); }; - const Partition & back() const { return v.back(); }; + const Partition & front() const { return *v.front(); }; + const Partition & back() const { return *v.back(); }; // Modifiers - void pop_back() { v.pop_back(); }; - void erase( const iterator position ) { v.erase( position ); }; - void clear() { v.clear(); }; - void push_back( const Partition & partition ) { v.push_back( partition ); }; - void insert( iterator position, const Partition & partition ) - { v.insert( position, partition ); }; + void pop_back(); + void erase( const iterator position ); + void clear(); + void push_back( const Partition & partition ); + void insert( iterator position, const Partition & partition ); private: - std::vector v; + std::vector v; }; } //GParted diff --git a/po/POTFILES.in b/po/POTFILES.in index 29741cf1..d7172e45 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -31,6 +31,7 @@ src/OperationLabelFileSystem.cc src/OperationNamePartition.cc src/OperationResizeMove.cc src/Partition.cc +src/PartitionVector.cc src/SWRaid_Info.cc src/TreeView_Detail.cc src/Utils.cc diff --git a/src/Makefile.am b/src/Makefile.am index 0d9cd362..1e19f66c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -47,6 +47,7 @@ gpartedbin_SOURCES = \ OperationNamePartition.cc \ OperationResizeMove.cc \ Partition.cc \ + PartitionVector.cc \ PipeCapture.cc \ Proc_Partitions_Info.cc \ SWRaid_Info.cc \ diff --git a/src/PartitionVector.cc b/src/PartitionVector.cc new file mode 100644 index 00000000..f05bedfd --- /dev/null +++ b/src/PartitionVector.cc @@ -0,0 +1,88 @@ +/* Copyright (C) 2015 Mike Fleetwood + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, see . + */ + +#include "../include/Partition.h" +#include "../include/PartitionVector.h" + +#include + +namespace GParted +{ + +PartitionVector::PartitionVector( const PartitionVector & src ) +{ + v.resize( src.size() ); + for ( unsigned int i = 0 ; i < src.size() ; i ++ ) + v[i] = new Partition( src[i] ); +} + +PartitionVector::~PartitionVector() +{ + for ( unsigned int i = 0 ; i < v.size() ; i ++ ) + delete v[i]; +} + +void PartitionVector::swap( PartitionVector & other ) +{ + std::swap( this->v, other.v ); +} + +PartitionVector & PartitionVector::operator=( PartitionVector rhs ) +{ + // Copy assignment implemented using copy-and-swap idiom. + // 1) Pass-by-value to get rhs variable copy constructed from source; + // 2) Swap contents of this PartitionVector with rhs variable copy; + // 3) Method returns, rhs variable goes out of scope and destructor called on old + // this PartitionVector to delete owned Partitions. + // Reference: + // Wikibooks: More C++ Idioms / Copy-and-swap + // https://en.wikibooks.org/wiki/More_C%2B%2B_Idioms/Copy-and-swap + rhs.swap( *this ); + return *this; +} + +void PartitionVector::pop_back() +{ + delete v.back(); + v.pop_back(); +} + +void PartitionVector::erase( const iterator position ) +{ + delete *position; + v.erase( position ); +} + +void PartitionVector::clear() +{ + for ( unsigned int i = 0 ; i < v.size() ; i ++ ) + delete v[i]; + v.clear(); +} + +void PartitionVector::push_back( const Partition & partition ) +{ + Partition * p = new Partition( partition ); + v.push_back( p ); +} + +void PartitionVector::insert( iterator position, const Partition & partition ) +{ + Partition * p = new Partition( partition ); + v.insert( position, p ); +} + +} //GParted