public void MakeEnum(CodeClass codeClass, BfsEnum dataEnum)
{
codeClass.ClassType = CodeClass.ClassTypeEnum.Struct;
//Only add nessecary internal enum aliases if there are any.
if (dataEnum.EnumAliases.Count > 0)
{
StringBuilder b = new StringBuilder();
b.Append("enum " + dataEnum.Name + "Enum {");
List<string> foundEnumAliases = new List<string>();
for (int i = 0; i < dataEnum.EnumFields.Count; i++)
{
BfsEnumField enumField = dataEnum.EnumFields[i];
if (enumField.Alias != null && !foundEnumAliases.Contains(enumField.Alias))
{
if (i != 0)
b.Append(", ");
b.Append(enumField.Alias);
foundEnumAliases.Add(enumField.Alias);
}
}
b.Append("}");
codeClass.CodeFields.Add(b.ToString());
codeClass.CodeFields.Add(dataEnum.Name + "Enum " + dataEnum.Name.ToLower() + ";");
}
//Adds the implicit 'value' variable for storing the read primitive type.
codeClass.CodeFields.Add(CSHelper.TypeMap(dataEnum.PrimitiveType).ToLower() + " value;");
CodeMethod codeMethod = new CodeMethod(dataEnum.Name + " Read(BfsBinaryReader file)");
codeClass.CodeMethods.Add(codeMethod);
string objectType = dataEnum.Name;
string varName = dataEnum.Name.ToLower();
codeMethod.CodeLines.Add(objectType + " " + varName + " = new " + objectType + "();");
codeMethod.CodeLines.Add(varName + ".value = file.Read" + dataEnum.PrimitiveType.PrimitiveType.ToString() + "();");
//Sorts the enum fields into categories to make a pretty switch-case/if-then-else structure.
List<BfsEnumField> singleValues = new List<BfsEnumField>();
List<BfsEnumField> rangeValues = new List<BfsEnumField>();
BfsEnumField elseValue = null;
foreach (BfsEnumField enumField in dataEnum.EnumFields)
if (enumField.EnumMatch is BfsEnumValue)
singleValues.Add(enumField);
else if (enumField.EnumMatch is BfsEnumRange)
rangeValues.Add(enumField);
else if (enumField.EnumMatch is BfsEnumElse)
elseValue = enumField;
string tab = string.Empty;
//If there are 2 or above single enum matches a switch/case statement is made with the values as cases.
//In case the value isn't any of the values it checks the ranges one by one in an if/else/elseif/elseif/... kind of way.
if (singleValues.Count > 1)
{
codeMethod.CodeLines.Add("switch(" + varName + ".value)");
codeMethod.CodeLines.Add("{");
tab = "\t\t";
foreach (BfsEnumField enumField in singleValues)
{
BfsEnumValue enumVal = enumField.EnumMatch as BfsEnumValue;
codeMethod.CodeLines.Add("\tcase " + enumVal.Value + ":");
if (enumField.Alias != null)
codeMethod.CodeLines.Add("\t\t" + varName + "." + varName + " = " + objectType + "Enum." + enumField.Alias + ";");
List<string> actionList = new List<string>();
bool addBreak = MakeActionList(dataEnum, actionList, enumField.Actions);
foreach (string str in actionList)
codeMethod.CodeLines.Add("\t\t" + str);
if (addBreak)
codeMethod.CodeLines.Add("\t\tbreak;");
}
codeMethod.CodeLines.Add("\tdefault:");
}
string defaultTab = "\t";
if (singleValues.Count <= 1)
defaultTab = string.Empty;
//If there only are one single value case, then include it in the if-then-else sequence
IfThenElseSequence ifthenelse = new IfThenElseSequence(defaultTab, varName + ": '" + "\" + " + varName + ".value + \"");
if (elseValue != null)
{
ifthenelse.ElseBlock = new IfBlock();
MakeActionList(dataEnum, ifthenelse.ElseBlock.CodeLines, elseValue.Actions);
}
int countIfElse = 0;
if (singleValues.Count == 1)
{
BfsEnumField enumField = singleValues[0];
BfsEnumValue enumVal = enumField.EnumMatch as BfsEnumValue;
IfBlock ifblock = new IfBlock(varName + ".value == " + enumVal.Value);
ifthenelse.IfBlocks.Add(ifblock);
if (enumField.Alias != null)
ifblock.CodeLines.Add(varName + "." + varName + " = " + objectType + "Enum." + enumField.Alias + ";");
MakeActionList(dataEnum, ifblock.CodeLines, enumField.Actions);
countIfElse++;
}
//Enum ranges
foreach (BfsEnumField enumField in rangeValues)
{
BfsEnumRange enumVal = enumField.EnumMatch as BfsEnumRange;
string firstEquality = ((enumVal.StartInclusion == BfsInclusionEnum.Included) ? ">= " : "> ") + enumVal.StartValue;
string secondEquality = ((enumVal.EndInclusion == BfsInclusionEnum.Included) ? "<= " : "< ") + enumVal.EndValue;
IfBlock ifblock = new IfBlock(varName + ".value " + firstEquality + " && " + varName + ".value " + secondEquality);
ifthenelse.IfBlocks.Add(ifblock);
if (enumField.Alias != null)
ifblock.CodeLines.Add(varName + "." + varName + " = " + objectType + "Enum." + enumField.Alias + ";");
MakeActionList(dataEnum, ifblock.CodeLines, enumField.Actions);
}
codeMethod.AddSplitLines(ifthenelse.ToString());
//End off the switch
if (singleValues.Count > 1)
{
//Only add the final 'break' if the default case doesn't throw any exception
//to prevent the code not reachable error
if (ifthenelse.IfBlocks.Count != 0 || !ifthenelse.ElseBlock.ToString().Contains("throw new "))
codeMethod.CodeLines.Add("\t\tbreak;");
codeMethod.CodeLines.Add("}");
}
codeMethod.CodeLines.Add("return " + varName + ";");
//ToString() method
CodeMethod toString = new CodeMethod("override string ToString()");
codeClass.CodeMethods.Add(toString);
if(dataEnum.EnumAliases.Count > 0)
toString.CodeLines.Add("return " + dataEnum.Name.ToLower() + ".ToString();");
else
toString.CodeLines.Add("return value.ToString();");
}