/* * MmsVariableSpecification.cs * * Copyright 2014-2024 Michael Zillgith * * This file is part of libIEC61850. * * libIEC61850 is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * libIEC61850 is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with libIEC61850. If not, see . * * See COPYING file for the complete license text. */ using System; using System.Runtime.InteropServices; using System.Collections.Generic; using System.Collections; using System.Text; namespace IEC61850 { namespace Common { /// /// MMS variable specification. This class is used to represent an MMS variable type definition. /// public class MmsVariableSpecification : IEnumerable { [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern void MmsVariableSpecification_destroy(IntPtr self); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern IntPtr MmsVariableSpecification_getNamedVariableRecursive(IntPtr variable, string nameId); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern int MmsVariableSpecification_getType(IntPtr self); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern IntPtr MmsVariableSpecification_getName(IntPtr self); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern int MmsVariableSpecification_getSize(IntPtr self); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern IntPtr MmsVariableSpecification_getChildSpecificationByIndex(IntPtr self, int index); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern IntPtr MmsVariableSpecification_getArrayElementSpecification(IntPtr self); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern int MmsVariableSpecification_getExponentWidth(IntPtr self); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern bool MmsVariableSpecification_isValueOfType(IntPtr self, IntPtr value); internal IntPtr self; private bool responsableForDeletion; /* only to prevent garbage collector to destroy parent element */ internal MmsVariableSpecification parent = null; internal MmsVariableSpecification(IntPtr self, MmsVariableSpecification parent) { this.self = self; this.responsableForDeletion = false; this.parent = parent; } internal MmsVariableSpecification(IntPtr self, bool responsableForDeletion) { this.self = self; this.responsableForDeletion = responsableForDeletion; } /// /// Get a child variable specification by its name /// /// the varibable specification of the child, or null if no such child is existing. /// The child name (can also be a path separating the elements with '.' or '$') public MmsVariableSpecification GetChildByName(string name) { StringBuilder nameId = new StringBuilder(name); nameId.Replace('.', '$'); IntPtr varSpecPtr = MmsVariableSpecification_getNamedVariableRecursive(self, nameId.ToString()); if (varSpecPtr != IntPtr.Zero) { return new MmsVariableSpecification(varSpecPtr, this); } else return null; } ~MmsVariableSpecification() { if (responsableForDeletion) MmsVariableSpecification_destroy(self); } /// /// Gets the MmsValue type of the variable /// /// /// The MmsType of the variable /// public new MmsType GetType() { return (MmsType)MmsVariableSpecification_getType(self); } /// /// The MmsValue type of the variable /// public MmsType MmsType { get { return (MmsType)MmsVariableSpecification_getType(self); } } /// /// Gets the type of the array elements. /// /// /// The array element type. /// /// This exception is thrown if the value is not of type MMS_ARRAY public MmsVariableSpecification getArrayElementType() { if (GetType() == MmsType.MMS_ARRAY) { IntPtr varSpecPtr = MmsVariableSpecification.MmsVariableSpecification_getArrayElementSpecification(self); return new MmsVariableSpecification(varSpecPtr, this); } else throw new MmsValueException("specification is of wrong type"); } /// /// The type of array elements (when the variable is of type MMS_ARRAY) /// public MmsVariableSpecification ArrayElementType { get { if (GetType() == MmsType.MMS_ARRAY) { IntPtr varSpecPtr = MmsVariableSpecification.MmsVariableSpecification_getArrayElementSpecification(self); return new MmsVariableSpecification(varSpecPtr, this); } else return null; } } /// /// Gets the element specification of a structure element /// /// /// The element of the structure at given index /// /// /// Index. /// public MmsVariableSpecification GetElement(int index) { if (GetType() == MmsType.MMS_STRUCTURE) { if ((index >= 0) && (index < Size())) { IntPtr varSpecPtr = MmsVariableSpecification_getChildSpecificationByIndex(self, index); return new MmsVariableSpecification(varSpecPtr, this); } else throw new MmsValueException("Index out of bounds"); } else throw new MmsValueException("specification is of wrong type"); } /// /// The element types for complex variables (MMS_STRUCTURE) /// public MmsVariableSpecification[] Elements { get { if (GetType() != MmsType.MMS_STRUCTURE) return null; List elements = new List(); for (int i = 0; i < Size(); i++) { elements.Add(GetElement(i)); } return elements.ToArray(); } } /// /// Gets the name of the variable (relative to the parent) /// /// /// The name. /// public string GetName() { IntPtr namePtr = MmsVariableSpecification_getName(self); return Marshal.PtrToStringAnsi(namePtr); } /// /// The name of the variable (relative to the parent) /// public string Name { get { return GetName(); } } /// /// Get the "size" of the variable (array size, number of structure elements ...) /// public int Size() { return MmsVariableSpecification_getSize(self); } /// /// The "size" of the variable (array size, number of structure elements ...) /// public int size { get { return MmsVariableSpecification_getSize(self); } } /// /// Determines whether the given value object matches this type /// /// true if the value matches this type; otherwise, false. /// the value to test. public bool IsValueOfType(MmsValue value) { return MmsVariableSpecification_isValueOfType(self, value.valueReference); } IEnumerator IEnumerable.GetEnumerator() { return new MmsVariableSpecificationEnumerator(this); } private class MmsVariableSpecificationEnumerator : IEnumerator { private MmsVariableSpecification value; private int index = -1; public MmsVariableSpecificationEnumerator(MmsVariableSpecification value) { this.value = value; } #region IEnumerator Members public void Reset() { index = -1; } public object Current { get { return value.GetElement(index); } } public bool MoveNext() { index++; if (index >= value.Size()) return false; else return true; } #endregion } } } }