Merge branch 'master' into develop
[jack2.git] / common / JackArgParser.cpp
blob2ca25c264ccf4ea74e7141537b4c8d97ea89982b
1 /*
2 Copyright (C) 2006-2008 Grame
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU Lesser General Public License as published by
6 the Free Software Foundation; either version 2.1 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 #include "JackDriverLoader.h"
21 #include "JackArgParser.h"
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <assert.h>
26 using namespace std;
28 namespace Jack {
30 // class JackArgParser ***************************************************
31 JackArgParser::JackArgParser ( const char* arg )
33 jack_log ( "JackArgParser::JackArgParser, arg_string : '%s'", arg );
35 fArgc = 0;
36 //if empty string
37 if ( strlen(arg) == 0 )
38 return;
39 fArgString = string(arg);
40 //else parse the arg string
41 const size_t arg_len = fArgString.length();
42 unsigned int i = 0;
43 size_t pos = 0;
44 size_t start = 0;
45 size_t copy_start = 0;
46 size_t copy_length = 0;
47 //we need a 'space terminated' string
48 fArgString += " ";
49 //first fill a vector with args
50 do {
51 //find the first non-space character from the actual position
52 start = fArgString.find_first_not_of ( ' ', start );
53 //get the next quote or space position
54 pos = fArgString.find_first_of ( " \"" , start );
55 //no more quotes or spaces, consider the end of the string
56 if ( pos == string::npos )
57 pos = arg_len;
58 //if double quote
59 if ( fArgString[pos] == '\"' ) {
60 //first character : copy the substring
61 if ( pos == start ) {
62 copy_start = start + 1;
63 pos = fArgString.find ( '\"', ++pos );
64 copy_length = pos - copy_start;
65 start = pos + 1;
67 //else there is something before the quote, first copy that
68 else {
69 copy_start = start;
70 copy_length = pos - copy_start;
71 start = pos;
74 //if space
75 if ( fArgString[pos] == ' ' ) {
76 //short option descriptor
77 if ( ( fArgString[start] == '-' ) && ( fArgString[start + 1] != '-' ) ) {
78 copy_start = start;
79 copy_length = 2;
80 start += copy_length;
82 //else copy all the space delimitated string
83 else {
84 copy_start = start;
85 copy_length = pos - copy_start;
86 start = pos + 1;
89 //then push the substring to the args vector
90 fArgv.push_back ( fArgString.substr ( copy_start, copy_length ) );
91 jack_log ( "JackArgParser::JackArgParser, add : '%s'", (*fArgv.rbegin()).c_str() );
92 } while ( start < arg_len );
94 //finally count the options
95 for ( i = 0; i < fArgv.size(); i++ )
96 if ( fArgv[i].at(0) == '-' )
97 fArgc++;
100 JackArgParser::~JackArgParser()
103 string JackArgParser::GetArgString()
105 return fArgString;
108 int JackArgParser::GetNumArgv()
110 return fArgv.size();
113 int JackArgParser::GetArgc()
115 return fArgc;
118 int JackArgParser::GetArgv ( vector<string>& argv )
120 argv = fArgv;
121 return 0;
124 int JackArgParser::GetArgv ( char** argv )
126 //argv must be NULL
127 if ( argv )
128 return -1;
129 //else allocate and fill it
130 argv = (char**)calloc (fArgv.size(), sizeof(char*));
131 if (argv == NULL)
133 return -1;
135 for ( unsigned int i = 0; i < fArgv.size(); i++ )
137 argv[i] = (char*)calloc(fArgv[i].length(), sizeof(char));
138 fill_n ( argv[i], fArgv[i].length() + 1, 0 );
139 fArgv[i].copy ( argv[i], fArgv[i].length() );
141 return 0;
144 void JackArgParser::DeleteArgv ( const char** argv )
146 unsigned int i;
147 for ( i = 0; i < fArgv.size(); i++ )
148 free((void*)argv[i]);
149 free((void*)argv);
152 bool JackArgParser::ParseParams ( jack_driver_desc_t* desc, JSList** param_list )
154 string options_list;
155 unsigned long i = 0;
156 unsigned int param = 0;
157 size_t param_id = 0;
158 JSList* params = NULL;
159 jack_driver_param_t* intclient_param;
161 for ( i = 0; i < desc->nparams; i++ )
162 options_list += desc->params[i].character;
164 for ( param = 0; param < fArgv.size(); param++ )
166 if ( fArgv[param][0] == '-' )
168 //valid option
169 if ( ( param_id = options_list.find_first_of ( fArgv[param].at(1) ) ) != string::npos )
171 intclient_param = static_cast<jack_driver_param_t*> ( calloc ( 1, sizeof ( jack_driver_param_t) ) );
172 intclient_param->character = desc->params[param_id].character;
174 switch ( desc->params[param_id].type )
176 case JackDriverParamInt:
177 if (param + 1 < fArgv.size()) // something to parse
178 intclient_param->value.i = atoi ( fArgv[param + 1].c_str() );
179 break;
181 case JackDriverParamUInt:
182 if (param + 1 < fArgv.size()) // something to parse
183 intclient_param->value.ui = strtoul ( fArgv[param + 1].c_str(), NULL, 10 );
184 break;
186 case JackDriverParamChar:
187 if (param + 1 < fArgv.size()) // something to parse
188 intclient_param->value.c = fArgv[param + 1][0];
189 break;
191 case JackDriverParamString:
192 if (param + 1 < fArgv.size()) // something to parse
193 fArgv[param + 1].copy ( intclient_param->value.str, min(static_cast<int>(fArgv[param + 1].length()), JACK_DRIVER_PARAM_STRING_MAX) );
194 break;
196 case JackDriverParamBool:
197 intclient_param->value.i = true;
198 break;
200 //add to the list
201 params = jack_slist_append ( params, intclient_param );
203 //invalid option
204 else {
205 if (fArgv[param][1] == 'h') {
206 fprintf(stdout, "Internal client parameters:\n");
207 jack_print_driver_options (desc, stdout);
208 return false;
209 } else {
210 jack_error ( "Invalid option '%c'", fArgv[param][1] );
216 assert(param_list);
217 *param_list = params;
218 return true;
221 void JackArgParser::FreeParams ( JSList* param_list )
223 JSList *node_ptr = param_list;
224 JSList *next_node_ptr;
226 while (node_ptr) {
227 next_node_ptr = node_ptr->next;
228 free(node_ptr->data);
229 free(node_ptr);
230 node_ptr = next_node_ptr;