]> git.mxchange.org Git - flightgear.git/commitdiff
Refactor aircraft-dir visiting.
authorJames Turner <zakalawe@mac.com>
Sat, 16 Nov 2013 14:22:34 +0000 (14:22 +0000)
committerJames Turner <zakalawe@mac.com>
Sat, 16 Nov 2013 14:24:37 +0000 (14:24 +0000)
Cap maximum depth to avoid bug 865

src/Main/AircraftDirVisitorBase.hxx [new file with mode: 0644]
src/Main/CMakeLists.txt
src/Main/fg_init.cxx
src/Main/fg_init.hxx
src/Main/options.cxx

diff --git a/src/Main/AircraftDirVisitorBase.hxx b/src/Main/AircraftDirVisitorBase.hxx
new file mode 100644 (file)
index 0000000..cb216c7
--- /dev/null
@@ -0,0 +1,115 @@
+//
+// AircraftDirVisitorBase.hxx - helper to traverse a heirarchy containing
+// aircraft dirs
+//
+// Written by Curtis Olson, started August 1997.
+//
+// Copyright (C) 1997  Curtis L. Olson  - http://www.flightgear.org/~curt
+//
+// 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, write to the Free Software
+// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+//
+
+#ifndef FG_MAIN_AIRCRAFT_DIR_VISITOR_HXX
+#define FG_MAIN_AIRCRAFT_DIR_VISITOR_HXX
+
+class AircraftDirVistorBase
+{
+public:
+    
+protected:
+    enum VisitResult {
+        VISIT_CONTINUE = 0,
+        VISIT_DONE,
+        VISIT_ERROR
+    };
+    
+    AircraftDirVistorBase() :
+        _maxDepth(2)
+    {
+        
+    }
+    
+    VisitResult visitAircraftPaths()
+    {
+        const string_list& paths(globals->get_aircraft_paths());
+        string_list::const_iterator it = paths.begin();
+        for (; it != paths.end(); ++it) {
+            VisitResult vr = visitDir(simgear::Dir(*it), 0);
+            if (vr != VISIT_CONTINUE) {
+                return vr;
+            }
+        } // of aircraft paths iteration
+        
+        // if we reach this point, search the default location (always last)
+        SGPath rootAircraft(globals->get_fg_root());
+        rootAircraft.append("Aircraft");
+        return visitDir(rootAircraft, 0);
+    }
+    
+    VisitResult visitPath(const SGPath& path, unsigned int depth)
+    {
+        if (!path.exists()) {
+            return VISIT_ERROR;
+        }
+        
+        return visit(path);
+    }
+    
+    VisitResult visitDir(const simgear::Dir& d, unsigned int depth)
+    {
+        if (!d.exists()) {
+            SG_LOG(SG_GENERAL, SG_WARN, "visitDir: no such path:" << d.path());
+            return VISIT_CONTINUE;
+        }
+        
+        if (depth >= _maxDepth) {
+            return VISIT_CONTINUE;
+        }
+        
+        bool recurse = true;
+        simgear::PathList setFiles(d.children(simgear::Dir::TYPE_FILE, "-set.xml"));
+        simgear::PathList::iterator p;
+        for (p = setFiles.begin(); p != setFiles.end(); ++p) {
+            
+            // if we found a -set.xml at this level, don't recurse any deeper
+            recurse = false;
+            VisitResult vr = visit(*p);
+            if (vr != VISIT_CONTINUE) {
+                return vr;
+            }
+        } // of -set.xml iteration
+        
+        if (!recurse) {
+            return VISIT_CONTINUE;
+        }
+        
+        simgear::PathList subdirs(d.children(simgear::Dir::TYPE_DIR | simgear::Dir::NO_DOT_OR_DOTDOT));
+        for (p = subdirs.begin(); p != subdirs.end(); ++p) {
+            VisitResult vr = visitDir(*p, depth + 1);
+            if (vr != VISIT_CONTINUE) {
+                return vr;
+            }
+        }
+
+        return VISIT_CONTINUE;
+    } // of visitDir method
+    
+    virtual VisitResult visit(const SGPath& path) = 0;
+    
+private:
+    unsigned int _maxDepth;
+};
+
+#endif // of FG_MAIN_AIRCRAFT_DIR_VISITOR_HXX
index af70f7846e60014c201d0bcdbf4322b5920e0f9f..aeade6aa0e271e60095e44b0494dfa81d263b2d0 100644 (file)
@@ -36,6 +36,7 @@ set(HEADERS
        util.hxx
     positioninit.hxx
     subsystemFactory.hxx
+    AircraftDirVisitorBase.hxx
        )
 
 get_property(FG_SOURCES GLOBAL PROPERTY FG_SOURCES)
index d1d4d15ca8237368e373b5e37941ea20f2c529be..ef6f637f8ec2a1e9172cada30804fe62b4dfe94c 100644 (file)
 #include "main.hxx"
 #include "positioninit.hxx"
 #include "util.hxx"
+#include "AircraftDirVisitorBase.hxx"
 
 #if defined(SG_MAC)
 #include <GUI/CocoaHelpers.h> // for Mac impl of platformDefaultDataPath()
@@ -154,68 +155,7 @@ string fgBasePackageVersion() {
     return version;
 }
 
-
-template <class T>
-bool fgFindAircraftInDir(const SGPath& dirPath, T* obj, bool (T::*pred)(const SGPath& p))
-{
-  if (!dirPath.exists()) {
-    SG_LOG(SG_GENERAL, SG_WARN, "fgFindAircraftInDir: no such path:" << dirPath.str());
-    return false;
-  }
-    
-  bool recurse = true;
-  simgear::Dir dir(dirPath);
-  simgear::PathList setFiles(dir.children(simgear::Dir::TYPE_FILE, "-set.xml"));
-  simgear::PathList::iterator p;
-  for (p = setFiles.begin(); p != setFiles.end(); ++p) {
-    // check file name ends with -set.xml
-    
-    // if we found a -set.xml at this level, don't recurse any deeper
-    recurse = false;
-    
-    bool done = (obj->*pred)(*p);
-    if (done) {
-      return true;
-    }
-  } // of -set.xml iteration
-  
-  if (!recurse) {
-    return false;
-  }
-  
-  simgear::PathList subdirs(dir.children(simgear::Dir::TYPE_DIR | simgear::Dir::NO_DOT_OR_DOTDOT));
-  for (p = subdirs.begin(); p != subdirs.end(); ++p) {
-    if (p->file() == "CVS") {
-      continue;
-    }
-    
-    if (fgFindAircraftInDir(*p, obj, pred)) {
-      return true;
-    }
-  } // of subdirs iteration
-  
-  return false;
-}
-
-template <class T>
-void fgFindAircraft(T* obj, bool (T::*pred)(const SGPath& p))
-{
-  const string_list& paths(globals->get_aircraft_paths());
-  string_list::const_iterator it = paths.begin();
-  for (; it != paths.end(); ++it) {
-    bool done = fgFindAircraftInDir(SGPath(*it), obj, pred);
-    if (done) {
-      return;
-    }
-  } // of aircraft paths iteration
-  
-  // if we reach this point, search the default location (always last)
-  SGPath rootAircraft(globals->get_fg_root());
-  rootAircraft.append("Aircraft");
-  fgFindAircraftInDir(rootAircraft, obj, pred);
-}
-
-class FindAndCacheAircraft
+class FindAndCacheAircraft : public AircraftDirVistorBase
 {
 public:
   FindAndCacheAircraft(SGPropertyNode* autoSave)
@@ -272,7 +212,7 @@ public:
       n->setAttribute(SGPropertyNode::USERARCHIVE, true);
       _cache->removeChildren("aircraft");
   
-      fgFindAircraft(this, &FindAndCacheAircraft::checkAircraft);
+        visitAircraftPaths();
     }
     
     if (_foundPath.str().empty()) {
@@ -348,7 +288,7 @@ private:
     return false;
   }
   
-  bool checkAircraft(const SGPath& p)
+  virtual VisitResult visit(const SGPath& p)
   {
     // create cache node
     int i = 0;
@@ -370,10 +310,10 @@ private:
 
     if ( boost::equals(fileName, _searchAircraft.c_str(), is_iequal()) ) {
         _foundPath = p;
-        return true;
+        return VISIT_DONE;
     }
 
-    return false;
+    return VISIT_CONTINUE;
   }
   
   std::string _searchAircraft;
@@ -966,120 +906,3 @@ void fgReInitSubsystems()
 }
 
 
-///////////////////////////////////////////////////////////////////////////////
-// helper object to implement the --show-aircraft command.
-// resides here so we can share the fgFindAircraftInDir template above,
-// and hence ensure this command lists exectly the same aircraft as the normal
-// loading path.
-class ShowAircraft 
-{
-public:
-  ShowAircraft()
-  {
-    _minStatus = getNumMaturity(fgGetString("/sim/aircraft-min-status", "all"));
-  }
-  
-  
-  void show(const SGPath& path)
-  {
-    fgFindAircraftInDir(path, this, &ShowAircraft::processAircraft);
-  
-       simgear::requestConsole(); // ensure console is shown on Windows
-
-    std::sort(_aircraft.begin(), _aircraft.end(), ciLessLibC());
-    cout << "Available aircraft:" << endl;
-    for ( unsigned int i = 0; i < _aircraft.size(); i++ ) {
-        cout << _aircraft[i] << endl;
-    }
-  }
-  
-private:
-  bool processAircraft(const SGPath& path)
-  {
-    SGPropertyNode root;
-    try {
-       readProperties(path.str(), &root);
-    } catch (sg_exception& ) {
-       return false;
-    }
-  
-    int maturity = 0;
-    string descStr("   ");
-    descStr += path.file();
-  // trim common suffix from file names
-    int nPos = descStr.rfind("-set.xml");
-    if (nPos == (int)(descStr.size() - 8)) {
-      descStr.resize(nPos);
-    }
-    
-    SGPropertyNode *node = root.getNode("sim");
-    if (node) {
-      SGPropertyNode* desc = node->getNode("description");
-      // if a status tag is found, read it in
-      if (node->hasValue("status")) {
-        maturity = getNumMaturity(node->getStringValue("status"));
-      }
-      
-      if (desc) {
-        if (descStr.size() <= 27+3) {
-          descStr.append(29+3-descStr.size(), ' ');
-        } else {
-          descStr += '\n';
-          descStr.append( 32, ' ');
-        }
-        descStr += desc->getStringValue();
-      }
-    } // of have 'sim' node
-    
-    if (maturity < _minStatus) {
-      return false;
-    }
-
-    _aircraft.push_back(descStr);
-    return false;
-  }
-
-
-  int getNumMaturity(const char * str) 
-  {
-    // changes should also be reflected in $FG_ROOT/data/options.xml & 
-    // $FG_ROOT/data/Translations/string-default.xml
-    const char* levels[] = {"alpha","beta","early-production","production"}; 
-
-    if (!strcmp(str, "all")) {
-      return 0;
-    }
-
-    for (size_t i=0; i<(sizeof(levels)/sizeof(levels[0]));i++) 
-      if (strcmp(str,levels[i])==0)
-        return i;
-
-    return 0;
-  }
-
-  // recommended in Meyers, Effective STL when internationalization and embedded
-  // NULLs aren't an issue.  Much faster than the STL or Boost lex versions.
-  struct ciLessLibC : public std::binary_function<string, string, bool>
-  {
-    bool operator()(const std::string &lhs, const std::string &rhs) const
-    {
-      return strcasecmp(lhs.c_str(), rhs.c_str()) < 0 ? 1 : 0;
-    }
-  };
-
-  int _minStatus;
-  string_list _aircraft;
-};
-
-void fgShowAircraft(const SGPath &path)
-{
-    ShowAircraft s;
-    s.show(path);
-        
-#ifdef _MSC_VER
-    cout << "Hit a key to continue..." << endl;
-    std::cin.get();
-#endif
-}
-
-
index ffadf6d22507b5d8fe6a3b8b79c1a74c9bf8231d..b26af11f26a553928faae94378b1b6773395507d 100644 (file)
@@ -64,15 +64,6 @@ void fgPostInitSubsystems();
 // Reset: this is what the 'reset' command (and hence, GUI) is attached to
 void fgReInitSubsystems();
 
-/*
- * Search in the current directory, and in on directory deeper
- * for <aircraft>-set.xml configuration files and show the aircaft name
- * and the contents of the<description> tag in a sorted manner.
- *
- * @parampath the directory to search for configuration files
- */
-void fgShowAircraft(const SGPath &path);
-
 #endif // _FG_INIT_HXX
 
 
index 6a5b8bbbead1f2fa49335547e5d8268a2dc64d07..06e57f36f35963d879ceae520903955346215f8e 100644 (file)
@@ -65,6 +65,7 @@
 #include <Viewer/viewer.hxx>
 #include <Viewer/viewmgr.hxx>
 #include <Environment/presets.hxx>
+#include "AircraftDirVisitorBase.hxx"
 
 #include <osg/Version>
 
@@ -241,6 +242,129 @@ void fgSetDefaults ()
       fgSetupProxy( envp );
 }
 
+///////////////////////////////////////////////////////////////////////////////
+// helper object to implement the --show-aircraft command.
+// resides here so we can share the fgFindAircraftInDir template above,
+// and hence ensure this command lists exectly the same aircraft as the normal
+// loading path.
+class ShowAircraft : public AircraftDirVistorBase
+{
+public:
+    ShowAircraft()
+    {
+        _minStatus = getNumMaturity(fgGetString("/sim/aircraft-min-status", "all"));
+    }
+    
+    
+    void show(const SGPath& path)
+    {
+        visitDir(path, 0);
+        
+        simgear::requestConsole(); // ensure console is shown on Windows
+        
+        std::sort(_aircraft.begin(), _aircraft.end(), ciLessLibC());
+        cout << "Available aircraft:" << endl;
+        for ( unsigned int i = 0; i < _aircraft.size(); i++ ) {
+            cout << _aircraft[i] << endl;
+        }
+    }
+    
+private:
+    virtual VisitResult visit(const SGPath& path)
+    {
+        SGPropertyNode root;
+        try {
+            readProperties(path.str(), &root);
+        } catch (sg_exception& ) {
+            return VISIT_CONTINUE;
+        }
+        
+        int maturity = 0;
+        string descStr("   ");
+        descStr += path.file();
+        // trim common suffix from file names
+        int nPos = descStr.rfind("-set.xml");
+        if (nPos == (int)(descStr.size() - 8)) {
+            descStr.resize(nPos);
+        }
+        
+        SGPropertyNode *node = root.getNode("sim");
+        if (node) {
+            SGPropertyNode* desc = node->getNode("description");
+            // if a status tag is found, read it in
+            if (node->hasValue("status")) {
+                maturity = getNumMaturity(node->getStringValue("status"));
+            }
+            
+            if (desc) {
+                if (descStr.size() <= 27+3) {
+                    descStr.append(29+3-descStr.size(), ' ');
+                } else {
+                    descStr += '\n';
+                    descStr.append( 32, ' ');
+                }
+                descStr += desc->getStringValue();
+            }
+        } // of have 'sim' node
+        
+        if (maturity >= _minStatus) {
+            _aircraft.push_back(descStr);
+        }
+        
+        return VISIT_CONTINUE;
+    }
+    
+    
+    int getNumMaturity(const char * str)
+    {
+        // changes should also be reflected in $FG_ROOT/data/options.xml &
+        // $FG_ROOT/data/Translations/string-default.xml
+        const char* levels[] = {"alpha","beta","early-production","production"};
+        
+        if (!strcmp(str, "all")) {
+            return 0;
+        }
+        
+        for (size_t i=0; i<(sizeof(levels)/sizeof(levels[0]));i++)
+            if (strcmp(str,levels[i])==0)
+                return i;
+        
+        return 0;
+    }
+    
+    // recommended in Meyers, Effective STL when internationalization and embedded
+    // NULLs aren't an issue.  Much faster than the STL or Boost lex versions.
+    struct ciLessLibC : public std::binary_function<string, string, bool>
+    {
+        bool operator()(const std::string &lhs, const std::string &rhs) const
+        {
+            return strcasecmp(lhs.c_str(), rhs.c_str()) < 0 ? 1 : 0;
+        }
+    };
+    
+    int _minStatus;
+    string_list _aircraft;
+};
+
+/*
+ * Search in the current directory, and in on directory deeper
+ * for <aircraft>-set.xml configuration files and show the aircaft name
+ * and the contents of the<description> tag in a sorted manner.
+ *
+ * @parampath the directory to search for configuration files
+ */
+void fgShowAircraft(const SGPath &path)
+{
+    ShowAircraft s;
+    s.show(path);
+    
+#ifdef _MSC_VER
+    cout << "Hit a key to continue..." << endl;
+    std::cin.get();
+#endif
+}
+
+
 static bool
 parse_wind (const string &wind, double * min_hdg, double * max_hdg,
            double * speed, double * gust)