private static SelectionCriterion _ParseCriterion(String s) { if (s == null) { return(null); } // shorthand for filename glob if (s.IndexOf(" ") == -1) { s = "name = " + s; } // inject spaces after open paren and before close paren string[] prPairs = { @"\((\S)", "( $1", @"(\S)\)", "$1 )", }; for (int i = 0; i + 1 < prPairs.Length; i += 2) { Regex rgx = new Regex(prPairs[i]); s = rgx.Replace(s, prPairs[i + 1]); } // split the expression into tokens string[] tokens = s.Trim().Split(' ', '\t'); if (tokens.Length < 3) { throw new ArgumentException(s); } SelectionCriterion current = null; LogicalConjunction pendingConjunction = LogicalConjunction.NONE; ParseState state; var stateStack = new System.Collections.Generic.Stack <ParseState>(); var critStack = new System.Collections.Generic.Stack <SelectionCriterion>(); stateStack.Push(ParseState.Start); for (int i = 0; i < tokens.Length; i++) { switch (tokens[i].ToLower()) { case "and": case "xor": case "or": state = stateStack.Peek(); if (state != ParseState.CriterionDone) { throw new ArgumentException(String.Join(" ", tokens, i, tokens.Length - i)); } if (tokens.Length <= i + 3) { throw new ArgumentException(String.Join(" ", tokens, i, tokens.Length - i)); } pendingConjunction = (LogicalConjunction)Enum.Parse(typeof(LogicalConjunction), tokens[i].ToUpper()); current = new CompoundCriterion { Left = current, Right = null, Conjunction = pendingConjunction }; stateStack.Push(state); stateStack.Push(ParseState.ConjunctionPending); critStack.Push(current); break; case "(": state = stateStack.Peek(); if (state != ParseState.Start && state != ParseState.ConjunctionPending && state != ParseState.OpenParen) { throw new ArgumentException(String.Join(" ", tokens, i, tokens.Length - i)); } if (tokens.Length <= i + 4) { throw new ArgumentException(String.Join(" ", tokens, i, tokens.Length - i)); } stateStack.Push(ParseState.OpenParen); break; case ")": state = stateStack.Pop(); if (stateStack.Peek() != ParseState.OpenParen) { throw new ArgumentException(String.Join(" ", tokens, i, tokens.Length - i)); } stateStack.Pop(); stateStack.Push(ParseState.CriterionDone); break; case "atime": case "ctime": case "mtime": if (tokens.Length <= i + 2) { throw new ArgumentException(String.Join(" ", tokens, i, tokens.Length - i)); } DateTime t; try { t = DateTime.ParseExact(tokens[i + 2], "yyyy-MM-dd-HH:mm:ss", null); } catch (FormatException) { t = DateTime.ParseExact(tokens[i + 2], "yyyy-MM-dd", null); } t = DateTime.SpecifyKind(t, DateTimeKind.Local).ToUniversalTime(); current = new TimeCriterion { Which = (WhichTime)Enum.Parse(typeof(WhichTime), tokens[i]), Operator = (ComparisonOperator)EnumUtil.Parse(typeof(ComparisonOperator), tokens[i + 1]), Time = t }; i += 2; stateStack.Push(ParseState.CriterionDone); break; case "length": case "size": if (tokens.Length <= i + 2) { throw new ArgumentException(String.Join(" ", tokens, i, tokens.Length - i)); } Int64 sz = 0; string v = tokens[i + 2]; if (v.ToUpper().EndsWith("K")) { sz = Int64.Parse(v.Substring(0, v.Length - 1)) * 1024; } else if (v.ToUpper().EndsWith("KB")) { sz = Int64.Parse(v.Substring(0, v.Length - 2)) * 1024; } else if (v.ToUpper().EndsWith("M")) { sz = Int64.Parse(v.Substring(0, v.Length - 1)) * 1024 * 1024; } else if (v.ToUpper().EndsWith("MB")) { sz = Int64.Parse(v.Substring(0, v.Length - 2)) * 1024 * 1024; } else if (v.ToUpper().EndsWith("G")) { sz = Int64.Parse(v.Substring(0, v.Length - 1)) * 1024 * 1024 * 1024; } else if (v.ToUpper().EndsWith("GB")) { sz = Int64.Parse(v.Substring(0, v.Length - 2)) * 1024 * 1024 * 1024; } else { sz = Int64.Parse(tokens[i + 2]); } current = new SizeCriterion { Size = sz, Operator = (ComparisonOperator)EnumUtil.Parse(typeof(ComparisonOperator), tokens[i + 1]) }; i += 2; stateStack.Push(ParseState.CriterionDone); break; case "filename": case "name": { if (tokens.Length <= i + 2) { throw new ArgumentException(String.Join(" ", tokens, i, tokens.Length - i)); } ComparisonOperator c = (ComparisonOperator)EnumUtil.Parse(typeof(ComparisonOperator), tokens[i + 1]); if (c != ComparisonOperator.NotEqualTo && c != ComparisonOperator.EqualTo) { throw new ArgumentException(String.Join(" ", tokens, i, tokens.Length - i)); } string m = tokens[i + 2]; // handle single-quoted filespecs (used to include spaces in filename patterns) if (m.StartsWith("'")) { int ix = i; if (!m.EndsWith("'")) { do { i++; if (tokens.Length <= i + 2) { throw new ArgumentException(String.Join(" ", tokens, ix, tokens.Length - ix)); } m += " " + tokens[i + 2]; } while (!tokens[i + 2].EndsWith("'")); } // trim off leading and trailing single quotes m = m.Substring(1, m.Length - 2); } current = new NameCriterion { MatchingFileSpec = m, Operator = c }; i += 2; stateStack.Push(ParseState.CriterionDone); } break; case "attributes": { if (tokens.Length <= i + 2) { throw new ArgumentException(String.Join(" ", tokens, i, tokens.Length - i)); } ComparisonOperator c = (ComparisonOperator)EnumUtil.Parse(typeof(ComparisonOperator), tokens[i + 1]); if (c != ComparisonOperator.NotEqualTo && c != ComparisonOperator.EqualTo) { throw new ArgumentException(String.Join(" ", tokens, i, tokens.Length - i)); } current = new AttributesCriterion { AttributeString = tokens[i + 2], Operator = c }; i += 2; stateStack.Push(ParseState.CriterionDone); } break; case "": // NOP stateStack.Push(ParseState.Whitespace); break; default: throw new ArgumentException("'" + tokens[i] + "'"); } state = stateStack.Peek(); if (state == ParseState.CriterionDone) { stateStack.Pop(); if (stateStack.Peek() == ParseState.ConjunctionPending) { while (stateStack.Peek() == ParseState.ConjunctionPending) { var cc = critStack.Pop() as CompoundCriterion; cc.Right = current; current = cc; // mark the parent as current (walk up the tree) stateStack.Pop(); // the conjunction is no longer pending state = stateStack.Pop(); if (state != ParseState.CriterionDone) { throw new ArgumentException("??"); } } } else { stateStack.Push(ParseState.CriterionDone); // not sure? } } if (state == ParseState.Whitespace) { stateStack.Pop(); } } return(current); }
private static SelectionCriterion _ParseCriterion(String s) { if (s == null) { return(null); } // inject spaces after open paren and before close paren, etc s = NormalizeCriteriaExpression(s); // no spaces in the criteria is shorthand for filename glob if (s.IndexOf(" ") == -1) { s = "name = " + s; } // split the expression into tokens string[] tokens = s.Trim().Split(' ', '\t'); if (tokens.Length < 3) { throw new ArgumentException(s); } SelectionCriterion current = null; LogicalConjunction pendingConjunction = LogicalConjunction.NONE; ParseState state; var stateStack = new System.Collections.Generic.Stack <ParseState>(); var critStack = new System.Collections.Generic.Stack <SelectionCriterion>(); stateStack.Push(ParseState.Start); for (int i = 0; i < tokens.Length; i++) { string tok1 = tokens[i].ToLower(); switch (tok1) { case "and": case "xor": case "or": state = stateStack.Peek(); if (state != ParseState.CriterionDone) { throw new ArgumentException(String.Join(" ", tokens, i, tokens.Length - i)); } if (tokens.Length <= i + 3) { throw new ArgumentException(String.Join(" ", tokens, i, tokens.Length - i)); } pendingConjunction = (LogicalConjunction)Enum.Parse(typeof(LogicalConjunction), tokens[i].ToUpper(), true); current = new CompoundCriterion { Left = current, Right = null, Conjunction = pendingConjunction }; stateStack.Push(state); stateStack.Push(ParseState.ConjunctionPending); critStack.Push(current); break; case "(": state = stateStack.Peek(); if (state != ParseState.Start && state != ParseState.ConjunctionPending && state != ParseState.OpenParen) { throw new ArgumentException(String.Join(" ", tokens, i, tokens.Length - i)); } if (tokens.Length <= i + 4) { throw new ArgumentException(String.Join(" ", tokens, i, tokens.Length - i)); } stateStack.Push(ParseState.OpenParen); break; case ")": state = stateStack.Pop(); if (stateStack.Peek() != ParseState.OpenParen) { throw new ArgumentException(String.Join(" ", tokens, i, tokens.Length - i)); } stateStack.Pop(); stateStack.Push(ParseState.CriterionDone); break; case "atime": case "ctime": case "mtime": if (tokens.Length <= i + 2) { throw new ArgumentException(String.Join(" ", tokens, i, tokens.Length - i)); } DateTime t; try { t = DateTime.ParseExact(tokens[i + 2], "yyyy-MM-dd-HH:mm:ss", null); } catch (FormatException) { try { t = DateTime.ParseExact(tokens[i + 2], "yyyy/MM/dd-HH:mm:ss", null); } catch (FormatException) { try { t = DateTime.ParseExact(tokens[i + 2], "yyyy/MM/dd", null); } catch (FormatException) { try { t = DateTime.ParseExact(tokens[i + 2], "MM/dd/yyyy", null); } catch (FormatException) { t = DateTime.ParseExact(tokens[i + 2], "yyyy-MM-dd", null); } } } } t = DateTime.SpecifyKind(t, DateTimeKind.Local).ToUniversalTime(); current = new TimeCriterion { Which = (WhichTime)Enum.Parse(typeof(WhichTime), tokens[i], true), Operator = (ComparisonOperator)EnumUtil.Parse(typeof(ComparisonOperator), tokens[i + 1]), Time = t }; i += 2; stateStack.Push(ParseState.CriterionDone); break; case "length": case "size": if (tokens.Length <= i + 2) { throw new ArgumentException(String.Join(" ", tokens, i, tokens.Length - i)); } Int64 sz = 0; string v = tokens[i + 2]; if (v.ToUpper().EndsWith("K")) { sz = Int64.Parse(v.Substring(0, v.Length - 1)) * 1024; } else if (v.ToUpper().EndsWith("KB")) { sz = Int64.Parse(v.Substring(0, v.Length - 2)) * 1024; } else if (v.ToUpper().EndsWith("M")) { sz = Int64.Parse(v.Substring(0, v.Length - 1)) * 1024 * 1024; } else if (v.ToUpper().EndsWith("MB")) { sz = Int64.Parse(v.Substring(0, v.Length - 2)) * 1024 * 1024; } else if (v.ToUpper().EndsWith("G")) { sz = Int64.Parse(v.Substring(0, v.Length - 1)) * 1024 * 1024 * 1024; } else if (v.ToUpper().EndsWith("GB")) { sz = Int64.Parse(v.Substring(0, v.Length - 2)) * 1024 * 1024 * 1024; } else { sz = Int64.Parse(tokens[i + 2]); } current = new SizeCriterion { Size = sz, Operator = (ComparisonOperator)EnumUtil.Parse(typeof(ComparisonOperator), tokens[i + 1]) }; i += 2; stateStack.Push(ParseState.CriterionDone); break; case "filename": case "name": { if (tokens.Length <= i + 2) { throw new ArgumentException(String.Join(" ", tokens, i, tokens.Length - i)); } ComparisonOperator c = (ComparisonOperator)EnumUtil.Parse(typeof(ComparisonOperator), tokens[i + 1]); if (c != ComparisonOperator.NotEqualTo && c != ComparisonOperator.EqualTo) { throw new ArgumentException(String.Join(" ", tokens, i, tokens.Length - i)); } string m = tokens[i + 2]; // handle single-quoted filespecs (used to include // spaces in filename patterns) if (m.StartsWith("'") && m.EndsWith("'")) { // trim off leading and trailing single quotes and // revert the control characters to spaces. m = m.Substring(1, m.Length - 2) .Replace("\u0006", " "); } // if (m.StartsWith("'")) // m = m.Replace("\u0006", " "); //Fix for Unix -> NormalizeCriteriaExpression replaces all slashes with backslashes if (Path.DirectorySeparatorChar == '/') { m = m.Replace('\\', Path.DirectorySeparatorChar); } current = new NameCriterion { MatchingFileSpec = m, Operator = c }; i += 2; stateStack.Push(ParseState.CriterionDone); } break; case "attrs": case "attributes": case "type": { if (tokens.Length <= i + 2) { throw new ArgumentException(String.Join(" ", tokens, i, tokens.Length - i)); } ComparisonOperator c = (ComparisonOperator)EnumUtil.Parse(typeof(ComparisonOperator), tokens[i + 1]); if (c != ComparisonOperator.NotEqualTo && c != ComparisonOperator.EqualTo) { throw new ArgumentException(String.Join(" ", tokens, i, tokens.Length - i)); } current = (tok1 == "type") ? (SelectionCriterion) new TypeCriterion { AttributeString = tokens[i + 2], Operator = c } : (SelectionCriterion) new AttributesCriterion { AttributeString = tokens[i + 2], Operator = c }; i += 2; stateStack.Push(ParseState.CriterionDone); } break; case "": // NOP stateStack.Push(ParseState.Whitespace); break; default: throw new ArgumentException("'" + tokens[i] + "'"); } state = stateStack.Peek(); if (state == ParseState.CriterionDone) { stateStack.Pop(); if (stateStack.Peek() == ParseState.ConjunctionPending) { while (stateStack.Peek() == ParseState.ConjunctionPending) { var cc = critStack.Pop() as CompoundCriterion; cc.Right = current; current = cc; // mark the parent as current (walk up the tree) stateStack.Pop(); // the conjunction is no longer pending state = stateStack.Pop(); if (state != ParseState.CriterionDone) { throw new ArgumentException("??"); } } } else { stateStack.Push(ParseState.CriterionDone); // not sure? } } if (state == ParseState.Whitespace) { stateStack.Pop(); } } return(current); }
private static SelectionCriterion _ParseCriterion(string s) { if (s == null) { return(null); } s = NormalizeCriteriaExpression(s); if (s.IndexOf(" ") == -1) { s = "name = " + s; } string[] array = s.Trim().Split(' ', '\t'); if (array.Length < 3) { throw new ArgumentException(s); } SelectionCriterion selectionCriterion = null; LogicalConjunction logicalConjunction = LogicalConjunction.NONE; Stack <ParseState> stack = new Stack <ParseState>(); Stack <SelectionCriterion> stack2 = new Stack <SelectionCriterion>(); stack.Push(ParseState.Start); for (int i = 0; i < array.Length; i++) { string text = array[i].ToLower(); ParseState parseState; switch (text) { case "and": case "xor": case "or": { parseState = stack.Peek(); if (parseState != ParseState.CriterionDone) { throw new ArgumentException(string.Join(" ", array, i, array.Length - i)); } if (array.Length <= i + 3) { throw new ArgumentException(string.Join(" ", array, i, array.Length - i)); } logicalConjunction = (LogicalConjunction)Enum.Parse(typeof(LogicalConjunction), array[i].ToUpper(), ignoreCase: true); CompoundCriterion compoundCriterion = new CompoundCriterion(); compoundCriterion.Left = selectionCriterion; compoundCriterion.Right = null; compoundCriterion.Conjunction = logicalConjunction; selectionCriterion = compoundCriterion; stack.Push(parseState); stack.Push(ParseState.ConjunctionPending); stack2.Push(selectionCriterion); break; } case "(": parseState = stack.Peek(); if (parseState != 0 && parseState != ParseState.ConjunctionPending && parseState != ParseState.OpenParen) { throw new ArgumentException(string.Join(" ", array, i, array.Length - i)); } if (array.Length <= i + 4) { throw new ArgumentException(string.Join(" ", array, i, array.Length - i)); } stack.Push(ParseState.OpenParen); break; case ")": parseState = stack.Pop(); if (stack.Peek() != ParseState.OpenParen) { throw new ArgumentException(string.Join(" ", array, i, array.Length - i)); } stack.Pop(); stack.Push(ParseState.CriterionDone); break; case "atime": case "ctime": case "mtime": { if (array.Length <= i + 2) { throw new ArgumentException(string.Join(" ", array, i, array.Length - i)); } DateTime value; try { value = DateTime.ParseExact(array[i + 2], "yyyy-MM-dd-HH:mm:ss", null); } catch (FormatException) { try { value = DateTime.ParseExact(array[i + 2], "yyyy/MM/dd-HH:mm:ss", null); } catch (FormatException) { try { value = DateTime.ParseExact(array[i + 2], "yyyy/MM/dd", null); } catch (FormatException) { try { value = DateTime.ParseExact(array[i + 2], "MM/dd/yyyy", null); } catch (FormatException) { value = DateTime.ParseExact(array[i + 2], "yyyy-MM-dd", null); } } } } value = DateTime.SpecifyKind(value, DateTimeKind.Local).ToUniversalTime(); TimeCriterion timeCriterion = new TimeCriterion(); timeCriterion.Which = (WhichTime)Enum.Parse(typeof(WhichTime), array[i], ignoreCase: true); timeCriterion.Operator = (ComparisonOperator)EnumUtil.Parse(typeof(ComparisonOperator), array[i + 1]); timeCriterion.Time = value; selectionCriterion = timeCriterion; i += 2; stack.Push(ParseState.CriterionDone); break; } case "length": case "size": { if (array.Length <= i + 2) { throw new ArgumentException(string.Join(" ", array, i, array.Length - i)); } long num = 0L; string text2 = array[i + 2]; num = (text2.ToUpper().EndsWith("K") ? (long.Parse(text2.Substring(0, text2.Length - 1)) * 1024) : (text2.ToUpper().EndsWith("KB") ? (long.Parse(text2.Substring(0, text2.Length - 2)) * 1024) : (text2.ToUpper().EndsWith("M") ? (long.Parse(text2.Substring(0, text2.Length - 1)) * 1024 * 1024) : (text2.ToUpper().EndsWith("MB") ? (long.Parse(text2.Substring(0, text2.Length - 2)) * 1024 * 1024) : (text2.ToUpper().EndsWith("G") ? (long.Parse(text2.Substring(0, text2.Length - 1)) * 1024 * 1024 * 1024) : ((!text2.ToUpper().EndsWith("GB")) ? long.Parse(array[i + 2]) : (long.Parse(text2.Substring(0, text2.Length - 2)) * 1024 * 1024 * 1024))))))); SizeCriterion sizeCriterion = new SizeCriterion(); sizeCriterion.Size = num; sizeCriterion.Operator = (ComparisonOperator)EnumUtil.Parse(typeof(ComparisonOperator), array[i + 1]); selectionCriterion = sizeCriterion; i += 2; stack.Push(ParseState.CriterionDone); break; } case "filename": case "name": { if (array.Length <= i + 2) { throw new ArgumentException(string.Join(" ", array, i, array.Length - i)); } ComparisonOperator comparisonOperator2 = (ComparisonOperator)EnumUtil.Parse(typeof(ComparisonOperator), array[i + 1]); if (comparisonOperator2 != ComparisonOperator.NotEqualTo && comparisonOperator2 != ComparisonOperator.EqualTo) { throw new ArgumentException(string.Join(" ", array, i, array.Length - i)); } string text3 = array[i + 2]; if (text3.StartsWith("'") && text3.EndsWith("'")) { text3 = text3.Substring(1, text3.Length - 2).Replace("\u0006", " "); } NameCriterion nameCriterion = new NameCriterion(); nameCriterion.MatchingFileSpec = text3; nameCriterion.Operator = comparisonOperator2; selectionCriterion = nameCriterion; i += 2; stack.Push(ParseState.CriterionDone); break; } case "attrs": case "attributes": case "type": { if (array.Length <= i + 2) { throw new ArgumentException(string.Join(" ", array, i, array.Length - i)); } ComparisonOperator comparisonOperator = (ComparisonOperator)EnumUtil.Parse(typeof(ComparisonOperator), array[i + 1]); if (comparisonOperator != ComparisonOperator.NotEqualTo && comparisonOperator != ComparisonOperator.EqualTo) { throw new ArgumentException(string.Join(" ", array, i, array.Length - i)); } object obj; if (!(text == "type")) { AttributesCriterion attributesCriterion = new AttributesCriterion(); attributesCriterion.AttributeString = array[i + 2]; attributesCriterion.Operator = comparisonOperator; obj = attributesCriterion; } else { TypeCriterion typeCriterion = new TypeCriterion(); typeCriterion.AttributeString = array[i + 2]; typeCriterion.Operator = comparisonOperator; obj = typeCriterion; } selectionCriterion = (SelectionCriterion)obj; i += 2; stack.Push(ParseState.CriterionDone); break; } case "": stack.Push(ParseState.Whitespace); break; default: throw new ArgumentException("'" + array[i] + "'"); } parseState = stack.Peek(); if (parseState == ParseState.CriterionDone) { stack.Pop(); if (stack.Peek() == ParseState.ConjunctionPending) { while (stack.Peek() == ParseState.ConjunctionPending) { CompoundCriterion compoundCriterion2 = stack2.Pop() as CompoundCriterion; compoundCriterion2.Right = selectionCriterion; selectionCriterion = compoundCriterion2; stack.Pop(); parseState = stack.Pop(); if (parseState != ParseState.CriterionDone) { throw new ArgumentException("??"); } } } else { stack.Push(ParseState.CriterionDone); } } if (parseState == ParseState.Whitespace) { stack.Pop(); } } return(selectionCriterion); }
private static SelectionCriterion _ParseCriterion(String s) { if (s == null) return null; // inject spaces after open paren and before close paren string[][] prPairs = { new string[] { @"\(\(", "( (" }, new string[] { @"\)\)", ") )" }, new string[] { @"\((\S)", "( $1" }, new string[] { @"(\S)\)", "$1 )" }, new string[] { @"(\S)\(", "$1 (" }, new string[] { @"\)(\S)", ") $1" }, new string[] { @"([^ ]+)>([^ ]+)", "$1 > $2" }, new string[] { @"([^ ]+)<([^ ]+)", "$1 < $2" }, new string[] { @"([^ ]+)!=([^ ]+)", "$1 != $2" }, new string[] { @"([^ ]+)=([^ ]+)", "$1 = $2" }, }; for (int i = 0; i < prPairs.Length; i++) { Regex rgx = new Regex(prPairs[i][0]); s = rgx.Replace(s, prPairs[i][1]); } // shorthand for filename glob if (s.IndexOf(" ") == -1) s = "name = " + s; // split the expression into tokens string[] tokens = s.Trim().Split(' ', '\t'); if (tokens.Length < 3) throw new ArgumentException(s); SelectionCriterion current = null; LogicalConjunction pendingConjunction = LogicalConjunction.NONE; ParseState state; var stateStack = new System.Collections.Generic.Stack<ParseState>(); var critStack = new System.Collections.Generic.Stack<SelectionCriterion>(); stateStack.Push(ParseState.Start); for (int i = 0; i < tokens.Length; i++) { string tok1 = tokens[i].ToLower(); switch (tok1) { case "and": case "xor": case "or": state = stateStack.Peek(); if (state != ParseState.CriterionDone) throw new ArgumentException(String.Join(" ", tokens, i, tokens.Length - i)); if (tokens.Length <= i + 3) throw new ArgumentException(String.Join(" ", tokens, i, tokens.Length - i)); pendingConjunction = (LogicalConjunction)Enum.Parse(typeof(LogicalConjunction), tokens[i].ToUpper(), true); current = new CompoundCriterion { Left = current, Right = null, Conjunction = pendingConjunction }; stateStack.Push(state); stateStack.Push(ParseState.ConjunctionPending); critStack.Push(current); break; case "(": state = stateStack.Peek(); if (state != ParseState.Start && state != ParseState.ConjunctionPending && state != ParseState.OpenParen) throw new ArgumentException(String.Join(" ", tokens, i, tokens.Length - i)); if (tokens.Length <= i + 4) throw new ArgumentException(String.Join(" ", tokens, i, tokens.Length - i)); stateStack.Push(ParseState.OpenParen); break; case ")": state = stateStack.Pop(); if (stateStack.Peek() != ParseState.OpenParen) throw new ArgumentException(String.Join(" ", tokens, i, tokens.Length - i)); stateStack.Pop(); stateStack.Push(ParseState.CriterionDone); break; case "atime": case "ctime": case "mtime": if (tokens.Length <= i + 2) throw new ArgumentException(String.Join(" ", tokens, i, tokens.Length - i)); DateTime t; try { t = DateTime.ParseExact(tokens[i + 2], "yyyy-MM-dd-HH:mm:ss", null); } catch (FormatException) { try { t = DateTime.ParseExact(tokens[i + 2], "yyyy/MM/dd-HH:mm:ss", null); } catch (FormatException) { try { t = DateTime.ParseExact(tokens[i + 2], "yyyy/MM/dd", null); } catch (FormatException) { try { t = DateTime.ParseExact(tokens[i + 2], "MM/dd/yyyy", null); } catch (FormatException) { t = DateTime.ParseExact(tokens[i + 2], "yyyy-MM-dd", null); } } } } t= DateTime.SpecifyKind(t, DateTimeKind.Local).ToUniversalTime(); current = new TimeCriterion { Which = (WhichTime)Enum.Parse(typeof(WhichTime), tokens[i], true), Operator = (ComparisonOperator)EnumUtil.Parse(typeof(ComparisonOperator), tokens[i + 1]), Time = t }; i += 2; stateStack.Push(ParseState.CriterionDone); break; case "length": case "size": if (tokens.Length <= i + 2) throw new ArgumentException(String.Join(" ", tokens, i, tokens.Length - i)); Int64 sz = 0; string v = tokens[i + 2]; if (v.ToUpper().EndsWith("K")) sz = Int64.Parse(v.Substring(0, v.Length - 1)) * 1024; else if (v.ToUpper().EndsWith("KB")) sz = Int64.Parse(v.Substring(0, v.Length - 2)) * 1024; else if (v.ToUpper().EndsWith("M")) sz = Int64.Parse(v.Substring(0, v.Length - 1)) * 1024 * 1024; else if (v.ToUpper().EndsWith("MB")) sz = Int64.Parse(v.Substring(0, v.Length - 2)) * 1024 * 1024; else if (v.ToUpper().EndsWith("G")) sz = Int64.Parse(v.Substring(0, v.Length - 1)) * 1024 * 1024 * 1024; else if (v.ToUpper().EndsWith("GB")) sz = Int64.Parse(v.Substring(0, v.Length - 2)) * 1024 * 1024 * 1024; else sz = Int64.Parse(tokens[i + 2]); current = new SizeCriterion { Size = sz, Operator = (ComparisonOperator)EnumUtil.Parse(typeof(ComparisonOperator), tokens[i + 1]) }; i += 2; stateStack.Push(ParseState.CriterionDone); break; case "filename": case "name": { if (tokens.Length <= i + 2) throw new ArgumentException(String.Join(" ", tokens, i, tokens.Length - i)); ComparisonOperator c = (ComparisonOperator)EnumUtil.Parse(typeof(ComparisonOperator), tokens[i + 1]); if (c != ComparisonOperator.NotEqualTo && c != ComparisonOperator.EqualTo) throw new ArgumentException(String.Join(" ", tokens, i, tokens.Length - i)); string m = tokens[i + 2]; // handle single-quoted filespecs (used to include spaces in filename patterns) if (m.StartsWith("'")) { int ix = i; if (!m.EndsWith("'")) { do { i++; if (tokens.Length <= i + 2) throw new ArgumentException(String.Join(" ", tokens, ix, tokens.Length - ix)); m += " " + tokens[i + 2]; } while (!tokens[i + 2].EndsWith("'")); } // trim off leading and trailing single quotes m = m.Substring(1, m.Length - 2); } current = new NameCriterion { MatchingFileSpec = m, Operator = c }; i += 2; stateStack.Push(ParseState.CriterionDone); } break; case "attrs": case "attributes": case "type": { if (tokens.Length <= i + 2) throw new ArgumentException(String.Join(" ", tokens, i, tokens.Length - i)); ComparisonOperator c = (ComparisonOperator)EnumUtil.Parse(typeof(ComparisonOperator), tokens[i + 1]); if (c != ComparisonOperator.NotEqualTo && c != ComparisonOperator.EqualTo) throw new ArgumentException(String.Join(" ", tokens, i, tokens.Length - i)); current = (tok1 == "type") ? (SelectionCriterion) new TypeCriterion { AttributeString = tokens[i + 2], Operator = c } : (SelectionCriterion) new AttributesCriterion { AttributeString = tokens[i + 2], Operator = c }; i += 2; stateStack.Push(ParseState.CriterionDone); } break; case "": // NOP stateStack.Push(ParseState.Whitespace); break; default: throw new ArgumentException("'" + tokens[i] + "'"); } state = stateStack.Peek(); if (state == ParseState.CriterionDone) { stateStack.Pop(); if (stateStack.Peek() == ParseState.ConjunctionPending) { while (stateStack.Peek() == ParseState.ConjunctionPending) { var cc = critStack.Pop() as CompoundCriterion; cc.Right = current; current = cc; // mark the parent as current (walk up the tree) stateStack.Pop(); // the conjunction is no longer pending state = stateStack.Pop(); if (state != ParseState.CriterionDone) throw new ArgumentException("??"); } } else stateStack.Push(ParseState.CriterionDone); // not sure? } if (state == ParseState.Whitespace) stateStack.Pop(); } return current; }