mat.c 61 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932
  1. /** @file mat.c
  2. * Matlab MAT version 5 file functions
  3. * @ingroup MAT
  4. */
  5. /*
  6. * Copyright (C) 2005-2006 Christopher C. Hulbert
  7. *
  8. * This library is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU Lesser General Public
  10. * License as published by the Free Software Foundation; either
  11. * version 2.1 of the License, or (at your option) any later version.
  12. *
  13. * This library is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  16. * Lesser General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with this library; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  21. */
  22. /* FIXME: Implement Unicode support */
  23. #include <stdlib.h>
  24. #include <string.h>
  25. #include <stdio.h>
  26. #include <math.h>
  27. #include <time.h>
  28. #include "matio.h"
  29. #include "mat5.h"
  30. #include "mat4.h"
  31. #include "matio_private.h"
  32. static void
  33. ReadData(mat_t *mat, matvar_t *matvar)
  34. {
  35. if ( mat == NULL || matvar == NULL || mat->fp == NULL )
  36. return;
  37. else if ( mat->version != MAT_FT_MAT4 )
  38. Read5(mat,matvar);
  39. else if ( mat->version == MAT_FT_MAT4 )
  40. Read4(mat,matvar);
  41. return;
  42. }
  43. /*
  44. *====================================================================
  45. * Public Functions
  46. *====================================================================
  47. */
  48. /** @brief Creates a new Matlab MAT file
  49. *
  50. * Tries to create a new Matlab MAT file with the given name and optional
  51. * header string. If no header string is given, the default string
  52. * is used containing the software, version, and date in it. If a header
  53. * string is given, at most the first 116 characters is written to the file.
  54. * The given header string need not be the full 116 characters, but MUST be
  55. * NULL terminated.
  56. * @ingroup MAT
  57. * @param matname Name of MAT file to create
  58. * @param hdr_str Optional header string, NULL to use default
  59. * @return A pointer to the MAT file or NULL if it failed. This is not a
  60. * simple FILE * and should not be used as one.
  61. */
  62. mat_t *
  63. Mat_Create(const char *matname,const char *hdr_str)
  64. {
  65. FILE *fp = NULL;
  66. mat_int16_t endian = 0, version;
  67. mat_t *mat = NULL;
  68. size_t err;
  69. time_t t;
  70. fp = fopen(matname,"wb");
  71. if ( !fp )
  72. return NULL;
  73. mat = malloc(sizeof(*mat));
  74. if ( !mat ) {
  75. fclose(fp);
  76. return NULL;
  77. }
  78. mat->fp = NULL;
  79. mat->header = NULL;
  80. mat->subsys_offset = NULL;
  81. mat->filename = NULL;
  82. mat->version = 0;
  83. mat->byteswap = 0;
  84. mat->mode = 0;
  85. mat->bof = 0;
  86. t = time(NULL);
  87. mat->fp = fp;
  88. mat->filename = strdup_printf("%s",matname);
  89. mat->mode = MAT_ACC_RDWR;
  90. mat->byteswap = 0;
  91. mat->header = calloc(1,128);
  92. mat->subsys_offset = calloc(1,16);
  93. memset(mat->header,' ',128);
  94. if ( hdr_str == NULL ) {
  95. err = mat_snprintf(mat->header,116,"MATLAB 5.0 MAT-file, Platform: %s, "
  96. "Created By: libmatio v%d.%d.%d on %s", MATIO_PLATFORM,
  97. MATIO_MAJOR_VERSION, MATIO_MINOR_VERSION, MATIO_RELEASE_LEVEL,
  98. ctime(&t));
  99. mat->header[115] = '\0'; /* Just to make sure it's NULL terminated */
  100. } else {
  101. err = mat_snprintf(mat->header,116,"%s",hdr_str);
  102. }
  103. mat->header[err] = ' ';
  104. mat_snprintf(mat->subsys_offset,15," ");
  105. mat->version = (int)0x0100;
  106. endian = 0x4d49;
  107. version = 0x0100;
  108. err = fwrite(mat->header,1,116,mat->fp);
  109. err = fwrite(mat->subsys_offset,1,8,mat->fp);
  110. err = fwrite(&version,2,1,mat->fp);
  111. err = fwrite(&endian,2,1,mat->fp);
  112. return mat;
  113. }
  114. /** @brief Opens an existing Matlab MAT file
  115. *
  116. * Tries to open a Matlab MAT file with the given name
  117. * @ingroup MAT
  118. * @param matname Name of MAT file to open
  119. * @param mode File access mode (MAT_ACC_RDONLY,MAT_ACC_RDWR,etc).
  120. * @return A pointer to the MAT file or NULL if it failed. This is not a
  121. * simple FILE * and should not be used as one.
  122. */
  123. mat_t *
  124. Mat_Open(const char *matname,int mode)
  125. {
  126. FILE *fp = NULL;
  127. mat_int16_t tmp, tmp2;
  128. int err;
  129. mat_t *mat = NULL;
  130. if ( (mode & 0x000000ff) == MAT_ACC_RDONLY ) {
  131. fp = fopen( matname, "rb" );
  132. if ( !fp )
  133. return NULL;
  134. } else if ( (mode & 0x000000ff) == MAT_ACC_RDWR ) {
  135. fp = fopen( matname, "r+b" );
  136. if ( !fp ) {
  137. mat = Mat_Create(matname,NULL);
  138. return mat;
  139. }
  140. } else {
  141. mat = Mat_Create(matname,NULL);
  142. return mat;
  143. }
  144. mat = malloc(sizeof(mat_t));
  145. if ( !mat ) {
  146. Mat_Critical("Couldn't allocate memory for the MAT file");
  147. fclose(fp);
  148. return NULL;
  149. }
  150. mat->fp = fp;
  151. if ( mode & MAT_FT_MAT4 ) {
  152. mat->header = NULL;
  153. mat->subsys_offset = NULL;
  154. mat->version = MAT_FT_MAT4;
  155. mat->byteswap = 0;
  156. mat->mode = mode;
  157. mat->filename = strdup_printf("%s",matname);
  158. mat->bof = ftell(mat->fp);
  159. } else {
  160. mat->header = malloc(128);
  161. mat->subsys_offset = malloc(8);
  162. mat->filename = NULL;
  163. err = fread(mat->header,1,116,fp);
  164. mat->header[116] = '\0';
  165. err = fread(mat->subsys_offset,1,8,fp);
  166. err = fread(&tmp2,2,1,fp);
  167. fread (&tmp,1,2,fp);
  168. mat->bof = ftell(mat->fp);
  169. mat->byteswap = -1;
  170. if (tmp == 0x4d49)
  171. mat->byteswap = 0;
  172. else if (tmp == 0x494d) {
  173. mat->byteswap = 1;
  174. Mat_int16Swap(&tmp2);
  175. }
  176. mat->version = (int)tmp2;
  177. if ( mat->byteswap < 0 ) {
  178. Mat_Critical("%s does not seem to be a valid MAT file",matname);
  179. Mat_Close(mat);
  180. mat=NULL;
  181. } else if ( mat->version != 0x0100 ) {
  182. Mat_Critical("%s is not a version 5 MAT file", matname);
  183. Mat_Close(mat);
  184. mat=NULL;
  185. } else {
  186. mat->filename = strdup_printf("%s",matname);
  187. mat->mode = mode;
  188. }
  189. }
  190. return mat;
  191. }
  192. /** @brief Closes an open Matlab MAT file
  193. *
  194. * Closes the given Matlab MAT file and frees any memory with it.
  195. * @ingroup MAT
  196. * @param mat Pointer to the MAT file
  197. * @retval 0
  198. */
  199. int
  200. Mat_Close( mat_t *mat )
  201. {
  202. if ( NULL != mat ) {
  203. if ( mat->fp )
  204. fclose(mat->fp);
  205. if ( mat->header )
  206. free(mat->header);
  207. if ( mat->subsys_offset )
  208. free(mat->subsys_offset);
  209. if ( mat->filename )
  210. free(mat->filename);
  211. free(mat);
  212. }
  213. return 0;
  214. }
  215. /** @brief Rewinds a Matlab MAT file to the first variable
  216. *
  217. * Rewinds a Matlab MAT file to the first variable
  218. * @ingroup MAT
  219. * @param mat Pointer to the MAT file
  220. * @retval 0 on success
  221. */
  222. int
  223. Mat_Rewind( mat_t *mat )
  224. {
  225. if ( mat->version != MAT_FT_MAT4 )
  226. fseek(mat->fp,128L,SEEK_SET);
  227. else
  228. fseek(mat->fp,0L,SEEK_SET);
  229. return 0;
  230. }
  231. /** @brief Returns the size of a Matlab Class
  232. *
  233. * Returns the size (in bytes) of the matlab class class_type
  234. * @ingroup MAT
  235. * @param class_type Matlab class type (MAT_C_*)
  236. * @returns Size of the class
  237. */
  238. size_t
  239. Mat_SizeOfClass(int class_type)
  240. {
  241. switch (class_type) {
  242. case MAT_C_DOUBLE:
  243. return sizeof(double);
  244. case MAT_C_SINGLE:
  245. return sizeof(float);
  246. #ifdef HAVE_MAT_INT64_T
  247. case MAT_C_INT64:
  248. return sizeof(mat_int64_t);
  249. #endif
  250. #ifdef HAVE_MAT_UINT64_T
  251. case MAT_C_UINT64:
  252. return sizeof(mat_uint64_t);
  253. #endif
  254. case MAT_C_INT32:
  255. return sizeof(mat_int32_t);
  256. case MAT_C_UINT32:
  257. return sizeof(mat_uint32_t);
  258. case MAT_C_INT16:
  259. return sizeof(mat_int16_t);
  260. case MAT_C_UINT16:
  261. return sizeof(mat_uint16_t);
  262. case MAT_C_INT8:
  263. return sizeof(mat_int8_t);
  264. case MAT_C_UINT8:
  265. return sizeof(mat_uint8_t);
  266. case MAT_C_CHAR:
  267. return sizeof(mat_int16_t);
  268. default:
  269. return 0;
  270. }
  271. }
  272. /*
  273. *===================================================================
  274. * MAT Variable Functions
  275. *===================================================================
  276. */
  277. /** @brief Allocates memory for a new matvar_t and initializes all the fields
  278. *
  279. * @ingroup MAT
  280. * @return A newly allocated matvar_t
  281. */
  282. matvar_t *
  283. Mat_VarCalloc(void)
  284. {
  285. matvar_t *matvar;
  286. matvar = malloc(sizeof(*matvar));
  287. if ( NULL != matvar ) {
  288. matvar->nbytes = 0;
  289. matvar->rank = 0;
  290. matvar->data_type = 0;
  291. matvar->data_size = 0;
  292. matvar->class_type = 0;
  293. matvar->isComplex = 0;
  294. matvar->isGlobal = 0;
  295. matvar->isLogical = 0;
  296. matvar->dims = NULL;
  297. matvar->name = NULL;
  298. matvar->data = NULL;
  299. matvar->mem_conserve = 0;
  300. matvar->compression = 0;
  301. matvar->fpos = 0;
  302. matvar->datapos = 0;
  303. matvar->fp = NULL;
  304. #if defined(HAVE_ZLIB)
  305. matvar->z = NULL;
  306. #endif
  307. }
  308. return matvar;
  309. }
  310. /** @brief Creates a MAT Variable with the given name and (optionally) data
  311. *
  312. * Creates a MAT variable that can be written to a Matlab MAT file with the
  313. * given name, data type, dimensions and data. Rank should always be 2 or more.
  314. * i.e. Scalar values would have rank=2 and dims[2] = {1,1}. Data type is
  315. * one of the MAT_T types. MAT adds MAT_T_STRUCT and MAT_T_CELL to create
  316. * Structures and Cell Arrays respectively. For MAT_T_STRUCT, data should be a
  317. * NULL terminated array of matvar_t * variables (i.e. for a 3x2 structure with
  318. * 10 fields, there should be 61 matvar_t * variables where the last one is
  319. * NULL). For cell arrays, the NULL termination isn't necessary. So to create
  320. * a cell array of size 3x2, data would be the address of an array of 6
  321. * matvar_t * variables.
  322. *
  323. * EXAMPLE:
  324. * To create a struct of size 3x2 with 3 fields:
  325. * @code
  326. * int rank=2, dims[2] = {3,2}, nfields = 3;
  327. * matvar_t **vars;
  328. *
  329. * vars = malloc((3*2*nfields+1)*sizeof(matvar_t *));
  330. * vars[0] = Mat_VarCreate(...);
  331. * :
  332. * vars[3*2*nfields-1] = Mat_VarCreate(...);
  333. * vars[3*2*nfields] = NULL;
  334. * @endcode
  335. *
  336. * EXAMPLE:
  337. * To create a cell array of size 3x2:
  338. * @code
  339. * int rank=2, dims[2] = {3,2};
  340. * matvar_t **vars;
  341. *
  342. * vars = malloc(3*2*sizeof(matvar_t *));
  343. * vars[0] = Mat_VarCreate(...);
  344. * :
  345. * vars[5] = Mat_VarCreate(...);
  346. * @endcode
  347. *
  348. * @ingroup MAT
  349. * @param name Name of the variable to create
  350. * @param class_type class type of the variable in Matlab(one of the mx Classes)
  351. * @param data_type data type of the variable (one of the MAT_T_ Types)
  352. * @param rank Rank of the variable
  353. * @param dims array of dimensions of the variable of size rank
  354. * @param data pointer to the data
  355. * @param opt 0, or bitwise or of the following options:
  356. * - MEM_CONSERVE to just use the pointer to the data and not copy the data
  357. * itself. Note that the pointer should not be freed until you are done
  358. * with the mat variable. The Mat_VarFree function will NOT free
  359. * data that was created with MEM_CONSERVE, so free it yourself.
  360. * - MAT_F_COMPLEX to specify that the data is complex. The data variable should
  361. * be a contigouse piece of memory with the real part written first and
  362. * the imaginary second
  363. * - MAT_F_GLOBAL to assign the variable as a global variable
  364. * - MAT_F_LOGICAL to specify that it is a logical variable
  365. * @return A MAT variable that can be written to a file or otherwise used
  366. */
  367. matvar_t *
  368. Mat_VarCreate(const char *name,int class_type,int data_type,int rank,int *dims,
  369. void *data,int opt)
  370. {
  371. int i, nmemb = 1, nfields = 0;
  372. matvar_t *matvar = NULL;
  373. if (dims == NULL) return NULL;
  374. matvar = Mat_VarCalloc();
  375. if ( NULL == matvar )
  376. return NULL;
  377. matvar->compression = COMPRESSION_NONE;
  378. matvar->isComplex = opt & MAT_F_COMPLEX;
  379. matvar->isGlobal = opt & MAT_F_GLOBAL;
  380. matvar->isLogical = opt & MAT_F_LOGICAL;
  381. if ( name )
  382. matvar->name = strdup_printf("%s",name);
  383. matvar->rank = rank;
  384. matvar->dims = malloc(matvar->rank*sizeof(int));
  385. for ( i = 0; i < matvar->rank; i++ ) {
  386. matvar->dims[i] = dims[i];
  387. nmemb *= dims[i];
  388. }
  389. matvar->class_type = class_type;
  390. matvar->data_type = data_type;
  391. switch ( data_type ) {
  392. case MAT_T_INT8:
  393. matvar->data_size = 1;
  394. break;
  395. case MAT_T_UINT8:
  396. matvar->data_size = 1;
  397. break;
  398. case MAT_T_INT16:
  399. matvar->data_size = 2;
  400. break;
  401. case MAT_T_UINT16:
  402. matvar->data_size = 2;
  403. break;
  404. case MAT_T_INT64:
  405. matvar->data_size = 8;
  406. break;
  407. case MAT_T_UINT64:
  408. matvar->data_size = 8;
  409. break;
  410. case MAT_T_INT32:
  411. matvar->data_size = 4;
  412. break;
  413. case MAT_T_UINT32:
  414. matvar->data_size = 4;
  415. break;
  416. case MAT_T_SINGLE:
  417. matvar->data_size = sizeof(float);
  418. break;
  419. case MAT_T_DOUBLE:
  420. matvar->data_size = sizeof(double);
  421. break;
  422. case MAT_T_UTF8:
  423. matvar->data_size = 1;
  424. break;
  425. case MAT_T_UTF16:
  426. matvar->data_size = 2;
  427. break;
  428. case MAT_T_UTF32:
  429. matvar->data_size = 4;
  430. break;
  431. case MAT_T_CELL:
  432. matvar->data_size = sizeof(matvar_t **);
  433. break;
  434. case MAT_T_STRUCT:
  435. {
  436. matvar_t **fields;
  437. if ( data == NULL )
  438. break;
  439. fields = data;
  440. nfields = 0;
  441. while ( fields[nfields] != NULL )
  442. nfields++;
  443. matvar->data_size = sizeof(matvar_t **);
  444. nmemb = nfields; /* nfields is really nmemb*nfields */
  445. break;
  446. }
  447. default:
  448. Mat_Error("Unrecognized data_type");
  449. Mat_VarFree(matvar);
  450. return NULL;
  451. }
  452. if ( matvar->class_type == MAT_C_CHAR ) {
  453. #if 0
  454. matvar->data_size = 1;
  455. nmemb++;
  456. #endif
  457. matvar->nbytes = nmemb*matvar->data_size;
  458. } else if ( matvar->class_type == MAT_C_SPARSE ) {
  459. matvar->data_size = sizeof(sparse_t);
  460. matvar->nbytes = nmemb*matvar->data_size;
  461. } else {
  462. matvar->nbytes = nmemb*matvar->data_size;
  463. }
  464. if ( data == NULL ) {
  465. matvar->data = NULL;
  466. } else if ( opt & MEM_CONSERVE ) {
  467. if ( matvar->isComplex ) {
  468. matvar->data = malloc(sizeof(struct ComplexSplit));
  469. if ( NULL != data ) {
  470. struct ComplexSplit *complex_data = matvar->data;
  471. struct ComplexSplit *complex_data_in = data;
  472. *complex_data = *complex_data_in;
  473. }
  474. } else {
  475. matvar->data = (void*)data;
  476. }
  477. matvar->mem_conserve = 1;
  478. } else {
  479. if ( matvar->isComplex ) {
  480. matvar->data = malloc(sizeof(struct ComplexSplit));
  481. if ( NULL != matvar->data ) {
  482. struct ComplexSplit *complex_data = matvar->data;
  483. struct ComplexSplit *complex_data_in = data;
  484. complex_data->Re = malloc(matvar->nbytes);
  485. complex_data->Im = malloc(matvar->nbytes);
  486. if ( NULL != complex_data->Re )
  487. memcpy(complex_data->Re,complex_data_in->Re,matvar->nbytes);
  488. if ( NULL != complex_data->Im )
  489. memcpy(complex_data->Im,complex_data_in->Im,matvar->nbytes);
  490. }
  491. } else {
  492. matvar->data = malloc(matvar->nbytes);
  493. if ( NULL != matvar->data )
  494. memcpy(matvar->data,data,matvar->nbytes);
  495. }
  496. matvar->mem_conserve = 0;
  497. }
  498. return matvar;
  499. }
  500. /** @brief Deletes a variable from a file
  501. *
  502. * @ingroup MAT
  503. * @param mat Pointer to the mat_t file structure
  504. * @param name Name of the variable to delete
  505. * @returns 0 on success
  506. */
  507. int
  508. Mat_VarDelete(mat_t *mat, char *name)
  509. {
  510. int err = 1;
  511. char *tmp_name, *new_name, *temp;
  512. mat_t *tmp;
  513. matvar_t *matvar;
  514. temp = strdup_printf("XXXXXX");
  515. tmp_name = mktemp(temp);
  516. tmp = Mat_Create(tmp_name,mat->header);
  517. if ( tmp != NULL ) {
  518. while ( NULL != (matvar = Mat_VarReadNext(mat)) ) {
  519. if ( strcmp(matvar->name,name) )
  520. Mat_VarWrite(tmp,matvar,0);
  521. else
  522. err = 0;
  523. Mat_VarFree(matvar);
  524. }
  525. /* FIXME: Memory leak */
  526. new_name = strdup_printf("%s",mat->filename);
  527. fclose(mat->fp);
  528. if ( (err = remove(new_name)) == -1 ) {
  529. Mat_Critical("remove of %s failed",new_name);
  530. } else if ( !Mat_Close(tmp) && (err=rename(tmp_name,new_name))==-1) {
  531. Mat_Critical("rename failed oldname=%s,newname=%s",tmp_name,
  532. new_name);
  533. } else {
  534. tmp = Mat_Open(new_name,mat->mode);
  535. memcpy(mat,tmp,sizeof(mat_t));
  536. }
  537. free(tmp);
  538. free(new_name);
  539. }
  540. free(temp);
  541. return err;
  542. }
  543. /** @brief Duplicates a matvar_t structure
  544. *
  545. * Provides a clean function for duplicating a matvar_t structure.
  546. * @ingroup MAT
  547. * @param in pointer to the matvar_t structure to be duplicated
  548. * @param opt 0 does a shallow duplicate and only assigns the data pointer to
  549. * the duplicated array. 1 will do a deep duplicate and actually
  550. * duplicate the contents of the data. Warning: If you do a shallow
  551. * copy and free both structures, the data will be freed twice and
  552. * memory will be corrupted. This may be fixed in a later release.
  553. * @returns Pointer to the duplicated matvar_t structure.
  554. */
  555. matvar_t *
  556. Mat_VarDuplicate(const matvar_t *in, int opt)
  557. {
  558. matvar_t *out;
  559. int i;
  560. out = malloc(sizeof(matvar_t));
  561. if ( out == NULL )
  562. return NULL;
  563. out->nbytes = in->nbytes;
  564. out->rank = in->rank;
  565. out->data_type = in->data_type;
  566. out->data_size = in->data_size;
  567. out->class_type = in->class_type;
  568. out->isComplex = in->isComplex;
  569. out->isGlobal = in->isGlobal;
  570. out->isLogical = in->isLogical;
  571. out->mem_conserve = in->mem_conserve;
  572. out->compression = in->compression;
  573. out->fpos = in->fpos;
  574. out->datapos = in->datapos;
  575. out->name = NULL;
  576. out->dims = NULL;
  577. out->data = NULL;
  578. #if defined(HAVE_ZLIB)
  579. out->z = NULL;
  580. #endif
  581. if (in->name != NULL && (NULL != (out->name = malloc(strlen(in->name)+1))))
  582. memcpy(out->name,in->name,strlen(in->name)+1);
  583. out->dims = malloc(in->rank*sizeof(int));
  584. if ( out->dims != NULL )
  585. memcpy(out->dims,in->dims,in->rank*sizeof(int));
  586. #if defined(HAVE_ZLIB)
  587. if ( (in->z != NULL) && (NULL != (out->z = malloc(sizeof(z_stream)))) )
  588. inflateCopy(out->z,in->z);
  589. #endif
  590. if ( !opt ) {
  591. out->data = in->data;
  592. } else if ( (in->data != NULL) && (in->class_type == MAT_C_STRUCT) ) {
  593. matvar_t **infields, **outfields;
  594. int nfields = 0;
  595. out->data = malloc(in->nbytes);
  596. if ( out->data != NULL && in->data_size > 0 ) {
  597. nfields = in->nbytes / in->data_size;
  598. infields = (matvar_t **)in->data;
  599. outfields = (matvar_t **)out->data;
  600. for ( i = 0; i < nfields; i++ ) {
  601. outfields[i] = Mat_VarDuplicate(infields[i],opt);
  602. }
  603. }
  604. } else if ( (in->data != NULL) && (in->class_type == MAT_C_CELL) ) {
  605. matvar_t **incells, **outcells;
  606. int ncells = 0;
  607. out->data = malloc(in->nbytes);
  608. if ( out->data != NULL && in->data_size > 0 ) {
  609. ncells = in->nbytes / in->data_size;
  610. incells = (matvar_t **)in->data;
  611. outcells = (matvar_t **)out->data;
  612. for ( i = 0; i < ncells; i++ ) {
  613. outcells[i] = Mat_VarDuplicate(incells[i],opt);
  614. }
  615. }
  616. } else if ( in->data != NULL ) {
  617. if ( out->isComplex ) {
  618. out->data = malloc(sizeof(struct ComplexSplit));
  619. if ( out->data != NULL ) {
  620. struct ComplexSplit *out_data = out->data;
  621. struct ComplexSplit *in_data = in->data;
  622. out_data->Re = malloc(out->nbytes);
  623. if ( NULL != out_data->Re )
  624. memcpy(out_data->Re,in_data->Re,out->nbytes);
  625. out_data->Im = malloc(out->nbytes);
  626. if ( NULL != out_data->Im )
  627. memcpy(out_data->Im,in_data->Im,out->nbytes);
  628. }
  629. } else {
  630. out->data = malloc(in->nbytes);
  631. if ( out->data != NULL )
  632. memcpy(out->data,in->data,in->nbytes);
  633. }
  634. }
  635. return out;
  636. }
  637. /** @brief Frees all the allocated memory associated with the structure
  638. *
  639. * Frees memory used by a MAT variable. Frees the data associated with a
  640. * MAT variable if it's non-NULL and MEM_CONSERVE was not used.
  641. * @ingroup MAT
  642. * @param matvar Pointer to the matvar_t structure
  643. */
  644. void
  645. Mat_VarFree(matvar_t *matvar)
  646. {
  647. if ( !matvar )
  648. return;
  649. if ( matvar->dims )
  650. free(matvar->dims);
  651. if ( matvar->name )
  652. free(matvar->name);
  653. if ( (matvar->data != NULL) && (matvar->class_type == MAT_C_STRUCT ||
  654. matvar->class_type == MAT_C_CELL) && matvar->data_size > 0 ) {
  655. int i;
  656. matvar_t **fields = matvar->data;
  657. int nfields = matvar->nbytes / matvar->data_size;
  658. for ( i = 0; i < nfields; i++ )
  659. Mat_VarFree(fields[i]);
  660. free(matvar->data);
  661. } else if ( (matvar->data != NULL) && (!matvar->mem_conserve) &&
  662. (matvar->class_type == MAT_C_SPARSE) ) {
  663. sparse_t *sparse;
  664. sparse = matvar->data;
  665. if ( sparse->ir != NULL )
  666. free(sparse->ir);
  667. if ( sparse->jc != NULL )
  668. free(sparse->jc);
  669. if ( sparse->data != NULL )
  670. free(sparse->data);
  671. free(sparse);
  672. } else {
  673. if ( matvar->isComplex && NULL != matvar->data ) {
  674. struct ComplexSplit *complex_data = matvar->data;
  675. if ( !matvar->mem_conserve ) {
  676. free(complex_data->Re);
  677. free(complex_data->Im);
  678. }
  679. free(complex_data);
  680. } else {
  681. if ( matvar->data && !matvar->mem_conserve )
  682. free(matvar->data);
  683. }
  684. }
  685. #if defined(HAVE_ZLIB)
  686. if ( matvar->compression == COMPRESSION_ZLIB ) {
  687. inflateEnd(matvar->z);
  688. free(matvar->z);
  689. }
  690. #endif
  691. /* FIXME: Why does this cause a SEGV? */
  692. #if 0
  693. memset(matvar,0,sizeof(matvar_t));
  694. #endif
  695. free(matvar);
  696. }
  697. void
  698. Mat_VarFree2(matvar_t *matvar)
  699. {
  700. if ( !matvar )
  701. return;
  702. if ( matvar->dims )
  703. free(matvar->dims);
  704. if ( matvar->name )
  705. free(matvar->name);
  706. if ( (matvar->data != NULL) && (matvar->class_type == MAT_C_STRUCT ||
  707. matvar->class_type == MAT_C_CELL) && matvar->data_size > 0 ) {
  708. int i;
  709. matvar_t **fields = (matvar_t **)matvar->data;
  710. int nfields = matvar->nbytes / matvar->data_size;
  711. for ( i = 0; i < nfields; i++ )
  712. Mat_VarFree(fields[i]);
  713. free(matvar->data);
  714. } else if ( (matvar->data != NULL) && (!matvar->mem_conserve) &&
  715. (matvar->class_type == MAT_C_SPARSE) ) {
  716. sparse_t *sparse;
  717. sparse = matvar->data;
  718. if ( sparse->ir != NULL )
  719. free(sparse->ir);
  720. if ( sparse->jc != NULL )
  721. free(sparse->jc);
  722. if ( sparse->data != NULL )
  723. free(sparse->data);
  724. free(sparse);
  725. } else {
  726. if ( matvar->data && !matvar->mem_conserve )
  727. free(matvar->data);
  728. }
  729. #if defined(HAVE_ZLIB)
  730. if ( matvar->compression == COMPRESSION_ZLIB )
  731. inflateEnd(matvar->z);
  732. #endif
  733. /* FIXME: Why does this cause a SEGV? */
  734. #if 0
  735. memset(matvar,0,sizeof(matvar_t));
  736. #endif
  737. }
  738. /** @brief Calculate a single subscript from a set of subscript values
  739. *
  740. * Calculates a single linear subscript (0-relative) given a 1-relative
  741. * subscript for each dimension. The calculation uses the formula below where
  742. * index is the linear index, s is an array of length RANK where each element
  743. * is the subscript for the correspondind dimension, D is an array whose
  744. * elements are the dimensions of the variable.
  745. * \f[
  746. * index = \sum\limits_{k=0}^{RANK-1} [(s_k - 1) \prod\limits_{l=0}^{k} D_l ]
  747. * \f]
  748. * @ingroup MAT
  749. * @param rank Rank of the variable
  750. * @param dims dimensions of the variable
  751. * @param subs Dimension subscripts
  752. * @return Single (linear) subscript
  753. */
  754. int
  755. Mat_CalcSingleSubscript(int rank,int *dims,int *subs)
  756. {
  757. int index = 0, i, j, k, err = 0;
  758. for ( i = 0; i < rank; i++ ) {
  759. k = subs[i];
  760. if ( k > dims[i] ) {
  761. err = 1;
  762. Mat_Critical("Mat_CalcSingleSubscript: index out of bounds");
  763. break;
  764. } else if ( k < 1 ) {
  765. err = 1;
  766. break;
  767. }
  768. k--;
  769. for ( j = i; j--; )
  770. k *= dims[j];
  771. index += k;
  772. }
  773. if ( err )
  774. index = -1;
  775. return index;
  776. }
  777. /** @brief Calculate a set of subscript values from a single(linear) subscript
  778. *
  779. * Calculates 1-relative subscripts for each dimension given a 0-relative
  780. * linear index. Subscripts are calculated as follows where s is the array
  781. * of dimension subscripts, D is the array of dimensions, and index is the
  782. * linear index.
  783. * \f[
  784. * s_k = \lfloor\frac{1}{L} \prod\limits_{l = 0}^{k} D_l\rfloor + 1
  785. * \f]
  786. * \f[
  787. * L = index - \sum\limits_{l = k}^{RANK - 1} s_k \prod\limits_{m = 0}^{k} D_m
  788. * \f]
  789. * @ingroup MAT
  790. * @param rank Rank of the variable
  791. * @param dims dimensions of the variable
  792. * @param index linear index
  793. * @return Array of dimension subscripts
  794. */
  795. int *
  796. Mat_CalcSubscripts(int rank,int *dims,int index)
  797. {
  798. int i, j, k, *subs;
  799. double l;
  800. subs = malloc(rank*sizeof(int));
  801. l = index;
  802. for ( i = rank; i--; ) {
  803. k = 1;
  804. for ( j = i; j--; )
  805. k *= dims[j];
  806. subs[i] = floor(l / (double)k);
  807. l -= subs[i]*k;
  808. subs[i]++;
  809. }
  810. return subs;
  811. }
  812. /** @brief Returns a pointer to the Cell array at a specific index
  813. *
  814. * Returns a pointer to the Cell Array Field at the given 1-relative index.
  815. * MAT file must be a version 5 matlab file.
  816. * @ingroup MAT
  817. * @param matvar Pointer to the Cell Array MAT variable
  818. * @param index linear index of cell to return
  819. * @return Pointer to the Cell Array Field on success, NULL on error
  820. */
  821. matvar_t *
  822. Mat_VarGetCell(matvar_t *matvar,int index)
  823. {
  824. int nmemb = 1, i;
  825. matvar_t *cell = NULL;
  826. if ( matvar == NULL )
  827. return NULL;
  828. for ( i = 0; i < matvar->rank; i++ )
  829. nmemb *= matvar->dims[i];
  830. if ( index < nmemb )
  831. cell = *((matvar_t **)matvar->data + index);
  832. return cell;
  833. }
  834. /** @brief Indexes a cell array
  835. *
  836. * Finds cells of a cell array given a start, stride, and edge for each.
  837. * dimension. The cells are placed in a pointer array. The cells should not
  838. * be freed, but the array of pointers should be. If copies are needed,
  839. * use Mat_VarDuplicate on each cell.
  840. * MAT File version must be 5.
  841. * @ingroup MAT
  842. * @param matvar Cell Array matlab variable
  843. * @param start vector of length rank with 0-relative starting coordinates for
  844. * each diemnsion.
  845. * @param stride vector of length rank with strides for each diemnsion.
  846. * @param edge vector of length rank with the number of elements to read in
  847. * each diemnsion.
  848. * @returns an array of pointers to the cells
  849. */
  850. matvar_t **
  851. Mat_VarGetCells(matvar_t *matvar,int *start,
  852. int *stride,int *edge)
  853. {
  854. int i, j, N, I = 0;
  855. int inc[10] = {0,}, cnt[10] = {0,}, dimp[10] = {0,};
  856. matvar_t **cells;
  857. if ( (matvar == NULL) || (start == NULL) || (stride == NULL) ||
  858. (edge == NULL) ) {
  859. return NULL;
  860. } else if ( matvar->rank > 10 ) {
  861. return NULL;
  862. }
  863. inc[0] = stride[0]-1;
  864. dimp[0] = matvar->dims[0];
  865. N = edge[0];
  866. I = start[0];
  867. for ( i = 1; i < matvar->rank; i++ ) {
  868. inc[i] = stride[i]-1;
  869. dimp[i] = matvar->dims[i-1];
  870. for ( j = i ; j--; ) {
  871. inc[i] *= matvar->dims[j];
  872. dimp[i] *= matvar->dims[j+1];
  873. }
  874. N *= edge[i];
  875. if ( start[i] > 0 )
  876. I += start[i]*dimp[i-1];
  877. }
  878. cells = malloc(N*sizeof(matvar_t *));
  879. for ( i = 0; i < N; i+=edge[0] ) {
  880. for ( j = 0; j < edge[0]; j++ ) {
  881. cells[i+j] = *((matvar_t **)matvar->data + I);
  882. I += stride[0];
  883. }
  884. for ( j = 1; j < matvar->rank-1; j++ ) {
  885. cnt[j]++;
  886. if ( (cnt[j] % edge[j]) == 0 ) {
  887. cnt[j] = 0;
  888. if ( (I % dimp[j]) != 0 ) {
  889. I += dimp[j]-(I % dimp[j]);
  890. }
  891. } else {
  892. I += matvar->dims[0]-edge[0]*stride[0]-start[0];
  893. I += inc[j];
  894. break;
  895. }
  896. }
  897. }
  898. return cells;
  899. }
  900. /** @brief Indexes a cell array
  901. *
  902. * Finds cells of a cell array given a linear indexed start, stride, and edge.
  903. * The cells are placed in a pointer array. The cells themself should not
  904. * be freed as they are part of the original cell array, but the pointer array
  905. * should be. If copies are needed, use Mat_VarDuplicate on each of the cells.
  906. * MAT file version must be 5.
  907. * @ingroup MAT
  908. * @param matvar Cell Array matlab variable
  909. * @param start starting index
  910. * @param stride stride
  911. * @param edge Number of cells to get
  912. * @returns an array of pointers to the cells
  913. */
  914. matvar_t **
  915. Mat_VarGetCellsLinear(matvar_t *matvar,int start,int stride,int edge)
  916. {
  917. int i, I = 0;
  918. matvar_t **cells;
  919. if ( matvar == NULL || matvar->rank > 10 ) {
  920. cells = NULL;
  921. } else {
  922. cells = malloc(edge*sizeof(matvar_t *));
  923. for ( i = 0; i < edge; i++ ) {
  924. cells[i] = *((matvar_t **)matvar->data + I);
  925. I += stride;
  926. }
  927. }
  928. return cells;
  929. }
  930. /** @brief Calculates the size of a matlab variable in bytes
  931. *
  932. * @ingroup MAT
  933. * @param matvar matlab variable
  934. * @returns size of the variable in bytes
  935. */
  936. size_t
  937. Mat_VarGetSize(matvar_t *matvar)
  938. {
  939. int nmemb, i;
  940. size_t bytes = 0;
  941. if ( matvar->class_type == MAT_C_STRUCT ) {
  942. int nfields;
  943. matvar_t **fields;
  944. /* This is really nmemb*nfields, but we'll get a
  945. * more accurate count of the bytes by loopoing over all of them
  946. */
  947. nfields = matvar->nbytes / matvar->data_size;
  948. fields = matvar->data;
  949. for ( i = 0; i < nfields; i++ )
  950. bytes += Mat_VarGetSize(fields[i]);
  951. } else if ( matvar->class_type == MAT_C_CELL ) {
  952. int ncells;
  953. matvar_t **cells;
  954. ncells = matvar->nbytes / matvar->data_size;
  955. cells = matvar->data;
  956. for ( i = 0; i < ncells; i++ )
  957. bytes += Mat_VarGetSize(cells[i]);
  958. } else {
  959. nmemb = 1;
  960. for ( i = 0; i < matvar->rank; i++ )
  961. nmemb *= matvar->dims[i];
  962. bytes += nmemb*Mat_SizeOfClass(matvar->class_type);
  963. }
  964. return bytes;
  965. }
  966. /** @brief Adds a field to a structure
  967. *
  968. * Adds the given field to the structure. fields should be an array of matvar_t
  969. * pointers of the same size as the structure (i.e. 1 field per structure
  970. * element).
  971. * @ingroup MAT
  972. * @param matvar Pointer to the Structure MAT variable
  973. * @param fields Array of fields to be added
  974. * @retval 0 on success
  975. */
  976. int
  977. Mat_VarAddStructField(matvar_t *matvar,matvar_t **fields)
  978. {
  979. int i, f, nfields, nmemb, cnt = 0;
  980. matvar_t **new_data,**old_data;
  981. if ( matvar == NULL || fields == NULL )
  982. return -1;
  983. nmemb = 1;
  984. for ( i = 0; i < matvar->rank; i++ )
  985. nmemb *= matvar->dims[i];
  986. nfields = matvar->nbytes / (nmemb*sizeof(matvar_t *));
  987. new_data = malloc((nfields+1)*nmemb*sizeof(matvar_t *));
  988. if ( new_data == NULL )
  989. return -1;
  990. old_data = matvar->data;
  991. for ( i = 0; i < nmemb; i++ ) {
  992. for ( f = 0; f < nfields; f++ )
  993. new_data[cnt++] = old_data[i*nfields+f];
  994. new_data[cnt++] = fields[i];
  995. }
  996. free(matvar->data);
  997. matvar->data = new_data;
  998. matvar->nbytes = (nfields+1)*nmemb*sizeof(matvar_t *);
  999. return 0;
  1000. }
  1001. /** @brief Returns the number of fields in a structure variable
  1002. *
  1003. * Returns the number of fields in the given structure.
  1004. * MAT file version must be 5.
  1005. * @ingroup MAT
  1006. * @param matvar Structure matlab variable
  1007. * @returns Number of fields, or a negative number on error
  1008. */
  1009. int
  1010. Mat_VarGetNumberOfFields(matvar_t *matvar)
  1011. {
  1012. int i, nfields, nmemb = 1;
  1013. if ( matvar == NULL || matvar->class_type != MAT_C_STRUCT ||
  1014. matvar->data_size == 0 ) {
  1015. nfields = -1;
  1016. } else {
  1017. for ( i = 0; i < matvar->rank; i++ )
  1018. nmemb *= matvar->dims[i];
  1019. nfields = matvar->nbytes / (nmemb*matvar->data_size);
  1020. }
  1021. return nfields;
  1022. }
  1023. /** @brief Finds a field of a structure
  1024. *
  1025. * Returns a pointer to the structure field at the given 0-relative index. MAT
  1026. * file version must be 5.
  1027. * @ingroup MAT
  1028. * @param matvar Pointer to the Structure MAT variable
  1029. * @param name_or_index Name of the field, or the 1-relative index of the field.
  1030. * If the index is used, it should be the address of an integer variable whose
  1031. * value is the index number.
  1032. * @param opt BY_NAME if the name_or_index is the name or BY_INDEX if the index
  1033. * was passed.
  1034. * @param index linear index of the structure to find the field of
  1035. * @return Pointer to the Structure Field on success, NULL on error
  1036. */
  1037. matvar_t *
  1038. Mat_VarGetStructField(matvar_t *matvar,void *name_or_index,int opt,int index)
  1039. {
  1040. int i, err = 0, nfields, nmemb;
  1041. matvar_t *field = NULL;
  1042. nmemb = 1;
  1043. for ( i = 0; i < matvar->rank; i++ )
  1044. nmemb *= matvar->dims[i];
  1045. nfields = matvar->nbytes / (nmemb*sizeof(matvar_t *));
  1046. if ( index >= nmemb || index < 0)
  1047. err = 1;
  1048. if ( !err && (opt == BY_INDEX) ) {
  1049. int field_index;
  1050. field_index = *(int *)name_or_index;
  1051. if ( field_index > nfields || field_index < 1 )
  1052. Mat_Critical("Mat_VarGetStructField: field index out of bounds");
  1053. else
  1054. field = *((matvar_t **)matvar->data+index*nfields+field_index - 1);
  1055. } else if ( !err && (opt == BY_NAME) ) {
  1056. char *field_name;
  1057. field_name = (char *)name_or_index;
  1058. for ( i = 0; i < nfields; i++ ) {
  1059. field = *((matvar_t **)matvar->data+index*nfields+i);
  1060. if ( !strcmp(field->name,field_name) )
  1061. break;
  1062. else
  1063. field = NULL;
  1064. }
  1065. }
  1066. return field;
  1067. }
  1068. /** @brief Indexes a structure
  1069. *
  1070. * Finds structures of a structure array given a start, stride, and edge for
  1071. * each dimension. The structures are placed in a new structure array. If
  1072. * copy_fields is non-zero, the indexed structures are copied and should be
  1073. * freed, but if copy_fields is zero, the indexed structures are pointers to
  1074. * the original, but should still be freed since the mem_conserve flag is set
  1075. * so that the structures are not freed.
  1076. * MAT File version must be 5.
  1077. * @ingroup MAT
  1078. * @param matvar Structure matlab variable
  1079. * @param start vector of length rank with 0-relative starting coordinates for
  1080. * each diemnsion.
  1081. * @param stride vector of length rank with strides for each diemnsion.
  1082. * @param edge vector of length rank with the number of elements to read in
  1083. * each diemnsion.
  1084. * @param copy_fields 1 to copy the fields, 0 to just set pointers to them.
  1085. * If 0 is used, the fields should not be freed themselves.
  1086. * @returns A new structure with fields indexed from matvar.
  1087. */
  1088. matvar_t *
  1089. Mat_VarGetStructs(matvar_t *matvar,int *start,int *stride,int *edge,
  1090. int copy_fields)
  1091. {
  1092. int i, j, N, I = 0;
  1093. int inc[10] = {0,}, cnt[10] = {0,}, dimp[10] = {0,};
  1094. int nfields, field;
  1095. matvar_t **fields, *struct_slab;
  1096. if ( (matvar == NULL) || (start == NULL) || (stride == NULL) ||
  1097. (edge == NULL) ) {
  1098. return NULL;
  1099. } else if ( matvar->rank > 10 ) {
  1100. return NULL;
  1101. } else if ( matvar->class_type != MAT_C_STRUCT ) {
  1102. return NULL;
  1103. }
  1104. struct_slab = Mat_VarDuplicate(matvar,0);
  1105. if ( !copy_fields )
  1106. struct_slab->mem_conserve = 1;
  1107. nfields = matvar->nbytes / matvar->data_size;
  1108. for ( i = 0; i < matvar->rank; i++ )
  1109. nfields = nfields / matvar->dims[i];
  1110. inc[0] = stride[0]-1;
  1111. dimp[0] = matvar->dims[0];
  1112. N = edge[0];
  1113. I = start[0]*nfields;
  1114. for ( i = 1; i < matvar->rank; i++ ) {
  1115. inc[i] = stride[i]-1;
  1116. dimp[i] = matvar->dims[i-1];
  1117. for ( j = i ; j--; ) {
  1118. inc[i] *= matvar->dims[j]*nfields;
  1119. dimp[i] *= matvar->dims[j+1];
  1120. }
  1121. N *= edge[i];
  1122. if ( start[i] > 0 )
  1123. I += start[i]*dimp[i-1]*nfields;
  1124. }
  1125. struct_slab->nbytes = N*nfields*sizeof(matvar_t *);
  1126. struct_slab->data = malloc(struct_slab->nbytes);
  1127. if ( struct_slab->data == NULL ) {
  1128. Mat_VarFree(struct_slab);
  1129. return NULL;
  1130. }
  1131. fields = struct_slab->data;
  1132. for ( i = 0; i < N; i+=edge[0] ) {
  1133. for ( j = 0; j < edge[0]; j++ ) {
  1134. for ( field = 0; field < nfields; field++ ) {
  1135. if ( copy_fields )
  1136. fields[(i+j)*nfields+field] =
  1137. Mat_VarDuplicate(*((matvar_t **)matvar->data + I),1);
  1138. else
  1139. fields[(i+j)*nfields+field] =
  1140. *((matvar_t **)matvar->data + I);
  1141. I++;
  1142. }
  1143. I += stride[0]*nfields;
  1144. }
  1145. for ( j = 1; j < matvar->rank-1; j++ ) {
  1146. cnt[j]++;
  1147. if ( (cnt[j] % edge[j]) == 0 ) {
  1148. cnt[j] = 0;
  1149. if ( (I % dimp[j]) != 0 ) {
  1150. I += dimp[j]-(I % dimp[j]);
  1151. }
  1152. } else {
  1153. I += matvar->dims[0]-edge[0]*stride[0]-start[0];
  1154. I += inc[j];
  1155. break;
  1156. }
  1157. }
  1158. }
  1159. return struct_slab;
  1160. }
  1161. /** @brief Indexes a structure
  1162. *
  1163. * Finds structures of a structure array given a single (linear)start, stride,
  1164. * and edge. The structures are placed in a new structure array. If
  1165. * copy_fields is non-zero, the indexed structures are copied and should be
  1166. * freed, but if copy_fields is zero, the indexed structures are pointers to
  1167. * the original, but should still be freed since the mem_conserve flag is set
  1168. * so that the structures are not freed.
  1169. * MAT File version must be 5.
  1170. * @ingroup MAT
  1171. * @param matvar Structure matlab variable
  1172. * @param start starting index
  1173. * @param stride stride
  1174. * @param edge Number of structures to get
  1175. * @param copy_fields 1 to copy the fields, 0 to just set pointers to them.
  1176. * If 0 is used, the fields should not be freed themselves.
  1177. * @returns A new structure with fields indexed from matvar
  1178. */
  1179. matvar_t *
  1180. Mat_VarGetStructsLinear(matvar_t *matvar,int start,int stride,int edge,
  1181. int copy_fields)
  1182. {
  1183. int i, I = 0, field, nfields;
  1184. matvar_t *struct_slab, **fields;
  1185. /* FIXME: Check allocations */
  1186. if ( matvar == NULL || matvar->rank > 10 ) {
  1187. struct_slab = NULL;
  1188. } else {
  1189. struct_slab = Mat_VarDuplicate(matvar,0);
  1190. if ( !copy_fields )
  1191. struct_slab->mem_conserve = 1;
  1192. nfields = matvar->nbytes / matvar->data_size;
  1193. for ( i = 0; i < matvar->rank; i++ )
  1194. nfields = nfields / matvar->dims[i];
  1195. struct_slab->nbytes = edge*nfields*sizeof(matvar_t *);
  1196. struct_slab->data = malloc(struct_slab->nbytes);
  1197. fields = struct_slab->data;
  1198. for ( i = 0; i < edge; i++ ) {
  1199. if ( copy_fields ) {
  1200. for ( field = 0; field < nfields; field++ ) {
  1201. fields[i*nfields+field] =
  1202. Mat_VarDuplicate(*((matvar_t **)matvar->data+I),1);
  1203. I++;
  1204. }
  1205. } else {
  1206. for ( field = 0; field < nfields; field++ ) {
  1207. fields[i+field] = *((matvar_t **)matvar->data + I);
  1208. I++;
  1209. }
  1210. }
  1211. I += stride;
  1212. }
  1213. }
  1214. return struct_slab;
  1215. }
  1216. /** @brief Prints the variable information
  1217. *
  1218. * Prints to stdout the values of the @ref matvar_t structure
  1219. * @ingroup MAT
  1220. * @param matvar Pointer to the matvar_t structure
  1221. * @param printdata set to 1 if the Variables data should be printed, else 0
  1222. */
  1223. void
  1224. Mat_VarPrint( matvar_t *matvar, int printdata )
  1225. {
  1226. if ( matvar == NULL || matvar->fp == NULL )
  1227. return;
  1228. else if ( matvar->fp->version != MAT_FT_MAT4 )
  1229. Mat_VarPrint5(matvar,printdata);
  1230. else if ( matvar->fp->version == MAT_FT_MAT4 )
  1231. Mat_VarPrint4(matvar,printdata);
  1232. return;
  1233. }
  1234. /** @brief Reads MAT variable data from a file
  1235. *
  1236. * Reads data from a MAT variable. The variable must have been read by
  1237. * Mat_VarReadInfo.
  1238. * @ingroup MAT
  1239. * @param mat MAT file to read data from
  1240. * @param matvar MAT variable information
  1241. * @param data pointer to store data in (must be pre-allocated)
  1242. * @param start array of starting indeces
  1243. * @param stride stride of data
  1244. * @param edge array specifying the number to read in each direction
  1245. * @retval 0 on success
  1246. */
  1247. int
  1248. Mat_VarReadData(mat_t *mat,matvar_t *matvar,void *data,
  1249. int *start,int *stride,int *edge)
  1250. {
  1251. int err = 0;
  1252. if ( mat->version != MAT_FT_MAT4 )
  1253. err = ReadData5(mat,matvar,data,start,stride,edge);
  1254. else
  1255. err = ReadData4(mat,matvar,data,start,stride,edge);
  1256. return err;
  1257. }
  1258. /** @brief Reads all the data for a matlab variable
  1259. *
  1260. * Allocates memory for an reads the data for a given matlab variable.
  1261. * @ingroup MAT
  1262. * @param mat Matlab MAT file structure pointer
  1263. * @param matvar Variable whose data is to be read
  1264. * @returns non-zero on error
  1265. */
  1266. int
  1267. Mat_VarReadDataAll(mat_t *mat,matvar_t *matvar)
  1268. {
  1269. int err = 0;
  1270. if ( (mat == NULL) || (matvar == NULL) )
  1271. err = 1;
  1272. else
  1273. ReadData(mat,matvar);
  1274. return err;
  1275. }
  1276. /** @brief Reads MAT variable data from a file
  1277. *
  1278. * Reads data from a MAT variable using a linear indexingmode. The variable
  1279. * must have been read by Mat_VarReadInfo.
  1280. * @ingroup MAT
  1281. * @param mat MAT file to read data from
  1282. * @param matvar MAT variable information
  1283. * @param data pointer to store data in (must be pre-allocated)
  1284. * @param start starting index
  1285. * @param stride stride of data
  1286. * @param edge number of elements to read
  1287. * @retval 0 on success
  1288. */
  1289. int
  1290. Mat_VarReadDataLinear(mat_t *mat,matvar_t *matvar,void *data,int start,
  1291. int stride,int edge)
  1292. {
  1293. int err = 0, nmemb = 1, i, data_type;
  1294. mat_int32_t tag[2];
  1295. if ( mat->version == MAT_FT_MAT4 )
  1296. return -1;
  1297. fseek(mat->fp,matvar->datapos,SEEK_SET);
  1298. if ( matvar->compression == COMPRESSION_NONE ) {
  1299. fread(tag,4,2,mat->fp);
  1300. if ( mat->byteswap ) {
  1301. Mat_int32Swap(tag);
  1302. Mat_int32Swap(tag+1);
  1303. }
  1304. data_type = tag[0] & 0x000000ff;
  1305. if ( tag[0] & 0xffff0000 ) { /* Data is packed in the tag */
  1306. fseek(mat->fp,-4,SEEK_CUR);
  1307. }
  1308. #if defined(HAVE_ZLIB)
  1309. } else if ( matvar->compression == COMPRESSION_ZLIB ) {
  1310. matvar->z->avail_in = 0;
  1311. InflateDataType(mat,matvar,tag);
  1312. if ( mat->byteswap ) {
  1313. Mat_int32Swap(tag);
  1314. Mat_int32Swap(tag+1);
  1315. }
  1316. data_type = tag[0] & 0x000000ff;
  1317. if ( !(tag[0] & 0xffff0000) ) {/* Data is NOT packed in the tag */
  1318. InflateSkip(mat,matvar->z,4);
  1319. }
  1320. #endif
  1321. }
  1322. for ( i = 0; i < matvar->rank; i++ )
  1323. nmemb *= matvar->dims[i];
  1324. if ( stride*(edge-1)+start+1 > nmemb ) {
  1325. err = 1;
  1326. } else {
  1327. stride--;
  1328. switch(matvar->class_type) {
  1329. case MAT_C_DOUBLE:
  1330. matvar->data_type = MAT_T_DOUBLE;
  1331. matvar->data_size = sizeof(double);
  1332. if ( matvar->compression == COMPRESSION_NONE ) {
  1333. stride *= Mat_SizeOf(data_type);
  1334. fseek(mat->fp,start,SEEK_CUR);
  1335. for ( i = 0; i < edge; i++ ) {
  1336. ReadDoubleData(mat,(double*)data+i,data_type,1);
  1337. fseek(mat->fp,stride,SEEK_CUR);
  1338. }
  1339. #if defined(HAVE_ZLIB)
  1340. } else {
  1341. z_stream z_copy;
  1342. err = inflateCopy(&z_copy,matvar->z);
  1343. InflateSkipData(mat,&z_copy,data_type,start);
  1344. for ( i = 0; i < edge; i++ ) {
  1345. ReadCompressedDoubleData(mat,&z_copy,(double*)data+i,
  1346. data_type,1);
  1347. InflateSkipData(mat,&z_copy,data_type,stride);
  1348. }
  1349. inflateEnd(&z_copy);
  1350. #endif
  1351. }
  1352. break;
  1353. case MAT_C_SINGLE:
  1354. matvar->data_type = MAT_T_SINGLE;
  1355. matvar->data_size = sizeof(float);
  1356. if ( matvar->compression == COMPRESSION_NONE ) {
  1357. stride *= Mat_SizeOf(data_type);
  1358. for ( i = 0; i < edge; i++ ) {
  1359. ReadSingleData(mat,(float*)data+i,data_type,1);
  1360. fseek(mat->fp,stride,SEEK_CUR);
  1361. }
  1362. #if defined(HAVE_ZLIB)
  1363. } else {
  1364. z_stream z_copy;
  1365. err = inflateCopy(&z_copy,matvar->z);
  1366. InflateSkipData(mat,&z_copy,data_type,start);
  1367. for ( i = 0; i < edge; i++ ) {
  1368. ReadCompressedSingleData(mat,&z_copy,(float*)data+i,
  1369. data_type,1);
  1370. InflateSkipData(mat,&z_copy,data_type,stride);
  1371. }
  1372. inflateEnd(&z_copy);
  1373. #endif
  1374. }
  1375. break;
  1376. #ifdef HAVE_MAT_INT64_T
  1377. case MAT_C_INT64:
  1378. matvar->data_type = MAT_T_INT64;
  1379. matvar->data_size = sizeof(mat_int64_t);
  1380. if ( matvar->compression == COMPRESSION_NONE ) {
  1381. stride *= Mat_SizeOf(data_type);
  1382. for ( i = 0; i < edge; i++ ) {
  1383. ReadInt64Data(mat,(mat_int64_t*)data+i,data_type,1);
  1384. fseek(mat->fp,stride,SEEK_CUR);
  1385. }
  1386. #if defined(HAVE_ZLIB)
  1387. } else {
  1388. z_stream z_copy;
  1389. err = inflateCopy(&z_copy,matvar->z);
  1390. InflateSkipData(mat,&z_copy,data_type,start);
  1391. for ( i = 0; i < edge; i++ ) {
  1392. ReadCompressedInt64Data(mat,&z_copy,(mat_int64_t*)data+i,
  1393. data_type,1);
  1394. InflateSkipData(mat,&z_copy,data_type,stride);
  1395. }
  1396. inflateEnd(&z_copy);
  1397. #endif
  1398. }
  1399. break;
  1400. #endif /* HAVE_MAT_INT64_T */
  1401. #ifdef HAVE_MAT_UINT64_T
  1402. case MAT_C_UINT64:
  1403. matvar->data_type = MAT_T_UINT64;
  1404. matvar->data_size = sizeof(mat_uint64_t);
  1405. if ( matvar->compression == COMPRESSION_NONE ) {
  1406. stride *= Mat_SizeOf(data_type);
  1407. for ( i = 0; i < edge; i++ ) {
  1408. ReadInt64Data(mat,(mat_int64_t*)data+i,data_type,1);
  1409. fseek(mat->fp,stride,SEEK_CUR);
  1410. }
  1411. #if defined(HAVE_ZLIB)
  1412. } else {
  1413. z_stream z_copy;
  1414. err = inflateCopy(&z_copy,matvar->z);
  1415. InflateSkipData(mat,&z_copy,data_type,start);
  1416. for ( i = 0; i < edge; i++ ) {
  1417. ReadCompressedInt64Data(mat,&z_copy,(mat_int64_t*)data+i,
  1418. data_type,1);
  1419. InflateSkipData(mat,&z_copy,data_type,stride);
  1420. }
  1421. inflateEnd(&z_copy);
  1422. #endif
  1423. }
  1424. break;
  1425. #endif /* HAVE_MAT_UINT64_T */
  1426. case MAT_C_INT32:
  1427. matvar->data_type = MAT_T_INT32;
  1428. matvar->data_size = sizeof(mat_int32_t);
  1429. if ( matvar->compression == COMPRESSION_NONE ) {
  1430. stride *= Mat_SizeOf(data_type);
  1431. for ( i = 0; i < edge; i++ ) {
  1432. ReadInt32Data(mat,(mat_int32_t*)data+i,data_type,1);
  1433. fseek(mat->fp,stride,SEEK_CUR);
  1434. }
  1435. #if defined(HAVE_ZLIB)
  1436. } else {
  1437. z_stream z_copy;
  1438. err = inflateCopy(&z_copy,matvar->z);
  1439. InflateSkipData(mat,&z_copy,data_type,start);
  1440. for ( i = 0; i < edge; i++ ) {
  1441. ReadCompressedInt32Data(mat,&z_copy,(mat_int32_t*)data+i,
  1442. data_type,1);
  1443. InflateSkipData(mat,&z_copy,data_type,stride);
  1444. }
  1445. inflateEnd(&z_copy);
  1446. #endif
  1447. }
  1448. break;
  1449. case MAT_C_UINT32:
  1450. matvar->data_type = MAT_T_UINT32;
  1451. matvar->data_size = sizeof(mat_uint32_t);
  1452. if ( matvar->compression == COMPRESSION_NONE ) {
  1453. stride *= Mat_SizeOf(data_type);
  1454. for ( i = 0; i < edge; i++ ) {
  1455. ReadInt32Data(mat,(mat_int32_t*)data+i,data_type,1);
  1456. fseek(mat->fp,stride,SEEK_CUR);
  1457. }
  1458. #if defined(HAVE_ZLIB)
  1459. } else {
  1460. z_stream z_copy;
  1461. err = inflateCopy(&z_copy,matvar->z);
  1462. InflateSkipData(mat,&z_copy,data_type,start);
  1463. for ( i = 0; i < edge; i++ ) {
  1464. ReadCompressedInt32Data(mat,&z_copy,(mat_int32_t*)data+i,
  1465. data_type,1);
  1466. InflateSkipData(mat,&z_copy,data_type,stride);
  1467. }
  1468. inflateEnd(&z_copy);
  1469. #endif
  1470. }
  1471. break;
  1472. case MAT_C_INT16:
  1473. matvar->data_type = MAT_T_INT16;
  1474. matvar->data_size = sizeof(mat_int16_t);
  1475. if ( matvar->compression == COMPRESSION_NONE ) {
  1476. stride *= Mat_SizeOf(data_type);
  1477. for ( i = 0; i < edge; i++ ) {
  1478. ReadInt16Data(mat,(mat_int16_t*)data+i,data_type,1);
  1479. fseek(mat->fp,stride,SEEK_CUR);
  1480. }
  1481. #if defined(HAVE_ZLIB)
  1482. } else {
  1483. z_stream z_copy;
  1484. err = inflateCopy(&z_copy,matvar->z);
  1485. InflateSkipData(mat,&z_copy,data_type,start);
  1486. for ( i = 0; i < edge; i++ ) {
  1487. ReadCompressedInt16Data(mat,&z_copy,(mat_int16_t*)data+i,
  1488. data_type,1);
  1489. InflateSkipData(mat,&z_copy,data_type,stride);
  1490. }
  1491. inflateEnd(&z_copy);
  1492. #endif
  1493. }
  1494. break;
  1495. case MAT_C_UINT16:
  1496. matvar->data_type = MAT_T_UINT16;
  1497. matvar->data_size = sizeof(mat_uint16_t);
  1498. if ( matvar->compression == COMPRESSION_NONE ) {
  1499. stride *= Mat_SizeOf(data_type);
  1500. for ( i = 0; i < edge; i++ ) {
  1501. ReadInt16Data(mat,(mat_int16_t*)data+i,data_type,1);
  1502. fseek(mat->fp,stride,SEEK_CUR);
  1503. }
  1504. #if defined(HAVE_ZLIB)
  1505. } else {
  1506. z_stream z_copy;
  1507. err = inflateCopy(&z_copy,matvar->z);
  1508. InflateSkipData(mat,&z_copy,data_type,start);
  1509. for ( i = 0; i < edge; i++ ) {
  1510. ReadCompressedInt16Data(mat,&z_copy,(mat_int16_t*)data+i,
  1511. data_type,1);
  1512. InflateSkipData(mat,&z_copy,data_type,stride);
  1513. }
  1514. inflateEnd(&z_copy);
  1515. #endif
  1516. }
  1517. break;
  1518. case MAT_C_INT8:
  1519. matvar->data_type = MAT_T_INT8;
  1520. matvar->data_size = sizeof(mat_int8_t);
  1521. if ( matvar->compression == COMPRESSION_NONE ) {
  1522. stride *= Mat_SizeOf(data_type);
  1523. for ( i = 0; i < edge; i++ ) {
  1524. ReadInt8Data(mat,(mat_int8_t*)data+i,data_type,1);
  1525. fseek(mat->fp,stride,SEEK_CUR);
  1526. }
  1527. #if defined(HAVE_ZLIB)
  1528. } else {
  1529. z_stream z_copy;
  1530. err = inflateCopy(&z_copy,matvar->z);
  1531. InflateSkipData(mat,&z_copy,data_type,start);
  1532. for ( i = 0; i < edge; i++ ) {
  1533. ReadCompressedInt8Data(mat,&z_copy,(mat_int8_t*)data+i,
  1534. data_type,1);
  1535. InflateSkipData(mat,&z_copy,data_type,stride);
  1536. }
  1537. inflateEnd(&z_copy);
  1538. #endif
  1539. }
  1540. break;
  1541. case MAT_C_UINT8:
  1542. matvar->data_type = MAT_T_UINT8;
  1543. matvar->data_size = sizeof(mat_uint8_t);
  1544. if ( matvar->compression == COMPRESSION_NONE ) {
  1545. stride *= Mat_SizeOf(data_type);
  1546. for ( i = 0; i < edge; i++ ) {
  1547. ReadInt8Data(mat,(mat_int8_t*)data+i,data_type,1);
  1548. fseek(mat->fp,stride,SEEK_CUR);
  1549. }
  1550. #if defined(HAVE_ZLIB)
  1551. } else {
  1552. z_stream z_copy;
  1553. err = inflateCopy(&z_copy,matvar->z);
  1554. InflateSkipData(mat,&z_copy,data_type,start);
  1555. for ( i = 0; i < edge; i++ ) {
  1556. ReadCompressedInt8Data(mat,&z_copy,(mat_int8_t*)data+i,
  1557. data_type,1);
  1558. InflateSkipData(mat,&z_copy,data_type,stride);
  1559. }
  1560. inflateEnd(&z_copy);
  1561. #endif
  1562. }
  1563. break;
  1564. }
  1565. }
  1566. return err;
  1567. }
  1568. /** @brief Reads the information of the next variable in a MAT file
  1569. *
  1570. * Reads the next variable's information (class,flags-complex/global/logical,
  1571. * rank,dimensions, name, etc) from the Matlab MAT file. After reading, the MAT
  1572. * file is positioned past the current variable.
  1573. * @ingroup MAT
  1574. * @param mat Pointer to the MAT file
  1575. * @return Pointer to the @ref matvar_t structure containing the MAT
  1576. * variable information
  1577. */
  1578. matvar_t *
  1579. Mat_VarReadNextInfo( mat_t *mat )
  1580. {
  1581. if( mat == NULL )
  1582. return NULL;
  1583. else if ( mat->version == 0x0100 )
  1584. return Mat_VarReadNextInfo5(mat);
  1585. else
  1586. return Mat_VarReadNextInfo4(mat);
  1587. return NULL;
  1588. }
  1589. /** @brief Reads the information of a variable with the given name from a MAT file
  1590. *
  1591. * Reads the named variable (or the next variable if name is NULL) information
  1592. * (class,flags-complex/global/logical,rank,dimensions,and name) from the
  1593. * Matlab MAT file
  1594. * @ingroup MAT
  1595. * @param mat Pointer to the MAT file
  1596. * @param name Name of the variable to read
  1597. * @return Pointer to the @ref matvar_t structure containing the MAT
  1598. * variable information
  1599. */
  1600. matvar_t *
  1601. Mat_VarReadInfo( mat_t *mat, char *name )
  1602. {
  1603. long fpos;
  1604. matvar_t *matvar = NULL;
  1605. if ( (mat == NULL) || (name == NULL) )
  1606. return NULL;
  1607. fpos = ftell(mat->fp);
  1608. fseek(mat->fp,mat->bof,SEEK_SET);
  1609. do {
  1610. #if 0
  1611. err = fread(&data_type,4,1,mat->fp);
  1612. if ( !err )
  1613. return NULL;
  1614. err = fread(&nBytes,4,1,mat->fp);
  1615. if ( mat->byteswap ) {
  1616. Mat_int32Swap(&data_type);
  1617. Mat_int32Swap(&nBytes);
  1618. }
  1619. curpos = ftell(mat->fp);
  1620. fseek(mat->fp,-8,SEEK_CUR);
  1621. #endif
  1622. matvar = Mat_VarReadNextInfo(mat);
  1623. if ( matvar != NULL ) {
  1624. if ( !matvar->name ) {
  1625. Mat_VarFree(matvar);
  1626. matvar = NULL;
  1627. } else if ( strcmp(matvar->name,name) ) {
  1628. Mat_VarFree(matvar);
  1629. matvar = NULL;
  1630. }
  1631. } else {
  1632. Mat_Critical("An error occurred in reading the MAT file");
  1633. break;
  1634. }
  1635. #if 0
  1636. fseek(mat->fp,curpos+nBytes,SEEK_SET);
  1637. #endif
  1638. } while ( !matvar && !feof(mat->fp) );
  1639. fseek(mat->fp,fpos,SEEK_SET);
  1640. return matvar;
  1641. }
  1642. /** @brief Reads the variable with the given name from a MAT file
  1643. *
  1644. * Reads the next variable in the Matlab MAT file
  1645. * @ingroup MAT
  1646. * @param mat Pointer to the MAT file
  1647. * @param name Name of the variable to read
  1648. * @return Pointer to the @ref matvar_t structure containing the MAT
  1649. * variable information
  1650. */
  1651. matvar_t *
  1652. Mat_VarRead( mat_t *mat, char *name )
  1653. {
  1654. long fpos;
  1655. matvar_t *matvar = NULL;;
  1656. if ( (mat == NULL) || (name == NULL) )
  1657. return NULL;
  1658. fpos = ftell(mat->fp);
  1659. matvar = Mat_VarReadInfo(mat,name);
  1660. if ( matvar )
  1661. ReadData(mat,matvar);
  1662. fseek(mat->fp,fpos,SEEK_SET);
  1663. return matvar;
  1664. }
  1665. /** @brief Reads the next variable in a MAT file
  1666. *
  1667. * Reads the next variable in the Matlab MAT file
  1668. * @ingroup MAT
  1669. * @param mat Pointer to the MAT file
  1670. * @return Pointer to the @ref matvar_t structure containing the MAT
  1671. * variable information
  1672. */
  1673. matvar_t *
  1674. Mat_VarReadNext( mat_t *mat )
  1675. {
  1676. long fpos;
  1677. matvar_t *matvar = NULL;
  1678. if ( feof(mat->fp) )
  1679. return NULL;
  1680. /* Read position so we can reset the file position if an error occurs */
  1681. fpos = ftell(mat->fp);
  1682. matvar = Mat_VarReadNextInfo(mat);
  1683. if ( matvar != NULL)
  1684. ReadData(mat,matvar);
  1685. else
  1686. fseek(mat->fp,fpos,SEEK_SET);
  1687. return matvar;
  1688. }
  1689. /** @brief Writes the given MAT variable to a MAT file
  1690. *
  1691. * Writes the MAT variable information stored in matvar to the given MAT file.
  1692. * The variable will be written to the end of the file.
  1693. * @ingroup MAT
  1694. * @param mat MAT file to write to
  1695. * @param matvar MAT variable information to write
  1696. * @retval 0 on success
  1697. */
  1698. int
  1699. Mat_VarWriteInfo(mat_t *mat, matvar_t *matvar )
  1700. {
  1701. if ( mat == NULL || matvar == NULL || mat->fp == NULL )
  1702. return -1;
  1703. else if ( mat->version != MAT_FT_MAT4 )
  1704. WriteInfo5(mat,matvar);
  1705. #if 0
  1706. else if ( mat->version == MAT_FT_MAT4 )
  1707. WriteInfo4(mat,matvar);
  1708. #endif
  1709. return 0;
  1710. }
  1711. /** @brief Writes the given data to the MAT variable
  1712. *
  1713. * Writes data to a MAT variable. The variable must have previously been
  1714. * written with Mat_VarWriteInfo.
  1715. * @ingroup MAT
  1716. * @param mat MAT file to write to
  1717. * @param matvar MAT variable information to write
  1718. * @param data pointer to the data to write
  1719. * @param start array of starting indeces
  1720. * @param stride stride of data
  1721. * @param edge array specifying the number to read in each direction
  1722. * @retval 0 on success
  1723. */
  1724. int
  1725. Mat_VarWriteData(mat_t *mat,matvar_t *matvar,void *data,
  1726. int *start,int *stride,int *edge)
  1727. {
  1728. int err = 0, k, N = 1;
  1729. fseek(mat->fp,matvar->datapos+8,SEEK_SET);
  1730. if ( mat == NULL || matvar == NULL || data == NULL ) {
  1731. err = -1;
  1732. } else if ( start == NULL && stride == NULL && edge == NULL ) {
  1733. for ( k = 0; k < matvar->rank; k++ )
  1734. N *= matvar->dims[k];
  1735. if ( matvar->compression == COMPRESSION_NONE )
  1736. WriteData(mat,data,N,matvar->data_type);
  1737. #if 0
  1738. else if ( matvar->compression == COMPRESSION_ZLIB ) {
  1739. WriteCompressedData(mat,matvar->z,data,N,matvar->data_type);
  1740. (void)deflateEnd(matvar->z);
  1741. free(matvar->z);
  1742. matvar->z = NULL;
  1743. }
  1744. #endif
  1745. } else if ( matvar->rank == 2 ) {
  1746. if ( stride[0]*(edge[0]-1)+start[0]+1 > matvar->dims[0] ) {
  1747. err = 1;
  1748. } else if ( stride[1]*(edge[1]-1)+start[1]+1 > matvar->dims[1] ) {
  1749. err = 1;
  1750. } else {
  1751. switch ( matvar->class_type ) {
  1752. case MAT_C_DOUBLE:
  1753. case MAT_C_SINGLE:
  1754. case MAT_C_INT64:
  1755. case MAT_C_UINT64:
  1756. case MAT_C_INT32:
  1757. case MAT_C_UINT32:
  1758. case MAT_C_INT16:
  1759. case MAT_C_UINT16:
  1760. case MAT_C_INT8:
  1761. case MAT_C_UINT8:
  1762. WriteDataSlab2(mat,data,matvar->data_type,matvar->dims,
  1763. start,stride,edge);
  1764. break;
  1765. case MAT_C_CHAR:
  1766. WriteCharDataSlab2(mat,data,matvar->data_type,matvar->dims,
  1767. start,stride,edge);
  1768. break;
  1769. }
  1770. }
  1771. }
  1772. return err;
  1773. }
  1774. /** @brief Writes the given MAT variable to a MAT file
  1775. *
  1776. * Writes the MAT variable information stored in matvar to the given MAT file.
  1777. * The variable will be written to the end of the file.
  1778. * @ingroup MAT
  1779. * @param mat MAT file to write to
  1780. * @param matvar MAT variable information to write
  1781. * @param compress Whether or not to compress the data
  1782. * (Only valid for version 5 MAT files and variables with numeric data)
  1783. * @retval 0 on success
  1784. */
  1785. int
  1786. Mat_VarWrite( mat_t *mat, matvar_t *matvar, int compress )
  1787. {
  1788. if ( mat == NULL || matvar == NULL )
  1789. return -1;
  1790. else if ( mat->version != MAT_FT_MAT4 )
  1791. Write5(mat,matvar,compress);
  1792. return 0;
  1793. }