BS 0.1 基础构建完成 / 0.2 Visual 同为Unity UI控件部分

This commit is contained in:
2025-07-21 15:49:39 +08:00
parent e400c616f4
commit f6750189d0
1768 changed files with 184236 additions and 0 deletions

View File

@@ -0,0 +1,571 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.IO;
using System.Text;
using System;
using ES3Types;
using System.Globalization;
namespace ES3Internal
{
/*
* Specific ES3Reader for reading JSON data.
*
* Note: Leading & trailing whitespace is ignored whenever
* reading characters which are part of the JSON syntax,
* i.e. { } [ ] , " " :
*/
public class ES3JSONReader : ES3Reader
{
private const char endOfStreamChar = (char)65535;
public StreamReader baseReader;
internal ES3JSONReader(Stream stream, ES3Settings settings, bool readHeaderAndFooter = true) : base(settings, readHeaderAndFooter)
{
this.baseReader = new StreamReader(stream);
// Read opening brace from file if we're loading straight from file.
if(readHeaderAndFooter)
{
try
{
SkipOpeningBraceOfFile();
}
catch
{
this.Dispose();
throw new FormatException("Cannot load from file because the data in it is not JSON data, or the data is encrypted.\nIf the save data is encrypted, please ensure that encryption is enabled when you load, and that you are using the same password used to encrypt the data.");
}
}
}
#region Property/Key Methods
/*
* Reads the name of a property, and must be positioned (with or without whitespace) either:
* - Before the '"' of a property name.
* - Before the ',' separating properties.
* - Before the '}' or ']' terminating this list of properties.
* Can be used in conjunction with Read(ES3Type) to read a property.
*/
public override string ReadPropertyName()
{
char c = PeekCharIgnoreWhitespace();
// Check whether there are any properties left to read.
if(IsTerminator(c))
return null;
else if(c == ',')
ReadCharIgnoreWhitespace();
else if(!IsQuotationMark(c))
throw new FormatException("Expected ',' separating properties or '\"' before property name, found '"+c+"'.");
var propertyName = Read_string();
if(propertyName == null)
throw new FormatException("Stream isn't positioned before a property.");
ES3Debug.Log("<b>"+propertyName+"</b> (reading property)", null, serializationDepth);
// Skip the ':' seperating property and value.
ReadCharIgnoreWhitespace(':');
return propertyName;
}
/*
* Reads the type data prefixed to this key.
* If ignore is true, it will return null to save the computation of converting
* the string to a Type.
*/
protected override Type ReadKeyPrefix(bool ignoreType=false)
{
StartReadObject();
Type dataType = null;
string propertyName = ReadPropertyName();
if(propertyName == ES3Type.typeFieldName)
{
string typeString = Read_string();
dataType = ignoreType ? null : ES3Reflection.GetType(typeString);
propertyName = ReadPropertyName();
}
if(propertyName != "value")
throw new FormatException("This data is not Easy Save Key Value data. Expected property name \"value\", found \""+propertyName+"\".");
return dataType;
}
protected override void ReadKeySuffix()
{
EndReadObject();
}
internal override bool StartReadObject()
{
base.StartReadObject();
return ReadNullOrCharIgnoreWhitespace('{');
}
internal override void EndReadObject()
{
ReadCharIgnoreWhitespace('}');
base.EndReadObject();
}
internal override bool StartReadDictionary()
{
return StartReadObject();
}
internal override void EndReadDictionary(){}
internal override bool StartReadDictionaryKey()
{
// If this is an empty Dictionary, return false.
if(PeekCharIgnoreWhitespace() == '}')
{
ReadCharIgnoreWhitespace();
return false;
}
return true;
}
internal override void EndReadDictionaryKey()
{
ReadCharIgnoreWhitespace(':');
}
internal override void StartReadDictionaryValue(){}
internal override bool EndReadDictionaryValue()
{
char c = ReadCharIgnoreWhitespace();
// If we find a ']', we reached the end of the array.
if(c == '}')
return true;
// Else, we should expect a comma.
else if(c != ',')
throw new FormatException("Expected ',' seperating Dictionary items or '}' terminating Dictionary, found '"+c+"'.");
return false;
}
internal override bool StartReadCollection()
{
return ReadNullOrCharIgnoreWhitespace('[');
}
internal override void EndReadCollection(){}
internal override bool StartReadCollectionItem()
{
// If this is an empty collection, return false.
if(PeekCharIgnoreWhitespace() == ']')
{
ReadCharIgnoreWhitespace();
return false;
}
return true;
}
internal override bool EndReadCollectionItem()
{
char c = ReadCharIgnoreWhitespace();
// If we find a ']', we reached the end of the array.
if(c == ']')
return true;
// Else, we should expect a comma.
else if(c != ',')
throw new FormatException("Expected ',' seperating collection items or ']' terminating collection, found '"+c+"'.");
return false;
}
#endregion
#region Seeking Methods
/*
* Reads a string value into a StreamWriter.
* Reader should be positioned after the opening quotation mark.
* Will also read the closing quotation mark.
* If the 'skip' parameter is true, data will not be written into a StreamWriter and will return null.
*/
private void ReadString(StreamWriter writer, bool skip=false)
{
bool endOfString = false;
// Read to end of string, or throw error if we reach end of stream.
while(!endOfString)
{
char c = ReadOrSkipChar(writer, skip);
switch(c)
{
case endOfStreamChar:
throw new FormatException("String without closing quotation mark detected.");
case '\\':
ReadOrSkipChar(writer, skip);
break;
default:
if(IsQuotationMark(c))
endOfString = true;
break;
}
}
}
/*
* Reads the current object in the stream.
* Stream position should be somewhere before the opening brace for the object.
* When this method successfully exits, it will be on the closing brace for the object.
* If the 'skip' parameter is true, data will not be written into a StreamWriter and will return null.
*/
internal override byte[] ReadElement(bool skip=false)
{
// If 'skip' is enabled, don't create a stream or writer as we'll discard all bytes we read.
StreamWriter writer = skip ? null : new StreamWriter(new MemoryStream(settings.bufferSize));
using(writer)
{
int nesting = 0;
char c = (char)baseReader.Peek();
// Determine if we're skipping a primitive type.
// First check if it's an opening object or array brace.
if(!IsOpeningBrace(c))
{
// If we're skipping a string, use SkipString().
if(c == '\"')
{
// Skip initial quotation mark as SkipString() requires this.
ReadOrSkipChar(writer, skip);
ReadString(writer, skip);
}
// Else we just need to read until we reach a closing brace.
else
// While we've not peeked a closing brace.
while(!IsEndOfValue((char)baseReader.Peek()))
ReadOrSkipChar(writer, skip);
if(skip)
return null;
writer.Flush();
return ((MemoryStream)writer.BaseStream).ToArray();
}
// Else, we're skipping a type surrounded by braces.
// Iterate through every character, logging nesting.
while(true)
{
c = ReadOrSkipChar(writer, skip);
if(c == endOfStreamChar) // Detect premature end of stream, which denotes missing closing brace.
throw new FormatException("Missing closing brace detected, as end of stream was reached before finding it.");
// Handle quoted strings.
// According to the RFC, only '\' and '"' must be escaped in strings.
if(IsQuotationMark(c))
{
ReadString(writer, skip);
continue;
}
// Handle braces and other characters.
switch(c)
{
case '{': // Entered another level of nesting.
case '[':
nesting++;
break;
case '}': // Exited a level of nesting.
case ']':
nesting--;
// If nesting < 1, we've come to the end of the object.
if(nesting<1)
{
if(skip)
return null;
writer.Flush();
return ((MemoryStream)writer.BaseStream).ToArray();
}
break;
default:
break;
}
}
}
}
/*
* Reads the next char into a stream, or ignores it if 'skip' is true.
*/
private char ReadOrSkipChar(StreamWriter writer, bool skip)
{
char c = (char)baseReader.Read();
if(!skip) writer.Write(c);
return c;
}
#endregion
#region JSON-specific methods.
/*
* Reads a char from the stream and ignores leading and trailing whitespace.
*/
private char ReadCharIgnoreWhitespace(bool ignoreTrailingWhitespace=true)
{
char c;
// Skip leading whitespace and read char.
while(IsWhiteSpace(c = (char)baseReader.Read()))
{}
// Skip trailing whitespace.
if(ignoreTrailingWhitespace)
while(IsWhiteSpace((char)baseReader.Peek()))
baseReader.Read();
return c;
}
/*
* Reads a char, or the NULL value, from the stream and ignores leading and trailing whitespace.
* Returns true if NULL was read.
*/
private bool ReadNullOrCharIgnoreWhitespace(char expectedChar)
{
char c = ReadCharIgnoreWhitespace();
// Check for null
if(c == 'n')
{
var chars = new char[3];
baseReader.ReadBlock(chars, 0, 3);
if((char)chars[0] == 'u' && (char)chars[1] == 'l' && (char)chars[2] == 'l')
return true;
}
if(c != expectedChar)
{
if(c == endOfStreamChar)
throw new FormatException("End of stream reached when expecting '"+expectedChar+"'.");
else
throw new FormatException("Expected \'"+expectedChar+"\' or \"null\", found \'"+c+"\'.");
}
return false;
}
/*
* Reads a char from the stream and ignores leading and trailing whitespace.
* Throws an error if the char isn't equal to the one specificed as a parameter, or if it's the end of stream.
*/
private char ReadCharIgnoreWhitespace(char expectedChar)
{
char c = ReadCharIgnoreWhitespace();
if(c != expectedChar)
{
if(c == endOfStreamChar)
throw new FormatException("End of stream reached when expecting '"+expectedChar+"'.");
else
throw new FormatException("Expected \'"+expectedChar+"\', found \'"+c+"\'.");
}
return c;
}
private bool ReadQuotationMarkOrNullIgnoreWhitespace()
{
char c = ReadCharIgnoreWhitespace(false); // Don't read trailing whitespace as this is the value.
if(c == 'n')
{
var chars = new char[3];
baseReader.ReadBlock(chars, 0, 3);
if((char)chars[0] == 'u' && (char)chars[1] == 'l' && (char)chars[2] == 'l')
return true;
}
else if(!IsQuotationMark(c))
{
if(c == endOfStreamChar)
throw new FormatException("End of stream reached when expecting quotation mark.");
else
throw new FormatException("Expected quotation mark, found \'"+c+"\'.");
}
return false;
}
/*
* Peeks the next char in the stream, ignoring leading whitespace, but not trailing whitespace.
*/
private char PeekCharIgnoreWhitespace(char expectedChar)
{
char c = PeekCharIgnoreWhitespace();
if(c != expectedChar)
{
if(c == endOfStreamChar)
throw new FormatException("End of stream reached while peeking, when expecting '"+expectedChar+"'.");
else
throw new FormatException("Expected \'"+expectedChar+"\', found \'"+c+"\'.");
}
return c;
}
/*
* Peeks the next char in the stream, ignoring leading whitespace, but not trailing whitespace.
* Throws an error if the char isn't equal to the one specificed as a parameter.
*/
private char PeekCharIgnoreWhitespace()
{
char c;
// Skip leading whitespace and read char.
while(IsWhiteSpace(c = (char)baseReader.Peek()))
baseReader.Read();
return c;
}
// Skips all whitespace immediately after the current position.
private void SkipWhiteSpace()
{
while(IsWhiteSpace((char)baseReader.Peek()))
baseReader.Read();
}
private void SkipOpeningBraceOfFile()
{
// Skip the whitespace and '{' at the beginning of the JSON file.
char firstChar = ReadCharIgnoreWhitespace();
if(firstChar != '{') // If first char isn't '{', it's not valid JSON.
throw new FormatException("File is not valid JSON. Expected '{' at beginning of file, but found '"+firstChar+"'.");
}
private static bool IsWhiteSpace(char c)
{
return (c == ' ' || c == '\t' || c == '\n' || c == '\r');
}
private static bool IsOpeningBrace(char c)
{
return (c == '{' || c == '[');
}
private static bool IsEndOfValue(char c)
{
return (c == '}' || c == ' ' || c == '\t' || c == ']' || c == ',' || c== ':' || c == endOfStreamChar || c == '\n' || c == '\r');
}
private static bool IsTerminator(char c)
{
return (c == '}' || c == ']');
}
private static bool IsQuotationMark(char c)
{
return c == '\"' || c == '“' || c == '”';
}
private static bool IsEndOfStream(char c)
{
return c == endOfStreamChar;
}
/*
* Reads a value (i.e. non-string, non-object) from the stream as a string.
* Used mostly in Read_[type]() methods.
*/
private string GetValueString()
{
StringBuilder builder = new StringBuilder();
while(!IsEndOfValue(PeekCharIgnoreWhitespace()))
builder.Append((char)baseReader.Read());
// If it's an empty value, return null.
if(builder.Length == 0)
return null;
return builder.ToString();
}
#endregion
#region Primitive Read() Methods.
internal override string Read_string()
{
if(ReadQuotationMarkOrNullIgnoreWhitespace())
return null;
char c;
StringBuilder sb = new StringBuilder();
while(!IsQuotationMark((c = (char)baseReader.Read())))
{
// If escape mark is found, generate correct escaped character.
if(c == '\\')
{
c = (char)baseReader.Read();
if(IsEndOfStream(c))
throw new FormatException("Reached end of stream while trying to read string literal.");
switch(c)
{
case 'b':
c = '\b';
break;
case 'f':
c = '\f';
break;
case 'n':
c = '\n';
break;
case 'r':
c = '\r';
break;
case 't':
c = '\t';
break;
default:
break;
}
}
sb.Append(c);
}
return sb.ToString();
}
internal override long Read_ref()
{
if (ES3ReferenceMgr.Current == null)
throw new InvalidOperationException("An Easy Save 3 Manager is required to load references. To add one to your scene, exit playmode and go to Tools > Easy Save 3 > Add Manager to Scene");
if (IsQuotationMark(PeekCharIgnoreWhitespace()))
return long.Parse(Read_string());
return Read_long();
}
internal override char Read_char() { return char.Parse( Read_string()); }
internal override float Read_float() { return float.Parse( GetValueString(), CultureInfo.InvariantCulture); }
internal override int Read_int() { return int.Parse( GetValueString()); }
internal override bool Read_bool() { return bool.Parse( GetValueString()); }
internal override decimal Read_decimal() { return decimal.Parse( GetValueString(), CultureInfo.InvariantCulture); }
internal override double Read_double() { return double.Parse( GetValueString(), CultureInfo.InvariantCulture); }
internal override long Read_long() { return long.Parse( GetValueString()); }
internal override ulong Read_ulong() { return ulong.Parse( GetValueString()); }
internal override uint Read_uint() { return uint.Parse( GetValueString()); }
internal override byte Read_byte() { return (byte)int.Parse( GetValueString()); }
internal override sbyte Read_sbyte() { return (sbyte)int.Parse( GetValueString()); }
internal override short Read_short() { return (short)int.Parse( GetValueString()); }
internal override ushort Read_ushort() { return (ushort)int.Parse( GetValueString()); }
internal override byte[] Read_byteArray(){ return System.Convert.FromBase64String(Read_string()); }
#endregion
public override void Dispose()
{
baseReader.Dispose();
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 5eedc5128a57d504d9cb206ccc982e79
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,455 @@
using UnityEngine;
using System.IO;
using System.Collections;
using System.Collections.Generic;
using System;
using System.ComponentModel;
using ES3Types;
using ES3Internal;
public abstract class ES3Reader : System.IDisposable
{
/// <summary>The settings used to create this reader.</summary>
public ES3Settings settings;
protected int serializationDepth = 0;
#region ES3Reader Abstract Methods
internal abstract int Read_int();
internal abstract float Read_float();
internal abstract bool Read_bool();
internal abstract char Read_char();
internal abstract decimal Read_decimal();
internal abstract double Read_double();
internal abstract long Read_long();
internal abstract ulong Read_ulong();
internal abstract byte Read_byte();
internal abstract sbyte Read_sbyte();
internal abstract short Read_short();
internal abstract ushort Read_ushort();
internal abstract uint Read_uint();
internal abstract string Read_string();
internal abstract byte[] Read_byteArray();
internal abstract long Read_ref();
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public abstract string ReadPropertyName();
protected abstract Type ReadKeyPrefix(bool ignore = false);
protected abstract void ReadKeySuffix();
internal abstract byte[] ReadElement(bool skip=false);
/// <summary>Disposes of the reader and it's underlying stream.</summary>
public abstract void Dispose();
// Seeks to the given key. Note that the stream position will not be reset.
internal virtual bool Goto(string key)
{
if (key == null)
throw new ArgumentNullException("Key cannot be NULL when loading data.");
string currentKey;
while ((currentKey = ReadPropertyName()) != key)
{
if (currentKey == null)
return false;
Skip();
}
return true;
}
internal virtual bool StartReadObject()
{
serializationDepth++;
return false;
}
internal virtual void EndReadObject()
{
serializationDepth--;
}
internal abstract bool StartReadDictionary();
internal abstract void EndReadDictionary();
internal abstract bool StartReadDictionaryKey();
internal abstract void EndReadDictionaryKey();
internal abstract void StartReadDictionaryValue();
internal abstract bool EndReadDictionaryValue();
internal abstract bool StartReadCollection();
internal abstract void EndReadCollection();
internal abstract bool StartReadCollectionItem();
internal abstract bool EndReadCollectionItem();
#endregion
internal ES3Reader(ES3Settings settings, bool readHeaderAndFooter = true)
{
this.settings = settings;
}
// If this is not null, the next call to the Properties will return this name.
internal string overridePropertiesName = null;
/// <summary>Allows you to enumerate over each field name. This should only be used within an ES3Type file.</summary>
public virtual ES3ReaderPropertyEnumerator Properties
{
get
{
return new ES3ReaderPropertyEnumerator (this);
}
}
internal virtual ES3ReaderRawEnumerator RawEnumerator
{
get
{
return new ES3ReaderRawEnumerator (this);
}
}
/*
* Skips the current object in the stream.
* Stream position should be somewhere before the opening brace for the object.
* When this method successfully exits, it will be on the closing brace for the object.
*/
/// <summary>Skips the current object in the stream.</summary>
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public virtual void Skip()
{
ReadElement(true);
}
/// <summary>Reads a value of type T from the reader.</summary>
public virtual T Read<T>()
{
return Read<T>(ES3TypeMgr.GetOrCreateES3Type(typeof(T)));
}
/// <summary>Reads a value of type T from the reader into an existing object.</summary>
/// <param name="obj">The object we want to read our value into.</param>
public virtual void ReadInto<T>(object obj)
{
ReadInto<T>(obj, ES3TypeMgr.GetOrCreateES3Type(typeof(T)));
}
/// <summary>Reads a property (i.e. a property name and value) from the reader, ignoring the property name and only returning the value.</summary>
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public T ReadProperty<T>()
{
return ReadProperty<T>(ES3TypeMgr.GetOrCreateES3Type(typeof(T)));
}
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public T ReadProperty<T>(ES3Type type)
{
ReadPropertyName();
return Read<T>(type);
}
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public long ReadRefProperty()
{
ReadPropertyName();
return Read_ref();
}
internal Type ReadType()
{
return ES3Reflection.GetType(Read<string>(ES3Type_string.Instance));
}
/// <summary>Sets the value of a private property on an object.</summary>
/// <param name="name">The name of the property we want to set.</param>
/// <param name="value">The value we want to set the property to.</param>
/// <param name="objectContainingProperty">The object containing the property we want to set.</param>
/// <returns>The objectContainingProperty object. This is helpful if you're setting a private property on a struct or other immutable type and need to return the boxed value.</returns>
public object SetPrivateProperty(string name, object value, object objectContainingProperty)
{
var property = ES3Reflection.GetES3ReflectedProperty(objectContainingProperty.GetType(), name);
if (property.IsNull)
throw new MissingMemberException("A private property named " + name + " does not exist in the type " + objectContainingProperty.GetType());
property.SetValue(objectContainingProperty, value);
return objectContainingProperty;
}
/// <summary>Sets the value of a private field on an object.</summary>
/// <param name="name">The name of the field we want to set.</param>
/// <param name="value">The value we want to set the field to.</param>
/// <param name="objectContainingField">The object containing the field we want to set.</param>
/// <returns>The objectContainingField object. This is helpful if you're setting a private property on a struct or other immutable type and need to return the boxed value.</returns>
public object SetPrivateField(string name, object value, object objectContainingField)
{
var field = ES3Reflection.GetES3ReflectedMember(objectContainingField.GetType(), name);
if(field.IsNull)
throw new MissingMemberException("A private field named "+ name + " does not exist in the type "+objectContainingField.GetType());
field.SetValue(objectContainingField, value);
return objectContainingField;
}
#region Read(key) & Read(key, obj) methods
/// <summary>Reads a value from the reader with the given key.</summary>
/// <param name="key">The key which uniquely identifies our value.</param>
public virtual T Read<T>(string key)
{
if(!Goto(key))
throw new KeyNotFoundException("Key \"" + key + "\" was not found in file \""+settings.FullPath+"\". Use Load<T>(key, defaultValue) if you want to return a default value if the key does not exist.");
Type type = ReadTypeFromHeader<T>();
T obj = Read<T>(ES3TypeMgr.GetOrCreateES3Type(type));
//ReadKeySuffix(); //No need to read key suffix as we're returning. Doing so would throw an error at this point for BinaryReaders.
return obj;
}
/// <summary>Reads a value from the reader with the given key, returning the default value if the key does not exist.</summary>
/// <param name="key">The key which uniquely identifies our value.</param>
/// <param name="defaultValue">The value we want to return if this key does not exist in the reader.</param>
public virtual T Read<T>(string key, T defaultValue)
{
if(!Goto(key))
return defaultValue;
Type type = ReadTypeFromHeader<T>();
T obj = Read<T>(ES3TypeMgr.GetOrCreateES3Type(type));
//ReadKeySuffix(); //No need to read key suffix as we're returning. Doing so would throw an error at this point for BinaryReaders.
return obj;
}
/// <summary>Reads a value from the reader with the given key into the provided object.</summary>
/// <param name="key">The key which uniquely identifies our value.</param>
/// <param name="obj">The object we want to load the value into.</param>
public virtual void ReadInto<T>(string key, T obj) where T : class
{
if(!Goto(key))
throw new KeyNotFoundException("Key \"" + key + "\" was not found in file \""+settings.FullPath+"\"");
Type type = ReadTypeFromHeader<T>();
ReadInto<T>(obj, ES3TypeMgr.GetOrCreateES3Type(type));
//ReadKeySuffix(); //No need to read key suffix as we're returning. Doing so would throw an error at this point for BinaryReaders.
}
protected virtual void ReadObject<T>(object obj, ES3Type type)
{
// Check for null.
if(StartReadObject())
return;
type.ReadInto<T>(this, obj);
EndReadObject();
}
protected virtual T ReadObject<T>(ES3Type type)
{
if(StartReadObject())
return default(T);
object obj = type.Read<T>(this);
EndReadObject();
return (T)obj;
}
#endregion
#region Read(ES3Type) & Read(obj,ES3Type) methods
/*
* Parses the next JSON Object in the stream (i.e. must be between '{' and '}' chars).
* If the first character in the Stream is not a '{', it will throw an error.
* Will also read the terminating '}'.
* If we have reached the end of stream, it will return null.
*/
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public virtual T Read<T>(ES3Type type)
{
if (type == null || type.isUnsupported)
throw new NotSupportedException("Type of " + type + " is not currently supported, and could not be loaded using reflection.");
else if (type.isPrimitive)
return (T)type.Read<T>(this);
else if (type.isCollection)
return (T)((ES3CollectionType)type).Read(this);
else if (type.isDictionary)
return (T)((ES3DictionaryType)type).Read(this);
else
return ReadObject<T>(type);
}
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public virtual void ReadInto<T>(object obj, ES3Type type)
{
if(type == null || type.isUnsupported)
throw new NotSupportedException("Type of "+obj.GetType()+" is not currently supported, and could not be loaded using reflection.");
else if(type.isCollection)
((ES3CollectionType)type).ReadInto(this, obj);
else if(type.isDictionary)
((ES3DictionaryType)type).ReadInto(this, obj);
else
ReadObject<T>(obj, type);
}
#endregion
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
internal Type ReadTypeFromHeader<T>()
{
// Check whether we need to determine the type by reading the header.
if(typeof(T) == typeof(object))
return ReadKeyPrefix();
else if(settings.typeChecking)
{
Type type = ReadKeyPrefix();
if(type != typeof(T))
throw new InvalidOperationException("Trying to load data of type "+typeof(T)+", but data contained in file is type of "+type+".");
return type;
}
else
{
ReadKeyPrefix(true);
return typeof(T);
}
}
/// <summary>Creates a new ES3Reader and loads the default file into it.</summary>
public static ES3Reader Create()
{
return Create(new ES3Settings());
}
/// <summary>Creates a new ES3Reader and loads a file in storage into it.</summary>
/// <param name="filePath">The relative or absolute path of the file we want to load into the reader.</param>
public static ES3Reader Create(string filePath)
{
return Create(new ES3Settings(filePath));
}
/// <summary>Creates a new ES3Reader and loads a file in storage into it.</summary>
/// <param name="filePath">The relative or absolute path of the file we want to load into the reader.</param>
/// <param name="settings">The settings we want to use to override the default settings.</param>
public static ES3Reader Create(string filePath, ES3Settings settings)
{
return Create(new ES3Settings(filePath, settings));
}
/// <summary>Creates a new ES3Reader and loads a file in storage into it.</summary>
/// <param name="settings">The settings we want to use to override the default settings.</param>
public static ES3Reader Create(ES3Settings settings)
{
Stream stream = ES3Stream.CreateStream(settings, ES3FileMode.Read);
if(stream == null)
return null;
// Get the baseWriter using the given Stream.
if (settings.format == ES3.Format.JSON)
return new ES3JSONReader(stream, settings);
return null;
}
/// <summary>Creates a new ES3Reader and loads the bytes provided into it.</summary>
public static ES3Reader Create(byte[] bytes)
{
return Create(bytes, new ES3Settings());
}
/// <summary>Creates a new ES3Reader and loads the bytes provided into it.</summary>
/// <param name="settings">The settings we want to use to override the default settings.</param>
public static ES3Reader Create(byte[] bytes, ES3Settings settings)
{
Stream stream = ES3Stream.CreateStream(new MemoryStream(bytes), settings, ES3FileMode.Read);
if(stream == null)
return null;
// Get the baseWriter using the given Stream.
if(settings.format == ES3.Format.JSON)
return new ES3JSONReader(stream, settings);
return null;
}
internal static ES3Reader Create(Stream stream, ES3Settings settings)
{
stream = ES3Stream.CreateStream(stream, settings, ES3FileMode.Read);
// Get the baseWriter using the given Stream.
if(settings.format == ES3.Format.JSON)
return new ES3JSONReader(stream, settings);
return null;
}
internal static ES3Reader Create(Stream stream, ES3Settings settings, bool readHeaderAndFooter)
{
// Get the baseWriter using the given Stream.
if(settings.format == ES3.Format.JSON)
return new ES3JSONReader(stream, settings, readHeaderAndFooter);
return null;
}
[EditorBrowsable(EditorBrowsableState.Never)]
public class ES3ReaderPropertyEnumerator
{
public ES3Reader reader;
public ES3ReaderPropertyEnumerator(ES3Reader reader)
{
this.reader = reader;
}
public IEnumerator GetEnumerator()
{
string propertyName;
while(true)
{
// Allows us to repeat a property name or insert one of our own.
if(reader.overridePropertiesName != null)
{
string tempName = reader.overridePropertiesName;
reader.overridePropertiesName = null;
yield return tempName;
}
else
{
if((propertyName = reader.ReadPropertyName()) == null)
yield break;
yield return propertyName;
}
}
}
}
[EditorBrowsable(EditorBrowsableState.Never)]
public class ES3ReaderRawEnumerator
{
public ES3Reader reader;
public ES3ReaderRawEnumerator(ES3Reader reader)
{
this.reader = reader;
}
public IEnumerator GetEnumerator()
{
while(true)
{
string key = reader.ReadPropertyName();
if(key == null)
yield break;
Type type = reader.ReadTypeFromHeader<object>();
byte[] bytes = reader.ReadElement();
reader.ReadKeySuffix();
if(type != null)
yield return new KeyValuePair<string,ES3Data>(key, new ES3Data(type, bytes));
}
}
}
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 29f55012df690f34984d485a5983d775
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,5 @@

public class ES3XMLReader
{
// Not Implemented
}

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: e951676a466b3e640829190b151f54f3
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: