/// <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); }
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; }