4 using System.Collections.Generic;
8 using System.Text.RegularExpressions;
9 using System.Threading.Tasks;
11 namespace SiliconStudio.Core.IO
19 public static readonly
char DirectorySeparatorChar =
'/';
20 public static readonly
char AltDirectorySeparatorChar =
'\\';
21 public static readonly
char[] AllDirectorySeparatorChars =
new[] { DirectorySeparatorChar, AltDirectorySeparatorChar };
23 private static readonly Regex pathSplitRegex =
new Regex(
@"(\\|/)");
28 private static Random tempFileRandom =
new Random(Environment.TickCount);
30 private static Dictionary<string, IVirtualFileProvider> providers =
new Dictionary<string, IVirtualFileProvider>();
82 Platform.IsVirtualFileSystemInitialized =
true;
84 #if SILICONSTUDIO_PLATFORM_ANDROID
85 ApplicationData =
new ZipFileSystemProvider(
"/data", PlatformAndroid.Context.ApplicationInfo.SourceDir);
90 #if SILICONSTUDIO_PLATFORM_IOS
109 return providers.Values;
121 if (providers.ContainsKey(provider.
RootPath))
122 throw new InvalidOperationException(
string.Format(
"A Virtual File Provider with the root path \"{0}\" already exists.", provider.
RootPath));
124 providers.Add(provider.RootPath, provider);
135 var mountPoints = providers.Where(x => x.Value == provider).ToArray();
136 foreach (var mountPoint
in mountPoints)
137 providers.Remove(mountPoint.Key);
141 var disposable = provider as IDisposable;
142 if (disposable != null)
143 disposable.Dispose();
166 mountPoint += VirtualFileSystem.DirectorySeparatorChar;
169 var provider = providers.FirstOrDefault(x => x.Key == mountPoint);
170 if (provider.Value != null)
173 return provider.Value;
187 if (path == null)
throw new ArgumentNullException(
"path");
188 var result = ResolveProviderUnsafe(path,
true);
189 if (result.Provider == null)
192 return result.Provider.FileExists(result.Path);
202 if (path == null)
throw new ArgumentNullException(
"path");
203 var result = ResolveProviderUnsafe(path,
true);
204 if (result.Provider == null)
207 return result.Provider.DirectoryExists(result.Path);
212 var result = ResolveProvider(path,
true);
213 result.Provider.FileDelete(result.Path);
216 public static void FileMove(
string sourcePath,
string destinationPath)
223 sourceResult.Provider.FileMove(sourceResult.Path, destinationResult.Path);
227 sourceResult.Provider.FileMove(sourceResult.Path, destinationResult.Provider, destinationResult.Path);
233 var result = ResolveProvider(path,
true);
234 return result.Provider.FileSize(result.Path);
239 var result = ResolveProvider(path,
true);
240 return result.Provider.GetLastWriteTime(result.Path);
246 return Task<bool>.Factory.StartNew(() => FileExists(path));
255 var resolveProviderResult = ResolveProvider(path,
true);
256 resolveProviderResult.Provider.CreateDirectory(resolveProviderResult.Path);
269 var resolveProviderResult = ResolveProvider(path,
false);
270 return resolveProviderResult.Provider.OpenStream(resolveProviderResult.Path, mode, access, share);
284 var resolveProviderResult = ResolveProvider(path,
false);
285 provider = resolveProviderResult.Provider;
286 return provider.OpenStream(resolveProviderResult.Path, mode, access, share);
291 return Task<Stream>.Factory.StartNew(() => OpenStream(path, mode, access, share));
301 var resolveProviderResult = ResolveProvider(path,
true);
302 return resolveProviderResult.Provider.GetAbsolutePath(resolveProviderResult.Path);
312 var resolveProviderResult = ResolveProvider(path,
false);
314 var sb =
new StringBuilder();
315 if (resolveProviderResult.Provider.RootPath !=
".")
317 sb.Append(resolveProviderResult.Provider.RootPath);
320 sb.Append(resolveProviderResult.Path);
322 return sb.ToString();
334 var resolveProviderResult = ResolveProvider(path,
true);
335 return Task.Factory.StartNew(() => resolveProviderResult.Provider.ListFiles(resolveProviderResult.Path, searchPattern, searchOption)
336 .Select(x => resolveProviderResult.Provider.RootPath + x).ToArray());
350 filename =
"pdx" + ((tempFileRandom.Next() + 1)).ToString(
"x") +
".tmp";
353 stream = ApplicationTemporary.OpenStream(filename, VirtualFileMode.CreateNew, VirtualFileAccess.ReadWrite);
358 if (tentatives++ > 0x10000)
361 }
while (stream == null);
364 return ApplicationTemporary.RootPath +
"/" + filename;
367 public static string BuildPath(
string path,
string relativePath)
369 return path.Substring(0, LastIndexOfDirectorySeparator(path) + 1) + relativePath;
379 if (!path.Contains(DirectorySeparatorChar +
".."))
382 var pathElements = pathSplitRegex.Split(path).ToList();
385 for (
int i = 0; i < pathElements.Count; ++i)
387 if (pathElements[i].Length > 1 && (pathElements[i][0] ==
'/' || pathElements[i][0] ==
'\\'))
388 pathElements[i] = pathElements[i][0].ToString();
391 for (
int i = 0; i < pathElements.Count; ++i)
393 if (pathElements[i] ==
"..")
396 if (i >= 3 && (pathElements[i - 1] ==
"/" || pathElements[i - 1] ==
"\\"))
398 pathElements.RemoveRange(i - 3, 4);
402 else if (pathElements[i] ==
".")
404 if (i >= 1 && (pathElements[i - 1] ==
"/" || pathElements[i - 1] ==
"\\"))
406 pathElements.RemoveRange(i - 1, 2);
409 else if (i + 1 < pathElements.Count && (pathElements[i + 1] ==
"/" || pathElements[i + 1] ==
"\\"))
411 pathElements.RemoveRange(i, 2);
417 return string.Join(string.Empty, pathElements);
427 public static string Combine(
string path1,
string path2)
429 if (path1.Length == 0)
431 if (path2.Length == 0)
434 var lastPath1 = path1[path1.Length - 1];
435 if (lastPath1 != DirectorySeparatorChar && lastPath1 != AltDirectorySeparatorChar)
436 return path1 + DirectorySeparatorChar + path2;
438 return path1 + path2;
451 throw new ArgumentNullException(
"path");
453 var lastSlashIndex = LastIndexOfDirectorySeparator(path);
454 if (lastSlashIndex == -1)
455 throw new ArgumentException(
string.Format(
"path [{0}] doesn't contain a /", path),
"path");
457 return path.Substring(0, lastSlashIndex);
468 throw new ArgumentNullException(
"path");
470 var lastSlashIndex = LastIndexOfDirectorySeparator(path);
472 return path.Substring(lastSlashIndex + 1);
483 var targetDirectories = target.Split(AllDirectorySeparatorChars, StringSplitOptions.RemoveEmptyEntries);
484 var sourceDirectories = sourcePath.Split(AllDirectorySeparatorChars, StringSplitOptions.RemoveEmptyEntries);
487 int length = Math.Min(targetDirectories.Length, sourceDirectories.Length);
489 for (commonRoot = 0; commonRoot < length; ++commonRoot)
491 if (targetDirectories[commonRoot] != sourceDirectories[commonRoot])
495 var result =
new StringBuilder();
498 for (
int i = commonRoot; i < sourceDirectories.Length; ++i)
500 result.Append(
".." + DirectorySeparatorChar);
504 for (
int i = commonRoot; i < targetDirectories.Length; ++i)
506 result.Append(targetDirectories[i]);
507 if (i < targetDirectories.Length - 1)
508 result.Append(DirectorySeparatorChar);
511 return result.ToString();
523 if (path == null)
throw new ArgumentNullException(
"path");
524 var result = ResolveProviderUnsafe(path, resolveTop);
525 if (result.Provider == null)
526 throw new InvalidOperationException(
string.Format(
"path [{0}] cannot be resolved to a provider.", path));
530 private static int LastIndexOfDirectorySeparator(
string path)
532 int length = path.Length;
533 while (--length >= 0)
535 var c = path[length];
536 if (c == DirectorySeparatorChar || c == AltDirectorySeparatorChar)
547 if (path.Contains(AltDirectorySeparatorChar))
549 path = path.Replace(AltDirectorySeparatorChar, DirectorySeparatorChar);
554 for (
int i = path.Length - 1; i >= 0; --i)
556 var pathChar = path[i];
557 var isResolvingTop = (i == path.Length - 1 && resolveTop);
558 if (!isResolvingTop && pathChar != DirectorySeparatorChar)
564 string providerpath = isResolvingTop && pathChar != DirectorySeparatorChar ?
new StringBuilder(path.Length + 1).Append(path).Append(DirectorySeparatorChar).ToString() : (i + 1) == path.Length ? path : path.Substring(0, i + 1);
566 if (providers.TryGetValue(providerpath, out provider))
571 return new ResolveProviderResult { Provider = provider, Path = path.Substring(providerpath.Length) };
A virtual file provider, that can returns a Stream for a given path.
Virtual abstraction over a file system. It handles access to files, http, packages, path rewrite, etc...
static IVirtualFileProvider MountFileSystem(string mountPoint, string path)
Mounts the specified path in the specified virtual file mount point.
static readonly IVirtualFileProvider ApplicationTemporary
The application temporary data provider.
static readonly IVirtualFileProvider ApplicationRoaming
The application user roaming folder. Included in backup.
A file system implementation for IVirtualFileProvider.
static ResolveProviderResult ResolveProviderUnsafe(string path, bool resolveTop)
static void FileMove(string sourcePath, string destinationPath)
static ResolveProviderResult ResolveProvider(string path, bool resolveTop)
Resolves the virtual file provider for a given path.
static bool FileExists(string path)
Checks the existence of a file.
VirtualFileShare
File share capabilities, equivalent of System.IO.FileShare.
static readonly char DirectorySeparatorChar
static string Resolvepath(string path)
Resolves the path.
static readonly IVirtualFileProvider ApplicationBinary
The application binary folder.
Exposes the whole file system through folder similar to Cygwin. As an example, "/c/Program Files/Test...
static Task< Stream > OpenStreamAsync(string path, VirtualFileMode mode, VirtualFileAccess access, VirtualFileShare share=VirtualFileShare.Read)
static bool DirectoryExists(string path)
Checks the existence of a directory.
static string GetParentFolder(string path)
Gets the parent folder.
static string GetTempFileName()
Creates a temporary zero-byte file and returns its full path.
static readonly IVirtualFileProvider ApplicationData
The application data file provider.
static IVirtualFileProvider ApplicationObjectDatabase
The application database file provider (ObjectId level).
static string Combine(string path1, string path2)
Combines the specified paths. Similiar to System.IO.Path.Combine(string, string). ...
static void FileDelete(string path)
VirtualFileAccess
File access equivalent of System.IO.FileAccess.
static string CreateRelativePath(string target, string sourcePath)
Creates the relative path that can access to target from sourcePath.
VirtualFileMode
File mode equivalent of System.IO.FileMode.
static string BuildPath(string path, string relativePath)
static Stream OpenStream(string path, VirtualFileMode mode, VirtualFileAccess access, VirtualFileShare share=VirtualFileShare.Read)
Opens the stream from a given path.
static Stream OpenStream(string path, VirtualFileMode mode, VirtualFileAccess access, VirtualFileShare share, out IVirtualFileProvider provider)
Opens the stream from a given path.
static void UnregisterProvider(IVirtualFileProvider provider, bool dispose=true)
Unregisters the specified virtual file provider.
static string GetFileName(string path)
Gets the file's name with its extension ("/path/to/file/fileName.ext"->"fileName.ext") ...
static void CreateDirectory(string path)
Creates all directories so that path exists.
static string ResolveAbsolutePath(string path)
Returns the path with its .. or . parts simplified.
static string GetAbsolutePath(string path)
Gets the absolute path (system dependent) for the specified path in the context of the virtual file s...
static string DefaultRootPath
static readonly IVirtualFileProvider ApplicationDatabase
The application database file provider (Index level).
static Task< string[]> ListFiles(string path, string searchPattern, VirtualSearchOption searchOption)
Lists the files matching a pattern in a specified directory.
IVirtualFileProvider Provider
static DateTime GetLastWriteTime(string path)
static readonly DriveFileProvider Drive
The whole host file system. This should be used only in tools.
static readonly IVirtualFileProvider ApplicationLocal
The application user local folder. Included in backup.
static Task< bool > FileExistsAsync(string path)
string RootPath
Gets or sets the root path of this provider. See remarks.
static IVirtualFileProvider RemountFileSystem(string mountPoint, string path)
Mounts or remounts the specified path in the specified virtual file mount point.
static void RegisterProvider(IVirtualFileProvider provider)
Registers the specified virtual file provider at the specified mount location.
static long FileSize(string path)
static readonly IVirtualFileProvider ApplicationCache
The application cache folder.