1441 lines
47 KiB
C#
1441 lines
47 KiB
C#
|
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<Boolean>._invoke = s => s.ToBoolean();
|
|||
|
Reader<Char>._invoke = s => (Char)s.ToInteger();
|
|||
|
Reader<Byte>._invoke = s => (Byte)s.ToInteger();
|
|||
|
Reader<SByte>._invoke = s => (SByte)s.ToInteger();
|
|||
|
Reader<Int16>._invoke = s => (Int16)s.ToInteger();
|
|||
|
Reader<UInt16>._invoke = s => (UInt16)s.ToInteger();
|
|||
|
Reader<Int32>._invoke = s => s.ToInteger();
|
|||
|
Reader<UInt32>._invoke = s => (UInt32)s.ToInteger();
|
|||
|
Reader<Int64>._invoke = s => s.ToInt64();
|
|||
|
Reader<UInt64>._invoke = s => (UInt64)s.ToInt64();
|
|||
|
Reader<String>._invoke = s => s.ToString();
|
|||
|
Reader<Single>._invoke = s => (Single)s.ToNumber();
|
|||
|
Reader<Double>._invoke = s => s.ToNumber();
|
|||
|
Reader<DataTable>._invoke = s => s.ToTable();
|
|||
|
Reader<System.Object>._invoke = s => s.ToUserData();
|
|||
|
}
|
|||
|
public static void DoInit() {
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
internal static class WriterInit {
|
|||
|
static WriterInit() {
|
|||
|
Writer<Boolean>._invoke = ( s, v ) => s.Set( v );
|
|||
|
Writer<Char>._invoke = ( s, v ) => s.Set( (int)v );
|
|||
|
Writer<Byte>._invoke = ( s, v ) => s.Set( (int)v );
|
|||
|
Writer<SByte>._invoke = ( s, v ) => s.Set( (int)v );
|
|||
|
Writer<Int16>._invoke = ( s, v ) => s.Set( (int)v );
|
|||
|
Writer<UInt16>._invoke = ( s, v ) => s.Set( (int)v );
|
|||
|
Writer<Int32>._invoke = ( s, v ) => s.Set( v );
|
|||
|
Writer<UInt32>._invoke = ( s, v ) => s.Set( (int)v );
|
|||
|
Writer<Int64>._invoke = ( s, v ) => s.Set( v );
|
|||
|
Writer<UInt64>._invoke = ( s, v ) => s.Set( (long)v );
|
|||
|
Writer<String>._invoke = ( s, v ) => s.Set( v );
|
|||
|
Writer<Single>._invoke = ( s, v ) => s.Set( (Double)v );
|
|||
|
Writer<Double>._invoke = ( s, v ) => s.Set( v );
|
|||
|
Writer<DataTable>._invoke = ( s, v ) => s.Set( v );
|
|||
|
Writer<System.Object>._invoke = ( s, v ) => s.SetUserData( v );
|
|||
|
}
|
|||
|
public static void DoInit() {
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public class Reader<T> {
|
|||
|
internal static MyFunc<Value, T> _invoke = null;
|
|||
|
internal static MyFunc<Value, T> _default = val => (T)val.ToUserData();
|
|||
|
public static MyFunc<Value, T> invoke
|
|||
|
{
|
|||
|
get {
|
|||
|
return _invoke ?? _default;
|
|||
|
}
|
|||
|
}
|
|||
|
static Reader() {
|
|||
|
ReaderInit.DoInit();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public class Writer<T> {
|
|||
|
internal static MyAction<Value, T> _invoke = null;
|
|||
|
internal static MyAction<Value, T> _default = (val, value) => val.SetUserData(value);
|
|||
|
public static MyAction<Value, T> invoke
|
|||
|
{
|
|||
|
get {
|
|||
|
return _invoke ?? _default;
|
|||
|
}
|
|||
|
}
|
|||
|
static Writer() {
|
|||
|
WriterInit.DoInit();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#region members
|
|||
|
Dictionary<String, Value> m_table = null;
|
|||
|
List<Value> m_array = null;
|
|||
|
#endregion
|
|||
|
|
|||
|
void _CheckTable() {
|
|||
|
if ( m_table == null ) {
|
|||
|
m_table = new Dictionary<String, Value>();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void _CheckArray() {
|
|||
|
if ( m_array == null ) {
|
|||
|
m_array = new List<Value>();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
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<T>( String name, out T value ) {
|
|||
|
var val = GetValue( name );
|
|||
|
if ( val != null ) {
|
|||
|
value = Reader<T>.invoke( val );
|
|||
|
return true;
|
|||
|
} else {
|
|||
|
value = default( T );
|
|||
|
return false;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public bool TryGet<T>( int index, out T value ) {
|
|||
|
var val = GetValue( index );
|
|||
|
if ( val != null ) {
|
|||
|
value = Reader<T>.invoke( val );
|
|||
|
if ( value != null ) {
|
|||
|
return true;
|
|||
|
} else {
|
|||
|
return false;
|
|||
|
}
|
|||
|
} else {
|
|||
|
value = default( T );
|
|||
|
return false;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public T Get<T>( String name ) {
|
|||
|
var val = GetValue( name );
|
|||
|
if ( val != null ) {
|
|||
|
return Reader<T>.invoke( val );
|
|||
|
} else {
|
|||
|
return default( T );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public T Get<T>( int index ) {
|
|||
|
var val = GetValue( index );
|
|||
|
if ( val != null ) {
|
|||
|
return Reader<T>.invoke( val );
|
|||
|
} else {
|
|||
|
return default( T );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public void Set<T>( String name, T value ) {
|
|||
|
_CheckTable();
|
|||
|
Value val = null;
|
|||
|
if ( m_table.TryGetValue( name, out val ) ) {
|
|||
|
Writer<T>.invoke( val, value );
|
|||
|
} else {
|
|||
|
val = new Value();
|
|||
|
Writer<T>.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<T>( 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<T>.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<T>( String name, T value ) {
|
|||
|
_CheckTable();
|
|||
|
if ( m_table.ContainsKey( name ) ) {
|
|||
|
return false;
|
|||
|
}
|
|||
|
var val = new Value();
|
|||
|
Writer<T>.invoke( val, value );
|
|||
|
m_table.Add( name, val );
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
public List<String> GetTableKeys() {
|
|||
|
if ( m_table == null ) {
|
|||
|
return null;
|
|||
|
}
|
|||
|
return new List<string>(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<T>( int index, T value ) {
|
|||
|
return Set<T>( 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<Boolean>._invoke = s => s.ToBoolean();
|
|||
|
Reader<Char>._invoke = s => (Char)s.ToInteger();
|
|||
|
Reader<Byte>._invoke = s => (Byte)s.ToInteger();
|
|||
|
Reader<SByte>._invoke = s => (SByte)s.ToInteger();
|
|||
|
Reader<Int16>._invoke = s => (Int16)s.ToInteger();
|
|||
|
Reader<UInt16>._invoke = s => (UInt16)s.ToInteger();
|
|||
|
Reader<Int32>._invoke = s => s.ToInteger();
|
|||
|
Reader<UInt32>._invoke = s => (UInt32)s.ToInteger();
|
|||
|
Reader<String>._invoke = s => s.ToString();
|
|||
|
Reader<Single>._invoke = s => (Single)s.ToNumber();
|
|||
|
Reader<Double>._invoke = s => s.ToNumber();
|
|||
|
Reader<DataTableEx>._invoke = s => s.ToTable();
|
|||
|
Reader<System.Object>._invoke = s => s.ToUserData();
|
|||
|
Reader<Vector2>._invoke = s => {
|
|||
|
if ( s.valueType == DataType.Vector2 ) {
|
|||
|
return s._val.vec2;
|
|||
|
} else {
|
|||
|
return Vector2.zero;
|
|||
|
}
|
|||
|
};
|
|||
|
Reader<Vector3>._invoke = s => {
|
|||
|
if ( s.valueType == DataType.Vector3 ) {
|
|||
|
return s._val.vec3;
|
|||
|
} else {
|
|||
|
return Vector3.zero;
|
|||
|
}
|
|||
|
};
|
|||
|
Reader<Vector4>._invoke = s => {
|
|||
|
if ( s.valueType == DataType.Vector4 ) {
|
|||
|
return s._val.vec4;
|
|||
|
} else {
|
|||
|
return Vector4.zero;
|
|||
|
}
|
|||
|
};
|
|||
|
Reader<Quaternion>._invoke = s => {
|
|||
|
if ( s.valueType == DataType.Quaternion ) {
|
|||
|
return s._val.quat;
|
|||
|
} else {
|
|||
|
return Quaternion.identity;
|
|||
|
}
|
|||
|
};
|
|||
|
Reader<Color>._invoke = s => {
|
|||
|
if ( s.valueType == DataType.Color4f ) {
|
|||
|
return s._val.color4f;
|
|||
|
} else {
|
|||
|
return default( Color );
|
|||
|
}
|
|||
|
};
|
|||
|
Reader<Color32>._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<Boolean>._invoke = ( s, v ) => s.Set( v );
|
|||
|
Writer<Char>._invoke = ( s, v ) => s.Set( (int)v );
|
|||
|
Writer<Byte>._invoke = ( s, v ) => s.Set( (int)v );
|
|||
|
Writer<SByte>._invoke = ( s, v ) => s.Set( (int)v );
|
|||
|
Writer<Int16>._invoke = ( s, v ) => s.Set( (int)v );
|
|||
|
Writer<UInt16>._invoke = ( s, v ) => s.Set( (int)v );
|
|||
|
Writer<Int32>._invoke = ( s, v ) => s.Set( v );
|
|||
|
Writer<UInt32>._invoke = ( s, v ) => s.Set( (int)v );
|
|||
|
Writer<String>._invoke = ( s, v ) => s.Set( v );
|
|||
|
Writer<Single>._invoke = ( s, v ) => s.Set( (Double)v );
|
|||
|
Writer<Double>._invoke = ( s, v ) => s.Set( v );
|
|||
|
Writer<DataTableEx>._invoke = ( s, v ) => s.Set( v );
|
|||
|
Writer<System.Object>._invoke = ( s, v ) => s.SetUserData( v );
|
|||
|
Writer<Vector2>._invoke = ( s, v ) => s.Set( v );
|
|||
|
Writer<Vector3>._invoke = ( s, v ) => s.Set( v );
|
|||
|
Writer<Vector4>._invoke = ( s, v ) => s.Set( v );
|
|||
|
Writer<Quaternion>._invoke = ( s, v ) => s.Set( v );
|
|||
|
Writer<Color>._invoke = ( s, v ) => s.Set( v );
|
|||
|
Writer<Color32>._invoke = ( s, v ) => s.Set( v );
|
|||
|
}
|
|||
|
public static void DoInit() {
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
internal class Reader<T> {
|
|||
|
internal static MyFunc<Value, T> _invoke = null;
|
|||
|
internal static MyFunc<Value, T> _default = val => (T)val.ToUserData();
|
|||
|
public static MyFunc<Value, T> invoke
|
|||
|
{
|
|||
|
get {
|
|||
|
return _invoke ?? _default;
|
|||
|
}
|
|||
|
}
|
|||
|
static Reader() {
|
|||
|
ReaderInit.DoInit();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
internal class Writer<T> {
|
|||
|
internal static MyAction<Value, T> _invoke = null;
|
|||
|
internal static MyAction<Value, T> _default = (val, value) => val.SetUserData(value);
|
|||
|
public static MyAction<Value, T> invoke
|
|||
|
{
|
|||
|
get {
|
|||
|
return _invoke ?? _default;
|
|||
|
}
|
|||
|
}
|
|||
|
static Writer() {
|
|||
|
WriterInit.DoInit();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
#region members
|
|||
|
Dictionary<String, Value> m_table = new Dictionary<String, Value>();
|
|||
|
List<Value> m_array = new List<Value>();
|
|||
|
#endregion
|
|||
|
|
|||
|
void _CheckTable() {
|
|||
|
if ( m_table == null ) {
|
|||
|
m_table = new Dictionary<String, Value>();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
void _CheckArray() {
|
|||
|
if ( m_array == null ) {
|
|||
|
m_array = new List<Value>();
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
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<T>( String name, out T value ) {
|
|||
|
var val = GetValue( name );
|
|||
|
if ( val != null ) {
|
|||
|
value = Reader<T>.invoke( val );
|
|||
|
return true;
|
|||
|
} else {
|
|||
|
value = default( T );
|
|||
|
return false;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public T Get<T>( String name ) {
|
|||
|
var val = GetValue( name );
|
|||
|
if ( val != null ) {
|
|||
|
return Reader<T>.invoke( val );
|
|||
|
} else {
|
|||
|
return default( T );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public T Get<T>( int index ) {
|
|||
|
var val = GetValue( index );
|
|||
|
if ( val != null ) {
|
|||
|
return Reader<T>.invoke( val );
|
|||
|
} else {
|
|||
|
return default( T );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public void Set<T>( String name, T value ) {
|
|||
|
_CheckTable();
|
|||
|
Value val = null;
|
|||
|
if ( m_table.TryGetValue( name, out val ) ) {
|
|||
|
Writer<T>.invoke( val, value );
|
|||
|
} else {
|
|||
|
val = new Value();
|
|||
|
Writer<T>.invoke( val, value );
|
|||
|
m_table.Add( name, val );
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
public bool Set<T>( 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<T>.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<T>( String name, T value ) {
|
|||
|
if ( m_table.ContainsKey( name ) ) {
|
|||
|
return false;
|
|||
|
}
|
|||
|
var val = new Value();
|
|||
|
Writer<T>.invoke( val, value );
|
|||
|
m_table.Add( name, val );
|
|||
|
return true;
|
|||
|
}
|
|||
|
|
|||
|
public List<string> GetTableKeys() {
|
|||
|
if ( m_table == null || m_table.Keys == null )
|
|||
|
return null;
|
|||
|
|
|||
|
return new List<string>( 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<T>( int index, T value ) {
|
|||
|
return Set<T>( 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 );
|
|||
|
}
|
|||
|
}
|
|||
|
}
|