]> https://gitweb.dealii.org/ - dealii.git/commitdiff
new PathSearch class
authorGuido Kanschat <dr.guido.kanschat@gmail.com>
Wed, 2 Mar 2005 22:37:44 +0000 (22:37 +0000)
committerGuido Kanschat <dr.guido.kanschat@gmail.com>
Wed, 2 Mar 2005 22:37:44 +0000 (22:37 +0000)
git-svn-id: https://svn.dealii.org/trunk@9956 0785d39b-7218-0410-832d-ea1e28bc413d

deal.II/base/include/base/path_search.h [new file with mode: 0644]
deal.II/base/source/path_search.cc [new file with mode: 0644]
deal.II/doc/news/changes.html
tests/base/Makefile

diff --git a/deal.II/base/include/base/path_search.h b/deal.II/base/include/base/path_search.h
new file mode 100644 (file)
index 0000000..e4cb63f
--- /dev/null
@@ -0,0 +1,258 @@
+//-----------------------------------------------------------------------
+//    $Id$
+//    Version: $Name$
+//
+//    Copyright (C) 2005 by the deal.II authors
+//
+//    This file is subject to QPL and may not be  distributed
+//    without copyright and license information. Please refer
+//    to the file deal.II/doc/license.html for the  text  and
+//    further information on this license.
+//
+//-----------------------------------------------------------------------
+#ifndef __deal2__path_search_h
+#define __deal2__path_search_h
+
+
+#include <string>
+#include <fstream>
+#include <map>
+#include <vector>
+#include <memory>
+
+#include <base/config.h>
+#include <base/exceptions.h>
+
+/**
+ * Support for searching files in a list of paths and with a list of
+ * suffixes.
+ *
+ * A list of search paths is maintained for each file class supported.
+ * A file class is defined by s unique string. The classes provided are
+ * <dl>
+ * <dt> MESH <dd> mesh input files in various formats (see GridIn)
+ * <dt> PARAMETER <dd> Parameter files (<tt>.prm</tt>)
+ * </dl>
+ *
+ * Additional file classes can be added easily by using add_class().
+ *
+ * Usage: First, you construct a PathSearch object for a certain file class,
+ * e.g. meshes. Then, you use the open() method to obtain a reference
+ * to an <tt>istream</tt> object.
+ * @verbatim
+ * #include <base/path_search.h>
+ *
+ * PathSearch search("MESH");
+ * istream& in = search.open("grid");
+ * ...
+ * @endverbatim
+ *
+ * This piece of code will first traverse all paths in the list set up
+ * for file class <TT>MESH</tt>. If it manages to open a file, it
+ * returns the <tt>istream</tt> object. If not, it will try to append
+ * the first suffix of the suffix list and do the same. And so on. If
+ * no file is found in the end, an exception is thrown.
+ *
+ * If you want to restrict your search to a certain mesh format,
+ * <tt>.inp</tt> for instance, then either use <tt>"grid.inp"</tt> in
+ * the code above or use the alternative open function
+ * @verbatim
+ * istream& in = search.open("grid", ".inp");
+ * @endverbatim
+ *
+ * Path lists are by default starting with the current directory
+ * (<tt>""</tt>), followed optionally by a standard directory of
+ * <acronym>deal.II</acronym>. Use show() to find out the path list
+ * for a given class. Paths and suffixes can be added using the
+ * functions add_path() and add_suffix(), repectively.
+ *
+ * @note Directories in the path list should always end with a
+ * trailing <tt>"/"</tt>, while suffixes should always start with a
+ * dot. These characters are not added automatically (allowing you to
+ * do some real file name editing).
+ *
+ * @todo Add support for environment variables like in kpathsea.
+ *
+ * @author Guido Kanschat, 2005
+ */
+
+class PathSearch
+{
+  public:
+                                    /**
+                                     * Position for adding a new item to a list.
+                                     */
+    enum Position
+    {
+                                          /// Add new item at end of list
+         back,
+                                          /// Add new item at front of list
+         front,
+                                          /// Add in path list after empty element
+         after_none
+    };
+    
+                                    /**
+                                     * Constructor. The first argument is a
+                                     * string identifying the class of files
+                                     * to be searched for.
+                                     *
+                                     * The debug argument determines
+                                     * the verbosity of this class.
+                                     */
+    PathSearch(const std::string& cls, const unsigned int debug=0);
+
+                                    /**
+                                     * Open a file in the class
+                                     * specified by the constructor.
+                                     */
+    std::istream& open(const std::string& filename);
+
+                                    /**
+                                     * Open a file in the class
+                                     * specified by the
+                                     * constructor. Do not use the
+                                     * standard suffix list, but only
+                                     * try to apply the suffix given.
+                                     */
+    std::istream& open(const std::string& filename,
+                      const std::string& suffix);
+    
+                                    /**
+                                     * Show the paths and suffixes
+                                     * used for this object.
+                                     */
+    template <class STREAM>
+    void show(STREAM& stream) const;
+    
+                                    /**
+                                     * Add a new class.
+                                     */
+    static void add_class (const std::string& cls);
+    
+                                    /**
+                                     * Add a path to the current
+                                     * class. See
+                                     * PathSearch::Position for
+                                     * possible position arguments.
+                                     */
+    void add_path (const std::string& path, Position pos = back);
+    
+                                    /**
+                                     * Add a path to the current
+                                     * class. See
+                                     * PathSearch::Position for
+                                     * possible position arguments.
+                                     */
+    void add_suffix (const std::string& suffix, Position pos = back);
+
+                                    /**
+                                     * This class was not
+                                     * registered in the path
+                                     * search mechanism.
+                                     */
+    DeclException1(ExcNoClass,
+                  std::string,
+                  << "The class "
+                  << arg1
+                  << " must be registered before referring it in PathSearch");
+    
+    DeclException2(ExcFileNotFound,
+                  std::string, std::string,
+                  << "The file \"" << arg1
+                  << "\"was not found in the path for files of class "
+                  << arg2);
+    
+  private:
+                                    /**
+                                     * Type of values in the class maps.
+                                     */
+    typedef std::map<std::string, std::vector<std::string> >::value_type map_type;
+    
+                                    /**
+                                     * Initialize the static list objects for further use.
+                                     */
+    static void initialize_classes();
+    
+                                    /**
+                                     * Get path list for a certain
+                                     * class. Used to set up
+                                     * #my_path_list in constructor.
+                                     */
+    static std::vector<std::string>& get_path_list(const std::string& cls);
+    
+                                    /**
+                                     * Get suffix list for a certain
+                                     * class. Used to set up
+                                     * #my_suffix_list in constructor.
+                                     */
+    static std::vector<std::string>& get_suffix_list(const std::string& cls);
+    
+                                    /**
+                                     * The flie class handled by this object.
+                                     */
+    const std::string cls;
+    
+                                    /**
+                                     * All path lists for all
+                                     * classes, such that we can
+                                     * build them only once.
+                                     */
+    static std::map<std::string, std::vector<std::string> > path_lists;
+    
+                                    /**
+                                     * List of suffixes for each class.
+                                     */
+    static std::map<std::string, std::vector<std::string> > suffix_lists;
+    
+                                    /**
+                                     * Path list for the class this object belongs to.
+                                     */
+    std::vector<std::string>& my_path_list;
+    
+                                    /**
+                                     * Suffix list for the class this object belongs to.
+                                     */
+    std::vector<std::string>& my_suffix_list;
+    
+                                    /**
+                                     * The file stream after open was called.
+                                     */
+    std::auto_ptr<std::ifstream> stream;
+
+                                    /**
+                                     * Debug flag. No output if zero.
+                                     */
+    const unsigned int debug;
+    
+                                    /**
+                                     * The empty string.
+                                     */
+    static std::string empty;
+};
+
+
+template <class STREAM>
+void
+PathSearch::show(STREAM& out) const
+{
+  out << "DEAL_II_" << cls << "PATH=\"";
+  bool first = true;
+  for (std::vector<std::string>::iterator p = my_path_list.begin();
+       p != my_path_list.end(); ++p)
+    {
+      if (!first)
+       out << ':';
+      out << *p;
+      first = false;
+    }
+  out << '"' << std::endl << " Suffixes";
+  for (std::vector<std::string>::iterator s = my_suffix_list.begin();
+       s != my_suffix_list.end(); ++s)
+    out << " \"" << *s << '"';
+  out << std::endl;
+}
+
+
+#endif
+
diff --git a/deal.II/base/source/path_search.cc b/deal.II/base/source/path_search.cc
new file mode 100644 (file)
index 0000000..c1caa6c
--- /dev/null
@@ -0,0 +1,221 @@
+//--------------------------------------------------------------------
+//      $Id$   
+//    Version: $Name$
+//
+//    Copyright (C) 2005 by the deal.II authors
+//
+//    This file is subject to QPL and may not be  distributed
+//    without copyright and license information. Please refer
+//    to the file deal.II/doc/license.html for the  text  and
+//    further information on this license.
+//
+//--------------------------------------------------------------------
+
+#include <base/path_search.h>
+#include <base/logstream.h>
+
+#include <iostream>
+
+//TODO:[GK] Clean up open functions, reuse code!
+
+std::map<std::string, std::vector<std::string> > PathSearch::path_lists;
+std::map<std::string, std::vector<std::string> > PathSearch::suffix_lists;
+std::string PathSearch::empty("");
+
+void
+PathSearch::initialize_classes()
+{
+  std::vector<std::string> v;
+  v.push_back(empty);
+  path_lists.insert(map_type(std::string("PARAMETER"), v));
+
+  v.push_back(std::string(DEAL_II_PATH "/lib/meshes/"));
+  path_lists.insert(map_type(std::string("MESH"), v));
+
+  v.clear();
+  v.push_back(empty);
+  v.push_back(std::string(".prm"));
+  suffix_lists.insert(map_type(std::string("PARAMETER"), v));
+  
+  v.clear();
+  v.push_back(empty);
+  v.push_back(std::string(".inp"));
+  v.push_back(std::string(".xda"));
+  v.push_back(std::string(".dbmesh"));
+  suffix_lists.insert(map_type(std::string("MESH"), v));
+}
+
+std::vector<std::string>&
+PathSearch::get_path_list(const std::string& cls)
+{
+  if (path_lists.empty())
+    initialize_classes();
+
+  Assert(path_lists.count(cls) != 0, ExcNoClass(cls));
+  
+  return path_lists.find(cls)->second;
+}
+
+
+std::vector<std::string>&
+PathSearch::get_suffix_list(const std::string& cls)
+{
+  Assert(suffix_lists.count(cls) != 0, ExcNoClass(cls));
+  
+  return suffix_lists.find(cls)->second;
+}
+
+
+PathSearch::PathSearch(const std::string& cls,
+                      const unsigned int debug)
+               :
+               cls(cls),
+               my_path_list(get_path_list(cls)),
+               my_suffix_list(get_suffix_list(cls)),
+               debug(debug)
+{}
+
+
+std::istream&
+PathSearch::open (const std::string& filename,
+                 const std::string& suffix)
+{
+  std::string name;
+  std::vector<std::string>::const_iterator path;
+  const std::vector<std::string>::const_iterator endp = my_path_list.end();
+
+  if (debug > 2)
+    deallog << "PathSearch[" << cls << "] "
+           << my_path_list.size() << " directories "
+           << std::endl;
+  
+                                  // Try without suffix first
+  for (path = my_path_list.begin(); path != endp; ++path)
+    {
+      name = *path + filename;
+      if (debug > 1)
+       deallog << "PathSearch[" << cls << "] trying "
+               << name << std::endl;
+      stream.reset(new std::ifstream(name.c_str()));
+      if (stream->is_open())
+       {
+         if (debug > 0)
+           deallog << "PathSearch[" << cls << "] opened "
+                   << name << std::endl;
+         return *stream;
+       }
+    }
+
+                                  // Now try with given suffix
+  for (path = my_path_list.begin(); path != endp; ++path)
+    {
+      name = *path + filename + suffix;
+      if (debug > 1)
+       deallog << "PathSearch[" << cls << "] trying "
+               << name << std::endl;
+      stream.reset(new std::ifstream(name.c_str()));
+      if (stream->is_open())
+       {
+         if (debug > 0)
+           deallog << "PathSearch[" << cls << "] opened "
+                   << name << std::endl;
+         return *stream;
+       }
+    }
+  AssertThrow(false, ExcFileNotFound(filename, cls));
+  return *stream;
+}
+
+
+std::istream&
+PathSearch::open (const std::string& filename)
+{
+  std::string name;
+  std::vector<std::string>::const_iterator suffix;
+  std::vector<std::string>::const_iterator path;
+  const std::vector<std::string>::const_iterator ends = my_suffix_list.end();
+  const std::vector<std::string>::const_iterator endp = my_path_list.end();
+
+  if (debug > 2)
+    deallog << "PathSearch[" << cls << "] "
+           << my_path_list.size() << " directories "
+           << my_suffix_list.size() << " suffixes"
+           << std::endl;
+  
+  for (suffix = my_suffix_list.begin(); suffix != ends; ++suffix)
+    {
+      for (path = my_path_list.begin(); path != endp; ++path)
+       {
+         name = *path + filename + *suffix;
+         if (debug > 1)
+           deallog << "PathSearch[" << cls << "] trying "
+                   << name << std::endl;
+         stream.reset(new std::ifstream(name.c_str()));
+         if (stream->is_open())
+           {
+             if (debug > 0)
+               deallog << "PathSearch[" << cls << "] opened "
+                       << name << std::endl;
+             return *stream;
+           }
+       }
+    }
+  AssertThrow(false, ExcFileNotFound(filename, cls));
+  return *stream;
+}
+
+
+void
+PathSearch::add_class (const std::string& cls)
+{
+                                  // Make sure standard classes are
+                                  // initialized first
+  if (path_lists.empty())
+    initialize_classes();
+                                  // Add empty path and empty suffix
+                                  // for new class
+  std::vector<std::string> v;
+  v.push_back(empty);
+  path_lists.insert(map_type(cls, v));
+  suffix_lists.insert(map_type(cls, v));
+}
+
+
+void
+PathSearch::add_path (const std::string& path,
+                     Position pos)
+{
+  if (pos == back)
+    my_path_list.push_back(path);
+  else if (pos == front)
+    my_path_list.insert(my_path_list.begin(), path);
+  else if (pos == after_none)
+    {
+      std::vector<std::string>::iterator
+       i = std::find(my_path_list.begin(), my_path_list.end(), empty);
+      if (i != my_path_list.end())
+       ++i;
+      my_path_list.insert(i, path);
+    }
+}
+
+
+void
+PathSearch::add_suffix (const std::string& suffix,
+                     Position pos)
+{
+  if (pos == back)
+    my_suffix_list.push_back(suffix);
+  else if (pos == front)
+    my_suffix_list.insert(my_suffix_list.begin(), suffix);
+  else if (pos == after_none)
+    {
+      std::vector<std::string>::iterator
+       i = std::find(my_suffix_list.begin(), my_suffix_list.end(), empty);
+      if (i != my_suffix_list.end())
+       ++i;
+      my_suffix_list.insert(i, suffix);
+    }
+}
+
+
index e7717b2045c81d7f2abef8ac1f99a1abd81270fc..1b1be4c146163904661c203263faadf8a0940266 100644 (file)
@@ -61,11 +61,17 @@ contributor's names are abbreviated by WB (Wolfgang Bangerth), GK
 
 <ol>
   <li> <p>
-       Fixed: The class <code>MultipleParameterLoop::UserClass</code> had only
+       New: Class <code class="class">PathSearch</code> allows to find
+       a file in a sequence of directories and by appending suffixes.
+       <br> 
+       (GK, 2005/03/02)
+       </p>
+  <li> <p>
+       Fixed: The class <code class="class">MultipleParameterLoop::UserClass</code> had only
        virtual abstract functions but no virtual destructor. This caused
        warnings with some compilers, and is generally bad practice
        anyway. This is now fixed. The same holds with respect to the class
-       <code>DataOutInterface</code>.
+       <code class="class">DataOutInterface</code>.
        <br> 
        (WB, 2005/02/20)
        </p>
index 1a7520906ecf535ee87434b5feba5e7d8c176787..b9ef3501b9c62be14cb4a866d2394b5ab8ffa0f4 100644 (file)
@@ -1,6 +1,6 @@
 ############################################################
 # $Id$
-# Copyright (C) 2000, 2001, 2002, 2003, 2004 by the deal.II authors
+# Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 by the deal.II authors
 ############################################################
 
 ############################################################
@@ -24,6 +24,7 @@ threads.cc : threads.pl
 
 data_out_base.exe  : data_out_base.g.$(OBJEXT)                      $(lib-base.g)
 logtest.exe        : logtest.g.$(OBJEXT)                            $(lib-base.g)
+path_search.exe    : path_search.g.$(OBJEXT)                        $(lib-base.g)
 polynomial_test.exe: polynomial_test.g.$(OBJEXT)                    $(lib-base.g)
 polynomial1d.exe   : polynomial1d.g.$(OBJEXT)                       $(lib-base.g)
 quadrature_test.exe: quadrature_test.g.$(OBJEXT)                    $(lib-base.g)
@@ -41,6 +42,7 @@ bdm.exe            : bdm.g.$(OBJEXT)                                $(lib-base.g
 auto_derivative_function.exe : auto_derivative_function.g.$(OBJEXT) $(libraries) $(lib-base.g)
 
 tests =  logtest reference quadrature_test quadrature_selector \
+        path_search \
          slice_vector table tensor \
           timer threads polynomial1d polynomial_test \
          auto_derivative_function anisotropic_1 anisotropic_2 \

In the beginning the Universe was created. This has made a lot of people very angry and has been widely regarded as a bad move.

Douglas Adams


Typeset in Trocchi and Trocchi Bold Sans Serif.