Skip to content

Commit

Permalink
Version 7.1.5 published.
Browse files Browse the repository at this point in the history
  • Loading branch information
Bruno de Souza Melo committed Nov 2, 2023
1 parent 4749068 commit 019eb9c
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 7 deletions.
4 changes: 2 additions & 2 deletions src/NuvTools.Common/NuvTools.Common.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
<SignAssembly>True</SignAssembly>
<AssemblyOriginatorKeyFile>NuvTools.Common.snk</AssemblyOriginatorKeyFile>
<Description>Common library for Web, Desktop and Mobile (MAUI) applications.</Description>
<Version>7.1.3</Version>
<Version>7.1.5</Version>
<GenerateDocumentationFile>True</GenerateDocumentationFile>
<EnforceCodeStyleInBuild>True</EnforceCodeStyleInBuild>
<PackageIcon>icon.png</PackageIcon>
Expand All @@ -20,7 +20,7 @@
<RepositoryType>git</RepositoryType>
<AnalysisLevel>latest</AnalysisLevel>
<PackageReadmeFile>README.md</PackageReadmeFile>
<PackageTags>NuvTools Calc Enumerator Regex Serialization ResultWrapper</PackageTags>
<PackageTags>NuvTools Calc Enumerator Regex Strings Serialization ResultWrapper</PackageTags>
<ImplicitUsings>true</ImplicitUsings>
</PropertyGroup>

Expand Down
91 changes: 87 additions & 4 deletions src/NuvTools.Common/Strings/StringExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,19 @@
using System.Globalization;
using System.Text;
using System.Text.Json;
using System.Text.RegularExpressions;

namespace NuvTools.Common.Strings;

public static class StringExtensions
{
/// <summary>
/// Gets the first characters from string.
/// </summary>
/// <param name="value">String that contains the characters to be extracted.</param>
/// <param name="length">The number of characters to be extracted.</param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
public static string Left(this string value, int length)
{
if (string.IsNullOrEmpty(value)) throw new ArgumentNullException(nameof(value));
Expand All @@ -15,6 +23,13 @@ public static string Left(this string value, int length)
return value.Length <= length ? value : value[..length];
}

/// <summary>
/// Gets the last characters from string.
/// </summary>
/// <param name="value">String that contains the characters to be extracted.</param>
/// <param name="length">The number of characters to be extracted.</param>
/// <returns></returns>
/// <exception cref="ArgumentNullException"></exception>
public static string Right(this string value, int length)
{
if (string.IsNullOrEmpty(value)) throw new ArgumentNullException(nameof(value));
Expand All @@ -24,13 +39,81 @@ public static string Right(this string value, int length)
return value.Length <= length ? value : value.Substring(value.Length - length, length);
}

public static string Format(this string format, params string[] values)
/// <summary>
/// Replaces the format item in a specified string with the string representation of a corresponding object by the key in the Dictionary.
/// </summary>
/// <param name="template">A composite format string.</param>
/// <param name="args">A string array that contains zero or more objects to format.</param>
/// <returns>A copy of format in which the format items have been replaced by the string representation of the corresponding strings in args.</returns>
/// <exception cref="ArgumentNullException"></exception>
public static string Format(this string template, params object[] args)
{
if (string.IsNullOrEmpty(format)) throw new ArgumentNullException(nameof(format));
if (string.IsNullOrEmpty(template)) throw new ArgumentNullException(nameof(template));
return template.Format(null, args);
}

/// <summary>
/// Replaces the format item in a specified string with the string representation of a corresponding object by the key in the Dictionary.
/// </summary>
/// <param name="template">A composite format string.</param>
/// <param name="args">A string array that contains zero or more objects to format.</param>
/// <param name="provider">An object that supplies culture-specific formatting information.</param>
/// <returns>A copy of format in which the format items have been replaced by the string representation of the corresponding strings in args.</returns>
/// <exception cref="ArgumentNullException"></exception>
public static string Format(this string template, IFormatProvider provider, params object[] args)
{
if (string.IsNullOrEmpty(template)) throw new ArgumentNullException(nameof(template));
if (args == null || args.Length == 0) throw new ArgumentNullException(nameof(args));

var dictionary = new Dictionary<string, object>();

for (int i = 0; i < args.Length; i++)
dictionary.Add(i.ToString(), args[i]);

return string.Format(format, values);
return template.Format(dictionary, provider);
}

/// <summary>
/// Replaces the format item in a specified string with the string representation of a corresponding object by the key in the Dictionary.
/// </summary>
/// <param name="template">A composite format string.</param>
/// <param name="args">A Dictionary that contains zero or more values to format by the key.</param>
/// <param name="provider">An object that supplies culture-specific formatting information.</param>
/// <returns>A copy of format in which the format items have been replaced by the string representation of the corresponding values in Dictionary.</returns>
/// <exception cref="ArgumentNullException"></exception>
public static string Format(this string template, Dictionary<string, object> args, IFormatProvider provider = null)
{
if (string.IsNullOrEmpty(template)) throw new ArgumentNullException(nameof(template));

if (args == null || args.Count == 0) throw new ArgumentNullException(nameof(args));

var regex = new Regex("{(?<variable>\\w+)(:(?<format>[\\w\\/]+))?\\}");
var templateTokens = regex.Matches(template).Select(e => e.Groups["variable"]).Select(e => e.Value).Distinct().ToList();

if (templateTokens.Count == 0) return template;

var dicIndex = new Dictionary<int, object>();
var index = -1;
foreach (var token in templateTokens)
{
index++;
args.TryGetValue(token, out var valueDic);

if (valueDic == null) args.TryGetValue(index.ToString(), out valueDic);

dicIndex.Add(index, valueDic);

template = regex.Replace(template, m =>
{
string variable = m.Groups["variable"].Value;
string format = m.Groups["format"].Value;
return $"{{{(variable == token ? index : variable)}{(!string.IsNullOrEmpty(format) ? ":" + format : string.Empty)}}}";
});
}

return string.Format(provider, template, dicIndex.Values.ToArray());
}

/// <summary>
/// Remove a sign, such as an accent or cedill.
Expand Down Expand Up @@ -73,7 +156,7 @@ public static string RemoveSpecialCharacters(this string value)
}

/// <summary>
/// Format the string to Json pretty-format.
/// Format the string to pretty-format Json.
/// </summary>
/// <param name="value">Json content.</param>
/// <returns></returns>
Expand Down
57 changes: 56 additions & 1 deletion tests/NuvTools.Common.Test/Strings/StringExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
using NUnit.Framework;
using NuvTools.Common.Strings;
using System;
using System.Collections.Generic;
using System.Globalization;

namespace NuvTools.Common.Tests.Strings
{
Expand All @@ -9,9 +12,61 @@ public class StringExtensions
[Test()]
public void FormatTest()
{
Assert.AreEqual("{0} Company".Format("Nuv Tools"), "Nuv Tools Company");
Assert.AreEqual("{0} Company {year} and profit {value:N2}".Format("Nuv Tools", 2023, 64.2893), "Nuv Tools Company 2023 and profit 64.29");
}

[Test()]
public void FormatDictionaryTest()
{
string value = "{0} testing {something} useful to {framework} and {something} " +
"again on {holiday:dd/MM/yyyy} and {notindictionary}. Only for {value:N2}";

Dictionary<string, object> variables = new(){
{ "0", "Bruno" },
{ "something", "Format Function" },
{ "framework", "Nuv Tools" },
{ "holiday", new DateTime(2023, 11,02,10,11,12) },
{ "value", 45.3532 }
};

Assert.AreEqual(value.Format(variables), "Bruno testing Format Function useful to Nuv Tools and Format Function again on 02/11/2023 and . Only for 45.35");
}

[Test()]
public void FormatDictionaryEmptyTest()
{
string value = "Nothing to replace";

Dictionary<string, object> variables = new(){
{ "0", "Bruno" },
{ "something", "Format Function" },
{ "framework", "Nuv Tools" },
{ "holiday", new DateTime(2023, 11,02,10,11,12) },
{ "value", 45.3532 }
};

Assert.AreEqual(value.Format(variables), value);

Assert.Throws<ArgumentNullException>(() => "".Format(new Dictionary<string, object>()));
Assert.Throws<ArgumentNullException>(() => value.Format(new Dictionary<string, object>()));
Assert.Throws<ArgumentNullException>(() => value.Format(null, new CultureInfo("pt-BR")));
}

[Test()]
public void FormatDictionaryCultureTest()
{
string value = "Testing {value:N2} and index {1}";

Dictionary<string, object> variables = new(){
{ "1", "Nuv Tools" },
{ "value", 52.38532 } //will be rounded
};

Assert.AreEqual(value.Format(variables, new CultureInfo("pt-BR")), "Testing 52,39 and index Nuv Tools");
}



[Test()]
public void LeftTest()
{
Expand Down

0 comments on commit 019eb9c

Please sign in to comment.