using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using Developpez.Dotnet.Collections;
using System.IO;
using System.Globalization;
namespace Developpez.Dotnet
{
///
/// Fournit des méthodes d'extension pour les chaines de caractères
///
public static class StringExtensions
{
///
/// Indique si une chaine est nulle ou vide
///
/// la chaine à tester
/// true si la chaine est nulle ou vide, false sinon
public static bool IsNullOrEmpty(this string s)
{
return string.IsNullOrEmpty(s);
}
///
/// Formate la chaine avec les valeurs spécifiées, de la même façon que
/// String.Format
///
/// La chaine de format
/// les valeurs à utiliser
/// La chaine formatée
public static string FormatWith(this string format, params object[] args)
{
return string.Format(format, args);
}
///
/// Inverse l'ordre des caractères d'une chaine
///
/// La chaine à inverser
/// La chaine inversée
public static string Reverse(this string s)
{
s.CheckArgumentNull("s");
bool wasFormD = false;
if (s.IsNormalized(NormalizationForm.FormD))
{
wasFormD = true;
s = s.Normalize(NormalizationForm.FormC);
}
s = new String((s as IEnumerable).Reverse().ToArray());
if (wasFormD)
{
s = s.Normalize(NormalizationForm.FormD);
}
return s;
}
///
/// Concatène toutes les chaines de la liste en plaçant le séparateur
/// spécifié entre chaque chaine
///
/// La liste de chaines à concaténer
/// Le séparateur à utiliser
/// La concaténation des chaines de la liste
public static string Join(this IEnumerable list, string separator)
{
list.CheckArgumentNull("list");
return string.Join(separator, list.ToArray());
}
///
/// Renvoie une chaine construite à partir d'une séquence de caractères
///
/// La séquence de caractères à transformer en chaine
/// Une chaine constituée des caractères de la séquence
public static string Join(this IEnumerable chars)
{
return new string(chars.ToArray());
}
///
/// Renvoie toutes les lignes d'une chaine de caractères
///
/// La chaine à découper en lignes
/// La liste des lignes de cette chaine
public static IEnumerable GetLines(this string s)
{
s.CheckArgumentNull("s");
return GetLinesIterator(s);
}
private static IEnumerable GetLinesIterator(this string s)
{
using (StringReader reader = new StringReader(s))
{
string line;
while ((line = reader.ReadLine()) != null)
{
yield return line;
}
}
}
private static MD5 _md5;
///
/// Renvoie le hash MD5 de la chaîne sous forme d'une chaine hexadécimale, en
/// se basant sur l'encodage ASCII
///
/// la chaine dont on veut obtenir le hash MD5
/// le hash MD5 sous forme d'une chaine hexadécimale
public static string GetMD5Digest(this string s)
{
return s.GetMD5Digest(Encoding.ASCII);
}
///
/// Renvoie le hash MD5 de la chaîne sous forme d'une chaine hexadécimale, en
/// se basant sur l'encodage spécifié
///
/// la chaine dont on veut obtenir le hash MD5
/// L'encodage à utiliser
/// le hash MD5 sous forme d'une chaine hexadécimale
public static string GetMD5Digest(this string s, Encoding encoding)
{
if (_md5 == null)
{
_md5 = MD5.Create();
}
byte[] stringBytes = encoding.GetBytes(s);
byte[] hashBytes = _md5.ComputeHash(stringBytes);
string hash = hashBytes.FormatAll("x2", null);
return hash;
}
///
/// Enlève les caractères diacritiques (accents, cédilles...) d'une chaine en les remplaçant par le
/// caractère de base.
///
/// La chaine dont on veut enlever les diacritiques
/// La chaine sans les diacritiques
public static string RemoveDiacritics(this string s)
{
s.CheckArgumentNull("s");
string formD = s.Normalize(NormalizationForm.FormD);
string noDiacriticsFormD = new string(
(formD as IEnumerable)
.Where(c => CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark)
.ToArray());
string noDiacritics = noDiacriticsFormD.Normalize(NormalizationForm.FormC);
return noDiacritics;
}
///
/// Retourne une chaîne contenant un nombre spécifié de caractères en partant de la gauche d'une chaîne.
///
/// chaine dont les caractères situés le plus à gauche sont retournés
/// Nombre de caractères à retourner
/// une chaîne contenant le nombre spécifié de caractères en partant de la gauche de s
public static string Left(this string s, int count)
{
if (count < 0 || count > s.Length)
throw new ArgumentOutOfRangeException("count", ExceptionMessages.SubstringCountOutOfRange);
return s.Substring(0, count);
}
///
/// Retourne une chaîne contenant un nombre spécifié de caractères en partant de la droite d'une chaîne.
///
/// chaine dont les caractères situés le plus à droite sont retournés
/// Nombre de caractères à retourner
/// une chaîne contenant le nombre spécifié de caractères en partant de la droite de s
public static string Right(this string s, int count)
{
if (count < 0 || count > s.Length)
throw new ArgumentOutOfRangeException("count", ExceptionMessages.SubstringCountOutOfRange);
return s.Substring(s.Length - count, count);
}
///
/// Renvoie un dictionnaire contenant le nombre d'occurences de chaque caractère de la chaine
///
/// La chaine pour laquelle on veut compter les caractères
/// Un dictionnaire contenant le nombre d'occurences de chaque caractère
public static IDictionary GetCharFrequencies(this string s)
{
var frequencies = new DefaultDictionary();
foreach (char c in s) frequencies[c]++;
return frequencies;
}
#region From/To
///
/// Renvoie une portion de chaine à partir de la position spécifiée
///
/// Chaine dont on veut extraire une portion
/// Position de début de la portion
/// La portion de chaine demandée
public static SubStringFrom From(this string s, int start)
{
return new SubStringFrom(s, start);
}
///
/// Termine une portion de chaine à la position spécifiée
///
/// Portion de chaine à terminer
/// Position de fin
/// La portion de chaine demandée
public static string To(this SubStringFrom subStringFrom, int end)
{
return subStringFrom.String.Substring(subStringFrom.Start, end - subStringFrom.Start + 1);
}
///
/// Renvoie une portion de chaine à partir de la sous-chaine spécifiée, sans inclure cette dernière
///
/// Chaine dont on veut extraire une portion
/// Sous-chaine de début de la portion
/// La portion de chaine demandée
public static SubStringFrom From(this string s, string start)
{
return s.From(start, false);
}
///
/// Renvoie une portion de chaine à partir de la sous-chaine spécifiée, en incluant éventuellement cette dernière
///
/// Chaine dont on veut extraire une portion
/// Sous-chaine de début de la portion
/// true pour inclure la chaine de début spécifiée dans le résultat, false sinon
/// La portion de chaine demandée
public static SubStringFrom From(this string s, string start, bool includeBoundary)
{
int iStart = s.IndexOf(start);
if (!includeBoundary && iStart >= 0)
iStart += start.Length;
return new SubStringFrom(s, iStart);
}
///
/// Termine une portion de chaine à la sous-chaine spécifiée, sans inclure cette dernière
///
/// Portion de chaine à terminer
/// Sous-chaine de fin
/// La portion de chaine demandée
public static string To(this SubStringFrom subStringFrom, string end)
{
return subStringFrom.To(end, false);
}
///
/// Termine une portion de chaine à la sous-chaine spécifiée, en incluant éventuellement cette dernière
///
/// Portion de chaine à terminer
/// Sous-chaine de fin
/// true pour inclure la chaine de fin spécifiée, false sinon
/// La portion de chaine demandée
public static string To(this SubStringFrom subStringFrom, string end, bool includeBoundary)
{
string s = subStringFrom.String;
int iStart = subStringFrom.Start;
int iEnd = s.IndexOf(end, iStart);
if (includeBoundary && iEnd > 0)
iEnd += end.Length;
if (iStart < 0 || iEnd < 0)
return String.Empty;
return s.Substring(iStart, iEnd - iStart);
}
///
/// Représente une portion d'une chaine de caractères à partir d'une position donnée
///
public class SubStringFrom
{
internal SubStringFrom(string s, int start)
{
this.String = s;
this.Start = start;
}
///
/// La chaine dont cet objet représente une portion
///
public string String { get; private set; }
///
/// La position de départ de la portion de chaine
///
public int Start { get; private set; }
///
/// Convertit implicitement un SubStringForm en String
///
/// SubStringForm à convertir
/// La chaine correspondante
public static implicit operator string(SubStringFrom subStringFrom)
{
if (subStringFrom.Start < 0)
return String.Empty;
return subStringFrom.String.Substring(subStringFrom.Start);
}
}
#endregion
}
}