00001 /*************************************************************************** 00002 * @file gnn_filewriter.c 00003 * @brief gnn_filewriter Implementation. 00004 * 00005 * @date : 28-09-03 18:10 00006 * @author : Pedro Ortega C. <peortega@dcc.uchile.cl> 00007 * Copyright 2003 Pedro Ortega C. 00008 ****************************************************************************/ 00009 /* 00010 * This program is free software; you can redistribute it and/or modify 00011 * it under the terms of the GNU General Public License as published by 00012 * the Free Software Foundation; either version 2 of the License, or 00013 * (at your option) any later version. 00014 * 00015 * This program is distributed in the hope that it will be useful, 00016 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00017 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00018 * GNU Library General Public License for more details. 00019 * 00020 * You should have received a copy of the GNU General Public License 00021 * along with this program; if not, write to the Free Software 00022 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00023 */ 00024 00025 00026 00027 /** 00028 * @defgroup gnn_filewriter_doc gnn_filewriter : File Output Device. 00029 * @ingroup gnn_output_doc 00030 * @brief Writes outputs sequentially to a file. 00031 * 00032 * The \ref gnn_filewriter implements a sequential file output device. The 00033 * output patterns are written to a given file stream. 00034 * 00035 * This is the datatype for a filewriter. It extends the basic 00036 * \ref gnn_output structure to include the additional pointer 00037 * to the output samples matrix, and a vector view. 00038 * 00039 * A filewriter, when created, opens the given file in ASCII mode. 00040 * Alternativelly, you can provide an already opened file pointer. After 00041 * that, it writes the given samples one after another (line per line) to 00042 * the opened output stream. 00043 * 00044 * By default, vectors are written line-wise, with the format "%g\t" to 00045 * seperate the elements (of the printed vector). A new format string can 00046 * be given, of course. 00047 * 00048 * Additionally, a prefix and a postfix format string can be used. 00049 * The are pre- and post-concatenated to the string containing the vector's 00050 * elements. 00051 * 00052 * As an example, the following output will be produced without pre- and 00053 * postfix strings: 00054 * 00055 * \code 00056 * 12.345 3.45 8 00057 * 0.1247 3.387 0.001 00058 * 78.56 5 89.23 00059 * 12.2356 0.147 0.235 00060 * \endcode 00061 * 00062 * Using the prefix "Pattern %d : [" and postfix "]", the same samples will 00063 * be printed as: 00064 * 00065 * \code 00066 * Pattern 0 : [12.345 3.45 8 ] 00067 * Pattern 1 : [0.1247 3.387 0.001 ] 00068 * Pattern 2 : [78.56 5 89.23 ] 00069 * Pattern 3 : [12.2356 0.147 0.235 ] 00070 * \endcode 00071 * 00072 * Please note that the prefix contains a "%d" substring. This is the one and 00073 * only allowed format command for the prefix, which will be replaced by the 00074 * number of the output sample to be written. 00075 */ 00076 00077 00078 00079 /******************************************/ 00080 /* Include Files */ 00081 /******************************************/ 00082 00083 #include <stdio.h> 00084 #include <string.h> 00085 #include "gnn_filewriter.h" 00086 00087 00088 00089 /******************************************/ 00090 /* Static Declaration */ 00091 /******************************************/ 00092 00093 /** 00094 * @brief The datatype for a filewriter. 00095 * @ingroup gnn_filewriter_doc 00096 * 00097 */ 00098 typedef struct _gnn_filewriter gnn_filewriter; 00099 00100 struct _gnn_filewriter 00101 { 00102 gnn_output set; 00103 FILE *fp; /*< The output file pointer. */ 00104 int fileowner; /*< 1 if the \ref gnn_filewriter owns the file. */ 00105 char *format; /*< The printing format for each vector component. */ 00106 char *prefix; /*< The prefix. */ 00107 char *postfix; /*< The postfix. */ 00108 }; 00109 00110 static int 00111 gnn_filewriter_put (gnn_output *set, size_t k, const gsl_vector *v); 00112 00113 static void 00114 gnn_filewriter_destroy (gnn_output *set); 00115 00116 00117 00118 /******************************************/ 00119 /* Static Implementation */ 00120 /******************************************/ 00121 00122 /** 00123 * @brief The "put" function. 00124 * @ingroup gnn_filewriter_doc 00125 * 00126 * @param set A pointer to a \ref gnn_filewriter. 00127 * @param k The index of the pattern to be stored. 00128 * @param v A pointer to the output vector to be stored. 00129 * @return Returns 0 if suceeded. 00130 */ 00131 static int 00132 gnn_filewriter_put (gnn_output *set, size_t k, const gsl_vector *v) 00133 { 00134 size_t i; 00135 gnn_filewriter *fset; 00136 00137 /* get view */ 00138 fset = (gnn_filewriter *) set; 00139 00140 /* print prefix */ 00141 if (fset->prefix) 00142 fprintf (fset->fp, fset->prefix, k); 00143 00144 /* printf output vector */ 00145 for (i=0; i<v->size; ++i) 00146 { 00147 fprintf (fset->fp, fset->format, gsl_vector_get (v, i)); 00148 } 00149 00150 /* print postfix */ 00151 if (fset->postfix) 00152 fprintf (fset->fp, fset->prefix, k); 00153 00154 /* next line */ 00155 fprintf (fset->fp, "\n"); 00156 00157 return 0; 00158 } 00159 00160 /** 00161 * @brief The "destroy" function. 00162 * @ingroup gnn_filewriter_doc 00163 * 00164 * @param set A pointer to a \ref gnn_filewriter. 00165 * @param k The index of the pattern to be stored. 00166 * @param v A pointer to the output vector to be stored. 00167 * @return Returns 0 if suceeded. 00168 */ 00169 static void 00170 gnn_filewriter_destroy (gnn_output *set) 00171 { 00172 gnn_filewriter *fset; 00173 00174 assert (set != NULL); 00175 00176 fset = (gnn_filewriter *) set; 00177 00178 if (fset->format != NULL) 00179 free (fset->format); 00180 if (fset->prefix != NULL) 00181 free (fset->prefix); 00182 if (fset->postfix != NULL) 00183 free (fset->postfix); 00184 if (fset->fileowner && fset->fp != NULL) 00185 fclose (fset->fp); 00186 } 00187 00188 00189 00190 /******************************************/ 00191 /* Public Interface */ 00192 /******************************************/ 00193 00194 /** 00195 * @brief Builds a new filewriter device. 00196 * @ingroup gnn_filewriter_doc 00197 * 00198 * This function creates a new \ref gnn_filewriter device with the 00199 * given opened file pointer. When destroyed, the stream won't be closed. 00200 * 00201 * @param fp A valid and opened file pointer. 00202 * @return Returns a pointer to a new \ref gnn_filewriter. 00203 */ 00204 gnn_output * 00205 gnn_filewriter_new (FILE *fp) 00206 { 00207 int status; 00208 gnn_output *set; 00209 gnn_filewriter *fset; 00210 00211 /* check filepointer */ 00212 if (fp == NULL) 00213 { 00214 GSL_ERROR_VAL ("a valid file pointer should be given", 00215 GSL_EINVAL, NULL); 00216 } 00217 00218 /* allocate */ 00219 fset = (gnn_filewriter *) calloc (sizeof (*fset), 1); 00220 if (fset == NULL) 00221 { 00222 GSL_ERROR_VAL ("could not allocate memory for gnn_filewriter", 00223 GSL_ENOMEM, NULL); 00224 } 00225 00226 /* get view */ 00227 set = (gnn_output *) fset; 00228 00229 /* initialize */ 00230 status = gnn_output_stream_init (set, NULL, 00231 gnn_filewriter_put, 00232 gnn_filewriter_destroy); 00233 if (status) 00234 { 00235 gnn_output_destroy (set); 00236 GSL_ERROR_VAL ("could not initialize gnn_filewriter", 00237 GSL_EFAILED, NULL); 00238 } 00239 00240 /* set fields */ 00241 fset->fp = fp; 00242 fset->fileowner = 0; 00243 fset->format = strdup ("%g\t"); 00244 fset->prefix = NULL; 00245 fset->postfix = NULL; 00246 00247 return set; 00248 } 00249 00250 /** 00251 * @brief Builds a new filewriter device with a given filename. 00252 * @ingroup gnn_filewriter_doc 00253 * 00254 * This function creates a new \ref gnn_filewriter device. It opens the 00255 * file \a filename for printing. The \ref gnn_filewriter is the owner of 00256 * the file and closes it when destroyed. 00257 * 00258 * @param filename A string containing the file name for printing. 00259 * @return Returns a pointer to a new \ref gnn_filewriter. 00260 */ 00261 gnn_output * 00262 gnn_filewriter_with_file_new (const char *filename) 00263 { 00264 int status; 00265 FILE *fp; 00266 gnn_output *set; 00267 gnn_filewriter *fset; 00268 00269 /* check filename */ 00270 if (filename == NULL) 00271 { 00272 GSL_ERROR_VAL ("a valid file pointer should be given", 00273 GSL_EINVAL, NULL); 00274 } 00275 00276 /* open file */ 00277 fp = fopen (filename, "w"); 00278 if (fp == NULL) 00279 { 00280 GSL_ERROR_VAL ("couldn't open the given file", GSL_EINVAL, NULL); 00281 } 00282 00283 /* create filewriter */ 00284 set = gnn_filewriter_new (fp); 00285 00286 /* set owner field */ 00287 fset = (gnn_filewriter *) set; 00288 fset->fileowner = 1; 00289 00290 return set; 00291 } 00292 00293 /** 00294 * @brief Sets a new print format. 00295 * @ingroup gnn_filewriter_doc 00296 * 00297 * This function sets a new print format for the vector elements of the 00298 * samples. The default is \c "%g\t", which separates the elements by tabs. 00299 * The \em format specifier should contain a valid double-precision 00300 * specifier, like \c "%f ", \c "%e " or \c "%g " (do not forget to include 00301 * a separator). 00302 * 00303 * @param set A pointer to a \ref gnn_filewriter. 00304 * @param fmt A format string for double precision values. 00305 * @return Returns a pointer to a new \ref gnn_filewriter. 00306 */ 00307 int 00308 gnn_filewriter_set_format (gnn_output *set, const char *fmt) 00309 { 00310 gnn_filewriter *fset; 00311 00312 assert (set != NULL); 00313 00314 if (fmt == NULL) 00315 { 00316 GSL_ERROR ("invalid format string", GSL_EINVAL); 00317 } 00318 00319 fset = (gnn_filewriter *) set; 00320 00321 if (fset->format != NULL) 00322 free (fset->format); 00323 fset->format = strdup (fmt); 00324 00325 return 0; 00326 } 00327 00328 /** 00329 * @brief Gets the print format. 00330 * @ingroup gnn_filewriter_doc 00331 * 00332 * This function returns a pointer to the currently used vector elements 00333 * print format. 00334 * 00335 * @param fmt A format string for double precision values. 00336 * @return Returns a pointer to a new \ref gnn_filewriter. 00337 */ 00338 const char * 00339 gnn_filewriter_get_format (gnn_output *set) 00340 { 00341 gnn_filewriter *fset; 00342 00343 assert (set != NULL); 00344 00345 fset = (gnn_filewriter *) set; 00346 00347 return fset->format; 00348 } 00349 00350 /** 00351 * @brief Sets a new printing prefix. 00352 * @ingroup gnn_filewriter_doc 00353 * 00354 * This function sets a new printing prefix, which will be prepended to every 00355 * printed output vector. This string can contain at most one integer 00356 * \em format specifier, like \c "N %d :". The placeholder will be filled 00357 * with the number of the written pattern. 00358 * 00359 * @param set A pointer to a \ref gnn_filewriter. 00360 * @param prefix A prefix format string or NULL. 00361 * @return Returns 0 if succeeded. 00362 */ 00363 int 00364 gnn_filewriter_set_prefix (gnn_output *set, const char *prefix) 00365 { 00366 gnn_filewriter *fset; 00367 00368 assert (set != NULL); 00369 00370 fset = (gnn_filewriter *) set; 00371 00372 if (fset->prefix != NULL) 00373 free (fset->prefix); 00374 fset->prefix = NULL; 00375 if (prefix != NULL) 00376 fset->prefix = strdup (prefix); 00377 00378 return 0; 00379 } 00380 00381 /** 00382 * @brief Gets the prefix format string. 00383 * @ingroup gnn_filewriter_doc 00384 * 00385 * This function returns a pointer to the currently used prefix string. 00386 * 00387 * @param set A pointer to a \ref gnn_filewriter. 00388 * @return Returns a pointer to the prefix or NULL. 00389 */ 00390 const char * 00391 gnn_filewriter_get_prefix (gnn_output *set) 00392 { 00393 gnn_filewriter *fset; 00394 00395 assert (set != NULL); 00396 00397 fset = (gnn_filewriter *) set; 00398 00399 return fset->prefix; 00400 } 00401 00402 /** 00403 * @brief Sets a new printing postfix. 00404 * @ingroup gnn_filewriter_doc 00405 * 00406 * This function sets a new printing postfix, which will be postpended to every 00407 * printed output vector. This string can contain at most one integer 00408 * \em format specifier, like \c "N %d :". The placeholder will be filled 00409 * with the number of the written pattern. 00410 * 00411 * @param set A pointer to a \ref gnn_filewriter. 00412 * @param prefix A postfix format string or NULL. 00413 * @return Returns 0 if succeeded. 00414 */ 00415 int 00416 gnn_filewriter_set_postfix (gnn_output *set, const char *postfix) 00417 { 00418 gnn_filewriter *fset; 00419 00420 assert (set != NULL); 00421 00422 fset = (gnn_filewriter *) set; 00423 00424 if (fset->postfix != NULL) 00425 free (fset->postfix); 00426 fset->postfix = NULL; 00427 if (postfix != NULL) 00428 fset->postfix = strdup (postfix); 00429 00430 return 0; 00431 } 00432 00433 /** 00434 * @brief Gets the postfix format string. 00435 * @ingroup gnn_filewriter_doc 00436 * 00437 * This function returns a pointer to the currently used postfix string. 00438 * 00439 * @param set A pointer to a \ref gnn_filewriter. 00440 * @return Returns a pointer to the postfix or NULL. 00441 */ 00442 const char * 00443 gnn_filewriter_get_postfix (gnn_output *set) 00444 { 00445 gnn_filewriter *fset; 00446 00447 assert (set != NULL); 00448 00449 fset = (gnn_filewriter *) set; 00450 00451 return fset->postfix; 00452 } 00453 00454 00455 /** 00456 * @brief Check if it owns the file. 00457 * @ingroup gnn_filewriter_doc 00458 * 00459 * This function returns 1 if the \ref gnn_filewriter owns the file. 00460 * 00461 * @param set A pointer to a \ref gnn_filewriter. 00462 * @return Returns 1 if it owns the file or 0 if not. 00463 */ 00464 int 00465 gnn_filewriter_owns_file (gnn_output *set) 00466 { 00467 gnn_filewriter *fset; 00468 00469 assert (set != NULL); 00470 00471 fset = (gnn_filewriter *) set; 00472 if (fset->fileowner) 00473 return 1; 00474 else 00475 return 0; 00476 } 00477 00478
1.2.18