public static NameValuePair[] ToNameValuePairs(this string data)
{
var results = new List<NameValuePair>();
var stateStack = new Stack<NameValueProcessState>();
var currentState = NameValueProcessState.parsingText;
var escapeChars = new Stack<char>();
var escapeChar = '\0';
var currentString = string.Empty;
foreach (var c in data)
{
switch (currentState)
{
case NameValueProcessState.parsingText:
switch (c)
{
case '[':
stateStack.Push(currentState);
currentState = NameValueProcessState.parsingArray;
currentString += c;
break;
case '{':
stateStack.Push(currentState);
currentState = NameValueProcessState.parsingObject;
currentString += c;
break;
case '"':
stateStack.Push(currentState);
currentState = NameValueProcessState.parsingValue;
currentString += c;
break;
case ',':
results.Add(currentString.ToNameValuePair());
currentString = string.Empty;
break;
default:
currentString += c;
break;
}
break;
case NameValueProcessState.parsingValue:
switch (c)
{
case '[':
stateStack.Push(currentState);
currentState = NameValueProcessState.parsingArray;
currentString += c;
break;
case '{':
stateStack.Push(currentState);
currentState = NameValueProcessState.parsingObject;
currentString += c;
break;
case '"':
currentState = stateStack.Pop();
currentString += c;
break;
default:
currentString += c;
break;
}
break;
case NameValueProcessState.enteringEscapeSequence:
{
escapeChars.Push(escapeChar);
escapeChar = c;
currentState = NameValueProcessState.parsingEscapeSequence;
}
break;
case NameValueProcessState.exitingEscapeSequence:
{
escapeChar = escapeChars.Pop();
currentState = stateStack.Pop();
}
break;
case NameValueProcessState.parsingEscapeSequence:
switch (c)
{
case '\'':
case '"':
// case '`':
currentState = stateStack.Pop();
currentString += c;
break;
default:
currentString += c;
break;
}
break;
case NameValueProcessState.parsingArray:
switch (c)
{
case '\'':
case '"':
//case '`':
stateStack.Push(currentState);
currentState = NameValueProcessState.parsingEscapeSequence;
currentString += c;
break;
case '[':
stateStack.Push(currentState);
currentString += c;
break;
case ']':
currentState = stateStack.Pop();
currentString += c;
break;
default:
currentString += c;
break;
}
break;
case NameValueProcessState.parsingObject:
switch (c)
{
case '{':
stateStack.Push(currentState);
currentString += c;
break;
case '}':
currentState = stateStack.Pop();
currentString += c;
break;
default:
currentString += c;
break;
}
break;
}
}
if (currentString.Trim() != string.Empty)
{
results.Add(currentString.ToNameValuePair());
}
return results.ToArray();
}