2016-08-03 10:59:49 +00:00
//---------------------------------------------------------------------
// <copyright file="StringUtil.cs" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
//
2017-08-21 15:34:15 +00:00
// @owner Microsoft
// @backupOwner Microsoft
2016-08-03 10:59:49 +00:00
//---------------------------------------------------------------------
using System ;
using System.Collections ;
using System.Collections.Generic ;
using System.Text ;
using System.Globalization ;
using System.Diagnostics ;
namespace System.Data.Common.Utils {
// This class provides some useful string utilities, e.g., converting a
// list to string.
internal static class StringUtil {
private const string s_defaultDelimiter = ", " ;
#region String Conversion - Unsorted
/// <summary>
/// Converts an enumeration of values to a delimited string list.
/// </summary>
/// <typeparam name="T">Type of elements to convert.</typeparam>
/// <param name="values">Values. If null, returns empty string.</param>
/// <param name="converter">Converter. If null, uses default invariant culture converter.</param>
/// <param name="delimiter">Delimiter. If null, uses default (', ')</param>
/// <returns>Delimited list of values in string.</returns>
internal static string BuildDelimitedList < T > ( IEnumerable < T > values , ToStringConverter < T > converter , string delimiter ) {
if ( null = = values ) { return String . Empty ; }
if ( null = = converter ) { converter = new ToStringConverter < T > ( InvariantConvertToString < T > ) ; }
if ( null = = delimiter ) { delimiter = s_defaultDelimiter ; }
StringBuilder sb = new StringBuilder ( ) ;
bool first = true ;
foreach ( T value in values ) {
if ( first ) { first = false ; }
else { sb . Append ( delimiter ) ; }
sb . Append ( converter ( value ) ) ;
}
return sb . ToString ( ) ;
}
// effects: Converts list to a string separated by a comma with
// string.Empty used for null values
internal static string ToCommaSeparatedString ( IEnumerable list ) {
return ToSeparatedString ( list , s_defaultDelimiter , string . Empty ) ;
}
// effects: Converts list to a string separated by "separator" with
// "nullValue" used for null values
internal static string ToSeparatedString ( IEnumerable list , string separator , string nullValue ) {
StringBuilder builder = new StringBuilder ( ) ;
ToSeparatedString ( builder , list , separator , nullValue ) ;
return builder . ToString ( ) ;
}
#endregion
#region String Conversion - Sorted
// effects: Converts the list to a list of strings, sorts its
// and then converts to a string separated by a comma with
// string.Empty used for null values
internal static string ToCommaSeparatedStringSorted ( IEnumerable list ) {
return ToSeparatedStringSorted ( list , s_defaultDelimiter , string . Empty ) ;
}
// effects: Converts the list to a list of strings, sorts its using
// StringComparer.Ordinal
// and then converts to a string separated by "separator" with
// with "nullValue" used for null values
internal static string ToSeparatedStringSorted ( IEnumerable list , string separator , string nullValue ) {
StringBuilder builder = new StringBuilder ( ) ;
ToSeparatedStringPrivate ( builder , list , separator , nullValue , true ) ;
return builder . ToString ( ) ;
}
#endregion
#region StringBuilder routines
internal static string MembersToCommaSeparatedString ( IEnumerable members )
{
StringBuilder builder = new StringBuilder ( ) ;
builder . Append ( "{" ) ;
StringUtil . ToCommaSeparatedString ( builder , members ) ;
builder . Append ( "}" ) ;
return builder . ToString ( ) ;
}
internal static void ToCommaSeparatedString ( StringBuilder builder , IEnumerable list ) {
ToSeparatedStringPrivate ( builder , list , s_defaultDelimiter , string . Empty , false ) ;
}
internal static void ToCommaSeparatedStringSorted ( StringBuilder builder , IEnumerable list ) {
ToSeparatedStringPrivate ( builder , list , s_defaultDelimiter , string . Empty , true ) ;
}
internal static void ToSeparatedString ( StringBuilder builder , IEnumerable list , string separator ) {
ToSeparatedStringPrivate ( builder , list , separator , string . Empty , false ) ;
}
internal static void ToSeparatedStringSorted ( StringBuilder builder , IEnumerable list , string separator ) {
ToSeparatedStringPrivate ( builder , list , separator , string . Empty , true ) ;
}
// effects: Modifies stringBuilder to contain a string of values from list
// separated by "separator" with "nullValue" used for null values
internal static void ToSeparatedString ( StringBuilder stringBuilder , IEnumerable list , string separator ,
string nullValue ) {
ToSeparatedStringPrivate ( stringBuilder , list , separator , nullValue , false ) ;
}
// effects: Converts the list to a list of strings, sorts its (if
// toSort is true) and then converts to a string separated by
// "separator" with "nullValue" used for null values.
private static void ToSeparatedStringPrivate ( StringBuilder stringBuilder , IEnumerable list , string separator ,
string nullValue , bool toSort ) {
if ( null = = list ) {
return ;
}
bool isFirst = true ;
// Get the list of strings first
List < string > elementStrings = new List < string > ( ) ;
foreach ( object element in list ) {
string str ;
// Get the element or its default null value
if ( element = = null ) {
str = nullValue ;
} else {
str = FormatInvariant ( "{0}" , element ) ;
}
elementStrings . Add ( str ) ;
}
if ( toSort = = true ) {
// Sort the list
elementStrings . Sort ( StringComparer . Ordinal ) ;
}
// Now add the strings to the stringBuilder
foreach ( string str in elementStrings ) {
if ( false = = isFirst ) {
stringBuilder . Append ( separator ) ;
}
stringBuilder . Append ( str ) ;
isFirst = false ;
}
}
#endregion
#region Some Helper routines
/// <summary>
/// This private static method checks a string to make sure that it is not empty.
/// Comparing with String.Empty is not sufficient since a string with nothing
/// but white space isn't considered "empty" by that rationale.
/// </summary>
internal static bool IsNullOrEmptyOrWhiteSpace ( string value )
{
return IsNullOrEmptyOrWhiteSpace ( value , 0 ) ;
}
internal static bool IsNullOrEmptyOrWhiteSpace ( string value , int offset )
{
// don't use Trim(), which will copy the string, which may be large, just to test for emptyness
//return String.IsNullOrEmpty(value) || String.IsNullOrEmpty(value.Trim());
if ( null ! = value )
{
for ( int i = offset ; i < value . Length ; + + i )
{
if ( ! Char . IsWhiteSpace ( value [ i ] ) )
{
return false ;
}
}
}
return true ;
}
// separate implementation from IsNullOrEmptyOrWhiteSpace(string, int) because that one will
// pick up the jit optimization to avoid boundary checks and the this won't is unknown (most likely not)
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] // referenced by System.Data.Entity.Design.dll
internal static bool IsNullOrEmptyOrWhiteSpace ( string value , int offset , int length )
{
// don't use Trim(), which will copy the string, which may be large, just to test for emptyness
//return String.IsNullOrEmpty(value) || String.IsNullOrEmpty(value.Trim());
if ( null ! = value )
{
length = Math . Min ( value . Length , length ) ;
for ( int i = offset ; i < length ; + + i )
{
if ( ! Char . IsWhiteSpace ( value [ i ] ) )
{
return false ;
}
}
}
return true ;
}
internal static string FormatInvariant ( string format , params object [ ] args ) {
Debug . Assert ( args . Length > 0 , "Formatting utilities must be called with at least one argument" ) ;
return String . Format ( CultureInfo . InvariantCulture , format , args ) ;
}
// effects: Formats args according to the format string and adds it
// to builder. Returns the modified builder
internal static StringBuilder FormatStringBuilder ( StringBuilder builder , string format , params object [ ] args ) {
Debug . Assert ( args . Length > 0 , "Formatting utilities must be called with at least one argument" ) ;
builder . AppendFormat ( CultureInfo . InvariantCulture , format , args ) ;
return builder ;
}
// effects: Generates a new line and then indents the new line by
// indent steps in builder -- indent steps are determined internally
// by this method. Returns the modified builder
internal static StringBuilder IndentNewLine ( StringBuilder builder , int indent ) {
builder . AppendLine ( ) ;
for ( int i = 0 ; i < indent ; i + + ) {
builder . Append ( " " ) ;
}
return builder ;
}
// effects: returns a string of the form 'arrayVarName[index]'
internal static string FormatIndex ( string arrayVarName , int index ) {
System . Text . StringBuilder builder = new System . Text . StringBuilder ( arrayVarName . Length + 10 + 2 ) ;
return builder . Append ( arrayVarName ) . Append ( '[' ) . Append ( index ) . Append ( ']' ) . ToString ( ) ;
}
private static string InvariantConvertToString < T > ( T value ) {
return String . Format ( CultureInfo . InvariantCulture , "{0}" , value ) ;
}
#endregion
#region Delegates
internal delegate string ToStringConverter < T > ( T value ) ;
#endregion
}
}