/**
 * Sets the user argument for a type.
 *
 * This can be used if a user argument needs relocating in GC.
 *
 * @returns IPRT status code.
 * @retval  VINF_SUCCESS on success.
 * @retval  VERR_FILE_NOT_FOUND if not found.
 *
 * @param   pszType     The type to update.
 * @param   pvUser      The new user argument value.
 */
RTDECL(int) RTStrFormatTypeSetUser(const char *pszType, void *pvUser)
{
    int32_t i;

    /*
     * Validate input.
     */
    AssertPtr(pszType);

    /*
     * Locate the entry and update it.
     */
    rtstrFormatTypeReadLock();

    i = rtstrFormatTypeLookup(pszType, strlen(pszType));
    if (i >= 0)
        ASMAtomicWritePtr(&g_aTypes[i].pvUser, pvUser);

    rtstrFormatTypeReadUnlock();

    Assert(i >= 0);
    return i >= 0
         ? VINF_SUCCESS
         : VERR_FILE_NOT_FOUND; /** @todo fix status code */
}
Ejemplo n.º 2
0
/**
 * Formats a type using a registered callback handler.
 *
 * This will handle %R[type].
 *
 * @returns The number of bytes formatted.
 * @param   pfnOutput       Pointer to output function.
 * @param   pvArgOutput     Argument for the output function.
 * @param   ppszFormat      Pointer to the format string pointer. Advance this till the char
 *                          after the format specifier.
 * @param   pArgs           Pointer to the argument list. Use this to fetch the arguments.
 * @param   cchWidth        Format Width. -1 if not specified.
 * @param   cchPrecision    Format Precision. -1 if not specified.
 * @param   fFlags          Flags (RTSTR_NTFS_*).
 * @param   chArgSize       The argument size specifier, 'l' or 'L'.
 */
DECLHIDDEN(size_t) rtstrFormatType(PFNRTSTROUTPUT pfnOutput, void *pvArgOutput, const char **ppszFormat,
                                   va_list *pArgs, int cchWidth, int cchPrecision, unsigned fFlags, char chArgSize)
{
    size_t      cch;
    int32_t     i;
    char const *pszTypeEnd;
    char const *pszType;
    char        ch;
    void       *pvValue = va_arg(*pArgs, void *);
    NOREF(chArgSize);

    /*
     * Parse out the type.
     */
    pszType = *ppszFormat + 2;
    *ppszFormat = pszType;
    Assert(pszType[-1] == '[');
    Assert(pszType[-2] == 'R');
    pszTypeEnd = pszType;
    while ((ch = *pszTypeEnd) != ']')
    {
        AssertReturn(ch != '\0', 0);
        AssertReturn(ch != '%', 0);
        AssertReturn(ch != '[', 0);
        pszTypeEnd++;
    }
    *ppszFormat = pszTypeEnd + 1;

    /*
     * Locate the entry and call the handler.
     */
    rtstrFormatTypeReadLock();

    i = rtstrFormatTypeLookup(pszType, pszTypeEnd - pszType);
    if (RT_LIKELY(i >= 0))
    {
#ifdef IN_RC
        PFNRTSTRFORMATTYPE pfnHandler = (PFNRTSTRFORMATTYPE)((intptr_t)&g_aTypes[0] + g_aTypes[i].offHandler);
#else
        PFNRTSTRFORMATTYPE pfnHandler = g_aTypes[i].pfnHandler;
#endif
        void *pvUser = ASMAtomicReadPtr(&g_aTypes[i].pvUser);

        rtstrFormatTypeReadUnlock();

        cch = pfnHandler(pfnOutput, pvArgOutput, g_aTypes[i].szType, pvValue, cchWidth, cchPrecision, fFlags, pvUser);
    }
    else
    {
        rtstrFormatTypeReadUnlock();

        cch  = pfnOutput(pvArgOutput, RT_STR_TUPLE("<missing:%R["));
        cch += pfnOutput(pvArgOutput, pszType, pszTypeEnd - pszType);
        cch += pfnOutput(pvArgOutput, RT_STR_TUPLE("]>"));
    }

    return cch;
}