Show the file size of the files in the tmp_dir on the LCD.
[ruwai.git] / software / c++ / ruwaicom / src / libmseed / unpack.c
blob0ff5260145392808623b9ce800cf3c3127d7aaba
1 /***************************************************************************
2 * unpack.c:
4 * Generic routines to unpack Mini-SEED records.
6 * Appropriate values from the record header will be byte-swapped to
7 * the host order. The purpose of this code is to provide a portable
8 * way of accessing common SEED data record header information. All
9 * data structures in SEED 2.4 data records are supported. The data
10 * samples are optionally decompressed/unpacked.
12 * Written by Chad Trabant,
13 * ORFEUS/EC-Project MEREDIAN
14 * IRIS Data Management Center
16 * modified: 2015.108
17 ***************************************************************************/
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <time.h>
22 #include <ctype.h>
24 #include "libmseed.h"
25 #include "unpackdata.h"
27 /* Function(s) internal to this file */
28 static int check_environment (int verbose);
30 /* Header and data byte order flags controlled by environment variables */
31 /* -2 = not checked, -1 = checked but not set, or 0 = LE and 1 = BE */
32 flag unpackheaderbyteorder = -2;
33 flag unpackdatabyteorder = -2;
35 /* Data encoding format/fallback controlled by environment variable */
36 /* -2 = not checked, -1 = checked but not set, or = encoding */
37 int unpackencodingformat = -2;
38 int unpackencodingfallback = -2;
40 /* A pointer to the srcname of the record being unpacked */
41 char *UNPACK_SRCNAME = NULL;
44 /***************************************************************************
45 * msr_unpack:
47 * Unpack a SEED data record header/blockettes and populate a MSRecord
48 * struct. All approriate fields are byteswapped, if needed, and
49 * pointers to structured data are setup in addition to setting the
50 * common header fields.
52 * If 'dataflag' is true the data samples are unpacked/decompressed
53 * and the MSRecord->datasamples pointer is set appropriately. The
54 * data samples will be either 32-bit integers, 32-bit floats or
55 * 64-bit floats (doubles) with the same byte order as the host
56 * machine. The MSRecord->numsamples will be set to the actual number
57 * of samples unpacked/decompressed and MSRecord->sampletype will
58 * indicated the sample type.
60 * All appropriate values will be byte-swapped to the host order,
61 * including the data samples.
63 * All header values, blockette values and data samples will be
64 * overwritten by subsequent calls to this function.
66 * If the msr struct is NULL it will be allocated.
68 * Returns MS_NOERROR and populates the MSRecord struct at *ppmsr on
69 * success, otherwise returns a libmseed error code (listed in
70 * libmseed.h).
71 ***************************************************************************/
72 int
73 msr_unpack ( char *record, int reclen, MSRecord **ppmsr,
74 flag dataflag, flag verbose )
76 flag headerswapflag = 0;
77 flag dataswapflag = 0;
78 int retval;
80 MSRecord *msr = NULL;
81 char sequence_number[7];
82 char srcname[50];
84 /* For blockette parsing */
85 BlktLink *blkt_link = 0;
86 uint16_t blkt_type;
87 uint16_t next_blkt;
88 uint32_t blkt_offset;
89 uint32_t blkt_length;
90 int blkt_count = 0;
92 if ( ! ppmsr )
94 ms_log (2, "msr_unpack(): ppmsr argument cannot be NULL\n");
95 return MS_GENERROR;
98 /* Verify that record includes a valid header */
99 if ( ! MS_ISVALIDHEADER(record) )
101 ms_recsrcname (record, srcname, 1);
102 ms_log (2, "msr_unpack(%s) Record header & quality indicator unrecognized: '%c'\n", srcname);
103 ms_log (2, "msr_unpack(%s) This is not a valid Mini-SEED record\n", srcname);
105 return MS_NOTSEED;
108 /* Verify that passed record length is within supported range */
109 if ( reclen < MINRECLEN || reclen > MAXRECLEN )
111 ms_recsrcname (record, srcname, 1);
112 ms_log (2, "msr_unpack(%s): Record length is out of range: %d\n", srcname, reclen);
113 return MS_OUTOFRANGE;
116 /* Initialize the MSRecord */
117 if ( ! (*ppmsr = msr_init (*ppmsr)) )
118 return MS_GENERROR;
120 /* Shortcut pointer, historical and help readability */
121 msr = *ppmsr;
123 /* Set raw record pointer and record length */
124 msr->record = record;
125 msr->reclen = reclen;
127 /* Check environment variables if necessary */
128 if ( unpackheaderbyteorder == -2 ||
129 unpackdatabyteorder == -2 ||
130 unpackencodingformat == -2 ||
131 unpackencodingfallback == -2 )
132 if ( check_environment(verbose) )
133 return MS_GENERROR;
135 /* Allocate and copy fixed section of data header */
136 msr->fsdh = realloc (msr->fsdh, sizeof (struct fsdh_s));
138 if ( msr->fsdh == NULL )
140 ms_log (2, "msr_unpack(): Cannot allocate memory\n");
141 return MS_GENERROR;
144 memcpy (msr->fsdh, record, sizeof (struct fsdh_s));
146 /* Check to see if byte swapping is needed by testing the year and day */
147 if ( ! MS_ISVALIDYEARDAY (msr->fsdh->start_time.year, msr->fsdh->start_time.day) )
148 headerswapflag = dataswapflag = 1;
150 /* Check if byte order is forced */
151 if ( unpackheaderbyteorder >= 0 )
153 headerswapflag = ( ms_bigendianhost() != unpackheaderbyteorder ) ? 1 : 0;
156 if ( unpackdatabyteorder >= 0 )
158 dataswapflag = ( ms_bigendianhost() != unpackdatabyteorder ) ? 1 : 0;
161 /* Swap byte order? */
162 if ( headerswapflag )
164 MS_SWAPBTIME (&msr->fsdh->start_time);
165 ms_gswap2a (&msr->fsdh->numsamples);
166 ms_gswap2a (&msr->fsdh->samprate_fact);
167 ms_gswap2a (&msr->fsdh->samprate_mult);
168 ms_gswap4a (&msr->fsdh->time_correct);
169 ms_gswap2a (&msr->fsdh->data_offset);
170 ms_gswap2a (&msr->fsdh->blockette_offset);
173 /* Populate some of the common header fields */
174 strncpy (sequence_number, msr->fsdh->sequence_number, 6);
175 sequence_number[6] = '\0';
176 msr->sequence_number = (int32_t) strtol (sequence_number, NULL, 10);
177 msr->dataquality = msr->fsdh->dataquality;
178 ms_strncpcleantail (msr->network, msr->fsdh->network, 2);
179 ms_strncpcleantail (msr->station, msr->fsdh->station, 5);
180 ms_strncpcleantail (msr->location, msr->fsdh->location, 2);
181 ms_strncpcleantail (msr->channel, msr->fsdh->channel, 3);
182 msr->samplecnt = msr->fsdh->numsamples;
184 /* Generate source name for MSRecord */
185 if ( msr_srcname (msr, srcname, 1) == NULL )
187 ms_log (2, "msr_unpack(): Cannot generate srcname\n");
188 return MS_GENERROR;
191 /* Set shared srcname pointer to source name */
192 UNPACK_SRCNAME = &srcname[0];
194 /* Report byte swapping status */
195 if ( verbose > 2 )
197 if ( headerswapflag )
198 ms_log (1, "%s: Byte swapping needed for unpacking of header\n",
199 UNPACK_SRCNAME);
200 else
201 ms_log (1, "%s: Byte swapping NOT needed for unpacking of header\n",
202 UNPACK_SRCNAME);
205 /* Traverse the blockettes */
206 blkt_offset = msr->fsdh->blockette_offset;
208 while ((blkt_offset != 0) &&
209 ((int)blkt_offset < reclen) &&
210 (blkt_offset < MAXRECLEN))
212 /* Every blockette has a similar 4 byte header: type and next */
213 memcpy (&blkt_type, record + blkt_offset, 2);
214 blkt_offset += 2;
215 memcpy (&next_blkt, record + blkt_offset, 2);
216 blkt_offset += 2;
218 if ( headerswapflag )
220 ms_gswap2 (&blkt_type);
221 ms_gswap2 (&next_blkt);
224 /* Get blockette length */
225 blkt_length = ms_blktlen (blkt_type,
226 record + blkt_offset - 4,
227 headerswapflag);
229 if ( blkt_length == 0 )
231 ms_log (2, "msr_unpack(%s): Unknown blockette length for type %d\n",
232 UNPACK_SRCNAME, blkt_type);
233 break;
236 /* Make sure blockette is contained within the msrecord buffer */
237 if ( (int)(blkt_offset - 4 + blkt_length) > reclen )
239 ms_log (2, "msr_unpack(%s): Blockette %d extends beyond record size, truncated?\n",
240 UNPACK_SRCNAME, blkt_type);
241 break;
244 if ( blkt_type == 100 )
245 { /* Found a Blockette 100 */
246 struct blkt_100_s *blkt_100;
248 blkt_link = msr_addblockette (msr, record + blkt_offset,
249 sizeof (struct blkt_100_s),
250 blkt_type, 0);
251 if ( ! blkt_link )
252 break;
254 blkt_link->blktoffset = blkt_offset - 4;
255 blkt_link->next_blkt = next_blkt;
257 blkt_100 = (struct blkt_100_s *) blkt_link->blktdata;
259 if ( headerswapflag )
261 ms_gswap4 (&blkt_100->samprate);
264 msr->samprate = msr->Blkt100->samprate;
267 else if ( blkt_type == 200 )
268 { /* Found a Blockette 200 */
269 struct blkt_200_s *blkt_200;
271 blkt_link = msr_addblockette (msr, record + blkt_offset,
272 sizeof (struct blkt_200_s),
273 blkt_type, 0);
274 if ( ! blkt_link )
275 break;
277 blkt_link->blktoffset = blkt_offset - 4;
278 blkt_link->next_blkt = next_blkt;
280 blkt_200 = (struct blkt_200_s *) blkt_link->blktdata;
282 if ( headerswapflag )
284 ms_gswap4 (&blkt_200->amplitude);
285 ms_gswap4 (&blkt_200->period);
286 ms_gswap4 (&blkt_200->background_estimate);
287 MS_SWAPBTIME (&blkt_200->time);
291 else if ( blkt_type == 201 )
292 { /* Found a Blockette 201 */
293 struct blkt_201_s *blkt_201;
295 blkt_link = msr_addblockette (msr, record + blkt_offset,
296 sizeof (struct blkt_201_s),
297 blkt_type, 0);
298 if ( ! blkt_link )
299 break;
301 blkt_link->blktoffset = blkt_offset - 4;
302 blkt_link->next_blkt = next_blkt;
304 blkt_201 = (struct blkt_201_s *) blkt_link->blktdata;
306 if ( headerswapflag )
308 ms_gswap4 (&blkt_201->amplitude);
309 ms_gswap4 (&blkt_201->period);
310 ms_gswap4 (&blkt_201->background_estimate);
311 MS_SWAPBTIME (&blkt_201->time);
315 else if ( blkt_type == 300 )
316 { /* Found a Blockette 300 */
317 struct blkt_300_s *blkt_300;
319 blkt_link = msr_addblockette (msr, record + blkt_offset,
320 sizeof (struct blkt_300_s),
321 blkt_type, 0);
322 if ( ! blkt_link )
323 break;
325 blkt_link->blktoffset = blkt_offset - 4;
326 blkt_link->next_blkt = next_blkt;
328 blkt_300 = (struct blkt_300_s *) blkt_link->blktdata;
330 if ( headerswapflag )
332 MS_SWAPBTIME (&blkt_300->time);
333 ms_gswap4 (&blkt_300->step_duration);
334 ms_gswap4 (&blkt_300->interval_duration);
335 ms_gswap4 (&blkt_300->amplitude);
336 ms_gswap4 (&blkt_300->reference_amplitude);
340 else if ( blkt_type == 310 )
341 { /* Found a Blockette 310 */
342 struct blkt_310_s *blkt_310;
344 blkt_link = msr_addblockette (msr, record + blkt_offset,
345 sizeof (struct blkt_310_s),
346 blkt_type, 0);
347 if ( ! blkt_link )
348 break;
350 blkt_link->blktoffset = blkt_offset - 4;
351 blkt_link->next_blkt = next_blkt;
353 blkt_310 = (struct blkt_310_s *) blkt_link->blktdata;
355 if ( headerswapflag )
357 MS_SWAPBTIME (&blkt_310->time);
358 ms_gswap4 (&blkt_310->duration);
359 ms_gswap4 (&blkt_310->period);
360 ms_gswap4 (&blkt_310->amplitude);
361 ms_gswap4 (&blkt_310->reference_amplitude);
365 else if ( blkt_type == 320 )
366 { /* Found a Blockette 320 */
367 struct blkt_320_s *blkt_320;
369 blkt_link = msr_addblockette (msr, record + blkt_offset,
370 sizeof (struct blkt_320_s),
371 blkt_type, 0);
372 if ( ! blkt_link )
373 break;
375 blkt_link->blktoffset = blkt_offset - 4;
376 blkt_link->next_blkt = next_blkt;
378 blkt_320 = (struct blkt_320_s *) blkt_link->blktdata;
380 if ( headerswapflag )
382 MS_SWAPBTIME (&blkt_320->time);
383 ms_gswap4 (&blkt_320->duration);
384 ms_gswap4 (&blkt_320->ptp_amplitude);
385 ms_gswap4 (&blkt_320->reference_amplitude);
389 else if ( blkt_type == 390 )
390 { /* Found a Blockette 390 */
391 struct blkt_390_s *blkt_390;
393 blkt_link = msr_addblockette (msr, record + blkt_offset,
394 sizeof (struct blkt_390_s),
395 blkt_type, 0);
396 if ( ! blkt_link )
397 break;
399 blkt_link->blktoffset = blkt_offset - 4;
400 blkt_link->next_blkt = next_blkt;
402 blkt_390 = (struct blkt_390_s *) blkt_link->blktdata;
404 if ( headerswapflag )
406 MS_SWAPBTIME (&blkt_390->time);
407 ms_gswap4 (&blkt_390->duration);
408 ms_gswap4 (&blkt_390->amplitude);
412 else if ( blkt_type == 395 )
413 { /* Found a Blockette 395 */
414 struct blkt_395_s *blkt_395;
416 blkt_link = msr_addblockette (msr, record + blkt_offset,
417 sizeof (struct blkt_395_s),
418 blkt_type, 0);
419 if ( ! blkt_link )
420 break;
422 blkt_link->blktoffset = blkt_offset - 4;
423 blkt_link->next_blkt = next_blkt;
425 blkt_395 = (struct blkt_395_s *) blkt_link->blktdata;
427 if ( headerswapflag )
429 MS_SWAPBTIME (&blkt_395->time);
433 else if ( blkt_type == 400 )
434 { /* Found a Blockette 400 */
435 struct blkt_400_s *blkt_400;
437 blkt_link = msr_addblockette (msr, record + blkt_offset,
438 sizeof (struct blkt_400_s),
439 blkt_type, 0);
440 if ( ! blkt_link )
441 break;
443 blkt_link->blktoffset = blkt_offset - 4;
444 blkt_link->next_blkt = next_blkt;
446 blkt_400 = (struct blkt_400_s *) blkt_link->blktdata;
448 if ( headerswapflag )
450 ms_gswap4 (&blkt_400->azimuth);
451 ms_gswap4 (&blkt_400->slowness);
452 ms_gswap2 (&blkt_400->configuration);
456 else if ( blkt_type == 405 )
457 { /* Found a Blockette 405 */
458 struct blkt_405_s *blkt_405;
460 blkt_link = msr_addblockette (msr, record + blkt_offset,
461 sizeof (struct blkt_405_s),
462 blkt_type, 0);
463 if ( ! blkt_link )
464 break;
466 blkt_link->blktoffset = blkt_offset - 4;
467 blkt_link->next_blkt = next_blkt;
469 blkt_405 = (struct blkt_405_s *) blkt_link->blktdata;
471 if ( headerswapflag )
473 ms_gswap2 (&blkt_405->delay_values);
476 if ( verbose > 0 )
478 ms_log (1, "msr_unpack(%s): WARNING Blockette 405 cannot be fully supported\n",
479 UNPACK_SRCNAME);
483 else if ( blkt_type == 500 )
484 { /* Found a Blockette 500 */
485 struct blkt_500_s *blkt_500;
487 blkt_link = msr_addblockette (msr, record + blkt_offset,
488 sizeof (struct blkt_500_s),
489 blkt_type, 0);
490 if ( ! blkt_link )
491 break;
493 blkt_link->blktoffset = blkt_offset - 4;
494 blkt_link->next_blkt = next_blkt;
496 blkt_500 = (struct blkt_500_s *) blkt_link->blktdata;
498 if ( headerswapflag )
500 ms_gswap4 (&blkt_500->vco_correction);
501 MS_SWAPBTIME (&blkt_500->time);
502 ms_gswap4 (&blkt_500->exception_count);
506 else if ( blkt_type == 1000 )
507 { /* Found a Blockette 1000 */
508 struct blkt_1000_s *blkt_1000;
510 blkt_link = msr_addblockette (msr, record + blkt_offset,
511 sizeof (struct blkt_1000_s),
512 blkt_type, 0);
513 if ( ! blkt_link )
514 break;
516 blkt_link->blktoffset = blkt_offset - 4;
517 blkt_link->next_blkt = next_blkt;
519 blkt_1000 = (struct blkt_1000_s *) blkt_link->blktdata;
521 /* Calculate record length in bytes as 2^(blkt_1000->reclen) */
522 msr->reclen = (uint32_t) 1 << blkt_1000->reclen;
524 /* Compare against the specified length */
525 if ( msr->reclen != reclen && verbose )
527 ms_log (2, "msr_unpack(%s): Record length in Blockette 1000 (%d) != specified length (%d)\n",
528 UNPACK_SRCNAME, msr->reclen, reclen);
531 msr->encoding = blkt_1000->encoding;
532 msr->byteorder = blkt_1000->byteorder;
535 else if ( blkt_type == 1001 )
536 { /* Found a Blockette 1001 */
537 blkt_link = msr_addblockette (msr, record + blkt_offset,
538 sizeof (struct blkt_1001_s),
539 blkt_type, 0);
540 if ( ! blkt_link )
541 break;
543 blkt_link->blktoffset = blkt_offset - 4;
544 blkt_link->next_blkt = next_blkt;
547 else if ( blkt_type == 2000 )
548 { /* Found a Blockette 2000 */
549 struct blkt_2000_s *blkt_2000;
550 uint16_t b2klen;
552 /* Read the blockette length from blockette */
553 memcpy (&b2klen, record + blkt_offset, 2);
554 if ( headerswapflag ) ms_gswap2 (&b2klen);
556 /* Minus four bytes for the blockette type and next fields */
557 b2klen -= 4;
559 blkt_link = msr_addblockette (msr, record + blkt_offset,
560 b2klen, blkt_type, 0);
561 if ( ! blkt_link )
562 break;
564 blkt_link->blktoffset = blkt_offset - 4;
565 blkt_link->next_blkt = next_blkt;
567 blkt_2000 = (struct blkt_2000_s *) blkt_link->blktdata;
569 if ( headerswapflag )
571 ms_gswap2 (&blkt_2000->length);
572 ms_gswap2 (&blkt_2000->data_offset);
573 ms_gswap4 (&blkt_2000->recnum);
577 else
578 { /* Unknown blockette type */
579 if ( blkt_length >= 4 )
581 blkt_link = msr_addblockette (msr, record + blkt_offset,
582 blkt_length - 4,
583 blkt_type, 0);
585 if ( ! blkt_link )
586 break;
588 blkt_link->blktoffset = blkt_offset - 4;
589 blkt_link->next_blkt = next_blkt;
593 /* Check that the next blockette offset is beyond the current blockette */
594 if ( next_blkt && next_blkt < (blkt_offset + blkt_length - 4) )
596 ms_log (2, "msr_unpack(%s): Offset to next blockette (%d) is within current blockette ending at byte %d\n",
597 UNPACK_SRCNAME, next_blkt, (blkt_offset + blkt_length - 4));
599 blkt_offset = 0;
601 /* Check that the offset is within record length */
602 else if ( next_blkt && next_blkt > reclen )
604 ms_log (2, "msr_unpack(%s): Offset to next blockette (%d) from type %d is beyond record length\n",
605 UNPACK_SRCNAME, next_blkt, blkt_type);
607 blkt_offset = 0;
609 else
611 blkt_offset = next_blkt;
614 blkt_count++;
615 } /* End of while looping through blockettes */
617 /* Check for a Blockette 1000 */
618 if ( msr->Blkt1000 == 0 )
620 if ( verbose > 1 )
622 ms_log (1, "%s: Warning: No Blockette 1000 found\n", UNPACK_SRCNAME);
626 /* Check that the data offset is after the blockette chain */
627 if ( blkt_link && msr->fsdh->numsamples && msr->fsdh->data_offset < (blkt_link->blktoffset + blkt_link->blktdatalen + 4) )
629 ms_log (1, "%s: Warning: Data offset in fixed header (%d) is within the blockette chain ending at %d\n",
630 UNPACK_SRCNAME, msr->fsdh->data_offset, (blkt_link->blktoffset + blkt_link->blktdatalen + 4));
633 /* Check that the blockette count matches the number parsed */
634 if ( msr->fsdh->numblockettes != blkt_count )
636 ms_log (1, "%s: Warning: Number of blockettes in fixed header (%d) does not match the number parsed (%d)\n",
637 UNPACK_SRCNAME, msr->fsdh->numblockettes, blkt_count);
640 /* Populate remaining common header fields */
641 msr->starttime = msr_starttime (msr);
642 msr->samprate = msr_samprate (msr);
644 /* Set MSRecord->byteorder if data byte order is forced */
645 if ( unpackdatabyteorder >= 0 )
647 msr->byteorder = unpackdatabyteorder;
650 /* Check if encoding format is forced */
651 if ( unpackencodingformat >= 0 )
653 msr->encoding = unpackencodingformat;
656 /* Use encoding format fallback if defined and no encoding is set,
657 * also make sure the byteorder is set by default to big endian */
658 if ( unpackencodingfallback >= 0 && msr->encoding == -1 )
660 msr->encoding = unpackencodingfallback;
662 if ( msr->byteorder == -1 )
664 msr->byteorder = 1;
668 /* Unpack the data samples if requested */
669 if ( dataflag && msr->samplecnt > 0 )
671 flag dswapflag = headerswapflag;
672 flag bigendianhost = ms_bigendianhost();
674 /* Determine byte order of the data and set the dswapflag as
675 needed; if no Blkt1000 or UNPACK_DATA_BYTEORDER environment
676 variable setting assume the order is the same as the header */
677 if ( msr->Blkt1000 != 0 && unpackdatabyteorder < 0 )
679 dswapflag = 0;
681 /* If BE host and LE data need swapping */
682 if ( bigendianhost && msr->byteorder == 0 )
683 dswapflag = 1;
684 /* If LE host and BE data (or bad byte order value) need swapping */
685 else if ( !bigendianhost && msr->byteorder > 0 )
686 dswapflag = 1;
688 else if ( unpackdatabyteorder >= 0 )
690 dswapflag = dataswapflag;
693 if ( verbose > 2 && dswapflag )
694 ms_log (1, "%s: Byte swapping needed for unpacking of data samples\n",
695 UNPACK_SRCNAME);
696 else if ( verbose > 2 )
697 ms_log (1, "%s: Byte swapping NOT needed for unpacking of data samples \n",
698 UNPACK_SRCNAME);
700 retval = msr_unpack_data (msr, dswapflag, verbose);
702 if ( retval < 0 )
703 return retval;
704 else
705 msr->numsamples = retval;
707 else
709 if ( msr->datasamples )
710 free (msr->datasamples);
712 msr->datasamples = 0;
713 msr->numsamples = 0;
716 /* Unset shared pointer to source name */
717 UNPACK_SRCNAME = NULL;
719 return MS_NOERROR;
720 } /* End of msr_unpack() */
723 /************************************************************************
724 * msr_unpack_data:
726 * Unpack Mini-SEED data samples for a given MSRecord. The packed
727 * data is accessed in the record indicated by MSRecord->record and
728 * the unpacked samples are placed in MSRecord->datasamples. The
729 * resulting data samples are either 32-bit integers, 32-bit floats
730 * or 64-bit floats in host byte order.
732 * Return number of samples unpacked or negative libmseed error code.
733 ************************************************************************/
735 msr_unpack_data ( MSRecord *msr, int swapflag, flag verbose )
737 int datasize; /* byte size of data samples in record */
738 int nsamples; /* number of samples unpacked */
739 int unpacksize; /* byte size of unpacked samples */
740 int samplesize = 0; /* size of the data samples in bytes */
741 const char *dbuf;
742 int32_t *diffbuff;
743 int32_t x0, xn;
745 /* Sanity record length */
746 if ( msr->reclen == -1 )
748 ms_log (2, "msr_unpack_data(%s): Record size unknown\n",
749 UNPACK_SRCNAME);
750 return MS_NOTSEED;
752 else if ( msr->reclen < MINRECLEN || msr->reclen > MAXRECLEN )
754 ms_log (2, "msr_unpack_data(%s): Unsupported record length: %d\n",
755 UNPACK_SRCNAME, msr->reclen);
756 return MS_OUTOFRANGE;
759 /* Sanity check data offset before creating a pointer based on the value */
760 if ( msr->fsdh->data_offset < 48 || msr->fsdh->data_offset >= msr->reclen )
762 ms_log (2, "msr_unpack_data(%s): data offset value is not valid: %d\n",
763 UNPACK_SRCNAME, msr->fsdh->data_offset);
764 return MS_GENERROR;
767 datasize = msr->reclen - msr->fsdh->data_offset;
768 dbuf = msr->record + msr->fsdh->data_offset;
770 switch (msr->encoding)
772 case DE_ASCII:
773 samplesize = 1; break;
774 case DE_INT16:
775 case DE_INT32:
776 case DE_FLOAT32:
777 case DE_STEIM1:
778 case DE_STEIM2:
779 case DE_GEOSCOPE24:
780 case DE_GEOSCOPE163:
781 case DE_GEOSCOPE164:
782 case DE_CDSN:
783 case DE_SRO:
784 case DE_DWWSSN:
785 samplesize = 4; break;
786 case DE_FLOAT64:
787 samplesize = 8; break;
788 default:
789 samplesize = 0; break;
792 /* Calculate buffer size needed for unpacked samples */
793 unpacksize = (int) msr->samplecnt * samplesize;
795 /* (Re)Allocate space for the unpacked data */
796 if ( unpacksize > 0 )
798 msr->datasamples = realloc (msr->datasamples, unpacksize);
800 if ( msr->datasamples == NULL )
802 ms_log (2, "msr_unpack_data(%s): Cannot (re)allocate memory\n",
803 UNPACK_SRCNAME);
804 return MS_GENERROR;
807 else
809 if ( msr->datasamples )
810 free (msr->datasamples);
811 msr->datasamples = 0;
812 msr->numsamples = 0;
815 if ( verbose > 2 )
816 ms_log (1, "%s: Unpacking %"PRId64" samples\n",
817 UNPACK_SRCNAME, msr->samplecnt);
819 /* Decide if this is a encoding that we can decode */
820 switch (msr->encoding)
823 case DE_ASCII:
824 if ( verbose > 1 )
825 ms_log (1, "%s: Found ASCII data\n", UNPACK_SRCNAME);
827 nsamples = (int)msr->samplecnt;
828 memcpy (msr->datasamples, dbuf, nsamples);
829 msr->sampletype = 'a';
830 break;
832 case DE_INT16:
833 if ( verbose > 1 )
834 ms_log (1, "%s: Unpacking INT-16 data samples\n", UNPACK_SRCNAME);
836 nsamples = msr_unpack_int_16 ((int16_t *)dbuf, (int)msr->samplecnt,
837 (int)msr->samplecnt, msr->datasamples,
838 swapflag);
839 msr->sampletype = 'i';
840 break;
842 case DE_INT32:
843 if ( verbose > 1 )
844 ms_log (1, "%s: Unpacking INT-32 data samples\n", UNPACK_SRCNAME);
846 nsamples = msr_unpack_int_32 ((int32_t *)dbuf, (int)msr->samplecnt,
847 (int)msr->samplecnt, msr->datasamples,
848 swapflag);
849 msr->sampletype = 'i';
850 break;
852 case DE_FLOAT32:
853 if ( verbose > 1 )
854 ms_log (1, "%s: Unpacking FLOAT-32 data samples\n", UNPACK_SRCNAME);
856 nsamples = msr_unpack_float_32 ((float *)dbuf, (int)msr->samplecnt,
857 (int)msr->samplecnt, msr->datasamples,
858 swapflag);
859 msr->sampletype = 'f';
860 break;
862 case DE_FLOAT64:
863 if ( verbose > 1 )
864 ms_log (1, "%s: Unpacking FLOAT-64 data samples\n", UNPACK_SRCNAME);
866 nsamples = msr_unpack_float_64 ((double *)dbuf, (int)msr->samplecnt,
867 (int)msr->samplecnt, msr->datasamples,
868 swapflag);
869 msr->sampletype = 'd';
870 break;
872 case DE_STEIM1:
873 diffbuff = (int32_t *) malloc(unpacksize);
874 if ( diffbuff == NULL )
876 ms_log (2, "msr_unpack_data(%s): Cannot allocate diff buffer\n",
877 UNPACK_SRCNAME);
878 return MS_GENERROR;
881 if ( verbose > 1 )
882 ms_log (1, "%s: Unpacking Steim-1 data frames\n", UNPACK_SRCNAME);
884 nsamples = msr_unpack_steim1 ((FRAME *)dbuf, datasize, (int)msr->samplecnt,
885 (int)msr->samplecnt, msr->datasamples, diffbuff,
886 &x0, &xn, swapflag, verbose);
887 msr->sampletype = 'i';
888 free (diffbuff);
889 break;
891 case DE_STEIM2:
892 diffbuff = (int32_t *) malloc(unpacksize);
893 if ( diffbuff == NULL )
895 ms_log (2, "msr_unpack_data(%s): Cannot allocate diff buffer\n",
896 UNPACK_SRCNAME);
897 return MS_GENERROR;
900 if ( verbose > 1 )
901 ms_log (1, "%s: Unpacking Steim-2 data frames\n", UNPACK_SRCNAME);
903 nsamples = msr_unpack_steim2 ((FRAME *)dbuf, datasize, (int)msr->samplecnt,
904 (int)msr->samplecnt, msr->datasamples, diffbuff,
905 &x0, &xn, swapflag, verbose);
906 msr->sampletype = 'i';
907 free (diffbuff);
908 break;
910 case DE_GEOSCOPE24:
911 case DE_GEOSCOPE163:
912 case DE_GEOSCOPE164:
913 if ( verbose > 1 )
915 if ( msr->encoding == DE_GEOSCOPE24 )
916 ms_log (1, "%s: Unpacking GEOSCOPE 24bit integer data samples\n",
917 UNPACK_SRCNAME);
918 if ( msr->encoding == DE_GEOSCOPE163 )
919 ms_log (1, "%s: Unpacking GEOSCOPE 16bit gain ranged/3bit exponent data samples\n",
920 UNPACK_SRCNAME);
921 if ( msr->encoding == DE_GEOSCOPE164 )
922 ms_log (1, "%s: Unpacking GEOSCOPE 16bit gain ranged/4bit exponent data samples\n",
923 UNPACK_SRCNAME);
926 nsamples = msr_unpack_geoscope (dbuf, (int)msr->samplecnt, (int)msr->samplecnt,
927 msr->datasamples, msr->encoding, swapflag);
928 msr->sampletype = 'f';
929 break;
931 case DE_CDSN:
932 if ( verbose > 1 )
933 ms_log (1, "%s: Unpacking CDSN encoded data samples\n", UNPACK_SRCNAME);
935 nsamples = msr_unpack_cdsn ((int16_t *)dbuf, (int)msr->samplecnt, (int)msr->samplecnt,
936 msr->datasamples, swapflag);
937 msr->sampletype = 'i';
938 break;
940 case DE_SRO:
941 if ( verbose > 1 )
942 ms_log (1, "%s: Unpacking SRO encoded data samples\n", UNPACK_SRCNAME);
944 nsamples = msr_unpack_sro ((int16_t *)dbuf, (int)msr->samplecnt, (int)msr->samplecnt,
945 msr->datasamples, swapflag);
946 msr->sampletype = 'i';
947 break;
949 case DE_DWWSSN:
950 if ( verbose > 1 )
951 ms_log (1, "%s: Unpacking DWWSSN encoded data samples\n", UNPACK_SRCNAME);
953 nsamples = msr_unpack_dwwssn ((int16_t *)dbuf, (int)msr->samplecnt, (int)msr->samplecnt,
954 msr->datasamples, swapflag);
955 msr->sampletype = 'i';
956 break;
958 default:
959 ms_log (2, "%s: Unsupported encoding format %d (%s)\n",
960 UNPACK_SRCNAME, msr->encoding, (char *) ms_encodingstr(msr->encoding));
962 return MS_UNKNOWNFORMAT;
965 return nsamples;
966 } /* End of msr_unpack_data() */
969 /************************************************************************
970 * check_environment:
972 * Check environment variables and set global variables appropriately.
974 * Return 0 on success and -1 on error.
975 ************************************************************************/
976 static int
977 check_environment (int verbose)
979 char *envvariable;
981 /* Read possible environmental variables that force byteorder */
982 if ( unpackheaderbyteorder == -2 )
984 if ( (envvariable = getenv("UNPACK_HEADER_BYTEORDER")) )
986 if ( *envvariable != '0' && *envvariable != '1' )
988 ms_log (2, "Environment variable UNPACK_HEADER_BYTEORDER must be set to '0' or '1'\n");
989 return -1;
991 else if ( *envvariable == '0' )
993 unpackheaderbyteorder = 0;
994 if ( verbose > 2 )
995 ms_log (1, "UNPACK_HEADER_BYTEORDER=0, unpacking little-endian header\n");
997 else
999 unpackheaderbyteorder = 1;
1000 if ( verbose > 2 )
1001 ms_log (1, "UNPACK_HEADER_BYTEORDER=1, unpacking big-endian header\n");
1004 else
1006 unpackheaderbyteorder = -1;
1010 if ( unpackdatabyteorder == -2 )
1012 if ( (envvariable = getenv("UNPACK_DATA_BYTEORDER")) )
1014 if ( *envvariable != '0' && *envvariable != '1' )
1016 ms_log (2, "Environment variable UNPACK_DATA_BYTEORDER must be set to '0' or '1'\n");
1017 return -1;
1019 else if ( *envvariable == '0' )
1021 unpackdatabyteorder = 0;
1022 if ( verbose > 2 )
1023 ms_log (1, "UNPACK_DATA_BYTEORDER=0, unpacking little-endian data samples\n");
1025 else
1027 unpackdatabyteorder = 1;
1028 if ( verbose > 2 )
1029 ms_log (1, "UNPACK_DATA_BYTEORDER=1, unpacking big-endian data samples\n");
1032 else
1034 unpackdatabyteorder = -1;
1038 /* Read possible environmental variable that forces encoding format */
1039 if ( unpackencodingformat == -2 )
1041 if ( (envvariable = getenv("UNPACK_DATA_FORMAT")) )
1043 unpackencodingformat = (int) strtol (envvariable, NULL, 10);
1045 if ( unpackencodingformat < 0 || unpackencodingformat > 33 )
1047 ms_log (2, "Environment variable UNPACK_DATA_FORMAT set to invalid value: '%d'\n", unpackencodingformat);
1048 return -1;
1050 else if ( verbose > 2 )
1051 ms_log (1, "UNPACK_DATA_FORMAT, unpacking data in encoding format %d\n", unpackencodingformat);
1053 else
1055 unpackencodingformat = -1;
1059 /* Read possible environmental variable to be used as a fallback encoding format */
1060 if ( unpackencodingfallback == -2 )
1062 if ( (envvariable = getenv("UNPACK_DATA_FORMAT_FALLBACK")) )
1064 unpackencodingfallback = (int) strtol (envvariable, NULL, 10);
1066 if ( unpackencodingfallback < 0 || unpackencodingfallback > 33 )
1068 ms_log (2, "Environment variable UNPACK_DATA_FORMAT_FALLBACK set to invalid value: '%d'\n",
1069 unpackencodingfallback);
1070 return -1;
1072 else if ( verbose > 2 )
1073 ms_log (1, "UNPACK_DATA_FORMAT_FALLBACK, fallback data unpacking encoding format %d\n",
1074 unpackencodingfallback);
1076 else
1078 unpackencodingfallback = 10; /* Default fallback is Steim-1 encoding */
1082 return 0;
1083 } /* End of check_environment() */