[Liblas-commits] hg-main-tree: add error checking to pipeline reader

liblas-commits at liblas.org liblas-commits at liblas.org
Wed Jul 27 15:48:44 EDT 2011


details:   http://hg.libpc.orghg-main-tree/rev/5390b5683fcf
changeset: 955:5390b5683fcf
user:      Michael P. Gerlek <mpg at flaxen.com>
date:      Wed Jul 27 12:48:20 2011 -0700
description:
add error checking to pipeline reader
Subject: hg-main-tree: merge

details:   http://hg.libpc.orghg-main-tree/rev/fd0fe36cbfa7
changeset: 956:fd0fe36cbfa7
user:      Michael P. Gerlek <mpg at flaxen.com>
date:      Wed Jul 27 12:48:39 2011 -0700
description:
merge

diffstat:

 apps/pc2pc.cpp                    |   57 ++++--
 include/pdal/PipelineManager.hpp  |   20 +-
 include/pdal/exceptions.hpp       |   10 +
 src/PipelineManager.cpp           |  323 ++++++++++++++++++++++++-------------
 test/data/pipeline_bad01.xml      |   26 +++
 test/data/pipeline_bad02.xml      |   26 +++
 test/data/pipeline_bad03.xml      |   29 +++
 test/data/pipeline_bad04.xml      |   26 +++
 test/data/pipeline_bad05.xml      |   33 +++
 test/data/pipeline_bad06.xml      |   33 +++
 test/data/pipeline_bad07.xml      |   33 +++
 test/data/pipeline_bad08.xml      |   26 +++
 test/data/pipeline_bad09.xml      |   26 +++
 test/data/pipeline_bad10.xml      |   18 ++
 test/unit/PipelineManagerTest.cpp |   44 +++++
 15 files changed, 594 insertions(+), 136 deletions(-)

diffs (truncated from 993 to 300 lines):

diff -r d364ec8b549c -r fd0fe36cbfa7 apps/pc2pc.cpp
--- a/apps/pc2pc.cpp	Wed Jul 27 09:06:40 2011 -0500
+++ b/apps/pc2pc.cpp	Wed Jul 27 12:48:39 2011 -0700
@@ -230,35 +230,56 @@
 
 
         pdal::drivers::oci::Reader reader(options);
-        // pdal::filters::ByteSwapFilter swapper(reader);
-        pdal::filters::ScalingFilter scalingFilter(reader, false);
-        
+        pdal::drivers::las::LasWriter* writer;
+
         pdal::SpatialReference out_ref(out_wkt);
         pdal::SpatialReference in_ref(reader.getSpatialReference());
-        
-        pdal::filters::ReprojectionFilter reprojectionFilter(scalingFilter, in_ref, out_ref);
-        pdal::filters::ScalingFilter descalingFilter(   reprojectionFilter, 
-                                                        scalex, offsetx,
-                                                        scaley, offsety, 
-                                                        scalez, offsetz, 
-                                                        true);
+        if (!(in_ref == out_ref)) 
+        {
+            // pdal::filters::ByteSwapFilter swapper(reader);
+            pdal::filters::ScalingFilter scalingFilter(reader, false);
+            pdal::filters::ReprojectionFilter reprojectionFilter(scalingFilter, in_ref, out_ref);
+            pdal::filters::ScalingFilter descalingFilter(   reprojectionFilter, 
+                                                            scalex, offsetx,
+                                                            scaley, offsety, 
+                                                            scalez, offsetz, 
+                                                            true);
 
-        pdal::drivers::las::LasWriter writer(descalingFilter, ofs);
-
-
-        if (compress)
-            writer.setCompressed(true);
-        writer.setChunkSize(oracle_options.get<boost::uint32_t>("capacity"));
-        writer.setPointFormat(pdal::drivers::las::PointFormat3);
+            writer = new pdal::drivers::las::LasWriter(descalingFilter, ofs);
+            if (compress)
+                writer->setCompressed(true);
+            writer->setChunkSize(oracle_options.get<boost::uint32_t>("capacity"));
+            writer->setPointFormat(pdal::drivers::las::PointFormat3);
         
 
-        writer.write(0);
+            writer->write(0);
+            delete writer;
+        }
+        else
+        {
+            writer = new pdal::drivers::las::LasWriter(reader, ofs);
+            if (compress)
+                writer->setCompressed(true);
+            writer->setChunkSize(oracle_options.get<boost::uint32_t>("capacity"));
+            writer->setPointFormat(pdal::drivers::las::PointFormat3);
+        
+
+            writer->write(0);
+            delete writer;
+        }
+        
+
+
+
+
             
         } catch (pdal::pdal_error& e)
         {
             std::cerr << "Error reading oracle: " << e.what() << std::endl;
+            return 1;
             
         }
+        
             
 
     #else
diff -r d364ec8b549c -r fd0fe36cbfa7 include/pdal/PipelineManager.hpp
--- a/include/pdal/PipelineManager.hpp	Wed Jul 27 09:06:40 2011 -0500
+++ b/include/pdal/PipelineManager.hpp	Wed Jul 27 12:48:39 2011 -0700
@@ -53,6 +53,9 @@
 
 class PDAL_DLL PipelineManager
 {
+private:
+    class StageParserContext;
+
 public:
     PipelineManager();
     ~PipelineManager();
@@ -76,15 +79,18 @@
     void writeWriterPipeline(const std::string& filename) const;
 
 private:
-    void parsePipeline(const boost::property_tree::ptree&, Writer*& writer, Stage*& stage);
+    boost::property_tree::ptree parsePipelineElement(const std::string& filename);
+    Writer* parseWriterRoot(const boost::property_tree::ptree&);
+    Stage* parseStageRoot(const boost::property_tree::ptree&);
 
-    Reader* parseReader(const boost::property_tree::ptree& tree);
-    Filter* parseFilter(const boost::property_tree::ptree& tree);
-    MultiFilter* parseMultiFilter(const boost::property_tree::ptree& tree);
-    Writer* parseWriter(const boost::property_tree::ptree& tree);
+    Stage* parseStageElement(const std::string& name, const boost::property_tree::ptree& subtree);
+    Reader* parseReaderElement(const boost::property_tree::ptree& tree);
+    Filter* parseFilterElement(const boost::property_tree::ptree& tree);
+    MultiFilter* parseMultiFilterElement(const boost::property_tree::ptree& tree);
+    Writer* parseWriterElement(const boost::property_tree::ptree& tree);
 
-    Option<std::string> parseOption(const boost::property_tree::ptree& tree);
-    std::string parseType(const boost::property_tree::ptree& tree);
+    Option<std::string> parseOptionElement(const boost::property_tree::ptree& tree);
+    std::string parseTypeElement(const boost::property_tree::ptree& tree);
 
     StageFactory m_factory;
 
diff -r d364ec8b549c -r fd0fe36cbfa7 include/pdal/exceptions.hpp
--- a/include/pdal/exceptions.hpp	Wed Jul 27 09:06:40 2011 -0500
+++ b/include/pdal/exceptions.hpp	Wed Jul 27 12:48:39 2011 -0700
@@ -159,6 +159,16 @@
     {}
 };
 
+
+// for errors when reading pipeline XML
+class pipeline_xml_error : public pdal_error
+{
+public:
+    pipeline_xml_error(std::string const& msg)
+        : pdal_error(msg)
+    {}
+};
+
 } // namespace pdal
 
 #endif // PDAL_EXCEPTION_HPP_INCLUDED
diff -r d364ec8b549c -r fd0fe36cbfa7 src/PipelineManager.cpp
--- a/src/PipelineManager.cpp	Wed Jul 27 09:06:40 2011 -0500
+++ b/src/PipelineManager.cpp	Wed Jul 27 12:48:39 2011 -0700
@@ -45,6 +45,7 @@
 #include <pdal/drivers/liblas/Writer.hpp>
 
 #include <boost/property_tree/xml_parser.hpp>
+#include <boost/optional.hpp>
 
 namespace pdal
 {
@@ -122,7 +123,68 @@
 }
 
 
-Option<std::string> PipelineManager::parseOption(const boost::property_tree::ptree& tree)
+class PipelineManager::StageParserContext
+{
+public:
+    enum Cardinality { None, One, Many };
+
+    StageParserContext(Cardinality cardinality)
+        : m_numTypes(0)
+        , m_cardinality(cardinality)
+        , m_numStages(0)
+    {
+        return;
+    }
+
+    void addType()
+    {
+        ++m_numTypes;
+    }
+
+    void addStage()
+    {
+        ++m_numStages;
+    }
+    
+    void addUnknown(const std::string& name)
+    {
+        throw pipeline_xml_error("unknown child of element: " + name);
+    }
+
+    void validate()
+    {
+        if (m_numTypes == 0)
+            throw pipeline_xml_error("expected Type element missing");
+        if (m_numTypes > 1)
+            throw pipeline_xml_error("extra Type element found");
+
+        if (m_cardinality == None)
+        {
+            if (m_numStages != 0)
+                throw pipeline_xml_error("found child stages where none expected");
+        }
+        if (m_cardinality == One)
+        {
+            if (m_numStages == 0)
+                throw pipeline_xml_error("expected child stage missing");
+            if (m_numStages > 1)
+                throw pipeline_xml_error("extra child stages found");
+        }
+        if (m_cardinality == Many)
+        {
+            if (m_numStages == 0)
+                throw pipeline_xml_error("expected child stage missing");
+        }
+    }
+
+private:
+    int m_numTypes;
+    Cardinality m_cardinality; // num child stages allowed
+    int m_numStages;
+};
+
+
+Option<std::string> PipelineManager::parseOptionElement(const boost::property_tree::ptree& tree)
 {
     // cur is an option element, such as this:
     //     <option>
@@ -138,7 +200,7 @@
 }
 
 
-std::string PipelineManager::parseType(const boost::property_tree::ptree& tree)
+std::string PipelineManager::parseTypeElement(const boost::property_tree::ptree& tree)
 {
     // tree is this:
     //     <type>drivers.foo.writer</type>
@@ -149,234 +211,278 @@
 }
 
 
-Reader* PipelineManager::parseReader(const boost::property_tree::ptree& tree)
+Stage* PipelineManager::parseStageElement(const std::string& name, const boost::property_tree::ptree& subtree)
+{
+    Stage* stage = NULL;
+
+    if (name == "Filter")
+    {
+        stage = parseFilterElement(subtree);
+    }
+    else if (name == "MultiFilter")
+    {
+        stage = parseMultiFilterElement(subtree);
+    }
+    else if (name == "Reader")
+    {
+        stage = parseReaderElement(subtree);
+    }
+    else
+    {
+        throw pipeline_xml_error("encountered unknown stage type");
+    }
+
+    return stage;
+}
+
+
+Reader* PipelineManager::parseReaderElement(const boost::property_tree::ptree& tree)
 {
     Options options;
     std::string type;
+    
+    StageParserContext context(StageParserContext::None);
 
     boost::property_tree::ptree::const_iterator iter = tree.begin();
     while (iter != tree.end())
     {
-        if (iter->first == "Type")
+        const std::string& name = iter->first;
+        const boost::property_tree::ptree& subtree = iter->second;
+
+        if (name == "Type")
         {
-            const boost::property_tree::ptree subtree = iter->second;
-            type = parseType(subtree);
+            context.addType();
+            type = parseTypeElement(subtree);
         }
-        else if (iter->first == "Option")
+        else if (name == "Option")
         {
-            const boost::property_tree::ptree subtree = iter->second;
-            Option<std::string> option = parseOption(subtree);
+            Option<std::string> option = parseOptionElement(subtree);
             options.add(option);
         }
         else
         {
-            throw pdal_error("xml reader invalid child of Reader element");
+            context.addUnknown(name);
         }
         ++iter;
     }
 
+    context.validate();
+
     Reader* ptr = addReader(type, options);
 
     return ptr;
 }


More information about the Liblas-commits mailing list