1 #ifdef _cplusplus
2 extern "C" {
3 #endif
4 #include "seqalign.h"
5
6 /* Function: is_gapped_SeqAlign(sa,pos)
7 *
8 * Descrip: Tells you whether either . or - characters occur at
9 * a position. Uses C-style coordinates
10 *
11 *
12 * Arg: sa [UNKN ] Undocumented argument [SeqAlign *]
13 * Arg: pos [UNKN ] Undocumented argument [int]
14 *
15 * Return [UNKN ] Undocumented return value [boolean]
16 *
17 */
18 # line 46 "seqalign.dy"
is_gapped_SeqAlign(SeqAlign * sa,int pos)19 boolean is_gapped_SeqAlign(SeqAlign * sa,int pos)
20 {
21 int i;
22
23 assert(sa != NULL);
24 assert(pos < sa->seq[0]->len);
25
26 for(i=0;i<sa->len;i++) {
27 if( sa->seq[i]->seq[pos] == '.' ||
28 sa->seq[i]->seq[pos] == '-' ) {
29 return TRUE;
30 }
31 }
32
33 return FALSE;
34
35 }
36
37 /* Function: trim_from_N_SeqAlign(sa)
38 *
39 * Descrip: trims sequence alignments to first and last
40 * non N character (for DNA obviously)
41 *
42 *
43 * Arg: sa [UNKN ] Undocumented argument [SeqAlign *]
44 *
45 * Return [UNKN ] Undocumented return value [SeqAlign *]
46 *
47 */
48 # line 68 "seqalign.dy"
trim_from_N_SeqAlign(SeqAlign * sa)49 SeqAlign * trim_from_N_SeqAlign(SeqAlign * sa)
50 {
51 int i;
52 int j;
53 int k;
54 int left = 0;
55 int right = 0;
56
57 SeqAlign * out;
58 Sequence * seq;
59
60 char buffer[MAXLINE];
61
62 assert(sa);
63 for(i=0;i<sa->len;i++) {
64 if( sa->seq[i]->len > left ) {
65 left = sa->seq[i]->len;
66 }
67 }
68
69 for(i=0;i<sa->len;i++) {
70 for(j=0;j<sa->seq[i]->len;j++) {
71 if( sa->seq[i]->seq[j] != 'N' ) {
72 break;
73 }
74 }
75 if( left > j ) {
76 left = j;
77 }
78
79 for(j=sa->seq[i]->len-1;j>=0;j--) {
80 if( sa->seq[i]->seq[j] != 'N' ) {
81 break;
82 }
83 }
84
85 if ( right < j ) {
86 right = j;
87 }
88
89 }
90
91
92 right++;
93 /* now we have left and right, make new sa */
94
95 out = SeqAlign_alloc_len(sa->len);
96
97 for(i=0;i<sa->len;i++) {
98 seq = Sequence_alloc();
99 add_SeqAlign(out,seq);
100 seq->name = stringalloc(sa->seq[i]->name);
101
102 for(j=left,k=0;j<right && j<sa->seq[i]->len;j++,k++) {
103 buffer[k] = sa->seq[i]->seq[j];
104 }
105 for(;j<right;j++,k++) {
106 buffer[k] = 'N';
107 }
108 buffer[k] = '\0';
109
110 seq->seq = stringalloc(buffer);
111 seq->len = k;
112 seq->type = SEQUENCE_DNA;
113 }
114
115
116 return out;
117
118 }
119
120 /* Function: reweight_SeqAlign(sal)
121 *
122 * Descrip: Provides reweighting for a seqalign so all the weights
123 * add up to 1.0
124 *
125 *
126 * Arg: sal [UNKN ] Undocumented argument [SeqAlign *]
127 *
128 */
129 # line 143 "seqalign.dy"
reweight_SeqAlign(SeqAlign * sal)130 void reweight_SeqAlign(SeqAlign * sal)
131 {
132 int i;
133 double total =0.0;
134
135 for(i=0;i<sal->len;i++) {
136 total += sal->seq[i]->weight;
137 }
138
139 for(i=0;i<sal->len;i++) {
140 sal->seq[i]->weight = sal->seq[i]->weight/ total;
141 }
142
143
144 }
145
146 /* Function: ColumnCount_from_SeqAlign(sa,col)
147 *
148 * Descrip: Gives you a column count
149 *
150 * You are supposed to have enough sense to
151 * cache this on the caller if you need it again
152 *
153 *
154 * Arg: sa [UNKN ] Undocumented argument [SeqAlign *]
155 * Arg: col [UNKN ] Undocumented argument [int]
156 *
157 * Return [UNKN ] Undocumented return value [ColumnCount *]
158 *
159 */
160 # line 165 "seqalign.dy"
ColumnCount_from_SeqAlign(SeqAlign * sa,int col)161 ColumnCount * ColumnCount_from_SeqAlign(SeqAlign * sa,int col)
162 {
163 ColumnCount * out;
164 double count[27] = { 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
165 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
166 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 , 0.0};
167 int i;
168
169 if( sa == NULL || sa->seq[0]->len < col ) {
170 warn("Cannot make column count at %d - out of range/seqalign null",col);
171 return NULL;
172 }
173
174 for(i=0;i<sa->len;i++) {
175
176 if( sa->seq[i]->len < col ) {
177 warn("For seqalign sequence %d (%s), although first seq ok, this doesn't extend to %d. Error.",i,sa->seq[i]->name,col);
178 return NULL;
179 }
180 if ( isalpha(sa->seq[i]->seq[col]) ) {
181 count[toupper(sa->seq[i]->seq[col]) - 'A']++;
182 } else {
183 count[26]++;
184 }
185
186 }
187
188 out = ColumnCount_alloc();
189 for(i=0;i<27;i++)
190 out->count[i] = count[i];
191
192 return out;
193 }
194
195 /* Function: write_selex_SeqAlign(sa,name_len,block_len,ofp)
196 *
197 * Descrip: Writes selex format
198 *
199 *
200 * Arg: sa [UNKN ] Undocumented argument [const SeqAlign *]
201 * Arg: name_len [UNKN ] Undocumented argument [int]
202 * Arg: block_len [UNKN ] Undocumented argument [int]
203 * Arg: ofp [UNKN ] Undocumented argument [FILE *]
204 *
205 * Return [UNKN ] Undocumented return value [boolean]
206 *
207 */
208 # line 202 "seqalign.dy"
write_selex_SeqAlign(const SeqAlign * sa,int name_len,int block_len,FILE * ofp)209 boolean write_selex_SeqAlign(const SeqAlign * sa,int name_len,int block_len,FILE * ofp)
210 {
211 int col;
212 int i;
213 int j;
214 int k;
215
216 assert(sa);
217 assert(ofp);
218 assert(name_len > 1);
219 assert(block_len > 1);
220
221
222 for(col=0;col<sa->seq[0]->len;) {
223 for(j=0;j<sa->len;j++) {
224 assert(sa->seq[j]->name);
225
226 for(k=0;k<name_len && sa->seq[j]->name[k] != '\0';k++) {
227 fputc(sa->seq[j]->name[k],ofp);
228 }
229 if( sa->seq[j]->name[k] == '\0' && k >= name_len ) {
230 warn("In printing selex alignment, name %s is truncated at %d",sa->seq[j]->name,k);
231 }
232
233 /* put in the rest of k */
234 for(;k<name_len;k++)
235 fputc(' ',ofp);
236
237 /* add one space */
238 fputc(' ',ofp);
239
240 /* do the block */
241
242 assert(sa->seq[j]->seq);
243
244 for(i=col;(i - col) < block_len && i < sa->seq[j]->len ; i++) {
245 fputc(sa->seq[j]->seq[i],ofp);
246 }
247 fputc('\n',ofp);
248 } /* end over all sequences for this block */
249
250 col += block_len;
251 fprintf(ofp,"\n\n");
252 }
253
254 return TRUE;
255 }
256
257 /* Function: read_fasta_SeqAlign_file(filename)
258 *
259 * Descrip: Reads in fasta file opening the file
260 *
261 *
262 * Arg: filename [UNKN ] Undocumented argument [char *]
263 *
264 * Return [UNKN ] Undocumented return value [SeqAlign *]
265 *
266 */
267 # line 253 "seqalign.dy"
read_fasta_SeqAlign_file(char * filename)268 SeqAlign * read_fasta_SeqAlign_file(char * filename)
269 {
270 FILE * ifp;
271 SeqAlign * out;
272
273 ifp = openfile(filename,"r");
274 if( ifp == NULL ) {
275 warn("Cannot open file %s",filename);
276 return NULL;
277 }
278
279 out = read_fasta_SeqAlign(ifp);
280
281 fclose(ifp);
282
283 return out;
284 }
285
286 /* Function: read_fasta_SeqAlign(ifp)
287 *
288 * Descrip: Reads in fasta file style alignments
289 *
290 *
291 * Arg: ifp [UNKN ] Undocumented argument [FILE *]
292 *
293 * Return [UNKN ] Undocumented return value [SeqAlign *]
294 *
295 */
296 # line 274 "seqalign.dy"
read_fasta_SeqAlign(FILE * ifp)297 SeqAlign * read_fasta_SeqAlign(FILE * ifp)
298 {
299 Sequence * seq;
300 SeqAlign * out;
301
302 out = SeqAlign_alloc_std();
303
304 while( (seq = read_fasta_Sequence(ifp)) != NULL ) {
305 fprintf(stderr,"Adding sequence %s\n",seq->name);
306 add_SeqAlign(out,seq);
307 }
308
309 /* in multi-fasta alignments, this indicates the end */
310 if( out->len == 0 ) {
311 free_SeqAlign(out);
312 return NULL;
313 }
314
315 return out;
316 }
317
318 /* Function: write_fasta_SeqAlign(sa,ofp)
319 *
320 * Descrip: writes out Fasta file
321 *
322 *
323 * Arg: sa [UNKN ] Undocumented argument [SeqAlign *]
324 * Arg: ofp [UNKN ] Undocumented argument [FILE *]
325 *
326 */
327 # line 298 "seqalign.dy"
write_fasta_SeqAlign(SeqAlign * sa,FILE * ofp)328 void write_fasta_SeqAlign(SeqAlign * sa,FILE * ofp)
329 {
330 int i;
331
332 for(i=0;i<sa->len;i++) {
333 write_fasta_Sequence(sa->seq[i],ofp);
334 }
335 }
336
337 /* Function: read_selex_SeqAlign_file(filename)
338 *
339 * Descrip: Open files as well
340 *
341 *
342 * Arg: filename [UNKN ] Undocumented argument [char *]
343 *
344 * Return [UNKN ] Undocumented return value [SeqAlign *]
345 *
346 */
347 # line 310 "seqalign.dy"
read_selex_SeqAlign_file(char * filename)348 SeqAlign * read_selex_SeqAlign_file(char * filename)
349 {
350 FILE * ifp;
351 SeqAlign * out;
352
353 ifp = openfile(filename,"r");
354 if( ifp == NULL ) {
355 warn("Cannot open file %s",filename);
356 return NULL;
357 }
358
359 out = read_selex_SeqAlign(ifp);
360
361 fclose(ifp);
362
363 return out;
364 }
365
366
367 /* Function: read_selex_SeqAlign(ifp)
368 *
369 * Descrip: Reads in selex (Stockholm) alignment
370 *
371 * At the moment ignores all #= stuff on the
372 * sequence
373 *
374 * Read HMMER documentation for a definition of
375 * the format
376 *
377 *
378 * Arg: ifp [UNKN ] Undocumented argument [FILE *]
379 *
380 * Return [UNKN ] Undocumented return value [SeqAlign *]
381 *
382 */
383 # line 338 "seqalign.dy"
read_selex_SeqAlign(FILE * ifp)384 SeqAlign * read_selex_SeqAlign(FILE * ifp)
385 {
386 char buffer[4096];
387 SeqAlign * out;
388 Sequence * temp;
389 int i;
390 boolean isfirst;
391 boolean isfseq;
392 boolean isend;
393 char * name;
394 char * seq;
395 char * strip;
396 int pos;
397
398 out = SeqAlign_alloc_std();
399
400 while( fgets(buffer,4096,ifp) != NULL ) {
401 /*fprintf(stderr,"(selex) reading %s in selex alignment\n",buffer);*/
402 if( buffer[0] == '#' )
403 continue; /* skips over # */
404 if( buffer[0] == '/' && buffer[1] == '/' )
405 break;
406 if( !isspace(buffer[0]) ) {
407 /** in a block **/
408
409 i = 0; /* this is the first sequence */
410 if( out->len == 0 ) {
411 isfirst = TRUE;
412 isfseq = TRUE;
413 } else {
414 isfirst = FALSE;
415 isfseq = FALSE;
416 }
417
418 for(;;) {
419 /* strip trailing white space */
420
421 for(strip = buffer + strlen(buffer) - 1;
422 strip > buffer && isspace(*strip);strip--)
423 ;
424
425 strip++;
426 *strip = '\0';
427
428 for(name = seq = buffer;!isspace(*seq) && *seq; seq++)
429 ;
430
431 /** if '\0' - worry **/
432
433 if( !*seq ) {
434 warn("For name %s in selex alignment, no sequence!",name);
435 return out;
436 }
437 *seq = '\0';
438 if( isfirst == TRUE ) {
439 temp = empty_Sequence_from_dynamic_memory(stringalloc(name));
440 add_SeqAlign(out,temp);
441 } else {
442 if ( i >= out->len ) {
443 warn("For sequence %s, got over previous blocks size",name);
444 return NULL;
445 }
446
447 temp = out->seq[i++];
448 }
449
450 /* if is fseq, then find the next character */
451
452 if( isfseq == TRUE ) {
453 for(seq++;*seq && isspace(*seq);seq++)
454 ;
455 if( *seq == '\0' ) {
456 warn("In first sequence %s, got to end of line with no sequence!",name);
457 return NULL;
458 }
459
460 isfseq = FALSE;
461 pos = seq - buffer;
462 }
463 /* else pos is as normal */
464
465 /* map all non alnum chars to '-' */
466
467 for(seq = buffer+pos;*seq;seq++) {
468 if( !isalnum(*seq) ) {
469 *seq = '-';
470 }
471 }
472
473 /* add to sequence */
474 add_string_to_Sequence(temp,buffer+pos);
475 /* get next line */
476
477 while( (seq = fgets(buffer,4096,ifp)) != NULL ) {
478 /*fprintf(stderr,"(selex - 2nd loop) reading %s in selex alignment\n",buffer);*/
479 if( buffer[0] != '#' )
480 break;
481
482 if( buffer[0] == '/' && buffer[1] == '/' )
483 break;
484
485 }
486
487 /*fprintf(stderr,"Broken from second loop\n");*/
488
489 if( seq == NULL ) {
490 /*fprintf(stderr,"End of sequence?\n");*/
491 isend = TRUE;
492 break;
493 }
494
495 if( buffer[0] == '/' && buffer[1] == '/' ) {
496 /*fprintf(stderr,"double slash terminator?\n");*/
497 isend = TRUE;
498 break;
499 }
500
501 /* if it is blank, break out of block */
502 if( !isalnum(buffer[0]) ) {
503 /*fprintf(stderr,"Back to loop?\n");*/
504 break;
505 }
506
507 }
508
509 if( isend == TRUE )
510 break;
511 } /* end of was a non space line */
512
513 /* else - ignore it !*/
514
515 }
516
517 return out;
518 }
519
520
521
522
523
524 # line 503 "seqalign.c"
525 /* Function: swap_SeqAlign(list,i,j)
526 *
527 * Descrip: swap function: an internal for qsort_SeqAlign
528 * swaps two positions in the array
529 *
530 *
531 * Arg: list [UNKN ] List of structures to swap in [Sequence **]
532 * Arg: i [UNKN ] swap position [int]
533 * Arg: j [UNKN ] swap position [int]
534 *
535 */
536 /* swap function for qsort function */
swap_SeqAlign(Sequence ** list,int i,int j)537 void swap_SeqAlign(Sequence ** list,int i,int j)
538 {
539 Sequence * temp;
540 temp=list[i];
541 list[i]=list[j];
542 list[j]=temp;
543 }
544
545
546 /* Function: qsort_SeqAlign(list,left,right,comp)
547 *
548 * Descrip: qsort - lifted from K&R
549 * sorts the array using quicksort
550 * Probably much better to call sort_SeqAlign which sorts from start to end
551 *
552 *
553 * Arg: list [UNKN ] List of structures to swap in [Sequence **]
554 * Arg: left [UNKN ] left position [int]
555 * Arg: right [UNKN ] right position [int]
556 * Arg: comp [FUNCP] Function which returns -1 or 1 to sort on [int (*comp]
557 *
558 */
qsort_SeqAlign(Sequence ** list,int left,int right,int (* comp)(Sequence *,Sequence *))559 void qsort_SeqAlign(Sequence ** list,int left,int right,int (*comp)(Sequence * ,Sequence * ))
560 {
561 int i,last;
562 if( left >= right )
563 return;
564
565
566 swap_SeqAlign(list,left,(left+right)/2);
567 last = left;
568 for ( i=left+1; i <= right;i++) {
569 if( (*comp)(list[i],list[left]) < 0)
570 swap_SeqAlign (list,++last,i);
571 }
572 swap_SeqAlign (list,left,last);
573 qsort_SeqAlign(list,left,last-1,comp);
574 qsort_SeqAlign(list,last+1,right,comp);
575 }
576
577
578 /* Function: sort_SeqAlign(obj,comp)
579 *
580 * Descrip: sorts from start to end using comp
581 * sorts the array using quicksort by calling qsort_SeqAlign
582 *
583 *
584 * Arg: obj [UNKN ] Object containing list [SeqAlign *]
585 * Arg: comp [FUNCP] Function which returns -1 or 1 to sort on [int (*comp]
586 *
587 */
sort_SeqAlign(SeqAlign * obj,int (* comp)(Sequence *,Sequence *))588 void sort_SeqAlign(SeqAlign * obj,int (*comp)(Sequence *, Sequence *))
589 {
590 qsort_SeqAlign(obj->seq,0,obj->len-1,comp);
591 return;
592 }
593
594
595 /* Function: expand_SeqAlign(obj,len)
596 *
597 * Descrip: Really an internal function for add_SeqAlign
598 *
599 *
600 * Arg: obj [UNKN ] Object which contains the list [SeqAlign *]
601 * Arg: len [UNKN ] Length to add one [int]
602 *
603 * Return [UNKN ] Undocumented return value [boolean]
604 *
605 */
expand_SeqAlign(SeqAlign * obj,int len)606 boolean expand_SeqAlign(SeqAlign * obj,int len)
607 {
608
609
610 if( obj->maxlen > obj->len ) {
611 warn("expand_SeqAlign called with no need");
612 return TRUE;
613 }
614
615
616 if( (obj->seq = (Sequence ** ) ckrealloc (obj->seq,sizeof(Sequence *)*len)) == NULL) {
617 warn("ckrealloc failed for expand_SeqAlign, returning FALSE");
618 return FALSE;
619 }
620 obj->maxlen = len;
621 return TRUE;
622 }
623
624
625 /* Function: add_SeqAlign(obj,add)
626 *
627 * Descrip: Adds another object to the list. It will expand the list if necessary
628 *
629 *
630 * Arg: obj [UNKN ] Object which contains the list [SeqAlign *]
631 * Arg: add [OWNER] Object to add to the list [Sequence *]
632 *
633 * Return [UNKN ] Undocumented return value [boolean]
634 *
635 */
636 /* will expand function if necessary */
add_SeqAlign(SeqAlign * obj,Sequence * add)637 boolean add_SeqAlign(SeqAlign * obj,Sequence * add)
638 {
639 if( obj->len >= obj->maxlen) {
640 if( expand_SeqAlign(obj,obj->len + SeqAlignLISTLENGTH) == FALSE)
641 return FALSE;
642 }
643
644
645 obj->seq[obj->len++]=add;
646 return TRUE;
647 }
648
649
650 /* Function: flush_SeqAlign(obj)
651 *
652 * Descrip: Frees the list elements, sets length to 0
653 * If you want to save some elements, use hard_link_xxx
654 * to protect them from being actually destroyed in the free
655 *
656 *
657 * Arg: obj [UNKN ] Object which contains the list [SeqAlign *]
658 *
659 * Return [UNKN ] Undocumented return value [int]
660 *
661 */
flush_SeqAlign(SeqAlign * obj)662 int flush_SeqAlign(SeqAlign * obj)
663 {
664 int i;
665
666
667 for(i=0;i<obj->len;i++) { /*for i over list length*/
668 if( obj->seq[i] != NULL) {
669 free_Sequence(obj->seq[i]);
670 obj->seq[i] = NULL;
671 }
672 } /* end of for i over list length */
673
674
675 obj->len = 0;
676 return i;
677 }
678
679
680 /* Function: SeqAlign_alloc_std(void)
681 *
682 * Descrip: Equivalent to SeqAlign_alloc_len(SeqAlignLISTLENGTH)
683 *
684 *
685 *
686 * Return [UNKN ] Undocumented return value [SeqAlign *]
687 *
688 */
SeqAlign_alloc_std(void)689 SeqAlign * SeqAlign_alloc_std(void)
690 {
691 return SeqAlign_alloc_len(SeqAlignLISTLENGTH);
692 }
693
694
695 /* Function: SeqAlign_alloc_len(len)
696 *
697 * Descrip: Allocates len length to all lists
698 *
699 *
700 * Arg: len [UNKN ] Length of lists to allocate [int]
701 *
702 * Return [UNKN ] Undocumented return value [SeqAlign *]
703 *
704 */
SeqAlign_alloc_len(int len)705 SeqAlign * SeqAlign_alloc_len(int len)
706 {
707 SeqAlign * out; /* out is exported at the end of function */
708
709
710 /* Call alloc function: return NULL if NULL */
711 /* Warning message alread in alloc function */
712 if((out = SeqAlign_alloc()) == NULL)
713 return NULL;
714
715
716 /* Calling ckcalloc for list elements */
717 if((out->seq = (Sequence ** ) ckcalloc (len,sizeof(Sequence *))) == NULL) {
718 warn("Warning, ckcalloc failed in SeqAlign_alloc_len");
719 return NULL;
720 }
721 out->len = 0;
722 out->maxlen = len;
723
724
725 return out;
726 }
727
728
729 /* Function: hard_link_SeqAlign(obj)
730 *
731 * Descrip: Bumps up the reference count of the object
732 * Meaning that multiple pointers can 'own' it
733 *
734 *
735 * Arg: obj [UNKN ] Object to be hard linked [SeqAlign *]
736 *
737 * Return [UNKN ] Undocumented return value [SeqAlign *]
738 *
739 */
hard_link_SeqAlign(SeqAlign * obj)740 SeqAlign * hard_link_SeqAlign(SeqAlign * obj)
741 {
742 if( obj == NULL ) {
743 warn("Trying to hard link to a SeqAlign object: passed a NULL object");
744 return NULL;
745 }
746 obj->dynamite_hard_link++;
747 return obj;
748 }
749
750
751 /* Function: SeqAlign_alloc(void)
752 *
753 * Descrip: Allocates structure: assigns defaults if given
754 *
755 *
756 *
757 * Return [UNKN ] Undocumented return value [SeqAlign *]
758 *
759 */
SeqAlign_alloc(void)760 SeqAlign * SeqAlign_alloc(void)
761 {
762 SeqAlign * out; /* out is exported at end of function */
763
764
765 /* call ckalloc and see if NULL */
766 if((out=(SeqAlign *) ckalloc (sizeof(SeqAlign))) == NULL) {
767 warn("SeqAlign_alloc failed ");
768 return NULL; /* calling function should respond! */
769 }
770 out->dynamite_hard_link = 1;
771 #ifdef PTHREAD
772 pthread_mutex_init(&(out->dynamite_mutex),NULL);
773 #endif
774 out->name = NULL;
775 out->seq = NULL;
776 out->len = out->maxlen = 0;
777
778
779 return out;
780 }
781
782
783 /* Function: free_SeqAlign(obj)
784 *
785 * Descrip: Free Function: removes the memory held by obj
786 * Will chain up to owned members and clear all lists
787 *
788 *
789 * Arg: obj [UNKN ] Object that is free'd [SeqAlign *]
790 *
791 * Return [UNKN ] Undocumented return value [SeqAlign *]
792 *
793 */
free_SeqAlign(SeqAlign * obj)794 SeqAlign * free_SeqAlign(SeqAlign * obj)
795 {
796 int return_early = 0;
797 int i;
798
799
800 if( obj == NULL) {
801 warn("Attempting to free a NULL pointer to a SeqAlign obj. Should be trappable");
802 return NULL;
803 }
804
805
806 #ifdef PTHREAD
807 assert(pthread_mutex_lock(&(obj->dynamite_mutex)) == 0);
808 #endif
809 if( obj->dynamite_hard_link > 1) {
810 return_early = 1;
811 obj->dynamite_hard_link--;
812 }
813 #ifdef PTHREAD
814 assert(pthread_mutex_unlock(&(obj->dynamite_mutex)) == 0);
815 #endif
816 if( return_early == 1)
817 return NULL;
818 if( obj->name != NULL)
819 ckfree(obj->name);
820 if( obj->seq != NULL) {
821 for(i=0;i<obj->len;i++) {
822 if( obj->seq[i] != NULL)
823 free_Sequence(obj->seq[i]);
824 }
825 ckfree(obj->seq);
826 }
827
828
829 ckfree(obj);
830 return NULL;
831 }
832
833
834 /* Function: hard_link_ColumnCount(obj)
835 *
836 * Descrip: Bumps up the reference count of the object
837 * Meaning that multiple pointers can 'own' it
838 *
839 *
840 * Arg: obj [UNKN ] Object to be hard linked [ColumnCount *]
841 *
842 * Return [UNKN ] Undocumented return value [ColumnCount *]
843 *
844 */
hard_link_ColumnCount(ColumnCount * obj)845 ColumnCount * hard_link_ColumnCount(ColumnCount * obj)
846 {
847 if( obj == NULL ) {
848 warn("Trying to hard link to a ColumnCount object: passed a NULL object");
849 return NULL;
850 }
851 obj->dynamite_hard_link++;
852 return obj;
853 }
854
855
856 /* Function: ColumnCount_alloc(void)
857 *
858 * Descrip: Allocates structure: assigns defaults if given
859 *
860 *
861 *
862 * Return [UNKN ] Undocumented return value [ColumnCount *]
863 *
864 */
ColumnCount_alloc(void)865 ColumnCount * ColumnCount_alloc(void)
866 {
867 ColumnCount * out; /* out is exported at end of function */
868
869
870 /* call ckalloc and see if NULL */
871 if((out=(ColumnCount *) ckalloc (sizeof(ColumnCount))) == NULL) {
872 warn("ColumnCount_alloc failed ");
873 return NULL; /* calling function should respond! */
874 }
875 out->dynamite_hard_link = 1;
876 #ifdef PTHREAD
877 pthread_mutex_init(&(out->dynamite_mutex),NULL);
878 #endif
879 /* count[27] is an array: no default possible */
880
881
882 return out;
883 }
884
885
886 /* Function: free_ColumnCount(obj)
887 *
888 * Descrip: Free Function: removes the memory held by obj
889 * Will chain up to owned members and clear all lists
890 *
891 *
892 * Arg: obj [UNKN ] Object that is free'd [ColumnCount *]
893 *
894 * Return [UNKN ] Undocumented return value [ColumnCount *]
895 *
896 */
free_ColumnCount(ColumnCount * obj)897 ColumnCount * free_ColumnCount(ColumnCount * obj)
898 {
899 int return_early = 0;
900
901
902 if( obj == NULL) {
903 warn("Attempting to free a NULL pointer to a ColumnCount obj. Should be trappable");
904 return NULL;
905 }
906
907
908 #ifdef PTHREAD
909 assert(pthread_mutex_lock(&(obj->dynamite_mutex)) == 0);
910 #endif
911 if( obj->dynamite_hard_link > 1) {
912 return_early = 1;
913 obj->dynamite_hard_link--;
914 }
915 #ifdef PTHREAD
916 assert(pthread_mutex_unlock(&(obj->dynamite_mutex)) == 0);
917 #endif
918 if( return_early == 1)
919 return NULL;
920
921
922 ckfree(obj);
923 return NULL;
924 }
925
926
927
928 #ifdef _cplusplus
929 }
930 #endif
931