Candor.StringExtensions.LexicalAdd C# (CSharp) Method

LexicalAdd() public static method

Performs a lexicographical addition to a string by any amount. See http://wikipedia.org/wiki/Lexicographical_order, and further remarks for this member.

This may or may not result in a value that sorts in the correct order as if it were a file name in a file explorer.

If the string is at the highest character for each position or the number added moves past that position, then a new character position is incremented to the left (by adding a character position). This then behaves the same as if the source was left whitespace padded. Performance scales based on the number of characters incremented in the string.

Incrementing the value always starts on the right and moves left as with numeric additions. Right whitespace padded strings will increment values in the whitespace before advancing to the characters on the left. If this is not desired behavior then Trim the source when passed into this method.

public static LexicalAdd ( this source, LexicalCharacterSet charSet, System.Boolean ignoreCase, System.Boolean treatNonCharsAsSpace, Int32 count ) : String
source this The string to increment from.
charSet LexicalCharacterSet The character set defining the characters and their order.
ignoreCase System.Boolean Specifies if case should be ignored as an incremented value. /// If true, incremented character positions will be the case of the majority of other /// values; which may or may not be the same as the character being replaced.
treatNonCharsAsSpace System.Boolean /// Indicates if non character set characters should be treated as /// a space and be eligible for incrementing. ///
count System.Int32
return String
        public static String LexicalAdd(this String source, LexicalCharacterSet charSet, Boolean ignoreCase, Boolean treatNonCharsAsSpace, Int32 count)
        {
            var chars = source.ToCharArray().ToList();
            //if (!chars.All(value => char.IsWhiteSpace(value) || charSet.Characters.Contains(value)))
            //    throw new ArgumentException(
            //        "The source string contains characters not available in the specified lexical increment character set.");
            if (count < 0)
                throw new ArgumentOutOfRangeException("count", count, "Only positive numbers can be added lexically at this time.");

            var characters = charSet.Characters;
            if (ignoreCase && charSet.IsCaseSensitive)
            {   //change 'characters' to an upper or lower case version
                var lowerCount = chars.Where(char.IsLower).Count();
                var upperCount = chars.Where(char.IsUpper).Count();
                if (lowerCount > upperCount)
                    characters = charSet.Characters.Where(value => !char.IsLetter(value) || char.IsLower(value)).ToList();
                else
                    characters = charSet.Characters.Where(value => !char.IsLetter(value) || char.IsUpper(value)).ToList();
            }
            var mathBase = ignoreCase ? charSet.CaseInsensitiveLength : charSet.CaseSensitiveLength;
            Int32 remain = count, carryOver = 0;
            //position is counting from the right most character, since we are treating these characters as a number
            for (var position = 1; remain > 0 || carryOver > 0 ; position++)
            {
                if (chars.Count < position)
                {
                    chars.Insert(0, ' ');
                }
                var positionBase = position == 1 ? 1 : Math.Pow(mathBase, position - 1);
                var posCount = ((int)((remain / positionBase) % mathBase)) + carryOver;
                if (posCount == mathBase)
                {   //no character change, pass along carry over
                    remain -= ((posCount - carryOver) * (int)positionBase);
                    carryOver = 1;
                }
                else if (posCount > 0)
                {
                    var posChar = chars[chars.Count - position];
                    var posCharIndex = characters.IndexOf(posChar);
                    if (ignoreCase && posCharIndex == -1 && char.IsLetter(posChar))
                    {   //Character removed when changing to an upper or lower case version, so get the equivalent case-insensitive character
                        posChar = char.IsLower(posChar) ? char.ToUpper(posChar) : char.ToLower(posChar);
                        posCharIndex = characters.IndexOf(posChar);
                    } //if whitespace char, leave posCharIndex at -1 for replacement
                    if (posCharIndex == -1 && !char.IsWhiteSpace(posChar) && !treatNonCharsAsSpace)
                        throw new ArgumentException(
                            "The source string contains characters not available in the specified lexical increment character set.");

                    chars[chars.Count - position] = characters[((posCharIndex + posCount) % mathBase)];
                    carryOver = posCharIndex + posCount < characters.Count ? 0 : 1;
                    remain = Math.Max(0, remain - posCount * (int)positionBase);
                }
            }

            return String.Concat(chars);
        }

Same methods

StringExtensions::LexicalAdd ( this source, LexicalCharacterSet charSet, System.Boolean ignoreCase, Int32 count ) : String