io.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  1. /** @file io.c
  2. * MAT I/O 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. #include <stdlib.h>
  23. #include <stdarg.h>
  24. #include <stdio.h>
  25. #include <string.h>
  26. #include "matio.h"
  27. #if !defined(HAVE_VA_COPY) && defined(HAVE___VA_COPY)
  28. # define va_copy(d,s) __va_copy(d,s)
  29. #elif !defined(HAVE_VA_COPY)
  30. # define va_copy(d,s) memcpy(&(d),&(s),sizeof(va_list))
  31. #endif
  32. #ifndef HAVE_VSNPRINTF
  33. # define vsnprintf mat_vsnprintf
  34. # ifdef __cplusplus
  35. extern "C" int vsnprintf(char *,size_t,const char *,va_list);
  36. # else
  37. extern int vsnprintf(char *,size_t,const char *,va_list);
  38. # endif
  39. #endif
  40. #ifndef HAVE_SNPRINTF
  41. # define snprintf mat_snprintf
  42. # ifdef __cplusplus
  43. extern "C" int snprintf(char *str,size_t size,const char *format,...);
  44. # else
  45. extern int snprintf(char *str,size_t size,const char *format,...);
  46. # endif
  47. #endif
  48. #ifndef HAVE_VASPRINTF
  49. # define vasprintf mat_vasprintf
  50. #endif
  51. #ifndef HAVE_ASPRINTF
  52. # define asprintf mat_asprintf
  53. #endif
  54. /** @cond 0 */
  55. #define LOG_LEVEL_ERROR 1
  56. #define LOG_LEVEL_CRITICAL 1 << 1
  57. #define LOG_LEVEL_WARNING 1 << 2
  58. #define LOG_LEVEL_MESSAGE 1 << 3
  59. #define LOG_LEVEL_DEBUG 1 << 4
  60. /** @endif */
  61. static void (*logfunc)(int log_level, char *message ) = NULL;
  62. static char *progname = NULL;
  63. /** @brief Allocates and prints to a new string
  64. *
  65. * @param format format string
  66. * @param ap variable argument list
  67. * @return Newly allocated string with format printed to it
  68. */
  69. char *
  70. strdup_vprintf(const char* format, va_list ap)
  71. {
  72. va_list ap2;
  73. int size;
  74. char* buffer;
  75. va_copy(ap2, ap);
  76. size = vsnprintf(NULL, 0, format, ap2)+1;
  77. va_end(ap2);
  78. buffer = malloc(size+1);
  79. if ( !buffer )
  80. return NULL;
  81. vsnprintf(buffer, size, format, ap);
  82. return buffer;
  83. }
  84. char *
  85. strdup_printf(const char* format, ...)
  86. {
  87. char* buffer;
  88. va_list ap;
  89. va_start(ap, format);
  90. buffer = strdup_vprintf(format, ap);
  91. va_end(ap);
  92. return buffer;
  93. }
  94. static void
  95. matio_error_func( int log_level, char *message )
  96. {
  97. if ( progname ) {
  98. if ( log_level & LOG_LEVEL_CRITICAL) {
  99. fprintf(stderr,"-E- %s: %s\n", progname, message);
  100. fflush(stderr);
  101. } else if ( log_level & LOG_LEVEL_ERROR ) {
  102. fprintf(stderr,"-E- %s: %s\n", progname, message);
  103. fflush(stderr);
  104. abort();
  105. } else if ( log_level & LOG_LEVEL_WARNING ) {
  106. fprintf(stderr,"-W- %s: %s\n", progname, message);
  107. fflush(stderr);
  108. } else if ( log_level & LOG_LEVEL_DEBUG ) {
  109. fprintf(stderr,"-D- %s: %s\n", progname, message);
  110. fflush(stderr);
  111. } else if ( log_level & LOG_LEVEL_MESSAGE ) {
  112. fprintf(stdout,"%s\n", message);
  113. fflush(stdout);
  114. }
  115. } else {
  116. if ( log_level & LOG_LEVEL_CRITICAL) {
  117. fprintf(stderr,"-E- : %s\n", message);
  118. fflush(stderr);
  119. } else if ( log_level & LOG_LEVEL_ERROR ) {
  120. fprintf(stderr,"-E- : %s\n", message);
  121. fflush(stderr);
  122. abort();
  123. } else if ( log_level & LOG_LEVEL_WARNING ) {
  124. fprintf(stderr,"-W- : %s\n", message);
  125. fflush(stderr);
  126. } else if ( log_level & LOG_LEVEL_DEBUG ) {
  127. fprintf(stderr,"-D- : %s\n", message);
  128. fflush(stderr);
  129. } else if ( log_level & LOG_LEVEL_MESSAGE ) {
  130. fprintf(stdout,"%s\n", message);
  131. fflush(stdout);
  132. }
  133. }
  134. }
  135. static void
  136. scats_log(int loglevel, const char *format, va_list ap)
  137. {
  138. char* buffer;
  139. if ( !logfunc ) return;
  140. buffer = strdup_vprintf(format, ap);
  141. (*logfunc)(loglevel,buffer);
  142. free(buffer);
  143. return;
  144. }
  145. /** @var debug
  146. * @brief holds the verbose level set in @ref SetVerbose
  147. * This variable is used to determine if information should be printed to
  148. * the screen
  149. * @ingroup libscatsio
  150. */
  151. static int debug = 0;
  152. /** @var verbose
  153. * @brief holds the verbose level set in @ref SetVerbose
  154. * This variable is used to determine if information should be printed to
  155. * the screen
  156. * @ingroup libscatsio
  157. */
  158. static int verbose = 0;
  159. /** @var silent
  160. * @brief holds the silent level set in @ref SetVerbose
  161. * If set, all output which is not an error is not displayed regardless
  162. * of verbose level
  163. * @ingroup libscatsio
  164. */
  165. static int silent = 0;
  166. /** @brief Sets verbose parameters
  167. *
  168. * Sets the verbose level and silent level. These values are used by
  169. * programs to determine what information should be printed to the screen
  170. * @ingroup libscatsio
  171. * @param verb sets logging verbosity level
  172. * @param s sets logging silent level
  173. */
  174. int Mat_SetVerbose( int verb, int s )
  175. {
  176. verbose = verb;
  177. silent = s;
  178. return 0;
  179. }
  180. /** @brief Sets verbose parameters
  181. *
  182. * Sets the verbose level and silent level. These values are used by
  183. * programs to determine what information should be printed to the screen
  184. * @ingroup libscatsio
  185. * @param verb sets logging verbosity level
  186. * @param s sets logging silent level
  187. */
  188. int Mat_SetDebug( int d )
  189. {
  190. debug = d;
  191. return 0;
  192. }
  193. /** @brief Log a message unless silent
  194. *
  195. * Logs the message unless the silent option is set (See @ref SetVerbose).
  196. * To log a message based on the verbose level, use @ref Mat_VerbMessage
  197. * @ingroup libscatsio
  198. * @param format message format
  199. */
  200. int Mat_Message( const char *format, ... )
  201. {
  202. va_list ap;
  203. if ( silent ) return 0;
  204. if ( !logfunc ) return 0;
  205. va_start(ap, format );
  206. scats_log(LOG_LEVEL_MESSAGE, format, ap );
  207. va_end(ap);
  208. return 0;
  209. }
  210. /** @brief Log a message based on verbose level
  211. *
  212. * If @e level is less than or equal to the set verbose level, the message
  213. * is printed. If the level is higher than the set verbose level nothing
  214. * is displayed.
  215. * @ingroup libscatsio
  216. * @param level verbose level
  217. * @param format message format
  218. */
  219. int Mat_DebugMessage( int level, const char *format, ... )
  220. {
  221. va_list ap;
  222. if ( silent ) return 0;
  223. if ( level > debug ) return 0;
  224. va_start(ap, format );
  225. scats_log(LOG_LEVEL_DEBUG, format, ap );
  226. va_end(ap);
  227. return 0;
  228. }
  229. /** @brief Log a message based on verbose level
  230. *
  231. * If @e level is less than or equal to the set verbose level, the message
  232. * is printed. If the level is higher than the set verbose level nothing
  233. * is displayed.
  234. * @ingroup libscatsio
  235. * @param level verbose level
  236. * @param format message format
  237. */
  238. int Mat_VerbMessage( int level, const char *format, ... )
  239. {
  240. va_list ap;
  241. if ( silent ) return 0;
  242. if ( level > verbose ) return 0;
  243. va_start(ap, format );
  244. scats_log(LOG_LEVEL_MESSAGE, format, ap );
  245. va_end(ap);
  246. return 0;
  247. }
  248. /** @brief Logs a Critical message and returns to the user
  249. *
  250. * Logs a Critical message and returns to the user. If the program should
  251. * stop running, use @ref Mat_Error
  252. * @ingroup libscatsio
  253. * @param format format string identical to printf format
  254. * @param ... arguments to the format string
  255. */
  256. void Mat_Critical( const char *format, ... )
  257. {
  258. va_list ap;
  259. va_start(ap, format );
  260. scats_log(LOG_LEVEL_CRITICAL, format, ap );
  261. va_end(ap);
  262. }
  263. /** @brief Logs a Critical message and aborts the program
  264. *
  265. * Logs an Error message and aborts
  266. * @ingroup libscatsio
  267. * @param format format string identical to printf format
  268. * @param ... arguments to the format string
  269. */
  270. void Mat_Error( const char *format, ... )
  271. {
  272. va_list ap;
  273. va_start(ap, format );
  274. scats_log( LOG_LEVEL_ERROR, format, ap );
  275. va_end(ap);
  276. }
  277. /** @brief Prints a helpstring to stdout and exits with status 1
  278. *
  279. * Prints the array of strings to stdout and exits with status 1. The array
  280. * of strings should have NULL as its last element
  281. * @code
  282. * char *helpstr[] = {"My Help string line1","My help string line 2",NULL};
  283. * Mat_Help(helpstr);
  284. * @endcode
  285. * @ingroup libscatsio
  286. * @param helpstr array of strings with NULL as its last element
  287. */
  288. void Mat_Help( const char *helpstr[] )
  289. {
  290. int i;
  291. for (i = 0; helpstr[i] != NULL; i++)
  292. printf("%s\n",helpstr[i]);
  293. exit(EXIT_SUCCESS);
  294. }
  295. /** @brief Closes the logging system
  296. *
  297. * @retval 1
  298. */
  299. int
  300. Mat_LogClose( )
  301. {
  302. logfunc = NULL;
  303. return 1;
  304. }
  305. /** @brief Intializes the logging system
  306. *
  307. * @ingroup libscatsio
  308. * @param prog_name Name of the program initializing the logging functions
  309. * @return 0 on success
  310. */
  311. int
  312. Mat_LogInit( char *prog_name )
  313. {
  314. logfunc = &matio_error_func;
  315. verbose = 0;
  316. silent = 0;
  317. return 0;
  318. }
  319. /** @brief Intializes the logging system
  320. *
  321. * @ingroup libscatsio
  322. * @param prog_name Name of the program initializing the logging functions
  323. * @param log_func pointer to the function to do the logging
  324. * @return 0 on success
  325. */
  326. int
  327. Mat_LogInitFunc(char *prog_name,void (*log_func)(int log_level,char *message))
  328. {
  329. logfunc = log_func;
  330. progname = prog_name;
  331. verbose = 0;
  332. silent = 0;
  333. return 0;
  334. }
  335. /** @brief Prints a warning message to stdout
  336. *
  337. * Logs a warning message then returns
  338. * @ingroup libscatsio
  339. * @param format format string identical to printf format
  340. * @param ... arguments to the format string
  341. */
  342. void Mat_Warning( const char *format, ... )
  343. {
  344. va_list ap;
  345. va_start(ap, format );
  346. scats_log(LOG_LEVEL_WARNING, format, ap );
  347. va_end(ap);
  348. }
  349. size_t
  350. Mat_SizeOf(int data_type)
  351. {
  352. switch (data_type) {
  353. case MAT_T_DOUBLE:
  354. return sizeof(double);
  355. case MAT_T_SINGLE:
  356. return sizeof(float);
  357. #ifdef HAVE_MAT_INT64_T
  358. case MAT_T_INT64:
  359. return sizeof(mat_int64_t);
  360. #endif
  361. #ifdef HAVE_MAT_INT64_T
  362. case MAT_T_UINT64:
  363. return sizeof(mat_uint64_t);
  364. #endif
  365. case MAT_T_INT32:
  366. return sizeof(mat_int32_t);
  367. case MAT_T_UINT32:
  368. return sizeof(mat_uint32_t);
  369. case MAT_T_INT16:
  370. return sizeof(mat_int16_t);
  371. case MAT_T_UINT16:
  372. return sizeof(mat_uint16_t);
  373. case MAT_T_INT8:
  374. return sizeof(mat_int8_t);
  375. case MAT_T_UINT8:
  376. return sizeof(mat_uint8_t);
  377. default:
  378. return 0;
  379. }
  380. }