static KeyValueData()
        {
            TKey defaultKey = default(TKey);
            TVal defaultVal = default(TVal);

            _null = new KeyValueData <TKey, TVal>(defaultKey, defaultVal);
        }
        /// <summary>
        ///  Parses multiple pairs on a single line.
        /// e.g. Location : Country = US, State = New York, City = Queens, Zip = 11375
        /// </summary>
        /// <param name="singleLineText"></param>
        /// <returns></returns>
        public virtual IList <KeyValueData <string, string> > ParseLineWithMultiPairs(string line)
        {
            // list of key value pairs.
            IList <KeyValueData <string, string> > keyValuePairs = new List <KeyValueData <string, string> >();
            KeyValueData <string, string>          keyValuePair  = ParseLine(line);

            // Empty ?
            if (keyValuePair == KeyValueData <string, string> .Empty)
            {
                keyValuePairs.Add(keyValuePair);
                return(keyValuePairs);
            }

            // If there are not multi-pairs
            if (string.IsNullOrEmpty(keyValuePair.Value) ||
                keyValuePair.Value.IndexOf(_settings.MultiPairDelimeter) == -1)
            {
                keyValuePair = InternalParseLine(keyValuePair.Value, _settings.MultiPairKeyValueDelimeter, true);
                keyValuePairs.Add(keyValuePair);
                return(keyValuePairs);
            }

            // Multiple pairs.
            string[] pairs = keyValuePair.Value.Split(new string[] { _settings.MultiPairDelimeter }, StringSplitOptions.None);
            foreach (string pair in pairs)
            {
                KeyValueData <string, string> keyValue = InternalParseLine(pair, _settings.MultiPairKeyValueDelimeter, true);
                keyValuePairs.Add(keyValue);
            }
            return(keyValuePairs);
        }
        /// <summary>
        /// Parsese the key/value text and then validates the key against the
        /// token lookup.
        /// Also sets the key based on the settings of the token if valid.
        /// </summary>
        /// <param name="text"></param>
        /// <param name="delimeter"></param>
        /// <returns></returns>
        protected override KeyValueData <string, string> InternalParseLine(string text, string delimeter, bool applySettings)
        {
            KeyValueData <string, string> pair = base.InternalParseLine(text, delimeter, false);

            // Only massage the key and validate it if there is a key.
            if (string.IsNullOrEmpty(pair.Key))
            {
                return(pair);
            }

            string key = pair.Key;

            // Convert to lowercase if token lookup is not case sensitive.
            // Trim white space if it's not important.
            if (!_tokenLookup.IsCaseSensitive && _settings.ConvertKeysToLowerCase)
            {
                key = key.ToLower();
            }
            if (!_tokenLookup.IsWhiteSpaceSensitive && _settings.TrimWhiteSpaceFromKeys)
            {
                key = key.Trim();
            }

            bool isValid = _tokenLookup.IsValid(key);

            // Set the new key, and whether it's valid.
            pair.SetIsValidKey(isValid);

            // Only set the new key if valid.
            pair.SetKey(key);

            return(pair);
        }
        /// <summary>
        /// Parses the text checking for multiple lines.
        /// </summary>
        /// <param name="textToParse"></param>
        /// <returns></returns>
        public virtual IList <KeyValueData <string, string> > Parse(string text, IList <string> errors)
        {
            ValidationResults result = Validate(errors, false, text, string.Empty);

            if (!result.IsValid)
            {
                return(null);
            }

            StringReader reader      = new StringReader(result.Text);
            string       currentLine = reader.ReadLine();
            IList <KeyValueData <string, string> > keyValueList = new List <KeyValueData <string, string> >();

            // More to read.
            while (currentLine != null)
            {
                KeyValueData <string, string> pair = ParseLine(currentLine);
                keyValueList.Add(pair);
                currentLine = reader.ReadLine();
            }
            return(keyValueList);
        }
        protected virtual KeyValueData <string, string> InternalParseLine(string text, string delimeter, bool applySettings)
        {
            // Check for emtpy string
            if (string.IsNullOrEmpty(text))
            {
                return(KeyValueData <string, string> .Empty);
            }

            // Now check to see if there is no delmiter or at the beggining.
            int ndxKeyValueSeparator = text.IndexOf(delimeter);

            if (ndxKeyValueSeparator <= 0)
            {
                return(new KeyValueData <string, string>(string.Empty, text, true));
            }

            string key   = text.Substring(0, ndxKeyValueSeparator);
            string value = text.Substring(ndxKeyValueSeparator + 1);

            KeyValueData <string, string> pair = new KeyValueData <string, string>(key, value, true);

            if (applySettings)
            {
                if (_settings.ConvertKeysToLowerCase)
                {
                    key = key.ToLower();
                }
                if (_settings.TrimWhiteSpaceFromKeys)
                {
                    key = key.Trim();
                }

                pair.SetKey(key);
            }
            return(pair);
        }
        /// <summary>
        /// !_tokenLookup.IsCaseSensitive && _settings.ConvertKeysToLowerCase
        /// !_tokenLookup.IsWhiteSpaceSensitive && _settings.TrimWhiteSpaceFromKeys
        /// </summary>
        /// <param name="textToParse"></param>
        /// <param name="delimeter"></param>
        /// <param name="trimKeys"></param>
        /// <param name="getLowerCaseKeys"></param>
        /// <returns></returns>
        public virtual KeyValueData <string, string> ParseLine(string text)
        {
            KeyValueData <string, string> pair = InternalParseLine(text, _settings.KeyValuePairDelimeter, true);

            return(pair);
        }