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); } /// /// Indique si une chaîne est nulle, vide ou composée uniquement d'espaces blancs. /// /// la chaine à tester /// true si la chaine est nulle, vide ou composée uniquement d'espaces blancs, false sinon public static bool IsNullOrWhiteSpace(this string s) { if (s != null) s = s.Trim(); 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()); } /// /// Enumère les lignes d'une chaine de caractères /// /// La chaine à découper en lignes /// La liste des lignes de cette chaine public static IEnumerable ReadLines(this string s) { s.CheckArgumentNull("s"); return ReadLinesIterator(s); } private static IEnumerable ReadLinesIterator(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.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); } /// /// Prend le nombre de caractères spécifié à partir du début de la portion /// /// Portion de chaine à partir de laquelle prendre les caractères /// Nombre de caractères à prendre /// La portion de chaine demandée public static string Take(this SubStringFrom subStringFrom, int count) { return subStringFrom.String.Substring(subStringFrom.Start, count); } /// /// 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 struct SubStringFrom { internal SubStringFrom(string s, int start) : this() { 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) { return subStringFrom.ToString(); } /// /// Renvoie une chaine équivalente à la portion de chaine /// /// Une chaine équivalente à la portion de chaine public override string ToString() { if (this.Start < 0) return String.Empty; return this.String.Substring(this.Start); } } #endregion } }