Main Page Class Hierarchy Compound List File List Compound Members File Members

# rw_mag.c

Go to the documentation of this file.

    00001 /*
    00002  *   THIS FILE IS UNDER RCS - DO NOT MODIFY UNLESS YOU HAVE
    00003  *   CHECKED IT OUT USING THE COMMAND CHECKOUT.
    00004  *
    00005  *    $Id: rw__mag_8c-source.html 2161 2006-05-19 16:55:03Z paulf $
    00006  *
    00007  *    Revision history:
    00008  *     $Log$
    00008  *     Revision 1.1  2006/05/19 16:55:02  paulf
    00008  *     first inclusion
    00008  *
    00009  *     Revision 1.11  2002/06/28 21:03:57  lucky
    00010  *     Fixed reading of mag phases -- it would not properly read float
    00011  *     values for amplitude and period
    00012  *
    00013  *     Revision 1.10  2001/08/07 16:54:17  lucky
    00014  *     Pre v6.0 checkin
    00015  *
    00016  *     Revision 1.9  2001/06/07 20:51:49  lucky
    00017  *     Modified wr_mag so that it checks for NULL strings. Before, if qid was null,
    00018  *     wr_mag would produce an invalid TYPE_MAGNITUDE message which could not
    00019  *     be parsed by rd_mag. This is not good, given that the qid is not known
    00020  *     in the review system.
    00021  *
    00022  *     Revision 1.8  2001/06/07 19:48:28  lucky
    00023  *     rd_chan_mag_lucky renamed to rd_chan_mag. The old rd_chan_mag is still
    00024  *     available as rd_chan_mag_Pete.
    00025  *
    00026  *     Revision 1.7  2001/05/31 21:09:02  lucky
    00027  *     Addedd rd_chan_mag_lucky; I don't think that rd_chan_mag in its original form
    00028  *     works. There are numerical comparisons of pointers, and other visible problems.
    00029  *
    00030  *     Revision 1.6  2001/05/26 21:04:59  lombard
    00031  *     Changed ML_INFO struct to MAG_CHAN_INFO struct to make it more
    00032  *     generic; now this struct should work with most mag types.
    00033  *     Fixed a number of obvious bugs and cleaned up the code.
    00034  *     But the parsers still have not been tested and this may not work.
    00035  *
    00036  *     Revision 1.5  2001/05/02 20:58:45  alex
    00037  *     *** empty log message ***
    00038  *
    00039  *     Revision 1.4  2001/05/01 22:38:48  davidk
    00040  *     moved the MagNames table out of the header file and into rw_mag.c
    00041  *
    00042  *     Revision 1.3  2001/05/01 20:26:02  davidk
    00043  *     Modified several new functions added by Alex, so that they compile and do not impede the
    00044  *     release.  The new functions have been added, but have not properly been tested and debugged,
    00045  *     at all.
    00046  *
    00047  *     Revision 1.2  2001/04/29 00:15:29  alex
    00048  *     Alex: changes for mag type int and string, and added alternate parsing routines.
    00049  *
    00050  *     Revision 1.1  2001/03/31 00:44:58  lombard
    00051  *     Initial revision
    00052  *
    00053  *
    00054  *
    00055  */
    00056
    00057 /* rw_mag.c
    00058  *
    00059  * Contains functions in that convert from a
    00060  * TYPE_MAGNITUDE message to a structure and visa versa.
    00061  *
    00062  * written by Pete Lombard   February, 2001
    00063  */
    00064
    00065 #include <stdio.h>
    00066 #include <string.h>
    00067 #include <earthworm.h>
    00068 #include <rw_mag.h>
    00069
    00070 /* Internal Function Prototypes */
    00071 static int strappend( char *s1, int s1max, char *s2 );
    00072 static int tokenlength( char *begtok, char c );
    00073
    00074 /********************************************************************
    00075  * rd_mag()                                                         *
    00076  * Reads an ascii TYPE_MAGNITUDE message and fills in a MAG_INFO    *
    00077  * structure which must be allocated by the caller                  *
    00078  * If, in addition, the caller allocates space for auxiliary        *
    00079  * structures at pMag->pMagAux (number of bytes in pMag->size_aux), *
    00080  * then rd_mag will call the appropriate function to decode the     *
    00081  * remainder of the message into appropriate structures.            *
    00082  * Currently supported magnitude types are: Ml                      *
    00083  * Returns 0 on success                                             *
    00084  *        -1 on parsing errors                                      *
    00085  *        -2 on insufficient space in pMagAux                       *
    00086  ********************************************************************/
    00087 int rd_mag( char *msg, int msgLen, MAG_INFO *pMag)
    00088 {
    00089   size_t size_aux;
    00090   char *pMagAux;
    00091
    00092   size_aux = pMag->size_aux;
    00093   pMagAux = (char *)pMag->pMagAux;
    00094   memset(pMag, 0, sizeof(MAG_INFO));
    00095
    00096   switch ( sscanf( msg
    00097                  , "%s MAG %d %s %lf %s %d %d %lf %lf %lf %d %s %d %d"
    00098                  ,  pMag->qid
    00099                  , &pMag->imagtype
    00100                  ,  pMag->szmagtype
    00101                  , &pMag->mag
    00102                  ,  pMag->algorithm
    00103                  , &pMag->nstations
    00104                  , &pMag->nchannels
    00105                  , &pMag->error
    00106                  , &pMag->quality
    00107                  , &pMag->mindist
    00108                  , &pMag->azimuth
    00109                  ,  pMag->qauthor
    00110                  , &pMag->origin_version
    00111                  , &pMag->qdds_version
    00112          )       )
    00113   {
    00114     case 12:  /* old-style, no origin version, qdds version numbers */
    00115          pMag->origin_version = 0;
    00116          pMag->qdds_version = 0;
    00117          break;
    00118     case 13:  /* new-style, with origin version, no qdds version */
    00119          pMag->qdds_version = 0;
    00120          break;
    00121     case 14:  /* new-style, with both number */
    00122          break;
    00123     default:
    00124          return( -1 );
    00125   }
    00126
    00127   if (pMagAux && size_aux > 0)
    00128   {
    00129     pMag->size_aux = size_aux;
    00130     pMag->pMagAux = pMagAux;
    00131
    00132     /* Read the rest of a Mag message */
    00133     if (pMag->pMagAux != NULL)
    00134         {
    00135          return( rd_chan_mag(msg, msgLen, (MAG_CHAN_INFO *)pMag->pMagAux,
    00136                           pMag->size_aux) );
    00137         }
    00138   }
    00139
    00140   return( 0 );
    00141 }
    00142
    00143 /*****************************************************************
    00144  * rd_chan_mag()                                                 *
    00145  * Reads an ascii TYPE_MAGNITUDE Ml message and fills in         *
    00146  * MAG_CHAN_INFO structures.                                     *
    00147  * This function can be called by rd_mag if sufficient space is  *
    00148  * allocated by its caller. Or it may be called after rd_mag     *
    00149  * when the caller has allocated space for `nchannels' of        *
    00150  * MAG_CHAN_INFO structures.                                     *
    00151  * Returns 0 on success                                          *
    00152  *        -1 on parsing errors                                   *
    00153  *        -2 on insufficient space in pMagAux                    *
    00154  *****************************************************************/
    00155 int rd_chan_mag ( char *msg, int msglen, MAG_CHAN_INFO *pMci, int size_ml)
    00156 {
    00157   char     *line;
    00158   char     *begtok;
    00159   char     *tmpMsg;     /* local copy of msg */
    00160   int       len;       /* length (bytes) of the next token */
    00161   int       nchan;     /* number of channels read from msg so far */
    00162   int       nML;       /* number of MAG_CHAN_INFO structures we can use */
    00163   int       rc;
    00164   int           index;
    00165
    00166   memset(pMci, 0, size_ml);
    00167   nML = size_ml / sizeof(MAG_CHAN_INFO);
    00168
    00169   tmpMsg = (char *) malloc (msglen);
    00170   strcpy (tmpMsg, msg);
    00171
    00172   nchan = 0;
    00173
    00174   /* Skip the first line */
    00175   len = tokenlength (tmpMsg, '\n');
    00176
    00177   index = len + 1;
    00178
    00179   /* Read next line from the message into working buffer */
    00180   while(index < (msglen-1))
    00181   {
    00182         /* Process next line */
    00183         line = tmpMsg + index;
    00184     len = tokenlength(line, '\n' );
    00185         line[len] = '\0';
    00186     index = index + len + 1;
    00187
    00188     begtok = line;
    00189     while( begtok[0] == ' ' && begtok[0] != '\0') begtok++;    /* go to 1st non-blank char */
    00190     if( begtok[0] == '\0' ) return( -1 );
    00191     len = tokenlength( begtok, '.' );
    00192     if( len >= TRACE_STA_LEN ) return( -1 );
    00193     strncpy( pMci[nchan].sta, begtok, len );
    00194         pMci[nchan].sta[len] = '\0';
    00195     begtok += len + 1;
    00196
    00197     len = tokenlength( begtok, '.' );
    00198     if( len >= TRACE_CHAN_LEN ) return( -1 );
    00199     strncpy( pMci[nchan].comp, begtok, len );
    00200         pMci[nchan].comp[len] = '\0';
    00201     begtok += len + 1;
    00202
    00203     len = tokenlength( begtok, ' ' );
    00204     if( len >= TRACE_NET_LEN ) return( -1 );
    00205     strncpy( pMci[nchan].net, begtok, len );
    00206         pMci[nchan].net[len] = '\0';
    00207     begtok += len + 1;
    00208
    00209     while( begtok[0] == ' ' && begtok[0] != '\0' ) begtok++;    /* go to next non-blank char */
    00210     if ( (rc = sscanf(begtok, "%lf %lf %lf %E %lf %f %E %lf %f",
    00211                       &(pMci[nchan].mag), &(pMci[nchan].dist), &(pMci[nchan].corr),
    00212                       &(pMci[nchan].Amp1), &(pMci[nchan].Time1), &(pMci[nchan].Period1),
    00213                       &(pMci[nchan].Amp2), &(pMci[nchan].Time2),
    00214                       &(pMci[nchan].Period2))) != 9)
    00215     {
    00216       if (rc == 6)
    00217       {
    00218         pMci[nchan].Amp2 = pMci[nchan].Time2 = pMci[nchan].Period2 = -1.0;
    00219         continue;
    00220       }
    00221       return( -1 );
    00222     }
    00223
    00224     nchan = nchan + 1;
    00225
    00226   }
    00227
    00228   return 0;
    00229 }
    00230
    00231
    00232
    00233 /*******************************************************************
    00234  * wr_mag()                                                        *
    00235  * Reads a MAG_INFO structure and writes an ascii TYPE_MAGNITUDE   *
    00236  * message (null terminated)                                       *
    00237  * Returns 0 on success, -1 on failure (potential buffer overflow) *
    00238  *******************************************************************/
    00239 int wr_mag( MAG_INFO *pMag, char *buf, int buflen )
    00240 {
    00241   char     tmp[256]; /* working buffer */
    00242   char     qid[256];
    00243   char     szmagtype[256];
    00244   char     algorithm[256];
    00245   char     qauthor[256];
    00246
    00247   memset( buf, 0, (size_t)buflen );    /* zero output buffer */
    00248
    00249   /*
    00250    * We should check for null strings, if for nothing else than to
    00251    * avoid mis-formatted message trickling down the system. LV 6/2001
    00252    */
    00253         if (strlen (pMag->qid) == 0)
    00254                 strcpy (qid, "UNKNOWN");
    00255         else
    00256                 strcpy (qid, pMag->qid);
    00257
    00258         if (strlen (pMag->szmagtype) == 0)
    00259                 strcpy (szmagtype, "UNKNOWN");
    00260         else
    00261                 strcpy (szmagtype, pMag->szmagtype);
    00262
    00263         if (strlen (pMag->algorithm) == 0)
    00264                 strcpy (algorithm, "UNKNOWN");
    00265         else
    00266                 strcpy (algorithm, pMag->algorithm);
    00267
    00268         if (strlen (pMag->qauthor) == 0)
    00269                 strcpy (qauthor, "UNKNOWN");
    00270         else
    00271                 strcpy (qauthor, pMag->qauthor);
    00272
    00273   sprintf(tmp, "%s MAG %d %s %0.2f %s %d %d %0.2f %0.2f %0.2f %d %s %d %d\n",
    00274           qid, pMag->imagtype, szmagtype, pMag->mag, algorithm,
    00275           pMag->nstations, pMag->nchannels, pMag->error, pMag->quality,
    00276           pMag->mindist, pMag->azimuth, qauthor, pMag->origin_version
    00277           , pMag->qdds_version
    00278           );
    00279
    00280   if ( strappend( buf, buflen, tmp ) ) return( -1 );
    00281
    00282   if (pMag->pMagAux != NULL)
    00283   {
    00284       return( wr_chan_mag( (MAG_CHAN_INFO *)pMag->pMagAux, pMag->nchannels,
    00285                            buf, buflen) );
    00286   }
    00287
    00288   return( 0 );
    00289 }
    00290
    00291 /*******************************************************************
    00292  * wr_chan_mag()                                                   *
    00293  * Reads MAG_CHAN_INFO structures and appends to an ascii          *
    00294  * TYPE_MAGNITUDE message (null terminated)                        *
    00295  * Normally this would be called by wr_mag().                      *
    00296  * Returns 0 on success, -1 on failure (potential buffer overflow) *
    00297  *******************************************************************/
    00298 int wr_chan_mag( MAG_CHAN_INFO *pMci, int nchannels, char *buf, int buflen )
    00299 {
    00300   int i;
    00301   char line[256];
    00302
    00303   for (i = 0; i < nchannels; i++)
    00304   {
    00305     sprintf(line,
    00306             "%s.%s.%s %.2f %.2f %.2f %9.2E %9.2f %9.2f %9.2E %9.2f %9.2f\n",
    00307             /*s  c  n mag  dist corr Amp1 Time1 Period1 Amp2 Time2 Period2 */
    00308             pMci[i].sta, pMci[i].comp, pMci[i].net,
    00309                         pMci[i].mag, pMci[i].dist, pMci[i].corr,
    00310             pMci[i].Amp1,
    00311             ( (pMci[i].Time1 < 0.0) ? -1.0 : pMci[i].Time1),
    00312             ( (pMci[i].Period1 < 0.0) ? -1.0 : pMci[i].Period1),
    00313             pMci[i].Amp2,
    00314             ( (pMci[i].Time2 < 0.0) ? -1.0 : pMci[i].Time2),
    00315             ( (pMci[i].Period2 < 0.0) ? -1.0 : pMci[i].Period2));
    00316
    00317       if ( strappend(buf, buflen, line))
    00318         return( -1 );
    00319   }
    00320   return( 0 );
    00321 }
    00322
    00323
    00324 /********************************************************************
    00325  * strappend() append second null-terminated character string to    *
    00326  * the first as long as there's enough room in the target buffer    *
    00327  * for both strings an the null-byte                                *
    00328  ********************************************************************/
    00329 static int strappend( char *s1, int s1max, char *s2 )
    00330 {
    00331   if( (int)strlen(s1)+(int)strlen(s2)+1 > s1max ) return( -1 );
    00332   strcat( s1, s2 );
    00333   return( 0 );
    00334 }
    00335
    00336 /********************************************************************
    00337  * tokenlength() given a null-terminated character string and a     *
    00338  * character that delimits the end of a token, tokenlength returns  *
    00339  * the length (in bytes) of the next token. If the character wasn't *
    00340  * found, tokenlength returns the length of the string.             *
    00341  ********************************************************************/
    00342 static int tokenlength( char *begtok, char c )
    00343 {
    00344   char    *endtok;   /* points to the end of this token */
    00345
    00346   endtok = strchr( begtok, c );
    00347   if( endtok == NULL ) return( (int)strlen(begtok) );
    00348   return( (int)(endtok-begtok) );
    00349 }