/// <summary> /// Parses a tag's contents into data. /// </summary> static public void Parse(StringSlice inSlice, IDelimiterRules inDelimiters, out TagData outTagData) { if (inDelimiters == null) { throw new ArgumentNullException("inDelimiters"); } StringSlice tag = inSlice; tag = tag.Trim(MinimalWhitespaceChars); bool bRemovedTagBoundaries = false; if (tag.StartsWith(inDelimiters.TagStartDelimiter)) { tag = tag.Substring(inDelimiters.TagStartDelimiter.Length); bRemovedTagBoundaries = true; } if (tag.EndsWith(inDelimiters.TagEndDelimiter)) { tag = tag.Substring(0, tag.Length - inDelimiters.TagEndDelimiter.Length); bRemovedTagBoundaries = true; } if (bRemovedTagBoundaries) { tag = tag.Trim(MinimalWhitespaceChars); } if (inSlice.Length == 0) { outTagData = default(TagData); return; } ClosingTagState closeState = 0; char endDelim = inDelimiters.RegionCloseDelimiter; if (endDelim != 0) { if (tag.StartsWith(endDelim)) { closeState |= ClosingTagState.Start; tag = tag.Substring(1); } if (tag.EndsWith(endDelim)) { closeState |= ClosingTagState.End; tag = tag.Substring(0, tag.Length - 1); } } if (closeState != 0) { tag = tag.Trim(MinimalWhitespaceChars); } char[] dataDelims = inDelimiters.TagDataDelimiters; int dataDelimIdx = tag.Length; foreach (var delim in dataDelims) { int idx = tag.IndexOf(delim); if (idx >= 0 && idx < dataDelimIdx) { dataDelimIdx = idx; if (idx <= 0) { break; } } } if (dataDelimIdx >= tag.Length) { outTagData.Id = tag; outTagData.Data = StringSlice.Empty; } else { outTagData.Id = tag.Substring(0, dataDelimIdx).TrimEnd(MinimalWhitespaceChars); outTagData.Data = tag.Substring(dataDelimIdx).TrimStart(dataDelims).TrimStart(MinimalWhitespaceChars); } outTagData.m_CloseState = closeState; }
/// <summary> /// Returns if the given string contains any text or rich text tags. /// </summary> static public bool ContainsText(StringSlice inString, IDelimiterRules inDelimiters, IEnumerable <string> inTextTags = null) { bool bTrackRichText = inDelimiters.RichText; bool bTrackTags = !bTrackRichText || !HasSameDelims(inDelimiters, RichTextDelimiters); int length = inString.Length; int charIdx = 0; int richStart = -1; int tagStart = -1; int copyStart = 0; while (charIdx < length) { if (bTrackRichText) { if (inString.AttemptMatch(charIdx, "<")) { richStart = charIdx; } else if (inString.AttemptMatch(charIdx, ">")) { return(true); } } if (bTrackTags) { if (inString.AttemptMatch(charIdx, inDelimiters.TagStartDelimiter)) { tagStart = charIdx; } else if (inString.AttemptMatch(charIdx, inDelimiters.TagEndDelimiter)) { StringSlice check = inString.Substring(copyStart, tagStart - copyStart); if (!check.IsWhitespace) { return(true); } if (inTextTags != null) { TagData data = TagData.Parse(inString.Substring(tagStart, charIdx - tagStart + 1), inDelimiters); foreach (var tag in inTextTags) { if (data.Id == tag) { return(true); } } } copyStart = charIdx + 1; tagStart = -1; richStart = -1; } } ++charIdx; } StringSlice finalCheck = inString.Substring(copyStart, length - copyStart); return(!finalCheck.IsWhitespace); }
internal bool Evaluate(TagData inData, object inContext, out TagEventData outEvent) { outEvent = new TagEventData(m_EventId); outEvent.IsClosing = inData.IsClosing(); switch (m_DataMode) { case DataMode.String: { if (inData.Data.IsEmpty) { outEvent.StringArgument = m_DefaultString; } else { outEvent.StringArgument = inData.Data; } break; } case DataMode.Float: { float arg; if (!StringParser.TryParseFloat(inData.Data, out arg)) { arg = m_DefaultValue.AsFloat(); } outEvent.Argument0 = arg; break; } case DataMode.Bool: { bool arg; if (!StringParser.TryParseBool(inData.Data, out arg)) { arg = m_DefaultValue.AsBool(); } outEvent.Argument0 = arg; break; } case DataMode.StringHash: { StringHash32 arg; if (!StringHash32.TryParse(inData.Data, out arg)) { arg = m_DefaultValue.AsStringHash(); } outEvent.Argument0 = arg; break; } } if (m_HandleClosing && outEvent.IsClosing) { outEvent.Type = m_EventClosingId; if (m_EventClosingDelegate != null) { m_EventClosingDelegate(inData, inContext, ref outEvent); } return(true); } else { if (m_EventDelegate != null) { m_EventDelegate(inData, inContext, ref outEvent); } return(true); } }
protected void ProcessInput(StringSlice inInput, TagString outTarget, object inContext, out bool outbModified) { bool bModified = false; bool bTrackRichText = m_Delimiters.RichText; bool bTrackTags = !bTrackRichText || !HasSameDelims(m_Delimiters, RichTextDelimiters); bool bIsCurlyBrace = HasSameDelims(m_Delimiters, CurlyBraceDelimiters); if (!bTrackRichText && m_EventProcessor == null && m_ReplaceProcessor == null) { // if we're not considering rich text, and we have no processors, there's nothing to do here outTarget.AddNode(TagNodeData.TextNode((uint)inInput.Length)); outbModified = false; return; } ParseState state = new ParseState(); state.Initialize(inInput, outTarget, inContext, m_RichBuilder, m_StrippedBuilder, m_SpliceBuilder); int length = state.Input.Length; int charIdx = 0; while (charIdx < length) { bool bHandled = false; if (bTrackRichText) { if (state.Input.AttemptMatch(charIdx, "<")) { state.RichStart = charIdx; } else if (state.RichStart >= 0 && state.Input.AttemptMatch(charIdx, ">")) { StringSlice richSlice = state.Input.Substring(state.RichStart + 1, charIdx - state.RichStart - 1); TagData richTag = TagData.Parse(richSlice, RichTextDelimiters); CopyNonRichText(ref state, state.RichStart); bool bRichHandled = false; if (RecognizeRichText(richTag, m_Delimiters)) { CopyRichTag(ref state, charIdx + 1); if (StringUtils.RichText.GeneratesVisibleCharacter(richTag.Id.ToString())) { CopyOnlyNonRichText(ref state, VisibleRichTagChar); } bRichHandled = true; } else if (!bTrackTags) { if (m_ReplaceProcessor != null) { string replace; if (m_ReplaceProcessor.TryReplace(richTag, richSlice, state.Context, out replace)) { if (ContainsPotentialTags(replace, m_Delimiters)) { RestartString(ref state, replace, charIdx + 1); charIdx = -1; length = state.Input.Length; } else { SkipText(ref state, charIdx + 1); AddNonRichText(ref state, replace); } bRichHandled = true; } } if (!bRichHandled && m_EventProcessor != null) { TagEventData eventData; if (m_EventProcessor.TryProcess(richTag, state.Context, out eventData)) { outTarget.AddEvent(eventData); SkipText(ref state, charIdx + 1); bRichHandled = true; } } } if (!bRichHandled) { Debug.LogWarningFormat("[TagStringParser] Unrecognized text tag '{0}' in source '{1}'", richSlice, inInput); CopyNonRichText(ref state, charIdx + 1); } else { bModified = true; } state.RichStart = -1; state.TagStart = -1; bHandled = true; } } if (!bHandled && bTrackTags) { if (state.Input.AttemptMatch(charIdx, m_Delimiters.TagStartDelimiter)) { state.TagStart = charIdx; } else if (state.TagStart >= 0 && state.Input.AttemptMatch(charIdx, m_Delimiters.TagEndDelimiter)) { StringSlice tagSlice = state.Input.Substring(state.TagStart + m_Delimiters.TagStartDelimiter.Length, charIdx - state.TagStart + 1 - m_Delimiters.TagEndDelimiter.Length - m_Delimiters.TagStartDelimiter.Length); TagData tag = TagData.Parse(tagSlice, m_Delimiters); CopyNonRichText(ref state, state.TagStart); bool bTagHandled = false; if (bIsCurlyBrace && tag.Data.IsEmpty) { int argIndex; if (StringParser.TryParseInt(tag.Id, out argIndex)) { CopyNonRichText(ref state, charIdx + 1); bTagHandled = true; } } if (!bTagHandled && m_ReplaceProcessor != null) { string replace; if (m_ReplaceProcessor.TryReplace(tag, tagSlice, state.Context, out replace)) { if (ContainsPotentialTags(replace, m_Delimiters)) { RestartString(ref state, replace, charIdx + 1); charIdx = -1; length = state.Input.Length; } else { SkipText(ref state, charIdx + 1); AddNonRichText(ref state, replace); } bTagHandled = true; } } if (!bTagHandled && m_EventProcessor != null) { TagEventData eventData; if (m_EventProcessor.TryProcess(tag, state.Context, out eventData)) { outTarget.AddEvent(eventData); SkipText(ref state, charIdx + 1); bTagHandled = true; } } if (!bTagHandled) { Debug.LogWarningFormat("[TagStringParser] Unrecognized text tag '{0}' in source '{1}'", tagSlice, inInput); CopyNonRichText(ref state, charIdx + 1); } else { bModified = true; } state.TagStart = -1; state.RichStart = -1; bHandled = true; } } if (!bHandled && state.TagStart == -1 && state.RichStart == -1 && m_ReplaceProcessor != null) { string charCodeReplace; if (m_ReplaceProcessor.TryReplace(state.Input[charIdx], inContext, out charCodeReplace)) { CopyNonRichText(ref state, charIdx); if (ContainsPotentialTags(charCodeReplace, m_Delimiters)) { RestartString(ref state, charCodeReplace, charIdx + 1); charIdx = -1; length = state.Input.Length; } else { SkipText(ref state, charIdx + 1); AddNonRichText(ref state, charCodeReplace); } } } ++charIdx; } CopyNonRichText(ref state, length); outbModified = bModified; }