Click here to Skip to main content
15,886,258 members
Articles / Programming Languages / C#

Resolving Symbolic References in a CodeDOM (Part 7)

Rate me:
Please Sign up or sign in to vote.
4.75/5 (6 votes)
2 Dec 2012CDDL12 min read 19.4K   509   14  
Resolving symbolic references in a CodeDOM.
// The Nova Project by Ken Beckett.
// Copyright (C) 2007-2012 Inevitable Software, all rights reserved.
// Released under the Common Development and Distribution License, CDDL-1.0: http://opensource.org/licenses/cddl1.php

using System;
using System.Collections;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace Nova.Utilities
{
    /// <summary>
    /// Static helper methods for the <see cref="string"/> class.
    /// </summary>
    public static class StringUtil
    {
        #region /* STATIC HELPER METHODS */

        /// <summary>
        /// Check if the specified string is empty, blank, or null.
        /// </summary>
        /// <param name="thisStr">The string to check.</param>
        /// <returns>True if string is empty, blank, or null.</returns>
        public static bool IsEmpty(string thisStr)
        {
            return (thisStr == null || thisStr.Trim() == "");
        }

        /// <summary>
        /// Check if the specified string is NOT empty, blank, or null.
        /// </summary>
        /// <param name="thisStr">The string to check.</param>
        /// <returns>True if string is NOT empty, blank, or null.</returns>
        public static bool NotEmpty(string thisStr)
        {
            return !(thisStr == null || thisStr.Trim() == "");
        }

        /// <summary>
        /// Return null if the string is empty, otherwise leave it unchanged.
        /// </summary>
        /// <param name="thisStr">The string to check.</param>
        /// <returns>Null if the string is empty, otherwise the unchanged string.</returns>
        public static string EmptyAsNull(string thisStr)
        {
            return (thisStr.Trim() == "" ? null : thisStr);
        }

        /// <summary>
        /// Get the length of the specified string, or 0 if it's null.
        /// </summary>
        /// <param name="thisStr">The string to check.</param>
        /// <returns>String length or 0 if null.</returns>
        public static int NNLength(string thisStr)
        {
            return (thisStr != null ? thisStr.Length : 0);
        }

        /// <summary>
        /// Compare if one string equals another, ignoring case and leading/trailing whitespace, and
        /// treating null and empty strings as equivalent.
        /// </summary>
        /// <param name="thisStr">The string to be compared.</param>
        /// <param name="str">The string to be compared to.</param>
        /// <returns>True if the strings are equal, otherwise false.</returns>
        public static bool NNEqualsIgnoreCase(string thisStr, string str)
        {
            return string.Equals((thisStr ?? "").Trim(), (str ?? "").Trim(), StringComparison.OrdinalIgnoreCase);
        }

        /// <summary>
        /// Check if the string contains the specified character, returning false if the string is null.
        /// </summary>
        /// <param name="thisStr">The string being operated on.</param>
        /// <param name="ch">The character being searched for.</param>
        /// <returns>True if the string contains the specified character, otherwise false.</returns>
        public static bool Contains(string thisStr, char ch)
        {
            if (thisStr != null)
                return (thisStr.IndexOf(ch) >= 0);
            return false;
        }

        /// <summary>
        /// Check if the string contains the specified substring using a case-insensitive compare, returning false if the string is null.
        /// </summary>
        /// <param name="thisStr">The string being operated on.</param>
        /// <param name="subString">The sub-string being searched for.</param>
        /// <returns>True if the string contains the specified substring, otherwise false.</returns>
        public static bool ContainsIgnoreCase(string thisStr, string subString)
        {
            if (thisStr != null)
                return (thisStr.IndexOf(subString, StringComparison.CurrentCultureIgnoreCase) >= 0);
            return false;
        }

        /// <summary>
        /// Return the number of consecutive specified chars at the specified starting index.
        /// </summary>
        /// <param name="thisStr">The string being operated on.</param>
        /// <param name="ch">The desired char.</param>
        /// <param name="startIndex">The starting index.</param>
        /// <returns>The number of chars found.</returns>
        public static int CharCount(string thisStr, char ch, int startIndex)
        {
            int count = 0;
            if (thisStr != null)
            {
                int length = thisStr.Length;
                for (int i = startIndex; i < length && thisStr[i] == ch; ++i)
                    ++count;
            }
            return count;
        }

        /// <summary>
        /// Convert all runs of spaces and tabs to a single space, and trim all leading and trailing whitespace.
        /// </summary>
        /// <param name="thisStr">The string to be normalized.</param>
        /// <returns>The normalized string.  An empty string is returned if the input string is null.</returns>
        public static string NormalizeWhitespace(string thisStr)
        {
            return Regex.Replace((thisStr ?? "").Trim(), "[ \t]+", " ");
        }

        /// <summary>
        /// Append one string to another, using an optional separator string if the destination string isn't empty.
        /// Treats both destination and source strings as empty if null.
        /// </summary>
        /// <param name="thisStr">The string to append to.</param>
        /// <param name="separator">The optional separator string to use if the destination string isn't empty.</param>
        /// <param name="str">The string to be appended.</param>
        /// <returns>The new string.</returns>
        public static string Append(string thisStr, string separator, string str)
        {
            return (string.IsNullOrEmpty(thisStr) ? str : (thisStr + separator + str));
        }

        /// <summary>
        /// Format the specified collection into a single string using the specified separating
        /// string to separate each item.  Null items are converted to empty strings.
        /// </summary>
        /// <param name="thisCollection">Collection to be converted to a string.</param>
        /// <param name="separator">Separating string to be inserted between items.</param>
        /// <returns>The collection contents formatted as a string.</returns>
        public static string ToString(IEnumerable thisCollection, string separator)
        {
            string result = "";
            if (thisCollection != null)
            {
                foreach (object obj in thisCollection)
                {
                    if (obj != null)
                        result = Append(result, separator, obj.ToString());
                }
            }
            return result;
        }

        /// <summary>
        /// Check if the specified string array contains the specified string.
        /// </summary>
        /// <param name="thisArray">The array to be searched.</param>
        /// <param name="value">The string value to search for.</param>
        /// <returns>True if the string array contains the specified value.</returns>
        public static bool Contains(string[] thisArray, string value)
        {
            bool contains = false;
            if (thisArray != null)
            {
                foreach (string str in thisArray)
                {
                    if (str == value)
                    {
                        contains = true;
                        break;
                    }
                }
            }
            return contains;
        }

        /// <summary>
        /// Convert a string to an int, returning a default value if the string is null or isn't a valid integer value.
        /// </summary>
        /// <param name="thisStr">The string to parse.</param>
        /// <param name="defaultValue">The value to return if parsing fails.</param>
        /// <returns>The parsed int value.</returns>
        public static int ParseInt(string thisStr, int defaultValue)
        {
            int val;
            return (int.TryParse(thisStr, out val) ? val : defaultValue);
        }

        /// <summary>
        /// Convert a string to an int, defaulting to 0 if the string is null or isn't a valid integer value.
        /// </summary>
        /// <param name="thisStr">The string to parse.</param>
        /// <returns>The parsed value.</returns>
        public static int ParseInt(string thisStr)
        {
            return ParseInt(thisStr, 0);
        }

        /// <summary>
        /// Convert a string to a bool, returning a default value if the string is null or isn't a valid bool value.
        /// </summary>
        /// <param name="thisStr">The string to parse.</param>
        /// <param name="defaultValue">The value to return if parsing fails.</param>
        /// <returns>The parsed bool value.</returns>
        public static bool ParseBool(string thisStr, bool defaultValue)
        {
            bool result = defaultValue;
            if (thisStr != null)
            {
                if (NNEqualsIgnoreCase(thisStr, "true") || thisStr.Trim() == "1" || NNEqualsIgnoreCase(thisStr, "yes") || NNEqualsIgnoreCase(thisStr, "y"))
                    result = true;
                else if (NNEqualsIgnoreCase(thisStr, "false") || thisStr.Trim() == "0" || NNEqualsIgnoreCase(thisStr, "no") || NNEqualsIgnoreCase(thisStr, "n"))
                    result = false;
            }
            return result;
        }

        /// <summary>
        /// Convert a string to a bool, returning false if the string is null or isn't a valid bool value.
        /// </summary>
        /// <param name="thisStr">The string to parse.</param>
        /// <returns>The parsed bool value.</returns>
        public static bool ParseBool(string thisStr)
        {
            return ParseBool(thisStr, false);
        }

        /// <summary>
        /// Convert a string to a double, returning a default value if the string is null or isn't a valid double value.
        /// </summary>
        /// <param name="thisStr">The string to parse.</param>
        /// <param name="defaultValue">The value to return if parsing fails.</param>
        /// <returns>The parsed double value.</returns>
        public static double ParseDouble(string thisStr, double defaultValue)
        {
            double val;
            return (double.TryParse(thisStr, out val) ? val : defaultValue);
        }

        /// <summary>
        /// Convert a string to a double, defaulting to 0 if the string is null or isn't a valid double value.
        /// </summary>
        /// <param name="thisStr">The string to parse.</param>
        /// <returns>The parsed value.</returns>
        public static double ParseDouble(string thisStr)
        {
            return ParseDouble(thisStr, 0);
        }

        /// <summary>
        /// Convert a string to a DateTime, returning a default value if the string is null or isn't a valid DateTime value.
        /// </summary>
        /// <param name="thisStr">The string to parse.</param>
        /// <param name="defaultValue">The value to return if parsing fails.</param>
        /// <returns>The parsed DateTime value.</returns>
        public static DateTime ParseDateTime(string thisStr, DateTime defaultValue)
        {
            DateTime val;
            return (DateTime.TryParse(thisStr, out val) ? val : defaultValue);
        }

        /// <summary>
        /// Convert a string to a DateTime, returning DateTime.MinValue if the string is null or isn't a valid DateTime value.
        /// </summary>
        /// <param name="thisStr">The string to parse.</param>
        /// <returns>The parsed DateTime value.</returns>
        public static DateTime ParseDateTime(string thisStr)
        {
            return ParseDateTime(thisStr, DateTime.MinValue);
        }

        /// <summary>
        /// Convert a string to an enum value, returning a default value if the string is null or isn't a valid enum value.
        /// </summary>
        /// <typeparam name="T">The type of the enum.</typeparam>
        /// <param name="thisStr">The string to parse.</param>
        /// <param name="defaultValue">The value to return if parsing fails.</param>
        /// <returns>The parsed enum value.</returns>
        public static T ParseEnum<T>(string thisStr, T defaultValue) where T : struct
        {
#if !TARGET_FRAMEWORK_3_5
            T result;
            return (Enum.TryParse(thisStr, out result) ? result : defaultValue);
#else
            T result = defaultValue;
            if (thisStr != null && thisStr.Count > 0)
            {
                try
                {
                    result = (T)Enum.Parse(typeof(T), thisStr, true);
                }
                catch { }
            }
            return result;
#endif
        }

        /// <summary>
        /// Convert a string to a generic value.
        /// </summary>
        /// <typeparam name="T">The generic type.</typeparam>
        /// <param name="thisStr">The string to parse.</param>
        /// <returns>The generic value</returns>
        public static T Parse<T>(string thisStr) where T : IConvertible
        {
            return (T)Convert.ChangeType(thisStr, typeof(T));
        }

        /// <summary>
        /// Convert a string to a generic value.
        /// </summary>
        /// <typeparam name="T">The generic type.</typeparam>
        /// <param name="thisStr">The string to parse.</param>
        /// <param name="defaultValue">The value to return if parsing fails</param>
        /// <returns>The generic value</returns>
        public static T Parse<T>(string thisStr, T defaultValue) where T : IConvertible
        {
            T result = defaultValue;
            if (!string.IsNullOrEmpty(thisStr))
            {
                try
                {
                    result = (T)Convert.ChangeType(thisStr, typeof(T));
                }
                catch { }
            }
            return result;
        }

        /// <summary>
        /// Convert a comma delimited string to an array of generic values
        /// </summary>
        /// <typeparam name="T">The generic type.</typeparam>
        /// <param name="thisStr">The string to parse.</param>
        /// <param name="defaultValues">The values to return if parsing fails</param>
        /// <param name="delim">The delimiter for fields in the string</param>
        /// <returns>An array of generic values</returns>
        public static T[] ParseArray<T>(string thisStr, T[] defaultValues, char delim) where T : IConvertible
        {
            T[] results = defaultValues;
            if (!string.IsNullOrEmpty(thisStr))
            {
                try
                {
                    IEnumerable<T> fields = Enumerable.Select<string, T>(thisStr.Split(delim), delegate(string text) { return Parse<T>(text); });
                    results = Enumerable.ToArray(fields);
                }
                catch { }
            }
            return results;
        }

        /// <summary>
        /// Convert a comma delimited string to an array of generic values
        /// </summary>
        /// <typeparam name="T">The generic type.</typeparam>
        /// <param name="thisStr">The string to parse.</param>
        /// <param name="defaultValues">The values to return if parsing fails</param>
        /// <returns>An array of generic values </returns>
        public static T[] ParseArray<T>(string thisStr, T[] defaultValues) where T : IConvertible
        {
            return ParseArray(thisStr, defaultValues, ',');
        }

        /// <summary>
        /// Expand any $(NAME) or %NAME% macros in the specified string with environment variable values.
        /// </summary>
        public static string ExpandEnvironmentMacros(string value)
        {
            if (!string.IsNullOrEmpty(value))
            {
                Regex regex = new Regex(@"%(\w+)%|\$\((\w+)\)");
                MatchCollection matches = regex.Matches(value);
                if (matches.Count > 0)
                {
                    string result = null;
                    int index = 0;
                    for (int i = 0; i < matches.Count; ++i)
                    {
                        Match match = matches[i];
                        int skippedLength = match.Index - index;
                        result += value.Substring(index, skippedLength);
                        index += skippedLength;
                        for (int j = 1; j < match.Groups.Count; ++j)
                        {
                            Group group = match.Groups[j];
                            if (group.Length > 0)
                            {
                                string macro = group.Value;
                                result += Environment.GetEnvironmentVariable(macro);
                            }
                        }
                        index += match.Length;
                    }
                    result += value.Substring(index);
                    return result;
                }
            }
            return value;
        }

        /// <summary>
        /// Convert all unicode escape sequences in the specified string that represent letters or digits into chars.
        /// </summary>
        /// <param name="source">The string to be converted.</param>
        /// <returns>A new string with unicode escapes converted to chars.</returns>
        public static string ConvertUnicodeEscapes(string source)
        {
            StringBuilder result = null;
            int i, start = 0;
            for (i = 0; i < source.Length; )
            {
                if (source[i] == '\\')
                {
                    // Check for "\uXXXX" or "\UXXXXXXXX"
                    int len = 0;
                    if (source[i + 1] == 'u')
                        len = 4;
                    else if (source[i + 1] == 'U')
                        len = 8;
                    if (len > 0)
                    {
                        try
                        {
                            if (CheckHex(source, i + 2, len))
                            {
                                // Convert 16-bit values to chars, or 32-bit values to surrogates (double chars)
                                if (result == null)
                                    result = new StringBuilder();
                                result.Append(source, start, i - start);
                                string hex = source.Substring(i + 2, len);
                                if (len == 4)
                                {
                                    ushort u16 = ushort.Parse(hex, NumberStyles.HexNumber);
                                    result.Append((char)u16);
                                }
                                else
                                {
                                    int u32 = int.Parse(hex, NumberStyles.HexNumber);
                                    result.Append(char.ConvertFromUtf32(u32));
                                }
                                i += 2 + len;
                                start = i;
                                continue;
                            }
                        }
                        catch { }
                    }
                }
                ++i;
            }
            return (result == null ? source : result.Append(source, start, i - start).ToString());
        }

        private static bool CheckHex(string str, int offset, int len)
        {
            for (int i = offset; i < offset + len; ++i)
            {
                if (!Uri.IsHexDigit(str[i]))
                    return false;
            }
            return true;
        }

        #endregion
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Common Development and Distribution License (CDDL)


Written By
Software Developer (Senior)
United States United States
I've been writing software since the late 70's, currently focusing mainly on C#.NET. I also like to travel around the world, and I own a Chocolate Factory (sadly, none of my employees are oompa loompas).

Comments and Discussions