1 /*=========================================================================
4 Module: $RCSfile: gdcmArgMgr.cxx,v $
6 Date: $Date: 2006/01/26 16:01:04 $
7 Version: $Revision: 1.18 $
9 Copyright (c) CREATIS (Centre de Recherche et d'Applications en Traitement de
10 l'Image). All rights reserved. See Doc/License.txt or
11 http://www.creatis.insa-lyon.fr/Public/Gdcm/License.html for details.
13 This software is distributed WITHOUT ANY WARRANTY; without even
14 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 PURPOSE. See the above copyright notices for more information.
17 =========================================================================*/
22 #include <string.h> // For strlen
24 #include <string.h> // For strtok and strlen
25 #include <stdlib.h> // For strtol and strtod
27 #include "gdcmArgMgr.h"
31 //-------------------------------------------------------------------------
32 // Constructor / Destructor
36 * @param argc arguments count, as passed to main()
37 * @param argv pointers array on the arguments passed to main()
39 ArgMgr::ArgMgr(int argc, char **argv)
46 /* Read the parameters of the command line *************************/
47 for ( ArgCount=0, nblettre=1 , i=0; i<argc; i++)
49 if ( FiltreLong(argv[i]) )
51 std::cout << "Argument too long ( > "
52 << ARG_LONG_MAX << ")" << std::endl;
55 if ( argv[i][0] == '@' )
57 nblettre += ArgLoadFromFile ( &argv[i][1] );
61 ArgLab [ArgCount] = strcpy ( (char *)malloc(strlen(argv[i])+1), argv[i] ) ;
62 nblettre += 1 + strlen(ArgLab[ArgCount]);
65 if (ArgCount >= ARGMAXCOUNT )
67 std::cout << "Too many Arguments ( more than "
68 << ARGMAXCOUNT << ")" << std::endl;
73 /* Fills an array with the already used parameters ****/
74 ArgUsed = (char *)calloc (1, ArgCount );
76 /* Builds the full string with all the parameters **************/
77 Appel = (char *) calloc (1, nblettre );
79 for ( *Appel = '\0', i=0; i<ArgCount; i++)
81 strcat ( Appel, ArgLab [i] ) ;
82 strcat ( Appel, " " ) ;
85 /* Splitting label from label value *************************************/
86 for ( i=0; i<ArgCount; i++)
88 char * egaloufin = ArgLab[i] ;
89 while ( (*egaloufin != '\0') && (*egaloufin != '=') )
91 if ( *egaloufin ) *(egaloufin++) = '\0';
95 /* Set labels to upper-case (labels are not case sensitive ) *********/
96 for ( i=0; i<ArgCount; i++)
97 ArgLab[i] = Majuscule ( ArgLab[i] ) ;
99 /* Standard arguments are managed by ArgStdArgs **********************/
104 * \brief canonical destructor
108 for(int i=0;i<ArgCount;i++)
118 * \brief checks if a parameter exists in the command line
119 * @param param label name
120 * @return 0 if label is not found
121 * else, returns the number of the spot it was found last time.
123 int ArgMgr::ArgMgrDefined( const char *param )
128 temp = Majuscule ( param ) ;
129 for ( i = ArgCount-1; i>0; i-- )
131 trouve = ( strcmp( ArgLab[i], temp )==0 ) ;
135 for ( int j=1; j<i; j++)
137 if ( (!ArgUsed[j])&&(!strcmp(ArgLab[i],ArgLab[j])) )
147 * \brief Gets the parameter value, read on the command line
148 * @param param name of the searched parameter label
149 * @return Value, as a char array, of the parameter
150 * whose label is given.
152 char *ArgMgr::ArgMgrValue ( const char *param )
155 if ( (trouve = ArgMgrDefined ( param )) != false )
156 return ArgStr[trouve] ;
162 * \brief Search for the first not yet used label
163 * @return Pointer to the char array holding the first non used label
165 const char *ArgMgr::ArgMgrUnused ( )
168 for ( i=ArgCount-1; i>0; i-- )
172 ArgMgrDefined(ArgLab[i]);
180 * \brief Prints unused labels, if any
181 * @return number of unused labels
183 int ArgMgr::ArgMgrPrintUnusedLabels ()
187 while ( (label=ArgMgrUnused())!=0 )
190 std::cout << "\n Unused Labels:" << std::endl
191 << "==============" << std::endl;
192 std::cout << "Label : " << label << " = "
193 << ArgMgrValue(label) << std::endl;
200 * \brief Prints program usage
201 * @param usage array of pointers to the documentation lines of the program.
202 * @return exception code
204 int ArgMgr::ArgMgrUsage(const char **usage )
207 std::cout << std::endl << *(usage++);
208 std::cout << std::endl;
213 * \brief Forget it, right now ...
214 * Saves a char. array in a parameter file
215 * whose name is given on command line by : PARAMOUT=???
216 * or, as a default, by ARG_DEFAULT_PARAMOUT
217 * @param param char. array that defines the parameter
218 * @return Entier correspondant au rang dans la liste de labels
220 int ArgMgr::ArgMgrSave ( const char *param )
224 if ( *ArgParamOut == '\0' )
228 fd = fopen ( ArgParamOut, "a+" );
233 fd = fopen ( ArgParamOut, "w" );
237 fprintf ( fd, "%s\n", param );
243 * \brief Gets an int value passed as an argument to a program
244 * (use default value if not found)
245 * EXAMPLE: int dimx = ArgMgrGetInt ( "DIMX", 256 );
246 * @param label label name
247 * @param defaultVal default value
248 * @return parameter value
250 int ArgMgr::ArgMgrGetInt(const char *label, int defaultVal)
252 return ( (ArgMgrDefined(label))
253 ? (atoi(ArgMgrValue(label)))
258 * \brief Gets a float value passed as an argument to a program
259 * (use default value if not found)
260 * EXAMPLE: float scale = ArgMgrGetFloat ( "SCALE", 0.33 );
261 * @param param label name
262 * @param defaultVal default value
263 * @return parameter value
265 float ArgMgr::ArgMgrGetFloat(const char *param, float defaultVal)
267 return ( (ArgMgrDefined(param))
268 ? ((float)atof(ArgMgrValue(param)))
273 * \brief Gets a 'string' value passed as an argument to a program
274 * (use default value if not found)
275 * EXAMPLE : char *imageName = ArgMgrGetString( "NAME", "test.dcm" );
276 * @param param label name
277 * @param defaultVal default value
278 * @return parameter value
280 const char *ArgMgr::ArgMgrGetString(const char *param, const char *defaultVal)
282 return ( (ArgMgrDefined(param))
283 ? (ArgMgrValue(param))
288 * \brief Gets a value amongst a set of values
289 * (use default value if not found)
290 * EXAMPLE: int nlab = ArgMgrGetLabel("CONFIRM","NO\\YES", 0);
291 * @param param label name
292 * @param liste character Chain describing the various values.
293 * Value are separated by '\\'.
294 * Not case sensitive.
295 * @param val number of default value
296 * @return int : range of value amongst the values list
298 int ArgMgr::ArgMgrGetLabel (const char *param, const char *liste, int val )
304 tmp = (char *) malloc(strlen(liste)+1);
307 if ( (vallab = ArgMgrGetString(param,(const char *)NULL)) != 0 )
309 for ( lab = strtok (tmp,"\\");
311 lab = strtok(0L,"\\"), i++ )
313 // strcmp ignoring case
314 if( strcasecmp(lab, vallab) == 0)
324 * \brief Demands a value amongst a set of values (abort if not found)
325 * EXaMPLE: int nlab = ArgMgrWantLabel("CONFIRM","NO\\YES", usage);
326 * @param param label name
327 * @param liste character Chain describing the various values.
328 * Labels are separated by '\\'.
330 * WARNING this will be changed (not const)
331 * @param usage Usage program (displayed if label not found)
332 * @return int : range of value amongst the values list
334 int ArgMgr::ArgMgrWantLabel (const char *param, char *liste, const char **usage )
339 if ( (vallab = ArgMgrGetString(param,0)) != 0 )
341 for ( lab = strtok (liste,"\\"); lab != 0; lab = strtok(0L,"\\"), i++ )
342 if ( strcasecmp(lab,vallab)==0)
351 * \brief Demands an int value passed as an argument to a program
352 * If not found usage is displayed and the prog aborted
353 * EXAMPLE: int dimx = ArgMgrWantInt ( "DIMX", usage );
354 * @param label label name
355 * @param usage Usage program (displayed if label not found)
356 * @return parameter value
358 int ArgMgr::ArgMgrWantInt (const char *label, const char **usage)
360 return ( (ArgMgrDefined(label) )
361 ? (atoi(ArgMgrValue(label) ) )
362 : (ArgMgrUsage(usage),1) );
366 * \brief Demands a float value passed as an argument to a program
367 * If not found usage is displayed and the prog aborted
368 * EXAMPLE: float scale = ArgMgrWantFloat ( "SCALE", usage );
369 * @param label label name
370 * @param usage Usage program (displayed if label not found)
371 * @return parameter value
373 float ArgMgr::ArgMgrWantFloat (const char *label, const char **usage)
375 return ( (ArgMgrDefined(label) )
376 ? ((float)atof(ArgMgrValue(label) ) )
377 : (ArgMgrUsage(usage),(float)1.0) );
381 * \brief Demands a 'string' value passed as an argument to a program
382 * If not found usage is displayed and the prog aborted
383 * EXAMPLE: char *code = ArgMgrWantString ( "CODE", usage );
384 * @param label Parameter label
385 * @param usage Usage program (displayed if label not found)
386 * @return parameter value
388 char *ArgMgr::ArgMgrWantString(const char *label, const char **usage)
390 return ( (ArgMgrDefined(label) )
391 ? (ArgMgrValue(label) )
392 : (ArgMgrUsage(usage),(char*)0) );
396 * \brief decodes and returns an array of 'STRING'
397 * EXAMPLE: char **codes = ArgMgrGetListOfString ( "CODES", &nbOfCodes );
398 * @param label label name
399 * @param number nb of found 'STRINGs'
400 * @return Pointer to the 'STRING' array; NULL if error
402 char **ArgMgr::ArgMgrGetListOfString ( const char *label, int *number )
405 char *value = ArgMgrValue(label);
414 *number = IdStrCountChar(value,',')+1; /* nb Elements = nb Commas +1 */
416 liste = (char **) malloc (sizeof(char*) * taille + strlen(value)+1);
419 value = strcpy( ((char*)liste)+sizeof(char*) * taille, value );
420 for ( elem = liste, chainecur = strtok(value,", ");
422 taille--, chainecur = (chainecur) ? strtok ( 0, ", " ) : 0 )
424 *(elem++) = chainecur;
430 * \brief decodes and returns an array of 'INT'
431 * EXAMPLE: int *points = ArgMgrGetListOfInt ( "POINTS", &nbOfPoints );
432 * @param label label name
433 * @param number nb of found INT
434 * @return Pointer to the INT array; NULL if error
436 int *ArgMgr::ArgMgrGetListOfInt ( const char *label, int *number )
438 char *value = ArgMgrValue(label);
447 *number = IdStrCountChar(value,',')+1; /* nb Elements = nb Commas +1 */
449 liste = (int *) calloc (1,sizeof(int)*taille );
457 *(elem++) = (int) strtol ( value, &value, 10 );
458 if ( *value == '\0' )
460 if ( *(value++) != ',' )
471 * \brief decodes and returns an array of 'FLOAT'
472 * @param label label name
473 * @param number number of found FLOATs
474 * @return Pointer to the FLOAT array; NULL if error
476 float *ArgMgr::ArgMgrGetListOfFloat ( const char *label, int *number )
478 char *value = ArgMgrValue(label);
484 *number = IdStrCountChar(value,',')+1; /* nb Elements = nb Commas +1 */
486 liste = (float *) calloc (1,sizeof(float)*taille );
497 *(elem++) = (float) strtod ( value, &value );
498 if ( *value == '\0' )
500 if ( *(value++) != ',' )
511 * \brief decodes and returns an array of 'INT pairs', passed in decimal
512 * @param param label name
513 * @param number nb of found pairs
514 * @return pointer to the array of 'INT pairs'; NULL if fail
516 int *ArgMgr::ArgMgrGetIntEnum ( const char *param, int *number )
518 char *value = ArgMgrValue(param);
525 liste = IdStrIntEnum(value, number);
530 * \brief decodes and returns an array of 'INT16 pairs', passed in hexadecimal
531 * @param param label name
532 * @param number nb of found pairs
533 * @return pointer to the array of 'INT16 pairs'; NULL if fail
535 uint16_t *ArgMgr::ArgMgrGetXInt16Enum ( const char *param, int *number )
537 char *value = ArgMgrValue(param);
544 liste = IdStrXInt16Enum(value, number);
548 * \brief decodes and returns an array of 'FLOAT pairs'
549 * @param param label name
550 * @param number nb of found pairs
551 * @return pointer to the array of 'FLOAT pairs'; NULL if fail
554 float *ArgMgr::ArgMgrGetFloatEnum ( const char *param, int *number )
556 char *value = ArgMgrValue(param);
563 liste = IdStrFloatEnum(value, number);
567 // ------------------------ Those are 'service functions' ---------------------
568 // ------------------------ internal use only ---------------------
571 * \brief Counts the nb of occurrences of a given charact within a 'string'
572 * @param chaine Pointer to the 'string'
573 * @param caract charact to count
574 * @return occurence number
576 int ArgMgr::IdStrCountChar (char *chaine, int caract)
580 for ( ptr = chaine ; *ptr!='\0' ; ptr ++ )
587 * \brief returns an array of 'INT pairs'
588 * @param value char array decribing a set of 'INT pairs' (f1-l1, f2-l2, ...)
589 * @param number nb of found INT pairs
590 * @return pointer to the array of 'INT pairs'
592 int *ArgMgr::IdStrIntEnum ( char* value, int *number)
598 *number = IdStrCountChar(value,',')+1; /* nb Elements = nb Commas +1 */
600 liste = (int *) calloc (1,sizeof(int)*2*taille );
608 liste[i] = (int) strtol ( value, &value, 10 );
609 if ( *value == '\0' )
614 if ( *(value++) != '-' )
621 liste[i+1] = (int) strtol ( value, &value, 10 );
623 if ( *value == '\0' )
625 if ( *(value++) != ',' )
636 * \brief returns an array of set of 'INT16 pairs', passed in Hexadecimal
637 * @param value char array decribing a set of 'INT16 pairs' (f1-l1, f2-l2, ...)
638 * coded in hexadecimal e.g. 0x0008,0x00ac
639 * @param number nb of found pairs
640 * @return array of set of 'INT16 pairs'
642 uint16_t *ArgMgr::IdStrXInt16Enum ( char *value, int *number)
648 *number = IdStrCountChar(value,',')+1; /* nb Elements = nb Commas +1 */
650 liste = (uint16_t *) calloc (1,sizeof(uint16_t)*2*taille );
658 liste[i] = (uint16_t) strtol ( value, &value, 16 );
659 if ( *value == '\0' )
664 if ( *(value++) != '-' )
671 liste[i+1] = (uint16_t) strtol ( value, &value, 16 );
673 if ( *value == '\0' )
675 if ( *(value++) != ',' )
685 * \brief returns an array of 'FLOAT pairs'
686 * @param value char array decribing a set of 'FLOAT pairs' (f1-l1, f2-l2, ...)
687 * @param number nb of found pairs
688 * @return pointer to the array of 'FLOAT pairs'; NULL if fail
690 float *ArgMgr::IdStrFloatEnum (char *value, int *number)
695 *number = IdStrCountChar(value,',')+1; /* nb Elements = nb Commas +1 */
697 liste = (float *) calloc (1,sizeof(float)*2*taille );
703 liste[i] = (float) strtod ( value, &value );
704 if ( *value == '\0' )
709 if ( *(value++) != '-' )
716 liste[i+1] = (float) strtod ( value, &value );
718 if ( *value == '\0' )
720 if ( *(value++) != ',' )
730 //-----------------------------------------------------------------------------
733 //-----------------------------------------------------------------------------
736 /**************************************************************************
738 * Nom de la fonction : Majuscule *
739 * Role ............. : Creates a new Upper case char array. *
740 * parameters ....... : Pointer to the initial char array. * *
741 * Valeur retournee . : Pointer to the new Upper case char array. *
743 **************************************************************************/
744 char *ArgMgr::Majuscule (const char *chaine )
746 char *ptr, *ptr2, *ptr3;
747 ptr2 = (char *)malloc(strlen(chaine)*sizeof(char)+1);
749 for ( ptr = (char *)chaine ; *ptr!='\0' ; ptr ++ )
751 *ptr3 = toupper ( * ptr ); ptr3++;
757 /**************************************************************************
759 * Nom de la fonction : FiltreLong *
760 * Role ............. : Stops the program if argument is too long. *
761 * ARG_LONG_MAX defines max length. *
762 * parameters ....... : Pointer to the argument. *
763 * Valeur retournee . : false if OK. *
765 **************************************************************************/
766 int ArgMgr::FiltreLong ( const char *arg )
769 while ( (n++<ARG_LONG_MAX) && (*(arg++) != '\0') ) ;
770 return (n>=ARG_LONG_MAX) ;
773 /*------------------------------------------------------------------------
774 | Role : Reads a parameter from a file
775 | Return : Type : char *
776 | Role : pointer to the label
777 | parameters : param : char *
778 | Role : one where the parameter will be stored
780 | Role : File description (assumed to be open)
781 +------------------------------------------------------------------------*/
782 const char *ArgMgr::LoadedParam ( const char *param, FILE *fd )
785 char *car = (char *)param;
789 /* remove spaces at the beginning****/
790 while ( isspace(carlu=fgetc (fd)) );
798 /* Read all the characters */
801 && ( ( (!quote)&&(!isspace(carlu)) )
802 ||( (quote)&& !(carlu=='\"') ) ) )
804 *(car++) = (char) carlu;
806 /* sans depasser la taille max*/
807 if ( nbcar >= ARG_LONG_MAX )
809 std::cout << "\nError: Argument too long ( > "
810 << ARG_LONG_MAX << ")in parameter file."
820 /*------------------------------------------------------------------------
821 | Role : Reading of arguments in a parameter file
822 | (this function is recursive).
823 | Return : Type : int
824 | Role : length needed to store all the parameters
825 | parameters : filename : char *
826 | Role : parameter File name
828 +------------------------------------------------------------------------*/
829 int ArgMgr::ArgLoadFromFile ( const char *filename )
832 char param[ARG_LONG_MAX+1];
835 fch = fopen ( filename, ID_RFILE_TEXT );
836 while ( LoadedParam (param, fch ) )
838 int n = strlen(param);
841 nbl += ArgLoadFromFile ( ¶m[1] );
845 ArgLab [ArgCount] = strcpy ((char *) malloc(n+1), param ) ;
848 if ( ArgCount >= ARGMAXCOUNT )
856 /*------------------------------------------------------------------------
857 | Role : Standard parameters management (on command line)
858 | Return : Type : void
860 +------------------------------------------------------------------------*/
861 void ArgMgr::ArgStdArgs()
866 if ( (ArgParamOut=ArgMgrValue((char*)ARG_LABEL_PARAMOUT))==0 )
867 ArgParamOut = ARG_DEFAULT_PARAMOUT;
868 if ( (logfile = ArgMgrValue((char*)ARG_LABEL_LOGFILE))!=0)
870 if ( *logfile == '\0' )
871 logfile = (char *)ARG_DEFAULT_LOGFILE;
872 fd = fopen ( logfile, "a+" );
875 fprintf ( fd, "%s\n", Appel );
881 /*------------------------------------------------------------------------
882 | Role : Sets in Upper Case.
883 | Return : Type : char *
884 | parameters : char *
885 +------------------------------------------------------------------------*/
886 char *ArgMgr::maj ( char *a )
891 if ( *b<='z' && *b>='a' ) *b = *b+'A'-'a';
896 //-----------------------------------------------------------------------------
899 //-----------------------------------------------------------------------------
900 } // end namespace gdcm