Do not reuse a single StreamReader for reading signatures. Avoids issues with XPathDocument closing the stream behind our backs.

This commit is contained in:
the_fiddler 2010-12-06 14:34:16 +00:00
parent e6bed64bd8
commit 355f5beb7b
5 changed files with 98 additions and 107 deletions

View file

@ -40,9 +40,9 @@ namespace Bind
class EnumProcessor class EnumProcessor
{ {
const string Path = "/signatures/replace/enum[@name='{0}']"; const string Path = "/signatures/replace/enum[@name='{0}']";
StreamReader Overrides { get; set; } string Overrides { get; set; }
public EnumProcessor(StreamReader overrides) public EnumProcessor(string overrides)
{ {
if (overrides == null) if (overrides == null)
throw new ArgumentNullException("overrides"); throw new ArgumentNullException("overrides");
@ -55,7 +55,6 @@ namespace Bind
var nav = new XPathDocument(Overrides).CreateNavigator(); var nav = new XPathDocument(Overrides).CreateNavigator();
enums = ProcessNames(enums, nav); enums = ProcessNames(enums, nav);
enums = ProcessConstants(enums, nav); enums = ProcessConstants(enums, nav);
Overrides.BaseStream.Seek(0, SeekOrigin.Begin);
return enums; return enums;
} }

View file

@ -46,9 +46,9 @@ namespace Bind
new Regex("(ib|[tdrey]s|[eE]n[vd]|bled|Flag|Tess|Status|Pixels|Instanced|Indexed|Varyings|Boolean|IDs)", RegexOptions.Compiled | RegexOptions.RightToLeft); new Regex("(ib|[tdrey]s|[eE]n[vd]|bled|Flag|Tess|Status|Pixels|Instanced|Indexed|Varyings|Boolean|IDs)", RegexOptions.Compiled | RegexOptions.RightToLeft);
static readonly Regex EndingsAddV = new Regex("^0", RegexOptions.Compiled); static readonly Regex EndingsAddV = new Regex("^0", RegexOptions.Compiled);
StreamReader Overrides { get; set; } string Overrides { get; set; }
public FuncProcessor(StreamReader overrides) public FuncProcessor(string overrides)
{ {
if (overrides == null) if (overrides == null)
throw new ArgumentNullException("overrides"); throw new ArgumentNullException("overrides");
@ -72,7 +72,6 @@ namespace Bind
wrappers = CreateCLSCompliantWrappers(wrappers, enums); wrappers = CreateCLSCompliantWrappers(wrappers, enums);
Console.WriteLine("Removing non-CLS compliant duplicates."); Console.WriteLine("Removing non-CLS compliant duplicates.");
Overrides.BaseStream.Seek(0, SeekOrigin.Begin);
return MarkCLSCompliance(wrappers); return MarkCLSCompliance(wrappers);
} }

View file

@ -70,26 +70,16 @@ namespace Bind.GL2
public virtual void Process() public virtual void Process()
{ {
using (var overrides = new StreamReader(Path.Combine(Settings.InputPath, Settings.OverridesFile))) string overrides = Path.Combine(Settings.InputPath, Settings.OverridesFile);
{ Type.GLTypes = SpecReader.ReadTypeMap(Path.Combine(Settings.InputPath, glTypemap));
using (StreamReader sr = Utilities.OpenSpecFile(Settings.InputPath, glTypemap)) Type.CSTypes = SpecReader.ReadCSTypeMap(Path.Combine(Settings.InputPath, csTypemap));
Type.GLTypes = SpecReader.ReadTypeMap(sr); Enums = SpecReader.ReadEnums(Path.Combine(Settings.InputPath, enumSpec));
using (StreamReader sr = Utilities.OpenSpecFile(Settings.InputPath, csTypemap)) Utilities.Merge(Enums, SpecReader.ReadEnums(overrides));
Type.CSTypes = SpecReader.ReadCSTypeMap(sr); Delegates = SpecReader.ReadDelegates(Path.Combine(Settings.InputPath, glSpec));
using (var sr = new StreamReader(Path.Combine(Settings.InputPath, enumSpec))) Utilities.Merge(Delegates, SpecReader.ReadDelegates(overrides));
{
Enums = SpecReader.ReadEnums(sr);
Utilities.Merge(Enums, SpecReader.ReadEnums(overrides));
}
using (var sr = new StreamReader(Path.Combine(Settings.InputPath, glSpec)))
{
Delegates = SpecReader.ReadDelegates(sr);
Utilities.Merge(Delegates, SpecReader.ReadDelegates(overrides));
}
Enums = new EnumProcessor(overrides).Process(Enums); Enums = new EnumProcessor(overrides).Process(Enums);
Wrappers = new FuncProcessor(overrides).Process(Delegates, Enums); Wrappers = new FuncProcessor(overrides).Process(Delegates, Enums);
}
} }
#endregion #endregion

View file

@ -12,9 +12,9 @@ namespace Bind
{ {
interface ISpecReader interface ISpecReader
{ {
DelegateCollection ReadDelegates(StreamReader specFile); DelegateCollection ReadDelegates(string file);
EnumCollection ReadEnums(StreamReader specFile); EnumCollection ReadEnums(string file);
Dictionary<string, string> ReadTypeMap(StreamReader specFile); Dictionary<string, string> ReadTypeMap(string file);
Dictionary<string, string> ReadCSTypeMap(StreamReader specFile); Dictionary<string, string> ReadCSTypeMap(string file);
} }
} }

View file

@ -102,115 +102,118 @@ namespace Bind
#region ISpecReader Members #region ISpecReader Members
public DelegateCollection ReadDelegates(StreamReader specFile) public DelegateCollection ReadDelegates(string file)
{ {
XPathDocument specs = new XPathDocument(specFile); var specs = new XPathDocument(file);
var delegates = ReadDelegates(specs.CreateNavigator().SelectSingleNode("/signatures/add")); var delegates = ReadDelegates(specs.CreateNavigator().SelectSingleNode("/signatures/add"));
specFile.BaseStream.Seek(0, SeekOrigin.Begin);
return delegates; return delegates;
} }
public Dictionary<string, string> ReadTypeMap(StreamReader specFile) public Dictionary<string, string> ReadTypeMap(string file)
{ {
Console.WriteLine("Reading opengl types."); using (var sr = new StreamReader(file))
Dictionary<string, string> GLTypes = new Dictionary<string, string>(); {
Console.WriteLine("Reading opengl types.");
Dictionary<string, string> GLTypes = new Dictionary<string, string>();
if (sr == null)
return GLTypes;
do
{
string line = sr.ReadLine();
if (String.IsNullOrEmpty(line) || line.StartsWith("#"))
continue;
string[] words = line.Split(" ,*\t".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
if (words[0].ToLower() == "void")
{
// Special case for "void" -> "". We make it "void" -> "void"
GLTypes.Add(words[0], "void");
}
else if (words[0] == "VoidPointer" || words[0] == "ConstVoidPointer")
{
// "(Const)VoidPointer" -> "void*"
GLTypes.Add(words[0], "void*");
}
else if (words[0] == "CharPointer" || words[0] == "charPointerARB")
{
// The typematching logic cannot handle pointers to pointers, e.g. CharPointer* -> char** -> string* -> string[].
// Hence we give it a push.
// Note: When both CurrentType == "String" and Pointer == true, the typematching is hardcoded to use
// String[] or StringBuilder[].
GLTypes.Add(words[0], "String");
}
/*else if (words[0].Contains("Pointer"))
{
GLTypes.Add(words[0], words[1].Replace("Pointer", "*"));
}*/
else if (words[1].Contains("GLvoid"))
{
GLTypes.Add(words[0], "void");
}
else if (words[1] == "const" && words[2] == "GLubyte")
{
GLTypes.Add(words[0], "String");
}
else if (words[1] == "struct")
{
GLTypes.Add(words[0], words[2]);
}
else
{
GLTypes.Add(words[0], words[1]);
}
}
while (!sr.EndOfStream);
if (specFile == null)
return GLTypes; return GLTypes;
do
{
string line = specFile.ReadLine();
if (String.IsNullOrEmpty(line) || line.StartsWith("#"))
continue;
string[] words = line.Split(" ,*\t".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
if (words[0].ToLower() == "void")
{
// Special case for "void" -> "". We make it "void" -> "void"
GLTypes.Add(words[0], "void");
}
else if (words[0] == "VoidPointer" || words[0] == "ConstVoidPointer")
{
// "(Const)VoidPointer" -> "void*"
GLTypes.Add(words[0], "void*");
}
else if (words[0] == "CharPointer" || words[0] == "charPointerARB")
{
// The typematching logic cannot handle pointers to pointers, e.g. CharPointer* -> char** -> string* -> string[].
// Hence we give it a push.
// Note: When both CurrentType == "String" and Pointer == true, the typematching is hardcoded to use
// String[] or StringBuilder[].
GLTypes.Add(words[0], "String");
}
/*else if (words[0].Contains("Pointer"))
{
GLTypes.Add(words[0], words[1].Replace("Pointer", "*"));
}*/
else if (words[1].Contains("GLvoid"))
{
GLTypes.Add(words[0], "void");
}
else if (words[1] == "const" && words[2] == "GLubyte")
{
GLTypes.Add(words[0], "String");
}
else if (words[1] == "struct")
{
GLTypes.Add(words[0], words[2]);
}
else
{
GLTypes.Add(words[0], words[1]);
}
} }
while (!specFile.EndOfStream);
return GLTypes;
} }
public Dictionary<string, string> ReadCSTypeMap(StreamReader specFile) public Dictionary<string, string> ReadCSTypeMap(string file)
{ {
Dictionary<string, string> CSTypes = new Dictionary<string, string>(); using (var sr = new StreamReader(file))
Console.WriteLine("Reading C# types.");
while (!specFile.EndOfStream)
{ {
string line = specFile.ReadLine(); Dictionary<string, string> CSTypes = new Dictionary<string, string>();
if (String.IsNullOrEmpty(line) || line.StartsWith("#")) Console.WriteLine("Reading C# types.");
continue;
string[] words = line.Split(" ,\t".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); while (!sr.EndOfStream)
if (words.Length < 2) {
continue; string line = sr.ReadLine();
if (String.IsNullOrEmpty(line) || line.StartsWith("#"))
continue;
if (((Settings.Compatibility & Settings.Legacy.NoBoolParameters) != Settings.Legacy.None) && words[1] == "bool") string[] words = line.Split(" ,\t".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
words[1] = "Int32"; if (words.Length < 2)
continue;
CSTypes.Add(words[0], words[1]); if (((Settings.Compatibility & Settings.Legacy.NoBoolParameters) != Settings.Legacy.None) && words[1] == "bool")
words[1] = "Int32";
CSTypes.Add(words[0], words[1]);
}
return CSTypes;
} }
return CSTypes;
} }
public EnumCollection ReadEnums(StreamReader specFile) public EnumCollection ReadEnums(string file)
{ {
// First, read all enum definitions from spec and override file. // First, read all enum definitions from spec and override file.
// Afterwards, read all token/enum overrides from overrides file. // Afterwards, read all token/enum overrides from overrides file.
// Every single enum is merged into // Every single enum is merged into
EnumCollection enums = new EnumCollection(); EnumCollection enums = new EnumCollection();
XPathDocument specs = new XPathDocument(specFile); var specs = new XPathDocument(file);
foreach (XPathNavigator nav in specs.CreateNavigator().Select("/signatures/add")) foreach (XPathNavigator nav in specs.CreateNavigator().Select("/signatures/add"))
{ {
var new_enums = ReadEnums(nav); var new_enums = ReadEnums(nav);
Utilities.Merge(enums, new_enums); Utilities.Merge(enums, new_enums);
} }
specFile.BaseStream.Seek(0, SeekOrigin.Begin);
return enums; return enums;
} }