public void MakeReadStruct(BfsStruct dataStruct, CodeMethod codeMethod)
{
//Wrap the binary reader class into a compression stream if nessecary
if (dataStruct.CompressionMethod != null)
{
if(dataStruct.CompressionMethod == "GZip" || dataStruct.CompressionMethod == "Deflate")
{
codeMethod.CodeLines.Add( dataStruct.CompressionMethod+"Stream bfs_decompress = new "+ dataStruct.CompressionMethod +"Stream(file.BaseStream, CompressionMode.Decompress);");
codeMethod.CodeLines.Add("file = new BfsBinaryReader(new BinaryReader(bfs_decompress), file.FileEndianness);");
}
else
BfsCompiler.ReportError("Does not know the compression mode '" + dataStruct.CompressionMethod + "'");
}
//The class to return
codeMethod.CodeLines.Add( dataStruct.Name + " " + dataStruct.Name.ToLower() + " = new " + dataStruct.Name + "();");
foreach (IBfsNamedField namedField in dataStruct.ParseOrder)
{
if (namedField is BfsStructField)
{
BfsStructField field = namedField as BfsStructField;
if (field.Conditional != null)
codeMethod.CodeLines.Add("if (" + CSHelper.MakeExpression(field.Conditional, dataStruct) + ")");
if (field.FieldType.ArrayExtension == null)
codeMethod.CodeLines.Add(((field.Conditional != null) ? "\t" : "") + dataStruct.Name.ToLower() + "." + field.Name + " = " + ReadType(field.FieldType)+ ";");
else
if (field.FieldType.ArrayExtension is BfsKnownArray)
{
BfsKnownArray knownArray = field.FieldType.ArrayExtension as BfsKnownArray;
codeMethod.CodeLines.Add(dataStruct.Name.ToLower() + "." + field.Name + " = new " + CSHelper.TypeMap(field.FieldType).ToLower() + "[" + CSHelper.MakeExpression(knownArray.Expression, dataStruct) + "];");
codeMethod.CodeLines.Add("for ( int i=0; i<" + CSHelper.MakeExpression(knownArray.Expression, dataStruct) + "; i++)");
codeMethod.CodeLines.Add("\t" + dataStruct.Name.ToLower() + "." + field.Name + "[i] = " + ReadType(field.FieldType) + ";");
}
else if (field.FieldType.ArrayExtension is BfsUnknownArray)
{
BfsUnknownArray unknownArray = field.FieldType.ArrayExtension as BfsUnknownArray;
//Make temporary copy of the list to convert all ascii strings into hex strings.
List<IBfsStopCase> stopcases = new List<IBfsStopCase>(unknownArray.StopCases);
bool stopAtEOF = false;
foreach (IBfsStopCase sc in stopcases)
if (sc is BfsStopCaseEndOfFile)
stopAtEOF = true;
string type = CSHelper.TypeMap(field.FieldType).ToLower();
codeMethod.CodeLines.Add(dataStruct.Name.ToLower() + "." + field.Name + " = new List<" + type + ">();");
codeMethod.CodeLines.Add("StopCaseTester " + field.Name + "_tester = new StopCaseTester(file, "+stopAtEOF.ToString().ToLower()+", new StopCase[] {");
bool hasInclude = false, hasSkipped = false;
bool onlyIncluded = true, onlySkipped = true;
for (int i = 0; i < stopcases.Count; i++)
{
byte[] stopcase = new byte [1];
if (stopcases[i] is BfsStopCaseHex)
stopcase = ByteArrayConverter.ConvertHexString((stopcases[i] as BfsStopCaseHex).HexString);
else if(stopcases[i] is BfsStopCaseString)
stopcase = ByteArrayConverter.ConvertString((stopcases[i] as BfsStopCaseString).StopString);
StringBuilder builder = new StringBuilder("\tnew StopCase(new byte [] { ");
for (int x = 0; x < stopcase.Length; x++)
{
builder.Append("0x" + stopcase[x].ToString("X"));
if (x < stopcase.Length - 1)
builder.Append(", ");
}
builder.Append(" }, ");
BfsInclusionEnum inclusion = stopcases[i].Inclusion;
bool included = (inclusion == BfsInclusionEnum.Included);
bool skipped = (inclusion == BfsInclusionEnum.Skipped);
builder.Append((included ? "true" : "false") + ", ");
//If things are consumed, they are automatically considered consumed so this is not needed.
builder.Append(((skipped && !included) ? "true" : "false") + ")");
if (stopcases[i].Inclusion == BfsInclusionEnum.Included)
hasInclude = true;
else
onlyIncluded = false;
if (stopcases[i].Inclusion == BfsInclusionEnum.Skipped)
hasSkipped = true;
else
onlySkipped = false;
if (i < stopcases.Count - 1)
builder.Append(",");
codeMethod.CodeLines.Add(builder.ToString());
}
codeMethod.CodeLines.Add("});");
codeMethod.CodeLines.Add("while("+field.Name + "_tester.CanContinue())");
codeMethod.CodeLines.Add("\t" + dataStruct.Name.ToLower() + "." + field.Name + ".Add(" + ReadType(field.FieldType) + ");");
string indent = string.Empty;
if (hasInclude)
{
//The 'if'-test on the inclusion stopcase is only needed if not all cases are included
if (!onlyIncluded)
{
codeMethod.CodeLines.Add("if(" + field.Name + "_tester.StoppedAtCase().isIncluded)");
indent = "\t";
}
codeMethod.CodeLines.Add(indent + field.Name + ".Add(" + ReadType(field.FieldType) + ");");
}
indent = string.Empty;
if (hasSkipped)
{
if (!onlySkipped)
{
codeMethod.CodeLines.Add("if(" + field.Name + "_tester.StoppedAtCase().isSkipped)");
indent = "\t";
}
codeMethod.CodeLines.Add(indent + "file.SkipBytes(" + field.Name + "_tester.StoppedAtCase().stopcase.Length);");
}
}
}
//Local fields
else if (namedField is BfsLocalField)
{
BfsLocalField field = namedField as BfsLocalField;
if (field.AssignmentExpression != null)
codeMethod.CodeLines.Add( dataStruct.Name.ToLower() + "." + field.Name + " = " + CSHelper.MakeExpression(field.AssignmentExpression, dataStruct) + ";");
}
}
codeMethod.CodeLines.Add("return " + dataStruct.Name.ToLower() + ";");
}