Line data Source code
1 : /* Copyright (C) 2010 Wildfire Games.
2 : *
3 : * Permission is hereby granted, free of charge, to any person obtaining
4 : * a copy of this software and associated documentation files (the
5 : * "Software"), to deal in the Software without restriction, including
6 : * without limitation the rights to use, copy, modify, merge, publish,
7 : * distribute, sublicense, and/or sell copies of the Software, and to
8 : * permit persons to whom the Software is furnished to do so, subject to
9 : * the following conditions:
10 : *
11 : * The above copyright notice and this permission notice shall be included
12 : * in all copies or substantial portions of the Software.
13 : *
14 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 : * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 : * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 : * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18 : * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19 : * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20 : * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 : */
22 :
23 : /*
24 : * helper functions for path strings.
25 : */
26 :
27 : #include "precompiled.h"
28 : #include "lib/path.h"
29 :
30 : #include <cstring>
31 : #include <cerrno>
32 :
33 : static const StatusDefinition pathStatusDefinitions[] = {
34 : { ERR::PATH_CHARACTER_ILLEGAL, L"illegal path character" },
35 : { ERR::PATH_CHARACTER_UNSAFE, L"unsafe path character" },
36 : { ERR::PATH_NOT_FOUND, L"path not found" },
37 : { ERR::PATH_MIXED_SEPARATORS, L"path contains both slash and backslash separators" }
38 : };
39 1 : STATUS_ADD_DEFINITIONS(pathStatusDefinitions);
40 :
41 :
42 7 : static bool path_is_dir_sep(wchar_t c)
43 : {
44 7 : if(c == '/' || c == '\\')
45 3 : return true;
46 4 : return false;
47 : }
48 :
49 : // is s2 a subpath of s1, or vice versa?
50 : // (equal counts as subpath)
51 9 : bool path_is_subpath(const wchar_t* s1, const wchar_t* s2)
52 : {
53 : // make sure s1 is the shorter string
54 9 : if(wcslen(s1) > wcslen(s2))
55 4 : std::swap(s1, s2);
56 :
57 9 : wchar_t c1 = 0, last_c1, c2;
58 : for(;;)
59 : {
60 63 : last_c1 = c1;
61 36 : c1 = *s1++, c2 = *s2++;
62 :
63 : // end of s1 reached:
64 36 : if(c1 == '\0')
65 : {
66 : // s1 matched s2 up until:
67 10 : if((c2 == '\0') || // its end (i.e. they're equal length) OR
68 9 : path_is_dir_sep(c2) || // start of next component OR
69 3 : path_is_dir_sep(last_c1)) // ", but both have a trailing slash
70 : // => is subpath
71 5 : return true;
72 : }
73 :
74 : // mismatch => is not subpath
75 31 : if(c1 != c2)
76 4 : return false;
77 : }
78 : }
79 :
80 :
81 : //-----------------------------------------------------------------------------
82 :
83 : // return pointer to the name component within path (i.e. skips over all
84 : // characters up to the last dir separator, if any).
85 385 : const wchar_t* path_name_only(const wchar_t* path)
86 : {
87 385 : const wchar_t* slash1 = wcsrchr(path, '/');
88 385 : const wchar_t* slash2 = wcsrchr(path, '\\');
89 : // neither present, it's a filename only
90 385 : if(!slash1 && !slash2)
91 2 : return path;
92 :
93 : // return name, i.e. component after the last slash
94 383 : const wchar_t* name = std::max(slash1, slash2)+1;
95 383 : return name;
96 : }
97 :
98 :
99 46963 : /*static*/ Status Path::Validate(String::value_type c)
100 : {
101 46963 : if(c < 32)
102 0 : return ERR::PATH_CHARACTER_UNSAFE;
103 :
104 : #if !OS_WIN
105 46963 : if(c >= UCHAR_MAX)
106 0 : return ERR::PATH_CHARACTER_UNSAFE;
107 : #endif
108 :
109 46963 : switch(c)
110 : {
111 0 : case '\\':
112 : case '/':
113 : case ':':
114 : case '"':
115 : case '?':
116 : case '*':
117 : case '<':
118 : case '>':
119 : case '|':
120 : case '^':
121 0 : return ERR::PATH_CHARACTER_ILLEGAL;
122 :
123 46963 : default:
124 46963 : return INFO::OK;
125 : }
126 3 : }
|