[geos-commits] [SCM] GEOS branch master updated. 5efe6357aa8b6d395baae14e16a853fd4bb5e0d9

git at osgeo.org git at osgeo.org
Fri Jun 28 17:05:44 PDT 2019


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GEOS".

The branch, master has been updated
       via  5efe6357aa8b6d395baae14e16a853fd4bb5e0d9 (commit)
      from  643b96c8f87315fcedf2e0b6bbb2b7e0b317270b (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 5efe6357aa8b6d395baae14e16a853fd4bb5e0d9
Author: Daniel Baston <dbaston at gmail.com>
Date:   Fri Jun 21 21:37:29 2019 -0400

    Augment GeometryFactory with a methods taking and returning unique_ptr

diff --git a/include/geos/geom/Geometry.h b/include/geos/geom/Geometry.h
index 4ae9f72..0e729b0 100644
--- a/include/geos/geom/Geometry.h
+++ b/include/geos/geom/Geometry.h
@@ -845,8 +845,8 @@ protected:
 
     /// Returns true if the array contains any non-empty Geometrys.
     template<typename T>
-    static bool hasNonEmptyElements(const std::vector<T*>* geometries) {
-        return std::any_of(geometries->begin(), geometries->end(), [](const Geometry* g) { return !g->isEmpty(); });
+    static bool hasNonEmptyElements(const std::vector<T>* geometries) {
+        return std::any_of(geometries->begin(), geometries->end(), [](const T& g) { return !g->isEmpty(); });
     }
 
     /// Returns true if the CoordinateSequence contains any null elements.
@@ -854,8 +854,8 @@ protected:
 
     /// Returns true if the vector contains any null elements.
     template<typename T>
-    static bool hasNullElements(const std::vector<T*>* geometries) {
-        return std::any_of(geometries->begin(), geometries->end(), [](const Geometry* g) { return g == nullptr; });
+    static bool hasNullElements(const std::vector<T>* geometries) {
+        return std::any_of(geometries->begin(), geometries->end(), [](const T& g) { return g == nullptr; });
     }
 
 //	static void reversePointOrder(CoordinateSequence* coordinates);
@@ -903,6 +903,15 @@ protected:
      */
     Geometry(const GeometryFactory* factory);
 
+    template<typename T>
+    static std::vector<std::unique_ptr<Geometry>> toGeometryArray(std::vector<std::unique_ptr<T>> && v) {
+        static_assert(std::is_base_of<Geometry, T>::value, "");
+        std::vector<std::unique_ptr<Geometry>> gv(v.size());
+        for (size_t i = 0; i < v.size(); i++) {
+            gv[i] = std::move(v[i]);
+        }
+        return gv;
+    }
 
 protected:
 
diff --git a/include/geos/geom/GeometryCollection.h b/include/geos/geom/GeometryCollection.h
index b284337..516180f 100644
--- a/include/geos/geom/GeometryCollection.h
+++ b/include/geos/geom/GeometryCollection.h
@@ -201,6 +201,13 @@ protected:
      */
     GeometryCollection(std::vector<Geometry*>* newGeoms, const GeometryFactory* newFactory);
 
+    GeometryCollection(std::vector<std::unique_ptr<Geometry>> && newGeoms, const GeometryFactory& newFactory);
+
+    /// Convenience constructor to build a GeometryCollection from vector of Geometry subclass pointers
+    template<typename T>
+    GeometryCollection(std::vector<std::unique_ptr<T>> && newGeoms, const GeometryFactory& newFactory) :
+        GeometryCollection(toGeometryArray(std::move(newGeoms)), newFactory) {}
+
     int
     getSortIndex() const override
     {
diff --git a/include/geos/geom/GeometryFactory.h b/include/geos/geom/GeometryFactory.h
index a44b8f9..74d3122 100644
--- a/include/geos/geom/GeometryFactory.h
+++ b/include/geos/geom/GeometryFactory.h
@@ -45,7 +45,6 @@ class LinearRing;
 class MultiLineString;
 class MultiPoint;
 class MultiPolygon;
-class Point;
 class Polygon;
 class PrecisionModel;
 }
@@ -184,6 +183,9 @@ public:
     GeometryCollection* createGeometryCollection(
         std::vector<Geometry*>* newGeoms) const;
 
+    std::unique_ptr<GeometryCollection> createGeometryCollection(
+            std::vector<std::unique_ptr<Geometry>> && newGeoms) const;
+
     /// Constructs a GeometryCollection with a deep-copy of args
     GeometryCollection* createGeometryCollection(
         const std::vector<Geometry*>& newGeoms) const;
@@ -199,6 +201,12 @@ public:
     MultiLineString* createMultiLineString(
         const std::vector<Geometry*>& fromLines) const;
 
+    std::unique_ptr<MultiLineString> createMultiLineString(
+            std::vector<std::unique_ptr<LineString>> && fromLines) const;
+
+    std::unique_ptr<MultiLineString> createMultiLineString(
+            std::vector<std::unique_ptr<Geometry>> && fromLines) const;
+
     /// Construct an EMPTY MultiPolygon
     MultiPolygon* createMultiPolygon() const;
 
@@ -209,14 +217,20 @@ public:
     MultiPolygon* createMultiPolygon(
         const std::vector<Geometry*>& fromPolys) const;
 
+    std::unique_ptr<MultiPolygon> createMultiPolygon(
+        std::vector<std::unique_ptr<Polygon>> && fromPolys) const;
+
+    std::unique_ptr<MultiPolygon> createMultiPolygon(
+            std::vector<std::unique_ptr<Geometry>> && fromPolys) const;
+
     /// Construct an EMPTY LinearRing
     LinearRing* createLinearRing() const;
 
     /// Construct a LinearRing taking ownership of given arguments
     LinearRing* createLinearRing(CoordinateSequence* newCoords) const;
 
-    std::unique_ptr<Geometry> createLinearRing(
-        std::unique_ptr<CoordinateSequence> newCoords) const;
+    std::unique_ptr<LinearRing> createLinearRing(
+        std::unique_ptr<CoordinateSequence> && newCoords) const;
 
     /// Construct a LinearRing with a deep-copy of given arguments
     LinearRing* createLinearRing(
@@ -228,6 +242,10 @@ public:
     /// Construct a MultiPoint taking ownership of given arguments
     MultiPoint* createMultiPoint(std::vector<Geometry*>* newPoints) const;
 
+    std::unique_ptr<MultiPoint> createMultiPoint(std::vector<std::unique_ptr<Point>> && newPoints) const;
+
+    std::unique_ptr<MultiPoint> createMultiPoint(std::vector<std::unique_ptr<Geometry>> && newPoints) const;
+
     /// Construct a MultiPoint with a deep-copy of given arguments
     MultiPoint* createMultiPoint(
         const std::vector<Geometry*>& fromPoints) const;
@@ -251,6 +269,11 @@ public:
     Polygon* createPolygon(LinearRing* shell,
                            std::vector<LinearRing*>* holes) const;
 
+    std::unique_ptr<Polygon> createPolygon(std::unique_ptr<LinearRing> && shell) const;
+
+    std::unique_ptr<Polygon> createPolygon(std::unique_ptr<LinearRing> && shell,
+                                           std::vector<std::unique_ptr<LinearRing>> && holes) const;
+
     /// Construct a Polygon with a deep-copy of given arguments
     Polygon* createPolygon(const LinearRing& shell,
                            const std::vector<LinearRing*>& holes) const;
@@ -264,8 +287,8 @@ public:
     /// Construct a LineString taking ownership of given argument
     LineString* createLineString(CoordinateSequence* coordinates) const;
 
-    std::unique_ptr<Geometry> createLineString(
-        std::unique_ptr<CoordinateSequence> coordinates) const;
+    std::unique_ptr<LineString> createLineString(
+        std::unique_ptr<CoordinateSequence> && coordinates) const;
 
     /// Construct a LineString with a deep-copy of given argument
     LineString* createLineString(
diff --git a/include/geos/geom/LineString.h b/include/geos/geom/LineString.h
index 5e0c438..a262d8d 100644
--- a/include/geos/geom/LineString.h
+++ b/include/geos/geom/LineString.h
@@ -193,8 +193,8 @@ protected:
     LineString(CoordinateSequence* pts, const GeometryFactory* newFactory);
 
     /// Hopefully cleaner version of the above
-    LineString(CoordinateSequence::Ptr pts,
-               const GeometryFactory* newFactory);
+    LineString(CoordinateSequence::Ptr && pts,
+               const GeometryFactory& newFactory);
 
     Envelope::Ptr computeEnvelopeInternal() const override;
 
diff --git a/include/geos/geom/LinearRing.h b/include/geos/geom/LinearRing.h
index 50c9a23..631e100 100644
--- a/include/geos/geom/LinearRing.h
+++ b/include/geos/geom/LinearRing.h
@@ -79,8 +79,8 @@ public:
                const GeometryFactory* newFactory);
 
     /// Hopefully cleaner version of the above
-    LinearRing(CoordinateSequence::Ptr points,
-               const GeometryFactory* newFactory);
+    LinearRing(CoordinateSequence::Ptr && points,
+            const GeometryFactory& newFactory);
 
     std::unique_ptr<Geometry>
     clone() const override
diff --git a/include/geos/geom/MultiLineString.h b/include/geos/geom/MultiLineString.h
index 602a6d6..6faa43b 100644
--- a/include/geos/geom/MultiLineString.h
+++ b/include/geos/geom/MultiLineString.h
@@ -24,6 +24,7 @@
 #include <geos/export.h>
 #include <geos/geom/GeometryCollection.h> // for inheritance
 #include <geos/geom/Dimension.h>
+#include <geos/geom/LineString.h>
 
 #include <string>
 #include <vector>
@@ -115,6 +116,12 @@ protected:
     MultiLineString(std::vector<Geometry*>* newLines,
                     const GeometryFactory* newFactory);
 
+    MultiLineString(std::vector<std::unique_ptr<LineString>> && newLines,
+            const GeometryFactory& newFactory);
+
+    MultiLineString(std::vector<std::unique_ptr<Geometry>> && newLines,
+                    const GeometryFactory& newFactory);
+
     MultiLineString(const MultiLineString& mp);
 
     int
diff --git a/include/geos/geom/MultiPoint.h b/include/geos/geom/MultiPoint.h
index 04655a7..20ee0c7 100644
--- a/include/geos/geom/MultiPoint.h
+++ b/include/geos/geom/MultiPoint.h
@@ -119,6 +119,10 @@ protected:
      */
     MultiPoint(std::vector<Geometry*>* newPoints, const GeometryFactory* newFactory);
 
+    MultiPoint(std::vector<std::unique_ptr<Point>> && newPoints, const GeometryFactory& newFactory);
+
+    MultiPoint(std::vector<std::unique_ptr<Geometry>> && newPoints, const GeometryFactory& newFactory);
+
     MultiPoint(const MultiPoint& mp): GeometryCollection(mp) {}
 
     const Coordinate* getCoordinateN(size_t n) const;
diff --git a/include/geos/geom/MultiPolygon.h b/include/geos/geom/MultiPolygon.h
index 2726781..dbcedd6 100644
--- a/include/geos/geom/MultiPolygon.h
+++ b/include/geos/geom/MultiPolygon.h
@@ -25,6 +25,7 @@
 #include <string>
 #include <vector>
 #include <geos/geom/GeometryCollection.h> // for inheritance
+#include <geos/geom/Polygon.h> // for inheritance
 #include <geos/geom/Dimension.h> // for Dimension::DimensionType
 
 #include <geos/inline.h>
@@ -115,6 +116,12 @@ protected:
      */
     MultiPolygon(std::vector<Geometry*>* newPolys, const GeometryFactory* newFactory);
 
+    MultiPolygon(std::vector<std::unique_ptr<Polygon>> && newPolys,
+            const GeometryFactory& newFactory);
+
+    MultiPolygon(std::vector<std::unique_ptr<Geometry>> && newPolys,
+                 const GeometryFactory& newFactory);
+
     MultiPolygon(const MultiPolygon& mp);
 
     int
diff --git a/include/geos/geom/Polygon.h b/include/geos/geom/Polygon.h
index 662d2f2..d274c7b 100644
--- a/include/geos/geom/Polygon.h
+++ b/include/geos/geom/Polygon.h
@@ -171,6 +171,13 @@ protected:
     Polygon(LinearRing* newShell, std::vector<LinearRing*>* newHoles,
             const GeometryFactory* newFactory);
 
+    Polygon(std::unique_ptr<LinearRing> && newShell,
+            const GeometryFactory& newFactory);
+
+    Polygon(std::unique_ptr<LinearRing> && newShell,
+            std::vector<std::unique_ptr<LinearRing>> && newHoles,
+            const GeometryFactory& newFactory);
+
     std::unique_ptr<LinearRing> shell;
 
     std::vector<std::unique_ptr<LinearRing>> holes;
diff --git a/src/geom/GeometryCollection.cpp b/src/geom/GeometryCollection.cpp
index a1fcf6b..46a2812 100644
--- a/src/geom/GeometryCollection.cpp
+++ b/src/geom/GeometryCollection.cpp
@@ -70,6 +70,17 @@ GeometryCollection::GeometryCollection(std::vector<Geometry*>* newGeoms, const G
     setSRID(getSRID());
 }
 
+GeometryCollection::GeometryCollection(std::vector<std::unique_ptr<Geometry>> && newGeoms, const GeometryFactory& factory) :
+    Geometry(&factory),
+    geometries(std::move(newGeoms)) {
+
+    if (hasNullElements(&geometries)) {
+        throw util::IllegalArgumentException("geometries must not contain null elements\n");
+    }
+
+    setSRID(getSRID());
+}
+
 void
 GeometryCollection::setSRID(int newSRID)
 {
diff --git a/src/geom/GeometryFactory.cpp b/src/geom/GeometryFactory.cpp
index bc8c430..161b36f 100644
--- a/src/geom/GeometryFactory.cpp
+++ b/src/geom/GeometryFactory.cpp
@@ -327,7 +327,7 @@ GeometryFactory::createPoint(const Coordinate& coordinate) const
     else {
         std::size_t dim = std::isnan(coordinate.z) ? 2 : 3;
         auto cl = coordinateListFactory->create(new vector<Coordinate>(1, coordinate), dim);
-        //cl->setAt(coordinate, 0);
+
         Point* ret = createPoint(cl.release());
         return ret;
     }
@@ -366,29 +366,34 @@ const
 
 /*public*/
 MultiLineString*
-GeometryFactory::createMultiLineString(const vector<Geometry*>& fromLines)
+GeometryFactory::createMultiLineString(const std::vector<Geometry*>& fromLines)
 const
 {
-    vector<Geometry*>* newGeoms = new vector<Geometry*>(fromLines.size());
+    std::vector<std::unique_ptr<Geometry>> newGeoms(fromLines.size());
+
     for(size_t i = 0; i < fromLines.size(); i++) {
-        const LineString* line = dynamic_cast<const LineString*>(fromLines[i]);
-        if(! line) {
+        auto line = dynamic_cast<const LineString*>(fromLines[i]);
+
+        if(!line) {
             throw geos::util::IllegalArgumentException("createMultiLineString called with a vector containing non-LineStrings");
         }
-        (*newGeoms)[i] = new LineString(*line);
-    }
-    MultiLineString* g = nullptr;
-    try {
-        g = new MultiLineString(newGeoms, this);
-    }
-    catch(...) {
-        for(size_t i = 0; i < newGeoms->size(); i++) {
-            delete(*newGeoms)[i];
-        }
-        delete newGeoms;
-        throw;
+
+        newGeoms[i].reset(new LineString(*line));
     }
-    return g;
+
+    return new MultiLineString(std::move(newGeoms), *this);
+}
+
+std::unique_ptr<MultiLineString>
+GeometryFactory::createMultiLineString(std::vector<std::unique_ptr<LineString>> && fromLines) const {
+    // Can't use make_unique because constructor is protected
+    return std::unique_ptr<MultiLineString>(new MultiLineString(std::move(fromLines), *this));
+}
+
+std::unique_ptr<MultiLineString>
+GeometryFactory::createMultiLineString(std::vector<std::unique_ptr<Geometry>> && fromLines) const {
+    // Can't use make_unique because constructor is protected
+    return std::unique_ptr<MultiLineString>(new MultiLineString(std::move(fromLines), *this));
 }
 
 /*public*/
@@ -412,26 +417,23 @@ GeometryFactory::createGeometryCollection(vector<Geometry*>* newGeoms) const
     return new GeometryCollection(newGeoms, this);
 }
 
+std::unique_ptr<GeometryCollection>
+GeometryFactory::createGeometryCollection(std::vector<std::unique_ptr<geos::geom::Geometry>> && newGeoms) const {
+    // Can't use make_unique because constructor is protected
+    return std::unique_ptr<GeometryCollection>(new GeometryCollection(std::move(newGeoms), *this));
+}
+
 /*public*/
 GeometryCollection*
-GeometryFactory::createGeometryCollection(const vector<Geometry*>& fromGeoms) const
+GeometryFactory::createGeometryCollection(const std::vector<Geometry*>& fromGeoms) const
 {
-    vector<Geometry*>* newGeoms = new vector<Geometry*>(fromGeoms.size());
+    std::vector<std::unique_ptr<Geometry>> newGeoms(fromGeoms.size());
+
     for(size_t i = 0; i < fromGeoms.size(); i++) {
-        (*newGeoms)[i] = fromGeoms[i]->clone().release();
+        newGeoms[i] = fromGeoms[i]->clone();
     }
-    GeometryCollection* g = nullptr;
-    try {
-        g = new GeometryCollection(newGeoms, this);
-    }
-    catch(...) {
-        for(size_t i = 0; i < newGeoms->size(); i++) {
-            delete(*newGeoms)[i];
-        }
-        delete newGeoms;
-        throw;
-    }
-    return g;
+
+    return new GeometryCollection(std::move(newGeoms), *this);
 }
 
 /*public*/
@@ -448,26 +450,31 @@ GeometryFactory::createMultiPolygon(vector<Geometry*>* newPolys) const
     return new MultiPolygon(newPolys, this);
 }
 
+std::unique_ptr<MultiPolygon>
+GeometryFactory::createMultiPolygon(std::vector<std::unique_ptr<Polygon>> && newPolys) const
+{
+    // Can't use make_unique because constructor is protected
+    return std::unique_ptr<MultiPolygon>(new MultiPolygon(std::move(newPolys), *this));
+}
+
+std::unique_ptr<MultiPolygon>
+GeometryFactory::createMultiPolygon(std::vector<std::unique_ptr<Geometry>> && newPolys) const
+{
+    // Can't use make_unique because constructor is protected
+    return std::unique_ptr<MultiPolygon>(new MultiPolygon(std::move(newPolys), *this));
+}
+
 /*public*/
 MultiPolygon*
-GeometryFactory::createMultiPolygon(const vector<Geometry*>& fromPolys) const
+GeometryFactory::createMultiPolygon(const std::vector<Geometry*>& fromPolys) const
 {
-    vector<Geometry*>* newGeoms = new vector<Geometry*>(fromPolys.size());
+    std::vector<std::unique_ptr<Geometry>> newGeoms(fromPolys.size());
+
     for(size_t i = 0; i < fromPolys.size(); i++) {
-        (*newGeoms)[i] = fromPolys[i]->clone().release();
-    }
-    MultiPolygon* g = nullptr;
-    try {
-        g = new MultiPolygon(newGeoms, this);
+        newGeoms[i] = fromPolys[i]->clone();
     }
-    catch(...) {
-        for(size_t i = 0; i < newGeoms->size(); i++) {
-            delete(*newGeoms)[i];
-        }
-        delete newGeoms;
-        throw;
-    }
-    return g;
+
+    return new MultiPolygon(std::move(newGeoms), *this);
 }
 
 /*public*/
@@ -484,11 +491,11 @@ GeometryFactory::createLinearRing(CoordinateSequence* newCoords) const
     return new LinearRing(newCoords, this);
 }
 
-/*public*/
-Geometry::Ptr
-GeometryFactory::createLinearRing(CoordinateSequence::Ptr newCoords) const
+std::unique_ptr<LinearRing>
+GeometryFactory::createLinearRing(CoordinateSequence::Ptr && newCoords) const
 {
-    return Geometry::Ptr(new LinearRing(std::move(newCoords), this));
+    // Can't use make_unique with protected constructor
+    return std::unique_ptr<LinearRing>(new LinearRing(std::move(newCoords), *this));
 }
 
 /*public*/
@@ -509,27 +516,28 @@ GeometryFactory::createMultiPoint(vector<Geometry*>* newPoints) const
     return new MultiPoint(newPoints, this);
 }
 
+std::unique_ptr<MultiPoint>
+GeometryFactory::createMultiPoint(std::vector<std::unique_ptr<Point>> && newPoints) const
+{
+    return std::unique_ptr<MultiPoint>(new MultiPoint(std::move(newPoints), *this));
+}
+
+std::unique_ptr<MultiPoint>
+GeometryFactory::createMultiPoint(std::vector<std::unique_ptr<Geometry>> && newPoints) const
+{
+    return std::unique_ptr<MultiPoint>(new MultiPoint(std::move(newPoints), *this));
+}
+
 /*public*/
 MultiPoint*
 GeometryFactory::createMultiPoint(const vector<Geometry*>& fromPoints) const
 {
-    vector<Geometry*>* newGeoms = new vector<Geometry*>(fromPoints.size());
+    std::vector<std::unique_ptr<Geometry>> newGeoms(fromPoints.size());
     for(size_t i = 0; i < fromPoints.size(); i++) {
-        (*newGeoms)[i] = fromPoints[i]->clone().release();
+        newGeoms[i] = fromPoints[i]->clone();
     }
 
-    MultiPoint* g = nullptr;
-    try {
-        g = new MultiPoint(newGeoms, this);
-    }
-    catch(...) {
-        for(size_t i = 0; i < newGeoms->size(); i++) {
-            delete(*newGeoms)[i];
-        }
-        delete newGeoms;
-        throw;
-    }
-    return g;
+    return new MultiPoint(std::move(newGeoms), *this);
 }
 
 /*public*/
@@ -544,24 +552,13 @@ MultiPoint*
 GeometryFactory::createMultiPoint(const CoordinateSequence& fromCoords) const
 {
     size_t npts = fromCoords.getSize();
-    vector<Geometry*>* pts = new vector<Geometry*>;
-    pts->reserve(npts);
+    vector<std::unique_ptr<Geometry>> pts(npts);
+
     for(size_t i = 0; i < npts; ++i) {
-        Point* pt = createPoint(fromCoords.getAt(i));
-        pts->push_back(pt);
-    }
-    MultiPoint* mp = nullptr;
-    try {
-        mp = createMultiPoint(pts);
-    }
-    catch(...) {
-        for(size_t i = 0; i < npts; ++i) {
-            delete(*pts)[i];
-        }
-        delete pts;
-        throw;
+        pts[i].reset(createPoint(fromCoords.getAt(i)));
     }
-    return mp;
+
+    return new MultiPoint(std::move(pts), *this);
 }
 
 /*public*/
@@ -569,24 +566,13 @@ MultiPoint*
 GeometryFactory::createMultiPoint(const std::vector<Coordinate>& fromCoords) const
 {
     size_t npts = fromCoords.size();
-    vector<Geometry*>* pts = new vector<Geometry*>;
-    pts->reserve(npts);
+    std::vector<std::unique_ptr<Geometry>> pts(npts);
+
     for(size_t i = 0; i < npts; ++i) {
-        Point* pt = createPoint(fromCoords[i]);
-        pts->push_back(pt);
+        pts[i].reset(createPoint(fromCoords[i]));
     }
-    MultiPoint* mp = nullptr;
-    try {
-        mp = createMultiPoint(pts);
-    }
-    catch(...) {
-        for(size_t i = 0; i < npts; ++i) {
-            delete(*pts)[i];
-        }
-        delete pts;
-        throw;
-    }
-    return mp;
+
+    return new MultiPoint(std::move(pts), *this);
 }
 
 /*public*/
@@ -604,29 +590,36 @@ const
     return new Polygon(shell, holes, this);
 }
 
+std::unique_ptr<Polygon>
+GeometryFactory::createPolygon(std::unique_ptr<LinearRing> && shell)
+const
+{
+    // Can't use make_unique with protected constructor
+    return std::unique_ptr<Polygon>(new Polygon(std::move(shell), *this));
+}
+
+std::unique_ptr<Polygon>
+GeometryFactory::createPolygon(std::unique_ptr<LinearRing> && shell, std::vector<std::unique_ptr<LinearRing>> && holes)
+const
+{
+    // Can't use make_unique with protected constructor
+    return std::unique_ptr<Polygon>(new Polygon(std::move(shell), std::move(holes), *this));
+}
+
 /*public*/
 Polygon*
-GeometryFactory::createPolygon(const LinearRing& shell, const vector<LinearRing*>& holes)
+GeometryFactory::createPolygon(const LinearRing& shell, const std::vector<LinearRing*>& holes)
 const
 {
-    LinearRing* newRing = new LinearRing(shell);
-    vector<LinearRing*>* newHoles = new vector<LinearRing*>(holes.size());
+    std::unique_ptr<LinearRing> newRing(new LinearRing(shell));
+
+    std::vector<std::unique_ptr<LinearRing>> newHoles(holes.size());
+
     for(size_t i = 0; i < holes.size(); i++) {
-        (*newHoles)[i] = new LinearRing(*(holes[i]));
+        newHoles[i].reset(new LinearRing(*holes[i]));
     }
-    Polygon* g = nullptr;
-    try {
-        g = new Polygon(newRing, newHoles, this);
-    }
-    catch(...) {
-        delete newRing;
-        for(size_t i = 0; i < holes.size(); i++) {
-            delete(*newHoles)[i];
-        }
-        delete newHoles;
-        throw;
-    }
-    return g;
+
+    return new Polygon(std::move(newRing), std::move(newHoles), *this);
 }
 
 /*public*/
@@ -640,8 +633,8 @@ GeometryFactory::createLineString() const
 std::unique_ptr<LineString>
 GeometryFactory::createLineString(const LineString& ls) const
 {
+    // Can't use make_unique with protected constructor
     return std::unique_ptr<LineString>(new LineString(ls));
-    //return make_unique<LineString>(ls); // TODO why doesn't this work?
 }
 
 /*public*/
@@ -653,11 +646,12 @@ const
 }
 
 /*public*/
-Geometry::Ptr
-GeometryFactory::createLineString(CoordinateSequence::Ptr newCoords)
+std::unique_ptr<LineString>
+GeometryFactory::createLineString(CoordinateSequence::Ptr && newCoords)
 const
 {
-    return Geometry::Ptr(new LineString(std::move(newCoords), this));
+    // Can't use make_unique with protected constructor
+    return std::unique_ptr<LineString>(new LineString(std::move(newCoords), *this));
 }
 
 /*public*/
diff --git a/src/geom/LineString.cpp b/src/geom/LineString.cpp
index c40a1ee..3ee0bbb 100644
--- a/src/geom/LineString.cpp
+++ b/src/geom/LineString.cpp
@@ -94,10 +94,10 @@ LineString::LineString(CoordinateSequence* newCoords,
 }
 
 /*public*/
-LineString::LineString(CoordinateSequence::Ptr newCoords,
-                       const GeometryFactory* factory)
+LineString::LineString(CoordinateSequence::Ptr && newCoords,
+                       const GeometryFactory& factory)
     :
-    Geometry(factory),
+    Geometry(&factory),
     points(std::move(newCoords))
 {
     validateConstruction();
diff --git a/src/geom/LinearRing.cpp b/src/geom/LinearRing.cpp
index 64e8357..7775720 100644
--- a/src/geom/LinearRing.cpp
+++ b/src/geom/LinearRing.cpp
@@ -46,10 +46,9 @@ LinearRing::LinearRing(CoordinateSequence* newCoords,
 }
 
 /*public*/
-LinearRing::LinearRing(CoordinateSequence::Ptr newCoords,
-                       const GeometryFactory* newFactory)
-    :
-    LineString(std::move(newCoords), newFactory)
+LinearRing::LinearRing(CoordinateSequence::Ptr && newCoords,
+                       const GeometryFactory& newFactory)
+        : LineString(std::move(newCoords), newFactory)
 {
     validateConstruction();
 }
diff --git a/src/geom/MultiLineString.cpp b/src/geom/MultiLineString.cpp
index 6eb07d5..a52a9cc 100644
--- a/src/geom/MultiLineString.cpp
+++ b/src/geom/MultiLineString.cpp
@@ -47,6 +47,16 @@ MultiLineString::MultiLineString(vector<Geometry*>* newLines,
 {
 }
 
+MultiLineString::MultiLineString(std::vector<std::unique_ptr<LineString>> && newLines,
+        const GeometryFactory& factory)
+        : GeometryCollection(std::move(newLines), factory)
+{}
+
+MultiLineString::MultiLineString(std::vector<std::unique_ptr<Geometry>> && newLines,
+                                 const GeometryFactory& factory)
+        : GeometryCollection(std::move(newLines), factory)
+{}
+
 MultiLineString::~MultiLineString() {}
 
 Dimension::DimensionType
diff --git a/src/geom/MultiPoint.cpp b/src/geom/MultiPoint.cpp
index ddb3690..0d22e99 100644
--- a/src/geom/MultiPoint.cpp
+++ b/src/geom/MultiPoint.cpp
@@ -18,26 +18,36 @@
  *
  **********************************************************************/
 
+#include <geos/geom/Point.h>
 #include <geos/geom/MultiPoint.h>
 #include <geos/geom/GeometryFactory.h>
 #include <geos/geom/Dimension.h>
 
 #include <vector>
 
-using namespace std;
-
-//using namespace geos::operation;
-
 namespace geos {
 namespace geom { // geos::geom
 
 /*protected*/
-MultiPoint::MultiPoint(vector<Geometry*>* newPoints, const GeometryFactory* factory)
+MultiPoint::MultiPoint(std::vector<Geometry*>* newPoints, const GeometryFactory* factory)
     :
     GeometryCollection(newPoints, factory)
 {
 }
 
+MultiPoint::MultiPoint(std::vector<std::unique_ptr<Point>> && newPoints, const GeometryFactory& factory)
+    :
+    GeometryCollection(std::move(newPoints), factory)
+{
+
+}
+
+MultiPoint::MultiPoint(std::vector<std::unique_ptr<Geometry>> && newPoints, const GeometryFactory& factory)
+        :
+        GeometryCollection(std::move(newPoints), factory)
+{
+
+}
 
 MultiPoint::~MultiPoint() {}
 
@@ -53,7 +63,7 @@ MultiPoint::getBoundaryDimension() const
     return Dimension::False;
 }
 
-string
+std::string
 MultiPoint::getGeometryType() const
 {
     return "MultiPoint";
diff --git a/src/geom/MultiPolygon.cpp b/src/geom/MultiPolygon.cpp
index 777c37e..efc78aa 100644
--- a/src/geom/MultiPolygon.cpp
+++ b/src/geom/MultiPolygon.cpp
@@ -44,6 +44,14 @@ MultiPolygon::MultiPolygon(vector<Geometry*>* newPolys, const GeometryFactory* f
       : GeometryCollection(newPolys, factory)
 {}
 
+MultiPolygon::MultiPolygon(std::vector<std::unique_ptr<Polygon>> && newPolys, const GeometryFactory& factory)
+      : GeometryCollection(std::move(newPolys), factory)
+{}
+
+MultiPolygon::MultiPolygon(std::vector<std::unique_ptr<Geometry>> && newPolys, const GeometryFactory& factory)
+        : GeometryCollection(std::move(newPolys), factory)
+{}
+
 MultiPolygon::~MultiPolygon() {}
 
 Dimension::DimensionType
diff --git a/src/geom/Polygon.cpp b/src/geom/Polygon.cpp
index 612f039..b10f360 100644
--- a/src/geom/Polygon.cpp
+++ b/src/geom/Polygon.cpp
@@ -87,6 +87,37 @@ Polygon::Polygon(LinearRing* newShell, std::vector<LinearRing*>* newHoles,
     }
 }
 
+Polygon::Polygon(std::unique_ptr<LinearRing> && newShell,
+                 const GeometryFactory& newFactory) :
+        Geometry(&newFactory),
+        shell(std::move(newShell))
+{
+    if(shell == nullptr) {
+        shell.reset(getFactory()->createLinearRing(nullptr));
+    }
+}
+
+Polygon::Polygon(std::unique_ptr<LinearRing> && newShell,
+                 std::vector<std::unique_ptr<LinearRing>> && newHoles,
+                 const GeometryFactory& newFactory) :
+                 Geometry(&newFactory),
+                 shell(std::move(newShell)),
+                 holes(std::move(newHoles))
+{
+    if(shell == nullptr) {
+        shell.reset(getFactory()->createLinearRing(nullptr));
+    }
+
+    // TODO move into validateConstruction() method
+    if(shell->isEmpty() && hasNonEmptyElements(&holes)) {
+        throw util::IllegalArgumentException("shell is empty but holes are not");
+    }
+    if (hasNullElements(&holes)) {
+        throw util::IllegalArgumentException("holes must not contain null elements");
+    }
+}
+
+
 std::unique_ptr<CoordinateSequence>
 Polygon::getCoordinates() const
 {
diff --git a/src/io/WKBReader.cpp b/src/io/WKBReader.cpp
index 95df676..ff1e260 100644
--- a/src/io/WKBReader.cpp
+++ b/src/io/WKBReader.cpp
@@ -319,125 +319,82 @@ WKBReader::readPolygon()
         shell = readLinearRing();
     }
 
-    vector<LinearRing*>* holes = nullptr;
     if(numRings > 1) {
-        try {
-            holes = new vector<LinearRing*>(numRings - 1);
-            for(int i = 0; i < numRings - 1; i++) {
-                (*holes)[i] = readLinearRing().release();
-            }
-        }
-        catch(...) {
-            for(unsigned int i = 0; i < holes->size(); i++) {
-                delete(*holes)[i];
-            }
-            delete holes;
-            throw;
+        std::vector<std::unique_ptr<LinearRing>> holes(numRings - 1);
+        for(int i = 0; i < numRings - 1; i++) {
+            holes[i] = readLinearRing();
         }
+
+        return factory.createPolygon(std::move(shell), std::move(holes));
     }
-    return std::unique_ptr<Polygon>(factory.createPolygon(shell.release(), holes));
+    return factory.createPolygon(std::move(shell));
 }
 
 std::unique_ptr<MultiPoint>
 WKBReader::readMultiPoint()
 {
     int numGeoms = dis.readInt();
-    vector<Geometry*>* geoms = new vector<Geometry*>(numGeoms);
-
-    try {
-        for(int i = 0; i < numGeoms; i++) {
-            auto g = readGeometry();
-            if(!dynamic_cast<Point*>(g.get())) {
-                stringstream err;
-                err << BAD_GEOM_TYPE_MSG << " MultiPoint";
-                throw ParseException(err.str());
-            }
-            (*geoms)[i] = g.release();
-        }
-    }
-    catch(...) {
-        for(unsigned int i = 0; i < geoms->size(); i++) {
-            delete(*geoms)[i];
+    std::vector<std::unique_ptr<Geometry>> geoms(numGeoms);
+
+    for(int i = 0; i < numGeoms; i++) {
+        geoms[i] = readGeometry();
+        if(!dynamic_cast<Point*>(geoms[i].get())) {
+            stringstream err;
+            err << BAD_GEOM_TYPE_MSG << " MultiPoint";
+            throw ParseException(err.str());
         }
-        delete geoms;
-        throw;
     }
-    return std::unique_ptr<MultiPoint>(factory.createMultiPoint(geoms));
+
+    return factory.createMultiPoint(std::move(geoms));
 }
 
 std::unique_ptr<MultiLineString>
 WKBReader::readMultiLineString()
 {
     int numGeoms = dis.readInt();
-    vector<Geometry*>* geoms = new vector<Geometry*>(numGeoms);
-
-    try {
-        for(int i = 0; i < numGeoms; i++) {
-            auto g = readGeometry();
-            if(!dynamic_cast<LineString*>(g.get())) {
-                stringstream err;
-                err << BAD_GEOM_TYPE_MSG << " LineString";
-                throw  ParseException(err.str());
-            }
-            (*geoms)[i] = g.release();
-        }
-    }
-    catch(...) {
-        for(unsigned int i = 0; i < geoms->size(); i++) {
-            delete(*geoms)[i];
+    std::vector<std::unique_ptr<Geometry>> geoms(numGeoms);
+
+    for(int i = 0; i < numGeoms; i++) {
+        geoms[i] = readGeometry();
+        if(!dynamic_cast<LineString*>(geoms[i].get())) {
+            stringstream err;
+            err << BAD_GEOM_TYPE_MSG << " LineString";
+            throw  ParseException(err.str());
         }
-        delete geoms;
-        throw;
     }
-    return std::unique_ptr<MultiLineString>(factory.createMultiLineString(geoms));
+
+    return factory.createMultiLineString(std::move(geoms));
 }
 
 std::unique_ptr<MultiPolygon>
 WKBReader::readMultiPolygon()
 {
     int numGeoms = dis.readInt();
-    vector<Geometry*>* geoms = new vector<Geometry*>(numGeoms);
-
-    try {
-        for(int i = 0; i < numGeoms; i++) {
-            auto g = readGeometry();
-            if(!dynamic_cast<Polygon*>(g.get())) {
-                stringstream err;
-                err << BAD_GEOM_TYPE_MSG << " Polygon";
-                throw  ParseException(err.str());
-            }
-            (*geoms)[i] = g.release();
+    std::vector<std::unique_ptr<Geometry>> geoms(numGeoms);
+
+    for(int i = 0; i < numGeoms; i++) {
+        geoms[i] = readGeometry();
+        if(!dynamic_cast<Polygon*>(geoms[i].get())) {
+            stringstream err;
+            err << BAD_GEOM_TYPE_MSG << " Polygon";
+            throw  ParseException(err.str());
         }
     }
-    catch(...) {
-        for(unsigned int i = 0; i < geoms->size(); i++) {
-            delete(*geoms)[i];
-        }
-        delete geoms;
-        throw;
-    }
-    return std::unique_ptr<MultiPolygon>(factory.createMultiPolygon(geoms));
+
+    return factory.createMultiPolygon(std::move(geoms));
 }
 
 std::unique_ptr<GeometryCollection>
 WKBReader::readGeometryCollection()
 {
     int numGeoms = dis.readInt();
-    vector<Geometry*>* geoms = new vector<Geometry*>(numGeoms);
+    std::vector<std::unique_ptr<Geometry>> geoms(numGeoms);
 
-    try {
-        for(int i = 0; i < numGeoms; i++) {
-            (*geoms)[i] = readGeometry().release();
-        }
+    for(int i = 0; i < numGeoms; i++) {
+        geoms[i] = readGeometry();
     }
-    catch(...) {
-        for(unsigned int i = 0; i < geoms->size(); i++) {
-            delete(*geoms)[i];
-        }
-        delete geoms;
-        throw;
-    }
-    return std::unique_ptr<GeometryCollection>(factory.createGeometryCollection(geoms));
+
+    return factory.createGeometryCollection(std::move(geoms));
 }
 
 std::unique_ptr<CoordinateSequence>
diff --git a/src/io/WKTReader.cpp b/src/io/WKTReader.cpp
index ff2d360..d89f1b0 100644
--- a/src/io/WKTReader.cpp
+++ b/src/io/WKTReader.cpp
@@ -265,18 +265,15 @@ WKTReader::readPointText(StringTokenizer* tokenizer)
 std::unique_ptr<LineString>
 WKTReader::readLineStringText(StringTokenizer* tokenizer)
 {
-    auto coords = getCoordinates(tokenizer);
-    LineString* ret = geometryFactory->createLineString(coords.release());
-    return std::unique_ptr<LineString>(ret);
+    auto&& coords = getCoordinates(tokenizer);
+    return geometryFactory->createLineString(std::move(coords));
 }
 
 std::unique_ptr<LinearRing>
 WKTReader::readLinearRingText(StringTokenizer* tokenizer)
 {
-    auto coords = getCoordinates(tokenizer);
-    LinearRing* ret;
-    ret = geometryFactory->createLinearRing(coords.release());
-    return std::unique_ptr<LinearRing>(ret);
+    auto&& coords = getCoordinates(tokenizer);
+    return geometryFactory->createLinearRing(std::move(coords));
 }
 
 std::unique_ptr<MultiPoint>
@@ -308,24 +305,14 @@ WKTReader::readMultiPointText(StringTokenizer* tokenizer)
 
     else if(tok == '(') {
         // Try to parse correct form "MULTIPOINT((0 0), (1 1))"
-        vector<Geometry*>* points = new vector<Geometry*>();
-        try {
-            do {
-                auto point = readPointText(tokenizer);
-                points->push_back(point.release());
-                nextToken = getNextCloserOrComma(tokenizer);
-            }
-            while(nextToken == ",");
-            return std::unique_ptr<MultiPoint>(geometryFactory->createMultiPoint(points));
-        }
-        catch(...) {
-            // clean up
-            for(size_t i = 0; i < points->size(); i++) {
-                delete(*points)[i];
-            }
-            delete points;
-            throw;
-        }
+        std::vector<std::unique_ptr<Point>> points;
+
+        do {
+            points.push_back(readPointText(tokenizer));
+            nextToken = getNextCloserOrComma(tokenizer);
+        } while(nextToken == ",");
+
+        return geometryFactory->createMultiPoint(std::move(points));
     }
 
     else {
@@ -363,32 +350,20 @@ WKTReader::readMultiPointText(StringTokenizer* tokenizer)
 std::unique_ptr<Polygon>
 WKTReader::readPolygonText(StringTokenizer* tokenizer)
 {
-    Polygon* poly = nullptr;
     string nextToken = getNextEmptyOrOpener(tokenizer);
     if(nextToken == "EMPTY") {
         return std::unique_ptr<Polygon>(geometryFactory->createPolygon(nullptr, nullptr));
     }
 
-    vector<LinearRing*>* holes = new vector<LinearRing*>();
-    try {
-        auto shell = readLinearRingText(tokenizer);
+    std::vector<std::unique_ptr<LinearRing>> holes;
+    auto shell = readLinearRingText(tokenizer);
+    nextToken = getNextCloserOrComma(tokenizer);
+    while(nextToken == ",") {
+        holes.push_back(readLinearRingText(tokenizer));
         nextToken = getNextCloserOrComma(tokenizer);
-        while(nextToken == ",") {
-            auto hole = readLinearRingText(tokenizer);
-            holes->push_back(hole.release());
-            nextToken = getNextCloserOrComma(tokenizer);
-        }
-        poly = geometryFactory->createPolygon(shell.get(), holes);
-        shell.release(); // release separately because Polygon constructor may throw
-    }
-    catch(...) {
-        for(unsigned int i = 0; i < holes->size(); i++) {
-            delete(*holes)[i];
-        }
-        delete holes;
-        throw;
     }
-    return std::unique_ptr<Polygon>(poly);
+
+    return geometryFactory->createPolygon(std::move(shell), std::move(holes));
 }
 
 std::unique_ptr<MultiLineString>
@@ -398,24 +373,14 @@ WKTReader::readMultiLineStringText(StringTokenizer* tokenizer)
     if(nextToken == "EMPTY") {
         return std::unique_ptr<MultiLineString>(geometryFactory->createMultiLineString(nullptr));
     }
-    vector<Geometry*>* lineStrings = new vector<Geometry*>();
-    std::unique_ptr<LineString> lineString;
-    try {
-        do {
-            lineString = readLineStringText(tokenizer);
-            lineStrings->push_back(lineString.release());
-            nextToken = getNextCloserOrComma(tokenizer);
-        } while (nextToken == ",");
-    }
-    catch(...) {
-        for(size_t i = 0; i < lineStrings->size(); i++) {
-            delete(*lineStrings)[i];
-        }
-        delete lineStrings;
-        throw;
-    }
-    MultiLineString* ret = geometryFactory->createMultiLineString(lineStrings);
-    return std::unique_ptr<MultiLineString>(ret);
+
+    std::vector<std::unique_ptr<LineString>> lineStrings;
+    do {
+        lineStrings.push_back(readLineStringText(tokenizer));
+        nextToken = getNextCloserOrComma(tokenizer);
+    } while (nextToken == ",");
+
+    return geometryFactory->createMultiLineString(std::move(lineStrings));
 }
 
 std::unique_ptr<MultiPolygon>
@@ -425,24 +390,14 @@ WKTReader::readMultiPolygonText(StringTokenizer* tokenizer)
     if(nextToken == "EMPTY") {
         return std::unique_ptr<MultiPolygon>(geometryFactory->createMultiPolygon(nullptr));
     }
-    vector<Geometry*>* polygons = new vector<Geometry*>();
-    std::unique_ptr<Polygon> polygon;
-    try {
-        do {
-            polygon = readPolygonText(tokenizer);
-            polygons->push_back(polygon.release());
-            nextToken = getNextCloserOrComma(tokenizer);
-        } while(nextToken == ",");
-    }
-    catch(...) {
-        for(size_t i = 0; i < polygons->size(); i++) {
-            delete(*polygons)[i];
-        }
-        delete polygons;
-        throw;
-    }
-    MultiPolygon* ret = geometryFactory->createMultiPolygon(polygons);
-    return std::unique_ptr<MultiPolygon>(ret);
+
+    std::vector<std::unique_ptr<Polygon>> polygons;
+    do {
+        polygons.push_back(readPolygonText(tokenizer));
+        nextToken = getNextCloserOrComma(tokenizer);
+    } while(nextToken == ",");
+
+    return geometryFactory->createMultiPolygon(std::move(polygons));
 }
 
 std::unique_ptr<GeometryCollection>
@@ -452,24 +407,14 @@ WKTReader::readGeometryCollectionText(StringTokenizer* tokenizer)
     if(nextToken == "EMPTY") {
         return std::unique_ptr<GeometryCollection>(geometryFactory->createGeometryCollection(nullptr));
     }
-    vector<Geometry*>* geoms = new vector<Geometry*>();
-    std::unique_ptr<Geometry> geom;
-    try {
-        do {
-            geom = readGeometryTaggedText(tokenizer);
-            geoms->push_back(geom.release());
-            nextToken = getNextCloserOrComma(tokenizer);
-        } while(nextToken == ",");
-    }
-    catch(...) {
-        for(size_t i = 0; i < geoms->size(); i++) {
-            delete(*geoms)[i];
-        }
-        delete geoms;
-        throw;
-    }
-    GeometryCollection* ret = geometryFactory->createGeometryCollection(geoms);
-    return std::unique_ptr<GeometryCollection>(ret);
+
+    std::vector<std::unique_ptr<Geometry>> geoms;
+    do {
+        geoms.push_back(readGeometryTaggedText(tokenizer));
+        nextToken = getNextCloserOrComma(tokenizer);
+    } while(nextToken == ",");
+
+    return geometryFactory->createGeometryCollection(std::move(geoms));
 }
 
 } // namespace geos.io
diff --git a/src/simplify/TaggedLineString.cpp b/src/simplify/TaggedLineString.cpp
index 5de6932..b2be0c8 100644
--- a/src/simplify/TaggedLineString.cpp
+++ b/src/simplify/TaggedLineString.cpp
@@ -20,6 +20,7 @@
 #include <geos/simplify/TaggedLineSegment.h>
 #include <geos/geom/CoordinateSequence.h>
 #include <geos/geom/LineString.h>
+#include <geos/geom/LinearRing.h>
 #include <geos/geom/Geometry.h> // for unique_ptr destructor
 #include <geos/geom/GeometryFactory.h>
 #include <geos/geom/CoordinateSequenceFactory.h>
@@ -224,8 +225,8 @@ TaggedLineString::asLineString() const
 unique_ptr<Geometry>
 TaggedLineString::asLinearRing() const
 {
-    return parentLine->getFactory()->createLinearRing(
-               getResultCoordinates());
+    return std::unique_ptr<Geometry>(parentLine->getFactory()->createLinearRing(
+               getResultCoordinates()));
 }
 
 /*public*/

-----------------------------------------------------------------------

Summary of changes:
 include/geos/geom/Geometry.h           |  17 ++-
 include/geos/geom/GeometryCollection.h |   7 +
 include/geos/geom/GeometryFactory.h    |  33 ++++-
 include/geos/geom/LineString.h         |   4 +-
 include/geos/geom/LinearRing.h         |   4 +-
 include/geos/geom/MultiLineString.h    |   7 +
 include/geos/geom/MultiPoint.h         |   4 +
 include/geos/geom/MultiPolygon.h       |   7 +
 include/geos/geom/Polygon.h            |   7 +
 src/geom/GeometryCollection.cpp        |  11 ++
 src/geom/GeometryFactory.cpp           | 232 ++++++++++++++++-----------------
 src/geom/LineString.cpp                |   6 +-
 src/geom/LinearRing.cpp                |   7 +-
 src/geom/MultiLineString.cpp           |  10 ++
 src/geom/MultiPoint.cpp                |  22 +++-
 src/geom/MultiPolygon.cpp              |   8 ++
 src/geom/Polygon.cpp                   |  31 +++++
 src/io/WKBReader.cpp                   | 125 ++++++------------
 src/io/WKTReader.cpp                   | 141 ++++++--------------
 src/simplify/TaggedLineString.cpp      |   5 +-
 20 files changed, 359 insertions(+), 329 deletions(-)


hooks/post-receive
-- 
GEOS


More information about the geos-commits mailing list