📄 msrutils.c
字号:
/*************************************************************************** * msrutils.c: * * Generic routines to operate on Mini-SEED records. * * Written by Chad Trabant * ORFEUS/EC-Project MEREDIAN * IRIS Data Management Center * * modified: 2008.161 ***************************************************************************/#include <stdio.h>#include <stdlib.h>#include <string.h>#include <time.h>#include "libmseed.h"/* A simple bitwise AND test to return 0 or 1 */#define bit(x,y) (x&y)?1:0/*************************************************************************** * msr_init: * * Initialize and return an MSRecord struct, allocating memory if * needed. If memory for the fsdh and datasamples fields has been * allocated the pointers will be retained for reuse. If a blockette * chain is present all associated memory will be released. * * Returns a pointer to a MSRecord struct on success or NULL on error. ***************************************************************************/MSRecord *msr_init ( MSRecord *msr ){ void *fsdh = 0; void *datasamples = 0; if ( ! msr ) { msr = (MSRecord *) malloc (sizeof(MSRecord)); } else { fsdh = msr->fsdh; datasamples = msr->datasamples; if ( msr->blkts ) msr_free_blktchain (msr); if ( msr->ststate ) free (msr->ststate); } if ( msr == NULL ) { ms_log (2, "msr_init(): Cannot allocate memory\n"); return NULL; } memset (msr, 0, sizeof (MSRecord)); msr->fsdh = fsdh; msr->datasamples = datasamples; msr->reclen = -1; msr->samplecnt = -1; msr->byteorder = -1; msr->encoding = -1; return msr;} /* End of msr_init() *//*************************************************************************** * msr_free: * * Free all memory associated with a MSRecord struct. ***************************************************************************/voidmsr_free ( MSRecord **ppmsr ){ if ( ppmsr != NULL && *ppmsr != 0 ) { /* Free fixed section header if populated */ if ( (*ppmsr)->fsdh ) free ((*ppmsr)->fsdh); /* Free blockette chain if populated */ if ( (*ppmsr)->blkts ) msr_free_blktchain (*ppmsr); /* Free datasamples if present */ if ( (*ppmsr)->datasamples ) free ((*ppmsr)->datasamples); /* Free stream processing state if present */ if ( (*ppmsr)->ststate ) free ((*ppmsr)->ststate); free (*ppmsr); *ppmsr = NULL; }} /* End of msr_free() *//*************************************************************************** * msr_free_blktchain: * * Free all memory associated with a blockette chain in a MSRecord * struct and set MSRecord->blkts to NULL. Also reset the shortcut * blockette pointers. ***************************************************************************/voidmsr_free_blktchain ( MSRecord *msr ){ if ( msr ) { if ( msr->blkts ) { BlktLink *bc = msr->blkts; BlktLink *nb = NULL; while ( bc ) { nb = bc->next; if ( bc->blktdata ) free (bc->blktdata); free (bc); bc = nb; } msr->blkts = 0; } msr->Blkt100 = 0; msr->Blkt1000 = 0; msr->Blkt1001 = 0; }} /* End of msr_free_blktchain() *//*************************************************************************** * msr_addblockette: * * Add a blockette to the blockette chain of an MSRecord. 'blktdata' * should be the body of the blockette type 'blkttype' of 'length' * bytes without the blockette header (type and next offsets). The * 'chainpos' value controls which end of the chain the blockette is * added to. If 'chainpos' is 0 the blockette will be added to the * end of the chain (last blockette), other wise it will be added to * the beginning of the chain (first blockette). * * Returns a pointer to the BlktLink added to the chain on success and * NULL on error. ***************************************************************************/BlktLink *msr_addblockette (MSRecord *msr, char *blktdata, int length, int blkttype, int chainpos){ BlktLink *blkt; if ( ! msr ) return NULL; blkt = msr->blkts; if ( blkt ) { if ( chainpos != 0 ) { blkt = (BlktLink *) malloc (sizeof(BlktLink)); blkt->next = msr->blkts; msr->blkts = blkt; } else { /* Find the last blockette */ while ( blkt && blkt->next ) { blkt = blkt->next; } blkt->next = (BlktLink *) malloc (sizeof(BlktLink)); blkt = blkt->next; blkt->next = 0; } if ( blkt == NULL ) { ms_log (2, "msr_addblockette(): Cannot allocate memory\n"); return NULL; } } else { msr->blkts = (BlktLink *) malloc (sizeof(BlktLink)); if ( msr->blkts == NULL ) { ms_log (2, "msr_addblockette(): Cannot allocate memory\n"); return NULL; } blkt = msr->blkts; blkt->next = 0; } blkt->blkt_type = blkttype; blkt->next_blkt = 0; blkt->blktdata = (char *) malloc (length); if ( blkt->blktdata == NULL ) { ms_log (2, "msr_addblockette(): Cannot allocate memory\n"); return NULL; } memcpy (blkt->blktdata, blktdata, length); blkt->blktdatalen = length; /* Setup the shortcut pointer for common blockettes */ switch ( blkttype ) { case 100: msr->Blkt100 = blkt->blktdata; break; case 1000: msr->Blkt1000 = blkt->blktdata; break; case 1001: msr->Blkt1001 = blkt->blktdata; break; } return blkt;} /* End of msr_addblockette() *//*************************************************************************** * msr_normalize_header: * * Normalize header values between the MSRecord struct and the * associated fixed-section of the header and blockettes. Essentially * this updates the SEED structured data in the MSRecord.fsdh struct * and MSRecord.blkts chain with values stored at the MSRecord level. * * Returns the header length in bytes on success or -1 on error. ***************************************************************************/intmsr_normalize_header ( MSRecord *msr, flag verbose ){ struct blkt_link_s *cur_blkt; char seqnum[7]; int offset = 0; int blktcnt = 0; int reclenexp = 0; int reclenfind; if ( ! msr ) return -1; /* Update values in fixed section of data header */ if ( msr->fsdh ) { if ( verbose > 2 ) ms_log (1, "Normalizing fixed section of data header\n"); /* Roll-over sequence number if necessary */ if ( msr->sequence_number > 999999 ) msr->sequence_number = 1; /* Update values in the MSRecord.fsdh struct */ snprintf (seqnum, 7, "%06d", msr->sequence_number); memcpy (msr->fsdh->sequence_number, seqnum, 6); msr->fsdh->dataquality = msr->dataquality; msr->fsdh->reserved = ' '; ms_strncpopen (msr->fsdh->network, msr->network, 2); ms_strncpopen (msr->fsdh->station, msr->station, 5); ms_strncpopen (msr->fsdh->location, msr->location, 2); ms_strncpopen (msr->fsdh->channel, msr->channel, 3); ms_hptime2btime (msr->starttime, &(msr->fsdh->start_time)); ms_genfactmult (msr->samprate, &(msr->fsdh->samprate_fact), &(msr->fsdh->samprate_mult)); offset += 48; if ( msr->blkts ) msr->fsdh->blockette_offset = offset; else msr->fsdh->blockette_offset = 0; } /* Traverse blockette chain and performs necessary updates*/ cur_blkt = msr->blkts; if ( cur_blkt && verbose > 2 ) ms_log (1, "Normalizing blockette chain\n"); while ( cur_blkt ) { offset += 4; if ( cur_blkt->blkt_type == 100 && msr->Blkt100 ) { msr->Blkt100->samprate = msr->samprate; offset += sizeof (struct blkt_100_s); } else if ( cur_blkt->blkt_type == 1000 && msr->Blkt1000 ) { msr->Blkt1000->byteorder = msr->byteorder; msr->Blkt1000->encoding = msr->encoding; /* Calculate the record length as an exponent of 2 */ for (reclenfind=1, reclenexp=1; reclenfind <= MAXRECLEN; reclenexp++) { reclenfind *= 2; if ( reclenfind == msr->reclen ) break; } if ( reclenfind != msr->reclen ) { ms_log (2, "msr_normalize_header(): Record length %d is not a power of 2\n", msr->reclen); return -1; } msr->Blkt1000->reclen = reclenexp; offset += sizeof (struct blkt_1000_s); } else if ( cur_blkt->blkt_type == 1001 ) { hptime_t sec, usec; /* Insert microseconds offset */ sec = msr->starttime / (HPTMODULUS / 10000); usec = msr->starttime - (sec * (HPTMODULUS / 10000)); usec /= (HPTMODULUS / 1000000); msr->Blkt1001->usec = (int8_t) usec; offset += sizeof (struct blkt_1001_s); } blktcnt++; cur_blkt = cur_blkt->next; } if ( msr->fsdh ) msr->fsdh->numblockettes = blktcnt; return offset;} /* End of msr_normalize_header() *//*************************************************************************** * msr_duplicate: * * Duplicate an MSRecord struct * including the fixed-section data * header and blockette chain. If * the datadup flag is true and the * source MSRecord has associated * data samples copy them as well. * * Returns a pointer to a new MSRecord on success and NULL on error. ***************************************************************************/MSRecord *msr_duplicate (MSRecord *msr, flag datadup){ MSRecord *dupmsr = 0; int samplesize = 0; if ( ! msr ) return NULL; /* Allocate target MSRecord structure */ if ( (dupmsr = msr_init (NULL)) == NULL ) return NULL; /* Copy MSRecord structure */ memcpy (dupmsr, msr, sizeof(MSRecord)); /* Copy fixed-section data header structure */ if ( msr->fsdh )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -