// Copyright 2017 Alexander Luzgarev using System; using System.Collections; using System.Collections.Generic; using System.Linq; namespace MatFileHandler { /// /// Structure array. /// internal class MatStructureArray : MatArray, IStructureArray { /// /// Initializes a new instance of the class. /// /// Array properties. /// Dimensions of the array. /// Array name. /// Array contents. public MatStructureArray( ArrayFlags flags, int[] dimensions, string name, Dictionary> fields) : base(flags, dimensions, name) { Fields = fields; } /// public IEnumerable FieldNames => Fields.Keys; /// /// Gets null: not implemented. /// public IReadOnlyDictionary[] Data => null; /// /// Gets a dictionary that maps field names to lists of values. /// internal Dictionary> Fields { get; } /// public IArray this[string field, params int[] list] { get => Fields[field][Dimensions.DimFlatten(list)]; set => Fields[field][Dimensions.DimFlatten(list)] = value; } /// IReadOnlyDictionary IArrayOf>.this[params int[] list] { get => ExtractStructure(Dimensions.DimFlatten(list)); set => throw new NotSupportedException( "Cannot set structure elements via this[params int[]] indexer. Use this[string, int[]] instead."); } private IReadOnlyDictionary ExtractStructure(int i) { return new MatStructureArrayElement(this, i); } /// /// Provides access to an element of a structure array by fields. /// internal class MatStructureArrayElement : IReadOnlyDictionary { /// /// Initializes a new instance of the class. /// /// Parent structure array. /// Index in the structure array. internal MatStructureArrayElement(MatStructureArray parent, int index) { Parent = parent; Index = index; } /// /// Gets the number of fields. /// public int Count => Parent.Fields.Count; /// /// Gets a list of all fields. /// public IEnumerable Keys => Parent.Fields.Keys; /// /// Gets a list of all values. /// public IEnumerable Values => Parent.Fields.Values.Select(array => array[Index]); private MatStructureArray Parent { get; } private int Index { get; } /// /// Gets the value of a given field. /// /// Field name. /// The corresponding value. public IArray this[string key] => Parent.Fields[key][Index]; /// /// Enumerates fieldstructure/value pairs of the dictionary. /// /// All field/value pairs in the structure. public IEnumerator> GetEnumerator() { foreach (var field in Parent.Fields) { yield return new KeyValuePair(field.Key, field.Value[Index]); } } /// /// Enumerates field/value pairs of the structure. /// /// All field/value pairs in the structure. IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } /// /// Checks if the structure has a given field. /// /// Field name /// True iff the structure has a given field. public bool ContainsKey(string key) => Parent.Fields.ContainsKey(key); /// /// Tries to get the value of a given field. /// /// Field name. /// Value (or null if the field is not present). /// Success status of the query. public bool TryGetValue(string key, out IArray value) { var success = Parent.Fields.TryGetValue(key, out var array); if (!success) { value = default(IArray); return false; } value = array[Index]; return true; } } } }