Switch to full style
For C/C++ coders discussions and solutions
Post a reply

How to implement Command Line Parser in C++ Code

Sat Nov 08, 2008 11:36 pm

How to implement Command Line Parser in C++ Code:
.h file :
cpp code
// CmdLineParser.h: interface for the CCmdLineParser class.
//
// Copyright (c) Pavel Antonov, 2002
//
// This code is provided "as is", with absolutely no warranty expressed
// or implied. Any use is at your own risk.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_CMDLINEPARSER_H__BE51B7B0_4BC9_44F1_9B88_DF33BE4280DF__INCLUDED_)
#define AFX_CMDLINEPARSER_H__BE51B7B0_4BC9_44F1_9B88_DF33BE4280DF__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

typedef CString CCmdLineParser_String ;

#include <map>
using std::map;

// Example of strings
// /Key1 /Key2 -Key3:Val3 -Key4:"Val 4-with/spaces/and-delimeters" /Key5:Val5
// /Key:"" is equal to /Key: and is equal to /Key
// /Key is equal to -Key
// If getCaseSensitive is false (by default), all keys are made lowercase.

// Examples of use:
// CCmdLineParser parser(_T("/Key1 /Key2: -Key3:Val3 -Key4:\"Val 4-with/spaces/and-delimeters\" /Key5:Val5"));
// ASSERT(parser.HasKey("Key1") == true);
// ASSERT(parser.HasKey("Key10") == false);
// ASSERT(parser.HasVal("Key2") == false);
// parser.GetVal("Key1") -> []; (empty string)
// parser.GetVal("Key2") -> []; (empty string)
// parser.GetVal("Key3") -> [Val3];
// parser.GetVal("Key4") -> [Val 4-with/spaces/and-delimeters];
// CCmdLineParser::POSITION pos = parser.getFirst();
// CString sKey, sVal;
// while(!parser.isLast(pos)) {
// parser.getNext(pos, sKey, sVal);
// printf("Key: [%s], Val: [%s]");
// }


class CCmdLineParser {
public:
class CValsMap : public map<CCmdLineParser_String, CCmdLineParser_String> {};
typedef CValsMap::const_iterator POSITION;
public:
CCmdLineParser(LPCTSTR sCmdLine = NULL, bool bCaseSensitive = false);
virtual ~CCmdLineParser();

bool Parse(LPCTSTR sCmdLine);

LPCTSTR getCmdLine() const { return m_sCmdLine; }

void setCaseSensitive(bool bSensitive) { m_bCaseSensitive = bSensitive; }
bool getCaseSensitive() const { return m_bCaseSensitive; }

const CValsMap& getVals() const { return m_ValsMap; }

// Start iterating through keys and values
POSITION getFirst() const;
// Get next key-value pair, returns empty sKey if end reached
POSITION getNext(POSITION& pos, CCmdLineParser_String& sKey, CCmdLineParser_String& sValue) const;
// just helper ;)
bool isLast(POSITION& pos) const;

// TRUE if "Key" present in command line
bool HasKey(LPCTSTR sKey) const;
// Is "key" present in command line and have some value
bool HasVal(LPCTSTR sKey) const;
// Returns value if value was found or NULL otherwise
LPCTSTR GetVal(LPCTSTR sKey) const;
// Returns true if value was found
bool GetVal(LPCTSTR sKey, CCmdLineParser_String& sValue) const;

private:
CValsMap::const_iterator findKey(LPCTSTR sKey) const;
private:
CCmdLineParser_String m_sCmdLine;
CValsMap m_ValsMap;
bool m_bCaseSensitive;

static const TCHAR m_sDelimeters[];
static const TCHAR m_sValueSep[];
static const TCHAR m_sQuotes[];
};

#endif // !defined(AFX_CMDLINEPARSER_H__BE51B7B0_4BC9_44F1_9B88_DF33BE4280DF__INCLUDED_)

.CPP file :
cpp code
// CmdLineParser.cpp: implementation of the CCmdLineParser class.
//
// Copyright (c) Pavel Antonov, 2002
//
// This code is provided "as is", with absolutely no warranty expressed
// or implied. Any use is at your own risk.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "CmdLineParser.h"

const TCHAR CCmdLineParser::m_sDelimeters[] = _T("-/");
const TCHAR CCmdLineParser::m_sQuotes[] = _T("\""); // Can be _T("\"\'"), for instance
const TCHAR CCmdLineParser::m_sValueSep[] = _T(" :"); // Space MUST be in set

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CCmdLineParser::CCmdLineParser(LPCTSTR sCmdLine, bool bCaseSensitive)
: m_bCaseSensitive(bCaseSensitive)
{
if(sCmdLine) {
Parse(sCmdLine);
}
}

CCmdLineParser::~CCmdLineParser()
{
m_ValsMap.clear();
}

bool CCmdLineParser::Parse(LPCTSTR sCmdLine) {
if(!sCmdLine) return false;

m_sCmdLine = sCmdLine;
m_ValsMap.clear();
const CCmdLineParser_String sEmpty;

int nArgs = 0;
LPCTSTR sCurrent = sCmdLine;
while(true) {
// /Key:"arg"
if(_tcslen(sCurrent) == 0) { break; } // No data left
LPCTSTR sArg = _tcspbrk(sCurrent, m_sDelimeters);
if(!sArg) break; // No delimeters found
sArg = _tcsinc(sArg);
// Key:"arg"
if(_tcslen(sArg) == 0) break; // String ends with delimeter
LPCTSTR sVal = _tcspbrk(sArg, m_sValueSep);
if(sVal == NULL) { //Key ends command line
CCmdLineParser_String csKey(sArg);
if(!m_bCaseSensitive) {
csKey.MakeLower();
}
m_ValsMap.insert(CValsMap::value_type(csKey, sEmpty));
break;
} else if(sVal[0] == _T(' ') || _tcslen(sVal) == 1 ) { // Key with no value or cmdline ends with /Key:
CCmdLineParser_String csKey(sArg, sVal - sArg);
if(!csKey.IsEmpty()) { // Prevent /: case
if(!m_bCaseSensitive) {
csKey.MakeLower();
}
m_ValsMap.insert(CValsMap::value_type(csKey, sEmpty));
}
sCurrent = _tcsinc(sVal);
continue;
} else { // Key with value
CCmdLineParser_String csKey(sArg, sVal - sArg);
if(!m_bCaseSensitive) {
csKey.MakeLower();
}

sVal = _tcsinc(sVal);
// "arg"
LPCTSTR sQuote = _tcspbrk(sVal, m_sQuotes), sEndQuote(NULL);
if(sQuote == sVal) { // Quoted String
sQuote = _tcsinc(sVal);
sEndQuote = _tcspbrk(sQuote, m_sQuotes);
} else {
sQuote = sVal;
sEndQuote = _tcschr(sQuote, _T(' '));
}

if(sEndQuote == NULL) { // No end quotes or terminating space, take rest of string
CCmdLineParser_String csVal(sQuote);
if(!csKey.IsEmpty()) { // Prevent /:val case
m_ValsMap.insert(CValsMap::value_type(csKey, csVal));
}
break;
} else { // End quote or space present
if(!csKey.IsEmpty()) { // Prevent /:"val" case
CCmdLineParser_String csVal(sQuote, sEndQuote - sQuote);
m_ValsMap.insert(CValsMap::value_type(csKey, csVal));
}
sCurrent = _tcsinc(sEndQuote);
continue;
}
}

}

return (nArgs > 0);
}

CCmdLineParser::CValsMap::const_iterator CCmdLineParser::findKey(LPCTSTR sKey) const {
CCmdLineParser_String s(sKey);
if(!m_bCaseSensitive) {
s.MakeLower();
}
return m_ValsMap.find(s);
}
// TRUE if "Key" present in command line
bool CCmdLineParser::HasKey(LPCTSTR sKey) const {
CValsMap::const_iterator it = findKey(sKey);
if(it == m_ValsMap.end()) return false;
return true;
}

// Is "key" present in command line and have some value
bool CCmdLineParser::HasVal(LPCTSTR sKey) const {
CValsMap::const_iterator it = findKey(sKey);
if(it == m_ValsMap.end()) return false;
if(it->second.IsEmpty()) return false;
return true;
}
// Returns value if value was found or NULL otherwise
LPCTSTR CCmdLineParser::GetVal(LPCTSTR sKey) const {
CValsMap::const_iterator it = findKey(sKey);
if(it == m_ValsMap.end()) return false;
return LPCTSTR(it->second);
}
// Returns true if value was found
bool CCmdLineParser::GetVal(LPCTSTR sKey, CCmdLineParser_String& sValue) const {
CValsMap::const_iterator it = findKey(sKey);
if(it == m_ValsMap.end()) return false;
sValue = it->second;
return true;
}

CCmdLineParser::POSITION CCmdLineParser::getFirst() const {
return m_ValsMap.begin();
}
CCmdLineParser::POSITION CCmdLineParser::getNext(POSITION& pos, CCmdLineParser_String& sKey, CCmdLineParser_String& sValue) const {
if(isLast(pos)) {
sKey.Empty();
return pos;
} else {
sKey = pos->first;
sValue = pos->second;
pos ++;
return pos;
}
}
// just helper ;)
bool CCmdLineParser::isLast(POSITION& pos) const {
return (pos == m_ValsMap.end());
}



Attachments
CmdLineParser_demo.zip
(53.25 KiB) Downloaded 864 times
CmdLineParser_src.zip
(2.73 KiB) Downloaded 810 times

Post a reply
  Related Posts  to : How to implement Command Line Parser in C++ Code
 Command Line Parser Code Using C++     -  
 read from command line     -  
 c program - command line prompt - need help     -  
 program to run shell command line functions     -  
 Command line chat (client and server)     -  
 Reading a File Line by Line in php     -  
 php simple XML parser     -  
 php SAX parser in action     -  
 How to implement HttpSessionListener in JSP     -  
 Implement an interface in php     -  

Topic Tags

C++ Projects