Exemplo n.º 1
0
/* Copies a <sep>-delimited unit from <from> into a new entry in <to>.
 *
 * \<sep> is not counted as the separator, but copied to the new entry
 * as <sep>.  No other escape sequences are supported.
 *
 * Returns the number of bytes read out of <from>; this may be more
 * than the length of the new entry in <to>.  The new entry is
 * prepended; the caller can reverse <to> once built.
 */
static size_t SubStrnCopyChr(Rlist **to, const char *from, char sep, char lstrip)
{
    assert(from && from[0]);
    size_t offset = 0;

    while (lstrip != '\0' && from[0] == lstrip && from[0] != '\0')
    {
        /* Skip over all instances of the 'lstrip' character (e.g. ' ') if
         * specified */
        from++;
        offset++;
    }
    if (from[0] == '\0')
    {
        /* Reached the end already so there's nothing to add to the result list,
           just tell the caller how far they can move. */
        return offset;
    }

    const char *end = from;
    size_t escapes = 0;
    while (end && end[0] && end[0] != sep)
    {
        end = strchr(end, sep);
        assert(end == NULL || end[0] == sep);
        if (end && end > from && end[-1] == '\\')
        {
            escapes++;
            end++;
        }
    }

    size_t consume = (end == NULL) ? strlen(from) : (end - from);
    assert(consume >= escapes);
    char copy[1 + consume - escapes], *dst = copy;

    for (const char *src = from; src[0] != '\0' && src[0] != sep; src++)
    {
        if (src[0] == '\\' && src[1] == sep)
        {
            src++; /* Skip over the backslash so we copy the sep */
        }
        dst++[0] = src[0];
    }
    assert(dst + 1 == copy + sizeof(copy));
    *dst = '\0';

    /* Prepend to the list and reverse when done, costing O(len),
     * instead of appending, which costs O(len**2). */
    RlistPrependRval(to, RvalCopyScalar((Rval) { copy, RVAL_TYPE_SCALAR }));
    return offset + consume;
}
Exemplo n.º 2
0
Rlist *RlistPrepend(Rlist **start, const void *item, RvalType type)
{
    switch (type)
    {
    case RVAL_TYPE_LIST:
        {
            Rlist *lp = NULL;
            for (const Rlist *rp = item; rp; rp = rp->next)
            {
                lp = RlistPrependRval(start, RvalCopy(rp->val));
            }
            return lp;
        }

    case RVAL_TYPE_SCALAR:
    case RVAL_TYPE_FNCALL:
    case RVAL_TYPE_CONTAINER:
    case RVAL_TYPE_NOPROMISEE:
        return RlistPrependRval(start, RvalNew(item, type));
    }

    assert(false);
    return NULL;
}
Exemplo n.º 3
0
/* Copies a <sep>-delimited unit from <from> into a new entry in <to>.
 *
 * \<sep> is not counted as the separator, but copied to the new entry
 * as <sep>.  No other escape sequences are supported.
 *
 * Returns the number of bytes read out of <from>; this may be more
 * than the length of the new entry in <to>.  The new entry is
 * prepended; the caller can reverse <to> once built.
 */
static size_t SubStrnCopyChr(Rlist **to, const char *from, char sep)
{
    assert(from && from[0]);

    const char *end = from;
    size_t escapes = 0;
    while (end && end[0] && end[0] != sep)
    {
        end = strchr(end, sep);
        assert(end == NULL || end[0] == sep);
        if (end && end > from && end[-1] == '\\')
        {
            escapes++;
            end++;
        }
    }

    size_t consume = (end == NULL) ? strlen(from) : (end - from);
    assert(consume >= escapes);
    char copy[1 + consume - escapes], *dst = copy;

    for (const char *src = from; src[0] != '\0' && src[0] != sep; src++)
    {
        if (src[0] == '\\' && src[1] == sep)
        {
            src++; /* Skip over the backslash so we copy the sep */
        }
        dst++[0] = src[0];
    }
    assert(dst + 1 == copy + sizeof(copy));
    *dst = '\0';

    /* Prepend to the list and reverse when done, costing O(len),
     * instead of appending, which costs O(len**2). */
    RlistPrependRval(to, RvalCopyScalar((Rval) { copy, RVAL_TYPE_SCALAR }));
    return consume;
}
Exemplo n.º 4
0
static Rlist *RlistPrependFnCall(Rlist **start, const FnCall *fn)
{
    return RlistPrependRval(start, RvalCopyFnCall((Rval) { (FnCall *)fn, RVAL_TYPE_FNCALL }));
}
Exemplo n.º 5
0
Rlist *RlistPrependScalar(Rlist **start, const char *scalar)
{
    return RlistPrependRval(start, RvalCopyScalar((Rval) { (char *)scalar, RVAL_TYPE_SCALAR }));
}