From f4fffcb7d69054242ba183314d77318b13139289 Mon Sep 17 00:00:00 2001 From: Guido Kanschat Date: Wed, 2 Mar 2005 22:37:44 +0000 Subject: [PATCH] new PathSearch class git-svn-id: https://svn.dealii.org/trunk@9956 0785d39b-7218-0410-832d-ea1e28bc413d --- deal.II/base/include/base/path_search.h | 258 ++++++++++++++++++++++++ deal.II/base/source/path_search.cc | 221 ++++++++++++++++++++ deal.II/doc/news/changes.html | 10 +- tests/base/Makefile | 4 +- 4 files changed, 490 insertions(+), 3 deletions(-) create mode 100644 deal.II/base/include/base/path_search.h create mode 100644 deal.II/base/source/path_search.cc diff --git a/deal.II/base/include/base/path_search.h b/deal.II/base/include/base/path_search.h new file mode 100644 index 0000000000..e4cb63fe9a --- /dev/null +++ b/deal.II/base/include/base/path_search.h @@ -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 +#include +#include +#include +#include + +#include +#include + +/** + * 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 + *
+ *
MESH
mesh input files in various formats (see GridIn) + *
PARAMETER
Parameter files (.prm) + *
+ * + * 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 istream object. + * @verbatim + * #include + * + * 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 MESH. If it manages to open a file, it + * returns the istream 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, + * .inp for instance, then either use "grid.inp" 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 + * (""), followed optionally by a standard directory of + * deal.II. 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 "/", 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 + 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 >::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& 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& 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 > path_lists; + + /** + * List of suffixes for each class. + */ + static std::map > suffix_lists; + + /** + * Path list for the class this object belongs to. + */ + std::vector& my_path_list; + + /** + * Suffix list for the class this object belongs to. + */ + std::vector& my_suffix_list; + + /** + * The file stream after open was called. + */ + std::auto_ptr stream; + + /** + * Debug flag. No output if zero. + */ + const unsigned int debug; + + /** + * The empty string. + */ + static std::string empty; +}; + + +template +void +PathSearch::show(STREAM& out) const +{ + out << "DEAL_II_" << cls << "PATH=\""; + bool first = true; + for (std::vector::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::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 index 0000000000..c1caa6c6b8 --- /dev/null +++ b/deal.II/base/source/path_search.cc @@ -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 +#include + +#include + +//TODO:[GK] Clean up open functions, reuse code! + +std::map > PathSearch::path_lists; +std::map > PathSearch::suffix_lists; +std::string PathSearch::empty(""); + +void +PathSearch::initialize_classes() +{ + std::vector 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& +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& +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::const_iterator path; + const std::vector::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::const_iterator suffix; + std::vector::const_iterator path; + const std::vector::const_iterator ends = my_suffix_list.end(); + const std::vector::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 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::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::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); + } +} + + diff --git a/deal.II/doc/news/changes.html b/deal.II/doc/news/changes.html index e7717b2045..1b1be4c146 100644 --- a/deal.II/doc/news/changes.html +++ b/deal.II/doc/news/changes.html @@ -61,11 +61,17 @@ contributor's names are abbreviated by WB (Wolfgang Bangerth), GK
  1. - Fixed: The class MultipleParameterLoop::UserClass had only + New: Class PathSearch allows to find + a file in a sequence of directories and by appending suffixes. +
    + (GK, 2005/03/02) +

    +
  2. + Fixed: The class MultipleParameterLoop::UserClass 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 - DataOutInterface. + DataOutInterface.
    (WB, 2005/02/20)

    diff --git a/tests/base/Makefile b/tests/base/Makefile index 1a7520906e..b9ef3501b9 100644 --- a/tests/base/Makefile +++ b/tests/base/Makefile @@ -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 \ -- 2.39.5