internal static int GetKeyValuePair(string connectionString, int currentPosition, StringBuilder buffer, bool useOdbcRules, out string keyname, out string keyvalue)
{
int startposition = currentPosition;
buffer.Length = 0;
keyname = null;
keyvalue = null;
char currentChar = '\0';
ParserState parserState = ParserState.NothingYet;
int length = connectionString.Length;
for (; currentPosition < length; ++currentPosition)
{
currentChar = connectionString[currentPosition];
switch (parserState)
{
case ParserState.NothingYet: // [\\s;]*
if ((';' == currentChar) || char.IsWhiteSpace(currentChar))
{
continue;
}
if ('\0' == currentChar) { parserState = ParserState.NullTermination; continue; }
if (char.IsControl(currentChar)) { throw ADP.ConnectionStringSyntax(startposition); }
startposition = currentPosition;
if ('=' != currentChar)
{
parserState = ParserState.Key;
break;
}
else
{
parserState = ParserState.KeyEqual;
continue;
}
case ParserState.Key: // (?<key>([^=\\s\\p{Cc}]|\\s+[^=\\s\\p{Cc}]|\\s+==|==)+)
if ('=' == currentChar) { parserState = ParserState.KeyEqual; continue; }
if (char.IsWhiteSpace(currentChar)) { break; }
if (char.IsControl(currentChar)) { throw ADP.ConnectionStringSyntax(startposition); }
break;
case ParserState.KeyEqual: // \\s*=(?!=)\\s*
if (!useOdbcRules && '=' == currentChar) { parserState = ParserState.Key; break; }
keyname = GetKeyName(buffer);
if (string.IsNullOrEmpty(keyname)) { throw ADP.ConnectionStringSyntax(startposition); }
buffer.Length = 0;
parserState = ParserState.KeyEnd;
goto case ParserState.KeyEnd;
case ParserState.KeyEnd:
if (char.IsWhiteSpace(currentChar)) { continue; }
if (useOdbcRules)
{
if ('{' == currentChar) { parserState = ParserState.BraceQuoteValue; break; }
}
else
{
if ('\'' == currentChar) { parserState = ParserState.SingleQuoteValue; continue; }
if ('"' == currentChar) { parserState = ParserState.DoubleQuoteValue; continue; }
}
if (';' == currentChar) { goto ParserExit; }
if ('\0' == currentChar) { goto ParserExit; }
if (char.IsControl(currentChar)) { throw ADP.ConnectionStringSyntax(startposition); }
parserState = ParserState.UnquotedValue;
break;
case ParserState.UnquotedValue: // "((?![\"'\\s])" + "([^;\\s\\p{Cc}]|\\s+[^;\\s\\p{Cc}])*" + "(?<![\"']))"
if (char.IsWhiteSpace(currentChar)) { break; }
if (char.IsControl(currentChar) || ';' == currentChar) { goto ParserExit; }
break;
case ParserState.DoubleQuoteValue: // "(\"([^\"\u0000]|\"\")*\")"
if ('"' == currentChar) { parserState = ParserState.DoubleQuoteValueQuote; continue; }
if ('\0' == currentChar) { throw ADP.ConnectionStringSyntax(startposition); }
break;
case ParserState.DoubleQuoteValueQuote:
if ('"' == currentChar) { parserState = ParserState.DoubleQuoteValue; break; }
keyvalue = GetKeyValue(buffer, false);
parserState = ParserState.QuotedValueEnd;
goto case ParserState.QuotedValueEnd;
case ParserState.SingleQuoteValue: // "('([^'\u0000]|'')*')"
if ('\'' == currentChar) { parserState = ParserState.SingleQuoteValueQuote; continue; }
if ('\0' == currentChar) { throw ADP.ConnectionStringSyntax(startposition); }
break;
case ParserState.SingleQuoteValueQuote:
if ('\'' == currentChar) { parserState = ParserState.SingleQuoteValue; break; }
keyvalue = GetKeyValue(buffer, false);
parserState = ParserState.QuotedValueEnd;
goto case ParserState.QuotedValueEnd;
case ParserState.BraceQuoteValue: // "(\\{([^\\}\u0000]|\\}\\})*\\})"
if ('}' == currentChar) { parserState = ParserState.BraceQuoteValueQuote; break; }
if ('\0' == currentChar) { throw ADP.ConnectionStringSyntax(startposition); }
break;
case ParserState.BraceQuoteValueQuote:
if ('}' == currentChar) { parserState = ParserState.BraceQuoteValue; break; }
keyvalue = GetKeyValue(buffer, false);
parserState = ParserState.QuotedValueEnd;
goto case ParserState.QuotedValueEnd;
case ParserState.QuotedValueEnd:
if (char.IsWhiteSpace(currentChar)) { continue; }
if (';' == currentChar) { goto ParserExit; }
if ('\0' == currentChar) { parserState = ParserState.NullTermination; continue; }
throw ADP.ConnectionStringSyntax(startposition); // unbalanced single quote
case ParserState.NullTermination: // [\\s;\u0000]*
if ('\0' == currentChar) { continue; }
if (char.IsWhiteSpace(currentChar)) { continue; }
throw ADP.ConnectionStringSyntax(currentPosition);
default:
throw ADP.InternalError(ADP.InternalErrorCode.InvalidParserState1);
}
buffer.Append(currentChar);
}
ParserExit:
switch (parserState)
{
case ParserState.Key:
case ParserState.DoubleQuoteValue:
case ParserState.SingleQuoteValue:
case ParserState.BraceQuoteValue:
// keyword not found/unbalanced double/single quote
throw ADP.ConnectionStringSyntax(startposition);
case ParserState.KeyEqual:
// equal sign at end of line
keyname = GetKeyName(buffer);
if (string.IsNullOrEmpty(keyname)) { throw ADP.ConnectionStringSyntax(startposition); }
break;
case ParserState.UnquotedValue:
// unquoted value at end of line
keyvalue = GetKeyValue(buffer, true);
char tmpChar = keyvalue[keyvalue.Length - 1];
if (!useOdbcRules && (('\'' == tmpChar) || ('"' == tmpChar)))
{
throw ADP.ConnectionStringSyntax(startposition); // unquoted value must not end in quote, except for odbc
}
break;
case ParserState.DoubleQuoteValueQuote:
case ParserState.SingleQuoteValueQuote:
case ParserState.BraceQuoteValueQuote:
case ParserState.QuotedValueEnd:
// quoted value at end of line
keyvalue = GetKeyValue(buffer, false);
break;
case ParserState.NothingYet:
case ParserState.KeyEnd:
case ParserState.NullTermination:
// do nothing
break;
default:
throw ADP.InternalError(ADP.InternalErrorCode.InvalidParserState2);
}
if ((';' == currentChar) && (currentPosition < connectionString.Length))
{
currentPosition++;
}
return currentPosition;
}