Location
A location object with information about a URL.
using System.Text.RegularExpressions;
namespace AngleSharp.DOM
{
[DOM("Location")]
public sealed class Location
{
private static readonly Regex parser = new Regex("^(?:([A-Za-z]+):)?(\\/{0,3})([0-9.\\-A-Za-z]+)(?::(\\d+))?(?:\\/([^?#]*))?(?:\\?([^#]*))?(?:#(.*))?$");
private string _url;
private string _scheme;
private string _slash;
private string _host;
private string _port;
private string _path;
private string _query;
private string _hash;
[DOM("hash")]
public string Hash {
get {
return NonEmpty(_hash, "#", null);
}
set {
_hash = Tolerate(value, "#", null);
TryRebuild();
}
}
[DOM("host")]
public string Host {
get {
return HostName + NonEmpty(_port, ":", null);
}
set {
int num = value.IndexOf(':');
if (num != -1) {
Port = value.Substring(num);
HostName = value.Substring(0, num);
} else {
Port = string.Empty;
HostName = value;
}
TryRebuild();
}
}
[DOM("hostname")]
public string HostName {
get {
return _host;
}
set {
_host = value;
TryRebuild();
}
}
[DOM("href")]
public string Href {
get {
return _url;
}
set {
ChangeTo(value);
}
}
[DOM("pathname")]
public string PathName {
get {
return "/" + _path;
}
set {
_path = Tolerate(value, "/", null);
TryRebuild();
}
}
[DOM("port")]
public string Port {
get {
return _port;
}
set {
_port = value;
TryRebuild();
}
}
[DOM("protocol")]
public string Protocol {
get {
return NonEmpty(_scheme, null, ":");
}
set {
_scheme = Tolerate(value, null, ":");
TryRebuild();
}
}
[DOM("search")]
public string Search {
get {
return NonEmpty(_query, "?", null);
}
set {
_query = Tolerate(value, "?", null);
TryRebuild();
}
}
internal Location(string url)
{
ChangeTo(url);
}
public override string ToString()
{
return _url;
}
private static string NonEmpty(string check, string prefix = null, string postfix = null)
{
if (string.IsNullOrEmpty(check))
return string.Empty;
return (prefix ?? string.Empty) + check + (postfix ?? string.Empty);
}
private static string Tolerate(string value, string prefix = null, string postfix = null)
{
if (prefix != null && value.StartsWith(prefix))
return value.Substring(prefix.Length);
if (postfix != null && value.EndsWith(postfix))
return value.Substring(0, value.Length - postfix.Length);
return value;
}
private static string Get(GroupCollection groups, int index)
{
if (groups.Count > index)
return groups[index].Value;
return null;
}
private void TryRebuild()
{
string value = Protocol + _slash + Host + PathName + Search + Hash;
ChangeTo(value);
}
private void ChangeTo(string value)
{
Match match = parser.Match(value);
if (match.Success) {
_url = Get(match.Groups, 0);
_scheme = Get(match.Groups, 1);
_slash = Get(match.Groups, 2);
_host = Get(match.Groups, 3);
_port = Get(match.Groups, 4);
_path = Get(match.Groups, 5);
_query = Get(match.Groups, 6);
_hash = Get(match.Groups, 7);
}
}
}
}