Skip to content

Instantly share code, notes, and snippets.

@wipiano
Created September 25, 2019 12:53
Show Gist options
  • Save wipiano/5ae95de1fa732b4363be2c04da3445a3 to your computer and use it in GitHub Desktop.
Save wipiano/5ae95de1fa732b4363be2c04da3445a3 to your computer and use it in GitHub Desktop.
Span での文字列操作
using System;
namespace IMC.Util
{
public static class ByteArrayExtensions
{
/// <summary>
/// 16 進数の文字列に変換します
/// </summary>
public static string ToHexString(this byte[] source, bool upperCase = false)
{
Span<char> buffer = stackalloc char[source.Length * 2];
source.WriteAsHexChars(buffer, out _, upperCase);
return buffer.ToString();
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.CompilerServices;
namespace IMC.Util
{
/// <summary>
/// char の Span 用 util
/// </summary>
public static class CharSpanUtility
{
/// <summary>
/// バイトを 16 進数として書き込みます
/// </summary>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void WriteAsHexChars(this byte b, Span<char> dest, out int charsWritten, bool upperCase = false)
{
ReadOnlySpan<char> source = upperCase ? s_byteToHexUpper[b] : s_byteToHexLower[b];
source.CopyTo(dest);
charsWritten = source.Length; // 2 固定のはず
}
/// <summary>
/// バイト列を 16 進数の列として書き込みます
/// </summary>
public static void WriteAsHexChars(this ReadOnlySpan<byte> bytes, Span<char> dest, out int charsWritten,
bool upperCase = false)
{
charsWritten = 0;
foreach (byte b in bytes)
{
b.WriteAsHexChars(dest.Slice(charsWritten), out var count, upperCase);
charsWritten += count;
}
}
/// <summary>
/// バイト列を 16 進数の列として書き込みます
/// </summary>
public static void WriteAsHexChars(this IEnumerable<byte> bytes, Span<char> dest, out int charsWritten,
bool upperCase = false)
{
charsWritten = 0;
foreach (byte b in bytes)
{
b.WriteAsHexChars(dest.Slice(charsWritten), out var count, upperCase);
charsWritten += count;
}
}
// byte -> char[] に変換するための 配列
private static readonly char[][] s_byteToHexLower =
Enumerable.Range(0, 256).Select(x => ((byte) x).ToString("x2").ToCharArray()).ToArray();
private static readonly char[][] s_byteToHexUpper =
Enumerable.Range(0, 256).Select(x => ((byte) x).ToString("X2").ToCharArray()).ToArray();
}
}
using System;
namespace IMC.Util
{
public ref struct SpanStringBuilder
{
private Span<char> _buffer;
private int _index;
public SpanStringBuilder(Span<char> buffer)
{
_buffer = buffer;
_index = 0;
}
public void Write(ReadOnlySpan<char> str)
{
str.CopyTo(_buffer.Slice(_index));
_index += str.Length;
}
public void WriteLine(ReadOnlySpan<char> str)
{
Write(str);
Write(Environment.NewLine);
}
public void Write(char c)
{
_buffer[_index++] = c;
}
public void Write(int value)
{
if (!value.TryFormat(_buffer.Slice(_index), out var charsWritten))
{
throw new OutOfMemoryException("buffer のサイズが足りません");
}
_index += charsWritten;
}
public Span<char> AsSpan() => _buffer.Slice(0, _index);
public override string ToString() => AsSpan().ToString();
}
using System;
namespace IMC.Util
{
public static class StringMutator
{
public static string SnakeCaseToPascalCase(this string snake)
{
ReadOnlySpan<char> snakeSpan = snake;
Span<char> buffer = stackalloc char[snakeSpan.Length];
int bufferPos = 0;
bool toUpper = true;
for (var i = 0; i < snake.Length; i++)
{
var target = snakeSpan[i];
if (target == '_')
{
toUpper = true;
}
else
{
buffer[bufferPos++] = toUpper ? char.ToUpper(target) : target;
toUpper = false;
}
}
return buffer.Slice(0, bufferPos).ToString();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment