mirror of
https://github.com/Ratstail91/Mementos.git
synced 2025-11-29 02:24:28 +11:00
278 lines
6.8 KiB
C#
278 lines
6.8 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Diagnostics;
|
|
using Ink.Runtime;
|
|
|
|
namespace Ink.Runtime
|
|
{
|
|
public class Path : IEquatable<Path>
|
|
{
|
|
static string parentId = "^";
|
|
|
|
// Immutable Component
|
|
public class Component : IEquatable<Component>
|
|
{
|
|
public int index { get; private set; }
|
|
public string name { get; private set; }
|
|
public bool isIndex { get { return index >= 0; } }
|
|
public bool isParent {
|
|
get {
|
|
return name == Path.parentId;
|
|
}
|
|
}
|
|
|
|
public Component(int index)
|
|
{
|
|
Debug.Assert(index >= 0);
|
|
this.index = index;
|
|
this.name = null;
|
|
}
|
|
|
|
public Component(string name)
|
|
{
|
|
Debug.Assert(name != null && name.Length > 0);
|
|
this.name = name;
|
|
this.index = -1;
|
|
}
|
|
|
|
public static Component ToParent()
|
|
{
|
|
return new Component (parentId);
|
|
}
|
|
|
|
public override string ToString ()
|
|
{
|
|
if (isIndex) {
|
|
return index.ToString ();
|
|
} else {
|
|
return name;
|
|
}
|
|
}
|
|
|
|
public override bool Equals (object obj)
|
|
{
|
|
return Equals (obj as Component);
|
|
}
|
|
|
|
public bool Equals(Component otherComp)
|
|
{
|
|
if (otherComp != null && otherComp.isIndex == this.isIndex) {
|
|
if (isIndex) {
|
|
return index == otherComp.index;
|
|
} else {
|
|
return name == otherComp.name;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public override int GetHashCode ()
|
|
{
|
|
if (isIndex)
|
|
return this.index;
|
|
else
|
|
return this.name.GetHashCode ();
|
|
}
|
|
}
|
|
|
|
public Component GetComponent(int index)
|
|
{
|
|
return _components[index];
|
|
}
|
|
|
|
public bool isRelative { get; private set; }
|
|
|
|
public Component head
|
|
{
|
|
get
|
|
{
|
|
if (_components.Count > 0) {
|
|
return _components.First ();
|
|
} else {
|
|
return null;
|
|
}
|
|
}
|
|
}
|
|
|
|
public Path tail
|
|
{
|
|
get
|
|
{
|
|
if (_components.Count >= 2) {
|
|
List<Component> tailComps = _components.GetRange (1, _components.Count - 1);
|
|
return new Path(tailComps);
|
|
}
|
|
|
|
else {
|
|
return Path.self;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
public int length { get { return _components.Count; } }
|
|
|
|
public Component lastComponent
|
|
{
|
|
get
|
|
{
|
|
var lastComponentIdx = _components.Count-1;
|
|
if( lastComponentIdx >= 0 )
|
|
return _components[lastComponentIdx];
|
|
else
|
|
return null;
|
|
}
|
|
}
|
|
|
|
public bool containsNamedComponent {
|
|
get {
|
|
foreach(var comp in _components) {
|
|
if( !comp.isIndex ) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public Path()
|
|
{
|
|
_components = new List<Component> ();
|
|
}
|
|
|
|
public Path(Component head, Path tail) : this()
|
|
{
|
|
_components.Add (head);
|
|
_components.AddRange (tail._components);
|
|
}
|
|
|
|
public Path(IEnumerable<Component> components, bool relative = false) : this()
|
|
{
|
|
this._components.AddRange (components);
|
|
this.isRelative = relative;
|
|
}
|
|
|
|
public Path(string componentsString) : this()
|
|
{
|
|
this.componentsString = componentsString;
|
|
}
|
|
|
|
public static Path self {
|
|
get {
|
|
var path = new Path ();
|
|
path.isRelative = true;
|
|
return path;
|
|
}
|
|
}
|
|
|
|
public Path PathByAppendingPath(Path pathToAppend)
|
|
{
|
|
Path p = new Path ();
|
|
|
|
int upwardMoves = 0;
|
|
for (int i = 0; i < pathToAppend._components.Count; ++i) {
|
|
if (pathToAppend._components [i].isParent) {
|
|
upwardMoves++;
|
|
} else {
|
|
break;
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < this._components.Count - upwardMoves; ++i) {
|
|
p._components.Add (this._components [i]);
|
|
}
|
|
|
|
for(int i=upwardMoves; i<pathToAppend._components.Count; ++i) {
|
|
p._components.Add (pathToAppend._components [i]);
|
|
}
|
|
|
|
return p;
|
|
}
|
|
|
|
public Path PathByAppendingComponent (Component c)
|
|
{
|
|
Path p = new Path ();
|
|
p._components.AddRange (_components);
|
|
p._components.Add (c);
|
|
return p;
|
|
}
|
|
|
|
public string componentsString {
|
|
get {
|
|
if( _componentsString == null ) {
|
|
_componentsString = StringExt.Join (".", _components);
|
|
if (isRelative) _componentsString = "." + _componentsString;
|
|
}
|
|
return _componentsString;
|
|
}
|
|
private set {
|
|
_components.Clear ();
|
|
|
|
_componentsString = value;
|
|
|
|
// Empty path, empty components
|
|
// (path is to root, like "/" in file system)
|
|
if (string.IsNullOrEmpty(_componentsString))
|
|
return;
|
|
|
|
// When components start with ".", it indicates a relative path, e.g.
|
|
// .^.^.hello.5
|
|
// is equivalent to file system style path:
|
|
// ../../hello/5
|
|
if (_componentsString [0] == '.') {
|
|
this.isRelative = true;
|
|
_componentsString = _componentsString.Substring (1);
|
|
} else {
|
|
this.isRelative = false;
|
|
}
|
|
|
|
var componentStrings = _componentsString.Split('.');
|
|
foreach (var str in componentStrings) {
|
|
int index;
|
|
if (int.TryParse (str , out index)) {
|
|
_components.Add (new Component (index));
|
|
} else {
|
|
_components.Add (new Component (str));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
string _componentsString;
|
|
|
|
public override string ToString()
|
|
{
|
|
return componentsString;
|
|
}
|
|
|
|
public override bool Equals (object obj)
|
|
{
|
|
return Equals (obj as Path);
|
|
}
|
|
|
|
public bool Equals (Path otherPath)
|
|
{
|
|
if (otherPath == null)
|
|
return false;
|
|
|
|
if (otherPath._components.Count != this._components.Count)
|
|
return false;
|
|
|
|
if (otherPath.isRelative != this.isRelative)
|
|
return false;
|
|
|
|
return otherPath._components.SequenceEqual (this._components);
|
|
}
|
|
|
|
public override int GetHashCode ()
|
|
{
|
|
// TODO: Better way to make a hash code!
|
|
return this.ToString ().GetHashCode ();
|
|
}
|
|
|
|
List<Component> _components;
|
|
}
|
|
}
|
|
|