1 /*=========================================================================
4 Module: $RCSfile: gdcmArgMgr.cxx,v $
6 Date: $Date: 2008/05/14 10:45:11 $
7 Version: $Revision: 1.28 $
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"
35 namespace GDCM_NAME_SPACE
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)
46 : ArgParamOut (NULL), ArgUsed(NULL), ArgLab(NULL), ArgStr(NULL), ArgCount(0), Appel(NULL)
50 ArgLab = new char *[ARGMAXCOUNT];
51 ArgStr = new char *[ARGMAXCOUNT];
53 /* Read the parameters of the command line *************************/
54 for ( ArgCount=0, nblettre=1 , i=0; i<argc; i++)
56 if ( FiltreLong(argv[i]) )
58 std::cout << "Argument too long ( > "
59 << ARG_LONG_MAX << ")" << std::endl;
62 if ( argv[i][0] == '@' )
64 nblettre += ArgLoadFromFile ( &argv[i][1] );
68 ArgLab [ArgCount] = strcpy ( (char *)malloc(strlen(argv[i])+1), argv[i] ) ;
69 nblettre += 1 + strlen(ArgLab[ArgCount]);
72 if (ArgCount >= ARGMAXCOUNT )
74 std::cout << "Too many Arguments ( more than "
75 << ARGMAXCOUNT << ")" << std::endl;
80 /* Fills an array with the already used parameters ****/
81 ArgUsed = (char *)calloc (1, ArgCount );
83 /* Builds the full string with all the parameters **************/
84 Appel = (char *) calloc (1, nblettre );
86 for ( *Appel = '\0', i=0; i<ArgCount; i++)
88 strcat ( Appel, ArgLab [i] ) ;
89 strcat ( Appel, " " ) ;
92 /* Splitting label from label value *************************************/
93 for ( i=0; i<ArgCount; i++)
95 char * egaloufin = ArgLab[i] ;
96 while ( (*egaloufin != '\0') && (*egaloufin != '=') )
99 *(egaloufin++) = '\0';
100 ArgStr[i]= egaloufin;
103 /* Set labels to upper-case (labels are not case sensitive ) *********/
105 for ( i=0; i<ArgCount; i++)
108 ArgLab[i] = Majuscule ( ArgLab[i] ) ;
109 //free (secu); //we still need it in the caller pgm.
112 /* Standard arguments are managed by ArgStdArgs **********************/
117 * \brief canonical destructor
121 for(int i=0;i<ArgCount;i++)
134 * \brief checks if a parameter exists in the command line
135 * @param param label name
136 * @return 0 if label is not found
137 * else, returns the number of the spot it was found last time.
139 int ArgMgr::ArgMgrDefined( const char *param )
144 temp = Majuscule ( param ) ;
145 for ( i = ArgCount-1; i>0; i-- )
147 trouve = ( strcmp( ArgLab[i], temp )==0 ) ;
152 for ( int j=1; j<i; j++)
154 if ( (!ArgUsed[j])&&(!strcmp(ArgLab[i],ArgLab[j])) )
165 * \brief Gets the parameter value, read on the command line
166 * @param param name of the searched parameter label
167 * @return Value, as a char array, of the parameter
168 * whose label is given.
170 char *ArgMgr::ArgMgrValue ( const char *param )
173 if ( (trouve = ArgMgrDefined ( param )) != false )
174 return ArgStr[trouve] ;
180 * \brief Search for the first not yet used label
181 * @return Pointer to the char array holding the first non used label
183 const char *ArgMgr::ArgMgrUnused ( )
186 for ( i=ArgCount-1; i>0; i-- )
190 ArgMgrDefined(ArgLab[i]);
198 * \brief Prints unused labels, if any
199 * @return number of unused labels
201 int ArgMgr::ArgMgrPrintUnusedLabels ()
205 while ( (label=ArgMgrUnused())!=0 )
208 std::cout << "\n Unused Labels:" << std::endl
209 << "==============" << std::endl;
210 std::cout << "Label : " << label << " = "
211 << ArgMgrValue(label) << std::endl;
218 * \brief Prints program usage
219 * @param usage array of pointers to the documentation lines of the program.
220 * @return exception code
222 int ArgMgr::ArgMgrUsage(const char **usage )
225 std::cout << std::endl << *(usage++);
226 std::cout << std::endl;
231 * \brief Forget it, right now ...
232 * Saves a char. array in a parameter file
233 * whose name is given on command line by : PARAMOUT=???
234 * or, as a default, by ARG_DEFAULT_PARAMOUT
235 * @param param char. array that defines the parameter
236 * @return Entier correspondant au rang dans la liste de labels
238 int ArgMgr::ArgMgrSave ( const char *param )
242 if ( *ArgParamOut == '\0' )
246 fd = fopen ( ArgParamOut, "a+" );
251 fd = fopen ( ArgParamOut, "w" );
255 fprintf ( fd, "%s\n", param );
261 * \brief Gets an int value passed as an argument to a program
262 * (use default value if not found)
263 * EXAMPLE: int dimx = ArgMgrGetInt ( "DIMX", 256 );
264 * @param label label name
265 * @param defaultVal default value
266 * @return parameter value
268 int ArgMgr::ArgMgrGetInt(const char *label, int defaultVal)
270 return ( (ArgMgrDefined(label))
271 ? (atoi(ArgMgrValue(label)))
276 * \brief Gets a float value passed as an argument to a program
277 * (use default value if not found)
278 * EXAMPLE: float scale = ArgMgrGetFloat ( "SCALE", 0.33 );
279 * @param param label name
280 * @param defaultVal default value
281 * @return parameter value
283 float ArgMgr::ArgMgrGetFloat(const char *param, float defaultVal)
285 return ( (ArgMgrDefined(param))
286 ? ((float)atof(ArgMgrValue(param)))
291 * \brief Gets a 'string' value passed as an argument to a program
292 * (use default value if not found)
293 * EXAMPLE : char *imageName = ArgMgrGetString( "NAME", "test.dcm" );
294 * @param param label name
295 * @param defaultVal default value
296 * @return parameter value
298 const char *ArgMgr::ArgMgrGetString(const char *param, const char *defaultVal)
300 return ( (ArgMgrDefined(param))
301 ? (ArgMgrValue(param))
306 * \brief Gets a value amongst a set of values
307 * (use default value if not found)
308 * EXAMPLE: int nlab = ArgMgrGetLabel("CONFIRM","NO\\YES", 0);
309 * @param param label name
310 * @param liste character Chain describing the various values.
311 * Value are separated by '\\'.
312 * Not case sensitive.
313 * @param val number of default value
314 * @return int : range of value amongst the values list
316 int ArgMgr::ArgMgrGetLabel (const char *param, const char *liste, int val )
322 tmp = (char *) malloc(strlen(liste)+1);
325 if ( (vallab = ArgMgrGetString(param,(const char *)NULL)) != 0 )
327 for ( lab = strtok (tmp,"\\");
329 lab = strtok(0L,"\\"), i++ )
331 // strcmp ignoring case
332 if( strcasecmp(lab, vallab) == 0)
342 * \brief Demands a value amongst a set of values (abort if not found)
343 * EXaMPLE: int nlab = ArgMgrWantLabel("CONFIRM","NO\\YES", usage);
344 * @param param label name
345 * @param liste character Chain describing the various values.
346 * Labels are separated by '\\'.
348 * WARNING this will be changed (not const)
349 * @param usage Usage program (displayed if label not found)
350 * @return int : range of value amongst the values list
352 int ArgMgr::ArgMgrWantLabel (const char *param, char *liste, const char **usage )
357 if ( (vallab = ArgMgrGetString(param,0)) != 0 )
359 for ( lab = strtok (liste,"\\"); lab != 0; lab = strtok(0L,"\\"), i++ )
360 if ( strcasecmp(lab,vallab)==0)
369 * \brief Demands an int value passed as an argument to a program
370 * If not found usage is displayed and the prog aborted
371 * EXAMPLE: int dimx = ArgMgrWantInt ( "DIMX", usage );
372 * @param label label name
373 * @param usage Usage program (displayed if label not found)
374 * @return parameter value
376 int ArgMgr::ArgMgrWantInt (const char *label, const char **usage)
378 return ( (ArgMgrDefined(label) )
379 ? (atoi(ArgMgrValue(label) ) )
380 : (ArgMgrUsage(usage),1) );
384 * \brief Demands a float value passed as an argument to a program
385 * If not found usage is displayed and the prog aborted
386 * EXAMPLE: float scale = ArgMgrWantFloat ( "SCALE", usage );
387 * @param label label name
388 * @param usage Usage program (displayed if label not found)
389 * @return parameter value
391 float ArgMgr::ArgMgrWantFloat (const char *label, const char **usage)
393 return ( (ArgMgrDefined(label) )
394 ? ((float)atof(ArgMgrValue(label) ) )
395 : (ArgMgrUsage(usage),(float)1.0) );
399 * \brief Demands a 'string' value passed as an argument to a program
400 * If not found usage is displayed and the prog aborted
401 * EXAMPLE: char *code = ArgMgrWantString ( "CODE", usage );
402 * @param label Parameter label
403 * @param usage Usage program (displayed if label not found)
404 * @return parameter value
406 char *ArgMgr::ArgMgrWantString(const char *label, const char **usage)
408 return ( (ArgMgrDefined(label) )
409 ? (ArgMgrValue(label) )
410 : (ArgMgrUsage(usage),(char*)0) );
414 * \brief decodes and returns an array of 'STRING'
415 * EXAMPLE: char **codes = ArgMgrGetListOfString ( "CODES", &nbOfCodes );
416 * @param label label name
417 * @param number nb of found 'STRINGs'
418 * @return Pointer to the 'STRING' array; NULL if error
420 char **ArgMgr::ArgMgrGetListOfString ( const char *label, int *number )
423 char *value = ArgMgrValue(label);
432 *number = IdStrCountChar(value,',')+1; /* nb Elements = nb Commas +1 */
434 liste = (char **) malloc (sizeof(char*) * taille + strlen(value)+1);
437 value = strcpy( ((char*)liste)+sizeof(char*) * taille, value );
438 for ( elem = liste, chainecur = strtok(value,", ");
440 taille--, chainecur = (chainecur) ? strtok ( 0, ", " ) : 0 )
442 *(elem++) = chainecur;
448 * \brief decodes and returns an array of 'INT'
449 * EXAMPLE: int *points = ArgMgrGetListOfInt ( "POINTS", &nbOfPoints );
450 * @param label label name
451 * @param number nb of found INT
452 * @return Pointer to the INT array; NULL if error
454 int *ArgMgr::ArgMgrGetListOfInt ( const char *label, int *number )
456 char *value = ArgMgrValue(label);
465 *number = IdStrCountChar(value,',')+1; /* nb Elements = nb Commas +1 */
467 liste = (int *) calloc (1,sizeof(int)*taille );
475 *(elem++) = (int) strtol ( value, &value, 10 );
476 if ( *value == '\0' )
478 if ( *(value++) != ',' )
489 * \brief decodes and returns an array of 'FLOAT'
490 * @param label label name
491 * @param number number of found FLOATs
492 * @return Pointer to the FLOAT array; NULL if error
494 float *ArgMgr::ArgMgrGetListOfFloat ( const char *label, int *number )
496 char *value = ArgMgrValue(label);
502 *number = IdStrCountChar(value,',')+1; /* nb Elements = nb Commas +1 */
504 liste = (float *) calloc (1,sizeof(float)*taille );
515 *(elem++) = (float) strtod ( value, &value );
516 if ( *value == '\0' )
518 if ( *(value++) != ',' )
529 * \brief decodes and returns an array of 'INT pairs', passed in decimal
530 * @param param label name
531 * @param number nb of found pairs
532 * @return pointer to the array of 'INT pairs'; NULL if fail
534 int *ArgMgr::ArgMgrGetIntEnum ( const char *param, int *number )
536 char *value = ArgMgrValue(param);
543 liste = IdStrIntEnum(value, number);
548 * \brief decodes and returns an array of 'INT16 pairs', passed in hexadecimal
549 * @param param label name
550 * @param number nb of found pairs
551 * @return pointer to the array of 'INT16 pairs'; NULL if fail
553 uint16_t *ArgMgr::ArgMgrGetXInt16Enum ( const char *param, int *number )
555 char *value = ArgMgrValue(param);
562 liste = IdStrXInt16Enum(value, number);
566 * \brief decodes and returns an array of 'FLOAT pairs'
567 * @param param label name
568 * @param number nb of found pairs
569 * @return pointer to the array of 'FLOAT pairs'; NULL if fail
572 float *ArgMgr::ArgMgrGetFloatEnum ( const char *param, int *number )
574 char *value = ArgMgrValue(param);
581 liste = IdStrFloatEnum(value, number);
585 // ------------------------ Those are 'service functions' ---------------------
586 // ------------------------ internal use only ---------------------
589 * \brief Counts the nb of occurrences of a given charact within a 'string'
590 * @param chaine Pointer to the 'string'
591 * @param caract charact to count
592 * @return occurence number
594 int ArgMgr::IdStrCountChar (char *chaine, int caract)
598 for ( ptr = chaine ; *ptr!='\0' ; ptr ++ )
605 * \brief returns an array of 'INT pairs'
606 * @param value char array decribing a set of 'INT pairs' (f1-l1, f2-l2, ...)
607 * @param number nb of found INT pairs
608 * @return pointer to the array of 'INT pairs'
610 int *ArgMgr::IdStrIntEnum ( char* value, int *number)
616 *number = IdStrCountChar(value,',')+1; /* nb Elements = nb Commas +1 */
618 liste = (int *) calloc (1,sizeof(int)*2*taille );
626 liste[i] = (int) strtol ( value, &value, 10 );
627 if ( *value == '\0' )
632 if ( *(value++) != '-' )
639 liste[i+1] = (int) strtol ( value, &value, 10 );
641 if ( *value == '\0' )
643 if ( *(value++) != ',' )
654 * \brief returns an array of set of 'INT16 pairs', passed in Hexadecimal
655 * @param value char array decribing a set of 'INT16 pairs' (f1-l1, f2-l2, ...)
656 * coded in hexadecimal e.g. 0x0008,0x00ac
657 * @param number nb of found pairs
658 * @return array of set of 'INT16 pairs'
660 uint16_t *ArgMgr::IdStrXInt16Enum ( char *value, int *number)
666 *number = IdStrCountChar(value,',')+1; /* nb Elements = nb Commas +1 */
668 liste = (uint16_t *) calloc (1,sizeof(uint16_t)*2*taille );
676 liste[i] = (uint16_t) strtol ( value, &value, 16 );
677 if ( *value == '\0' )
682 if ( *(value++) != '-' )
689 liste[i+1] = (uint16_t) strtol ( value, &value, 16 );
691 if ( *value == '\0' )
693 if ( *(value++) != ',' )
703 * \brief returns an array of 'FLOAT pairs'
704 * @param value char array decribing a set of 'FLOAT pairs' (f1-l1, f2-l2, ...)
705 * @param number nb of found pairs
706 * @return pointer to the array of 'FLOAT pairs'; NULL if fail
708 float *ArgMgr::IdStrFloatEnum (char *value, int *number)
713 *number = IdStrCountChar(value,',')+1; /* nb Elements = nb Commas +1 */
715 liste = (float *) calloc (1,sizeof(float)*2*taille );
721 liste[i] = (float) strtod ( value, &value );
722 if ( *value == '\0' )
727 if ( *(value++) != '-' )
734 liste[i+1] = (float) strtod ( value, &value );
736 if ( *value == '\0' )
738 if ( *(value++) != ',' )
748 //-----------------------------------------------------------------------------
751 //-----------------------------------------------------------------------------
754 /**************************************************************************
756 * Nom de la fonction : Majuscule *
757 * Role ............. : Creates a new Upper case char array. *
758 * parameters ....... : Pointer to the initial char array. * *
759 * Valeur retournee . : Pointer to the new Upper case char array. *
761 **************************************************************************/
762 char *ArgMgr::Majuscule (const char *chaine )
764 char *ptr, *ptr2, *ptr3;
765 ptr2 = (char *)malloc(strlen(chaine)*sizeof(char)+1);
767 for ( ptr = const_cast<char *>(chaine) ; *ptr!='\0' ; ptr ++ )
769 *ptr3 = toupper ( * ptr ); ptr3++;
775 /**************************************************************************
777 * Nom de la fonction : FiltreLong *
778 * Role ............. : Stops the program if argument is too long. *
779 * ARG_LONG_MAX defines max length. *
780 * parameters ....... : Pointer to the argument. *
781 * Valeur retournee . : false if OK. *
783 **************************************************************************/
784 int ArgMgr::FiltreLong ( const char *arg )
787 while ( (n++<ARG_LONG_MAX) && (*(arg++) != '\0') ) ;
788 return (n>=ARG_LONG_MAX) ;
791 /*------------------------------------------------------------------------
792 | Role : Reads a parameter from a file
793 | Return : Type : char *
794 | Role : pointer to the label
795 | parameters : param : char *
796 | Role : one where the parameter will be stored
798 | Role : File description (assumed to be open)
799 +------------------------------------------------------------------------*/
800 const char *ArgMgr::LoadedParam ( const char *param, FILE *fd )
803 char *car = const_cast<char *>(param);
807 /* remove spaces at the beginning****/
808 while ( isspace(carlu=fgetc (fd)) ) {}
816 /* Read all the characters */
819 && ( ( (!quote)&&(!isspace(carlu)) )
820 ||( (quote)&& !(carlu=='\"') ) ) )
822 *(car++) = (char) carlu;
824 /* sans depasser la taille max*/
825 if ( nbcar >= ARG_LONG_MAX )
827 std::cout << "\nError: Argument too long ( > "
828 << ARG_LONG_MAX << ")in parameter file."
838 /*------------------------------------------------------------------------
839 | Role : Reading of arguments in a parameter file
840 | (this function is recursive).
841 | Return : Type : int
842 | Role : length needed to store all the parameters
843 | parameters : filename : char *
844 | Role : parameter File name
846 +------------------------------------------------------------------------*/
847 int ArgMgr::ArgLoadFromFile ( const char *filename )
850 char param[ARG_LONG_MAX+1];
853 fch = fopen ( filename, ID_RFILE_TEXT );
854 while ( LoadedParam (param, fch ) )
856 size_t n = strlen(param);
859 nbl += ArgLoadFromFile ( ¶m[1] );
863 ArgLab [ArgCount] = strcpy ((char *) malloc(n+1), param ) ;
866 if ( ArgCount >= ARGMAXCOUNT )
871 return static_cast< int >( nbl );
874 /*------------------------------------------------------------------------
875 | Role : Standard parameters management (on command line)
876 | Return : Type : void
878 +------------------------------------------------------------------------*/
879 void ArgMgr::ArgStdArgs()
884 if ( (ArgParamOut=ArgMgrValue(const_cast<char*>(ARG_LABEL_PARAMOUT)))==0 )
885 ArgParamOut = ARG_DEFAULT_PARAMOUT;
886 if ( (logfile = ArgMgrValue(const_cast<char*>(ARG_LABEL_LOGFILE)))!=0)
888 if ( *logfile == '\0' )
889 logfile = const_cast<char *>(ARG_DEFAULT_LOGFILE);
890 fd = fopen ( logfile, "a+" );
893 fprintf ( fd, "%s\n", Appel );
899 /*------------------------------------------------------------------------
900 | Role : Sets in Upper Case.
901 | Return : Type : char *
902 | parameters : char *
903 +------------------------------------------------------------------------*/
904 char *ArgMgr::maj ( char *a )
909 if ( *b<='z' && *b>='a' ) *b = *b+'A'-'a';
914 //-----------------------------------------------------------------------------
917 //-----------------------------------------------------------------------------
918 } // end namespace gdcm