public StructField AddField(StructField field) { _fieldsByName.Add(field.Name, field); _fields.Add(field); return(field); }
public StructField AddField(StructField field) { _fieldsByName.Add(field.Name, field); _fields.Add(field); return field; }
private int Read(StructField field, IntPtr offset, out FieldValue valueOut) { if (!field.IsArray) { return(this.ReadOnce(field, offset, out valueOut)); } // read array FieldValue value = new FieldValue() { FieldType = field.RawType, Name = field.Name }; int readSize = 0; List <FieldValue> valueArray = new List <FieldValue>(); for (int i = 0; i < field.VarArrayLength; i++) { FieldValue elementValue; readSize = offset.Increment(readSize).Align(field.Alignment).Decrement(offset).ToInt32(); readSize += this.ReadOnce(field, offset.Increment(readSize), out elementValue); elementValue.Name = "[" + i.ToString() + "]"; valueArray.Add(elementValue); } value.Value = valueArray.ToArray(); value.StructName = field.StructName; valueOut = value; return(readSize); }
public void RemoveField(StructField field) { _fieldsByName.Remove(field.Name); _fields.Remove(field); }
private unsafe int ReadOnce(StructField field, IntPtr offset, out FieldValue valueOut) { FieldValue value = new FieldValue() { FieldType = field.Type, Name = field.Name }; int readSize = 0; switch (field.Type) { case FieldType.Bool32: value.Value = Utils.ToInt32(IOProvider.ReadBytes(offset, 4), Utils.Endianness.Little) != 0; readSize = 4; break; case FieldType.Bool8: value.Value = IOProvider.ReadBytes(offset, 1)[0] != 0; readSize = 1; break; case FieldType.CharASCII: value.Value = (char)IOProvider.ReadBytes(offset, 1)[0]; readSize = 1; break; case FieldType.CharUTF16: value.Value = Encoding.Unicode.GetString(IOProvider.ReadBytes(offset, 2))[0]; readSize = 2; break; case FieldType.Double: { long data = Utils.ToInt64( IOProvider.ReadBytes(offset, 8), Utils.Endianness.Little); value.Value = *(double*)&data; readSize = 8; } break; case FieldType.Int16: value.Value = (short)Utils.ToUInt16( IOProvider.ReadBytes(offset, 2), Utils.Endianness.Little); readSize = 2; break; case FieldType.Int32: value.Value = Utils.ToInt32( IOProvider.ReadBytes(offset, 4), Utils.Endianness.Little); readSize = 4; break; case FieldType.Int64: value.Value = Utils.ToInt64( IOProvider.ReadBytes(offset, 8), Utils.Endianness.Little); readSize = 8; break; case FieldType.Int8: value.Value = (sbyte)IOProvider.ReadBytes(offset, 1)[0]; readSize = 1; break; case FieldType.PVoid: value.Value = IOProvider.ReadBytes(offset, IntPtr.Size).ToIntPtr(); readSize = IntPtr.Size; break; case FieldType.Single: { int data = Utils.ToInt32( IOProvider.ReadBytes(offset, 4), Utils.Endianness.Little); value.Value = *(float*)&data; readSize = 4; } break; case FieldType.StringASCII: { StringBuilder str = new StringBuilder(); if (field.VarLength == -1) { int i; for (i = 0; ; i++) { byte b = IOProvider.ReadBytes(offset.Increment(i), 1)[0]; if (b == 0) break; str.Append((char)b); } readSize = i; } else { str.Append(Encoding.ASCII.GetString( IOProvider.ReadBytes(offset, field.VarLength))); readSize = field.VarLength; } value.Value = str.ToString(); } break; case FieldType.StringUTF16: { StringBuilder str = new StringBuilder(); if (field.VarLength == -1) { int i; for (i = 0; ; i += 2) { byte[] b = IOProvider.ReadBytes(offset.Increment(i), 2); if (Utils.IsEmpty(b)) break; str.Append(Encoding.Unicode.GetString(b)); } readSize = i; } else { str.Append(Encoding.Unicode.GetString( IOProvider.ReadBytes(offset, field.VarLength * 2))); // each char is 2 bytes readSize = field.VarLength; } value.Value = str.ToString(); } break; case FieldType.Struct: { FieldValue[] valuesOut; StructDef struc = Structs[field.StructName]; struc.IOProvider = this.IOProvider; struc.Offset = offset; struc.Structs = this.Structs; readSize = struc.Read(out valuesOut); value.Value = valuesOut; value.StructName = field.StructName; } break; case FieldType.UInt16: value.Value = Utils.ToUInt16( IOProvider.ReadBytes(offset, 2), Utils.Endianness.Little); readSize = 2; break; case FieldType.UInt32: value.Value = Utils.ToUInt32( IOProvider.ReadBytes(offset, 4), Utils.Endianness.Little); readSize = 4; break; case FieldType.UInt64: value.Value = (ulong)Utils.ToInt64( IOProvider.ReadBytes(offset, 8), Utils.Endianness.Little); readSize = 8; break; case FieldType.UInt8: value.Value = IOProvider.ReadBytes(offset, 1)[0]; readSize = 1; break; default: readSize = 0; break; } valueOut = value; return readSize; }
private int Read(StructField field, IntPtr offset, out FieldValue valueOut) { if (!field.IsArray) return this.ReadOnce(field, offset, out valueOut); // read array FieldValue value = new FieldValue() { FieldType = field.RawType, Name = field.Name }; int readSize = 0; List<FieldValue> valueArray = new List<FieldValue>(); for (int i = 0; i < field.VarArrayLength; i++) { FieldValue elementValue; readSize = offset.Increment(readSize).Align(field.Alignment).Decrement(offset).ToInt32(); readSize += this.ReadOnce(field, offset.Increment(readSize), out elementValue); elementValue.Name = "[" + i.ToString() + "]"; valueArray.Add(elementValue); } value.Value = valueArray.ToArray(); value.StructName = field.StructName; valueOut = value; return readSize; }
private void ParseStructDef(string text, ref int i) { StructDef def = new StructDef(); _eatResult = EatWhitespace(text, ref i); string structName = EatId(text, ref i); if (_eatResult || string.IsNullOrEmpty(structName)) { throw new ParserException(_fileName, _lineNumber, "Expected identifier (struct name)"); } if (_structs.ContainsKey(structName)) { throw new ParserException(_fileName, _lineNumber, "Struct name '" + structName + "' already used"); } // add it first so that structs can be self-referential _structs.Add(structName, null); // { _eatResult = EatWhitespace(text, ref i); string openingBrace = EatSymbol(text, ref i); if (_eatResult || openingBrace != "{") { throw new ParserException(_fileName, _lineNumber, "Expected '{'"); } while (true) { // } _eatResult = EatWhitespace(text, ref i); string endBrace = EatSymbol(text, ref i); if (_eatResult) { throw new ParserException(_fileName, _lineNumber, "Expected type name or '}'"); } if (endBrace == "}") { break; } if (endBrace.Length > 0) { throw new ParserException(_fileName, _lineNumber, "Unexpected '" + endBrace + "'"); } // TYPE _eatResult = EatWhitespace(text, ref i); string typeName = EatId(text, ref i); if (_eatResult || string.IsNullOrEmpty(typeName)) { throw new ParserException(_fileName, _lineNumber, "Expected type name"); } FieldType type; if (_typeDefs.ContainsKey(typeName)) { type = this.GetType(typeName); } else { type = FieldType.Struct; if (!_structs.ContainsKey(typeName)) { throw new ParserException(_fileName, _lineNumber, "Unknown identifier '" + typeName + "' (type or struct name)"); } } // type, without the pointer or array flag FieldType justType = type; // TYPE* // optional asterisk (pointer) _eatResult = EatWhitespace(text, ref i); if (EatSymbol(text, ref i) == "*") { if (this.IsTypePointer(type)) { throw new ParserException(_fileName, _lineNumber, "Invalid '*'; type '" + typeName + "' is already a pointer"); } type |= FieldType.Pointer; } // TYPE* FIELDNAME _eatResult = EatWhitespace(text, ref i); string fieldName = EatId(text, ref i); if (_eatResult || string.IsNullOrEmpty(fieldName)) { throw new ParserException(_fileName, _lineNumber, "Expected identifier (struct field name)"); } if (def.ContainsField(fieldName)) { throw new ParserException(_fileName, _lineNumber, "Field name '" + fieldName + "' already used"); } _eatResult = EatWhitespace(text, ref i); string leftSqBracket = EatSymbol(text, ref i); int varLength = 0; if (leftSqBracket == "[") { _eatResult = EatWhitespace(text, ref i); string fieldRefName = EatId(text, ref i); string fieldSizeSpec = EatNumber(text, ref i); if (!string.IsNullOrEmpty(fieldRefName)) { if (!def.ContainsField(fieldRefName)) { throw new ParserException(_fileName, _lineNumber, "Unknown identifier '" + fieldRefName + "' (field name)"); } def.GetField(fieldRefName).SetsVarOn = fieldName; // const add/multiply int iSave = i; _eatResult = EatWhitespace(text, ref i); string plusOrMulOrDivSign = EatSymbol(text, ref i); if (plusOrMulOrDivSign == "+") { def.GetField(fieldRefName).SetsVarOnAdd = EatParseInt(text, ref i); } else if (plusOrMulOrDivSign == "*") { def.GetField(fieldRefName).SetsVarOnMultiply = EatParseFloat(text, ref i); int iSave2 = i; _eatResult = EatWhitespace(text, ref i); string plusSign = EatSymbol(text, ref i); if (plusSign == "+") { def.GetField(fieldRefName).SetsVarOnAdd = EatParseInt(text, ref i); } else if (plusSign == "-") { def.GetField(fieldRefName).SetsVarOnAdd = -EatParseInt(text, ref i); } else { i = iSave2; } } else if (plusOrMulOrDivSign == "/") { // here we just set SetsVarOnMultiply to 1 / value def.GetField(fieldRefName).SetsVarOnMultiply = 1 / EatParseFloat(text, ref i); int iSave2 = i; _eatResult = EatWhitespace(text, ref i); string plusSign = EatSymbol(text, ref i); if (plusSign == "+") { def.GetField(fieldRefName).SetsVarOnAdd = EatParseInt(text, ref i); } else if (plusSign == "-") { def.GetField(fieldRefName).SetsVarOnAdd = -EatParseInt(text, ref i); } else { i = iSave2; } } else { // that didn't work; restore the index i = iSave; } } else if (!string.IsNullOrEmpty(fieldSizeSpec)) { try { //varLength = (int)BaseConverter.ToNumberParse(fieldSizeSpec); varLength = (int)BaseConverter.ToNumberParse(fieldSizeSpec); } catch { throw new ParserException(_fileName, _lineNumber, "Could not parse number '" + fieldSizeSpec + "'"); } } else { throw new ParserException(_fileName, _lineNumber, "Number or identifier expected (size specifier)"); } // if it's not a string, it's an array if (justType != FieldType.StringASCII && justType != FieldType.StringUTF16) { type |= FieldType.Array; } _eatResult = EatWhitespace(text, ref i); string rightSqBracket = EatSymbol(text, ref i); if (_eatResult || rightSqBracket != "]") { throw new ParserException(_fileName, _lineNumber, "Expected ']'"); } // fix up the semicolon _eatResult = EatWhitespace(text, ref i); leftSqBracket = EatSymbol(text, ref i); } // TYPE* FIELDNAME; string endSemicolon = leftSqBracket; if (_eatResult || endSemicolon != ";") { throw new ParserException(_fileName, _lineNumber, "Expected ';'"); } StructField field = new StructField(fieldName, type); if (field.Type == FieldType.Struct) { field.StructName = typeName; } field.VarArrayLength = varLength; field.VarLength = varLength; def.AddField(field); } _structs[structName] = def; }
private void ParseStructDef(string text, ref int i) { StructDef def = new StructDef(); _eatResult = EatWhitespace(text, ref i); string structName = EatId(text, ref i); if (_eatResult || structName == "") throw new ParserException(_fileName, _lineNumber, "Expected identifier (struct name)"); if (_structs.ContainsKey(structName)) throw new ParserException(_fileName, _lineNumber, "Struct name '" + structName + "' already used"); // add it first so that structs can be self-referential _structs.Add(structName, null); // { _eatResult = EatWhitespace(text, ref i); string openingBrace = EatSymbol(text, ref i); if (_eatResult || openingBrace != "{") throw new ParserException(_fileName, _lineNumber, "Expected '{'"); while (true) { // } _eatResult = EatWhitespace(text, ref i); string endBrace = EatSymbol(text, ref i); if (_eatResult) throw new ParserException(_fileName, _lineNumber, "Expected type name or '}'"); if (endBrace == "}") break; if (endBrace.Length > 0) throw new ParserException(_fileName, _lineNumber, "Unexpected '" + endBrace + "'"); // TYPE _eatResult = EatWhitespace(text, ref i); string typeName = EatId(text, ref i); if (_eatResult || typeName == "") throw new ParserException(_fileName, _lineNumber, "Expected type name"); FieldType type; if (_typeDefs.ContainsKey(typeName)) { type = this.GetType(typeName); } else { type = FieldType.Struct; if (!_structs.ContainsKey(typeName)) throw new ParserException(_fileName, _lineNumber, "Unknown identifier '" + typeName + "' (type or struct name)"); } // type, without the pointer or array flag FieldType justType = type; // TYPE* // optional asterisk (pointer) _eatResult = EatWhitespace(text, ref i); if (EatSymbol(text, ref i) == "*") { if (this.IsTypePointer(type)) throw new ParserException(_fileName, _lineNumber, "Invalid '*'; type '" + typeName + "' is already a pointer"); type |= FieldType.Pointer; } // TYPE* FIELDNAME _eatResult = EatWhitespace(text, ref i); string fieldName = EatId(text, ref i); if (_eatResult || fieldName == "") throw new ParserException(_fileName, _lineNumber, "Expected identifier (struct field name)"); if (def.ContainsField(fieldName)) throw new ParserException(_fileName, _lineNumber, "Field name '" + fieldName + "' already used"); _eatResult = EatWhitespace(text, ref i); string leftSqBracket = EatSymbol(text, ref i); int varLength = 0; if (leftSqBracket == "[") { _eatResult = EatWhitespace(text, ref i); string fieldRefName = EatId(text, ref i); string fieldSizeSpec = EatNumber(text, ref i); if (fieldRefName != "") { if (!def.ContainsField(fieldRefName)) throw new ParserException(_fileName, _lineNumber, "Unknown identifier '" + fieldRefName + "' (field name)"); def.GetField(fieldRefName).SetsVarOn = fieldName; // const add/multiply int iSave = i; _eatResult = EatWhitespace(text, ref i); string plusOrMulOrDivSign = EatSymbol(text, ref i); if (plusOrMulOrDivSign == "+") { def.GetField(fieldRefName).SetsVarOnAdd = EatParseInt(text, ref i); } else if (plusOrMulOrDivSign == "*") { def.GetField(fieldRefName).SetsVarOnMultiply = EatParseFloat(text, ref i); int iSave2 = i; _eatResult = EatWhitespace(text, ref i); string plusSign = EatSymbol(text, ref i); if (plusSign == "+") def.GetField(fieldRefName).SetsVarOnAdd = EatParseInt(text, ref i); else if (plusSign == "-") def.GetField(fieldRefName).SetsVarOnAdd = -EatParseInt(text, ref i); else i = iSave2; } else if (plusOrMulOrDivSign == "/") { // here we just set SetsVarOnMultiply to 1 / value def.GetField(fieldRefName).SetsVarOnMultiply = 1 / EatParseFloat(text, ref i); int iSave2 = i; _eatResult = EatWhitespace(text, ref i); string plusSign = EatSymbol(text, ref i); if (plusSign == "+") def.GetField(fieldRefName).SetsVarOnAdd = EatParseInt(text, ref i); else if (plusSign == "-") def.GetField(fieldRefName).SetsVarOnAdd = -EatParseInt(text, ref i); else i = iSave2; } else { // that didn't work; restore the index i = iSave; } } else if (fieldSizeSpec != "") { try { varLength = (int)BaseConverter.ToNumberParse(fieldSizeSpec); varLength = (int)BaseConverter.ToNumberParse(fieldSizeSpec); } catch { throw new ParserException(_fileName, _lineNumber, "Could not parse number '" + fieldSizeSpec + "'"); } } else { throw new ParserException(_fileName, _lineNumber, "Number or identifier expected (size specifier)"); } // if it's not a string, it's an array if (justType != FieldType.StringASCII && justType != FieldType.StringUTF16) type |= FieldType.Array; _eatResult = EatWhitespace(text, ref i); string rightSqBracket = EatSymbol(text, ref i); if (_eatResult || rightSqBracket != "]") throw new ParserException(_fileName, _lineNumber, "Expected ']'"); // fix up the semicolon _eatResult = EatWhitespace(text, ref i); leftSqBracket = EatSymbol(text, ref i); } // TYPE* FIELDNAME; string endSemicolon = leftSqBracket; if (_eatResult || endSemicolon != ";") throw new ParserException(_fileName, _lineNumber, "Expected ';'"); StructField field = new StructField(fieldName, type); if (field.Type == FieldType.Struct) field.StructName = typeName; field.VarArrayLength = varLength; field.VarLength = varLength; def.AddField(field); } _structs[structName] = def; }
private unsafe int ReadOnce(StructField field, IntPtr offset, out FieldValue valueOut) { FieldValue value = new FieldValue() { FieldType = field.Type, Name = field.Name }; int readSize = 0; switch (field.Type) { case FieldType.Bool32: value.Value = Utils.ToInt32(IOProvider.ReadBytes(offset, 4), Utils.Endianness.Little) != 0; readSize = 4; break; case FieldType.Bool8: value.Value = IOProvider.ReadBytes(offset, 1)[0] != 0; readSize = 1; break; case FieldType.CharASCII: value.Value = (char)IOProvider.ReadBytes(offset, 1)[0]; readSize = 1; break; case FieldType.CharUTF16: value.Value = Encoding.Unicode.GetString(IOProvider.ReadBytes(offset, 2))[0]; readSize = 2; break; case FieldType.Double: { long data = Utils.ToInt64( IOProvider.ReadBytes(offset, 8), Utils.Endianness.Little); value.Value = *(double *)&data; readSize = 8; } break; case FieldType.Int16: value.Value = (short)Utils.ToUInt16( IOProvider.ReadBytes(offset, 2), Utils.Endianness.Little); readSize = 2; break; case FieldType.Int32: value.Value = Utils.ToInt32( IOProvider.ReadBytes(offset, 4), Utils.Endianness.Little); readSize = 4; break; case FieldType.Int64: value.Value = Utils.ToInt64( IOProvider.ReadBytes(offset, 8), Utils.Endianness.Little); readSize = 8; break; case FieldType.Int8: value.Value = (sbyte)IOProvider.ReadBytes(offset, 1)[0]; readSize = 1; break; case FieldType.PVoid: value.Value = IOProvider.ReadBytes(offset, IntPtr.Size).ToIntPtr(); readSize = IntPtr.Size; break; case FieldType.Single: { int data = Utils.ToInt32( IOProvider.ReadBytes(offset, 4), Utils.Endianness.Little); value.Value = *(float *)&data; readSize = 4; } break; case FieldType.StringASCII: { StringBuilder str = new StringBuilder(); if (field.VarLength == -1) { int i; for (i = 0; ; i++) { byte b = IOProvider.ReadBytes(offset.Increment(i), 1)[0]; if (b == 0) { break; } str.Append((char)b); } readSize = i; } else { str.Append(Encoding.ASCII.GetString( IOProvider.ReadBytes(offset, field.VarLength))); readSize = field.VarLength; } value.Value = str.ToString(); } break; case FieldType.StringUTF16: { StringBuilder str = new StringBuilder(); if (field.VarLength == -1) { int i; for (i = 0; ; i += 2) { byte[] b = IOProvider.ReadBytes(offset.Increment(i), 2); if (Utils.IsEmpty(b)) { break; } str.Append(Encoding.Unicode.GetString(b)); } readSize = i; } else { str.Append(Encoding.Unicode.GetString( IOProvider.ReadBytes(offset, field.VarLength * 2))); // each char is 2 bytes readSize = field.VarLength; } value.Value = str.ToString(); } break; case FieldType.Struct: { FieldValue[] valuesOut; StructDef struc = Structs[field.StructName]; struc.IOProvider = this.IOProvider; struc.Offset = offset; struc.Structs = this.Structs; readSize = struc.Read(out valuesOut); value.Value = valuesOut; value.StructName = field.StructName; } break; case FieldType.UInt16: value.Value = Utils.ToUInt16( IOProvider.ReadBytes(offset, 2), Utils.Endianness.Little); readSize = 2; break; case FieldType.UInt32: value.Value = Utils.ToUInt32( IOProvider.ReadBytes(offset, 4), Utils.Endianness.Little); readSize = 4; break; case FieldType.UInt64: value.Value = (ulong)Utils.ToInt64( IOProvider.ReadBytes(offset, 8), Utils.Endianness.Little); readSize = 8; break; case FieldType.UInt8: value.Value = IOProvider.ReadBytes(offset, 1)[0]; readSize = 1; break; default: readSize = 0; break; } valueOut = value; return(readSize); }