Paradox Game Engine  v1.0.0 beta06
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros Pages
DatabaseFileProvider.cs
Go to the documentation of this file.
1 // Copyright (c) 2014 Silicon Studio Corp. (http://siliconstudio.co.jp)
2 // This file is distributed under GPL v3. See LICENSE.md for details.
3 using System;
4 using System.IO;
5 using System.Linq;
6 using System.Text.RegularExpressions;
7 
8 using SiliconStudio.Core.Storage;
9 using SiliconStudio.Core.Serialization;
10 using SiliconStudio.Core.Serialization.Assets;
11 
12 namespace SiliconStudio.Core.IO
13 {
15  {
16  private readonly IAssetIndexMap assetIndexMap;
17  private readonly ObjectDatabase objectDatabase;
18 
19  public DatabaseFileProvider(ObjectDatabase objectDatabase, string mountPoint = null) : this(objectDatabase.AssetIndexMap, objectDatabase, mountPoint)
20  {
21  }
22 
23  public DatabaseFileProvider(IAssetIndexMap assetIndexMap, ObjectDatabase objectDatabase, string mountPoint = null) : base(mountPoint)
24  {
25  this.assetIndexMap = assetIndexMap;
26  this.objectDatabase = objectDatabase;
27  }
28 
30  {
31  get { return assetIndexMap; }
32  }
33 
35  {
36  get { return objectDatabase; }
37  }
38 
39  /// <inheritdoc/>
40  public override Stream OpenStream(string url, VirtualFileMode mode, VirtualFileAccess access, VirtualFileShare share = VirtualFileShare.Read, StreamFlags streamFlags = StreamFlags.None)
41  {
42  // Open or create the file through the underlying (IAssetIndexMap, IOdbBackend) couple.
43  // Also read/write a ObjectHeader.
44  if (mode == VirtualFileMode.Open)
45  {
46  ObjectId objectId;
47  if (url.StartsWith("obj/"))
48  ObjectId.TryParse(url.Substring(4), out objectId);
49  else if (!assetIndexMap.TryGetValue(url, out objectId))
50  throw new FileNotFoundException();
51 
52  var result = objectDatabase.OpenStream(objectId, mode, access, share);
53 
54  // copy the stream into a memory stream in order to make it seek-able
55  if (streamFlags == StreamFlags.Seekable && !result.CanSeek)
56  {
57  var buffer = new byte[result.Length - result.Position];
58  result.Read(buffer, 0, buffer.Length);
59  return new DatabaseReadFileStream(objectId, new MemoryStream(buffer), 0);
60  }
61 
62  return new DatabaseReadFileStream(objectId, result, result.Position);
63  }
64 
65  if (mode == VirtualFileMode.Create)
66  {
67  if (url.StartsWith("obj/"))
68  throw new NotSupportedException();
69 
70  var stream = objectDatabase.CreateStream();
71 
72  // Header will be written by DatabaseWriteFileStream
73  var result = new DatabaseWriteFileStream(stream, stream.Position);
74 
75  stream.Disposed += x =>
76  {
77  // Commit index changes
78  assetIndexMap[url] = x.CurrentHash;
79  };
80 
81  return result;
82  }
83 
84  throw new ArgumentException("mode");
85  }
86 
87  public override string[] ListFiles(string url, string searchPattern, VirtualSearchOption searchOption)
88  {
89  url = Regex.Escape(url);
90  searchPattern = Regex.Escape(searchPattern).Replace(@"\*", "[^/]*").Replace(@"\?", "[^/]");
91  string recursivePattern = searchOption == VirtualSearchOption.AllDirectories ? "(.*/)*" : "/?";
92  var regex = new Regex("^" + url + recursivePattern + searchPattern + "$");
93 
94  return assetIndexMap.SearchValues(x => regex.IsMatch(x.Key)).Select(x => x.Key).ToArray();
95  }
96 
97  public override bool FileExists(string url)
98  {
99  ObjectId objectId;
100  return assetIndexMap.TryGetValue(url, out objectId)
101  && objectDatabase.Exists(objectId);
102  }
103 
104  public override long FileSize(string url)
105  {
106  ObjectId objectId;
107  if (!assetIndexMap.TryGetValue(url, out objectId))
108  throw new FileNotFoundException();
109 
110  return objectDatabase.GetSize(objectId);
111  }
112 
113  public override string GetAbsolutePath(string url)
114  {
115  ObjectId objectId;
116  if (!assetIndexMap.TryGetValue(url, out objectId))
117  throw new FileNotFoundException();
118 
119  return objectDatabase.GetFilePath(objectId);
120  }
121 
122 
123  /// <summary>
124  /// Resolves the given VFS URL into a ObjectId and its DatabaseFileProvider.
125  /// </summary>
126  /// <param name="url">The URL to resolve.</param>
127  /// <param name="objectId">The object id.</param>
128  /// <returns>The <see cref="DatabaseFileProvider"/> containing this object if it could be found; [null] otherwise.</returns>
129  public static DatabaseFileProvider ResolveObjectId(string url, out ObjectId objectId)
130  {
131  var resolveProviderResult = VirtualFileSystem.ResolveProvider(url, false);
132  var provider = resolveProviderResult.Provider as DatabaseFileProvider;
133  if (provider == null)
134  {
135  objectId = ObjectId.Empty;
136  return null;
137  }
138  return provider.AssetIndexMap.TryGetValue(resolveProviderResult.Path, out objectId) ? provider : null;
139  }
140 
141  abstract class DatabaseFileStream : VirtualFileStream, IDatabaseStream
142  {
143  protected DatabaseFileStream(Stream internalStream, long startPosition, bool seekToBeginning = true)
144  : base(internalStream, startPosition, seekToBeginning: seekToBeginning)
145  {
146  }
147 
148  public abstract ObjectId ObjectId { get; }
149  }
150 
151  class DatabaseReadFileStream : DatabaseFileStream
152  {
153  private ObjectId id;
154  public DatabaseReadFileStream(ObjectId id, Stream internalStream, long startPosition)
155  : base(internalStream, startPosition, false)
156  {
157  this.id = id;
158  }
159 
160  public override ObjectId ObjectId
161  {
162  get
163  {
164  return id;
165  }
166  }
167  }
168 
169  class DatabaseWriteFileStream : DatabaseFileStream
170  {
171  public DatabaseWriteFileStream(Stream internalStream, long startPosition)
172  : base(internalStream, startPosition, false)
173  {
174  }
175 
176  public override ObjectId ObjectId
177  {
178  get
179  {
180  throw new NotSupportedException();
181  }
182  }
183  }
184  }
185 }
static DatabaseFileProvider ResolveObjectId(string url, out ObjectId objectId)
Resolves the given VFS URL into a ObjectId and its DatabaseFileProvider.
Abstract base class for IVirtualFileProvider.
VirtualFileShare
File share capabilities, equivalent of System.IO.FileShare.
override bool FileExists(string url)
Determines whether the specified path points to an existing file. The path.
Gives access to the object database.
override Stream OpenStream(string url, VirtualFileMode mode, VirtualFileAccess access, VirtualFileShare share=VirtualFileShare.Read, StreamFlags streamFlags=StreamFlags.None)
Opens a Stream from the specified path. The path.The mode.The access.The process sharing mode...
VirtualFileAccess
File access equivalent of System.IO.FileAccess.
VirtualFileMode
File mode equivalent of System.IO.FileMode.
A hash to uniquely identify data.
Definition: ObjectId.cs:13
DatabaseFileProvider(IAssetIndexMap assetIndexMap, ObjectDatabase objectDatabase, string mountPoint=null)
document false
override string GetAbsolutePath(string url)
Gets the absolute path for the specified local path from this provider. The path local to this instan...
static bool TryParse(string input, out ObjectId result)
Tries to parse an ObjectId from a string.
Definition: ObjectId.cs:102
A multithreaded wrapper over a Stream, used by the VirtualFileSystem. It also allows restricted acces...
StreamFlags
Describes the different type of streams.
Definition: StreamFlags.cs:11
DatabaseFileProvider(ObjectDatabase objectDatabase, string mountPoint=null)
override long FileSize(string url)
Returns the size of the specified file in bytes The file or directory for which to obtain sizeA long ...
override string[] ListFiles(string url, string searchPattern, VirtualSearchOption searchOption)
Returns the list of files from the specified path. The path.The search pattern.The search option...