VirtualBox

Changeset 96729 in vbox


Ignore:
Timestamp:
Sep 14, 2022 9:14:53 AM (2 years ago)
Author:
vboxsync
Message:

IPRT/getopt: Added index variant with 0 or 1 and optionally and w/ implicit dash. Thought I needed for converting some options to use indexes, but here it is anyways.

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/iprt/getopt.h

    r96407 r96729  
    130130/** The index value is attached to the argument - only valid for long arguments. */
    131131#define RTGETOPT_FLAG_INDEX                     RT_BIT(19)
     132/** Used with RTGETOPT_FLAG_INDEX, setting index to zero if none given.
     133 * (The default is to fail with VERR_GETOPT_INDEX_MISSING.)  */
     134#define RTGETOPT_FLAG_INDEX_DEF_0               RT_BIT(20)
     135/** Used with RTGETOPT_FLAG_INDEX, setting index to one if none given.
     136 * (The default is to fail with VERR_GETOPT_INDEX_MISSING.)  */
     137#define RTGETOPT_FLAG_INDEX_DEF_1               RT_BIT(21)
     138/** For simplicity. */
     139#define RTGETOPT_FLAG_INDEX_DEF_MASK            (RT_BIT(20) | RT_BIT(21))
     140/** For simple conversion. */
     141#define RTGETOPT_FLAG_INDEX_DEF_SHIFT           20
     142/** For use with RTGETOPT_FLAG_INDEX_DEF_0 or RTGETOPT_FLAG_INDEX_DEF_1 to
     143 *  imply a dash before the index when a digit is specified.
     144 * This is for transitioning from options without index to optionally allow
     145 * index options, i.e. "--long" defaults to either index 1 or 1 using the above
     146 * flags, while "--long-1" explicitly gives the index ("--long-" is not valid).
     147 * This flag matches an "-" separating the "--long" string
     148 * (RTGETOPTDEFS::pszLong) from the index value.  */
     149#define RTGETOPT_FLAG_INDEX_DEF_DASH            RT_BIT(22)
    132150/** Treat the long option as case insensitive. */
    133 #define RTGETOPT_FLAG_ICASE                     RT_BIT(20)
     151#define RTGETOPT_FLAG_ICASE                     RT_BIT(23)
    134152/** Mask of valid bits - for validation. */
    135153#define RTGETOPT_VALID_MASK                     (  RTGETOPT_REQ_MASK \
     
    138156                                                 | RTGETOPT_FLAG_DEC \
    139157                                                 | RTGETOPT_FLAG_INDEX \
    140                                                  | RTGETOPT_FLAG_ICASE)
     158                                                 | RTGETOPT_FLAG_INDEX_DEF_0 \
     159                                                 | RTGETOPT_FLAG_INDEX_DEF_1 \
     160                                                 | RTGETOPT_FLAG_INDEX_DEF_DASH \
     161                                                 | RTGETOPT_FLAG_ICASE )
    141162/** @} */
    142163
     
    165186 *
    166187 * What ends up here depends on argument format in the option definition.
    167  *
    168  * @remarks Integers will bet put in the \a i and \a u members and sign/zero extended
    169  *          according to the signedness indicated by the \a fFlags. So, you can choose
    170  *          use which ever of the integer members for accessing the value regardless
    171  *          of restrictions indicated in the \a fFlags.
    172188 */
    173189typedef union RTGETOPTUNION
  • trunk/src/VBox/Runtime/common/misc/getopt.cpp

    r96407 r96729  
    102102    {
    103103        Assert(!(paOptions[i].fFlags & ~RTGETOPT_VALID_MASK));
     104        Assert(   !(paOptions[i].fFlags & (RTGETOPT_FLAG_INDEX_DEF_MASK | RTGETOPT_FLAG_INDEX_DEF_DASH))
     105               || (paOptions[i].fFlags & RTGETOPT_FLAG_INDEX) );
    104106        Assert(paOptions[i].iShort > 0);
    105107        Assert(paOptions[i].iShort != VINF_GETOPT_NOT_OPTION);
     
    175177        if (pOpt->pszLong)
    176178        {
    177             if ((pOpt->fFlags & RTGETOPT_REQ_MASK) != RTGETOPT_REQ_NOTHING)
     179            uint32_t const fOptFlags = pOpt->fFlags;
     180            if ((fOptFlags & RTGETOPT_REQ_MASK) != RTGETOPT_REQ_NOTHING)
    178181            {
    179182                /*
     
    189192                size_t cchLong = strlen(pOpt->pszLong);
    190193                if (   !strncmp(pszOption, pOpt->pszLong, cchLong)
    191                     || (   pOpt->fFlags & RTGETOPT_FLAG_ICASE
     194                    || (   (fOptFlags & RTGETOPT_FLAG_ICASE)
    192195                        && !RTStrNICmp(pszOption, pOpt->pszLong, cchLong)))
    193196                {
    194                     if (pOpt->fFlags & RTGETOPT_FLAG_INDEX)
     197                    if (   (fOptFlags & RTGETOPT_FLAG_INDEX_DEF_DASH)
     198                        && pszOption[cchLong] == '-'
     199                        && RT_C_IS_DIGIT(pszOption[cchLong + 1])) /* given "--long" we match "--long-1" but not "--long-". */
     200                        cchLong++;
     201                    if (fOptFlags & RTGETOPT_FLAG_INDEX)
    195202                        while (RT_C_IS_DIGIT(pszOption[cchLong]))
    196203                            cchLong++;
     
    201208                }
    202209            }
    203             else if (pOpt->fFlags & RTGETOPT_FLAG_INDEX)
     210            else if (fOptFlags & RTGETOPT_FLAG_INDEX)
    204211            {
    205212                /*
     
    209216                size_t cchLong = strlen(pOpt->pszLong);
    210217                if (   !strncmp(pszOption, pOpt->pszLong, cchLong)
    211                     || (   pOpt->fFlags & RTGETOPT_FLAG_ICASE
     218                    || (   (fOptFlags & RTGETOPT_FLAG_ICASE)
    212219                        && !RTStrNICmp(pszOption, pOpt->pszLong, cchLong)))
    213220                {
     221                    if (   (fOptFlags & RTGETOPT_FLAG_INDEX_DEF_DASH)
     222                        && pszOption[cchLong] == '-'
     223                        && RT_C_IS_DIGIT(pszOption[cchLong + 1]))
     224                        cchLong++;
    214225                    while (RT_C_IS_DIGIT(pszOption[cchLong]))
    215226                        cchLong++;
     
    219230            }
    220231            else if (   !strcmp(pszOption, pOpt->pszLong)
    221                      || (   pOpt->fFlags & RTGETOPT_FLAG_ICASE
     232                     || (   (fOptFlags & RTGETOPT_FLAG_ICASE)
    222233                         && !RTStrICmp(pszOption, pOpt->pszLong)))
    223234                return pOpt;
     
    660671        pValueUnion->pDef = pOpt; /* in case of no value or error. */
    661672
    662         if ((pOpt->fFlags & RTGETOPT_REQ_MASK) != RTGETOPT_REQ_NOTHING)
     673        uint32_t const fOptFlags = pOpt->fFlags;
     674        if ((fOptFlags & RTGETOPT_REQ_MASK) != RTGETOPT_REQ_NOTHING)
    663675        {
    664676            /*
     
    692704            {
    693705                size_t cchLong = strlen(pOpt->pszLong);
    694                 if (pOpt->fFlags & RTGETOPT_FLAG_INDEX)
    695                 {
    696 
    697                     if (pszArgThis[cchLong] == '\0')
    698                         return VERR_GETOPT_INDEX_MISSING;
    699 
    700                     uint32_t uIndex;
    701                     char *pszRet = NULL;
    702                     int rc = RTStrToUInt32Ex(&pszArgThis[cchLong], &pszRet, 10, &uIndex);
    703                     if (rc == VWRN_TRAILING_CHARS)
     706                if (fOptFlags & RTGETOPT_FLAG_INDEX)
     707                {
     708                    if (   pszArgThis[cchLong] != '\0'
     709                        || (fOptFlags & RTGETOPT_FLAG_INDEX_DEF_MASK))
    704710                    {
    705                         if (   pszRet[0] != ':'
    706                             && pszRet[0] != '=')
    707                             return VERR_GETOPT_INVALID_ARGUMENT_FORMAT;
    708                         pState->uIndex = uIndex;
    709                         pszValue = pszRet + 1;
    710                     }
    711                     else if (rc == VINF_SUCCESS)
    712                     {
    713                         if (iThis + 1 + pState->cNonOptions >= pState->argc)
    714                             return VERR_GETOPT_REQUIRED_ARGUMENT_MISSING;
    715                         pState->uIndex = uIndex;
    716                         pszValue = pState->argv[iThis + pState->cNonOptions + 1];
    717                         rtGetOptMoveArgvEntries(&pState->argv[iThis + 1], &pState->argv[iThis + pState->cNonOptions + 1]);
    718                         pState->iNext++;
     711                        if (   (fOptFlags & RTGETOPT_FLAG_INDEX_DEF_DASH)
     712                            && pszArgThis[cchLong] == '-')
     713                            cchLong++;
     714
     715                        uint32_t uIndex;
     716                        char *pszRet = NULL;
     717                        int rc = RTStrToUInt32Ex(&pszArgThis[cchLong], &pszRet, 10, &uIndex);
     718                        if (   rc == VERR_NO_DIGITS
     719                            && (fOptFlags & RTGETOPT_FLAG_INDEX_DEF_MASK))
     720                        {
     721                            uIndex = ((fOptFlags & RTGETOPT_FLAG_INDEX_DEF_MASK) >> RTGETOPT_FLAG_INDEX_DEF_SHIFT) - 1;
     722                            rc = pszRet[0] == '\0' ? VINF_SUCCESS : VWRN_TRAILING_CHARS;
     723                        }
     724                        if (rc == VWRN_TRAILING_CHARS)
     725                        {
     726                            if (   pszRet[0] != ':'
     727                                && pszRet[0] != '=')
     728                                return VERR_GETOPT_INVALID_ARGUMENT_FORMAT;
     729                            pState->uIndex = uIndex;
     730                            pszValue = pszRet + 1;
     731                        }
     732                        else if (rc == VINF_SUCCESS)
     733                        {
     734                            if (iThis + 1 + pState->cNonOptions >= pState->argc)
     735                                return VERR_GETOPT_REQUIRED_ARGUMENT_MISSING;
     736                            pState->uIndex = uIndex;
     737                            pszValue = pState->argv[iThis + pState->cNonOptions + 1];
     738                            rtGetOptMoveArgvEntries(&pState->argv[iThis + 1], &pState->argv[iThis + pState->cNonOptions + 1]);
     739                            pState->iNext++;
     740                        }
     741                        else
     742                            AssertMsgFailedReturn(("%s\n", pszArgThis), VERR_GETOPT_INVALID_ARGUMENT_FORMAT); /* search bug */
    719743                    }
    720744                    else
    721                         AssertMsgFailedReturn(("%s\n", pszArgThis), VERR_GETOPT_INVALID_ARGUMENT_FORMAT); /* search bug */
     745                        return VERR_GETOPT_INDEX_MISSING;
    722746                }
    723747                else
     
    739763             * Set up the ValueUnion.
    740764             */
    741             int rc = rtGetOptProcessValue(pOpt->fFlags, pszValue, pValueUnion);
     765            int rc = rtGetOptProcessValue(fOptFlags, pszValue, pValueUnion);
    742766            if (RT_FAILURE(rc))
    743767                return rc;
     
    765789            }
    766790        }
    767         else if (pOpt->fFlags & RTGETOPT_FLAG_INDEX)
    768         {
    769             size_t cchLong = strlen(pOpt->pszLong);
    770             if (pszArgThis[cchLong] == '\0')
     791        else if (fOptFlags & RTGETOPT_FLAG_INDEX)
     792        {
     793            size_t   cchLong = strlen(pOpt->pszLong);
     794            uint32_t uIndex;
     795            if (pszArgThis[cchLong] != '\0')
     796            {
     797                if (   (fOptFlags & RTGETOPT_FLAG_INDEX_DEF_DASH)
     798                    && pszArgThis[cchLong] == '-')
     799                    cchLong++;
     800                if (RTStrToUInt32Full(&pszArgThis[cchLong], 10, &uIndex) == VINF_SUCCESS)
     801                    pState->uIndex = uIndex;
     802                else
     803                    AssertMsgFailedReturn(("%s\n", pszArgThis), VERR_GETOPT_INVALID_ARGUMENT_FORMAT); /* search bug */
     804            }
     805            else if (fOptFlags & RTGETOPT_FLAG_INDEX_DEF_MASK)
     806                uIndex = ((fOptFlags & RTGETOPT_FLAG_INDEX_DEF_MASK) >> RTGETOPT_FLAG_INDEX_DEF_SHIFT) - 1;
     807            else
    771808                return VERR_GETOPT_INDEX_MISSING;
    772 
    773             uint32_t uIndex;
    774             if (RTStrToUInt32Full(&pszArgThis[cchLong], 10, &uIndex) == VINF_SUCCESS)
    775                 pState->uIndex = uIndex;
    776             else
    777                 AssertMsgFailedReturn(("%s\n", pszArgThis), VERR_GETOPT_INVALID_ARGUMENT_FORMAT); /* search bug */
    778809        }
    779810
  • trunk/src/VBox/Runtime/testcase/tstRTGetOpt.cpp

    r96407 r96729  
    119119        { "--optpair32",        411, RTGETOPT_REQ_UINT32_OPTIONAL_PAIR  },
    120120        { "--optpair64",        412, RTGETOPT_REQ_UINT64_OPTIONAL_PAIR  },
     121        { "--boolean0index",    413, RTGETOPT_REQ_BOOL_ONOFF | RTGETOPT_FLAG_INDEX | RTGETOPT_FLAG_INDEX_DEF_0 },
     122        { "--boolean1index",    414, RTGETOPT_REQ_BOOL_ONOFF | RTGETOPT_FLAG_INDEX | RTGETOPT_FLAG_INDEX_DEF_1 },
     123        { "--boolean-dash-idx", 415, RTGETOPT_REQ_BOOL_ONOFF | RTGETOPT_FLAG_INDEX | RTGETOPT_FLAG_INDEX_DEF_0 | RTGETOPT_FLAG_INDEX_DEF_DASH },
    121124    };
    122125
     
    191194        "--booleanindex7",   "off",
    192195        "--booleanindex9",   "invalid",
     196
     197        /* bool on/off with optional index */
     198        "--boolean0index9",     "on",
     199        "--boolean0index",      "off",
     200        "--boolean1index42",    "off",
     201        "--boolean1index",      "on",
     202        "--boolean-dash-idx",   "off",
     203        "--boolean-dash-idx-2", "on",
     204        "--boolean-dash-idx-3=off",
     205        "--boolean-dash-idx:on",
    193206
    194207        /* standard options */
     
    437450    CHECK_GETOPT(RTGetOpt(&GetState, &Val), VERR_GETOPT_UNKNOWN_OPTION, 2);
    438451    CHECK(RT_VALID_PTR(Val.psz) && !strcmp(Val.psz, "invalid"));
     452
     453    /* bool on/off with optional indexed argument  */
     454    CHECK_GETOPT(RTGetOpt(&GetState, &Val), 413, 2);
     455    CHECK(Val.f);
     456    CHECK(GetState.uIndex == 9);
     457
     458    CHECK_GETOPT(RTGetOpt(&GetState, &Val), 413, 2);
     459    CHECK(!Val.f);
     460    CHECK(GetState.uIndex == 0);
     461
     462    CHECK_GETOPT(RTGetOpt(&GetState, &Val), 414, 2);
     463    CHECK(!Val.f);
     464    CHECK(GetState.uIndex == 42);
     465
     466    CHECK_GETOPT(RTGetOpt(&GetState, &Val), 414, 2);
     467    CHECK(Val.f);
     468    CHECK(GetState.uIndex == 1);
     469
     470    CHECK_GETOPT(RTGetOpt(&GetState, &Val), 415, 2);
     471    CHECK(!Val.f);
     472    CHECK(GetState.uIndex == 0);
     473
     474    CHECK_GETOPT(RTGetOpt(&GetState, &Val), 415, 2);
     475    CHECK(Val.f);
     476    CHECK(GetState.uIndex == 2);
     477
     478    CHECK_GETOPT(RTGetOpt(&GetState, &Val), 415, 1);
     479    CHECK(!Val.f);
     480    CHECK(GetState.uIndex == 3);
     481
     482    CHECK_GETOPT(RTGetOpt(&GetState, &Val), 415, 1);
     483    CHECK(Val.f);
     484    CHECK(GetState.uIndex == 0);
    439485
    440486    /* standard options. */
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette