static void Main(string[] args) { var fileName = args.Length > 0 ? args[0] : "default.realm"; using (var mmf = MemoryMappedFile.CreateFromFile(fileName, FileMode.Open, null, 0, MemoryMappedFileAccess.Read)) using (var accessor = mmf.CreateViewAccessor(0, 0, MemoryMappedFileAccess.Read)) { var header = RealmFileHeader.ReadFrom(accessor); Console.WriteLine("File Format Version: {0}", header.GetTopRef().FileFormatVersion); // ファイル内では、 ref の値はそのまま使える(追加でアロケーションすると話は別) var topArray = new RealmArray(new ReferenceAccessor(accessor, header.GetTopRef().Ref)); Console.WriteLine("Top Array Count: {0}", topArray.Count); // HasRefs な Array に数値が入っているので、最下位ビットが 1 になっている // ビットシフトで元の値が手に入る Console.WriteLine("Logical File Size: {0}", (ulong)topArray[2] >> 1); // 配列の 1 番目がテーブル名リスト var tableNameArray = new RealmArrayString(new ReferenceAccessor(accessor, (ulong)topArray[0]), false); // 2 番目がテーブルのリスト var tableArray = new RealmArray(new ReferenceAccessor(accessor, (ulong)topArray[1])); Console.WriteLine(); Console.WriteLine("Tables"); for (var i = 0; i < tableNameArray.Count; i++) { var table = new RealmTable(new ReferenceAccessor(accessor, (ulong)tableArray[i])); Console.WriteLine(" - {0} (Count: {1})", tableNameArray[i], table.RowCount); PrintTableSpec(table.Spec, tableNameArray, GetBacklinkTarget, 2); } Console.WriteLine(); Console.WriteLine("Contents"); for (var i = 0; i < tableNameArray.Count; i++) { var table = new RealmTable(new ReferenceAccessor(accessor, (ulong)tableArray[i])); Console.WriteLine(" - {0} ({1}/{2})", tableNameArray[i], Math.Min(table.RowCount, PrintCount), table.RowCount); PrintTableContent(table, GetBacklinkTarget, 2); } string GetBacklinkTarget(int tableIndex, int columnIndex) { var targetTable = new RealmTable(tableArray.Ref.NewRef((ulong)tableArray[tableIndex])); var targetColumnName = targetTable.Spec.GetColumn(columnIndex).Name; return(tableNameArray[tableIndex] + "." + targetColumnName); } Debugger.Break(); } }
public TableSpec(ReferenceAccessor @ref) { this.Ref = @ref; var specArray = new RealmArray(@ref); this._types = new RealmArray(@ref.NewRef((ulong)specArray[0])); this._names = new RealmArrayString(@ref.NewRef((ulong)specArray[1]), false); this._attr = new RealmArray(@ref.NewRef((ulong)specArray[2])); if (specArray.Count >= 4) { var subspecsRef = (ulong)specArray[3]; if (subspecsRef != 0) { this._subspecs = new RealmArray(@ref.NewRef(subspecsRef)); } } }
public string GetString(int columnIndex, int rowIndex) { var spec = this.Spec.GetColumn(columnIndex); var nullable = spec.Nullable; if (spec.Type == ColumnType.String) { var(leaf, indexInLeaf) = this.GetFromBpTree(columnIndex, rowIndex); var leafHeader = new RealmArrayHeader(leaf); var longStrings = leafHeader.HasRefs; var isBig = leafHeader.ContextFlag; string value; if (!longStrings) { // 要素はすべて15バイト以下 // https://github.com/realm/realm-core/blob/v5.12.7/src/realm/column_string.cpp#L38-L39 value = new RealmArrayString(leaf, nullable)[indexInLeaf]; } else if (!isBig) { // 要素はすべて63バイト以下 value = new RealmArrayStringLong(leaf, nullable)[indexInLeaf]; } else { value = new RealmArrayBigBlobs(leaf).GetString(indexInLeaf); } return(value == null && !nullable ? "" : value); } else if (spec.Type == ColumnType.StringEnum) { // Table::optimize (各種言語バインディングからは未使用)で // 半分以上の値が重複している String カラムを圧縮したときに誕生する throw new NotImplementedException("StringEnum"); } else { throw new InvalidOperationException($"このカラムの型は {spec.Type} です。"); } }