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

src/libsphinxbase/util/bio.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  * bio.c -- Sphinx-3 binary file I/O functions.
00039  * 
00040  * **********************************************
00041  * CMU ARPA Speech Project
00042  *
00043  * Copyright (c) 1996 Carnegie Mellon University.
00044  * ALL RIGHTS RESERVED.
00045  * **********************************************
00046  * 
00047  * HISTORY
00048  * $Log$
00049  * Revision 1.4  2005/06/21  20:40:46  arthchan2003
00050  * 1, Fixed doxygen documentation, 2, Add the $ keyword.
00051  * 
00052  * Revision 1.3  2005/03/30 01:22:46  archan
00053  * Fixed mistakes in last updates. Add
00054  *
00055  * 
00056  * 02-Jul-1997  M K Ravishankar (rkm@cs.cmu.edu) at Carnegie Mellon University
00057  *              Bugfix: Added byteswapping in bio_verify_chksum().
00058  * 
00059  * 18-Dec-1996  M K Ravishankar (rkm@cs.cmu.edu) at Carnegie Mellon University
00060  *              Created.
00061  */
00062 
00063 #include <stdio.h>
00064 #include <string.h>
00065 #include <assert.h>
00066 
00067 #ifdef _MSC_VER
00068 #pragma warning (disable: 4996)
00069 #endif
00070 
00071 #include "bio.h"
00072 #include "err.h"
00073 #include "ckd_alloc.h"
00074 
00075 
00076 #define BIO_HDRARG_MAX  32
00077 #define END_COMMENT     "*end_comment*\n"
00078 
00079 
00080 static void
00081 bcomment_read(FILE * fp)
00082 {
00083     __BIGSTACKVARIABLE__ char iline[16384];
00084 
00085     while (fgets(iline, sizeof(iline), fp) != NULL) {
00086         if (strcmp(iline, END_COMMENT) == 0)
00087             return;
00088     }
00089     E_FATAL("Missing %s marker\n", END_COMMENT);
00090 }
00091 
00092 
00093 static int32
00094 swap_check(FILE * fp)
00095 {
00096     uint32 magic;
00097 
00098     if (fread(&magic, sizeof(uint32), 1, fp) != 1) {
00099         E_ERROR("Cannot read BYTEORDER MAGIC NO.\n");
00100         return -1;
00101     }
00102 
00103     if (magic != BYTE_ORDER_MAGIC) {
00104         /* either need to swap or got bogus magic number */
00105         SWAP_INT32(&magic);
00106 
00107         if (magic == BYTE_ORDER_MAGIC)
00108             return 1;
00109 
00110         SWAP_INT32(&magic);
00111         E_ERROR("Bad BYTEORDER MAGIC NO: %08x, expecting %08x\n",
00112                 magic, BYTE_ORDER_MAGIC);
00113         return -1;
00114     }
00115 
00116     return 0;
00117 }
00118 
00119 
00120 void
00121 bio_hdrarg_free(char **argname, char **argval)
00122 {
00123     int32 i;
00124 
00125     for (i = 0; argname[i]; i++) {
00126         ckd_free(argname[i]);
00127         ckd_free(argval[i]);
00128     }
00129     ckd_free(argname);
00130     ckd_free(argval);
00131 }
00132 
00133 
00134 int32
00135 bio_writehdr_version(FILE * fp, char *version)
00136 {
00137     uint32 b;
00138 
00139     fprintf(fp, "s3\n");
00140     fprintf(fp, "version %s\n", version);
00141     fprintf(fp, "endhdr\n");
00142     fflush(fp);
00143 
00144     b = (uint32) BYTE_ORDER_MAGIC;
00145     fwrite(&b, sizeof(uint32), 1, fp);
00146     fflush(fp);
00147 
00148     return 0;
00149 }
00150 
00151 
00152 int32
00153 bio_readhdr(FILE * fp, char ***argname, char ***argval, int32 * swap)
00154 {
00155     __BIGSTACKVARIABLE__ char line[16384], word[4096];
00156     int32 i, l;
00157     int32 lineno;
00158 
00159     *argname = (char **) ckd_calloc(BIO_HDRARG_MAX + 1, sizeof(char *));
00160     *argval = (char **) ckd_calloc(BIO_HDRARG_MAX, sizeof(char *));
00161 
00162     lineno = 0;
00163     if (fgets(line, sizeof(line), fp) == NULL)
00164         E_FATAL("Premature EOF, line %d\n", lineno);
00165     lineno++;
00166 
00167     if ((line[0] == 's') && (line[1] == '3') && (line[2] == '\n')) {
00168         /* New format (post Dec-1996, including checksums); read argument-value pairs */
00169         for (i = 0;;) {
00170             if (fgets(line, sizeof(line), fp) == NULL)
00171                 E_FATAL("Premature EOF, line %d\n", lineno);
00172             lineno++;
00173 
00174             if (sscanf(line, "%s%n", word, &l) != 1)
00175                 E_FATAL("Header format error, line %d\n", lineno);
00176             if (strcmp(word, "endhdr") == 0)
00177                 break;
00178             if (word[0] == '#') /* Skip comments */
00179                 continue;
00180 
00181             if (i >= BIO_HDRARG_MAX)
00182                 E_FATAL
00183                     ("Max arg-value limit(%d) exceeded; increase BIO_HDRARG_MAX\n",
00184                      BIO_HDRARG_MAX);
00185 
00186             (*argname)[i] = ckd_salloc(word);
00187             if (sscanf(line + l, "%s", word) != 1)      /* Multi-word values not allowed */
00188                 E_FATAL("Header format error, line %d\n", lineno);
00189             (*argval)[i] = ckd_salloc(word);
00190             i++;
00191         }
00192     }
00193     else {
00194         /* Old format (without checksums); the first entry must be the version# */
00195         if (sscanf(line, "%s", word) != 1)
00196             E_FATAL("Header format error, line %d\n", lineno);
00197 
00198         (*argname)[0] = ckd_salloc("version");
00199         (*argval)[0] = ckd_salloc(word);
00200         i = 1;
00201 
00202         bcomment_read(fp);
00203     }
00204     (*argname)[i] = NULL;
00205 
00206     if ((*swap = swap_check(fp)) < 0)
00207         E_FATAL("swap_check failed\n");
00208 
00209     return 0;
00210 }
00211 
00212 
00213 static uint32
00214 chksum_accum(void *buf, int32 el_sz, int32 n_el, uint32 sum)
00215 {
00216     int32 i;
00217     uint8 *i8;
00218     uint16 *i16;
00219     uint32 *i32;
00220 
00221     switch (el_sz) {
00222     case 1:
00223         i8 = (uint8 *) buf;
00224         for (i = 0; i < n_el; i++)
00225             sum = (sum << 5 | sum >> 27) + i8[i];
00226         break;
00227     case 2:
00228         i16 = (uint16 *) buf;
00229         for (i = 0; i < n_el; i++)
00230             sum = (sum << 10 | sum >> 22) + i16[i];
00231         break;
00232     case 4:
00233         i32 = (uint32 *) buf;
00234         for (i = 0; i < n_el; i++)
00235             sum = (sum << 20 | sum >> 12) + i32[i];
00236         break;
00237     default:
00238         E_FATAL("Unsupported elemsize for checksum: %d\n", el_sz);
00239         break;
00240     }
00241 
00242     return sum;
00243 }
00244 
00245 
00246 static void
00247 swap_buf(void *buf, int32 el_sz, int32 n_el)
00248 {
00249     int32 i;
00250     uint16 *buf16;
00251     uint32 *buf32;
00252 
00253     switch (el_sz) {
00254     case 1:
00255         break;
00256     case 2:
00257         buf16 = (uint16 *) buf;
00258         for (i = 0; i < n_el; i++)
00259             SWAP_INT16(buf16 + i);
00260         break;
00261     case 4:
00262         buf32 = (uint32 *) buf;
00263         for (i = 0; i < n_el; i++)
00264             SWAP_INT32(buf32 + i);
00265         break;
00266     default:
00267         E_FATAL("Unsupported elemsize for byteswapping: %d\n", el_sz);
00268         break;
00269     }
00270 }
00271 
00272 
00273 int32
00274 bio_fread(void *buf, int32 el_sz, int32 n_el, FILE * fp, int32 swap,
00275           uint32 * chksum)
00276 {
00277     if (fread(buf, el_sz, n_el, fp) != (size_t) n_el)
00278         return -1;
00279 
00280     if (swap)
00281         swap_buf(buf, el_sz, n_el);
00282 
00283     if (chksum)
00284         *chksum = chksum_accum(buf, el_sz, n_el, *chksum);
00285 
00286     return n_el;
00287 }
00288 
00289 int32
00290 bio_fwrite(void *buf, int32 el_sz, int32 n_el, FILE *fp,
00291            int32 swap, uint32 *chksum)
00292 {
00293     if (chksum)
00294         *chksum = chksum_accum(buf, el_sz, n_el, *chksum);
00295     if (swap) {
00296         void *nbuf;
00297         int rv;
00298 
00299         nbuf = ckd_calloc(n_el, el_sz);
00300         memcpy(nbuf, buf, n_el * el_sz);
00301         swap_buf(nbuf, el_sz, n_el);
00302         rv = fwrite(nbuf, el_sz, n_el, fp);
00303         ckd_free(nbuf);
00304         return rv;
00305     }
00306     else {
00307         return fwrite(buf, el_sz, n_el, fp);
00308     }
00309 }
00310 
00311 int32
00312 bio_fread_1d(void **buf, size_t el_sz, uint32 * n_el, FILE * fp,
00313              int32 sw, uint32 * ck)
00314 {
00315     /* Read 1-d array size */
00316     if (bio_fread(n_el, sizeof(int32), 1, fp, sw, ck) != 1)
00317         E_FATAL("fread(arraysize) failed\n");
00318     if (*n_el <= 0)
00319         E_FATAL("Bad arraysize: %d\n", *n_el);
00320 
00321     /* Allocate memory for array data */
00322     *buf = (void *) ckd_calloc(*n_el, el_sz);
00323 
00324     /* Read array data */
00325     if (bio_fread(*buf, el_sz, *n_el, fp, sw, ck) != *n_el)
00326         E_FATAL("fread(arraydata) failed\n");
00327 
00328     return *n_el;
00329 }
00330 
00331 int32
00332 bio_fread_2d(void ***arr,
00333              size_t e_sz,
00334              uint32 *d1,
00335              uint32 *d2,
00336              FILE *fp,
00337              uint32 swap,
00338              uint32 *chksum)
00339 {
00340     uint32 l_d1, l_d2;
00341     uint32 n;
00342     size_t ret;
00343     void *raw;
00344     
00345     ret = bio_fread(&l_d1, sizeof(uint32), 1, fp, swap, chksum);
00346     if (ret != 1) {
00347         if (ret == 0) {
00348             E_ERROR_SYSTEM("Unable to read complete data");
00349         }
00350         else {
00351             E_ERROR_SYSTEM("OS error in bio_fread_2d");
00352         }
00353         return -1;
00354     }
00355     ret = bio_fread(&l_d2, sizeof(uint32), 1, fp, swap, chksum);
00356     if (ret != 1) {
00357         if (ret == 0) {
00358             E_ERROR_SYSTEM("Unable to read complete data");
00359         }
00360         else {
00361             E_ERROR_SYSTEM("OS error in bio_fread_2d");
00362         }
00363         return -1;
00364     }
00365     if (bio_fread_1d(&raw, e_sz, &n, fp, swap, chksum) != n)
00366         return -1;
00367 
00368     assert(n == l_d1*l_d2);
00369 
00370     *d1 = l_d1;
00371     *d2 = l_d2;
00372     *arr = ckd_alloc_2d_ptr(l_d1, l_d2, raw, e_sz);
00373 
00374     return n;
00375 }
00376 
00377 int32
00378 bio_fread_3d(void ****arr,
00379              size_t e_sz,
00380              uint32 *d1,
00381              uint32 *d2,
00382              uint32 *d3,
00383              FILE *fp,
00384              uint32 swap,
00385              uint32 *chksum)
00386 {
00387     uint32 l_d1;
00388     uint32 l_d2;
00389     uint32 l_d3;
00390     uint32 n;
00391     void *raw;
00392     size_t ret;
00393 
00394     ret = bio_fread(&l_d1, sizeof(uint32), 1, fp, swap, chksum);
00395     if (ret != 1) {
00396         if (ret == 0) {
00397             E_ERROR_SYSTEM("Unable to read complete data");
00398         }
00399         else {
00400             E_ERROR_SYSTEM("OS error in bio_fread_3d");
00401         }
00402         return -1;
00403     }
00404     ret = bio_fread(&l_d2, sizeof(uint32), 1, fp, swap, chksum);
00405     if (ret != 1) {
00406         if (ret == 0) {
00407             E_ERROR_SYSTEM("Unable to read complete data");
00408         }
00409         else {
00410             E_ERROR_SYSTEM("OS error in bio_fread_3d");
00411         }
00412         return -1;
00413     }
00414     ret = bio_fread(&l_d3, sizeof(uint32), 1, fp, swap, chksum);
00415     if (ret != 1) {
00416         if (ret == 0) {
00417             E_ERROR_SYSTEM("Unable to read complete data");
00418         }
00419         else {
00420             E_ERROR_SYSTEM("OS error in bio_fread_3d");
00421         }
00422         return -1;
00423     }
00424 
00425     if (bio_fread_1d(&raw, e_sz, &n, fp, swap, chksum) != n) {
00426         return -1;
00427     }
00428 
00429     assert(n == l_d1 * l_d2 * l_d3);
00430 
00431     *arr = ckd_alloc_3d_ptr(l_d1, l_d2, l_d3, raw, e_sz);
00432     *d1 = l_d1;
00433     *d2 = l_d2;
00434     *d3 = l_d3;
00435     
00436     return n;
00437 }
00438 
00439 void
00440 bio_verify_chksum(FILE * fp, int32 byteswap, uint32 chksum)
00441 {
00442     uint32 file_chksum;
00443 
00444     if (fread(&file_chksum, sizeof(uint32), 1, fp) != 1)
00445         E_FATAL("fread(chksum) failed\n");
00446     if (byteswap)
00447         SWAP_INT32(&file_chksum);
00448     if (file_chksum != chksum)
00449         E_FATAL
00450             ("Checksum error; file-checksum %08x, computed %08x\n",
00451              file_chksum, chksum);
00452 }

Generated on Thu Jan 6 2011 for SphinxBase by  doxygen 1.7.1