⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pack.c

📁 C编写的格式转换程序
💻 C
📖 第 1 页 / 共 2 页
字号:
/*************************************************************************** * pack.c: * * Generic routines to pack Mini-SEED records using an MSrecord as a * header template and data source. * * Written by Chad Trabant, *   IRIS Data Management Center * * modified: 2008.220 ***************************************************************************/#include <stdio.h>#include <stdlib.h>#include <string.h>#include <time.h>#include "libmseed.h"#include "packdata.h"/* Function(s) internal to this file */static int msr_pack_header_raw (MSRecord *msr, char *rawrec, int maxheaderlen,				flag swapflag, flag normalize, flag verbose);static int msr_update_header (MSRecord * msr, char *rawrec, flag swapflag,			      flag verbose);static int msr_pack_data (void *dest, void *src, int maxsamples, int maxdatabytes,			  int *packsamples, int32_t *lastintsample, flag comphistory,			  char sampletype, flag encoding, flag swapflag,			  flag verbose);/* Header and data byte order flags controlled by environment variables *//* -2 = not checked, -1 = checked but not set, or 0 = LE and 1 = BE */flag packheaderbyteorder = -2;flag packdatabyteorder = -2;/* A pointer to the srcname of the record being packed */char *PACK_SRCNAME = NULL;/*************************************************************************** * msr_pack: * * Pack data into SEED data records.  Using the record header values * in the MSRecord as a template the common header fields are packed * into the record header, blockettes in the blockettes chain are * packed and data samples are packed in the encoding format indicated * by the MSRecord->encoding field.  A Blockette 1000 will be added if * one is not present. * * The MSRecord->datasamples array and MSRecord->numsamples value will * not be changed by this routine.  It is the responsibility of the * calling routine to adjust the data buffer if desired. * * As each record is filled and finished they are passed to * record_handler which expects 1) a char * to the record, 2) the * length of the record and 3) a pointer supplied by the original * caller containing optional private data (handlerdata).  It is the * responsibility of record_handler to process the record, the memory * will be re-used or freed when record_handler returns. * * If the flush flag != 0 all of the data will be packed into data * records even though the last one will probably not be filled. * * Default values are: data record & quality indicator = 'D', record * length = 4096, encoding = 11 (Steim2) and byteorder = 1 (MSBF). * The defaults are triggered when the the msr->dataquality is 0 or * msr->reclen, msr->encoding and msr->byteorder are -1 respectively. * * Returns the number of records created on success and -1 on error. ***************************************************************************/intmsr_pack ( MSRecord * msr, void (*record_handler) (char *, int, void *),	   void *handlerdata, int *packedsamples, flag flush, flag verbose ){  uint16_t *HPnumsamples;  uint16_t *HPdataoffset;  char *rawrec;  char *envvariable;  char srcname[50];    flag headerswapflag = 0;  flag dataswapflag = 0;  flag packret;    int samplesize;  int headerlen;  int dataoffset;  int maxdatabytes;  int maxsamples;  int recordcnt = 0;  int totalpackedsamples;  int packsamples, packoffset;    if ( ! msr )    return -1;    if ( ! record_handler )    {      ms_log (2, "msr_pack(): record_handler() function pointer not set!\n");      return -1;    }  /* Allocate stream processing state space if needed */  if ( ! msr->ststate )    {      msr->ststate = (StreamState *) malloc (sizeof(StreamState));      if ( ! msr->ststate )        {          ms_log (2, "msr_pack(): Could not allocate memory for StreamState\n");          return -1;        }      memset (msr->ststate, 0, sizeof(StreamState));    }  /* Generate source name for MSRecord */  if ( msr_srcname (msr, srcname, 1) == NULL )    {      ms_log (2, "msr_unpack_data(): Cannot generate srcname\n");      return MS_GENERROR;    }    /* Set shared srcname pointer to source name */  PACK_SRCNAME = &srcname[0];    /* Read possible environmental variables that force byteorder */  if ( packheaderbyteorder == -2 )    {      if ( (envvariable = getenv("PACK_HEADER_BYTEORDER")) )	{	  if ( *envvariable != '0' && *envvariable != '1' )	    {	      ms_log (2, "Environment variable PACK_HEADER_BYTEORDER must be set to '0' or '1'\n");	      return -1;	    }	  else if ( *envvariable == '0' )	    {	      packheaderbyteorder = 0;	      if ( verbose > 2 )		ms_log (1, "PACK_HEADER_BYTEORDER=0, packing little-endian header\n");	    }	  else	    {	      packheaderbyteorder = 1;	      if ( verbose > 2 )		ms_log (1, "PACK_HEADER_BYTEORDER=1, packing big-endian header\n");	    }	}      else	{	  packheaderbyteorder = -1;	}    }  if ( packdatabyteorder == -2 )    {      if ( (envvariable = getenv("PACK_DATA_BYTEORDER")) )	{	  if ( *envvariable != '0' && *envvariable != '1' )	    {	      ms_log (2, "Environment variable PACK_DATA_BYTEORDER must be set to '0' or '1'\n");	      return -1;	    }	  else if ( *envvariable == '0' )	    {	      packdatabyteorder = 0;	      if ( verbose > 2 )		ms_log (1, "PACK_DATA_BYTEORDER=0, packing little-endian data samples\n");	    }	  else	    {	      packdatabyteorder = 1;	      if ( verbose > 2 )		ms_log (1, "PACK_DATA_BYTEORDER=1, packing big-endian data samples\n");	    }	}      else	{	  packdatabyteorder = -1;	}    }  /* Set default indicator, record length, byte order and encoding if needed */  if ( msr->dataquality == 0 ) msr->dataquality = 'D';  if ( msr->reclen == -1 ) msr->reclen = 4096;  if ( msr->byteorder == -1 )  msr->byteorder = 1;  if ( msr->encoding == -1 ) msr->encoding = DE_STEIM2;    /* Cleanup/reset sequence number */  if ( msr->sequence_number <= 0 || msr->sequence_number > 999999)    msr->sequence_number = 1;    if ( msr->reclen < MINRECLEN || msr->reclen > MAXRECLEN )    {      ms_log (2, "msr_pack(%s): Record length is out of range: %d\n",	      PACK_SRCNAME, msr->reclen);      return -1;    }    if ( msr->numsamples <= 0 )    {      ms_log (2, "msr_pack(%s): No samples to pack\n", PACK_SRCNAME);      return -1;    }    samplesize = ms_samplesize (msr->sampletype);    if ( ! samplesize )    {      ms_log (2, "msr_pack(%s): Unknown sample type '%c'\n",	      PACK_SRCNAME, msr->sampletype);      return -1;    }    /* Sanity check for msr/quality indicator */  if ( ! MS_ISDATAINDICATOR(msr->dataquality) )    {      ms_log (2, "msr_pack(%s): Record header & quality indicator unrecognized: '%c'\n",	      PACK_SRCNAME, msr->dataquality);      ms_log (2, "msr_pack(%s): Packing failed.\n", PACK_SRCNAME);      return -1;    }    /* Allocate space for data record */  rawrec = (char *) malloc (msr->reclen);    if ( rawrec == NULL )    {      ms_log (2, "msr_pack(%s): Cannot allocate memory\n", PACK_SRCNAME);      return -1;    }    /* Set header pointers to known offsets into FSDH */  HPnumsamples = (uint16_t *) (rawrec + 30);  HPdataoffset = (uint16_t *) (rawrec + 44);    /* Check to see if byte swapping is needed */  if ( msr->byteorder != ms_bigendianhost() )    headerswapflag = dataswapflag = 1;    /* Check if byte order is forced */  if ( packheaderbyteorder >= 0 )    {      headerswapflag = ( msr->byteorder != packheaderbyteorder ) ? 1 : 0;    }    if ( packdatabyteorder >= 0 )    {      dataswapflag = ( msr->byteorder != packdatabyteorder ) ? 1 : 0;    }    if ( verbose > 2 )    {      if ( headerswapflag && dataswapflag )	ms_log (1, "%s: Byte swapping needed for packing of header and data samples\n", PACK_SRCNAME);      else if ( headerswapflag )	ms_log (1, "%s: Byte swapping needed for packing of header\n", PACK_SRCNAME);      else if ( dataswapflag )	ms_log (1, "%s: Byte swapping needed for packing of data samples\n", PACK_SRCNAME);      else	ms_log (1, "%s: Byte swapping NOT needed for packing\n", PACK_SRCNAME);    }    /* Add a blank 1000 Blockette if one is not present, the blockette values     will be populated in msr_pack_header_raw()/msr_normalize_header() */  if ( ! msr->Blkt1000 )    {      struct blkt_1000_s blkt1000;      memset (&blkt1000, 0, sizeof (struct blkt_1000_s));            if ( verbose > 2 )	ms_log (1, "%s: Adding 1000 Blockette\n", PACK_SRCNAME);            if ( ! msr_addblockette (msr, (char *) &blkt1000, sizeof(struct blkt_1000_s), 1000, 0) )	{	  ms_log (2, "msr_pack(%s): Error adding 1000 Blockette\n", PACK_SRCNAME);	  return -1;	}    }    headerlen = msr_pack_header_raw (msr, rawrec, msr->reclen, headerswapflag, 1, verbose);    if ( headerlen == -1 )    {      ms_log (2, "msr_pack(%s): Error packing header\n", PACK_SRCNAME);      return -1;    }  /* Determine offset to encoded data */  if ( msr->encoding == DE_STEIM1 || msr->encoding == DE_STEIM2 )    {      dataoffset = 64;      while ( dataoffset < headerlen )	dataoffset += 64;            /* Zero memory between blockettes and data if any */      memset (rawrec + headerlen, 0, dataoffset - headerlen);    }  else    {      dataoffset = headerlen;    }    *HPdataoffset = (uint16_t) dataoffset;  if ( headerswapflag ) ms_gswap2 (HPdataoffset);    /* Determine the max data bytes and sample count */  maxdatabytes = msr->reclen - dataoffset;    if ( msr->encoding == DE_STEIM1 )    {      maxsamples = (int) (maxdatabytes/64) * STEIM1_FRAME_MAX_SAMPLES;    }  else if ( msr->encoding == DE_STEIM2 )    {      maxsamples = (int) (maxdatabytes/64) * STEIM2_FRAME_MAX_SAMPLES;    }  else    {      maxsamples = maxdatabytes / samplesize;    }    /* Pack samples into records */  *HPnumsamples = 0;  totalpackedsamples = 0;  if ( packedsamples ) *packedsamples = 0;  packoffset = 0;    while ( (msr->numsamples - totalpackedsamples) > maxsamples || flush )    {      packret = msr_pack_data (rawrec + dataoffset,			       (char *) msr->datasamples + packoffset,			       (msr->numsamples - totalpackedsamples), maxdatabytes,			       &packsamples, &msr->ststate->lastintsample, msr->ststate->comphistory,			       msr->sampletype, msr->encoding, dataswapflag, verbose);            if ( packret )	{	  ms_log (2, "msr_pack(%s): Error packing record\n", PACK_SRCNAME);	  return -1;	}            packoffset += packsamples * samplesize;            /* Update number of samples */      *HPnumsamples = (uint16_t) packsamples;      if ( headerswapflag ) ms_gswap2 (HPnumsamples);            if ( verbose > 0 )	ms_log (1, "%s: Packed %d samples\n", PACK_SRCNAME, packsamples);            /* Send record to handler */      record_handler (rawrec, msr->reclen, handlerdata);            totalpackedsamples += packsamples;      if ( packedsamples ) *packedsamples = totalpackedsamples;      msr->ststate->packedsamples += packsamples;            /* Update record header for next record */      msr->sequence_number = ( msr->sequence_number >= 999999 ) ? 1 : msr->sequence_number + 1;      if ( msr->samprate > 0 )        msr->starttime += (double) packsamples / msr->samprate * HPTMODULUS;      msr_update_header (msr, rawrec, headerswapflag, verbose);            recordcnt++;      msr->ststate->packedrecords++;      /* Set compression history flag for subsequent records (Steim encodings) */      if ( ! msr->ststate->comphistory )        msr->ststate->comphistory = 1;           if ( totalpackedsamples >= msr->numsamples )	break;    }    if ( verbose > 2 )    ms_log (1, "%s: Packed %d total samples\n", PACK_SRCNAME, totalpackedsamples);    free (rawrec);    return recordcnt;} /* End of msr_pack() *//*************************************************************************** * msr_pack_header: * * Pack data header/blockettes into the SEED record at * MSRecord->record.  Unlike msr_pack no default values are applied, * the header structures are expected to be self describing and no * Blockette 1000 will be added.  This routine is only useful for * re-packing a record header. * * Returns the header length in bytes on success and -1 on error. ***************************************************************************/intmsr_pack_header ( MSRecord *msr, flag normalize, flag verbose ){  char srcname[50];  char *envvariable;  flag headerswapflag = 0;  int headerlen;  int maxheaderlen;    if ( ! msr )    return -1;    /* Generate source name for MSRecord */  if ( msr_srcname (msr, srcname, 1) == NULL )    {      ms_log (2, "msr_unpack_data(): Cannot generate srcname\n");      return MS_GENERROR;    }    /* Set shared srcname pointer to source name */  PACK_SRCNAME = &srcname[0];  /* Read possible environmental variables that force byteorder */  if ( packheaderbyteorder == -2 )    {      if ( (envvariable = getenv("PACK_HEADER_BYTEORDER")) )	{	  if ( *envvariable != '0' && *envvariable != '1' )	    {	      ms_log (2, "Environment variable PACK_HEADER_BYTEORDER must be set to '0' or '1'\n");	      return -1;	    }	  else if ( *envvariable == '0' )	    {	      packheaderbyteorder = 0;	      if ( verbose > 2 )		ms_log (1, "PACK_HEADER_BYTEORDER=0, packing little-endian header\n");	    }	  else	    {	      packheaderbyteorder = 1;	      if ( verbose > 2 )		ms_log (1, "PACK_HEADER_BYTEORDER=1, packing big-endian header\n");	    }	}      else	{	  packheaderbyteorder = -1;	}    }  if ( msr->reclen < MINRECLEN || msr->reclen > MAXRECLEN )    {      ms_log (2, "msr_pack_header(%s): record length is out of range: %d\n",	      PACK_SRCNAME, msr->reclen);      return -1;    }    if ( msr->byteorder != 0 && msr->byteorder != 1 )    {      ms_log (2, "msr_pack_header(%s): byte order is not defined correctly: %d\n",	      PACK_SRCNAME, msr->byteorder);      return -1;    }      if ( msr->fsdh )    {      maxheaderlen = (msr->fsdh->data_offset > 0) ?	msr->fsdh->data_offset :	msr->reclen;    }  else    {      maxheaderlen = msr->reclen;    }      /* Check to see if byte swapping is needed */  if ( msr->byteorder != ms_bigendianhost() )    headerswapflag = 1;    /* Check if byte order is forced */  if ( packheaderbyteorder >= 0 )    {      headerswapflag = ( msr->byteorder != packheaderbyteorder ) ? 1: 0;    }    if ( verbose > 2 )    {      if ( headerswapflag )	ms_log (1, "%s: Byte swapping needed for packing of header\n", PACK_SRCNAME);      else	ms_log (1, "%s: Byte swapping NOT needed for packing of header\n", PACK_SRCNAME);    }    headerlen = msr_pack_header_raw (msr, msr->record, maxheaderlen,				   headerswapflag, normalize, verbose);    return headerlen;}  /* End of msr_pack_header() *//*************************************************************************** * msr_pack_header_raw: * * Pack data header/blockettes into the specified SEED data record. * * Returns the header length in bytes on success or -1 on error. ***************************************************************************/static intmsr_pack_header_raw ( MSRecord *msr, char *rawrec, int maxheaderlen,		      flag swapflag, flag normalize, flag verbose ){  struct blkt_link_s *cur_blkt;  struct fsdh_s *fsdh;  int16_t offset;  int blktcnt = 0;  int nextoffset;  if ( ! msr || ! rawrec )    return -1;    /* Make sure a fixed section of data header is available */  if ( ! msr->fsdh )    {      msr->fsdh = (struct fsdh_s *) calloc (1, sizeof (struct fsdh_s));

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -