oculus1

annotate libovr/Src/Kernel/OVR_String_PathUtil.cpp @ 29:9a973ef0e2a3

fixed the performance issue under MacOSX by replacing glutSolidTeapot (which uses glEvalMesh) with my own teapot generator.
author John Tsiombikas <nuclear@member.fsf.org>
date Sun, 27 Oct 2013 06:31:18 +0200
parents e2f9e4603129
children
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