using System; using System.Collections.Generic; using System.Text; using System.Runtime.InteropServices; using UnityEngine; using Thousandto.Core.Base; namespace Thousandto.Core.Base { public class DataTable { public enum DataType { Nil, UserData, Bool, Integer, Int64, Double, String, Table, } public class Value { [StructLayout( LayoutKind.Explicit )] struct __Value { [FieldOffset( 0 )] internal DataType type; [FieldOffset( 4 )] internal bool bVal; [FieldOffset( 4 )] internal int iVal; [FieldOffset( 4 )] internal long iVal64; [FieldOffset( 4 )] internal double dVal; }; __Value _val; System.Object obj; // pointer 8 bytes on 64bit OS public DataType valueType { get { return _val.type; } } public Value() { _val.type = DataType.Nil; } public Value( bool value ) { _val.type = DataType.Bool; _val.bVal = value; } public Value( int value ) { _val.type = DataType.Integer; _val.iVal = value; } public Value( long value ) { _val.type = DataType.Int64; _val.iVal64 = value; } public Value( double value ) { _val.type = DataType.Double; _val.dVal = value; } public Value( String value ) { _val.type = DataType.String; obj = value ?? String.Empty; } public Value( DataTable value ) { _val.type = DataType.Table; obj = value; } public bool ToBoolean() { if ( _val.type == DataType.Bool ) { return _val.bVal; } else if ( _val.type == DataType.Double ) { return _val.dVal != 0 ? true : false; } else if ( _val.type == DataType.Integer ) { return _val.iVal != 0 ? true : false; } else if ( _val.type == DataType.Int64 ) { return _val.iVal64 != 0 ? true : false; } else if ( _val.type == DataType.String ) { bool ret; if ( bool.TryParse( obj as String, out ret ) ) { return ret; } else { return false; } } else { return false; } } public long ToInt64() { if ( _val.type == DataType.Integer ) { return (long)_val.iVal; } else if ( _val.type == DataType.Double ) { return (long)_val.dVal; } else if ( _val.type == DataType.Int64 ) { return (long)_val.iVal64; } else if ( _val.type == DataType.Bool ) { return _val.bVal ? 1L : 0L; } else if ( _val.type == DataType.String ) { long ret; if ( long.TryParse( obj as String, out ret ) ) { return ret; } else { return 0L; } } else { return 0L; } } public int ToInteger() { if ( _val.type == DataType.Integer ) { return _val.iVal; } else if ( _val.type == DataType.Double ) { return (int)_val.dVal; } else if ( _val.type == DataType.Int64 ) { return (int)_val.iVal64; } else if ( _val.type == DataType.Bool ) { return _val.bVal ? 1 : 0; } else if ( _val.type == DataType.String ) { int ret; if ( int.TryParse( obj as String, out ret ) ) { return ret; } else { return 0; } } else { return 0; } } public double ToNumber() { if ( _val.type == DataType.Double ) { return _val.dVal; } else if ( _val.type == DataType.Integer ) { return _val.iVal; } else if ( _val.type == DataType.Int64 ) { return _val.iVal64; } else if ( _val.type == DataType.Bool ) { return _val.bVal ? 1 : 0; } else if ( _val.type == DataType.String ) { double ret; if ( double.TryParse( obj as String, out ret ) ) { return ret; } else { return 0; } } else { return 0; } } public new String ToString() { if ( _val.type == DataType.String ) { return obj as String; } else if ( _val.type == DataType.Integer ) { return _val.iVal.ToString(); } else if ( _val.type == DataType.Int64 ) { return _val.iVal64.ToString(); } else if ( _val.type == DataType.Double ) { return _val.dVal.ToString(); } else if ( _val.type == DataType.Bool ) { return _val.bVal.ToString(); } else if ( _val.type == DataType.UserData ) { return obj.ToString(); } else if ( _val.type == DataType.Table ) { var table = obj as DataTable; return table != null ? table.ToString( 0 ) : "null"; } else { return "null"; } } public DataTable ToTable() { if ( _val.type == DataType.Table ) { return obj as DataTable; } else { return null; } } public System.Object ToUserData() { if ( _val.type == DataType.UserData ) { return obj; } else { return null; } } public void SetUserData( System.Object val ) { _val.type = DataType.UserData; obj = val; } public void Set( bool val ) { if ( _val.type != DataType.Bool ) { _val.type = DataType.Bool; obj = null; } _val.bVal = val; } public void Set( int val ) { if ( _val.type != DataType.Integer ) { _val.type = DataType.Integer; obj = null; } _val.iVal = val; } public void Set( long val ) { if ( _val.type != DataType.Int64 ) { _val.type = DataType.Int64; obj = null; } _val.iVal64 = val; } public void Set( double val ) { if ( _val.type != DataType.Double ) { _val.type = DataType.Double; obj = null; } _val.dVal = val; } public void Set( float val ) { if ( _val.type != DataType.Double ) { _val.type = DataType.Double; obj = null; } _val.dVal = val; } public void Set( String val ) { _val.type = DataType.String; obj = val; } public void Set( DataTable val ) { _val.type = DataType.Table; obj = val; } public void Get( out bool val ) { val = ToBoolean(); } public void Get( out int val ) { val = ToInteger(); } public void Get( out long val ) { val = ToInt64(); } public void Get( out double val ) { val = ToNumber(); } public void Get( out float val ) { val = (float)ToNumber(); } public void Get( out String val ) { val = ToString(); } public void Get( out DataTable val ) { val = ToTable(); } } internal static class ReaderInit { static ReaderInit() { Reader._invoke = s => s.ToBoolean(); Reader._invoke = s => (Char)s.ToInteger(); Reader._invoke = s => (Byte)s.ToInteger(); Reader._invoke = s => (SByte)s.ToInteger(); Reader._invoke = s => (Int16)s.ToInteger(); Reader._invoke = s => (UInt16)s.ToInteger(); Reader._invoke = s => s.ToInteger(); Reader._invoke = s => (UInt32)s.ToInteger(); Reader._invoke = s => s.ToInt64(); Reader._invoke = s => (UInt64)s.ToInt64(); Reader._invoke = s => s.ToString(); Reader._invoke = s => (Single)s.ToNumber(); Reader._invoke = s => s.ToNumber(); Reader._invoke = s => s.ToTable(); Reader._invoke = s => s.ToUserData(); } public static void DoInit() { } } internal static class WriterInit { static WriterInit() { Writer._invoke = ( s, v ) => s.Set( v ); Writer._invoke = ( s, v ) => s.Set( (int)v ); Writer._invoke = ( s, v ) => s.Set( (int)v ); Writer._invoke = ( s, v ) => s.Set( (int)v ); Writer._invoke = ( s, v ) => s.Set( (int)v ); Writer._invoke = ( s, v ) => s.Set( (int)v ); Writer._invoke = ( s, v ) => s.Set( v ); Writer._invoke = ( s, v ) => s.Set( (int)v ); Writer._invoke = ( s, v ) => s.Set( v ); Writer._invoke = ( s, v ) => s.Set( (long)v ); Writer._invoke = ( s, v ) => s.Set( v ); Writer._invoke = ( s, v ) => s.Set( (Double)v ); Writer._invoke = ( s, v ) => s.Set( v ); Writer._invoke = ( s, v ) => s.Set( v ); Writer._invoke = ( s, v ) => s.SetUserData( v ); } public static void DoInit() { } } public class Reader { internal static MyFunc _invoke = null; internal static MyFunc _default = val => (T)val.ToUserData(); public static MyFunc invoke { get { return _invoke ?? _default; } } static Reader() { ReaderInit.DoInit(); } } public class Writer { internal static MyAction _invoke = null; internal static MyAction _default = (val, value) => val.SetUserData(value); public static MyAction invoke { get { return _invoke ?? _default; } } static Writer() { WriterInit.DoInit(); } } #region members Dictionary m_table = null; List m_array = null; #endregion void _CheckTable() { if ( m_table == null ) { m_table = new Dictionary(); } } void _CheckArray() { if ( m_array == null ) { m_array = new List(); } } public Value GetValue( String name ) { if ( m_table == null ) { return null; } Value val = null; if ( m_table.TryGetValue( name, out val ) ) { return val; } return null; } public Value GetValue( int index ) { if ( m_array != null && m_array.Count > index && index >= 0 ) { Value value = m_array[index]; if ( value != null && value.valueType != DataType.Nil ) { return value; } } return null; } #region getters public int GetInteger( String name ) { var val = GetValue( name ); if ( val != null ) { return val.ToInteger(); } else { return 0; } } public int GetInteger( int index ) { var val = GetValue( index ); if ( val != null ) { return val.ToInteger(); } else { return 0; } } public double GetNumber( String name ) { var val = GetValue( name ); if ( val != null ) { return val.ToNumber(); } else { return 0; } } public double GetNumber( int index ) { var val = GetValue( index ); if ( val != null ) { return val.ToNumber(); } else { return 0; } } public bool GetBoolean( String name ) { var val = GetValue( name ); if ( val != null ) { return val.ToBoolean(); } else { return false; } } public bool GetBoolean( int index ) { var val = GetValue( index ); if ( val != null ) { return val.ToBoolean(); } else { return false; } } public String GetString( String name ) { var val = GetValue( name ); if ( val != null ) { return val.ToString(); } else { return String.Empty; } } public String GetString( int index ) { var val = GetValue( index ); if ( val != null ) { return val.ToString(); } else { return String.Empty; } } public System.Object GetUserData( String name ) { var val = GetValue( name ); if ( val != null ) { return val.ToUserData(); } else { return null; } } public System.Object GetUserData( int index ) { var val = GetValue( index ); if ( val != null ) { return val.ToUserData(); } else { return null; } } public DataTable GetTable( String name ) { var val = GetValue( name ); if ( val != null ) { return val.ToTable(); } else { return null; } } public DataTable GetTable( int index ) { var val = GetValue( index ); if ( val != null ) { return val.ToTable(); } else { return null; } } #endregion public bool TryGet( String name, out T value ) { var val = GetValue( name ); if ( val != null ) { value = Reader.invoke( val ); return true; } else { value = default( T ); return false; } } public bool TryGet( int index, out T value ) { var val = GetValue( index ); if ( val != null ) { value = Reader.invoke( val ); if ( value != null ) { return true; } else { return false; } } else { value = default( T ); return false; } } public T Get( String name ) { var val = GetValue( name ); if ( val != null ) { return Reader.invoke( val ); } else { return default( T ); } } public T Get( int index ) { var val = GetValue( index ); if ( val != null ) { return Reader.invoke( val ); } else { return default( T ); } } public void Set( String name, T value ) { _CheckTable(); Value val = null; if ( m_table.TryGetValue( name, out val ) ) { Writer.invoke( val, value ); } else { val = new Value(); Writer.invoke( val, value ); m_table.Add( name, val ); } } public void SetArrayCapacity( int size ) { _CheckArray(); if ( m_array.Capacity < size ) { m_array.Capacity = size; } else { m_array.TrimExcess(); } } public bool Set( int index, T value ) { if ( index < 0 ) { return false; } _CheckArray(); int lack = index - m_array.Count + 1; for ( int i = 0; i < lack; ++i ) { m_array.Add( null ); } var val = m_array[index]; if ( val == null ) { m_array[index] = val = new Value(); } Writer.invoke( val, value ); return true; } public bool Contains( String name, DataType type = DataType.Nil ) { var val = GetValue( name ); if ( val != null ) { return val.valueType == type && type != DataType.Nil || type == DataType.Nil && val.valueType != DataType.Nil; } return false; } public bool Contains( int index, DataType type = DataType.Nil ) { var val = GetValue( index ); if ( val != null ) { return val.valueType == type && type != DataType.Nil || type == DataType.Nil && val.valueType != DataType.Nil; } return false; } public bool Add( String name, T value ) { _CheckTable(); if ( m_table.ContainsKey( name ) ) { return false; } var val = new Value(); Writer.invoke( val, value ); m_table.Add( name, val ); return true; } public List GetTableKeys() { if ( m_table == null ) { return null; } return new List(m_table.Keys); } public void ClearArray() { if ( m_array != null ) { m_array.Clear(); } } public void ClearTable() { if ( m_table != null ) { m_table.Clear(); } } public void Clear() { if ( m_array != null ) { m_array.Clear(); m_array.TrimExcess(); } if ( m_table != null ) { m_table.Clear(); } } public int GetArrayCount() { return m_array != null ? m_array.Count : 0; } public int GetTableCount() { return m_table != null ? m_table.Count : 0; } public bool Add( int index, T value ) { return Set( index, value ); } public bool Remove( String name ) { return m_table != null && m_table.Remove( name ); } public bool Remove( int index ) { if ( m_array != null && m_array.Count > index ) { m_array[index] = new Value(); return true; } return false; } internal String ToString( int level ) { StringBuilder _sb = new StringBuilder(); if ( m_table != null ) { foreach ( var entry in m_table ) { var name = entry.Key; var val = entry.Value; if ( level > 0 ) { _sb.Append( '\t', level ); } if ( val.valueType != DataType.Table ) { _sb.Append( String.Format( "{0} = {1}\n", name, val.ToString() ) ); } else { DataTable table = val.ToTable(); _sb.Append( String.Format( "{0}:\n", name ) ); _sb.Append( String.Format( "{0}\n", table.ToString( level + 1 ) ) ); } } } if ( m_array != null && m_array.Count > 0 ) { _sb.Append( '\n' ); for ( int i = 0; i < m_array.Count; ++i ) { var val = m_array[i]; if ( level > 0 ) { _sb.Append( '\t', level ); } if ( val.valueType != DataType.Nil ) { if ( val.valueType != DataType.Table ) { _sb.Append( String.Format( "[{0}] = {1}\n", i, val.ToString() ) ); } else { DataTable table = val.ToTable(); _sb.Append( String.Format( "[{0}]:\n", i ) ); _sb.Append( String.Format( "{0}\n", table.ToString( level + 1 ) ) ); } } } } return _sb.ToString(); } public new String ToString() { return ToString( 0 ); } } public class DataTableEx { public enum DataType { Nil, UserData, Bool, Integer, Double, String, Table, Vector2, Vector3, Vector4, Quaternion, Color4f, Color32, } public class Value { [StructLayout( LayoutKind.Explicit )] internal struct __Value { [FieldOffset( 0 )] internal DataType type; [FieldOffset( 4 )] internal bool bVal; [FieldOffset( 4 )] internal int iVal; [FieldOffset( 4 )] internal long iVal64; [FieldOffset( 4 )] internal double dVal; [FieldOffset( 4 )] internal Vector2 vec2; [FieldOffset( 4 )] internal Vector3 vec3; [FieldOffset( 4 )] internal Vector4 vec4; [FieldOffset( 4 )] internal Quaternion quat; [FieldOffset( 4 )] internal Color color4f; [FieldOffset( 4 )] internal Color32 color32; }; internal __Value _val; System.Object obj; // pointer 8 bytes on 64bit OS public DataType valueType { get { return _val.type; } } public Value() { _val.type = DataType.Nil; } public Value( bool value ) { _val.type = DataType.Bool; _val.bVal = value; } public Value( int value ) { _val.type = DataType.Integer; _val.iVal = value; } public Value( double value ) { _val.type = DataType.Double; _val.dVal = value; } public Value( String value ) { _val.type = DataType.String; obj = value ?? String.Empty; } public Value( DataTableEx value ) { _val.type = DataType.Table; obj = value; } public Value( Vector2 value ) { _val.type = DataType.Vector2; _val.vec2 = value; } public Value( Vector3 value ) { _val.type = DataType.Vector3; _val.vec3 = value; } public Value( Vector4 value ) { _val.type = DataType.Vector4; _val.vec4 = value; } public Value( Quaternion value ) { _val.type = DataType.Quaternion; _val.quat = value; } public Value( Color value ) { _val.type = DataType.Color4f; _val.color4f = value; } public Value( Color32 value ) { _val.type = DataType.Color32; _val.color32 = value; } public bool ToBoolean() { if ( _val.type == DataType.Bool ) { return _val.bVal; } else if ( _val.type == DataType.Double ) { return _val.dVal != 0 ? true : false; } else if ( _val.type == DataType.Integer ) { return _val.iVal != 0 ? true : false; } else if ( _val.type == DataType.String ) { bool ret; if ( bool.TryParse( obj as String, out ret ) ) { return ret; } else { return false; } } else { return false; } } public int ToInteger() { if ( _val.type == DataType.Integer ) { return _val.iVal; } else if ( _val.type == DataType.Double ) { return (int)_val.dVal; } else if ( _val.type == DataType.Bool ) { return _val.bVal ? 1 : 0; } else if ( _val.type == DataType.String ) { int ret; if ( int.TryParse( obj as String, out ret ) ) { return ret; } else { return 0; } } else { return 0; } } public double ToNumber() { if ( _val.type == DataType.Double ) { return _val.dVal; } else if ( _val.type == DataType.Integer ) { return _val.iVal; } else if ( _val.type == DataType.Bool ) { return _val.bVal ? 1 : 0; } else if ( _val.type == DataType.String ) { double ret; if ( double.TryParse( obj as String, out ret ) ) { return ret; } else { return 0; } } else { return 0; } } public new String ToString() { if ( _val.type == DataType.String ) { return obj as String; } else if ( _val.type == DataType.Integer ) { return _val.iVal.ToString(); } else if ( _val.type == DataType.Double ) { return _val.dVal.ToString(); } else if ( _val.type == DataType.Bool ) { return _val.bVal.ToString(); } else { return String.Empty; } } public DataTableEx ToTable() { if ( _val.type == DataType.Table ) { return obj as DataTableEx; } else { return null; } } public System.Object ToUserData() { if ( _val.type == DataType.UserData ) { return obj; } else { return null; } } public void SetUserData( System.Object val ) { _val.type = DataType.UserData; obj = val; } public void Set( bool val ) { if ( _val.type != DataType.Bool ) { _val.type = DataType.Bool; obj = null; } _val.bVal = val; } public void Set( int val ) { if ( _val.type != DataType.Integer ) { _val.type = DataType.Integer; obj = null; } _val.iVal = val; } public void Set( double val ) { if ( _val.type != DataType.Double ) { _val.type = DataType.Double; obj = null; } _val.dVal = val; } public void Set( float val ) { if ( _val.type != DataType.Double ) { _val.type = DataType.Double; obj = null; } _val.dVal = val; } public void Set( String val ) { _val.type = DataType.String; obj = val; } public void Set( DataTableEx val ) { _val.type = DataType.Table; obj = val; } public void Set( Vector2 val ) { _val.type = DataType.Vector2; _val.vec2 = val; } public void Set( Vector3 val ) { _val.type = DataType.Vector3; _val.vec3 = val; } public void Set( Vector4 val ) { _val.type = DataType.Vector4; _val.vec4 = val; } public void Set( Quaternion val ) { _val.type = DataType.Quaternion; _val.quat = val; } public void Set( Color val ) { _val.type = DataType.Color4f; _val.color4f = val; } public void Set( Color32 val ) { _val.type = DataType.Color32; _val.color32 = val; } public void Get( out bool val ) { val = ToBoolean(); } public void Get( out int val ) { val = ToInteger(); } public void Get( out double val ) { val = ToNumber(); } public void Get( out float val ) { val = (float)ToNumber(); } public void Get( out String val ) { val = ToString(); } public void Get( out DataTableEx val ) { val = ToTable(); } public void Get( out Vector2 val ) { if ( _val.type == DataType.Vector2 ) { val = _val.vec2; } else { val = Vector2.zero; } } public void Get( out Vector3 val ) { if ( _val.type == DataType.Vector3 ) { val = _val.vec3; } else { val = Vector3.zero; } } public void Get( out Vector4 val ) { if ( _val.type == DataType.Vector4 ) { val = _val.vec4; } else { val = Vector4.zero; } } public void Get( out Quaternion val ) { if ( _val.type == DataType.Quaternion ) { val = _val.quat; } else { val = Quaternion.identity; } } public void Get( out Color val ) { if ( _val.type == DataType.Color4f ) { val = _val.color4f; } else { val = default( Color ); } } public void Get( out Color32 val ) { if ( _val.type == DataType.Color32 ) { val = _val.color32; } else { val = default( Color32 ); } } } internal static class ReaderInit { static ReaderInit() { Reader._invoke = s => s.ToBoolean(); Reader._invoke = s => (Char)s.ToInteger(); Reader._invoke = s => (Byte)s.ToInteger(); Reader._invoke = s => (SByte)s.ToInteger(); Reader._invoke = s => (Int16)s.ToInteger(); Reader._invoke = s => (UInt16)s.ToInteger(); Reader._invoke = s => s.ToInteger(); Reader._invoke = s => (UInt32)s.ToInteger(); Reader._invoke = s => s.ToString(); Reader._invoke = s => (Single)s.ToNumber(); Reader._invoke = s => s.ToNumber(); Reader._invoke = s => s.ToTable(); Reader._invoke = s => s.ToUserData(); Reader._invoke = s => { if ( s.valueType == DataType.Vector2 ) { return s._val.vec2; } else { return Vector2.zero; } }; Reader._invoke = s => { if ( s.valueType == DataType.Vector3 ) { return s._val.vec3; } else { return Vector3.zero; } }; Reader._invoke = s => { if ( s.valueType == DataType.Vector4 ) { return s._val.vec4; } else { return Vector4.zero; } }; Reader._invoke = s => { if ( s.valueType == DataType.Quaternion ) { return s._val.quat; } else { return Quaternion.identity; } }; Reader._invoke = s => { if ( s.valueType == DataType.Color4f ) { return s._val.color4f; } else { return default( Color ); } }; Reader._invoke = s => { if ( s.valueType == DataType.Color32 ) { return s._val.color32; } else { return default( Color32 ); } }; } public static void DoInit() { } } internal static class WriterInit { static WriterInit() { Writer._invoke = ( s, v ) => s.Set( v ); Writer._invoke = ( s, v ) => s.Set( (int)v ); Writer._invoke = ( s, v ) => s.Set( (int)v ); Writer._invoke = ( s, v ) => s.Set( (int)v ); Writer._invoke = ( s, v ) => s.Set( (int)v ); Writer._invoke = ( s, v ) => s.Set( (int)v ); Writer._invoke = ( s, v ) => s.Set( v ); Writer._invoke = ( s, v ) => s.Set( (int)v ); Writer._invoke = ( s, v ) => s.Set( v ); Writer._invoke = ( s, v ) => s.Set( (Double)v ); Writer._invoke = ( s, v ) => s.Set( v ); Writer._invoke = ( s, v ) => s.Set( v ); Writer._invoke = ( s, v ) => s.SetUserData( v ); Writer._invoke = ( s, v ) => s.Set( v ); Writer._invoke = ( s, v ) => s.Set( v ); Writer._invoke = ( s, v ) => s.Set( v ); Writer._invoke = ( s, v ) => s.Set( v ); Writer._invoke = ( s, v ) => s.Set( v ); Writer._invoke = ( s, v ) => s.Set( v ); } public static void DoInit() { } } internal class Reader { internal static MyFunc _invoke = null; internal static MyFunc _default = val => (T)val.ToUserData(); public static MyFunc invoke { get { return _invoke ?? _default; } } static Reader() { ReaderInit.DoInit(); } } internal class Writer { internal static MyAction _invoke = null; internal static MyAction _default = (val, value) => val.SetUserData(value); public static MyAction invoke { get { return _invoke ?? _default; } } static Writer() { WriterInit.DoInit(); } } #region members Dictionary m_table = new Dictionary(); List m_array = new List(); #endregion void _CheckTable() { if ( m_table == null ) { m_table = new Dictionary(); } } void _CheckArray() { if ( m_array == null ) { m_array = new List(); } } public Value GetValue( String name ) { Value val = null; if ( m_table.TryGetValue( name, out val ) ) { return val; } return null; } public Value GetValue( int index ) { if ( m_array.Count > index && index >= 0 ) { return m_array[index]; } return null; } #region getters public int GetInteger( String name ) { var val = GetValue( name ); if ( val != null ) { return val.ToInteger(); } else { return 0; } } public int GetInteger( int index ) { var val = GetValue( index ); if ( val != null ) { return val.ToInteger(); } else { return 0; } } public double GetNumber( String name ) { var val = GetValue( name ); if ( val != null ) { return val.ToNumber(); } else { return 0; } } public double GetNumber( int index ) { var val = GetValue( index ); if ( val != null ) { return val.ToNumber(); } else { return 0; } } public bool GetBoolean( String name ) { var val = GetValue( name ); if ( val != null ) { return val.ToBoolean(); } else { return false; } } public bool GetBoolean( int index ) { var val = GetValue( index ); if ( val != null ) { return val.ToBoolean(); } else { return false; } } public String GetString( String name ) { var val = GetValue( name ); if ( val != null ) { return val.ToString(); } else { return String.Empty; } } public String GetString( int index ) { var val = GetValue( index ); if ( val != null ) { return val.ToString(); } else { return String.Empty; } } public System.Object GetUserData( String name ) { var val = GetValue( name ); if ( val != null ) { return val.ToUserData(); } else { return null; } } public System.Object GetUserData( int index ) { var val = GetValue( index ); if ( val != null ) { return val.ToUserData(); } else { return null; } } public DataTableEx GetTable( String name ) { var val = GetValue( name ); if ( val != null ) { return val.ToTable(); } else { return null; } } public DataTableEx GetTable( int index ) { var val = GetValue( index ); if ( val != null ) { return val.ToTable(); } else { return null; } } #endregion public bool TryGet( String name, out T value ) { var val = GetValue( name ); if ( val != null ) { value = Reader.invoke( val ); return true; } else { value = default( T ); return false; } } public T Get( String name ) { var val = GetValue( name ); if ( val != null ) { return Reader.invoke( val ); } else { return default( T ); } } public T Get( int index ) { var val = GetValue( index ); if ( val != null ) { return Reader.invoke( val ); } else { return default( T ); } } public void Set( String name, T value ) { _CheckTable(); Value val = null; if ( m_table.TryGetValue( name, out val ) ) { Writer.invoke( val, value ); } else { val = new Value(); Writer.invoke( val, value ); m_table.Add( name, val ); } } public bool Set( int index, T value ) { if ( index < 0 ) { return false; } int lack = index - m_array.Count + 1; for ( int i = 0; i < lack; ++i ) { m_array.Add( null ); } var val = m_array[index]; if ( val == null ) { m_array[index] = val = new Value(); } Writer.invoke( val, value ); return true; } public bool Contains( String name, DataType type = DataType.Nil ) { var val = GetValue( name ); if ( val != null ) { return val.valueType == type && type != DataType.Nil || type == DataType.Nil && val.valueType != DataType.Nil; } return false; } public bool Contains( int index, DataType type = DataType.Nil ) { var val = GetValue( index ); if ( val != null ) { return val.valueType == type && type != DataType.Nil || type == DataType.Nil && val.valueType != DataType.Nil; } return false; } public bool Add( String name, T value ) { if ( m_table.ContainsKey( name ) ) { return false; } var val = new Value(); Writer.invoke( val, value ); m_table.Add( name, val ); return true; } public List GetTableKeys() { if ( m_table == null || m_table.Keys == null ) return null; return new List( m_table.Keys);; } public void ClearArray() { m_array.Clear(); } public void ClearTable() { m_table.Clear(); } public void Clear() { m_array.Clear(); m_table.Clear(); } public int GetArrayCount() { return m_array.Count; } public int GetTableCount() { return m_table.Count; } public bool Add( int index, T value ) { return Set( index, value ); } public bool Remove( String name ) { return m_table.Remove( name ); } public bool Remove( int index ) { if ( m_array != null && m_array.Count > index ) { m_array[index] = new Value(); return true; } return false; } internal String ToString( int level ) { StringBuilder _sb = new StringBuilder(); foreach ( var entry in m_table ) { var name = entry.Key; var val = entry.Value; if ( level > 0 ) { _sb.Append( '\t', level ); } if ( val.valueType != DataType.Table ) { _sb.Append( String.Format( "{0} = {1}\n", name, val.ToString() ) ); } else { DataTableEx table = val.ToTable(); _sb.Append( String.Format( "{0}:\n", name ) ); _sb.Append( String.Format( "{0}\n", table.ToString( level + 1 ) ) ); } } if ( m_array.Count > 0 ) { _sb.Append( '\n' ); for ( int i = 0; i < m_array.Count; ++i ) { var val = m_array[i]; if ( level > 0 ) { _sb.Append( '\t', level ); } if ( val.valueType != DataType.Nil ) { if ( val.valueType != DataType.Table ) { _sb.Append( String.Format( "[{0}] = {1}\n", i, val.ToString() ) ); } else { DataTableEx table = val.ToTable(); _sb.Append( String.Format( "[{0}]:\n", i ) ); _sb.Append( String.Format( "{0}\n", table.ToString( level + 1 ) ) ); } } } } return _sb.ToString(); } public new String ToString() { return ToString( 0 ); } } }