nmxp_chan.c 22.1 KB
Newer Older
1 2
/*! \file
 *
Matteo Quintiliani's avatar
Matteo Quintiliani committed
3
 * \brief Channels for Nanometrics Protocol Library
4 5 6 7 8 9
 *
 * Author:
 * 	Matteo Quintiliani
 * 	Istituto Nazionale di Geofisica e Vulcanologia - Italy
 *	quintiliani@ingv.it
 *
10
 * $Id: nmxp_chan.c,v 1.47 2010-09-14 09:38:52 mtheo Exp $
Matteo Quintiliani's avatar
Matteo Quintiliani committed
11
 *
12 13 14
 */

#include "nmxp_chan.h"
Matteo Quintiliani's avatar
Matteo Quintiliani committed
15
#include "nmxp_base.h"
16
#include "nmxp_memory.h"
17 18

#include <string.h>
19
#include <stdlib.h>
20

21
int nmxp_chan_cpy_sta_chan(const char *net_dot_station_dot_channel, char *station_code, char *channel_code, char *network_code, char *location_code) {
22
    int ret = 0;
23 24
    int errors = 0;
    int i;
25
    char *period1 = NULL, *period2 = NULL, *period3 = NULL;
26 27
    char *tmp_name = NULL;

28
    if(net_dot_station_dot_channel || station_code || channel_code || network_code || location_code) {
29 30 31

	station_code[0] = 0;
	channel_code[0] = 0;
32
	network_code[0] = 0;
33
	location_code[0] = 0;
34

35
	tmp_name = NMXP_MEM_STRDUP(net_dot_station_dot_channel);
36 37 38 39 40 41 42 43
	/* count '.' */
	i=0;
	while(i < strlen(tmp_name)  && !errors) {
	    if(tmp_name[i] == '.') {
		if(!period1) {
		    period1 = tmp_name+i;
		} else if(!period2) {
		    period2 = tmp_name+i;
44 45
		} else if(!period3) {
		    period3 = tmp_name+i;
46 47 48 49 50 51 52 53
		} else {
		    errors++;
		}
	    }
	    i++;
	}
	if(!errors && period1) {
	    ret = 1;
54 55
	    if(period3) {
		/* NET.STA.CHAN.LOC */
56 57
		*period1++ = '\0';
		*period2++ = '\0';
58
		*period3++ = '\0';
59 60 61
		strncpy(network_code, tmp_name, NMXP_CHAN_MAX_SIZE_STR_PATTERN);
		strncpy(station_code, period1, NMXP_CHAN_MAX_SIZE_STR_PATTERN);
		strncpy(channel_code, period2, NMXP_CHAN_MAX_SIZE_STR_PATTERN);
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
		strncpy(location_code, period3, NMXP_CHAN_MAX_SIZE_STR_PATTERN);
	    } else
	    if(period2) {
		/* TODO NECESSARY  */
		/* NET.STA.CHAN */
		/* OR */
		/* STA.CHAN.LOC */
		*period1++ = '\0';
		*period2++ = '\0';
		if( strlen(period1) == 3 && strlen(period2) == 2) {
		    /* STA.CHAN.LOC */
		    strncpy(station_code, tmp_name, NMXP_CHAN_MAX_SIZE_STR_PATTERN);
		    strncpy(channel_code, period1, NMXP_CHAN_MAX_SIZE_STR_PATTERN);
		    strncpy(location_code, period2, NMXP_CHAN_MAX_SIZE_STR_PATTERN);
		} else
		if( strlen(tmp_name) == 2 && strlen(period2) == 3) {
		    /* NET.STA.CHAN */
		    strncpy(network_code, tmp_name, NMXP_CHAN_MAX_SIZE_STR_PATTERN);
		    strncpy(station_code, period1, NMXP_CHAN_MAX_SIZE_STR_PATTERN);
		    strncpy(channel_code, period2, NMXP_CHAN_MAX_SIZE_STR_PATTERN);
		} else {
		  nmxp_log(NMXP_LOG_ERR, NMXP_LOG_D_CHANNEL, "Name %s is not in NET.STA.CHA.LOC format! (NET. .LOC are optional)\n",
		      NMXP_LOG_STR(net_dot_station_dot_channel));
		}
86
	    } else {
87 88
		/* STA.CHAN */
		*period1++ = '\0';
89 90
		strncpy(station_code, tmp_name, NMXP_CHAN_MAX_SIZE_STR_PATTERN);
		strncpy(channel_code, period1, NMXP_CHAN_MAX_SIZE_STR_PATTERN);
91
	    }
92
	} else {
93 94
	    nmxp_log(NMXP_LOG_ERR, NMXP_LOG_D_CHANNEL, "Name %s is not in NET.STA.CHAN format! (NET. is optional)\n",
		    NMXP_LOG_STR(net_dot_station_dot_channel));
95 96 97
	}

	if(tmp_name) {
98
	    NMXP_MEM_FREE(tmp_name);
99
	    tmp_name = NULL;
100
	}
101

102
    } else {
103 104
	nmxp_log(NMXP_LOG_ERR, NMXP_LOG_D_CHANNEL, "Some parameter is NULL in nmxp_chan_cpy_sta_chan() %s.\n",
		NMXP_LOG_STR(net_dot_station_dot_channel));
105 106 107 108 109 110
    }

    return ret;
}


111 112 113 114 115 116
/*
 * Match string against the extended regular expression in
 * pattern, treating errors as no match.
 *
 * return 1 for match, 0 for no match, -1 on error for invalid pattern, -2 on error for invalid station_dot_channel
 */
117
int nmxp_chan_match(const char *net_dot_station_dot_channel, char *pattern)
118 119 120
{
    int ret = 0;
    int i, l;
121 122 123
    char sta_pattern[NMXP_CHAN_MAX_SIZE_STR_PATTERN];
    char cha_pattern[NMXP_CHAN_MAX_SIZE_STR_PATTERN];
    char net_pattern[NMXP_CHAN_MAX_SIZE_STR_PATTERN];
124
    char loc_pattern[NMXP_CHAN_MAX_SIZE_STR_PATTERN];
125
    char sta_sdc[NMXP_CHAN_MAX_SIZE_STR_PATTERN];
126 127 128
    char *cha_sdc;

    /* validate pattern channel */
129
    if(!nmxp_chan_cpy_sta_chan(pattern, sta_pattern, cha_pattern, net_pattern, loc_pattern)) {
130 131
	nmxp_log(NMXP_LOG_ERR, NMXP_LOG_D_CHANNEL, "Channel pattern %s is not in STA.CHAN format!\n",
		NMXP_LOG_STR(pattern));
132 133 134
	return -1;
    }

135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
    l = strlen(loc_pattern);
    i = 0;
    while(i < l  &&  ret != -1) {
	if(  !(
		(loc_pattern[i] >= 'A'  &&  loc_pattern[i] <= 'Z')
		|| (loc_pattern[i] >= 'a'  &&  loc_pattern[i] <= 'z')
		|| (loc_pattern[i] >= '0'  &&  loc_pattern[i] <= '9')
		|| (loc_pattern[i] == '-')
		)
	  ) {
	    nmxp_log(NMXP_LOG_ERR, NMXP_LOG_D_CHANNEL, "Channel pattern %s has not valid LOC format!\n",
		    NMXP_LOG_STR(pattern));
	    return -1;
	}
	i++;
    }
    
152 153 154 155 156 157 158 159 160
    l = strlen(net_pattern);
    i = 0;
    while(i < l  &&  ret != -1) {
	if(  !(
		(net_pattern[i] >= 'A'  &&  net_pattern[i] <= 'Z')
		|| (net_pattern[i] >= 'a'  &&  net_pattern[i] <= 'z')
		|| (net_pattern[i] >= '0'  &&  net_pattern[i] <= '9')
		)
	  ) {
161 162
	    nmxp_log(NMXP_LOG_ERR, NMXP_LOG_D_CHANNEL, "Channel pattern %s has not valid NET format!\n",
		    NMXP_LOG_STR(pattern));
163 164 165 166 167
	    return -1;
	}
	i++;
    }
    
168
    l = strlen(sta_pattern);
169 170 171
    if(((l == 1) && sta_pattern[0] == '*')) {
	/* do nothing */
    } else {
172 173 174 175 176 177 178 179 180
    i = 0;
    while(i < l  &&  ret != -1) {
	if(  !(
		(sta_pattern[i] >= 'A'  &&  sta_pattern[i] <= 'Z')
		|| (sta_pattern[i] >= 'a'  &&  sta_pattern[i] <= 'z')
		|| (sta_pattern[i] >= '0'  &&  sta_pattern[i] <= '9')
		|| (sta_pattern[i] == '_' )
	     )
	  ) {
181 182
	    nmxp_log(NMXP_LOG_ERR, NMXP_LOG_D_CHANNEL, "Channel pattern %s has not valid STA format!\n",
		    NMXP_LOG_STR(pattern));
183 184 185 186
	    return -1;
	}
	i++;
    }
187
    }
188 189 190
    
    l = strlen(cha_pattern);
    if(l != 3) {
191 192
	nmxp_log(NMXP_LOG_ERR, NMXP_LOG_D_CHANNEL, "Channel pattern %s has not valid CHAN format!\n",
		NMXP_LOG_STR(pattern));
193 194 195 196 197 198 199 200 201 202 203
	return -1;
    }
    i = 0;
    while(i < l  &&  ret != -1) {
	if(  !(
		    (cha_pattern[i] >= 'A'  &&  cha_pattern[i] <= 'Z')
		    || (cha_pattern[i] >= 'a'  &&  cha_pattern[i] <= 'z')
		    || (cha_pattern[i] == '_' )
		    || (cha_pattern[i] == '?' )
	      )
	  ) {
204 205
	    nmxp_log(NMXP_LOG_ERR, NMXP_LOG_D_CHANNEL, "Channel pattern %s has not valid CHAN format!\n",
		    NMXP_LOG_STR(pattern));
206 207 208 209 210
	    return -1;
	}
	i++;
    }

211
    strncpy(sta_sdc, net_dot_station_dot_channel, NMXP_CHAN_MAX_SIZE_STR_PATTERN);
212
    if( (cha_sdc = strchr(sta_sdc, '.')) == NULL ) {
213 214
	nmxp_log(NMXP_LOG_ERR, NMXP_LOG_D_CHANNEL, "Channel %s is not in STA.CHAN format!\n",
		NMXP_LOG_STR(net_dot_station_dot_channel));
215 216 217 218 219 220 221
	return -2;
    }
    if(cha_sdc) {
	*cha_sdc++ = '\0';
    }
    l = strlen(cha_sdc);
    if(l != 3) {
222
	nmxp_log(NMXP_LOG_ERR, NMXP_LOG_D_CHANNEL, "Channel %s has not valid CHAN format!\n",
223
		NMXP_LOG_STR(net_dot_station_dot_channel));
224 225 226
	return -1;
    }

227 228 229
    l = strlen(sta_pattern);
    if ( (strcasecmp(sta_sdc, sta_pattern) == 0) 
	    || ((l == 1) && sta_pattern[0] == '*')) {
230 231 232 233 234 235 236 237 238 239 240 241 242 243
	/* matching CHAN */
	ret = 1;
	i = 0;
	while(i < 3  &&  ret != 0) {
	    ret = ((cha_pattern[i] == '?')? 1 : (cha_pattern[i] == cha_sdc[i]));
	    i++;
	}
    }


    return ret;
}


Matteo Quintiliani's avatar
Matteo Quintiliani committed
244
int nmxp_chan_lookupKey(char* name, NMXP_CHAN_LIST *channelList)
245
{
246 247
    int chan_number = channelList->number;
    int i_chan = 0;
248

249
    for (i_chan = 0; i_chan < chan_number; i_chan++)
250
    {
251 252
	if (strcasecmp(name, channelList->channel[i_chan].name) == 0)
	    return channelList->channel[i_chan].key;
253 254 255 256 257
    }

    return -1;
}

258

259
int nmxp_chan_lookupKeyIndex(int32_t key, NMXP_CHAN_LIST_NET *channelList)
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276
{
    int i_chan = 0;
    int ret = -1;

    i_chan = 0;
    while(i_chan < channelList->number  &&  ret == -1)
    {
	if ( key == channelList->channel[i_chan].key ) {
	    ret = i_chan;
	}
	i_chan++;
    }

    return ret;
}


277
char *nmxp_chan_lookupName(int32_t key, NMXP_CHAN_LIST_NET *channelList)
278
{
279
    int i_chan = 0;
280
    char *ret = (char *) NMXP_MEM_MALLOC(NMXP_CHAN_MAX_SIZE_NAME);
281

282 283 284
    ret[0] = 0;

    for (i_chan = 0; i_chan < channelList->number; i_chan++)
285
    {
286
	if ( key == channelList->channel[i_chan].key ) {
287
	    strncpy(ret, channelList->channel[i_chan].name, NMXP_CHAN_MAX_SIZE_NAME);
288
	}
289 290
    }

291
    if(ret[0] == 0) {
292
	NMXP_MEM_FREE(ret);
293 294 295 296
	return NULL;
    } else {
	return ret;
    }
297 298
}

299

300
NMXP_CHAN_LIST *nmxp_chan_getType(NMXP_CHAN_LIST *channelList, NMXP_DATATYPE dataType) {
301 302 303 304 305
    NMXP_CHAN_LIST *ret_channelList = NULL;

    int chan_number = channelList->number;
    int i_chan = 0;

306
    ret_channelList = (NMXP_CHAN_LIST *) NMXP_MEM_MALLOC(sizeof(NMXP_CHAN_LIST));
307 308 309 310
    ret_channelList->number = 0;

    for (i_chan = 0; i_chan < chan_number; i_chan++)
    {
311
	if ( getDataTypeFromKey(channelList->channel[i_chan].key) == dataType) {
312
	    ret_channelList->channel[ret_channelList->number].key = channelList->channel[i_chan].key;
313
	    strncpy(ret_channelList->channel[ret_channelList->number].name, channelList->channel[i_chan].name, NMXP_CHAN_MAX_SIZE_NAME);
314 315 316 317 318 319 320
	    ret_channelList->number++;
	}
    }

    return ret_channelList;
}

321

322
NMXP_CHAN_LIST_NET *nmxp_chan_subset(NMXP_CHAN_LIST *channelList, NMXP_DATATYPE dataType, char *sta_chan_list, const char *network_code_default, const char *location_code_default) {
323
    NMXP_CHAN_LIST_NET *ret_channelList = NULL;
324
    int istalist, ista;
325 326
    char sta_chan_code_pattern[100];
    int i_chan, ret_match;
327 328 329
    char network_code[NMXP_CHAN_MAX_SIZE_STR_PATTERN];
    char station_code[NMXP_CHAN_MAX_SIZE_STR_PATTERN];
    char channel_code[NMXP_CHAN_MAX_SIZE_STR_PATTERN];
330
    char location_code[NMXP_CHAN_MAX_SIZE_STR_PATTERN];
331 332 333 334
    int i_chan_found = -1;
    int i_chan_duplicated = -1;
    char *nmxp_channel_name = NULL;
    char nmxp_channel_name_duplicated[50];
335

336
    ret_channelList = (NMXP_CHAN_LIST_NET *) NMXP_MEM_MALLOC(sizeof(NMXP_CHAN_LIST_NET));
337 338
    ret_channelList->number = 0;

339 340
    istalist = 0;
    while(sta_chan_list[istalist] != sep_chan_list  &&  sta_chan_list[istalist] != 0) {
341 342
	
	/* Build sta_chan_code_pattern from sta_chan_list */
343 344
	ista = 0;
	while(sta_chan_list[istalist] != sep_chan_list  &&  sta_chan_list[istalist] != 0) {
345
	    sta_chan_code_pattern[ista++] = sta_chan_list[istalist++];
346
	}
347
	sta_chan_code_pattern[ista] = 0;
348 349 350
	if(sta_chan_list[istalist] == sep_chan_list) {
	    istalist++;
	}
351 352 353 354 355 356

	/* Match name to sta_chan_code_pattern and set i_chan_found */
	nmxp_channel_name = NULL;
	nmxp_channel_name_duplicated[0] = 0;
	i_chan_found = -1;
	i_chan_duplicated = -1;
357 358
	ret_match = 1;
	i_chan = 0;
359
	while(i_chan < channelList->number && ret_match != -1) {
360
	    ret_match = nmxp_chan_match(channelList->channel[i_chan].name, sta_chan_code_pattern);
361
	    if(ret_match == 1) {
362 363 364 365 366 367 368
		    if(getDataTypeFromKey(channelList->channel[i_chan].key) == dataType) {
			/* Check for channel duplication */
			nmxp_channel_name = nmxp_chan_lookupName(channelList->channel[i_chan].key, ret_channelList);
			if(nmxp_channel_name == NULL) {
			    /* Add channel */
			    i_chan_found = i_chan;
			    ret_channelList->channel[ret_channelList->number].key =        channelList->channel[i_chan_found].key;
369
			    strncpy(ret_channelList->channel[ret_channelList->number].name, channelList->channel[i_chan_found].name, NMXP_CHAN_MAX_SIZE_NAME);
370 371 372 373 374
			    nmxp_chan_cpy_sta_chan(sta_chan_code_pattern, station_code, channel_code, network_code, location_code);
			    snprintf(ret_channelList->channel[ret_channelList->number].name, NMXP_CHAN_MAX_SIZE_NAME, "%s.%s.%s",
				    (network_code[0] != 0)? network_code : network_code_default, channelList->channel[i_chan_found].name,
				    (location_code[0] != 0)? location_code : location_code_default );
			    nmxp_log(NMXP_LOG_NORM, NMXP_LOG_D_CHANNEL, "Added %s for %s .\n",
375 376 377 378 379
				    ret_channelList->channel[ret_channelList->number].name, sta_chan_code_pattern);
			    ret_channelList->number++;
			} else {
			    strncpy(nmxp_channel_name_duplicated, nmxp_channel_name, 50);
			    i_chan_duplicated = i_chan;
380 381 382 383 384 385 386 387 388 389

			    if(i_chan_duplicated != -1) {
				/* Warning message for duplication */
				nmxp_log(NMXP_LOG_WARN, NMXP_LOG_D_ANY, "Pattern %s duplicates %s. Kept %s. (%d, Key %d).\n",
					sta_chan_code_pattern,
					channelList->channel[i_chan_duplicated].name,
					NMXP_LOG_STR(nmxp_channel_name_duplicated),
					i_chan_duplicated, channelList->channel[i_chan_duplicated].key);
			    }

390 391
			    NMXP_MEM_FREE(nmxp_channel_name);
			    nmxp_channel_name = NULL;
392
			}
393 394 395
		    }
	    }
	    i_chan++;
396
	}
397 398 399

	if(i_chan_found == -1  &&  i_chan_duplicated == -1) {
	    /* Error message for channel not found of channel is not dataType */
400
	    nmxp_log(NMXP_LOG_ERR, NMXP_LOG_D_ANY, "Pattern %s does not match to any key.\n",
401 402 403
		    sta_chan_code_pattern);
	}

404
    }
405
    
406 407 408 409
    return ret_channelList;
}


410
/* Comparison Key Function*/
411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428
int chan_key_compare(const void *a, const void *b)
{
    int ret = 0;
    NMXP_CHAN_KEY *pa = (NMXP_CHAN_KEY *) a; 
    NMXP_CHAN_KEY *pb = (NMXP_CHAN_KEY *) b;

    if(pa->key > pb->key) {
	ret = 1;
    } else if(pa->key < pb->key) {
	ret = -1;
    }
    return ret;
}

void nmxp_chan_sortByKey(NMXP_CHAN_LIST *channelList) {
    qsort (channelList->channel, channelList->number, sizeof (NMXP_CHAN_KEY), chan_key_compare);
}

429
/* Comparison Name Function*/
430 431 432 433 434 435 436 437 438 439 440 441
int chan_name_compare(const void *a, const void *b)
{
    NMXP_CHAN_KEY *pa = (NMXP_CHAN_KEY *) a; 
    NMXP_CHAN_KEY *pb = (NMXP_CHAN_KEY *) b;

    return strcmp(pa->name, pb->name);
}

void nmxp_chan_sortByName(NMXP_CHAN_LIST *channelList) {
    qsort (channelList->channel, channelList->number, sizeof (NMXP_CHAN_KEY), chan_name_compare);
}

442 443

void nmxp_chan_print_channelList(NMXP_CHAN_LIST *channelList) {
444
    int chan_number = 0;
445 446
    int i_chan = 0;

447 448 449 450 451 452 453 454 455 456 457 458 459 460 461
    if(channelList) {
	chan_number = channelList->number;
	nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_CHANNEL, "%04d channels:\n", chan_number);

	for (i_chan = 0; i_chan < chan_number; i_chan++)
	{
	    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "%04d %12d %6s%c%-11s\n",
		    i_chan+1,
		    channelList->channel[i_chan].key,
		    "    ",
		    ' ',
		    NMXP_LOG_STR(channelList->channel[i_chan].name));
	}
    } else {
	nmxp_log(NMXP_LOG_ERR, NMXP_LOG_D_CHANNEL, "Channel list is NULL.\n");
462 463 464 465
    }

}

466

467
void nmxp_chan_print_channelList_with_match(NMXP_CHAN_LIST *channelList, char *sta_chan_list, int flag_statefile) {
468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502
    int chan_number = 0;
    int i_chan = 0;
    int ret_match = 0;
    int istalist, ista;
    char sta_chan_code_pattern[100];

    if(channelList) {
	chan_number = channelList->number;
	nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_CHANNEL, "%04d channels:\n", chan_number);

	for (i_chan = 0; i_chan < chan_number; i_chan++)
	{
	    if(sta_chan_list) {

		ret_match = 0;
		istalist = 0;
		while(sta_chan_list[istalist] != sep_chan_list  &&  sta_chan_list[istalist] != 0  &&  ret_match == 0) {

		    /* Build sta_chan_code_pattern from sta_chan_list */
		    ista = 0;
		    while(sta_chan_list[istalist] != sep_chan_list  &&  sta_chan_list[istalist] != 0) {
			sta_chan_code_pattern[ista++] = sta_chan_list[istalist++];
		    }
		    sta_chan_code_pattern[ista] = 0;
		    if(sta_chan_list[istalist] == sep_chan_list) {
			istalist++;
		    }

		    ret_match = nmxp_chan_match(channelList->channel[i_chan].name, sta_chan_code_pattern);
		}

	    } else {
		ret_match = 1;
	    }
	    if(ret_match == 1) {
503 504 505 506 507 508 509 510 511 512 513 514 515
		if(flag_statefile) {
		    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "%-11s # %12d\n",
			    NMXP_LOG_STR(channelList->channel[i_chan].name),
			    channelList->channel[i_chan].key
			    );
		} else {
		    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "%04d %12d %6s%c%-11s\n",
			    i_chan+1,
			    channelList->channel[i_chan].key,
			    "    ",
			    ' ',
			    NMXP_LOG_STR(channelList->channel[i_chan].name));
		}
516 517 518 519 520 521 522 523 524
	    }
	}
    } else {
	nmxp_log(NMXP_LOG_ERR, NMXP_LOG_D_CHANNEL, "Channel list is NULL.\n");
    }

}


525
void nmxp_chan_print_netchannelList(NMXP_CHAN_LIST_NET *channelList) {
526 527 528
    int chan_number = channelList->number;
    int i_chan = 0;

529
    nmxp_log(NMXP_LOG_NORM, NMXP_LOG_D_CHANNEL, "%04d channels:\n", chan_number);
530 531 532

    for (i_chan = 0; i_chan < chan_number; i_chan++)
    {
533 534 535
	nmxp_log(NMXP_LOG_NORM, NMXP_LOG_D_CHANNEL, "%04d %12d %s\n",
		i_chan+1, channelList->channel[i_chan].key,
		NMXP_LOG_STR(channelList->channel[i_chan].name));
536 537 538 539
    }

}

Matteo Quintiliani's avatar
Matteo Quintiliani committed
540 541 542 543 544

void nmxp_meta_chan_free(NMXP_META_CHAN_LIST **chan_list) {
    NMXP_META_CHAN_LIST *iter = *chan_list;
    NMXP_META_CHAN_LIST *iter_next = NULL;

545
    nmxp_log(NMXP_LOG_NORM, NMXP_LOG_D_CHANNEL, "nmxp_meta_chan_free()\n");
Matteo Quintiliani's avatar
Matteo Quintiliani committed
546 547 548 549

    if(iter) {
	iter_next = iter->next;
	while(iter) {
550
	    NMXP_MEM_FREE(iter);
Matteo Quintiliani's avatar
Matteo Quintiliani committed
551 552 553 554 555 556 557 558
	    iter = iter_next;
	    iter_next = iter->next;
	}
	*chan_list = NULL;
    }

}

559
int nmxp_meta_chan_compare(NMXP_META_CHAN_LIST *item1, NMXP_META_CHAN_LIST *item2, NMXP_META_CHAN_LIST_SORT_TYPE sorttype) {
560
    int ret = 0;
561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586
    switch(sorttype) {
	case NMXP_META_SORT_KEY:
	    if(item1->key > item2->key) {
		ret = 1;
	    } else if(item1->key < item2->key) {
		ret = -1;
	    }
	    break;
	case NMXP_META_SORT_NAME:
	    ret = strcmp(item1->name, item2->name);
	    break;
	case NMXP_META_SORT_START_TIME:
	    if(item1->start_time > item2->start_time) {
		ret = 1;
	    } else if(item1->start_time < item2->start_time) {
		ret = -1;
	    }
	    break;
	case NMXP_META_SORT_END_TIME:
	    if(item1->end_time > item2->end_time) {
		ret = 1;
	    } else if(item1->end_time < item2->end_time) {
		ret = -1;
	    }
	    break;
	default:
587
	    nmxp_log(NMXP_LOG_ERR, NMXP_LOG_D_CHANNEL, "Sort type %d not defined!\n", sorttype);
588
	    break;
589 590 591 592
    }
    return ret;
}

593
NMXP_META_CHAN_LIST *nmxp_meta_chan_add(NMXP_META_CHAN_LIST **chan_list, int32_t key, char *name, int32_t start_time, int32_t end_time, char *network, NMXP_META_CHAN_LIST_SORT_TYPE sorttype) {
Matteo Quintiliani's avatar
Matteo Quintiliani committed
594 595 596
    NMXP_META_CHAN_LIST *iter = NULL;
    NMXP_META_CHAN_LIST *new_item = NULL;

597
    if(sorttype != NMXP_META_SORT_KEY  &&  sorttype != NMXP_META_SORT_NAME) {
598 599
	nmxp_log(NMXP_LOG_ERR, NMXP_LOG_D_CHANNEL,
		"nmxp_meta_chan_add() can only accept NMXP_META_SORT_KEY or NMXP_META_SORT_NAME. Fixed NMXP_META_SORT_KEY!\n");
600 601
	sorttype = NMXP_META_SORT_KEY;
    }
Matteo Quintiliani's avatar
Matteo Quintiliani committed
602

603
    new_item = (NMXP_META_CHAN_LIST *) NMXP_MEM_MALLOC(sizeof(NMXP_META_CHAN_LIST));
Matteo Quintiliani's avatar
Matteo Quintiliani committed
604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623
    new_item->key = 0;
    new_item->name[0] = 0;
    new_item->start_time = 0;
    new_item->end_time = 0;
    new_item->network[0] = 0;
    new_item->next = NULL;
    new_item->key = key;
    if(name) {
	strncpy(new_item->name, name, 12);
    }
    new_item->start_time = start_time;
    new_item->end_time = end_time;
    if(network) {
	strncpy(new_item->network, network, 12);
    }


    if(*chan_list == NULL) {
	*chan_list = new_item;
    } else {
624
	if(nmxp_meta_chan_compare(new_item, *chan_list, sorttype) < 0) {
Matteo Quintiliani's avatar
Matteo Quintiliani committed
625 626 627
	    new_item->next = *chan_list;
	    *chan_list = new_item;
	} else {
628
	    for(iter = *chan_list; iter->next != NULL  && nmxp_meta_chan_compare(new_item, iter->next, sorttype) > 0; iter = iter->next) {
Matteo Quintiliani's avatar
Matteo Quintiliani committed
629 630 631 632 633 634 635 636 637 638 639 640 641
	    }
	    new_item->next = iter->next;
	    iter->next = new_item;
	}
    }

    return new_item;
}

NMXP_META_CHAN_LIST *nmxp_meta_chan_search_key(NMXP_META_CHAN_LIST *chan_list, int32_t key) {
    NMXP_META_CHAN_LIST *iter = chan_list;
    int found = 0;

Matteo Quintiliani's avatar
Matteo Quintiliani committed
642
    /* nmxp_log(NMXP_LOG_NORM, NMXP_LOG_D_CHANNEL, "nmxp_meta_chan_search_key()\n"); */
Matteo Quintiliani's avatar
Matteo Quintiliani committed
643 644 645 646 647 648 649 650 651 652 653 654 655 656 657

    while(iter != NULL  &&  !found) {
	if(iter->key == key) {
	    found = 1;
	} else {
	    iter = iter->next;
	}
    }

    return iter;
}

NMXP_META_CHAN_LIST *nmxp_meta_chan_set_name(NMXP_META_CHAN_LIST *chan_list, int32_t key, char *name) {
    NMXP_META_CHAN_LIST *ret = NULL;

658
    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_CHANNEL, "nmxp_meta_chan_set_name()\n");
Matteo Quintiliani's avatar
Matteo Quintiliani committed
659 660 661 662 663 664 665 666 667 668 669

    if( (ret = nmxp_meta_chan_search_key(chan_list, key)) ) {
	strncpy(ret->name, name, 12);
    }

    return ret;
}

NMXP_META_CHAN_LIST *nmxp_meta_chan_set_times(NMXP_META_CHAN_LIST *chan_list, int32_t key, int32_t start_time, int32_t end_time) {
    NMXP_META_CHAN_LIST *ret = NULL;

Matteo Quintiliani's avatar
Matteo Quintiliani committed
670
    /* nmxp_log(NMXP_LOG_NORM, NMXP_LOG_D_CHANNEL, "nmxp_meta_chan_set_times()\n"); */
Matteo Quintiliani's avatar
Matteo Quintiliani committed
671 672 673 674 675 676 677 678 679 680 681 682

    if( (ret = nmxp_meta_chan_search_key(chan_list, key)) ) {
	ret->start_time = start_time;
	ret->end_time = end_time;
    }

    return ret;
}

NMXP_META_CHAN_LIST *nmxp_meta_chan_set_network(NMXP_META_CHAN_LIST *chan_list, int32_t key, char *network) {
    NMXP_META_CHAN_LIST *ret = NULL;

683
    nmxp_log(NMXP_LOG_NORM, NMXP_LOG_D_CHANNEL, "nmxp_meta_chan_set_network()\n");
Matteo Quintiliani's avatar
Matteo Quintiliani committed
684 685 686 687 688 689 690 691 692 693

    if( (ret = nmxp_meta_chan_search_key(chan_list, key)) ) {
	strncpy(ret->network, network, 12);
    }

    return ret;
}

void nmxp_meta_chan_print(NMXP_META_CHAN_LIST *chan_list) {
    NMXP_META_CHAN_LIST *iter = chan_list;
694
    char str_start_time[NMXP_DATA_MAX_SIZE_DATE], str_end_time[NMXP_DATA_MAX_SIZE_DATE];
Matteo Quintiliani's avatar
Matteo Quintiliani committed
695 696
    int i_chan = 0;

Matteo Quintiliani's avatar
Matteo Quintiliani committed
697 698 699
    str_start_time[0] = 0;
    str_end_time[0] = 0;

700
    nmxp_log(NMXP_LOG_NORM, NMXP_LOG_D_CHANNEL, "nmxp_meta_chan_print()\n");
Matteo Quintiliani's avatar
Matteo Quintiliani committed
701 702 703 704 705

    while(iter != NULL) {
	nmxp_data_to_str(str_start_time, iter->start_time);
	nmxp_data_to_str(str_end_time,   iter->end_time);

706 707
	nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "%04d %12d %6s%c%-11s (%s  -  %s)\n",
		i_chan+1,
Matteo Quintiliani's avatar
Matteo Quintiliani committed
708
		iter->key,
709
		NMXP_LOG_STR(iter->network),
710
		(strcmp(iter->network, "")==0)? ' ' : '.',
711 712 713
		NMXP_LOG_STR(iter->name),
		NMXP_LOG_STR(str_start_time),
		NMXP_LOG_STR(str_end_time)
Matteo Quintiliani's avatar
Matteo Quintiliani committed
714 715
		);
	iter = iter->next;
716
	i_chan++;
Matteo Quintiliani's avatar
Matteo Quintiliani committed
717 718 719 720
    }
}


721 722
void nmxp_meta_chan_print_with_match(NMXP_META_CHAN_LIST *chan_list, char *sta_chan_list) {
    NMXP_META_CHAN_LIST *iter = chan_list;
723
    char str_start_time[NMXP_DATA_MAX_SIZE_DATE], str_end_time[NMXP_DATA_MAX_SIZE_DATE];
724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777
    int i_chan = 0;
    int ret_match = 0;
    int istalist, ista;
    char sta_chan_code_pattern[100];

    str_start_time[0] = 0;
    str_end_time[0] = 0;

    nmxp_log(NMXP_LOG_NORM, NMXP_LOG_D_CHANNEL, "nmxp_meta_chan_print()\n");

    while(iter != NULL) {
	nmxp_data_to_str(str_start_time, iter->start_time);
	nmxp_data_to_str(str_end_time,   iter->end_time);

	if(sta_chan_list) {

	    ret_match = 0;
	    istalist = 0;
	    while(sta_chan_list[istalist] != sep_chan_list  &&  sta_chan_list[istalist] != 0  &&  ret_match == 0) {

		/* Build sta_chan_code_pattern from sta_chan_list */
		ista = 0;
		while(sta_chan_list[istalist] != sep_chan_list  &&  sta_chan_list[istalist] != 0) {
		    sta_chan_code_pattern[ista++] = sta_chan_list[istalist++];
		}
		sta_chan_code_pattern[ista] = 0;
		if(sta_chan_list[istalist] == sep_chan_list) {
		    istalist++;
		}

		ret_match = nmxp_chan_match(iter->name, sta_chan_code_pattern);
	    }

	} else {
	    ret_match = 1;
	}
	if(ret_match == 1) {
	    nmxp_log(NMXP_LOG_NORM_NO, NMXP_LOG_D_ANY, "%04d %12d %6s%c%-11s (%s  -  %s)\n",
		    i_chan+1,
		    iter->key,
		    NMXP_LOG_STR(iter->network),
		    (strcmp(iter->network, "")==0)? ' ' : '.',
		    NMXP_LOG_STR(iter->name),
		    NMXP_LOG_STR(str_start_time),
		    NMXP_LOG_STR(str_end_time)
		    );
	}
	iter = iter->next;
	i_chan++;
    }
}



Matteo Quintiliani's avatar
Matteo Quintiliani committed
778