forked from MonoGame/MonoGame
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathTitleContainer.cs
More file actions
124 lines (105 loc) · 4.22 KB
/
TitleContainer.cs
File metadata and controls
124 lines (105 loc) · 4.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
// MonoGame - Copyright (C) MonoGame Foundation, Inc
// This file is subject to the terms and conditions defined in
// file 'LICENSE.txt', which is part of this source code package.
using System;
using System.IO;
using System.Threading.Tasks;
using MonoGame.Framework.Content;
using MonoGame.Framework.Utilities;
namespace Microsoft.Xna.Framework
{
/// <summary>
/// Provides functionality for opening a stream in the title storage area.
/// </summary>
public static partial class TitleContainer
{
static partial void PlatformInit();
static TitleContainer()
{
Location = string.Empty;
PlatformInit();
}
/// <summary>
/// Set this to a valid <see cref="IContentProvider"/> for the <see cref="TitleContainer"/> to check any
/// content requests by it.
/// </summary>
public static IContentProvider ContentProvider { get; set; }
internal static string Location { get; private set; }
/// <summary>
/// Returns an open stream to an existing file in the title storage area.
/// </summary>
/// <param name="name">The filepath relative to the title storage area.</param>
/// <returns>An open stream if a file is found.</returns>
/// <exception cref="ArgumentNullException">If the name is null or invalid.</exception>
/// <exception cref="FileNotFoundException">If a file is not found.</exception>
public static Stream OpenStream(string name)
{
if (string.IsNullOrEmpty(name))
throw new ArgumentNullException(nameof(name));
// We do not accept absolute paths here.
if (Path.IsPathRooted(name))
throw new ArgumentException("Invalid filename. TitleContainer.OpenStream requires a relative path.", name);
if (ContentProvider != null)
{
var task = Task.Run(() => ContentProvider.FetchContent(name));
task.Wait();
var response = task.Result;
if (!response)
{
throw new Exception($"Content client failed to get a valid response for content: {name}");
}
}
// Normalize the file path.
var safeName = NormalizeRelativePath(name);
// Call the platform code to open the stream. Any errors at this point should result in a file not found.
Stream stream = null;
try
{
if (ContentProvider != null)
{
stream = ContentProvider.OpenReadStream(safeName);
}
stream ??= PlatformOpenStream(safeName);
if (stream == null)
{
throw FileNotFoundException(name, null);
}
}
catch (FileNotFoundException)
{
throw;
}
catch (Exception ex)
{
throw new FileNotFoundException(name, ex);
}
return stream;
}
/// <summary>
/// Faster version of <see cref="OpenStream"/> as it doesn't rely on exceptions in error cases.
/// </summary>
internal static Stream OpenStreamNoException(string name)
{
if (string.IsNullOrEmpty(name) || Path.IsPathRooted(name))
{
return null;
}
var safeName = NormalizeRelativePath(name);
try
{
return PlatformOpenStream(safeName);
}
catch { }
return null;
}
private static Exception FileNotFoundException(string name, Exception inner)
{
return new FileNotFoundException("Error loading \"" + name + "\". File not found.", inner);
}
private static string NormalizeRelativePath(string name)
{
var uri = new Uri("file:///" + FileHelpers.UrlEncode(name));
return uri.LocalPath[1..].Replace(FileHelpers.NotSeparator, FileHelpers.Separator);
}
}
}