/// <summary> /// Create an <see cref="XSPath"/> containing a single path segment. /// </summary> /// <param name="pathSegment"> /// The path segment. /// </param> /// <returns> /// The new <see cref="XSPath"/>. /// </returns> public static XSPath FromSegment(string pathSegment) { if (pathSegment == null) { throw new ArgumentNullException(nameof(pathSegment)); } return(FromSegment( XSPathSegment.Create(pathSegment) )); }
/// <summary> /// Append a segment to the path. /// </summary> /// <param name="pathSegment"> /// The segment to append. /// </param> /// <returns> /// The new <see cref="XSPath"/>. /// </returns> public XSPath Append(XSPathSegment pathSegment) { if (pathSegment == null) { throw new ArgumentNullException(nameof(pathSegment)); } return(new XSPath( parent: this, leaf: pathSegment )); }
/// <summary> /// Create a new <see cref="XSPath"/> by adding a leaf <see cref="XSPathSegment"/> onto the parent <see cref="XSPath"/>'s list of segments. /// </summary> /// <param name="parent"> /// The parent <see cref="XSPath"/>. /// </param> /// <param name="leaf"> /// The leaf <see cref="XSPathSegment"/> to append. /// </param> XSPath(XSPath parent, XSPathSegment leaf) { if (parent == null) { throw new ArgumentNullException(nameof(parent)); } if (leaf == null) { throw new ArgumentNullException(nameof(leaf)); } _parent = parent; _ancestorSegments = _parent._segments;; _segments = _ancestorSegments.Add(leaf); }
/// <summary> /// Create an <see cref="XSPath"/> containing a single path segment. /// </summary> /// <param name="pathSegment"> /// The path segment. /// </param> /// <returns> /// The new <see cref="XSPath"/>. /// </returns> public static XSPath FromSegment(XSPathSegment pathSegment) { if (pathSegment == null) { throw new ArgumentNullException(nameof(pathSegment)); } if (pathSegment == XSPathSegment.Root) { return(Root); } return(new XSPath( ImmutableList <XSPathSegment> .Empty, ImmutableList <XSPathSegment> .Empty.Add(pathSegment) )); }
/// <summary> /// Append a path or segment to the path. /// </summary> /// <param name="pathOrSegment"> /// The path or path-segment to append. /// </param> /// <returns> /// The new <see cref="XSPath"/>. /// </returns> public XSPath Append(string pathOrSegment) { if (pathOrSegment == null) { throw new ArgumentNullException(nameof(pathOrSegment)); } if (pathOrSegment.IndexOf(PathSeparatorCharacter) != -1) { return(Append( Parse(pathOrSegment) )); } return(Append( XSPathSegment.Create(pathOrSegment) )); }
/// <summary> /// Determine whether the list of <see cref="XSPathSegment"/>s starts with another list of <see cref="XSPathSegment"/>s. /// </summary> /// <param name="segments"> /// The list of <see cref="XSPathSegment"/>s. /// </param> /// <param name="otherSegments"> /// The other list of <see cref="XSPathSegment"/>s.s /// </param> /// <returns> /// <c>true</c>, if <paramref name="segments"/> starts with <paramref name="segments"/>; otherwise, <c>false</c>. /// </returns> public static bool StartsWith(this ImmutableList <XSPathSegment> segments, ImmutableList <XSPathSegment> otherSegments) { if (segments == null) { throw new ArgumentNullException(nameof(segments)); } if (otherSegments == null) { throw new ArgumentNullException(nameof(otherSegments)); } if (segments.Count == 0) { return(false); // Logical short-circuit: can't have a prefix. } if (otherSegments.Count > segments.Count) { return(false); // Logical short-circuit: can't be a prefix. } for (int index = 0; index < otherSegments.Count; index++) { if (index >= segments.Count) { return(false); } XSPathSegment segment = segments[index]; XSPathSegment otherSegment = otherSegments[index]; if (segment.IsWildcard || otherSegment.IsWildcard) { continue; // Wildcards always match. } if (otherSegment != segment) { return(false); } } return(true); }
/// <summary> /// Parse a string into an <see cref="XSPathSegment"/>s. /// </summary> /// <param name="path"> /// The string to parse. /// </param> /// <returns> /// The <see cref="XSPath"/>. /// </returns> public static IEnumerable <XSPathSegment> ParseSegments(string path) { if (path == null) { throw new ArgumentNullException(nameof(path)); } if (path == PathSeparatorString) { yield return(XSPathSegment.Root); } if (path[path.Length - 1] == PathSeparatorCharacter) { path = path.Substring(0, path.Length - 1); } string[] pathSegments = path.Split(new char[] { PathSeparatorCharacter }); foreach (string pathSegment in pathSegments) { yield return(XSPathSegment.Create(pathSegment)); } }
/// <summary> /// Determine whether the list of <see cref="XSPathSegment"/>s ends with another list of <see cref="XSPathSegment"/>s. /// </summary> /// <param name="segments"> /// The list of <see cref="XSPathSegment"/>s. /// </param> /// <param name="otherSegments"> /// The other list of <see cref="XSPathSegment"/>s.s /// </param> /// <returns> /// <c>true</c>, if <paramref name="segments"/> ends with <paramref name="segments"/>; otherwise, <c>false</c>. /// </returns> public static bool EndsWith(this ImmutableList <XSPathSegment> segments, ImmutableList <XSPathSegment> otherSegments) { if (segments == null) { throw new ArgumentNullException(nameof(segments)); } if (otherSegments == null) { throw new ArgumentNullException(nameof(otherSegments)); } if (segments.Count == 0) { return(false); // Logical short-circuit: can't have a prefix. } int index = segments.Count - 1; int ancestorIndex = otherSegments.Count - 1; for ( ; index >= 0 && ancestorIndex >= 0; index--, ancestorIndex--) { XSPathSegment segment = segments[index]; XSPathSegment otherSegment = otherSegments[ancestorIndex]; if (segment.IsWildcard || otherSegment.IsWildcard) { continue; // Wildcards always match. } if (otherSegment != segment) { return(false); } } return(true); }