Skip to content

Commit 3236ffa

Browse files
committed
feat(extensions): 为 LittleEndian 添加 bytes 和 string 读写方法
新增以下小端字节序读写方法,与 BigEndian 保持 API 一致性: - WriteBytesLittleEndianValue: 写入带长度前缀的字节数组 - ReadBytesLittleEndianValue: 读取字节数组(3个重载) - WriteStringLittleEndianValue: 写入字符串 - ReadStringLittleEndianValue: 读取字符串
1 parent d34ef16 commit 3236ffa

1 file changed

Lines changed: 177 additions & 0 deletions

File tree

GameFrameX.Foundation.Extensions/ByteExtensions.LittleEndian.cs

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
using System;
22
using System.Buffers.Binary;
3+
using System.Text;
4+
using GameFrameX.Foundation.Localization.Core;
5+
using GameFrameX.Foundation.Extensions.Localization;
36

47
namespace GameFrameX.Foundation.Extensions;
58

@@ -130,6 +133,66 @@ public static void WriteDoubleLittleEndianValue(this byte[] buffer, double value
130133
offset += ConstBaseTypeSize.DoubleSize;
131134
}
132135

136+
/// <summary>
137+
/// 将一个字节数组(带长度前缀)以小端字节序写入指定的缓冲区,并更新偏移量。
138+
/// </summary>
139+
/// <param name="buffer">要写入的缓冲区。</param>
140+
/// <param name="value">要写入的值,不能为 null。</param>
141+
/// <param name="offset">要写入值的缓冲区中的偏移量。</param>
142+
/// <exception cref="ArgumentNullException">当 <paramref name="buffer"/> 或 <paramref name="value"/> 为 null 时抛出。</exception>
143+
/// <exception cref="ArgumentOutOfRangeException">当 <paramref name="offset"/> 为负数或缓冲区空间不足时抛出。</exception>
144+
public static void WriteBytesLittleEndianValue(this byte[] buffer, byte[] value, ref int offset)
145+
{
146+
ArgumentNullException.ThrowIfNull(buffer, nameof(buffer));
147+
ArgumentNullException.ThrowIfNull(value, nameof(value));
148+
ArgumentOutOfRangeException.ThrowIfNegative(offset, nameof(offset));
149+
150+
if (offset + value.Length + ConstBaseTypeSize.IntSize > buffer.Length)
151+
{
152+
throw new ArgumentOutOfRangeException(nameof(offset),
153+
LocalizationService.GetString(LocalizationKeys.Exceptions.BufferTooSmall, offset + value.Length + ConstBaseTypeSize.IntSize, buffer.Length));
154+
}
155+
156+
buffer.WriteIntLittleEndianValue(value.Length, ref offset);
157+
value.AsSpan().CopyTo(buffer.AsSpan(offset, value.Length));
158+
offset += value.Length;
159+
}
160+
161+
/// <summary>
162+
/// 将一个字符串以小端字节序写入指定的缓冲区,并更新偏移量。
163+
/// </summary>
164+
/// <param name="buffer">要写入的缓冲区。</param>
165+
/// <param name="value">要写入的值。</param>
166+
/// <param name="offset">要写入值的缓冲区中的偏移量。</param>
167+
/// <exception cref="ArgumentNullException">当 <paramref name="buffer"/> 为 null 时抛出。</exception>
168+
/// <exception cref="ArgumentOutOfRangeException">当 <paramref name="offset"/> 为负数或缓冲区空间不足时抛出。</exception>
169+
public static void WriteStringLittleEndianValue(this byte[] buffer, string value, ref int offset)
170+
{
171+
ArgumentNullException.ThrowIfNull(buffer, nameof(buffer));
172+
ArgumentOutOfRangeException.ThrowIfNegative(offset, nameof(offset));
173+
174+
if (value == null)
175+
{
176+
value = string.Empty;
177+
}
178+
179+
var len = Encoding.UTF8.GetByteCount(value);
180+
181+
if (len > short.MaxValue)
182+
{
183+
throw new ArgumentException(LocalizationService.GetString(LocalizationKeys.Exceptions.StringLengthExceedMaxValue, len, short.MaxValue));
184+
}
185+
186+
if (offset + len + ConstBaseTypeSize.ShortSize > buffer.Length)
187+
{
188+
throw new ArgumentOutOfRangeException(nameof(offset), LocalizationService.GetString(LocalizationKeys.Exceptions.BufferTooSmall, offset + len + ConstBaseTypeSize.ShortSize, buffer.Length));
189+
}
190+
191+
Encoding.UTF8.GetBytes(value, 0, value.Length, buffer, offset + ConstBaseTypeSize.ShortSize);
192+
WriteShortLittleEndianValue(buffer, (short)len, ref offset);
193+
offset += len;
194+
}
195+
133196
#endregion
134197

135198
#region Read LittleEndian
@@ -262,5 +325,119 @@ public static double ReadDoubleLittleEndianValue(this byte[] buffer, ref int off
262325
return value;
263326
}
264327

328+
/// <summary>
329+
/// 从指定偏移量开始读取指定长度的字节数组(小端字节序)。
330+
/// </summary>
331+
/// <param name="buffer">要操作的字节缓冲区。</param>
332+
/// <param name="offset">操作的起始偏移量。</param>
333+
/// <param name="len">需要读取的字节数组长度。</param>
334+
/// <returns>返回从缓冲区读取的 byte[] 类型数据。</returns>
335+
/// <exception cref="ArgumentNullException">当 <paramref name="buffer"/> 为 null 时抛出。</exception>
336+
/// <exception cref="ArgumentOutOfRangeException">当 <paramref name="offset"/> 为负数或读取位置超出缓冲区边界时抛出。</exception>
337+
public static byte[] ReadBytesLittleEndianValue(this byte[] buffer, int offset, int len)
338+
{
339+
ArgumentNullException.ThrowIfNull(buffer, nameof(buffer));
340+
ArgumentOutOfRangeException.ThrowIfNegative(offset, nameof(offset));
341+
342+
if (len <= 0)
343+
{
344+
return Array.Empty<byte>();
345+
}
346+
347+
if (offset + len > buffer.Length)
348+
{
349+
throw new ArgumentOutOfRangeException(nameof(offset), LocalizationService.GetString(LocalizationKeys.Exceptions.OffsetOutsideBufferBoundsSimple));
350+
}
351+
352+
var data = new byte[len];
353+
buffer.AsSpan(offset, len).CopyTo(data);
354+
return data;
355+
}
356+
357+
/// <summary>
358+
/// 从指定偏移量开始读取指定长度的字节数组(小端字节序)。
359+
/// </summary>
360+
/// <param name="buffer">要操作的字节缓冲区。</param>
361+
/// <param name="offset">操作的起始偏移量。</param>
362+
/// <param name="len">需要读取的字节数组长度。</param>
363+
/// <returns>返回从缓冲区读取的 byte[] 类型数据。</returns>
364+
/// <exception cref="ArgumentNullException">当 <paramref name="buffer"/> 为 null 时抛出。</exception>
365+
/// <exception cref="ArgumentOutOfRangeException">当 <paramref name="offset"/> 为负数或读取位置超出缓冲区边界时抛出。</exception>
366+
public static byte[] ReadBytesLittleEndianValue(this byte[] buffer, ref int offset, int len)
367+
{
368+
ArgumentNullException.ThrowIfNull(buffer, nameof(buffer));
369+
ArgumentOutOfRangeException.ThrowIfNegative(offset, nameof(offset));
370+
371+
if (len <= 0)
372+
{
373+
return Array.Empty<byte>();
374+
}
375+
376+
if (offset + len > buffer.Length)
377+
{
378+
throw new ArgumentOutOfRangeException(nameof(offset), LocalizationService.GetString(LocalizationKeys.Exceptions.OffsetOutsideBufferBoundsSimple));
379+
}
380+
381+
var data = new byte[len];
382+
buffer.AsSpan(offset, len).CopyTo(data);
383+
offset += len;
384+
return data;
385+
}
386+
387+
/// <summary>
388+
/// 从指定偏移量开始读取字节数组,长度作为 int 类型数据在字节数组的开头(小端字节序)。
389+
/// </summary>
390+
/// <param name="buffer">要操作的字节缓冲区。</param>
391+
/// <param name="offset">操作的起始偏移量,操作完成后,会自动累加读取的字节长度以及 int 类型长度。</param>
392+
/// <returns>返回从缓冲区读取的 byte[] 类型数据。</returns>
393+
/// <exception cref="ArgumentNullException">当 <paramref name="buffer"/> 为 null 时抛出。</exception>
394+
/// <exception cref="ArgumentOutOfRangeException">当 <paramref name="offset"/> 为负数或读取位置超出缓冲区边界时抛出。</exception>
395+
public static byte[] ReadBytesLittleEndianValue(this byte[] buffer, ref int offset)
396+
{
397+
var len = ReadIntLittleEndianValue(buffer, ref offset);
398+
399+
if (len <= 0)
400+
{
401+
return Array.Empty<byte>();
402+
}
403+
404+
if (offset + len > buffer.Length)
405+
{
406+
throw new ArgumentOutOfRangeException(nameof(offset), LocalizationService.GetString(LocalizationKeys.Exceptions.OffsetOutsideBufferBoundsSimple));
407+
}
408+
409+
var data = new byte[len];
410+
buffer.AsSpan(offset, len).CopyTo(data);
411+
offset += len;
412+
return data;
413+
}
414+
415+
/// <summary>
416+
/// 从字节数组中以指定偏移量读取字符串(小端字节序)。
417+
/// </summary>
418+
/// <param name="buffer">要从中读取数据的字节数组。</param>
419+
/// <param name="offset">读取数据的起始偏移量,此偏移量在读取后会自动增加。</param>
420+
/// <returns>读取的字符串,若读取长度小于等于0或偏移量超出数组长度,返回空字符串。</returns>
421+
/// <exception cref="ArgumentNullException">当 <paramref name="buffer"/> 为 null 时抛出。</exception>
422+
/// <exception cref="ArgumentOutOfRangeException">当 <paramref name="offset"/> 为负数或读取位置超出缓冲区边界时抛出。</exception>
423+
public static string ReadStringLittleEndianValue(this byte[] buffer, ref int offset)
424+
{
425+
var len = ReadShortLittleEndianValue(buffer, ref offset);
426+
427+
if (len <= 0)
428+
{
429+
return string.Empty;
430+
}
431+
432+
if (offset + len > buffer.Length)
433+
{
434+
throw new ArgumentOutOfRangeException(nameof(offset), LocalizationService.GetString(LocalizationKeys.Exceptions.OffsetOutsideBufferBoundsSimple));
435+
}
436+
437+
var value = Encoding.UTF8.GetString(buffer, offset, len);
438+
offset += len;
439+
return value;
440+
}
441+
265442
#endregion
266443
}

0 commit comments

Comments
 (0)