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