1/*
2Copyright (c) 2006, Michael Kazhdan and Matthew Bolitho
3All rights reserved.
4
5Redistribution and use in source and binary forms, with or without modification,
6are permitted provided that the following conditions are met:
7
8Redistributions of source code must retain the above copyright notice, this list of
9conditions and the following disclaimer. Redistributions in binary form must reproduce
10the above copyright notice, this list of conditions and the following disclaimer
11in the documentation and/or other materials provided with the distribution.
12
13Neither the name of the Johns Hopkins University nor the names of its contributors
14may be used to endorse or promote products derived from this software without specific
15prior written permission.
16
17THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
18EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO THE IMPLIED WARRANTIES
19OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
20SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
21INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
22TO, PROCUREMENT OF SUBSTITUTE  GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
23BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
25ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
26DAMAGE.
27*/
28
29
30#include <stdio.h>
31#include <stdlib.h>
32#include <string.h>
33#include <assert.h>
34#include "CmdLineParser.h"
35
36
37#ifdef WIN32
38int strcasecmp(char* c1,char* c2){return _stricmp(c1,c2);}
39#endif
40
41cmdLineReadable::cmdLineReadable(const char* name)
42{
43	set=false;
44	this->name=new char[strlen(name)+1];
45	strcpy(this->name,name);
46}
47cmdLineReadable::~cmdLineReadable(void)
48{
49	if(name) delete[] name;
50	name=NULL;
51}
52int cmdLineReadable::read(char**,int){
53	set=true;
54	return 0;
55}
56void cmdLineReadable::writeValue(char* str)
57{
58	str[0] = 0;
59}
60
61////////////////
62// cmdLineInt //
63////////////////
64cmdLineInt::cmdLineInt(const char* name) : cmdLineReadable(name) {value=0;}
65cmdLineInt::cmdLineInt(const char* name,const int& v) : cmdLineReadable(name) {value=v;}
66int cmdLineInt::read(char** argv,int argc){
67	if(argc>0){
68		value=atoi(argv[0]);
69		set=true;
70		return 1;
71	}
72	else{return 0;}
73}
74void cmdLineInt::writeValue(char* str)
75{
76	sprintf(str,"%d",value);
77}
78
79//////////////////
80// cmdLineFloat //
81//////////////////
82cmdLineFloat::cmdLineFloat(const char* name) : cmdLineReadable(name) {value=0;}
83cmdLineFloat::cmdLineFloat(const char* name, const float& v) : cmdLineReadable(name) {value=v;}
84int cmdLineFloat::read(char** argv,int argc){
85	if(argc>0){
86		value=(float)atof(argv[0]);
87		set=true;
88		return 1;
89	}
90	else{return 0;}
91}
92void cmdLineFloat::writeValue(char* str)
93{
94	sprintf(str,"%f",value);
95}
96
97///////////////////
98// cmdLineString //
99///////////////////
100cmdLineString::cmdLineString(const char* name) : cmdLineReadable(name) {value=NULL;}
101cmdLineString::~cmdLineString(void)
102{
103	if(value)	delete[] value;
104	value=NULL;
105}
106int cmdLineString::read(char** argv,int argc){
107	if(argc>0)
108	{
109		value=new char[strlen(argv[0])+1];
110		strcpy(value,argv[0]);
111		set=true;
112		return 1;
113	}
114	else{return 0;}
115}
116void cmdLineString::writeValue(char* str)
117{
118	sprintf(str,"%s",value);
119}
120
121////////////////////
122// cmdLineStrings //
123////////////////////
124cmdLineStrings::cmdLineStrings(const char* name,int Dim) : cmdLineReadable(name)
125{
126	this->Dim=Dim;
127	values=new char*[Dim];
128	for(int i=0;i<Dim;i++)	values[i]=NULL;
129}
130cmdLineStrings::~cmdLineStrings(void)
131{
132	for(int i=0;i<Dim;i++)
133	{
134		if(values[i])	delete[] values[i];
135		values[i]=NULL;
136	}
137	delete[] values;
138	values=NULL;
139}
140int cmdLineStrings::read(char** argv,int argc)
141{
142	if(argc>=Dim)
143	{
144		for(int i=0;i<Dim;i++)
145		{
146			values[i]=new char[strlen(argv[i])+1];
147			strcpy(values[i],argv[i]);
148		}
149		set=true;
150		return Dim;
151	}
152	else	return 0;
153}
154void cmdLineStrings::writeValue(char* str)
155{
156	char* temp=str;
157	for(int i=0;i<Dim;i++)
158	{
159		sprintf(temp,"%s ",values[i]);
160		temp=str+strlen(str);
161	}
162}
163
164
165char* GetFileExtension(char* fileName){
166	char* fileNameCopy;
167	char* ext=NULL;
168	char* temp;
169
170	fileNameCopy=new char[strlen(fileName)+1];
171	assert(fileNameCopy);
172	strcpy(fileNameCopy,fileName);
173	temp=strtok(fileNameCopy,".");
174	while(temp!=NULL)
175	{
176		if(ext!=NULL){delete[] ext;}
177		ext=new char[strlen(temp)+1];
178		assert(ext);
179		strcpy(ext,temp);
180		temp=strtok(NULL,".");
181	}
182	delete[] fileNameCopy;
183	return ext;
184}
185char* GetLocalFileName(char* fileName){
186	char* fileNameCopy;
187	char* name=NULL;
188	char* temp;
189
190	fileNameCopy=new char[strlen(fileName)+1];
191	assert(fileNameCopy);
192	strcpy(fileNameCopy,fileName);
193	temp=strtok(fileNameCopy,"\\");
194	while(temp!=NULL){
195		if(name!=NULL){delete[] name;}
196		name=new char[strlen(temp)+1];
197		assert(name);
198		strcpy(name,temp);
199		temp=strtok(NULL,"\\");
200	}
201	delete[] fileNameCopy;
202	return name;
203}
204
205void cmdLineParse(int argc, char **argv,int num,cmdLineReadable** readable,int dumpError)
206{
207	int i,j;
208	while (argc > 0)
209	{
210		if (argv[0][0] == '-' && argv[0][1]=='-')
211		{
212			for(i=0;i<num;i++)
213			{
214				if (!strcmp(&argv[0][2],readable[i]->name))
215				{
216					argv++, argc--;
217					j=readable[i]->read(argv,argc);
218					argv+=j,argc-=j;
219					break;
220				}
221			}
222			if(i==num){
223				if(dumpError)
224				{
225					fprintf(stderr, "invalid option: %s\n",*argv);
226					fprintf(stderr, "possible options are:\n");
227					for(i=0;i<num;i++)	fprintf(stderr, "  %s\n",readable[i]->name);
228				}
229				argv++, argc--;
230			}
231		}
232		else
233		{
234			if(dumpError)
235			{
236				fprintf(stderr, "invalid option: %s\n", *argv);
237				fprintf(stderr, "  options must start with a \'--\'\n");
238			}
239			argv++, argc--;
240		}
241	}
242}
243char** ReadWords(const char* fileName,int& cnt)
244{
245	char** names;
246	char temp[500];
247	FILE* fp;
248
249	fp=fopen(fileName,"r");
250	if(!fp){return NULL;}
251	cnt=0;
252	while(fscanf(fp," %s ",temp)==1){cnt++;}
253	fclose(fp);
254
255	names=new char*[cnt];
256	if(!names){return NULL;}
257
258	fp=fopen(fileName,"r");
259	if(!fp){
260		delete[] names;
261		cnt=0;
262		return NULL;
263	}
264	cnt=0;
265	while(fscanf(fp," %s ",temp)==1){
266		names[cnt]=new char[strlen(temp)+1];
267		if(!names){
268			for(int j=0;j<cnt;j++){delete[] names[j];}
269			delete[] names;
270			cnt=0;
271			fclose(fp);
272			return NULL;
273		}
274		strcpy(names[cnt],temp);
275		cnt++;
276	}
277	fclose(fp);
278	return names;
279}
280