internal static string[] ParseMultipartIdentifier(string name, string leftQuote, string rightQuote, char separator, int limit, bool removequotes, string property, bool ThrowOnEmptyMultipartName) { if (limit <= 0) { throw ADP.InvalidMultipartNameToManyParts(property, name, limit); } if (((-1 != leftQuote.IndexOf(separator)) || (-1 != rightQuote.IndexOf(separator))) || (leftQuote.Length != rightQuote.Length)) { throw ADP.InvalidMultipartNameIncorrectUsageOfQuotes(property, name); } string[] ary = new string[limit]; int index = 0; MPIState state = MPIState.MPI_Value; StringBuilder builder = new StringBuilder(name.Length); StringBuilder builder2 = null; char ch2 = ' '; for (int i = 0; i < name.Length; i++) { int num5; char ch = name[i]; switch (state) { case MPIState.MPI_Value: { if (!IsWhitespace(ch)) { if (ch != separator) { break; } ary[index] = string.Empty; IncrementStringCount(name, ary, ref index, property); } continue; } case MPIState.MPI_ParseNonQuote: { if (ch != separator) { goto Label_0135; } ary[index] = builder.ToString(); IncrementStringCount(name, ary, ref index, property); state = MPIState.MPI_Value; continue; } case MPIState.MPI_LookForSeparator: { if (!IsWhitespace(ch)) { if (ch != separator) { throw ADP.InvalidMultipartNameIncorrectUsageOfQuotes(property, name); } IncrementStringCount(name, ary, ref index, property); state = MPIState.MPI_Value; } continue; } case MPIState.MPI_LookForNextCharOrSeparator: { if (IsWhitespace(ch)) { goto Label_01DD; } if (ch != separator) { goto Label_01BB; } IncrementStringCount(name, ary, ref index, property); state = MPIState.MPI_Value; continue; } case MPIState.MPI_ParseQuote: { if (ch != ch2) { goto Label_0203; } if (!removequotes) { builder.Append(ch); } state = MPIState.MPI_RightQuote; continue; } case MPIState.MPI_RightQuote: { if (ch != ch2) { goto Label_021E; } builder.Append(ch); state = MPIState.MPI_ParseQuote; continue; } default: { continue; } } if (-1 != (num5 = leftQuote.IndexOf(ch))) { ch2 = rightQuote[num5]; builder.Length = 0; if (!removequotes) { builder.Append(ch); } state = MPIState.MPI_ParseQuote; } else { if (-1 != rightQuote.IndexOf(ch)) { throw ADP.InvalidMultipartNameIncorrectUsageOfQuotes(property, name); } builder.Length = 0; builder.Append(ch); state = MPIState.MPI_ParseNonQuote; } continue; Label_0135: if (-1 != rightQuote.IndexOf(ch)) { throw ADP.InvalidMultipartNameIncorrectUsageOfQuotes(property, name); } if (-1 != leftQuote.IndexOf(ch)) { throw ADP.InvalidMultipartNameIncorrectUsageOfQuotes(property, name); } if (IsWhitespace(ch)) { ary[index] = builder.ToString(); if (builder2 == null) { builder2 = new StringBuilder(); } builder2.Length = 0; builder2.Append(ch); state = MPIState.MPI_LookForNextCharOrSeparator; } else { builder.Append(ch); } continue; Label_01BB: builder.Append(builder2); builder.Append(ch); ary[index] = builder.ToString(); state = MPIState.MPI_ParseNonQuote; continue; Label_01DD: builder2.Append(ch); continue; Label_0203: builder.Append(ch); continue; Label_021E: if (ch == separator) { ary[index] = builder.ToString(); IncrementStringCount(name, ary, ref index, property); state = MPIState.MPI_Value; } else { if (!IsWhitespace(ch)) { throw ADP.InvalidMultipartNameIncorrectUsageOfQuotes(property, name); } ary[index] = builder.ToString(); state = MPIState.MPI_LookForSeparator; } } switch (state) { case MPIState.MPI_Value: case MPIState.MPI_LookForSeparator: case MPIState.MPI_LookForNextCharOrSeparator: break; case MPIState.MPI_ParseNonQuote: case MPIState.MPI_RightQuote: ary[index] = builder.ToString(); break; default: throw ADP.InvalidMultipartNameIncorrectUsageOfQuotes(property, name); } if (ary[0] == null) { if (ThrowOnEmptyMultipartName) { throw ADP.InvalidMultipartName(property, name); } return(ary); } int num3 = (limit - index) - 1; if (num3 > 0) { for (int j = limit - 1; j >= num3; j--) { ary[j] = ary[j - num3]; ary[j - num3] = null; } } return(ary); }
internal static string[] ParseMultipartIdentifier(string name, string leftQuote, string rightQuote, char separator, int limit, bool removequotes, string property, bool ThrowOnEmptyMultipartName) { if (limit <= 0) { throw ADP.InvalidMultipartNameToManyParts(property, name, limit); } if (-1 != leftQuote.IndexOf(separator) || -1 != rightQuote.IndexOf(separator) || leftQuote.Length != rightQuote.Length) { throw ADP.InvalidMultipartNameIncorrectUsageOfQuotes(property, name); } string[] parsedNames = new string[limit]; // return string array int stringCount = 0; // index of current string in the buffer MPIState state = MPIState.MPI_Value; // Initalize the starting state StringBuilder sb = new StringBuilder(name.Length); // String buffer to hold the string being currently built, init the string builder so it will never be resized StringBuilder whitespaceSB = null; // String buffer to hold whitespace used when parsing nonquoted strings 'a b . c d' = 'a b' and 'c d' char rightQuoteChar = ' '; // Right quote character to use given the left quote character found. for (int index = 0; index < name.Length; ++index) { char testchar = name[index]; switch (state) { case MPIState.MPI_Value: { int quoteIndex; if (IsWhitespace(testchar)) { // Is White Space then skip the whitespace continue; } else if (testchar == separator) { // If we found a separator, no string was found, initalize the string we are parsing to Empty and the next one to Empty. // This is NOT a redundent setting of string.Empty it solves the case where we are parsing ".foo" and we should be returning null, null, empty, foo parsedNames[stringCount] = string.Empty; IncrementStringCount(name, parsedNames, ref stringCount, property); } else if (-1 != (quoteIndex = leftQuote.IndexOf(testchar))) { // If we are a left quote rightQuoteChar = rightQuote[quoteIndex]; // record the corresponding right quote for the left quote sb.Length = 0; if (!removequotes) { sb.Append(testchar); } state = MPIState.MPI_ParseQuote; } else if (-1 != rightQuote.IndexOf(testchar)) { // If we shouldn't see a right quote throw ADP.InvalidMultipartNameIncorrectUsageOfQuotes(property, name); } else { sb.Length = 0; sb.Append(testchar); state = MPIState.MPI_ParseNonQuote; } break; } case MPIState.MPI_ParseNonQuote: { if (testchar == separator) { parsedNames[stringCount] = sb.ToString(); // set the currently parsed string IncrementStringCount(name, parsedNames, ref stringCount, property); state = MPIState.MPI_Value; } else // Quotes are not valid inside a non-quoted name if (-1 != rightQuote.IndexOf(testchar)) { throw ADP.InvalidMultipartNameIncorrectUsageOfQuotes(property, name); } else if (-1 != leftQuote.IndexOf(testchar)) { throw ADP.InvalidMultipartNameIncorrectUsageOfQuotes(property, name); } else if (IsWhitespace(testchar)) { // If it is Whitespace parsedNames[stringCount] = sb.ToString(); // Set the currently parsed string if (null == whitespaceSB) { whitespaceSB = new StringBuilder(); } whitespaceSB.Length = 0; whitespaceSB.Append(testchar); // start to record the whitespace, if we are parsing a name like "foo bar" we should return "foo bar" state = MPIState.MPI_LookForNextCharOrSeparator; } else { sb.Append(testchar); } break; } case MPIState.MPI_LookForNextCharOrSeparator: { if (!IsWhitespace(testchar)) { // If it is not whitespace if (testchar == separator) { IncrementStringCount(name, parsedNames, ref stringCount, property); state = MPIState.MPI_Value; } else { // If its not a separator and not whitespace sb.Append(whitespaceSB); sb.Append(testchar); parsedNames[stringCount] = sb.ToString(); // Need to set the name here in case the string ends here. state = MPIState.MPI_ParseNonQuote; } } else { whitespaceSB.Append(testchar); } break; } case MPIState.MPI_ParseQuote: { if (testchar == rightQuoteChar) { // if se are on a right quote see if we are escapeing the right quote or ending the quoted string if (!removequotes) { sb.Append(testchar); } state = MPIState.MPI_RightQuote; } else { sb.Append(testchar); // Append what we are currently parsing } break; } case MPIState.MPI_RightQuote: { if (testchar == rightQuoteChar) { // If the next char is a another right quote then we were escapeing the right quote sb.Append(testchar); state = MPIState.MPI_ParseQuote; } else if (testchar == separator) { // If its a separator then record what we've parsed parsedNames[stringCount] = sb.ToString(); IncrementStringCount(name, parsedNames, ref stringCount, property); state = MPIState.MPI_Value; } else if (!IsWhitespace(testchar)) { // If it is not whitespace we got problems throw ADP.InvalidMultipartNameIncorrectUsageOfQuotes(property, name); } else { // It is a whitespace character so the following char should be whitespace, separator, or end of string anything else is bad parsedNames[stringCount] = sb.ToString(); state = MPIState.MPI_LookForSeparator; } break; } case MPIState.MPI_LookForSeparator: { if (!IsWhitespace(testchar)) { // If it is not whitespace if (testchar == separator) { // If it is a separator IncrementStringCount(name, parsedNames, ref stringCount, property); state = MPIState.MPI_Value; } else { // Othewise not a separator throw ADP.InvalidMultipartNameIncorrectUsageOfQuotes(property, name); } } break; } } } // Resolve final states after parsing the string switch (state) { case MPIState.MPI_Value: // These states require no extra action case MPIState.MPI_LookForSeparator: case MPIState.MPI_LookForNextCharOrSeparator: break; case MPIState.MPI_ParseNonQuote: // Dump what ever was parsed case MPIState.MPI_RightQuote: parsedNames[stringCount] = sb.ToString(); break; case MPIState.MPI_ParseQuote: // Invalid Ending States default: throw ADP.InvalidMultipartNameIncorrectUsageOfQuotes(property, name); } if (parsedNames[0] == null) { if (ThrowOnEmptyMultipartName) { throw ADP.InvalidMultipartName(property, name); // Name is entirely made up of whitespace } } else { // Shuffle the parsed name, from left justification to right justification, ie [a][b][null][null] goes to [null][null][a][b] int offset = limit - stringCount - 1; if (offset > 0) { for (int x = limit - 1; x >= offset; --x) { parsedNames[x] = parsedNames[x - offset]; parsedNames[x - offset] = null; } } } return(parsedNames); }
/// <summary> /// Core function for parsing the multipart identifer string. /// Note: Left quote strings need to correspond 1 to 1 with the right quote strings /// example: "ab" "cd", passed in for the left and the right quote /// would set a or b as a starting quote character. /// If a is the starting quote char then c would be the ending quote char /// otherwise if b is the starting quote char then d would be the ending quote character. /// </summary> /// <param name="name">string to parse</param> /// <param name="leftQuote">set of characters which are valid quoteing characters to initiate a quote</param> /// <param name="rightQuote">set of characters which are valid to stop a quote, array index's correspond to the the leftquote array.</param> /// <param name="separator">separator to use</param> /// <returns></returns> internal static List <string> ParseMultipartIdentifier(string name, string leftQuote, string rightQuote, char separator) { Debug.Assert(-1 == leftQuote.IndexOf(separator) && -1 == rightQuote.IndexOf(separator) && leftQuote.Length == rightQuote.Length, "Incorrect usage of quotes"); List <string> parsedNames = new List <string>(); parsedNames.Add(null); int stringCount = 0; // index of current string in the list MPIState state = MPIState.MPI_Value; // Initalize the starting state StringBuilder sb = new StringBuilder(name.Length); // String buffer to hold the string being currently built, init the string builder so it will never be resized StringBuilder whitespaceSB = null; // String buffer to hold white space used when parsing nonquoted strings 'a b . c d' = 'a b' and 'c d' char rightQuoteChar = ' '; // Right quote character to use given the left quote character found. for (int index = 0; index < name.Length; ++index) { char testchar = name[index]; switch (state) { case MPIState.MPI_Value: { int quoteIndex; if (IsWhitespace(testchar)) { // Is White Space then skip the whitespace continue; } else if (testchar == separator) { // If we found a separator, no string was found, initalize the string we are parsing to Empty and the next one to Empty. // This is NOT a redundent setting of string.Empty it solves the case where we are parsing ".foo" and we should be returning null, null, empty, foo parsedNames[stringCount] = string.Empty; IncrementStringCount(parsedNames, ref stringCount); } else if (-1 != (quoteIndex = leftQuote.IndexOf(testchar))) { // If we are a left quote rightQuoteChar = rightQuote[quoteIndex]; // record the corresponding right quote for the left quote sb.Length = 0; state = MPIState.MPI_ParseQuote; } else if (-1 != rightQuote.IndexOf(testchar)) { // If we shouldn't see a right quote throw EntityUtil.ADP_InvalidMultipartNameDelimiterUsage(); } else { sb.Length = 0; sb.Append(testchar); state = MPIState.MPI_ParseNonQuote; } break; } case MPIState.MPI_ParseNonQuote: { if (testchar == separator) { parsedNames[stringCount] = sb.ToString(); // set the currently parsed string IncrementStringCount(parsedNames, ref stringCount); state = MPIState.MPI_Value; } else // Quotes are not valid inside a non-quoted name if (-1 != rightQuote.IndexOf(testchar)) { throw EntityUtil.ADP_InvalidMultipartNameDelimiterUsage(); } else if (-1 != leftQuote.IndexOf(testchar)) { throw EntityUtil.ADP_InvalidMultipartNameDelimiterUsage(); } else if (IsWhitespace(testchar)) { // If it is Whitespace parsedNames[stringCount] = sb.ToString(); // Set the currently parsed string if (null == whitespaceSB) { whitespaceSB = new StringBuilder(); } whitespaceSB.Length = 0; whitespaceSB.Append(testchar); // start to record the white space, if we are parsing a name like "name with space" we should return "name with space" state = MPIState.MPI_LookForNextCharOrSeparator; } else { sb.Append(testchar); } break; } case MPIState.MPI_LookForNextCharOrSeparator: { if (!IsWhitespace(testchar)) { // If it is not whitespace if (testchar == separator) { IncrementStringCount(parsedNames, ref stringCount); state = MPIState.MPI_Value; } else { // If its not a separator and not whitespace sb.Append(whitespaceSB); sb.Append(testchar); parsedNames[stringCount] = sb.ToString(); // Need to set the name here in case the string ends here. state = MPIState.MPI_ParseNonQuote; } } else { whitespaceSB.Append(testchar); } break; } case MPIState.MPI_ParseQuote: { if (testchar == rightQuoteChar) { // if se are on a right quote see if we are escapeing the right quote or ending the quoted string state = MPIState.MPI_RightQuote; } else { sb.Append(testchar); // Append what we are currently parsing } break; } case MPIState.MPI_RightQuote: { if (testchar == rightQuoteChar) { // If the next char is a another right quote then we were escapeing the right quote sb.Append(testchar); state = MPIState.MPI_ParseQuote; } else if (testchar == separator) { // If its a separator then record what we've parsed parsedNames[stringCount] = sb.ToString(); IncrementStringCount(parsedNames, ref stringCount); state = MPIState.MPI_Value; } else if (!IsWhitespace(testchar)) { // If it is not white space we got problems throw EntityUtil.ADP_InvalidMultipartNameDelimiterUsage(); } else { // It is a whitespace character so the following char should be whitespace, separator, or end of string anything else is bad parsedNames[stringCount] = sb.ToString(); state = MPIState.MPI_LookForSeparator; } break; } case MPIState.MPI_LookForSeparator: { if (!IsWhitespace(testchar)) { // If it is not whitespace if (testchar == separator) { // If it is a separator IncrementStringCount(parsedNames, ref stringCount); state = MPIState.MPI_Value; } else { // Othewise not a separator throw EntityUtil.ADP_InvalidMultipartNameDelimiterUsage(); } } break; } } } // Resolve final states after parsing the string switch (state) { case MPIState.MPI_Value: // These states require no extra action case MPIState.MPI_LookForSeparator: case MPIState.MPI_LookForNextCharOrSeparator: break; case MPIState.MPI_ParseNonQuote: // Dump what ever was parsed case MPIState.MPI_RightQuote: parsedNames[stringCount] = sb.ToString(); break; case MPIState.MPI_ParseQuote: // Invalid Ending States default: throw EntityUtil.ADP_InvalidMultipartNameDelimiterUsage(); } return(parsedNames); }