/// <summary> /// Parses a string to the query data. /// </summary> /// <param name="query">The query string.</param> /// <param name="append">true if append instead of override; otherwise, false.</param> /// <param name="encoding">The optional encoding.</param> /// <returns>The count of query item added.</returns> /// <exception cref="FormatException">The format is not correct.</exception> public int ParseSet(string query, bool append = false, Encoding encoding = null) { if (!append) { Clear(); } if (string.IsNullOrWhiteSpace(query)) { return(0); } var queryTrim = query.TrimStart(); if (queryTrim.IndexOf('{') == 0) { queryTrim = queryTrim.Substring(1).Trim(); var lastPos = queryTrim.LastIndexOf('}'); if (lastPos >= 0) { queryTrim = queryTrim.Substring(0, lastPos); } var count = 0; string name = null; StringBuilder sb = null; var level = new List <char>(); StringBuilder backSlash = null; bool ignoreRest = false; bool lastBackSlash = false; foreach (var c in queryTrim) { if (ignoreRest) { switch (c) { case '\r': case '\n': ignoreRest = false; break; } lastBackSlash = false; continue; } if (c == '\\') { if (lastBackSlash) { sb.Append(c); } else { backSlash = new StringBuilder(); } lastBackSlash = !lastBackSlash; continue; } lastBackSlash = false; if (backSlash != null) { if (StringExtensions.ReplaceBackSlash(sb, backSlash, c)) { backSlash = null; } continue; } if (sb == null) { if (c == '/') { ignoreRest = true; continue; } if (c == '"') { sb = new StringBuilder(); level.Add('"'); continue; } if (name == null) { if (NameChars.IndexOf(c) > -1) { sb = new StringBuilder(); level.Add(':'); sb.Append(c); } continue; } if (c == '{') { level.Add('}'); } else if (c == '[') { level.Add(']'); } else if (NumBoolChars.IndexOf(c) > -1) { level.Add(','); } else { continue; } sb = new StringBuilder(); sb.Append(c); continue; } if (level.Count == 0) { continue; } var lastLevelChar = level[level.Count - 1]; if (c == lastLevelChar) { level.RemoveAt(level.Count - 1); if (name == null) { name = sb.ToString(); sb = null; continue; } else if (level.Count == 0) { if (c == ',') { var sbStr = sb.ToString().Trim(); sb = new StringBuilder(sbStr); if (sbStr == "null" || sbStr == "undefined") { name = null; sb = null; continue; } } else if (c == '"') { } else { sb.Append(c); } ListExtensions.Add(this, name, sb.ToString()); name = null; sb = null; continue; } } else if (lastLevelChar == ':' && name == null) { if (c == '\r' || c == '\n' || c == '\t' || c == ' ' || c == ',' || c == '+') { sb = null; } else if (c == '/') { sb = null; ignoreRest = true; } else if (NameChars.IndexOf(c) < 0) { throw new FormatException("The format of query string is not correct."); } if (sb == null) { level.RemoveAt(level.Count - 1); continue; } } else if (c == '"') { level.Add('"'); } else if (lastLevelChar != '"') { if (c == '{') { level.Add('}'); } else if (c == '[') { level.Add(']'); } } if (sb == null) { sb = new StringBuilder(); } sb.Append(c); } if (!string.IsNullOrWhiteSpace(name) && sb != null) { var sbStr = sb.ToString().Trim(); if (sbStr != "null" && sbStr != "undefined") { ListExtensions.Add(this, name, sbStr); } } return(count); } if (encoding == null) { encoding = DefaultEncoding ?? Encoding.UTF8; } var pos = query.IndexOf("?"); if (pos >= 0) { query = query.Substring(pos + 1); } pos = query.IndexOf("#"); if (pos >= 0) { query = query.Substring(0, pos); } var arr = query.Split('&', '\r', '\n'); foreach (var item in arr) { pos = item.IndexOf("="); if (pos < 0) { if (item.Length == 0) { continue; } ListExtensions.Add(this, WebFormat.UrlDecode(item, encoding), string.Empty); } else { var key = item.Substring(0, pos); var value = item.Substring(pos + 1); if (key.Length == 0 && value.Length == 0) { continue; } ListExtensions.Add(this, WebFormat.UrlDecode(key, encoding), WebFormat.UrlDecode(value, encoding)); } } return(arr.Length); }