#include "stdafx.h"
#include "hwincommandline.h"
#include "hwinexception.h"
#include "hwinenvironment.h"
#include "hwinio.h"
namespace harlinn
{
namespace windows
{
HWIN_EXPORT Commandline::Commandline()
: options(CommandlineOptions::Default)
{}
HWIN_EXPORT Commandline::Commandline(const String& theCommandline, CommandlineOptions theCommandlineOptions)
: commandline(theCommandline),options(theCommandlineOptions)
{}
HWIN_EXPORT Commandline::Commandline(const wchar_t* theCommandline, CommandlineOptions theCommandlineOptions)
: commandline(theCommandline),options(theCommandlineOptions)
{}
HWIN_EXPORT Commandline::Commandline(const wchar_t* theCommandline, size_t theCommandlineLength, CommandlineOptions theCommandlineOptions)
: commandline(theCommandline,theCommandlineLength),options(theCommandlineOptions)
{}
void Commandline::Parse()
{
Base::clear();
command = String();
auto length = commandline.length();
if(length)
{
const wchar_t *start = commandline.c_str();
const wchar_t *end = start + length;
while(start < end && (iswspace(*start) || *start < L'\x20' ))
{
start++;
}
if(start < end)
{
end--;
while(iswspace(*end) || *end < L'\x20')
{
end--;
}
end++;
if( (options & CommandlineOptions::FirstIsCommand) == CommandlineOptions::FirstIsCommand)
{
start = ParseFirst(start,end);
}
while(start < end)
{
start = ParseArgument(start,end);
}
}
}
}
const wchar_t* Commandline::ParseFirst(const wchar_t* start, const wchar_t* end)
{
String s;
bool inQuote = false;
const wchar_t* p = start;
// Eat whitespace
while(p < end && (iswspace(*p) || *p < L'\x20' ))
{
p++;
}
while(p < end)
{
wchar_t c = *p;
if(c == L'"')
{
if(inQuote)
{
if( *(p-1) != L'"' )
{
inQuote = false;
}
else
{
s+= c;
}
}
else
{
inQuote = true;
}
}
else
{
if(iswspace(c))
{
if(inQuote)
{
s+= c;
}
else
{
break;
}
}
else
{
s+= c;
}
}
p++;
}
if( (options & CommandlineOptions::ExpandEnvironmentVariables) == CommandlineOptions::ExpandEnvironmentVariables)
{
command = Environment::Expand( s );
}
else
{
command = s;
}
return p;
}
const wchar_t* Commandline::ParseArgument(const wchar_t* start, const wchar_t* end)
{
String s;
bool inQuote = false;
const wchar_t* p = start;
// Eat whitespace
while(p < end && (iswspace(*p) || *p < L'\x20' ))
{
p++;
}
while(p < end)
{
wchar_t c = *p;
if(c == L'"')
{
if(inQuote)
{
if( *(p-1) != L'"' )
{
inQuote = false;
}
else
{
s+= c;
}
}
else
{
inQuote = true;
}
}
else
{
if(iswspace(c))
{
if(inQuote)
{
s+= c;
}
else
{
break;
}
}
else
{
s+= c;
}
}
p++;
}
if( (options & CommandlineOptions::ExpandEnvironmentVariables) == CommandlineOptions::ExpandEnvironmentVariables)
{
s = Environment::Expand( s );
}
if(( (options & CommandlineOptions::ExpandWildCards) == CommandlineOptions::ExpandWildCards) &&
(s.IndexOfAnyOf(L"?*") != String::npos) && s.StartsWith(L"/?") == false )
{
Expand(s);
}
else
{
push_back(s);
}
return p;
}
void Commandline::Expand(const String& theArgument)
{
FileSystemEntriesBase entries(theArgument);
if(entries.Read())
{
do
{
push_back(entries.FullPath());
}while(entries.Read());
}
else
{
push_back(theArgument);
}
}
}
}