1 /*  taxcs.c
2 * ===========================================================================
3 *
4 *                            PUBLIC DOMAIN NOTICE
5 *               National Center for Biotechnology Information
6 *
7 *  This software/database is a "United States Government Work" under the
8 *  terms of the United States Copyright Act.  It was written as part of
9 *  the author's official duties as a United States Government employee and
10 *  thus cannot be copyrighted.  This software/database is freely available
11 *  to the public for use. The National Library of Medicine and the U.S.
12 *  Government have not placed any restriction on its use or reproduction.
13 *
14 *  Although all reasonable efforts have been taken to ensure the accuracy
15 *  and reliability of the software and data, the NLM and the U.S.
16 *  Government do not and cannot warrant the performance or results that
17 *  may be obtained by using this software or data. The NLM and the U.S.
18 *  Government disclaim all warranties, express or implied, including
19 *  warranties of performance, merchantability or fitness for any particular
20 *  purpose.
21 *
22 *  Please cite the author in any work or product based on this material.
23 *
24 * ===========================================================================
25 *
26 * File Name:  taxcs.c
27 *
28 * Author:  Vladimir Soussov
29 *
30 * File Description:  taxonomy server/client common utilities
31 *
32 *
33 * $Log: taxcs.c,v $
34 * Revision 1.3  1998/09/01 15:41:39  soussov
35 * removing warnings
36 *
37 * Revision 1.2  1998/04/01 17:34:06  soussov
38 * changed tp include <>
39 *
40 * Revision 1.1  1998/02/10 20:11:59  soussov
41 * taxon2 related soft
42 *
43 * Revision 1.2  1997/05/12 18:32:33  soussov
44 * 05/12/97
45 *
46  * Revision 1.1.1.1  1997/04/30  21:29:41  soussov
47  * initial tree for taxon2
48  *
49 *
50 */
51 
52 #include <time.h>
53 #include <stdlib.h>
54 #include <txcommon.h>
55 
56 /*
57 typedef struct t_nameClass {
58     Int2 priority;
59     char class_txt[34];
60 } TaxNameClass, PNTR TaxNameClassPtr;
61  */
62 static Int2 class_alloced= 16;
63 static TaxNameClassPtr name_class= NULL;
64 
tax_getBaseTime(void)65 Int4 tax_getBaseTime(void)
66 {
67     static Int4 basetime= 0;
68     static Boolean baseTime_set= FALSE;
69 
70     if(!baseTime_set) {
71 	Int4 yy, vv, dd= 0;
72 	time_t t= 0;
73 
74 	vv= gmtime(&t)->tm_year;
75 
76 	if(vv > 0) {
77 	    for(yy= 1900; yy < (1900 + vv); yy++) {
78 		if(yy%4 == 0) dd+= 366;
79 		else dd+= 365;
80 	    }
81 
82 	    dd--;
83 
84 	    basetime= (dd*24)*60;
85 	}
86 	baseTime_set= TRUE;
87 
88     }
89 
90     return basetime;
91 }
92 
tax_prntTime(Int4 t)93 CharPtr tax_prntTime(Int4 t)
94 {
95     time_t ttt= (t - tax_getBaseTime())* 60;
96 
97     return asctime(localtime(&ttt));
98 }
99 
tax_getTime(void)100 Int4 tax_getTime(void)
101 {
102     time_t ttt= time(NULL);
103     Int4 t= ttt/60 + tax_getBaseTime();
104     return t;
105 }
106 
tax_addNameClass(Int4 class_cde,CharPtr class_txt,Int4 priority)107 Boolean tax_addNameClass(Int4 class_cde, CharPtr class_txt, Int4 priority)
108 {
109     Int2 i;
110 
111     if(name_class == NULL) {
112 	name_class= MemNew(sizeof(TaxNameClass)*class_alloced);
113 	if(name_class == NULL) return FALSE;
114 
115 	for(i= 0; i < class_alloced; i++) {
116 	    name_class[i].priority= 1000;
117 	    name_class[i].class_txt[0]= name_class[i].class_txt[33]= '\0';
118 	}
119     }
120 
121     if(class_cde < 0) return FALSE;
122 
123     if(class_cde >= class_alloced) {
124 	TaxNameClassPtr tmp= MemMore(name_class, sizeof(TaxNameClass)*(class_cde + 8));
125 
126 	if(tmp == NULL) return FALSE;
127 
128 	name_class= tmp;
129 	for(i= class_alloced; i < class_cde + 8; i++) {
130 	    name_class[i].priority= 1000;
131 	    name_class[i].class_txt[0]= name_class[i].class_txt[33]= '\0';
132 	}
133 	class_alloced= class_cde + 8;
134     }
135 
136     name_class[class_cde].priority= priority;
137     StringNCpy(name_class[class_cde].class_txt, class_txt, 33);
138 
139     return TRUE;
140 }
141 
tax_getNameClass(Int4 class_cde,Int4Ptr priority)142 CharPtr tax_getNameClass(Int4 class_cde, Int4Ptr priority)
143 {
144     if((class_cde < 0) || (class_cde >= class_alloced)) {
145 	if(priority != NULL) *priority= 1000;
146 	return "";
147     }
148 
149     if(priority != NULL) *priority= name_class[class_cde].priority;
150     return name_class[class_cde].class_txt;
151 }
152 
tax_getClass_cde(CharPtr class_txt)153 Int4 tax_getClass_cde(CharPtr class_txt)
154 {
155     Int2 i;
156 
157     if(class_txt == NULL) return -1;
158 
159     for(i= 0; i < class_alloced; i++) {
160 	if(StringICmp(name_class[i].class_txt, class_txt) == 0) return (Int4)i;
161     }
162 
163     return -1;
164 }
165 
tax_dumpNameClasses(void (* dmpFunc)(VoidPtr,Int2,Int2,CharPtr),VoidPtr usrData)166 Boolean tax_dumpNameClasses(void (*dmpFunc)(VoidPtr, Int2, Int2, CharPtr), VoidPtr usrData)
167 {
168     Int2 i;
169 
170     if((name_class == NULL) || (dmpFunc == NULL)) return FALSE;
171 
172     for(i= 0; i < class_alloced; i++) {
173 	if(name_class[i].class_txt[0] != '\0') {
174 	    (*dmpFunc)(usrData, i, name_class[i].priority, name_class[i].class_txt);
175 	}
176     }
177     return TRUE;
178 }
179 
180 /*
181 typedef struct t_rank {
182     char rank_txt[64];
183 } TaxRank, PNTR TaxRankPtr;
184  */
185 
186 static Int2 rank_alloced= 48, d_rank= 1;
187 static TaxRankPtr tax_rank= NULL;
188 
tax_addRank(Int2 rank_id,CharPtr rank_txt)189 Boolean tax_addRank(Int2 rank_id, CharPtr rank_txt)
190 {
191     Int2 i;
192 
193     rank_id+= d_rank;
194 
195     if(tax_rank == NULL) {
196 	tax_rank= MemNew(sizeof(TaxRank)*rank_alloced);
197 	if(tax_rank == NULL) return FALSE;
198 
199 	for(i= 0; i < rank_alloced; i++) {
200 	    tax_rank[i].rank_txt[0]= tax_rank[i].rank_txt[63]= '\0';
201 	}
202     }
203 
204     if(rank_id < 0) return FALSE;
205 
206     if(rank_id >= rank_alloced) {
207 	TaxRankPtr tmp= MemMore(tax_rank, sizeof(TaxRank)*(rank_id + 8));
208 
209 	if(tmp == NULL) return FALSE;
210 
211 	tax_rank= tmp;
212 	for(i= rank_alloced; i < rank_id + 8; i++) {
213 	    tax_rank[i].rank_txt[0]= tax_rank[i].rank_txt[63]= '\0';
214 	}
215 	rank_alloced= rank_id + 8;
216     }
217 
218     StringNCpy(tax_rank[rank_id].rank_txt, rank_txt, 63);
219 
220     return TRUE;
221 }
222 
tax_getRank(Int2 rank_id)223 CharPtr tax_getRank(Int2 rank_id)
224 {
225     rank_id+= d_rank;
226 
227     if((rank_id < 0) || (rank_id >= rank_alloced)) return "";
228 
229     return tax_rank[rank_id].rank_txt;
230 }
231 
tax_getRankId(CharPtr rank_txt)232 Int2 tax_getRankId(CharPtr rank_txt)
233 {
234     Int2 i;
235 
236     if(rank_txt == NULL) return -d_rank;
237 
238     for(i= 0; i < rank_alloced; i++) {
239 	if(StringICmp(tax_rank[i].rank_txt, rank_txt) == 0) return i - d_rank;
240     }
241 
242     return -d_rank;
243 }
244 
245 
tax_dumpRanks(void (* dmpFunc)(VoidPtr,Int2,CharPtr),VoidPtr usrData)246 Boolean tax_dumpRanks(void (*dmpFunc)(VoidPtr, Int2, CharPtr), VoidPtr usrData)
247 {
248     Int2 i;
249 
250     if((tax_rank == NULL) || (dmpFunc == NULL)) return FALSE;
251 
252     for(i= 0; i < rank_alloced; i++) {
253 	if(tax_rank[i].rank_txt[0] != '\0') {
254 	    (*dmpFunc)(usrData, i - d_rank, tax_rank[i].rank_txt);
255 	}
256     }
257     return TRUE;
258 }
259 
260 /*
261 typedef struct t_division {
262     char div_cde[4];
263     char div_txt[64];
264 } TaxDivision, PNTR TaxDivisionPtr;
265  */
266 
267 static Int2 div_alloced= 16;
268 static TaxDivisionPtr tax_div= NULL;
269 
tax_addDivision(Int4 div_id,CharPtr div_cde,CharPtr div_txt)270 Boolean tax_addDivision(Int4 div_id, CharPtr div_cde, CharPtr div_txt)
271 {
272     Int2 i;
273 
274     if(tax_div == NULL) {
275 	tax_div= MemNew(sizeof(TaxDivision)*div_alloced);
276 	if(tax_div == NULL) return FALSE;
277 
278 	for(i= 0; i < div_alloced; i++) {
279 	    tax_div[i].div_cde[0]= tax_div[i].div_cde[3]=
280 		tax_div[i].div_txt[0]= tax_div[i].div_txt[63]= '\0';
281 	}
282     }
283 
284     if(div_id < 0) return FALSE;
285 
286     if(div_id >= div_alloced) {
287 	TaxDivisionPtr tmp= MemMore(tax_div, sizeof(TaxDivision)*(div_id + 8));
288 
289 	if(tmp == NULL) return FALSE;
290 
291 	tax_div= tmp;
292 	for(i= div_alloced; i < div_id + 8; i++) {
293 	    tax_div[i].div_cde[0]= tax_div[i].div_cde[3]=
294 		tax_div[i].div_txt[0]= tax_div[i].div_txt[63]= '\0';
295 	}
296 	div_alloced= div_id + 8;
297     }
298 
299     StringNCpy(tax_div[div_id].div_cde, div_cde, 3);
300     StringNCpy(tax_div[div_id].div_txt, div_txt, 63);
301 
302     return TRUE;
303 }
304 
tax_getDivision(Int2 div_id,CharPtr * div_cde,CharPtr * div_txt)305 Boolean tax_getDivision(Int2 div_id, CharPtr* div_cde, CharPtr* div_txt)
306 {
307     if((div_id < 0) || (div_id >= div_alloced)) return FALSE;
308 
309     if(div_cde != NULL) *div_cde= tax_div[div_id].div_cde;
310     if(div_txt != NULL) *div_txt= tax_div[div_id].div_txt;
311     return TRUE;
312 }
313 
tax_getDivisionId(CharPtr div_cde,CharPtr div_txt)314 Int2 tax_getDivisionId(CharPtr div_cde, CharPtr div_txt)
315 {
316     Int2 i;
317 
318     if(div_cde != NULL) {
319 	for(i= 0; i < div_alloced; i++) {
320 	    if(StringICmp(tax_div[i].div_cde, div_cde) == 0) return i;
321 	}
322     }
323 
324     if(div_txt != NULL) {
325 	for(i= 0; i < div_alloced; i++) {
326 	    if(StringICmp(tax_div[i].div_txt, div_txt) == 0) return i;
327 	}
328     }
329 
330     return -1;
331 }
332 
tax_dumpDivisions(void (* dmpFunc)(VoidPtr,Int2,CharPtr,CharPtr),VoidPtr usrData)333 Boolean tax_dumpDivisions(void (*dmpFunc)(VoidPtr, Int2, CharPtr, CharPtr), VoidPtr usrData)
334 {
335     Int2 i;
336 
337     if((tax_div == NULL) || (dmpFunc == NULL)) return FALSE;
338 
339     for(i= 0; i < div_alloced; i++) {
340 	if(tax_div[i].div_txt[0] != '\0') {
341 	    (*dmpFunc)(usrData, i, tax_div[i].div_cde, tax_div[i].div_txt);
342 	}
343     }
344     return TRUE;
345 }
346 
347 /*
348 typedef struct t_genCode {
349     char gc_name[128];
350 } TaxGenCode, PNTR TaxGenCodePtr;
351  */
352 static Int2 gc_alloced= 20;
353 static TaxGenCodePtr tax_gc= NULL;
354 
tax_addGC(Int2 gc_id,CharPtr gc_txt)355 Boolean tax_addGC(Int2 gc_id, CharPtr gc_txt)
356 {
357     Int2 i;
358 
359     if(tax_gc == NULL) {
360 	tax_gc= MemNew(sizeof(TaxGenCode)*gc_alloced);
361 	if(tax_gc == NULL) return FALSE;
362 
363 	for(i= 0; i < gc_alloced; i++) {
364 	    tax_gc[i].gc_name[0]= tax_gc[i].gc_name[127]= '\0';
365 	}
366     }
367 
368     if(gc_id < 0) return FALSE;
369 
370     if(gc_id >= gc_alloced) {
371 	TaxGenCodePtr tmp= MemMore(tax_gc, sizeof(TaxGenCode)*(gc_id + 8));
372 
373 	if(tmp == NULL) return FALSE;
374 
375 	tax_gc= tmp;
376 	for(i= gc_alloced; i < gc_id + 8; i++) {
377 	    tax_gc[i].gc_name[0]= tax_gc[i].gc_name[127]= '\0';
378 	}
379 	gc_alloced= gc_id + 8;
380     }
381 
382     StringNCpy(tax_gc[gc_id].gc_name, gc_txt, 127);
383 
384     return TRUE;
385 }
386 
tax_getGCName(Int2 gc_id)387 CharPtr tax_getGCName(Int2 gc_id)
388 {
389 
390     if((gc_id < 0) || (gc_id >= gc_alloced)) return "";
391 
392     return tax_gc[gc_id].gc_name;
393 }
394 
tax_getGCId(CharPtr gc_txt)395 Int2 tax_getGCId(CharPtr gc_txt)
396 {
397     Int2 i;
398 
399     if(gc_txt == NULL) return -1;
400 
401     for(i= 0; i < gc_alloced; i++) {
402 	if(StringICmp(tax_gc[i].gc_name, gc_txt) == 0) return i;
403     }
404 
405     return -1;
406 }
407 
tax_dumpGCs(void (* dmpFunc)(VoidPtr,Int2,CharPtr),VoidPtr usrData)408 Boolean tax_dumpGCs(void (*dmpFunc)(VoidPtr, Int2, CharPtr), VoidPtr usrData)
409 {
410     Int2 i;
411 
412     if((tax_gc == NULL) || (dmpFunc == NULL)) return FALSE;
413 
414     for(i= 0; i < gc_alloced; i++) {
415 	if(tax_gc[i].gc_name[0] != '\0') {
416 	    (*dmpFunc)(usrData, i, tax_gc[i].gc_name);
417 	}
418     }
419     return TRUE;
420 }
421 
422 
423 #ifdef TAX_LOG
424 
425 #include <rex_util.h>
426 
get_token(CharPtr str,CharPtr token)427 static CharPtr get_token(CharPtr str, CharPtr token)
428 {
429   int i;
430 
431   token[2]= '\0';
432 
433   while(IS_WHITESP(*str)) {
434     if(*str == '\0') return NULL;
435     ++str;
436   }
437 
438   if(*str == '\0') return NULL;
439 
440   for(i= 1; i < 250; i++) {
441     if(IS_WHITESP(*str)) {
442       token[i]= ' ';
443       token[i+1]= '\0';
444       return str;
445     }
446 
447     if(*str == '\0') {
448       token[i]= ' ';
449       token[i+1]= '\0';
450       return NULL;
451     }
452 
453     token[i]= TO_UPPER(*str);
454     str++;
455   }
456 
457   token[i]= ' ';
458   token[i+1]= '*';
459   token[i+2]= '\0';
460   return str;
461 }
462 
tax_matchName(CharPtr orgName,CharPtr str,Int4 mode)463 Boolean tax_matchName(CharPtr orgName, CharPtr str, Int4 mode)
464 {
465     if(StringICmp(orgName, str) == 0) return TRUE;
466 
467     if(mode == TAX_RE_SEARCH) {
468 	/* regular expression search */
469 	char nBuff[256];
470 	Int4 k;
471 	rex_handler rh;
472 	Boolean res;
473 
474 	strncpy(&nBuff[1], str, 250);
475 	nBuff[0]= '@';
476 	k= strlen(nBuff);
477 	nBuff[k]= '@';
478 	nBuff[k+1]= '\0';
479 	rh= rex_setExpr(nBuff, REX_NO_CASE | REX_NO_SPACE);
480 	if(rh == NULL) return 0;
481 
482 	nBuff[0]= '@';
483 	for(k= 0; (k < 250) && (orgName[k] != '\0'); k++) {
484 	    nBuff[k+1]= toupper(orgName[k]);
485 	}
486 	k++;
487 	nBuff[k]= '@';
488 	nBuff[k+1]= '\0';
489 
490 	res= rex_cmp(rh, nBuff);
491 
492 	free(rh);
493 	return res;
494     }
495 
496     if(mode == TAX_TOKEN_SEARCH) {
497 	char nBuff[256];
498 	Int4 k;
499 	rex_handler rh[16];
500 	Int2 nof_rh, j, res;
501 	CharPtr tail= str;
502 
503 	nBuff[0]= '*';
504 	nBuff[1]= ' ';
505 	for(nof_rh= 0; (nof_rh != 16) && (tail != NULL); nof_rh++) {
506 	    tail= get_token(tail, nBuff);
507 	    rh[nof_rh]= rex_setExpr(nBuff, REX_NO_CASE | REX_NO_SPACE);
508 	    if(rh[nof_rh] == NULL) nof_rh--;
509 	}
510 	if(nof_rh < 1) return FALSE;
511 
512 	nBuff[0]= ' ';
513 
514 	tail= orgName;
515 	for(k= 0; (k < 250) && (tail[k] != '\0'); k++) {
516 	    nBuff[k+1]= toupper(tail[k]);
517 	}
518 	k++;
519 	nBuff[k]= ' ';
520 	nBuff[k+1]= '\0';
521 
522 	for(res= 1, j= 0; (j < nof_rh) && (res > 0); j++) {
523 	    res= rex_cmp(rh[j], nBuff);
524 	}
525 
526 	for(j= 0; j < nof_rh; j++) {
527 	    free(rh[j]);
528 	}
529 	return (res != 0)? TRUE : FALSE;
530     }
531 
532     return FALSE;
533 }
534 #endif
535