public static utf_query_result query_utf_key(Stream infile, long offset, int index, string name) { utf_query query = new utf_query(); query.index = index; query.name = name; return query_utf_nofail(infile, offset, query); }
public static utf_query_result query_utf_nofail(Stream infile, long offset, utf_query query) { utf_query_result result = query_utf(infile, offset, query); ErrorStuff.CHECK_ERROR(result.valid == 0, "didn't find valid @UTF table where one was expected"); ErrorStuff.CHECK_ERROR(query != null && result.found == 0, "key not found"); return result; }
public static utf_query_result analyze_utf(Stream infile, long offset, int indent, int print, utf_query query) { byte[] buf = new byte[4]; long table_info_table_offset; uint table_info_table_size; uint table_info_schema_offset; uint table_info_rows_offset; uint table_info_string_table_offset; uint table_info_data_offset; uint table_info_table_name; // references index in string_table ushort table_info_columns; ushort table_info_row_width; uint table_info_rows; byte[] string_table = null; utf_column_info[] schema = null; utf_query_result result = new utf_query_result(); result.valid = 0; if (print != 0) { Util.printf_indent(indent); Console.WriteLine("{"); } indent += INDENT_LEVEL; table_info_table_offset = offset; // check header byte[] UTF_signature = Encoding.ASCII.GetBytes("@UTF"); Util.get_bytes_seek(offset, infile, buf, 4); if (!Util.memcmp(buf, UTF_signature)) { if (print != 0) { Util.printf_indent(indent); Console.WriteLine("not a @UTF table at {0:X8}", offset); } indent -= INDENT_LEVEL; if (print != 0) { Util.printf_indent(indent); Console.WriteLine("}"); } string_table = null; schema = null; return result; } // get table size table_info_table_size = Util.get_32_be(infile); table_info_schema_offset = 0x20; table_info_rows_offset = Util.get_32_be(infile); table_info_string_table_offset = Util.get_32_be(infile); table_info_data_offset = Util.get_32_be(infile); uint table_name_string = Util.get_32_be(infile); table_info_columns = Util.get_16_be(infile); table_info_row_width = Util.get_16_be(infile); table_info_rows = Util.get_32_be(infile); // allocate for string table long string_table_size = table_info_data_offset - table_info_string_table_offset; string_table = new byte[string_table_size + 1]; // load schema schema = new utf_column_info[table_info_columns]; for (int i = 0; i < schema.Length; ++i) { schema[i] = new utf_column_info(); } { int i; for (i = 0; i < table_info_columns; i++) { schema[i].type = Util.get_byte(infile); schema[i].column_name = Util.get_32_be(infile); if ((schema[i].type & COLUMN_STORAGE_MASK) == COLUMN_STORAGE_CONSTANT) { schema[i].constant_offset = infile.Position; switch (schema[i].type & COLUMN_TYPE_MASK) { case COLUMN_TYPE_STRING: Util.get_32_be(infile); break; case COLUMN_TYPE_8BYTE: case COLUMN_TYPE_DATA: Util.get_32_be(infile); Util.get_32_be(infile); break; case COLUMN_TYPE_FLOAT: case COLUMN_TYPE_4BYTE2: case COLUMN_TYPE_4BYTE: Util.get_32_be(infile); break; case COLUMN_TYPE_2BYTE2: case COLUMN_TYPE_2BYTE: Util.get_16_be(infile); break; case COLUMN_TYPE_1BYTE2: case COLUMN_TYPE_1BYTE: Util.get_byte(infile); break; default: ErrorStuff.CHECK_ERROR(true, "unknown type for constant"); break; } } } } // read string table Util.get_bytes_seek(table_info_string_table_offset + 8 + offset, infile, string_table, string_table_size); table_info_table_name = table_name_string; // fill in the default stuff result.valid = 1; result.found = 0; result.rows = table_info_rows; result.name_offset = table_name_string; result.string_table_offset = table_info_string_table_offset; result.data_offset = table_info_data_offset; // explore the values if (query != null || print != 0) { int i, j; for (i = 0; i < table_info_rows; i++) { if (print == 0 && query != null && i != query.index) continue; long row_offset = table_info_table_offset + 8 + table_info_rows_offset + i * table_info_row_width; long row_start_offset = row_offset; if (print != 0) { Util.printf_indent(indent); Console.WriteLine("{0}[{1}] = {{", ReadString(string_table, table_info_table_name), i); } indent += INDENT_LEVEL; for (j = 0; j < table_info_columns; j++) { byte type = schema[j].type; long constant_offset = schema[j].constant_offset; int constant = 0; int qthis = (query != null && i == query.index && ReadString(string_table, schema[j].column_name) == query.name) ? 1 : 0; if (print != 0) { Util.printf_indent(indent); Console.Write("{0:x8} {1:x2} {2} = ", row_offset - row_start_offset, type, ReadString(string_table, schema[j].column_name)); } if (qthis != 0) { result.found = 1; result.type = schema[j].type & COLUMN_TYPE_MASK; } switch (schema[j].type & COLUMN_STORAGE_MASK) { case COLUMN_STORAGE_PERROW: break; case COLUMN_STORAGE_CONSTANT: constant = 1; break; case COLUMN_STORAGE_ZERO: if (print != 0) { Console.WriteLine("UNDEFINED"); } if (qthis != 0) { result.value_u64 = 0; } continue; default: ErrorStuff.CHECK_ERROR(true, "unknown storage class"); break; } if (true) { long data_offset; int bytes_read = 0; if (constant != 0) { data_offset = constant_offset; if (print != 0) { Console.Write("constant "); } } else { data_offset = row_offset; } if (qthis != 0) { result.data_position = data_offset; } switch (type & COLUMN_TYPE_MASK) { case COLUMN_TYPE_STRING: { uint string_offset; string_offset = Util.get_32_be_seek(data_offset, infile); bytes_read = 4; if (print != 0) { Console.WriteLine("\"{0}\"", ReadString(string_table, string_offset)); } if (qthis != 0) { result.value_string = string_offset; } } break; case COLUMN_TYPE_DATA: { uint vardata_offset, vardata_size; vardata_offset = Util.get_32_be_seek(data_offset, infile); vardata_size = Util.get_32_be(infile); bytes_read = 8; if (print != 0) { Console.Write("[0x{0:x8}]", vardata_offset); Console.WriteLine(" (size 0x{0:x8})", vardata_size); } if (qthis != 0) { result.value_data = new offset_size_pair() { offset = vardata_offset, size = vardata_size }; } if (vardata_size != 0 && print != 0) { // assume that the data is another table analyze_utf(infile, table_info_table_offset + 8 + table_info_data_offset + vardata_offset, indent, print, null ); } } break; case COLUMN_TYPE_8BYTE: { ulong value = Util.get_64_be_seek(data_offset, infile); if (print != 0) { Console.WriteLine("0x{0:x}", value); } if (qthis != 0) { result.value_u64 = value; } bytes_read = 8; break; } case COLUMN_TYPE_4BYTE2: case COLUMN_TYPE_4BYTE: if ((type & COLUMN_TYPE_MASK) == COLUMN_TYPE_4BYTE2 && print != 0) { Console.Write("type 2 "); } { uint value = Util.get_32_be_seek(data_offset, infile); if (print != 0) { Console.WriteLine("{0}", value); } if (qthis != 0) { result.value_u32 = value; } bytes_read = 4; } break; case COLUMN_TYPE_2BYTE2: case COLUMN_TYPE_2BYTE: if ((type & COLUMN_TYPE_MASK) == COLUMN_TYPE_2BYTE2 && print != 0) { Console.Write("type 2 "); } { ushort value = Util.get_16_be_seek(data_offset, infile); if (print != 0) { Console.WriteLine("{0}", value); } if (qthis != 0) { result.value_u16 = value; } bytes_read = 2; } break; case COLUMN_TYPE_FLOAT: if (true) { uint int_float; int_float = Util.get_32_be_seek(data_offset, infile); if (print != 0) { Console.WriteLine("{0}", Util.reinterpret_to_float(int_float)); } if (qthis != 0) { result.value_u32 = int_float; } } bytes_read = 4; break; case COLUMN_TYPE_1BYTE2: case COLUMN_TYPE_1BYTE: if ((type & COLUMN_TYPE_MASK) == COLUMN_TYPE_1BYTE2 && print != 0) { Console.Write("type 2 "); } { byte value = Util.get_byte_seek(data_offset, infile); if (print != 0) { Console.WriteLine("{0}", value); } if (qthis != 0) { result.value_u8 = value; } bytes_read = 1; } break; default: ErrorStuff.CHECK_ERROR(true, "unknown normal type"); break; } if (constant == 0) { row_offset += bytes_read; } } // useless if end } // column for loop end indent -= INDENT_LEVEL; if (print != 0) { Util.printf_indent(indent); Console.WriteLine("}"); } ErrorStuff.CHECK_ERROR(row_offset - row_start_offset != table_info_row_width, "column widths do now add up to row width"); if (query != null && print == 0 && i >= query.index) break; } // row for loop end } // explore values block end indent -= INDENT_LEVEL; if (print != 0) { Util.printf_indent(indent); Console.WriteLine("}"); } string_table = null; schema = null; return result; }
public static utf_query_result query_utf(Stream infile, long offset, utf_query query) { return analyze_utf(infile, offset, 0, 0, query); }