Jack2 1.9.6

JackArgParser.cpp

00001 /*
00002   Copyright (C) 2006-2008 Grame
00003 
00004   This program is free software; you can redistribute it and/or modify
00005   it under the terms of the GNU Lesser General Public License as published by
00006   the Free Software Foundation; either version 2.1 of the License, or
00007   (at your option) any later version.
00008 
00009   This program 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 Lesser General Public License for more details.
00013 
00014   You should have received a copy of the GNU Lesser General Public License
00015   along with this program; if not, write to the Free Software
00016   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00017 
00018 */
00019 
00020 #include "JackDriverLoader.h"
00021 #include "JackArgParser.h"
00022 #include <stdlib.h>
00023 #include <stdio.h>
00024 #include <assert.h>
00025 
00026 using namespace std;
00027 
00028 namespace Jack {
00029 
00030     // class JackArgParser ***************************************************
00031     JackArgParser::JackArgParser ( const char* arg )
00032     {
00033         jack_log ( "JackArgParser::JackArgParser, arg_string : '%s'", arg );
00034 
00035         fArgc = 0;
00036         //if empty string
00037         if ( strlen(arg) == 0 )
00038             return;
00039         fArgString = string(arg);
00040         //else parse the arg string
00041         const size_t arg_len = fArgString.length();
00042         unsigned int i = 0;
00043         size_t pos = 0;
00044         size_t start = 0;
00045         size_t copy_start = 0;
00046         size_t copy_length = 0;
00047         //we need a 'space terminated' string
00048         fArgString += " ";
00049         //first fill a vector with args
00050         do {
00051             //find the first non-space character from the actual position
00052             start = fArgString.find_first_not_of ( ' ', start );
00053             //get the next quote or space position
00054             pos = fArgString.find_first_of ( " \"" , start );
00055             //no more quotes or spaces, consider the end of the string
00056             if ( pos == string::npos )
00057                 pos = arg_len;
00058             //if double quote
00059             if ( fArgString[pos] == '\"' ) {
00060                 //first character : copy the substring
00061                 if ( pos == start ) {
00062                     copy_start = start + 1;
00063                     pos = fArgString.find ( '\"', ++pos );
00064                     copy_length = pos - copy_start;
00065                     start = pos + 1;
00066                 }
00067                 //else there is someting before the quote, first copy that
00068                 else {
00069                     copy_start = start;
00070                     copy_length = pos - copy_start;
00071                     start = pos;
00072                 }
00073             }
00074             //if space
00075             if ( fArgString[pos] == ' ' ) {
00076                 //short option descriptor
00077                 if ( ( fArgString[start] == '-' ) && ( fArgString[start + 1] != '-' ) ) {
00078                     copy_start = start;
00079                     copy_length = 2;
00080                     start += copy_length;
00081                 }
00082                 //else copy all the space delimitated string
00083                 else {
00084                     copy_start = start;
00085                     copy_length = pos - copy_start;
00086                     start = pos + 1;
00087                                 }
00088             }
00089             //then push the substring to the args vector
00090             fArgv.push_back ( fArgString.substr ( copy_start, copy_length ) );
00091             jack_log ( "JackArgParser::JackArgParser, add : '%s'", (*fArgv.rbegin()).c_str() );
00092         } while ( start < arg_len );
00093 
00094         //finally count the options
00095         for ( i = 0; i < fArgv.size(); i++ )
00096             if ( fArgv[i].at(0) == '-' )
00097                 fArgc++;
00098     }
00099 
00100     JackArgParser::~JackArgParser()
00101     {}
00102 
00103     string JackArgParser::GetArgString()
00104     {
00105         return fArgString;
00106     }
00107 
00108     int JackArgParser::GetNumArgv()
00109     {
00110         return fArgv.size();
00111     }
00112 
00113     int JackArgParser::GetArgc()
00114     {
00115         return fArgc;
00116     }
00117 
00118     int JackArgParser::GetArgv ( vector<string>& argv )
00119     {
00120         argv = fArgv;
00121         return 0;
00122     }
00123 
00124     int JackArgParser::GetArgv ( char** argv )
00125     {
00126         //argv must be NULL
00127         if ( argv )
00128             return -1;
00129         //else allocate and fill it
00130         argv = (char**)calloc (fArgv.size(), sizeof(char*));
00131         if (argv == NULL) 
00132         {
00133             return -1;
00134         }
00135         for ( unsigned int i = 0; i < fArgv.size(); i++ )
00136         {
00137             argv[i] = (char*)calloc(fArgv[i].length(), sizeof(char));
00138             fill_n ( argv[i], fArgv[i].length() + 1, 0 );
00139             fArgv[i].copy ( argv[i], fArgv[i].length() );
00140         }
00141         return 0;
00142     }
00143 
00144     void JackArgParser::DeleteArgv ( const char** argv )
00145     {
00146         unsigned int i;
00147         for ( i = 0; i < fArgv.size(); i++ )
00148             free((void*)argv[i]);
00149         free((void*)argv);
00150     }
00151 
00152     bool JackArgParser::ParseParams ( jack_driver_desc_t* desc, JSList** param_list )
00153     {
00154         string options_list;
00155         unsigned long i = 0;
00156         unsigned int param = 0;
00157         size_t param_id = 0;
00158         JSList* params = NULL;
00159         jack_driver_param_t* intclient_param;
00160         
00161         for ( i = 0; i < desc->nparams; i++ )
00162             options_list += desc->params[i].character;
00163 
00164         for ( param = 0; param < fArgv.size(); param++ )
00165         {
00166             if ( fArgv[param][0] == '-' )
00167             {
00168                 //valid option
00169                 if ( ( param_id = options_list.find_first_of ( fArgv[param].at(1) ) ) != string::npos )
00170                 {
00171                     intclient_param = static_cast<jack_driver_param_t*> ( calloc ( 1, sizeof ( jack_driver_param_t) ) );
00172                     intclient_param->character = desc->params[param_id].character;
00173                     
00174                     switch ( desc->params[param_id].type )
00175                     {
00176                         case JackDriverParamInt:
00177                             if (param + 1 < fArgv.size()) // something to parse
00178                                 intclient_param->value.i = atoi ( fArgv[param + 1].c_str() );
00179                             break;
00180                             
00181                         case JackDriverParamUInt:
00182                             if (param + 1 < fArgv.size()) // something to parse
00183                                 intclient_param->value.ui = strtoul ( fArgv[param + 1].c_str(), NULL, 10 );
00184                             break;
00185                             
00186                         case JackDriverParamChar:
00187                             if (param + 1 < fArgv.size()) // something to parse
00188                                 intclient_param->value.c = fArgv[param + 1][0];
00189                             break;
00190                             
00191                         case JackDriverParamString:
00192                             if (param + 1 < fArgv.size()) // something to parse
00193                                 fArgv[param + 1].copy ( intclient_param->value.str, min(static_cast<int>(fArgv[param + 1].length()), JACK_DRIVER_PARAM_STRING_MAX) );
00194                             break;
00195                             
00196                         case JackDriverParamBool:
00197                             intclient_param->value.i = true;
00198                             break;
00199                     }
00200                     //add to the list
00201                     params = jack_slist_append ( params, intclient_param );
00202                 }
00203                 //invalid option
00204                 else {
00205                     if (fArgv[param][1] == 'h') {
00206                         fprintf(stdout, "Internal client parameters:\n");
00207                         jack_print_driver_options (desc, stdout);
00208                         return false;
00209                     } else {
00210                         jack_error ( "Invalid option '%c'", fArgv[param][1] );
00211                     }
00212                 }
00213             }
00214         }
00215 
00216         assert(param_list);
00217         *param_list = params;
00218         return true;
00219     }
00220     
00221     void JackArgParser::FreeParams ( JSList* param_list )
00222     {
00223         JSList *node_ptr = param_list;
00224         JSList *next_node_ptr;
00225     
00226         while (node_ptr) {
00227             next_node_ptr = node_ptr->next;
00228             free(node_ptr->data);
00229             free(node_ptr);
00230             node_ptr = next_node_ptr;
00231         }
00232     }
00233 
00234 }
00235