1 /** @file read_data.c
2  * Matlab MAT version 5 file functions
3  * @ingroup MAT
4  */
5 /*
6  * Copyright (c) 2005-2019, Christopher C. Hulbert
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright notice, this
13  *    list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright notice,
16  *    this list of conditions and the following disclaimer in the documentation
17  *    and/or other materials provided with the distribution.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30 
31 /* FIXME: Implement Unicode support */
32 #include <stddef.h>
33 #include <stdlib.h>
34 #include <string.h>
35 #include <stdio.h>
36 #include <math.h>
37 #include <time.h>
38 #include "matio_private.h"
39 #if defined(HAVE_ZLIB)
40 #   include <plugin/z/lib/zlib.h>
41 #endif
42 
43 #if !defined(READ_BLOCK_SIZE)
44 #define READ_BLOCK_SIZE (256)
45 #endif
46 
47 #define READ_DATA_NOSWAP(T) \
48     do { \
49         if ( len <= READ_BLOCK_SIZE ) { \
50             bytesread += fread(v,data_size,len,(FILE*)mat->fp); \
51             for ( j = 0; j < len; j++ ) { \
52                 data[j] = (T)v[j]; \
53             } \
54         } else { \
55             for ( i = 0; i < len-READ_BLOCK_SIZE; i+=READ_BLOCK_SIZE ) { \
56                 bytesread += fread(v,data_size,READ_BLOCK_SIZE,(FILE*)mat->fp); \
57                 for ( j = 0; j < READ_BLOCK_SIZE; j++ ) { \
58                     data[i+j] = (T)v[j]; \
59                 } \
60             } \
61             if ( len > i ) { \
62                 bytesread += fread(v,data_size,len-i,(FILE*)mat->fp); \
63                 for ( j = 0; j < len-i; j++ ) { \
64                     data[i+j] = (T)v[j]; \
65                 } \
66             }\
67         } \
68     } while (0)
69 
70 #define READ_DATA(T, SwapFunc) \
71     do { \
72         if ( mat->byteswap ) { \
73             if ( len <= READ_BLOCK_SIZE ) { \
74                 bytesread += fread(v,data_size,len,(FILE*)mat->fp); \
75                 for ( j = 0; j < len; j++ ) { \
76                     data[j] = (T)SwapFunc(&v[j]); \
77                 } \
78             } else { \
79                 for ( i = 0; i < len-READ_BLOCK_SIZE; i+=READ_BLOCK_SIZE ) { \
80                     bytesread += fread(v,data_size,READ_BLOCK_SIZE,(FILE*)mat->fp); \
81                     for ( j = 0; j < READ_BLOCK_SIZE; j++ ) { \
82                         data[i+j] = (T)SwapFunc(&v[j]); \
83                     } \
84                 } \
85                 if ( len > i ) { \
86                     bytesread += fread(v,data_size,len-i,(FILE*)mat->fp); \
87                     for ( j = 0; j < len-i; j++ ) { \
88                         data[i+j] = (T)SwapFunc(&v[j]); \
89                     } \
90                 }\
91             } \
92         } else { \
93             READ_DATA_NOSWAP(T); \
94         } \
95     } while (0)
96 
97 #ifdef HAVE_MAT_INT64_T
98 #define READ_DATA_INT64(T) \
99     do { \
100         if ( MAT_T_INT64 == data_type ) { \
101             mat_int64_t v[READ_BLOCK_SIZE]; \
102             READ_DATA(T, Mat_int64Swap); \
103         } \
104     } while (0)
105 #else
106 #define READ_DATA_INT64(T)
107 #endif /* HAVE_MAT_INT64_T */
108 
109 #ifdef HAVE_MAT_UINT64_T
110 #define READ_DATA_UINT64(T) \
111     do { \
112         if ( MAT_T_UINT64 == data_type ) { \
113             mat_uint64_t v[READ_BLOCK_SIZE]; \
114             READ_DATA(T, Mat_uint64Swap); \
115         } \
116     } while (0)
117 #else
118 #define READ_DATA_UINT64(T)
119 #endif /* HAVE_MAT_UINT64_T */
120 
121 #define READ_DATA_TYPE(T) \
122     do { \
123         switch ( data_type ) { \
124             case MAT_T_DOUBLE: \
125             { \
126                 double v[READ_BLOCK_SIZE]; \
127                 READ_DATA(T, Mat_doubleSwap); \
128                 break; \
129             } \
130             case MAT_T_SINGLE: \
131             { \
132                 float v[READ_BLOCK_SIZE]; \
133                 READ_DATA(T, Mat_floatSwap); \
134                 break; \
135             } \
136             case MAT_T_INT32: \
137             { \
138                 mat_int32_t v[READ_BLOCK_SIZE]; \
139                 READ_DATA(T, Mat_int32Swap); \
140                 break; \
141             } \
142             case MAT_T_UINT32: \
143             { \
144                 mat_uint32_t v[READ_BLOCK_SIZE]; \
145                 READ_DATA(T, Mat_uint32Swap); \
146                 break; \
147             } \
148             case MAT_T_INT16: \
149             { \
150                 mat_int16_t v[READ_BLOCK_SIZE]; \
151                 READ_DATA(T, Mat_int16Swap); \
152                 break; \
153             } \
154             case MAT_T_UINT16: \
155             { \
156                 mat_uint16_t v[READ_BLOCK_SIZE]; \
157                 READ_DATA(T, Mat_uint16Swap); \
158                 break; \
159             } \
160             case MAT_T_INT8: \
161             { \
162                 mat_int8_t v[READ_BLOCK_SIZE]; \
163                 READ_DATA_NOSWAP(T); \
164                 break; \
165             } \
166             case MAT_T_UINT8: \
167             { \
168                 mat_uint8_t v[READ_BLOCK_SIZE]; \
169                 READ_DATA_NOSWAP(T); \
170                 break; \
171             } \
172             default: \
173                 READ_DATA_INT64(T); \
174                 READ_DATA_UINT64(T); \
175                 break; \
176         } \
177     } while (0)
178 
179 #if defined(HAVE_ZLIB)
180 #define READ_COMPRESSED_DATA(T, SwapFunc) \
181     do { \
182         if ( mat->byteswap ) { \
183             for ( i = 0; i < len; i++ ) { \
184                 InflateData(mat,z,&v,data_size); \
185                 data[i] = (T)SwapFunc(&v); \
186             } \
187         } else { \
188             for ( i = 0; i < len; i++ ) { \
189                 InflateData(mat,z,&v,data_size); \
190                 data[i] = (T)v; \
191             } \
192         } \
193     } while (0)
194 
195 #ifdef HAVE_MAT_INT64_T
196 #define READ_COMPRESSED_DATA_INT64(T) \
197     do { \
198         if ( MAT_T_INT64 == data_type ) { \
199             mat_int64_t v; \
200             READ_COMPRESSED_DATA(T, Mat_int64Swap); \
201         } \
202     } while (0)
203 #else
204 #define READ_COMPRESSED_DATA_INT64(T)
205 #endif /* HAVE_MAT_INT64_T */
206 
207 #ifdef HAVE_MAT_UINT64_T
208 #define READ_COMPRESSED_DATA_UINT64(T) \
209     do { \
210         if ( MAT_T_UINT64 == data_type ) { \
211             mat_uint64_t v; \
212             READ_COMPRESSED_DATA(T, Mat_uint64Swap); \
213         } \
214     } while (0)
215 #else
216 #define READ_COMPRESSED_DATA_UINT64(T)
217 #endif /* HAVE_MAT_UINT64_T */
218 
219 #define READ_COMPRESSED_DATA_TYPE(T) \
220     do { \
221         switch ( data_type ) { \
222             case MAT_T_DOUBLE: \
223             { \
224                 double v; \
225                 READ_COMPRESSED_DATA(T, Mat_doubleSwap); \
226                 break; \
227             } \
228             case MAT_T_SINGLE: \
229             { \
230                 float v; \
231                 READ_COMPRESSED_DATA(T, Mat_floatSwap); \
232                 break; \
233             } \
234             case MAT_T_INT32: \
235             { \
236                 mat_int32_t v; \
237                 READ_COMPRESSED_DATA(T, Mat_int32Swap); \
238                 break; \
239             } \
240             case MAT_T_UINT32: \
241             { \
242                 mat_uint32_t v; \
243                 READ_COMPRESSED_DATA(T, Mat_uint32Swap); \
244                 break; \
245             } \
246             case MAT_T_INT16: \
247             { \
248                 mat_int16_t v; \
249                 READ_COMPRESSED_DATA(T, Mat_int16Swap); \
250                 break; \
251             } \
252             case MAT_T_UINT16: \
253             { \
254                 mat_uint16_t v; \
255                 READ_COMPRESSED_DATA(T, Mat_uint16Swap); \
256                 break; \
257             } \
258             case MAT_T_UINT8: \
259             { \
260                 mat_uint8_t v; \
261                 for ( i = 0; i < len; i++ ) { \
262                     InflateData(mat,z,&v,data_size); \
263                     data[i] = (T)v; \
264                 } \
265                 break; \
266             } \
267             case MAT_T_INT8: \
268             { \
269                 mat_int8_t v; \
270                 for ( i = 0; i < len; i++ ) { \
271                     InflateData(mat,z,&v,data_size); \
272                     data[i] = (T)v; \
273                 } \
274                 break; \
275             } \
276             default: \
277                 READ_COMPRESSED_DATA_INT64(T); \
278                 READ_COMPRESSED_DATA_UINT64(T); \
279                 break; \
280         } \
281     } while (0)
282 #endif
283 
284 /*
285  * --------------------------------------------------------------------------
286  *    Routines to read data of any type into arrays of a specific type
287  * --------------------------------------------------------------------------
288  */
289 
290 /** @cond mat_devman */
291 
292 /** @brief Reads data of type @c data_type into a double type
293  *
294  * Reads from the MAT file @c len elements of data type @c data_type storing
295  * them as double's in @c data.
296  * @ingroup mat_internal
297  * @param mat MAT file pointer
298  * @param data Pointer to store the output double values (len*sizeof(double))
299  * @param data_type one of the @c matio_types enumerations which is the source
300  *                  data type in the file
301  * @param len Number of elements of type @c data_type to read from the file
302  * @retval Number of bytes read from the file
303  */
304 int
ReadDoubleData(mat_t * mat,double * data,enum matio_types data_type,int len)305 ReadDoubleData(mat_t *mat,double *data,enum matio_types data_type,int len)
306 {
307     int bytesread = 0, i, j;
308     size_t data_size;
309 
310     if ( (mat == NULL) || (data == NULL) || (mat->fp == NULL) )
311         return 0;
312 
313     data_size = Mat_SizeOf(data_type);
314 
315     switch ( data_type ) {
316         case MAT_T_DOUBLE:
317         {
318             bytesread += fread(data,data_size,len,(FILE*)mat->fp);
319             if ( mat->byteswap ) {
320                 for ( i = 0; i < len; i++ ) {
321                     (void)Mat_doubleSwap(data+i);
322                 }
323             }
324             break;
325         }
326         case MAT_T_SINGLE:
327         {
328             float v[READ_BLOCK_SIZE];
329             READ_DATA(double, Mat_floatSwap);
330             break;
331         }
332 #ifdef HAVE_MAT_INT64_T
333         case MAT_T_INT64:
334         {
335             mat_int64_t v[READ_BLOCK_SIZE];
336             READ_DATA(double, Mat_int64Swap);
337             break;
338         }
339 #endif
340 #ifdef HAVE_MAT_UINT64_T
341         case MAT_T_UINT64:
342         {
343             mat_uint64_t v[READ_BLOCK_SIZE];
344             READ_DATA(double, Mat_uint64Swap);
345             break;
346         }
347 #endif
348         case MAT_T_INT32:
349         {
350             mat_int32_t v[READ_BLOCK_SIZE];
351             READ_DATA(double, Mat_int32Swap);
352             break;
353         }
354         case MAT_T_UINT32:
355         {
356             mat_uint32_t v[READ_BLOCK_SIZE];
357             READ_DATA(double, Mat_uint32Swap);
358             break;
359         }
360         case MAT_T_INT16:
361         {
362             mat_int16_t v[READ_BLOCK_SIZE];
363             READ_DATA(double, Mat_int16Swap);
364             break;
365         }
366         case MAT_T_UINT16:
367         {
368             mat_uint16_t v[READ_BLOCK_SIZE];
369             READ_DATA(double, Mat_uint16Swap);
370             break;
371         }
372         case MAT_T_INT8:
373         {
374             mat_int8_t v[READ_BLOCK_SIZE];
375             READ_DATA_NOSWAP(double);
376             break;
377         }
378         case MAT_T_UINT8:
379         {
380             mat_uint8_t v[READ_BLOCK_SIZE];
381             READ_DATA_NOSWAP(double);
382             break;
383         }
384         default:
385             return 0;
386     }
387     bytesread *= data_size;
388     return bytesread;
389 }
390 
391 #if defined(HAVE_ZLIB)
392 /** @brief Reads data of type @c data_type into a double type
393  *
394  * Reads from the MAT file @c len compressed elements of data type @c data_type
395  * storing them as double's in @c data.
396  * @ingroup mat_internal
397  * @param mat MAT file pointer
398  * @param z Pointer to the zlib stream for inflation
399  * @param data Pointer to store the output double values (len*sizeof(double))
400  * @param data_type one of the @c matio_types enumerations which is the source
401  *                  data type in the file
402  * @param len Number of elements of type @c data_type to read from the file
403  * @retval Number of bytes read from the file
404  */
405 int
ReadCompressedDoubleData(mat_t * mat,z_streamp z,double * data,enum matio_types data_type,int len)406 ReadCompressedDoubleData(mat_t *mat,z_streamp z,double *data,
407     enum matio_types data_type,int len)
408 {
409     int nBytes = 0, i;
410     unsigned int data_size;
411     union _buf {
412         float           f[256];
413 #ifdef HAVE_MAT_INT64_T
414         mat_int64_t   i64[128];
415 #endif
416 #ifdef HAVE_MAT_UINT64_T
417         mat_uint64_t ui64[128];
418 #endif
419         mat_int32_t   i32[256];
420         mat_uint32_t ui32[256];
421         mat_int16_t   i16[512];
422         mat_uint16_t ui16[512];
423         mat_int8_t     i8[1024];
424         mat_uint8_t   ui8[1024];
425     } buf;
426 
427     data_size = (unsigned int)Mat_SizeOf(data_type);
428 
429     switch ( data_type ) {
430         case MAT_T_DOUBLE:
431         {
432             if ( mat->byteswap ) {
433                 InflateData(mat,z,data,len*data_size);
434                 for ( i = 0; i < len; i++ )
435                     (void)Mat_doubleSwap(data+i);
436             } else {
437                 InflateData(mat,z,data,len*data_size);
438             }
439             break;
440         }
441         case MAT_T_SINGLE:
442         {
443             if ( mat->byteswap ) {
444                 if ( len <= 256 ){
445                     InflateData(mat,z,buf.f,len*data_size);
446                     for ( i = 0; i < len; i++ )
447                         data[i] = Mat_floatSwap(buf.f+i);
448                 } else {
449                     int j;
450                     len -= 256;
451                     for ( i = 0; i < len; i+=256 ) {
452                         InflateData(mat,z,buf.f,256*data_size);
453                         for ( j = 0; j < 256; j++ )
454                             data[i+j] = Mat_floatSwap(buf.f+j);
455                     }
456                     len = len-(i-256);
457                     InflateData(mat,z,buf.f,len*data_size);
458                     for ( j = 0; j < len; j++ )
459                         data[i+j] = Mat_floatSwap(buf.f+j);
460                 }
461             } else {
462                 if ( len <= 256 ){
463                     InflateData(mat,z,buf.f,len*data_size);
464                     for ( i = 0; i < len; i++ )
465                         data[i] = buf.f[i];
466                 } else {
467                     int j;
468                     len -= 256;
469                     for ( i = 0; i < len; i+=256 ) {
470                         InflateData(mat,z,buf.f,256*data_size);
471                         for ( j = 0; j < 256; j++ )
472                             data[i+j] = buf.f[j];
473                     }
474                     len = len-(i-256);
475                     InflateData(mat,z,buf.f,len*data_size);
476                     for ( j = 0; j < len; j++ )
477                         data[i+j] = buf.f[j];
478                 }
479             }
480             break;
481         }
482 #ifdef HAVE_MAT_INT64_T
483         case MAT_T_INT64:
484         {
485             if ( mat->byteswap ) {
486                 if ( len <= 128 ){
487                     InflateData(mat,z,buf.i64,len*data_size);
488                     for ( i = 0; i < len; i++ )
489                         data[i] = (double)Mat_int64Swap(buf.i64+i);
490                 } else {
491                     int j;
492                     len -= 128;
493                     for ( i = 0; i < len; i+=128 ) {
494                         InflateData(mat,z,buf.i64,128*data_size);
495                         for ( j = 0; j < 128; j++ )
496                             data[i+j] = (double)Mat_int64Swap(buf.i64+j);
497                     }
498                     len = len-(i-128);
499                     InflateData(mat,z,buf.i64,len*data_size);
500                     for ( j = 0; j < len; j++ )
501                         data[i+j] = (double)Mat_int64Swap(buf.i64+j);
502                 }
503             } else {
504                 if ( len <= 128 ){
505                     InflateData(mat,z,buf.i64,len*data_size);
506                     for ( i = 0; i < len; i++ )
507                         data[i] = (double)buf.i64[i];
508                 } else {
509                     int j;
510                     len -= 128;
511                     for ( i = 0; i < len; i+=128 ) {
512                         InflateData(mat,z,buf.i64,128*data_size);
513                         for ( j = 0; j < 128; j++ )
514                             data[i+j] = (double)buf.i64[j];
515                     }
516                     len = len-(i-128);
517                     InflateData(mat,z,buf.i64,len*data_size);
518                     for ( j = 0; j < len; j++ )
519                         data[i+j] = (double)buf.i64[j];
520                 }
521             }
522             break;
523         }
524 #endif
525 #ifdef HAVE_MAT_UINT64_T
526         case MAT_T_UINT64:
527         {
528             if ( mat->byteswap ) {
529                 if ( len <= 128 ){
530                     InflateData(mat,z,buf.ui64,len*data_size);
531                     for ( i = 0; i < len; i++ )
532                         data[i] = (double)Mat_uint64Swap(buf.ui64+i);
533                 } else {
534                     int j;
535                     len -= 128;
536                     for ( i = 0; i < len; i+=128 ) {
537                         InflateData(mat,z,buf.ui64,128*data_size);
538                         for ( j = 0; j < 128; j++ )
539                             data[i+j] = (double)Mat_uint64Swap(buf.ui64+j);
540                     }
541                     len = len-(i-128);
542                     InflateData(mat,z,buf.ui64,len*data_size);
543                     for ( j = 0; j < len; j++ )
544                         data[i+j] = (double)Mat_uint64Swap(buf.ui64+j);
545                 }
546             } else {
547                 if ( len <= 128 ){
548                     InflateData(mat,z,buf.ui64,len*data_size);
549                     for ( i = 0; i < len; i++ )
550                         data[i] = (double)buf.ui64[i];
551                 } else {
552                     int j;
553                     len -= 128;
554                     for ( i = 0; i < len; i+=128 ) {
555                         InflateData(mat,z,buf.ui64,128*data_size);
556                         for ( j = 0; j < 128; j++ )
557                             data[i+j] = (double)buf.ui64[j];
558                     }
559                     len = len-(i-128);
560                     InflateData(mat,z,buf.ui64,len*data_size);
561                     for ( j = 0; j < len; j++ )
562                         data[i+j] = (double)buf.ui64[j];
563                 }
564             }
565             break;
566         }
567 #endif
568         case MAT_T_INT32:
569         {
570             if ( mat->byteswap ) {
571                 if ( len <= 256 ){
572                     InflateData(mat,z,buf.i32,len*data_size);
573                     for ( i = 0; i < len; i++ )
574                         data[i] = Mat_int32Swap(buf.i32+i);
575                 } else {
576                     int j;
577                     len -= 256;
578                     for ( i = 0; i < len; i+=256 ) {
579                         InflateData(mat,z,buf.i32,256*data_size);
580                         for ( j = 0; j < 256; j++ )
581                             data[i+j] = Mat_int32Swap(buf.i32+j);
582                     }
583                     len = len-(i-256);
584                     InflateData(mat,z,buf.i32,len*data_size);
585                     for ( j = 0; j < len; j++ )
586                         data[i+j] = Mat_int32Swap(buf.i32+j);
587                 }
588             } else {
589                 if ( len <= 256 ){
590                     InflateData(mat,z,buf.i32,len*data_size);
591                     for ( i = 0; i < len; i++ )
592                         data[i] = buf.i32[i];
593                 } else {
594                     int j;
595                     len -= 256;
596                     for ( i = 0; i < len; i+=256 ) {
597                         InflateData(mat,z,buf.i32,256*data_size);
598                         for ( j = 0; j < 256; j++ )
599                             data[i+j] = buf.i32[j];
600                     }
601                     len = len-(i-256);
602                     InflateData(mat,z,buf.i32,len*data_size);
603                     for ( j = 0; j < len; j++ )
604                         data[i+j] = buf.i32[j];
605                 }
606             }
607             break;
608         }
609         case MAT_T_UINT32:
610         {
611             if ( mat->byteswap ) {
612                 if ( len <= 256 ){
613                     InflateData(mat,z,buf.ui32,len*data_size);
614                     for ( i = 0; i < len; i++ )
615                         data[i] = Mat_uint32Swap(buf.ui32+i);
616                 } else {
617                     int j;
618                     len -= 256;
619                     for ( i = 0; i < len; i+=256 ) {
620                         InflateData(mat,z,buf.ui32,256*data_size);
621                         for ( j = 0; j < 256; j++ )
622                             data[i+j] = Mat_uint32Swap(buf.ui32+j);
623                     }
624                     len = len-(i-256);
625                     InflateData(mat,z,buf.ui32,len*data_size);
626                     for ( j = 0; j < len; j++ )
627                         data[i+j] = Mat_uint32Swap(buf.ui32+j);
628                 }
629             } else {
630                 if ( len <= 256 ) {
631                     InflateData(mat,z,buf.ui32,len*data_size);
632                     for ( i = 0; i < len; i++ )
633                         data[i] = buf.ui32[i];
634                 } else {
635                     int j;
636                     len -= 256;
637                     for ( i = 0; i < len; i+=256 ) {
638                         InflateData(mat,z,buf.ui32,256*data_size);
639                         for ( j = 0; j < 256; j++ )
640                             data[i+j] = buf.ui32[j];
641                     }
642                     len = len-(i-256);
643                     InflateData(mat,z,buf.ui32,len*data_size);
644                     for ( j = 0; j < len; j++ )
645                         data[i+j] = buf.ui32[j];
646                 }
647             }
648             break;
649         }
650         case MAT_T_INT16:
651         {
652             if ( mat->byteswap ) {
653                 if ( len <= 512 ){
654                     InflateData(mat,z,buf.i16,len*data_size);
655                     for ( i = 0; i < len; i++ )
656                         data[i] = Mat_int16Swap(buf.i16+i);
657                 } else {
658                     int j;
659                     len -= 512;
660                     for ( i = 0; i < len; i+=512 ) {
661                         InflateData(mat,z,buf.i16,512*data_size);
662                         for ( j = 0; j < 512; j++ )
663                             data[i+j] = Mat_int16Swap(buf.i16+j);
664                     }
665                     len = len-(i-512);
666                     InflateData(mat,z,buf.i16,len*data_size);
667                     for ( j = 0; j < len; j++ )
668                         data[i+j] = Mat_int16Swap(buf.i16+j);
669                 }
670             } else {
671                 if ( len <= 512 ) {
672                     InflateData(mat,z,buf.i16,len*data_size);
673                     for ( i = 0; i < len; i++ )
674                         data[i] = buf.i16[i];
675                 } else {
676                     int j;
677                     len -= 512;
678                     for ( i = 0; i < len; i+=512 ) {
679                         InflateData(mat,z,buf.i16,512*data_size);
680                         for ( j = 0; j < 512; j++ )
681                             data[i+j] = buf.i16[j];
682                     }
683                     len = len-(i-512);
684                     InflateData(mat,z,buf.i16,len*data_size);
685                     for ( j = 0; j < len; j++ )
686                         data[i+j] = buf.i16[j];
687                 }
688             }
689             break;
690         }
691         case MAT_T_UINT16:
692         {
693             if ( mat->byteswap ) {
694                 if ( len <= 512 ){
695                     InflateData(mat,z,buf.ui16,len*data_size);
696                     for ( i = 0; i < len; i++ )
697                         data[i] = Mat_uint16Swap(buf.ui16+i);
698                 } else {
699                     int j;
700                     len -= 512;
701                     for ( i = 0; i < len; i+=512 ) {
702                         InflateData(mat,z,buf.ui16,512*data_size);
703                         for ( j = 0; j < 512; j++ )
704                             data[i+j] = Mat_uint16Swap(buf.ui16+j);
705                     }
706                     len = len-(i-512);
707                     InflateData(mat,z,buf.ui16,len*data_size);
708                     for ( j = 0; j < len; j++ )
709                         data[i+j] = Mat_uint16Swap(buf.ui16+j);
710                 }
711             } else {
712                 if ( len <= 512 ) {
713                     InflateData(mat,z,buf.ui16,len*data_size);
714                     for ( i = 0; i < len; i++ )
715                         data[i] = buf.ui16[i];
716                 } else {
717                     int j;
718                     len -= 512;
719                     for ( i = 0; i < len; i+=512 ) {
720                         InflateData(mat,z,buf.ui16,512*data_size);
721                         for ( j = 0; j < 512; j++ )
722                             data[i+j] = buf.ui16[j];
723                     }
724                     len = len-(i-512);
725                     InflateData(mat,z,buf.ui16,len*data_size);
726                     for ( j = 0; j < len; j++ )
727                         data[i+j] = buf.ui16[j];
728                 }
729             }
730             break;
731         }
732         case MAT_T_UINT8:
733         {
734             if ( len <= 1024 ) {
735                 InflateData(mat,z,buf.ui8,len*data_size);
736                 for ( i = 0; i < len; i++ )
737                     data[i] = buf.ui8[i];
738             } else {
739                 int j;
740                 len -= 1024;
741                 for ( i = 0; i < len; i+=1024 ) {
742                     InflateData(mat,z,buf.ui8,1024*data_size);
743                     for ( j = 0; j < 1024; j++ )
744                         data[i+j] = buf.ui8[j];
745                 }
746                 len = len-(i-1024);
747                 InflateData(mat,z,buf.ui8,len*data_size);
748                 for ( j = 0; j < len; j++ )
749                     data[i+j] = buf.ui8[j];
750             }
751             break;
752         }
753         case MAT_T_INT8:
754         {
755             if ( len <= 1024 ) {
756                 InflateData(mat,z,buf.i8,len*data_size);
757                 for ( i = 0; i < len; i++ )
758                     data[i] = buf.i8[i];
759             } else {
760                 int j;
761                 len -= 1024;
762                 for ( i = 0; i < len; i+=1024 ) {
763                     InflateData(mat,z,buf.i8,1024*data_size);
764                     for ( j = 0; j < 1024; j++ )
765                         data[i+j] = buf.i8[j];
766                 }
767                 len = len-(i-1024);
768                 InflateData(mat,z,buf.i8,len*data_size);
769                 for ( j = 0; j < len; j++ )
770                     data[i+j] = buf.i8[j];
771             }
772             break;
773         }
774         default:
775             return 0;
776     }
777     nBytes = len*data_size;
778     return nBytes;
779 }
780 #endif
781 
782 /** @brief Reads data of type @c data_type into a float type
783  *
784  * Reads from the MAT file @c len elements of data type @c data_type storing
785  * them as float's in @c data.
786  * @ingroup mat_internal
787  * @param mat MAT file pointer
788  * @param data Pointer to store the output float values (len*sizeof(float))
789  * @param data_type one of the @c matio_types enumerations which is the source
790  *                  data type in the file
791  * @param len Number of elements of type @c data_type to read from the file
792  * @retval Number of bytes read from the file
793  */
794 int
ReadSingleData(mat_t * mat,float * data,enum matio_types data_type,int len)795 ReadSingleData(mat_t *mat,float *data,enum matio_types data_type,int len)
796 {
797     int bytesread = 0, i, j;
798     size_t data_size;
799 
800     if ( (mat == NULL) || (data == NULL) || (mat->fp == NULL) )
801         return 0;
802 
803     data_size = Mat_SizeOf(data_type);
804     READ_DATA_TYPE(float);
805     bytesread *= data_size;
806     return bytesread;
807 }
808 
809 #if defined(HAVE_ZLIB)
810 /** @brief Reads data of type @c data_type into a float type
811  *
812  * Reads from the MAT file @c len compressed elements of data type @c data_type
813  * storing them as float's in @c data.
814  * @ingroup mat_internal
815  * @param mat MAT file pointer
816  * @param z Pointer to the zlib stream for inflation
817  * @param data Pointer to store the output float values (len*sizeof(float))
818  * @param data_type one of the @c matio_types enumerations which is the source
819  *                  data type in the file
820  * @param len Number of elements of type @c data_type to read from the file
821  * @retval Number of bytes read from the file
822  */
823 int
ReadCompressedSingleData(mat_t * mat,z_streamp z,float * data,enum matio_types data_type,int len)824 ReadCompressedSingleData(mat_t *mat,z_streamp z,float *data,
825     enum matio_types data_type,int len)
826 {
827     int nBytes = 0, i;
828     unsigned int data_size;
829 
830     if ( (mat == NULL) || (data == NULL) || (z == NULL) )
831         return 0;
832 
833     data_size = (unsigned int)Mat_SizeOf(data_type);
834     READ_COMPRESSED_DATA_TYPE(float);
835     nBytes = len*data_size;
836     return nBytes;
837 }
838 #endif
839 
840 #ifdef HAVE_MAT_INT64_T
841 /** @brief Reads data of type @c data_type into a signed 64-bit integer type
842  *
843  * Reads from the MAT file @c len elements of data type @c data_type storing
844  * them as signed 64-bit integers in @c data.
845  * @ingroup mat_internal
846  * @param mat MAT file pointer
847  * @param data Pointer to store the output signed 64-bit integer values
848  *             (len*sizeof(mat_int64_t))
849  * @param data_type one of the @c matio_types enumerations which is the source
850  *                  data type in the file
851  * @param len Number of elements of type @c data_type to read from the file
852  * @retval Number of bytes read from the file
853  */
854 int
ReadInt64Data(mat_t * mat,mat_int64_t * data,enum matio_types data_type,int len)855 ReadInt64Data(mat_t *mat,mat_int64_t *data,enum matio_types data_type,int len)
856 {
857     int bytesread = 0, i, j;
858     size_t data_size;
859 
860     if ( (mat == NULL) || (data == NULL) || (mat->fp == NULL) )
861         return 0;
862 
863     data_size = Mat_SizeOf(data_type);
864     READ_DATA_TYPE(mat_int64_t);
865     bytesread *= data_size;
866     return bytesread;
867 }
868 
869 #if defined(HAVE_ZLIB)
870 /** @brief Reads data of type @c data_type into a signed 64-bit integer type
871  *
872  * Reads from the MAT file @c len compressed elements of data type @c data_type
873  * storing them as signed 64-bit integers in @c data.
874  * @ingroup mat_internal
875  * @param mat MAT file pointer
876  * @param z Pointer to the zlib stream for inflation
877  * @param data Pointer to store the output signed 64-bit integer values
878  *             (len*sizeof(mat_int64_t))
879  * @param data_type one of the @c matio_types enumerations which is the source
880  *                  data type in the file
881  * @param len Number of elements of type @c data_type to read from the file
882  * @retval Number of bytes read from the file
883  */
884 int
ReadCompressedInt64Data(mat_t * mat,z_streamp z,mat_int64_t * data,enum matio_types data_type,int len)885 ReadCompressedInt64Data(mat_t *mat,z_streamp z,mat_int64_t *data,
886     enum matio_types data_type,int len)
887 {
888     int nBytes = 0, i;
889     unsigned int data_size;
890 
891     if ( (mat == NULL) || (data == NULL) || (z == NULL) )
892         return 0;
893 
894     data_size = (unsigned int)Mat_SizeOf(data_type);
895     READ_COMPRESSED_DATA_TYPE(mat_int64_t);
896     nBytes = len*data_size;
897     return nBytes;
898 }
899 #endif
900 #endif /* HAVE_MAT_INT64_T */
901 
902 #ifdef HAVE_MAT_UINT64_T
903 /** @brief Reads data of type @c data_type into an unsigned 64-bit integer type
904  *
905  * Reads from the MAT file @c len elements of data type @c data_type storing
906  * them as unsigned 64-bit integers in @c data.
907  * @ingroup mat_internal
908  * @param mat MAT file pointer
909  * @param data Pointer to store the output unsigned 64-bit integer values
910  *             (len*sizeof(mat_uint64_t))
911  * @param data_type one of the @c matio_types enumerations which is the source
912  *                  data type in the file
913  * @param len Number of elements of type @c data_type to read from the file
914  * @retval Number of bytes read from the file
915  */
916 int
ReadUInt64Data(mat_t * mat,mat_uint64_t * data,enum matio_types data_type,int len)917 ReadUInt64Data(mat_t *mat,mat_uint64_t *data,enum matio_types data_type,int len)
918 {
919     int bytesread = 0, i, j;
920     size_t data_size;
921 
922     if ( (mat == NULL) || (data == NULL) || (mat->fp == NULL) )
923         return 0;
924 
925     data_size = Mat_SizeOf(data_type);
926     READ_DATA_TYPE(mat_uint64_t);
927     bytesread *= data_size;
928     return bytesread;
929 }
930 
931 #if defined(HAVE_ZLIB)
932 /** @brief Reads data of type @c data_type into an unsigned 64-bit integer type
933  *
934  * Reads from the MAT file @c len compressed elements of data type @c data_type
935  * storing them as unsigned 64-bit integers in @c data.
936  * @ingroup mat_internal
937  * @param mat MAT file pointer
938  * @param z Pointer to the zlib stream for inflation
939  * @param data Pointer to store the output unsigned 64-bit integer values
940  *             (len*sizeof(mat_uint64_t))
941  * @param data_type one of the @c matio_types enumerations which is the source
942  *                  data type in the file
943  * @param len Number of elements of type @c data_type to read from the file
944  * @retval Number of bytes read from the file
945  */
946 int
ReadCompressedUInt64Data(mat_t * mat,z_streamp z,mat_uint64_t * data,enum matio_types data_type,int len)947 ReadCompressedUInt64Data(mat_t *mat,z_streamp z,mat_uint64_t *data,
948     enum matio_types data_type,int len)
949 {
950     int nBytes = 0, i;
951     unsigned int data_size;
952 
953     if ( (mat == NULL) || (data == NULL) || (z == NULL) )
954         return 0;
955 
956     data_size = (unsigned int)Mat_SizeOf(data_type);
957     READ_COMPRESSED_DATA_TYPE(mat_uint64_t);
958     nBytes = len*data_size;
959     return nBytes;
960 }
961 #endif /* HAVE_ZLIB */
962 #endif /* HAVE_MAT_UINT64_T */
963 
964 /** @brief Reads data of type @c data_type into a signed 32-bit integer type
965  *
966  * Reads from the MAT file @c len elements of data type @c data_type storing
967  * them as signed 32-bit integers in @c data.
968  * @ingroup mat_internal
969  * @param mat MAT file pointer
970  * @param data Pointer to store the output signed 32-bit integer values
971  *             (len*sizeof(mat_int32_t))
972  * @param data_type one of the @c matio_types enumerations which is the source
973  *                  data type in the file
974  * @param len Number of elements of type @c data_type to read from the file
975  * @retval Number of bytes read from the file
976  */
977 int
ReadInt32Data(mat_t * mat,mat_int32_t * data,enum matio_types data_type,int len)978 ReadInt32Data(mat_t *mat,mat_int32_t *data,enum matio_types data_type,int len)
979 {
980     int bytesread = 0, i, j;
981     size_t data_size;
982 
983     if ( (mat == NULL) || (data == NULL) || (mat->fp == NULL) )
984         return 0;
985 
986     data_size = Mat_SizeOf(data_type);
987     READ_DATA_TYPE(mat_int32_t);
988     bytesread *= data_size;
989     return bytesread;
990 }
991 
992 #if defined(HAVE_ZLIB)
993 /** @brief Reads data of type @c data_type into a signed 32-bit integer type
994  *
995  * Reads from the MAT file @c len compressed elements of data type @c data_type
996  * storing them as signed 32-bit integers in @c data.
997  * @ingroup mat_internal
998  * @param mat MAT file pointer
999  * @param z Pointer to the zlib stream for inflation
1000  * @param data Pointer to store the output signed 32-bit integer values
1001  *             (len*sizeof(mat_int32_t))
1002  * @param data_type one of the @c matio_types enumerations which is the source
1003  *                  data type in the file
1004  * @param len Number of elements of type @c data_type to read from the file
1005  * @retval Number of bytes read from the file
1006  */
1007 int
ReadCompressedInt32Data(mat_t * mat,z_streamp z,mat_int32_t * data,enum matio_types data_type,int len)1008 ReadCompressedInt32Data(mat_t *mat,z_streamp z,mat_int32_t *data,
1009     enum matio_types data_type,int len)
1010 {
1011     int nBytes = 0, i;
1012     unsigned int data_size;
1013 
1014     if ( (mat == NULL) || (data == NULL) || (z == NULL) )
1015         return 0;
1016 
1017     data_size = (unsigned int)Mat_SizeOf(data_type);
1018     READ_COMPRESSED_DATA_TYPE(mat_int32_t);
1019     nBytes = len*data_size;
1020     return nBytes;
1021 }
1022 #endif
1023 
1024 /** @brief Reads data of type @c data_type into an unsigned 32-bit integer type
1025  *
1026  * Reads from the MAT file @c len elements of data type @c data_type storing
1027  * them as unsigned 32-bit integers in @c data.
1028  * @ingroup mat_internal
1029  * @param mat MAT file pointer
1030  * @param data Pointer to store the output unsigned 32-bit integer values
1031  *             (len*sizeof(mat_uint32_t))
1032  * @param data_type one of the @c matio_types enumerations which is the source
1033  *                  data type in the file
1034  * @param len Number of elements of type @c data_type to read from the file
1035  * @retval Number of bytes read from the file
1036  */
1037 int
ReadUInt32Data(mat_t * mat,mat_uint32_t * data,enum matio_types data_type,int len)1038 ReadUInt32Data(mat_t *mat,mat_uint32_t *data,enum matio_types data_type,int len)
1039 {
1040     int bytesread = 0, i, j;
1041     size_t data_size;
1042 
1043     if ( (mat == NULL) || (data == NULL) || (mat->fp == NULL) )
1044         return 0;
1045 
1046     data_size = Mat_SizeOf(data_type);
1047     READ_DATA_TYPE(mat_uint32_t);
1048     bytesread *= data_size;
1049     return bytesread;
1050 }
1051 
1052 #if defined(HAVE_ZLIB)
1053 /** @brief Reads data of type @c data_type into an unsigned 32-bit integer type
1054  *
1055  * Reads from the MAT file @c len compressed elements of data type @c data_type
1056  * storing them as unsigned 32-bit integers in @c data.
1057  * @ingroup mat_internal
1058  * @param mat MAT file pointer
1059  * @param z Pointer to the zlib stream for inflation
1060  * @param data Pointer to store the output unsigned 32-bit integer values
1061  *             (len*sizeof(mat_uint32_t))
1062  * @param data_type one of the @c matio_types enumerations which is the source
1063  *                  data type in the file
1064  * @param len Number of elements of type @c data_type to read from the file
1065  * @retval Number of bytes read from the file
1066  */
1067 int
ReadCompressedUInt32Data(mat_t * mat,z_streamp z,mat_uint32_t * data,enum matio_types data_type,int len)1068 ReadCompressedUInt32Data(mat_t *mat,z_streamp z,mat_uint32_t *data,
1069     enum matio_types data_type,int len)
1070 {
1071     int nBytes = 0, i;
1072     unsigned int data_size;
1073 
1074     if ( (mat == NULL) || (data == NULL) || (z == NULL) )
1075         return 0;
1076 
1077     data_size = (unsigned int)Mat_SizeOf(data_type);
1078     READ_COMPRESSED_DATA_TYPE(mat_uint32_t);
1079     nBytes = len*data_size;
1080     return nBytes;
1081 }
1082 #endif
1083 
1084 /** @brief Reads data of type @c data_type into a signed 16-bit integer type
1085  *
1086  * Reads from the MAT file @c len elements of data type @c data_type storing
1087  * them as signed 16-bit integers in @c data.
1088  * @ingroup mat_internal
1089  * @param mat MAT file pointer
1090  * @param data Pointer to store the output signed 16-bit integer values
1091  *             (len*sizeof(mat_int16_t))
1092  * @param data_type one of the @c matio_types enumerations which is the source
1093  *                  data type in the file
1094  * @param len Number of elements of type @c data_type to read from the file
1095  * @retval Number of bytes read from the file
1096  */
1097 int
ReadInt16Data(mat_t * mat,mat_int16_t * data,enum matio_types data_type,int len)1098 ReadInt16Data(mat_t *mat,mat_int16_t *data,enum matio_types data_type,int len)
1099 {
1100     int bytesread = 0, i, j;
1101     size_t data_size;
1102 
1103     if ( (mat == NULL) || (data == NULL) || (mat->fp == NULL) )
1104         return 0;
1105 
1106     data_size = Mat_SizeOf(data_type);
1107     READ_DATA_TYPE(mat_int16_t);
1108     bytesread *= data_size;
1109     return bytesread;
1110 }
1111 
1112 #if defined(HAVE_ZLIB)
1113 /** @brief Reads data of type @c data_type into a signed 16-bit integer type
1114  *
1115  * Reads from the MAT file @c len compressed elements of data type @c data_type
1116  * storing them as signed 16-bit integers in @c data.
1117  * @ingroup mat_internal
1118  * @param mat MAT file pointer
1119  * @param z Pointer to the zlib stream for inflation
1120  * @param data Pointer to store the output signed 16-bit integer values
1121  *             (len*sizeof(mat_int16_t))
1122  * @param data_type one of the @c matio_types enumerations which is the source
1123  *                  data type in the file
1124  * @param len Number of elements of type @c data_type to read from the file
1125  * @retval Number of bytes read from the file
1126  */
1127 int
ReadCompressedInt16Data(mat_t * mat,z_streamp z,mat_int16_t * data,enum matio_types data_type,int len)1128 ReadCompressedInt16Data(mat_t *mat,z_streamp z,mat_int16_t *data,
1129     enum matio_types data_type,int len)
1130 {
1131     int nBytes = 0, i;
1132     unsigned int data_size;
1133 
1134     if ( (mat == NULL) || (data == NULL) || (z == NULL) )
1135         return 0;
1136 
1137     data_size = (unsigned int)Mat_SizeOf(data_type);
1138     READ_COMPRESSED_DATA_TYPE(mat_int16_t);
1139     nBytes = len*data_size;
1140     return nBytes;
1141 }
1142 #endif
1143 
1144 /** @brief Reads data of type @c data_type into an unsigned 16-bit integer type
1145  *
1146  * Reads from the MAT file @c len elements of data type @c data_type storing
1147  * them as unsigned 16-bit integers in @c data.
1148  * @ingroup mat_internal
1149  * @param mat MAT file pointer
1150  * @param data Pointer to store the output unsigned 16-bit integer values
1151  *             (len*sizeof(mat_uint16_t))
1152  * @param data_type one of the @c matio_types enumerations which is the source
1153  *                  data type in the file
1154  * @param len Number of elements of type @c data_type to read from the file
1155  * @retval Number of bytes read from the file
1156  */
1157 int
ReadUInt16Data(mat_t * mat,mat_uint16_t * data,enum matio_types data_type,int len)1158 ReadUInt16Data(mat_t *mat,mat_uint16_t *data,enum matio_types data_type,int len)
1159 {
1160     int bytesread = 0, i, j;
1161     size_t data_size;
1162 
1163     if ( (mat == NULL) || (data == NULL) || (mat->fp == NULL) )
1164         return 0;
1165 
1166     data_size = Mat_SizeOf(data_type);
1167     READ_DATA_TYPE(mat_uint16_t);
1168     bytesread *= data_size;
1169     return bytesread;
1170 }
1171 
1172 #if defined(HAVE_ZLIB)
1173 /** @brief Reads data of type @c data_type into an unsigned 16-bit integer type
1174  *
1175  * Reads from the MAT file @c len compressed elements of data type @c data_type
1176  * storing them as unsigned 16-bit integers in @c data.
1177  * @ingroup mat_internal
1178  * @param mat MAT file pointer
1179  * @param z Pointer to the zlib stream for inflation
1180  * @param data Pointer to store the output n unsigned 16-bit integer values
1181  *             (len*sizeof(mat_uint16_t))
1182  * @param data_type one of the @c matio_types enumerations which is the source
1183  *                  data type in the file
1184  * @param len Number of elements of type @c data_type to read from the file
1185  * @retval Number of bytes read from the file
1186  */
1187 int
ReadCompressedUInt16Data(mat_t * mat,z_streamp z,mat_uint16_t * data,enum matio_types data_type,int len)1188 ReadCompressedUInt16Data(mat_t *mat,z_streamp z,mat_uint16_t *data,
1189     enum matio_types data_type,int len)
1190 {
1191     int nBytes = 0, i;
1192     unsigned int data_size;
1193 
1194     if ( (mat == NULL) || (data == NULL) || (z == NULL) )
1195         return 0;
1196 
1197     data_size = (unsigned int)Mat_SizeOf(data_type);
1198     READ_COMPRESSED_DATA_TYPE(mat_uint16_t);
1199     nBytes = len*data_size;
1200     return nBytes;
1201 }
1202 #endif
1203 
1204 /** @brief Reads data of type @c data_type into a signed 8-bit integer type
1205  *
1206  * Reads from the MAT file @c len elements of data type @c data_type storing
1207  * them as signed 8-bit integers in @c data.
1208  * @ingroup mat_internal
1209  * @param mat MAT file pointer
1210  * @param data Pointer to store the output signed 8-bit integer values
1211  *             (len*sizeof(mat_int8_t))
1212  * @param data_type one of the @c matio_types enumerations which is the source
1213  *                  data type in the file
1214  * @param len Number of elements of type @c data_type to read from the file
1215  * @retval Number of bytes read from the file
1216  */
1217 int
ReadInt8Data(mat_t * mat,mat_int8_t * data,enum matio_types data_type,int len)1218 ReadInt8Data(mat_t *mat,mat_int8_t *data,enum matio_types data_type,int len)
1219 {
1220     int bytesread = 0, i, j;
1221     size_t data_size;
1222 
1223     if ( (mat == NULL) || (data == NULL) || (mat->fp == NULL) )
1224         return 0;
1225 
1226     data_size = Mat_SizeOf(data_type);
1227     READ_DATA_TYPE(mat_int8_t);
1228     bytesread *= data_size;
1229     return bytesread;
1230 }
1231 
1232 #if defined(HAVE_ZLIB)
1233 /** @brief Reads data of type @c data_type into a signed 8-bit integer type
1234  *
1235  * Reads from the MAT file @c len compressed elements of data type @c data_type
1236  * storing them as signed 8-bit integers in @c data.
1237  * @ingroup mat_internal
1238  * @param mat MAT file pointer
1239  * @param z Pointer to the zlib stream for inflation
1240  * @param data Pointer to store the output signed 8-bit integer values
1241  *             (len*sizeof(mat_int8_t))
1242  * @param data_type one of the @c matio_types enumerations which is the source
1243  *                  data type in the file
1244  * @param len Number of elements of type @c data_type to read from the file
1245  * @retval Number of bytes read from the file
1246  */
1247 int
ReadCompressedInt8Data(mat_t * mat,z_streamp z,mat_int8_t * data,enum matio_types data_type,int len)1248 ReadCompressedInt8Data(mat_t *mat,z_streamp z,mat_int8_t *data,
1249     enum matio_types data_type,int len)
1250 {
1251     int nBytes = 0, i;
1252     unsigned int data_size;
1253 
1254     if ( (mat == NULL) || (data == NULL) || (z == NULL) )
1255         return 0;
1256 
1257     data_size = (unsigned int)Mat_SizeOf(data_type);
1258     READ_COMPRESSED_DATA_TYPE(mat_int8_t);
1259     nBytes = len*data_size;
1260     return nBytes;
1261 }
1262 #endif
1263 
1264 /** @brief Reads data of type @c data_type into an unsigned 8-bit integer type
1265  *
1266  * Reads from the MAT file @c len elements of data type @c data_type storing
1267  * them as unsigned 8-bit integers in @c data.
1268  * @ingroup mat_internal
1269  * @param mat MAT file pointer
1270  * @param data Pointer to store the output unsigned 8-bit integer values
1271  *             (len*sizeof(mat_uint8_t))
1272  * @param data_type one of the @c matio_types enumerations which is the source
1273  *                  data type in the file
1274  * @param len Number of elements of type @c data_type to read from the file
1275  * @retval Number of bytes read from the file
1276  */
1277 int
ReadUInt8Data(mat_t * mat,mat_uint8_t * data,enum matio_types data_type,int len)1278 ReadUInt8Data(mat_t *mat,mat_uint8_t *data,enum matio_types data_type,int len)
1279 {
1280     int bytesread = 0, i, j;
1281     size_t data_size;
1282 
1283     if ( (mat == NULL) || (data == NULL) || (mat->fp == NULL) )
1284         return 0;
1285 
1286     data_size = Mat_SizeOf(data_type);
1287     READ_DATA_TYPE(mat_uint8_t);
1288     bytesread *= data_size;
1289     return bytesread;
1290 }
1291 
1292 #if defined(HAVE_ZLIB)
1293 /** @brief Reads data of type @c data_type into an unsigned 8-bit integer type
1294  *
1295  * Reads from the MAT file @c len compressed elements of data type @c data_type
1296  * storing them as unsigned 8-bit integers in @c data.
1297  * @ingroup mat_internal
1298  * @param mat MAT file pointer
1299  * @param z Pointer to the zlib stream for inflation
1300  * @param data Pointer to store the output 8-bit integer values
1301  *             (len*sizeof(mat_uint8_t))
1302  * @param data_type one of the @c matio_types enumerations which is the source
1303  *                  data type in the file
1304  * @param len Number of elements of type @c data_type to read from the file
1305  * @retval Number of bytes read from the file
1306  */
1307 int
ReadCompressedUInt8Data(mat_t * mat,z_streamp z,mat_uint8_t * data,enum matio_types data_type,int len)1308 ReadCompressedUInt8Data(mat_t *mat,z_streamp z,mat_uint8_t *data,
1309     enum matio_types data_type,int len)
1310 {
1311     int nBytes = 0, i;
1312     unsigned int data_size;
1313 
1314     if ( (mat == NULL) || (data == NULL) || (z == NULL) )
1315         return 0;
1316 
1317     data_size = (unsigned int)Mat_SizeOf(data_type);
1318     READ_COMPRESSED_DATA_TYPE(mat_uint8_t);
1319     nBytes = len*data_size;
1320     return nBytes;
1321 }
1322 #endif
1323 
1324 #undef READ_DATA
1325 #undef READ_DATA_TYPE
1326 #undef READ_DATA_INT64
1327 #undef READ_DATA_UINT64
1328 #if defined(HAVE_ZLIB)
1329 #undef READ_COMPRESSED_DATA
1330 #undef READ_COMPRESSED_DATA_TYPE
1331 #undef READ_COMPRESSED_DATA_INT64
1332 #undef READ_COMPRESSED_DATA_UINT64
1333 #endif
1334 #if defined(HAVE_ZLIB)
1335 /** @brief Reads data of type @c data_type into a char type
1336  *
1337  * Reads from the MAT file @c len compressed elements of data type @c data_type
1338  * storing them as char's in @c data.
1339  * @ingroup mat_internal
1340  * @param mat MAT file pointer
1341  * @param z Pointer to the zlib stream for inflation
1342  * @param data Pointer to store the output char values (len*sizeof(char))
1343  * @param data_type one of the @c matio_types enumerations which is the source
1344  *                  data type in the file
1345  * @param len Number of elements of type @c data_type to read from the file
1346  * @retval Number of bytes read from the file
1347  */
1348 int
ReadCompressedCharData(mat_t * mat,z_streamp z,char * data,enum matio_types data_type,int len)1349 ReadCompressedCharData(mat_t *mat,z_streamp z,char *data,
1350     enum matio_types data_type,int len)
1351 {
1352     int nBytes = 0;
1353     unsigned int data_size;
1354 
1355     if ( mat == NULL || data == NULL || mat->fp == NULL )
1356         return 0;
1357 
1358     data_size = (unsigned int)Mat_SizeOf(data_type);
1359 
1360     switch ( data_type ) {
1361         case MAT_T_UINT8:
1362         case MAT_T_UTF8:
1363             InflateData(mat,z,data,len*data_size);
1364             break;
1365         case MAT_T_UINT16:
1366         case MAT_T_UTF16:
1367             InflateData(mat,z,data,len*data_size);
1368             if ( mat->byteswap ) {
1369                 int i;
1370                 for ( i = 0; i < len; i++ ) {
1371                     Mat_uint16Swap((mat_uint16_t*)&data[2*i]);
1372                 }
1373             }
1374             break;
1375         default:
1376             Mat_Warning("ReadCompressedCharData: %d is not a supported data "
1377                 "type for character data", data_type);
1378             break;
1379     }
1380     nBytes = len*data_size;
1381     return nBytes;
1382 }
1383 #endif
1384 
1385 int
ReadCharData(mat_t * mat,char * data,enum matio_types data_type,int len)1386 ReadCharData(mat_t *mat,char *data,enum matio_types data_type,int len)
1387 {
1388     int bytesread = 0;
1389     size_t data_size;
1390 
1391     if ( mat == NULL || data == NULL || mat->fp == NULL )
1392         return 0;
1393 
1394     data_size = Mat_SizeOf(data_type);
1395 
1396     switch ( data_type ) {
1397         case MAT_T_UINT8:
1398         case MAT_T_UTF8:
1399             bytesread += fread(data,data_size,len,(FILE*)mat->fp);
1400             break;
1401         case MAT_T_UINT16:
1402         case MAT_T_UTF16:
1403         {
1404             mat_uint16_t ui16;
1405             int i;
1406             if ( mat->byteswap ) {
1407                 for ( i = 0; i < len; i++ ) {
1408                     bytesread += fread(&ui16,data_size,1,(FILE*)mat->fp);
1409                     data[i] = (char)Mat_uint16Swap(&ui16);
1410                 }
1411             } else {
1412                 for ( i = 0; i < len; i++ ) {
1413                     bytesread += fread(&ui16,data_size,1,(FILE*)mat->fp);
1414                     data[i] = (char)ui16;
1415                 }
1416             }
1417             break;
1418         }
1419         default:
1420             Mat_Warning("ReadCharData: %d is not a supported data type for "
1421                 "character data", data_type);
1422             break;
1423     }
1424     return bytesread;
1425 }
1426 
1427 /*
1428  *-------------------------------------------------------------------
1429  *  Routines to read "slabs" of data
1430  *-------------------------------------------------------------------
1431  */
1432 
1433 #define READ_DATA_SLABN_RANK_LOOP \
1434     do { \
1435         for ( j = 1; j < rank; j++ ) { \
1436             cnt[j]++; \
1437             if ( (cnt[j] % edge[j]) == 0 ) { \
1438                 cnt[j] = 0; \
1439                 if ( (I % dimp[j]) != 0 ) { \
1440                     (void)fseek((FILE*)mat->fp,data_size*(dimp[j]-(I % dimp[j]) + dimp[j-1]*start[j]),SEEK_CUR); \
1441                     I += dimp[j]-(I % dimp[j]) + (ptrdiff_t)dimp[j-1]*start[j]; \
1442                 } else if ( start[j] ) { \
1443                     (void)fseek((FILE*)mat->fp,data_size*(dimp[j-1]*start[j]),SEEK_CUR); \
1444                     I += (ptrdiff_t)dimp[j-1]*start[j]; \
1445                 } \
1446             } else { \
1447                 I += inc[j]; \
1448                 (void)fseek((FILE*)mat->fp,data_size*inc[j],SEEK_CUR); \
1449                 break; \
1450             } \
1451         } \
1452     } while (0)
1453 
1454 #define READ_DATA_SLABN(ReadDataFunc) \
1455     do { \
1456         inc[0]  = stride[0]-1; \
1457         dimp[0] = dims[0]; \
1458         N       = edge[0]; \
1459         I       = 0; /* start[0]; */ \
1460         for ( i = 1; i < rank; i++ ) { \
1461             inc[i]  = stride[i]-1; \
1462             dimp[i] = dims[i-1]; \
1463             for ( j = i; j--; ) { \
1464                 inc[i]  *= dims[j]; \
1465                 dimp[i] *= dims[j+1]; \
1466             } \
1467             N *= edge[i]; \
1468             I += (ptrdiff_t)dimp[i-1]*start[i]; \
1469         } \
1470         (void)fseek((FILE*)mat->fp,I*data_size,SEEK_CUR); \
1471         if ( stride[0] == 1 ) { \
1472             for ( i = 0; i < N; i+=edge[0] ) { \
1473                 if ( start[0] ) { \
1474                     (void)fseek((FILE*)mat->fp,start[0]*data_size,SEEK_CUR); \
1475                     I += start[0]; \
1476                 } \
1477                 ReadDataFunc(mat,ptr+i,data_type,edge[0]); \
1478                 I += dims[0]-start[0]; \
1479                 (void)fseek((FILE*)mat->fp,data_size*(dims[0]-edge[0]-start[0]), \
1480                     SEEK_CUR); \
1481                 READ_DATA_SLABN_RANK_LOOP; \
1482             } \
1483         } else { \
1484             for ( i = 0; i < N; i+=edge[0] ) { \
1485                 if ( start[0] ) { \
1486                     (void)fseek((FILE*)mat->fp,start[0]*data_size,SEEK_CUR); \
1487                     I += start[0]; \
1488                 } \
1489                 for ( j = 0; j < edge[0]; j++ ) { \
1490                     ReadDataFunc(mat,ptr+i+j,data_type,1); \
1491                     (void)fseek((FILE*)mat->fp,data_size*(stride[0]-1),SEEK_CUR); \
1492                     I += stride[0]; \
1493                 } \
1494                 I += dims[0]-(ptrdiff_t)edge[0]*stride[0]-start[0]; \
1495                 (void)fseek((FILE*)mat->fp,data_size* \
1496                     (dims[0]-(ptrdiff_t)edge[0]*stride[0]-start[0]),SEEK_CUR); \
1497                 READ_DATA_SLABN_RANK_LOOP; \
1498             } \
1499         } \
1500     } while (0)
1501 
1502 /** @brief Reads data of type @c data_type by user-defined dimensions
1503  *
1504  * @ingroup mat_internal
1505  * @param mat MAT file pointer
1506  * @param data Pointer to store the output data
1507  * @param class_type Type of data class (matio_classes enumerations)
1508  * @param data_type Datatype of the stored data (matio_types enumerations)
1509  * @param rank Number of dimensions in the data
1510  * @param dims Dimensions of the data
1511  * @param start Index to start reading data in each dimension
1512  * @param stride Read every @c stride elements in each dimension
1513  * @param edge Number of elements to read in each dimension
1514  * @retval Number of bytes read from the file, or -1 on error
1515  */
1516 int
ReadDataSlabN(mat_t * mat,void * data,enum matio_classes class_type,enum matio_types data_type,int rank,size_t * dims,int * start,int * stride,int * edge)1517 ReadDataSlabN(mat_t *mat,void *data,enum matio_classes class_type,
1518     enum matio_types data_type,int rank,size_t *dims,int *start,int *stride,
1519     int *edge)
1520 {
1521     int nBytes = 0, i, j, N, I = 0;
1522     int inc[10] = {0,}, cnt[10] = {0,}, dimp[10] = {0,};
1523     size_t data_size;
1524 
1525     if ( (mat   == NULL) || (data   == NULL) || (mat->fp == NULL) ||
1526          (start == NULL) || (stride == NULL) || (edge    == NULL) ) {
1527         return -1;
1528     } else if ( rank > 10 ) {
1529         return -1;
1530     }
1531 
1532     data_size = Mat_SizeOf(data_type);
1533 
1534     switch ( class_type ) {
1535         case MAT_C_DOUBLE:
1536         {
1537             double *ptr = (double*)data;
1538             READ_DATA_SLABN(ReadDoubleData);
1539             break;
1540         }
1541         case MAT_C_SINGLE:
1542         {
1543             float *ptr = (float*)data;
1544             READ_DATA_SLABN(ReadSingleData);
1545             break;
1546         }
1547 #ifdef HAVE_MAT_INT64_T
1548         case MAT_C_INT64:
1549         {
1550             mat_int64_t *ptr = (mat_int64_t*)data;
1551             READ_DATA_SLABN(ReadInt64Data);
1552             break;
1553         }
1554 #endif /* HAVE_MAT_INT64_T */
1555 #ifdef HAVE_MAT_UINT64_T
1556         case MAT_C_UINT64:
1557         {
1558             mat_uint64_t *ptr = (mat_uint64_t*)data;
1559             READ_DATA_SLABN(ReadUInt64Data);
1560             break;
1561         }
1562 #endif /* HAVE_MAT_UINT64_T */
1563         case MAT_C_INT32:
1564         {
1565             mat_int32_t *ptr = (mat_int32_t*)data;
1566             READ_DATA_SLABN(ReadInt32Data);
1567             break;
1568         }
1569         case MAT_C_UINT32:
1570         {
1571             mat_uint32_t *ptr = (mat_uint32_t*)data;
1572             READ_DATA_SLABN(ReadUInt32Data);
1573             break;
1574         }
1575         case MAT_C_INT16:
1576         {
1577             mat_int16_t *ptr = (mat_int16_t*)data;
1578             READ_DATA_SLABN(ReadInt16Data);
1579             break;
1580         }
1581         case MAT_C_UINT16:
1582         {
1583             mat_uint16_t *ptr = (mat_uint16_t*)data;
1584             READ_DATA_SLABN(ReadUInt16Data);
1585             break;
1586         }
1587         case MAT_C_INT8:
1588         {
1589             mat_int8_t *ptr = (mat_int8_t*)data;
1590             READ_DATA_SLABN(ReadInt8Data);
1591             break;
1592         }
1593         case MAT_C_UINT8:
1594         {
1595             mat_uint8_t *ptr = (mat_uint8_t*)data;
1596             READ_DATA_SLABN(ReadUInt8Data);
1597             break;
1598         }
1599         default:
1600             nBytes = 0;
1601     }
1602     return nBytes;
1603 }
1604 
1605 #undef READ_DATA_SLABN
1606 #undef READ_DATA_SLABN_RANK_LOOP
1607 
1608 #if defined(HAVE_ZLIB)
1609 #define READ_COMPRESSED_DATA_SLABN_RANK_LOOP \
1610     do { \
1611         for ( j = 1; j < rank; j++ ) { \
1612             cnt[j]++; \
1613             if ( (cnt[j] % edge[j]) == 0 ) { \
1614                 cnt[j] = 0; \
1615                 if ( (I % dimp[j]) != 0 ) { \
1616                     InflateSkipData(mat,&z_copy,data_type, dimp[j]-(I % dimp[j]) + dimp[j-1]*start[j]); \
1617                     I += dimp[j]-(I % dimp[j]) + (ptrdiff_t)dimp[j-1]*start[j]; \
1618                 } else if ( start[j] ) { \
1619                     InflateSkipData(mat,&z_copy,data_type, dimp[j-1]*start[j]); \
1620                     I += (ptrdiff_t)dimp[j-1]*start[j]; \
1621                 } \
1622             } else { \
1623                 if ( inc[j] ) { \
1624                     I += inc[j]; \
1625                     InflateSkipData(mat,&z_copy,data_type,inc[j]); \
1626                 } \
1627                 break; \
1628             } \
1629         } \
1630     } while (0)
1631 
1632 #define READ_COMPRESSED_DATA_SLABN(ReadDataFunc) \
1633     do { \
1634         inc[0]  = stride[0]-1; \
1635         dimp[0] = dims[0]; \
1636         N       = edge[0]; \
1637         I       = 0; \
1638         for ( i = 1; i < rank; i++ ) { \
1639             inc[i]  = stride[i]-1; \
1640             dimp[i] = dims[i-1]; \
1641             for ( j = i; j--; ) { \
1642                 inc[i]  *= dims[j]; \
1643                 dimp[i] *= dims[j+1]; \
1644             } \
1645             N *= edge[i]; \
1646             I += (ptrdiff_t)dimp[i-1]*start[i]; \
1647         } \
1648         /* Skip all data to the starting indices */ \
1649         InflateSkipData(mat,&z_copy,data_type,I); \
1650         if ( stride[0] == 1 ) { \
1651             for ( i = 0; i < N; i+=edge[0] ) { \
1652                 if ( start[0] ) { \
1653                     InflateSkipData(mat,&z_copy,data_type,start[0]); \
1654                     I += start[0]; \
1655                 } \
1656                 ReadDataFunc(mat,&z_copy,ptr+i,data_type,edge[0]); \
1657                 InflateSkipData(mat,&z_copy,data_type,dims[0]-start[0]-edge[0]); \
1658                 I += dims[0]-start[0]; \
1659                 READ_COMPRESSED_DATA_SLABN_RANK_LOOP; \
1660             } \
1661         } else { \
1662             for ( i = 0; i < N; i+=edge[0] ) { \
1663                 if ( start[0] ) { \
1664                     InflateSkipData(mat,&z_copy,data_type,start[0]); \
1665                     I += start[0]; \
1666                 } \
1667                 for ( j = 0; j < edge[0]-1; j++ ) { \
1668                     ReadDataFunc(mat,&z_copy,ptr+i+j,data_type,1); \
1669                     InflateSkipData(mat,&z_copy,data_type,(stride[0]-1)); \
1670                     I += stride[0]; \
1671                 } \
1672                 ReadDataFunc(mat,&z_copy,ptr+i+j,data_type,1); \
1673                 I += dims[0]-(ptrdiff_t)(edge[0]-1)*stride[0]-start[0]; \
1674                 InflateSkipData(mat,&z_copy,data_type,dims[0]-(ptrdiff_t)(edge[0]-1)*stride[0]-start[0]-1); \
1675                 READ_COMPRESSED_DATA_SLABN_RANK_LOOP; \
1676             } \
1677         } \
1678     } while (0)
1679 
1680 /** @brief Reads data of type @c data_type by user-defined dimensions
1681  *
1682  * @ingroup mat_internal
1683  * @param mat MAT file pointer
1684  * @param z zlib compression stream
1685  * @param data Pointer to store the output data
1686  * @param class_type Type of data class (matio_classes enumerations)
1687  * @param data_type Datatype of the stored data (matio_types enumerations)
1688  * @param rank Number of dimensions in the data
1689  * @param dims Dimensions of the data
1690  * @param start Index to start reading data in each dimension
1691  * @param stride Read every @c stride elements in each dimension
1692  * @param edge Number of elements to read in each dimension
1693  * @retval Number of bytes read from the file, or -1 on error
1694  */
1695 int
ReadCompressedDataSlabN(mat_t * mat,z_streamp z,void * data,enum matio_classes class_type,enum matio_types data_type,int rank,size_t * dims,int * start,int * stride,int * edge)1696 ReadCompressedDataSlabN(mat_t *mat,z_streamp z,void *data,
1697     enum matio_classes class_type,enum matio_types data_type,int rank,
1698     size_t *dims,int *start,int *stride,int *edge)
1699 {
1700     int nBytes = 0, i, j, N, I = 0;
1701     int inc[10] = {0,}, cnt[10] = {0,}, dimp[10] = {0,};
1702     z_stream z_copy = {0,};
1703 
1704     if ( (mat   == NULL) || (data   == NULL) || (mat->fp == NULL) ||
1705          (start == NULL) || (stride == NULL) || (edge    == NULL) ) {
1706         return 1;
1707     } else if ( rank > 10 ) {
1708         return 1;
1709     }
1710 
1711     i = inflateCopy(&z_copy,z);
1712     switch ( class_type ) {
1713         case MAT_C_DOUBLE:
1714         {
1715             double *ptr = (double*)data;
1716             READ_COMPRESSED_DATA_SLABN(ReadCompressedDoubleData);
1717             break;
1718         }
1719         case MAT_C_SINGLE:
1720         {
1721             float *ptr = (float*)data;
1722             READ_COMPRESSED_DATA_SLABN(ReadCompressedSingleData);
1723             break;
1724         }
1725 #ifdef HAVE_MAT_INT64_T
1726         case MAT_C_INT64:
1727         {
1728             mat_int64_t *ptr = (mat_int64_t*)data;
1729             READ_COMPRESSED_DATA_SLABN(ReadCompressedInt64Data);
1730             break;
1731         }
1732 #endif /* HAVE_MAT_INT64_T */
1733 #ifdef HAVE_MAT_UINT64_T
1734         case MAT_C_UINT64:
1735         {
1736             mat_uint64_t *ptr = (mat_uint64_t*)data;
1737             READ_COMPRESSED_DATA_SLABN(ReadCompressedUInt64Data);
1738             break;
1739         }
1740 #endif /* HAVE_MAT_UINT64_T */
1741         case MAT_C_INT32:
1742         {
1743             mat_int32_t *ptr = (mat_int32_t*)data;
1744             READ_COMPRESSED_DATA_SLABN(ReadCompressedInt32Data);
1745             break;
1746         }
1747         case MAT_C_UINT32:
1748         {
1749             mat_uint32_t *ptr = (mat_uint32_t*)data;
1750             READ_COMPRESSED_DATA_SLABN(ReadCompressedUInt32Data);
1751             break;
1752         }
1753         case MAT_C_INT16:
1754         {
1755             mat_int16_t *ptr = (mat_int16_t*)data;
1756             READ_COMPRESSED_DATA_SLABN(ReadCompressedInt16Data);
1757             break;
1758         }
1759         case MAT_C_UINT16:
1760         {
1761             mat_uint16_t *ptr = (mat_uint16_t*)data;
1762             READ_COMPRESSED_DATA_SLABN(ReadCompressedUInt16Data);
1763             break;
1764         }
1765         case MAT_C_INT8:
1766         {
1767             mat_int8_t *ptr = (mat_int8_t*)data;
1768             READ_COMPRESSED_DATA_SLABN(ReadCompressedInt8Data);
1769             break;
1770         }
1771         case MAT_C_UINT8:
1772         {
1773             mat_uint8_t *ptr = (mat_uint8_t*)data;
1774             READ_COMPRESSED_DATA_SLABN(ReadCompressedUInt8Data);
1775             break;
1776         }
1777         default:
1778             nBytes = 0;
1779     }
1780     inflateEnd(&z_copy);
1781     return nBytes;
1782 }
1783 
1784 #undef READ_COMPRESSED_DATA_SLABN
1785 #undef READ_COMPRESSED_DATA_SLABN_RANK_LOOP
1786 #endif
1787 
1788 #define READ_DATA_SLAB1(ReadDataFunc) \
1789     do { \
1790         if ( !stride ) { \
1791             bytesread+=ReadDataFunc(mat,ptr,data_type,edge); \
1792         } else { \
1793             for ( i = 0; i < edge; i++ ) { \
1794                 bytesread+=ReadDataFunc(mat,ptr+i,data_type,1); \
1795                 (void)fseek((FILE*)mat->fp,stride,SEEK_CUR); \
1796             } \
1797         } \
1798     } while (0)
1799 
1800 /** @brief Reads data of type @c data_type by user-defined dimensions for 1-D
1801  *         data
1802  *
1803  * @ingroup mat_internal
1804  * @param mat MAT file pointer
1805  * @param data Pointer to store the output data
1806  * @param class_type Type of data class (matio_classes enumerations)
1807  * @param data_type Datatype of the stored data (matio_types enumerations)
1808  * @param start Index to start reading data
1809  * @param stride Read every @c stride elements
1810  * @param edge Number of elements to read
1811  * @return Number of bytes read from the file, or -1 on error
1812  */
1813 int
ReadDataSlab1(mat_t * mat,void * data,enum matio_classes class_type,enum matio_types data_type,int start,int stride,int edge)1814 ReadDataSlab1(mat_t *mat,void *data,enum matio_classes class_type,
1815     enum matio_types data_type,int start,int stride,int edge)
1816 {
1817     int i;
1818     size_t data_size;
1819     int    bytesread = 0;
1820 
1821     data_size = Mat_SizeOf(data_type);
1822     (void)fseek((FILE*)mat->fp,start*data_size,SEEK_CUR);
1823     stride = data_size*(stride-1);
1824 
1825     switch ( class_type ) {
1826         case MAT_C_DOUBLE:
1827         {
1828             double *ptr = (double*)data;
1829             READ_DATA_SLAB1(ReadDoubleData);
1830             break;
1831         }
1832         case MAT_C_SINGLE:
1833         {
1834             float *ptr = (float*)data;
1835             READ_DATA_SLAB1(ReadSingleData);
1836             break;
1837         }
1838 #ifdef HAVE_MAT_INT64_T
1839         case MAT_C_INT64:
1840         {
1841             mat_int64_t *ptr = (mat_int64_t*)data;
1842             READ_DATA_SLAB1(ReadInt64Data);
1843             break;
1844         }
1845 #endif /* HAVE_MAT_INT64_T */
1846 #ifdef HAVE_MAT_UINT64_T
1847         case MAT_C_UINT64:
1848         {
1849             mat_uint64_t *ptr = (mat_uint64_t*)data;
1850             READ_DATA_SLAB1(ReadUInt64Data);
1851             break;
1852         }
1853 #endif /* HAVE_MAT_UINT64_T */
1854         case MAT_C_INT32:
1855         {
1856             mat_int32_t *ptr = (mat_int32_t*)data;
1857             READ_DATA_SLAB1(ReadInt32Data);
1858             break;
1859         }
1860         case MAT_C_UINT32:
1861         {
1862             mat_uint32_t *ptr = (mat_uint32_t*)data;
1863             READ_DATA_SLAB1(ReadUInt32Data);
1864             break;
1865         }
1866         case MAT_C_INT16:
1867         {
1868             mat_int16_t *ptr = (mat_int16_t*)data;
1869             READ_DATA_SLAB1(ReadInt16Data);
1870             break;
1871         }
1872         case MAT_C_UINT16:
1873         {
1874             mat_uint16_t *ptr = (mat_uint16_t*)data;
1875             READ_DATA_SLAB1(ReadUInt16Data);
1876             break;
1877         }
1878         case MAT_C_INT8:
1879         {
1880             mat_int8_t *ptr = (mat_int8_t*)data;
1881             READ_DATA_SLAB1(ReadInt8Data);
1882             break;
1883         }
1884         case MAT_C_UINT8:
1885         {
1886             mat_uint8_t *ptr = (mat_uint8_t*)data;
1887             READ_DATA_SLAB1(ReadUInt8Data);
1888             break;
1889         }
1890         default:
1891             return 0;
1892     }
1893 
1894     return bytesread;
1895 }
1896 
1897 #undef READ_DATA_SLAB1
1898 
1899 #define READ_DATA_SLAB2(ReadDataFunc) \
1900     do { \
1901         /* If stride[0] is 1 and stride[1] is 1, we are reading all of the */ \
1902         /* data so get rid of the loops. */ \
1903         if ( (stride[0] == 1 && edge[0] == dims[0]) && \
1904              (stride[1] == 1) ) { \
1905             ReadDataFunc(mat,ptr,data_type,(ptrdiff_t)edge[0]*edge[1]); \
1906         } else { \
1907             row_stride = (long)(stride[0]-1)*data_size; \
1908             col_stride = (long)stride[1]*dims[0]*data_size; \
1909             pos = ftell((FILE*)mat->fp); \
1910             if ( pos == -1L ) { \
1911                 Mat_Critical("Couldn't determine file position"); \
1912                 return -1; \
1913             } \
1914             (void)fseek((FILE*)mat->fp,(long)start[1]*dims[0]*data_size,SEEK_CUR); \
1915             for ( i = 0; i < edge[1]; i++ ) { \
1916                 pos = ftell((FILE*)mat->fp); \
1917                 if ( pos == -1L ) { \
1918                     Mat_Critical("Couldn't determine file position"); \
1919                     return -1; \
1920                 } \
1921                 (void)fseek((FILE*)mat->fp,(long)start[0]*data_size,SEEK_CUR); \
1922                 for ( j = 0; j < edge[0]; j++ ) { \
1923                     ReadDataFunc(mat,ptr++,data_type,1); \
1924                     (void)fseek((FILE*)mat->fp,row_stride,SEEK_CUR); \
1925                 } \
1926                 pos2 = ftell((FILE*)mat->fp); \
1927                 if ( pos2 == -1L ) { \
1928                     Mat_Critical("Couldn't determine file position"); \
1929                     return -1; \
1930                 } \
1931                 pos +=col_stride-pos2; \
1932                 (void)fseek((FILE*)mat->fp,pos,SEEK_CUR); \
1933             } \
1934         } \
1935     } while (0)
1936 
1937 /** @brief Reads data of type @c data_type by user-defined dimensions for 2-D
1938  *         data
1939  *
1940  * @ingroup mat_internal
1941  * @param mat MAT file pointer
1942  * @param data Pointer to store the output data
1943  * @param class_type Type of data class (matio_classes enumerations)
1944  * @param data_type Datatype of the stored data (matio_types enumerations)
1945  * @param dims Dimensions of the data
1946  * @param start Index to start reading data in each dimension
1947  * @param stride Read every @c stride elements in each dimension
1948  * @param edge Number of elements to read in each dimension
1949  * @retval Number of bytes read from the file, or -1 on error
1950  */
1951 int
ReadDataSlab2(mat_t * mat,void * data,enum matio_classes class_type,enum matio_types data_type,size_t * dims,int * start,int * stride,int * edge)1952 ReadDataSlab2(mat_t *mat,void *data,enum matio_classes class_type,
1953     enum matio_types data_type,size_t *dims,int *start,int *stride,int *edge)
1954 {
1955     int nBytes = 0, data_size, i, j;
1956     long pos, row_stride, col_stride, pos2;
1957 
1958     if ( (mat   == NULL) || (data   == NULL) || (mat->fp == NULL) ||
1959          (start == NULL) || (stride == NULL) || (edge    == NULL) ) {
1960         return 0;
1961     }
1962 
1963     data_size = Mat_SizeOf(data_type);
1964 
1965     switch ( class_type ) {
1966         case MAT_C_DOUBLE:
1967         {
1968             double *ptr = (double*)data;
1969             READ_DATA_SLAB2(ReadDoubleData);
1970             break;
1971         }
1972         case MAT_C_SINGLE:
1973         {
1974             float *ptr = (float*)data;
1975             READ_DATA_SLAB2(ReadSingleData);
1976             break;
1977         }
1978 #ifdef HAVE_MAT_INT64_T
1979         case MAT_C_INT64:
1980         {
1981             mat_int64_t *ptr = (mat_int64_t*)data;
1982             READ_DATA_SLAB2(ReadInt64Data);
1983             break;
1984         }
1985 #endif /* HAVE_MAT_INT64_T */
1986 #ifdef HAVE_MAT_UINT64_T
1987         case MAT_C_UINT64:
1988         {
1989             mat_uint64_t *ptr = (mat_uint64_t*)data;
1990             READ_DATA_SLAB2(ReadUInt64Data);
1991             break;
1992         }
1993 #endif /* HAVE_MAT_UINT64_T */
1994         case MAT_C_INT32:
1995         {
1996             mat_int32_t *ptr = (mat_int32_t*)data;
1997             READ_DATA_SLAB2(ReadInt32Data);
1998             break;
1999         }
2000         case MAT_C_UINT32:
2001         {
2002             mat_uint32_t *ptr = (mat_uint32_t*)data;
2003             READ_DATA_SLAB2(ReadUInt32Data);
2004             break;
2005         }
2006         case MAT_C_INT16:
2007         {
2008             mat_int16_t *ptr = (mat_int16_t*)data;
2009             READ_DATA_SLAB2(ReadInt16Data);
2010             break;
2011         }
2012         case MAT_C_UINT16:
2013         {
2014             mat_uint16_t *ptr = (mat_uint16_t*)data;
2015             READ_DATA_SLAB2(ReadUInt16Data);
2016             break;
2017         }
2018         case MAT_C_INT8:
2019         {
2020             mat_int8_t *ptr = (mat_int8_t*)data;
2021             READ_DATA_SLAB2(ReadInt8Data);
2022             break;
2023         }
2024         case MAT_C_UINT8:
2025         {
2026             mat_uint8_t *ptr = (mat_uint8_t*)data;
2027             READ_DATA_SLAB2(ReadUInt8Data);
2028             break;
2029         }
2030         default:
2031             nBytes = 0;
2032     }
2033     return nBytes;
2034 }
2035 
2036 #undef READ_DATA_SLAB2
2037 
2038 #if defined(HAVE_ZLIB)
2039 #define READ_COMPRESSED_DATA_SLAB1(ReadDataFunc) \
2040     do { \
2041         if ( !stride ) { \
2042             nBytes+=ReadDataFunc(mat,&z_copy,ptr,data_type,edge); \
2043         } else { \
2044             for ( i = 0; i < edge; i++ ) { \
2045                 nBytes+=ReadDataFunc(mat,&z_copy,ptr+i,data_type,1); \
2046                 InflateSkipData(mat,&z_copy,data_type,stride); \
2047             } \
2048         } \
2049     } while (0)
2050 
2051 /** @brief Reads data of type @c data_type by user-defined dimensions for 1-D
2052  *         data
2053  *
2054  * @ingroup mat_internal
2055  * @param mat MAT file pointer
2056  * @param z zlib compression stream
2057  * @param data Pointer to store the output data
2058  * @param class_type Type of data class (matio_classes enumerations)
2059  * @param data_type Datatype of the stored data (matio_types enumerations)
2060  * @param dims Dimensions of the data
2061  * @param start Index to start reading data in each dimension
2062  * @param stride Read every @c stride elements in each dimension
2063  * @param edge Number of elements to read in each dimension
2064  * @retval Number of bytes read from the file, or -1 on error
2065  */
2066 int
ReadCompressedDataSlab1(mat_t * mat,z_streamp z,void * data,enum matio_classes class_type,enum matio_types data_type,int start,int stride,int edge)2067 ReadCompressedDataSlab1(mat_t *mat,z_streamp z,void *data,
2068     enum matio_classes class_type,enum matio_types data_type,int start,
2069     int stride,int edge)
2070 {
2071     int nBytes = 0, i, err;
2072     z_stream z_copy = {0,};
2073 
2074     if ( (mat == NULL) || (data == NULL) || (mat->fp == NULL) )
2075         return 0;
2076 
2077     stride--;
2078     err = inflateCopy(&z_copy,z);
2079     InflateSkipData(mat,&z_copy,data_type,start);
2080     switch ( class_type ) {
2081         case MAT_C_DOUBLE:
2082         {
2083             double *ptr = (double*)data;
2084             READ_COMPRESSED_DATA_SLAB1(ReadCompressedDoubleData);
2085             break;
2086         }
2087         case MAT_C_SINGLE:
2088         {
2089             float *ptr = (float*)data;
2090             READ_COMPRESSED_DATA_SLAB1(ReadCompressedSingleData);
2091             break;
2092         }
2093 #ifdef HAVE_MAT_INT64_T
2094         case MAT_C_INT64:
2095         {
2096             mat_int64_t *ptr = (mat_int64_t*)data;
2097             READ_COMPRESSED_DATA_SLAB1(ReadCompressedInt64Data);
2098             break;
2099         }
2100 #endif /* HAVE_MAT_INT64_T */
2101 #ifdef HAVE_MAT_UINT64_T
2102         case MAT_C_UINT64:
2103         {
2104             mat_uint64_t *ptr = (mat_uint64_t*)data;
2105             READ_COMPRESSED_DATA_SLAB1(ReadCompressedUInt64Data);
2106             break;
2107         }
2108 #endif /* HAVE_MAT_UINT64_T */
2109         case MAT_C_INT32:
2110         {
2111             mat_int32_t *ptr = (mat_int32_t*)data;
2112             READ_COMPRESSED_DATA_SLAB1(ReadCompressedInt32Data);
2113             break;
2114         }
2115         case MAT_C_UINT32:
2116         {
2117             mat_uint32_t *ptr = (mat_uint32_t*)data;
2118             READ_COMPRESSED_DATA_SLAB1(ReadCompressedUInt32Data);
2119             break;
2120         }
2121         case MAT_C_INT16:
2122         {
2123             mat_int16_t *ptr = (mat_int16_t*)data;
2124             READ_COMPRESSED_DATA_SLAB1(ReadCompressedInt16Data);
2125             break;
2126         }
2127         case MAT_C_UINT16:
2128         {
2129             mat_uint16_t *ptr = (mat_uint16_t*)data;
2130             READ_COMPRESSED_DATA_SLAB1(ReadCompressedUInt16Data);
2131             break;
2132         }
2133         case MAT_C_INT8:
2134         {
2135             mat_int8_t *ptr = (mat_int8_t*)data;
2136             READ_COMPRESSED_DATA_SLAB1(ReadCompressedInt8Data);
2137             break;
2138         }
2139         case MAT_C_UINT8:
2140         {
2141             mat_uint8_t *ptr = (mat_uint8_t*)data;
2142             READ_COMPRESSED_DATA_SLAB1(ReadCompressedUInt8Data);
2143             break;
2144         }
2145         default:
2146             break;
2147     }
2148     inflateEnd(&z_copy);
2149     return nBytes;
2150 }
2151 
2152 #undef READ_COMPRESSED_DATA_SLAB1
2153 
2154 #define READ_COMPRESSED_DATA_SLAB2(ReadDataFunc) \
2155     do {\
2156         row_stride = (stride[0]-1); \
2157         col_stride = (stride[1]-1)*dims[0]; \
2158         InflateSkipData(mat,&z_copy,data_type,start[1]*dims[0]); \
2159         /* If stride[0] is 1 and stride[1] is 1, we are reading all of the */ \
2160         /* data so get rid of the loops.  If stride[0] is 1 and stride[1] */ \
2161         /* is not 0, we are reading whole columns, so get rid of inner loop */ \
2162         /* to speed up the code */ \
2163         if ( (stride[0] == 1 && edge[0] == dims[0]) && \
2164              (stride[1] == 1) ) { \
2165             ReadDataFunc(mat,&z_copy,ptr,data_type,(ptrdiff_t)edge[0]*edge[1]); \
2166         } else if ( stride[0] == 1 ) { \
2167             for ( i = 0; i < edge[1]; i++ ) { \
2168                 InflateSkipData(mat,&z_copy,data_type,start[0]); \
2169                 ReadDataFunc(mat,&z_copy,ptr,data_type,edge[0]); \
2170                 ptr += edge[0]; \
2171                 pos = dims[0]-(ptrdiff_t)(edge[0]-1)*stride[0]-1-start[0] + col_stride; \
2172                 InflateSkipData(mat,&z_copy,data_type,pos); \
2173             } \
2174         } else { \
2175             for ( i = 0; i < edge[1]; i++ ) { \
2176                 InflateSkipData(mat,&z_copy,data_type,start[0]); \
2177                 for ( j = 0; j < edge[0]-1; j++ ) { \
2178                     ReadDataFunc(mat,&z_copy,ptr++,data_type,1); \
2179                     InflateSkipData(mat,&z_copy,data_type,row_stride); \
2180                 } \
2181                 ReadDataFunc(mat,&z_copy,ptr++,data_type,1); \
2182                 pos = dims[0]-(ptrdiff_t)(edge[0]-1)*stride[0]-1-start[0] + col_stride; \
2183                 InflateSkipData(mat,&z_copy,data_type,pos); \
2184             } \
2185         } \
2186     } while (0)
2187 
2188 /** @brief Reads data of type @c data_type by user-defined dimensions for 2-D
2189  *         data
2190  *
2191  * @ingroup mat_internal
2192  * @param mat MAT file pointer
2193  * @param z zlib compression stream
2194  * @param data Pointer to store the output data
2195  * @param class_type Type of data class (matio_classes enumerations)
2196  * @param data_type Datatype of the stored data (matio_types enumerations)
2197  * @param dims Dimensions of the data
2198  * @param start Index to start reading data in each dimension
2199  * @param stride Read every @c stride elements in each dimension
2200  * @param edge Number of elements to read in each dimension
2201  * @retval Number of bytes read from the file, or -1 on error
2202  */
2203 int
ReadCompressedDataSlab2(mat_t * mat,z_streamp z,void * data,enum matio_classes class_type,enum matio_types data_type,size_t * dims,int * start,int * stride,int * edge)2204 ReadCompressedDataSlab2(mat_t *mat,z_streamp z,void *data,
2205     enum matio_classes class_type,enum matio_types data_type,size_t *dims,
2206     int *start,int *stride,int *edge)
2207 {
2208     int nBytes = 0, i, j, err;
2209     int pos, row_stride, col_stride;
2210     z_stream z_copy = {0,};
2211 
2212     if ( (mat   == NULL) || (data   == NULL) || (mat->fp == NULL) ||
2213          (start == NULL) || (stride == NULL) || (edge    == NULL) ) {
2214         return 0;
2215     }
2216 
2217     err = inflateCopy(&z_copy,z);
2218     switch ( class_type ) {
2219         case MAT_C_DOUBLE:
2220         {
2221             double *ptr = (double*)data;
2222             READ_COMPRESSED_DATA_SLAB2(ReadCompressedDoubleData);
2223             break;
2224         }
2225         case MAT_C_SINGLE:
2226         {
2227             float *ptr = (float*)data;
2228             READ_COMPRESSED_DATA_SLAB2(ReadCompressedSingleData);
2229             break;
2230         }
2231 #ifdef HAVE_MAT_INT64_T
2232         case MAT_C_INT64:
2233         {
2234             mat_int64_t *ptr = (mat_int64_t*)data;
2235             READ_COMPRESSED_DATA_SLAB2(ReadCompressedInt64Data);
2236             break;
2237         }
2238 #endif /* HAVE_MAT_INT64_T */
2239 #ifdef HAVE_MAT_UINT64_T
2240         case MAT_C_UINT64:
2241         {
2242             mat_uint64_t *ptr = (mat_uint64_t*)data;
2243             READ_COMPRESSED_DATA_SLAB2(ReadCompressedUInt64Data);
2244             break;
2245         }
2246 #endif /* HAVE_MAT_UINT64_T */
2247         case MAT_C_INT32:
2248         {
2249             mat_int32_t *ptr = (mat_int32_t*)data;
2250             READ_COMPRESSED_DATA_SLAB2(ReadCompressedInt32Data);
2251             break;
2252         }
2253         case MAT_C_UINT32:
2254         {
2255             mat_uint32_t *ptr = (mat_uint32_t*)data;
2256             READ_COMPRESSED_DATA_SLAB2(ReadCompressedUInt32Data);
2257             break;
2258         }
2259         case MAT_C_INT16:
2260         {
2261             mat_int16_t *ptr = (mat_int16_t*)data;
2262             READ_COMPRESSED_DATA_SLAB2(ReadCompressedInt16Data);
2263             break;
2264         }
2265         case MAT_C_UINT16:
2266         {
2267             mat_uint16_t *ptr = (mat_uint16_t*)data;
2268             READ_COMPRESSED_DATA_SLAB2(ReadCompressedUInt16Data);
2269             break;
2270         }
2271         case MAT_C_INT8:
2272         {
2273             mat_int8_t *ptr = (mat_int8_t*)data;
2274             READ_COMPRESSED_DATA_SLAB2(ReadCompressedInt8Data);
2275             break;
2276         }
2277         case MAT_C_UINT8:
2278         {
2279             mat_uint8_t *ptr = (mat_uint8_t*)data;
2280             READ_COMPRESSED_DATA_SLAB2(ReadCompressedUInt8Data);
2281             break;
2282         }
2283         default:
2284             nBytes = 0;
2285     }
2286     inflateEnd(&z_copy);
2287     return nBytes;
2288 }
2289 
2290 #undef READ_COMPRESSED_DATA_SLAB2
2291 #endif
2292 
2293 /** @endcond */
2294