1 /*=========================================================================
4 Module: $RCSfile: gdcmArgMgr.cxx,v $
6 Date: $Date: 2006/05/31 16:39:25 $
7 Version: $Revision: 1.23 $
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 // No strcasecmp in WIN32 world, but stricmp
25 // http://www.opengroup.org/onlinepubs/007908799/xsh/strcasecmp.html
27 #define strcasecmp stricmp
30 #include <string.h> // For strtok and strlen
31 #include <stdlib.h> // For strtol and strtod
33 #include "gdcmArgMgr.h"
37 //-------------------------------------------------------------------------
38 // Constructor / Destructor
42 * @param argc arguments count, as passed to main()
43 * @param argv pointers array on the arguments passed to main()
45 ArgMgr::ArgMgr(int argc, char **argv)
52 /* Read the parameters of the command line *************************/
53 for ( ArgCount=0, nblettre=1 , i=0; i<argc; i++)
55 if ( FiltreLong(argv[i]) )
57 std::cout << "Argument too long ( > "
58 << ARG_LONG_MAX << ")" << std::endl;
61 if ( argv[i][0] == '@' )
63 nblettre += ArgLoadFromFile ( &argv[i][1] );
67 ArgLab [ArgCount] = strcpy ( (char *)malloc(strlen(argv[i])+1), argv[i] ) ;
68 nblettre += 1 + strlen(ArgLab[ArgCount]);
71 if (ArgCount >= ARGMAXCOUNT )
73 std::cout << "Too many Arguments ( more than "
74 << ARGMAXCOUNT << ")" << std::endl;
79 /* Fills an array with the already used parameters ****/
80 ArgUsed = (char *)calloc (1, ArgCount );
82 /* Builds the full string with all the parameters **************/
83 Appel = (char *) calloc (1, nblettre );
85 for ( *Appel = '\0', i=0; i<ArgCount; i++)
87 strcat ( Appel, ArgLab [i] ) ;
88 strcat ( Appel, " " ) ;
91 /* Splitting label from label value *************************************/
92 for ( i=0; i<ArgCount; i++)
94 char * egaloufin = ArgLab[i] ;
95 while ( (*egaloufin != '\0') && (*egaloufin != '=') )
97 if ( *egaloufin ) *(egaloufin++) = '\0';
101 /* Set labels to upper-case (labels are not case sensitive ) *********/
103 for ( i=0; i<ArgCount; i++)
106 ArgLab[i] = Majuscule ( ArgLab[i] ) ;
107 //free (secu); //we still need it in the caller pgm.
110 /* Standard arguments are managed by ArgStdArgs **********************/
115 * \brief canonical destructor
119 for(int i=0;i<ArgCount;i++)
129 * \brief checks if a parameter exists in the command line
130 * @param param label name
131 * @return 0 if label is not found
132 * else, returns the number of the spot it was found last time.
134 int ArgMgr::ArgMgrDefined( const char *param )
139 temp = Majuscule ( param ) ;
140 for ( i = ArgCount-1; i>0; i-- )
142 trouve = ( strcmp( ArgLab[i], temp )==0 ) ;
147 for ( int j=1; j<i; j++)
149 if ( (!ArgUsed[j])&&(!strcmp(ArgLab[i],ArgLab[j])) )
160 * \brief Gets the parameter value, read on the command line
161 * @param param name of the searched parameter label
162 * @return Value, as a char array, of the parameter
163 * whose label is given.
165 char *ArgMgr::ArgMgrValue ( const char *param )
168 if ( (trouve = ArgMgrDefined ( param )) != false )
169 return ArgStr[trouve] ;
175 * \brief Search for the first not yet used label
176 * @return Pointer to the char array holding the first non used label
178 const char *ArgMgr::ArgMgrUnused ( )
181 for ( i=ArgCount-1; i>0; i-- )
185 ArgMgrDefined(ArgLab[i]);
193 * \brief Prints unused labels, if any
194 * @return number of unused labels
196 int ArgMgr::ArgMgrPrintUnusedLabels ()
200 while ( (label=ArgMgrUnused())!=0 )
203 std::cout << "\n Unused Labels:" << std::endl
204 << "==============" << std::endl;
205 std::cout << "Label : " << label << " = "
206 << ArgMgrValue(label) << std::endl;
213 * \brief Prints program usage
214 * @param usage array of pointers to the documentation lines of the program.
215 * @return exception code
217 int ArgMgr::ArgMgrUsage(const char **usage )
220 std::cout << std::endl << *(usage++);
221 std::cout << std::endl;
226 * \brief Forget it, right now ...
227 * Saves a char. array in a parameter file
228 * whose name is given on command line by : PARAMOUT=???
229 * or, as a default, by ARG_DEFAULT_PARAMOUT
230 * @param param char. array that defines the parameter
231 * @return Entier correspondant au rang dans la liste de labels
233 int ArgMgr::ArgMgrSave ( const char *param )
237 if ( *ArgParamOut == '\0' )
241 fd = fopen ( ArgParamOut, "a+" );
246 fd = fopen ( ArgParamOut, "w" );
250 fprintf ( fd, "%s\n", param );
256 * \brief Gets an int value passed as an argument to a program
257 * (use default value if not found)
258 * EXAMPLE: int dimx = ArgMgrGetInt ( "DIMX", 256 );
259 * @param label label name
260 * @param defaultVal default value
261 * @return parameter value
263 int ArgMgr::ArgMgrGetInt(const char *label, int defaultVal)
265 return ( (ArgMgrDefined(label))
266 ? (atoi(ArgMgrValue(label)))
271 * \brief Gets a float value passed as an argument to a program
272 * (use default value if not found)
273 * EXAMPLE: float scale = ArgMgrGetFloat ( "SCALE", 0.33 );
274 * @param param label name
275 * @param defaultVal default value
276 * @return parameter value
278 float ArgMgr::ArgMgrGetFloat(const char *param, float defaultVal)
280 return ( (ArgMgrDefined(param))
281 ? ((float)atof(ArgMgrValue(param)))
286 * \brief Gets a 'string' value passed as an argument to a program
287 * (use default value if not found)
288 * EXAMPLE : char *imageName = ArgMgrGetString( "NAME", "test.dcm" );
289 * @param param label name
290 * @param defaultVal default value
291 * @return parameter value
293 const char *ArgMgr::ArgMgrGetString(const char *param, const char *defaultVal)
295 return ( (ArgMgrDefined(param))
296 ? (ArgMgrValue(param))
301 * \brief Gets a value amongst a set of values
302 * (use default value if not found)
303 * EXAMPLE: int nlab = ArgMgrGetLabel("CONFIRM","NO\\YES", 0);
304 * @param param label name
305 * @param liste character Chain describing the various values.
306 * Value are separated by '\\'.
307 * Not case sensitive.
308 * @param val number of default value
309 * @return int : range of value amongst the values list
311 int ArgMgr::ArgMgrGetLabel (const char *param, const char *liste, int val )
317 tmp = (char *) malloc(strlen(liste)+1);
320 if ( (vallab = ArgMgrGetString(param,(const char *)NULL)) != 0 )
322 for ( lab = strtok (tmp,"\\");
324 lab = strtok(0L,"\\"), i++ )
326 // strcmp ignoring case
327 if( strcasecmp(lab, vallab) == 0)
337 * \brief Demands a value amongst a set of values (abort if not found)
338 * EXaMPLE: int nlab = ArgMgrWantLabel("CONFIRM","NO\\YES", usage);
339 * @param param label name
340 * @param liste character Chain describing the various values.
341 * Labels are separated by '\\'.
343 * WARNING this will be changed (not const)
344 * @param usage Usage program (displayed if label not found)
345 * @return int : range of value amongst the values list
347 int ArgMgr::ArgMgrWantLabel (const char *param, char *liste, const char **usage )
352 if ( (vallab = ArgMgrGetString(param,0)) != 0 )
354 for ( lab = strtok (liste,"\\"); lab != 0; lab = strtok(0L,"\\"), i++ )
355 if ( strcasecmp(lab,vallab)==0)
364 * \brief Demands an int value passed as an argument to a program
365 * If not found usage is displayed and the prog aborted
366 * EXAMPLE: int dimx = ArgMgrWantInt ( "DIMX", usage );
367 * @param label label name
368 * @param usage Usage program (displayed if label not found)
369 * @return parameter value
371 int ArgMgr::ArgMgrWantInt (const char *label, const char **usage)
373 return ( (ArgMgrDefined(label) )
374 ? (atoi(ArgMgrValue(label) ) )
375 : (ArgMgrUsage(usage),1) );
379 * \brief Demands a float value passed as an argument to a program
380 * If not found usage is displayed and the prog aborted
381 * EXAMPLE: float scale = ArgMgrWantFloat ( "SCALE", usage );
382 * @param label label name
383 * @param usage Usage program (displayed if label not found)
384 * @return parameter value
386 float ArgMgr::ArgMgrWantFloat (const char *label, const char **usage)
388 return ( (ArgMgrDefined(label) )
389 ? ((float)atof(ArgMgrValue(label) ) )
390 : (ArgMgrUsage(usage),(float)1.0) );
394 * \brief Demands a 'string' value passed as an argument to a program
395 * If not found usage is displayed and the prog aborted
396 * EXAMPLE: char *code = ArgMgrWantString ( "CODE", usage );
397 * @param label Parameter label
398 * @param usage Usage program (displayed if label not found)
399 * @return parameter value
401 char *ArgMgr::ArgMgrWantString(const char *label, const char **usage)
403 return ( (ArgMgrDefined(label) )
404 ? (ArgMgrValue(label) )
405 : (ArgMgrUsage(usage),(char*)0) );
409 * \brief decodes and returns an array of 'STRING'
410 * EXAMPLE: char **codes = ArgMgrGetListOfString ( "CODES", &nbOfCodes );
411 * @param label label name
412 * @param number nb of found 'STRINGs'
413 * @return Pointer to the 'STRING' array; NULL if error
415 char **ArgMgr::ArgMgrGetListOfString ( const char *label, int *number )
418 char *value = ArgMgrValue(label);
427 *number = IdStrCountChar(value,',')+1; /* nb Elements = nb Commas +1 */
429 liste = (char **) malloc (sizeof(char*) * taille + strlen(value)+1);
432 value = strcpy( ((char*)liste)+sizeof(char*) * taille, value );
433 for ( elem = liste, chainecur = strtok(value,", ");
435 taille--, chainecur = (chainecur) ? strtok ( 0, ", " ) : 0 )
437 *(elem++) = chainecur;
443 * \brief decodes and returns an array of 'INT'
444 * EXAMPLE: int *points = ArgMgrGetListOfInt ( "POINTS", &nbOfPoints );
445 * @param label label name
446 * @param number nb of found INT
447 * @return Pointer to the INT array; NULL if error
449 int *ArgMgr::ArgMgrGetListOfInt ( const char *label, int *number )
451 char *value = ArgMgrValue(label);
460 *number = IdStrCountChar(value,',')+1; /* nb Elements = nb Commas +1 */
462 liste = (int *) calloc (1,sizeof(int)*taille );
470 *(elem++) = (int) strtol ( value, &value, 10 );
471 if ( *value == '\0' )
473 if ( *(value++) != ',' )
484 * \brief decodes and returns an array of 'FLOAT'
485 * @param label label name
486 * @param number number of found FLOATs
487 * @return Pointer to the FLOAT array; NULL if error
489 float *ArgMgr::ArgMgrGetListOfFloat ( const char *label, int *number )
491 char *value = ArgMgrValue(label);
497 *number = IdStrCountChar(value,',')+1; /* nb Elements = nb Commas +1 */
499 liste = (float *) calloc (1,sizeof(float)*taille );
510 *(elem++) = (float) strtod ( value, &value );
511 if ( *value == '\0' )
513 if ( *(value++) != ',' )
524 * \brief decodes and returns an array of 'INT pairs', passed in decimal
525 * @param param label name
526 * @param number nb of found pairs
527 * @return pointer to the array of 'INT pairs'; NULL if fail
529 int *ArgMgr::ArgMgrGetIntEnum ( const char *param, int *number )
531 char *value = ArgMgrValue(param);
538 liste = IdStrIntEnum(value, number);
543 * \brief decodes and returns an array of 'INT16 pairs', passed in hexadecimal
544 * @param param label name
545 * @param number nb of found pairs
546 * @return pointer to the array of 'INT16 pairs'; NULL if fail
548 uint16_t *ArgMgr::ArgMgrGetXInt16Enum ( const char *param, int *number )
550 char *value = ArgMgrValue(param);
557 liste = IdStrXInt16Enum(value, number);
561 * \brief decodes and returns an array of 'FLOAT pairs'
562 * @param param label name
563 * @param number nb of found pairs
564 * @return pointer to the array of 'FLOAT pairs'; NULL if fail
567 float *ArgMgr::ArgMgrGetFloatEnum ( const char *param, int *number )
569 char *value = ArgMgrValue(param);
576 liste = IdStrFloatEnum(value, number);
580 // ------------------------ Those are 'service functions' ---------------------
581 // ------------------------ internal use only ---------------------
584 * \brief Counts the nb of occurrences of a given charact within a 'string'
585 * @param chaine Pointer to the 'string'
586 * @param caract charact to count
587 * @return occurence number
589 int ArgMgr::IdStrCountChar (char *chaine, int caract)
593 for ( ptr = chaine ; *ptr!='\0' ; ptr ++ )
600 * \brief returns an array of 'INT pairs'
601 * @param value char array decribing a set of 'INT pairs' (f1-l1, f2-l2, ...)
602 * @param number nb of found INT pairs
603 * @return pointer to the array of 'INT pairs'
605 int *ArgMgr::IdStrIntEnum ( char* value, int *number)
611 *number = IdStrCountChar(value,',')+1; /* nb Elements = nb Commas +1 */
613 liste = (int *) calloc (1,sizeof(int)*2*taille );
621 liste[i] = (int) strtol ( value, &value, 10 );
622 if ( *value == '\0' )
627 if ( *(value++) != '-' )
634 liste[i+1] = (int) strtol ( value, &value, 10 );
636 if ( *value == '\0' )
638 if ( *(value++) != ',' )
649 * \brief returns an array of set of 'INT16 pairs', passed in Hexadecimal
650 * @param value char array decribing a set of 'INT16 pairs' (f1-l1, f2-l2, ...)
651 * coded in hexadecimal e.g. 0x0008,0x00ac
652 * @param number nb of found pairs
653 * @return array of set of 'INT16 pairs'
655 uint16_t *ArgMgr::IdStrXInt16Enum ( char *value, int *number)
661 *number = IdStrCountChar(value,',')+1; /* nb Elements = nb Commas +1 */
663 liste = (uint16_t *) calloc (1,sizeof(uint16_t)*2*taille );
671 liste[i] = (uint16_t) strtol ( value, &value, 16 );
672 if ( *value == '\0' )
677 if ( *(value++) != '-' )
684 liste[i+1] = (uint16_t) strtol ( value, &value, 16 );
686 if ( *value == '\0' )
688 if ( *(value++) != ',' )
698 * \brief returns an array of 'FLOAT pairs'
699 * @param value char array decribing a set of 'FLOAT pairs' (f1-l1, f2-l2, ...)
700 * @param number nb of found pairs
701 * @return pointer to the array of 'FLOAT pairs'; NULL if fail
703 float *ArgMgr::IdStrFloatEnum (char *value, int *number)
708 *number = IdStrCountChar(value,',')+1; /* nb Elements = nb Commas +1 */
710 liste = (float *) calloc (1,sizeof(float)*2*taille );
716 liste[i] = (float) strtod ( value, &value );
717 if ( *value == '\0' )
722 if ( *(value++) != '-' )
729 liste[i+1] = (float) strtod ( value, &value );
731 if ( *value == '\0' )
733 if ( *(value++) != ',' )
743 //-----------------------------------------------------------------------------
746 //-----------------------------------------------------------------------------
749 /**************************************************************************
751 * Nom de la fonction : Majuscule *
752 * Role ............. : Creates a new Upper case char array. *
753 * parameters ....... : Pointer to the initial char array. * *
754 * Valeur retournee . : Pointer to the new Upper case char array. *
756 **************************************************************************/
757 char *ArgMgr::Majuscule (const char *chaine )
759 char *ptr, *ptr2, *ptr3;
760 ptr2 = (char *)malloc(strlen(chaine)*sizeof(char)+1);
762 for ( ptr = (char *)chaine ; *ptr!='\0' ; ptr ++ )
764 *ptr3 = toupper ( * ptr ); ptr3++;
770 /**************************************************************************
772 * Nom de la fonction : FiltreLong *
773 * Role ............. : Stops the program if argument is too long. *
774 * ARG_LONG_MAX defines max length. *
775 * parameters ....... : Pointer to the argument. *
776 * Valeur retournee . : false if OK. *
778 **************************************************************************/
779 int ArgMgr::FiltreLong ( const char *arg )
782 while ( (n++<ARG_LONG_MAX) && (*(arg++) != '\0') ) ;
783 return (n>=ARG_LONG_MAX) ;
786 /*------------------------------------------------------------------------
787 | Role : Reads a parameter from a file
788 | Return : Type : char *
789 | Role : pointer to the label
790 | parameters : param : char *
791 | Role : one where the parameter will be stored
793 | Role : File description (assumed to be open)
794 +------------------------------------------------------------------------*/
795 const char *ArgMgr::LoadedParam ( const char *param, FILE *fd )
798 char *car = (char *)param;
802 /* remove spaces at the beginning****/
803 while ( isspace(carlu=fgetc (fd)) );
811 /* Read all the characters */
814 && ( ( (!quote)&&(!isspace(carlu)) )
815 ||( (quote)&& !(carlu=='\"') ) ) )
817 *(car++) = (char) carlu;
819 /* sans depasser la taille max*/
820 if ( nbcar >= ARG_LONG_MAX )
822 std::cout << "\nError: Argument too long ( > "
823 << ARG_LONG_MAX << ")in parameter file."
833 /*------------------------------------------------------------------------
834 | Role : Reading of arguments in a parameter file
835 | (this function is recursive).
836 | Return : Type : int
837 | Role : length needed to store all the parameters
838 | parameters : filename : char *
839 | Role : parameter File name
841 +------------------------------------------------------------------------*/
842 int ArgMgr::ArgLoadFromFile ( const char *filename )
845 char param[ARG_LONG_MAX+1];
848 fch = fopen ( filename, ID_RFILE_TEXT );
849 while ( LoadedParam (param, fch ) )
851 int n = strlen(param);
854 nbl += ArgLoadFromFile ( ¶m[1] );
858 ArgLab [ArgCount] = strcpy ((char *) malloc(n+1), param ) ;
861 if ( ArgCount >= ARGMAXCOUNT )
869 /*------------------------------------------------------------------------
870 | Role : Standard parameters management (on command line)
871 | Return : Type : void
873 +------------------------------------------------------------------------*/
874 void ArgMgr::ArgStdArgs()
879 if ( (ArgParamOut=ArgMgrValue((char*)ARG_LABEL_PARAMOUT))==0 )
880 ArgParamOut = ARG_DEFAULT_PARAMOUT;
881 if ( (logfile = ArgMgrValue((char*)ARG_LABEL_LOGFILE))!=0)
883 if ( *logfile == '\0' )
884 logfile = (char *)ARG_DEFAULT_LOGFILE;
885 fd = fopen ( logfile, "a+" );
888 fprintf ( fd, "%s\n", Appel );
894 /*------------------------------------------------------------------------
895 | Role : Sets in Upper Case.
896 | Return : Type : char *
897 | parameters : char *
898 +------------------------------------------------------------------------*/
899 char *ArgMgr::maj ( char *a )
904 if ( *b<='z' && *b>='a' ) *b = *b+'A'-'a';
909 //-----------------------------------------------------------------------------
912 //-----------------------------------------------------------------------------
913 } // end namespace gdcm