• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

tbeu / matio / #1084

14 May 2026 07:12PM UTC coverage: 82.866% (-0.06%) from 82.922%
#1084

push

travis-ci

tbeu
Fix memory leak

As reported by https://issues.oss-fuzz.com/511973610

1 of 12 new or added lines in 1 file covered. (8.33%)

4 existing lines in 1 file now uncovered.

13145 of 15863 relevant lines covered (82.87%)

53090.91 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

97.24
/src/read_data.c
1
/** @file read_data.c
2
 * Matlab MAT version 5 file functions
3
 * @ingroup MAT
4
 */
5
/*
6
 * Copyright (c) 2015-2026, The matio contributors
7
 * Copyright (c) 2005-2014, Christopher C. Hulbert
8
 * All rights reserved.
9
 *
10
 * SPDX-License-Identifier: BSD-2-Clause
11
 */
12

13
#include "matio_private.h"
14
#if HAVE_ZLIB
15
#include <zlib.h>
16
#endif
17
#include <stddef.h>
18
#include <stdlib.h>
19
#include <string.h>
20
#include <stdio.h>
21
#include <limits.h>
22
#include <math.h>
23
#include <time.h>
24

25
#define READ_DATA_NOSWAP(T)                                           \
26
    do {                                                              \
27
        const size_t block_size = READ_BLOCK_SIZE / data_size;        \
28
        err = MATIO_E_NO_ERROR;                                       \
29
        if ( len <= block_size ) {                                    \
30
            readCount = fread(v, data_size, len, (FILE *)mat->fp);    \
31
            if ( readCount == len ) {                                 \
32
                for ( i = 0; i < len; i++ ) {                         \
33
                    data[i] = (T)v[i];                                \
34
                }                                                     \
35
            } else {                                                  \
36
                err = MATIO_E_GENERIC_READ_ERROR;                     \
37
                break;                                                \
38
            }                                                         \
39
        } else {                                                      \
40
            size_t j;                                                 \
41
            readCount = 0;                                            \
42
            for ( i = 0; i < len - block_size; i += block_size ) {    \
43
                j = fread(v, data_size, block_size, (FILE *)mat->fp); \
44
                readCount += j;                                       \
45
                if ( j == block_size ) {                              \
46
                    for ( j = 0; j < block_size; j++ ) {              \
47
                        data[i + j] = (T)v[j];                        \
48
                    }                                                 \
49
                } else {                                              \
50
                    err = MATIO_E_GENERIC_READ_ERROR;                 \
51
                    break;                                            \
52
                }                                                     \
53
            }                                                         \
54
            if ( err ) {                                              \
55
                break;                                                \
56
            }                                                         \
57
            if ( len > i ) {                                          \
58
                j = fread(v, data_size, len - i, (FILE *)mat->fp);    \
59
                readCount += j;                                       \
60
                if ( j == len - i ) {                                 \
61
                    for ( j = 0; j < len - i; j++ ) {                 \
62
                        data[i + j] = (T)v[j];                        \
63
                    }                                                 \
64
                } else {                                              \
65
                    err = MATIO_E_GENERIC_READ_ERROR;                 \
66
                    break;                                            \
67
                }                                                     \
68
            }                                                         \
69
        }                                                             \
70
    } while ( 0 )
71

72
#define READ_DATA(T, SwapFunc)                                            \
73
    do {                                                                  \
74
        if ( mat->byteswap ) {                                            \
75
            const size_t block_size = READ_BLOCK_SIZE / data_size;        \
76
            err = MATIO_E_NO_ERROR;                                       \
77
            if ( len <= block_size ) {                                    \
78
                readCount = fread(v, data_size, len, (FILE *)mat->fp);    \
79
                if ( readCount == len ) {                                 \
80
                    for ( i = 0; i < len; i++ ) {                         \
81
                        data[i] = (T)SwapFunc(&v[i]);                     \
82
                    }                                                     \
83
                } else {                                                  \
84
                    err = MATIO_E_GENERIC_READ_ERROR;                     \
85
                    break;                                                \
86
                }                                                         \
87
            } else {                                                      \
88
                size_t j;                                                 \
89
                readCount = 0;                                            \
90
                for ( i = 0; i < len - block_size; i += block_size ) {    \
91
                    j = fread(v, data_size, block_size, (FILE *)mat->fp); \
92
                    readCount += j;                                       \
93
                    if ( j == block_size ) {                              \
94
                        for ( j = 0; j < block_size; j++ ) {              \
95
                            data[i + j] = (T)SwapFunc(&v[j]);             \
96
                        }                                                 \
97
                    } else {                                              \
98
                        err = MATIO_E_GENERIC_READ_ERROR;                 \
99
                        break;                                            \
100
                    }                                                     \
101
                }                                                         \
102
                if ( err ) {                                              \
103
                    break;                                                \
104
                }                                                         \
105
                if ( len > i ) {                                          \
106
                    j = fread(v, data_size, len - i, (FILE *)mat->fp);    \
107
                    readCount += j;                                       \
108
                    if ( j == len - i ) {                                 \
109
                        for ( j = 0; j < len - i; j++ ) {                 \
110
                            data[i + j] = (T)SwapFunc(&v[j]);             \
111
                        }                                                 \
112
                    } else {                                              \
113
                        err = MATIO_E_GENERIC_READ_ERROR;                 \
114
                        break;                                            \
115
                    }                                                     \
116
                }                                                         \
117
            }                                                             \
118
        } else {                                                          \
119
            READ_DATA_NOSWAP(T);                                          \
120
            if ( err ) {                                                  \
121
                break;                                                    \
122
            }                                                             \
123
        }                                                                 \
124
    } while ( 0 )
125

126
#if HAVE_ZLIB
127
#define READ_COMPRESSED_DATA_NOSWAP(T)                                                \
128
    do {                                                                              \
129
        const size_t block_size = READ_BLOCK_SIZE / data_size;                        \
130
        if ( len <= block_size ) {                                                    \
131
            err = InflateData(mat, z, v, (mat_uint32_t)(len * data_size));            \
132
            if ( err ) {                                                              \
133
                break;                                                                \
134
            }                                                                         \
135
            for ( i = 0; i < len; i++ ) {                                             \
136
                data[i] = (T)v[i];                                                    \
137
            }                                                                         \
138
        } else {                                                                      \
139
            mat_uint32_t j;                                                           \
140
            len -= (mat_uint32_t)block_size;                                          \
141
            for ( i = 0; i < len; i += (mat_uint32_t)block_size ) {                   \
142
                err = InflateData(mat, z, v, (mat_uint32_t)(block_size * data_size)); \
143
                if ( err ) {                                                          \
144
                    break;                                                            \
145
                }                                                                     \
146
                for ( j = 0; j < block_size; j++ ) {                                  \
147
                    data[i + j] = (T)v[j];                                            \
148
                }                                                                     \
149
            }                                                                         \
150
            if ( err ) {                                                              \
151
                break;                                                                \
152
            }                                                                         \
153
            len -= (mat_uint32_t)(i - block_size);                                    \
154
            err = InflateData(mat, z, v, (mat_uint32_t)(len * data_size));            \
155
            if ( err ) {                                                              \
156
                break;                                                                \
157
            }                                                                         \
158
            for ( j = 0; j < len; j++ ) {                                             \
159
                data[i + j] = (T)v[j];                                                \
160
            }                                                                         \
161
        }                                                                             \
162
    } while ( 0 )
163

164
#define READ_COMPRESSED_DATA(T, SwapFunc)                                                 \
165
    do {                                                                                  \
166
        if ( mat->byteswap ) {                                                            \
167
            const size_t block_size = READ_BLOCK_SIZE / data_size;                        \
168
            if ( len <= block_size ) {                                                    \
169
                err = InflateData(mat, z, v, (mat_uint32_t)(len * data_size));            \
170
                if ( err ) {                                                              \
171
                    break;                                                                \
172
                }                                                                         \
173
                for ( i = 0; i < len; i++ ) {                                             \
174
                    data[i] = (T)SwapFunc(&v[i]);                                         \
175
                }                                                                         \
176
            } else {                                                                      \
177
                mat_uint32_t j;                                                           \
178
                len -= (mat_uint32_t)block_size;                                          \
179
                for ( i = 0; i < len; i += (mat_uint32_t)block_size ) {                   \
180
                    err = InflateData(mat, z, v, (mat_uint32_t)(block_size * data_size)); \
181
                    if ( err ) {                                                          \
182
                        break;                                                            \
183
                    }                                                                     \
184
                    for ( j = 0; j < block_size; j++ ) {                                  \
185
                        data[i + j] = (T)SwapFunc(&v[j]);                                 \
186
                    }                                                                     \
187
                }                                                                         \
188
                if ( err ) {                                                              \
189
                    break;                                                                \
190
                }                                                                         \
191
                len -= (mat_uint32_t)(i - block_size);                                    \
192
                err = InflateData(mat, z, v, (mat_uint32_t)(len * data_size));            \
193
                if ( err ) {                                                              \
194
                    break;                                                                \
195
                }                                                                         \
196
                for ( j = 0; j < len; j++ ) {                                             \
197
                    data[i + j] = (T)SwapFunc(&v[j]);                                     \
198
                }                                                                         \
199
            }                                                                             \
200
        } else {                                                                          \
201
            READ_COMPRESSED_DATA_NOSWAP(T);                                               \
202
            if ( err ) {                                                                  \
203
                break;                                                                    \
204
            }                                                                             \
205
        }                                                                                 \
206
    } while ( 0 )
207

208
#endif
209

210
/*
211
 * --------------------------------------------------------------------------
212
 *    Routines to read data of any type into arrays of a specific type
213
 * --------------------------------------------------------------------------
214
 */
215

216
/** @cond mat_devman */
217

218
#define READ_TYPE_DOUBLE 1
219
#define READ_TYPE_SINGLE 2
220
#define READ_TYPE_INT64 3
221
#define READ_TYPE_UINT64 4
222
#define READ_TYPE_INT32 5
223
#define READ_TYPE_UINT32 6
224
#define READ_TYPE_INT16 7
225
#define READ_TYPE_UINT16 8
226
#define READ_TYPE_INT8 9
227
#define READ_TYPE_UINT8 10
228

229
#define READ_TYPE double
230
#define READ_TYPE_TYPE READ_TYPE_DOUBLE
231
#define READ_TYPED_FUNC1 ReadDoubleData
232
#define READ_TYPED_FUNC2 ReadCompressedDoubleData
233
#include "read_data_impl.h"
234
#undef READ_TYPE
235
#undef READ_TYPE_TYPE
236
#undef READ_TYPED_FUNC1
237
#undef READ_TYPED_FUNC2
238

239
#define READ_TYPE float
240
#define READ_TYPE_TYPE READ_TYPE_SINGLE
241
#define READ_TYPED_FUNC1 ReadSingleData
242
#define READ_TYPED_FUNC2 ReadCompressedSingleData
243
#include "read_data_impl.h"
244
#undef READ_TYPE
245
#undef READ_TYPE_TYPE
246
#undef READ_TYPED_FUNC1
247
#undef READ_TYPED_FUNC2
248

249
#ifdef HAVE_MAT_INT64_T
250
#define READ_TYPE mat_int64_t
251
#define READ_TYPE_TYPE READ_TYPE_INT64
252
#define READ_TYPED_FUNC1 ReadInt64Data
253
#define READ_TYPED_FUNC2 ReadCompressedInt64Data
254
#include "read_data_impl.h"
255
#undef READ_TYPE
256
#undef READ_TYPE_TYPE
257
#undef READ_TYPED_FUNC1
258
#undef READ_TYPED_FUNC2
259
#endif /* HAVE_MAT_INT64_T */
260

261
#ifdef HAVE_MAT_UINT64_T
262
#define READ_TYPE mat_uint64_t
263
#define READ_TYPE_TYPE READ_TYPE_UINT64
264
#define READ_TYPED_FUNC1 ReadUInt64Data
265
#define READ_TYPED_FUNC2 ReadCompressedUInt64Data
266
#include "read_data_impl.h"
267
#undef READ_TYPE
268
#undef READ_TYPE_TYPE
269
#undef READ_TYPED_FUNC1
270
#undef READ_TYPED_FUNC2
271
#endif /* HAVE_MAT_UINT64_T */
272

273
#define READ_TYPE mat_int32_t
274
#define READ_TYPE_TYPE READ_TYPE_INT32
275
#define READ_TYPED_FUNC1 ReadInt32Data
276
#define READ_TYPED_FUNC2 ReadCompressedInt32Data
277
#include "read_data_impl.h"
278
#undef READ_TYPE
279
#undef READ_TYPE_TYPE
280
#undef READ_TYPED_FUNC1
281
#undef READ_TYPED_FUNC2
282

283
#define READ_TYPE mat_uint32_t
284
#define READ_TYPE_TYPE READ_TYPE_UINT32
285
#define READ_TYPED_FUNC1 ReadUInt32Data
286
#define READ_TYPED_FUNC2 ReadCompressedUInt32Data
287
#include "read_data_impl.h"
288
#undef READ_TYPE
289
#undef READ_TYPE_TYPE
290
#undef READ_TYPED_FUNC1
291
#undef READ_TYPED_FUNC2
292

293
#define READ_TYPE mat_int16_t
294
#define READ_TYPE_TYPE READ_TYPE_INT16
295
#define READ_TYPED_FUNC1 ReadInt16Data
296
#define READ_TYPED_FUNC2 ReadCompressedInt16Data
297
#include "read_data_impl.h"
298
#undef READ_TYPE
299
#undef READ_TYPE_TYPE
300
#undef READ_TYPED_FUNC1
301
#undef READ_TYPED_FUNC2
302

303
#define READ_TYPE mat_uint16_t
304
#define READ_TYPE_TYPE READ_TYPE_UINT16
305
#define READ_TYPED_FUNC1 ReadUInt16Data
306
#define READ_TYPED_FUNC2 ReadCompressedUInt16Data
307
#include "read_data_impl.h"
308
#undef READ_TYPE
309
#undef READ_TYPE_TYPE
310
#undef READ_TYPED_FUNC1
311
#undef READ_TYPED_FUNC2
312

313
#define READ_TYPE mat_int8_t
314
#define READ_TYPE_TYPE READ_TYPE_INT8
315
#define READ_TYPED_FUNC1 ReadInt8Data
316
#define READ_TYPED_FUNC2 ReadCompressedInt8Data
317
#include "read_data_impl.h"
318
#undef READ_TYPE
319
#undef READ_TYPE_TYPE
320
#undef READ_TYPED_FUNC1
321
#undef READ_TYPED_FUNC2
322

323
#define READ_TYPE mat_uint8_t
324
#define READ_TYPE_TYPE READ_TYPE_UINT8
325
#define READ_TYPED_FUNC1 ReadUInt8Data
326
#define READ_TYPED_FUNC2 ReadCompressedUInt8Data
327
#include "read_data_impl.h"
328
#undef READ_TYPE
329
#undef READ_TYPE_TYPE
330
#undef READ_TYPED_FUNC1
331
#undef READ_TYPED_FUNC2
332

333
#if HAVE_ZLIB
334
/** @brief Reads data of type @c data_type into a char type
335
 *
336
 * Reads from the MAT file @c len compressed elements of data type @c data_type
337
 * storing them as char's in @c data.
338
 * @ingroup mat_internal
339
 * @param mat MAT file pointer
340
 * @param z Pointer to the zlib stream for inflation
341
 * @param data Pointer to store the output char values (len*sizeof(char))
342
 * @param data_type one of the @c matio_types enumerations which is the source
343
 *                  data type in the file
344
 * @param len Number of elements of type @c data_type to read from the file
345
 * @retval Number of bytes read from the file
346
 */
347
int
348
ReadCompressedCharData(mat_t *mat, z_streamp z, void *data, enum matio_types data_type, size_t len)
5,145✔
349
{
350
    size_t nBytes = 0;
5,145✔
351
    int err;
5,145✔
352

353
    if ( mat == NULL || data == NULL || mat->fp == NULL )
5,145✔
354
        return MATIO_E_BAD_ARGUMENT;
355

356
    err = Mul(&nBytes, len, Mat_SizeOf(data_type));
5,145✔
357
    if ( err ) {
5,145✔
358
        return err;
359
    }
360

361
    switch ( data_type ) {
5,145✔
362
        case MAT_T_UINT8:
5,046✔
363
        case MAT_T_UTF8:
364
            err = InflateData(mat, z, data, (mat_uint32_t)nBytes);
5,046✔
365
            break;
5,046✔
366
        case MAT_T_UINT16:
99✔
367
        case MAT_T_UTF16:
368
            err = InflateData(mat, z, data, (mat_uint32_t)nBytes);
99✔
369
            if ( !err && mat->byteswap ) {
99✔
370
                mat_uint16_t *ptr = (mat_uint16_t *)data;
371
                size_t i;
372
                for ( i = 0; i < len; i++ ) {
×
UNCOV
373
                    Mat_uint16Swap(&ptr[i]);
×
374
                }
375
            }
376
            break;
377
        default:
378
            err = MATIO_E_FILE_FORMAT_VIOLATION;
379
            break;
380
    }
381

382
    return err;
383
}
384
#endif
385

386
int
387
ReadCharData(mat_t *mat, void *_data, enum matio_types data_type, size_t len)
6,054✔
388
{
389
    int err;
6,054✔
390
    size_t data_size;
6,054✔
391

392
    if ( mat == NULL || _data == NULL || mat->fp == NULL )
6,054✔
393
        return MATIO_E_BAD_ARGUMENT;
394

395
    data_size = Mat_SizeOf(data_type);
6,054✔
396

397
    switch ( data_type ) {
6,054✔
398
        case MAT_T_UINT8:
4,921✔
399
        case MAT_T_UTF8: {
400
            size_t nBytes = 0;
4,921✔
401
            err = Read(_data, data_size, len, (FILE *)mat->fp, &nBytes);
4,921✔
402
            break;
4,921✔
403
        }
404
        case MAT_T_UINT16:
1,133✔
405
        case MAT_T_UTF16: {
406
            size_t i, readCount;
1,133✔
407
            mat_uint16_t *data = (mat_uint16_t *)_data;
1,133✔
408
            mat_uint16_t v[READ_BLOCK_SIZE / sizeof(mat_uint16_t)];
1,133✔
409
            READ_DATA(mat_uint16_t, Mat_uint16Swap);
33,453✔
410
            break;
1,133✔
411
        }
412
        default:
413
            err = MATIO_E_FILE_FORMAT_VIOLATION;
414
            break;
415
    }
416
    return err;
417
}
418

419
#undef READ_DATA
420
#undef READ_DATA_NOSWAP
421

422
/*
423
 *-------------------------------------------------------------------
424
 *  Routines to read "slabs" of data
425
 *-------------------------------------------------------------------
426
 */
427

428
#define READ_DATA_SLABN_RANK_LOOP                                                                 \
429
    do {                                                                                          \
430
        for ( j = 1; j < rank; j++ ) {                                                            \
431
            cnt[j]++;                                                                             \
432
            if ( (cnt[j] % edge[j]) == 0 ) {                                                      \
433
                cnt[j] = 0;                                                                       \
434
                if ( (I % dimp[j]) != 0 ) {                                                       \
435
                    (void)fseek((FILE *)mat->fp,                                                  \
436
                                data_size * (dimp[j] - (I % dimp[j]) + dimp[j - 1] * start[j]),   \
437
                                SEEK_CUR);                                                        \
438
                    I += dimp[j] - (I % dimp[j]) + (ptrdiff_t)dimp[j - 1] * start[j];             \
439
                } else if ( start[j] ) {                                                          \
440
                    (void)fseek((FILE *)mat->fp, data_size * (dimp[j - 1] * start[j]), SEEK_CUR); \
441
                    I += (ptrdiff_t)dimp[j - 1] * start[j];                                       \
442
                }                                                                                 \
443
            } else {                                                                              \
444
                I += inc[j];                                                                      \
445
                (void)fseek((FILE *)mat->fp, data_size * inc[j], SEEK_CUR);                       \
446
                break;                                                                            \
447
            }                                                                                     \
448
        }                                                                                         \
449
    } while ( 0 )
450

451
#define READ_DATA_SLABN(ReadDataFunc)                                                          \
452
    do {                                                                                       \
453
        inc[0] = stride[0] - 1;                                                                \
454
        dimp[0] = dims[0];                                                                     \
455
        N = edge[0];                                                                           \
456
        I = 0; /* start[0]; */                                                                 \
457
        for ( i = 1; i < rank; i++ ) {                                                         \
458
            inc[i] = stride[i] - 1;                                                            \
459
            dimp[i] = dims[i - 1];                                                             \
460
            for ( j = i; j--; ) {                                                              \
461
                inc[i] *= dims[j];                                                             \
462
                dimp[i] *= dims[j + 1];                                                        \
463
            }                                                                                  \
464
            N *= edge[i];                                                                      \
465
            I += (ptrdiff_t)dimp[i - 1] * start[i];                                            \
466
        }                                                                                      \
467
        (void)fseek((FILE *)mat->fp, I * data_size, SEEK_CUR);                                 \
468
        if ( stride[0] == 1 ) {                                                                \
469
            for ( i = 0; i < N; i += edge[0] ) {                                               \
470
                if ( start[0] ) {                                                              \
471
                    (void)fseek((FILE *)mat->fp, start[0] * data_size, SEEK_CUR);              \
472
                    I += start[0];                                                             \
473
                }                                                                              \
474
                err = ReadDataFunc(mat, ptr + i, data_type, edge[0]);                          \
475
                if ( err ) {                                                                   \
476
                    break;                                                                     \
477
                }                                                                              \
478
                I += dims[0] - start[0];                                                       \
479
                (void)fseek((FILE *)mat->fp, data_size * (dims[0] - edge[0] - start[0]),       \
480
                            SEEK_CUR);                                                         \
481
                READ_DATA_SLABN_RANK_LOOP;                                                     \
482
            }                                                                                  \
483
        } else {                                                                               \
484
            for ( i = 0; i < N; i += edge[0] ) {                                               \
485
                if ( start[0] ) {                                                              \
486
                    (void)fseek((FILE *)mat->fp, start[0] * data_size, SEEK_CUR);              \
487
                    I += start[0];                                                             \
488
                }                                                                              \
489
                for ( j = 0; j < edge[0]; j++ ) {                                              \
490
                    err = ReadDataFunc(mat, ptr + i + j, data_type, 1);                        \
491
                    if ( err ) {                                                               \
492
                        break;                                                                 \
493
                    }                                                                          \
494
                    (void)fseek((FILE *)mat->fp, data_size * (stride[0] - 1), SEEK_CUR);       \
495
                    I += stride[0];                                                            \
496
                }                                                                              \
497
                if ( err ) {                                                                   \
498
                    break;                                                                     \
499
                }                                                                              \
500
                I += dims[0] - (ptrdiff_t)edge[0] * stride[0] - start[0];                      \
501
                (void)fseek((FILE *)mat->fp,                                                   \
502
                            data_size * (dims[0] - (ptrdiff_t)edge[0] * stride[0] - start[0]), \
503
                            SEEK_CUR);                                                         \
504
                READ_DATA_SLABN_RANK_LOOP;                                                     \
505
            }                                                                                  \
506
        }                                                                                      \
507
    } while ( 0 )
508

509
static int
510
CheckEdgeOverflow(int rank, const int *edge)
2,100✔
511
{
512
    int i, err;
2,100✔
513
    size_t nElements = 1;
2,100✔
514
    for ( i = 0; i < rank; i++ ) {
8,400✔
515
        if ( edge[i] < 0 ) {
6,300✔
516
            return 1;
517
        }
518
        err = Mul(&nElements, nElements, (size_t)edge[i]);
6,300✔
519
        if ( err || nElements > (size_t)INT_MAX ) {
6,300✔
520
            return 1;
521
        }
522
    }
523
    return 0;
524
}
525

526
/** @brief Reads data of type @c data_type by user-defined dimensions
527
 *
528
 * @ingroup mat_internal
529
 * @param mat MAT file pointer
530
 * @param data Pointer to store the output data
531
 * @param class_type Type of data class (matio_classes enumerations)
532
 * @param data_type Datatype of the stored data (matio_types enumerations)
533
 * @param rank Number of dimensions in the data
534
 * @param dims Dimensions of the data
535
 * @param start Index to start reading data in each dimension
536
 * @param stride Read every @c stride elements in each dimension
537
 * @param edge Number of elements to read in each dimension
538
 * @retval Number of bytes read from the file, or -1 on error
539
 */
540
int
541
ReadDataSlabN(mat_t *mat, void *data, enum matio_classes class_type, enum matio_types data_type,
1,380✔
542
              int rank, const size_t *dims, const int *start, const int *stride, const int *edge)
543
{
544
    int err;
1,380✔
545
    int i, j, N, I = 0;
1,380✔
546
    int inc[10] =
1,380✔
547
        {
548
            0,
549
        },
550
        cnt[10] =
1,380✔
551
            {
552
                0,
553
            },
554
        dimp[10] = {
1,380✔
555
            0,
556
        };
557
    size_t data_size;
1,380✔
558

559
    if ( (mat == NULL) || (data == NULL) || (mat->fp == NULL) || (start == NULL) ||
1,380✔
560
         (stride == NULL) || (edge == NULL) ) {
1,380✔
561
        return MATIO_E_BAD_ARGUMENT;
562
    } else if ( rank > 10 ) {
1,380✔
563
        return MATIO_E_BAD_ARGUMENT;
564
    }
565

566
    if ( CheckEdgeOverflow(rank, edge) ) {
1,380✔
567
        return MATIO_E_BAD_ARGUMENT;
568
    }
569

570
    data_size = Mat_SizeOf(data_type);
1,380✔
571

572
    switch ( class_type ) {
1,380✔
573
        case MAT_C_DOUBLE: {
138✔
574
            double *ptr = (double *)data;
138✔
575
            READ_DATA_SLABN(ReadDoubleData);
2,772✔
576
            break;
577
        }
578
        case MAT_C_SINGLE: {
138✔
579
            float *ptr = (float *)data;
138✔
580
            READ_DATA_SLABN(ReadSingleData);
2,772✔
581
            break;
582
        }
583
#ifdef HAVE_MAT_INT64_T
584
        case MAT_C_INT64: {
138✔
585
            mat_int64_t *ptr = (mat_int64_t *)data;
138✔
586
            READ_DATA_SLABN(ReadInt64Data);
2,772✔
587
            break;
588
        }
589
#endif /* HAVE_MAT_INT64_T */
590
#ifdef HAVE_MAT_UINT64_T
591
        case MAT_C_UINT64: {
138✔
592
            mat_uint64_t *ptr = (mat_uint64_t *)data;
138✔
593
            READ_DATA_SLABN(ReadUInt64Data);
2,772✔
594
            break;
595
        }
596
#endif /* HAVE_MAT_UINT64_T */
597
        case MAT_C_INT32: {
138✔
598
            mat_int32_t *ptr = (mat_int32_t *)data;
138✔
599
            READ_DATA_SLABN(ReadInt32Data);
2,772✔
600
            break;
601
        }
602
        case MAT_C_UINT32: {
138✔
603
            mat_uint32_t *ptr = (mat_uint32_t *)data;
138✔
604
            READ_DATA_SLABN(ReadUInt32Data);
2,772✔
605
            break;
606
        }
607
        case MAT_C_INT16: {
138✔
608
            mat_int16_t *ptr = (mat_int16_t *)data;
138✔
609
            READ_DATA_SLABN(ReadInt16Data);
2,772✔
610
            break;
611
        }
612
        case MAT_C_UINT16: {
138✔
613
            mat_uint16_t *ptr = (mat_uint16_t *)data;
138✔
614
            READ_DATA_SLABN(ReadUInt16Data);
2,772✔
615
            break;
616
        }
617
        case MAT_C_INT8: {
138✔
618
            mat_int8_t *ptr = (mat_int8_t *)data;
138✔
619
            READ_DATA_SLABN(ReadInt8Data);
2,772✔
620
            break;
621
        }
622
        case MAT_C_UINT8: {
138✔
623
            mat_uint8_t *ptr = (mat_uint8_t *)data;
138✔
624
            READ_DATA_SLABN(ReadUInt8Data);
2,772✔
625
            break;
626
        }
627
        default:
628
            err = MATIO_E_FILE_FORMAT_VIOLATION;
629
            break;
630
    }
631
    return err;
632
}
633

634
#undef READ_DATA_SLABN
635
#undef READ_DATA_SLABN_RANK_LOOP
636

637
#if HAVE_ZLIB
638
#define READ_COMPRESSED_DATA_SLABN_RANK_LOOP                                           \
639
    do {                                                                               \
640
        for ( j = 1; j < rank; j++ ) {                                                 \
641
            cnt[j]++;                                                                  \
642
            if ( (cnt[j] % edge[j]) == 0 ) {                                           \
643
                cnt[j] = 0;                                                            \
644
                if ( (I % dimp[j]) != 0 ) {                                            \
645
                    InflateSkipData(mat, &z_copy, data_type,                           \
646
                                    dimp[j] - (I % dimp[j]) + dimp[j - 1] * start[j]); \
647
                    I += dimp[j] - (I % dimp[j]) + (ptrdiff_t)dimp[j - 1] * start[j];  \
648
                } else if ( start[j] ) {                                               \
649
                    InflateSkipData(mat, &z_copy, data_type, dimp[j - 1] * start[j]);  \
650
                    I += (ptrdiff_t)dimp[j - 1] * start[j];                            \
651
                }                                                                      \
652
            } else {                                                                   \
653
                if ( inc[j] ) {                                                        \
654
                    I += inc[j];                                                       \
655
                    InflateSkipData(mat, &z_copy, data_type, inc[j]);                  \
656
                }                                                                      \
657
                break;                                                                 \
658
            }                                                                          \
659
        }                                                                              \
660
    } while ( 0 )
661

662
#define READ_COMPRESSED_DATA_SLABN(ReadDataFunc)                                                \
663
    do {                                                                                        \
664
        inc[0] = stride[0] - 1;                                                                 \
665
        dimp[0] = dims[0];                                                                      \
666
        N = edge[0];                                                                            \
667
        I = 0;                                                                                  \
668
        for ( i = 1; i < rank; i++ ) {                                                          \
669
            inc[i] = stride[i] - 1;                                                             \
670
            dimp[i] = dims[i - 1];                                                              \
671
            for ( j = i; j--; ) {                                                               \
672
                inc[i] *= dims[j];                                                              \
673
                dimp[i] *= dims[j + 1];                                                         \
674
            }                                                                                   \
675
            N *= edge[i];                                                                       \
676
            I += (ptrdiff_t)dimp[i - 1] * start[i];                                             \
677
        }                                                                                       \
678
        /* Skip all data to the starting indices */                                             \
679
        InflateSkipData(mat, &z_copy, data_type, I);                                            \
680
        if ( stride[0] == 1 ) {                                                                 \
681
            for ( i = 0; i < N; i += edge[0] ) {                                                \
682
                if ( start[0] ) {                                                               \
683
                    InflateSkipData(mat, &z_copy, data_type, start[0]);                         \
684
                    I += start[0];                                                              \
685
                }                                                                               \
686
                ReadDataFunc(mat, &z_copy, ptr + i, data_type, edge[0]);                        \
687
                InflateSkipData(mat, &z_copy, data_type, dims[0] - start[0] - edge[0]);         \
688
                I += dims[0] - start[0];                                                        \
689
                READ_COMPRESSED_DATA_SLABN_RANK_LOOP;                                           \
690
            }                                                                                   \
691
        } else {                                                                                \
692
            for ( i = 0; i < N; i += edge[0] ) {                                                \
693
                if ( start[0] ) {                                                               \
694
                    InflateSkipData(mat, &z_copy, data_type, start[0]);                         \
695
                    I += start[0];                                                              \
696
                }                                                                               \
697
                for ( j = 0; j < edge[0] - 1; j++ ) {                                           \
698
                    ReadDataFunc(mat, &z_copy, ptr + i + j, data_type, 1);                      \
699
                    InflateSkipData(mat, &z_copy, data_type, (stride[0] - 1));                  \
700
                    I += stride[0];                                                             \
701
                }                                                                               \
702
                ReadDataFunc(mat, &z_copy, ptr + i + j, data_type, 1);                          \
703
                I += dims[0] - (ptrdiff_t)(edge[0] - 1) * stride[0] - start[0];                 \
704
                InflateSkipData(mat, &z_copy, data_type,                                        \
705
                                dims[0] - (ptrdiff_t)(edge[0] - 1) * stride[0] - start[0] - 1); \
706
                READ_COMPRESSED_DATA_SLABN_RANK_LOOP;                                           \
707
            }                                                                                   \
708
        }                                                                                       \
709
    } while ( 0 )
710

711
/** @brief Reads data of type @c data_type by user-defined dimensions
712
 *
713
 * @ingroup mat_internal
714
 * @param mat MAT file pointer
715
 * @param z zlib compression stream
716
 * @param data Pointer to store the output data
717
 * @param class_type Type of data class (matio_classes enumerations)
718
 * @param data_type Datatype of the stored data (matio_types enumerations)
719
 * @param rank Number of dimensions in the data
720
 * @param dims Dimensions of the data
721
 * @param start Index to start reading data in each dimension
722
 * @param stride Read every @c stride elements in each dimension
723
 * @param edge Number of elements to read in each dimension
724
 * @retval Number of bytes read from the file, or -1 on error
725
 */
726
int
727
ReadCompressedDataSlabN(mat_t *mat, z_streamp z, void *data, enum matio_classes class_type,
720✔
728
                        enum matio_types data_type, int rank, const size_t *dims, const int *start,
729
                        const int *stride, const int *edge)
730
{
731
    int nBytes = 0, i, j, N, I = 0, err;
720✔
732
    int inc[10] =
720✔
733
        {
734
            0,
735
        },
736
        cnt[10] =
720✔
737
            {
738
                0,
739
            },
740
        dimp[10] = {
720✔
741
            0,
742
        };
743
    z_stream z_copy = {
720✔
744
        0,
745
    };
746

747
    if ( (mat == NULL) || (data == NULL) || (mat->fp == NULL) || (start == NULL) ||
720✔
748
         (stride == NULL) || (edge == NULL) ) {
720✔
749
        return 0;
750
    } else if ( rank > 10 ) {
720✔
751
        return 0;
752
    }
753

754
    if ( CheckEdgeOverflow(rank, edge) ) {
720✔
755
        return 0;
756
    }
757

758
    err = inflateCopy(&z_copy, z);
720✔
759
    if ( err != Z_OK ) {
720✔
760
        Mat_Critical("inflateCopy returned error %s", zError(err));
×
UNCOV
761
        return -1;
×
762
    }
763
    switch ( class_type ) {
720✔
764
        case MAT_C_DOUBLE: {
72✔
765
            double *ptr = (double *)data;
72✔
766
            READ_COMPRESSED_DATA_SLABN(ReadCompressedDoubleData);
1,656✔
767
            break;
768
        }
769
        case MAT_C_SINGLE: {
72✔
770
            float *ptr = (float *)data;
72✔
771
            READ_COMPRESSED_DATA_SLABN(ReadCompressedSingleData);
1,656✔
772
            break;
773
        }
774
#ifdef HAVE_MAT_INT64_T
775
        case MAT_C_INT64: {
72✔
776
            mat_int64_t *ptr = (mat_int64_t *)data;
72✔
777
            READ_COMPRESSED_DATA_SLABN(ReadCompressedInt64Data);
1,656✔
778
            break;
779
        }
780
#endif /* HAVE_MAT_INT64_T */
781
#ifdef HAVE_MAT_UINT64_T
782
        case MAT_C_UINT64: {
72✔
783
            mat_uint64_t *ptr = (mat_uint64_t *)data;
72✔
784
            READ_COMPRESSED_DATA_SLABN(ReadCompressedUInt64Data);
1,656✔
785
            break;
786
        }
787
#endif /* HAVE_MAT_UINT64_T */
788
        case MAT_C_INT32: {
72✔
789
            mat_int32_t *ptr = (mat_int32_t *)data;
72✔
790
            READ_COMPRESSED_DATA_SLABN(ReadCompressedInt32Data);
1,656✔
791
            break;
792
        }
793
        case MAT_C_UINT32: {
72✔
794
            mat_uint32_t *ptr = (mat_uint32_t *)data;
72✔
795
            READ_COMPRESSED_DATA_SLABN(ReadCompressedUInt32Data);
1,656✔
796
            break;
797
        }
798
        case MAT_C_INT16: {
72✔
799
            mat_int16_t *ptr = (mat_int16_t *)data;
72✔
800
            READ_COMPRESSED_DATA_SLABN(ReadCompressedInt16Data);
1,656✔
801
            break;
802
        }
803
        case MAT_C_UINT16: {
72✔
804
            mat_uint16_t *ptr = (mat_uint16_t *)data;
72✔
805
            READ_COMPRESSED_DATA_SLABN(ReadCompressedUInt16Data);
1,656✔
806
            break;
807
        }
808
        case MAT_C_INT8: {
72✔
809
            mat_int8_t *ptr = (mat_int8_t *)data;
72✔
810
            READ_COMPRESSED_DATA_SLABN(ReadCompressedInt8Data);
1,656✔
811
            break;
812
        }
813
        case MAT_C_UINT8: {
72✔
814
            mat_uint8_t *ptr = (mat_uint8_t *)data;
72✔
815
            READ_COMPRESSED_DATA_SLABN(ReadCompressedUInt8Data);
1,656✔
816
            break;
817
        }
818
        default:
819
            nBytes = 0;
820
    }
821
    inflateEnd(&z_copy);
720✔
822
    return nBytes;
720✔
823
}
824

825
#undef READ_COMPRESSED_DATA_SLABN
826
#undef READ_COMPRESSED_DATA_SLABN_RANK_LOOP
827
#endif
828

829
#define READ_DATA_SLAB1(ReadDataFunc)                            \
830
    do {                                                         \
831
        if ( !stride ) {                                         \
832
            err = ReadDataFunc(mat, ptr, data_type, edge);       \
833
        } else {                                                 \
834
            for ( i = 0; i < edge; i++ ) {                       \
835
                err = ReadDataFunc(mat, ptr + i, data_type, 1);  \
836
                if ( err ) {                                     \
837
                    break;                                       \
838
                }                                                \
839
                (void)fseeko((FILE *)mat->fp, stride, SEEK_CUR); \
840
            }                                                    \
841
        }                                                        \
842
    } while ( 0 )
843

844
/** @brief Reads data of type @c data_type by user-defined dimensions for 1-D
845
 *         data
846
 *
847
 * @ingroup mat_internal
848
 * @param mat MAT file pointer
849
 * @param data Pointer to store the output data
850
 * @param class_type Type of data class (matio_classes enumerations)
851
 * @param data_type Datatype of the stored data (matio_types enumerations)
852
 * @param start Index to start reading data
853
 * @param stride Read every @c stride elements
854
 * @param edge Number of elements to read
855
 * @retval 0 on success
856
 */
857
int
858
ReadDataSlab1(mat_t *mat, void *data, enum matio_classes class_type, enum matio_types data_type,
126✔
859
              int start, int stride, int edge)
860
{
861
    int err, i;
126✔
862
    size_t data_size;
126✔
863

864
    data_size = Mat_SizeOf(data_type);
126✔
865
    (void)fseek((FILE *)mat->fp, start * data_size, SEEK_CUR);
126✔
866
    stride = data_size * (stride - 1);
126✔
867

868
    switch ( class_type ) {
126✔
869
        case MAT_C_DOUBLE: {
18✔
870
            double *ptr = (double *)data;
18✔
871
            READ_DATA_SLAB1(ReadDoubleData);
258✔
872
            break;
873
        }
874
        case MAT_C_SINGLE: {
12✔
875
            float *ptr = (float *)data;
12✔
876
            READ_DATA_SLAB1(ReadSingleData);
204✔
877
            break;
878
        }
879
#ifdef HAVE_MAT_INT64_T
880
        case MAT_C_INT64: {
12✔
881
            mat_int64_t *ptr = (mat_int64_t *)data;
12✔
882
            READ_DATA_SLAB1(ReadInt64Data);
204✔
883
            break;
884
        }
885
#endif /* HAVE_MAT_INT64_T */
886
#ifdef HAVE_MAT_UINT64_T
887
        case MAT_C_UINT64: {
12✔
888
            mat_uint64_t *ptr = (mat_uint64_t *)data;
12✔
889
            READ_DATA_SLAB1(ReadUInt64Data);
204✔
890
            break;
891
        }
892
#endif /* HAVE_MAT_UINT64_T */
893
        case MAT_C_INT32: {
12✔
894
            mat_int32_t *ptr = (mat_int32_t *)data;
12✔
895
            READ_DATA_SLAB1(ReadInt32Data);
204✔
896
            break;
897
        }
898
        case MAT_C_UINT32: {
12✔
899
            mat_uint32_t *ptr = (mat_uint32_t *)data;
12✔
900
            READ_DATA_SLAB1(ReadUInt32Data);
204✔
901
            break;
902
        }
903
        case MAT_C_INT16: {
12✔
904
            mat_int16_t *ptr = (mat_int16_t *)data;
12✔
905
            READ_DATA_SLAB1(ReadInt16Data);
204✔
906
            break;
907
        }
908
        case MAT_C_UINT16: {
12✔
909
            mat_uint16_t *ptr = (mat_uint16_t *)data;
12✔
910
            READ_DATA_SLAB1(ReadUInt16Data);
204✔
911
            break;
912
        }
913
        case MAT_C_INT8: {
12✔
914
            mat_int8_t *ptr = (mat_int8_t *)data;
12✔
915
            READ_DATA_SLAB1(ReadInt8Data);
204✔
916
            break;
917
        }
918
        case MAT_C_UINT8: {
12✔
919
            mat_uint8_t *ptr = (mat_uint8_t *)data;
12✔
920
            READ_DATA_SLAB1(ReadUInt8Data);
204✔
921
            break;
922
        }
923
        default:
924
            err = MATIO_E_FILE_FORMAT_VIOLATION;
925
            break;
926
    }
927

928
    return err;
126✔
929
}
930

931
#undef READ_DATA_SLAB1
932

933
#define READ_DATA_SLAB2(ReadDataFunc)                                                           \
934
    do {                                                                                        \
935
        /* If stride[0] is 1 and stride[1] is 1, we are reading all of the */                   \
936
        /* data so get rid of the loops. */                                                     \
937
        if ( (stride[0] == 1 && (size_t)edge[0] == dims[0]) && (stride[1] == 1) ) {             \
938
            err = ReadDataFunc(mat, ptr, data_type, (ptrdiff_t)edge[0] * edge[1]);              \
939
        } else {                                                                                \
940
            row_stride = (mat_off_t)(stride[0] - 1) * data_size;                                \
941
            col_stride = (mat_off_t)stride[1] * dims[0] * data_size;                            \
942
            pos = ftello((FILE *)mat->fp);                                                      \
943
            if ( pos == -1L ) {                                                                 \
944
                Mat_Critical("Couldn't determine file position");                               \
945
                return MATIO_E_GENERIC_READ_ERROR;                                              \
946
            }                                                                                   \
947
            (void)fseeko((FILE *)mat->fp, (mat_off_t)start[1] * dims[0] * data_size, SEEK_CUR); \
948
            for ( i = 0; i < edge[1]; i++ ) {                                                   \
949
                pos = ftello((FILE *)mat->fp);                                                  \
950
                if ( pos == -1L ) {                                                             \
951
                    Mat_Critical("Couldn't determine file position");                           \
952
                    return MATIO_E_GENERIC_READ_ERROR;                                          \
953
                }                                                                               \
954
                (void)fseeko((FILE *)mat->fp, (mat_off_t)start[0] * data_size, SEEK_CUR);       \
955
                for ( j = 0; j < edge[0]; j++ ) {                                               \
956
                    err = ReadDataFunc(mat, ptr++, data_type, 1);                               \
957
                    if ( err ) {                                                                \
958
                        return err;                                                             \
959
                    }                                                                           \
960
                    (void)fseeko((FILE *)mat->fp, row_stride, SEEK_CUR);                        \
961
                }                                                                               \
962
                pos2 = ftello((FILE *)mat->fp);                                                 \
963
                if ( pos2 == -1L ) {                                                            \
964
                    Mat_Critical("Couldn't determine file position");                           \
965
                    return MATIO_E_GENERIC_READ_ERROR;                                          \
966
                }                                                                               \
967
                pos += col_stride - pos2;                                                       \
968
                (void)fseeko((FILE *)mat->fp, pos, SEEK_CUR);                                   \
969
            }                                                                                   \
970
        }                                                                                       \
971
    } while ( 0 )
972

973
/** @brief Reads data of type @c data_type by user-defined dimensions for 2-D
974
 *         data
975
 *
976
 * @ingroup mat_internal
977
 * @param mat MAT file pointer
978
 * @param data Pointer to store the output data
979
 * @param class_type Type of data class (matio_classes enumerations)
980
 * @param data_type Datatype of the stored data (matio_types enumerations)
981
 * @param dims Dimensions of the data
982
 * @param start Index to start reading data in each dimension
983
 * @param stride Read every @c stride elements in each dimension
984
 * @param edge Number of elements to read in each dimension
985
 * @retval 0 on success
986
 */
987
int
988
ReadDataSlab2(mat_t *mat, void *data, enum matio_classes class_type, enum matio_types data_type,
1,386✔
989
              const size_t *dims, const int *start, const int *stride, const int *edge)
990
{
991
    int err;
1,386✔
992
    int data_size, i, j;
1,386✔
993
    mat_off_t pos, row_stride, col_stride, pos2;
1,386✔
994

995
    if ( (mat == NULL) || (data == NULL) || (mat->fp == NULL) || (start == NULL) ||
1,386✔
996
         (stride == NULL) || (edge == NULL) ) {
1,386✔
997
        return MATIO_E_BAD_ARGUMENT;
998
    }
999

1000
    data_size = Mat_SizeOf(data_type);
1,386✔
1001

1002
    switch ( class_type ) {
1,386✔
1003
        case MAT_C_DOUBLE: {
144✔
1004
            double *ptr = (double *)data;
144✔
1005
            READ_DATA_SLAB2(ReadDoubleData);
936✔
1006
            break;
1007
        }
1008
        case MAT_C_SINGLE: {
138✔
1009
            float *ptr = (float *)data;
138✔
1010
            READ_DATA_SLAB2(ReadSingleData);
930✔
1011
            break;
1012
        }
1013
#ifdef HAVE_MAT_INT64_T
1014
        case MAT_C_INT64: {
138✔
1015
            mat_int64_t *ptr = (mat_int64_t *)data;
138✔
1016
            READ_DATA_SLAB2(ReadInt64Data);
930✔
1017
            break;
1018
        }
1019
#endif /* HAVE_MAT_INT64_T */
1020
#ifdef HAVE_MAT_UINT64_T
1021
        case MAT_C_UINT64: {
138✔
1022
            mat_uint64_t *ptr = (mat_uint64_t *)data;
138✔
1023
            READ_DATA_SLAB2(ReadUInt64Data);
930✔
1024
            break;
1025
        }
1026
#endif /* HAVE_MAT_UINT64_T */
1027
        case MAT_C_INT32: {
138✔
1028
            mat_int32_t *ptr = (mat_int32_t *)data;
138✔
1029
            READ_DATA_SLAB2(ReadInt32Data);
930✔
1030
            break;
1031
        }
1032
        case MAT_C_UINT32: {
138✔
1033
            mat_uint32_t *ptr = (mat_uint32_t *)data;
138✔
1034
            READ_DATA_SLAB2(ReadUInt32Data);
930✔
1035
            break;
1036
        }
1037
        case MAT_C_INT16: {
138✔
1038
            mat_int16_t *ptr = (mat_int16_t *)data;
138✔
1039
            READ_DATA_SLAB2(ReadInt16Data);
930✔
1040
            break;
1041
        }
1042
        case MAT_C_UINT16: {
138✔
1043
            mat_uint16_t *ptr = (mat_uint16_t *)data;
138✔
1044
            READ_DATA_SLAB2(ReadUInt16Data);
930✔
1045
            break;
1046
        }
1047
        case MAT_C_INT8: {
138✔
1048
            mat_int8_t *ptr = (mat_int8_t *)data;
138✔
1049
            READ_DATA_SLAB2(ReadInt8Data);
930✔
1050
            break;
1051
        }
1052
        case MAT_C_UINT8: {
138✔
1053
            mat_uint8_t *ptr = (mat_uint8_t *)data;
138✔
1054
            READ_DATA_SLAB2(ReadUInt8Data);
930✔
1055
            break;
1056
        }
1057
        default:
1058
            err = MATIO_E_FILE_FORMAT_VIOLATION;
1059
            break;
1060
    }
1061
    return err;
1062
}
1063

1064
#undef READ_DATA_SLAB2
1065

1066
#if HAVE_ZLIB
1067
#define READ_COMPRESSED_DATA_SLAB1(ReadDataFunc)                             \
1068
    do {                                                                     \
1069
        if ( !stride ) {                                                     \
1070
            nBytes += ReadDataFunc(mat, &z_copy, ptr, data_type, edge);      \
1071
        } else {                                                             \
1072
            for ( i = 0; i < edge; i++ ) {                                   \
1073
                nBytes += ReadDataFunc(mat, &z_copy, ptr + i, data_type, 1); \
1074
                InflateSkipData(mat, &z_copy, data_type, stride);            \
1075
            }                                                                \
1076
        }                                                                    \
1077
    } while ( 0 )
1078

1079
/** @brief Reads data of type @c data_type by user-defined dimensions for 1-D
1080
 *         data
1081
 *
1082
 * @ingroup mat_internal
1083
 * @param mat MAT file pointer
1084
 * @param z zlib compression stream
1085
 * @param data Pointer to store the output data
1086
 * @param class_type Type of data class (matio_classes enumerations)
1087
 * @param data_type Datatype of the stored data (matio_types enumerations)
1088
 * @param start Index to start reading data in each dimension
1089
 * @param stride Read every @c stride elements in each dimension
1090
 * @param edge Number of elements to read in each dimension
1091
 * @retval Number of bytes read from the file, or -1 on error
1092
 */
1093
int
1094
ReadCompressedDataSlab1(mat_t *mat, z_streamp z, void *data, enum matio_classes class_type,
60✔
1095
                        enum matio_types data_type, int start, int stride, int edge)
1096
{
1097
    int nBytes = 0, i, err;
60✔
1098
    z_stream z_copy = {
60✔
1099
        0,
1100
    };
1101

1102
    if ( (mat == NULL) || (data == NULL) || (mat->fp == NULL) )
60✔
1103
        return 0;
1104

1105
    stride--;
60✔
1106
    err = inflateCopy(&z_copy, z);
60✔
1107
    if ( err != Z_OK ) {
60✔
1108
        Mat_Critical("inflateCopy returned error %s", zError(err));
×
UNCOV
1109
        return -1;
×
1110
    }
1111
    InflateSkipData(mat, &z_copy, data_type, start);
60✔
1112
    switch ( class_type ) {
60✔
1113
        case MAT_C_DOUBLE: {
6✔
1114
            double *ptr = (double *)data;
6✔
1115
            READ_COMPRESSED_DATA_SLAB1(ReadCompressedDoubleData);
168✔
1116
            break;
1117
        }
1118
        case MAT_C_SINGLE: {
6✔
1119
            float *ptr = (float *)data;
6✔
1120
            READ_COMPRESSED_DATA_SLAB1(ReadCompressedSingleData);
168✔
1121
            break;
1122
        }
1123
#ifdef HAVE_MAT_INT64_T
1124
        case MAT_C_INT64: {
6✔
1125
            mat_int64_t *ptr = (mat_int64_t *)data;
6✔
1126
            READ_COMPRESSED_DATA_SLAB1(ReadCompressedInt64Data);
168✔
1127
            break;
1128
        }
1129
#endif /* HAVE_MAT_INT64_T */
1130
#ifdef HAVE_MAT_UINT64_T
1131
        case MAT_C_UINT64: {
6✔
1132
            mat_uint64_t *ptr = (mat_uint64_t *)data;
6✔
1133
            READ_COMPRESSED_DATA_SLAB1(ReadCompressedUInt64Data);
168✔
1134
            break;
1135
        }
1136
#endif /* HAVE_MAT_UINT64_T */
1137
        case MAT_C_INT32: {
6✔
1138
            mat_int32_t *ptr = (mat_int32_t *)data;
6✔
1139
            READ_COMPRESSED_DATA_SLAB1(ReadCompressedInt32Data);
168✔
1140
            break;
1141
        }
1142
        case MAT_C_UINT32: {
6✔
1143
            mat_uint32_t *ptr = (mat_uint32_t *)data;
6✔
1144
            READ_COMPRESSED_DATA_SLAB1(ReadCompressedUInt32Data);
168✔
1145
            break;
1146
        }
1147
        case MAT_C_INT16: {
6✔
1148
            mat_int16_t *ptr = (mat_int16_t *)data;
6✔
1149
            READ_COMPRESSED_DATA_SLAB1(ReadCompressedInt16Data);
168✔
1150
            break;
1151
        }
1152
        case MAT_C_UINT16: {
6✔
1153
            mat_uint16_t *ptr = (mat_uint16_t *)data;
6✔
1154
            READ_COMPRESSED_DATA_SLAB1(ReadCompressedUInt16Data);
168✔
1155
            break;
1156
        }
1157
        case MAT_C_INT8: {
6✔
1158
            mat_int8_t *ptr = (mat_int8_t *)data;
6✔
1159
            READ_COMPRESSED_DATA_SLAB1(ReadCompressedInt8Data);
168✔
1160
            break;
1161
        }
1162
        case MAT_C_UINT8: {
6✔
1163
            mat_uint8_t *ptr = (mat_uint8_t *)data;
6✔
1164
            READ_COMPRESSED_DATA_SLAB1(ReadCompressedUInt8Data);
168✔
1165
            break;
1166
        }
1167
        default:
1168
            break;
1169
    }
1170
    inflateEnd(&z_copy);
60✔
1171
    return nBytes;
60✔
1172
}
1173

1174
#undef READ_COMPRESSED_DATA_SLAB1
1175

1176
#define READ_COMPRESSED_DATA_SLAB2(ReadDataFunc)                                                  \
1177
    do {                                                                                          \
1178
        row_stride = (stride[0] - 1);                                                             \
1179
        col_stride = (stride[1] - 1) * dims[0];                                                   \
1180
        InflateSkipData(mat, &z_copy, data_type, start[1] * dims[0]);                             \
1181
        /* If stride[0] is 1 and stride[1] is 1, we are reading all of the */                     \
1182
        /* data so get rid of the loops.  If stride[0] is 1 and stride[1] */                      \
1183
        /* is not 0, we are reading whole columns, so get rid of inner loop */                    \
1184
        /* to speed up the code */                                                                \
1185
        if ( (stride[0] == 1 && (size_t)edge[0] == dims[0]) && (stride[1] == 1) ) {               \
1186
            ReadDataFunc(mat, &z_copy, ptr, data_type, (ptrdiff_t)edge[0] * edge[1]);             \
1187
        } else if ( stride[0] == 1 ) {                                                            \
1188
            for ( i = 0; i < edge[1]; i++ ) {                                                     \
1189
                InflateSkipData(mat, &z_copy, data_type, start[0]);                               \
1190
                ReadDataFunc(mat, &z_copy, ptr, data_type, edge[0]);                              \
1191
                ptr += edge[0];                                                                   \
1192
                pos = dims[0] - (ptrdiff_t)(edge[0] - 1) * stride[0] - 1 - start[0] + col_stride; \
1193
                InflateSkipData(mat, &z_copy, data_type, pos);                                    \
1194
            }                                                                                     \
1195
        } else {                                                                                  \
1196
            for ( i = 0; i < edge[1]; i++ ) {                                                     \
1197
                InflateSkipData(mat, &z_copy, data_type, start[0]);                               \
1198
                for ( j = 0; j < edge[0] - 1; j++ ) {                                             \
1199
                    ReadDataFunc(mat, &z_copy, ptr++, data_type, 1);                              \
1200
                    InflateSkipData(mat, &z_copy, data_type, row_stride);                         \
1201
                }                                                                                 \
1202
                ReadDataFunc(mat, &z_copy, ptr++, data_type, 1);                                  \
1203
                pos = dims[0] - (ptrdiff_t)(edge[0] - 1) * stride[0] - 1 - start[0] + col_stride; \
1204
                InflateSkipData(mat, &z_copy, data_type, pos);                                    \
1205
            }                                                                                     \
1206
        }                                                                                         \
1207
    } while ( 0 )
1208

1209
/** @brief Reads data of type @c data_type by user-defined dimensions for 2-D
1210
 *         data
1211
 *
1212
 * @ingroup mat_internal
1213
 * @param mat MAT file pointer
1214
 * @param z zlib compression stream
1215
 * @param data Pointer to store the output data
1216
 * @param class_type Type of data class (matio_classes enumerations)
1217
 * @param data_type Datatype of the stored data (matio_types enumerations)
1218
 * @param dims Dimensions of the data
1219
 * @param start Index to start reading data in each dimension
1220
 * @param stride Read every @c stride elements in each dimension
1221
 * @param edge Number of elements to read in each dimension
1222
 * @retval Number of bytes read from the file, or -1 on error
1223
 */
1224
int
1225
ReadCompressedDataSlab2(mat_t *mat, z_streamp z, void *data, enum matio_classes class_type,
660✔
1226
                        enum matio_types data_type, const size_t *dims, const int *start,
1227
                        const int *stride, const int *edge)
1228
{
1229
    int nBytes = 0, i, j, err;
660✔
1230
    int pos, row_stride, col_stride;
660✔
1231
    z_stream z_copy = {
660✔
1232
        0,
1233
    };
1234

1235
    if ( (mat == NULL) || (data == NULL) || (mat->fp == NULL) || (start == NULL) ||
660✔
1236
         (stride == NULL) || (edge == NULL) ) {
660✔
1237
        return 0;
1238
    }
1239

1240
    err = inflateCopy(&z_copy, z);
660✔
1241
    if ( err != Z_OK ) {
660✔
1242
        Mat_Critical("inflateCopy returned error %s", zError(err));
×
UNCOV
1243
        return -1;
×
1244
    }
1245
    switch ( class_type ) {
660✔
1246
        case MAT_C_DOUBLE: {
66✔
1247
            double *ptr = (double *)data;
66✔
1248
            READ_COMPRESSED_DATA_SLAB2(ReadCompressedDoubleData);
486✔
1249
            break;
1250
        }
1251
        case MAT_C_SINGLE: {
66✔
1252
            float *ptr = (float *)data;
66✔
1253
            READ_COMPRESSED_DATA_SLAB2(ReadCompressedSingleData);
486✔
1254
            break;
1255
        }
1256
#ifdef HAVE_MAT_INT64_T
1257
        case MAT_C_INT64: {
66✔
1258
            mat_int64_t *ptr = (mat_int64_t *)data;
66✔
1259
            READ_COMPRESSED_DATA_SLAB2(ReadCompressedInt64Data);
486✔
1260
            break;
1261
        }
1262
#endif /* HAVE_MAT_INT64_T */
1263
#ifdef HAVE_MAT_UINT64_T
1264
        case MAT_C_UINT64: {
66✔
1265
            mat_uint64_t *ptr = (mat_uint64_t *)data;
66✔
1266
            READ_COMPRESSED_DATA_SLAB2(ReadCompressedUInt64Data);
486✔
1267
            break;
1268
        }
1269
#endif /* HAVE_MAT_UINT64_T */
1270
        case MAT_C_INT32: {
66✔
1271
            mat_int32_t *ptr = (mat_int32_t *)data;
66✔
1272
            READ_COMPRESSED_DATA_SLAB2(ReadCompressedInt32Data);
486✔
1273
            break;
1274
        }
1275
        case MAT_C_UINT32: {
66✔
1276
            mat_uint32_t *ptr = (mat_uint32_t *)data;
66✔
1277
            READ_COMPRESSED_DATA_SLAB2(ReadCompressedUInt32Data);
486✔
1278
            break;
1279
        }
1280
        case MAT_C_INT16: {
66✔
1281
            mat_int16_t *ptr = (mat_int16_t *)data;
66✔
1282
            READ_COMPRESSED_DATA_SLAB2(ReadCompressedInt16Data);
486✔
1283
            break;
1284
        }
1285
        case MAT_C_UINT16: {
66✔
1286
            mat_uint16_t *ptr = (mat_uint16_t *)data;
66✔
1287
            READ_COMPRESSED_DATA_SLAB2(ReadCompressedUInt16Data);
486✔
1288
            break;
1289
        }
1290
        case MAT_C_INT8: {
66✔
1291
            mat_int8_t *ptr = (mat_int8_t *)data;
66✔
1292
            READ_COMPRESSED_DATA_SLAB2(ReadCompressedInt8Data);
486✔
1293
            break;
1294
        }
1295
        case MAT_C_UINT8: {
66✔
1296
            mat_uint8_t *ptr = (mat_uint8_t *)data;
66✔
1297
            READ_COMPRESSED_DATA_SLAB2(ReadCompressedUInt8Data);
486✔
1298
            break;
1299
        }
1300
        default:
1301
            nBytes = 0;
1302
    }
1303
    inflateEnd(&z_copy);
660✔
1304
    return nBytes;
660✔
1305
}
1306

1307
#undef READ_COMPRESSED_DATA_SLAB2
1308
#endif
1309

1310
/** @endcond */
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc