Show the file size of the files in the tmp_dir on the LCD.
[ruwai.git] / software / c++ / ruwaicom / src / libmseed / pack.c
blobe520cdbf0090ed5cf16163619ec7beaca020c398
1 /***************************************************************************
2 * pack.c:
4 * Generic routines to pack Mini-SEED records using an MSrecord as a
5 * header template and data source.
7 * Written by Chad Trabant,
8 * IRIS Data Management Center
10 * modified: 2015.213
11 ***************************************************************************/
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 #include <time.h>
18 #include "libmseed.h"
19 #include "packdata.h"
21 /* Function(s) internal to this file */
22 static int msr_pack_header_raw (MSRecord *msr, char *rawrec, int maxheaderlen,
23 flag swapflag, flag normalize,
24 struct blkt_1001_s **blkt1001, flag verbose);
25 static int msr_update_header (MSRecord * msr, char *rawrec, flag swapflag,
26 struct blkt_1001_s *blkt1001, flag verbose);
27 static int msr_pack_data (void *dest, void *src, int maxsamples, int maxdatabytes,
28 int *packsamples, int32_t *lastintsample, flag comphistory,
29 char sampletype, flag encoding, flag swapflag,
30 flag verbose);
32 /* Header and data byte order flags controlled by environment variables */
33 /* -2 = not checked, -1 = checked but not set, or 0 = LE and 1 = BE */
34 flag packheaderbyteorder = -2;
35 flag packdatabyteorder = -2;
37 /* A pointer to the srcname of the record being packed */
38 char *PACK_SRCNAME = NULL;
41 /***************************************************************************
42 * msr_pack:
44 * Pack data into SEED data records. Using the record header values
45 * in the MSRecord as a template the common header fields are packed
46 * into the record header, blockettes in the blockettes chain are
47 * packed and data samples are packed in the encoding format indicated
48 * by the MSRecord->encoding field. A Blockette 1000 will be added if
49 * one is not present.
51 * The MSRecord->datasamples array and MSRecord->numsamples value will
52 * not be changed by this routine. It is the responsibility of the
53 * calling routine to adjust the data buffer if desired.
55 * As each record is filled and finished they are passed to
56 * record_handler which expects 1) a char * to the record, 2) the
57 * length of the record and 3) a pointer supplied by the original
58 * caller containing optional private data (handlerdata). It is the
59 * responsibility of record_handler to process the record, the memory
60 * will be re-used or freed when record_handler returns.
62 * If the flush flag != 0 all of the data will be packed into data
63 * records even though the last one will probably not be filled.
65 * Default values are: data record & quality indicator = 'D', record
66 * length = 4096, encoding = 11 (Steim2) and byteorder = 1 (MSBF).
67 * The defaults are triggered when the the msr->dataquality is 0 or
68 * msr->reclen, msr->encoding and msr->byteorder are -1 respectively.
70 * Returns the number of records created on success and -1 on error.
71 ***************************************************************************/
72 int
73 msr_pack ( MSRecord * msr, void (*record_handler) (char *, int, void *),
74 void *handlerdata, int64_t *packedsamples, flag flush, flag verbose )
76 uint16_t *HPnumsamples;
77 uint16_t *HPdataoffset;
78 struct blkt_1001_s *HPblkt1001 = NULL;
80 char *rawrec;
81 char *envvariable;
82 char srcname[50];
84 flag headerswapflag = 0;
85 flag dataswapflag = 0;
86 flag packret;
88 int samplesize;
89 int headerlen;
90 int dataoffset;
91 int maxdatabytes;
92 int maxsamples;
93 int recordcnt = 0;
94 int packsamples, packoffset;
95 int64_t totalpackedsamples;
96 hptime_t segstarttime;
98 if ( ! msr )
99 return -1;
101 if ( ! record_handler )
103 ms_log (2, "msr_pack(): record_handler() function pointer not set!\n");
104 return -1;
107 /* Allocate stream processing state space if needed */
108 if ( ! msr->ststate )
110 msr->ststate = (StreamState *) malloc (sizeof(StreamState));
111 if ( ! msr->ststate )
113 ms_log (2, "msr_pack(): Could not allocate memory for StreamState\n");
114 return -1;
116 memset (msr->ststate, 0, sizeof(StreamState));
119 /* Generate source name for MSRecord */
120 if ( msr_srcname (msr, srcname, 1) == NULL )
122 ms_log (2, "msr_unpack_data(): Cannot generate srcname\n");
123 return MS_GENERROR;
126 /* Set shared srcname pointer to source name */
127 PACK_SRCNAME = &srcname[0];
129 /* Track original segment start time for new start time calculation */
130 segstarttime = msr->starttime;
132 /* Read possible environmental variables that force byteorder */
133 if ( packheaderbyteorder == -2 )
135 if ( (envvariable = getenv("PACK_HEADER_BYTEORDER")) )
137 if ( *envvariable != '0' && *envvariable != '1' )
139 ms_log (2, "Environment variable PACK_HEADER_BYTEORDER must be set to '0' or '1'\n");
140 return -1;
142 else if ( *envvariable == '0' )
144 packheaderbyteorder = 0;
145 if ( verbose > 2 )
146 ms_log (1, "PACK_HEADER_BYTEORDER=0, packing little-endian header\n");
148 else
150 packheaderbyteorder = 1;
151 if ( verbose > 2 )
152 ms_log (1, "PACK_HEADER_BYTEORDER=1, packing big-endian header\n");
155 else
157 packheaderbyteorder = -1;
160 if ( packdatabyteorder == -2 )
162 if ( (envvariable = getenv("PACK_DATA_BYTEORDER")) )
164 if ( *envvariable != '0' && *envvariable != '1' )
166 ms_log (2, "Environment variable PACK_DATA_BYTEORDER must be set to '0' or '1'\n");
167 return -1;
169 else if ( *envvariable == '0' )
171 packdatabyteorder = 0;
172 if ( verbose > 2 )
173 ms_log (1, "PACK_DATA_BYTEORDER=0, packing little-endian data samples\n");
175 else
177 packdatabyteorder = 1;
178 if ( verbose > 2 )
179 ms_log (1, "PACK_DATA_BYTEORDER=1, packing big-endian data samples\n");
182 else
184 packdatabyteorder = -1;
188 /* Set default indicator, record length, byte order and encoding if needed */
189 if ( msr->dataquality == 0 ) msr->dataquality = 'D';
190 if ( msr->reclen == -1 ) msr->reclen = 4096;
191 if ( msr->byteorder == -1 ) msr->byteorder = 1;
192 if ( msr->encoding == -1 ) msr->encoding = DE_STEIM2;
194 /* Cleanup/reset sequence number */
195 if ( msr->sequence_number <= 0 || msr->sequence_number > 999999)
196 msr->sequence_number = 1;
198 if ( msr->reclen < MINRECLEN || msr->reclen > MAXRECLEN )
200 ms_log (2, "msr_pack(%s): Record length is out of range: %d\n",
201 PACK_SRCNAME, msr->reclen);
202 return -1;
205 if ( msr->numsamples <= 0 )
207 ms_log (2, "msr_pack(%s): No samples to pack\n", PACK_SRCNAME);
208 return -1;
211 samplesize = ms_samplesize (msr->sampletype);
213 if ( ! samplesize )
215 ms_log (2, "msr_pack(%s): Unknown sample type '%c'\n",
216 PACK_SRCNAME, msr->sampletype);
217 return -1;
220 /* Sanity check for msr/quality indicator */
221 if ( ! MS_ISDATAINDICATOR(msr->dataquality) )
223 ms_log (2, "msr_pack(%s): Record header & quality indicator unrecognized: '%c'\n",
224 PACK_SRCNAME, msr->dataquality);
225 ms_log (2, "msr_pack(%s): Packing failed.\n", PACK_SRCNAME);
226 return -1;
229 /* Allocate space for data record */
230 rawrec = (char *) malloc (msr->reclen);
232 if ( rawrec == NULL )
234 ms_log (2, "msr_pack(%s): Cannot allocate memory\n", PACK_SRCNAME);
235 return -1;
238 /* Set header pointers to known offsets into FSDH */
239 HPnumsamples = (uint16_t *) (rawrec + 30);
240 HPdataoffset = (uint16_t *) (rawrec + 44);
242 /* Check to see if byte swapping is needed */
243 if ( msr->byteorder != ms_bigendianhost() )
244 headerswapflag = dataswapflag = 1;
246 /* Check if byte order is forced */
247 if ( packheaderbyteorder >= 0 )
249 headerswapflag = ( msr->byteorder != packheaderbyteorder ) ? 1 : 0;
252 if ( packdatabyteorder >= 0 )
254 dataswapflag = ( msr->byteorder != packdatabyteorder ) ? 1 : 0;
257 if ( verbose > 2 )
259 if ( headerswapflag && dataswapflag )
260 ms_log (1, "%s: Byte swapping needed for packing of header and data samples\n", PACK_SRCNAME);
261 else if ( headerswapflag )
262 ms_log (1, "%s: Byte swapping needed for packing of header\n", PACK_SRCNAME);
263 else if ( dataswapflag )
264 ms_log (1, "%s: Byte swapping needed for packing of data samples\n", PACK_SRCNAME);
265 else
266 ms_log (1, "%s: Byte swapping NOT needed for packing\n", PACK_SRCNAME);
269 /* Add a blank 1000 Blockette if one is not present, the blockette values
270 will be populated in msr_pack_header_raw()/msr_normalize_header() */
271 if ( ! msr->Blkt1000 )
273 struct blkt_1000_s blkt1000;
274 memset (&blkt1000, 0, sizeof (struct blkt_1000_s));
276 if ( verbose > 2 )
277 ms_log (1, "%s: Adding 1000 Blockette\n", PACK_SRCNAME);
279 if ( ! msr_addblockette (msr, (char *) &blkt1000, sizeof(struct blkt_1000_s), 1000, 0) )
281 ms_log (2, "msr_pack(%s): Error adding 1000 Blockette\n", PACK_SRCNAME);
282 free (rawrec);
283 return -1;
287 headerlen = msr_pack_header_raw (msr, rawrec, msr->reclen, headerswapflag, 1, &HPblkt1001, verbose);
289 if ( headerlen == -1 )
291 ms_log (2, "msr_pack(%s): Error packing header\n", PACK_SRCNAME);
292 free (rawrec);
293 return -1;
296 /* Determine offset to encoded data */
297 if ( msr->encoding == DE_STEIM1 || msr->encoding == DE_STEIM2 )
299 dataoffset = 64;
300 while ( dataoffset < headerlen )
301 dataoffset += 64;
303 /* Zero memory between blockettes and data if any */
304 memset (rawrec + headerlen, 0, dataoffset - headerlen);
306 else
308 dataoffset = headerlen;
311 *HPdataoffset = (uint16_t) dataoffset;
312 if ( headerswapflag ) ms_gswap2 (HPdataoffset);
314 /* Determine the max data bytes and sample count */
315 maxdatabytes = msr->reclen - dataoffset;
317 if ( msr->encoding == DE_STEIM1 )
319 maxsamples = (int) (maxdatabytes/64) * STEIM1_FRAME_MAX_SAMPLES;
321 else if ( msr->encoding == DE_STEIM2 )
323 maxsamples = (int) (maxdatabytes/64) * STEIM2_FRAME_MAX_SAMPLES;
325 else
327 maxsamples = maxdatabytes / samplesize;
330 /* Pack samples into records */
331 *HPnumsamples = 0;
332 totalpackedsamples = 0;
333 if ( packedsamples ) *packedsamples = 0;
334 packoffset = 0;
336 while ( (msr->numsamples - totalpackedsamples) > maxsamples || flush )
338 packret = msr_pack_data (rawrec + dataoffset,
339 (char *) msr->datasamples + packoffset,
340 (int)(msr->numsamples - totalpackedsamples), maxdatabytes,
341 &packsamples, &msr->ststate->lastintsample, msr->ststate->comphistory,
342 msr->sampletype, msr->encoding, dataswapflag, verbose);
344 if ( packret )
346 ms_log (2, "msr_pack(%s): Error packing record\n", PACK_SRCNAME);
347 free (rawrec);
348 return -1;
351 packoffset += packsamples * samplesize;
353 /* Update number of samples */
354 *HPnumsamples = (uint16_t) packsamples;
355 if ( headerswapflag ) ms_gswap2 (HPnumsamples);
357 if ( verbose > 0 )
358 ms_log (1, "%s: Packed %d samples\n", PACK_SRCNAME, packsamples);
360 /* Send record to handler */
361 record_handler (rawrec, msr->reclen, handlerdata);
363 totalpackedsamples += packsamples;
364 if ( packedsamples ) *packedsamples = totalpackedsamples;
365 msr->ststate->packedsamples += packsamples;
367 /* Update record header for next record */
368 msr->sequence_number = ( msr->sequence_number >= 999999 ) ? 1 : msr->sequence_number + 1;
369 if ( msr->samprate > 0 )
370 msr->starttime = segstarttime + (hptime_t)(totalpackedsamples / msr->samprate * HPTMODULUS + 0.5);
372 msr_update_header (msr, rawrec, headerswapflag, HPblkt1001, verbose);
374 recordcnt++;
375 msr->ststate->packedrecords++;
377 /* Set compression history flag for subsequent records (Steim encodings) */
378 if ( ! msr->ststate->comphistory )
379 msr->ststate->comphistory = 1;
381 if ( totalpackedsamples >= msr->numsamples )
382 break;
385 if ( verbose > 2 )
386 ms_log (1, "%s: Packed %d total samples\n", PACK_SRCNAME, totalpackedsamples);
388 free (rawrec);
390 return recordcnt;
391 } /* End of msr_pack() */
394 /***************************************************************************
395 * msr_pack_header:
397 * Pack data header/blockettes into the SEED record at
398 * MSRecord->record. Unlike msr_pack no default values are applied,
399 * the header structures are expected to be self describing and no
400 * Blockette 1000 will be added. This routine is only useful for
401 * re-packing a record header.
403 * Returns the header length in bytes on success and -1 on error.
404 ***************************************************************************/
406 msr_pack_header ( MSRecord *msr, flag normalize, flag verbose )
408 char srcname[50];
409 char *envvariable;
410 flag headerswapflag = 0;
411 int headerlen;
412 int maxheaderlen;
414 if ( ! msr )
415 return -1;
417 /* Generate source name for MSRecord */
418 if ( msr_srcname (msr, srcname, 1) == NULL )
420 ms_log (2, "msr_unpack_data(): Cannot generate srcname\n");
421 return MS_GENERROR;
424 /* Set shared srcname pointer to source name */
425 PACK_SRCNAME = &srcname[0];
427 /* Read possible environmental variables that force byteorder */
428 if ( packheaderbyteorder == -2 )
430 if ( (envvariable = getenv("PACK_HEADER_BYTEORDER")) )
432 if ( *envvariable != '0' && *envvariable != '1' )
434 ms_log (2, "Environment variable PACK_HEADER_BYTEORDER must be set to '0' or '1'\n");
435 return -1;
437 else if ( *envvariable == '0' )
439 packheaderbyteorder = 0;
440 if ( verbose > 2 )
441 ms_log (1, "PACK_HEADER_BYTEORDER=0, packing little-endian header\n");
443 else
445 packheaderbyteorder = 1;
446 if ( verbose > 2 )
447 ms_log (1, "PACK_HEADER_BYTEORDER=1, packing big-endian header\n");
450 else
452 packheaderbyteorder = -1;
456 if ( msr->reclen < MINRECLEN || msr->reclen > MAXRECLEN )
458 ms_log (2, "msr_pack_header(%s): record length is out of range: %d\n",
459 PACK_SRCNAME, msr->reclen);
460 return -1;
463 if ( msr->byteorder != 0 && msr->byteorder != 1 )
465 ms_log (2, "msr_pack_header(%s): byte order is not defined correctly: %d\n",
466 PACK_SRCNAME, msr->byteorder);
467 return -1;
470 if ( msr->fsdh )
472 maxheaderlen = (msr->fsdh->data_offset > 0) ?
473 msr->fsdh->data_offset :
474 msr->reclen;
476 else
478 maxheaderlen = msr->reclen;
481 /* Check to see if byte swapping is needed */
482 if ( msr->byteorder != ms_bigendianhost() )
483 headerswapflag = 1;
485 /* Check if byte order is forced */
486 if ( packheaderbyteorder >= 0 )
488 headerswapflag = ( msr->byteorder != packheaderbyteorder ) ? 1: 0;
491 if ( verbose > 2 )
493 if ( headerswapflag )
494 ms_log (1, "%s: Byte swapping needed for packing of header\n", PACK_SRCNAME);
495 else
496 ms_log (1, "%s: Byte swapping NOT needed for packing of header\n", PACK_SRCNAME);
499 headerlen = msr_pack_header_raw (msr, msr->record, maxheaderlen,
500 headerswapflag, normalize, NULL, verbose);
502 return headerlen;
503 } /* End of msr_pack_header() */
506 /***************************************************************************
507 * msr_pack_header_raw:
509 * Pack data header/blockettes into the specified SEED data record.
511 * Returns the header length in bytes on success or -1 on error.
512 ***************************************************************************/
513 static int
514 msr_pack_header_raw ( MSRecord *msr, char *rawrec, int maxheaderlen,
515 flag swapflag, flag normalize,
516 struct blkt_1001_s **blkt1001, flag verbose )
518 struct blkt_link_s *cur_blkt;
519 struct fsdh_s *fsdh;
520 int16_t offset;
521 int blktcnt = 0;
522 int nextoffset;
524 if ( ! msr || ! rawrec )
525 return -1;
527 /* Make sure a fixed section of data header is available */
528 if ( ! msr->fsdh )
530 msr->fsdh = (struct fsdh_s *) calloc (1, sizeof (struct fsdh_s));
532 if ( msr->fsdh == NULL )
534 ms_log (2, "msr_pack_header_raw(%s): Cannot allocate memory\n",
535 PACK_SRCNAME);
536 return -1;
540 /* Update the SEED structures associated with the MSRecord */
541 if ( normalize )
542 if ( msr_normalize_header (msr, verbose) < 0 )
544 ms_log (2, "msr_pack_header_raw(%s): error normalizing header values\n",
545 PACK_SRCNAME);
546 return -1;
549 if ( verbose > 2 )
550 ms_log (1, "%s: Packing fixed section of data header\n", PACK_SRCNAME);
552 if ( maxheaderlen > msr->reclen )
554 ms_log (2, "msr_pack_header_raw(%s): maxheaderlen of %d is beyond record length of %d\n",
555 PACK_SRCNAME, maxheaderlen, msr->reclen);
556 return -1;
559 if ( maxheaderlen < (int)sizeof(struct fsdh_s) )
561 ms_log (2, "msr_pack_header_raw(%s): maxheaderlen of %d is too small, must be >= %d\n",
562 PACK_SRCNAME, maxheaderlen, sizeof(struct fsdh_s));
563 return -1;
566 fsdh = (struct fsdh_s *) rawrec;
567 offset = 48;
569 /* Roll-over sequence number if necessary */
570 if ( msr->sequence_number > 999999 )
571 msr->sequence_number = 1;
573 /* Copy FSDH associated with the MSRecord into the record */
574 memcpy (fsdh, msr->fsdh, sizeof(struct fsdh_s));
576 /* Swap byte order? */
577 if ( swapflag )
579 MS_SWAPBTIME (&fsdh->start_time);
580 ms_gswap2 (&fsdh->numsamples);
581 ms_gswap2 (&fsdh->samprate_fact);
582 ms_gswap2 (&fsdh->samprate_mult);
583 ms_gswap4 (&fsdh->time_correct);
584 ms_gswap2 (&fsdh->data_offset);
585 ms_gswap2 (&fsdh->blockette_offset);
588 /* Traverse blockette chain and pack blockettes at 'offset' */
589 cur_blkt = msr->blkts;
591 while ( cur_blkt && offset < maxheaderlen )
593 /* Check that the blockette fits */
594 if ( (offset + 4 + cur_blkt->blktdatalen) > maxheaderlen )
596 ms_log (2, "msr_pack_header_raw(%s): header exceeds maxheaderlen of %d\n",
597 PACK_SRCNAME, maxheaderlen);
598 break;
601 /* Pack blockette type and leave space for next offset */
602 memcpy (rawrec + offset, &cur_blkt->blkt_type, 2);
603 if ( swapflag ) ms_gswap2 (rawrec + offset);
604 nextoffset = offset + 2;
605 offset += 4;
607 if ( cur_blkt->blkt_type == 100 )
609 struct blkt_100_s *blkt_100 = (struct blkt_100_s *) (rawrec + offset);
610 memcpy (blkt_100, cur_blkt->blktdata, sizeof (struct blkt_100_s));
611 offset += sizeof (struct blkt_100_s);
613 if ( swapflag )
615 ms_gswap4 (&blkt_100->samprate);
619 else if ( cur_blkt->blkt_type == 200 )
621 struct blkt_200_s *blkt_200 = (struct blkt_200_s *) (rawrec + offset);
622 memcpy (blkt_200, cur_blkt->blktdata, sizeof (struct blkt_200_s));
623 offset += sizeof (struct blkt_200_s);
625 if ( swapflag )
627 ms_gswap4 (&blkt_200->amplitude);
628 ms_gswap4 (&blkt_200->period);
629 ms_gswap4 (&blkt_200->background_estimate);
630 MS_SWAPBTIME (&blkt_200->time);
634 else if ( cur_blkt->blkt_type == 201 )
636 struct blkt_201_s *blkt_201 = (struct blkt_201_s *) (rawrec + offset);
637 memcpy (blkt_201, cur_blkt->blktdata, sizeof (struct blkt_201_s));
638 offset += sizeof (struct blkt_201_s);
640 if ( swapflag )
642 ms_gswap4 (&blkt_201->amplitude);
643 ms_gswap4 (&blkt_201->period);
644 ms_gswap4 (&blkt_201->background_estimate);
645 MS_SWAPBTIME (&blkt_201->time);
649 else if ( cur_blkt->blkt_type == 300 )
651 struct blkt_300_s *blkt_300 = (struct blkt_300_s *) (rawrec + offset);
652 memcpy (blkt_300, cur_blkt->blktdata, sizeof (struct blkt_300_s));
653 offset += sizeof (struct blkt_300_s);
655 if ( swapflag )
657 MS_SWAPBTIME (&blkt_300->time);
658 ms_gswap4 (&blkt_300->step_duration);
659 ms_gswap4 (&blkt_300->interval_duration);
660 ms_gswap4 (&blkt_300->amplitude);
661 ms_gswap4 (&blkt_300->reference_amplitude);
665 else if ( cur_blkt->blkt_type == 310 )
667 struct blkt_310_s *blkt_310 = (struct blkt_310_s *) (rawrec + offset);
668 memcpy (blkt_310, cur_blkt->blktdata, sizeof (struct blkt_310_s));
669 offset += sizeof (struct blkt_310_s);
671 if ( swapflag )
673 MS_SWAPBTIME (&blkt_310->time);
674 ms_gswap4 (&blkt_310->duration);
675 ms_gswap4 (&blkt_310->period);
676 ms_gswap4 (&blkt_310->amplitude);
677 ms_gswap4 (&blkt_310->reference_amplitude);
681 else if ( cur_blkt->blkt_type == 320 )
683 struct blkt_320_s *blkt_320 = (struct blkt_320_s *) (rawrec + offset);
684 memcpy (blkt_320, cur_blkt->blktdata, sizeof (struct blkt_320_s));
685 offset += sizeof (struct blkt_320_s);
687 if ( swapflag )
689 MS_SWAPBTIME (&blkt_320->time);
690 ms_gswap4 (&blkt_320->duration);
691 ms_gswap4 (&blkt_320->ptp_amplitude);
692 ms_gswap4 (&blkt_320->reference_amplitude);
696 else if ( cur_blkt->blkt_type == 390 )
698 struct blkt_390_s *blkt_390 = (struct blkt_390_s *) (rawrec + offset);
699 memcpy (blkt_390, cur_blkt->blktdata, sizeof (struct blkt_390_s));
700 offset += sizeof (struct blkt_390_s);
702 if ( swapflag )
704 MS_SWAPBTIME (&blkt_390->time);
705 ms_gswap4 (&blkt_390->duration);
706 ms_gswap4 (&blkt_390->amplitude);
710 else if ( cur_blkt->blkt_type == 395 )
712 struct blkt_395_s *blkt_395 = (struct blkt_395_s *) (rawrec + offset);
713 memcpy (blkt_395, cur_blkt->blktdata, sizeof (struct blkt_395_s));
714 offset += sizeof (struct blkt_395_s);
716 if ( swapflag )
718 MS_SWAPBTIME (&blkt_395->time);
722 else if ( cur_blkt->blkt_type == 400 )
724 struct blkt_400_s *blkt_400 = (struct blkt_400_s *) (rawrec + offset);
725 memcpy (blkt_400, cur_blkt->blktdata, sizeof (struct blkt_400_s));
726 offset += sizeof (struct blkt_400_s);
728 if ( swapflag )
730 ms_gswap4 (&blkt_400->azimuth);
731 ms_gswap4 (&blkt_400->slowness);
732 ms_gswap2 (&blkt_400->configuration);
736 else if ( cur_blkt->blkt_type == 405 )
738 struct blkt_405_s *blkt_405 = (struct blkt_405_s *) (rawrec + offset);
739 memcpy (blkt_405, cur_blkt->blktdata, sizeof (struct blkt_405_s));
740 offset += sizeof (struct blkt_405_s);
742 if ( swapflag )
744 ms_gswap2 (&blkt_405->delay_values);
747 if ( verbose > 0 )
749 ms_log (1, "msr_pack_header_raw(%s): WARNING Blockette 405 cannot be fully supported\n",
750 PACK_SRCNAME);
754 else if ( cur_blkt->blkt_type == 500 )
756 struct blkt_500_s *blkt_500 = (struct blkt_500_s *) (rawrec + offset);
757 memcpy (blkt_500, cur_blkt->blktdata, sizeof (struct blkt_500_s));
758 offset += sizeof (struct blkt_500_s);
760 if ( swapflag )
762 ms_gswap4 (&blkt_500->vco_correction);
763 MS_SWAPBTIME (&blkt_500->time);
764 ms_gswap4 (&blkt_500->exception_count);
768 else if ( cur_blkt->blkt_type == 1000 )
770 struct blkt_1000_s *blkt_1000 = (struct blkt_1000_s *) (rawrec + offset);
771 memcpy (blkt_1000, cur_blkt->blktdata, sizeof (struct blkt_1000_s));
772 offset += sizeof (struct blkt_1000_s);
774 /* This guarantees that the byte order is in sync with msr_pack() */
775 if ( packdatabyteorder >= 0 )
776 blkt_1000->byteorder = packdatabyteorder;
779 else if ( cur_blkt->blkt_type == 1001 )
781 struct blkt_1001_s *blkt_1001 = (struct blkt_1001_s *) (rawrec + offset);
782 memcpy (blkt_1001, cur_blkt->blktdata, sizeof (struct blkt_1001_s));
783 offset += sizeof (struct blkt_1001_s);
785 /* Track location of Blockette 1001 if requested */
786 if ( blkt1001 )
787 *blkt1001 = blkt_1001;
790 else if ( cur_blkt->blkt_type == 2000 )
792 struct blkt_2000_s *blkt_2000 = (struct blkt_2000_s *) (rawrec + offset);
793 memcpy (blkt_2000, cur_blkt->blktdata, cur_blkt->blktdatalen);
794 offset += cur_blkt->blktdatalen;
796 if ( swapflag )
798 ms_gswap2 (&blkt_2000->length);
799 ms_gswap2 (&blkt_2000->data_offset);
800 ms_gswap4 (&blkt_2000->recnum);
803 /* Nothing done to pack the opaque headers and data, they should already
804 be packed into the blockette payload */
807 else
809 memcpy (rawrec + offset, cur_blkt->blktdata, cur_blkt->blktdatalen);
810 offset += cur_blkt->blktdatalen;
813 /* Pack the offset to the next blockette */
814 if ( cur_blkt->next )
816 memcpy (rawrec + nextoffset, &offset, 2);
817 if ( swapflag ) ms_gswap2 (rawrec + nextoffset);
819 else
821 memset (rawrec + nextoffset, 0, 2);
824 blktcnt++;
825 cur_blkt = cur_blkt->next;
828 fsdh->numblockettes = blktcnt;
830 if ( verbose > 2 )
831 ms_log (1, "%s: Packed %d blockettes\n", PACK_SRCNAME, blktcnt);
833 return offset;
834 } /* End of msr_pack_header_raw() */
837 /***************************************************************************
838 * msr_update_header:
840 * Update the header values that change between records: start time,
841 * sequence number, etc.
843 * Returns 0 on success or -1 on error.
844 ***************************************************************************/
845 static int
846 msr_update_header ( MSRecord *msr, char *rawrec, flag swapflag,
847 struct blkt_1001_s *blkt1001, flag verbose )
849 struct fsdh_s *fsdh;
850 hptime_t hptimems;
851 int8_t usecoffset;
852 char seqnum[7];
854 if ( ! msr || ! rawrec )
855 return -1;
857 if ( verbose > 2 )
858 ms_log (1, "%s: Updating fixed section of data header\n", PACK_SRCNAME);
860 fsdh = (struct fsdh_s *) rawrec;
862 /* Pack values into the fixed section of header */
863 snprintf (seqnum, 7, "%06d", msr->sequence_number);
864 memcpy (fsdh->sequence_number, seqnum, 6);
866 /* Get start time rounded to tenths of milliseconds and microsecond offset */
867 ms_hptime2tomsusecoffset (msr->starttime, &hptimems, &usecoffset);
869 /* Update fixed-section start time */
870 ms_hptime2btime (hptimems, &(fsdh->start_time));
872 /* Swap byte order? */
873 if ( swapflag )
875 MS_SWAPBTIME (&fsdh->start_time);
878 /* Update microsecond offset value if Blockette 1001 is present */
879 if ( msr->Blkt1001 && blkt1001 )
881 /* Update microseconds offset in blockette chain entry */
882 msr->Blkt1001->usec = usecoffset;
884 /* Update microseconds offset in packed header */
885 blkt1001->usec = usecoffset;
888 return 0;
889 } /* End of msr_update_header() */
892 /************************************************************************
893 * msr_pack_data:
895 * Pack Mini-SEED data samples. The input data samples specified as
896 * 'src' will be packed with 'encoding' format and placed in 'dest'.
898 * If a pointer to a 32-bit integer sample is provided in the
899 * argument 'lastintsample' and 'comphistory' is true the sample
900 * value will be used to seed the difference buffer for Steim1/2
901 * encoding and provide a compression history. It will also be
902 * updated with the last sample packed in order to be used with a
903 * subsequent call to this routine.
905 * The number of samples packed will be placed in 'packsamples' and
906 * the number of bytes packed will be placed in 'packbytes'.
908 * Return 0 on success and a negative number on error.
909 ************************************************************************/
910 static int
911 msr_pack_data (void *dest, void *src, int maxsamples, int maxdatabytes,
912 int *packsamples, int32_t *lastintsample, flag comphistory,
913 char sampletype, flag encoding, flag swapflag, flag verbose)
915 int retval;
916 int nframes;
917 int npacked;
918 int32_t *intbuff;
919 int32_t d0;
921 /* Decide if this is a format that we can decode */
922 switch (encoding)
925 case DE_ASCII:
926 if ( sampletype != 'a' )
928 ms_log (2, "%s: Sample type must be ascii (a) for ASCII encoding not '%c'\n",
929 PACK_SRCNAME, sampletype);
930 return -1;
933 if ( verbose > 1 )
934 ms_log (1, "%s: Packing ASCII data\n", PACK_SRCNAME);
936 retval = msr_pack_text (dest, src, maxsamples, maxdatabytes, 1,
937 &npacked, packsamples);
939 break;
941 case DE_INT16:
942 if ( sampletype != 'i' )
944 ms_log (2, "%s: Sample type must be integer (i) for integer-16 encoding not '%c'\n",
945 PACK_SRCNAME, sampletype);
946 return -1;
949 if ( verbose > 1 )
950 ms_log (1, "%s: Packing INT-16 data samples\n", PACK_SRCNAME);
952 retval = msr_pack_int_16 (dest, src, maxsamples, maxdatabytes, 1,
953 &npacked, packsamples, swapflag);
955 break;
957 case DE_INT32:
958 if ( sampletype != 'i' )
960 ms_log (2, "%s: Sample type must be integer (i) for integer-32 encoding not '%c'\n",
961 PACK_SRCNAME, sampletype);
962 return -1;
965 if ( verbose > 1 )
966 ms_log (1, "%s: Packing INT-32 data samples\n", PACK_SRCNAME);
968 retval = msr_pack_int_32 (dest, src, maxsamples, maxdatabytes, 1,
969 &npacked, packsamples, swapflag);
971 break;
973 case DE_FLOAT32:
974 if ( sampletype != 'f' )
976 ms_log (2, "%s: Sample type must be float (f) for float-32 encoding not '%c'\n",
977 PACK_SRCNAME, sampletype);
978 return -1;
981 if ( verbose > 1 )
982 ms_log (1, "%s: Packing FLOAT-32 data samples\n", PACK_SRCNAME);
984 retval = msr_pack_float_32 (dest, src, maxsamples, maxdatabytes, 1,
985 &npacked, packsamples, swapflag);
987 break;
989 case DE_FLOAT64:
990 if ( sampletype != 'd' )
992 ms_log (2, "%s: Sample type must be double (d) for float-64 encoding not '%c'\n",
993 PACK_SRCNAME, sampletype);
994 return -1;
997 if ( verbose > 1 )
998 ms_log (1, "%s: Packing FLOAT-64 data samples\n", PACK_SRCNAME);
1000 retval = msr_pack_float_64 (dest, src, maxsamples, maxdatabytes, 1,
1001 &npacked, packsamples, swapflag);
1003 break;
1005 case DE_STEIM1:
1006 if ( sampletype != 'i' )
1008 ms_log (2, "%s: Sample type must be integer (i) for Steim-1 compression not '%c'\n",
1009 PACK_SRCNAME, sampletype);
1010 return -1;
1013 intbuff = (int32_t *) src;
1015 /* If a previous sample is supplied use it for compression history otherwise cold-start */
1016 d0 = ( lastintsample && comphistory ) ? (intbuff[0] - *lastintsample) : 0;
1018 if ( verbose > 1 )
1019 ms_log (1, "%s: Packing Steim-1 data frames\n", PACK_SRCNAME);
1021 nframes = maxdatabytes / 64;
1023 retval = msr_pack_steim1 (dest, src, d0, maxsamples, nframes, 1,
1024 &npacked, packsamples, swapflag);
1026 /* If a previous sample is supplied update it with the last sample value */
1027 if ( lastintsample && retval == 0 )
1028 *lastintsample = intbuff[*packsamples-1];
1030 break;
1032 case DE_STEIM2:
1033 if ( sampletype != 'i' )
1035 ms_log (2, "%s: Sample type must be integer (i) for Steim-2 compression not '%c'\n",
1036 PACK_SRCNAME, sampletype);
1037 return -1;
1040 intbuff = (int32_t *) src;
1042 /* If a previous sample is supplied use it for compression history otherwise cold-start */
1043 d0 = ( lastintsample && comphistory ) ? (intbuff[0] - *lastintsample) : 0;
1045 if ( verbose > 1 )
1046 ms_log (1, "%s: Packing Steim-2 data frames\n", PACK_SRCNAME);
1048 nframes = maxdatabytes / 64;
1050 retval = msr_pack_steim2 (dest, src, d0, maxsamples, nframes, 1,
1051 &npacked, packsamples, swapflag);
1053 /* If a previous sample is supplied update it with the last sample value */
1054 if ( lastintsample && retval == 0 )
1055 *lastintsample = intbuff[*packsamples-1];
1057 break;
1059 default:
1060 ms_log (2, "%s: Unable to pack format %d\n", PACK_SRCNAME, encoding);
1062 return -1;
1065 return retval;
1066 } /* End of msr_pack_data() */