Check the serial connection in record mode using parsed sample
[ruwai.git] / software / c++ / ruwaicom / src / libmseed / selection.c
blob4f150f1a0732d7d6487ea6d4906a944d6e96b564
1 /***************************************************************************
2 * selection.c:
4 * Generic routines to manage selection lists.
6 * Written by Chad Trabant unless otherwise noted
7 * IRIS Data Management Center
9 * modified: 2014.197
10 ***************************************************************************/
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <errno.h>
16 #include <time.h>
18 #include "libmseed.h"
20 static int ms_globmatch (char *string, char *pattern);
23 /***************************************************************************
24 * ms_matchselect:
26 * Test the specified parameters for a matching selection entry. The
27 * srcname parameter may contain globbing characters. The NULL value
28 * (matching any times) for the start and end times is HPTERROR.
30 * Return Selections pointer to matching entry on successful match and
31 * NULL for no match or error.
32 ***************************************************************************/
33 Selections *
34 ms_matchselect (Selections *selections, char *srcname, hptime_t starttime,
35 hptime_t endtime, SelectTime **ppselecttime)
37 Selections *findsl = NULL;
38 SelectTime *findst = NULL;
39 SelectTime *matchst = NULL;
41 if ( selections )
43 findsl = selections;
44 while ( findsl )
46 if ( ms_globmatch (srcname, findsl->srcname) )
48 findst = findsl->timewindows;
49 while ( findst )
51 if ( starttime != HPTERROR && findst->starttime != HPTERROR &&
52 (starttime < findst->starttime && ! (starttime <= findst->starttime && endtime >= findst->starttime)) )
53 { findst = findst->next; continue; }
54 else if ( endtime != HPTERROR && findst->endtime != HPTERROR &&
55 (endtime > findst->endtime && ! (starttime <= findst->endtime && endtime >= findst->endtime)) )
56 { findst = findst->next; continue; }
58 matchst = findst;
59 break;
63 if ( matchst )
64 break;
65 else
66 findsl = findsl->next;
70 if ( ppselecttime )
71 *ppselecttime = matchst;
73 return ( matchst ) ? findsl : NULL;
74 } /* End of ms_matchselect() */
77 /***************************************************************************
78 * msr_matchselect:
80 * A simple wrapper for calling ms_matchselect() using details from a
81 * MSRecord struct.
83 * Return Selections pointer to matching entry on successful match and
84 * NULL for no match or error.
85 ***************************************************************************/
86 Selections *
87 msr_matchselect (Selections *selections, MSRecord *msr, SelectTime **ppselecttime)
89 char srcname[50];
90 hptime_t endtime;
92 if ( ! selections || ! msr )
93 return NULL;
95 msr_srcname (msr, srcname, 1);
96 endtime = msr_endtime (msr);
98 return ms_matchselect (selections, srcname, msr->starttime, endtime,
99 ppselecttime);
100 } /* End of msr_matchselect() */
103 /***************************************************************************
104 * ms_addselect:
106 * Add select parameters to a specified selection list. The srcname
107 * argument may contain globbing parameters. The NULL value (matching
108 * any value) for the start and end times is HPTERROR.
110 * Return 0 on success and -1 on error.
111 ***************************************************************************/
113 ms_addselect (Selections **ppselections, char *srcname,
114 hptime_t starttime, hptime_t endtime)
116 Selections *newsl = NULL;
117 SelectTime *newst = NULL;
119 if ( ! ppselections || ! srcname )
120 return -1;
122 /* Allocate new SelectTime and populate */
123 if ( ! (newst = (SelectTime *) calloc (1, sizeof(SelectTime))) )
125 ms_log (2, "Cannot allocate memory\n");
126 return -1;
129 newst->starttime = starttime;
130 newst->endtime = endtime;
132 /* Add new Selections struct to begining of list */
133 if ( ! *ppselections )
135 /* Allocate new Selections and populate */
136 if ( ! (newsl = (Selections *) calloc (1, sizeof(Selections))) )
138 ms_log (2, "Cannot allocate memory\n");
139 return -1;
142 strncpy (newsl->srcname, srcname, sizeof(newsl->srcname));
143 newsl->srcname[sizeof(newsl->srcname) - 1] = '\0';
145 /* Add new Selections struct as first in list */
146 *ppselections = newsl;
147 newsl->timewindows = newst;
149 else
151 Selections *findsl = *ppselections;
152 Selections *matchsl = 0;
154 /* Search for matching Selectlink entry */
155 while ( findsl )
157 if ( ! strcmp (findsl->srcname, srcname) )
159 matchsl = findsl;
160 break;
163 findsl = findsl->next;
166 if ( matchsl )
168 /* Add time window selection to beginning of window list */
169 newst->next = matchsl->timewindows;
170 matchsl->timewindows = newst;
172 else
174 /* Allocate new Selections and populate */
175 if ( ! (newsl = (Selections *) calloc (1, sizeof(Selections))) )
177 ms_log (2, "Cannot allocate memory\n");
178 return -1;
181 strncpy (newsl->srcname, srcname, sizeof(newsl->srcname));
182 newsl->srcname[sizeof(newsl->srcname) - 1] = '\0';
184 /* Add new Selections to beginning of list */
185 newsl->next = *ppselections;
186 *ppselections = newsl;
187 newsl->timewindows = newst;
191 return 0;
192 } /* End of ms_addselect() */
195 /***************************************************************************
196 * ms_addselect_comp:
198 * Add select parameters to a specified selection list based on
199 * separate name components. The network, station, location, channel
200 * and quality arguments may contain globbing parameters. The NULL
201 * value (matching any value) for the start and end times is HPTERROR.
203 * If any of the naming parameters are not supplied (pointer is NULL)
204 * a wildcard for all matches is substituted. As a special case, if
205 * the location ID (loc) is set to "--" to match a space-space/blank
206 * ID it will be translated to an empty string to match libmseed's
207 * notation.
209 * Return 0 on success and -1 on error.
210 ***************************************************************************/
212 ms_addselect_comp (Selections **ppselections, char *net, char* sta, char *loc,
213 char *chan, char *qual, hptime_t starttime, hptime_t endtime)
215 char srcname[100];
216 char selnet[20];
217 char selsta[20];
218 char selloc[20];
219 char selchan[20];
220 char selqual[20];
222 if ( ! ppselections )
223 return -1;
225 if ( net )
227 strncpy (selnet, net, sizeof(selnet));
228 selnet[sizeof(selnet)-1] = '\0';
230 else
231 strcpy (selnet, "*");
233 if ( sta )
235 strncpy (selsta, sta, sizeof(selsta));
236 selsta[sizeof(selsta)-1] = '\0';
238 else
239 strcpy (selsta, "*");
241 if ( loc )
243 /* Test for special case blank location ID */
244 if ( ! strcmp (loc, "--") )
245 selloc[0] = '\0';
246 else
248 strncpy (selloc, loc, sizeof(selloc));
249 selloc[sizeof(selloc)-1] = '\0';
252 else
253 strcpy (selloc, "*");
255 if ( chan )
257 strncpy (selchan, chan, sizeof(selchan));
258 selchan[sizeof(selchan)-1] = '\0';
260 else
261 strcpy (selchan, "*");
263 if ( qual )
265 strncpy (selqual, qual, sizeof(selqual));
266 selqual[sizeof(selqual)-1] = '\0';
268 else
269 strcpy (selqual, "?");
271 /* Create the srcname globbing match for this entry */
272 snprintf (srcname, sizeof(srcname), "%s_%s_%s_%s_%s",
273 selnet, selsta, selloc, selchan, selqual);
275 /* Add selection to list */
276 if ( ms_addselect (ppselections, srcname, starttime, endtime) )
277 return -1;
279 return 0;
280 } /* End of ms_addselect_comp() */
283 /***************************************************************************
284 * ms_readselectionsfile:
286 * Read a list of data selections from a file and them to the
287 * specified selections list. On errors this routine will leave
288 * allocated memory unreachable (leaked), it is expected that this is
289 * a program failing condition.
291 * As a special case if the filename is "-", selection lines will be
292 * read from stdin.
294 * Returns count of selections added on success and -1 on error.
295 ***************************************************************************/
297 ms_readselectionsfile (Selections **ppselections, char *filename)
299 FILE *fp;
300 hptime_t starttime;
301 hptime_t endtime;
302 char selectline[200];
303 char *selnet;
304 char *selsta;
305 char *selloc;
306 char *selchan;
307 char *selqual;
308 char *selstart;
309 char *selend;
310 char *cp;
311 char next;
312 int selectcount = 0;
313 int linecount = 0;
315 if ( ! ppselections || ! filename )
316 return -1;
318 if ( strcmp (filename, "-" ) )
320 if ( ! (fp = fopen(filename, "rb")) )
322 ms_log (2, "Cannot open file %s: %s\n", filename, strerror(errno));
323 return -1;
326 else
328 /* Use stdin as special case */
329 fp = stdin;
332 while ( fgets (selectline, sizeof(selectline)-1, fp) )
334 selnet = 0;
335 selsta = 0;
336 selloc = 0;
337 selchan = 0;
338 selqual = 0;
339 selstart = 0;
340 selend = 0;
342 linecount++;
344 /* Guarantee termination */
345 selectline[sizeof(selectline)-1] = '\0';
347 /* End string at first newline character if any */
348 if ( (cp = strchr(selectline, '\n')) )
349 *cp = '\0';
351 /* Skip empty lines */
352 if ( ! strlen (selectline) )
353 continue;
355 /* Skip comment lines */
356 if ( *selectline == '#' )
357 continue;
359 /* Parse: identify components of selection and terminate */
360 cp = selectline;
361 next = 1;
362 while ( *cp )
364 if ( *cp == ' ' || *cp == '\t' ) { *cp = '\0'; next = 1; }
365 else if ( *cp == '#' ) { *cp = '\0'; break; }
366 else if ( next && ! selnet ) { selnet = cp; next = 0; }
367 else if ( next && ! selsta ) { selsta = cp; next = 0; }
368 else if ( next && ! selloc ) { selloc = cp; next = 0; }
369 else if ( next && ! selchan ) { selchan = cp; next = 0; }
370 else if ( next && ! selqual ) { selqual = cp; next = 0; }
371 else if ( next && ! selstart ) { selstart = cp; next = 0; }
372 else if ( next && ! selend ) { selend = cp; next = 0; }
373 else if ( next ) { *cp = '\0'; break; }
374 cp++;
377 /* Skip line if network, station, location and channel are not defined */
378 if ( ! selnet || ! selsta || ! selloc || ! selchan )
380 ms_log (2, "[%s] Skipping data selection line number %d\n", filename, linecount);
381 continue;
384 if ( selstart )
386 starttime = ms_seedtimestr2hptime (selstart);
387 if ( starttime == HPTERROR )
389 ms_log (2, "Cannot convert data selection start time (line %d): %s\n", linecount, selstart);
390 return -1;
393 else
395 starttime = HPTERROR;
398 if ( selend )
400 endtime = ms_seedtimestr2hptime (selend);
401 if ( endtime == HPTERROR )
403 ms_log (2, "Cannot convert data selection end time (line %d): %s\n", linecount, selend);
404 return -1;
407 else
409 endtime = HPTERROR;
412 /* Add selection to list */
413 if ( ms_addselect_comp (ppselections, selnet, selsta, selloc, selchan, selqual, starttime, endtime) )
415 ms_log (2, "[%s] Error adding selection on line %d\n", filename, linecount);
416 return -1;
419 selectcount++;
422 if ( fp != stdin )
423 fclose (fp);
425 return selectcount;
426 } /* End of ms_readselectionsfile() */
429 /***************************************************************************
430 * ms_freeselections:
432 * Free all memory associated with a Selections struct.
433 ***************************************************************************/
434 void
435 ms_freeselections ( Selections *selections )
437 Selections *select;
438 Selections *selectnext;
439 SelectTime *selecttime;
440 SelectTime *selecttimenext;
442 if ( selections )
444 select = selections;
446 while ( select )
448 selectnext = select->next;
450 selecttime = select->timewindows;
452 while ( selecttime )
454 selecttimenext = selecttime->next;
456 free (selecttime);
458 selecttime = selecttimenext;
461 free (select);
463 select = selectnext;
467 } /* End of ms_freeselections() */
470 /***************************************************************************
471 * ms_printselections:
473 * Print the selections list using the ms_log() facility.
474 ***************************************************************************/
475 void
476 ms_printselections ( Selections *selections )
478 Selections *select;
479 SelectTime *selecttime;
480 char starttime[50];
481 char endtime[50];
483 if ( ! selections )
484 return;
486 select = selections;
487 while ( select )
489 ms_log (0, "Selection: %s\n", select->srcname);
491 selecttime = select->timewindows;
492 while ( selecttime )
494 if ( selecttime->starttime != HPTERROR )
495 ms_hptime2seedtimestr (selecttime->starttime, starttime, 1);
496 else
497 strncpy (starttime, "No start time", sizeof(starttime)-1);
499 if ( selecttime->endtime != HPTERROR )
500 ms_hptime2seedtimestr (selecttime->endtime, endtime, 1);
501 else
502 strncpy (endtime, "No end time", sizeof(endtime)-1);
504 ms_log (0, " %30s %30s\n", starttime, endtime);
506 selecttime = selecttime->next;
509 select = select->next;
511 } /* End of ms_printselections() */
514 /***********************************************************************
515 * robust glob pattern matcher
516 * ozan s. yigit/dec 1994
517 * public domain
519 * glob patterns:
520 * * matches zero or more characters
521 * ? matches any single character
522 * [set] matches any character in the set
523 * [^set] matches any character NOT in the set
524 * where a set is a group of characters or ranges. a range
525 * is written as two characters seperated with a hyphen: a-z denotes
526 * all characters between a to z inclusive.
527 * [-set] set matches a literal hypen and any character in the set
528 * []set] matches a literal close bracket and any character in the set
530 * char matches itself except where char is '*' or '?' or '['
531 * \char matches char, including any pattern character
533 * examples:
534 * a*c ac abc abbc ...
535 * a?c acc abc aXc ...
536 * a[a-z]c aac abc acc ...
537 * a[-a-z]c a-c aac abc ...
539 * Revision 1.4 2004/12/26 12:38:00 ct
540 * Changed function name (amatch -> globmatch), variables and
541 * formatting for clarity. Also add matching header globmatch.h.
543 * Revision 1.3 1995/09/14 23:24:23 oz
544 * removed boring test/main code.
546 * Revision 1.2 94/12/11 10:38:15 oz
547 * charset code fixed. it is now robust and interprets all
548 * variations of charset [i think] correctly, including [z-a] etc.
550 * Revision 1.1 94/12/08 12:45:23 oz
551 * Initial revision
552 ***********************************************************************/
554 #define GLOBMATCH_TRUE 1
555 #define GLOBMATCH_FALSE 0
556 #define GLOBMATCH_NEGATE '^' /* std char set negation char */
558 /***********************************************************************
559 * ms_globmatch:
561 * Check if a string matches a globbing pattern.
563 * Return 0 if string does not match pattern and non-zero otherwise.
564 **********************************************************************/
565 static int
566 ms_globmatch (char *string, char *pattern)
568 int negate;
569 int match;
570 int c;
572 while ( *pattern )
574 if ( !*string && *pattern != '*' )
575 return GLOBMATCH_FALSE;
577 switch ( c = *pattern++ )
580 case '*':
581 while ( *pattern == '*' )
582 pattern++;
584 if ( !*pattern )
585 return GLOBMATCH_TRUE;
587 if ( *pattern != '?' && *pattern != '[' && *pattern != '\\' )
588 while ( *string && *pattern != *string )
589 string++;
591 while ( *string )
593 if ( ms_globmatch(string, pattern) )
594 return GLOBMATCH_TRUE;
595 string++;
597 return GLOBMATCH_FALSE;
599 case '?':
600 if ( *string )
601 break;
602 return GLOBMATCH_FALSE;
604 /* set specification is inclusive, that is [a-z] is a, z and
605 * everything in between. this means [z-a] may be interpreted
606 * as a set that contains z, a and nothing in between.
608 case '[':
609 if ( *pattern != GLOBMATCH_NEGATE )
610 negate = GLOBMATCH_FALSE;
611 else
613 negate = GLOBMATCH_TRUE;
614 pattern++;
617 match = GLOBMATCH_FALSE;
619 while ( !match && (c = *pattern++) )
621 if ( !*pattern )
622 return GLOBMATCH_FALSE;
624 if ( *pattern == '-' ) /* c-c */
626 if ( !*++pattern )
627 return GLOBMATCH_FALSE;
628 if ( *pattern != ']' )
630 if ( *string == c || *string == *pattern ||
631 ( *string > c && *string < *pattern ) )
632 match = GLOBMATCH_TRUE;
634 else
635 { /* c-] */
636 if ( *string >= c )
637 match = GLOBMATCH_TRUE;
638 break;
641 else /* cc or c] */
643 if ( c == *string )
644 match = GLOBMATCH_TRUE;
645 if ( *pattern != ']' )
647 if ( *pattern == *string )
648 match = GLOBMATCH_TRUE;
650 else
651 break;
655 if ( negate == match )
656 return GLOBMATCH_FALSE;
659 * if there is a match, skip past the charset and continue on
661 while ( *pattern && *pattern != ']' )
662 pattern++;
663 if ( !*pattern++ ) /* oops! */
664 return GLOBMATCH_FALSE;
665 break;
667 case '\\':
668 if ( *pattern )
669 c = *pattern++;
670 default:
671 if ( c != *string )
672 return GLOBMATCH_FALSE;
673 break;
676 string++;
679 return !*string;
680 } /* End of ms_globmatch() */