public static RouteTemplate Parse(string routeTemplate) { if (routeTemplate == null) { routeTemplate = String.Empty; } if (IsInvalidRouteTemplate(routeTemplate)) { throw new ArgumentException(Resources.TemplateRoute_InvalidRouteTemplate, nameof(routeTemplate)); } var context = new TemplateParserContext(routeTemplate); var segments = new List<TemplateSegment>(); while (context.Next()) { if (context.Current == Separator) { // If we get here is means that there's a consecutive '/' character. // Templates don't start with a '/' and parsing a segment consumes the separator. throw new ArgumentException(Resources.TemplateRoute_CannotHaveConsecutiveSeparators, nameof(routeTemplate)); } else { if (!ParseSegment(context, segments)) { throw new ArgumentException(context.Error, nameof(routeTemplate)); } } } if (IsAllValid(context, segments)) { return new RouteTemplate(segments); } else { throw new ArgumentException(context.Error, nameof(routeTemplate)); } }
public static RouteTemplate Parse(string routeTemplate) { if (routeTemplate == null) { routeTemplate = String.Empty; } if (IsInvalidRouteTemplate(routeTemplate)) { throw new ArgumentException(Resources.TemplateRoute_InvalidRouteTemplate, "routeTemplate"); } var context = new TemplateParserContext(routeTemplate); var segments = new List <TemplateSegment>(); while (context.Next()) { if (context.Current == Separator) { // If we get here is means that there's a consecutive '/' character. // Templates don't start with a '/' and parsing a segment consumes the separator. throw new ArgumentException(Resources.TemplateRoute_CannotHaveConsecutiveSeparators, "routeTemplate"); } else { if (!ParseSegment(context, segments)) { throw new ArgumentException(context.Error, "routeTemplate"); } } } if (IsAllValid(context, segments)) { return(new RouteTemplate(segments)); } else { throw new ArgumentException(context.Error, "routeTemplate"); } }
public static RouteTemplate Parse(string routeTemplate) { if (routeTemplate == null) { routeTemplate = String.Empty; } var trimmedRouteTemplate = TrimPrefix(routeTemplate); var context = new TemplateParserContext(trimmedRouteTemplate); var segments = new List <TemplateSegment>(); while (context.Next()) { if (context.Current == Separator) { // If we get here is means that there's a consecutive '/' character. // Templates don't start with a '/' and parsing a segment consumes the separator. throw new ArgumentException("invlaid segement", nameof(routeTemplate)); } else { if (!ParseSegment(context, segments)) { throw new ArgumentException(context.Error, nameof(routeTemplate)); } } } if (IsAllValid(context, segments)) { return(new RouteTemplate(routeTemplate, segments)); } else { throw new ArgumentException(context.Error, nameof(routeTemplate)); } }
private static bool ParseSegment(TemplateParserContext context, List<TemplateSegment> segments) { Debug.Assert(context != null); Debug.Assert(segments != null); var segment = new TemplateSegment(); while (true) { if (context.Current == OpenBrace) { if (!context.Next()) { // This is a dangling open-brace, which is not allowed context.Error = Resources.TemplateRoute_MismatchedParameter; return false; } if (context.Current == OpenBrace) { // This is an 'escaped' brace in a literal, like "{{foo" context.Back(); if (!ParseLiteral(context, segment)) { return false; } } else { // This is the inside of a parameter if (!ParseParameter(context, segment)) { return false; } } } else if (context.Current == Separator) { // We've reached the end of the segment break; } else { if (!ParseLiteral(context, segment)) { return false; } } if (!context.Next()) { // We've reached the end of the string break; } } if (IsSegmentValid(context, segment)) { segments.Add(segment); return true; } else { return false; } }
private static bool ParseLiteral(TemplateParserContext context, TemplateSegment segment) { context.Mark(); string encoded; while (true) { if (context.Current == Separator) { encoded = context.Capture(); context.Back(); break; } else if (context.Current == OpenBrace) { if (!context.Next()) { // This is a dangling open-brace, which is not allowed context.Error = Resources.TemplateRoute_MismatchedParameter; return false; } if (context.Current == OpenBrace) { // This is an 'escaped' brace in a literal, like "{{foo" - keep going. } else { // We've just seen the start of a parameter, so back up and return context.Back(); encoded = context.Capture(); context.Back(); break; } } else if (context.Current == CloseBrace) { if (!context.Next()) { // This is a dangling close-brace, which is not allowed context.Error = Resources.TemplateRoute_MismatchedParameter; return false; } if (context.Current == CloseBrace) { // This is an 'escaped' brace in a literal, like "{{foo" - keep going. } else { // This is an unbalanced close-brace, which is not allowed context.Error = Resources.TemplateRoute_MismatchedParameter; return false; } } if (!context.Next()) { encoded = context.Capture(); break; } } var decoded = encoded.Replace("}}", "}").Replace("{{", "{"); if (IsValidLiteral(context, decoded)) { segment.Parts.Add(TemplatePart.CreateLiteral(decoded)); return true; } else { return false; } }
private static bool ParseParameter(TemplateParserContext context, TemplateSegment segment) { context.Mark(); while (true) { if (context.Current == OpenBrace) { // This is an open brace inside of a parameter, it has to be escaped if (context.Next()) { if (context.Current != OpenBrace) { // If we see something like "{p1:regex(^\d{3", we will come here. context.Error = Resources.TemplateRoute_UnescapedBrace; return false; } } else { // This is a dangling open-brace, which is not allowed // Example: "{p1:regex(^\d{" context.Error = Resources.TemplateRoute_MismatchedParameter; return false; } } else if (context.Current == CloseBrace) { // When we encounter Closed brace here, it either means end of the parameter or it is a closed // brace in the parameter, in that case it needs to be escaped. // Example: {p1:regex(([}}])\w+}. First pair is escaped one and last marks end of the parameter if (!context.Next()) { // This is the end of the string -and we have a valid parameter context.Back(); break; } if (context.Current == CloseBrace) { // This is an 'escaped' brace in a parameter name } else { // This is the end of the parameter context.Back(); break; } } if (!context.Next()) { // This is a dangling open-brace, which is not allowed context.Error = Resources.TemplateRoute_MismatchedParameter; return false; } } var rawParameter = context.Capture(); var decoded = rawParameter.Replace("}}", "}").Replace("{{", "{"); // At this point, we need to parse the raw name for inline constraint, // default values and optional parameters. var templatePart = InlineRouteParameterParser.ParseRouteParameter(decoded); if (templatePart.IsCatchAll && templatePart.IsOptional) { context.Error = Resources.TemplateRoute_CatchAllCannotBeOptional; return false; } if (templatePart.IsOptional && templatePart.DefaultValue != null) { // Cannot be optional and have a default value. // The only way to declare an optional parameter is to have a ? at the end, // hence we cannot have both default value and optional parameter within the template. // A workaround is to add it as a separate entry in the defaults argument. context.Error = Resources.TemplateRoute_OptionalCannotHaveDefaultValue; return false; } var parameterName = templatePart.Name; if (IsValidParameterName(context, parameterName)) { segment.Parts.Add(templatePart); return true; } else { return false; } }
private static bool ParseSegment(TemplateParserContext context, List <TemplateSegment> segments) { Debug.Assert(context != null); Debug.Assert(segments != null); var segment = new TemplateSegment(); while (true) { if (context.Current == OpenBrace) { if (!context.Next()) { // This is a dangling open-brace, which is not allowed context.Error = Resources.TemplateRoute_MismatchedParameter; return(false); } if (context.Current == OpenBrace) { // This is an 'escaped' brace in a literal, like "{{foo" context.Back(); if (!ParseLiteral(context, segment)) { return(false); } } else { // This is the inside of a parameter if (!ParseParameter(context, segment)) { return(false); } } } else if (context.Current == Separator) { // We've reached the end of the segment break; } else { if (!ParseLiteral(context, segment)) { return(false); } } if (!context.Next()) { // We've reached the end of the string break; } } if (IsSegmentValid(context, segment)) { segments.Add(segment); return(true); } else { return(false); } }
private static bool ParseLiteral(TemplateParserContext context, TemplateSegment segment) { context.Mark(); string encoded; while (true) { if (context.Current == Separator) { encoded = context.Capture(); context.Back(); break; } else if (context.Current == OpenBrace) { if (!context.Next()) { // This is a dangling open-brace, which is not allowed context.Error = Resources.TemplateRoute_MismatchedParameter; return(false); } if (context.Current == OpenBrace) { // This is an 'escaped' brace in a literal, like "{{foo" - keep going. } else { // We've just seen the start of a parameter, so back up and return context.Back(); encoded = context.Capture(); context.Back(); break; } } else if (context.Current == CloseBrace) { if (!context.Next()) { // This is a dangling close-brace, which is not allowed context.Error = Resources.TemplateRoute_MismatchedParameter; return(false); } if (context.Current == CloseBrace) { // This is an 'escaped' brace in a literal, like "{{foo" - keep going. } else { // This is an unbalanced close-brace, which is not allowed context.Error = Resources.TemplateRoute_MismatchedParameter; return(false); } } if (!context.Next()) { encoded = context.Capture(); break; } } var decoded = encoded.Replace("}}", "}").Replace("{{", "}"); if (IsValidLiteral(context, decoded)) { segment.Parts.Add(TemplatePart.CreateLiteral(decoded)); return(true); } else { return(false); } }
private static bool ParseParameter(TemplateParserContext context, TemplateSegment segment) { context.Mark(); while (true) { if (context.Current == Separator) { // This is a dangling open-brace, which is not allowed context.Error = Resources.TemplateRoute_MismatchedParameter; return(false); } else if (context.Current == OpenBrace) { // If we see a '{' while parsing a parameter name it's invalid. We'll just accept it for now // and let the validation code for the name find it. } else if (context.Current == CloseBrace) { if (!context.Next()) { // This is the end of the string - and we have a valid parameter context.Back(); break; } if (context.Current == CloseBrace) { // This is an 'escaped' brace in a parameter name, which is not allowed. // We'll just accept it for now and let the validation code for the name find it. } else { // This is the end of the parameter context.Back(); break; } } if (!context.Next()) { // This is a dangling open-brace, which is not allowed context.Error = Resources.TemplateRoute_MismatchedParameter; return(false); } } var rawParameter = context.Capture(); // At this point, we need to parse the raw name for inline constraint, // default values and optional parameters. var templatePart = InlineRouteParameterParser.ParseRouteParameter(rawParameter); if (templatePart.IsCatchAll && templatePart.IsOptional) { context.Error = Resources.TemplateRoute_CatchAllCannotBeOptional; return(false); } if (templatePart.IsOptional && templatePart.DefaultValue != null) { // Cannot be optional and have a default value. // The only way to declare an optional parameter is to have a ? at the end, // hence we cannot have both default value and optional parameter within the template. // A workaround is to add it as a separate entry in the defaults argument. context.Error = Resources.TemplateRoute_OptionalCannotHaveDefaultValue; return(false); } var parameterName = templatePart.Name; if (IsValidParameterName(context, parameterName)) { segment.Parts.Add(templatePart); return(true); } else { return(false); } }
private static bool ParseParameter(TemplateParserContext context, TemplateSegment segment) { context.Mark(); while (true) { if (context.Current == OpenBrace) { // This is an open brace inside of a parameter, it has to be escaped if (context.Next()) { if (context.Current != OpenBrace) { // If we see something like "{p1:regex(^\d{3", we will come here. context.Error = Resources.TemplateRoute_UnescapedBrace; return(false); } } else { // This is a dangling open-brace, which is not allowed // Example: "{p1:regex(^\d{" context.Error = Resources.TemplateRoute_MismatchedParameter; return(false); } } else if (context.Current == CloseBrace) { // When we encounter Closed brace here, it either means end of the parameter or it is a closed // brace in the parameter, in that case it needs to be escaped. // Example: {p1:regex(([}}])\w+}. First pair is escaped one and last marks end of the parameter if (!context.Next()) { // This is the end of the string -and we have a valid parameter context.Back(); break; } if (context.Current == CloseBrace) { // This is an 'escaped' brace in a parameter name } else { // This is the end of the parameter context.Back(); break; } } if (!context.Next()) { // This is a dangling open-brace, which is not allowed context.Error = Resources.TemplateRoute_MismatchedParameter; return(false); } } var rawParameter = context.Capture(); var decoded = rawParameter.Replace("}}", "}").Replace("{{", "{"); // At this point, we need to parse the raw name for inline constraint, // default values and optional parameters. var templatePart = InlineRouteParameterParser.ParseRouteParameter(decoded); if (templatePart.IsCatchAll && templatePart.IsOptional) { context.Error = Resources.TemplateRoute_CatchAllCannotBeOptional; return(false); } if (templatePart.IsOptional && templatePart.DefaultValue != null) { // Cannot be optional and have a default value. // The only way to declare an optional parameter is to have a ? at the end, // hence we cannot have both default value and optional parameter within the template. // A workaround is to add it as a separate entry in the defaults argument. context.Error = Resources.TemplateRoute_OptionalCannotHaveDefaultValue; return(false); } var parameterName = templatePart.Name; if (IsValidParameterName(context, parameterName)) { segment.Parts.Add(templatePart); return(true); } else { return(false); } }