Example #1
0
        /// <summary>
        /// Parses separated decimal bytes from a string.
        /// </summary>
        /// <param name="s">A string containing delimited decimal integer numbers.</param>
        /// <param name="separator">A separator delimiting the values.</param>
        /// <returns>A byte array containing the decimal values as bytes.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="s"/> is <see langword="null"/>.</exception>
        /// <exception cref="ArgumentException"><paramref name="separator"/> is <see langword="null"/>&#160;or empty.</exception>
        /// <exception cref="FormatException"><paramref name="s"/> is not of the correct format.</exception>
        /// <exception cref="OverflowException">A value in <paramref name="s"/> does not fit in the range of a <see cref="byte">byte</see> value.</exception>
        public static byte[] ParseDecimalBytes(this string s, string separator)
        {
            if (s == null)
            {
                Throw.ArgumentNullException(Argument.s);
            }

            if (String.IsNullOrEmpty(separator))
            {
                Throw.ArgumentException(Argument.separator, Res.StringExtensionsSeparatorNullOrEmpty);
            }

            List <StringSegmentInternal> values = new StringSegmentInternal(s).Split(separator);
            int len = values.Count;

            byte[] result = new byte[len];
            for (int i = 0; i < len; i++)
            {
                StringSegmentInternal segment = values[i];
                segment.Trim();
                if (!segment.TryParseIntQuick(false, Byte.MaxValue, out ulong value))
                {
                    Throw.ArgumentException(Argument.s, Res.StringExtensionsCannotParseAsType(segment.ToString(), Reflector.ByteType));
                }
                result[i] = (byte)value;
            }

            return(result);
        }
Example #2
0
        /// <summary>
        /// Parses delimited hex values from a string into an array of bytes.
        /// </summary>
        /// <param name="s">A string containing delimited hex values.</param>
        /// <param name="separator">A separator delimiting the hex values. If <see langword="null"/>, then <paramref name="s"/> is parsed as a continuous hex stream.</param>
        /// <returns>A byte array containing the hex values as bytes.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="s"/> is <see langword="null"/>.</exception>
        /// <exception cref="ArgumentException"><paramref name="separator"/> is <see langword="null"/>&#160;or empty, and <paramref name="s"/> does not consist of event number of hex digits,
        /// or parsing failed.</exception>
        public static byte[] ParseHexBytes(this string s, string separator)
        {
            if (s == null)
            {
                Throw.ArgumentNullException(Argument.s);
            }

            if (string.IsNullOrEmpty(separator))
            {
                return(ParseHexBytes(s));
            }

            List <StringSegmentInternal> values = new StringSegmentInternal(s).Split(separator);
            int len = values.Count;

            byte[] result = new byte[len];
            for (int i = 0; i < len; i++)
            {
                StringSegmentInternal segment = values[i];
                segment.Trim();
                if (!Parser.TryParseHexByte(segment, out result[i]))
                {
                    Throw.ArgumentException(Argument.s, Res.StringExtensionsCannotParseAsType(segment.ToString(), Reflector.ByteType));
                }
            }

            return(result);
        }
Example #3
0
            private static bool TryParseBoolean(string s, CultureInfo culture, out object value)
            {
                var segment = new StringSegmentInternal(s);

                segment.Trim();
                if (segment.EqualsOrdinalIgnoreCase(Boolean.FalseString))
                {
                    value = false;
                    return(true);
                }

                if (segment.EqualsOrdinalIgnoreCase(Boolean.TrueString))
                {
                    value = true;
                    return(true);
                }

                // allowing also an integer, which will be true for nonzero value
                if (segment.TryParseIntQuick(true, Int64.MaxValue, out ulong result))
                {
                    value = result != 0L;
                    return(true);
                }

                value = null;
                return(false);
            }
Example #4
0
            internal static bool TryParseHexByte(StringSegmentInternal s, out byte value)
            {
                if (s.Length > 0)
                {
                    s.TrimStart('0');

                    if (s.Length == 2 && TryParseHexDigit(s[0], out int hi) && TryParseHexDigit(s[1], out int lo))
                    {
                        value = (byte)((hi << 4) | lo);
                        return(true);
                    }

                    if (s.Length == 1 && TryParseHexDigit(s[0], out int result))
                    {
                        value = (byte)result;
                        return(true);
                    }

                    // if now empty it means valid 0
                    if (s.Length == 0)
                    {
                        value = 0;
                        return(true);
                    }
                }

                value = default;
                return(false);
            }
        public static unsafe string GetRelativePath(string target, string baseDirectory, bool isCaseSensitive)
        {
            if (target == null)
            {
                Throw.ArgumentNullException(Argument.target);
            }
            if (target.Length == 0)
            {
                Throw.ArgumentException(Argument.target, Res.ArgumentEmpty);
            }
            if (baseDirectory == null)
            {
                Throw.ArgumentNullException(Argument.baseDirectory);
            }
            if (baseDirectory.Length == 0)
            {
                Throw.ArgumentException(Argument.baseDirectory, Res.ArgumentEmpty);
            }

            target        = Path.GetFullPath(target);
            baseDirectory = Path.GetFullPath(baseDirectory);

            var srcDir = new StringSegmentInternal(baseDirectory);

            srcDir.TrimEnd(Path.DirectorySeparatorChar);
            List <StringSegmentInternal> basePathParts = srcDir.Split(Path.DirectorySeparatorChar);

            var dstDir = new StringSegmentInternal(target);

            dstDir.TrimEnd(Path.DirectorySeparatorChar);
            List <StringSegmentInternal> targetPathParts = dstDir.Split(Path.DirectorySeparatorChar);

            int commonPathDepth = 0;
            int len             = Math.Min(basePathParts.Count, targetPathParts.Count);

            if (isCaseSensitive)
            {
                for (int i = 0; i < len; i++)
                {
                    if (!basePathParts[i].Equals(targetPathParts[i]))
                    {
                        break;
                    }
                    commonPathDepth += 1;
                }
            }
            else
            {
                for (int i = 0; i < len; i++)
                {
                    if (!basePathParts[i].EqualsOrdinalIgnoreCase(targetPathParts[i]))
                    {
                        break;
                    }
                    commonPathDepth += 1;
                }
            }

            // no common parts
            if (commonPathDepth == 0)
            {
                return(target);
            }

            int baseOnlyCount   = basePathParts.Count - commonPathDepth;
            int targetPathCount = targetPathParts.Count;

            len = baseOnlyCount > 0 ? baseOnlyCount * 2 + (baseOnlyCount - 1) : 0; // .. and path separators
            for (int i = commonPathDepth; i < targetPathCount; i++)
            {
                if (len > 0)
                {
                    len += 1;
                }
                len += targetPathParts[i].Length;
            }

            string result = new String('\0', len);

            fixed(char *pResult = result)
            {
                var sb = new MutableStringBuilder(pResult, len);

                for (int i = 0; i < baseOnlyCount; i++)
                {
                    if (i > 0)
                    {
                        sb.Append(Path.DirectorySeparatorChar);
                    }
                    sb.Append("..");
                }

                for (int i = commonPathDepth; i < targetPathCount; i++)
                {
                    if (sb.Length > 0)
                    {
                        sb.Append(Path.DirectorySeparatorChar);
                    }
                    sb.Append(targetPathParts[i]);
                }
            }

            if (result.Length == 0)
            {
                return(".");
            }
            return(result);
        }
Example #6
0
        /// <summary>
        /// Tries to convert the string representation of the name or numeric value of one or more enumerated values to an equivalent enumerated object.
        /// In case of success the return value is <see langword="true"/>&#160;and parsed <see langword="enum"/>&#160;is returned in <paramref name="result"/> parameter.
        /// </summary>
        /// <param name="value">The <see cref="string">string</see> representation of the enumerated value or values to parse.</param>
        /// <param name="separator">In case of more values specifies the separator among the values. If <see langword="null"/>&#160;or is empty, then comma (<c>,</c>) separator is used.</param>
        /// <param name="ignoreCase">If <see langword="true"/>, ignores case; otherwise, regards case.</param>
        /// <param name="result">Returns the default value of <typeparamref name="TEnum"/>, if return value is <see langword="false"/>; otherwise, the parsed <see langword="enum"/>&#160;value.</param>
        /// <returns><see langword="false"/>&#160;if the <see cref="string">string</see> in <paramref name="value"/> parameter cannot be parsed as <typeparamref name="TEnum"/>; otherwise, <see langword="true"/>.</returns>
        /// <exception cref="ArgumentNullException"><paramref name="value"/> is <see langword="null"/>.</exception>
        public static bool TryParse(string value, string separator, bool ignoreCase, out TEnum result)
        {
            if (value == null)
            {
                Throw.ArgumentNullException(Argument.value);
            }

            // simple name match test (always case-sensitive)
            if (NameValuePairs.TryGetValue(value, out result))
            {
                return(true);
            }

            var s = new StringSegmentInternal(value);

            s.Trim();
            result = default(TEnum);
            if (s.Length == 0)
            {
                return(false);
            }

            // simple numeric value
            char c = s[0];

            if (((c >= '0' && c <= '9') || c == '-' || c == '+') && s.TryParseIntQuick(underlyingInfo.IsSigned, underlyingInfo.MaxValue, out ulong numericValue))
            {
                result = converter.ToEnum(numericValue);
                return(true);
            }

            // rest: flags enum or ignored case
            if (String.IsNullOrEmpty(separator))
            {
                separator = EnumExtensions.DefaultParseSeparator;
            }

            ulong acc = 0UL;
            StringKeyedDictionary <ulong> dict = ignoreCase ? NameRawValuePairsIgnoreCase : NameRawValuePairs;

            while (s.TryGetNextSegment(separator, out StringSegmentInternal token))
            {
                token.Trim();
                if (token.Length == 0)
                {
                    return(false);
                }

                // literal token found in dictionary
                if (dict.TryGetValue(token, out ulong tokens))
                {
                    acc |= tokens;
                    continue;
                }

                // checking if is numeric token
                c = token[0];
                if (((c >= '0' && c <= '9') || c == '-' || c == '+') && token.TryParseIntQuick(underlyingInfo.IsSigned, underlyingInfo.MaxValue, out numericValue))
                {
                    acc |= numericValue;
                    continue;
                }

                // none of above
                return(false);
            }

            result = converter.ToEnum(acc);
            return(true);
        }
Example #7
0
 internal override int GetHashCode(StringSegmentInternal obj) => obj.GetHashCode();
Example #8
0
 internal override bool Equals(StringSegmentInternal x, string y) => x.Equals(y);
Example #9
0
 internal override bool Equals(StringSegmentInternal x, string y) => Throw.InternalError <bool>("Not expected to be called");
Example #10
0
 internal override int GetHashCode(StringSegmentInternal obj) => Throw.InternalError <int>("Not expected to be called");
Example #11
0
 internal override int GetHashCode(StringSegmentInternal obj) => obj.GetHashCodeOrdinalIgnoreCase();
Example #12
0
 internal override bool Equals(StringSegmentInternal x, string y) => x.EqualsOrdinalIgnoreCase(y);
Example #13
0
            private static bool TryParseKnownValueType <T>(string s, CultureInfo culture, out T value)
            {
                Debug.Assert(typeof(T).IsValueType, "T must be a value type so the branches can be optimized away by the JIT compiler");
                // Important:
                // - Branches will be optimized away by JIT but only if we use typeof(SomeValueType) and not Reflector.XXXType
                // - In release build there will be no boxing for (T)(object)value and the JITted code will be much
                //   simpler compared to the usually more elegant pattern matching

                if (typeof(T) == typeof(bool))
                {
                    var segment = new StringSegmentInternal(s);
                    segment.Trim();
                    if (segment.EqualsOrdinalIgnoreCase(Boolean.FalseString))
                    {
                        value = (T)(object)false;
                        return(true);
                    }

                    if (segment.EqualsOrdinalIgnoreCase(Boolean.TrueString))
                    {
                        value = (T)(object)true;
                        return(true);
                    }

                    // allowing also an integer, which will be true for nonzero value
                    if (segment.TryParseIntQuick(true, Int64.MaxValue, out ulong result))
                    {
                        value = (T)(object)(result != 0L);
                        return(true);
                    }

                    value = default;
                    return(false);
                }

                if (typeof(T) == typeof(byte))
                {
                    if (Byte.TryParse(s, NumberStyles.Integer, culture, out byte result))
                    {
                        value = (T)(object)result;
                        return(true);
                    }
                }

                if (typeof(T) == typeof(sbyte))
                {
                    if (SByte.TryParse(s, NumberStyles.Integer, culture, out sbyte result))
                    {
                        value = (T)(object)result;
                        return(true);
                    }
                }

                if (typeof(T) == typeof(short))
                {
                    if (Int16.TryParse(s, NumberStyles.Integer, culture, out short result))
                    {
                        value = (T)(object)result;
                        return(true);
                    }
                }

                if (typeof(T) == typeof(ushort))
                {
                    if (UInt16.TryParse(s, NumberStyles.Integer, culture, out ushort result))
                    {
                        value = (T)(object)result;
                        return(true);
                    }
                }

                if (typeof(T) == typeof(int))
                {
                    if (Int32.TryParse(s, NumberStyles.Integer, culture, out int result))
                    {
                        value = (T)(object)result;
                        return(true);
                    }
                }

                if (typeof(T) == typeof(uint))
                {
                    if (UInt32.TryParse(s, NumberStyles.Integer, culture, out uint result))
                    {
                        value = (T)(object)result;
                        return(true);
                    }
                }

                if (typeof(T) == typeof(long))
                {
                    if (Int64.TryParse(s, NumberStyles.Integer, culture, out long result))
                    {
                        value = (T)(object)result;
                        return(true);
                    }
                }

                if (typeof(T) == typeof(ulong))
                {
                    if (UInt64.TryParse(s, NumberStyles.Integer, culture, out ulong result))
                    {
                        value = (T)(object)result;
                        return(true);
                    }
                }

                if (typeof(T) == typeof(IntPtr))
                {
                    if (Int64.TryParse(s, NumberStyles.Integer, culture, out long result))
                    {
                        value = (T)(object)new IntPtr(result);
                        return(true);
                    }
                }

                if (typeof(T) == typeof(UIntPtr))
                {
                    if (UInt64.TryParse(s, NumberStyles.Integer, culture, out ulong result))
                    {
                        value = (T)(object)new UIntPtr(result);
                        return(true);
                    }
                }

                if (typeof(T) == typeof(char))
                {
                    if (Char.TryParse(s, out char result))
                    {
                        value = (T)(object)result;
                        return(true);
                    }
                }

                if (typeof(T) == typeof(float))
                {
                    if (Single.TryParse(s, floatStyle, culture, out float result))
                    {
                        if (result.Equals(0f) && s.Trim().StartsWith(culture.NumberFormat.NegativeSign, StringComparison.Ordinal))
                        {
                            result = FloatExtensions.NegativeZero;
                        }
                        value = (T)(object)result;
                        return(true);
                    }
                }

                if (typeof(T) == typeof(double))
                {
                    if (Double.TryParse(s, floatStyle, culture, out double result))
                    {
                        if (result.Equals(0d) && s.Trim().StartsWith(culture.NumberFormat.NegativeSign, StringComparison.Ordinal))
                        {
                            result = DoubleExtensions.NegativeZero;
                        }
                        value = (T)(object)result;
                        return(true);
                    }
                }

                if (typeof(T) == typeof(decimal))
                {
                    if (Decimal.TryParse(s, floatStyle, culture, out decimal result))
                    {
                        value = (T)(object)result;
                        return(true);
                    }
                }

                if (typeof(T) == typeof(TimeSpan))
                {
#if NET35
                    if (TimeSpan.TryParse(s, out TimeSpan result))
#else
                    if (TimeSpan.TryParse(s, culture, out TimeSpan result))
#endif
                    {
                        value = (T)(object)result;
                        return(true);
                    }
                }

                if (typeof(T) == typeof(DateTime))
                {
                    s = s.TrimEnd();
                    if (s.Length > 0)
                    {
                        DateTimeStyles style = s[s.Length - 1] == 'Z' ? DateTimeStyles.AdjustToUniversal : DateTimeStyles.None;
                        if (DateTime.TryParse(s, culture, style, out DateTime result))
                        {
                            value = (T)(object)result;
                            return(true);
                        }
                    }
                }

                if (typeof(T) == typeof(DateTimeOffset))
                {
                    s = s.TrimEnd();
                    if (s.Length > 0)
                    {
                        DateTimeStyles style = s[s.Length - 1] == 'Z' ? DateTimeStyles.AdjustToUniversal : DateTimeStyles.None;
                        if (DateTimeOffset.TryParse(s, culture, style, out DateTimeOffset result))
                        {
                            value = (T)(object)result;
                            return(true);
                        }
                    }
                }

                value = default;
                return(false);
            }