Home | History | Annotate | Line # | Download | only in common
SearchPath.cpp revision 1.1
      1 /*
      2  * File:	SearchPath.cpp
      3  *
      4  * Copyright (c) Freescale Semiconductor, Inc. All rights reserved.
      5  * See included license file for license details.
      6  */
      7 
      8 #include "SearchPath.h"
      9 #include <stdio.h>
     10 
     11 #if defined(WIN32)
     12 	#define PATH_SEP_CHAR '\\'
     13 	#define PATH_SEP_STRING "\\"
     14 #else
     15 	#define PATH_SEP_CHAR '/'
     16 	#define PATH_SEP_STRING "/"
     17 #endif
     18 
     19 PathSearcher * PathSearcher::s_searcher = NULL;
     20 
     21 //! This function will create the global path search object if it has
     22 //! not already been created.
     23 PathSearcher & PathSearcher::getGlobalSearcher()
     24 {
     25 	if (!s_searcher)
     26 	{
     27 		s_searcher = new PathSearcher;
     28 	}
     29 
     30 	return *s_searcher;
     31 }
     32 
     33 void PathSearcher::addSearchPath(std::string & path)
     34 {
     35 	m_paths.push_back(path);
     36 }
     37 
     38 //! The \a base path argument can be either a relative or absolute path. If the path
     39 //! is relative, then it is joined with search paths one after another until a matching
     40 //! file is located or all search paths are exhausted. If the \a base is absolute,
     41 //! only that path is tested and if invalid false is returned.
     42 //!
     43 //! \param base A path to the file that is to be found.
     44 //! \param targetType Currently ignored. In the future it will let you select whether to
     45 //!		find a file or directory.
     46 //! \param searchCwd If set to true, the current working directory is searched before using
     47 //!		any of the search paths. Otherwise only the search paths are considered.
     48 //! \param[out] result When true is returned this string is set to the first path at which
     49 //!		a valid file was found.
     50 //!
     51 //! \retval true A matching file was found among the search paths. The contents of \a result
     52 //!		are a valid path.
     53 //! \retval false No match could be made. \a result has been left unmodified.
     54 bool PathSearcher::search(const std::string & base, target_type_t targetType, bool searchCwd, std::string & result)
     55 {
     56 	FILE * tempFile;
     57 	bool absolute = isAbsolute(base);
     58 
     59 	// Try cwd first if requested. Same process applies to absolute paths.
     60 	if (absolute || searchCwd)
     61 	{
     62 		tempFile = fopen(base.c_str(), "r");
     63 		if (tempFile)
     64 		{
     65 			fclose(tempFile);
     66 			result = base;
     67 			return true;
     68 		}
     69 	}
     70 
     71 	// If the base path is absolute and the previous test failed, then we don't go any further.
     72 	if (absolute)
     73 	{
     74 		return false;
     75 	}
     76 
     77 	// Iterate over all search paths.
     78 	string_list_t::const_iterator it = m_paths.begin();
     79 	for (; it != m_paths.end(); ++it)
     80 	{
     81 		std::string searchPath = joinPaths(*it, base);
     82 
     83 		tempFile = fopen(searchPath.c_str(), "r");
     84 		if (tempFile)
     85 		{
     86 			fclose(tempFile);
     87 			result = searchPath;
     88 			return true;
     89 		}
     90 	}
     91 
     92 	// Couldn't find anything matching the base path.
     93 	return false;
     94 }
     95 
     96 bool PathSearcher::isAbsolute(const std::string & path)
     97 {
     98 #if __WIN32__
     99 	return path.size() >= 3 && path[1] == ':' && path[2] == '\\';
    100 #else
    101 	return path.size() >= 1 && path[0] == '/';
    102 #endif
    103 }
    104 
    105 std::string PathSearcher::joinPaths(const std::string & first, const std::string & second)
    106 {
    107 	// Start with first string.
    108 	std::string result = first;
    109 
    110 	// Add path separator if needed
    111 	if ((first[first.size() - 1] != PATH_SEP_CHAR) && (second[0] != PATH_SEP_CHAR))
    112 	{
    113 		result += PATH_SEP_STRING;
    114 	}
    115 
    116 	// Append the second string.
    117 	result += second;
    118 
    119 	// And return the whole mess.
    120 	return result;
    121 }
    122