1 /*=========================================================================
4 Module: $RCSfile: gdcmArgMgr.cxx,v $
6 Date: $Date: 2005/06/06 12:37:58 $
7 Version: $Revision: 1.1 $
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"
29 #define ARG_DEFAULT_PARAMOUT "fileout.par"
30 #define ARG_DEFAULT_LOGFILE "gdcm.log"
35 //-------------------------------------------------------------------------
36 // Constructor / Destructor
40 * @param argc arguments count, as passed to main()
41 * @param argv pointers array on the arguments passed to main()
43 ArgMgr::ArgMgr(int argc, char *argv[])
50 /* Read the parameters of the command line *************************/
51 for ( ArgCount=0, nblettre=1 , i=0; i<argc; i++)
53 if ( FiltreLong(argv[i]) )
55 std::cout << "Argument too long ( > "
56 << ARG_LONG_MAX << ")" << std::endl;
59 if ( argv[i][0] == '@' )
61 nblettre += ArgLoadFromFile ( &argv[i][1] );
65 ArgLab [ArgCount] = strcpy ( (char *)malloc(strlen(argv[i])+1), argv[i] ) ;
66 nblettre += 1 + strlen(ArgLab[ArgCount]);
69 if (ArgCount >= ARGMAXCOUNT )
71 std::cout << "Too many Arguments ( more than "
72 << ARGMAXCOUNT << ")" << std::endl;
77 /* Fills an array with the alreadu used parameters ****/
78 ArgUsed = (char *)calloc (1, ArgCount );
80 /* Builds the full string with all the parameters **************/
81 Appel = (char *) calloc (1, nblettre );
83 for ( *Appel = '\0', i=0; i<ArgCount; i++)
85 strcat ( Appel, ArgLab [i] ) ;
86 strcat ( Appel, " " ) ;
89 /* Splitting label from label value *************************************/
90 for ( i=0; i<ArgCount; i++)
92 char * egaloufin = ArgLab[i] ;
93 while ( (*egaloufin != '\0') && (*egaloufin != '=') )
95 if ( *egaloufin ) *(egaloufin++) = '\0';
99 /* Set labels to upper-case (labels are not case sensitive ) *********/
100 for ( i=0; i<ArgCount; i++)
101 ArgLab[i] = Majuscule ( ArgLab[i] ) ;
103 /* Standard arguments are managed by ArgStdArgs **********************/
108 * \brief canonical destructor
112 for(int i=0;i<ArgCount;i++)
122 * \brief checks if a parameter exists in the command line
123 * @param searchParam name of the searched parameter label
124 * @return true if parameter 'label' exists
125 * Actually, it returns 0 if label is not found
126 * else, returns the number of the spot it was found last time.
128 int ArgMgr::ArgMgrDefined( char *searchParam )
132 temp = Majuscule ( searchParam ) ;
133 for ( trouve = false, i = ArgCount-1; i>0; i-- )
135 trouve = ! strcmp( ArgLab[i], temp ) ;
139 for ( int j=1; j<i; j++)
141 if ( (!ArgUsed[j])&&(!strcmp(ArgLab[i],ArgLab[j])) )
151 * \brief Gets the parameter value, read on the command line
152 * @param param name of the searched parameter label
153 * @return Value, as a characters string, of the parameter
154 * whose label is given.
156 char *ArgMgr::ArgMgrValue ( char *param )
159 if ( (trouve = ArgMgrDefined ( param )) != false )
160 return ArgStr[trouve] ;
166 * \brief Search for the first not yet used label
167 * @return Pointer to a char array holding the first non used label
169 char *ArgMgr::ArgMgrUnused ( )
172 for ( i=ArgCount-1; i>0; i-- )
176 ArgMgrDefined(ArgLab[i]);
184 * \brief Prints unused labels, if any
185 * @return number of unused labels
187 int ArgMgr::ArgMgrPrintUnusedLabels ()
191 while ( (label=ArgMgrUnused())!=0 )
194 std::cout << "\n Unused Labels:" << std::endl
195 << "==============" << std::endl;
196 std::cout << "Label : " << label << " = "
197 << ArgMgrValue(label) << std::endl;
204 * \brief Prints program usage
205 * @param usage array of pointers to the documentation lines
207 * @return exception code
209 int ArgMgr::ArgMgrUsage(char **usage_text )
211 while ( *usage_text )
212 std::cout << std::endl << *(usage_text++);
213 std::cout << std::endl;
219 * \brief Forget it, right now ...
220 * sauvegarde une chaine de caract. dans un fichier de parameters
221 * Le nom du fichier est celui specifie sur la ligne
222 * d'appel par : PARAMOUT=???
223 * ou, par defaut, celui donne par ARG_DEFAULT_PARAMOUT
224 * @param param Chaine de caractere definissant le parameter:
225 * @return Entier correspondant au rang dans la liste de labels
227 int ArgMgr::ArgMgrSave ( char *param )
231 if ( *ArgParamOut == '\0' )
235 fd = fopen ( ArgParamOut, "a+" );
240 fd = fopen ( ArgParamOut, "w" );
244 fprintf ( fd, "%s\n", param );
250 * \brief Gets an int value passed as an argument to a program
251 * (use default value if not found)
252 * EXEMPLE: int dimx = ArgMgrGetInt ( "DIMX", 256 );
253 * @param label parameter label
254 * @param defaultVal default value
255 * @return parameter value
257 int ArgMgr::ArgMgrGetInt(char *label, int defaultVal)
259 return ( (ArgMgrDefined(label))
260 ? (atoi(ArgMgrValue(label)))
265 * \brief Gets a float value passed as an argument to a program
266 * (use default value if not found)
267 * EXEMPLE: float scale = ArgMgrGetFloat ( "SCALE", 0.33 );
268 * @param label parameter label
269 * @param defaultVal default value
270 * @return parameter value
272 float ArgMgr::ArgMgrGetFloat(char *label, float defaultVal)
274 return ( (ArgMgrDefined(label))
275 ? (atof(ArgMgrValue(label)))
280 * \brief Gets a 'string' value passed as an argument to a program
281 * (use default value if not found)
282 * @param label parameter label
283 * @param defaultVal default value
284 * @return parameter value
286 char *ArgMgr::ArgMgrGetString(char *label, char *defaultVal)
288 return ( (ArgMgrDefined(label))
289 ? (ArgMgrValue(label))
294 * \brief Gets a value amongst a set od values
295 * (use default value if not found)
296 * EXEMPLE: int nlab = ArgMgrGetLabel("CONFIRM","NO\\YES", 0);
297 * @param label parameter label
298 * @param liste character Chain describing the varous values.
299 * Value are separated by '\\'.
300 * Not case sensitive.
301 * @param val number of default value
302 * @return int : range of value amongst the values list
304 int ArgMgr::ArgMgrGetLabel (char *label, char *liste, int val )
310 tmp = (char *) malloc(strlen(liste)+1);
313 if ( (vallab = ArgMgrGetString(label,(char *)NULL)) != 0 )
315 for ( lab = strtok (tmp,"\\");
317 lab = strtok(0L,"\\"), i++ )
319 if ( strcmp(maj(lab),maj(vallab))==0)
329 * \brief Lecture d'un arg.de type label parmi un ensemble de labels
330 * EXEMPLE: int nlab = ArgMgrWantLabel("CONFIRM","NO\\YES", usage);
331 * @param label Parameter label
332 * @param liste Chaine de caracteres decrivant les differents labels.
333 * Chaque label est separe par un '\\'.
334 * Aucune difference n'est faite entre maj./min.
335 * @param usage Usage program (displayed if label not found)
336 * @return Entier correspondant au rang dans la liste de labels
338 int ArgMgr::ArgMgrWantLabel (char *label, char *liste, char *usage[] )
343 if ( (vallab = ArgMgrGetString(label,0)) != 0 )
345 for ( lab = strtok (liste,"\\"); lab != 0; lab = strtok(0L,"\\"), i++ )
346 if ( strcmp(maj(lab),maj(vallab))==0)
355 * \brief Demands an int value passed as an argument to a program
356 * If not found usage is displayed and the prog aborted
357 * EXEMPLE: int dimx = ArgMgrWantInt ( "DIMX", usage );
358 * @param label Parameter label
359 * @param usage Usage program (displayed if label not found)
360 * @return parameter value
362 int ArgMgr::ArgMgrWantInt (char *label, char **usage)
364 return ( (ArgMgrDefined(label) )
365 ? (atoi(ArgMgrValue(label) ) )
366 : (ArgMgrUsage(usage),1) );
370 * \brief Demands a float value passed as an argument to a program
371 * If not found usage is displayed and the prog aborted
372 * EXEMPLE: float scale = ArgMgrWantFloat ( "SCALE", usage );
373 * @param label Parameter label
374 * @param usage Usage program (displayed if label not found)
375 * @return parameter value
377 float ArgMgr::ArgMgrWantFloat (char *label, char **usage)
379 return ( (ArgMgrDefined(label) )
380 ? (atof(ArgMgrValue(label) ) )
381 : (ArgMgrUsage(usage),1.0) );
385 * \brief Demands a 'string' value passed as an argument to a program
386 * If not found usage is displayed and the prog aborted
387 * EXEMPLE: char *code = ArgMgrWantString ( "CODE", usage );
388 * @param label Parameter label
389 * @param usage Usage program (displayed if label not found)
390 * @return parameter value
392 char *ArgMgr::ArgMgrWantString(char *label, char **usage)
394 return ( (ArgMgrDefined(label) )
395 ? (ArgMgrValue(label) )
396 : (ArgMgrUsage(usage),(char*)0) );
400 * \brief decodage des elements d'un argument 'liste de STRING' de lgr qcq
401 * @param label pointer vers le label de la liste
402 * @param number taille de la liste trouvee
403 * @return Pointer vers le tableau de lgr 'taille'
404 * Pointer NULL si erreur
406 char **ArgMgr::ArgMgrGetListOfString ( char *label, int *nbElem )
409 char *value = ArgMgrValue(label);
415 *nbElem = IdStrCountChar(value,',')+1; /* nb Elements = nb Commas +1 */
417 liste = (char **) malloc (sizeof(char*) * taille + strlen(value)+1);
420 value = strcpy( ((char*)liste)+sizeof(char*) * taille, value );
421 for ( elem = liste, chainecur = strtok(value,", ");
423 taille--, chainecur = (chainecur) ? strtok ( 0, ", " ) : 0 )
425 *(elem++) = chainecur;
431 * \brief decodage des elements d'un argument 'liste diINTEGER' de lgr quelconque
432 * @param label pointer vers le label de la liste
433 * @param number taille de la liste trouvee
434 * @return Pointer vers le tableau de lgr 'taille'
435 * Pointer NULL si erreur
437 int *ArgMgr::ArgMgrGetListOfInt ( char *label, int *number )
439 char *value = ArgMgrValue(label);
445 *number = IdStrCountChar(value,',')+1; /* nb Elements = nb Commas +1 */
447 liste = (int *) calloc (1,sizeof(int)*taille );
455 *(elem++) = (int) strtol ( value, &value, 10 );
456 if ( *value == '\0' )
458 if ( *(value++) != ',' )
469 * \brief decodage des elements d'un argument 'liste de FLOAT' de lgr qcq
470 * @param label pointer vers le label de la liste
471 * @param number taille de la liste trouvee
472 * @return Pointer vers le tableau de lgr 'taille'
475 float *ArgMgr::ArgMgrGetListOfFloat ( char *label, int *number )
477 char *value = ArgMgrValue(label);
483 *number = IdStrCountChar(value,',')+1; /* nb Elements = nb Commas +1 */
485 liste = (float *) calloc (1,sizeof(float)*taille );
493 *(elem++) = (float) strtod ( value, &value );
494 if ( *value == '\0' )
496 if ( *(value++) != ',' )
507 * \brief Counts the nb of occurrences of a given charact within a 'string'
508 * @param chaine Pointer to the 'string'
509 * @param caract charact to count
510 * @return occurence number
512 int ArgMgr::IdStrCountChar (char *chaine, int caract)
516 for ( ptr = chaine ; *ptr!='\0' ; ptr ++ )
523 * \brief renvoie 1 tableau contenant une liste d'intervalles entiers
524 * @param value pointer vers la zone allouee contenant les
525 * intervalles (deb1,fin1, deb2,fin2, ...)
526 * @param number Pointer vers le nb d'interv trouves
527 * @return 1 tableau contenant une liste d'intervalles entiers
529 int *ArgMgr::IdStrIntEnum ( char* value, int *number)
535 *number = IdStrCountChar(value,',')+1; /* nb Elements = nb Virgules +1 */
537 liste = (int *) calloc (1,sizeof(int)*2*taille );
545 liste[i] = (int) strtol ( value, &value, 10 );
546 if ( *value == '\0' )
551 if ( *(value++) != '-' )
558 liste[i+1] = (int) strtol ( value, &value, 10 );
560 if ( *value == '\0' )
562 if ( *(value++) != ',' )
573 * \brief renvoie 1 tableau contenant une liste d'intervalles FLOAT
574 * @param value pointer vers la zone allouee contenant les
575 * intervalles (deb1,fin1, deb2,fin2, ...)
576 * @param number Pointer vers le nb d'interv trouves
577 * @return 1 tableau contenant une liste d'intervalles FLOAT
579 float *ArgMgr::IdStrFloatEnum (char *value, int *number)
584 *number = IdStrCountChar(value,',')+1; /* nb Elements = nb Virgules +1 */
586 liste = (float *) calloc (1,sizeof(float)*2*taille );
592 liste[i] = (float) strtod ( value, &value );
593 if ( *value == '\0' )
598 if ( *(value++) != '-' )
605 liste[i+1] = (float) strtod ( value, &value );
607 if ( *value == '\0' )
609 if ( *(value++) != ',' )
620 * \brief decodage des elements d'un argument 'intervalles d'int' de lgr quelconque
621 * @param label pointer vers le label de la liste
622 * @param number taille de la liste d'intervalles trouvee
623 * @return Pointer vers le tableau de taille '2*nbElem'
624 * Pointer NULL si erreur
626 int *ArgMgr::ArgMgrGetIntEnum ( char *label, int *number )
628 char *value = ArgMgrValue(label);
632 liste = IdStrIntEnum(value, number);
637 * \brief decodage des elements d'un argument 'intervalles d'int' de lgr quelconque
638 * @param label pointer vers le label de la liste
639 * @param number taille de la liste d'intervalles trouvee
640 * @return Pointer vers le tableau de taille '2*nbElem'
641 * Pointer NULL si erreur
643 float *ArgMgr::ArgMgrGetFloatEnum ( char *label, int *number )
645 char *value = ArgMgrValue(label);
649 liste = IdStrFloatEnum(value, number);
653 //-----------------------------------------------------------------------------
656 //-----------------------------------------------------------------------------
659 /**************************************************************************
661 * Nom de la fonction : Majuscule *
662 * Role ............. : Met une chaine de caracteres en majuscules. *
663 * parameters ....... : Pointer vers la chaine. *
664 * Valeur retournee . : pointer vers cette meme chaine en majuscule. *
666 **************************************************************************/
667 char *ArgMgr::Majuscule (char *chaine )
669 char *ptr, *ptr2, *ptr3;
670 ptr2 = (char *)malloc(strlen(chaine)*sizeof(char)+1);
672 for ( ptr = chaine ; *ptr!='\0' ; ptr ++ )
674 *ptr3 = toupper ( * ptr ); ptr3++;
680 /**************************************************************************
682 * Nom de la fonction : FiltreLong *
683 * Role ............. : Arrete le programme si l'argument est trop long. *
684 * ARG_LONG_MAX definit cette longueur. *
685 * parameters ....... : Pointer vers l'argument. *
686 * Valeur retournee . : Faux s'il n'y a pas d'erreur. *
687 * Vrai s'il y a une erreur. *
688 **************************************************************************/
689 int ArgMgr::FiltreLong ( char *arg )
692 while ( (n++<ARG_LONG_MAX) && (*(arg++) != '\0') ) ;
693 return (n>=ARG_LONG_MAX) ;
696 /*------------------------------------------------------------------------
697 | Role : Lit un parameter depuis un fichier
698 | Retour : Type : char *
699 | Role : pointer vers le label
700 | parameters : param : char *
701 | Role : one ou il faut stocker le parameter
703 | Role : descripteur du fichier (suppose ouvert)
704 +------------------------------------------------------------------------*/
705 char *ArgMgr::LoadedParam ( char *param, FILE *fd )
712 /* On supprime les espaces ****/
713 /* du debut de chaine *********/
714 while ( isspace(carlu=fgetc (fd)) );
717 /* On cherche une " eventuelle */
722 /* On lit tous les caracteres */
725 && ( ( (!quote)&&(!isspace(carlu)) )
726 ||( (quote)&& !(carlu=='\"') ) ) )
728 *(car++) = (char) carlu;
730 /* sans depasser la taille max*/
731 if ( nbcar >= ARG_LONG_MAX )
733 std::cout << "\nError: Argument too long ( > "
734 << ARG_LONG_MAX << ")in parameter file."
744 /*------------------------------------------------------------------------
745 | Role : Lecture d'arguments dans un fichier de parameters
746 | (cette fonction est recursive).
747 | Retour : Type : int
748 | Role : retourne le nombre de lettres necessaires
749 | pour stocker en memoire tous les parameters
750 | parameters : filename : char *
751 | Role : nom du fichier de parameter
753 +------------------------------------------------------------------------*/
754 int ArgMgr::ArgLoadFromFile ( char *filename )
757 char param[ARG_LONG_MAX+1];
760 fch = fopen ( filename, ID_RFILE_TEXT );
761 while ( LoadedParam (param, fch ) )
763 int n = strlen(param);
766 nbl += ArgLoadFromFile ( ¶m[1] );
770 ArgLab [ArgCount] = strcpy ((char *) malloc(n+1), param ) ;
773 if ( ArgCount >= ARGMAXCOUNT )
781 /*------------------------------------------------------------------------
782 | Role : Gestion des parameters standard de la ligne d'argument.
783 | Retour : Type : void
785 +------------------------------------------------------------------------*/
786 void ArgMgr::ArgStdArgs()
791 if ( (ArgParamOut=ArgMgrValue(ARG_LABEL_PARAMOUT))==0 )
792 ArgParamOut = ARG_DEFAULT_PARAMOUT;
793 if ( (logfile = ArgMgrValue(ARG_LABEL_LOGFILE))!=0)
795 if ( *logfile == '\0' )
796 logfile = ARG_DEFAULT_LOGFILE;
797 fd = fopen ( logfile, "a+" );
800 fprintf ( fd, "%s\n", Appel );
806 /*------------------------------------------------------------------------
807 | Role : met en majuscule 'sur place'.
808 | Retour : Type : char *
809 | parameters : char *
810 +------------------------------------------------------------------------*/
811 char *ArgMgr::maj ( char *a )
816 if ( *b<='z' && *b>='a' ) *b = *b+'A'-'a';
821 //-----------------------------------------------------------------------------
824 //-----------------------------------------------------------------------------
825 } // end namespace gdcm