diff --git a/CMakeLists.txt b/CMakeLists.txt index d4169bb..4e79cfb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,6 +49,9 @@ if(BUILD_TESTS) enable_testing() + + add_test(NAME GeneralFIR-E COMMAND src/mysofa2json -o tmp.json + ${PROJECT_SOURCE_DIR}/tests/testfile.sofa) add_test(NAME Mesh2HRTF COMMAND src/mysofa2json -c -o tmp.json ${PROJECT_SOURCE_DIR}/tests/Mesh2HRTF.sofa) add_test(NAME latTestAziBeRTA_Resamp1_Fran COMMAND src/mysofa2json -c -o tmp.json diff --git a/src/hdf/btree.c b/src/hdf/btree.c index 7bb2236..674017a 100644 --- a/src/hdf/btree.c +++ b/src/hdf/btree.c @@ -7,9 +7,9 @@ #include "reader.h" #include #include +#include #include #include -#include /* * @@ -212,16 +212,16 @@ void btreeFree(struct BTREE *btree) { free(btree->records); } int treeRead(struct READER *reader, struct DATAOBJECT *data) { - int i, j, err, olen, elements, size, x, y, z, b, e, dy, dz, sx, sy, sz, dzy, - szy; + int d, p, b = 0, c[HDF_MAX_DIMENSIONALITY]; + int i, j, err, olen, elements, size, e; char *input, *output; uint8_t node_type, node_level; uint16_t entries_used; uint32_t size_of_chunk; uint32_t filter_mask; - uint64_t address_of_left_sibling, address_of_right_sibling, start[4], - child_pointer, key, store; + uint64_t address_of_left_sibling, address_of_right_sibling, + start[HDF_MAX_DIMENSIONALITY], child_pointer, key, store; char buf[5]; @@ -230,9 +230,9 @@ int treeRead(struct READER *reader, struct DATAOBJECT *data) { UNUSED(address_of_left_sibling); UNUSED(key); - if (data->ds.dimensionality > 3) { - mylog("TREE dimensions > 3"); // LCOV_EXCL_LINE - return MYSOFA_INVALID_FORMAT; // LCOV_EXCL_LINE + if (data->ds.dimensionality > HDF_MAX_DIMENSIONALITY) { + mylog("TREE dimensions > %d\n", HDF_MAX_DIMENSIONALITY); // LCOV_EXCL_LINE + return MYSOFA_INVALID_FORMAT; // LCOV_EXCL_LINE } /* read signature */ @@ -256,18 +256,11 @@ int treeRead(struct READER *reader, struct DATAOBJECT *data) { elements = 1; for (j = 0; j < data->ds.dimensionality; j++) elements *= data->datalayout_chunk[j]; - dy = data->datalayout_chunk[1]; - dz = data->datalayout_chunk[2]; - sx = data->ds.dimension_size[0]; - sy = data->ds.dimension_size[1]; - sz = data->ds.dimension_size[2]; - dzy = dz * dy; - szy = sz * sy; size = data->datalayout_chunk[data->ds.dimensionality]; mylog("elements %d size %d\n", elements, size); - if (elements <= 0 || size <= 0 || elements > INT_MAX/size) + if (elements <= 0 || size <= 0 || elements > INT_MAX / size) return MYSOFA_INVALID_FORMAT; // LCOV_EXCL_LINE if (!(output = malloc(elements * size))) { return MYSOFA_NO_MEMORY; // LCOV_EXCL_LINE @@ -324,52 +317,42 @@ int treeRead(struct READER *reader, struct DATAOBJECT *data) { return MYSOFA_INVALID_FORMAT; // LCOV_EXCL_LINE } - switch (data->ds.dimensionality) { - case 1: - for (i = 0; i < olen; i++) { - b = i / elements; - x = i % elements + start[0]; - if (x < sx) { + for (d = 0; d < data->ds.dimensionality; d++) { + c[d] = 0; + } - j = x * size + b; - if (j >= 0 && j < data->data_len) { - ((char *)data->data)[j] = output[i]; - } + for (i = 0; i < olen; i++) { + + // calculate and check destination pointer + p = 0; + for (d = 0; d < data->ds.dimensionality; d++) { + if (c[d] + start[d] >= data->ds.dimension_size[d]) { + p = -1; + break; } + p = p * data->ds.dimension_size[d] + c[d] + start[d]; } - break; - case 2: - for (i = 0; i < olen; i++) { - b = i / elements; - x = i % elements; - y = x % dy + start[1]; - x = x / dy + start[0]; - if (y < sy && x < sx) { - j = ((x * sy + y) * size) + b; - if (j >= 0 && j < data->data_len) { - ((char *)data->data)[j] = output[i]; - } + + // copy data if within bounds + if (p >= 0) { + p = p * size + b; + if (p < data->data_len) { + ((char *)data->data)[p] = output[i]; } } - break; - case 3: - for (i = 0; i < olen; i++) { - b = i / elements; - x = i % elements; - z = x % dz + start[2]; - y = (x / dz) % dy + start[1]; - x = (x / dzy) + start[0]; - if (z < sz && y < sy && x < sx) { - j = (x * szy + y * sz + z) * size + b; - if (j >= 0 && j < data->data_len) { - ((char *)data->data)[j] = output[i]; + + // increase source coordinates + for (d = data->ds.dimensionality - 1; d >= 0; d--) { + c[d]++; + if (c[d] < data->datalayout_chunk[d]) { + break; + } else { + c[d] = 0; + if (d == 0) { // at last, increase bytes + b++; } } } - break; - default: - mylog("invalid dim\n"); // LCOV_EXCL_LINE - return MYSOFA_INTERNAL_ERROR; // LCOV_EXCL_LINE } if (mysofa_seek(reader, store, SEEK_SET) < 0) { diff --git a/src/hdf/dataobject.c b/src/hdf/dataobject.c index ec6656b..df2d689 100644 --- a/src/hdf/dataobject.c +++ b/src/hdf/dataobject.c @@ -129,9 +129,10 @@ static int readOHDRHeaderMessageDataspace(struct READER *reader, int version = mysofa_getc(reader); ds->dimensionality = (uint8_t)mysofa_getc(reader); - if (ds->dimensionality > 4) { - mylog("dimensionality must be lower than 5\n"); // LCOV_EXCL_LINE - return MYSOFA_INVALID_FORMAT; // LCOV_EXCL_LINE + if (ds->dimensionality > HDF_MAX_DIMENSIONALITY) { + mylog("dimensionality must not be larger than %d\n", + HDF_MAX_DIMENSIONALITY); // LCOV_EXCL_LINE + return MYSOFA_INVALID_FORMAT; // LCOV_EXCL_LINE } ds->flags = (uint8_t)mysofa_getc(reader); @@ -466,7 +467,7 @@ static int readOHDRHeaderMessageDataLayout(struct READER *reader, int i, err; uint64_t size; - uint8_t dimensionality, layout_class; + uint8_t layout_class; uint32_t dataset_element_size; uint64_t data_address, store, data_size; @@ -520,28 +521,25 @@ static int readOHDRHeaderMessageDataLayout(struct READER *reader, break; case 2: - dimensionality = (uint8_t)mysofa_getc(reader); - mylog("dimensionality %d\n", dimensionality); - - if (dimensionality < 1 || dimensionality > DATAOBJECT_MAX_DIMENSIONALITY) { - mylog("data layout 2: invalid dimensionality %d %lu %lu\n", - dimensionality, sizeof(data->datalayout_chunk), - sizeof(data->datalayout_chunk[0])); + i = mysofa_getc(reader); // chunk dimensionality is one greater than dataset + if (i != data->ds.dimensionality + 1) { + mylog("data layout 2: invalid dimensionality %d %lu %lu vs. %d\n", i, + sizeof(data->datalayout_chunk), sizeof(data->datalayout_chunk[0]), + data->ds.dimensionality); return MYSOFA_INVALID_FORMAT; // LCOV_EXCL_LINE } data_address = readValue(reader, reader->superblock.size_of_offsets); mylog(" CHUNK %" PRIX64 "\n", data_address); - for (i = 0; i < dimensionality; i++) { + for (i = 0; i <= data->ds.dimensionality; i++) { data->datalayout_chunk[i] = readValue(reader, 4); - mylog(" %d\n", data->datalayout_chunk[i]); + mylog(" %d:%d\n", i, data->datalayout_chunk[i]); } /* TODO last entry? error in spec: ?*/ - - size = data->datalayout_chunk[dimensionality - 1]; + size = data->datalayout_chunk[data->ds.dimensionality]; for (i = 0; i < data->ds.dimensionality; i++) size *= data->ds.dimension_size[i]; - if (validAddress(reader, data_address) && dimensionality <= 4) { + if (validAddress(reader, data_address)) { store = mysofa_tell(reader); if (mysofa_seek(reader, data_address, SEEK_SET) < 0) return errno; // LCOV_EXCL_LINE diff --git a/src/hdf/reader.h b/src/hdf/reader.h index 6838995..76f7092 100644 --- a/src/hdf/reader.h +++ b/src/hdf/reader.h @@ -13,6 +13,8 @@ #define UNUSED(x) (void)(x) +#define HDF_MAX_DIMENSIONALITY 4 + struct READER; struct DIR; struct DATAOBJECT; @@ -84,7 +86,7 @@ struct ATTRIBUTEINFO { }; struct DATASPACE { - uint64_t dimension_size[4], dimension_max_size[4]; + uint64_t dimension_size[HDF_MAX_DIMENSIONALITY], dimension_max_size[HDF_MAX_DIMENSIONALITY]; uint8_t dimensionality, flags, type; }; @@ -107,8 +109,6 @@ struct DATATYPE { uint32_t list; /* size of a list in bytes */ }; -#define DATAOBJECT_MAX_DIMENSIONALITY 5 - struct DATAOBJECT { char *name; @@ -126,7 +126,7 @@ struct DATAOBJECT { struct BTREE attributes_btree; struct FRACTALHEAP attributes_heap; - int datalayout_chunk[DATAOBJECT_MAX_DIMENSIONALITY]; + int datalayout_chunk[HDF_MAX_DIMENSIONALITY + 1]; struct MYSOFA_ATTRIBUTE *attributes; struct DIR *directory; diff --git a/tests/testfile.sofa b/tests/testfile.sofa new file mode 100644 index 0000000..50c5d0a Binary files /dev/null and b/tests/testfile.sofa differ