rev |
line source |
nuclear@3
|
1 /************************************************************************************
|
nuclear@3
|
2
|
nuclear@3
|
3 Filename : OVR_String_PathUtil.cpp
|
nuclear@3
|
4 Content : String filename/url helper function
|
nuclear@3
|
5 Created : September 19, 2012
|
nuclear@3
|
6 Notes :
|
nuclear@3
|
7
|
nuclear@3
|
8 Copyright : Copyright 2012 Oculus VR, Inc. All Rights reserved.
|
nuclear@3
|
9
|
nuclear@3
|
10 Use of this software is subject to the terms of the Oculus license
|
nuclear@3
|
11 agreement provided at the time of installation or download, or which
|
nuclear@3
|
12 otherwise accompanies this software in either electronic or hard copy form.
|
nuclear@3
|
13
|
nuclear@3
|
14 ************************************************************************************/
|
nuclear@3
|
15
|
nuclear@3
|
16 #include "OVR_String.h"
|
nuclear@3
|
17 #include "OVR_UTF8Util.h"
|
nuclear@3
|
18
|
nuclear@3
|
19 namespace OVR {
|
nuclear@3
|
20
|
nuclear@3
|
21 //--------------------------------------------------------------------
|
nuclear@3
|
22 // ***** Path-Scanner helper function
|
nuclear@3
|
23
|
nuclear@3
|
24 // Scans file path finding filename start and extension start, fills in their addess.
|
nuclear@3
|
25 void ScanFilePath(const char* url, const char** pfilename, const char** pext)
|
nuclear@3
|
26 {
|
nuclear@3
|
27 const char* urlStart = url;
|
nuclear@3
|
28 const char *filename = 0;
|
nuclear@3
|
29 const char *lastDot = 0;
|
nuclear@3
|
30
|
nuclear@3
|
31 UInt32 charVal = UTF8Util::DecodeNextChar(&url);
|
nuclear@3
|
32
|
nuclear@3
|
33 while (charVal != 0)
|
nuclear@3
|
34 {
|
nuclear@3
|
35 if ((charVal == '/') || (charVal == '\\'))
|
nuclear@3
|
36 {
|
nuclear@3
|
37 filename = url;
|
nuclear@3
|
38 lastDot = 0;
|
nuclear@3
|
39 }
|
nuclear@3
|
40 else if (charVal == '.')
|
nuclear@3
|
41 {
|
nuclear@3
|
42 lastDot = url - 1;
|
nuclear@3
|
43 }
|
nuclear@3
|
44
|
nuclear@3
|
45 charVal = UTF8Util::DecodeNextChar(&url);
|
nuclear@3
|
46 }
|
nuclear@3
|
47
|
nuclear@3
|
48 if (pfilename)
|
nuclear@3
|
49 {
|
nuclear@3
|
50 // It was a naked filename
|
nuclear@3
|
51 if (urlStart && (*urlStart != '.') && *urlStart)
|
nuclear@3
|
52 *pfilename = urlStart;
|
nuclear@3
|
53 else
|
nuclear@3
|
54 *pfilename = filename;
|
nuclear@3
|
55 }
|
nuclear@3
|
56
|
nuclear@3
|
57 if (pext)
|
nuclear@3
|
58 {
|
nuclear@3
|
59 *pext = lastDot;
|
nuclear@3
|
60 }
|
nuclear@3
|
61 }
|
nuclear@3
|
62
|
nuclear@3
|
63 // Scans till the end of protocol. Returns first character past protocol,
|
nuclear@3
|
64 // 0 if not found.
|
nuclear@3
|
65 // - protocol: 'file://', 'http://'
|
nuclear@3
|
66 const char* ScanPathProtocol(const char* url)
|
nuclear@3
|
67 {
|
nuclear@3
|
68 UInt32 charVal = UTF8Util::DecodeNextChar(&url);
|
nuclear@3
|
69 UInt32 charVal2;
|
nuclear@3
|
70
|
nuclear@3
|
71 while (charVal != 0)
|
nuclear@3
|
72 {
|
nuclear@3
|
73 // Treat a colon followed by a slash as absolute.
|
nuclear@3
|
74 if (charVal == ':')
|
nuclear@3
|
75 {
|
nuclear@3
|
76 charVal2 = UTF8Util::DecodeNextChar(&url);
|
nuclear@3
|
77 charVal = UTF8Util::DecodeNextChar(&url);
|
nuclear@3
|
78 if ((charVal == '/') && (charVal2 == '\\'))
|
nuclear@3
|
79 return url;
|
nuclear@3
|
80 }
|
nuclear@3
|
81 charVal = UTF8Util::DecodeNextChar(&url);
|
nuclear@3
|
82 }
|
nuclear@3
|
83 return 0;
|
nuclear@3
|
84 }
|
nuclear@3
|
85
|
nuclear@3
|
86
|
nuclear@3
|
87 //--------------------------------------------------------------------
|
nuclear@3
|
88 // ***** String Path API implementation
|
nuclear@3
|
89
|
nuclear@3
|
90 bool String::HasAbsolutePath(const char* url)
|
nuclear@3
|
91 {
|
nuclear@3
|
92 // Absolute paths can star with:
|
nuclear@3
|
93 // - protocols: 'file://', 'http://'
|
nuclear@3
|
94 // - windows drive: 'c:\'
|
nuclear@3
|
95 // - UNC share name: '\\share'
|
nuclear@3
|
96 // - unix root '/'
|
nuclear@3
|
97
|
nuclear@3
|
98 // On the other hand, relative paths are:
|
nuclear@3
|
99 // - directory: 'directory/file'
|
nuclear@3
|
100 // - this directory: './file'
|
nuclear@3
|
101 // - parent directory: '../file'
|
nuclear@3
|
102 //
|
nuclear@3
|
103 // For now, we don't parse '.' or '..' out, but instead let it be concatenated
|
nuclear@3
|
104 // to string and let the OS figure it out. This, however, is not good for file
|
nuclear@3
|
105 // name matching in library/etc, so it should be improved.
|
nuclear@3
|
106
|
nuclear@3
|
107 if (!url || !*url)
|
nuclear@3
|
108 return true; // Treat empty strings as absolute.
|
nuclear@3
|
109
|
nuclear@3
|
110 UInt32 charVal = UTF8Util::DecodeNextChar(&url);
|
nuclear@3
|
111
|
nuclear@3
|
112 // Fist character of '/' or '\\' means absolute url.
|
nuclear@3
|
113 if ((charVal == '/') || (charVal == '\\'))
|
nuclear@3
|
114 return true;
|
nuclear@3
|
115
|
nuclear@3
|
116 while (charVal != 0)
|
nuclear@3
|
117 {
|
nuclear@3
|
118 // Treat a colon followed by a slash as absolute.
|
nuclear@3
|
119 if (charVal == ':')
|
nuclear@3
|
120 {
|
nuclear@3
|
121 charVal = UTF8Util::DecodeNextChar(&url);
|
nuclear@3
|
122 // Protocol or windows drive. Absolute.
|
nuclear@3
|
123 if ((charVal == '/') || (charVal == '\\'))
|
nuclear@3
|
124 return true;
|
nuclear@3
|
125 }
|
nuclear@3
|
126 else if ((charVal == '/') || (charVal == '\\'))
|
nuclear@3
|
127 {
|
nuclear@3
|
128 // Not a first character (else 'if' above the loop would have caught it).
|
nuclear@3
|
129 // Must be a relative url.
|
nuclear@3
|
130 break;
|
nuclear@3
|
131 }
|
nuclear@3
|
132
|
nuclear@3
|
133 charVal = UTF8Util::DecodeNextChar(&url);
|
nuclear@3
|
134 }
|
nuclear@3
|
135
|
nuclear@3
|
136 // We get here for relative paths.
|
nuclear@3
|
137 return false;
|
nuclear@3
|
138 }
|
nuclear@3
|
139
|
nuclear@3
|
140
|
nuclear@3
|
141 bool String::HasExtension(const char* path)
|
nuclear@3
|
142 {
|
nuclear@3
|
143 const char* ext = 0;
|
nuclear@3
|
144 ScanFilePath(path, 0, &ext);
|
nuclear@3
|
145 return ext != 0;
|
nuclear@3
|
146 }
|
nuclear@3
|
147 bool String::HasProtocol(const char* path)
|
nuclear@3
|
148 {
|
nuclear@3
|
149 return ScanPathProtocol(path) != 0;
|
nuclear@3
|
150 }
|
nuclear@3
|
151
|
nuclear@3
|
152
|
nuclear@3
|
153 String String::GetPath() const
|
nuclear@3
|
154 {
|
nuclear@3
|
155 const char* filename = 0;
|
nuclear@3
|
156 ScanFilePath(ToCStr(), &filename, 0);
|
nuclear@3
|
157
|
nuclear@3
|
158 // Technically we can have extra logic somewhere for paths,
|
nuclear@3
|
159 // such as enforcing protocol and '/' only based on flags,
|
nuclear@3
|
160 // but we keep it simple for now.
|
nuclear@3
|
161 return String(ToCStr(), filename ? (filename-ToCStr()) : GetSize());
|
nuclear@3
|
162 }
|
nuclear@3
|
163
|
nuclear@3
|
164 String String::GetProtocol() const
|
nuclear@3
|
165 {
|
nuclear@3
|
166 const char* protocolEnd = ScanPathProtocol(ToCStr());
|
nuclear@3
|
167 return String(ToCStr(), protocolEnd ? (protocolEnd-ToCStr()) : 0);
|
nuclear@3
|
168 }
|
nuclear@3
|
169
|
nuclear@3
|
170 String String::GetFilename() const
|
nuclear@3
|
171 {
|
nuclear@3
|
172 const char* filename = 0;
|
nuclear@3
|
173 ScanFilePath(ToCStr(), &filename, 0);
|
nuclear@3
|
174 return String(filename);
|
nuclear@3
|
175 }
|
nuclear@3
|
176 String String::GetExtension() const
|
nuclear@3
|
177 {
|
nuclear@3
|
178 const char* ext = 0;
|
nuclear@3
|
179 ScanFilePath(ToCStr(), 0, &ext);
|
nuclear@3
|
180 return String(ext);
|
nuclear@3
|
181 }
|
nuclear@3
|
182
|
nuclear@3
|
183 void String::StripExtension()
|
nuclear@3
|
184 {
|
nuclear@3
|
185 const char* ext = 0;
|
nuclear@3
|
186 ScanFilePath(ToCStr(), 0, &ext);
|
nuclear@3
|
187 if (ext)
|
nuclear@3
|
188 {
|
nuclear@3
|
189 *this = String(ToCStr(), ext-ToCStr());
|
nuclear@3
|
190 }
|
nuclear@3
|
191 }
|
nuclear@3
|
192
|
nuclear@3
|
193 void String::StripProtocol()
|
nuclear@3
|
194 {
|
nuclear@3
|
195 const char* protocol = ScanPathProtocol(ToCStr());
|
nuclear@3
|
196 if (protocol)
|
nuclear@3
|
197 AssignString(protocol, OVR_strlen(protocol));
|
nuclear@3
|
198 }
|
nuclear@3
|
199
|
nuclear@3
|
200 } // OVR
|