121 lines
2.9 KiB
C#
121 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);
|
|
}
|
|
}
|
|
}
|