1 /*=========================================================================
4 Module: $RCSfile: gdcmArgMgr.cxx,v $
6 Date: $Date: 2006/01/26 18:26:04 $
7 Version: $Revision: 1.19 $
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 borland, but stricmp
26 #define strcasecmp stricmp
29 #include <string.h> // For strtok and strlen
30 #include <stdlib.h> // For strtol and strtod
32 #include "gdcmArgMgr.h"
36 //-------------------------------------------------------------------------
37 // Constructor / Destructor
41 * @param argc arguments count, as passed to main()
42 * @param argv pointers array on the arguments passed to main()
44 ArgMgr::ArgMgr(int argc, char **argv)
51 /* Read the parameters of the command line *************************/
52 for ( ArgCount=0, nblettre=1 , i=0; i<argc; i++)
54 if ( FiltreLong(argv[i]) )
56 std::cout << "Argument too long ( > "
57 << ARG_LONG_MAX << ")" << std::endl;
60 if ( argv[i][0] == '@' )
62 nblettre += ArgLoadFromFile ( &argv[i][1] );
66 ArgLab [ArgCount] = strcpy ( (char *)malloc(strlen(argv[i])+1), argv[i] ) ;
67 nblettre += 1 + strlen(ArgLab[ArgCount]);
70 if (ArgCount >= ARGMAXCOUNT )
72 std::cout << "Too many Arguments ( more than "
73 << ARGMAXCOUNT << ")" << std::endl;
78 /* Fills an array with the already used parameters ****/
79 ArgUsed = (char *)calloc (1, ArgCount );
81 /* Builds the full string with all the parameters **************/
82 Appel = (char *) calloc (1, nblettre );
84 for ( *Appel = '\0', i=0; i<ArgCount; i++)
86 strcat ( Appel, ArgLab [i] ) ;
87 strcat ( Appel, " " ) ;
90 /* Splitting label from label value *************************************/
91 for ( i=0; i<ArgCount; i++)
93 char * egaloufin = ArgLab[i] ;
94 while ( (*egaloufin != '\0') && (*egaloufin != '=') )
96 if ( *egaloufin ) *(egaloufin++) = '\0';
100 /* Set labels to upper-case (labels are not case sensitive ) *********/
101 for ( i=0; i<ArgCount; i++)
102 ArgLab[i] = Majuscule ( ArgLab[i] ) ;
104 /* Standard arguments are managed by ArgStdArgs **********************/
109 * \brief canonical destructor
113 for(int i=0;i<ArgCount;i++)
123 * \brief checks if a parameter exists in the command line
124 * @param param label name
125 * @return 0 if label is not found
126 * else, returns the number of the spot it was found last time.
128 int ArgMgr::ArgMgrDefined( const char *param )
133 temp = Majuscule ( param ) ;
134 for ( i = ArgCount-1; i>0; i-- )
136 trouve = ( strcmp( ArgLab[i], temp )==0 ) ;
140 for ( int j=1; j<i; j++)
142 if ( (!ArgUsed[j])&&(!strcmp(ArgLab[i],ArgLab[j])) )
152 * \brief Gets the parameter value, read on the command line
153 * @param param name of the searched parameter label
154 * @return Value, as a char array, of the parameter
155 * whose label is given.
157 char *ArgMgr::ArgMgrValue ( const char *param )
160 if ( (trouve = ArgMgrDefined ( param )) != false )
161 return ArgStr[trouve] ;
167 * \brief Search for the first not yet used label
168 * @return Pointer to the char array holding the first non used label
170 const char *ArgMgr::ArgMgrUnused ( )
173 for ( i=ArgCount-1; i>0; i-- )
177 ArgMgrDefined(ArgLab[i]);
185 * \brief Prints unused labels, if any
186 * @return number of unused labels
188 int ArgMgr::ArgMgrPrintUnusedLabels ()
192 while ( (label=ArgMgrUnused())!=0 )
195 std::cout << "\n Unused Labels:" << std::endl
196 << "==============" << std::endl;
197 std::cout << "Label : " << label << " = "
198 << ArgMgrValue(label) << std::endl;
205 * \brief Prints program usage
206 * @param usage array of pointers to the documentation lines of the program.
207 * @return exception code
209 int ArgMgr::ArgMgrUsage(const char **usage )
212 std::cout << std::endl << *(usage++);
213 std::cout << std::endl;
218 * \brief Forget it, right now ...
219 * Saves a char. array in a parameter file
220 * whose name is given on command line by : PARAMOUT=???
221 * or, as a default, by ARG_DEFAULT_PARAMOUT
222 * @param param char. array that defines the parameter
223 * @return Entier correspondant au rang dans la liste de labels
225 int ArgMgr::ArgMgrSave ( const char *param )
229 if ( *ArgParamOut == '\0' )
233 fd = fopen ( ArgParamOut, "a+" );
238 fd = fopen ( ArgParamOut, "w" );
242 fprintf ( fd, "%s\n", param );
248 * \brief Gets an int value passed as an argument to a program
249 * (use default value if not found)
250 * EXAMPLE: int dimx = ArgMgrGetInt ( "DIMX", 256 );
251 * @param label label name
252 * @param defaultVal default value
253 * @return parameter value
255 int ArgMgr::ArgMgrGetInt(const char *label, int defaultVal)
257 return ( (ArgMgrDefined(label))
258 ? (atoi(ArgMgrValue(label)))
263 * \brief Gets a float value passed as an argument to a program
264 * (use default value if not found)
265 * EXAMPLE: float scale = ArgMgrGetFloat ( "SCALE", 0.33 );
266 * @param param label name
267 * @param defaultVal default value
268 * @return parameter value
270 float ArgMgr::ArgMgrGetFloat(const char *param, float defaultVal)
272 return ( (ArgMgrDefined(param))
273 ? ((float)atof(ArgMgrValue(param)))
278 * \brief Gets a 'string' value passed as an argument to a program
279 * (use default value if not found)
280 * EXAMPLE : char *imageName = ArgMgrGetString( "NAME", "test.dcm" );
281 * @param param label name
282 * @param defaultVal default value
283 * @return parameter value
285 const char *ArgMgr::ArgMgrGetString(const char *param, const char *defaultVal)
287 return ( (ArgMgrDefined(param))
288 ? (ArgMgrValue(param))
293 * \brief Gets a value amongst a set of values
294 * (use default value if not found)
295 * EXAMPLE: int nlab = ArgMgrGetLabel("CONFIRM","NO\\YES", 0);
296 * @param param label name
297 * @param liste character Chain describing the various values.
298 * Value are separated by '\\'.
299 * Not case sensitive.
300 * @param val number of default value
301 * @return int : range of value amongst the values list
303 int ArgMgr::ArgMgrGetLabel (const char *param, const char *liste, int val )
309 tmp = (char *) malloc(strlen(liste)+1);
312 if ( (vallab = ArgMgrGetString(param,(const char *)NULL)) != 0 )
314 for ( lab = strtok (tmp,"\\");
316 lab = strtok(0L,"\\"), i++ )
318 // strcmp ignoring case
319 if( strcasecmp(lab, vallab) == 0)
329 * \brief Demands a value amongst a set of values (abort if not found)
330 * EXaMPLE: int nlab = ArgMgrWantLabel("CONFIRM","NO\\YES", usage);
331 * @param param label name
332 * @param liste character Chain describing the various values.
333 * Labels are separated by '\\'.
335 * WARNING this will be changed (not const)
336 * @param usage Usage program (displayed if label not found)
337 * @return int : range of value amongst the values list
339 int ArgMgr::ArgMgrWantLabel (const char *param, char *liste, const char **usage )
344 if ( (vallab = ArgMgrGetString(param,0)) != 0 )
346 for ( lab = strtok (liste,"\\"); lab != 0; lab = strtok(0L,"\\"), i++ )
347 if ( strcasecmp(lab,vallab)==0)
356 * \brief Demands an int value passed as an argument to a program
357 * If not found usage is displayed and the prog aborted
358 * EXAMPLE: int dimx = ArgMgrWantInt ( "DIMX", usage );
359 * @param label label name
360 * @param usage Usage program (displayed if label not found)
361 * @return parameter value
363 int ArgMgr::ArgMgrWantInt (const char *label, const char **usage)
365 return ( (ArgMgrDefined(label) )
366 ? (atoi(ArgMgrValue(label) ) )
367 : (ArgMgrUsage(usage),1) );
371 * \brief Demands a float value passed as an argument to a program
372 * If not found usage is displayed and the prog aborted
373 * EXAMPLE: float scale = ArgMgrWantFloat ( "SCALE", usage );
374 * @param label label name
375 * @param usage Usage program (displayed if label not found)
376 * @return parameter value
378 float ArgMgr::ArgMgrWantFloat (const char *label, const char **usage)
380 return ( (ArgMgrDefined(label) )
381 ? ((float)atof(ArgMgrValue(label) ) )
382 : (ArgMgrUsage(usage),(float)1.0) );
386 * \brief Demands a 'string' value passed as an argument to a program
387 * If not found usage is displayed and the prog aborted
388 * EXAMPLE: char *code = ArgMgrWantString ( "CODE", usage );
389 * @param label Parameter label
390 * @param usage Usage program (displayed if label not found)
391 * @return parameter value
393 char *ArgMgr::ArgMgrWantString(const char *label, const char **usage)
395 return ( (ArgMgrDefined(label) )
396 ? (ArgMgrValue(label) )
397 : (ArgMgrUsage(usage),(char*)0) );
401 * \brief decodes and returns an array of 'STRING'
402 * EXAMPLE: char **codes = ArgMgrGetListOfString ( "CODES", &nbOfCodes );
403 * @param label label name
404 * @param number nb of found 'STRINGs'
405 * @return Pointer to the 'STRING' array; NULL if error
407 char **ArgMgr::ArgMgrGetListOfString ( const char *label, int *number )
410 char *value = ArgMgrValue(label);
419 *number = IdStrCountChar(value,',')+1; /* nb Elements = nb Commas +1 */
421 liste = (char **) malloc (sizeof(char*) * taille + strlen(value)+1);
424 value = strcpy( ((char*)liste)+sizeof(char*) * taille, value );
425 for ( elem = liste, chainecur = strtok(value,", ");
427 taille--, chainecur = (chainecur) ? strtok ( 0, ", " ) : 0 )
429 *(elem++) = chainecur;
435 * \brief decodes and returns an array of 'INT'
436 * EXAMPLE: int *points = ArgMgrGetListOfInt ( "POINTS", &nbOfPoints );
437 * @param label label name
438 * @param number nb of found INT
439 * @return Pointer to the INT array; NULL if error
441 int *ArgMgr::ArgMgrGetListOfInt ( const char *label, int *number )
443 char *value = ArgMgrValue(label);
452 *number = IdStrCountChar(value,',')+1; /* nb Elements = nb Commas +1 */
454 liste = (int *) calloc (1,sizeof(int)*taille );
462 *(elem++) = (int) strtol ( value, &value, 10 );
463 if ( *value == '\0' )
465 if ( *(value++) != ',' )
476 * \brief decodes and returns an array of 'FLOAT'
477 * @param label label name
478 * @param number number of found FLOATs
479 * @return Pointer to the FLOAT array; NULL if error
481 float *ArgMgr::ArgMgrGetListOfFloat ( const char *label, int *number )
483 char *value = ArgMgrValue(label);
489 *number = IdStrCountChar(value,',')+1; /* nb Elements = nb Commas +1 */
491 liste = (float *) calloc (1,sizeof(float)*taille );
502 *(elem++) = (float) strtod ( value, &value );
503 if ( *value == '\0' )
505 if ( *(value++) != ',' )
516 * \brief decodes and returns an array of 'INT pairs', passed in decimal
517 * @param param label name
518 * @param number nb of found pairs
519 * @return pointer to the array of 'INT pairs'; NULL if fail
521 int *ArgMgr::ArgMgrGetIntEnum ( const char *param, int *number )
523 char *value = ArgMgrValue(param);
530 liste = IdStrIntEnum(value, number);
535 * \brief decodes and returns an array of 'INT16 pairs', passed in hexadecimal
536 * @param param label name
537 * @param number nb of found pairs
538 * @return pointer to the array of 'INT16 pairs'; NULL if fail
540 uint16_t *ArgMgr::ArgMgrGetXInt16Enum ( const char *param, int *number )
542 char *value = ArgMgrValue(param);
549 liste = IdStrXInt16Enum(value, number);
553 * \brief decodes and returns an array of 'FLOAT pairs'
554 * @param param label name
555 * @param number nb of found pairs
556 * @return pointer to the array of 'FLOAT pairs'; NULL if fail
559 float *ArgMgr::ArgMgrGetFloatEnum ( const char *param, int *number )
561 char *value = ArgMgrValue(param);
568 liste = IdStrFloatEnum(value, number);
572 // ------------------------ Those are 'service functions' ---------------------
573 // ------------------------ internal use only ---------------------
576 * \brief Counts the nb of occurrences of a given charact within a 'string'
577 * @param chaine Pointer to the 'string'
578 * @param caract charact to count
579 * @return occurence number
581 int ArgMgr::IdStrCountChar (char *chaine, int caract)
585 for ( ptr = chaine ; *ptr!='\0' ; ptr ++ )
592 * \brief returns an array of 'INT pairs'
593 * @param value char array decribing a set of 'INT pairs' (f1-l1, f2-l2, ...)
594 * @param number nb of found INT pairs
595 * @return pointer to the array of 'INT pairs'
597 int *ArgMgr::IdStrIntEnum ( char* value, int *number)
603 *number = IdStrCountChar(value,',')+1; /* nb Elements = nb Commas +1 */
605 liste = (int *) calloc (1,sizeof(int)*2*taille );
613 liste[i] = (int) strtol ( value, &value, 10 );
614 if ( *value == '\0' )
619 if ( *(value++) != '-' )
626 liste[i+1] = (int) strtol ( value, &value, 10 );
628 if ( *value == '\0' )
630 if ( *(value++) != ',' )
641 * \brief returns an array of set of 'INT16 pairs', passed in Hexadecimal
642 * @param value char array decribing a set of 'INT16 pairs' (f1-l1, f2-l2, ...)
643 * coded in hexadecimal e.g. 0x0008,0x00ac
644 * @param number nb of found pairs
645 * @return array of set of 'INT16 pairs'
647 uint16_t *ArgMgr::IdStrXInt16Enum ( char *value, int *number)
653 *number = IdStrCountChar(value,',')+1; /* nb Elements = nb Commas +1 */
655 liste = (uint16_t *) calloc (1,sizeof(uint16_t)*2*taille );
663 liste[i] = (uint16_t) strtol ( value, &value, 16 );
664 if ( *value == '\0' )
669 if ( *(value++) != '-' )
676 liste[i+1] = (uint16_t) strtol ( value, &value, 16 );
678 if ( *value == '\0' )
680 if ( *(value++) != ',' )
690 * \brief returns an array of 'FLOAT pairs'
691 * @param value char array decribing a set of 'FLOAT pairs' (f1-l1, f2-l2, ...)
692 * @param number nb of found pairs
693 * @return pointer to the array of 'FLOAT pairs'; NULL if fail
695 float *ArgMgr::IdStrFloatEnum (char *value, int *number)
700 *number = IdStrCountChar(value,',')+1; /* nb Elements = nb Commas +1 */
702 liste = (float *) calloc (1,sizeof(float)*2*taille );
708 liste[i] = (float) strtod ( value, &value );
709 if ( *value == '\0' )
714 if ( *(value++) != '-' )
721 liste[i+1] = (float) strtod ( value, &value );
723 if ( *value == '\0' )
725 if ( *(value++) != ',' )
735 //-----------------------------------------------------------------------------
738 //-----------------------------------------------------------------------------
741 /**************************************************************************
743 * Nom de la fonction : Majuscule *
744 * Role ............. : Creates a new Upper case char array. *
745 * parameters ....... : Pointer to the initial char array. * *
746 * Valeur retournee . : Pointer to the new Upper case char array. *
748 **************************************************************************/
749 char *ArgMgr::Majuscule (const char *chaine )
751 char *ptr, *ptr2, *ptr3;
752 ptr2 = (char *)malloc(strlen(chaine)*sizeof(char)+1);
754 for ( ptr = (char *)chaine ; *ptr!='\0' ; ptr ++ )
756 *ptr3 = toupper ( * ptr ); ptr3++;
762 /**************************************************************************
764 * Nom de la fonction : FiltreLong *
765 * Role ............. : Stops the program if argument is too long. *
766 * ARG_LONG_MAX defines max length. *
767 * parameters ....... : Pointer to the argument. *
768 * Valeur retournee . : false if OK. *
770 **************************************************************************/
771 int ArgMgr::FiltreLong ( const char *arg )
774 while ( (n++<ARG_LONG_MAX) && (*(arg++) != '\0') ) ;
775 return (n>=ARG_LONG_MAX) ;
778 /*------------------------------------------------------------------------
779 | Role : Reads a parameter from a file
780 | Return : Type : char *
781 | Role : pointer to the label
782 | parameters : param : char *
783 | Role : one where the parameter will be stored
785 | Role : File description (assumed to be open)
786 +------------------------------------------------------------------------*/
787 const char *ArgMgr::LoadedParam ( const char *param, FILE *fd )
790 char *car = (char *)param;
794 /* remove spaces at the beginning****/
795 while ( isspace(carlu=fgetc (fd)) );
803 /* Read all the characters */
806 && ( ( (!quote)&&(!isspace(carlu)) )
807 ||( (quote)&& !(carlu=='\"') ) ) )
809 *(car++) = (char) carlu;
811 /* sans depasser la taille max*/
812 if ( nbcar >= ARG_LONG_MAX )
814 std::cout << "\nError: Argument too long ( > "
815 << ARG_LONG_MAX << ")in parameter file."
825 /*------------------------------------------------------------------------
826 | Role : Reading of arguments in a parameter file
827 | (this function is recursive).
828 | Return : Type : int
829 | Role : length needed to store all the parameters
830 | parameters : filename : char *
831 | Role : parameter File name
833 +------------------------------------------------------------------------*/
834 int ArgMgr::ArgLoadFromFile ( const char *filename )
837 char param[ARG_LONG_MAX+1];
840 fch = fopen ( filename, ID_RFILE_TEXT );
841 while ( LoadedParam (param, fch ) )
843 int n = strlen(param);
846 nbl += ArgLoadFromFile ( ¶m[1] );
850 ArgLab [ArgCount] = strcpy ((char *) malloc(n+1), param ) ;
853 if ( ArgCount >= ARGMAXCOUNT )
861 /*------------------------------------------------------------------------
862 | Role : Standard parameters management (on command line)
863 | Return : Type : void
865 +------------------------------------------------------------------------*/
866 void ArgMgr::ArgStdArgs()
871 if ( (ArgParamOut=ArgMgrValue((char*)ARG_LABEL_PARAMOUT))==0 )
872 ArgParamOut = ARG_DEFAULT_PARAMOUT;
873 if ( (logfile = ArgMgrValue((char*)ARG_LABEL_LOGFILE))!=0)
875 if ( *logfile == '\0' )
876 logfile = (char *)ARG_DEFAULT_LOGFILE;
877 fd = fopen ( logfile, "a+" );
880 fprintf ( fd, "%s\n", Appel );
886 /*------------------------------------------------------------------------
887 | Role : Sets in Upper Case.
888 | Return : Type : char *
889 | parameters : char *
890 +------------------------------------------------------------------------*/
891 char *ArgMgr::maj ( char *a )
896 if ( *b<='z' && *b>='a' ) *b = *b+'A'-'a';
901 //-----------------------------------------------------------------------------
904 //-----------------------------------------------------------------------------
905 } // end namespace gdcm