ssc/ssc/import resolver.cs
arookas 2f9b251fd8 Cleanup.
TIL I can set the automatic formatting of opening braces in VS. What
have I been doing all this time??
2015-12-28 03:37:10 -05:00

100 lines
2.9 KiB
C#

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace arookas {
public abstract class sunImportResolver {
static sunImportResolver defaultResolver = new sunDefaultImportResolver();
public static sunImportResolver Default { get { return defaultResolver; } }
public abstract void EnterFile(sunScriptFile file);
public abstract void ExitFile(sunScriptFile file);
public abstract sunImportResult ResolveImport(string name, out sunScriptFile file);
// default implementation
sealed class sunDefaultImportResolver : sunImportResolver {
List<sunScriptFile> imports = new List<sunScriptFile>(10);
Stack<sunScriptFile> current = new Stack<sunScriptFile>(5);
string rootDirectory, currentDirectory;
string CurrentDirectory { get { return current.Count > 0 ? Path.GetDirectoryName(current.Peek().Name) : currentDirectory; } }
public sunDefaultImportResolver() {
rootDirectory = AppDomain.CurrentDomain.BaseDirectory;
currentDirectory = Directory.GetCurrentDirectory();
}
public override void EnterFile(sunScriptFile file) { current.Push(file); }
public override void ExitFile(sunScriptFile file) { current.Pop(); }
public override sunImportResult ResolveImport(string name, out sunScriptFile file) {
file = null;
string fullPath;
if (Path.IsPathRooted(name)) {
// if the path is absolute, just use it directly
fullPath = name;
if (!File.Exists(fullPath)) {
return sunImportResult.Missing;
}
}
else {
// check if the file exists relative to the current one;
// if it's not there, check the root directory
fullPath = Path.Combine(CurrentDirectory, name);
if (!File.Exists(fullPath)) {
fullPath = Path.Combine(rootDirectory, name);
if (!File.Exists(fullPath)) {
return sunImportResult.Missing;
}
}
}
// make sure the file has not been imported yet
if (imports.Any(i => i.Name == fullPath)) {
return sunImportResult.Skipped;
}
// open the file
try {
file = new sunScriptFile(name, File.OpenRead(fullPath));
}
catch {
return sunImportResult.FailedToLoad;
}
imports.Add(file);
return sunImportResult.Loaded;
}
}
}
public enum sunImportResult {
Loaded,
Skipped,
Missing,
FailedToLoad,
}
public class sunScriptFile : IDisposable {
public string Name { get; private set; }
public Stream Stream { get; private set; }
public sunScriptFile(string name, Stream stream) {
if (name == null) {
throw new ArgumentNullException("name");
}
if (stream == null) {
throw new ArgumentNullException("stream");
}
if (!stream.CanRead) {
throw new ArgumentException("Stream does not support reading.", "stream");
}
Name = name;
Stream = stream;
}
public void Dispose() {
Stream.Dispose();
}
public TextReader GetReader() {
return new StreamReader(Stream);
}
}
}