VirtualBox

Changeset 69062 in vbox


Ignore:
Timestamp:
Oct 12, 2017 3:05:52 PM (7 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
118342
Message:

IPRT: Added RTIniFileQueryPair for key/value pair enumeration.

Location:
trunk
Files:
3 edited

Legend:

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

    r68317 r69062  
    7777
    7878/**
    79  * Queries a value in a section.
     79 * Queries a named value in a section.
    8080 *
    8181 * The first matching value is returned.  The matching is by default case
     
    9999                                     char *pszValue, size_t cbValue, size_t *pcbActual);
    100100
     101/**
     102 * Queries a key-value pair in a section by ordinal.
     103 *
     104 * @returns IPRT status code.
     105 * @retval  VERR_NOT_FOUND if the section wasn't found or if it contains no pair
     106 *          with the given ordinal value.
     107 *
     108 * @param   hIniFile        The INI-file handle.
     109 * @param   pszSection      The section name.  Pass NULL to refer to the
     110 *                          unsectioned key space at the top of the file.
     111 * @param   idxPair         The pair to fetch (counting from 0).
     112 *
     113 * @param   pszKey          Where to return the key name.
     114 * @param   cbKey           Size of the buffer @a pszKey points to.
     115 * @param   pcbKeyActual    Where to return the actual key size excluding
     116 *                          terminator on success.  On VERR_BUFFER_OVERFLOW this
     117 *                          will be set to the buffer size needed to hold the
     118 *                          value, terminator included.  Optional.
     119 *
     120 * @param   pszValue        Where to return the value.
     121 * @param   cbValue         Size of the buffer @a pszValue points to.
     122 * @param   pcbValueActual  Where to return the actual value size excluding
     123 *                          terminator on success.  On VERR_BUFFER_OVERFLOW this
     124 *                          will be set to the buffer size needed to hold the
     125 *                          value, terminator included. Optional.
     126 */
     127RTDECL(int)      RTIniFileQueryPair(RTINIFILE hIniFile, const char *pszSection, uint32_t idxPair,
     128                                    char *pszKey, size_t cbKey, size_t *pcbKeyActual,
     129                                    char *pszValue, size_t cbValue, size_t *pcbValueActual);
     130
    101131
    102132/** @} */
  • trunk/include/iprt/mangling.h

    r69011 r69062  
    10201020# define RTIniFileRetain                                RT_MANGLER(RTIniFileRetain)
    10211021# define RTIniFileRelease                               RT_MANGLER(RTIniFileRelease)
     1022# define RTIniFileQueryPair                             RT_MANGLER(RTIniFileQueryPair)
    10221023# define RTIniFileQueryValue                            RT_MANGLER(RTIniFileQueryValue)
    10231024# define RTIsoFsClose                                   RT_MANGLER(RTIsoFsClose)
  • trunk/src/VBox/Runtime/common/misc/inifile.cpp

    r69060 r69062  
    438438            if (ch != '=')
    439439            {
    440                 /** @todo deal with escaped eqal signs? */
     440                /** @todo deal with escaped equal signs? */
    441441                pszEqual = strchr(psz, '=');
    442442                if (pszEqual)
     
    573573}
    574574
     575
     576/**
     577 * Worker for RTIniFileQueryPair.
     578 *
     579 * This can also be used to count the number of pairs in a section.
     580 */
     581static int rtIniFileQueryPairInSection(PRTINIFILEINT pThis, PRTINIFILESECTION pSection, uint32_t *pidxPair,
     582                                       char *pszKey, size_t cbKey, size_t *pcbKeyActual,
     583                                       char *pszValue, size_t cbValue, size_t *pcbValueActual)
     584{
     585    uint32_t idxPair = *pidxPair;
     586
     587    /*
     588     * Scan the section, looking for the matching key.
     589     */
     590    Assert(pSection->cchSkipToValues <= pSection->cchSection);
     591    const char * const  pszEnd  = &pThis->pszFile[pSection->offName + pSection->cchSection];
     592    const char *        pszNext = pszEnd;
     593    for (const char    *psz     = &pThis->pszFile[pSection->offName + pSection->cchSkipToValues];
     594         (uintptr_t)psz < (uintptr_t)pszEnd;
     595         psz = pszNext)
     596    {
     597        /* Find start of next line so we can use 'continue' to skip a line. */
     598        pszNext = strchr(psz, '\n');
     599        if (pszNext)
     600            pszNext++;
     601        else
     602            pszNext = pszEnd;
     603
     604        /* Skip leading spaces. */
     605        char ch;
     606        while ((ch = *psz) != '\0' && RT_C_IS_SPACE(ch))
     607            psz++;
     608        if (   ch != ';'  /* comment line */
     609            && ch != '\n' /* empty line */
     610            && ch != '\r' /* empty line */
     611            && (uintptr_t)psz < (uintptr_t)pszEnd)
     612        {
     613            /* Find end of key name, if any. */
     614            const char *pszCurKey = psz;
     615            size_t      cchCurKey;
     616            const char *pszEqual;
     617            if (ch != '=')
     618            {
     619                /** @todo deal with escaped equal signs? */
     620                pszEqual = strchr(psz, '=');
     621                if (pszEqual)
     622                {
     623                    if ((uintptr_t)pszEqual < (uintptr_t)pszNext)
     624                        cchCurKey = pszEqual - pszCurKey;
     625                    else
     626                        continue;
     627                }
     628                else
     629                    break;
     630            }
     631            else
     632            {
     633                cchCurKey = 0;
     634                pszEqual  = psz;
     635            }
     636
     637            /* Is this the pair we're looking for? */
     638            if (idxPair > 0)
     639                idxPair--;
     640            else
     641            {
     642                /*
     643                 * Yes it's the stuff we're looking for.
     644                 * Prepare the the return stuff.
     645                 */
     646
     647                /* Strip trailing spaces from the key name. */
     648                while (cchCurKey > 0 && RT_C_IS_SPACE(pszCurKey[cchCurKey - 1]))
     649                    cchCurKey--;
     650
     651                /* Skip leading blanks from the value. */
     652                psz = pszEqual + 1;
     653                while ((ch = *psz) && RT_C_IS_SPACE(ch) && ch != '\n')
     654                    psz++;
     655
     656                /* Strip trailing spaces from the value. */
     657                size_t cchCurValue = pszNext - psz;
     658                while (cchCurValue > 1 && RT_C_IS_SPACE(psz[cchCurValue - 1]))
     659                    cchCurValue--;
     660
     661                /* Strip value quotes. */
     662                if (   cchCurValue > 2
     663                    && (   (ch = *psz) == '"'
     664                        || ch          == '\'' )
     665                    && psz[cchCurValue - 1] == ch)
     666                {
     667                    cchCurValue -= 2;
     668                    psz++;
     669                }
     670
     671                /*
     672                 * Copy the stuff out.
     673                 */
     674                if (   cchCurValue < cbValue
     675                    && cchCurKey   < cbKey)
     676                {
     677                    memcpy(pszKey, pszCurKey, cchCurKey);
     678                    pszKey[cchCurKey] = '\0';
     679                    if (pcbKeyActual)
     680                        *pcbKeyActual = cchCurKey;
     681
     682                    memcpy(pszValue, psz, cchCurValue);
     683                    pszValue[cchCurValue] = '\0';
     684                    if (pcbValueActual)
     685                        *pcbValueActual = cchCurValue;
     686
     687                    *pidxPair = 0;
     688                    return VINF_SUCCESS;
     689                }
     690
     691                /* Buffer overflow. Copy out what we can. */
     692                if (cbKey > 0)
     693                {
     694                    if (cchCurKey < cbKey)
     695                        cbKey = cchCurKey + 1;
     696                    memcpy(pszKey, pszCurKey, cbKey - 1);
     697                    pszKey[cbKey - 1] = '\0';
     698                }
     699                if (pcbKeyActual)
     700                    *pcbKeyActual = cchCurKey + 1;
     701
     702                if (cbValue > 0)
     703                {
     704                    if (cchCurValue < cbValue)
     705                        cbValue = cchCurValue + 1;
     706                    memcpy(pszValue, psz, cbValue - 1);
     707                    pszValue[cbValue - 1] = '\0';
     708                }
     709                if (pcbValueActual)
     710                    *pcbValueActual = cchCurValue + 1;
     711
     712                *pidxPair = 0;
     713                return VERR_BUFFER_OVERFLOW;
     714            }
     715        }
     716    }
     717    *pidxPair = idxPair;
     718    return VERR_NOT_FOUND;
     719}
     720
     721
     722/**
     723 * Queries a key-value pair in a section by ordinal.
     724 *
     725 * @returns IPRT status code.
     726 * @retval  VERR_NOT_FOUND if the section wasn't found or if it contains no pair
     727 *          with the given ordinal value.
     728 *
     729 * @param   hIniFile        The INI-file handle.
     730 * @param   pszSection      The section name.  Pass NULL to refer to the
     731 *                          unsectioned key space at the top of the file.
     732 * @param   idxPair         The pair to fetch (counting from 0).
     733 *
     734 * @param   pszKey          Where to return the key name.
     735 * @param   cbKey           Size of the buffer @a pszKey points to.
     736 * @param   pcbKeyActual    Where to return the actual key size excluding
     737 *                          terminator on success.  On VERR_BUFFER_OVERFLOW this
     738 *                          will be set to the buffer size needed to hold the
     739 *                          value, terminator included.  Optional.
     740 *
     741 * @param   pszValue        Where to return the value.
     742 * @param   cbValue         Size of the buffer @a pszValue points to.
     743 * @param   pcbValueActual  Where to return the actual value size excluding
     744 *                          terminator on success.  On VERR_BUFFER_OVERFLOW this
     745 *                          will be set to the buffer size needed to hold the
     746 *                          value, terminator included. Optional.
     747 */
     748RTDECL(int) RTIniFileQueryPair(RTINIFILE hIniFile, const char *pszSection, uint32_t idxPair,
     749                               char *pszKey, size_t cbKey, size_t *pcbKeyActual,
     750                               char *pszValue, size_t cbValue, size_t *pcbValueActual)
     751{
     752    /*
     753     * Validate input.
     754     */
     755    PRTINIFILEINT pThis = hIniFile;
     756    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
     757    AssertReturn(pThis->u32Magic == RTINIFILE_MAGIC, VERR_INVALID_HANDLE);
     758    AssertPtrNullReturn(pszSection, VERR_INVALID_POINTER);
     759    if (cbKey)
     760        AssertPtrReturn(pszKey, VERR_INVALID_POINTER);
     761    AssertPtrNullReturn(pcbKeyActual, VERR_INVALID_POINTER);
     762    if (cbValue)
     763        AssertPtrReturn(pszValue, VERR_INVALID_POINTER);
     764    AssertPtrNullReturn(pcbValueActual, VERR_INVALID_POINTER);
     765
     766    /*
     767     * Search relevant sections.
     768     */
     769    int rc;
     770    if (pszSection == NULL)
     771        rc = rtIniFileQueryPairInSection(pThis, &pThis->paSections[0], &idxPair,
     772                                         pszKey, cbKey, pcbKeyActual, pszValue, cbValue, pcbValueActual);
     773    else
     774    {
     775        rc = VERR_NOT_FOUND;
     776        uint32_t const cchSection = (uint32_t)strlen(pszSection);
     777        for (uint32_t iSection = 1; iSection < pThis->cSections; iSection++)
     778            if (   pThis->paSections[iSection].cchName == cchSection
     779                && RTStrNICmp(&pThis->pszFile[pThis->paSections[iSection].offName], pszSection, cchSection) == 0)
     780            {
     781                rc = rtIniFileQueryPairInSection(pThis, &pThis->paSections[iSection], &idxPair,
     782                                                 pszKey, cbKey, pcbKeyActual, pszValue, cbValue, pcbValueActual);
     783                if (rc != VERR_NOT_FOUND)
     784                    break;
     785            }
     786    }
     787    return rc;
     788}
     789
Note: See TracChangeset for help on using the changeset viewer.

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