/*****************************************************************************
  FILENAME: args.hpp

*****************************************************************************
  Notes:
// General application class that encapsulates main(argc, argv) arguments
// and provides methods to access:
//  . program name (full name, path, plain name and short name, that is,
//    name part before the extension dot character)
//  . arguments (in short 'args') as strings or numbers
//  . managed options aka switches (arguments beginning with '-' or '/')
// args and option are accessed through an index which is zero-bqsed 
// TARGETS: mainly Microsoft-based OS's, Linux also
 *****************************************************************************/

#ifndef __ARGS_HPP__
#define __ARGS_HPP__ IS INCLUDED FROM NOW ON

#include <stdlib.h>

typedef const char* const tArgArray[];

class cArgvManager
 {
  public:
   // ctor's and dtor
    // PrgName is the equivalement of argv[0]
    // If PrgName is not null, argv[0] is ignored and replaced with it
    // This can be useful when argv[0] does not represent the full qualified name
    // as with Windows XP... see note after this class definition
    // NB: argv and PrgName contents must not change during lifetime of this object
	 cArgvManager(int argc, tArgArray argv, const char* PrgName=NULL);
    // splits continous command line into tokens
    // PrgName is the equivalement of Argv[0]
    // this pamameter must remain stable during the object life time
    // this ctor is useful with some non command-line applications, e.g. WinMain(..., lpCmdLine, ...)
	 cArgvManager(const char* CmdLine, const char* PrgName="");
	 ~cArgvManager();
    // NB all indexes start from 0
	 const char* arg(int index) const;
    // translate arg at index into long
	 long int lArg(int index) const;
    // translate arg at index into double
	 double dArg(int index) const;
	 int argnb() const { return(mArgs); }
   // Methods to get program name
	 const char* fullPrgName() const { return(mFullPrgName); }
    // path
	 const char* path() const { return(mPrgPath); }
    // name + extension
	 const char* prgName() const { return(mPrgName); }
    // basename: name without extension
	 const char* prgShortName() const { return(mPrgShortName); }
   // Options methods
   // Rules: an option arg begins with a leading '-' or '/' followed by
   // an option character, and, possibly separated from an associated value by a '=',
   // ':' or nothing
   // so in short, syntax for an option looks like: -|/<optionCharacter>[[:|=]<optionValue>]
    // option look-up (starting from *last* argument)
    // optc: option character
    // bCaseSensitive : case sensitive if this parameter is different from 0
    // return: index or -1 if not found
   int option(char optc, int bCaseSensitive=0);
   // value of option at index as a string
   // returns NULL if no value has been defined 
	 const char* optValue(int index) const;
    // value of option at index as a long
    // returns 0l if no value has been defined 
	 long int optlValue(int index) const;
    // value of option at index as a double
    // returns 0.0 if no value has been defined 
	 double optdValue(int index) const;
    // lookup for the next *non* option arg starting *after* zero-based index (-1 is then a 
    // valid value to start from the beginning)
    // -1 if no next option exists
   int nextNonOption(int index=-1);
  protected:
	  int mArgs;
	  const char* const* mArgv;
    const char* mFullPrgName;
	  char* mPrgName;
	  char* mPrgShortName;
	  char* mPrgPath;
	  int membersInit(int, const char * const [], const char*);

    // additional members for the constructor that takes a string
    char** mAutoArgv;
    int mAutoArgc;
    char* mAutoCmdLine;
 };

/******************************************************
 Note on full qualified program name (to be supplied as third parameter after argc and argv in the class constructor)
 Code example to get this fully qualified name when argv[0] is not so (under Windows-XP and MS Visual Studio 10 for example)

  static char fullExeName[2048];
  // this special system call here as for special unclear reasons (compiler, Windows version?)
  // argv[0] is now the name of program invocation on the command line and no
  // longer the full qualified name (i.e. with path) of the executable
  // we get it externally through this Win32 ANSI Kernel32 system call
  ::GetModuleFileNameA(NULL, fullExeName, sizeof(fullExeName)-1);
  fullExeName[sizeof(fullExeName)-1]='\0'; // this fixes a bug in Windows XP/2000 (very unlikely regarding the provided buffer size)
******************************************************/

#endif