public override void SetupByOffset() { for (int i = 0; i < Selectors.Length; i++) { ShortElement c = (ShortElement)Selectors[i]; var val = c.Value; var target = _script.GetElement(val); if (target != null && target is StringConst) // || (target is StringPart) { var r = new RefToElement(_script, c.Address, c.Value) { Source = this }; c.ReplaceBy(r); Selectors[i] = r; r.SetupByOffset(); } } { if (Selectors[3] is ShortElement s) { StringPart p = _script.GetStringPart(s.Value); if (p != null) { _script.Register(p); var r = new RefToElement(_script, s.Address, s.Value) { Source = this }; s.ReplaceBy(r); Selectors[3] = r; r.SetupByOffset(); } } } var nameRef = (Selectors[3] as RefToElement)?.Reference; if (nameRef != null) { if (nameRef is StringConst s) { Name = s.Value; s.IsClassName = true; } else if (nameRef is StringPart p) { Name = p.String; p.OrigString.IsClassName = true; } } foreach (var r in FuncCode) { r.SetupByOffset(); } }
/// <summary> /// Collapses internal whitespace to single space, removes leading/trailing whitespace, folds case. /// </summary> private static string NormalizeReference(StringPart s) { if (s.Length == 0) { return(string.Empty); } return(NormalizeWhitespace(s.Source, s.StartIndex, s.Length).ToUpperInvariant()); }
private bool TryParseEscapeSequence(ref StringPart part) { int start = this.text.Position; this.text.Next(); if (escapeChar.IndexOf(this.text.Char()) >= 0) { this.text.Next(); part = new StringPart(new TextSpan(this.text.Position - 2, 2)); return(true); } if (Char.IsDigit(this.text.Char()) && Char.IsDigit(this.text.NChar()) && Char.IsDigit(this.text.NNChar())) { // a trigraph this.text.Skip(3); part = new StringPart(new TextSpan(this.text.Position - 4, 4)); return(true); } if (this.text.Char() == '0' && !Char.IsDigit(this.text.NChar())) { // \0 this.text.Next(); part = new StringPart(new TextSpan(this.text.Position - 2, 2)); return(true); } if (this.text.Char() == 'u') { this.text.Next(); this.text.Mark(); TextSpan?span = TryParseShortUnicode(); if (span.HasValue) { part = new StringPart(span.Value); return(true); } this.text.BackToMark(); } if (this.text.Char() == 'U') { this.text.Next(); this.text.Mark(); TextSpan?span = TryParseLongUnicode(); if (span.HasValue) { part = new StringPart(span.Value); return(true); } this.text.BackToMark(); } // unrecognized sequence, return it as error this.text.Next(); int length = this.text.Position - start; part = new StringPart(new TextSpan(start, length), StringPartType.EscapeSequenceError); return(true); }
/// <summary> /// Adds a new reference to the dictionary, if the label does not already exist there. /// Assumes that the length of the label does not exceed <see cref="Reference.MaximumReferenceLabelLength"/>. /// </summary> private static void AddReference(Dictionary <string, Reference> refmap, StringPart label, string url, string title) { var normalizedLabel = NormalizeReference(label); if (refmap.ContainsKey(normalizedLabel)) { return; } refmap.Add(normalizedLabel, new Reference(normalizedLabel, url, title)); }
/// <summary> /// Writes the line. /// </summary> /// <param name="line">The line.</param> public void WriteLine(StringPart line) { //var t = text[text.Count - 1]; //text.RemoveAt(text.Count - 1); //t.Batch.Clear(); //t.Batch.Write(line); //t.Height = t.Batch.CalculateArea(Int2D.Zero, Justification, Area.Width).Height; //text.Insert(0, t); Write(line.ToString()); moveNextDrawToNewLine = true; }
/// <summary> /// Escapes special HTML characters. /// </summary> /// <remarks>Orig: escape_html(inp, preserve_entities)</remarks> internal static void EscapeHtml(StringPart input, HtmlTextWriter target) { if (input.Length == 0) { return; } int pos; int lastPos = input.StartIndex; char[] buffer; if (target.Buffer.Length < input.Length) { buffer = target.Buffer = new char[input.Length]; } else { buffer = target.Buffer; } input.Source.CopyTo(input.StartIndex, buffer, 0, input.Length); while ((pos = input.Source.IndexOfAny(EscapeHtmlCharacters, lastPos, input.Length - lastPos + input.StartIndex)) != -1) { target.Write(buffer, lastPos - input.StartIndex, pos - lastPos); lastPos = pos + 1; switch (input.Source[pos]) { case '<': target.WriteConstant(EscapeHtmlLessThan); break; case '>': target.WriteConstant(EscapeHtmlGreaterThan); break; case '&': target.WriteConstant(EscapeHtmlAmpersand); break; case '"': target.WriteConstant(EscapeHtmlQuote); break; } } target.Write(buffer, lastPos - input.StartIndex, input.Length - lastPos + input.StartIndex); }
private bool TryParseEscapeSequence(ref StringPart part) { text.Next(); if (escapeChar.IndexOf(text.Char()) >= 0) { text.Next(); part = new StringPart(new Span(text.Position - 2, 2)); return(true); } if (Char.IsDigit(text.Char()) && Char.IsDigit(text.NChar()) && Char.IsDigit(text.NNChar())) { // a trigraph text.Skip(3); part = new StringPart(new Span(text.Position - 4, 4)); return(true); } if (text.Char() == '0' && !Char.IsDigit(text.NChar())) { // \0 text.Next(); part = new StringPart(new Span(text.Position - 2, 2)); return(true); } if (text.Char() == 'u') { text.Next(); text.Mark(); Span?span = TryParseShortUnicode(); if (span.HasValue) { part = new StringPart(span.Value); return(true); } text.BackToMark(); } if (text.Char() == 'U') { text.Next(); text.Mark(); Span?span = TryParseLongUnicode(); if (span.HasValue) { part = new StringPart(span.Value); return(true); } text.BackToMark(); } return(false); }
public ParsedMatch <T>?TryMatch(StringPart stringPart) { var match = _regex.Match(stringPart.Target, stringPart.StartIndex, stringPart.Length); if (!match.Success) { return(null); } // Overload regex.Match(string, int, int) doesn't take the whole string into account, // it effectively functions as a match check on a substring. // Which is super weird because regex.Match(string, int) takes the whole input in context. // So in order to properly account for ^/$ regex tokens, we need to make sure that // the expression also matches on the bigger part of the input. if (!_regex.IsMatch(stringPart.Target[..stringPart.EndIndex], stringPart.StartIndex))
public ParsedMatch <T>?TryMatch(StringPart stringPart) { var index = stringPart.Target.IndexOf(_needle, stringPart.StartIndex, stringPart.Length, _comparison); if (index < 0) { return(null); } var stringPartMatch = stringPart.Slice(index, _needle.Length); var value = _transform(stringPartMatch); return(value is not null ? new ParsedMatch <T>(stringPartMatch, value) : null); }
/// <summary> /// Determines if the given string has non-whitespace characters in it /// </summary> public static bool HasNonWhitespace(StringPart part) { var s = part.Source; var i = part.StartIndex; var l = i + part.Length; while (i < l) { if (!Utilities.IsWhitespace(s[i])) { return(true); } i++; } return(false); }
/// <summary> /// Parses the contents of [..] for a reference label. Only used for parsing /// reference definition labels for use with the reference dictionary because /// it does not properly parse nested inlines. /// /// Assumes the source starts with '[' character. /// Returns null and does not advance if no matching ] is found. /// Note the precedence: code backticks have precedence over label bracket /// markers, which have precedence over *, _, and other inline formatting /// markers. So, 2 below contains a link while 1 does not: /// 1. [a link `with a ](/url)` character /// 2. [a link *with emphasized ](/url) text* /// </summary> private static StringPart?ParseReferenceLabel(Subject subj) { var startPos = subj.Position; var source = subj.Buffer; var len = subj.Length; var labelStartPos = ++subj.Position; len = subj.Position + Reference.MaximumReferenceLabelLength; if (len > source.Length) { len = source.Length; } subj.Position = source.IndexOfAny(BracketSpecialCharacters, subj.Position, len - subj.Position); while (subj.Position > -1) { var c = source[subj.Position]; if (c == '\\') { subj.Position += 2; if (subj.Position >= len) { break; } subj.Position = source.IndexOfAny(BracketSpecialCharacters, subj.Position, len - subj.Position); } else if (c == '[') { break; } else { var label = new StringPart(source, labelStartPos, subj.Position - labelStartPos); subj.Position++; return(label); } } subj.Position = startPos; return(null); }
public void Write(StringPart value) { if (value.Length == 0) { return; } if (this.Buffer.Length < value.Length) { this.Buffer = new char[value.Length]; } value.Source.CopyTo(value.StartIndex, this.Buffer, 0, value.Length); if (this._windowsNewLine) { var lastPos = value.StartIndex; var pos = lastPos; while (-1 != (pos = value.Source.IndexOf('\n', pos, value.Length - pos + value.StartIndex))) { var lastC = pos == 0 ? this._last : value.Source[pos - 1]; if (lastC != '\r') { this._inner.Write(this.Buffer, lastPos - value.StartIndex, pos - lastPos); this._inner.Write('\r'); lastPos = pos; } pos++; } this._inner.Write(this.Buffer, lastPos - value.StartIndex, value.Length - lastPos + value.StartIndex); } else { this._inner.Write(this.Buffer, 0, value.Length); } this._last = this.Buffer[value.Length - 1]; }
private bool ParseFormatSpecifier(ref StringPart result) { // text.Char() == '{' int start = text.Position; int len = 1; text.Next(); while (!text.EndOfLine) { len++; if (text.Char() == '}') { result = new StringPart(start, len, StringPartType.FormatSpecifier); text.Next(); return(true); } text.Next(); } return(false); }
public static IEnumerable <ParsedMatch <T> > MatchAll <T>(this IMatcher <T> matcher, StringPart stringPart, Func <StringPart, T> transformFallback) { // Loop through segments divided by individual matches var currentIndex = stringPart.StartIndex; while (currentIndex < stringPart.EndIndex) { // Find a match within this segment var match = matcher.TryMatch(stringPart.Slice(currentIndex, stringPart.EndIndex - currentIndex)); // If there's no match - break if (match is null) { break; } // If this match doesn't start immediately at current index - transform and yield fallback first if (match.StringPart.StartIndex > currentIndex) { var fallbackPart = stringPart.Slice(currentIndex, match.StringPart.StartIndex - currentIndex); yield return(new ParsedMatch <T>(fallbackPart, transformFallback(fallbackPart))); } // Yield match yield return(match); // Shift current index to the end of the match currentIndex = match.StringPart.StartIndex + match.StringPart.Length; } // If EOL wasn't reached - transform and yield remaining part as fallback if (currentIndex < stringPart.EndIndex) { var fallbackPart = stringPart.Slice(currentIndex); yield return(new ParsedMatch <T>(fallbackPart, transformFallback(fallbackPart))); } }
/// <summary> /// Appends text onto the last line written. /// </summary> /// <param name="text">The text to append.</param> public void Write(StringPart line) { if (moveNextDrawToNewLine || text.Count == 0) { text.Add(line); moveNextDrawToNewLine = false; } else { var current = text[text.Count - 1]; text[text.Count - 1] = current.ToString() + line.ToString(); } //if (line[line.Length - 1] == '\n') // moveNextDrawToNewLine = true; text.RemoveRange(0, Math.Max(0, text.Count - historyCapacity)); if (startIndex == text.Count - 1) { ScrollToNewest(); } }
/// <summary> /// Checks if the reference dictionary contains a reference with the given label and returns it, /// otherwise returns <see langword="null"/>. /// Returns <see cref="Reference.InvalidReference"/> if the reference label is not valid. /// </summary> private static Reference LookupReference(DocumentData data, StringPart lab) { if (data?.ReferenceMap == null) { return(null); } if (lab.Length > Reference.MaximumReferenceLabelLength) { return(Reference.InvalidReference); } string label = NormalizeReference(lab); Reference r; if (data.ReferenceMap.TryGetValue(label, out r)) { return(r); } return(null); }
public StringPart?Next() { while (!text.EndOfLine) { if (text.Char() == '\\') { return(BasicCStringScanner.ParseEscapeSequence(text)); } else if (text.Char() == '{' && text.NChar() == '{') { text.Next(); // skip it } else if (text.Char() == '{' && !isInterpolated) { StringPart part = new StringPart(); if (ParseFormatSpecifier(ref part)) { return(part); } } text.Next(); } return(null); }
private void WriteEncodedHtml(StringPart text) { HtmlFormatterSlim.EscapeHtml(text, _target); }
private void Write(StringPart text) { _target.Write(text); }
private void WriteStringStart() { if (_currStringPart == StringPart.None) { _writer.Write("\""); } else if (_currStringPart == StringPart.Outside) { _writer.Write(" & \""); } _currStringPart = StringPart.Inside; }
private void WriteStringEnd(bool final) { if (_currStringPart == StringPart.Inside) _writer.Write("\""); if (final) { _currStringPart = StringPart.None; } else { _currStringPart = StringPart.Outside; } }
private static IReadOnlyList <MarkdownNode> Parse(StringPart stringPart, IMatcher <MarkdownNode> matcher) => matcher .MatchAll(stringPart, p => new TextNode(p.ToString())) .Select(r => r.Value) .ToArray();
private static IReadOnlyList <Node> ParseMinimal(StringPart stringPart) => Parse(stringPart, MinimalAggregateNodeMatcher);
private static Inline HandleRightSquareBracket(Subject subj) { // move past ']' subj.Position++; bool canClose; var istack = InlineStack.FindMatchingOpener(subj.LastPendingInline, InlineStack.InlineStackPriority.Links, '[', out canClose); if (istack != null) { // if the opener is "inactive" then it means that there was a nested link if (istack.DelimeterCount == -1) { InlineStack.RemoveStackEntry(istack, subj, istack); return(new Inline("]", subj.Position - 1, subj.Position)); } var endpos = subj.Position; // try parsing details for '[foo](/url "title")' or '[foo][bar]' var details = ParseLinkDetails(subj); // try lookup of the brackets themselves if (details == null || details == Reference.SelfReference) { var startpos = istack.StartPosition; var label = new StringPart(subj.Buffer, startpos, endpos - startpos - 1); details = LookupReference(subj.ReferenceMap, label); } if (details == Reference.InvalidReference) { details = null; } MatchSquareBracketStack(istack, subj, details); return(null); } var inlText = new Inline("]", subj.Position - 1, subj.Position); if (canClose) { // note that the current implementation will not work if there are other inlines with priority // higher than Links. // to fix this the parsed link details should be added to the closer element in the stack. throw new NotSupportedException("It is not supported to have inline stack priority higher than Links."); ////istack = new InlineStack(); ////istack.Delimeter = '['; ////istack.StartingInline = inlText; ////istack.StartPosition = subj.Position; ////istack.Priority = InlineStack.InlineStackPriority.Links; ////istack.Flags = InlineStack.InlineStackFlags.Closer; ////InlineStack.AppendStackEntry(istack, subj); } return(inlText); }
/// <summary> /// Checks if the reference dictionary contains a reference with the given label and returns it, /// otherwise returns <c>null</c>. /// Returns <see cref="Reference.InvalidReference"/> if the reference label is not valid. /// </summary> private static Reference LookupReference(Dictionary <string, Reference> refmap, StringPart lab) { if (refmap == null) { return(null); } if (lab.Length > Reference.MaximumReferenceLabelLength) { return(Reference.InvalidReference); } string label = NormalizeReference(lab); Reference r; if (refmap.TryGetValue(label, out r)) { return(r); } return(null); }
public ParsedMatch(StringPart stringPart, T value) { StringPart = stringPart; Value = value; }
public AbstractRoute(string pattern, MethodInfo methodInfo, IWaConfig config) { this.config = config; method = methodInfo; foreach (var part in pattern.Split(new[] { '/' })) { if (part.IndexOf('{') == 0) { if (part[part.Length - 1] != '}') { throw new Exception("part must end with }"); } var pair = part.Substring(1, part.Length - 2).Split(new[] { ':' }); Part newPart; /*if (pair.Length == 2) * { * switch (pair[1]) * { * case "int": * newPart = new IntPart(); * break; * case "long": * newPart = new LongPart(); * break; * default: * throw new Exception("unsupported type"); * } * } * else * { * newPart = new StringPart(); * } * newPart.pattern = pair[0]; * if (newPart.pattern[newPart.pattern.Length -1 ] == '?') * { * newPart.pattern = newPart.pattern.Substring(0, newPart.pattern.Length - 1); * newPart.optional = true; * }*/ string partName = pair[0]; bool optional = false; if (partName[partName.Length - 1] == '?') { partName = partName.Substring(0, partName.Length - 1); optional = true; } var parameter = methodInfo.GetParameters().SingleOrDefault(p => p.Name == partName); if (parameter == null) { throw new Exception(string.Format("method {0} parameter {1} cannot be found (from pattern {2})", methodInfo.Name, partName, pattern)); } if (parameter.ParameterType.IsEnum) { newPart = new EnumPart(parameter.ParameterType); } else if (parameter.ParameterType == typeof(string)) { newPart = new StringPart(); } else if (parameter.ParameterType == typeof(long)) { newPart = new LongPart(); } else if (parameter.ParameterType == typeof(int)) { newPart = new IntPart(); } else { throw new Exception("Unsupported uri part parameter type " + parameter.ParameterType.Name); } newPart.pattern = partName; newPart.optional = optional; newPart.order = parameter.Position; parts.Add(newPart); } else if (part.Length > 0) { parts.Add(new Part { pattern = part }); } } body = method.GetParameters().Where(p => p.GetCustomAttribute <FromBodyAttribute>() != null).SingleOrDefault(); foreach (var parameter in method.GetParameters().Where(p => p.GetCustomAttribute <FromUriAttribute>() != null)) { if (query == null) { query = new Dictionary <string, Part>(); } if (parameter.ParameterType == typeof(int)) { query[parameter.Name] = new IntPart { order = parameter.Position } } ; else if (parameter.ParameterType == typeof(long)) { query[parameter.Name] = new LongPart { order = parameter.Position } } ; else if (parameter.ParameterType == typeof(string)) { query[parameter.Name] = new StringPart { order = parameter.Position } } ; else if (parameter.ParameterType == typeof(bool)) { query[parameter.Name] = new BoolPart { order = parameter.Position } } ; else if (parameter.ParameterType == typeof(double)) { query[parameter.Name] = new DoublePart { order = parameter.Position } } ; else if (parameter.ParameterType == typeof(DateTime)) { query[parameter.Name] = new DatePart { order = parameter.Position } } ; else if (parameter.ParameterType.IsEnum) { query[parameter.Name] = new EnumPart(parameter.ParameterType) { order = parameter.Position } } ; else { throw new Exception("Parameter type " + parameter.ParameterType + " unsupported in " + method.DeclaringType.FullName + "." + method.Name); } if (parameter.HasDefaultValue) { query[parameter.Name].optional = true; query[parameter.Name].defaultValue = parameter.DefaultValue; } } var unmappedParameter = method.GetParameters().FirstOrDefault(p => p.GetCustomAttribute <FromBodyAttribute>() == null && p.GetCustomAttribute <FromUriAttribute>() == null && !parts.Any(x => x.order == p.Position)); if (unmappedParameter != null) { throw new Exception("Parameter " + unmappedParameter.Name + " has not been mapped in " + method.Name + " from " + method.DeclaringType.Name); } numberOfMandatoryParts = parts.Count(p => !p.optional); }