181 #ifndef INCLUDED_SimpleOpt
182 #define INCLUDED_SimpleOpt
188 # define SO_STATICBUF SO_MAX_ARGS
192 # define SO_STATICBUF 50
197 #define _T(s) (char*)s
307 #define SO_END_OF_OPTIONS { -1, NULL, SO_NONE }
312 # define SO_ASSERT(b) _ASSERTE(b)
315 # define SO_ASSERT(b) assert(b)
318 # define SO_ASSERT(b)
326 template<
class SOCHAR>
346 : m_rgShuffleBuf(NULL)
348 Init(0, NULL, NULL, 0);
358 : m_rgShuffleBuf(NULL)
360 Init(argc, argv, a_rgOptions, a_nFlags);
392 const SOption * a_rgOptions,
401 m_rgOptions = a_rgOptions;
411 inline void SetFlags(
int a_nFlags) { m_nFlags = a_nFlags; }
415 return (m_nFlags & a_nFlag) == a_nFlag;
453 inline int OptionId()
const {
return m_nOptionId; }
460 inline const SOCHAR *
OptionText()
const {
return m_pszOptionText; }
467 inline SOCHAR *
OptionArg()
const {
return m_pszOptionArg; }
488 inline int FileCount()
const {
return m_argc - m_nLastArg; }
495 inline SOCHAR *
File(
int n)
const {
497 return m_argv[m_nLastArg + n];
501 inline SOCHAR **
Files()
const {
return &m_argv[m_nLastArg]; }
507 SOCHAR PrepareArg(SOCHAR * a_pszString)
const;
509 void ShuffleArg(
int a_nStartIdx,
int a_nCount);
510 int LookupOption(
const SOCHAR * a_pszOption)
const;
511 int CalcMatch(
const SOCHAR *a_pszSource,
const SOCHAR *a_pszTest)
const;
514 inline SOCHAR * FindEquals(SOCHAR *s)
const {
515 while (*s && *s != (SOCHAR)
'=') ++s;
516 return *s ? s : NULL;
518 bool IsEqual(SOCHAR a_cLeft, SOCHAR a_cRight,
int a_nArgType)
const;
520 inline void Copy(SOCHAR ** ppDst, SOCHAR ** ppSrc,
int nCount)
const {
523 while (nCount-- > 0) *ppDst++ = *ppSrc++;
525 memcpy(ppDst, ppSrc, nCount *
sizeof(SOCHAR*));
530 const SOption * m_rgOptions;
538 const SOCHAR * m_pszOptionText;
539 SOCHAR * m_pszOptionArg;
543 SOCHAR ** m_rgShuffleBuf;
550 template<
class SOCHAR>
562 m_rgOptions = a_rgOptions;
566 m_pszOptionText = NULL;
567 m_pszOptionArg = NULL;
569 m_szShort[0] = (SOCHAR)
'-';
570 m_szShort[2] = (SOCHAR)
'\0';
575 if (m_argc > SO_MAX_ARGS) {
581 if (m_rgShuffleBuf) {
582 free(m_rgShuffleBuf);
585 m_rgShuffleBuf = (SOCHAR**) malloc(
sizeof(SOCHAR*) * m_argc);
586 if (!m_rgShuffleBuf) {
595 template<
class SOCHAR>
600 if (m_argc > SO_MAX_ARGS) {
601 SO_ASSERT(!
"Too many args! Check the return value of Init()!");
607 if (m_pszClump && *m_pszClump) {
609 bool bIsValid = NextClumped();
610 while (*m_pszClump && !bIsValid && HasFlag(
SO_O_NOERR)) {
611 bIsValid = NextClumped();
623 m_nOptionIdx = m_nNextOption;
625 m_pszOptionText = NULL;
626 m_pszOptionArg = NULL;
632 int nOptIdx = m_nOptionIdx;
633 while (nTableIdx < 0 && nOptIdx < m_nLastArg) {
634 SOCHAR * pszArg = m_argv[nOptIdx];
635 m_pszOptionArg = NULL;
638 cFirst = PrepareArg(pszArg);
639 if (pszArg[0] == (SOCHAR)
'-') {
641 m_pszOptionArg = FindEquals(pszArg);
642 if (m_pszOptionArg) {
643 *m_pszOptionArg++ = (SOCHAR)
'\0';
646 nTableIdx = LookupOption(pszArg);
652 && pszArg[0] == (SOCHAR)
'-'
654 && pszArg[1] != (SOCHAR)
'-'
659 m_szShort[1] = pszArg[1];
660 int nIdx = LookupOption(m_szShort);
663 || m_rgOptions[nIdx].nArgType ==
SO_OPT))
665 m_pszOptionArg = &pszArg[2];
674 m_pszClump = &pszArg[1];
676 if (nOptIdx > m_nOptionIdx) {
677 ShuffleArg(m_nOptionIdx, nOptIdx - m_nOptionIdx);
687 if (!HasFlag(
SO_O_NOERR) && pszArg[0] == (SOCHAR)
'-') {
688 m_pszOptionText = pszArg;
694 if (m_pszOptionArg) {
695 *(--m_pszOptionArg) = (SOCHAR)
'=';
701 if (nOptIdx >= m_nLastArg) {
702 if (nOptIdx > m_nOptionIdx) {
703 ShuffleArg(m_nOptionIdx, nOptIdx - m_nOptionIdx);
712 m_nLastError = (
ESOError) nTableIdx;
715 m_nOptionId = m_rgOptions[nTableIdx].nId;
716 m_pszOptionText = m_rgOptions[nTableIdx].pszArg;
719 nArgType = m_rgOptions[nTableIdx].nArgType;
722 if (m_pszOptionArg) {
728 if (m_pszOptionArg) {
739 if (!m_pszOptionArg) {
756 if (nOptIdx > m_nOptionIdx) {
757 ShuffleArg(m_nOptionIdx, nOptIdx - m_nOptionIdx);
766 SOCHAR ** ppArgs = MultiArg(1);
768 m_pszOptionArg = *ppArgs;
775 template<
class SOCHAR>
779 if (m_nNextOption < m_nLastArg) {
780 ShuffleArg(m_nNextOption, m_nLastArg - m_nNextOption);
784 template<
class SOCHAR>
796 && a_pszString[0] == (SOCHAR)
'/'
798 && a_pszString[1] != (SOCHAR)
'-')
800 a_pszString[0] = (SOCHAR)
'-';
804 return a_pszString[0];
807 template<
class SOCHAR>
812 m_szShort[1] = *m_pszClump++;
814 m_pszOptionText = NULL;
815 m_pszOptionArg = NULL;
819 int nSavedFlags = m_nFlags;
821 int nTableIdx = LookupOption(m_szShort);
822 m_nFlags = nSavedFlags;
826 m_pszOptionText = m_szShort;
827 m_nLastError = (
ESOError) nTableIdx;
832 m_pszOptionText = m_rgOptions[nTableIdx].pszArg;
833 ESOArgType nArgType = m_rgOptions[nTableIdx].nArgType;
835 m_nOptionId = m_rgOptions[nTableIdx].nId;
840 m_nOptionId = m_rgOptions[nTableIdx].nId;
841 m_pszOptionArg = m_pszClump;
842 while (*m_pszClump) ++m_pszClump;
859 template<
class SOCHAR>
867 SOCHAR **
buf = m_rgShuffleBuf ? m_rgShuffleBuf : staticBuf;
868 int nTail = m_argc - a_nStartIdx - a_nCount;
871 Copy(
buf, m_argv + a_nStartIdx, a_nCount);
874 Copy(m_argv + a_nStartIdx, m_argv + a_nStartIdx + a_nCount, nTail);
877 Copy(m_argv + a_nStartIdx + nTail,
buf, a_nCount);
880 m_nLastArg -= a_nCount;
885 template<
class SOCHAR>
888 const SOCHAR * a_pszOption
892 int nBestMatchLen = 0;
893 int nLastMatchLen = 0;
895 for (
int n = 0; m_rgOptions[n].nId >= 0; ++n) {
898 SO_ASSERT(m_rgOptions[n].pszArg[0] != (SOCHAR)
'/');
900 int nMatchLen = CalcMatch(m_rgOptions[n].pszArg, a_pszOption);
901 if (nMatchLen == -1) {
904 if (nMatchLen > 0 && nMatchLen >= nBestMatchLen) {
905 nLastMatchLen = nBestMatchLen;
906 nBestMatchLen = nMatchLen;
913 if (HasFlag(
SO_O_EXACT) || nBestMatch == -1) {
921 template<
class SOCHAR>
924 const SOCHAR * a_pszSource,
925 const SOCHAR * a_pszTest
928 if (!a_pszSource || !a_pszTest) {
934 if (a_pszSource[0] !=
'-') {
937 else if (a_pszSource[1] !=
'-' && !a_pszSource[2]) {
942 while (*a_pszSource == (SOCHAR)
'-' && *a_pszSource == *a_pszTest) {
946 if (*a_pszSource == (SOCHAR)
'-' || *a_pszTest == (SOCHAR)
'-') {
952 while (*a_pszSource && IsEqual(*a_pszSource, *a_pszTest, nArgType)) {
980 template<
class SOCHAR>
989 if (m_nFlags & a_nArgType) {
990 if (a_cLeft >=
'A' && a_cLeft <=
'Z') a_cLeft +=
'a' -
'A';
991 if (a_cRight >=
'A' && a_cRight <=
'Z') a_cRight +=
'a' -
'A';
993 return a_cLeft == a_cRight;
998 template<
class SOCHAR>
1005 if (m_nNextOption + a_nCount > m_nLastArg) {
1011 SOCHAR ** rgpszArg = &m_argv[m_nNextOption];
1016 for (
int n = 0; n < a_nCount; ++n) {
1017 SOCHAR ch = PrepareArg(rgpszArg[n]);
1018 if (rgpszArg[n][0] == (SOCHAR)
'-') {
1019 rgpszArg[n][0] = ch;
1023 rgpszArg[n][0] = ch;
1028 m_nNextOption += a_nCount;
1043 #if defined(_UNICODE)
1045 # define CSimpleOpt CSimpleOptW
1048 # define CSimpleOpt CSimpleOptA
CSimpleOptTempl< wchar_t > CSimpleOptW
wchar_t version of CSimpleOpt
enum _ESOArgType ESOArgType
CSimpleOptTempl< char > CSimpleOptA
ASCII/MBCS version of CSimpleOpt.
@ SO_ARG_MISSING
Required argument was not supplied.
enum _ESOError ESOError
Error values.
#define SO_ASSERT(b)
assertion used to test input data
Implementation of the SimpleOpt class.
int FileCount() const
Returned the number of entries in the Files() array.
bool Init(int a_argc, SOCHAR *a_argv[], const SOption *a_rgOptions, int a_nFlags=0)
Initialize the class in preparation for calling Next.
const SOCHAR * OptionText() const
Return the pszArg from the options array for the current option.
int OptionId() const
Return the nId value from the options array for the current option.
SOCHAR * OptionArg() const
Return the argument for the current option where one exists.
CSimpleOptTempl(int argc, SOCHAR *argv[], const SOption *a_rgOptions, int a_nFlags=0)
Initialize the class in preparation for use.
void SetOptions(const SOption *a_rgOptions)
Change the current options table during option parsing.
CSimpleOptTempl()
Initialize the class. Init() must be called later.
SOCHAR ** Files() const
Return the array of files.
ESOError LastError() const
Return the last error that occurred.
bool Next()
Advance to the next option if available.
SOCHAR ** MultiArg(int n)
Validate and return the desired number of arguments.
void SetFlags(int a_nFlags)
Change the current flags during option parsing.
bool HasFlag(int a_nFlag) const
Query if a particular flag is set.
SOCHAR * File(int n) const
Return the specified file argument.
~CSimpleOptTempl()
Deallocate any allocated memory.
Structure used to define all known options.