181 #ifndef INCLUDED_SimpleOpt
182 #define INCLUDED_SimpleOpt
188 # define SO_STATICBUF SO_MAX_ARGS
192 # define SO_STATICBUF 50
302 #define SO_END_OF_OPTIONS { -1, NULL, SO_NONE }
307 # define SO_ASSERT(b) _ASSERTE(b)
310 # define SO_ASSERT(b) assert(b)
313 # define SO_ASSERT(b)
321 template<
class SOCHAR>
341 : m_rgShuffleBuf(NULL)
343 Init(0, NULL, NULL, 0);
353 : m_rgShuffleBuf(NULL)
355 Init(argc, argv, a_rgOptions, a_nFlags);
387 const SOption * a_rgOptions,
396 m_rgOptions = a_rgOptions;
406 inline void SetFlags(
int a_nFlags) { m_nFlags = a_nFlags; }
410 return (m_nFlags & a_nFlag) == a_nFlag;
448 inline int OptionId()
const {
return m_nOptionId; }
455 inline const SOCHAR *
OptionText()
const {
return m_pszOptionText; }
462 inline SOCHAR *
OptionArg()
const {
return m_pszOptionArg; }
483 inline int FileCount()
const {
return m_argc - m_nLastArg; }
490 inline SOCHAR *
File(
int n)
const {
492 return m_argv[m_nLastArg + n];
496 inline SOCHAR **
Files()
const {
return &m_argv[m_nLastArg]; }
502 SOCHAR PrepareArg(SOCHAR * a_pszString)
const;
504 void ShuffleArg(
int a_nStartIdx,
int a_nCount);
505 int LookupOption(
const SOCHAR * a_pszOption)
const;
506 int CalcMatch(
const SOCHAR *a_pszSource,
const SOCHAR *a_pszTest)
const;
509 inline SOCHAR * FindEquals(SOCHAR *s)
const {
510 while (*s && *s != (SOCHAR)
'=') ++s;
511 return *s ? s : NULL;
513 bool IsEqual(SOCHAR a_cLeft, SOCHAR a_cRight,
int a_nArgType)
const;
515 inline void Copy(SOCHAR ** ppDst, SOCHAR ** ppSrc,
int nCount)
const {
518 while (nCount-- > 0) *ppDst++ = *ppSrc++;
520 memcpy(ppDst, ppSrc, nCount *
sizeof(SOCHAR*));
525 const SOption * m_rgOptions;
533 const SOCHAR * m_pszOptionText;
534 SOCHAR * m_pszOptionArg;
538 SOCHAR ** m_rgShuffleBuf;
545 template<
class SOCHAR>
557 m_rgOptions = a_rgOptions;
561 m_pszOptionText = NULL;
562 m_pszOptionArg = NULL;
564 m_szShort[0] = (SOCHAR)
'-';
565 m_szShort[2] = (SOCHAR)
'\0';
570 if (m_argc > SO_MAX_ARGS) {
576 if (m_rgShuffleBuf) {
577 free(m_rgShuffleBuf);
579 if (m_argc > SO_STATICBUF) {
580 m_rgShuffleBuf = (SOCHAR**) malloc(
sizeof(SOCHAR*) * m_argc);
581 if (!m_rgShuffleBuf) {
590 template<
class SOCHAR>
595 if (m_argc > SO_MAX_ARGS) {
596 SO_ASSERT(!
"Too many args! Check the return value of Init()!");
602 if (m_pszClump && *m_pszClump) {
604 bool bIsValid = NextClumped();
605 while (*m_pszClump && !bIsValid && HasFlag(
SO_O_NOERR)) {
606 bIsValid = NextClumped();
618 m_nOptionIdx = m_nNextOption;
620 m_pszOptionText = NULL;
621 m_pszOptionArg = NULL;
627 int nOptIdx = m_nOptionIdx;
628 while (nTableIdx < 0 && nOptIdx < m_nLastArg) {
629 SOCHAR * pszArg = m_argv[nOptIdx];
630 m_pszOptionArg = NULL;
633 cFirst = PrepareArg(pszArg);
634 if (pszArg[0] == (SOCHAR)
'-') {
636 m_pszOptionArg = FindEquals(pszArg);
637 if (m_pszOptionArg) {
638 *m_pszOptionArg++ = (SOCHAR)
'\0';
641 nTableIdx = LookupOption(pszArg);
647 && pszArg[0] == (SOCHAR)
'-'
649 && pszArg[1] != (SOCHAR)
'-'
654 m_szShort[1] = pszArg[1];
655 int nIdx = LookupOption(m_szShort);
658 || m_rgOptions[nIdx].nArgType ==
SO_OPT))
660 m_pszOptionArg = &pszArg[2];
669 m_pszClump = &pszArg[1];
671 if (nOptIdx > m_nOptionIdx) {
672 ShuffleArg(m_nOptionIdx, nOptIdx - m_nOptionIdx);
682 if (!HasFlag(
SO_O_NOERR) && pszArg[0] == (SOCHAR)
'-') {
683 m_pszOptionText = pszArg;
689 if (m_pszOptionArg) {
690 *(--m_pszOptionArg) = (SOCHAR)
'=';
696 if (nOptIdx >= m_nLastArg) {
697 if (nOptIdx > m_nOptionIdx) {
698 ShuffleArg(m_nOptionIdx, nOptIdx - m_nOptionIdx);
707 m_nLastError = (
ESOError) nTableIdx;
710 m_nOptionId = m_rgOptions[nTableIdx].nId;
711 m_pszOptionText = m_rgOptions[nTableIdx].pszArg;
714 nArgType = m_rgOptions[nTableIdx].nArgType;
717 if (m_pszOptionArg) {
723 if (m_pszOptionArg) {
734 if (!m_pszOptionArg) {
751 if (nOptIdx > m_nOptionIdx) {
752 ShuffleArg(m_nOptionIdx, nOptIdx - m_nOptionIdx);
761 SOCHAR ** ppArgs = MultiArg(1);
763 m_pszOptionArg = *ppArgs;
770 template<
class SOCHAR>
774 if (m_nNextOption < m_nLastArg) {
775 ShuffleArg(m_nNextOption, m_nLastArg - m_nNextOption);
779 template<
class SOCHAR>
791 && a_pszString[0] == (SOCHAR)
'/'
793 && a_pszString[1] != (SOCHAR)
'-')
795 a_pszString[0] = (SOCHAR)
'-';
799 return a_pszString[0];
802 template<
class SOCHAR>
807 m_szShort[1] = *m_pszClump++;
809 m_pszOptionText = NULL;
810 m_pszOptionArg = NULL;
814 int nSavedFlags = m_nFlags;
816 int nTableIdx = LookupOption(m_szShort);
817 m_nFlags = nSavedFlags;
821 m_pszOptionText = m_szShort;
822 m_nLastError = (
ESOError) nTableIdx;
827 m_pszOptionText = m_rgOptions[nTableIdx].pszArg;
828 ESOArgType nArgType = m_rgOptions[nTableIdx].nArgType;
830 m_nOptionId = m_rgOptions[nTableIdx].nId;
835 m_nOptionId = m_rgOptions[nTableIdx].nId;
836 m_pszOptionArg = m_pszClump;
837 while (*m_pszClump) ++m_pszClump;
854 template<
class SOCHAR>
861 SOCHAR * staticBuf[SO_STATICBUF];
862 SOCHAR ** buf = m_rgShuffleBuf ? m_rgShuffleBuf : staticBuf;
863 int nTail = m_argc - a_nStartIdx - a_nCount;
866 Copy(buf, m_argv + a_nStartIdx, a_nCount);
869 Copy(m_argv + a_nStartIdx, m_argv + a_nStartIdx + a_nCount, nTail);
872 Copy(m_argv + a_nStartIdx + nTail, buf, a_nCount);
875 m_nLastArg -= a_nCount;
880 template<
class SOCHAR>
883 const SOCHAR * a_pszOption
887 int nBestMatchLen = 0;
888 int nLastMatchLen = 0;
890 for (
int n = 0; m_rgOptions[n].nId >= 0; ++n) {
893 SO_ASSERT(m_rgOptions[n].pszArg[0] != (SOCHAR)
'/');
895 int nMatchLen = CalcMatch(m_rgOptions[n].pszArg, a_pszOption);
896 if (nMatchLen == -1) {
899 if (nMatchLen > 0 && nMatchLen >= nBestMatchLen) {
900 nLastMatchLen = nBestMatchLen;
901 nBestMatchLen = nMatchLen;
908 if (HasFlag(
SO_O_EXACT) || nBestMatch == -1) {
916 template<
class SOCHAR>
919 const SOCHAR * a_pszSource,
920 const SOCHAR * a_pszTest
923 if (!a_pszSource || !a_pszTest) {
929 if (a_pszSource[0] !=
'-') {
932 else if (a_pszSource[1] !=
'-' && !a_pszSource[2]) {
937 while (*a_pszSource == (SOCHAR)
'-' && *a_pszSource == *a_pszTest) {
941 if (*a_pszSource == (SOCHAR)
'-' || *a_pszTest == (SOCHAR)
'-') {
947 while (*a_pszSource && IsEqual(*a_pszSource, *a_pszTest, nArgType)) {
975 template<
class SOCHAR>
984 if (m_nFlags & a_nArgType) {
985 if (a_cLeft >=
'A' && a_cLeft <=
'Z') a_cLeft +=
'a' -
'A';
986 if (a_cRight >=
'A' && a_cRight <=
'Z') a_cRight +=
'a' -
'A';
988 return a_cLeft == a_cRight;
993 template<
class SOCHAR>
1000 if (m_nNextOption + a_nCount > m_nLastArg) {
1006 SOCHAR ** rgpszArg = &m_argv[m_nNextOption];
1011 for (
int n = 0; n < a_nCount; ++n) {
1012 SOCHAR ch = PrepareArg(rgpszArg[n]);
1013 if (rgpszArg[n][0] == (SOCHAR)
'-') {
1014 rgpszArg[n][0] = ch;
1018 rgpszArg[n][0] = ch;
1023 m_nNextOption += a_nCount;
1038 #if defined(_UNICODE)
1040 # define CSimpleOpt CSimpleOptW
1043 # define CSimpleOpt CSimpleOptA
1046 #endif // INCLUDED_SimpleOpt