Merge "Report tests using Draw*BaseVertex as NotSupported" am: f96636fdfa
[platform/upstream/VK-GL-CTS.git] / framework / delibs / decpp / deFilePath.cpp
1 /*-------------------------------------------------------------------------
2  * drawElements C++ Base Library
3  * -----------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Filesystem path class.
22  *//*--------------------------------------------------------------------*/
23
24 #include "deFilePath.hpp"
25
26 #include <vector>
27 #include <stdexcept>
28
29 #include <sys/stat.h>
30 #include <sys/types.h>
31
32 #if (DE_OS == DE_OS_WIN32)
33 #       define VC_EXTRALEAN
34 #       define WIN32_LEAN_AND_MEAN
35 #       define NOMINMAX
36 #       include <windows.h>
37 #endif
38
39 using std::string;
40
41 namespace de
42 {
43
44 #if (DE_OS == DE_OS_WIN32)
45         const std::string FilePath::separator = "\\";
46 #else
47         const std::string FilePath::separator = "/";
48 #endif
49
50 FilePath::FilePath (const std::vector<std::string>& components)
51 {
52         for (size_t ndx = 0; ndx < components.size(); ndx++)
53         {
54                 if (!m_path.empty() && !isSeparator(m_path[m_path.size()-1]))
55                         m_path += separator;
56                 m_path += components[ndx];
57         }
58 }
59
60 void FilePath::split (std::vector<std::string>& components) const
61 {
62         components.clear();
63
64         int curCompStart = 0;
65         int pos;
66
67         if (isWinNetPath())
68                 components.push_back(separator + separator);
69         else if (isRootPath() && !beginsWithDrive())
70                 components.push_back(separator);
71
72         for (pos = 0; pos < (int)m_path.length(); pos++)
73         {
74                 const char c = m_path[pos];
75
76                 if (isSeparator(c))
77                 {
78                         if (pos - curCompStart > 0)
79                                 components.push_back(m_path.substr(curCompStart, pos - curCompStart));
80
81                         curCompStart = pos+1;
82                 }
83         }
84
85         if (pos - curCompStart > 0)
86                 components.push_back(m_path.substr(curCompStart, pos - curCompStart));
87 }
88
89 FilePath FilePath::join (const std::vector<std::string>& components)
90 {
91         return FilePath(components);
92 }
93
94 FilePath& FilePath::normalize (void)
95 {
96         std::vector<std::string>        components;
97         std::vector<std::string>        reverseNormalizedComponents;
98
99         split(components);
100
101         m_path = "";
102
103         int numUp = 0;
104
105         // Do in reverse order and eliminate any . or .. components
106         for (int ndx = (int)components.size()-1; ndx >= 0; ndx--)
107         {
108                 const std::string& comp = components[ndx];
109                 if (comp == "..")
110                         numUp += 1;
111                 else if (comp == ".")
112                         continue;
113                 else if (numUp > 0)
114                         numUp -= 1; // Skip part
115                 else
116                         reverseNormalizedComponents.push_back(comp);
117         }
118
119         if (isAbsolutePath() && numUp > 0)
120                 throw std::runtime_error("Cannot normalize path: invalid path");
121
122         // Prepend necessary ".." components
123         while (numUp--)
124                 reverseNormalizedComponents.push_back("..");
125
126         if (reverseNormalizedComponents.empty() && components.back() == ".")
127                 reverseNormalizedComponents.push_back("."); // Composed of "." components only
128
129         *this = join(std::vector<std::string>(reverseNormalizedComponents.rbegin(), reverseNormalizedComponents.rend()));
130
131         return *this;
132 }
133
134 FilePath FilePath::normalize (const FilePath& path)
135 {
136         return FilePath(path).normalize();
137 }
138
139 std::string FilePath::getBaseName (void) const
140 {
141         std::vector<std::string> components;
142         split(components);
143         return !components.empty() ? components[components.size()-1] : std::string("");
144 }
145
146 std::string     FilePath::getDirName (void) const
147 {
148         std::vector<std::string> components;
149         split(components);
150         if (components.size() > 1)
151         {
152                 components.pop_back();
153                 return FilePath(components).getPath();
154         }
155         else if (isAbsolutePath())
156                 return separator;
157         else
158                 return std::string(".");
159 }
160
161 std::string FilePath::getFileExtension (void) const
162 {
163         std::string baseName = getBaseName();
164         size_t dotPos = baseName.find_last_of('.');
165         if (dotPos == std::string::npos)
166                 return std::string("");
167         else
168                 return baseName.substr(dotPos+1);
169 }
170
171 bool FilePath::exists (void) const
172 {
173         FilePath        normPath        = FilePath::normalize(*this);
174         struct          stat            st;
175         int                     result          = stat(normPath.getPath(), &st);
176         return result == 0;
177 }
178
179 FilePath::Type FilePath::getType (void) const
180 {
181         FilePath        normPath        = FilePath::normalize(*this);
182         struct          stat            st;
183         int                     result          = stat(normPath.getPath(), &st);
184
185         if (result != 0)
186                 return TYPE_UNKNOWN;
187
188         int type = st.st_mode & S_IFMT;
189         if (type == S_IFREG)
190                 return TYPE_FILE;
191         else if (type == S_IFDIR)
192                 return TYPE_DIRECTORY;
193         else
194                 return TYPE_UNKNOWN;
195 }
196
197 bool FilePath::beginsWithDrive (void) const
198 {
199         for (int ndx = 0; ndx < (int)m_path.length(); ndx++)
200         {
201                 if (m_path[ndx] == ':' && ndx+1 < (int)m_path.length() && isSeparator(m_path[ndx+1]))
202                         return true; // First part is drive letter.
203                 if (isSeparator(m_path[ndx]))
204                         return false;
205         }
206         return false;
207 }
208
209 bool FilePath::isAbsolutePath (void) const
210 {
211         return isRootPath() || isWinNetPath() || beginsWithDrive();
212 }
213
214 void FilePath_selfTest (void)
215 {
216         DE_TEST_ASSERT(!FilePath(".").isAbsolutePath());
217         DE_TEST_ASSERT(!FilePath("..\\foo").isAbsolutePath());
218         DE_TEST_ASSERT(!FilePath("foo").isAbsolutePath());
219         DE_TEST_ASSERT(FilePath("\\foo/bar").isAbsolutePath());
220         DE_TEST_ASSERT(FilePath("/foo").isAbsolutePath());
221         DE_TEST_ASSERT(FilePath("\\").isAbsolutePath());
222         DE_TEST_ASSERT(FilePath("\\\\net\\loc").isAbsolutePath());
223         DE_TEST_ASSERT(FilePath("C:\\file.txt").isAbsolutePath());
224         DE_TEST_ASSERT(FilePath("c:/file.txt").isAbsolutePath());
225
226         DE_TEST_ASSERT(string(".") == FilePath(".//.").normalize().getPath());
227         DE_TEST_ASSERT(string(".") == FilePath(".").normalize().getPath());
228         DE_TEST_ASSERT((string("..") + FilePath::separator + "test") == FilePath("foo/../bar/../../test").normalize().getPath());
229         DE_TEST_ASSERT((FilePath::separator + "foo" + FilePath::separator + "foo.txt") == FilePath("/foo\\bar/..\\dir\\..\\foo.txt").normalize().getPath());
230         DE_TEST_ASSERT((string("c:") + FilePath::separator + "foo" + FilePath::separator + "foo.txt") == FilePath("c:/foo\\bar/..\\dir\\..\\foo.txt").normalize().getPath());
231         DE_TEST_ASSERT((FilePath::separator + FilePath::separator + "foo" + FilePath::separator + "foo.txt") == FilePath("\\\\foo\\bar/..\\dir\\..\\foo.txt").normalize().getPath());
232
233         DE_TEST_ASSERT(FilePath("foo/bar"               ).getBaseName() == "bar");
234         DE_TEST_ASSERT(FilePath("foo/bar/"              ).getBaseName() == "bar");
235         DE_TEST_ASSERT(FilePath("foo\\bar"              ).getBaseName() == "bar");
236         DE_TEST_ASSERT(FilePath("foo\\bar\\"    ).getBaseName() == "bar");
237         DE_TEST_ASSERT(FilePath("foo/bar"               ).getDirName()  == "foo");
238         DE_TEST_ASSERT(FilePath("foo/bar/"              ).getDirName()  == "foo");
239         DE_TEST_ASSERT(FilePath("foo\\bar"              ).getDirName()  == "foo");
240         DE_TEST_ASSERT(FilePath("foo\\bar\\"    ).getDirName()  == "foo");
241         DE_TEST_ASSERT(FilePath("/foo/bar/baz"  ).getDirName()  == FilePath::separator + "foo" + FilePath::separator + "bar");
242 }
243
244 static void createDirectoryImpl (const char* path)
245 {
246 #if (DE_OS == DE_OS_WIN32)
247         if (!CreateDirectory(path, DE_NULL))
248                 throw std::runtime_error("Failed to create directory");
249 #elif (DE_OS == DE_OS_UNIX) || (DE_OS == DE_OS_OSX) || (DE_OS == DE_OS_IOS) || (DE_OS == DE_OS_ANDROID) || (DE_OS == DE_OS_SYMBIAN) || (DE_OS == DE_OS_QNX)
250         if (mkdir(path, 0777) != 0)
251                 throw std::runtime_error("Failed to create directory");
252 #else
253 #       error Implement createDirectoryImpl() for your platform.
254 #endif
255 }
256
257 void createDirectory (const char* path)
258 {
259         FilePath        dirPath         = FilePath::normalize(path);
260         FilePath        parentPath      (dirPath.getDirName());
261
262         if (dirPath.exists())
263                 throw std::runtime_error("Destination exists already");
264         else if (!parentPath.exists())
265                 throw std::runtime_error("Parent directory doesn't exist");
266         else if (parentPath.getType() != FilePath::TYPE_DIRECTORY)
267                 throw std::runtime_error("Parent is not directory");
268
269         createDirectoryImpl(path);
270 }
271
272 void createDirectoryAndParents (const char* path)
273 {
274         std::vector<std::string>        createPaths;
275         FilePath                                        curPath         (path);
276
277         if (curPath.exists())
278                 throw std::runtime_error("Destination exists already");
279
280         while (!curPath.exists())
281         {
282                 createPaths.push_back(curPath.getPath());
283
284                 std::string parent = curPath.getDirName();
285                 DE_CHECK_RUNTIME_ERR(parent != curPath.getPath());
286                 curPath = FilePath(parent);
287         }
288
289         // Create in reverse order.
290         for (std::vector<std::string>::const_reverse_iterator parentIter = createPaths.rbegin(); parentIter != createPaths.rend(); parentIter++)
291                 createDirectory(parentIter->c_str());
292 }
293
294 } // de