Skip to content

Commit 29db1e4

Browse files
committed
Добавлены методы CRC для строк и тесты к ним
В проект добавлены методы-расширения для вычисления CRC-8, CRC-16, CRC-32, CRC-64 для строк с поддержкой настройки параметров. Методы ComputeSHA256 и ComputeMD5 перенесены в отдельный partial-класс. Добавлены модульные тесты для проверки корректности вычислений CRC. Обновлены using-директивы и объявление класса StringExtensions.
1 parent 4d73799 commit 29db1e4

3 files changed

Lines changed: 189 additions & 15 deletions

File tree

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
#nullable enable
2+
using System.Runtime.CompilerServices;
3+
using System.Text;
4+
using MathCore.Hash.CRC;
5+
6+
namespace System;
7+
8+
public static partial class StringExtensions
9+
{
10+
/// <summary>Вычисляет SHA256-хеш строки</summary>
11+
/// <param name="text">Исходная строка</param>
12+
/// <param name="encoding">Кодировка</param>
13+
/// <returns>Массив байт с хешем</returns>
14+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
15+
public static byte[] ComputeSHA256(this string text, Encoding? encoding = null) => (encoding ?? Encoding.Default).GetBytes(text).ComputeSHA256();
16+
17+
/// <summary>Вычисляет MD5-хеш строки</summary>
18+
/// <param name="text">Исходная строка</param>
19+
/// <param name="encoding">Кодировка</param>
20+
/// <returns>Массив байт с хешем</returns>
21+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
22+
public static byte[] ComputeMD5(this string text, Encoding? encoding = null) => (encoding ?? Encoding.Default).GetBytes(text).ComputeMD5();
23+
24+
/// <summary>Вычисляет CRC-8 строки</summary>
25+
/// <param name="text">Исходная строка</param>
26+
/// <param name="encoding">Кодировка</param>
27+
/// <param name="Polynomial">Полином для вычисления CRC-8</param>
28+
/// <param name="InitialValue">Начальное значение CRC</param>
29+
/// <param name="RefIn">Отражение входных байтов</param>
30+
/// <param name="RefOut">Отражение выходного значения</param>
31+
/// <param name="XOROut">Значение для XOR с окончательным CRC</param>
32+
/// <returns>Вычисленное значение CRC-8</returns>
33+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
34+
public static byte ComputeCRC8(
35+
this string text,
36+
Encoding? encoding = null,
37+
byte Polynomial = 0x07,
38+
byte InitialValue = 0x00,
39+
bool RefIn = false,
40+
bool RefOut = false,
41+
byte XOROut = 0x00) =>
42+
CRC8.Hash((encoding ?? Encoding.Default).GetBytes(text), Polynomial, InitialValue, RefIn, RefOut, XOROut);
43+
44+
/// <summary>Вычисляет CRC-16 строки</summary>
45+
/// <param name="text">Исходная строка</param>
46+
/// <param name="encoding">Кодировка</param>
47+
/// <param name="Polynomial">Полином для вычисления CRC-16</param>
48+
/// <param name="InitialValue">Начальное значение CRC</param>
49+
/// <param name="RefIn">Отражение входных байтов</param>
50+
/// <param name="RefOut">Отражение выходного значения</param>
51+
/// <param name="XOROut">Значение для XOR с окончательным CRC</param>
52+
/// <returns>Вычисленное значение CRC-16</returns>
53+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
54+
public static ushort ComputeCRC16(
55+
this string text,
56+
Encoding? encoding = null,
57+
ushort Polynomial = 0x1021,
58+
ushort InitialValue = 0x0000,
59+
bool RefIn = false,
60+
bool RefOut = false,
61+
ushort XOROut = 0x0000) =>
62+
CRC16.Hash((encoding ?? Encoding.Default).GetBytes(text), Polynomial, InitialValue, RefIn, RefOut, XOROut);
63+
64+
/// <summary>Вычисляет CRC-32 строки</summary>
65+
/// <param name="text">Исходная строка</param>
66+
/// <param name="encoding">Кодировка</param>
67+
/// <param name="Polynomial">Полином для вычисления CRC-32</param>
68+
/// <param name="InitialValue">Начальное значение CRC</param>
69+
/// <param name="RefIn">Отражение входных байтов</param>
70+
/// <param name="RefOut">Отражение выходного значения</param>
71+
/// <param name="XOROut">Значение для XOR с окончательным CRC</param>
72+
/// <returns>Вычисленное значение CRC-32</returns>
73+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
74+
public static uint ComputeCRC32(
75+
this string text,
76+
Encoding? encoding = null,
77+
uint Polynomial = 0x04C11DB7,
78+
uint InitialValue = 0xFFFFFFFF,
79+
bool RefIn = false,
80+
bool RefOut = false,
81+
uint XOROut = 0xFFFFFFFF) =>
82+
CRC32.Hash((encoding ?? Encoding.Default).GetBytes(text), Polynomial, InitialValue, RefIn, RefOut, XOROut);
83+
84+
/// <summary>Вычисляет CRC-64 строки</summary>
85+
/// <param name="text">Исходная строка</param>
86+
/// <param name="encoding">Кодировка</param>
87+
/// <param name="Polynomial">Полином для вычисления CRC-64</param>
88+
/// <param name="InitialValue">Начальное значение CRC</param>
89+
/// <param name="RefIn">Отражение входных байтов</param>
90+
/// <param name="RefOut">Отражение выходного значения</param>
91+
/// <param name="XOROut">Значение для XOR с окончательным CRC</param>
92+
/// <returns>Вычисленное значение CRC-64</returns>
93+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
94+
public static ulong ComputeCRC64(
95+
this string text,
96+
Encoding? encoding = null,
97+
ulong Polynomial = 0x000000000000001B,
98+
ulong InitialValue = 0x0000000000000000,
99+
bool RefIn = false,
100+
bool RefOut = false,
101+
ulong XOROut = 0x0000000000000000) =>
102+
CRC64.Hash((encoding ?? Encoding.Default).GetBytes(text), Polynomial, InitialValue, RefIn, RefOut, XOROut);
103+
}

MathCore/Extensions/String/StringExtensions.cs

Lines changed: 1 addition & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
namespace System;
1616

1717
/// <summary>Методы-расширения класса <see cref="T:System.String">строк</see></summary>
18-
public static class StringExtensions
18+
public static partial class StringExtensions
1919
{
2020
/// <summary>Подсчитывает количество вхождений символа в строке</summary>
2121
/// <param name="s">Исходная строка</param>
@@ -270,20 +270,6 @@ public static async Task<string> DecompressAsStringAsync(this byte[] bytes, Canc
270270
public static string JoinStrings(this IEnumerable<string> strings, char separator) => string.Join(separator, strings);
271271
#endif
272272

273-
/// <summary>Вычисляет SHA256-хеш строки</summary>
274-
/// <param name="text">Исходная строка</param>
275-
/// <param name="encoding">Кодировка</param>
276-
/// <returns>Массив байт с хешем</returns>
277-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
278-
public static byte[] ComputeSHA256(this string text, Encoding? encoding = null) => (encoding ?? Encoding.Default).GetBytes(text).ComputeSHA256();
279-
280-
/// <summary>Вычисляет MD5-хеш строки</summary>
281-
/// <param name="text">Исходная строка</param>
282-
/// <param name="encoding">Кодировка</param>
283-
/// <returns>Массив байт с хешем</returns>
284-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
285-
public static byte[] ComputeMD5(this string text, Encoding? encoding = null) => (encoding ?? Encoding.Default).GetBytes(text).ComputeMD5();
286-
287273
/// <summary>Перечисление подстрок, разделяемых указанным строковым шаблоном</summary>
288274
/// <param name="Str">Разбиваемая строка</param>
289275
/// <param name="EndPattern">Строковый шаблон разбиения</param>
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
using System.Text;
2+
3+
namespace MathCore.Tests.Extensions.Strings;
4+
5+
[TestClass]
6+
public class StringExtensionsCRCTests
7+
{
8+
[TestMethod]
9+
public void ComputeCRC32_Standard_ZIP()
10+
{
11+
const string data = "123456789";
12+
const uint expected = 0xCBF43926;
13+
14+
var actual = data.ComputeCRC32(
15+
Polynomial: 0xEDB88320,
16+
InitialValue: 0xFFFFFFFF,
17+
XOROut: 0xFFFFFFFF,
18+
RefIn: true,
19+
RefOut: false);
20+
21+
Assert.AreEqual(expected, actual);
22+
}
23+
24+
[TestMethod]
25+
public void ComputeCRC8_FromByteSequence()
26+
{
27+
var bytes = new byte[] { 0x3F, 0xA2, 0x13, 0x21, 0x03 };
28+
var text = Encoding.Latin1.GetString(bytes);
29+
const byte expected = 0x18;
30+
31+
var actual = text.ComputeCRC8(encoding: Encoding.Latin1);
32+
33+
Assert.AreEqual(expected, actual);
34+
}
35+
36+
[TestMethod]
37+
public void ComputeCRC8_WithCustomParameters()
38+
{
39+
var bytes = new byte[] { 0x3F, 0xA2, 0x13, 0x21, 0x03 };
40+
var text = Encoding.Latin1.GetString(bytes);
41+
const byte expected = 0xDE;
42+
43+
var actual = text.ComputeCRC8(
44+
encoding: Encoding.Latin1,
45+
Polynomial: 0x07,
46+
InitialValue: 0xFF,
47+
XOROut: 0xFF);
48+
49+
Assert.AreEqual(expected, actual);
50+
}
51+
52+
[TestMethod]
53+
public void ComputeCRC_AllVariants_Different()
54+
{
55+
const string text = "Test Data For CRC";
56+
57+
var crc8 = text.ComputeCRC8();
58+
var crc16 = text.ComputeCRC16();
59+
var crc32 = text.ComputeCRC32(Polynomial: 0xEDB88320, InitialValue: 0xFFFFFFFF, XOROut: 0xFFFFFFFF, RefIn: true, RefOut: false);
60+
var crc64 = text.ComputeCRC64();
61+
62+
Assert.AreNotEqual((ulong)crc8, (ulong)crc16);
63+
Assert.AreNotEqual((ulong)crc16, (ulong)crc32);
64+
Assert.AreNotEqual(crc32, (uint)crc64);
65+
}
66+
67+
[TestMethod]
68+
public void ComputeCRC_Consistency()
69+
{
70+
const string text = "Consistency check string";
71+
72+
var a1 = text.ComputeCRC32(Polynomial: 0xEDB88320, InitialValue: 0xFFFFFFFF, XOROut: 0xFFFFFFFF, RefIn: true, RefOut: false);
73+
var a2 = text.ComputeCRC32(Polynomial: 0xEDB88320, InitialValue: 0xFFFFFFFF, XOROut: 0xFFFFFFFF, RefIn: true, RefOut: false);
74+
75+
Assert.AreEqual(a1, a2);
76+
}
77+
78+
[TestMethod]
79+
public void ComputeCRC32_NonEmpty()
80+
{
81+
const string text = "Some random test text";
82+
var crc = text.ComputeCRC32(Polynomial: 0xEDB88320, InitialValue: 0xFFFFFFFF, XOROut: 0xFFFFFFFF, RefIn: true, RefOut: false);
83+
Assert.IsTrue(crc >= 0);
84+
}
85+
}

0 commit comments

Comments
 (0)