CSharp examples for System:String Parse
Parses key value pair expressions from a string.
// Copyright ? 2011, Grid Protection Alliance. All Rights Reserved. using System.Text.RegularExpressions; using System.Text; using System.IO;/*w ww . ja va 2 s .co m*/ using System.Globalization; using System.ComponentModel; using System.Collections.Generic; using System; public class Main{ /// <summary> /// Parses key/value pair expressions from a string. Parameter pairs are delimited by <paramref name="keyValueDelimeter"/> /// and multiple pairs separated by <paramref name="parameterDelimeter"/>. Supports encapsulated nested expressions. /// </summary> /// <param name="value">String containing key/value pair expressions to parse.</param> /// <param name="parameterDelimeter">Character that delimits one key/value pair from another.</param> /// <param name="keyValueDelimeter">Character that delimits key from value.</param> /// <param name="startValueDelimeter">Optional character that marks the start of a value such that value could contain other /// <paramref name="parameterDelimeter"/> or <paramref name="keyValueDelimeter"/> characters.</param> /// <param name="endValueDelimeter">Optional character that marks the end of a value such that value could contain other /// <paramref name="parameterDelimeter"/> or <paramref name="keyValueDelimeter"/> characters.</param> /// <param name="ignoreDuplicateKeys">Flag determines whether duplicates are ignored. If flag is set to <c>false</c> an /// <see cref="ArgumentException"/> will be thrown when all key parameters are not unique.</param> /// <returns>Dictionary of key/value pairs.</returns> /// <remarks> /// <para> /// Parses a string containing key/value pair expressions (e.g., "localPort=5001; transportProtocol=UDP; interface=0.0.0.0"). /// This method treats all "keys" as case-insensitive. Nesting of key/value pair expressions is allowed by encapsulating the /// value using the <paramref name="startValueDelimeter"/> and <paramref name="endValueDelimeter"/> values (e.g., /// "dataChannel={Port=-1;Clients=localhost:8800}; commandChannel={Port=8900}; dataFormat=FloatingPoint;"). There must be one /// <paramref name="endValueDelimeter"/> for each encountered <paramref name="startValueDelimeter"/> in the value or a /// <see cref="FormatException"/> will be thrown. Multiple levels of nesting is supported. If the <paramref name="ignoreDuplicateKeys"/> /// flag is set to <c>false</c> an <see cref="ArgumentException"/> will be thrown when all key parameters are not unique. Note /// that keys within nested expressions are considered separate key/value pair strings and are not considered when checking /// for duplicate keys. /// </para> /// </remarks> /// <exception cref="ArgumentNullException">value is null.</exception> /// <exception cref="ArgumentException">All delimiters must be unique -or- all keys must be unique when /// <paramref name="ignoreDuplicateKeys"/> is set to <c>false</c>.</exception> /// <exception cref="FormatException">Total nested key/value value pair expressions are mismatched -or- encountered /// <paramref name="endValueDelimeter"/> before <paramref name="startValueDelimeter"/>.</exception> public static Dictionary<string, string> ParseKeyValuePairs(this string value, char parameterDelimeter = ';', char keyValueDelimeter = '=', char startValueDelimeter = '{', char endValueDelimeter = '}', bool ignoreDuplicateKeys = true) { if (value == (string)null) throw new ArgumentNullException("value"); if (parameterDelimeter == keyValueDelimeter || parameterDelimeter == startValueDelimeter || parameterDelimeter == endValueDelimeter || keyValueDelimeter == startValueDelimeter || keyValueDelimeter == endValueDelimeter || startValueDelimeter == endValueDelimeter) throw new ArgumentException("All delimiters must be unique"); Dictionary<string, string> keyValuePairs = new Dictionary<string, string>(StringComparer.CurrentCultureIgnoreCase); StringBuilder escapedValue = new StringBuilder(); string escapedParameterDelimeter = parameterDelimeter.RegexEncode(); string escapedKeyValueDelimeter = keyValueDelimeter.RegexEncode(); string escapedStartValueDelimeter = startValueDelimeter.RegexEncode(); string escapedEndValueDelimeter = endValueDelimeter.RegexEncode(); string[] elements; string key, unescapedValue; bool valueEscaped = false; int delimiterDepth = 0; char character; // Escape any parameter or key/value delimiters within tagged value sequences // For example, the following string: // "normalKVP=-1; nestedKVP={p1=true; p2=false}") // would be encoded as: // "normalKVP=-1; nestedKVP=p1\\u003dtrue\\u003b p2\\u003dfalse") for (int x = 0; x < value.Length; x++) { character = value[x]; if (character == startValueDelimeter) { if (!valueEscaped) { valueEscaped = true; continue; // Don't add tag start delimiter to final value } else { // Handle nested delimiters delimiterDepth++; } } if (character == endValueDelimeter) { if (valueEscaped) { if (delimiterDepth > 0) { // Handle nested delimiters delimiterDepth--; } else { valueEscaped = false; continue; // Don't add tag stop delimiter to final value } } else { throw new FormatException(string.Format("Failed to parse key/value pairs: invalid delimiter mismatch. Encountered end value delimiter \'{0}\' before start value delimiter \'{1}\'.", endValueDelimeter, startValueDelimeter)); } } if (valueEscaped) { // Escape any delimiter characters inside nested key/value pair if (character == parameterDelimeter) escapedValue.Append(escapedParameterDelimeter); else if (character == keyValueDelimeter) escapedValue.Append(escapedKeyValueDelimeter); else if (character == startValueDelimeter) escapedValue.Append(escapedStartValueDelimeter); else if (character == endValueDelimeter) escapedValue.Append(escapedEndValueDelimeter); else escapedValue.Append(character); } else { escapedValue.Append(character); } } if (delimiterDepth != 0 || valueEscaped) { // If value is still escaped, tagged expression was not terminated if (valueEscaped) delimiterDepth = 1; throw new FormatException(string.Format("Failed to parse key/value pairs: invalid delimiter mismatch. Encountered more {0} than {1}.", delimiterDepth > 0 ? "start value delimiters \'" + startValueDelimeter + "\'" : "end value delimiters \'" + endValueDelimeter + "\'", delimiterDepth < 0 ? "start value delimiters \'" + startValueDelimeter + "\'" : "end value delimiters \'" + endValueDelimeter + "\'")); } // Parse key/value pairs from escaped value foreach (string parameter in escapedValue.ToString().Split(parameterDelimeter)) { // Parse out parameter's key/value elements elements = parameter.Split(keyValueDelimeter); if (elements.Length == 2) { // Get key expression key = elements[0].ToString().Trim(); // Get unescaped value expression unescapedValue = elements[1].ToString().Trim(). Replace(escapedParameterDelimeter, parameterDelimeter.ToString()). Replace(escapedKeyValueDelimeter, keyValueDelimeter.ToString()). Replace(escapedStartValueDelimeter, startValueDelimeter.ToString()). Replace(escapedEndValueDelimeter, endValueDelimeter.ToString()); // Add key/value pair to dictionary if (ignoreDuplicateKeys) { // Add or replace key elements with unescaped value keyValuePairs[key] = unescapedValue; } else { // Add key elements with unescaped value throwing an exception for encountered duplicate keys if (keyValuePairs.ContainsKey(key)) throw new ArgumentException(string.Format("Failed to parse key/value pairs: duplicate key encountered. Key \"{0}\" is not unique within the string: \"{1}\"", key, value)); keyValuePairs.Add(key, unescapedValue); } } } return keyValuePairs; } }