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

tbeu / matio / #1029

11 Apr 2026 08:31AM UTC coverage: 83.341% (+0.002%) from 83.339%
#1029

push

travis-ci

tbeu
Add support for MCOS

As reported by https://github.com/tbeu/matio/issues/47, https://github.com/tbeu/matio/issues/77, https://github.com/tbeu/matio/issues/148, https://github.com/tbeu/matio/issues/263, https://github.com/tbeu/matio/issues/270, https://github.com/tbeu/matio/issues/272

1725 of 2235 new or added lines in 7 files covered. (77.18%)

1697 existing lines in 12 files now uncovered.

13017 of 15619 relevant lines covered (83.34%)

53651.79 hits per line

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

97.15
/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 <math.h>
22
#include <time.h>
23

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

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

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

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

207
#endif
208

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

215
/** @cond mat_devman */
216

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

381
    return err;
382
}
383
#endif
384

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

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

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

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

418
#undef READ_DATA
419
#undef READ_DATA_NOSWAP
420

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

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

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

508
/** @brief Reads data of type @c data_type by user-defined dimensions
509
 *
510
 * @ingroup mat_internal
511
 * @param mat MAT file pointer
512
 * @param data Pointer to store the output data
513
 * @param class_type Type of data class (matio_classes enumerations)
514
 * @param data_type Datatype of the stored data (matio_types enumerations)
515
 * @param rank Number of dimensions in the data
516
 * @param dims Dimensions of the data
517
 * @param start Index to start reading data in each dimension
518
 * @param stride Read every @c stride elements in each dimension
519
 * @param edge Number of elements to read in each dimension
520
 * @retval Number of bytes read from the file, or -1 on error
521
 */
522
int
523
ReadDataSlabN(mat_t *mat, void *data, enum matio_classes class_type, enum matio_types data_type,
1,380✔
524
              int rank, const size_t *dims, const int *start, const int *stride, const int *edge)
525
{
526
    int err;
1,380✔
527
    int i, j, N, I = 0;
1,380✔
528
    int inc[10] =
1,380✔
529
        {
530
            0,
531
        },
532
        cnt[10] =
1,380✔
533
            {
534
                0,
535
            },
536
        dimp[10] = {
1,380✔
537
            0,
538
        };
539
    size_t data_size;
1,380✔
540

541
    if ( (mat == NULL) || (data == NULL) || (mat->fp == NULL) || (start == NULL) ||
1,380✔
542
         (stride == NULL) || (edge == NULL) ) {
1,380✔
543
        return MATIO_E_BAD_ARGUMENT;
544
    } else if ( rank > 10 ) {
1,380✔
545
        return MATIO_E_BAD_ARGUMENT;
546
    }
547

548
    data_size = Mat_SizeOf(data_type);
1,380✔
549

550
    switch ( class_type ) {
1,380✔
551
        case MAT_C_DOUBLE: {
138✔
552
            double *ptr = (double *)data;
138✔
553
            READ_DATA_SLABN(ReadDoubleData);
2,772✔
554
            break;
555
        }
556
        case MAT_C_SINGLE: {
138✔
557
            float *ptr = (float *)data;
138✔
558
            READ_DATA_SLABN(ReadSingleData);
2,772✔
559
            break;
560
        }
561
#ifdef HAVE_MAT_INT64_T
562
        case MAT_C_INT64: {
138✔
563
            mat_int64_t *ptr = (mat_int64_t *)data;
138✔
564
            READ_DATA_SLABN(ReadInt64Data);
2,772✔
565
            break;
566
        }
567
#endif /* HAVE_MAT_INT64_T */
568
#ifdef HAVE_MAT_UINT64_T
569
        case MAT_C_UINT64: {
138✔
570
            mat_uint64_t *ptr = (mat_uint64_t *)data;
138✔
571
            READ_DATA_SLABN(ReadUInt64Data);
2,772✔
572
            break;
573
        }
574
#endif /* HAVE_MAT_UINT64_T */
575
        case MAT_C_INT32: {
138✔
576
            mat_int32_t *ptr = (mat_int32_t *)data;
138✔
577
            READ_DATA_SLABN(ReadInt32Data);
2,772✔
578
            break;
579
        }
580
        case MAT_C_UINT32: {
138✔
581
            mat_uint32_t *ptr = (mat_uint32_t *)data;
138✔
582
            READ_DATA_SLABN(ReadUInt32Data);
2,772✔
583
            break;
584
        }
585
        case MAT_C_INT16: {
138✔
586
            mat_int16_t *ptr = (mat_int16_t *)data;
138✔
587
            READ_DATA_SLABN(ReadInt16Data);
2,772✔
588
            break;
589
        }
590
        case MAT_C_UINT16: {
138✔
591
            mat_uint16_t *ptr = (mat_uint16_t *)data;
138✔
592
            READ_DATA_SLABN(ReadUInt16Data);
2,772✔
593
            break;
594
        }
595
        case MAT_C_INT8: {
138✔
596
            mat_int8_t *ptr = (mat_int8_t *)data;
138✔
597
            READ_DATA_SLABN(ReadInt8Data);
2,772✔
598
            break;
599
        }
600
        case MAT_C_UINT8: {
138✔
601
            mat_uint8_t *ptr = (mat_uint8_t *)data;
138✔
602
            READ_DATA_SLABN(ReadUInt8Data);
2,772✔
603
            break;
604
        }
605
        default:
606
            err = MATIO_E_FILE_FORMAT_VIOLATION;
607
            break;
608
    }
609
    return err;
610
}
611

612
#undef READ_DATA_SLABN
613
#undef READ_DATA_SLABN_RANK_LOOP
614

615
#if HAVE_ZLIB
616
#define READ_COMPRESSED_DATA_SLABN_RANK_LOOP                                           \
617
    do {                                                                               \
618
        for ( j = 1; j < rank; j++ ) {                                                 \
619
            cnt[j]++;                                                                  \
620
            if ( (cnt[j] % edge[j]) == 0 ) {                                           \
621
                cnt[j] = 0;                                                            \
622
                if ( (I % dimp[j]) != 0 ) {                                            \
623
                    InflateSkipData(mat, &z_copy, data_type,                           \
624
                                    dimp[j] - (I % dimp[j]) + dimp[j - 1] * start[j]); \
625
                    I += dimp[j] - (I % dimp[j]) + (ptrdiff_t)dimp[j - 1] * start[j];  \
626
                } else if ( start[j] ) {                                               \
627
                    InflateSkipData(mat, &z_copy, data_type, dimp[j - 1] * start[j]);  \
628
                    I += (ptrdiff_t)dimp[j - 1] * start[j];                            \
629
                }                                                                      \
630
            } else {                                                                   \
631
                if ( inc[j] ) {                                                        \
632
                    I += inc[j];                                                       \
633
                    InflateSkipData(mat, &z_copy, data_type, inc[j]);                  \
634
                }                                                                      \
635
                break;                                                                 \
636
            }                                                                          \
637
        }                                                                              \
638
    } while ( 0 )
639

640
#define READ_COMPRESSED_DATA_SLABN(ReadDataFunc)                                                \
641
    do {                                                                                        \
642
        inc[0] = stride[0] - 1;                                                                 \
643
        dimp[0] = dims[0];                                                                      \
644
        N = edge[0];                                                                            \
645
        I = 0;                                                                                  \
646
        for ( i = 1; i < rank; i++ ) {                                                          \
647
            inc[i] = stride[i] - 1;                                                             \
648
            dimp[i] = dims[i - 1];                                                              \
649
            for ( j = i; j--; ) {                                                               \
650
                inc[i] *= dims[j];                                                              \
651
                dimp[i] *= dims[j + 1];                                                         \
652
            }                                                                                   \
653
            N *= edge[i];                                                                       \
654
            I += (ptrdiff_t)dimp[i - 1] * start[i];                                             \
655
        }                                                                                       \
656
        /* Skip all data to the starting indices */                                             \
657
        InflateSkipData(mat, &z_copy, data_type, I);                                            \
658
        if ( stride[0] == 1 ) {                                                                 \
659
            for ( i = 0; i < N; i += edge[0] ) {                                                \
660
                if ( start[0] ) {                                                               \
661
                    InflateSkipData(mat, &z_copy, data_type, start[0]);                         \
662
                    I += start[0];                                                              \
663
                }                                                                               \
664
                ReadDataFunc(mat, &z_copy, ptr + i, data_type, edge[0]);                        \
665
                InflateSkipData(mat, &z_copy, data_type, dims[0] - start[0] - edge[0]);         \
666
                I += dims[0] - start[0];                                                        \
667
                READ_COMPRESSED_DATA_SLABN_RANK_LOOP;                                           \
668
            }                                                                                   \
669
        } else {                                                                                \
670
            for ( i = 0; i < N; i += edge[0] ) {                                                \
671
                if ( start[0] ) {                                                               \
672
                    InflateSkipData(mat, &z_copy, data_type, start[0]);                         \
673
                    I += start[0];                                                              \
674
                }                                                                               \
675
                for ( j = 0; j < edge[0] - 1; j++ ) {                                           \
676
                    ReadDataFunc(mat, &z_copy, ptr + i + j, data_type, 1);                      \
677
                    InflateSkipData(mat, &z_copy, data_type, (stride[0] - 1));                  \
678
                    I += stride[0];                                                             \
679
                }                                                                               \
680
                ReadDataFunc(mat, &z_copy, ptr + i + j, data_type, 1);                          \
681
                I += dims[0] - (ptrdiff_t)(edge[0] - 1) * stride[0] - start[0];                 \
682
                InflateSkipData(mat, &z_copy, data_type,                                        \
683
                                dims[0] - (ptrdiff_t)(edge[0] - 1) * stride[0] - start[0] - 1); \
684
                READ_COMPRESSED_DATA_SLABN_RANK_LOOP;                                           \
685
            }                                                                                   \
686
        }                                                                                       \
687
    } while ( 0 )
688

689
/** @brief Reads data of type @c data_type by user-defined dimensions
690
 *
691
 * @ingroup mat_internal
692
 * @param mat MAT file pointer
693
 * @param z zlib compression stream
694
 * @param data Pointer to store the output data
695
 * @param class_type Type of data class (matio_classes enumerations)
696
 * @param data_type Datatype of the stored data (matio_types enumerations)
697
 * @param rank Number of dimensions in the data
698
 * @param dims Dimensions of the data
699
 * @param start Index to start reading data in each dimension
700
 * @param stride Read every @c stride elements in each dimension
701
 * @param edge Number of elements to read in each dimension
702
 * @retval Number of bytes read from the file, or -1 on error
703
 */
704
int
705
ReadCompressedDataSlabN(mat_t *mat, z_streamp z, void *data, enum matio_classes class_type,
720✔
706
                        enum matio_types data_type, int rank, const size_t *dims, const int *start,
707
                        const int *stride, const int *edge)
708
{
709
    int nBytes = 0, i, j, N, I = 0, err;
720✔
710
    int inc[10] =
720✔
711
        {
712
            0,
713
        },
714
        cnt[10] =
720✔
715
            {
716
                0,
717
            },
718
        dimp[10] = {
720✔
719
            0,
720
        };
721
    z_stream z_copy = {
720✔
722
        0,
723
    };
724

725
    if ( (mat == NULL) || (data == NULL) || (mat->fp == NULL) || (start == NULL) ||
720✔
726
         (stride == NULL) || (edge == NULL) ) {
720✔
727
        return 0;
728
    } else if ( rank > 10 ) {
720✔
729
        return 0;
730
    }
731

732
    err = inflateCopy(&z_copy, z);
720✔
733
    if ( err != Z_OK ) {
720✔
UNCOV
734
        Mat_Critical("inflateCopy returned error %s", zError(err));
×
UNCOV
735
        return -1;
×
736
    }
737
    switch ( class_type ) {
720✔
738
        case MAT_C_DOUBLE: {
72✔
739
            double *ptr = (double *)data;
72✔
740
            READ_COMPRESSED_DATA_SLABN(ReadCompressedDoubleData);
1,656✔
741
            break;
742
        }
743
        case MAT_C_SINGLE: {
72✔
744
            float *ptr = (float *)data;
72✔
745
            READ_COMPRESSED_DATA_SLABN(ReadCompressedSingleData);
1,656✔
746
            break;
747
        }
748
#ifdef HAVE_MAT_INT64_T
749
        case MAT_C_INT64: {
72✔
750
            mat_int64_t *ptr = (mat_int64_t *)data;
72✔
751
            READ_COMPRESSED_DATA_SLABN(ReadCompressedInt64Data);
1,656✔
752
            break;
753
        }
754
#endif /* HAVE_MAT_INT64_T */
755
#ifdef HAVE_MAT_UINT64_T
756
        case MAT_C_UINT64: {
72✔
757
            mat_uint64_t *ptr = (mat_uint64_t *)data;
72✔
758
            READ_COMPRESSED_DATA_SLABN(ReadCompressedUInt64Data);
1,656✔
759
            break;
760
        }
761
#endif /* HAVE_MAT_UINT64_T */
762
        case MAT_C_INT32: {
72✔
763
            mat_int32_t *ptr = (mat_int32_t *)data;
72✔
764
            READ_COMPRESSED_DATA_SLABN(ReadCompressedInt32Data);
1,656✔
765
            break;
766
        }
767
        case MAT_C_UINT32: {
72✔
768
            mat_uint32_t *ptr = (mat_uint32_t *)data;
72✔
769
            READ_COMPRESSED_DATA_SLABN(ReadCompressedUInt32Data);
1,656✔
770
            break;
771
        }
772
        case MAT_C_INT16: {
72✔
773
            mat_int16_t *ptr = (mat_int16_t *)data;
72✔
774
            READ_COMPRESSED_DATA_SLABN(ReadCompressedInt16Data);
1,656✔
775
            break;
776
        }
777
        case MAT_C_UINT16: {
72✔
778
            mat_uint16_t *ptr = (mat_uint16_t *)data;
72✔
779
            READ_COMPRESSED_DATA_SLABN(ReadCompressedUInt16Data);
1,656✔
780
            break;
781
        }
782
        case MAT_C_INT8: {
72✔
783
            mat_int8_t *ptr = (mat_int8_t *)data;
72✔
784
            READ_COMPRESSED_DATA_SLABN(ReadCompressedInt8Data);
1,656✔
785
            break;
786
        }
787
        case MAT_C_UINT8: {
72✔
788
            mat_uint8_t *ptr = (mat_uint8_t *)data;
72✔
789
            READ_COMPRESSED_DATA_SLABN(ReadCompressedUInt8Data);
1,656✔
790
            break;
791
        }
792
        default:
793
            nBytes = 0;
794
    }
795
    inflateEnd(&z_copy);
720✔
796
    return nBytes;
720✔
797
}
798

799
#undef READ_COMPRESSED_DATA_SLABN
800
#undef READ_COMPRESSED_DATA_SLABN_RANK_LOOP
801
#endif
802

803
#define READ_DATA_SLAB1(ReadDataFunc)                            \
804
    do {                                                         \
805
        if ( !stride ) {                                         \
806
            err = ReadDataFunc(mat, ptr, data_type, edge);       \
807
        } else {                                                 \
808
            for ( i = 0; i < edge; i++ ) {                       \
809
                err = ReadDataFunc(mat, ptr + i, data_type, 1);  \
810
                if ( err ) {                                     \
811
                    break;                                       \
812
                }                                                \
813
                (void)fseeko((FILE *)mat->fp, stride, SEEK_CUR); \
814
            }                                                    \
815
        }                                                        \
816
    } while ( 0 )
817

818
/** @brief Reads data of type @c data_type by user-defined dimensions for 1-D
819
 *         data
820
 *
821
 * @ingroup mat_internal
822
 * @param mat MAT file pointer
823
 * @param data Pointer to store the output data
824
 * @param class_type Type of data class (matio_classes enumerations)
825
 * @param data_type Datatype of the stored data (matio_types enumerations)
826
 * @param start Index to start reading data
827
 * @param stride Read every @c stride elements
828
 * @param edge Number of elements to read
829
 * @retval 0 on success
830
 */
831
int
832
ReadDataSlab1(mat_t *mat, void *data, enum matio_classes class_type, enum matio_types data_type,
126✔
833
              int start, int stride, int edge)
834
{
835
    int err, i;
126✔
836
    size_t data_size;
126✔
837

838
    data_size = Mat_SizeOf(data_type);
126✔
839
    (void)fseek((FILE *)mat->fp, start * data_size, SEEK_CUR);
126✔
840
    stride = data_size * (stride - 1);
126✔
841

842
    switch ( class_type ) {
126✔
843
        case MAT_C_DOUBLE: {
18✔
844
            double *ptr = (double *)data;
18✔
845
            READ_DATA_SLAB1(ReadDoubleData);
258✔
846
            break;
847
        }
848
        case MAT_C_SINGLE: {
12✔
849
            float *ptr = (float *)data;
12✔
850
            READ_DATA_SLAB1(ReadSingleData);
204✔
851
            break;
852
        }
853
#ifdef HAVE_MAT_INT64_T
854
        case MAT_C_INT64: {
12✔
855
            mat_int64_t *ptr = (mat_int64_t *)data;
12✔
856
            READ_DATA_SLAB1(ReadInt64Data);
204✔
857
            break;
858
        }
859
#endif /* HAVE_MAT_INT64_T */
860
#ifdef HAVE_MAT_UINT64_T
861
        case MAT_C_UINT64: {
12✔
862
            mat_uint64_t *ptr = (mat_uint64_t *)data;
12✔
863
            READ_DATA_SLAB1(ReadUInt64Data);
204✔
864
            break;
865
        }
866
#endif /* HAVE_MAT_UINT64_T */
867
        case MAT_C_INT32: {
12✔
868
            mat_int32_t *ptr = (mat_int32_t *)data;
12✔
869
            READ_DATA_SLAB1(ReadInt32Data);
204✔
870
            break;
871
        }
872
        case MAT_C_UINT32: {
12✔
873
            mat_uint32_t *ptr = (mat_uint32_t *)data;
12✔
874
            READ_DATA_SLAB1(ReadUInt32Data);
204✔
875
            break;
876
        }
877
        case MAT_C_INT16: {
12✔
878
            mat_int16_t *ptr = (mat_int16_t *)data;
12✔
879
            READ_DATA_SLAB1(ReadInt16Data);
204✔
880
            break;
881
        }
882
        case MAT_C_UINT16: {
12✔
883
            mat_uint16_t *ptr = (mat_uint16_t *)data;
12✔
884
            READ_DATA_SLAB1(ReadUInt16Data);
204✔
885
            break;
886
        }
887
        case MAT_C_INT8: {
12✔
888
            mat_int8_t *ptr = (mat_int8_t *)data;
12✔
889
            READ_DATA_SLAB1(ReadInt8Data);
204✔
890
            break;
891
        }
892
        case MAT_C_UINT8: {
12✔
893
            mat_uint8_t *ptr = (mat_uint8_t *)data;
12✔
894
            READ_DATA_SLAB1(ReadUInt8Data);
204✔
895
            break;
896
        }
897
        default:
898
            err = MATIO_E_FILE_FORMAT_VIOLATION;
899
            break;
900
    }
901

902
    return err;
126✔
903
}
904

905
#undef READ_DATA_SLAB1
906

907
#define READ_DATA_SLAB2(ReadDataFunc)                                                \
908
    do {                                                                             \
909
        /* If stride[0] is 1 and stride[1] is 1, we are reading all of the */        \
910
        /* data so get rid of the loops. */                                          \
911
        if ( (stride[0] == 1 && (size_t)edge[0] == dims[0]) && (stride[1] == 1) ) {  \
912
            err = ReadDataFunc(mat, ptr, data_type, (ptrdiff_t)edge[0] * edge[1]);   \
913
        } else {                                                                     \
914
            row_stride = (stride[0] - 1) * data_size;                                \
915
            col_stride = stride[1] * dims[0] * data_size;                            \
916
            pos = ftello((FILE *)mat->fp);                                           \
917
            if ( pos == -1L ) {                                                      \
918
                Mat_Critical("Couldn't determine file position");                    \
919
                return MATIO_E_GENERIC_READ_ERROR;                                   \
920
            }                                                                        \
921
            (void)fseeko((FILE *)mat->fp, start[1] * dims[0] * data_size, SEEK_CUR); \
922
            for ( i = 0; i < edge[1]; i++ ) {                                        \
923
                pos = ftello((FILE *)mat->fp);                                       \
924
                if ( pos == -1L ) {                                                  \
925
                    Mat_Critical("Couldn't determine file position");                \
926
                    return MATIO_E_GENERIC_READ_ERROR;                               \
927
                }                                                                    \
928
                (void)fseeko((FILE *)mat->fp, start[0] * data_size, SEEK_CUR);       \
929
                for ( j = 0; j < edge[0]; j++ ) {                                    \
930
                    err = ReadDataFunc(mat, ptr++, data_type, 1);                    \
931
                    if ( err ) {                                                     \
932
                        return err;                                                  \
933
                    }                                                                \
934
                    (void)fseeko((FILE *)mat->fp, row_stride, SEEK_CUR);             \
935
                }                                                                    \
936
                pos2 = ftello((FILE *)mat->fp);                                      \
937
                if ( pos2 == -1L ) {                                                 \
938
                    Mat_Critical("Couldn't determine file position");                \
939
                    return MATIO_E_GENERIC_READ_ERROR;                               \
940
                }                                                                    \
941
                pos += col_stride - pos2;                                            \
942
                (void)fseeko((FILE *)mat->fp, pos, SEEK_CUR);                        \
943
            }                                                                        \
944
        }                                                                            \
945
    } while ( 0 )
946

947
/** @brief Reads data of type @c data_type by user-defined dimensions for 2-D
948
 *         data
949
 *
950
 * @ingroup mat_internal
951
 * @param mat MAT file pointer
952
 * @param data Pointer to store the output data
953
 * @param class_type Type of data class (matio_classes enumerations)
954
 * @param data_type Datatype of the stored data (matio_types enumerations)
955
 * @param dims Dimensions of the data
956
 * @param start Index to start reading data in each dimension
957
 * @param stride Read every @c stride elements in each dimension
958
 * @param edge Number of elements to read in each dimension
959
 * @retval 0 on success
960
 */
961
int
962
ReadDataSlab2(mat_t *mat, void *data, enum matio_classes class_type, enum matio_types data_type,
1,386✔
963
              const size_t *dims, const int *start, const int *stride, const int *edge)
964
{
965
    int err;
1,386✔
966
    int data_size, i, j;
1,386✔
967
    mat_off_t pos, row_stride, col_stride, pos2;
1,386✔
968

969
    if ( (mat == NULL) || (data == NULL) || (mat->fp == NULL) || (start == NULL) ||
1,386✔
970
         (stride == NULL) || (edge == NULL) ) {
1,386✔
971
        return MATIO_E_BAD_ARGUMENT;
972
    }
973

974
    data_size = Mat_SizeOf(data_type);
1,386✔
975

976
    switch ( class_type ) {
1,386✔
977
        case MAT_C_DOUBLE: {
144✔
978
            double *ptr = (double *)data;
144✔
979
            READ_DATA_SLAB2(ReadDoubleData);
936✔
980
            break;
981
        }
982
        case MAT_C_SINGLE: {
138✔
983
            float *ptr = (float *)data;
138✔
984
            READ_DATA_SLAB2(ReadSingleData);
930✔
985
            break;
986
        }
987
#ifdef HAVE_MAT_INT64_T
988
        case MAT_C_INT64: {
138✔
989
            mat_int64_t *ptr = (mat_int64_t *)data;
138✔
990
            READ_DATA_SLAB2(ReadInt64Data);
930✔
991
            break;
992
        }
993
#endif /* HAVE_MAT_INT64_T */
994
#ifdef HAVE_MAT_UINT64_T
995
        case MAT_C_UINT64: {
138✔
996
            mat_uint64_t *ptr = (mat_uint64_t *)data;
138✔
997
            READ_DATA_SLAB2(ReadUInt64Data);
930✔
998
            break;
999
        }
1000
#endif /* HAVE_MAT_UINT64_T */
1001
        case MAT_C_INT32: {
138✔
1002
            mat_int32_t *ptr = (mat_int32_t *)data;
138✔
1003
            READ_DATA_SLAB2(ReadInt32Data);
930✔
1004
            break;
1005
        }
1006
        case MAT_C_UINT32: {
138✔
1007
            mat_uint32_t *ptr = (mat_uint32_t *)data;
138✔
1008
            READ_DATA_SLAB2(ReadUInt32Data);
930✔
1009
            break;
1010
        }
1011
        case MAT_C_INT16: {
138✔
1012
            mat_int16_t *ptr = (mat_int16_t *)data;
138✔
1013
            READ_DATA_SLAB2(ReadInt16Data);
930✔
1014
            break;
1015
        }
1016
        case MAT_C_UINT16: {
138✔
1017
            mat_uint16_t *ptr = (mat_uint16_t *)data;
138✔
1018
            READ_DATA_SLAB2(ReadUInt16Data);
930✔
1019
            break;
1020
        }
1021
        case MAT_C_INT8: {
138✔
1022
            mat_int8_t *ptr = (mat_int8_t *)data;
138✔
1023
            READ_DATA_SLAB2(ReadInt8Data);
930✔
1024
            break;
1025
        }
1026
        case MAT_C_UINT8: {
138✔
1027
            mat_uint8_t *ptr = (mat_uint8_t *)data;
138✔
1028
            READ_DATA_SLAB2(ReadUInt8Data);
930✔
1029
            break;
1030
        }
1031
        default:
1032
            err = MATIO_E_FILE_FORMAT_VIOLATION;
1033
            break;
1034
    }
1035
    return err;
1036
}
1037

1038
#undef READ_DATA_SLAB2
1039

1040
#if HAVE_ZLIB
1041
#define READ_COMPRESSED_DATA_SLAB1(ReadDataFunc)                             \
1042
    do {                                                                     \
1043
        if ( !stride ) {                                                     \
1044
            nBytes += ReadDataFunc(mat, &z_copy, ptr, data_type, edge);      \
1045
        } else {                                                             \
1046
            for ( i = 0; i < edge; i++ ) {                                   \
1047
                nBytes += ReadDataFunc(mat, &z_copy, ptr + i, data_type, 1); \
1048
                InflateSkipData(mat, &z_copy, data_type, stride);            \
1049
            }                                                                \
1050
        }                                                                    \
1051
    } while ( 0 )
1052

1053
/** @brief Reads data of type @c data_type by user-defined dimensions for 1-D
1054
 *         data
1055
 *
1056
 * @ingroup mat_internal
1057
 * @param mat MAT file pointer
1058
 * @param z zlib compression stream
1059
 * @param data Pointer to store the output data
1060
 * @param class_type Type of data class (matio_classes enumerations)
1061
 * @param data_type Datatype of the stored data (matio_types enumerations)
1062
 * @param start Index to start reading data in each dimension
1063
 * @param stride Read every @c stride elements in each dimension
1064
 * @param edge Number of elements to read in each dimension
1065
 * @retval Number of bytes read from the file, or -1 on error
1066
 */
1067
int
1068
ReadCompressedDataSlab1(mat_t *mat, z_streamp z, void *data, enum matio_classes class_type,
60✔
1069
                        enum matio_types data_type, int start, int stride, int edge)
1070
{
1071
    int nBytes = 0, i, err;
60✔
1072
    z_stream z_copy = {
60✔
1073
        0,
1074
    };
1075

1076
    if ( (mat == NULL) || (data == NULL) || (mat->fp == NULL) )
60✔
1077
        return 0;
1078

1079
    stride--;
60✔
1080
    err = inflateCopy(&z_copy, z);
60✔
1081
    if ( err != Z_OK ) {
60✔
UNCOV
1082
        Mat_Critical("inflateCopy returned error %s", zError(err));
×
UNCOV
1083
        return -1;
×
1084
    }
1085
    InflateSkipData(mat, &z_copy, data_type, start);
60✔
1086
    switch ( class_type ) {
60✔
1087
        case MAT_C_DOUBLE: {
6✔
1088
            double *ptr = (double *)data;
6✔
1089
            READ_COMPRESSED_DATA_SLAB1(ReadCompressedDoubleData);
168✔
1090
            break;
1091
        }
1092
        case MAT_C_SINGLE: {
6✔
1093
            float *ptr = (float *)data;
6✔
1094
            READ_COMPRESSED_DATA_SLAB1(ReadCompressedSingleData);
168✔
1095
            break;
1096
        }
1097
#ifdef HAVE_MAT_INT64_T
1098
        case MAT_C_INT64: {
6✔
1099
            mat_int64_t *ptr = (mat_int64_t *)data;
6✔
1100
            READ_COMPRESSED_DATA_SLAB1(ReadCompressedInt64Data);
168✔
1101
            break;
1102
        }
1103
#endif /* HAVE_MAT_INT64_T */
1104
#ifdef HAVE_MAT_UINT64_T
1105
        case MAT_C_UINT64: {
6✔
1106
            mat_uint64_t *ptr = (mat_uint64_t *)data;
6✔
1107
            READ_COMPRESSED_DATA_SLAB1(ReadCompressedUInt64Data);
168✔
1108
            break;
1109
        }
1110
#endif /* HAVE_MAT_UINT64_T */
1111
        case MAT_C_INT32: {
6✔
1112
            mat_int32_t *ptr = (mat_int32_t *)data;
6✔
1113
            READ_COMPRESSED_DATA_SLAB1(ReadCompressedInt32Data);
168✔
1114
            break;
1115
        }
1116
        case MAT_C_UINT32: {
6✔
1117
            mat_uint32_t *ptr = (mat_uint32_t *)data;
6✔
1118
            READ_COMPRESSED_DATA_SLAB1(ReadCompressedUInt32Data);
168✔
1119
            break;
1120
        }
1121
        case MAT_C_INT16: {
6✔
1122
            mat_int16_t *ptr = (mat_int16_t *)data;
6✔
1123
            READ_COMPRESSED_DATA_SLAB1(ReadCompressedInt16Data);
168✔
1124
            break;
1125
        }
1126
        case MAT_C_UINT16: {
6✔
1127
            mat_uint16_t *ptr = (mat_uint16_t *)data;
6✔
1128
            READ_COMPRESSED_DATA_SLAB1(ReadCompressedUInt16Data);
168✔
1129
            break;
1130
        }
1131
        case MAT_C_INT8: {
6✔
1132
            mat_int8_t *ptr = (mat_int8_t *)data;
6✔
1133
            READ_COMPRESSED_DATA_SLAB1(ReadCompressedInt8Data);
168✔
1134
            break;
1135
        }
1136
        case MAT_C_UINT8: {
6✔
1137
            mat_uint8_t *ptr = (mat_uint8_t *)data;
6✔
1138
            READ_COMPRESSED_DATA_SLAB1(ReadCompressedUInt8Data);
168✔
1139
            break;
1140
        }
1141
        default:
1142
            break;
1143
    }
1144
    inflateEnd(&z_copy);
60✔
1145
    return nBytes;
60✔
1146
}
1147

1148
#undef READ_COMPRESSED_DATA_SLAB1
1149

1150
#define READ_COMPRESSED_DATA_SLAB2(ReadDataFunc)                                                  \
1151
    do {                                                                                          \
1152
        row_stride = (stride[0] - 1);                                                             \
1153
        col_stride = (stride[1] - 1) * dims[0];                                                   \
1154
        InflateSkipData(mat, &z_copy, data_type, start[1] * dims[0]);                             \
1155
        /* If stride[0] is 1 and stride[1] is 1, we are reading all of the */                     \
1156
        /* data so get rid of the loops.  If stride[0] is 1 and stride[1] */                      \
1157
        /* is not 0, we are reading whole columns, so get rid of inner loop */                    \
1158
        /* to speed up the code */                                                                \
1159
        if ( (stride[0] == 1 && (size_t)edge[0] == dims[0]) && (stride[1] == 1) ) {               \
1160
            ReadDataFunc(mat, &z_copy, ptr, data_type, (ptrdiff_t)edge[0] * edge[1]);             \
1161
        } else if ( stride[0] == 1 ) {                                                            \
1162
            for ( i = 0; i < edge[1]; i++ ) {                                                     \
1163
                InflateSkipData(mat, &z_copy, data_type, start[0]);                               \
1164
                ReadDataFunc(mat, &z_copy, ptr, data_type, edge[0]);                              \
1165
                ptr += edge[0];                                                                   \
1166
                pos = dims[0] - (ptrdiff_t)(edge[0] - 1) * stride[0] - 1 - start[0] + col_stride; \
1167
                InflateSkipData(mat, &z_copy, data_type, pos);                                    \
1168
            }                                                                                     \
1169
        } else {                                                                                  \
1170
            for ( i = 0; i < edge[1]; i++ ) {                                                     \
1171
                InflateSkipData(mat, &z_copy, data_type, start[0]);                               \
1172
                for ( j = 0; j < edge[0] - 1; j++ ) {                                             \
1173
                    ReadDataFunc(mat, &z_copy, ptr++, data_type, 1);                              \
1174
                    InflateSkipData(mat, &z_copy, data_type, row_stride);                         \
1175
                }                                                                                 \
1176
                ReadDataFunc(mat, &z_copy, ptr++, data_type, 1);                                  \
1177
                pos = dims[0] - (ptrdiff_t)(edge[0] - 1) * stride[0] - 1 - start[0] + col_stride; \
1178
                InflateSkipData(mat, &z_copy, data_type, pos);                                    \
1179
            }                                                                                     \
1180
        }                                                                                         \
1181
    } while ( 0 )
1182

1183
/** @brief Reads data of type @c data_type by user-defined dimensions for 2-D
1184
 *         data
1185
 *
1186
 * @ingroup mat_internal
1187
 * @param mat MAT file pointer
1188
 * @param z zlib compression stream
1189
 * @param data Pointer to store the output data
1190
 * @param class_type Type of data class (matio_classes enumerations)
1191
 * @param data_type Datatype of the stored data (matio_types enumerations)
1192
 * @param dims Dimensions of the data
1193
 * @param start Index to start reading data in each dimension
1194
 * @param stride Read every @c stride elements in each dimension
1195
 * @param edge Number of elements to read in each dimension
1196
 * @retval Number of bytes read from the file, or -1 on error
1197
 */
1198
int
1199
ReadCompressedDataSlab2(mat_t *mat, z_streamp z, void *data, enum matio_classes class_type,
660✔
1200
                        enum matio_types data_type, const size_t *dims, const int *start,
1201
                        const int *stride, const int *edge)
1202
{
1203
    int nBytes = 0, i, j, err;
660✔
1204
    int pos, row_stride, col_stride;
660✔
1205
    z_stream z_copy = {
660✔
1206
        0,
1207
    };
1208

1209
    if ( (mat == NULL) || (data == NULL) || (mat->fp == NULL) || (start == NULL) ||
660✔
1210
         (stride == NULL) || (edge == NULL) ) {
660✔
1211
        return 0;
1212
    }
1213

1214
    err = inflateCopy(&z_copy, z);
660✔
1215
    if ( err != Z_OK ) {
660✔
UNCOV
1216
        Mat_Critical("inflateCopy returned error %s", zError(err));
×
UNCOV
1217
        return -1;
×
1218
    }
1219
    switch ( class_type ) {
660✔
1220
        case MAT_C_DOUBLE: {
66✔
1221
            double *ptr = (double *)data;
66✔
1222
            READ_COMPRESSED_DATA_SLAB2(ReadCompressedDoubleData);
486✔
1223
            break;
1224
        }
1225
        case MAT_C_SINGLE: {
66✔
1226
            float *ptr = (float *)data;
66✔
1227
            READ_COMPRESSED_DATA_SLAB2(ReadCompressedSingleData);
486✔
1228
            break;
1229
        }
1230
#ifdef HAVE_MAT_INT64_T
1231
        case MAT_C_INT64: {
66✔
1232
            mat_int64_t *ptr = (mat_int64_t *)data;
66✔
1233
            READ_COMPRESSED_DATA_SLAB2(ReadCompressedInt64Data);
486✔
1234
            break;
1235
        }
1236
#endif /* HAVE_MAT_INT64_T */
1237
#ifdef HAVE_MAT_UINT64_T
1238
        case MAT_C_UINT64: {
66✔
1239
            mat_uint64_t *ptr = (mat_uint64_t *)data;
66✔
1240
            READ_COMPRESSED_DATA_SLAB2(ReadCompressedUInt64Data);
486✔
1241
            break;
1242
        }
1243
#endif /* HAVE_MAT_UINT64_T */
1244
        case MAT_C_INT32: {
66✔
1245
            mat_int32_t *ptr = (mat_int32_t *)data;
66✔
1246
            READ_COMPRESSED_DATA_SLAB2(ReadCompressedInt32Data);
486✔
1247
            break;
1248
        }
1249
        case MAT_C_UINT32: {
66✔
1250
            mat_uint32_t *ptr = (mat_uint32_t *)data;
66✔
1251
            READ_COMPRESSED_DATA_SLAB2(ReadCompressedUInt32Data);
486✔
1252
            break;
1253
        }
1254
        case MAT_C_INT16: {
66✔
1255
            mat_int16_t *ptr = (mat_int16_t *)data;
66✔
1256
            READ_COMPRESSED_DATA_SLAB2(ReadCompressedInt16Data);
486✔
1257
            break;
1258
        }
1259
        case MAT_C_UINT16: {
66✔
1260
            mat_uint16_t *ptr = (mat_uint16_t *)data;
66✔
1261
            READ_COMPRESSED_DATA_SLAB2(ReadCompressedUInt16Data);
486✔
1262
            break;
1263
        }
1264
        case MAT_C_INT8: {
66✔
1265
            mat_int8_t *ptr = (mat_int8_t *)data;
66✔
1266
            READ_COMPRESSED_DATA_SLAB2(ReadCompressedInt8Data);
486✔
1267
            break;
1268
        }
1269
        case MAT_C_UINT8: {
66✔
1270
            mat_uint8_t *ptr = (mat_uint8_t *)data;
66✔
1271
            READ_COMPRESSED_DATA_SLAB2(ReadCompressedUInt8Data);
486✔
1272
            break;
1273
        }
1274
        default:
1275
            nBytes = 0;
1276
    }
1277
    inflateEnd(&z_copy);
660✔
1278
    return nBytes;
660✔
1279
}
1280

1281
#undef READ_COMPRESSED_DATA_SLAB2
1282
#endif
1283

1284
/** @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