From 61cb54a0303a4b44da9609c709b53f68491f0f7c Mon Sep 17 00:00:00 2001 From: mbdavid Date: Sat, 11 Mar 2017 14:01:42 -0300 Subject: [PATCH] Add Regex to custom type #515 --- LiteDB.Tests/LiteDB.Tests.csproj | 1 + LiteDB.Tests/Mapper/CustomTypeTest.cs | 51 ++++++++++++++++++++++++++ LiteDB/Database/LiteDatabase.cs | 3 ++ LiteDB/Engine/Disks/FileDiskService.cs | 39 +++++++++++++++----- LiteDB/Mapper/BsonMapper.cs | 5 +++ LiteDB/Utils/ConnectionString.cs | 10 +++++ LiteDB/Utils/FileOptions.cs | 3 ++ 7 files changed, 103 insertions(+), 9 deletions(-) create mode 100644 LiteDB.Tests/Mapper/CustomTypeTest.cs diff --git a/LiteDB.Tests/LiteDB.Tests.csproj b/LiteDB.Tests/LiteDB.Tests.csproj index 00022004e..df29215a2 100644 --- a/LiteDB.Tests/LiteDB.Tests.csproj +++ b/LiteDB.Tests/LiteDB.Tests.csproj @@ -70,6 +70,7 @@ + diff --git a/LiteDB.Tests/Mapper/CustomTypeTest.cs b/LiteDB.Tests/Mapper/CustomTypeTest.cs new file mode 100644 index 000000000..08b7a6deb --- /dev/null +++ b/LiteDB.Tests/Mapper/CustomTypeTest.cs @@ -0,0 +1,51 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.IO; +using System.Linq; +using System.Collections.Generic; +using System.Text.RegularExpressions; + +namespace LiteDB.Tests +{ + #region Model + + public class CustomType + { + public Regex Re1 { get; set; } + public Regex Re2 { get; set; } + + public Uri Url { get; set; } + public TimeSpan Ts { get; set; } + } + + #endregion + + [TestClass] + public class CustomTypeTest + { + [TestMethod] + public void CustomType_Test() + { + var mapper = new BsonMapper(); + var o = new CustomType + { + Re1 = new Regex("^a+"), + Re2 = new Regex("^a*", RegexOptions.Compiled | RegexOptions.IgnorePatternWhitespace), + Url = new Uri("http://www.litedb.org"), + Ts = TimeSpan.FromSeconds(10) + }; + + var doc = mapper.ToDocument(o); + var no = mapper.ToObject(doc); + + Assert.AreEqual("^a+", doc["Re1"].AsString); + Assert.AreEqual("^a*", doc["Re2"].AsDocument["p"].AsString); + + Assert.AreEqual(o.Re1.ToString(), no.Re1.ToString()); + Assert.AreEqual(o.Re2.ToString(), no.Re2.ToString()); + Assert.AreEqual(o.Re2.Options, no.Re2.Options); + Assert.AreEqual(o.Url, no.Url); + Assert.AreEqual(o.Ts, no.Ts); + } + } +} \ No newline at end of file diff --git a/LiteDB/Database/LiteDatabase.cs b/LiteDB/Database/LiteDatabase.cs index b3edab031..b55c007cc 100644 --- a/LiteDB/Database/LiteDatabase.cs +++ b/LiteDB/Database/LiteDatabase.cs @@ -63,6 +63,9 @@ public LiteDatabase(ConnectionString connectionString, BsonMapper mapper = null) var options = new FileOptions { +#if !NET35 + Async = _connectionString.Async, +#endif InitialSize = _connectionString.InitialSize, LimitSize = _connectionString.LimitSize, Journal = _connectionString.Journal diff --git a/LiteDB/Engine/Disks/FileDiskService.cs b/LiteDB/Engine/Disks/FileDiskService.cs index 1e22692c9..bcb3ca530 100644 --- a/LiteDB/Engine/Disks/FileDiskService.cs +++ b/LiteDB/Engine/Disks/FileDiskService.cs @@ -2,6 +2,9 @@ using System.Collections.Generic; using System.IO; using System.Threading; +#if !NET35 +using System.Threading.Tasks; +#endif namespace LiteDB { @@ -66,11 +69,10 @@ public void Initialize(Logger log, string password) if (_options.FileMode == FileMode.ReadOnly) _options.Journal = false; // open/create file using read only/exclusive options - _stream = new FileStream(_filename, + _stream = CreateFileStream(_filename, _options.FileMode == FileMode.ReadOnly ? System.IO.FileMode.Open : System.IO.FileMode.OpenOrCreate, _options.FileMode == FileMode.ReadOnly ? FileAccess.Read : FileAccess.ReadWrite, - _options.FileMode == FileMode.Exclusive ? FileShare.None : FileShare.ReadWrite, - BasePage.PAGE_SIZE); + _options.FileMode == FileMode.Exclusive ? FileShare.None : FileShare.ReadWrite); // if file is new, initialize if (_stream.Length == 0) @@ -179,11 +181,10 @@ public void WriteJournal(ICollection pages) if (_journal == null) { // open or create datafile if not exists - _journal = new FileStream(_journalFilename, + _journal = CreateFileStream(_journalFilename, System.IO.FileMode.OpenOrCreate, FileAccess.ReadWrite, - FileShare.ReadWrite, - BasePage.PAGE_SIZE); + FileShare.ReadWrite); } // lock first byte @@ -223,11 +224,10 @@ public IEnumerable ReadJournal() { try { - _journal = new FileStream(_journalFilename, + _journal = CreateFileStream(_journalFilename, System.IO.FileMode.Open, FileAccess.ReadWrite, - FileShare.ReadWrite, - BasePage.PAGE_SIZE); + FileShare.ReadWrite); // just avoid initialize recovery if journal is empty if (_journal.Length == 0) yield break; @@ -335,5 +335,26 @@ public void Unlock(LockState state) } #endregion + + /// + /// Create a new filestream. Can be synced over async task (netstandard) + /// + private FileStream CreateFileStream(string path, System.IO.FileMode mode, FileAccess access, FileShare share) + { +#if !NET35 + if (_options.Async) + { + return this.SyncOverAsync(() => new FileStream(path, mode, access, share, BasePage.PAGE_SIZE)); + } +#endif + return new FileStream(path, mode, access, share, BasePage.PAGE_SIZE); + } + +#if !NET35 + private T SyncOverAsync(Func f) + { + return Task.Run(f).ConfigureAwait(false).GetAwaiter().GetResult(); + } +#endif } } \ No newline at end of file diff --git a/LiteDB/Mapper/BsonMapper.cs b/LiteDB/Mapper/BsonMapper.cs index 09d9b6a0f..0cafe340b 100644 --- a/LiteDB/Mapper/BsonMapper.cs +++ b/LiteDB/Mapper/BsonMapper.cs @@ -116,6 +116,11 @@ public BsonMapper(Func customTypeInstantiator = null) RegisterType(uri => uri.AbsoluteUri, bson => new Uri(bson.AsString)); RegisterType(value => new BsonValue(value.UtcDateTime), bson => bson.AsDateTime.ToUniversalTime()); RegisterType(value => new BsonValue(value.Ticks), bson => new TimeSpan(bson.AsInt64)); + RegisterType( + r => r.Options == RegexOptions.None ? new BsonValue(r.ToString()) : new BsonDocument { { "p", r.ToString() }, { "o", (int)r.Options } }, + value => value.IsString ? new Regex(value) : new Regex(value.AsDocument["p"].AsString, (RegexOptions)value.AsDocument["o"].AsInt32) + ); + #endregion Register CustomTypes diff --git a/LiteDB/Utils/ConnectionString.cs b/LiteDB/Utils/ConnectionString.cs index 99069f6dd..cb4373e39 100644 --- a/LiteDB/Utils/ConnectionString.cs +++ b/LiteDB/Utils/ConnectionString.cs @@ -64,6 +64,13 @@ public class ConnectionString /// public bool Upgrade { get; set; } +#if !NET35 + /// + /// "async": Use "sync over async" to UWP apps access any directory + /// + public bool Async { get; set; } +#endif + /// /// Initialize empty connection string /// @@ -105,6 +112,9 @@ public ConnectionString(string connectionString) this.LimitSize = values.GetFileSize(@"limit size", long.MaxValue); this.Log = values.GetValue("log", Logger.NONE); this.Upgrade = values.GetValue("upgrade", false); +#if !NET35 + this.Async = values.GetValue("async", false); +#endif } } } \ No newline at end of file diff --git a/LiteDB/Utils/FileOptions.cs b/LiteDB/Utils/FileOptions.cs index 42087a5c8..2f50896ba 100644 --- a/LiteDB/Utils/FileOptions.cs +++ b/LiteDB/Utils/FileOptions.cs @@ -11,6 +11,9 @@ public class FileOptions public long InitialSize { get; set; } public long LimitSize { get; set; } public FileMode FileMode { get; set; } +#if !NET35 + public bool Async { get; set; } +#endif public FileOptions() {