2023-11-12 01:59:17 +08:00
using CodeWalker.GameFiles ;
2024-01-07 02:41:10 +08:00
using Collections.Pooled ;
using CommunityToolkit.HighPerformance.Buffers ;
2023-11-12 01:59:17 +08:00
using SharpDX ;
2017-09-21 18:33:05 +08:00
using System ;
2024-01-07 02:41:10 +08:00
using System.Collections ;
2017-09-21 18:33:05 +08:00
using System.Collections.Generic ;
2024-01-07 02:41:10 +08:00
using System.Diagnostics.CodeAnalysis ;
2017-09-21 18:33:05 +08:00
using System.Linq ;
2024-01-07 02:41:10 +08:00
using System.Runtime.Intrinsics.Arm ;
2017-09-21 18:33:05 +08:00
using System.Text ;
2019-01-19 01:31:13 +08:00
using System.Text.RegularExpressions ;
2017-09-21 18:33:05 +08:00
using System.Threading.Tasks ;
using System.Xml ;
2023-11-12 01:59:17 +08:00
using System.Xml.Linq ;
2017-09-21 18:33:05 +08:00
namespace CodeWalker
{
public static class Xml
{
2023-11-12 01:59:17 +08:00
public static void ValidateReaderState ( XmlReader reader , string element )
{
2024-01-07 02:41:10 +08:00
if ( reader is null )
2023-11-12 01:59:17 +08:00
{
throw new ArgumentNullException ( nameof ( reader ) ) ;
}
if ( ! reader . IsStartElement ( ) )
{
throw new InvalidOperationException ( $"Expected reader to be at a start element but was at \" { reader . NodeType } \ " with name \"{reader.Name}\"" ) ;
}
if ( reader . Name ! = element )
{
throw new InvalidOperationException ( $"Expected reader to be at start element of \" { element } \ " but was at \"{reader.NodeType}\" with name \"{reader.Name}\"" ) ;
}
}
2017-09-21 18:33:05 +08:00
2024-01-07 02:41:10 +08:00
public static bool TryGetAttribute ( this XElement element , string attribute , [ NotNullWhen ( true ) ] out XAttribute ? attr )
2017-09-21 18:33:05 +08:00
{
2024-01-07 02:41:10 +08:00
attr = element . Attribute ( attribute ) ;
if ( attr is null )
return false ;
return true ;
}
public static string? GetStringAttribute ( this XmlNode ? node , string attribute )
{
if ( node is null | | node . Attributes is null )
return null ;
2017-09-21 18:33:05 +08:00
return node . Attributes [ attribute ] ? . InnerText ;
}
2024-01-07 02:41:10 +08:00
public static bool GetBoolAttribute ( this XElement element , string attribute = "value" )
2017-09-21 18:33:05 +08:00
{
2024-01-07 02:41:10 +08:00
ArgumentNullException . ThrowIfNull ( element , nameof ( element ) ) ;
var val = element . Attribute ( attribute ) ;
if ( val is null ) return false ;
bool . TryParse ( val . Value , out var b ) ;
return b ;
}
public static bool GetBoolAttribute ( this XmlNode ? node , string attribute )
{
if ( node is null )
return false ;
string? val = node . Attributes ? [ attribute ] ? . InnerText ;
_ = bool . TryParse ( val , out var b ) ;
2017-09-21 18:33:05 +08:00
return b ;
}
2024-01-07 02:41:10 +08:00
public static int GetIntAttribute ( this XmlNode ? node , string attribute )
2017-09-21 18:33:05 +08:00
{
2024-01-07 02:41:10 +08:00
if ( node is null )
return 0 ;
string? val = node . Attributes ? [ attribute ] ? . InnerText ;
_ = int . TryParse ( val , out var i ) ;
2017-09-21 18:33:05 +08:00
return i ;
}
2024-01-07 02:41:10 +08:00
public static uint GetUIntAttribute ( this XmlNode ? node , string attribute )
2019-01-19 01:31:13 +08:00
{
2024-01-07 02:41:10 +08:00
if ( node is null )
return 0 ;
string? val = node . Attributes ? [ attribute ] ? . InnerText ;
_ = uint . TryParse ( val , out var i ) ;
2019-01-19 01:31:13 +08:00
return i ;
}
2024-01-07 02:41:10 +08:00
public static ulong GetULongAttribute ( this XmlNode ? node , string attribute )
2020-01-21 00:12:36 +08:00
{
2024-01-07 02:41:10 +08:00
if ( node is null )
return 0 ;
string? val = node . Attributes ? [ attribute ] ? . InnerText ;
_ = ulong . TryParse ( val , out var i ) ;
2020-01-21 00:12:36 +08:00
return i ;
}
2024-01-07 02:41:10 +08:00
public static float GetFloatAttribute ( this XmlNode ? node , string attribute )
2017-09-21 18:33:05 +08:00
{
2024-01-07 02:41:10 +08:00
if ( node is null )
return 0 ;
string? val = node . Attributes ? [ attribute ] ? . InnerText ;
_ = FloatUtil . TryParse ( val , out var f ) ;
2017-09-21 18:33:05 +08:00
return f ;
}
2024-01-07 02:41:10 +08:00
public static string? GetChildInnerText ( this XmlNode ? node , string name )
2017-09-21 18:33:05 +08:00
{
2024-01-07 02:41:10 +08:00
if ( node is null )
return null ;
2017-09-21 18:33:05 +08:00
return node . SelectSingleNode ( name ) ? . InnerText ;
}
2023-11-12 01:59:17 +08:00
2024-01-07 02:41:10 +08:00
public static string? GetChildInnerText ( this XElement ? node , string name ) {
if ( node is null )
return null ;
return node . Element ( name ) ? . Value ;
2023-11-12 01:59:17 +08:00
}
public static string GetChildInnerText ( XmlReader reader , string name )
{
ValidateReaderState ( reader , name ) ;
if ( reader . NodeType = = XmlNodeType . Element )
{
if ( reader . IsEmptyElement )
{
reader . ReadStartElement ( ) ;
2024-01-07 02:41:10 +08:00
return string . Empty ;
2023-11-12 01:59:17 +08:00
}
return reader . ReadElementContentAsString ( ) ;
}
else
{
return reader . ReadContentAsString ( ) ;
}
}
2024-01-07 02:41:10 +08:00
public static bool GetChildBoolInnerText ( this XElement ? node , string name )
2023-11-12 01:59:17 +08:00
{
2024-01-07 02:41:10 +08:00
if ( node is null )
return false ;
string? val = node . Element ( name ) ? . Value ;
if ( string . IsNullOrEmpty ( val ) )
return false ;
2023-11-12 01:59:17 +08:00
2024-01-07 02:41:10 +08:00
_ = bool . TryParse ( val , out var b ) ;
2023-11-12 01:59:17 +08:00
return b ;
}
public static bool GetChildBoolInnerText ( XmlReader reader , string name )
{
ValidateReaderState ( reader , name ) ;
if ( reader . NodeType = = XmlNodeType . Element )
{
return reader . ReadElementContentAsBoolean ( ) ;
}
else
{
return reader . ReadContentAsBoolean ( ) ;
}
}
2024-01-07 02:41:10 +08:00
public static bool GetChildBoolInnerText ( this XmlNode ? node , string name )
2017-09-25 01:45:30 +08:00
{
2024-01-07 02:41:10 +08:00
if ( node is null )
return false ;
string? val = node . SelectSingleNode ( name ) ? . InnerText ;
_ = bool . TryParse ( val , out var b ) ;
2017-09-25 01:45:30 +08:00
return b ;
}
2024-01-07 02:41:10 +08:00
public static int GetChildIntInnerText ( this XmlNode ? node , string name )
2017-09-25 01:45:30 +08:00
{
2024-01-07 02:41:10 +08:00
if ( node is null )
return 0 ;
string? val = node . SelectSingleNode ( name ) ? . InnerText ;
_ = int . TryParse ( val , out var i ) ;
2017-09-25 01:45:30 +08:00
return i ;
}
2024-01-07 02:41:10 +08:00
public static float GetChildFloatInnerText ( this XmlNode ? node , string name )
2017-09-25 01:45:30 +08:00
{
2024-01-07 02:41:10 +08:00
if ( node is null )
return 0 ;
string? val = node . SelectSingleNode ( name ) ? . InnerText ;
_ = FloatUtil . TryParse ( val , out var f ) ;
2017-09-25 01:45:30 +08:00
return f ;
}
2023-11-12 01:59:17 +08:00
public static float GetChildFloatInnerText ( XmlReader reader , string name )
{
ValidateReaderState ( reader , name ) ;
return reader . ReadElementContentAsFloat ( ) ;
}
2019-01-11 15:15:25 +08:00
public static T GetChildEnumInnerText < T > ( XmlNode node , string name ) where T : struct
{
2024-01-07 02:41:10 +08:00
if ( node is null )
return new T ( ) ;
string? val = node . SelectSingleNode ( name ) ? . InnerText ;
2019-01-11 15:15:25 +08:00
return GetEnumValue < T > ( val ) ;
}
2024-01-07 02:41:10 +08:00
public static T GetEnumValue < T > ( string? val ) where T : struct
2019-01-11 15:15:25 +08:00
{
2019-12-28 13:01:09 +08:00
if ( string . IsNullOrEmpty ( val ) )
{
2024-01-07 02:41:10 +08:00
return default ;
2019-12-28 13:01:09 +08:00
}
2023-11-12 01:59:17 +08:00
if ( val . StartsWith ( "hash_" , StringComparison . OrdinalIgnoreCase ) )
2019-01-11 15:15:25 +08:00
{
//convert hash_12ABC to Unk_12345
2024-01-07 02:41:10 +08:00
//var substr = val.Substring(5);
//var uval = Convert.ToUInt32(substr, 16);
_ = int . TryParse ( val . AsSpan ( 5 ) , System . Globalization . NumberStyles . HexNumber , null , out var result ) ;
val = $"Unk_{result}" ;
2019-01-11 15:15:25 +08:00
}
T enumval ;
Enum . TryParse ( val , out enumval ) ;
return enumval ;
}
2023-11-12 01:59:17 +08:00
public static bool GetChildBoolAttribute ( XmlReader reader , string name , string attribute = "value" )
{
ValidateReaderState ( reader , name ) ;
string val = reader . GetAttribute ( attribute ) ;
bool . TryParse ( val , out bool boolval ) ;
reader . ReadStartElement ( ) ;
2017-09-21 18:33:05 +08:00
2023-11-12 01:59:17 +08:00
return boolval ;
}
2020-01-21 23:45:27 +08:00
public static bool GetChildBoolAttribute ( XmlNode node , string name , string attribute = "value" )
2017-09-21 18:33:05 +08:00
{
if ( node = = null ) return false ;
string val = node . SelectSingleNode ( name ) ? . Attributes [ attribute ] ? . InnerText ;
bool b ;
bool . TryParse ( val , out b ) ;
return b ;
}
2023-11-12 01:59:17 +08:00
public static int GetChildIntAttribute ( XmlReader reader , string name , string attribute = "value" )
{
ValidateReaderState ( reader , name ) ;
string val = reader . GetAttribute ( attribute ) ;
int . TryParse ( val , out var i ) ;
reader . ReadStartElement ( ) ;
return i ;
}
2020-01-21 23:45:27 +08:00
public static int GetChildIntAttribute ( XmlNode node , string name , string attribute = "value" )
2017-09-21 18:33:05 +08:00
{
if ( node = = null ) return 0 ;
string val = node . SelectSingleNode ( name ) ? . Attributes [ attribute ] ? . InnerText ;
int i ;
int . TryParse ( val , out i ) ;
return i ;
}
2023-11-12 01:59:17 +08:00
public static uint GetChildUIntAttribute ( XmlReader reader , string name , string attribute = "value" )
{
if ( reader = = null ) return 0 ;
uint i ;
string val = reader . GetAttribute ( attribute ) ;
if ( val ? . StartsWith ( "0x" , StringComparison . OrdinalIgnoreCase ) ? ? false )
{
2024-01-07 02:41:10 +08:00
//var subs = val.Substring(2);
//i = Convert.ToUInt32(subs, 16);
_ = uint . TryParse ( val . AsSpan ( 2 ) , System . Globalization . NumberStyles . HexNumber , null , out i ) ;
2023-11-12 01:59:17 +08:00
}
else
{
2024-01-07 02:41:10 +08:00
_ = uint . TryParse ( val , out i ) ;
2023-11-12 01:59:17 +08:00
}
return i ;
}
2020-01-21 23:45:27 +08:00
public static uint GetChildUIntAttribute ( XmlNode node , string name , string attribute = "value" )
2019-01-11 15:15:25 +08:00
{
if ( node = = null ) return 0 ;
string val = node . SelectSingleNode ( name ) ? . Attributes [ attribute ] ? . InnerText ;
uint i ;
2023-11-12 01:59:17 +08:00
if ( val ? . StartsWith ( "0x" , StringComparison . OrdinalIgnoreCase ) ? ? false )
2019-01-11 15:15:25 +08:00
{
2024-01-07 02:41:10 +08:00
//var subs = val.Substring(2);
//i = Convert.ToUInt32(subs, 16);
_ = uint . TryParse ( val . AsSpan ( 2 ) , System . Globalization . NumberStyles . HexNumber , null , out i ) ;
2019-01-11 15:15:25 +08:00
}
else
{
2024-01-07 02:41:10 +08:00
_ = uint . TryParse ( val , out i ) ;
2019-01-11 15:15:25 +08:00
}
return i ;
}
2022-03-29 20:32:29 +08:00
public static ulong GetChildULongAttribute ( XmlNode node , string name , string attribute = "value" )
{
if ( node = = null ) return 0 ;
string val = node . SelectSingleNode ( name ) ? . Attributes [ attribute ] ? . InnerText ;
ulong i ;
2023-11-12 01:59:17 +08:00
if ( val ? . StartsWith ( "0x" , StringComparison . OrdinalIgnoreCase ) ? ? false )
2022-03-29 20:32:29 +08:00
{
2024-01-07 02:41:10 +08:00
//var subs = val.Substring(2);
//i = Convert.ToUInt64(subs, 16);
_ = ulong . TryParse ( val . AsSpan ( 2 ) , System . Globalization . NumberStyles . HexNumber , null , out i ) ;
2022-03-29 20:32:29 +08:00
}
else
{
2024-01-07 02:41:10 +08:00
_ = ulong . TryParse ( val , out i ) ;
2022-03-29 20:32:29 +08:00
}
return i ;
}
2023-11-12 01:59:17 +08:00
public static float GetChildFloatAttribute ( XmlReader reader , string name , string attribute = "value" )
{
if ( ! string . IsNullOrEmpty ( name ) )
{
ValidateReaderState ( reader , name ) ;
}
string val = reader . GetAttribute ( attribute ) ;
FloatUtil . TryParse ( val , out float f ) ;
if ( ! string . IsNullOrEmpty ( name ) )
{
reader . ReadStartElement ( ) ;
}
return f ;
}
2024-01-07 02:41:10 +08:00
public static float GetChildFloatAttribute ( XmlNode ? node , string name , string attribute = "value" )
2017-09-21 18:33:05 +08:00
{
2024-01-07 02:41:10 +08:00
if ( node is null )
return 0 ;
string? val = node . SelectSingleNode ( name ) ? . Attributes ? [ attribute ] ? . InnerText ;
2017-09-21 18:33:05 +08:00
float f ;
FloatUtil . TryParse ( val , out f ) ;
return f ;
}
2024-01-07 02:41:10 +08:00
public static string? GetChildStringAttribute ( XmlNode node , string name , string attribute = "value" )
2017-09-21 18:33:05 +08:00
{
2024-01-07 02:41:10 +08:00
if ( node is null ) return string . Empty ;
string? val = node . SelectSingleNode ( name ) ? . Attributes ? [ attribute ] ? . InnerText ;
2017-09-21 18:33:05 +08:00
return val ;
}
2023-11-12 01:59:17 +08:00
2024-01-07 02:41:10 +08:00
public static string? GetChildStringAttribute ( XmlReader reader , string name , string attribute = "value" )
2023-11-12 01:59:17 +08:00
{
ValidateReaderState ( reader , name ) ;
var val = reader . GetAttribute ( attribute ) ;
reader . ReadStartElement ( ) ;
return val ;
}
2020-01-21 23:45:27 +08:00
public static Vector2 GetChildVector2Attributes ( XmlNode node , string name , string x = "x" , string y = "y" )
2019-01-11 15:15:25 +08:00
{
float fx = GetChildFloatAttribute ( node , name , x ) ;
float fy = GetChildFloatAttribute ( node , name , y ) ;
return new Vector2 ( fx , fy ) ;
}
2023-11-12 01:59:17 +08:00
public static Vector3 GetChildVector3Attributes ( XmlReader reader , string name , string x = "x" , string y = "y" , string z = "z" )
{
ValidateReaderState ( reader , name ) ;
float fx = GetChildFloatAttribute ( reader , null , x ) ;
float fy = GetChildFloatAttribute ( reader , null , y ) ;
float fz = GetChildFloatAttribute ( reader , null , z ) ;
reader . ReadStartElement ( ) ;
return new Vector3 ( fx , fy , fz ) ;
}
2020-01-21 23:45:27 +08:00
public static Vector3 GetChildVector3Attributes ( XmlNode node , string name , string x = "x" , string y = "y" , string z = "z" )
2017-09-21 18:33:05 +08:00
{
float fx = GetChildFloatAttribute ( node , name , x ) ;
float fy = GetChildFloatAttribute ( node , name , y ) ;
float fz = GetChildFloatAttribute ( node , name , z ) ;
return new Vector3 ( fx , fy , fz ) ;
}
2020-01-21 23:45:27 +08:00
public static Vector4 GetChildVector4Attributes ( XmlNode node , string name , string x = "x" , string y = "y" , string z = "z" , string w = "w" )
2019-01-11 15:15:25 +08:00
{
float fx = GetChildFloatAttribute ( node , name , x ) ;
float fy = GetChildFloatAttribute ( node , name , y ) ;
float fz = GetChildFloatAttribute ( node , name , z ) ;
float fw = GetChildFloatAttribute ( node , name , w ) ;
return new Vector4 ( fx , fy , fz , fw ) ;
}
2017-09-21 18:33:05 +08:00
public static XmlElement GetChild ( XmlElement element , string name )
{
return element . SelectSingleNode ( name ) as XmlElement ;
}
public static XmlElement AddChild ( XmlDocument doc , XmlNode node , string name )
{
XmlElement child = doc . CreateElement ( name ) ;
node . AppendChild ( child ) ;
return child ;
}
2023-11-12 01:59:17 +08:00
public static bool IsItemElement ( this XmlReader reader )
{
if ( reader . MoveToContent ( ) = = XmlNodeType . Element & & reader . Name = = "Item" )
{
return true ;
}
return false ;
}
2024-01-07 02:41:10 +08:00
public static void MoveToStartElement ( this XmlReader reader , string name )
{
var startDepth = reader . Depth ;
while ( reader . Read ( ) & & startDepth < = reader . Depth )
{
if ( reader . IsStartElement ( ) & & reader . Name = = name )
{
break ;
}
}
}
public static IEnumerable < XElement > IterateItems ( this XmlReader reader , string parentElementName )
2023-11-12 01:59:17 +08:00
{
ValidateReaderState ( reader , parentElementName ) ;
reader . MoveToContent ( ) ;
if ( reader . IsEmptyElement )
{
// Move past empty element
reader . ReadStartElement ( parentElementName ) ;
yield break ;
}
2024-01-07 02:41:10 +08:00
var startDepth = reader . Depth ;
2023-11-12 01:59:17 +08:00
reader . ReadStartElement ( parentElementName ) ;
2024-01-07 02:41:10 +08:00
while ( reader . IsItemElement ( ) & & startDepth < reader . Depth )
2023-11-12 01:59:17 +08:00
{
if ( XNode . ReadFrom ( reader ) is XElement el )
{
yield return el ;
}
}
reader . ReadEndElement ( ) ;
}
2017-09-21 18:33:05 +08:00
public static XmlElement AddChildWithInnerText ( XmlDocument doc , XmlNode node , string name , string innerText )
{
XmlElement child = AddChild ( doc , node , name ) ;
child . InnerText = innerText ;
return child ;
}
public static XmlElement AddChildWithAttribute ( XmlDocument doc , XmlNode node , string name , string attributeName , string attributeValue )
{
XmlElement child = AddChild ( doc , node , name ) ;
child . SetAttribute ( attributeName , attributeValue ) ;
return child ;
}
2019-01-19 01:31:13 +08:00
2024-01-07 02:41:10 +08:00
public static byte [ ] GetRawByteArray ( XmlNode ? node , int fromBase = 16 )
2019-01-19 01:31:13 +08:00
{
2024-01-07 02:41:10 +08:00
if ( node = = null )
return [ ] ;
using var data = new PooledList < byte > ( ) ;
2019-01-19 01:31:13 +08:00
var split = Regex . Split ( node . InnerText , @"[\s\r\n\t]" ) ;
for ( int i = 0 ; i < split . Length ; i + + )
{
if ( ! string . IsNullOrEmpty ( split [ i ] ) )
{
var str = split [ i ] ;
if ( string . IsNullOrEmpty ( str ) ) continue ;
2020-01-21 00:12:36 +08:00
var val = Convert . ToByte ( str , fromBase ) ;
2019-01-19 01:31:13 +08:00
data . Add ( val ) ;
}
}
return data . ToArray ( ) ;
}
2020-01-21 00:12:36 +08:00
public static byte [ ] GetChildRawByteArray ( XmlNode node , string name , int fromBase = 16 )
2019-01-19 01:31:13 +08:00
{
var cnode = node . SelectSingleNode ( name ) ;
2020-01-21 00:12:36 +08:00
return GetRawByteArray ( cnode , fromBase ) ;
2019-01-19 01:31:13 +08:00
}
2024-01-07 02:41:10 +08:00
public static byte [ ] ? GetChildRawByteArrayNullable ( XmlNode node , string name , int fromBase = 16 )
2020-01-23 23:55:48 +08:00
{
var cnode = node . SelectSingleNode ( name ) ;
var arr = GetRawByteArray ( cnode , fromBase ) ;
2024-01-07 02:41:10 +08:00
return arr . Length > 0 ? arr : null ;
2020-01-23 23:55:48 +08:00
}
2019-01-19 01:31:13 +08:00
2024-01-07 02:41:10 +08:00
public static ushort [ ] GetRawUshortArray ( XmlNode ? node )
2020-01-19 23:08:04 +08:00
{
2024-01-07 02:41:10 +08:00
if ( node is null )
return [ ] ;
using var data = new PooledList < ushort > ( ) ;
2020-01-19 23:08:04 +08:00
var split = Regex . Split ( node . InnerText , @"[\s\r\n\t]" ) ;
for ( int i = 0 ; i < split . Length ; i + + )
{
if ( ! string . IsNullOrEmpty ( split [ i ] ) )
{
var str = split [ i ] ;
if ( string . IsNullOrEmpty ( str ) ) continue ;
var val = ( ushort ) 0 ;
ushort . TryParse ( str , out val ) ;
data . Add ( val ) ;
}
}
return data . ToArray ( ) ;
}
public static ushort [ ] GetChildRawUshortArray ( XmlNode node , string name )
{
var cnode = node . SelectSingleNode ( name ) ;
return GetRawUshortArray ( cnode ) ;
}
2024-01-07 02:41:10 +08:00
public static ushort [ ] ? GetChildRawUshortArrayNullable ( XmlNode node , string name )
2020-01-23 23:55:48 +08:00
{
var cnode = node . SelectSingleNode ( name ) ;
var arr = GetRawUshortArray ( cnode ) ;
2024-01-07 02:41:10 +08:00
return arr . Length > 0 ? arr : null ;
2020-01-23 23:55:48 +08:00
}
2020-01-19 23:08:04 +08:00
2024-01-07 02:41:10 +08:00
public static uint [ ] GetRawUintArray ( XmlNode ? node )
2019-11-14 15:58:20 +08:00
{
2024-01-07 02:41:10 +08:00
if ( node = = null )
return [ ] ;
using var data = new PooledList < uint > ( ) ;
2019-11-14 15:58:20 +08:00
var split = Regex . Split ( node . InnerText , @"[\s\r\n\t]" ) ;
for ( int i = 0 ; i < split . Length ; i + + )
{
if ( ! string . IsNullOrEmpty ( split [ i ] ) )
{
var str = split [ i ] ;
if ( string . IsNullOrEmpty ( str ) ) continue ;
var val = 0 u ;
uint . TryParse ( str , out val ) ;
data . Add ( val ) ;
}
}
return data . ToArray ( ) ;
}
public static uint [ ] GetChildRawUintArray ( XmlNode node , string name )
{
var cnode = node . SelectSingleNode ( name ) ;
return GetRawUintArray ( cnode ) ;
}
2024-01-07 02:41:10 +08:00
public static uint [ ] ? GetChildRawUintArrayNullable ( XmlNode node , string name )
2020-01-23 23:55:48 +08:00
{
var cnode = node . SelectSingleNode ( name ) ;
var arr = GetRawUintArray ( cnode ) ;
2024-01-07 02:41:10 +08:00
return arr . Length > 0 ? arr : null ;
2020-01-23 23:55:48 +08:00
}
2019-11-14 15:58:20 +08:00
2024-01-07 02:41:10 +08:00
public static int [ ] GetRawIntArray ( XmlNode ? node )
2019-11-23 00:57:00 +08:00
{
2024-01-07 02:41:10 +08:00
if ( node is null )
return [ ] ;
using var data = new PooledList < int > ( ) ;
2019-11-23 00:57:00 +08:00
var split = Regex . Split ( node . InnerText , @"[\s\r\n\t]" ) ;
for ( int i = 0 ; i < split . Length ; i + + )
{
if ( ! string . IsNullOrEmpty ( split [ i ] ) )
{
var str = split [ i ] ;
if ( string . IsNullOrEmpty ( str ) ) continue ;
var val = 0 ;
int . TryParse ( str , out val ) ;
data . Add ( val ) ;
}
}
return data . ToArray ( ) ;
}
public static int [ ] GetChildRawIntArray ( XmlNode node , string name )
{
var cnode = node . SelectSingleNode ( name ) ;
return GetRawIntArray ( cnode ) ;
}
2024-01-07 02:41:10 +08:00
public static int [ ] ? GetChildRawIntArrayNullable ( XmlNode node , string name )
2020-01-23 23:55:48 +08:00
{
var cnode = node . SelectSingleNode ( name ) ;
var arr = GetRawIntArray ( cnode ) ;
return ( ( arr ! = null ) & & ( arr . Length > 0 ) ) ? arr : null ;
}
2019-11-23 00:57:00 +08:00
2024-01-07 02:41:10 +08:00
public static float [ ] GetRawFloatArray ( XmlNode ? node )
2019-03-11 22:13:04 +08:00
{
2024-01-07 02:41:10 +08:00
if ( node is null )
return [ ] ;
using var items = new PooledList < float > ( ) ;
2019-11-14 15:58:20 +08:00
var split = Regex . Split ( node . InnerText , @"[\s\r\n\t]" ) ; //node.InnerText.Split('\n');//
2019-03-11 22:13:04 +08:00
for ( int i = 0 ; i < split . Length ; i + + )
{
var s = split [ i ] ? . Trim ( ) ;
if ( string . IsNullOrEmpty ( s ) ) continue ;
var f = FloatUtil . Parse ( s ) ;
items . Add ( f ) ;
}
return items . ToArray ( ) ;
}
public static float [ ] GetChildRawFloatArray ( XmlNode node , string name )
{
var cnode = node . SelectSingleNode ( name ) ;
return GetRawFloatArray ( cnode ) ;
}
2024-01-07 02:41:10 +08:00
public static float [ ] ? GetChildRawFloatArrayNullable ( XmlNode node , string name )
2020-01-23 23:55:48 +08:00
{
var cnode = node . SelectSingleNode ( name ) ;
var arr = GetRawFloatArray ( cnode ) ;
2024-01-07 02:41:10 +08:00
return arr . Length > 0 ? arr : null ;
2020-01-23 23:55:48 +08:00
}
2019-03-11 22:13:04 +08:00
2024-01-07 02:41:10 +08:00
public static Vector2 [ ] GetRawVector2Array ( XmlNode ? node )
2019-01-19 01:31:13 +08:00
{
2024-01-07 02:41:10 +08:00
if ( node is null )
return [ ] ;
2019-01-19 01:31:13 +08:00
float x = 0f ;
float y = 0f ;
2024-01-07 02:41:10 +08:00
using var items = new PooledList < Vector2 > ( ) ;
2019-01-19 01:31:13 +08:00
var split = node . InnerText . Split ( '\n' ) ; // Regex.Split(node.InnerText, @"[\s\r\n\t]");
for ( int i = 0 ; i < split . Length ; i + + )
{
var s = split [ i ] ? . Trim ( ) ;
if ( string . IsNullOrEmpty ( s ) ) continue ;
var split2 = s . Split ( ',' ) ; // Regex.Split(s, @"[\s\t]");
int c = 0 ;
x = 0f ; y = 0f ;
for ( int n = 0 ; n < split2 . Length ; n + + )
{
var ts = split2 [ n ] ? . Trim ( ) ;
if ( string . IsNullOrEmpty ( ts ) ) continue ;
var f = FloatUtil . Parse ( ts ) ;
switch ( c )
{
case 0 : x = f ; break ;
case 1 : y = f ; break ;
//case 2: z = f; break;
}
c + + ;
}
if ( c > = 2 )
{
var val = new Vector2 ( x , y ) ;
items . Add ( val ) ;
}
}
return items . ToArray ( ) ;
}
public static Vector2 [ ] GetChildRawVector2Array ( XmlNode node , string name )
{
var cnode = node . SelectSingleNode ( name ) ;
return GetRawVector2Array ( cnode ) ;
}
2024-01-07 02:41:10 +08:00
public static Vector3 [ ] GetRawVector3Array ( XmlNode ? node )
2019-01-19 01:31:13 +08:00
{
2024-01-07 02:41:10 +08:00
if ( node is null )
return [ ] ;
2019-01-19 01:31:13 +08:00
float x = 0f ;
float y = 0f ;
float z = 0f ;
2024-01-07 02:41:10 +08:00
using var items = new PooledList < Vector3 > ( ) ;
2019-01-19 01:31:13 +08:00
var split = node . InnerText . Split ( '\n' ) ; // Regex.Split(node.InnerText, @"[\s\r\n\t]");
for ( int i = 0 ; i < split . Length ; i + + )
{
var s = split [ i ] ? . Trim ( ) ;
if ( string . IsNullOrEmpty ( s ) ) continue ;
var split2 = s . Split ( ',' ) ; // Regex.Split(s, @"[\s\t]");
int c = 0 ;
x = 0f ; y = 0f ;
for ( int n = 0 ; n < split2 . Length ; n + + )
{
var ts = split2 [ n ] ? . Trim ( ) ;
if ( string . IsNullOrEmpty ( ts ) ) continue ;
var f = FloatUtil . Parse ( ts ) ;
switch ( c )
{
case 0 : x = f ; break ;
case 1 : y = f ; break ;
case 2 : z = f ; break ;
}
c + + ;
}
if ( c > = 3 )
{
var val = new Vector3 ( x , y , z ) ;
items . Add ( val ) ;
}
}
return items . ToArray ( ) ;
}
public static Vector3 [ ] GetChildRawVector3Array ( XmlNode node , string name )
{
var cnode = node . SelectSingleNode ( name ) ;
return GetRawVector3Array ( cnode ) ;
}
2024-01-07 02:41:10 +08:00
public static Vector3 [ ] ? GetChildRawVector3ArrayNullable ( XmlNode node , string name )
2020-01-16 15:03:24 +08:00
{
var cnode = node . SelectSingleNode ( name ) ;
var arr = GetRawVector3Array ( cnode ) ;
2024-01-07 02:41:10 +08:00
return arr . Length > 0 ? arr : null ;
2020-01-16 15:03:24 +08:00
}
2019-01-19 01:31:13 +08:00
2024-01-07 02:41:10 +08:00
public static Vector4 [ ] GetRawVector4Array ( XmlNode ? node )
2019-01-20 13:54:42 +08:00
{
2024-01-07 02:41:10 +08:00
if ( node is null )
return [ ] ;
2019-01-20 13:54:42 +08:00
float z = 0f ;
float w = 0f ;
2024-01-07 02:41:10 +08:00
using var items = new PooledList < Vector4 > ( ) ;
2019-01-20 13:54:42 +08:00
var split = node . InnerText . Split ( '\n' ) ; // Regex.Split(node.InnerText, @"[\s\r\n\t]");
for ( int i = 0 ; i < split . Length ; i + + )
{
var s = split [ i ] ? . Trim ( ) ;
if ( string . IsNullOrEmpty ( s ) ) continue ;
var split2 = s . Split ( ',' ) ; // Regex.Split(s, @"[\s\t]");
int c = 0 ;
2024-01-07 02:41:10 +08:00
float x = 0f ;
float y = 0f ;
2019-01-20 13:54:42 +08:00
for ( int n = 0 ; n < split2 . Length ; n + + )
{
var ts = split2 [ n ] ? . Trim ( ) ;
2024-01-07 02:41:10 +08:00
if ( string . IsNullOrEmpty ( ts ) )
continue ;
2019-01-20 13:54:42 +08:00
var f = FloatUtil . Parse ( ts ) ;
switch ( c )
{
case 0 : x = f ; break ;
case 1 : y = f ; break ;
case 2 : z = f ; break ;
case 3 : w = f ; break ;
}
c + + ;
}
if ( c > = 4 )
{
var val = new Vector4 ( x , y , z , w ) ;
items . Add ( val ) ;
}
}
return items . ToArray ( ) ;
}
public static Vector4 [ ] GetChildRawVector4Array ( XmlNode node , string name )
{
var cnode = node . SelectSingleNode ( name ) ;
return GetRawVector4Array ( cnode ) ;
}
2024-01-07 02:41:10 +08:00
public static Vector4 [ ] ? GetChildRawVector4ArrayNullable ( XmlNode node , string name )
2020-01-23 23:55:48 +08:00
{
var cnode = node . SelectSingleNode ( name ) ;
var arr = GetRawVector4Array ( cnode ) ;
2024-01-07 02:41:10 +08:00
return arr . Length > 0 ? arr : null ;
2020-01-23 23:55:48 +08:00
}
2019-01-20 13:54:42 +08:00
2024-01-07 02:41:10 +08:00
public static Matrix GetMatrix ( XmlNode ? node )
2020-01-21 00:12:36 +08:00
{
2024-01-07 02:41:10 +08:00
if ( node is null )
return Matrix . Identity ;
2020-01-21 00:12:36 +08:00
var arr = GetRawFloatArray ( node ) ;
2024-01-07 02:41:10 +08:00
if ( arr . Length ! = 16 )
return Matrix . Identity ;
2020-01-21 00:12:36 +08:00
return new Matrix ( arr ) ;
}
public static Matrix GetChildMatrix ( XmlNode node , string name )
{
var cnode = node . SelectSingleNode ( name ) ;
return GetMatrix ( cnode ) ;
}
2019-01-19 01:31:13 +08:00
2017-09-21 18:33:05 +08:00
}
2024-01-07 02:41:10 +08:00
public class XmlNameTableThreadSafe : NameTable
{
//private object _locker = new object();
public StringPool StringPool ;
public XmlNameTableThreadSafe ( )
: this ( 256 )
{ }
public XmlNameTableThreadSafe ( int stringPoolSize )
: base ( )
{
StringPool = new StringPool ( stringPoolSize ) ;
}
public override string Add ( string key )
{
return StringPool . GetOrAdd ( key ) ;
}
public override string Add ( char [ ] key , int start , int len )
{
return StringPool . GetOrAdd ( key . AsSpan ( start , len ) ) ;
}
public override string? Get ( char [ ] key , int start , int len )
{
StringPool . TryGet ( key . AsSpan ( start , len ) , out var value ) ;
return value ;
//return stringPool.Get(key.AsSpan(start, len));
}
public override string? Get ( string value )
{
StringPool . TryGet ( value , out var result ) ;
return result ;
}
}
2017-09-21 18:33:05 +08:00
}