Welcome to little lamb

Code » limb » release » tree

[release] / src / liblimb / copa.h / copa_next.c

/* This file is part of limb                           https://lila.oss/limb
 * Copyright (C) 2023 Olivier Brunel                          jjk@jjacky.com */
/* SPDX-License-Identifier: GPL-2.0-only */
#include <ctype.h>
#include <errno.h>
#include <limb/bytestr.h>
#include <limb/copa.h>

int
copa_next(struct copa *ctx)
{
    /* not the first line? */
    if (ctx->nlen)
        /* move to the next line */
        ctx->noff += byte_chr(copa_name(ctx), ctx->dlen - ctx->noff, '\n');

    /* move past spaces */
    while (ctx->noff < ctx->dlen && isspace(ctx->data[ctx->noff]))
        ++ctx->noff;
    /* EOF */
    if (ctx->noff == ctx->dlen)
        return 0;

    /* comments */
    if (ctx->data[ctx->noff] == ';' || ctx->data[ctx->noff] == '#')
        return (++ctx->nlen, copa_next(ctx));

    /* search for end of line */
    ctx->nlen = byte_chr(copa_name(ctx), ctx->dlen - ctx->noff, '\n');

    /* search for an '=' sign, i.e. a value */
    ctx->voff = byte_chr(copa_name(ctx), ctx->nlen, '=');
    if (ctx->voff == ctx->nlen) {
        /* no value */
        ctx->vlen = 0;

        /* remove trailing spaces on name */
        while (ctx->nlen && isspace(ctx->data[ctx->noff + ctx->nlen - 1]))
            --ctx->nlen;

        /* section? */
        if (ctx->data[ctx->noff] == '[' && ctx->data[ctx->noff + ctx->nlen - 1] == ']') {
            ++ctx->noff;
            ctx->nlen -= 2;
        }

        /* no section name ("[]") */
        if (!ctx->nlen) return (errno = ENODATA, -1);

        return 1;
    }

    /* adjust offsets/lengths */
    ctx->vlen = ctx->nlen - ctx->voff - 1;
    ctx->nlen = ctx->voff;
    ctx->voff += ctx->noff + 1;

    /* remove trailing spaces on name */
    while (ctx->nlen && isspace(ctx->data[ctx->noff + ctx->nlen - 1]))
        --ctx->nlen;

    /* nothing before '=' */
    if (!ctx->nlen) return (errno = EINVAL, -1);

    /* move value past spaces */
    while (ctx->vlen && isspace(ctx->data[ctx->voff])) {
        ++ctx->voff;
        --ctx->vlen;
    }

    /* nothing after '=' */
    if (!ctx->vlen) return (errno = ENOMSG, -1);

    /* remova trailing spaces on value */
    while (ctx->vlen && isspace(ctx->data[ctx->voff + ctx->vlen - 1]))
        --ctx->vlen;

    return 1;
}