1 /***************************************************************************
2  * libmseed.h:
3  *
4  * Interface declarations for the Mini-SEED library (libmseed).
5  *
6  * This library is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as
8  * published by the Free Software Foundation; either version 3 of the
9  * License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful, but
12  * WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License (GNU-LGPL) for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this software.
18  * If not, see <https://www.gnu.org/licenses/>.
19  *
20  * Copyright (C) 2017 Chad Trabant
21  * IRIS Data Management Center
22  ***************************************************************************/
23 
24 #ifndef LIBMSEED_H
25 #define LIBMSEED_H 1
26 
27 #ifdef __cplusplus
28 extern "C" {
29 #endif
30 
31 #define LIBMSEED_VERSION "2.19.5"
32 #define LIBMSEED_RELEASE "2017.283"
33 
34 /* C99 standard headers */
35 #include <stdlib.h>
36 #include <stdio.h>
37 #include <stdarg.h>
38 #include <time.h>
39 #include <string.h>
40 #include <ctype.h>
41 
42 /* This library uses structs that map to SEED header/blockette
43    structures that are required to have a layout exactly as specified,
44    i.e. no padding.
45 
46    If "ATTRIBUTE_PACKED" is defined at compile time (e.g. -DATTRIBUTE_PACKED)
47    the preprocessor will use the define below to add the "packed" attribute
48    to effected structs.  This attribute is supported by GCC and increasingly
49    more compilers.
50   */
51 #if defined(ATTRIBUTE_PACKED)
52   #define LMP_PACKED __attribute__((packed))
53 #else
54   #define LMP_PACKED
55 #endif
56 
57 /* Set platform specific defines */
58 #if defined(__linux__) || defined(__linux) || defined(__CYGWIN__)
59   #define LMP_LINUX 1
60   #define LMP_GLIBC2 1 /* Deprecated */
61 #elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
62   #define LMP_BSD 1
63 #elif defined(__sun__) || defined(__sun)
64   #define LMP_SOLARIS 1
65 #elif defined(WIN32) || defined(_WIN32) || defined(WIN64) || defined(_WIN64)
66   #define LMP_WIN 1
67   #define LMP_WIN32 1 /* Deprecated */
68 #endif
69 
70 /* Set platform specific features */
71 #if defined(LMP_LINUX) || defined(LMP_BSD) || defined(LMP_SOLARIS)
72   #include <unistd.h>
73   #include <inttypes.h>
74 #elif defined(LMP_WIN)
75   #include <windows.h>
76   #include <sys/types.h>
77 
78   /* For MSVC 2012 and earlier define standard int types, otherwise use inttypes.h */
79   #if defined(_MSC_VER) && _MSC_VER <= 1700
80     typedef signed char int8_t;
81     typedef unsigned char uint8_t;
82     typedef signed short int int16_t;
83     typedef unsigned short int uint16_t;
84     typedef signed int int32_t;
85     typedef unsigned int uint32_t;
86     typedef signed __int64 int64_t;
87     typedef unsigned __int64 uint64_t;
88   #else
89     #include <inttypes.h>
90   #endif
91 
92   /* For MSVC define PRId64 and SCNd64 if needed */
93   #if defined(_MSC_VER)
94     #if !defined(PRId64)
95       #define PRId64 "I64d"
96     #endif
97     #if !defined(SCNd64)
98       #define SCNd64 "I64d"
99     #endif
100 
101     #define snprintf _snprintf
102     #define vsnprintf _vsnprintf
103     #define strcasecmp _stricmp
104     #define strncasecmp _strnicmp
105     #define strtoull _strtoui64
106     #define strdup _strdup
107     #define fileno _fileno
108   #endif
109 
110   /* Extras needed for MinGW */
111   #if defined(__MINGW32__) || defined(__MINGW64__)
112     #include <fcntl.h>
113 
114     #define fstat _fstat
115     #define stat _stat
116   #endif
117 #else
118   #include <inttypes.h>
119 #endif
120 
121 extern int LM_SIZEOF_OFF_T;  /* Size of off_t data type determined at build time */
122 
123 #define MINRECLEN   128      /* Minimum Mini-SEED record length, 2^7 bytes */
124                              /* Note: the SEED specification minimum is 256 */
125 #define MAXRECLEN   1048576  /* Maximum Mini-SEED record length, 2^20 bytes */
126 
127 /* SEED data encoding types */
128 #define DE_ASCII       0
129 #define DE_INT16       1
130 #define DE_INT32       3
131 #define DE_FLOAT32     4
132 #define DE_FLOAT64     5
133 #define DE_STEIM1      10
134 #define DE_STEIM2      11
135 #define DE_GEOSCOPE24  12
136 #define DE_GEOSCOPE163 13
137 #define DE_GEOSCOPE164 14
138 #define DE_CDSN        16
139 #define DE_SRO         30
140 #define DE_DWWSSN      32
141 
142 /* Library return and error code values, error values should always be negative */
143 #define MS_ENDOFFILE        1        /* End of file reached return value */
144 #define MS_NOERROR          0        /* No error */
145 #define MS_GENERROR        -1        /* Generic unspecified error */
146 #define MS_NOTSEED         -2        /* Data not SEED */
147 #define MS_WRONGLENGTH     -3        /* Length of data read was not correct */
148 #define MS_OUTOFRANGE      -4        /* SEED record length out of range */
149 #define MS_UNKNOWNFORMAT   -5        /* Unknown data encoding format */
150 #define MS_STBADCOMPFLAG   -6        /* Steim, invalid compression flag(s) */
151 
152 /* Define the high precision time tick interval as 1/modulus seconds */
153 /* Default modulus of 1000000 defines tick interval as a microsecond */
154 #define HPTMODULUS 1000000
155 
156 /* Error code for routines that normally return a high precision time.
157  * The time value corresponds to '1902/1/1 00:00:00.000000' with the
158  * default HPTMODULUS */
159 #define HPTERROR -2145916800000000LL
160 
161 /* Macros to scale between Unix/POSIX epoch time & high precision time */
162 #define MS_EPOCH2HPTIME(X) X * (hptime_t) HPTMODULUS
163 #define MS_HPTIME2EPOCH(X) X / HPTMODULUS
164 
165 /* Macro to test a character for data record indicators */
166 #define MS_ISDATAINDICATOR(X) (X=='D' || X=='R' || X=='Q' || X=='M')
167 
168 /* Macro to test default sample rate tolerance: abs(1-sr1/sr2) < 0.0001 */
169 #define MS_ISRATETOLERABLE(A,B) (ms_dabs (1.0 - (A / B)) < 0.0001)
170 
171 /* Macro to test for sane year and day values, used primarily to
172  * determine if byte order swapping is needed.
173  *
174  * Year : between 1900 and 2100
175  * Day  : between 1 and 366
176  *
177  * This test is non-unique (non-deterministic) for days 1, 256 and 257
178  * in the year 2056 because the swapped values are also within range.
179  */
180 #define MS_ISVALIDYEARDAY(Y,D) (Y >= 1900 && Y <= 2100 && D >= 1 && D <= 366)
181 
182 /* Macro to test memory for a SEED data record signature by checking
183  * SEED data record header values at known byte offsets to determine
184  * if the memory contains a valid record.
185  *
186  * Offset = Value
187  * [0-5]  = Digits, spaces or NULL, SEED sequence number
188  *     6  = Data record quality indicator
189  *     7  = Space or NULL [not valid SEED]
190  *     24 = Start hour (0-23)
191  *     25 = Start minute (0-59)
192  *     26 = Start second (0-60)
193  *
194  * Usage:
195  *   MS_ISVALIDHEADER ((char *)X)  X buffer must contain at least 27 bytes
196  */
197 #define MS_ISVALIDHEADER(X) (                               \
198   (isdigit ((int) *(X))   || *(X)   == ' ' || !*(X) )   &&  \
199   (isdigit ((int) *(X+1)) || *(X+1) == ' ' || !*(X+1) ) &&  \
200   (isdigit ((int) *(X+2)) || *(X+2) == ' ' || !*(X+2) ) &&  \
201   (isdigit ((int) *(X+3)) || *(X+3) == ' ' || !*(X+3) ) &&  \
202   (isdigit ((int) *(X+4)) || *(X+4) == ' ' || !*(X+4) ) &&  \
203   (isdigit ((int) *(X+5)) || *(X+5) == ' ' || !*(X+5) ) &&  \
204   MS_ISDATAINDICATOR(*(X+6)) &&                             \
205   (*(X+7) == ' ' || *(X+7) == '\0') &&                      \
206   (int)(*(X+24)) >= 0 && (int)(*(X+24)) <= 23 &&            \
207   (int)(*(X+25)) >= 0 && (int)(*(X+25)) <= 59 &&            \
208   (int)(*(X+26)) >= 0 && (int)(*(X+26)) <= 60 )
209 
210 /* Macro to test memory for a blank/noise SEED data record signature
211  * by checking for a valid SEED sequence number and padding characters
212  * to determine if the memory contains a valid blank/noise record.
213  *
214  * Offset = Value
215  * [0-5]  = Digits or NULL, SEED sequence number
216  * [6-47] = Space character (ASCII 32), remainder of fixed header
217  *
218  * Usage:
219  *   MS_ISVALIDBLANK ((char *)X)  X buffer must contain at least 27 bytes
220  */
221 #define MS_ISVALIDBLANK(X) (                             \
222   (isdigit ((int) *(X))   || !*(X) ) &&                  \
223   (isdigit ((int) *(X+1)) || !*(X+1) ) &&                \
224   (isdigit ((int) *(X+2)) || !*(X+2) ) &&                \
225   (isdigit ((int) *(X+3)) || !*(X+3) ) &&                \
226   (isdigit ((int) *(X+4)) || !*(X+4) ) &&                \
227   (isdigit ((int) *(X+5)) || !*(X+5) ) &&                \
228   (*(X+6) ==' ') && (*(X+7) ==' ') && (*(X+8) ==' ') &&  \
229   (*(X+9) ==' ') && (*(X+10)==' ') && (*(X+11)==' ') &&  \
230   (*(X+12)==' ') && (*(X+13)==' ') && (*(X+14)==' ') &&  \
231   (*(X+15)==' ') && (*(X+16)==' ') && (*(X+17)==' ') &&  \
232   (*(X+18)==' ') && (*(X+19)==' ') && (*(X+20)==' ') &&  \
233   (*(X+21)==' ') && (*(X+22)==' ') && (*(X+23)==' ') &&  \
234   (*(X+24)==' ') && (*(X+25)==' ') && (*(X+26)==' ') &&  \
235   (*(X+27)==' ') && (*(X+28)==' ') && (*(X+29)==' ') &&  \
236   (*(X+30)==' ') && (*(X+31)==' ') && (*(X+32)==' ') &&  \
237   (*(X+33)==' ') && (*(X+34)==' ') && (*(X+35)==' ') &&  \
238   (*(X+36)==' ') && (*(X+37)==' ') && (*(X+38)==' ') &&  \
239   (*(X+39)==' ') && (*(X+40)==' ') && (*(X+41)==' ') &&  \
240   (*(X+42)==' ') && (*(X+43)==' ') && (*(X+44)==' ') &&  \
241   (*(X+45)==' ') && (*(X+46)==' ') && (*(X+47)==' ') )
242 
243 /* A simple bitwise AND test to return 0 or 1 */
244 #define bit(x,y) (x&y)?1:0
245 
246 /* Require a large (>= 64-bit) integer type for hptime_t */
247 typedef int64_t hptime_t;
248 
249 /* A single byte flag type */
250 typedef int8_t flag;
251 
252 /* SEED binary time */
253 typedef struct btime_s
254 {
255   uint16_t  year;
256   uint16_t  day;
257   uint8_t   hour;
258   uint8_t   min;
259   uint8_t   sec;
260   uint8_t   unused;
261   uint16_t  fract;
262 } LMP_PACKED
263 BTime;
264 
265 /* Fixed section data of header */
266 struct fsdh_s
267 {
268   char      sequence_number[6];
269   char      dataquality;
270   char      reserved;
271   char      station[5];
272   char      location[2];
273   char      channel[3];
274   char      network[2];
275   BTime     start_time;
276   uint16_t  numsamples;
277   int16_t   samprate_fact;
278   int16_t   samprate_mult;
279   uint8_t   act_flags;
280   uint8_t   io_flags;
281   uint8_t   dq_flags;
282   uint8_t   numblockettes;
283   int32_t   time_correct;
284   uint16_t  data_offset;
285   uint16_t  blockette_offset;
286 } LMP_PACKED;
287 
288 /* Blockette 100, Sample Rate (without header) */
289 struct blkt_100_s
290 {
291   float     samprate;
292   int8_t    flags;
293   uint8_t   reserved[3];
294 } LMP_PACKED;
295 
296 /* Blockette 200, Generic Event Detection (without header) */
297 struct blkt_200_s
298 {
299   float     amplitude;
300   float     period;
301   float     background_estimate;
302   uint8_t   flags;
303   uint8_t   reserved;
304   BTime     time;
305   char      detector[24];
306 } LMP_PACKED;
307 
308 /* Blockette 201, Murdock Event Detection (without header) */
309 struct blkt_201_s
310 {
311   float     amplitude;
312   float     period;
313   float     background_estimate;
314   uint8_t   flags;
315   uint8_t   reserved;
316   BTime     time;
317   uint8_t   snr_values[6];
318   uint8_t   loopback;
319   uint8_t   pick_algorithm;
320   char      detector[24];
321 } LMP_PACKED;
322 
323 /* Blockette 300, Step Calibration (without header) */
324 struct blkt_300_s
325 {
326   BTime     time;
327   uint8_t   numcalibrations;
328   uint8_t   flags;
329   uint32_t  step_duration;
330   uint32_t  interval_duration;
331   float     amplitude;
332   char      input_channel[3];
333   uint8_t   reserved;
334   uint32_t  reference_amplitude;
335   char      coupling[12];
336   char      rolloff[12];
337 } LMP_PACKED;
338 
339 /* Blockette 310, Sine Calibration (without header) */
340 struct blkt_310_s
341 {
342   BTime     time;
343   uint8_t   reserved1;
344   uint8_t   flags;
345   uint32_t  duration;
346   float     period;
347   float     amplitude;
348   char      input_channel[3];
349   uint8_t   reserved2;
350   uint32_t  reference_amplitude;
351   char      coupling[12];
352   char      rolloff[12];
353 } LMP_PACKED;
354 
355 /* Blockette 320, Pseudo-random Calibration (without header) */
356 struct blkt_320_s
357 {
358   BTime     time;
359   uint8_t   reserved1;
360   uint8_t   flags;
361   uint32_t  duration;
362   float     ptp_amplitude;
363   char      input_channel[3];
364   uint8_t   reserved2;
365   uint32_t  reference_amplitude;
366   char      coupling[12];
367   char      rolloff[12];
368   char      noise_type[8];
369 } LMP_PACKED;
370 
371 /* Blockette 390, Generic Calibration (without header) */
372 struct blkt_390_s
373 {
374   BTime     time;
375   uint8_t   reserved1;
376   uint8_t   flags;
377   uint32_t  duration;
378   float     amplitude;
379   char      input_channel[3];
380   uint8_t   reserved2;
381 } LMP_PACKED;
382 
383 /* Blockette 395, Calibration Abort (without header) */
384 struct blkt_395_s
385 {
386   BTime     time;
387   uint8_t   reserved[2];
388 } LMP_PACKED;
389 
390 /* Blockette 400, Beam (without header) */
391 struct blkt_400_s
392 {
393   float     azimuth;
394   float     slowness;
395   uint16_t  configuration;
396   uint8_t   reserved[2];
397 } LMP_PACKED;
398 
399 /* Blockette 405, Beam Delay (without header) */
400 struct blkt_405_s
401 {
402   uint16_t  delay_values[1];
403 };
404 
405 /* Blockette 500, Timing (without header) */
406 struct blkt_500_s
407 {
408   float     vco_correction;
409   BTime     time;
410   int8_t    usec;
411   uint8_t   reception_qual;
412   uint32_t  exception_count;
413   char      exception_type[16];
414   char      clock_model[32];
415   char      clock_status[128];
416 } LMP_PACKED;
417 
418 /* Blockette 1000, Data Only SEED (without header) */
419 struct blkt_1000_s
420 {
421   uint8_t   encoding;
422   uint8_t   byteorder;
423   uint8_t   reclen;
424   uint8_t   reserved;
425 } LMP_PACKED;
426 
427 /* Blockette 1001, Data Extension (without header) */
428 struct blkt_1001_s
429 {
430   uint8_t   timing_qual;
431   int8_t    usec;
432   uint8_t   reserved;
433   uint8_t   framecnt;
434 } LMP_PACKED;
435 
436 /* Blockette 2000, Opaque Data (without header) */
437 struct blkt_2000_s
438 {
439   uint16_t  length;
440   uint16_t  data_offset;
441   uint32_t  recnum;
442   uint8_t   byteorder;
443   uint8_t   flags;
444   uint8_t   numheaders;
445   char      payload[1];
446 } LMP_PACKED;
447 
448 /* Blockette chain link, generic linkable blockette index */
449 typedef struct blkt_link_s
450 {
451   uint16_t            blktoffset;    /* Offset to this blockette */
452   uint16_t            blkt_type;     /* Blockette type */
453   uint16_t            next_blkt;     /* Offset to next blockette */
454   void               *blktdata;      /* Blockette data */
455   uint16_t            blktdatalen;   /* Length of blockette data in bytes */
456   struct blkt_link_s *next;
457 }
458 BlktLink;
459 
460 typedef struct StreamState_s
461 {
462   int64_t   packedrecords;           /* Count of packed records */
463   int64_t   packedsamples;           /* Count of packed samples */
464   int32_t   lastintsample;           /* Value of last integer sample packed */
465   flag      comphistory;             /* Control use of lastintsample for compression history */
466 }
467 StreamState;
468 
469 typedef struct MSRecord_s {
470   char           *record;            /* Mini-SEED record */
471   int32_t         reclen;            /* Length of Mini-SEED record in bytes */
472 
473   /* Pointers to SEED data record structures */
474   struct fsdh_s      *fsdh;          /* Fixed Section of Data Header */
475   BlktLink           *blkts;         /* Root of blockette chain */
476   struct blkt_100_s  *Blkt100;       /* Blockette 100, if present */
477   struct blkt_1000_s *Blkt1000;      /* Blockette 1000, if present */
478   struct blkt_1001_s *Blkt1001;      /* Blockette 1001, if present */
479 
480   /* Common header fields in accessible form */
481   int32_t         sequence_number;   /* SEED record sequence number */
482   char            network[11];       /* Network designation, NULL terminated */
483   char            station[11];       /* Station designation, NULL terminated */
484   char            location[11];      /* Location designation, NULL terminated */
485   char            channel[11];       /* Channel designation, NULL terminated */
486   char            dataquality;       /* Data quality indicator */
487   hptime_t        starttime;         /* Record start time, corrected (first sample) */
488   double          samprate;          /* Nominal sample rate (Hz) */
489   int64_t         samplecnt;         /* Number of samples in record */
490   int8_t          encoding;          /* Data encoding format */
491   int8_t          byteorder;         /* Original/Final byte order of record */
492 
493   /* Data sample fields */
494   void           *datasamples;       /* Data samples, 'numsamples' of type 'sampletype'*/
495   int64_t         numsamples;        /* Number of data samples in datasamples */
496   char            sampletype;        /* Sample type code: a, i, f, d */
497 
498   /* Stream oriented state information */
499   StreamState    *ststate;           /* Stream processing state information */
500 }
501 MSRecord;
502 
503 /* Container for a continuous trace, linkable */
504 typedef struct MSTrace_s {
505   char            network[11];       /* Network designation, NULL terminated */
506   char            station[11];       /* Station designation, NULL terminated */
507   char            location[11];      /* Location designation, NULL terminated */
508   char            channel[11];       /* Channel designation, NULL terminated */
509   char            dataquality;       /* Data quality indicator */
510   char            type;              /* MSTrace type code */
511   hptime_t        starttime;         /* Time of first sample */
512   hptime_t        endtime;           /* Time of last sample */
513   double          samprate;          /* Nominal sample rate (Hz) */
514   int64_t         samplecnt;         /* Number of samples in trace coverage */
515   void           *datasamples;       /* Data samples, 'numsamples' of type 'sampletype' */
516   int64_t         numsamples;        /* Number of data samples in datasamples */
517   char            sampletype;        /* Sample type code: a, i, f, d */
518   void           *prvtptr;           /* Private pointer for general use, unused by libmseed */
519   StreamState    *ststate;           /* Stream processing state information */
520   struct MSTrace_s *next;            /* Pointer to next trace */
521 }
522 MSTrace;
523 
524 /* Container for a group (chain) of traces */
525 typedef struct MSTraceGroup_s {
526   int32_t           numtraces;       /* Number of MSTraces in the trace chain */
527   struct MSTrace_s *traces;          /* Root of the trace chain */
528 }
529 MSTraceGroup;
530 
531 /* Container for a continuous trace segment, linkable */
532 typedef struct MSTraceSeg_s {
533   hptime_t        starttime;         /* Time of first sample */
534   hptime_t        endtime;           /* Time of last sample */
535   double          samprate;          /* Nominal sample rate (Hz) */
536   int64_t         samplecnt;         /* Number of samples in trace coverage */
537   void           *datasamples;       /* Data samples, 'numsamples' of type 'sampletype'*/
538   int64_t         numsamples;        /* Number of data samples in datasamples */
539   char            sampletype;        /* Sample type code: a, i, f, d */
540   void           *prvtptr;           /* Private pointer for general use, unused by libmseed */
541   struct MSTraceSeg_s *prev;         /* Pointer to previous segment */
542   struct MSTraceSeg_s *next;         /* Pointer to next segment */
543 }
544 MSTraceSeg;
545 
546 /* Container for a trace ID, linkable */
547 typedef struct MSTraceID_s {
548   char            network[11];       /* Network designation, NULL terminated */
549   char            station[11];       /* Station designation, NULL terminated */
550   char            location[11];      /* Location designation, NULL terminated */
551   char            channel[11];       /* Channel designation, NULL terminated */
552   char            dataquality;       /* Data quality indicator */
553   char            srcname[45];       /* Source name (Net_Sta_Loc_Chan_Qual), NULL terminated */
554   char            type;              /* Trace type code */
555   hptime_t        earliest;          /* Time of earliest sample */
556   hptime_t        latest;            /* Time of latest sample */
557   void           *prvtptr;           /* Private pointer for general use, unused by libmseed */
558   int32_t         numsegments;       /* Number of segments for this ID */
559   struct MSTraceSeg_s *first;        /* Pointer to first of list of segments */
560   struct MSTraceSeg_s *last;         /* Pointer to last of list of segments */
561   struct MSTraceID_s *next;          /* Pointer to next trace */
562 }
563 MSTraceID;
564 
565 /* Container for a continuous trace segment, linkable */
566 typedef struct MSTraceList_s {
567   int32_t             numtraces;     /* Number of traces in list */
568   struct MSTraceID_s *traces;        /* Pointer to list of traces */
569   struct MSTraceID_s *last;          /* Pointer to last used trace in list */
570 }
571 MSTraceList;
572 
573 /* Data selection structure time window definition containers */
574 typedef struct SelectTime_s {
575   hptime_t starttime;    /* Earliest data for matching channels */
576   hptime_t endtime;      /* Latest data for matching channels */
577   struct SelectTime_s *next;
578 } SelectTime;
579 
580 /* Data selection structure definition containers */
581 typedef struct Selections_s {
582   char srcname[100];     /* Matching (globbing) source name: Net_Sta_Loc_Chan_Qual */
583   struct SelectTime_s *timewindows;
584   struct Selections_s *next;
585 } Selections;
586 
587 
588 /* Global variables (defined in pack.c) and macros to set/force
589  * pack byte orders */
590 extern flag packheaderbyteorder;
591 extern flag packdatabyteorder;
592 #define MS_PACKHEADERBYTEORDER(X) (packheaderbyteorder = X);
593 #define MS_PACKDATABYTEORDER(X) (packdatabyteorder = X);
594 
595 /* Global variables (defined in unpack.c) and macros to set/force
596  * unpack byte orders */
597 extern flag unpackheaderbyteorder;
598 extern flag unpackdatabyteorder;
599 #define MS_UNPACKHEADERBYTEORDER(X) (unpackheaderbyteorder = X);
600 #define MS_UNPACKDATABYTEORDER(X) (unpackdatabyteorder = X);
601 
602 /* Global variables (defined in unpack.c) and macros to set/force
603  * encoding and fallback encoding */
604 extern int unpackencodingformat;
605 extern int unpackencodingfallback;
606 #define MS_UNPACKENCODINGFORMAT(X) (unpackencodingformat = X);
607 #define MS_UNPACKENCODINGFALLBACK(X) (unpackencodingfallback = X);
608 
609 /* Mini-SEED record related functions */
610 extern int           msr_parse (char *record, int recbuflen, MSRecord **ppmsr, int reclen,
611 				flag dataflag, flag verbose);
612 
613 extern int           msr_parse_selection ( char *recbuf, int recbuflen, int64_t *offset,
614 					   MSRecord **ppmsr, int reclen,
615 					   Selections *selections, flag dataflag, flag verbose );
616 
617 extern int           msr_unpack (char *record, int reclen, MSRecord **ppmsr,
618 				 flag dataflag, flag verbose);
619 
620 extern int           msr_pack (MSRecord *msr, void (*record_handler) (char *, int, void *),
621 		 	       void *handlerdata, int64_t *packedsamples, flag flush, flag verbose );
622 
623 extern int           msr_pack_header (MSRecord *msr, flag normalize, flag verbose);
624 
625 extern int           msr_unpack_data (MSRecord *msr, int swapflag, flag verbose);
626 
627 extern MSRecord*     msr_init (MSRecord *msr);
628 extern void          msr_free (MSRecord **ppmsr);
629 extern void          msr_free_blktchain (MSRecord *msr);
630 extern BlktLink*     msr_addblockette (MSRecord *msr, char *blktdata, int length,
631 				       int blkttype, int chainpos);
632 extern int           msr_normalize_header (MSRecord *msr, flag verbose);
633 extern MSRecord*     msr_duplicate (MSRecord *msr, flag datadup);
634 extern double        msr_samprate (MSRecord *msr);
635 extern double        msr_nomsamprate (MSRecord *msr);
636 extern hptime_t      msr_starttime (MSRecord *msr);
637 extern hptime_t      msr_starttime_uc (MSRecord *msr);
638 extern hptime_t      msr_endtime (MSRecord *msr);
639 extern char*         msr_srcname (MSRecord *msr, char *srcname, flag quality);
640 extern void          msr_print (MSRecord *msr, flag details);
641 extern double        msr_host_latency (MSRecord *msr);
642 
643 extern int           ms_detect (const char *record, int recbuflen);
644 extern int           ms_parse_raw (char *record, int maxreclen, flag details, flag swapflag);
645 
646 
647 /* MSTrace related functions */
648 extern MSTrace*      mst_init (MSTrace *mst);
649 extern void          mst_free (MSTrace **ppmst);
650 extern MSTraceGroup* mst_initgroup (MSTraceGroup *mstg);
651 extern void          mst_freegroup (MSTraceGroup **ppmstg);
652 extern MSTrace*      mst_findmatch (MSTrace *startmst, char dataquality,
653 				    char *network, char *station, char *location, char *channel);
654 extern MSTrace*      mst_findadjacent (MSTraceGroup *mstg, flag *whence, char dataquality,
655 				       char *network, char *station, char *location, char *channel,
656 				       double samprate, double sampratetol,
657 				       hptime_t starttime, hptime_t endtime, double timetol);
658 extern int           mst_addmsr (MSTrace *mst, MSRecord *msr, flag whence);
659 extern int           mst_addspan (MSTrace *mst, hptime_t starttime,  hptime_t endtime,
660 				  void *datasamples, int64_t numsamples,
661 				  char sampletype, flag whence);
662 extern MSTrace*      mst_addmsrtogroup (MSTraceGroup *mstg, MSRecord *msr, flag dataquality,
663 					double timetol, double sampratetol);
664 extern MSTrace*      mst_addtracetogroup (MSTraceGroup *mstg, MSTrace *mst);
665 extern int           mst_groupheal (MSTraceGroup *mstg, double timetol, double sampratetol);
666 extern int           mst_groupsort (MSTraceGroup *mstg, flag quality);
667 extern int           mst_convertsamples (MSTrace *mst, char type, flag truncate);
668 extern char *        mst_srcname (MSTrace *mst, char *srcname, flag quality);
669 extern void          mst_printtracelist (MSTraceGroup *mstg, flag timeformat,
670 					 flag details, flag gaps);
671 extern void          mst_printsynclist ( MSTraceGroup *mstg, char *dccid, flag subsecond );
672 extern void          mst_printgaplist (MSTraceGroup *mstg, flag timeformat,
673 				       double *mingap, double *maxgap);
674 extern int           mst_pack (MSTrace *mst, void (*record_handler) (char *, int, void *),
675 			       void *handlerdata, int reclen, flag encoding, flag byteorder,
676 			       int64_t *packedsamples, flag flush, flag verbose,
677 			       MSRecord *mstemplate);
678 extern int           mst_packgroup (MSTraceGroup *mstg, void (*record_handler) (char *, int, void *),
679 				    void *handlerdata, int reclen, flag encoding, flag byteorder,
680 				    int64_t *packedsamples, flag flush, flag verbose,
681 				    MSRecord *mstemplate);
682 
683 /* MSTraceList related functions */
684 extern MSTraceList * mstl_init ( MSTraceList *mstl );
685 extern void          mstl_free ( MSTraceList **ppmstl, flag freeprvtptr );
686 extern MSTraceSeg *  mstl_addmsr ( MSTraceList *mstl, MSRecord *msr, flag dataquality,
687 				   flag autoheal, double timetol, double sampratetol );
688 extern int           mstl_convertsamples ( MSTraceSeg *seg, char type, flag truncate );
689 extern void          mstl_printtracelist ( MSTraceList *mstl, flag timeformat,
690 					   flag details, flag gaps );
691 extern void          mstl_printsynclist ( MSTraceList *mstl, char *dccid, flag subsecond );
692 extern void          mstl_printgaplist (MSTraceList *mstl, flag timeformat,
693 					double *mingap, double *maxgap);
694 
695 /* Reading Mini-SEED records from files */
696 typedef struct MSFileParam_s
697 {
698   FILE *fp;
699   char  filename[512];
700   char *rawrec;
701   int   readlen;
702   int   readoffset;
703   int   packtype;
704   off_t packhdroffset;
705   off_t filepos;
706   off_t filesize;
707   int   recordcount;
708 } MSFileParam;
709 
710 extern int      ms_readmsr (MSRecord **ppmsr, const char *msfile, int reclen, off_t *fpos, int *last,
711 			    flag skipnotdata, flag dataflag, flag verbose);
712 extern int      ms_readmsr_r (MSFileParam **ppmsfp, MSRecord **ppmsr, const char *msfile, int reclen,
713 			      off_t *fpos, int *last, flag skipnotdata, flag dataflag, flag verbose);
714 extern int      ms_readmsr_main (MSFileParam **ppmsfp, MSRecord **ppmsr, const char *msfile, int reclen,
715 				 off_t *fpos, int *last, flag skipnotdata, flag dataflag, Selections *selections, flag verbose);
716 extern int      ms_readtraces (MSTraceGroup **ppmstg, const char *msfile, int reclen, double timetol, double sampratetol,
717 			       flag dataquality, flag skipnotdata, flag dataflag, flag verbose);
718 extern int      ms_readtraces_timewin (MSTraceGroup **ppmstg, const char *msfile, int reclen, double timetol, double sampratetol,
719 				       hptime_t starttime, hptime_t endtime, flag dataquality, flag skipnotdata, flag dataflag, flag verbose);
720 extern int      ms_readtraces_selection (MSTraceGroup **ppmstg, const char *msfile, int reclen, double timetol, double sampratetol,
721 					 Selections *selections, flag dataquality, flag skipnotdata, flag dataflag, flag verbose);
722 extern int      ms_readtracelist (MSTraceList **ppmstl, const char *msfile, int reclen, double timetol, double sampratetol,
723 				  flag dataquality, flag skipnotdata, flag dataflag, flag verbose);
724 extern int      ms_readtracelist_timewin (MSTraceList **ppmstl, const char *msfile, int reclen, double timetol, double sampratetol,
725 					  hptime_t starttime, hptime_t endtime, flag dataquality, flag skipnotdata, flag dataflag, flag verbose);
726 extern int      ms_readtracelist_selection (MSTraceList **ppmstl, const char *msfile, int reclen, double timetol, double sampratetol,
727 					    Selections *selections, flag dataquality, flag skipnotdata, flag dataflag, flag verbose);
728 
729 extern int      msr_writemseed ( MSRecord *msr, const char *msfile, flag overwrite, int reclen,
730 				 flag encoding, flag byteorder, flag verbose );
731 extern int      mst_writemseed ( MSTrace *mst, const char *msfile, flag overwrite, int reclen,
732 				 flag encoding, flag byteorder, flag verbose );
733 extern int      mst_writemseedgroup ( MSTraceGroup *mstg, const char *msfile, flag overwrite,
734 				      int reclen, flag encoding, flag byteorder, flag verbose );
735 
736 /* General use functions */
737 extern char*    ms_recsrcname (char *record, char *srcname, flag quality);
738 extern int      ms_splitsrcname (char *srcname, char *net, char *sta, char *loc, char *chan, char *qual);
739 extern int      ms_strncpclean (char *dest, const char *source, int length);
740 extern int      ms_strncpcleantail (char *dest, const char *source, int length);
741 extern int      ms_strncpopen (char *dest, const char *source, int length);
742 extern int      ms_doy2md (int year, int jday, int *month, int *mday);
743 extern int      ms_md2doy (int year, int month, int mday, int *jday);
744 extern hptime_t ms_btime2hptime (BTime *btime);
745 extern char*    ms_btime2isotimestr (BTime *btime, char *isotimestr);
746 extern char*    ms_btime2mdtimestr (BTime *btime, char *mdtimestr);
747 extern char*    ms_btime2seedtimestr (BTime *btime, char *seedtimestr);
748 extern int      ms_hptime2tomsusecoffset (hptime_t hptime, hptime_t *toms, int8_t *usecoffset);
749 extern int      ms_hptime2btime (hptime_t hptime, BTime *btime);
750 extern char*    ms_hptime2isotimestr (hptime_t hptime, char *isotimestr, flag subsecond);
751 extern char*    ms_hptime2mdtimestr (hptime_t hptime, char *mdtimestr, flag subsecond);
752 extern char*    ms_hptime2seedtimestr (hptime_t hptime, char *seedtimestr, flag subsecond);
753 extern hptime_t ms_time2hptime (int year, int day, int hour, int min, int sec, int usec);
754 extern hptime_t ms_seedtimestr2hptime (char *seedtimestr);
755 extern hptime_t ms_timestr2hptime (char *timestr);
756 extern double   ms_nomsamprate (int factor, int multiplier);
757 extern int      ms_genfactmult (double samprate, int16_t *factor, int16_t *multiplier);
758 extern int      ms_ratapprox (double real, int *num, int *den, int maxval, double precision);
759 extern int      ms_bigendianhost (void);
760 extern double   ms_dabs (double val);
761 extern double   ms_rsqrt64 (double val);
762 
763 
764 /* Lookup functions */
765 extern uint8_t  ms_samplesize (const char sampletype);
766 extern char*    ms_encodingstr (const char encoding);
767 extern char*    ms_blktdesc (uint16_t blkttype);
768 extern uint16_t ms_blktlen (uint16_t blkttype, const char *blktdata, flag swapflag);
769 extern char *   ms_errorstr (int errorcode);
770 
771 /* Logging facility */
772 #define MAX_LOG_MSG_LENGTH  200      /* Maximum length of log messages */
773 
774 /* Logging parameters */
775 typedef struct MSLogParam_s
776 {
777   void (*log_print)(char*);
778   const char *logprefix;
779   void (*diag_print)(char*);
780   const char *errprefix;
781 } MSLogParam;
782 
783 extern int    ms_log (int level, ...);
784 extern int    ms_log_l (MSLogParam *logp, int level, ...);
785 extern void   ms_loginit (void (*log_print)(char*), const char *logprefix,
786 			  void (*diag_print)(char*), const char *errprefix);
787 extern MSLogParam *ms_loginit_l (MSLogParam *logp,
788 			         void (*log_print)(char*), const char *logprefix,
789 			         void (*diag_print)(char*), const char *errprefix);
790 
791 /* Selection functions */
792 extern Selections *ms_matchselect (Selections *selections, char *srcname,
793 				   hptime_t starttime, hptime_t endtime, SelectTime **ppselecttime);
794 extern Selections *msr_matchselect (Selections *selections, MSRecord *msr, SelectTime **ppselecttime);
795 extern int      ms_addselect (Selections **ppselections, char *srcname,
796 			      hptime_t starttime, hptime_t endtime);
797 extern int      ms_addselect_comp (Selections **ppselections, char *net, char* sta, char *loc,
798 				   char *chan, char *qual, hptime_t starttime, hptime_t endtime);
799 extern int      ms_readselectionsfile (Selections **ppselections, char *filename);
800 extern void     ms_freeselections (Selections *selections);
801 extern void     ms_printselections (Selections *selections);
802 
803 /* Leap second declarations, implementation in gentutils.c */
804 typedef struct LeapSecond_s
805 {
806   hptime_t leapsecond;
807   int32_t  TAIdelta;
808   struct LeapSecond_s *next;
809 } LeapSecond;
810 
811 extern LeapSecond *leapsecondlist;
812 extern int ms_readleapseconds (char *envvarname);
813 extern int ms_readleapsecondfile (char *filename);
814 
815 /* Generic byte swapping routines */
816 extern void     ms_gswap2 ( void *data2 );
817 extern void     ms_gswap3 ( void *data3 );
818 extern void     ms_gswap4 ( void *data4 );
819 extern void     ms_gswap8 ( void *data8 );
820 
821 /* Generic byte swapping routines for memory aligned quantities */
822 extern void     ms_gswap2a ( void *data2 );
823 extern void     ms_gswap4a ( void *data4 );
824 extern void     ms_gswap8a ( void *data8 );
825 
826 /* Byte swap macro for the BTime struct */
827 #define MS_SWAPBTIME(x) \
828   ms_gswap2 (x.year);   \
829   ms_gswap2 (x.day);    \
830   ms_gswap2 (x.fract);
831 
832 /* Platform portable functions */
833 extern off_t lmp_ftello (FILE *stream);
834 extern int lmp_fseeko (FILE *stream, off_t offset, int whence);
835 
836 #ifdef __cplusplus
837 }
838 #endif
839 
840 #endif /* LIBMSEED_H */
841