• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Classes
  • Files
  • File List
  • File Members

src/CommandLine.cpp

00001 /*
00002  *   This file is part of the Standard Portable Library (SPL).
00003  *
00004  *   SPL is free software: you can redistribute it and/or modify
00005  *   it under the terms of the GNU General Public License as published by
00006  *   the Free Software Foundation, either version 3 of the License, or
00007  *   (at your option) any later version.
00008  *
00009  *   SPL is distributed in the hope that it will be useful,
00010  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  *   GNU General Public License for more details.
00013  *
00014  *   You should have received a copy of the GNU General Public License
00015  *   along with SPL.  If not, see <http://www.gnu.org/licenses/>.
00016  */
00017 #include <spl/configuration/CommandLine.h>
00018 #include <spl/Exception.h>
00019 
00020 using namespace spl;
00021 
00022 CommandLine::CommandLine()
00023 : m_switchIdx(), m_args(), m_switches()
00024 {
00025 }
00026 
00027 CommandLine::CommandLine(const int argc, const char **argv)
00028 : m_switchIdx(), m_args(), m_switches()
00029 {
00030         if ( ! Parse( argc, argv ) )
00031         {
00032                 throw new InvalidArgumentException("Parse failed");
00033         }
00034 }
00035 
00036 CommandLine::CommandLine(const CommandLine& cl)
00037 : m_switchIdx(), m_args(), m_switches()
00038 {
00039         *this = cl;
00040 }
00041 
00042 CommandLine::~CommandLine()
00043 {
00044         Clear();
00045 }
00046 
00047 CommandLine& CommandLine::operator =(const CommandLine& cl)
00048 {
00049         Clear();
00050 
00051         m_switchIdx = cl.m_switchIdx;
00052         m_args = cl.m_args;
00053         m_switches = cl.m_switches;
00054 
00055         return *this;
00056 }
00057 
00058 void CommandLine::Clear()
00059 {
00060         m_args.Clear();
00061         m_switchIdx.Clear();
00062         m_switches.Clear();
00063 }
00064 
00065 void CommandLine::SetSwitch(const String& key, const String& value)
00066 {
00067         m_switchIdx.Set(key, value);
00068         m_switches.Add(key);
00069 }
00070 
00071 static inline bool _IsUnixSwitch( const char *str )
00072 {
00073         return '-' == str[0];
00074 }
00075 
00076 static inline bool _IsWinSwitch( const char *str )
00077 {
00078         return '/' == str[0];
00079 }
00080 
00081 static inline bool _SwitchHasValue( const char *str, const bool unixStyle )
00082 {
00083         if ( unixStyle )
00084         {
00085                 return IndexOfCh( str, '=' ) > -1;
00086         }
00087         return IndexOfCh( str, ':' ) > -1;
00088 }
00089 
00090 static inline bool _IsSwitch( const char *str, const bool unixStyle )
00091 {
00092         if ( unixStyle )
00093         {
00094                 return _IsUnixSwitch( str );
00095         }
00096         return _IsWinSwitch( str );
00097 }
00098 
00099 static void _ParseSwitch( const char *str, const bool unixStyle, char *buf )
00100 {
00101         int bufpos = 0;
00102         int pos = 1;
00103         if ( unixStyle && '-' == str[1] )
00104         {
00105                 // --name style
00106                 pos = 2;
00107         }
00108         while ( pos < 254 && '\0' != str[pos] )
00109         {
00110                 if ( unixStyle && '=' == str[pos] )
00111                 {
00112                         break;
00113                 }
00114                 else if ( ':' == str[pos] )
00115                 {
00116                         break;
00117                 }
00118                 buf[bufpos++] = str[pos++];
00119         }
00120         buf[bufpos] = '\0';
00121 }
00122 
00131 bool CommandLine::Parse(const int argc, const char **argv)
00132 {
00133         bool styleSet = false;
00134         bool unixStyle = true;
00135         int x;
00136         char buf[255];
00137 
00138         Clear();
00139         
00140         for ( x = 0; x < argc; x++ )
00141         {
00142                 if ( !styleSet && _IsUnixSwitch(argv[x]) )
00143                 {
00144                         styleSet = true;
00145                         unixStyle = true;
00146                 }
00147                 if ( !styleSet && _IsWinSwitch(argv[x]) )
00148                 {
00149                         if ( 0 != x )
00150                         {
00151                                 // on unix, the full path name (including leading '/') is passed
00152                                 // as arg 0.
00153                                 styleSet = true;
00154                                 unixStyle = false;
00155                         }
00156                 }
00157                 if ( styleSet )
00158                 {
00159                         // might be -X or -X val or -X=val or /X:val or just a value
00160                         if ( ! _IsSwitch(argv[x], unixStyle) )
00161                         {
00162                                 // just a value
00163                                 m_args.Add( String( argv[x] ) );
00164                         }
00165                         else
00166                         {
00167                                 _ParseSwitch(argv[x], unixStyle, buf);
00168                                 m_switches.Add(buf);
00169                                 if ( _SwitchHasValue(argv[x], unixStyle) )
00170                                 {
00171                                         m_switchIdx.Set(buf, ParseValue( argv[x], unixStyle ));
00172                                 }
00173                                 else
00174                                 {
00175                                         m_switchIdx.Set( buf, String() );
00176                                 }
00177                         }
00178                 }
00179                 else
00180                 {
00181                         // an arg
00182                         m_args.Add( String(argv[x]) );
00183                 }
00184         }
00185         ValidateMem();
00186         return true;
00187 }
00188 
00189 String CommandLine::ParseValue( const String& str, const bool unixStyle )
00190 {
00191         int pos;
00192         if ( unixStyle )
00193         {
00194                 ASSERT('-' == str[0]);
00195                 pos = str.IndexOf('=');
00196         }
00197         else
00198         {
00199                 ASSERT('/' == str[0]);
00200                 pos = str.IndexOf(':');
00201         }
00202         ASSERT( pos > 1 );
00203         
00204         return *str.Substring(pos+1);
00205 }
00206 
00207 String& CommandLine::GetSwitch(const String& argNoDashOrSlash, const String& defValue)
00208 {
00209         String& ret = GetSwitch(argNoDashOrSlash);
00210         if ( ret.Length() != 0 )
00211         {
00212                 return ret;
00213         }
00214         SetSwitch(argNoDashOrSlash, defValue);
00215         return GetSwitch(argNoDashOrSlash);
00216 }
00217 
00218 #ifdef DEBUG
00219 void CommandLine::ValidateMem() const
00220 {
00221         m_args.ValidateMem();
00222         m_switchIdx.ValidateMem();
00223         m_switches.ValidateMem();
00224 }
00225 
00226 void CommandLine::CheckMem() const
00227 {
00228         m_args.CheckMem();
00229         m_switchIdx.CheckMem();
00230         m_switches.CheckMem();
00231 }
00232 #endif