/// <summary>
        /// Returns the first few characters of the string with a length
        /// specified by the given parameter. If the string's length is less than the
        /// given length the complete string is returned. If length is zero or
        /// less an empty string is returned
        /// </summary>
        /// <param name="s">the string to process</param>
        /// <param name="length">Number of characters to return</param>
        /// <returns></returns>
        public static string Left(this SubstrExtensionPoint sp, int length)
        {
            string e = sp.ExtendedValue;

            length = Math.Max(length, 0);
            return(e.Safe(s => (s.Length > length) ? s.Substring(0, length) : s));
        }
        /// <summary>
        /// Returns the last few characters of the string with a length
        /// specified by the given parameter. If the string's length is less than the
        /// given length the complete string is returned. If length is zero or
        /// less an empty string is returned
        /// </summary>
        /// <param name="ep">the string to process</param>
        /// <param name="length">Number of characters to return</param>
        /// <returns></returns>
        public static string Right(this SubstrExtensionPoint ep, int length)
        {
            string e = ep.ExtendedValue;

            length = Math.Max(length, 0);
            return(e.Safe(s => (s.Length > length) ? s.Substring(s.Length - length, length) : s));
        }
        /// <summary>
        /// Returns the left part from the first ocurrence of the given substring (without the substring).
        /// </summary>
        /// <remarks>
        /// Features driven by this set of rules:
        /// <list type="bullet">
        /// <item><description>null.LeftFromFirst(*) --> null</description></item>
        /// <item><description>null and string.Empty are always substrings of a not null string</description></item>
        /// /// <item><description>string.Empty only contains itself and null</description></item>
        /// <item><description>*.LeftFromFirst(notFound) --> null</description></item>
        /// </list>
        /// </remarks>
        public static string LeftFromFirst(this SubstrExtensionPoint sp, string substring, StringComparison comparison = StringComparison.Ordinal)
        {
            string e = sp.ExtendedValue;

            return(e.Safe(s =>
            {
                substring = substring.EmptyIfNull();
                int indexOfSubstringStart = s.IndexOf(substring, comparison) >= 0 ?
                                            s.IndexOf(substring, comparison) : -1;

                return indexOfSubstringStart < 0 ? null : sp.Left(indexOfSubstringStart);
            }));
        }
        /// <summary>
        /// Returns the right part from the first ocurrence of the given substring (without the substring).
        /// </summary>
        /// <remarks>
        /// Features driven by this set of rules:
        /// <list type="bullet">
        /// <item><description>null.RightFromFirst(*) --> null</description></item>
        /// <item><description>null and string.Empty are always substrings of a not null string</description></item>
        /// /// <item><description>string.Empty only contains itself and null</description></item>
        /// <item><description>*.RightFromFirst(notFound) --> null</description></item>
        /// </list>
        /// </remarks>
        public static string RightFromFirst(this SubstrExtensionPoint sp, string substring, StringComparison comparison = StringComparison.Ordinal)
        {
            string e = sp.ExtendedValue;

            return(e.Safe(s =>
            {
                substring = substring.EmptyIfNull();
                int indexOfSubstringEnd = s.IndexOf(substring, comparison) >= 0 ?
                                          s.IndexOf(substring, comparison) + substring.Length :
                                          -1;
                return indexOfSubstringEnd < 0 ? null : sp.Right(s.Length - indexOfSubstringEnd);
            }));
        }
        /// <summary>
        /// Returns the left part from the last ocurrence of the given substring (without the substring).
        /// </summary>
        /// <remarks>
        /// Features driven by this set of rules:
        /// <list type="bullet">
        /// <item><description>null.LeftFromLast(*) --> null</description></item>
        /// <item><description>null and string.Empty are always substrings of a not null string</description></item>
        /// /// <item><description>string.Empty only contains itself and null</description></item>
        /// <item><description>*.LeftFromLast(notFound) --> null</description></item>
        /// </list>
        /// </remarks>

        public static string LeftFromLast(this SubstrExtensionPoint sp, string substring, StringComparison comparison = StringComparison.Ordinal)
        {
            string e = sp.ExtendedValue;

            return(e.Safe(s =>
            {
                substring = substring.EmptyIfNull();
                int indexOfSubstringStart = -1;

                if (substring.IsEmpty())
                {
                    indexOfSubstringStart = 0;
                }
                else if (s.LastIndexOf(substring, comparison) >= 0)
                {
                    indexOfSubstringStart = s.LastIndexOf(substring, comparison);
                }

                return indexOfSubstringStart < 0 ? null : sp.Left(indexOfSubstringStart);
            }));
        }