1 /* 2 *Copyright (C) 2018 Laurent Tréguier 3 * 4 *This file is part of DLS. 5 * 6 *DLS is free software: you can redistribute it and/or modify 7 *it under the terms of the GNU General Public License as published by 8 *the Free Software Foundation, either version 3 of the License, or 9 *(at your option) any later version. 10 * 11 *DLS is distributed in the hope that it will be useful, 12 *but WITHOUT ANY WARRANTY; without even the implied warranty of 13 *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 *GNU General Public License for more details. 15 * 16 *You should have received a copy of the GNU General Public License 17 *along with DLS. If not, see <http://www.gnu.org/licenses/>. 18 * 19 */ 20 21 module dls.util.uri; 22 23 class Uri 24 { 25 import dls.protocol.definitions : DocumentUri; 26 import std.regex : regex; 27 28 private static enum _reg = regex( 29 `(?:([\w-]+)://)?([\w.]+(?::\d+)?)?([^\?#]+)(?:\?([\w=&]+))?(?:#([\w-]+))?`); 30 private string _uri; 31 private string _scheme; 32 private string _authority; 33 private string _path; 34 private string _query; 35 private string _fragment; 36 37 @property string path() const 38 { 39 return _path; 40 } 41 42 this(DocumentUri uri) 43 { 44 import std.regex : matchAll; 45 import std.uri : decodeComponent; 46 47 _uri = decodeComponent(uri); 48 auto matches = matchAll(_uri, _reg); 49 50 //dfmt off 51 _scheme = matches.front[1]; 52 _authority = matches.front[2]; 53 _path = matches.front[3].normalized; 54 _query = matches.front[4]; 55 _fragment = matches.front[5]; 56 //dfmt on 57 } 58 59 override string toString() const 60 { 61 return _uri; 62 } 63 64 static Uri fromPath(string path) 65 { 66 import std.algorithm : startsWith; 67 import std.format : format; 68 import std..string : tr; 69 import std.uri : encode; 70 71 immutable uriPath = path.tr(`\`, `/`); 72 return new Uri(encode(format!"file://%s%s"(uriPath.startsWith('/') ? "" : "/", uriPath))); 73 } 74 75 alias toString this; 76 } 77 78 string normalized(const string path) 79 { 80 import std.array : array; 81 import std.path : asNormalizedPath; 82 83 string res; 84 85 version (Windows) 86 { 87 import std.algorithm : startsWith; 88 import std.path : driveName, stripDrive; 89 import std.uni : asUpperCase; 90 import std.utf : toUTF8; 91 92 if (path.startsWith('/') || path.startsWith('\\')) 93 { 94 return path[1 .. $].normalized; 95 } 96 97 res = driveName(path).asUpperCase().toUTF8() ~ stripDrive(path); 98 } 99 else 100 { 101 res = path; 102 } 103 104 return asNormalizedPath(res).array; 105 } 106 107 int filenameCmp(const Uri a, const Uri b) 108 { 109 import std.path : filenameCmp; 110 111 return filenameCmp(a.path, b.path); 112 } 113 114 bool sameFile(const Uri a, const Uri b) 115 { 116 return filenameCmp(a, b) == 0; 117 }