Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Issue #333] Change single value writing to use SCALAR spaces #337

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 50 additions & 21 deletions HDF5-CSharp/Hdf5Dataset.cs
Original file line number Diff line number Diff line change
Expand Up @@ -271,27 +271,56 @@ public static (bool success, Array result) ReadDataset<T>(long groupId, string n
return dsetRW.ReadArray<T>(groupId, name, alternativeName, mandatory);
}

/// <summary>
/// Writes one value to a hdf5 file
/// </summary>
/// <typeparam name="T">Generic parameter strings or primitive type</typeparam>
/// <param name="groupId">id of the group. Can also be a file Id</param>
/// <param name="name">name of the dataset</param>
/// <param name="dset">The dataset</param>
/// <returns>status of the write method</returns>
public static (int success, long CreatedgroupId) WriteOneValue<T>(long groupId, string name, T dset, Dictionary<string, List<string>> attributes)
{
if (typeof(T) == typeof(string))
//WriteStrings(groupId, name, new string[] { dset.ToString() });
{
return dsetRW.WriteArray(groupId, name, new T[1] { dset }, attributes);
}

Array oneVal = new T[1, 1] { { dset } };
return dsetRW.WriteArray(groupId, name, oneVal, attributes);
}

public static void WriteDataset(long groupId, string name, Array collection)
/// <summary>
/// Writes one value to a hdf5 file
/// </summary>
/// <typeparam name="T">Generic parameter strings or primitive type</typeparam>
/// <param name="groupId">id of the group. Can also be a file Id</param>
/// <param name="name">name of the dataset</param>
/// <param name="dset">The dataset</param>
/// <returns>status of the write method</returns>
public static (int success, long CreatedgroupId) WriteOneValue<T>(long groupId, string name, T value, Dictionary<string, List<string>> attributes)
{
var spaceId = H5S.create(H5S.class_t.SCALAR);
var datatype = GetDatatype(typeof(T));
var typeId = H5T.copy(datatype);

GCHandle hnd;
if (datatype == H5T.C_S1 || datatype == H5T.FORTRAN_S1)
{
int stringLen = (value as string).Length;

H5T.set_size(typeId, new IntPtr(stringLen));

byte[] strByteArray = new byte[stringLen + 1];
// Write the string to the buffer, with the last element being 0 as the string terminator
for (int i = 0; i < stringLen; ++i)
{
strByteArray[i] = Convert.ToByte((value as string)[i]);
}
hnd = GCHandle.Alloc(strByteArray, GCHandleType.Pinned);
}
else
{
hnd = GCHandle.Alloc(value, GCHandleType.Pinned);
}

string normalizedName = Hdf5Utils.NormalizedName(name);
var datasetId = Hdf5Utils.GetDatasetId(groupId, normalizedName, typeId, spaceId, H5P.DEFAULT);
if (datasetId == -1L)
{
return (-1, -1L);
}

var result = H5D.write(datasetId, typeId, H5S.ALL, H5S.ALL, H5P.DEFAULT, hnd.AddrOfPinnedObject());
hnd.Free();
H5D.close(datasetId);
H5S.close(spaceId);
H5T.close(typeId);
return (result, datasetId);
}

public static void WriteDataset(long groupId, string name, Array collection)
{
dsetRW.WriteArray(groupId, name, collection, new Dictionary<string, List<string>>());
}
Expand Down
75 changes: 29 additions & 46 deletions HDF5-CSharp/Hdf5Strings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,68 +110,51 @@ public static (int success, long CreatedgroupId) WriteStrings(long groupId, stri

public static int WriteAsciiString(long groupId, string name, string str)
{
var spaceNullId = H5S.create(H5S.class_t.NULL);
var spaceScalarId = H5S.create(H5S.class_t.SCALAR);
var spaceScalarId = H5S.create(H5S.class_t.SCALAR);

// create two datasets of the extended ASCII character set
// store as H5T.FORTRAN_S1 -> space padding
int strLength = str.Length;

int strLength = str.Length;
ulong[] dims = { (ulong)strLength, 1 };
var memId = H5T.copy(H5T.C_S1);
// Set the size needed for the string. Leave one extra space for a null-terminated string
H5T.set_size(memId, new IntPtr(strLength + 1));

/* Create the dataset. */
//name = ToHdf5Name(name);
var datasetId = H5D.create(groupId, Hdf5Utils.NormalizedName(name), memId, spaceScalarId);

var spaceId = H5S.create_simple(1, dims, null);
var datasetId = H5D.create(groupId, Hdf5Utils.NormalizedName(name), H5T.FORTRAN_S1, spaceId);
H5S.close(spaceId);
byte[] wdata = new byte[strLength];
// Write the string to the buffer, with the last element being 0 as the string terminator
for (int i = 0; i < strLength; ++i)
{
wdata[i] = Convert.ToByte(str[i]);
}

// we write from C and must provide null-terminated strings
GCHandle hnd = GCHandle.Alloc(wdata, GCHandleType.Pinned);

byte[] wdata = new byte[strLength * 2];

for (int i = 0; i < strLength; ++i)
{
wdata[2 * i] = Convert.ToByte(str[i]);
}

var memId = H5T.copy(H5T.C_S1);
H5T.set_size(memId, new IntPtr(2));
GCHandle hnd = GCHandle.Alloc(wdata, GCHandleType.Pinned);
int result = H5D.write(datasetId, memId, H5S.ALL,
H5S.ALL, H5P.DEFAULT, hnd.AddrOfPinnedObject());
hnd.Free();
H5T.close(memId);
H5D.close(datasetId);
return result;
}
int result = H5D.write(datasetId, memId, H5S.ALL, H5S.ALL, H5P.DEFAULT, hnd.AddrOfPinnedObject());
hnd.Free();
H5S.close(spaceScalarId);
H5T.close(memId);
H5D.close(datasetId);
return result;
}

public static string ReadAsciiString(long groupId, string name)
{
var datatype = H5T.FORTRAN_S1;

//name = ToHdf5Name(name);

var datasetId = H5D.open(groupId, Hdf5Utils.NormalizedName(name));
var spaceId = H5D.get_space(datasetId);
int rank = H5S.get_simple_extent_ndims(spaceId);
ulong[] maxDims = new ulong[rank];
ulong[] dims = new ulong[rank];
ulong[] chunkDims = new ulong[rank];
var memId_n = H5S.get_simple_extent_dims(spaceId, dims, null);
// we write from C and must provide null-terminated strings

byte[] wdata = new byte[dims[0] * 2];

ulong spaceNeeded = H5D.get_storage_size(datasetId);
byte[] wdata = new byte[spaceNeeded];

var memId = H5T.copy(H5T.C_S1);
H5T.set_size(memId, new IntPtr(2));
GCHandle hnd = GCHandle.Alloc(wdata, GCHandleType.Pinned);
int resultId = H5D.read(datasetId, memId, H5S.ALL,
var memId = H5T.copy(H5T.C_S1);
H5T.set_size(memId, new IntPtr((int)spaceNeeded));

int resultId = H5D.read(datasetId, memId, H5S.ALL,
H5S.ALL, H5P.DEFAULT, hnd.AddrOfPinnedObject());
hnd.Free();

wdata = wdata.Where((b, i) => i % 2 == 0).
Select(b => (b == 0) ? (byte)32 : b).ToArray();
// Remove the null termination of the string
wdata = wdata.Where(b => b != 0).ToArray();
string result = Encoding.ASCII.GetString(wdata);

H5T.close(memId);
Expand Down
Loading