/***************************************************************************
                   Argument Parser Class (ArgParser.cpp)
                -----------------------------------------

	begin      : 2013/02/13
	copyright  : (C) 2013 Solbox Inc.
	author     : Development 1 Team
					- 2013/02/13 - 1st dadamin
	email      : dev1@solbox.com
	version    : 3.2.0

	CopyRight(C) 2005 Solbox Inc. All Rights reserved.
	Redistribution and use in source and binary forms, with or with out
	modification, are not permitted in outside of Solbox Inc.
***************************************************************************/

// CHG 2020-11-09 huibong FreeBSD 12.2 컴파일시 오류 발생 관련 header 추가 (#33297)
//                 - _exit() 사용 컴파일 오류 발생 관련 #include <unistd.h> 구문 추가
#include <unistd.h>

#include "ArgParser.h"


CArgParser::CArgParser(int argc, char** argv)
{
	for (int i=1; i<argc; i++)
	{
#ifdef _DEBUG
		cout << "arg i = " << i << "," << argv[i] << endl;
#endif // _DEBUG
		m_args.push_back(argv[i]);
	}
}

CArgParser::~CArgParser()
{
	m_args.clear();
}

void CArgParser::dashes2underscores(const char *input, char *output)
{
	char c = 0;
	char *o = output;
	const char *i = input;
	// first two characters are copied as-is
	*o = *i++;
	if (*o++ == '\0')
		return;
	*o = *i++;
	if (*o++ == '\0')
		return;
	for (; ((c = *i)); ++i) 
	{
		if (c == '=') 
		{
			strcpy(o, i);
			return;
		}
		if (c == '-')
			*o++ = '_';
		else
			*o++ = c;
	}
	*o++ = '\0';
}

bool CArgParser::parsewitharg(vector<char*>::iterator &i, std::string *ret, va_list ap)
{
	const char *first = *i;
	char tmp[strlen(first)+1];
	dashes2underscores(first, tmp);
	first = tmp;
	const char *a;
	int strlen_a;

	// does this argument match any of the possibilities?
	while (1) 
	{
		a = va_arg(ap, char*);
		if (a == NULL)
			return false;
		strlen_a = strlen(a);
		char a2[strlen_a+1];
		dashes2underscores(a, a2);
		if (strncmp(a2, first, strlen(a2)) == 0) 
		{
			if (first[strlen_a] == '=') 
			{
				*ret = first + strlen_a + 1;
				i = m_args.erase(i);
				return true;
			}
			else if (first[strlen_a] == '\0') 
			{
				// find second part (or not)
				if (i+1 == m_args.end()) 
				{
					cerr << "[error] Option " << *i << " requires an argument." << std::endl;
					_exit(EXIT_FAILURE);
				}
				i = m_args.erase(i);
				*ret = *i;
				i = m_args.erase(i);
				return true;
			}
		}
	}

	return false;
}

bool CArgParser::argparseflag(vector<char*>::iterator &i, ...)
{
	const char *first = *i;
	char tmp[strlen(first)+1];
	dashes2underscores(first, tmp);
	first = tmp;
	const char *a;
	va_list ap;

	va_start(ap, i);
	while (1) 
	{
		a = va_arg(ap, char*);
		if (a == NULL) 
		{
			va_end(ap);
			return false;
		}

		char a2[strlen(a)+1];
		dashes2underscores(a, a2);
		if (strcmp(a2, first) == 0) 
		{
			i = m_args.erase(i);
			va_end(ap);
			return true;
		}
	}

	return false;
}

bool CArgParser::argparsewitharg(vector<char*>::iterator &i, string *ret, ...)
{
	bool r;
	va_list ap;
	va_start(ap, ret);
	r = parsewitharg(i, ret, ap);
	va_end(ap);
	return r;
}

bool CArgParser::checkvalue(const char *c, string *ret/* = NULL*/)
{
	for (vector<char*>::iterator i = m_args.begin(); i != m_args.end(); ++i) 
	{
		if(ret)
		{
			if(argparsewitharg(i,ret, c, (char*)NULL))
				return true;
		}
		else
		{
			if(argparseflag(i,c, (char*)NULL))
				return true;
		}
			
	}

	return false;
}
