Click here to Skip to main content
Click here to Skip to main content
Add your own
alternative version

Resolving Symbolic References in a CodeDOM (Part 7)

, 2 Dec 2012
Resolving symbolic references in a CodeDOM.
Nova.0.6.exe.zip
Nova.0.6.zip
Nova.CLI
Properties
Nova.CodeDOM
CodeDOM
Annotations
Base
Comments
Base
DocComments
CodeRef
Base
List
Name
Base
Other
Simple
CompilerDirectives
Base
Conditionals
Base
Messages
Base
Pragmas
Base
Symbols
Base
Base
Interfaces
Expressions
AnonymousMethods
Base
Operators
Base
Binary
Arithmetic
Base
Assignment
Base
Bitwise
Base
Conditional
Relational
Base
Shift
Base
Other
Base
Unary
Base
Other
References
Base
GotoTargets
Base
Methods
Namespaces
Other
Properties
Types
Base
Variables
Base
Projects
Assemblies
Namespaces
References
Base
Statements
Base
Conditionals
Base
Exceptions
Generics
Constraints
Base
Iterators
Base
Jumps
Loops
Methods
OperatorDecls
Miscellaneous
Namespaces
Properties
Base
Events
Types
Base
Variables
Base
Parsing
Base
Properties
Rendering
Resolving
Utilities
Mono.Cecil
Reflection
Nova.Examples
Properties
Nova.Studio
Images
About.png
Configuration.png
EditCopy.png
EditCut.png
EditDelete.png
EditPaste.png
EditRedo.png
EditUndo.png
Error.png
Exit.png
FileNew.png
FileOpen.png
FileSave.png
FileSaveAll.png
FileSaveAs.png
Find.png
Help.png
Info.png
Logo.png
Options.png
Print.png
PrintPreview.png
Properties.png
Todo.png
Warning.png
Objects.ico
Properties
Settings.settings
Nova.Test
Properties
Nova.UI
CodeDOM
Annotations
Base
Comments
Base
DocComments
CodeRef
Base
List
Name
Base
Other
Simple
CompilerDirectives
Base
Conditionals
Base
Messages
Base
Pragmas
Base
Symbols
Base
Base
Expressions
AnonymousMethods
Base
Operators
Base
Binary
Arithmetic
Base
Assignment
Base
Bitwise
Base
Conditional
Relational
Base
Shift
Base
Other
Base
Unary
Base
Other
References
Base
GotoTargets
Base
Methods
Namespaces
Other
Properties
Types
Base
Variables
Base
Projects
Namespaces
References
Base
Statements
Base
Conditionals
Base
Exceptions
Generics
Constraints
Base
Iterators
Base
Jumps
Loops
Methods
OperatorDecls
Miscellaneous
Namespaces
Properties
Base
Events
Types
Base
Variables
Base
Properties
Resolving
Utilties
// 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)

Share

About the Author

KenBeckett
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).

| Advertise | Privacy | Mobile
Web02 | 2.8.140827.1 | Last Updated 2 Dec 2012
Article Copyright 2012 by KenBeckett
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid