/// <summary> /// Expand globs in the given <code>filePattern</code> into a collection of /// file patterns so that in the expanded set no file pattern has a /// slash character ("/") in a curly bracket pair. /// </summary> /// <param name="filePattern"/> /// <returns>expanded file patterns</returns> /// <exception cref="System.IO.IOException"></exception> public static IList <string> Expand(string filePattern) { IList <string> fullyExpanded = new AList <string>(); IList <GlobExpander.StringWithOffset> toExpand = new AList <GlobExpander.StringWithOffset >(); toExpand.AddItem(new GlobExpander.StringWithOffset(filePattern, 0)); while (!toExpand.IsEmpty()) { GlobExpander.StringWithOffset path = toExpand.Remove(0); IList <GlobExpander.StringWithOffset> expanded = ExpandLeftmost(path); if (expanded == null) { fullyExpanded.AddItem(path.@string); } else { toExpand.AddRange(0, expanded); } } return(fullyExpanded); }
/// <summary> /// Expand the leftmost outer curly bracket pair containing a /// slash character ("/") in <code>filePattern</code>. /// </summary> /// <param name="filePattern"/> /// <returns>expanded file patterns</returns> /// <exception cref="System.IO.IOException"></exception> private static IList <GlobExpander.StringWithOffset> ExpandLeftmost(GlobExpander.StringWithOffset filePatternWithOffset) { string filePattern = filePatternWithOffset.@string; int leftmost = LeftmostOuterCurlyContainingSlash(filePattern, filePatternWithOffset .offset); if (leftmost == -1) { return(null); } int curlyOpen = 0; StringBuilder prefix = new StringBuilder(Runtime.Substring(filePattern, 0 , leftmost)); StringBuilder suffix = new StringBuilder(); IList <string> alts = new AList <string>(); StringBuilder alt = new StringBuilder(); StringBuilder cur = prefix; for (int i = leftmost; i < filePattern.Length; i++) { char c = filePattern[i]; if (cur == suffix) { cur.Append(c); } else { if (c == '\\') { i++; if (i >= filePattern.Length) { throw new IOException("Illegal file pattern: " + "An escaped character does not present for glob " + filePattern + " at " + i); } c = filePattern[i]; cur.Append(c); } else { if (c == '{') { if (curlyOpen++ == 0) { alt.Length = 0; cur = alt; } else { cur.Append(c); } } else { if (c == '}' && curlyOpen > 0) { if (--curlyOpen == 0) { alts.AddItem(alt.ToString()); alt.Length = 0; cur = suffix; } else { cur.Append(c); } } else { if (c == ',') { if (curlyOpen == 1) { alts.AddItem(alt.ToString()); alt.Length = 0; } else { cur.Append(c); } } else { cur.Append(c); } } } } } } IList <GlobExpander.StringWithOffset> exp = new AList <GlobExpander.StringWithOffset >(); foreach (string @string in alts) { exp.AddItem(new GlobExpander.StringWithOffset(prefix + @string + suffix, prefix.Length )); } return(exp); }