251 lines
7.9 KiB
C#
251 lines
7.9 KiB
C#
using System;
|
|
using System.Threading.Tasks;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using UnityEngine;
|
|
using System.Threading;
|
|
|
|
namespace LeanCloud.Storage.Internal
|
|
{
|
|
/// <summary>
|
|
/// Implements `IStorageController` for PCL targets, based off of PCLStorage.
|
|
/// </summary>
|
|
public class StorageController : IStorageController
|
|
{
|
|
private const string LeanCloudStorageFileName = "LeanCloud.settings";
|
|
|
|
private TaskQueue taskQueue = new TaskQueue();
|
|
private string settingsPath;
|
|
private StorageDictionary storageDictionary;
|
|
private bool isWebPlayer;
|
|
|
|
private class StorageDictionary : IStorageDictionary<string, object>
|
|
{
|
|
private object mutex;
|
|
private Dictionary<string, object> dictionary;
|
|
private string settingsPath;
|
|
private bool isWebPlayer;
|
|
|
|
public StorageDictionary(string settingsPath, bool isWebPlayer)
|
|
{
|
|
this.settingsPath = settingsPath;
|
|
this.isWebPlayer = isWebPlayer;
|
|
|
|
mutex = new object();
|
|
dictionary = new Dictionary<string, object>();
|
|
}
|
|
|
|
internal Task SaveAsync()
|
|
{
|
|
string jsonEncoded;
|
|
lock (mutex)
|
|
{
|
|
jsonEncoded = Json.Encode(dictionary);
|
|
}
|
|
|
|
if (this.isWebPlayer)
|
|
{
|
|
PlayerPrefs.SetString(LeanCloudStorageFileName, jsonEncoded);
|
|
PlayerPrefs.Save();
|
|
}
|
|
else if (Application.platform == RuntimePlatform.tvOS)
|
|
{
|
|
Debug.Log("Running on TvOS, prefs cannot be saved.");
|
|
}
|
|
else
|
|
{
|
|
using (var fs = new FileStream(settingsPath, FileMode.Create, FileAccess.Write))
|
|
{
|
|
using (var writer = new StreamWriter(fs))
|
|
{
|
|
writer.Write(jsonEncoded);
|
|
}
|
|
}
|
|
}
|
|
|
|
return Task.FromResult<object>(null);
|
|
}
|
|
|
|
internal Task LoadAsync()
|
|
{
|
|
string jsonString = null;
|
|
|
|
try
|
|
{
|
|
if (this.isWebPlayer)
|
|
{
|
|
jsonString = PlayerPrefs.GetString(LeanCloudStorageFileName, null);
|
|
}
|
|
else if (Application.platform == RuntimePlatform.tvOS)
|
|
{
|
|
Debug.Log("Running on TvOS, prefs cannot be loaded.");
|
|
}
|
|
else
|
|
{
|
|
using (var fs = new FileStream(settingsPath, FileMode.Open, FileAccess.Read))
|
|
{
|
|
var reader = new StreamReader(fs);
|
|
jsonString = reader.ReadToEnd();
|
|
}
|
|
}
|
|
}
|
|
catch (Exception)
|
|
{
|
|
// Do nothing
|
|
}
|
|
|
|
if (jsonString == null)
|
|
{
|
|
lock (mutex)
|
|
{
|
|
dictionary = new Dictionary<string, object>();
|
|
return Task.FromResult<object>(null);
|
|
}
|
|
}
|
|
|
|
Dictionary<string, object> decoded = Json.Parse(jsonString) as Dictionary<string, object>;
|
|
lock (mutex)
|
|
{
|
|
dictionary = decoded ?? new Dictionary<string, object>();
|
|
return Task.FromResult<object>(null);
|
|
}
|
|
}
|
|
|
|
internal void Update(IDictionary<string, object> contents)
|
|
{
|
|
lock (mutex)
|
|
{
|
|
dictionary = contents.ToDictionary(p => p.Key, p => p.Value);
|
|
}
|
|
}
|
|
|
|
public Task AddAsync(string key, object value)
|
|
{
|
|
lock (mutex)
|
|
{
|
|
dictionary[key] = value;
|
|
}
|
|
return SaveAsync();
|
|
}
|
|
|
|
public Task RemoveAsync(string key)
|
|
{
|
|
lock (mutex)
|
|
{
|
|
dictionary.Remove(key);
|
|
}
|
|
return SaveAsync();
|
|
}
|
|
|
|
public bool ContainsKey(string key)
|
|
{
|
|
lock (mutex)
|
|
{
|
|
return dictionary.ContainsKey(key);
|
|
}
|
|
}
|
|
|
|
public IEnumerable<string> Keys
|
|
{
|
|
get { lock (mutex) { return dictionary.Keys; } }
|
|
}
|
|
|
|
public bool TryGetValue(string key, out object value)
|
|
{
|
|
lock (mutex)
|
|
{
|
|
return dictionary.TryGetValue(key, out value);
|
|
}
|
|
}
|
|
|
|
public IEnumerable<object> Values
|
|
{
|
|
get { lock (mutex) { return dictionary.Values; } }
|
|
}
|
|
|
|
public object this[string key]
|
|
{
|
|
get { lock (mutex) { return dictionary[key]; } }
|
|
}
|
|
|
|
public int Count
|
|
{
|
|
get { lock (mutex) { return dictionary.Count; } }
|
|
}
|
|
|
|
public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
|
|
{
|
|
lock (mutex)
|
|
{
|
|
return dictionary.GetEnumerator();
|
|
}
|
|
}
|
|
|
|
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
|
|
{
|
|
lock (mutex)
|
|
{
|
|
return dictionary.GetEnumerator();
|
|
}
|
|
}
|
|
}
|
|
|
|
public StorageController()
|
|
: this(Path.Combine(Application.persistentDataPath, LeanCloudStorageFileName), false)
|
|
{
|
|
|
|
}
|
|
|
|
public StorageController(String settingsPath)
|
|
: this(settingsPath, false)
|
|
{
|
|
|
|
}
|
|
public StorageController(bool isWebPlayer, string fileNamePrefix)
|
|
: this(Path.Combine(Application.persistentDataPath, string.Format("{0}_{1}", fileNamePrefix, LeanCloudStorageFileName)), isWebPlayer)
|
|
{
|
|
|
|
}
|
|
|
|
public StorageController(string settingsPath, bool isWebPlayer)
|
|
{
|
|
this.settingsPath = settingsPath;
|
|
this.isWebPlayer = isWebPlayer;
|
|
}
|
|
|
|
public Task<IStorageDictionary<string, object>> LoadAsync()
|
|
{
|
|
return taskQueue.Enqueue(toAwait =>
|
|
{
|
|
return toAwait.ContinueWith(_ =>
|
|
{
|
|
if (storageDictionary != null)
|
|
{
|
|
return Task.FromResult<IStorageDictionary<string, object>>(storageDictionary);
|
|
}
|
|
storageDictionary = new StorageDictionary(settingsPath, this.isWebPlayer);
|
|
return storageDictionary.LoadAsync().OnSuccess(__ => storageDictionary as IStorageDictionary<string, object>);
|
|
}).Unwrap();
|
|
}, CancellationToken.None);
|
|
}
|
|
|
|
public Task<IStorageDictionary<string, object>> SaveAsync(IDictionary<string, object> contents)
|
|
{
|
|
return taskQueue.Enqueue(toAwait =>
|
|
{
|
|
return toAwait.ContinueWith(_ =>
|
|
{
|
|
if (storageDictionary == null)
|
|
{
|
|
storageDictionary = new StorageDictionary(settingsPath, this.isWebPlayer);
|
|
}
|
|
|
|
storageDictionary.Update(contents);
|
|
return storageDictionary.SaveAsync().OnSuccess(__ => storageDictionary as IStorageDictionary<string, object>);
|
|
}).Unwrap();
|
|
}, CancellationToken.None);
|
|
}
|
|
}
|
|
}
|