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