mirror of
https://github.com/xivdev/Penumbra.git
synced 2025-12-12 10:17:22 +01:00
75 lines
No EOL
2.5 KiB
C#
75 lines
No EOL
2.5 KiB
C#
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
|
|
namespace Penumbra.GameData.ByteString;
|
|
|
|
// Utf8String is a wrapper around unsafe byte strings.
|
|
// It may be used to store owned strings in unmanaged space,
|
|
// as well as refer to unowned strings.
|
|
// Unowned strings may change their value and thus become corrupt,
|
|
// so they should never be stored, just used locally or with great care.
|
|
// The string keeps track of whether it is owned or not, it also can keep track
|
|
// of some other information, like the string being pure ASCII, ASCII-lowercase or null-terminated.
|
|
// Owned strings are always null-terminated.
|
|
// Any constructed string will compute its own CRC32-value (as long as the string itself is not changed).
|
|
public sealed unsafe partial class Utf8String : IEnumerable< byte >
|
|
{
|
|
// We keep information on some of the state of the Utf8String in specific bits.
|
|
// This costs some potential max size, but that is not relevant for our case.
|
|
// Except for destruction/dispose, or if the non-owned pointer changes values,
|
|
// the CheckedFlag, AsciiLowerCaseFlag and AsciiFlag are the only things that are mutable.
|
|
private const uint NullTerminatedFlag = 0x80000000;
|
|
private const uint OwnedFlag = 0x40000000;
|
|
private const uint AsciiCheckedFlag = 0x04000000;
|
|
private const uint AsciiFlag = 0x08000000;
|
|
private const uint AsciiLowerCheckedFlag = 0x10000000;
|
|
private const uint AsciiLowerFlag = 0x20000000;
|
|
private const uint FlagMask = 0x03FFFFFF;
|
|
|
|
public bool IsNullTerminated
|
|
=> ( _length & NullTerminatedFlag ) != 0;
|
|
|
|
public bool IsOwned
|
|
=> ( _length & OwnedFlag ) != 0;
|
|
|
|
public bool IsAscii
|
|
=> CheckAscii();
|
|
|
|
public bool IsAsciiLowerCase
|
|
=> CheckAsciiLower();
|
|
|
|
public byte* Path
|
|
=> _path;
|
|
|
|
public int Crc32
|
|
=> _crc32;
|
|
|
|
public int Length
|
|
=> ( int )( _length & FlagMask );
|
|
|
|
public bool IsEmpty
|
|
=> Length == 0;
|
|
|
|
public ReadOnlySpan< byte > Span
|
|
=> new(_path, Length);
|
|
|
|
public byte this[ int idx ]
|
|
=> ( uint )idx < Length ? _path[ idx ] : throw new IndexOutOfRangeException();
|
|
|
|
public IEnumerator< byte > GetEnumerator()
|
|
{
|
|
for( var i = 0; i < Length; ++i )
|
|
{
|
|
yield return Span[ i ];
|
|
}
|
|
}
|
|
|
|
IEnumerator IEnumerable.GetEnumerator()
|
|
=> GetEnumerator();
|
|
|
|
// Only not readonly due to dispose.
|
|
// ReSharper disable once NonReadonlyMemberInGetHashCode
|
|
public override int GetHashCode()
|
|
=> _crc32;
|
|
} |