1 /*****************************************************************************
2    Major portions of this software are copyrighted by the Medical College
3    of Wisconsin, 1994-2000, and are released under the Gnu General Public
4    License, Version 2.  See the file README.Copyright for details.
5 ******************************************************************************/
6 
7 #include "mrilib.h"
8 #include "thd.h"
9 
10 /***********************************************************************
11   The first set of routines is concerned with "attributes".
12   These are values stored in the header file of a dataset,
13   and can be conceived of being in the form
14     name = value value value ...
15   where "name" is an identifying string, and "value value value ..."
16   is an array of values.  These attributes are read in, and later
17   interrogated to form the actual data structure of a THD_3dim_dataset.
18 ************************************************************************/
19 
atr_print(ATR_any * atr,char * ssep,char * spsep,char quote,int do_name)20 void atr_print( ATR_any *atr, char *ssep, char *spsep, char quote, int do_name)
21 {
22    int ii ;
23    char ssep_def[]={"~"};
24    int neword = 1;
25 
26    if (!ssep) ssep = ssep_def;
27 
28    switch( atr->type ){
29 
30       default:
31          ERROR_message("Illegal attribute type found: %d",atr->type);
32       exit(1) ;
33 
34       case ATR_FLOAT_TYPE:{
35          ATR_float *aa = (ATR_float *) atr ;
36          if( do_name ) printf("%s = ",aa->name) ;
37          for( ii=0 ; ii < aa->nfl ; ii++ )
38             printf("%s ",MV_format_fval(aa->fl[ii])) ;
39          printf("\n") ;
40       }
41       return ;
42 
43       case ATR_INT_TYPE:{
44          ATR_int *aa = (ATR_int *) atr ;
45          if( do_name ) printf("%s = ",aa->name) ;
46          for( ii=0 ; ii < aa->nin ; ii++ )
47             printf("%d ",aa->in[ii]) ;
48          printf("\n") ;
49       }
50       return ;
51 
52       case ATR_STRING_TYPE:{
53          ATR_string *aa = (ATR_string *) atr ;
54          char *str = (char *)malloc(sizeof(char)*(aa->nch+1)) ;
55          char *eee ;
56          memcpy(str,aa->ch,aa->nch) ; str[aa->nch] = '\0' ;
57 
58 #if 0
59          eee = tross_Expand_String(str) ;
60 #else
61          eee = NULL ;
62 #endif
63          if( do_name ) printf("%s = ",aa->name) ;
64          if( eee != NULL ){
65             printf("%s\n",eee) ; free(eee) ;
66          } else if( str[0] != '\0' ){
67             int isb = 0;
68             neword = 1;
69             for (ii=0; ii<aa->nch;++ii) {
70                if (str[ii] == '\0') {
71                   ++isb;
72                   if (quote != '\0') printf("%c", quote);
73                   if (strcmp(ssep,"NUM") == 0) {
74                      /* handled below*/
75                   } else {
76                      printf("%s",ssep);
77                   }
78                   neword = 1;
79                } else {
80                   if (neword) {
81                      if (strcmp(ssep,"NUM") == 0) {
82                         printf(" %d ",isb);
83                      }
84                      if (quote != '\0') printf("%c", quote);
85                   }
86                   if (spsep && str[ii] == ' ') printf("%s", spsep);
87                   else printf("%c", str[ii]);
88                   neword = 0;
89                }
90             }
91             printf("\n") ;
92          } else {
93             printf("(null)\n") ;
94          }
95          free(str) ;
96       }
97       return ;
98    }
99 }
100 
101 /*-----------------------------------------------------------------------*/
102 /*!  Given the rudiments of a datablock, read all the attributes into it
103 -------------------------------------------------------------------------*/
104 
THD_read_all_atr(char * headername,THD_datablock * blk)105 void THD_read_all_atr( char *headername , THD_datablock *blk )
106 {
107    ATR_any *next_atr ;
108    int code , ii ;
109    FILE *header_file ;
110 
111 ENTRY("THD_read_all_atr") ;
112 
113    if( ! ISVALID_DATABLOCK(blk) )
114       THD_FATAL_ERROR( "Illegal datablock type in THD_read_all_atr" ) ;
115 
116    blk->natr       = 0 ;     /* initialize to no attributes */
117    blk->natr_alloc = 0 ;
118    blk->atr        = NULL ;
119 
120    /*--- certain types of filenames are verboten ---*/
121 
122    if( STRING_HAS_SUFFIX(headername,".mnc")    ) EXRETURN ;
123    if( STRING_HAS_SUFFIX(headername,".nii")    ) EXRETURN ;
124    if( STRING_HAS_SUFFIX(headername,".nii.gz") ) EXRETURN ;
125    if( STRING_HAS_SUFFIX(headername,".mri")    ) EXRETURN ;
126    if( STRING_HAS_SUFFIX(headername,".ctf")    ) EXRETURN ;
127    if( STRING_HAS_SUFFIX(headername,".hdr")    ) EXRETURN ;
128    if( STRING_HAS_SUFFIX(headername,".mpg")    ) EXRETURN ;
129 
130    /*--- open file; if unable to do so, exeunt ---*/
131 
132    header_file = fopen( headername , "r" ) ;
133    if( header_file == NULL ) EXRETURN ;
134 
135    /*--- 01 Jun 2005: check if this is a NIML-style header file ---*/
136 
137    { char buf[1024] , *cpt ; int nbuf ;
138      nbuf = fread( buf , 1 , 1023 , header_file ) ;    /* read first 1K */
139      if( nbuf > 0 ){                                  /* got something? */
140        buf[nbuf] = '\0' ;
141        cpt = strstr( buf , "<AFNI_" ) ;
142        if( cpt != NULL ){                        /*** NIML Dataset!!! ***/
143          fclose( header_file ) ;                 /* is reopened by NIML */
144          THD_read_niml_atr( headername , blk ) ; /** read the new way! **/
145          EXRETURN ;
146        }
147      }
148      rewind( header_file ) ; /*** old style dataset ==> read it below ***/
149    }
150 
151    /*----- read attributes from the header file -----*/
152 
153    do{
154       char aname[THD_MAX_NAME] , atypestr[THD_MAX_NAME] ;
155       int  atype , acount ;
156 
157       atypestr[0] = aname[0] = '\0' ; acount = 0 ;
158 
159       code = fscanf( header_file ,
160                      " type = %s name = %s count = %d" ,
161                      atypestr , aname , &acount ) ;
162 
163       if( code == 3 && acount == 0 ) continue ;  /* 24 Nov 2009 */
164 
165       code = (code != 3 || acount < 1) ? FAIL : SUCCESS ;
166       if( code == FAIL ) break ;  /* bad read */
167 
168       for( atype=FIRST_ATR_TYPE ; atype <= LAST_ATR_TYPE ; atype++ )
169          if( strcmp(atypestr,ATR_typestr[atype]) == 0 ) break ;
170 
171       if( atype > LAST_ATR_TYPE ){ /* bad read */
172          code = FAIL ;
173          break ;
174       }
175 
176       if( blk->natr == blk->natr_alloc ){  /* make new space */
177          blk->natr_alloc  += ATR_ALLINC ;
178          blk->atr          = (ATR_any *)
179                              RwcRealloc( (char *)blk->atr,
180                                         sizeof(ATR_any) * blk->natr_alloc );
181       }
182       next_atr = &(blk->atr[blk->natr]) ;
183       (blk->natr)++ ;
184 
185       switch( atype ){
186 
187          case ATR_FLOAT_TYPE:{
188             ATR_float *new_atr = (ATR_float *) next_atr ;
189             char bbb[256] ;
190 
191             new_atr->type = ATR_FLOAT_TYPE ;
192             new_atr->name = RwcNewString( aname ) ;
193             new_atr->nfl  = acount ;
194             new_atr->fl   = (float *) RwcMalloc( sizeof(float) * acount ) ;
195 
196             code = 0 ;
197             for( ii=0 ; ii < acount ; ii++ ){
198 #if 0
199                code += fscanf( header_file , "%f" , &(new_atr->fl[ii]) ) ;
200 #else
201                bbb[0] = '\0' ; fscanf( header_file , "%255s" , bbb ) ;
202                if( bbb[0] != '\0' ){
203                   new_atr->fl[ii] = strtod( bbb , NULL ) ;
204                   code++ ;
205                }
206 #endif
207             }
208             code = (code != acount) ? FAIL : SUCCESS ;
209 
210             ADDTO_KILL( blk->kl , new_atr->name ) ;
211             ADDTO_KILL( blk->kl , new_atr->fl ) ;
212          }
213          break ;
214 
215          case ATR_INT_TYPE:{
216             ATR_int *new_atr = (ATR_int *) next_atr ;
217 
218             new_atr->type = ATR_INT_TYPE ;
219             new_atr->name = RwcNewString( aname ) ;
220             new_atr->nin  = acount ;
221             new_atr->in   = (int *) RwcMalloc( sizeof(int) * acount ) ;
222 
223             code = 0 ;
224             for( ii=0 ; ii < acount ; ii++ ){
225                code += fscanf( header_file , "%d" , &(new_atr->in[ii]) ) ;
226             }
227             code = (code != acount) ? FAIL : SUCCESS ;
228 
229             ADDTO_KILL( blk->kl , new_atr->name ) ;
230             ADDTO_KILL( blk->kl , new_atr->in ) ;
231          }
232          break ;
233 
234          case ATR_STRING_TYPE:{
235             ATR_string *new_atr = (ATR_string *) next_atr ;
236 
237             new_atr->type = ATR_STRING_TYPE ;
238             new_atr->name = RwcNewString( aname ) ;
239             new_atr->nch  = acount ;
240             new_atr->ch   = (char *) RwcMalloc( sizeof(char) * acount ) ;
241 
242             fscanf( header_file , " '" ) ;
243 
244             code = 0 ;
245             for( ii=0 ; ii < acount ; ii++ ){
246                code += fscanf( header_file , "%c" , &(new_atr->ch[ii]) ) ;
247             }
248             code = (code != acount) ? FAIL : SUCCESS ;
249 
250             THD_unzblock( acount , new_atr->ch ) ;
251 
252             ADDTO_KILL( blk->kl , new_atr->name ) ;
253             ADDTO_KILL( blk->kl , new_atr->ch ) ;
254          }
255          break ;
256       }  /* end of switch */
257 
258       if( code == FAIL ) break ;  /* exit if an error! */
259    } while(1) ; /* end of for loop over all attributes */
260 
261    fclose( header_file ) ; EXRETURN ;
262 }
263 
264 /*-----------------------------------------------------------------------*/
265 /*! Read NIML-formatted attributes from the header file. [01 Jun 2005]
266 -------------------------------------------------------------------------*/
267 
THD_read_niml_atr(char * headername,THD_datablock * blk)268 void THD_read_niml_atr( char *headername , THD_datablock *blk )
269 {
270    NI_stream ns ;
271    void *nini ;
272    NI_group *ngr ;
273    char sname[2048] ;
274    long fsize ;
275 
276 ENTRY("THD_read_niml_atr") ;
277 
278    /** open NIML stream to read from the file **/
279 
280    if( headername == NULL || *headername == '\0' || blk == NULL ) EXRETURN ;
281    fsize = NI_filesize(headername) ; if( fsize <= 10 ) EXRETURN ;
282    sprintf(sname,"file:%s",headername) ; STATUS(sname) ;
283    ns = NI_stream_open( sname , "r" ) ;
284    if( ns == (NI_stream)NULL ) EXRETURN ;
285    if( fsize > NI_BUFSIZE ){
286      fsize = MIN( 4*NI_BUFSIZE , fsize ) ;
287      NI_stream_setbufsize( ns , fsize ) ;
288    }
289 
290    /** read one group element from it (e.g., skipping the XML prolog) **/
291 
292    while(1){
293      nini = NI_read_element( ns , 9 ) ;
294      if( nini == NULL ){ NI_stream_close(ns); EXRETURN; }      /* bad! */
295      if( NI_element_type(nini) == NI_GROUP_TYPE ) break ;      /* good */
296      NI_free_element(nini) ;                       /* not what we want */
297    }
298    NI_stream_close( ns ) ;
299    ngr = (NI_group *)nini ;
300    if( strncmp(ngr->name,"AFNI_",5) != 0 ){ NI_free_element(ngr); EXRETURN; }
301 
302    /** actually process element, then exit stage right **/
303 
304    THD_dblkatr_from_niml( ngr , blk ) ;  /* cf. thd_nimlatr.c */
305    NI_free_element( ngr ) ;
306    EXRETURN ;
307 }
308 
309 /*-----------------------------------------------------------------------
310   29 April 1998: erase all attributes from a datablock
311 -------------------------------------------------------------------------*/
312 
THD_erase_all_atr(THD_datablock * blk)313 void THD_erase_all_atr( THD_datablock *blk )
314 {
315    int ia ;
316    ATR_any *next_atr ;
317 
318 ENTRY("THD_erase_all_atr") ;
319 
320    if( !ISVALID_DATABLOCK(blk) || blk->natr == 0 || blk->atr == NULL ) EXRETURN ;
321 
322    for( ia=0 ; ia < blk->natr ; ia++ ){
323       next_atr = blk->atr + ia ;
324 
325       switch( next_atr->type ){
326          case ATR_FLOAT_TYPE:{
327             ATR_float *aa = (ATR_float *) next_atr ;
328             SINGLE_KILL( blk->kl , aa->name ) ;
329             SINGLE_KILL( blk->kl , aa->fl ) ;
330          }
331          break ;
332 
333          case ATR_STRING_TYPE:{
334             ATR_string *aa = (ATR_string *) next_atr ;
335             SINGLE_KILL( blk->kl , aa->name ) ;
336             SINGLE_KILL( blk->kl , aa->ch ) ;
337          }
338          break ;
339 
340          case ATR_INT_TYPE:{
341             ATR_int *aa = (ATR_int *) next_atr ;
342             SINGLE_KILL( blk->kl , aa->name ) ;
343             SINGLE_KILL( blk->kl , aa->in ) ;
344          }
345          break ;
346       }
347 
348       next_atr->type = ILLEGAL_TYPE ;
349    }
350 
351    blk->natr = 0 ;
352    EXRETURN ;
353 }
354 
355 /*-----------------------------------------------------------------------
356    29 April 1998: erase a single attribute, given by name
357 -------------------------------------------------------------------------*/
358 
THD_erase_one_atr(THD_datablock * blk,char * name)359 void THD_erase_one_atr( THD_datablock *blk , char *name )
360 {
361    ATR_any *next_atr ;
362 
363 ENTRY("THD_erase_one_atr") ;
364 
365    if( ! ISVALID_DATABLOCK(blk) || name     == NULL ||
366        blk->natr == 0           || blk->atr == NULL   ) EXRETURN ;
367 
368    next_atr = THD_find_atr( blk , name ) ;
369 
370    if( next_atr == NULL ) EXRETURN ;
371 
372    switch( next_atr->type ){
373       case ATR_FLOAT_TYPE:{
374          ATR_float *aa = (ATR_float *) next_atr ;
375          SINGLE_KILL( blk->kl , aa->name ) ;
376          SINGLE_KILL( blk->kl , aa->fl ) ;
377       }
378       break ;
379 
380       case ATR_STRING_TYPE:{
381          ATR_string *aa = (ATR_string *) next_atr ;
382          SINGLE_KILL( blk->kl , aa->name ) ;
383          SINGLE_KILL( blk->kl , aa->ch ) ;
384       }
385       break ;
386 
387       case ATR_INT_TYPE:{
388          ATR_int *aa = (ATR_int *) next_atr ;
389          SINGLE_KILL( blk->kl , aa->name ) ;
390          SINGLE_KILL( blk->kl , aa->in ) ;
391       }
392       break ;
393    }
394 
395    next_atr->type = ILLEGAL_TYPE ;
396    EXRETURN ;
397 }
398 
399 /*-----------------------------------------------------------------------
400   given a datablock and an attribute name, return the pointer to the
401   attribute structure that matches (if none, return NULL)
402 -------------------------------------------------------------------------*/
403 
THD_find_atr(THD_datablock * blk,char * name)404 ATR_any * THD_find_atr( THD_datablock *blk , char *name )
405 {
406    int ia ;
407 
408 ENTRY("THD_find_atr") ;
409 
410    if( ! ISVALID_DATABLOCK(blk) )
411       THD_FATAL_ERROR( "Illegal block type in THD_find_atr" ) ;
412 
413    if( blk->natr == 0 || blk->atr == NULL ) RETURN(NULL) ;
414 
415    /* loop over attributes and check names */
416 
417    for( ia=0 ; ia < blk->natr ; ia++ ){
418       char *aname ;
419       ATR_any *next_atr = &(blk->atr[ia]) ;  /* pointer to this atr */
420 
421       /* extract pointer to name from next_atr */
422 
423       switch( next_atr->type ){
424 
425          default: aname = NULL ; break ;
426 
427          case ATR_FLOAT_TYPE:{
428             ATR_float *aa = (ATR_float *) next_atr ;
429             aname = aa->name ;
430          }
431          break ;
432 
433          case ATR_STRING_TYPE:{
434             ATR_string *aa = (ATR_string *) next_atr ;
435             aname = aa->name ;
436          }
437          break ;
438 
439          case ATR_INT_TYPE:{
440             ATR_int *aa = (ATR_int *) next_atr ;
441             aname = aa->name ;
442          }
443          break ;
444       }
445 
446       /* check if names match; if so, return the result */
447 
448       if( aname != NULL && strcmp(aname,name) == 0 ) RETURN(next_atr) ;
449 
450    } /* end of loop over attributes */
451 
452    RETURN(NULL) ;  /* none matched */
453 }
454 
455 /*-----------------------------------------------------------------------*/
456 
THD_find_float_atr(THD_datablock * blk,char * name)457 ATR_float * THD_find_float_atr( THD_datablock *blk , char *name )
458 {
459    ATR_any *aa ;
460    aa = THD_find_atr( blk , name ) ;
461 
462    if( aa == NULL || aa->type != ATR_FLOAT_TYPE ) return NULL ;
463    else                                           return (ATR_float *) aa ;
464 }
465 
466 /*-----------------------------------------------------------------------*/
467 
THD_find_int_atr(THD_datablock * blk,char * name)468 ATR_int * THD_find_int_atr( THD_datablock *blk , char *name )
469 {
470    ATR_any *aa ;
471    aa = THD_find_atr( blk , name ) ;
472 
473    if( aa == NULL || aa->type != ATR_INT_TYPE ) return NULL ;
474    else                                         return (ATR_int *) aa ;
475 }
476 
477 /*-----------------------------------------------------------------------*/
478 
THD_find_string_atr(THD_datablock * blk,char * name)479 ATR_string * THD_find_string_atr( THD_datablock *blk , char *name )
480 {
481    ATR_any *aa ;
482    aa = THD_find_atr( blk , name ) ;
483 
484    if( aa == NULL || aa->type != ATR_STRING_TYPE ) return NULL ;
485    else                                            return (ATR_string *)aa;
486 }
487 
488 /*-----------------------------------------------------------------------
489   given a datablock, set an attribute
490   (if name is same as existing attribute, will overwrite)
491 -------------------------------------------------------------------------*/
492 
THD_set_atr(THD_datablock * blk,char * aname,int atype,int acount,void * ar)493 void THD_set_atr( THD_datablock *blk , char *aname ,
494                   int atype , int acount , void *ar )
495 {
496    ATR_any *old_atr , *atr ;
497 
498 ENTRY("THD_set_atr") ;
499 
500    if( ! ISVALID_DATABLOCK(blk) )
501      THD_FATAL_ERROR( "Illegal block type in THD_set_atr" ) ;
502 
503    if( acount < 0 || ar == NULL || aname == NULL )
504      THD_FATAL_ERROR( "Illegal input data in THD_set_atr" ) ;
505 
506    if( acount == 0 ) EXRETURN ;  /* 24 Nov 2009 */
507 
508    STATUS(aname) ;
509 
510    old_atr = THD_find_atr( blk , aname ) ;  /* find matching name */
511 
512    if( old_atr != NULL ){  /* if an attribute with this name already is */
513 
514       atr = old_atr ;
515 
516       switch( old_atr->type ){  /* free data in old attribute */
517 
518          default: break ;  /* something unpleasant */
519 
520          case ATR_FLOAT_TYPE:{
521             ATR_float *aa = (ATR_float *) old_atr ;
522 
523             SINGLE_KILL( blk->kl , aa->name ) ;
524             SINGLE_KILL( blk->kl , aa->fl   ) ;
525          }
526          break ;
527 
528          case ATR_INT_TYPE:{
529             ATR_int *aa = (ATR_int *) old_atr ;
530 
531             SINGLE_KILL( blk->kl , aa->name ) ;
532             SINGLE_KILL( blk->kl , aa->in   ) ;
533          }
534          break ;
535 
536          case ATR_STRING_TYPE:{
537             ATR_string *aa = (ATR_string *) old_atr ;
538 
539             SINGLE_KILL( blk->kl , aa->name ) ;
540             SINGLE_KILL( blk->kl , aa->ch   ) ;
541          }
542          break ;
543       }  /* end of switch */
544 
545    } else {  /* this is a new attribute name for this datablock */
546 
547       int ia ;
548 
549       for( ia=0 ; ia < blk->natr ; ia++ )     /* 29 April 1998: look for an */
550          if( blk->atr[ia].type < 0 ) break ;  /* unused one before the end  */
551 
552       if( ia == blk->natr_alloc ){            /* need to extend array */
553          blk->natr_alloc  += ATR_ALLINC ;
554          blk->atr          = (ATR_any *)
555                              RwcRealloc( (char *)blk->atr,
556                                         sizeof(ATR_any) * blk->natr_alloc );
557       }
558       atr = &(blk->atr[ia]) ;
559       if( ia == blk->natr ) (blk->natr)++ ;
560    }
561 
562    /* at this point, atr points to the location to store the data;
563       now, allocate space for the actual data and store it */
564 
565    switch( atype ){
566 
567       case ATR_FLOAT_TYPE:{
568          ATR_float *new_atr = (ATR_float *) atr ;
569 
570          new_atr->type = ATR_FLOAT_TYPE ;
571          new_atr->name = RwcNewString( aname ) ;
572          new_atr->nfl  = acount ;
573          new_atr->fl   = (float *) RwcMalloc( sizeof(float) * acount ) ;
574          memcpy( new_atr->fl , ar , sizeof(float)*acount ) ;
575 
576          ADDTO_KILL( blk->kl , new_atr->name ) ;
577          ADDTO_KILL( blk->kl , new_atr->fl ) ;
578       }
579       break ;
580 
581       case ATR_INT_TYPE:{
582          ATR_int *new_atr = (ATR_int *) atr ;
583 
584          new_atr->type = ATR_INT_TYPE ;
585          new_atr->name = RwcNewString( aname ) ;
586          new_atr->nin  = acount ;
587          new_atr->in   = (int *) RwcMalloc( sizeof(int) * acount ) ;
588          memcpy( new_atr->in , ar , sizeof(int)*acount ) ;
589 
590          ADDTO_KILL( blk->kl , new_atr->name ) ;
591          ADDTO_KILL( blk->kl , new_atr->in ) ;
592 
593 #if 0
594 if(PRINT_TRACING){
595   char str[256] ; int ii ;
596   sprintf(str,"INT atr: name=%s nin=%d vals::",new_atr->name,new_atr->nin) ;
597   STATUS(str) ;
598   for( ii=0 ; ii < acount ; ii++ ) printf(" %d",new_atr->in[ii]) ;
599   printf("\n") ;
600 }
601 #endif
602       }
603       break ;
604 
605       case ATR_STRING_TYPE:{
606          ATR_string *new_atr = (ATR_string *) atr ;
607 
608          new_atr->type = ATR_STRING_TYPE ;
609          new_atr->name = RwcNewString( aname ) ;
610          new_atr->nch  = acount ;
611          new_atr->ch   = (char *) RwcMalloc( sizeof(char) * acount ) ;
612          memcpy( new_atr->ch , ar , sizeof(char)*acount ) ;
613          new_atr->ch[acount-1] = '\0' ;
614          /*** fprintf(stderr,"Have %d chars\n", acount);
615               atr_print( (ATR_any *)new_atr, NULL , NULL, '\0', 1) ; ***/
616 
617          ADDTO_KILL( blk->kl , new_atr->name ) ;
618          ADDTO_KILL( blk->kl , new_atr->ch ) ;
619       }
620       break ;
621    }  /* end of switch */
622 
623    EXRETURN ;
624 }
625 
626 /*-----------------------------------------------------------------------*/
627 
THD_set_float_atr(THD_datablock * blk,char * name,int n,float * fl)628 void THD_set_float_atr( THD_datablock *blk ,
629                         char *name , int n , float *fl )
630 {
631 ENTRY("THD_set_float_atr") ;
632    THD_set_atr( blk , name , ATR_FLOAT_TYPE , n , fl ) ;
633 EXRETURN ;
634 }
635 
636 /*-----------------------------------------------------------------------*/
637 
THD_set_int_atr(THD_datablock * blk,char * name,int n,int * in)638 void THD_set_int_atr( THD_datablock *blk ,
639                       char *name , int n , int *in )
640 {
641 ENTRY("THD_set_int_atr") ;
642    THD_set_atr( blk , name , ATR_INT_TYPE , n , in ) ;
643 EXRETURN ;
644 }
645 
646 /*-----------------------------------------------------------------------*/
647 
THD_set_char_atr(THD_datablock * blk,char * name,int n,char * str)648 void THD_set_char_atr( THD_datablock *blk ,
649                        char *name , int n , char *str )
650 {
651 ENTRY("THD_set_char_atr") ;
652    THD_set_atr( blk , name , ATR_STRING_TYPE , n , str ) ;
653 EXRETURN ;
654 }
655 
656 /*-----------------------------------------------------------------------*/
657 /*! Remove attributes from a dataset that might contain identifying
658     strings.  Can't help against sneaky users who put them into
659     other places, but might be good enough for non-programmers.
660 -------------------------------------------------------------------------*/
661 
THD_anonymize_dset(THD_3dim_dataset * dset)662 void THD_anonymize_dset( THD_3dim_dataset *dset ) /* 08 Jul 2005 */
663 {
664    THD_datablock *blk ;
665    int ia ;
666 
667 ENTRY("THD_anonymize_dset") ;
668 
669    if( !ISVALID_DSET(dset) ) EXRETURN ;
670    blk = dset->dblk ;
671    if( !ISVALID_DATABLOCK(blk) || blk->natr <= 0 ) EXRETURN ;
672 
673    for( ia=0 ; ia < blk->natr ; ia++ ){
674      char *aname ;
675      ATR_any *next_atr = &(blk->atr[ia]) ;  /* pointer to this atr */
676 
677      switch( next_atr->type ){
678 
679        default: aname = NULL ; break ;
680 
681        case ATR_FLOAT_TYPE:{
682          ATR_float *aa = (ATR_float *) next_atr ;
683          aname = aa->name ;
684        }
685        break ;
686 
687        case ATR_STRING_TYPE:{
688          ATR_string *aa = (ATR_string *) next_atr ;
689          aname = aa->name ;
690        }
691        break ;
692 
693        case ATR_INT_TYPE:{
694          ATR_int *aa = (ATR_int *) next_atr ;
695          aname = aa->name ;
696        }
697        break ;
698      }
699 
700      if( aname == NULL || *aname == '\0' ) continue ;
701 
702      if( strstr(aname,"NOTE") != NULL || strstr(aname,"_NAME") != NULL )
703        THD_erase_one_atr( blk , aname ) ;
704    }
705 
706    THD_set_string_atr( blk , ATRNAME_LABEL1         , "none" ) ;
707    THD_set_string_atr( blk , ATRNAME_LABEL2         , "none" ) ;
708    THD_set_string_atr( blk , ATRNAME_DATANAME       , "none" ) ;
709    THD_erase_one_atr ( blk , ATRNAME_BRICK_KEYWORDS          ) ;
710    THD_erase_one_atr ( blk , ATRNAME_KEYWORDS                ) ;
711 
712    EXRETURN ;
713 }
714 
715 /*------------------------------------------------------------------*/
716 
THD_copy_atr(ATR_any * atr)717 ATR_any * THD_copy_atr( ATR_any *atr )  /* 03 Aug 2005 */
718 {
719    ATR_any *atr_out=NULL ;
720 
721 ENTRY("THD_copy_atr") ;
722 
723    if( atr == NULL ) RETURN(NULL) ;
724 
725    switch( atr->type ){
726 
727      case ATR_FLOAT_TYPE:{
728        ATR_float *aa = (ATR_float *)atr , *qq ;
729        qq = (ATR_float *)RwcMalloc(sizeof(ATR_float)) ;
730        qq->type = ATR_FLOAT_TYPE ;
731        qq->name = RwcNewString( aa->name ) ;
732        qq->nfl  = aa->nfl ;
733        qq->fl   = (float *) RwcMalloc( sizeof(float) * aa->nfl ) ;
734        memcpy( qq->fl , aa->fl , sizeof(float) * aa->nfl ) ;
735        atr_out = (ATR_any *)qq ;
736      }
737      break ;
738 
739      case ATR_STRING_TYPE:{
740        ATR_string *aa = (ATR_string *)atr , *qq ;
741        qq = (ATR_string *)RwcMalloc(sizeof(ATR_string)) ;
742        qq->type = ATR_STRING_TYPE ;
743        qq->name = RwcNewString( aa->name ) ;
744        qq->nch  = aa->nch ;
745        qq->ch   = (char *) RwcMalloc( sizeof(char) * aa->nch ) ;
746        memcpy( qq->ch , aa->ch , sizeof(char) * aa->nch ) ;
747        atr_out = (ATR_any *)qq ;
748      }
749      break ;
750 
751      case ATR_INT_TYPE:{
752        ATR_int *aa = (ATR_int *)atr , *qq ;
753        qq = (ATR_int *)RwcMalloc(sizeof(ATR_int)) ;
754        qq->type = ATR_INT_TYPE ;
755        qq->name = RwcNewString( aa->name ) ;
756        qq->nin  = aa->nin ;
757        qq->in   = (int *) RwcMalloc( sizeof(int) * aa->nin ) ;
758        memcpy( qq->in , aa->in , sizeof(int) * aa->nin ) ;
759        atr_out = (ATR_any *)qq ;
760      }
761      break ;
762    }
763 
764    RETURN(atr_out) ;
765 }
766 
767 /*------------------------------------------------------------------*/
768 
THD_insert_atr(THD_datablock * blk,ATR_any * atr)769 void THD_insert_atr( THD_datablock *blk , ATR_any *atr )  /* 03 Aug 2005 */
770 {
771 ENTRY("THD_insert_atr") ;
772 
773    if( ! ISVALID_DATABLOCK(blk) || atr == NULL ) EXRETURN ;
774 
775    switch( atr->type ){
776 
777      case ATR_FLOAT_TYPE:{
778        ATR_float *aa = (ATR_float *)atr ;
779        THD_set_atr( blk , aa->name , ATR_FLOAT_TYPE , aa->nfl , aa->fl ) ;
780      }
781      break ;
782 
783      case ATR_STRING_TYPE:{
784        ATR_string *aa = (ATR_string *)atr ;
785        THD_set_atr( blk , aa->name , ATR_STRING_TYPE , aa->nch , aa->ch ) ;
786      }
787      break ;
788 
789      case ATR_INT_TYPE:{
790        ATR_int *aa = (ATR_int *)atr ;
791        THD_set_atr( blk , aa->name , ATR_INT_TYPE , aa->nin , aa->in ) ;
792      }
793      break ;
794    }
795 
796    EXRETURN ;
797 }
798 
799 /*------------------------------------------------------------------*/
800 
THD_copy_labeltable_atr(THD_datablock * d1,THD_datablock * d2)801 int THD_copy_labeltable_atr( THD_datablock *d1,  THD_datablock *d2)
802 {
803    ATR_any *atr=NULL;
804 
805    ENTRY("THD_copy_labeltable_atr") ;
806 
807    if (!d1 || !d2 || !ISVALID_DATABLOCK(d1) || !ISVALID_DATABLOCK(d2)) RETURN(0);
808    if ((atr = THD_find_atr(d2, "VALUE_LABEL_DTABLE"))) {
809       THD_insert_atr( d1 , THD_copy_atr( atr ) ) ;
810    }
811    if ((atr = THD_find_atr(d2, "ATLAS_LABEL_TABLE"))) {
812       THD_insert_atr( d1 , THD_copy_atr( atr ) ) ;
813    }
814    RETURN(1);
815 }
816