Adam Johnson
10 years ago
17 changed files with 1339 additions and 1275 deletions
@ -0,0 +1,618 @@ |
|||||||
|
/*==LICENSE==*
|
||||||
|
|
||||||
|
CyanWorlds.com Engine - MMOG client, server and tools |
||||||
|
Copyright (C) 2011 Cyan Worlds, Inc. |
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify |
||||||
|
it under the terms of the GNU General Public License as published by |
||||||
|
the Free Software Foundation, either version 3 of the License, or |
||||||
|
(at your option) any later version. |
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful, |
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||||
|
GNU General Public License for more details. |
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License |
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Additional permissions under GNU GPL version 3 section 7 |
||||||
|
|
||||||
|
If you modify this Program, or any covered work, by linking or |
||||||
|
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK, |
||||||
|
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent |
||||||
|
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK |
||||||
|
(or a modified version of those libraries), |
||||||
|
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA, |
||||||
|
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG |
||||||
|
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the |
||||||
|
licensors of this Program grant you additional |
||||||
|
permission to convey the resulting work. Corresponding Source for a |
||||||
|
non-source form of such a combination shall include the source code for |
||||||
|
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered |
||||||
|
work. |
||||||
|
|
||||||
|
You can contact Cyan Worlds, Inc. by email legal@cyan.com |
||||||
|
or by snail mail at: |
||||||
|
Cyan Worlds, Inc. |
||||||
|
14617 N Newport Hwy |
||||||
|
Mead, WA 99021 |
||||||
|
|
||||||
|
*==LICENSE==*/ |
||||||
|
|
||||||
|
#include "plCmdParser.h" |
||||||
|
|
||||||
|
#include <vector> |
||||||
|
#include <algorithm> |
||||||
|
|
||||||
|
#define WHITESPACE " \"\t\r\n\x1A" |
||||||
|
#define FLAGS "-/" |
||||||
|
#define SEPARATORS "=:" |
||||||
|
#define TOGGLES "+-" |
||||||
|
#define ALL WHITESPACE FLAGS SEPARATORS TOGGLES |
||||||
|
|
||||||
|
#define hsCheckFlagBits(f,c,m) ((f & m)==c) |
||||||
|
|
||||||
|
|
||||||
|
struct plCmdArgData |
||||||
|
{ |
||||||
|
plCmdArgDef def; |
||||||
|
|
||||||
|
union { |
||||||
|
bool boolVal; |
||||||
|
float floatVal; |
||||||
|
int32_t intVal; |
||||||
|
const char* strVal; |
||||||
|
uint32_t uintVal; |
||||||
|
} val; |
||||||
|
|
||||||
|
plString buffer; |
||||||
|
size_t nameChars; |
||||||
|
bool isSpecified; |
||||||
|
}; |
||||||
|
|
||||||
|
struct plCmdTokenState { |
||||||
|
size_t fPendingIndex; |
||||||
|
size_t fUnflaggedIndex; |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
class plCmdParserImpl |
||||||
|
{ |
||||||
|
protected: |
||||||
|
plString fProgramName; |
||||||
|
std::vector<plCmdArgData> fArgArray; |
||||||
|
std::vector<uint32_t> fLookupArray; |
||||||
|
std::vector<uint32_t> fUnflaggedArray; |
||||||
|
uint32_t fRequiredCount; |
||||||
|
CmdError fError; |
||||||
|
|
||||||
|
void SetDefaultValue(plCmdArgData& arg); |
||||||
|
bool ProcessValue(plCmdTokenState* state, size_t index, const plString& str); |
||||||
|
bool TokenizeFlags(plCmdTokenState* state, const plString& str); |
||||||
|
bool LookupFlagged(plString& name, size_t* lastIndex, bool force=false) const; |
||||||
|
|
||||||
|
public: |
||||||
|
plCmdParserImpl(const plCmdArgDef* defs, size_t defCount); |
||||||
|
|
||||||
|
bool Tokenize(plCmdTokenState* state, std::vector<plString>& strs); |
||||||
|
const plCmdArgData* FindArgByName(const plString& name) const; |
||||||
|
const plCmdArgData* FindArgById(size_t id) const; |
||||||
|
bool CheckAllRequiredArguments(plCmdTokenState* state); |
||||||
|
|
||||||
|
const plString GetProgramName() const { return fProgramName; } |
||||||
|
|
||||||
|
CmdError GetError() const { return fError; } |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
plCmdParserImpl::plCmdParserImpl(const plCmdArgDef* defs, size_t defCount) |
||||||
|
{ |
||||||
|
size_t loop; |
||||||
|
fError = kCmdErrorSuccess; |
||||||
|
|
||||||
|
// Save the argument definitions
|
||||||
|
size_t maxId = 0; |
||||||
|
size_t unflaggedCount = 0; |
||||||
|
|
||||||
|
fArgArray.resize(defCount); |
||||||
|
|
||||||
|
for (loop = 0; loop < defCount; ++loop) { |
||||||
|
plCmdArgDef def = defs[loop]; |
||||||
|
|
||||||
|
// Check whether this argument is flagged
|
||||||
|
bool flagged = hsCheckFlagBits(def.flags, |
||||||
|
kCmdArgFlagged, |
||||||
|
kCmdArgMask); |
||||||
|
|
||||||
|
// Disallow names on unflagged arguments
|
||||||
|
ASSERT(flagged || !def.name.IsEmpty()); |
||||||
|
|
||||||
|
// Store the argument data
|
||||||
|
plCmdArgData& arg = fArgArray[loop]; |
||||||
|
arg.def = def; |
||||||
|
arg.buffer = ""; |
||||||
|
arg.nameChars = def.name.GetSize(); |
||||||
|
arg.isSpecified = false; |
||||||
|
|
||||||
|
SetDefaultValue(arg); |
||||||
|
maxId = std::max(maxId, def.id); |
||||||
|
|
||||||
|
// Track the number of unflagged arguments
|
||||||
|
if (!flagged) { |
||||||
|
++unflaggedCount; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
// Build the id lookup table
|
||||||
|
size_t idTableSize = std::min(maxId + 1, defCount * 2); |
||||||
|
fLookupArray.resize(idTableSize); |
||||||
|
|
||||||
|
for (loop = 0; loop < defCount; ++loop) { |
||||||
|
if (defs[loop].id < idTableSize) { |
||||||
|
fLookupArray[defs[loop].id] = loop; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
// Build the unflagged array
|
||||||
|
size_t unflaggedIndex = 0; |
||||||
|
fUnflaggedArray.resize(unflaggedCount); |
||||||
|
|
||||||
|
for (loop = 0; loop < defCount; ++loop) { |
||||||
|
bool req = hsCheckFlagBits(defs[loop].flags, |
||||||
|
kCmdArgRequired, |
||||||
|
kCmdArgMask); |
||||||
|
|
||||||
|
if (req) { |
||||||
|
fUnflaggedArray[unflaggedIndex++] = loop; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
fRequiredCount = unflaggedIndex; |
||||||
|
|
||||||
|
for (loop = 0; loop < defCount; ++loop) { |
||||||
|
bool flagged = hsCheckFlagBits(defs[loop].flags, |
||||||
|
kCmdArgFlagged, |
||||||
|
kCmdArgMask); |
||||||
|
|
||||||
|
bool req = hsCheckFlagBits(defs[loop].flags, |
||||||
|
kCmdArgRequired, |
||||||
|
kCmdArgMask); |
||||||
|
|
||||||
|
if (!flagged && !req) { |
||||||
|
fUnflaggedArray[unflaggedIndex++] = loop; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
void plCmdParserImpl::SetDefaultValue(plCmdArgData& arg) |
||||||
|
{ |
||||||
|
uint32_t argType = arg.def.flags & kCmdTypeMask; |
||||||
|
|
||||||
|
switch (argType) { |
||||||
|
case kCmdTypeBool: |
||||||
|
arg.val.boolVal = !hsCheckFlagBits(arg.def.flags, |
||||||
|
kCmdBoolSet, |
||||||
|
kCmdBoolMask); |
||||||
|
break; |
||||||
|
|
||||||
|
case kCmdTypeInt: |
||||||
|
arg.val.intVal = 0; |
||||||
|
break; |
||||||
|
|
||||||
|
case kCmdTypeUint: |
||||||
|
arg.val.uintVal = 0; |
||||||
|
break; |
||||||
|
|
||||||
|
case kCmdTypeFloat: |
||||||
|
arg.val.floatVal = 0.0f; |
||||||
|
break; |
||||||
|
|
||||||
|
case kCmdTypeString: |
||||||
|
arg.val.strVal = ""; |
||||||
|
break; |
||||||
|
|
||||||
|
DEFAULT_FATAL(argType); |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
bool plCmdParserImpl::Tokenize(plCmdTokenState* state, std::vector<plString>& strs) |
||||||
|
{ |
||||||
|
bool result = true; |
||||||
|
|
||||||
|
for (auto it = strs.begin(); result && it != strs.end(); ++it) { |
||||||
|
if (fProgramName.IsEmpty()) { |
||||||
|
fProgramName = *it; |
||||||
|
continue; |
||||||
|
} |
||||||
|
|
||||||
|
// If the previous argument is awaiting a value, then use this token
|
||||||
|
// as the value
|
||||||
|
if (state->fPendingIndex != size_t(-1)) { |
||||||
|
result = ProcessValue(state, state->fPendingIndex, *it); |
||||||
|
state->fPendingIndex = size_t(-1); |
||||||
|
continue; |
||||||
|
} |
||||||
|
|
||||||
|
// Identify and process flagged parameters
|
||||||
|
if ((*it).REMatch("[" FLAGS "].+") && TokenizeFlags(state, *it)) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
|
||||||
|
// Process unflagged parameters
|
||||||
|
if (state->fUnflaggedIndex < fUnflaggedArray.size()) { |
||||||
|
result = ProcessValue(state, fUnflaggedArray[state->fUnflaggedIndex++], *it); |
||||||
|
continue; |
||||||
|
} |
||||||
|
|
||||||
|
// Process invalid parameters
|
||||||
|
if (!fError) { |
||||||
|
fError = kCmdErrorTooManyArgs; |
||||||
|
} |
||||||
|
result = false; |
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
bool plCmdParserImpl::ProcessValue(plCmdTokenState* state, size_t index, const plString& str) |
||||||
|
{ |
||||||
|
plCmdArgData& arg = fArgArray[index]; |
||||||
|
arg.isSpecified = true; |
||||||
|
uint32_t argType = arg.def.flags & kCmdTypeMask; |
||||||
|
|
||||||
|
switch (argType) { |
||||||
|
case kCmdTypeBool: |
||||||
|
if (str.CompareI("true") == 0) |
||||||
|
arg.val.boolVal = true; |
||||||
|
else if (str.CompareI("false") == 0) |
||||||
|
arg.val.boolVal = false; |
||||||
|
else if (str.IsEmpty()) |
||||||
|
arg.val.boolVal = hsCheckFlagBits(arg.def.flags, |
||||||
|
kCmdBoolSet, |
||||||
|
kCmdBoolMask); |
||||||
|
else |
||||||
|
fError = kCmdErrorInvalidValue; |
||||||
|
break; |
||||||
|
|
||||||
|
case kCmdTypeFloat: |
||||||
|
arg.val.floatVal = str.ToFloat(); |
||||||
|
break; |
||||||
|
|
||||||
|
case kCmdTypeInt: |
||||||
|
arg.val.intVal = str.ToInt(); |
||||||
|
break; |
||||||
|
|
||||||
|
case kCmdTypeString: |
||||||
|
arg.buffer = str; |
||||||
|
arg.val.strVal = arg.buffer.c_str(); |
||||||
|
break; |
||||||
|
|
||||||
|
case kCmdTypeUint: |
||||||
|
arg.val.uintVal = str.ToUInt(10); |
||||||
|
break; |
||||||
|
|
||||||
|
DEFAULT_FATAL(argType); |
||||||
|
|
||||||
|
} |
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
bool plCmdParserImpl::TokenizeFlags(plCmdTokenState* state, const plString& str) |
||||||
|
{ |
||||||
|
bool result = true; |
||||||
|
std::vector<plString> tokens = str.Tokenize(ALL); |
||||||
|
|
||||||
|
for (auto it = tokens.begin(); result && it != tokens.end(); ++it) { |
||||||
|
size_t lastIndex = size_t(-1); |
||||||
|
plString buffer = *it; |
||||||
|
|
||||||
|
if (buffer.IsEmpty()) { |
||||||
|
continue; |
||||||
|
} |
||||||
|
|
||||||
|
while (result) { |
||||||
|
// Lookup the argument name
|
||||||
|
result = LookupFlagged(buffer, &lastIndex); |
||||||
|
if (!result) { |
||||||
|
fError = kCmdErrorInvalidArg; |
||||||
|
result = false; |
||||||
|
} |
||||||
|
|
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
if (!result) { |
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
// Check for an argument value provided using a separator
|
||||||
|
if (str.REMatch(".+[" SEPARATORS "].+") && !(*(++it)).IsEmpty()) { |
||||||
|
result = ProcessValue(state, lastIndex, *it); |
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
bool isBool = hsCheckFlagBits(fArgArray[lastIndex].def.flags, |
||||||
|
kCmdTypeBool, |
||||||
|
kCmdTypeMask); |
||||||
|
|
||||||
|
// Process values for boolean arguments
|
||||||
|
if (isBool) { |
||||||
|
result = ProcessValue(state, lastIndex, plString::Null); |
||||||
|
continue; |
||||||
|
} |
||||||
|
|
||||||
|
// Process values for non-boolean arguments
|
||||||
|
else { |
||||||
|
// Check for an argument value immediately following the name
|
||||||
|
if (!buffer.IsEmpty()) { |
||||||
|
result = ProcessValue(state, lastIndex, buffer); |
||||||
|
break; |
||||||
|
} |
||||||
|
|
||||||
|
// Check for an argument value in the next token
|
||||||
|
else { |
||||||
|
state->fPendingIndex = lastIndex; |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
bool plCmdParserImpl::LookupFlagged(plString& name, size_t* lastIndex, bool force) const |
||||||
|
{ |
||||||
|
size_t argCount = fArgArray.size(); |
||||||
|
size_t chars = name.GetSize(); |
||||||
|
size_t bestIndex = size_t(-1); |
||||||
|
size_t bestChars = 0; |
||||||
|
|
||||||
|
|
||||||
|
size_t prevChars = 0; |
||||||
|
if (*lastIndex != size_t(-1)) { |
||||||
|
prevChars = fArgArray[*lastIndex].def.name.GetSize(); |
||||||
|
} |
||||||
|
|
||||||
|
for (; prevChars != size_t(-1) && !bestChars; --prevChars) { |
||||||
|
// Find this argument in the list
|
||||||
|
for (size_t index = 0; index < argCount; ++index) { |
||||||
|
const plCmdArgData& arg = fArgArray[index]; |
||||||
|
|
||||||
|
// Ignore non-flagged arguments
|
||||||
|
bool flagged = hsCheckFlagBits(arg.def.flags, |
||||||
|
kCmdArgFlagged, |
||||||
|
kCmdArgMask); |
||||||
|
if (!flagged && !force) |
||||||
|
continue; |
||||||
|
|
||||||
|
// Ignore this arg if it wouldn't beat the previous best match
|
||||||
|
if (arg.def.name.GetSize() < bestChars + prevChars) |
||||||
|
continue; |
||||||
|
|
||||||
|
// Ignore this argument if it doesn't match the prefix
|
||||||
|
bool caseSensitive = hsCheckBits(arg.def.flags, |
||||||
|
kCmdCaseSensitive); |
||||||
|
|
||||||
|
if (prevChars) { |
||||||
|
const plCmdArgData& prev = fArgArray[*lastIndex]; |
||||||
|
|
||||||
|
if (prevChars >= arg.def.name.GetSize()) |
||||||
|
continue; |
||||||
|
|
||||||
|
if (caseSensitive && |
||||||
|
arg.def.name.CompareN(prev.def.name, prevChars)) |
||||||
|
continue; |
||||||
|
|
||||||
|
if (!caseSensitive && |
||||||
|
arg.def.name.CompareNI(prev.def.name, prevChars)) |
||||||
|
continue; |
||||||
|
} |
||||||
|
|
||||||
|
// Ignore this argument if it doesn't match the suffix
|
||||||
|
plString suffix = arg.def.name.Substr(prevChars); |
||||||
|
if (caseSensitive && suffix.CompareN(name, std::min(name.GetSize(), suffix.GetSize()))) |
||||||
|
continue; |
||||||
|
|
||||||
|
if (!caseSensitive && suffix.CompareNI(name, std::min(name.GetSize(), suffix.GetSize()))) |
||||||
|
continue; |
||||||
|
|
||||||
|
// Track the best match
|
||||||
|
bestIndex = index; |
||||||
|
bestChars = arg.def.name.GetSize() - prevChars; |
||||||
|
if (bestChars == chars) |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Return the result
|
||||||
|
name = name.Substr(bestChars); |
||||||
|
*lastIndex = bestIndex; |
||||||
|
return bestChars != 0; |
||||||
|
} |
||||||
|
|
||||||
|
const plCmdArgData* plCmdParserImpl::FindArgByName(const plString& name) const |
||||||
|
{ |
||||||
|
// Search for an argument with this name
|
||||||
|
size_t index = size_t(-1); |
||||||
|
plString arg = name; |
||||||
|
if (!LookupFlagged(arg, &index, true)) { |
||||||
|
return nullptr; |
||||||
|
} |
||||||
|
|
||||||
|
// Return the argument data
|
||||||
|
return &fArgArray[index]; |
||||||
|
} |
||||||
|
|
||||||
|
const plCmdArgData* plCmdParserImpl::FindArgById(size_t id) const |
||||||
|
{ |
||||||
|
// Search for the argument with this id
|
||||||
|
size_t index; |
||||||
|
if (id < fLookupArray.size()) { |
||||||
|
index = fLookupArray[id]; |
||||||
|
} else { |
||||||
|
for (index = 0; index < fArgArray.size(); ++index) { |
||||||
|
if (fArgArray[index].def.id == id) { |
||||||
|
break; |
||||||
|
} |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
// Verify that we found the correct argument
|
||||||
|
if ((index >= fArgArray.size()) || (fArgArray[index].def.id != id)) { |
||||||
|
return nullptr; |
||||||
|
} |
||||||
|
|
||||||
|
// Return the argument data
|
||||||
|
return &fArgArray[index]; |
||||||
|
} |
||||||
|
|
||||||
|
bool plCmdParserImpl::CheckAllRequiredArguments(plCmdTokenState* state) |
||||||
|
{ |
||||||
|
bool result = (state->fUnflaggedIndex >= fRequiredCount); |
||||||
|
|
||||||
|
if (!result) { |
||||||
|
fError = kCmdErrorTooFewArgs; |
||||||
|
} |
||||||
|
|
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
plCmdParser::plCmdParser(const plCmdArgDef* defs, size_t defCount) |
||||||
|
{ |
||||||
|
Initialize(defs, defCount); |
||||||
|
} |
||||||
|
|
||||||
|
plCmdParser::~plCmdParser() |
||||||
|
{ |
||||||
|
delete fParser; |
||||||
|
} |
||||||
|
|
||||||
|
void plCmdParser::Initialize(const plCmdArgDef* defs, size_t defCount) |
||||||
|
{ |
||||||
|
fParser = new plCmdParserImpl(defs, defCount); |
||||||
|
} |
||||||
|
|
||||||
|
bool plCmdParser::Parse(const plString& cmdLine) |
||||||
|
{ |
||||||
|
// Process the command line
|
||||||
|
plCmdTokenState state = { |
||||||
|
size_t(-1), // pending index
|
||||||
|
0 // unflagged index
|
||||||
|
}; |
||||||
|
|
||||||
|
std::vector<plString> tokens = cmdLine.Tokenize(WHITESPACE); |
||||||
|
|
||||||
|
bool result = fParser->Tokenize(&state, tokens); |
||||||
|
|
||||||
|
if (result) { |
||||||
|
result = fParser->CheckAllRequiredArguments(&state); |
||||||
|
} |
||||||
|
|
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
bool plCmdParser::Parse(std::vector<plString>& argv) |
||||||
|
{ |
||||||
|
// Process the command line
|
||||||
|
plCmdTokenState state = { |
||||||
|
size_t(-1), // pending index
|
||||||
|
0 // unflagged index
|
||||||
|
}; |
||||||
|
|
||||||
|
bool result = fParser->Tokenize(&state, argv); |
||||||
|
|
||||||
|
if (result) { |
||||||
|
result = fParser->CheckAllRequiredArguments(&state); |
||||||
|
} |
||||||
|
|
||||||
|
return result; |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
const plString plCmdParser::GetProgramName() const |
||||||
|
{ |
||||||
|
return fParser->GetProgramName(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
bool plCmdParser::GetBool(size_t id) const |
||||||
|
{ |
||||||
|
return fParser->FindArgById(id)->val.boolVal; |
||||||
|
} |
||||||
|
|
||||||
|
bool plCmdParser::GetBool(const plString& name) const |
||||||
|
{ |
||||||
|
return fParser->FindArgByName(name)->val.boolVal; |
||||||
|
} |
||||||
|
|
||||||
|
float plCmdParser::GetFloat(size_t id) const |
||||||
|
{ |
||||||
|
return fParser->FindArgById(id)->val.floatVal; |
||||||
|
} |
||||||
|
|
||||||
|
float plCmdParser::GetFloat(const plString& name) const |
||||||
|
{ |
||||||
|
return fParser->FindArgByName(name)->val.floatVal; |
||||||
|
} |
||||||
|
|
||||||
|
int32_t plCmdParser::GetInt(size_t id) const |
||||||
|
{ |
||||||
|
return fParser->FindArgById(id)->val.intVal; |
||||||
|
} |
||||||
|
|
||||||
|
int32_t plCmdParser::GetInt(const plString& name) const |
||||||
|
{ |
||||||
|
return fParser->FindArgByName(name)->val.intVal; |
||||||
|
} |
||||||
|
|
||||||
|
const plString plCmdParser::GetString(size_t id) const |
||||||
|
{ |
||||||
|
return fParser->FindArgById(id)->val.strVal; |
||||||
|
} |
||||||
|
|
||||||
|
const plString plCmdParser::GetString(const plString& name) const |
||||||
|
{ |
||||||
|
return fParser->FindArgByName(name)->val.strVal; |
||||||
|
} |
||||||
|
|
||||||
|
uint32_t plCmdParser::GetUint(size_t id) const |
||||||
|
{ |
||||||
|
return fParser->FindArgById(id)->val.uintVal; |
||||||
|
} |
||||||
|
|
||||||
|
uint32_t plCmdParser::GetUint(const plString& name) const |
||||||
|
{ |
||||||
|
return fParser->FindArgByName(name)->val.uintVal; |
||||||
|
} |
||||||
|
|
||||||
|
bool plCmdParser::IsSpecified(size_t id) const |
||||||
|
{ |
||||||
|
if (const plCmdArgData* data = fParser->FindArgById(id)) { |
||||||
|
return data->isSpecified; |
||||||
|
} |
||||||
|
|
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
bool plCmdParser::IsSpecified(const plString& name) const |
||||||
|
{ |
||||||
|
if (const plCmdArgData* data = fParser->FindArgByName(name)) { |
||||||
|
return data->isSpecified; |
||||||
|
} |
||||||
|
|
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
CmdError plCmdParser::GetError() const |
||||||
|
{ |
||||||
|
return fParser->GetError(); |
||||||
|
} |
@ -0,0 +1,136 @@ |
|||||||
|
/*==LICENSE==*
|
||||||
|
|
||||||
|
CyanWorlds.com Engine - MMOG client, server and tools |
||||||
|
Copyright (C) 2011 Cyan Worlds, Inc. |
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify |
||||||
|
it under the terms of the GNU General Public License as published by |
||||||
|
the Free Software Foundation, either version 3 of the License, or |
||||||
|
(at your option) any later version. |
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful, |
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||||
|
GNU General Public License for more details. |
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License |
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Additional permissions under GNU GPL version 3 section 7 |
||||||
|
|
||||||
|
If you modify this Program, or any covered work, by linking or |
||||||
|
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK, |
||||||
|
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent |
||||||
|
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK |
||||||
|
(or a modified version of those libraries), |
||||||
|
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA, |
||||||
|
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG |
||||||
|
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the |
||||||
|
licensors of this Program grant you additional |
||||||
|
permission to convey the resulting work. Corresponding Source for a |
||||||
|
non-source form of such a combination shall include the source code for |
||||||
|
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered |
||||||
|
work. |
||||||
|
|
||||||
|
You can contact Cyan Worlds, Inc. by email legal@cyan.com |
||||||
|
or by snail mail at: |
||||||
|
Cyan Worlds, Inc. |
||||||
|
14617 N Newport Hwy |
||||||
|
Mead, WA 99021 |
||||||
|
|
||||||
|
*==LICENSE==*/ |
||||||
|
|
||||||
|
#ifndef _plCmdParser_h_ |
||||||
|
#define _plCmdParser_h_ |
||||||
|
|
||||||
|
#include "plString.h" |
||||||
|
|
||||||
|
enum CmdArg |
||||||
|
{ |
||||||
|
kCmdArgFlagged = 0x0, // default
|
||||||
|
kCmdArgOptional = 0x1, |
||||||
|
kCmdArgRequired = 0x2, |
||||||
|
kCmdArgMask = 0xF |
||||||
|
}; |
||||||
|
|
||||||
|
enum CmdType |
||||||
|
{ |
||||||
|
kCmdTypeBool = 0x0 << 4, // default
|
||||||
|
kCmdTypeInt = 0x1 << 4, |
||||||
|
kCmdTypeUint = 0x2 << 4, |
||||||
|
kCmdTypeFloat = 0x3 << 4, |
||||||
|
kCmdTypeString = 0x4 << 4, |
||||||
|
kCmdTypeMask = 0xF << 4 |
||||||
|
}; |
||||||
|
|
||||||
|
enum CmdBool |
||||||
|
{ |
||||||
|
kCmdBoolSet = 0x0 << 8, // default
|
||||||
|
kCmdBoolUnset = 0x1 << 8, |
||||||
|
kCmdBoolMask = 0xF << 8 |
||||||
|
}; |
||||||
|
|
||||||
|
enum CmdCase |
||||||
|
{ |
||||||
|
kCmdCaseSensitive = 0x1 << 28 |
||||||
|
}; |
||||||
|
|
||||||
|
// Error codes
|
||||||
|
enum CmdError |
||||||
|
{ |
||||||
|
kCmdErrorSuccess, |
||||||
|
kCmdErrorInvalidArg, |
||||||
|
kCmdErrorInvalidValue, |
||||||
|
kCmdErrorTooFewArgs, |
||||||
|
kCmdErrorTooManyArgs, |
||||||
|
kNumCmdErrors |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
struct plCmdArgDef |
||||||
|
{ |
||||||
|
uint32_t flags; |
||||||
|
plString name; // must be compile-time constant
|
||||||
|
size_t id; |
||||||
|
}; |
||||||
|
|
||||||
|
|
||||||
|
class plCmdParser |
||||||
|
{ |
||||||
|
protected: |
||||||
|
class plCmdParserImpl* fParser; |
||||||
|
|
||||||
|
plCmdParser() : fParser(nullptr) { } |
||||||
|
void Initialize(const plCmdArgDef* defs, size_t defCount); |
||||||
|
|
||||||
|
public: |
||||||
|
plCmdParser(const plCmdArgDef* defs, size_t defCount); |
||||||
|
virtual ~plCmdParser(); |
||||||
|
|
||||||
|
bool Parse(const plString& cmdLine); |
||||||
|
bool Parse(std::vector<plString>& argv); |
||||||
|
|
||||||
|
const plString GetProgramName() const; |
||||||
|
|
||||||
|
bool GetBool(size_t id) const; |
||||||
|
bool GetBool(const plString& name) const; |
||||||
|
|
||||||
|
float GetFloat(size_t id) const; |
||||||
|
float GetFloat(const plString& name) const; |
||||||
|
|
||||||
|
int32_t GetInt(size_t id) const; |
||||||
|
int32_t GetInt(const plString& name) const; |
||||||
|
|
||||||
|
const plString GetString(size_t id) const; |
||||||
|
const plString GetString(const plString& name) const; |
||||||
|
|
||||||
|
uint32_t GetUint(size_t id) const; |
||||||
|
uint32_t GetUint(const plString& name) const; |
||||||
|
|
||||||
|
bool IsSpecified(size_t id) const; |
||||||
|
bool IsSpecified(const plString& name) const; |
||||||
|
|
||||||
|
CmdError GetError() const; |
||||||
|
}; |
||||||
|
|
||||||
|
#endif //_plCmdParser_h_
|
@ -1,41 +0,0 @@ |
|||||||
/*==LICENSE==*
|
|
||||||
|
|
||||||
CyanWorlds.com Engine - MMOG client, server and tools |
|
||||||
Copyright (C) 2011 Cyan Worlds, Inc. |
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify |
|
||||||
it under the terms of the GNU General Public License as published by |
|
||||||
the Free Software Foundation, either version 3 of the License, or |
|
||||||
(at your option) any later version. |
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful, |
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
GNU General Public License for more details. |
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License |
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
Additional permissions under GNU GPL version 3 section 7 |
|
||||||
|
|
||||||
If you modify this Program, or any covered work, by linking or |
|
||||||
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK, |
|
||||||
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent |
|
||||||
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK |
|
||||||
(or a modified version of those libraries), |
|
||||||
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA, |
|
||||||
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG |
|
||||||
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the |
|
||||||
licensors of this Program grant you additional |
|
||||||
permission to convey the resulting work. Corresponding Source for a |
|
||||||
non-source form of such a combination shall include the source code for |
|
||||||
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered |
|
||||||
work. |
|
||||||
|
|
||||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com |
|
||||||
or by snail mail at: |
|
||||||
Cyan Worlds, Inc. |
|
||||||
14617 N Newport Hwy |
|
||||||
Mead, WA 99021 |
|
||||||
|
|
||||||
*==LICENSE==*/ |
|
@ -1,60 +0,0 @@ |
|||||||
/*==LICENSE==*
|
|
||||||
|
|
||||||
CyanWorlds.com Engine - MMOG client, server and tools |
|
||||||
Copyright (C) 2011 Cyan Worlds, Inc. |
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify |
|
||||||
it under the terms of the GNU General Public License as published by |
|
||||||
the Free Software Foundation, either version 3 of the License, or |
|
||||||
(at your option) any later version. |
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful, |
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
GNU General Public License for more details. |
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License |
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
Additional permissions under GNU GPL version 3 section 7 |
|
||||||
|
|
||||||
If you modify this Program, or any covered work, by linking or |
|
||||||
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK, |
|
||||||
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent |
|
||||||
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK |
|
||||||
(or a modified version of those libraries), |
|
||||||
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA, |
|
||||||
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG |
|
||||||
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the |
|
||||||
licensors of this Program grant you additional |
|
||||||
permission to convey the resulting work. Corresponding Source for a |
|
||||||
non-source form of such a combination shall include the source code for |
|
||||||
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered |
|
||||||
work. |
|
||||||
|
|
||||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com |
|
||||||
or by snail mail at: |
|
||||||
Cyan Worlds, Inc. |
|
||||||
14617 N Newport Hwy |
|
||||||
Mead, WA 99021 |
|
||||||
|
|
||||||
*==LICENSE==*/ |
|
||||||
/*****************************************************************************
|
|
||||||
* |
|
||||||
* $/Plasma20/Sources/Plasma/NucleusLib/pnUtils/Private/Win32/pnUtW32Misc.cpp |
|
||||||
*
|
|
||||||
***/ |
|
||||||
|
|
||||||
#include "../pnUtils.h" |
|
||||||
|
|
||||||
/*****************************************************************************
|
|
||||||
* |
|
||||||
* Exports |
|
||||||
* |
|
||||||
***/ |
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
const wchar_t * AppGetCommandLine () { |
|
||||||
return GetCommandLineW(); |
|
||||||
} |
|
||||||
|
|
@ -1,650 +0,0 @@ |
|||||||
/*==LICENSE==*
|
|
||||||
|
|
||||||
CyanWorlds.com Engine - MMOG client, server and tools |
|
||||||
Copyright (C) 2011 Cyan Worlds, Inc. |
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify |
|
||||||
it under the terms of the GNU General Public License as published by |
|
||||||
the Free Software Foundation, either version 3 of the License, or |
|
||||||
(at your option) any later version. |
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful, |
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
GNU General Public License for more details. |
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License |
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
Additional permissions under GNU GPL version 3 section 7 |
|
||||||
|
|
||||||
If you modify this Program, or any covered work, by linking or |
|
||||||
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK, |
|
||||||
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent |
|
||||||
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK |
|
||||||
(or a modified version of those libraries), |
|
||||||
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA, |
|
||||||
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG |
|
||||||
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the |
|
||||||
licensors of this Program grant you additional |
|
||||||
permission to convey the resulting work. Corresponding Source for a |
|
||||||
non-source form of such a combination shall include the source code for |
|
||||||
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered |
|
||||||
work. |
|
||||||
|
|
||||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com |
|
||||||
or by snail mail at: |
|
||||||
Cyan Worlds, Inc. |
|
||||||
14617 N Newport Hwy |
|
||||||
Mead, WA 99021 |
|
||||||
|
|
||||||
*==LICENSE==*/ |
|
||||||
/*****************************************************************************
|
|
||||||
* |
|
||||||
* $/Plasma20/Sources/Plasma/NucleusLib/pnUtils/Private/pnUtCmd.cpp |
|
||||||
*
|
|
||||||
***/ |
|
||||||
|
|
||||||
#include "pnUtCmd.h" |
|
||||||
#include "pnUtMisc.h" |
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
|
||||||
* |
|
||||||
* Private |
|
||||||
* |
|
||||||
***/ |
|
||||||
|
|
||||||
#define WHITESPACE L" \"\t\r\n\x1A" |
|
||||||
#define FLAGS L"-/" |
|
||||||
#define SEPARATORS L"=:" |
|
||||||
#define TOGGLES L"+-" |
|
||||||
#define ALL WHITESPACE FLAGS SEPARATORS TOGGLES |
|
||||||
|
|
||||||
#if HS_BUILD_FOR_WIN32 |
|
||||||
static const unsigned kMaxTokenLength = MAX_PATH; |
|
||||||
#else |
|
||||||
static const unsigned kMaxTokenLength = 1024; |
|
||||||
#endif |
|
||||||
|
|
||||||
struct CmdArgData { |
|
||||||
CmdArgDef def; |
|
||||||
union { |
|
||||||
bool boolVal; |
|
||||||
float floatVal; |
|
||||||
int intVal; |
|
||||||
const wchar_t * strVal; |
|
||||||
unsigned unsignedVal; |
|
||||||
} val; |
|
||||||
wchar_t * buffer; |
|
||||||
unsigned nameChars; |
|
||||||
bool isSpecified; |
|
||||||
|
|
||||||
~CmdArgData () { |
|
||||||
if (buffer) |
|
||||||
free(buffer); |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
struct CmdTokState { |
|
||||||
CCmdParser * parser; |
|
||||||
unsigned pendingIndex; |
|
||||||
unsigned unflaggedIndex; |
|
||||||
}; |
|
||||||
|
|
||||||
class CICmdParser { |
|
||||||
private: |
|
||||||
FARRAYOBJ(CmdArgData) m_argArray; |
|
||||||
FARRAY(unsigned) m_idLookupArray; |
|
||||||
unsigned m_requiredCount; |
|
||||||
FARRAY(unsigned) m_unflaggedArray; |
|
||||||
|
|
||||||
inline bool CheckFlag (unsigned flags, unsigned flag, unsigned mask) const; |
|
||||||
void Error (const CmdTokState * state, ECmdError errorCode, const wchar_t arg[], const wchar_t value[]) const; |
|
||||||
bool LookupFlagged (const wchar_t ** name, unsigned * lastIndex) const; |
|
||||||
bool ProcessValue (CmdTokState * state, unsigned index, const wchar_t str[]); |
|
||||||
void SetDefaultValue (CmdArgData & arg); |
|
||||||
bool TokenizeFlags (CmdTokState * state, const wchar_t str[]); |
|
||||||
|
|
||||||
public: |
|
||||||
CICmdParser (const CmdArgDef def[], unsigned defCount); |
|
||||||
bool CheckAllRequiredArguments (CmdTokState * state); |
|
||||||
const CmdArgData * FindArgById (unsigned id) const; |
|
||||||
const CmdArgData * FindArgByName (const wchar_t name[]) const; |
|
||||||
bool Tokenize (CmdTokState * state, const wchar_t str[]); |
|
||||||
|
|
||||||
}; |
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
|
||||||
* |
|
||||||
* CICmdParser implementation |
|
||||||
* |
|
||||||
***/ |
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
bool CICmdParser::CheckFlag (unsigned flags, unsigned flag, unsigned mask) const { |
|
||||||
return ((flags & mask) == flag); |
|
||||||
} |
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
bool CICmdParser::CheckAllRequiredArguments (CmdTokState * state) { |
|
||||||
bool result = (state->unflaggedIndex >= m_requiredCount); |
|
||||||
if (!result) |
|
||||||
Error(state, kCmdErrorTooFewArgs, nil, nil); |
|
||||||
return result; |
|
||||||
} |
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
CICmdParser::CICmdParser (const CmdArgDef def[], unsigned defCount) { |
|
||||||
unsigned loop; |
|
||||||
|
|
||||||
// Save the argument definitions
|
|
||||||
unsigned maxId = 0; |
|
||||||
unsigned unflaggedCount = 0; |
|
||||||
m_argArray.SetCount(defCount); |
|
||||||
for (loop = 0; loop < defCount; ++loop) { |
|
||||||
|
|
||||||
// Check whether this argument is flagged
|
|
||||||
bool flagged = CheckFlag(def[loop].flags, kCmdArgFlagged, kCmdMaskArg); |
|
||||||
|
|
||||||
// Disallow names on unflagged arguments
|
|
||||||
ASSERT(flagged || !def[loop].name); |
|
||||||
|
|
||||||
// Store the argument data
|
|
||||||
CmdArgData & arg = m_argArray[loop]; |
|
||||||
arg.def = def[loop]; |
|
||||||
arg.buffer = nil; |
|
||||||
arg.nameChars = def[loop].name ? StrLen(def[loop].name) : 0; |
|
||||||
arg.isSpecified = false; |
|
||||||
SetDefaultValue(arg); |
|
||||||
maxId = std::max(maxId, def[loop].id); |
|
||||||
|
|
||||||
// Track the number of unflagged arguments
|
|
||||||
if (!flagged) |
|
||||||
++unflaggedCount; |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
// Build the id lookup table
|
|
||||||
unsigned idTableSize = std::min(maxId + 1, defCount * 2); |
|
||||||
m_idLookupArray.SetCount(idTableSize); |
|
||||||
m_idLookupArray.Zero(); |
|
||||||
for (loop = 0; loop < defCount; ++loop) |
|
||||||
if (def[loop].id < idTableSize) |
|
||||||
m_idLookupArray[def[loop].id] = loop; |
|
||||||
|
|
||||||
// Build the unflagged array
|
|
||||||
unsigned unflaggedIndex = 0; |
|
||||||
m_unflaggedArray.SetCount(unflaggedCount); |
|
||||||
for (loop = 0; loop < defCount; ++loop) |
|
||||||
if (CheckFlag(def[loop].flags, kCmdArgRequired, kCmdMaskArg)) |
|
||||||
m_unflaggedArray[unflaggedIndex++] = loop; |
|
||||||
m_requiredCount = unflaggedIndex; |
|
||||||
for (loop = 0; loop < defCount; ++loop) |
|
||||||
if (!(CheckFlag(def[loop].flags, kCmdArgFlagged, kCmdMaskArg) || |
|
||||||
CheckFlag(def[loop].flags, kCmdArgRequired, kCmdMaskArg))) |
|
||||||
m_unflaggedArray[unflaggedIndex++] = loop; |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
void CICmdParser::Error (const CmdTokState * state, ECmdError errorCode, const wchar_t arg[], const wchar_t value[]) const { |
|
||||||
|
|
||||||
// Compose the error text
|
|
||||||
// (This text is only provided as a shortcut for trivial applications that
|
|
||||||
// don't want to compose their own text. Normally, an application would
|
|
||||||
// compose error text using its own localized strings.)
|
|
||||||
unsigned chars = 256 + (arg ? StrLen(arg) : 0) + (value ? StrLen(value) : 0); |
|
||||||
wchar_t * buffer = (wchar_t *)malloc(chars * sizeof(wchar_t)); |
|
||||||
switch (errorCode) { |
|
||||||
|
|
||||||
case kCmdErrorInvalidArg: |
|
||||||
StrPrintf(buffer, chars, L"Invalid argument: %s", arg); |
|
||||||
break; |
|
||||||
|
|
||||||
case kCmdErrorInvalidValue: |
|
||||||
StrPrintf(buffer, chars, L"Argument %s invalid value: %s", arg, value); |
|
||||||
break; |
|
||||||
|
|
||||||
case kCmdErrorTooFewArgs: |
|
||||||
StrPrintf(buffer, chars, L"Too few arguments"); |
|
||||||
break; |
|
||||||
|
|
||||||
case kCmdErrorTooManyArgs: |
|
||||||
StrPrintf(buffer, chars, L"Too many arguments: %s", arg); |
|
||||||
break; |
|
||||||
|
|
||||||
DEFAULT_FATAL(errorCode); |
|
||||||
} |
|
||||||
|
|
||||||
// Call the error handler
|
|
||||||
state->parser->OnError(buffer, errorCode, arg, value); |
|
||||||
|
|
||||||
// Free memory
|
|
||||||
free(buffer); |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
const CmdArgData * CICmdParser::FindArgById (unsigned id) const { |
|
||||||
|
|
||||||
// Search for the argument with this id
|
|
||||||
unsigned index; |
|
||||||
if (id < m_idLookupArray.Count()) |
|
||||||
index = m_idLookupArray[id]; |
|
||||||
else |
|
||||||
for (index = 0; index < m_argArray.Count(); ++index) |
|
||||||
if (m_argArray[index].def.id == id) |
|
||||||
break; |
|
||||||
|
|
||||||
// Verify that we found the correct argument
|
|
||||||
if ( (index >= m_argArray.Count()) || |
|
||||||
(m_argArray[index].def.id != id) ) |
|
||||||
return nil; |
|
||||||
|
|
||||||
// Return the argument data
|
|
||||||
return &m_argArray[index]; |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
const CmdArgData * CICmdParser::FindArgByName (const wchar_t name[]) const { |
|
||||||
|
|
||||||
// Search for an argument with this name
|
|
||||||
unsigned index = (unsigned)-1; |
|
||||||
if (!LookupFlagged(&name, &index)) |
|
||||||
return nil; |
|
||||||
|
|
||||||
// Return the argument data
|
|
||||||
return &m_argArray[index]; |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
bool CICmdParser::LookupFlagged (const wchar_t ** name, unsigned * lastIndex) const { |
|
||||||
unsigned argCount = m_argArray.Count(); |
|
||||||
unsigned chars = StrLen(*name); |
|
||||||
unsigned bestIndex = (unsigned)-1; |
|
||||||
unsigned bestChars = 0; |
|
||||||
|
|
||||||
// Check whether this argument is a suffix to any previously
|
|
||||||
// provided prefix in this token
|
|
||||||
for (unsigned prevChars = (*lastIndex != (unsigned)-1) ? m_argArray[*lastIndex].nameChars : 0; |
|
||||||
(prevChars != (unsigned)-1) && !bestChars; |
|
||||||
--prevChars) { |
|
||||||
const CmdArgData & prev = prevChars ? m_argArray[*lastIndex] : *(const CmdArgData *)nil; |
|
||||||
|
|
||||||
// Find this argument in the list
|
|
||||||
for (unsigned index = 0; index < argCount; ++index) { |
|
||||||
const CmdArgData & arg = m_argArray[index]; |
|
||||||
|
|
||||||
// Ignore non-flagged arguments
|
|
||||||
if (!CheckFlag(arg.def.flags, kCmdArgFlagged, kCmdMaskArg)) |
|
||||||
continue; |
|
||||||
|
|
||||||
// Ignore this argument if it wouldn't beat the previous best match
|
|
||||||
if (arg.nameChars < bestChars + prevChars) |
|
||||||
continue; |
|
||||||
|
|
||||||
// Ignore this argument if it doesn't match the prefix
|
|
||||||
bool caseSensitive = CheckFlag(arg.def.flags, kCmdCaseSensitive, kCmdCaseSensitive); |
|
||||||
if ( prevChars && |
|
||||||
( (prevChars >= arg.nameChars) || |
|
||||||
( caseSensitive && StrCmp(arg.def.name, prev.def.name, prevChars)) || |
|
||||||
(!caseSensitive && StrCmpI(arg.def.name, prev.def.name, prevChars)) ) ) |
|
||||||
continue; |
|
||||||
|
|
||||||
// Ignore this argument if it doesn't match the suffix
|
|
||||||
if ( ( caseSensitive && StrCmp(*name, arg.def.name + prevChars, arg.nameChars - prevChars)) || |
|
||||||
(!caseSensitive && StrCmpI(*name, arg.def.name + prevChars, arg.nameChars - prevChars)) ) |
|
||||||
continue; |
|
||||||
|
|
||||||
// Track the best match
|
|
||||||
bestIndex = index; |
|
||||||
bestChars = arg.nameChars - prevChars; |
|
||||||
if (bestChars == chars) |
|
||||||
break; |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
// Return the result
|
|
||||||
*name += bestChars; |
|
||||||
*lastIndex = bestIndex; |
|
||||||
return (bestChars != 0); |
|
||||||
} |
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
bool CICmdParser::ProcessValue (CmdTokState * state, unsigned index, const wchar_t str[]) { |
|
||||||
CmdArgData & arg = m_argArray[index]; |
|
||||||
arg.isSpecified = true; |
|
||||||
unsigned argType = arg.def.flags & kCmdMaskType; |
|
||||||
switch (argType) { |
|
||||||
|
|
||||||
case kCmdTypeBool: |
|
||||||
if (*str == '+') |
|
||||||
arg.val.boolVal = true; |
|
||||||
else if (*str == '-') |
|
||||||
arg.val.boolVal = false; |
|
||||||
else if (!*str) |
|
||||||
arg.val.boolVal = CheckFlag(arg.def.flags, kCmdBoolSet, kCmdMaskBool); |
|
||||||
else |
|
||||||
Error(state, kCmdErrorInvalidValue, arg.def.name, str); |
|
||||||
break; |
|
||||||
|
|
||||||
case kCmdTypeFloat: |
|
||||||
{ |
|
||||||
const wchar_t * endPtr; |
|
||||||
arg.val.floatVal = StrToFloat(str, &endPtr); |
|
||||||
if (*endPtr) |
|
||||||
Error(state, kCmdErrorInvalidValue, arg.def.name, str); |
|
||||||
} |
|
||||||
break; |
|
||||||
|
|
||||||
case kCmdTypeInt: |
|
||||||
{ |
|
||||||
const wchar_t * endPtr; |
|
||||||
arg.val.intVal = StrToInt(str, &endPtr); |
|
||||||
if (*endPtr) |
|
||||||
Error(state, kCmdErrorInvalidValue, arg.def.name, str); |
|
||||||
} |
|
||||||
break; |
|
||||||
|
|
||||||
case kCmdTypeString: |
|
||||||
if (arg.buffer) |
|
||||||
free(arg.buffer); |
|
||||||
arg.buffer = StrDup(str); |
|
||||||
arg.val.strVal = arg.buffer; |
|
||||||
break; |
|
||||||
|
|
||||||
case kCmdTypeUnsigned: |
|
||||||
{ |
|
||||||
const wchar_t * endPtr; |
|
||||||
arg.val.unsignedVal = StrToUnsigned(str, &endPtr, 10); |
|
||||||
if (*endPtr) |
|
||||||
Error(state, kCmdErrorInvalidValue, arg.def.name, str); |
|
||||||
} |
|
||||||
break; |
|
||||||
|
|
||||||
DEFAULT_FATAL(argType); |
|
||||||
|
|
||||||
} |
|
||||||
return true; |
|
||||||
} |
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
void CICmdParser::SetDefaultValue (CmdArgData & arg) { |
|
||||||
unsigned argType = arg.def.flags & kCmdMaskType; |
|
||||||
switch (argType) { |
|
||||||
|
|
||||||
case kCmdTypeBool: |
|
||||||
arg.val.boolVal = !CheckFlag(arg.def.flags, kCmdBoolSet, kCmdMaskBool); |
|
||||||
break; |
|
||||||
|
|
||||||
case kCmdTypeInt: |
|
||||||
arg.val.intVal = 0; |
|
||||||
break; |
|
||||||
|
|
||||||
case kCmdTypeUnsigned: |
|
||||||
arg.val.unsignedVal = 0; |
|
||||||
break; |
|
||||||
|
|
||||||
case kCmdTypeFloat: |
|
||||||
arg.val.floatVal = 0.0f; |
|
||||||
break; |
|
||||||
|
|
||||||
case kCmdTypeString: |
|
||||||
arg.val.strVal = L""; |
|
||||||
break; |
|
||||||
|
|
||||||
DEFAULT_FATAL(argType); |
|
||||||
|
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
bool CICmdParser::Tokenize (CmdTokState * state, const wchar_t str[]) { |
|
||||||
wchar_t buffer[kMaxTokenLength]; |
|
||||||
bool result = true; |
|
||||||
while (result && StrTokenize(&str, buffer, arrsize(buffer), WHITESPACE)) { |
|
||||||
|
|
||||||
// If the previous argument is awaiting a value, then use this token
|
|
||||||
// as the value
|
|
||||||
if (state->pendingIndex != (unsigned)-1) { |
|
||||||
result = ProcessValue(state, state->pendingIndex, buffer); |
|
||||||
state->pendingIndex = (unsigned)-1; |
|
||||||
continue; |
|
||||||
} |
|
||||||
|
|
||||||
// Identify and process flagged parameters
|
|
||||||
if (StrChr(FLAGS, buffer[0]) && TokenizeFlags(state, buffer)) |
|
||||||
continue; |
|
||||||
|
|
||||||
// Process unflagged parameters
|
|
||||||
if (state->unflaggedIndex < m_unflaggedArray.Count()) { |
|
||||||
result = ProcessValue(state, m_unflaggedArray[state->unflaggedIndex++], buffer); |
|
||||||
continue; |
|
||||||
} |
|
||||||
|
|
||||||
// Process extra parameters
|
|
||||||
if (state->parser->OnExtra(buffer)) |
|
||||||
continue; |
|
||||||
|
|
||||||
// Process invalid parameters
|
|
||||||
Error(state, kCmdErrorTooManyArgs, buffer, nil); |
|
||||||
result = false; |
|
||||||
break; |
|
||||||
|
|
||||||
} |
|
||||||
return result; |
|
||||||
} |
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
bool CICmdParser::TokenizeFlags (CmdTokState * state, const wchar_t str[]) { |
|
||||||
|
|
||||||
// Process each separately flagged token within the string
|
|
||||||
wchar_t buffer[kMaxTokenLength]; |
|
||||||
bool result = true; |
|
||||||
while (result && StrTokenize(&str, buffer, arrsize(buffer), ALL)) { |
|
||||||
if (!buffer[0]) |
|
||||||
continue; |
|
||||||
|
|
||||||
// Process each flag within the token
|
|
||||||
unsigned lastIndex = (unsigned)-1; |
|
||||||
const wchar_t * bufferPtr = buffer; |
|
||||||
while (result) { |
|
||||||
|
|
||||||
// Lookup the argument name
|
|
||||||
result = LookupFlagged(&bufferPtr, &lastIndex); |
|
||||||
if (!result) { |
|
||||||
Error(state, kCmdErrorInvalidArg, bufferPtr, nil); |
|
||||||
result = false; |
|
||||||
break; |
|
||||||
} |
|
||||||
|
|
||||||
// If this argument is boolean, allow it to share a common prefix
|
|
||||||
// with the next argument. In this case there is no place for
|
|
||||||
// the user to provide a value, so use the default value.
|
|
||||||
if (*bufferPtr &&
|
|
||||||
CheckFlag(m_argArray[lastIndex].def.flags, kCmdTypeBool, kCmdMaskType)) { |
|
||||||
result = ProcessValue(state, lastIndex, L""); |
|
||||||
continue; |
|
||||||
} |
|
||||||
|
|
||||||
break; |
|
||||||
} |
|
||||||
if (!result) |
|
||||||
break; |
|
||||||
|
|
||||||
// Check for an argument value provided using a separator
|
|
||||||
if (*str && StrChr(SEPARATORS, *str)) { |
|
||||||
result = ProcessValue(state, lastIndex, str + 1); |
|
||||||
break; |
|
||||||
} |
|
||||||
|
|
||||||
// Process values for boolean arguments
|
|
||||||
if (CheckFlag(m_argArray[lastIndex].def.flags, kCmdTypeBool, kCmdMaskType)) { |
|
||||||
|
|
||||||
// Check for a value provided with a toggle
|
|
||||||
if (*str && StrChr(TOGGLES, *str)) { |
|
||||||
wchar_t tempStr[] = {*str, 0}; |
|
||||||
result = ProcessValue(state, lastIndex, tempStr); |
|
||||||
++str; |
|
||||||
continue; |
|
||||||
} |
|
||||||
|
|
||||||
// Check for a default value
|
|
||||||
else { |
|
||||||
result = ProcessValue(state, lastIndex, L""); |
|
||||||
continue; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
// Process values for non-boolean arguments
|
|
||||||
else { |
|
||||||
|
|
||||||
// Check for an argument value immediately following the name
|
|
||||||
if (*bufferPtr) { |
|
||||||
result = ProcessValue(state, lastIndex, bufferPtr); |
|
||||||
break; |
|
||||||
} |
|
||||||
|
|
||||||
// Check for an argument value in the next token
|
|
||||||
else { |
|
||||||
state->pendingIndex = lastIndex; |
|
||||||
break; |
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
|
|
||||||
} |
|
||||||
return result; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
|
||||||
* |
|
||||||
* CCmdParser implementation |
|
||||||
* |
|
||||||
***/ |
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
CCmdParser::CCmdParser () { |
|
||||||
fParser = nil; |
|
||||||
} |
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
CCmdParser::CCmdParser (const CmdArgDef def[], unsigned defCount) { |
|
||||||
Initialize(def, defCount); |
|
||||||
} |
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
CCmdParser::~CCmdParser () { |
|
||||||
delete fParser; |
|
||||||
} |
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
bool CCmdParser::GetBool (unsigned id) const { |
|
||||||
return fParser->FindArgById(id)->val.boolVal; |
|
||||||
} |
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
bool CCmdParser::GetBool (const wchar_t name[]) const { |
|
||||||
return fParser->FindArgByName(name)->val.boolVal; |
|
||||||
} |
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
float CCmdParser::GetFloat (unsigned id) const { |
|
||||||
return fParser->FindArgById(id)->val.floatVal; |
|
||||||
} |
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
float CCmdParser::GetFloat (const wchar_t name[]) const { |
|
||||||
return fParser->FindArgByName(name)->val.floatVal; |
|
||||||
} |
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
int CCmdParser::GetInt (unsigned id) const { |
|
||||||
return fParser->FindArgById(id)->val.intVal; |
|
||||||
} |
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
int CCmdParser::GetInt (const wchar_t name[]) const { |
|
||||||
return fParser->FindArgByName(name)->val.intVal; |
|
||||||
} |
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
const wchar_t * CCmdParser::GetString (unsigned id) const { |
|
||||||
return fParser->FindArgById(id)->val.strVal; |
|
||||||
} |
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
const wchar_t * CCmdParser::GetString (const wchar_t name[]) const { |
|
||||||
return fParser->FindArgByName(name)->val.strVal; |
|
||||||
} |
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
unsigned CCmdParser::GetUnsigned (unsigned id) const { |
|
||||||
return fParser->FindArgById(id)->val.unsignedVal; |
|
||||||
} |
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
unsigned CCmdParser::GetUnsigned (const wchar_t name[]) const { |
|
||||||
return fParser->FindArgByName(name)->val.unsignedVal; |
|
||||||
} |
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
void CCmdParser::Initialize (const CmdArgDef def[], unsigned defCount) { |
|
||||||
fParser = new CICmdParser(def, defCount); |
|
||||||
} |
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
bool CCmdParser::IsSpecified (unsigned id) const { |
|
||||||
if (const CmdArgData * data = fParser->FindArgById(id)) |
|
||||||
return data->isSpecified; |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
bool CCmdParser::IsSpecified (const wchar_t name[]) const { |
|
||||||
if (const CmdArgData * data = fParser->FindArgByName(name)) |
|
||||||
return data->isSpecified; |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
void CCmdParser::OnError (const wchar_t str[], ECmdError errorCode, const wchar_t arg[], const wchar_t value[]) { |
|
||||||
} |
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
bool CCmdParser::OnExtra (const wchar_t str[]) { |
|
||||||
return false; |
|
||||||
} |
|
||||||
|
|
||||||
//===========================================================================
|
|
||||||
bool CCmdParser::Parse (const wchar_t cmdLine[]) { |
|
||||||
// If no command line was passed, use the application's command line,
|
|
||||||
// skipping past the program name
|
|
||||||
if (!cmdLine) { |
|
||||||
cmdLine = AppGetCommandLine(); |
|
||||||
StrTokenize(&cmdLine, nil, 0, WHITESPACE); |
|
||||||
while (*cmdLine == L' ') |
|
||||||
++cmdLine; |
|
||||||
} |
|
||||||
|
|
||||||
// Process the command line
|
|
||||||
CmdTokState state = { |
|
||||||
this, |
|
||||||
(unsigned)-1, // pending index
|
|
||||||
0 // unflagged index
|
|
||||||
}; |
|
||||||
bool result; |
|
||||||
result = fParser->Tokenize(&state, cmdLine); |
|
||||||
if (result) |
|
||||||
result = fParser->CheckAllRequiredArguments(&state); |
|
||||||
|
|
||||||
return result; |
|
||||||
} |
|
@ -1,136 +0,0 @@ |
|||||||
/*==LICENSE==*
|
|
||||||
|
|
||||||
CyanWorlds.com Engine - MMOG client, server and tools |
|
||||||
Copyright (C) 2011 Cyan Worlds, Inc. |
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify |
|
||||||
it under the terms of the GNU General Public License as published by |
|
||||||
the Free Software Foundation, either version 3 of the License, or |
|
||||||
(at your option) any later version. |
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful, |
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
GNU General Public License for more details. |
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License |
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
Additional permissions under GNU GPL version 3 section 7 |
|
||||||
|
|
||||||
If you modify this Program, or any covered work, by linking or |
|
||||||
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK, |
|
||||||
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent |
|
||||||
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK |
|
||||||
(or a modified version of those libraries), |
|
||||||
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA, |
|
||||||
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG |
|
||||||
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the |
|
||||||
licensors of this Program grant you additional |
|
||||||
permission to convey the resulting work. Corresponding Source for a |
|
||||||
non-source form of such a combination shall include the source code for |
|
||||||
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered |
|
||||||
work. |
|
||||||
|
|
||||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com |
|
||||||
or by snail mail at: |
|
||||||
Cyan Worlds, Inc. |
|
||||||
14617 N Newport Hwy |
|
||||||
Mead, WA 99021 |
|
||||||
|
|
||||||
*==LICENSE==*/ |
|
||||||
/*****************************************************************************
|
|
||||||
* |
|
||||||
* $/Plasma20/Sources/Plasma/NucleusLib/pnUtils/Private/pnUtCmd.h |
|
||||||
*
|
|
||||||
***/ |
|
||||||
|
|
||||||
#ifndef PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNUTILS_PRIVATE_PNUTCMD_H |
|
||||||
#define PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNUTILS_PRIVATE_PNUTCMD_H |
|
||||||
|
|
||||||
#include "Pch.h" |
|
||||||
#include "pnUtArray.h" |
|
||||||
#include "pnUtStr.h" |
|
||||||
|
|
||||||
/*****************************************************************************
|
|
||||||
* |
|
||||||
* Constants |
|
||||||
* |
|
||||||
***/ |
|
||||||
|
|
||||||
// Sets of mutually exclusive flags
|
|
||||||
const unsigned kCmdArgFlagged = 0x0 << 0; // default
|
|
||||||
const unsigned kCmdArgOptional = 0x1 << 0; |
|
||||||
const unsigned kCmdArgRequired = 0x2 << 0; |
|
||||||
const unsigned kCmdMaskArg = 0xf << 0; |
|
||||||
|
|
||||||
const unsigned kCmdTypeBool = 0x0 << 4; // default
|
|
||||||
const unsigned kCmdTypeInt = 0x1 << 4; |
|
||||||
const unsigned kCmdTypeUnsigned = 0x2 << 4; |
|
||||||
const unsigned kCmdTypeFloat = 0x3 << 4; |
|
||||||
const unsigned kCmdTypeString = 0x4 << 4; |
|
||||||
const unsigned kCmdMaskType = 0xf << 4; |
|
||||||
|
|
||||||
const unsigned kCmdBoolSet = 0x0 << 8; // default
|
|
||||||
const unsigned kCmdBoolUnset = 0x1 << 8; |
|
||||||
const unsigned kCmdMaskBool = 0xf << 8; |
|
||||||
|
|
||||||
// Other flags
|
|
||||||
const unsigned kCmdCaseSensitive = 0x1 << 28; |
|
||||||
|
|
||||||
|
|
||||||
// Error codes
|
|
||||||
enum ECmdError { |
|
||||||
kCmdErrorInvalidArg, |
|
||||||
kCmdErrorInvalidValue, |
|
||||||
kCmdErrorTooFewArgs, |
|
||||||
kCmdErrorTooManyArgs, |
|
||||||
kNumCmdErrors |
|
||||||
}; |
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
|
||||||
* |
|
||||||
* Types |
|
||||||
* |
|
||||||
***/ |
|
||||||
|
|
||||||
struct CmdArgDef { |
|
||||||
unsigned flags; |
|
||||||
const wchar_t * name; // must be compile-time constant
|
|
||||||
unsigned id; |
|
||||||
}; |
|
||||||
|
|
||||||
class CCmdParser { |
|
||||||
class CICmdParser * fParser; |
|
||||||
|
|
||||||
static void DispatchError (const wchar_t str[], ECmdError errorCode, const wchar_t arg[], const wchar_t value[], void * param); |
|
||||||
static bool DispatchExtra (const wchar_t str[], void * param); |
|
||||||
|
|
||||||
protected: |
|
||||||
CCmdParser (); |
|
||||||
void Initialize (const CmdArgDef def[], unsigned defCount); |
|
||||||
|
|
||||||
public: |
|
||||||
CCmdParser (const CmdArgDef def[], unsigned defCount); |
|
||||||
virtual ~CCmdParser (); |
|
||||||
|
|
||||||
bool GetBool (unsigned id) const; |
|
||||||
bool GetBool (const wchar_t name[]) const; |
|
||||||
float GetFloat (unsigned id) const; |
|
||||||
float GetFloat (const wchar_t name[]) const; |
|
||||||
int GetInt (unsigned id) const; |
|
||||||
int GetInt (const wchar_t name[]) const; |
|
||||||
const wchar_t * GetString (unsigned id) const; |
|
||||||
const wchar_t * GetString (const wchar_t name[]) const; |
|
||||||
unsigned GetUnsigned (unsigned id) const; |
|
||||||
unsigned GetUnsigned (const wchar_t name[]) const; |
|
||||||
bool IsSpecified (unsigned id) const; |
|
||||||
bool IsSpecified (const wchar_t name[]) const; |
|
||||||
|
|
||||||
virtual void OnError (const wchar_t str[], ECmdError errorCode, const wchar_t arg[], const wchar_t value[]); |
|
||||||
virtual bool OnExtra (const wchar_t str[]); |
|
||||||
|
|
||||||
bool Parse (const wchar_t cmdLine[] = nil); |
|
||||||
}; |
|
||||||
#endif |
|
@ -1,91 +0,0 @@ |
|||||||
/*==LICENSE==*
|
|
||||||
|
|
||||||
CyanWorlds.com Engine - MMOG client, server and tools |
|
||||||
Copyright (C) 2011 Cyan Worlds, Inc. |
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify |
|
||||||
it under the terms of the GNU General Public License as published by |
|
||||||
the Free Software Foundation, either version 3 of the License, or |
|
||||||
(at your option) any later version. |
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful, |
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
GNU General Public License for more details. |
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License |
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
Additional permissions under GNU GPL version 3 section 7 |
|
||||||
|
|
||||||
If you modify this Program, or any covered work, by linking or |
|
||||||
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK, |
|
||||||
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent |
|
||||||
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK |
|
||||||
(or a modified version of those libraries), |
|
||||||
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA, |
|
||||||
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG |
|
||||||
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the |
|
||||||
licensors of this Program grant you additional |
|
||||||
permission to convey the resulting work. Corresponding Source for a |
|
||||||
non-source form of such a combination shall include the source code for |
|
||||||
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered |
|
||||||
work. |
|
||||||
|
|
||||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com |
|
||||||
or by snail mail at: |
|
||||||
Cyan Worlds, Inc. |
|
||||||
14617 N Newport Hwy |
|
||||||
Mead, WA 99021 |
|
||||||
|
|
||||||
*==LICENSE==*/ |
|
||||||
/*****************************************************************************
|
|
||||||
* |
|
||||||
* $/Plasma20/Sources/Plasma/NucleusLib/pnUtils/Private/pnUtMisc.cpp |
|
||||||
*
|
|
||||||
***/ |
|
||||||
|
|
||||||
#include "pnUtMisc.h" |
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
|
||||||
* |
|
||||||
* Private data |
|
||||||
* |
|
||||||
***/ |
|
||||||
|
|
||||||
static void * s_moduleInstance; |
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
|
||||||
* |
|
||||||
* Public functions |
|
||||||
* |
|
||||||
***/ |
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void ModuleSetInstance (void * instance) { |
|
||||||
s_moduleInstance = instance; |
|
||||||
} |
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
void * ModuleGetInstance () { |
|
||||||
return s_moduleInstance; |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
|
||||||
* |
|
||||||
* Dll initialization |
|
||||||
* |
|
||||||
***/ |
|
||||||
|
|
||||||
//============================================================================
|
|
||||||
#if HS_BUILD_FOR_WIN32 |
|
||||||
BOOL WINAPI PreDllMain (HANDLE handle, DWORD reason, LPVOID) { |
|
||||||
if (reason == DLL_PROCESS_ATTACH) { |
|
||||||
ModuleSetInstance(handle); |
|
||||||
} |
|
||||||
return true; |
|
||||||
} |
|
||||||
#endif |
|
@ -1,72 +0,0 @@ |
|||||||
/*==LICENSE==*
|
|
||||||
|
|
||||||
CyanWorlds.com Engine - MMOG client, server and tools |
|
||||||
Copyright (C) 2011 Cyan Worlds, Inc. |
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify |
|
||||||
it under the terms of the GNU General Public License as published by |
|
||||||
the Free Software Foundation, either version 3 of the License, or |
|
||||||
(at your option) any later version. |
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful, |
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
||||||
GNU General Public License for more details. |
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License |
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
Additional permissions under GNU GPL version 3 section 7 |
|
||||||
|
|
||||||
If you modify this Program, or any covered work, by linking or |
|
||||||
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK, |
|
||||||
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent |
|
||||||
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK |
|
||||||
(or a modified version of those libraries), |
|
||||||
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA, |
|
||||||
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG |
|
||||||
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the |
|
||||||
licensors of this Program grant you additional |
|
||||||
permission to convey the resulting work. Corresponding Source for a |
|
||||||
non-source form of such a combination shall include the source code for |
|
||||||
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered |
|
||||||
work. |
|
||||||
|
|
||||||
You can contact Cyan Worlds, Inc. by email legal@cyan.com |
|
||||||
or by snail mail at: |
|
||||||
Cyan Worlds, Inc. |
|
||||||
14617 N Newport Hwy |
|
||||||
Mead, WA 99021 |
|
||||||
|
|
||||||
*==LICENSE==*/ |
|
||||||
/*****************************************************************************
|
|
||||||
* |
|
||||||
* $/Plasma20/Sources/Plasma/NucleusLib/pnUtils/Private/pnUtMisc.h |
|
||||||
*
|
|
||||||
***/ |
|
||||||
|
|
||||||
#ifndef PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNUTILS_PRIVATE_PNUTMISC_H |
|
||||||
#define PLASMA20_SOURCES_PLASMA_NUCLEUSLIB_PNUTILS_PRIVATE_PNUTMISC_H |
|
||||||
|
|
||||||
#include "Pch.h" |
|
||||||
#include "pnUtArray.h" |
|
||||||
|
|
||||||
/*****************************************************************************
|
|
||||||
* |
|
||||||
* Module instance functions |
|
||||||
* |
|
||||||
***/ |
|
||||||
|
|
||||||
void ModuleSetInstance (void * instance); |
|
||||||
void * ModuleGetInstance (); |
|
||||||
|
|
||||||
|
|
||||||
/*****************************************************************************
|
|
||||||
* |
|
||||||
* Command line functions |
|
||||||
* |
|
||||||
***/ |
|
||||||
|
|
||||||
const wchar_t * AppGetCommandLine (); |
|
||||||
|
|
||||||
#endif |
|
@ -0,0 +1,547 @@ |
|||||||
|
/*==LICENSE==*
|
||||||
|
|
||||||
|
CyanWorlds.com Engine - MMOG client, server and tools |
||||||
|
Copyright (C) 2011 Cyan Worlds, Inc. |
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify |
||||||
|
it under the terms of the GNU General Public License as published by |
||||||
|
the Free Software Foundation, either version 3 of the License, or |
||||||
|
(at your option) any later version. |
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful, |
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||||
|
GNU General Public License for more details. |
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License |
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Additional permissions under GNU GPL version 3 section 7 |
||||||
|
|
||||||
|
If you modify this Program, or any covered work, by linking or |
||||||
|
combining it with any of RAD Game Tools Bink SDK, Autodesk 3ds Max SDK, |
||||||
|
NVIDIA PhysX SDK, Microsoft DirectX SDK, OpenSSL library, Independent |
||||||
|
JPEG Group JPEG library, Microsoft Windows Media SDK, or Apple QuickTime SDK |
||||||
|
(or a modified version of those libraries), |
||||||
|
containing parts covered by the terms of the Bink SDK EULA, 3ds Max EULA, |
||||||
|
PhysX SDK EULA, DirectX SDK EULA, OpenSSL and SSLeay licenses, IJG |
||||||
|
JPEG Library README, Windows Media SDK EULA, or QuickTime SDK EULA, the |
||||||
|
licensors of this Program grant you additional |
||||||
|
permission to convey the resulting work. Corresponding Source for a |
||||||
|
non-source form of such a combination shall include the source code for |
||||||
|
the parts of OpenSSL and IJG JPEG Library used as well as that of the covered |
||||||
|
work. |
||||||
|
|
||||||
|
You can contact Cyan Worlds, Inc. by email legal@cyan.com |
||||||
|
or by snail mail at: |
||||||
|
Cyan Worlds, Inc. |
||||||
|
14617 N Newport Hwy |
||||||
|
Mead, WA 99021 |
||||||
|
|
||||||
|
*==LICENSE==*/ |
||||||
|
|
||||||
|
#include <cstring> |
||||||
|
#include <gtest/gtest.h> |
||||||
|
#include "plCmdParser.h" |
||||||
|
|
||||||
|
TEST(plCmdParser, basic_parsing) |
||||||
|
{ |
||||||
|
const plCmdArgDef cmds[] = { |
||||||
|
{ kCmdArgRequired | kCmdTypeString, "path", 0} |
||||||
|
}; |
||||||
|
|
||||||
|
plCmdParser parser(cmds, arrsize(cmds)); |
||||||
|
bool success = parser.Parse("plCmdParser ~/.plasma/config.dat"); |
||||||
|
|
||||||
|
plString prog = parser.GetProgramName(); |
||||||
|
plString path = parser.GetString(0); |
||||||
|
|
||||||
|
EXPECT_EQ(success, true); |
||||||
|
EXPECT_STREQ(prog.c_str(), "plCmdParser"); |
||||||
|
EXPECT_STREQ(path.c_str(), "~/.plasma/config.dat"); |
||||||
|
EXPECT_EQ(parser.GetError(), kCmdErrorSuccess); |
||||||
|
} |
||||||
|
|
||||||
|
TEST(plCmdParser, argv_parsing) |
||||||
|
{ |
||||||
|
const plCmdArgDef cmds[] = { |
||||||
|
{ kCmdArgRequired | kCmdTypeString, "path", 0} |
||||||
|
}; |
||||||
|
|
||||||
|
plCmdParser parser(cmds, arrsize(cmds)); |
||||||
|
|
||||||
|
const char* args[] = {"plCmdParser", "~/.plasma/config.dat"}; |
||||||
|
int argc = 2; |
||||||
|
|
||||||
|
std::vector<plString> tokens(args, args+argc); |
||||||
|
|
||||||
|
bool success = parser.Parse(tokens); |
||||||
|
|
||||||
|
plString prog = parser.GetProgramName(); |
||||||
|
plString path = parser.GetString(0); |
||||||
|
|
||||||
|
EXPECT_EQ(success, true); |
||||||
|
EXPECT_STREQ(prog.c_str(), "plCmdParser"); |
||||||
|
EXPECT_STREQ(path.c_str(), "~/.plasma/config.dat"); |
||||||
|
EXPECT_EQ(parser.GetError(), kCmdErrorSuccess); |
||||||
|
} |
||||||
|
|
||||||
|
TEST(plCmdParser, argv_preserving_spaces) |
||||||
|
{ |
||||||
|
const plCmdArgDef cmds[] = { |
||||||
|
{ kCmdArgRequired | kCmdTypeString, "path", 0} |
||||||
|
}; |
||||||
|
|
||||||
|
plCmdParser parser(cmds, arrsize(cmds)); |
||||||
|
|
||||||
|
const char* args[] = {"plCmdParser", "~/.plasma/Uru Live/config.dat"}; |
||||||
|
int argc = 2; |
||||||
|
|
||||||
|
std::vector<plString> tokens(args, args+argc); |
||||||
|
|
||||||
|
bool success = parser.Parse(tokens); |
||||||
|
|
||||||
|
plString prog = parser.GetProgramName(); |
||||||
|
plString path = parser.GetString(0); |
||||||
|
|
||||||
|
EXPECT_EQ(success, true); |
||||||
|
EXPECT_STREQ(prog.c_str(), "plCmdParser"); |
||||||
|
EXPECT_STREQ(path.c_str(), "~/.plasma/Uru Live/config.dat"); |
||||||
|
EXPECT_EQ(parser.GetError(), kCmdErrorSuccess); |
||||||
|
} |
||||||
|
|
||||||
|
TEST(plCmdParser, wchar_argv_parsing) |
||||||
|
{ |
||||||
|
const plCmdArgDef cmds[] = { |
||||||
|
{ kCmdArgRequired | kCmdTypeString, "path", 0} |
||||||
|
}; |
||||||
|
|
||||||
|
plCmdParser parser(cmds, arrsize(cmds)); |
||||||
|
|
||||||
|
const wchar_t* args[] = {L"plCmdParser", L"~/.plasma/config.dat"}; |
||||||
|
int argc = 2; |
||||||
|
|
||||||
|
std::vector<plString> tokens(argc); |
||||||
|
for (int i = 0; i < argc; i++) { |
||||||
|
tokens.push_back(plString::FromWchar(args[i])); |
||||||
|
} |
||||||
|
|
||||||
|
bool success = parser.Parse(tokens); |
||||||
|
|
||||||
|
plString prog = parser.GetProgramName(); |
||||||
|
plString path = parser.GetString(0); |
||||||
|
|
||||||
|
EXPECT_EQ(success, true); |
||||||
|
EXPECT_STREQ(prog.c_str(), "plCmdParser"); |
||||||
|
EXPECT_STREQ(path.c_str(), "~/.plasma/config.dat"); |
||||||
|
EXPECT_EQ(parser.GetError(), kCmdErrorSuccess); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
TEST(plCmdParser, flagged_int) |
||||||
|
{ |
||||||
|
const plCmdArgDef cmds[] = { |
||||||
|
{ kCmdTypeInt, "size", 0} |
||||||
|
}; |
||||||
|
|
||||||
|
plCmdParser parser(cmds, arrsize(cmds)); |
||||||
|
parser.Parse("plCmdParser --size 5"); |
||||||
|
|
||||||
|
int32_t size = parser.GetInt(0); |
||||||
|
|
||||||
|
EXPECT_EQ(size, 5); |
||||||
|
} |
||||||
|
|
||||||
|
TEST(plCmdParser, flagged_int_short) |
||||||
|
{ |
||||||
|
const plCmdArgDef cmds[] = { |
||||||
|
{ kCmdTypeInt, "size", 0} |
||||||
|
}; |
||||||
|
|
||||||
|
plCmdParser parser(cmds, arrsize(cmds)); |
||||||
|
parser.Parse("plCmdParser -s 5"); |
||||||
|
|
||||||
|
int32_t size = parser.GetInt(0); |
||||||
|
|
||||||
|
EXPECT_EQ(size, 5); |
||||||
|
} |
||||||
|
|
||||||
|
TEST(plCmdParser, flagged_int_assign) |
||||||
|
{ |
||||||
|
const plCmdArgDef cmds[] = { |
||||||
|
{ kCmdTypeInt, "size", 0} |
||||||
|
}; |
||||||
|
|
||||||
|
plCmdParser parser(cmds, arrsize(cmds)); |
||||||
|
parser.Parse("plCmdParser --size=5"); |
||||||
|
|
||||||
|
int32_t size = parser.GetInt(0); |
||||||
|
|
||||||
|
EXPECT_EQ(size, 5); |
||||||
|
} |
||||||
|
|
||||||
|
TEST(plCmdParser, flagged_int_slash) |
||||||
|
{ |
||||||
|
const plCmdArgDef cmds[] = { |
||||||
|
{ kCmdTypeInt, "size", 0} |
||||||
|
}; |
||||||
|
|
||||||
|
plCmdParser parser(cmds, arrsize(cmds)); |
||||||
|
parser.Parse("plCmdParser /size -5"); |
||||||
|
|
||||||
|
int32_t size = parser.GetInt(0); |
||||||
|
|
||||||
|
EXPECT_EQ(size, -5); |
||||||
|
} |
||||||
|
|
||||||
|
TEST(plCmdParser, flagged_int_bystring) |
||||||
|
{ |
||||||
|
const plCmdArgDef cmds[] = { |
||||||
|
{ kCmdTypeInt, "size", 0} |
||||||
|
}; |
||||||
|
|
||||||
|
plCmdParser parser(cmds, arrsize(cmds)); |
||||||
|
parser.Parse("plCmdParser --size 5"); |
||||||
|
|
||||||
|
int32_t size = parser.GetInt("size"); |
||||||
|
|
||||||
|
EXPECT_EQ(size, 5); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
TEST(plCmdParser, flagged_uint) |
||||||
|
{ |
||||||
|
const plCmdArgDef cmds[] = { |
||||||
|
{ kCmdTypeUint, "size", 0} |
||||||
|
}; |
||||||
|
|
||||||
|
plCmdParser parser(cmds, arrsize(cmds)); |
||||||
|
parser.Parse("plCmdParser --size 5"); |
||||||
|
|
||||||
|
uint32_t size = parser.GetUint(0); |
||||||
|
|
||||||
|
EXPECT_EQ(size, 5); |
||||||
|
} |
||||||
|
|
||||||
|
TEST(plCmdParser, flagged_uint_bystring) |
||||||
|
{ |
||||||
|
const plCmdArgDef cmds[] = { |
||||||
|
{ kCmdTypeUint, "size", 0} |
||||||
|
}; |
||||||
|
|
||||||
|
plCmdParser parser(cmds, arrsize(cmds)); |
||||||
|
parser.Parse("plCmdParser --size 5"); |
||||||
|
|
||||||
|
uint32_t size = parser.GetUint("size"); |
||||||
|
|
||||||
|
EXPECT_EQ(size, 5); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
TEST(plCmdParser, flagged_float) |
||||||
|
{ |
||||||
|
const plCmdArgDef cmds[] = { |
||||||
|
{ kCmdTypeFloat, "volume", 0} |
||||||
|
}; |
||||||
|
|
||||||
|
plCmdParser parser(cmds, arrsize(cmds)); |
||||||
|
parser.Parse("plCmdParser --volume 0.5"); |
||||||
|
|
||||||
|
float vol = parser.GetFloat(0); |
||||||
|
|
||||||
|
EXPECT_EQ(vol, 0.5); |
||||||
|
} |
||||||
|
|
||||||
|
TEST(plCmdParser, flagged_float_bystring) |
||||||
|
{ |
||||||
|
const plCmdArgDef cmds[] = { |
||||||
|
{ kCmdTypeFloat, "volume", 0} |
||||||
|
}; |
||||||
|
|
||||||
|
plCmdParser parser(cmds, arrsize(cmds)); |
||||||
|
parser.Parse("plCmdParser --volume 0.5"); |
||||||
|
|
||||||
|
float vol = parser.GetFloat("volume"); |
||||||
|
|
||||||
|
EXPECT_EQ(vol, 0.5); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
TEST(plCmdParser, flagged_string) |
||||||
|
{ |
||||||
|
const plCmdArgDef cmds[] = { |
||||||
|
{ kCmdTypeString, "path", 0} |
||||||
|
}; |
||||||
|
|
||||||
|
plCmdParser parser(cmds, arrsize(cmds)); |
||||||
|
parser.Parse("plCmdParser --path foo"); |
||||||
|
|
||||||
|
plString path = parser.GetString(0); |
||||||
|
|
||||||
|
EXPECT_STREQ(path.c_str(), "foo"); |
||||||
|
} |
||||||
|
|
||||||
|
TEST(plCmdParser, flagged_string_bystring) |
||||||
|
{ |
||||||
|
const plCmdArgDef cmds[] = { |
||||||
|
{ kCmdTypeString, "path", 0} |
||||||
|
}; |
||||||
|
|
||||||
|
plCmdParser parser(cmds, arrsize(cmds)); |
||||||
|
parser.Parse("plCmdParser --path foo"); |
||||||
|
|
||||||
|
plString path = parser.GetString("path"); |
||||||
|
|
||||||
|
EXPECT_STREQ(path.c_str(), "foo"); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
TEST(plCmdParser, flagged_bool_default) |
||||||
|
{ |
||||||
|
const plCmdArgDef cmds[] = { |
||||||
|
{ kCmdTypeBool, "verbose", 0} |
||||||
|
}; |
||||||
|
|
||||||
|
plCmdParser parser(cmds, arrsize(cmds)); |
||||||
|
parser.Parse("plCmdParser --verbose"); |
||||||
|
|
||||||
|
bool verbose = parser.GetBool(0); |
||||||
|
|
||||||
|
EXPECT_EQ(verbose, true); |
||||||
|
} |
||||||
|
|
||||||
|
TEST(plCmdParser, flagged_bool_true) |
||||||
|
{ |
||||||
|
const plCmdArgDef cmds[] = { |
||||||
|
{ kCmdTypeBool, "verbose", 0} |
||||||
|
}; |
||||||
|
|
||||||
|
plCmdParser parser(cmds, arrsize(cmds)); |
||||||
|
parser.Parse("plCmdParser --verbose=TRUE"); |
||||||
|
|
||||||
|
bool verbose = parser.GetBool(0); |
||||||
|
|
||||||
|
EXPECT_EQ(verbose, true); |
||||||
|
} |
||||||
|
|
||||||
|
TEST(plCmdParser, flagged_bool_false) |
||||||
|
{ |
||||||
|
const plCmdArgDef cmds[] = { |
||||||
|
{ kCmdTypeBool, "verbose", 0} |
||||||
|
}; |
||||||
|
|
||||||
|
plCmdParser parser(cmds, arrsize(cmds)); |
||||||
|
parser.Parse("plCmdParser --verbose=FALSE"); |
||||||
|
|
||||||
|
bool verbose = parser.GetBool(0); |
||||||
|
|
||||||
|
EXPECT_EQ(verbose, false); |
||||||
|
} |
||||||
|
|
||||||
|
TEST(plCmdParser, flagged_bool_invalid) |
||||||
|
{ |
||||||
|
const plCmdArgDef cmds[] = { |
||||||
|
{ kCmdTypeBool, "verbose", 0} |
||||||
|
}; |
||||||
|
|
||||||
|
plCmdParser parser(cmds, arrsize(cmds)); |
||||||
|
parser.Parse("plCmdParser --verbose=foo"); |
||||||
|
|
||||||
|
bool verbose = parser.GetBool(0); |
||||||
|
|
||||||
|
EXPECT_EQ(verbose, false); |
||||||
|
EXPECT_EQ(parser.GetError(), kCmdErrorInvalidValue); |
||||||
|
} |
||||||
|
|
||||||
|
TEST(plCmdParser, flagged_bool_bystring) |
||||||
|
{ |
||||||
|
const plCmdArgDef cmds[] = { |
||||||
|
{ kCmdTypeBool, "verbose", 0} |
||||||
|
}; |
||||||
|
|
||||||
|
plCmdParser parser(cmds, arrsize(cmds)); |
||||||
|
parser.Parse("plCmdParser --verbose"); |
||||||
|
|
||||||
|
bool verbose = parser.GetBool("verbose"); |
||||||
|
|
||||||
|
EXPECT_EQ(verbose, true); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
TEST(plCmdParser, optional_unspecified) |
||||||
|
{ |
||||||
|
const plCmdArgDef cmds[] = { |
||||||
|
{ kCmdTypeInt | kCmdArgOptional, "speed", 0} |
||||||
|
}; |
||||||
|
|
||||||
|
plCmdParser parser(cmds, arrsize(cmds)); |
||||||
|
parser.Parse("plCmdParser"); |
||||||
|
|
||||||
|
bool specified = parser.IsSpecified(0); |
||||||
|
int32_t speed = parser.GetInt(0); |
||||||
|
|
||||||
|
EXPECT_EQ(specified, false); |
||||||
|
EXPECT_EQ(speed, 0); |
||||||
|
} |
||||||
|
|
||||||
|
TEST(plCmdParser, optional_specified) |
||||||
|
{ |
||||||
|
const plCmdArgDef cmds[] = { |
||||||
|
{ kCmdTypeInt | kCmdArgOptional, "speed", 0} |
||||||
|
}; |
||||||
|
|
||||||
|
plCmdParser parser(cmds, arrsize(cmds)); |
||||||
|
parser.Parse("plCmdParser 1"); |
||||||
|
|
||||||
|
bool specified = parser.IsSpecified(0); |
||||||
|
int32_t speed = parser.GetInt(0); |
||||||
|
|
||||||
|
EXPECT_EQ(specified, true); |
||||||
|
EXPECT_EQ(speed, 1); |
||||||
|
} |
||||||
|
|
||||||
|
TEST(plCmdParser, optional_specified_bystring) |
||||||
|
{ |
||||||
|
const plCmdArgDef cmds[] = { |
||||||
|
{ kCmdTypeInt | kCmdArgOptional, "speed", 0} |
||||||
|
}; |
||||||
|
|
||||||
|
plCmdParser parser(cmds, arrsize(cmds)); |
||||||
|
parser.Parse("plCmdParser 1"); |
||||||
|
|
||||||
|
bool specified = parser.IsSpecified("speed"); |
||||||
|
int32_t speed = parser.GetInt("speed"); |
||||||
|
|
||||||
|
EXPECT_EQ(specified, true); |
||||||
|
EXPECT_EQ(speed, 1); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
TEST(plCmdParser, specified_invalid) |
||||||
|
{ |
||||||
|
const plCmdArgDef cmds[] = { |
||||||
|
{ kCmdTypeInt | kCmdArgOptional, "speed", 0} |
||||||
|
}; |
||||||
|
|
||||||
|
plCmdParser parser(cmds, arrsize(cmds)); |
||||||
|
parser.Parse("plCmdParser 1"); |
||||||
|
|
||||||
|
bool specified = parser.IsSpecified(1); |
||||||
|
|
||||||
|
EXPECT_EQ(specified, false); |
||||||
|
} |
||||||
|
|
||||||
|
TEST(plCmdParser, specified_invalid_bystring) |
||||||
|
{ |
||||||
|
const plCmdArgDef cmds[] = { |
||||||
|
{ kCmdTypeInt | kCmdArgOptional, "speed", 0} |
||||||
|
}; |
||||||
|
|
||||||
|
plCmdParser parser(cmds, arrsize(cmds)); |
||||||
|
parser.Parse("plCmdParser 1"); |
||||||
|
|
||||||
|
bool specified = parser.IsSpecified("path"); |
||||||
|
|
||||||
|
EXPECT_EQ(specified, false); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
TEST(plCmdParser, flagged_weird_id) |
||||||
|
{ |
||||||
|
const plCmdArgDef cmds[] = { |
||||||
|
{ kCmdTypeInt, "size", 10} |
||||||
|
}; |
||||||
|
|
||||||
|
plCmdParser parser(cmds, arrsize(cmds)); |
||||||
|
parser.Parse("plCmdParser --size 5"); |
||||||
|
|
||||||
|
int32_t size = parser.GetInt(10); |
||||||
|
|
||||||
|
EXPECT_EQ(size, 5); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
TEST(plCmdParser, fake_flag) |
||||||
|
{ |
||||||
|
const plCmdArgDef cmds[] = { |
||||||
|
{ kCmdTypeInt, "size", 0} |
||||||
|
}; |
||||||
|
|
||||||
|
plCmdParser parser(cmds, arrsize(cmds)); |
||||||
|
bool success = parser.Parse("plCmdParser --speed 5"); |
||||||
|
|
||||||
|
EXPECT_EQ(success, false); |
||||||
|
EXPECT_EQ(parser.GetError(), kCmdErrorInvalidArg); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
TEST(plCmdParser, too_many_args) |
||||||
|
{ |
||||||
|
const plCmdArgDef cmds[] = { |
||||||
|
{ kCmdTypeInt, "size", 0} |
||||||
|
}; |
||||||
|
|
||||||
|
plCmdParser parser(cmds, arrsize(cmds)); |
||||||
|
bool success = parser.Parse("plCmdParser --size 10 foo"); |
||||||
|
|
||||||
|
EXPECT_EQ(success, false); |
||||||
|
EXPECT_EQ(parser.GetError(), kCmdErrorTooManyArgs); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
TEST(plCmdParser, missing_required) |
||||||
|
{ |
||||||
|
const plCmdArgDef cmds[] = { |
||||||
|
{ kCmdArgRequired | kCmdTypeString, "path", 0} |
||||||
|
}; |
||||||
|
|
||||||
|
plCmdParser parser(cmds, arrsize(cmds)); |
||||||
|
bool success = parser.Parse("plCmdParser"); |
||||||
|
|
||||||
|
EXPECT_EQ(success, false); |
||||||
|
EXPECT_EQ(parser.GetError(), kCmdErrorTooFewArgs); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
TEST(plCmdParser, combined_assign) |
||||||
|
{ |
||||||
|
const plCmdArgDef cmds[] = { |
||||||
|
{ kCmdTypeInt, "size", 0} |
||||||
|
}; |
||||||
|
|
||||||
|
plCmdParser parser(cmds, arrsize(cmds)); |
||||||
|
parser.Parse("plCmdParser --size5"); |
||||||
|
|
||||||
|
int32_t size = parser.GetInt(0); |
||||||
|
|
||||||
|
EXPECT_EQ(size, 5); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
TEST(plCmdParser, case_sensitive_nomatch) |
||||||
|
{ |
||||||
|
const plCmdArgDef cmds[] = { |
||||||
|
{ kCmdTypeInt | kCmdCaseSensitive, "Size", 0} |
||||||
|
}; |
||||||
|
|
||||||
|
plCmdParser parser(cmds, arrsize(cmds)); |
||||||
|
parser.Parse("plCmdParser -s 5"); |
||||||
|
|
||||||
|
bool specified = parser.IsSpecified(0); |
||||||
|
|
||||||
|
EXPECT_EQ(specified, false); |
||||||
|
} |
||||||
|
|
||||||
|
TEST(plCmdParser, case_sensitive_match) |
||||||
|
{ |
||||||
|
const plCmdArgDef cmds[] = { |
||||||
|
{ kCmdTypeInt | kCmdCaseSensitive, "Size", 0} |
||||||
|
}; |
||||||
|
|
||||||
|
plCmdParser parser(cmds, arrsize(cmds)); |
||||||
|
parser.Parse("plCmdParser -S 5"); |
||||||
|
|
||||||
|
bool specified = parser.IsSpecified(0); |
||||||
|
|
||||||
|
EXPECT_EQ(specified, true); |
||||||
|
} |
Loading…
Reference in new issue