// 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;
}
}
}
}