public static hid_t CreateEnumType <T>() { var size = EnumHelper.GetUnderlyingTypeSize <T>(); if (size != 1 && size != 2 && size != 4 && size != 8) { throw new ArgumentException("Unexpected enum type size."); } var enumType = H5T.create(H5T.class_t.ENUM, new IntPtr(size)); if (enumType < 0) { return(-1); } var type = typeof(T); // The mapping from symbols to integers is N:1 in C but 1:1 in HDF. // Consider: // enum MyEnum // { // Foo = 0, // Bar = Foo, // } var values = Enum.GetValues(type).OfType <T>().Distinct().ToArray(); for (int i = 0; i < values.Length; ++i) { var value = values[i]; var unmanagedBuffer = new UnmanagedBuffer(size); unmanagedBuffer.WriteEnum(value); // TODO: Should I call H5T.convert before H5T.enum_insert? if (H5T.enum_insert(enumType, Enum.GetName(type, value), unmanagedBuffer) < 0) { H5T.close(enumType); return(-1); } } return(enumType); }
private static long GetHdfTypeIdFromType(Type type) { var elementType = type.IsArray ? type.GetElementType() : type; if (elementType == typeof(bool)) { return(H5T.NATIVE_UINT8); } else if (elementType == typeof(byte)) { return(H5T.NATIVE_UINT8); } else if (elementType == typeof(sbyte)) { return(H5T.NATIVE_INT8); } else if (elementType == typeof(ushort)) { return(H5T.NATIVE_UINT16); } else if (elementType == typeof(short)) { return(H5T.NATIVE_INT16); } else if (elementType == typeof(uint)) { return(H5T.NATIVE_UINT32); } else if (elementType == typeof(int)) { return(H5T.NATIVE_INT32); } else if (elementType == typeof(ulong)) { return(H5T.NATIVE_UINT64); } else if (elementType == typeof(long)) { return(H5T.NATIVE_INT64); } else if (elementType == typeof(float)) { return(H5T.NATIVE_FLOAT); } else if (elementType == typeof(double)) { return(H5T.NATIVE_DOUBLE); } // issues: https://en.wikipedia.org/wiki/Long_double //else if (elementType == typeof(decimal)) // return H5T.NATIVE_LDOUBLE; else if (elementType.IsEnum) { var baseTypeId = TestUtils.GetHdfTypeIdFromType(Enum.GetUnderlyingType(elementType)); var typeId = H5T.enum_create(baseTypeId); foreach (var value in Enum.GetValues(type)) { var value_converted = Convert.ToInt64(value); var name = Enum.GetName(type, value_converted); var handle = GCHandle.Alloc(value_converted, GCHandleType.Pinned); H5T.enum_insert(typeId, name, handle.AddrOfPinnedObject()); } return(typeId); } else if (elementType == typeof(string) || elementType == typeof(IntPtr)) { var typeId = H5T.copy(H5T.C_S1); H5T.set_size(typeId, H5T.VARIABLE); H5T.set_cset(typeId, H5T.cset_t.UTF8); return(typeId); } else if (elementType.IsValueType && !elementType.IsPrimitive) { var typeId = H5T.create(H5T.class_t.COMPOUND, new IntPtr(Marshal.SizeOf(elementType))); foreach (var fieldInfo in elementType.GetFields()) { var fieldType = TestUtils.GetHdfTypeIdFromType(fieldInfo.FieldType); var attribute = fieldInfo.GetCustomAttribute <H5NameAttribute>(true); var hdfFieldName = attribute is not null ? attribute.Name : fieldInfo.Name; H5T.insert(typeId, hdfFieldName, Marshal.OffsetOf(elementType, fieldInfo.Name), fieldType); if (H5I.is_valid(fieldType) > 0) { H5T.close(fieldType); } } return(typeId); } else { throw new NotSupportedException(); } }
public static hid_t CreateEnumType <T>(string[] names, T[] values) { if (names == null) { throw new ArgumentNullException("names"); } if (values == null) { throw new ArgumentNullException("values"); } if (names.Length == 0) { throw new ArgumentException("names"); } if (values.Length == 0) { throw new ArgumentException("values"); } if (names.Length != values.Length) { throw new ArgumentException("names.Length != values.Length"); } if (names.Any(string.IsNullOrEmpty)) { throw new ArgumentException("names"); } if (names.Distinct().Count() != names.Length) { throw new ArgumentException("duplicate in names"); } if (values.Distinct().Count() != values.Length) { throw new ArgumentException("duplicate in values"); } var type = typeof(T); var size = 0; if (type.IsEnum) { size = EnumHelper.GetUnderlyingTypeSize <T>(); } else { size = Marshal.SizeOf(type); } var enumType = H5T.create(H5T.class_t.ENUM, new IntPtr(size)); if (enumType < 0) { throw new HDF5Exception("Failed to create enum type"); } for (int i = 0; i < values.Length; ++i) { var value = values[i]; var unmanagedBuffer = new UnmanagedBuffer(size); if (type.IsEnum) { unmanagedBuffer.WriteEnum(value); } else { unmanagedBuffer.Write(value); } // TODO: Should I call H5T.convert before H5T.enum_insert? if (H5T.enum_insert(enumType, names[i], unmanagedBuffer) < 0) { H5T.close(enumType); throw new HDF5Exception("Failed to insert enum: {0} = {1}", names[i], value); } } return(enumType); }