/// <inheritdoc /> public void WriteXml(XmlWriter writer) { writer.WriteAttributeString(nameof(Location), Location.ToFormatString()); if (EndsWithDelimiter) { writer.WriteAttributeString(nameof(EndsWithDelimiter), bool.TrueString); } if (PathParts.Any()) { writer.WriteStartElement("Path"); foreach (var pathPart in PathParts.ToArray()) { writer.WriteElementString(pathPart.Value.ToString(), pathPart.Key); } writer.WriteEndElement(); //</Path> } if (FormatterName != null) { writer.WriteStartElement("Format"); writer.WriteAttributeString(nameof(FormatterName), FormatterName); foreach (var expressionArgument in Formats) { writer.WriteStartElement("Argument"); expressionArgument.WriteXml(writer); writer.WriteEndElement(); //</Argument> } writer.WriteEndElement(); //</Format> } }
public KeyValuePair <string, PathType>?CompileCurrent(TokenzierContext context, int index, out Func <IMorestachioError> errProducer) { if (CurrentPart == ".") { PathParts.Add(null, PathType.SelfAssignment); } else if (CurrentPart == "../") { PathParts.Add(null, PathType.ParentSelector); } else if (CurrentPart == "~") { PathParts.Add(null, PathType.RootSelector); } else if (CurrentPart == "?") { PathParts.Add(null, PathType.ObjectSelector); } else if (CurrentPart.Trim() != string.Empty) { if (!ComputeCurrentPart(context, index, out errProducer)) { errProducer = () => ( new InvalidPathSyntaxError(context.CurrentLocation.Offset(index) .AddWindow(new CharacterSnippedLocation(1, index, CurrentPart)), CurrentPart, "Invalid character")); return(default);
public string GetFormatterName(TokenzierContext context, int index, out bool found, out Func <IMorestachioError> errProducer) { var last = CompileCurrent(context, index, out errProducer); if (last == null) { if (CurrentPart == string.Empty) { last = new KeyValuePair <string, PathType>(string.Empty, PathType.DataPath); } else { found = false; return(null); } } found = true; if (last.Value.Value != PathType.DataPath) { PathParts.Add(last.Value.Key, last.Value.Value); return(string.Empty); } return(last.Value.Key); }
/// <inheritdoc /> public void WriteXml(XmlWriter writer) { writer.WriteAttributeString(nameof(Location), Location.ToFormatString()); if (FormatterName != null) { writer.WriteAttributeString(nameof(FormatterName), FormatterName); } if (PathParts.Any()) { var pathStr = string.Join(",", PathParts.Select(f => { if (f.Key != null) { return("{" + f.Value + ";" + f.Key + "}"); } return("{" + f.Value + "}"); })); writer.WriteAttributeString(nameof(PathParts), pathStr); } foreach (var expressionArgument in Formats) { writer.WriteStartElement("Format"); expressionArgument.WriteXml(writer); writer.WriteEndElement(); //</Format> } }
/// <inheritdoc /> public void GetObjectData(SerializationInfo info, StreamingContext context) { info.AddValue(nameof(PathParts), PathParts.ToArray()); info.AddValue(nameof(Formats), Formats); info.AddValue(nameof(FormatterName), FormatterName); info.AddValue(nameof(Location), Location.ToFormatString()); info.AddValue(nameof(EndsWithDelimiter), EndsWithDelimiter); }
private IEnumerable <IRemoteFolder> GetAncestors() { for (int i = 0; i < PathParts.Length; i++) { string path = string.Join(PathSeparator.ToString(), PathParts.Take(i + 1)); yield return(new SimpleRemoteFolder(path, PathSeparator, RootPath)); } }
public override int GetHashCode() { unchecked { var hashCode = (PathParts != null ? PathParts.GetHashCode() : 0); hashCode = (hashCode * 397) ^ (Formats != null ? Formats.GetHashCode() : 0); hashCode = (hashCode * 397) ^ (FormatterName != null ? FormatterName.GetHashCode() : 0); hashCode = (hashCode * 397) ^ (Location != null ? Location.GetHashCode() : 0); return(hashCode); } }
protected RemoteItem(string path, char pathSeparator, string rootPath = null) { Path = path ?? ""; PathSeparator = pathSeparator; RelativePath = !string.IsNullOrEmpty(rootPath) ? Path.Replace(rootPath, "") : Path; PathParts = RelativePath.Split(PathSeparator); RootPath = rootPath ?? ""; _ancestors = new Lazy <IReadOnlyCollection <IRemoteFolder> >(() => GetAncestors().ToArray()); _name = new Lazy <string>(() => PathParts.Last()); }
private bool ComputeCurrentPart(TokenzierContext context, int index) { var checkPathPart = CheckPathPart(); if (checkPathPart != -1) { context.Errors.Add( new InvalidPathSyntaxError(context.CurrentLocation.Offset(index) .AddWindow(new CharacterSnippedLocation(1, checkPathPart, CurrentPart)), CurrentPart)); return(false); } if (CurrentPart == "null") { if (PathParts.Any()) { context.Errors.Add( new InvalidPathSyntaxError(context.CurrentLocation.Offset(index) .AddWindow(new CharacterSnippedLocation(1, index, CurrentPart)), CurrentPart, "An null must be at the start of an expression")); return(false); } PathParts.Add(new KeyValuePair <string, PathType>(null, PathType.Null)); } else if (CurrentPart == "true" || CurrentPart == "false") { if (PathParts.Any()) { context.Errors.Add( new InvalidPathSyntaxError(context.CurrentLocation.Offset(index) .AddWindow(new CharacterSnippedLocation(1, index, CurrentPart)), CurrentPart, "An boolean must be at the start of an expression")); return(false); } PathParts.Add(new KeyValuePair <string, PathType>(CurrentPart, PathType.Boolean)); } else { PathParts.Add(new KeyValuePair <string, PathType>(CurrentPart, PathType.DataPath)); } return(true); }
/// <inheritdoc /> protected bool Equals(MorestachioExpression other) { if (other.PathParts.Count != PathParts.Count) { return(false); } if (other.Formats.Count != Formats.Count) { return(false); } if (other.FormatterName != FormatterName) { return(false); } if (!other.Location.Equals(Location)) { return(false); } var parts = PathParts.ToArray(); var otherParts = other.PathParts.ToArray(); if (parts.Length != otherParts.Length || Formats.Count != other.Formats.Count) { return(false); } for (var index = 0; index < parts.Length; index++) { var thisPart = parts[index]; var thatPart = otherParts[index]; if (thatPart.Value != thisPart.Value || thatPart.Key != thisPart.Key) { return(false); } } for (var index = 0; index < Formats.Count; index++) { var thisArgument = Formats[index]; var thatArgument = other.Formats[index]; if (!thisArgument.Equals(thatArgument)) { return(false); } } return(true); }
/// <inheritdoc /> public async ContextObjectPromise GetValue(ContextObject contextObject, ScopeData scopeData) { if (!PathParts.Any() && Formats.Count == 1 && FormatterName == "") { //indicates the usage of brackets return(await Formats[0].GetValue(contextObject, scopeData)); } var contextForPath = contextObject.GetContextForPath(PathParts, scopeData, this); if (!Formats.Any() && FormatterName == null) { return(contextForPath); } if (contextForPath == contextObject) { contextForPath = contextObject.CloneForEdit(); } var arguments = new FormatterArgumentType[Formats.Count]; var naturalValue = contextObject.FindNextNaturalContextObject(); for (var index = 0; index < Formats.Count; index++) { var formatterArgument = Formats[index]; var value = await formatterArgument.MorestachioExpression.GetValue(naturalValue, scopeData); arguments[index] = new FormatterArgumentType(index, formatterArgument.Name, value?.Value); } //contextForPath.Value = await contextForPath.Format(FormatterName, argList, scopeData); if (Cache == null) { Cache = contextForPath.PrepareFormatterCall( contextForPath.Value?.GetType() ?? typeof(object), FormatterName, arguments, scopeData); } if (Cache != null /* && !Equals(Cache.Value, default(FormatterCache))*/) { contextForPath.Value = await scopeData.ParserOptions.Formatters.Execute(Cache, contextForPath.Value, scopeData.ParserOptions, arguments); contextForPath.MakeSyntetic(); } return(contextForPath); }
public IList <KeyValuePair <string, PathType> > CompileListWithCurrent(TokenzierContext context, int index, out Func <IMorestachioError> errProducer) { var last = CompileCurrent(context, index, out errProducer); if (last == null) { return(PathParts.GetList()); } if (!(PathParts.Many && last.Value.Value == PathType.SelfAssignment)) { PathParts.Add(last.Value.Key, last.Value.Value); } return(PathParts.GetList()); }
public IList <KeyValuePair <string, PathType> > Compile(TokenzierContext context, int index) { if (CurrentPart == ".") { PathParts.Add(new KeyValuePair <string, PathType>(null, PathType.SelfAssignment)); } else if (CurrentPart == "../") { PathParts.Add(new KeyValuePair <string, PathType>(null, PathType.ParentSelector)); } else if (CurrentPart == "~") { PathParts.Add(new KeyValuePair <string, PathType>(null, PathType.RootSelector)); } else if (CurrentPart == "?") { PathParts.Add(new KeyValuePair <string, PathType>(null, PathType.ObjectSelector)); } else if (CurrentPart.Trim() != "") { if (CurrentPartIsNumber) { PathParts.Add(new KeyValuePair <string, PathType>(CurrentPart, PathType.Number)); } else { if (!ComputeCurrentPart(context, index)) { return(new KeyValuePair <string, PathType> [0]); } } } if (PathParts.Count > 1 && PathParts.Last().Value == PathType.SelfAssignment) { PathParts.Remove(PathParts.Last()); } //if (!PathParts.Any()) //{ // hasError = 0; // return PathParts; //} CurrentPart = ""; return(PathParts); }
public string GetFormatterName() { string lastPartIsFormatterName; //PathParts.LastOrDefault().Key; if (LastCharWasDelimiter) { lastPartIsFormatterName = CurrentPart; } else { lastPartIsFormatterName = PathParts.LastOrDefault().Key; PathParts.RemoveAt(PathParts.Count - 1); } CurrentPart = ""; return(lastPartIsFormatterName); }
private void UpdatePath() { PathParts.Clear(); foreach (var student in Path) { PathParts.Add(new PathPart() { Text = student.Name, Color = student.TextColor }); if (student != Path.Last()) { PathParts.Add(new PathPart() { Text = " | ", Color = Colors.Black }); } } }
/// <summary> /// Breaks down the URL used to request the information into chunks that the event handlers can use to decide what to serve. /// </summary> /// <param name="request"></param> /// <remarks><para> /// .NET unescapes percent-escaped characters before it picks out query strings etc. Virtual Radar WebServer uses the URL to /// carry character strings, in particular they could contain encoded reserved characters such as ?, / and =. If you try /// to decode those strings with .NET the escaped reserved characters cause problems, although RFC1738 does say: /// </para><para> /// "On the other hand, characters that are not required to be encoded (including alphanumerics) may be encoded within /// the scheme-specific part of a URL, as long as they are not being used for a reserved purpose". /// </para><para> /// This would imply that .NET's default behaviour is wrong. It should break the URL down using the unescaped string and then /// unescape each part of the string. "As long as they are not being used for a reserved purpose" implies that reserved characters /// should be treated as normal characters and not for their reserved purpose if they have been escaped. In particular a URL such /// as 'http://127.0.0.1/MyRoot/Folder%3FName%3DValue/Hello.txt' should be interpreted as a path of '/MyRoot/Folder?Name=Value' /// and no query strings - the default .NET behaviour is to resolve that as a path of '/MyRoot/Folder' and a name-value of /// Name = Value. /// </para></remarks> private void DecomposeRequestUrl(IRequest request) { WebSite = ""; PathAndFile = ""; Path = ""; if (!String.IsNullOrEmpty(request.RawUrl) && request.RawUrl.StartsWith(Root, StringComparison.OrdinalIgnoreCase)) { WebSite = String.Format("{0}://{1}{2}", request.Url.Scheme, request.Url.Authority, Root); var rawUrl = request.RawUrl.Substring(Root.Length); var querySplitPosn = rawUrl.IndexOf('?'); var path = querySplitPosn == -1 ? rawUrl : rawUrl.Substring(0, querySplitPosn); var query = querySplitPosn == -1 ? "" : rawUrl.Substring(querySplitPosn + 1); PathAndFile = HttpUtility.UrlDecode(path); if (PathAndFile.Length == 0) { PathAndFile = "/"; } var pathBuffer = new StringBuilder(); var pathParts = path.Split('/'); for (var i = 0; i < pathParts.Length; ++i) { var chunk = HttpUtility.UrlDecode(pathParts[i]); if (i + 1 == pathParts.Length) { File = chunk; } else if (chunk.Length > 0) { PathParts.Add(chunk); pathBuffer.Append('/'); pathBuffer.Append(chunk); } } Path = pathBuffer.Length == 0 ? "/" : pathBuffer.ToString(); QueryString = HttpUtility.ParseQueryString(query); } }
/// <inheritdoc /> public CompiledExpression Compile() { if (!PathParts.HasValue && Formats.Count == 0 && FormatterName == null) { return((contextObject, data) => contextObject.ToPromise()); } if (!PathParts.HasValue && Formats.Count == 1 && FormatterName == "") { //this enables the usage of brackets. A formatter that has no name and one argument e.g ".(data + 1)" or "(data + 1)" should be considered a bracket return((contextObject, data) => Formats[0].GetValue(contextObject, data)); } if (PathParts.Count == 1 && PathParts.Current.Value == PathType.Null) { return((contextObject, scopeData) => scopeData.ParserOptions .CreateContextObject("x:null", null).ToPromise()); } var pathParts = PathParts.ToArray(); Func <ContextObject, ScopeData, IMorestachioExpression, ContextObject> getContext = null; if (pathParts.Length != 0) { var pathQueue = new Func <ContextObject, ScopeData, IMorestachioExpression, ContextObject> [pathParts.Length]; var idx = 0; if (pathParts.Length > 0 && pathParts.First().Value == PathType.DataPath) { var key = pathParts[0].Key; pathQueue[idx++] = ((context, scopeData, expression) => { var variable = scopeData.GetVariable(context, key); if (variable != null) { return(variable); } return(context.ExecuteDataPath(key, expression, context.Value?.GetType(), scopeData)); }); } for (; idx < pathQueue.Length;) { var pathPart = pathParts[idx]; var key = pathPart.Key; switch (pathPart.Value) { case PathType.DataPath: pathQueue[idx++] = ((contextObject, scopeData, expression) => { return(contextObject.ExecuteDataPath(key, expression, contextObject.Value?.GetType(), scopeData)); }); break; case PathType.RootSelector: pathQueue[idx++] = ((contextObject, scopeData, expression) => { return(contextObject.ExecuteRootSelector()); }); break; case PathType.ParentSelector: pathQueue[idx++] = ((contextObject, scopeData, expression) => { var natContext = contextObject.FindNextNaturalContextObject(); return(natContext?.Parent ?? contextObject); }); break; case PathType.ObjectSelector: pathQueue[idx++] = ((contextObject, scopeData, expression) => { return(contextObject.ExecuteObjectSelector(key, contextObject.Value?.GetType(), scopeData)); }); break; case PathType.Null: pathQueue[idx++] = ((contextObject, scopeData, expression) => { return(scopeData.ParserOptions.CreateContextObject("x:null", null)); }); break; case PathType.Boolean: var booleanValue = key == "true"; pathQueue[idx++] = ((contextObject, scopeData, expression) => { var booleanContext = scopeData.ParserOptions.CreateContextObject(".", booleanValue); booleanContext.IsNaturalContext = true; return(booleanContext); }); break; case PathType.SelfAssignment: case PathType.ThisPath: pathQueue[idx++] = ((contextObject, scopeDate, expression) => contextObject); break; default: throw new ArgumentOutOfRangeException(); } } if (pathQueue.Length == 1) { getContext = pathQueue[0]; } else { getContext = (contextObject, data, expression) => { for (var index = 0; index < pathQueue.Length; index++) { var func = pathQueue[index]; contextObject = func(contextObject, data, expression); } return(contextObject); }; } } if (!Formats.Any() && FormatterName == null) { if (getContext == null) { return((contextObject, data) => contextObject.ToPromise()); } return((contextObject, data) => getContext(contextObject, data, this).ToPromise()); } var formatsCompiled = Formats.ToDictionary(f => f, f => { if (f.IsCompileTimeEval()) { return(f.GetCompileTimeValue()); } return(f.Compile()); }).ToArray(); var arguments = new FormatterArgumentType[formatsCompiled.Length]; var allConstants = formatsCompiled.All(e => e.Key.IsCompileTimeEval()); if (allConstants) { for (var index = 0; index < formatsCompiled.Length; index++) { var keyValuePair = formatsCompiled[index]; arguments[index] = new FormatterArgumentType(index, keyValuePair.Key.Name, keyValuePair.Value); } } FormatterCache cache = null; async Promise CallFormatter( ContextObject naturalContext, ContextObject outputContext, ScopeData scopeData) { if (!allConstants) { for (var index = 0; index < formatsCompiled.Length; index++) { var formatterArgument = formatsCompiled[index]; object value; if (formatterArgument.Value is CompiledExpression cex) { value = (await cex(naturalContext, scopeData))?.Value; } else { value = formatterArgument.Value; } arguments[index] = new FormatterArgumentType(index, formatterArgument.Key.Name, value); } } if (cache == null) { cache = outputContext.PrepareFormatterCall( outputContext.Value?.GetType() ?? typeof(object), FormatterName, arguments, scopeData); } if (cache != null) { outputContext.Value = await scopeData.ParserOptions.Formatters.Execute(cache, outputContext.Value, scopeData.ParserOptions, arguments); outputContext.MakeSyntetic(); } } if (getContext == null) { return(async(contextObject, scopeData) => { var ctx = scopeData.ParserOptions.CreateContextObject("", contextObject.Value, contextObject); contextObject = contextObject.FindNextNaturalContextObject(); await CallFormatter(contextObject, ctx, scopeData); return ctx; }); } return(async(contextObject, scopeData) => { var ctx = getContext(contextObject, scopeData, this); await CallFormatter(contextObject, ctx, scopeData); return ctx; }); }
public bool Add(char c, TokenzierContext context, int index, out Func <IMorestachioError> errProducer) { errProducer = null; if (!Tokenizer.IsExpressionPathChar(c)) { errProducer = () => new InvalidPathSyntaxError(context.CurrentLocation.Offset(index) .AddWindow(new CharacterSnippedLocation(1, index, CurrentPart)), CurrentPart); return(false); } if (PathParts.IsNullValue) { errProducer = () => new InvalidPathSyntaxError(context.CurrentLocation.Offset(index) .AddWindow(new CharacterSnippedLocation(1, index, CurrentPart)), CurrentPart, "Nothing can follow on a null"); return(false); } LastCharWasDelimiter = c == '.'; if (c == '/') { if (CurrentPart == "..") { if (PathParts.Any && !PathParts.HasParentSelector) { errProducer = () => new InvalidPathSyntaxError(context.CurrentLocation.Offset(index) .AddWindow(new CharacterSnippedLocation(1, index, CurrentPart)), CurrentPart, "An Parent selector '..\\' can only follow on another parent selector like and never on an root or an data selector"); return(false); } PathParts.Add(null, PathType.ParentSelector); CurrentPart = string.Empty; return(true); } errProducer = () => new InvalidPathSyntaxError(context.CurrentLocation.Offset(index) .AddWindow(new CharacterSnippedLocation(1, index, CurrentPart)), CurrentPart, "Unexpected '/'. Expected ether the start of an expression or an './'"); return(false); } if (c == '~') { if (CurrentPart != string.Empty || PathParts.Any) { errProducer = () => new InvalidPathSyntaxError(context.CurrentLocation.Offset(index) .AddWindow(new CharacterSnippedLocation(1, index, CurrentPart)), CurrentPart, "An root selector '~' must be at the start of an expression"); return(false); } PathParts.Add(null, PathType.RootSelector); CurrentPart = string.Empty; return(true); } if (c == '?') { PathParts.Add(null, PathType.ObjectSelector); CurrentPart = string.Empty; return(true); } if (c != '.' && CurrentPart == "." && !PathParts.Any) { //in this case somebody wrote .data //so ignore the dot CurrentPart = string.Empty; } if (CurrentPart != string.Empty && CurrentPart != "." && c == '.') { if (!ComputeCurrentPart(context, index, out errProducer)) { return(false); } CurrentPart = ""; } else { CurrentPart += c; } return(true); }
public ObjectPropertyInfo Clone() => new ObjectPropertyInfo() { PathParts = PathParts.ToList() };
private bool ComputeCurrentPart(TokenzierContext context, int index, out Func <IMorestachioError> errProducer) { errProducer = null; var checkPathPart = CheckPathPart(); if (checkPathPart != -1) { errProducer = () => ( new InvalidPathSyntaxError(context.CurrentLocation.Offset(index) .AddWindow(new CharacterSnippedLocation(1, checkPathPart, CurrentPart)), CurrentPart)); return(false); } if (CurrentPart == "null") { if (PathParts.Any) { errProducer = () => ( new InvalidPathSyntaxError(context.CurrentLocation.Offset(index) .AddWindow(new CharacterSnippedLocation(1, index, CurrentPart)), CurrentPart, "An null must be at the start of an expression")); return(false); } PathParts.Add(null, PathType.Null); return(true); } if (CurrentPart == "true" || CurrentPart == "false") { if (PathParts.Any) { errProducer = () => ( new InvalidPathSyntaxError(context.CurrentLocation.Offset(index) .AddWindow(new CharacterSnippedLocation(1, index, CurrentPart)), CurrentPart, "An boolean must be at the start of an expression")); return(false); } PathParts.Add(CurrentPart, PathType.Boolean); return(true); } if (CurrentPart == "../") { PathParts.Add(null, PathType.ParentSelector); return(true); } if (CurrentPart == "~") { PathParts.Add(null, PathType.RootSelector); return(true); } if (CurrentPart == "?") { PathParts.Add(null, PathType.ObjectSelector); return(true); } PathParts.Add(CurrentPart, PathType.DataPath); return(true); }
public IList <KeyValuePair <string, PathType> > Compile(TokenzierContext context, int index) { return(PathParts.GetList()); }
public static string CombinePathsUri(params string[] PathParts) { return(PathParts.SelectMany(s => s.Split(new[] { "\\", "/", " " }, StringSplitOptions.RemoveEmptyEntries)) .Aggregate("/", (a, b) => a == "/" ? $"{a}{b}" : $"{a}/{b}")); }
/// <summary> /// Initializes a <see cref="ParsedPath"/> from another <see cref="ParsedPath"/> which avoids the need to reparse the path. /// </summary> /// <param name="path">The source path</param> /// <param name="parts">The parts to copy from the source path</param> public ParsedPath(ParsedPath path, PathParts parts) { switch (parts) { case PathParts.Machine: this.machineLength = path.machineLength; this.path = path.Machine; break; case PathParts.Share: this.shareLength = path.shareLength; this.path = path.Share; break; case PathParts.Drive: this.driveLength = path.driveLength; this.path = path.Drive; break; case PathParts.Directory: this.dirLength = path.dirLength; this.path = path.Directory; break; case PathParts.File: this.fileLength = path.fileLength; this.path = path.File; break; case PathParts.Extension: this.extLength = path.extLength; this.path = path.Extension; break; case PathParts.Volume: if (path.HasDrive) { this.driveLength = path.driveLength; this.path = path.Drive; } else { this.machineLength = path.machineLength; this.shareLength = path.shareLength; this.path = path.Machine + path.Share; } break; case PathParts.Unc: this.machineLength = path.machineLength; this.shareLength = path.shareLength; this.path = path.Machine + path.Share; break; case PathParts.VolumeAndDirectory: if (path.HasDrive) { this.driveLength = path.driveLength; this.dirLength = path.dirLength; this.path = path.Drive + path.Directory; } else { this.machineLength = path.machineLength; this.shareLength = path.shareLength; this.dirLength = path.dirLength; this.path = path.Machine + path.Share + path.Directory; } break; case PathParts.VolumeDirectoryAndFile: if (path.HasDrive) { this.driveLength = path.driveLength; this.dirLength = path.dirLength; this.fileLength = path.fileLength; this.path = path.Drive + path.Directory + path.File; } else { this.machineLength = path.machineLength; this.shareLength = path.shareLength; this.dirLength = path.dirLength; this.fileLength = path.fileLength; this.path = path.Machine + path.Share + path.Directory + path.File; } break; case PathParts.DirectoryAndFile: this.dirLength = path.dirLength; this.fileLength = path.fileLength; this.path = path.Directory + path.File; break; case PathParts.DirectoryFileAndExtension: this.dirLength = path.dirLength; this.fileLength = path.fileLength; this.extLength = path.extLength; this.path = path.Directory + path.File + path.Extension; break; case PathParts.FileAndExtension: this.fileLength = path.fileLength; this.extLength = path.extLength; this.path = path.File + path.Extension; break; case PathParts.All: if (path.HasDrive) { this.driveLength = path.driveLength; this.dirLength = path.dirLength; this.fileLength = path.fileLength; this.extLength = path.extLength; this.path = path.Drive + path.Directory + path.File + path.Extension; } else { this.machineLength = path.machineLength; this.shareLength = path.shareLength; this.dirLength = path.dirLength; this.fileLength = path.fileLength; this.extLength = path.extLength; this.path = path.Machine + path.Share + path.Directory + path.File + path.Extension; } break; } }
public override string ToString() { return($"Path={string.Join("/", PathParts.Select(x => x.PartType == PathPart.PathPartType.Argument ? $"{{{x.Value}}}" : x.Value))}, Parameters={string.Join("&", Parameters.Select(x => $"{x.Name}={x.Value}"))}, Fragment={Fragment}"); }
public bool Add(char c, TokenzierContext context, int index) { if (!Tokenizer.IsExpressionChar(c)) { context.Errors.Add( new InvalidPathSyntaxError(context.CurrentLocation.Offset(index) .AddWindow(new CharacterSnippedLocation(1, index, CurrentPart)), CurrentPart)); return(false); } if (PathParts.Any(f => f.Value == PathType.Null)) { context.Errors.Add( new InvalidPathSyntaxError(context.CurrentLocation.Offset(index) .AddWindow(new CharacterSnippedLocation(1, index, CurrentPart)), CurrentPart, "Nothing can follow on a null")); } LastCharWasDelimiter = c == '.'; if (c == '/') { if (CurrentPart == "..") { if (PathParts.Any() && PathParts.Any(e => e.Value != PathType.ParentSelector)) { context.Errors.Add( new InvalidPathSyntaxError(context.CurrentLocation.Offset(index) .AddWindow(new CharacterSnippedLocation(1, index, CurrentPart)), CurrentPart, "An Parent selector '..\\' can only follow on another parent selector like and never on an root or an data selector")); return(false); } PathParts.Add(new KeyValuePair <string, PathType>(null, PathType.ParentSelector)); CurrentPart = ""; return(true); } context.Errors.Add( new InvalidPathSyntaxError(context.CurrentLocation.Offset(index) .AddWindow(new CharacterSnippedLocation(1, index, CurrentPart)), CurrentPart, "Unexpected '/'. Expected ether the start of an expression or an './'")); return(false); } if (c == '~') { if (CurrentPart != string.Empty || PathParts.Any()) { context.Errors.Add( new InvalidPathSyntaxError(context.CurrentLocation.Offset(index) .AddWindow(new CharacterSnippedLocation(1, index, CurrentPart)), CurrentPart, "An root selector '~' must be at the start of an expression")); return(false); } PathParts.Add(new KeyValuePair <string, PathType>(null, PathType.RootSelector)); CurrentPart = ""; return(true); } if (c == '?') { PathParts.Add(new KeyValuePair <string, PathType>(null, PathType.ObjectSelector)); CurrentPart = ""; return(true); } if (c != '.' && CurrentPart == "." && PathParts.Count == 0) { //in this case somebody wrote .data //so ignore the dot CurrentPart = ""; } if (CurrentPart != "" && CurrentPart != "." && c == '.') { if (CurrentPartIsNumber) { if (CurrentPart.Contains(".")) { PathParts.Add(new KeyValuePair <string, PathType>(CurrentPart, PathType.Number)); CurrentPart = ""; } else { CurrentPart += c; } return(true); } if (!ComputeCurrentPart(context, index)) { return(false); } CurrentPart = ""; } else { if (CurrentPart == string.Empty && char.IsDigit(c)) { CurrentPartIsNumber = true; if (PathParts.Any()) { context.Errors.Add( new InvalidPathSyntaxError(context.CurrentLocation.Offset(index) .AddWindow(new CharacterSnippedLocation(1, index, CurrentPart)), CurrentPart, "A number expression must be at the start of the expression and cannot follow on anything else")); return(false); } } CurrentPart += c; } return(true); }