• Main Page
  • Related Pages
  • Data Structures
  • Files
  • File List
  • Globals

src/libsphinxbase/util/pio.c

00001 /* -*- c-basic-offset: 4; indent-tabs-mode: nil -*- */
00002 /* ====================================================================
00003  * Copyright (c) 1999-2004 Carnegie Mellon University.  All rights
00004  * reserved.
00005  *
00006  * Redistribution and use in source and binary forms, with or without
00007  * modification, are permitted provided that the following conditions
00008  * are met:
00009  *
00010  * 1. Redistributions of source code must retain the above copyright
00011  *    notice, this list of conditions and the following disclaimer. 
00012  *
00013  * 2. Redistributions in binary form must reproduce the above copyright
00014  *    notice, this list of conditions and the following disclaimer in
00015  *    the documentation and/or other materials provided with the
00016  *    distribution.
00017  *
00018  * This work was supported in part by funding from the Defense Advanced 
00019  * Research Projects Agency and the National Science Foundation of the 
00020  * United States of America, and the CMU Sphinx Speech Consortium.
00021  *
00022  * THIS SOFTWARE IS PROVIDED BY CARNEGIE MELLON UNIVERSITY ``AS IS'' AND 
00023  * ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 
00024  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
00025  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY
00026  * NOR ITS EMPLOYEES BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
00027  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
00028  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 
00029  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
00030  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
00031  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
00032  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00033  *
00034  * ====================================================================
00035  *
00036  */
00037 
00038 #include <config.h>
00039 
00040 #include <stdio.h>
00041 #include <stdlib.h>
00042 #include <string.h>
00043 #ifdef HAVE_UNISTD_H
00044 #include <unistd.h>
00045 #endif
00046 #include <assert.h>
00047 
00048 #include "pio.h"
00049 #include "err.h"
00050 #include "ckd_alloc.h"
00051 
00052 FILE *
00053 fopen_comp(const char *file, const char *mode, int32 * ispipe)
00054 {
00055     FILE *fp;
00056 
00057 #ifndef HAVE_POPEN
00058     *ispipe = 0; /* No popen() on WinCE */
00059 #else /* HAVE_POPEN */
00060     int32 k, isgz;
00061     k = strlen(file);
00062 #if defined(WIN32)
00063     *ispipe = (k > 3) && ((strcmp(file + k - 3, ".gz") == 0)
00064                           || (strcmp(file + k - 3, ".GZ") == 0));
00065     isgz = *ispipe;
00066 #else
00067     *ispipe = 0;
00068     isgz = 0;
00069     if ((k > 2)
00070         && ((strcmp(file + k - 2, ".Z") == 0)
00071             || (strcmp(file + k - 2, ".z") == 0))) {
00072         *ispipe = 1;
00073     }
00074     else {
00075         if ((k > 3) && ((strcmp(file + k - 3, ".gz") == 0)
00076                         || (strcmp(file + k - 3, ".GZ") == 0))) {
00077             *ispipe = 1;
00078             isgz = 1;
00079         }
00080     }
00081 #endif /* NOT WIN32 */
00082 #endif /* HAVE_POPEN */
00083 
00084     if (*ispipe) {
00085 #ifndef HAVE_POPEN
00086         /* Shouldn't get here, anyway */
00087         E_FATAL("No popen() on WinCE\n");
00088 #else
00089         char command[16384];
00090 #if defined(WIN32) 
00091         if (strcmp(mode, "r") == 0) {
00092             sprintf(command, "gzip.exe -d -c %s", file);
00093             if ((fp = _popen(command, mode)) == NULL) {
00094                 E_ERROR_SYSTEM("_popen (%s,%s) failed\n", command, mode);
00095                 return NULL;
00096             }
00097         }
00098         else if (strcmp(mode, "w") == 0) {
00099             sprintf(command, "gzip.exe > %s", file);
00100 
00101             if ((fp = _popen(command, mode)) == NULL) {
00102                 E_ERROR_SYSTEM("_popen (%s,%s) failed\n", command, mode);
00103                 return NULL;
00104             }
00105         }
00106         else {
00107             E_ERROR("fopen_comp not implemented for mode = %s\n", mode);
00108             return NULL;
00109         }
00110 #else
00111         if (strcmp(mode, "r") == 0) {
00112             if (isgz)
00113                 sprintf(command, "gunzip -c %s", file);
00114             else
00115                 sprintf(command, "zcat %s", file);
00116 
00117             if ((fp = popen(command, mode)) == NULL) {
00118                 E_ERROR_SYSTEM("popen (%s,%s) failed\n", command, mode);
00119                 return NULL;
00120             }
00121         }
00122         else if (strcmp(mode, "w") == 0) {
00123             if (isgz)
00124                 sprintf(command, "gzip > %s", file);
00125             else
00126                 sprintf(command, "compress -c > %s", file);
00127 
00128             if ((fp = popen(command, mode)) == NULL) {
00129                 E_ERROR_SYSTEM("popen (%s,%s) failed\n", command, mode);
00130                 return NULL;
00131             }
00132         }
00133         else {
00134             E_ERROR("fopen_comp not implemented for mode = %s\n", mode);
00135             return NULL;
00136         }
00137 #endif /* NOT WIN32 */
00138 #endif /* HAVE_POPEN */
00139     }
00140     else {
00141         fp = fopen(file, mode);
00142     }
00143 
00144     return (fp);
00145 }
00146 
00147 
00148 void
00149 fclose_comp(FILE * fp, int32 ispipe)
00150 {
00151     if (ispipe) {
00152 #ifdef HAVE_POPEN
00153 #if defined(WIN32)
00154         _pclose(fp);
00155 #else
00156         pclose(fp);
00157 #endif
00158 #endif
00159     }
00160     else
00161         fclose(fp);
00162 }
00163 
00164 
00165 FILE *
00166 fopen_compchk(const char *file, int32 * ispipe)
00167 {
00168 #ifndef HAVE_POPEN
00169     *ispipe = 0; /* No popen() on WinCE */
00170     /* And therefore the rest of this function is useless. */
00171     return (fopen_comp(file, "r", ispipe));
00172 #else /* HAVE_POPEN */
00173     char tmpfile[16384];
00174     int32 k, isgz;
00175     struct stat statbuf;
00176 
00177     k = strlen(file);
00178 
00179 #if defined(WIN32)
00180     *ispipe = (k > 3) && ((strcmp(file + k - 3, ".gz") == 0)
00181                           || (strcmp(file + k - 3, ".GZ") == 0));
00182     isgz = *ispipe;
00183 #else
00184     *ispipe = 0;
00185     isgz = 0;
00186     if ((k > 2)
00187         && ((strcmp(file + k - 2, ".Z") == 0)
00188             || (strcmp(file + k - 2, ".z") == 0))) {
00189         *ispipe = 1;
00190     }
00191     else {
00192         if ((k > 3) && ((strcmp(file + k - 3, ".gz") == 0)
00193                         || (strcmp(file + k - 3, ".GZ") == 0))) {
00194             *ispipe = 1;
00195             isgz = 1;
00196         }
00197     }
00198 #endif
00199 
00200     strcpy(tmpfile, file);
00201     if (stat(tmpfile, &statbuf) != 0) {
00202         /* File doesn't exist; try other compressed/uncompressed form, as appropriate */
00203         E_ERROR_SYSTEM("stat(%s) failed\n", tmpfile);
00204 
00205         if (*ispipe) {
00206             if (isgz)
00207                 tmpfile[k - 3] = '\0';
00208             else
00209                 tmpfile[k - 2] = '\0';
00210 
00211             if (stat(tmpfile, &statbuf) != 0)
00212                 return NULL;
00213         }
00214         else {
00215             strcpy(tmpfile + k, ".gz");
00216             if (stat(tmpfile, &statbuf) != 0) {
00217 #if (! WIN32)
00218                 strcpy(tmpfile + k, ".Z");
00219                 if (stat(tmpfile, &statbuf) != 0)
00220                     return NULL;
00221 #else
00222                 return NULL;
00223 #endif
00224             }
00225         }
00226 
00227         E_WARN("Using %s instead of %s\n", tmpfile, file);
00228     }
00229 
00230     return (fopen_comp(tmpfile, "r", ispipe));
00231 #endif /* HAVE_POPEN */
00232 }
00233 
00234 lineiter_t *
00235 lineiter_start(FILE *fh)
00236 {
00237     lineiter_t *li;
00238 
00239     li = ckd_calloc(1, sizeof(*li));
00240     li->buf = ckd_malloc(128);
00241     li->buf[0] = '\0';
00242     li->bsiz = 128;
00243     li->len = 0;
00244     li->fh = fh;
00245 
00246     return lineiter_next(li);
00247 }
00248 
00249 lineiter_t *
00250 lineiter_next(lineiter_t *li)
00251 {
00252     /* Read a line and check for EOF. */
00253     if (fgets(li->buf, li->bsiz, li->fh) == NULL) {
00254         lineiter_free(li);
00255         return NULL;
00256     }
00257     /* If we managed to read the whole thing, then we are done
00258      * (this will be by far the most common result). */
00259     li->len = strlen(li->buf);
00260     if (li->len < li->bsiz - 1 || li->buf[li->len - 1] == '\n')
00261         return li;
00262 
00263     /* Otherwise we have to reallocate and keep going. */
00264     while (1) {
00265         li->bsiz *= 2;
00266         li->buf = ckd_realloc(li->buf, li->bsiz);
00267         /* If we get an EOF, we are obviously done. */
00268         if (fgets(li->buf + li->len, li->bsiz - li->len, li->fh) == NULL) {
00269             li->len += strlen(li->buf + li->len);
00270             return li;
00271         }
00272         li->len += strlen(li->buf + li->len);
00273         /* If we managed to read the whole thing, then we are done. */
00274         if (li->len < li->bsiz - 1 || li->buf[li->len - 1] == '\n')
00275             return li;
00276     }
00277 
00278     /* Shouldn't get here. */
00279     return li;
00280 }
00281 
00282 void
00283 lineiter_free(lineiter_t *li)
00284 {
00285     ckd_free(li->buf);
00286     ckd_free(li);
00287 }
00288 
00289 char *
00290 fread_line(FILE *stream, size_t *out_len)
00291 {
00292     char *output, *outptr;
00293     char buf[128];
00294 
00295     output = outptr = NULL;
00296     while (fgets(buf, sizeof(buf), stream)) {
00297         size_t len = strlen(buf);
00298         /* Append this data to the buffer. */
00299         if (output == NULL) {
00300             output = ckd_malloc(len + 1);
00301             outptr = output;
00302         }
00303         else {
00304             size_t cur = outptr - output;
00305             output = ckd_realloc(output, cur + len + 1);
00306             outptr = output + cur;
00307         }
00308         memcpy(outptr, buf, len + 1);
00309         outptr += len;
00310         /* Stop on a short read or end of line. */
00311         if (len < sizeof(buf)-1 || buf[len-1] == '\n')
00312             break;
00313     }
00314     if (out_len) *out_len = outptr - output;
00315     return output;
00316 }
00317 
00318 
00319 #define FREAD_RETRY_COUNT       60
00320 
00321 int32
00322 fread_retry(void *pointer, int32 size, int32 num_items, FILE * stream)
00323 {
00324     char *data;
00325     uint32 n_items_read;
00326     uint32 n_items_rem;
00327     uint32 n_retry_rem;
00328     int32 loc;
00329 
00330     n_retry_rem = FREAD_RETRY_COUNT;
00331 
00332     data = pointer;
00333     loc = 0;
00334     n_items_rem = num_items;
00335 
00336     do {
00337         n_items_read = fread(&data[loc], size, n_items_rem, stream);
00338 
00339         n_items_rem -= n_items_read;
00340 
00341         if (n_items_rem > 0) {
00342             /* an incomplete read occurred */
00343 
00344             if (n_retry_rem == 0)
00345                 return -1;
00346 
00347             if (n_retry_rem == FREAD_RETRY_COUNT) {
00348                 E_ERROR_SYSTEM("fread() failed; retrying...\n");
00349             }
00350 
00351             --n_retry_rem;
00352 
00353             loc += n_items_read * size;
00354 #ifdef HAVE_UNISTD_H
00355             sleep(1);
00356 #endif
00357         }
00358     } while (n_items_rem > 0);
00359 
00360     return num_items;
00361 }
00362 
00363 
00364 #ifdef _WIN32_WCE /* No stat() on WinCE */
00365 int32
00366 stat_retry(const char *file, struct stat * statbuf)
00367 {
00368     WIN32_FIND_DATA file_data;
00369     HANDLE *h;
00370     wchar_t *wfile;
00371     size_t len;
00372 
00373     len = mbstowcs(NULL, file, 0) + 1;
00374     wfile = ckd_calloc(len, sizeof(*wfile));
00375     mbstowcs(wfile, file, len);
00376     if ((h = FindFirstFile(wfile, &file_data)) == INVALID_HANDLE_VALUE) {
00377         ckd_free(wfile);
00378         return -1;
00379     }
00380     ckd_free(wfile);
00381     memset(statbuf, 0, sizeof(statbuf));
00382     statbuf->st_mtime = file_data.ftLastWriteTime.dwLowDateTime;
00383     statbuf->st_size = file_data.nFileSizeLow;
00384     FindClose(h);
00385 
00386     return 0;
00387 }
00388 
00389 
00390 int32
00391 stat_mtime(const char *file)
00392 {
00393     struct stat statbuf;
00394 
00395     if (stat_retry(file, &statbuf) != 0)
00396         return -1;
00397 
00398     return ((int32) statbuf.st_mtime);
00399 }
00400 #else
00401 #define STAT_RETRY_COUNT        10
00402 int32
00403 stat_retry(const char *file, struct stat * statbuf)
00404 {
00405     int32 i;
00406 
00407     
00408     
00409     for (i = 0; i < STAT_RETRY_COUNT; i++) {
00410 
00411 #ifndef HAVE_SYS_STAT_H
00412                 FILE *fp;
00413 
00414                 if ((fp=(FILE *)fopen(file, "r"))!= 0)
00415                 {
00416                     fseek( fp, 0, SEEK_END);
00417                     statbuf->st_size = ftell( fp );
00418                     fclose(fp);
00419                     return 0;
00420                 }
00421         
00422 #else /* HAVE_SYS_STAT_H */
00423         if (stat(file, statbuf) == 0)
00424             return 0;
00425 #endif
00426         if (i == 0) {
00427             E_ERROR_SYSTEM("stat(%s) failed; retrying...\n", file);
00428         }
00429 #ifdef HAVE_UNISTD_H
00430         sleep(1);
00431 #endif
00432     }
00433 
00434     return -1;
00435 }
00436 
00437 int32
00438 stat_mtime(const char *file)
00439 {
00440     struct stat statbuf;
00441 
00442 #ifdef HAVE_SYS_STAT_H
00443     if (stat(file, &statbuf) != 0)
00444         return -1;
00445 #else /* HAVE_SYS_STAT_H */
00446     if (stat_retry(file, &statbuf) != 0)
00447         return -1;
00448 #endif /* HAVE_SYS_STAT_H */
00449 
00450     return ((int32) statbuf.st_mtime);
00451 }
00452 #endif /* !_WIN32_WCE */

Generated on Fri Jan 14 2011 for SphinxBase by  doxygen 1.7.1