Browse Source Download (without any required ccan dependencies)




bounded string builder with three valued comparator


Dan Good <>


xstring handles string concatenation to a buffer, flagging truncation. Additions can be transactional, where the addition wholly succeeds or the buffer is reterminated at its prior length. Once flagged, no further additions are allowed. Clearing reuses the buffer from the beginning.

When comparing two xstrings, the truncation state is taken into account. If either is truncated, an equality test returns unknown (-1). Testing if x contains y returns unknown (-1) if y is truncated. If x is whole, the test returns true (1) or false (0) appropriately. If x is truncated, the test returns true (1) if the known portion of x contains y, and unknown (-1) otherwise.

The structure members are intended for direct access.


// demo - break long lines
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <err.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>

#include "ccan/xstring/xstring.h"

#define MAXLEN 80
#define MARGIN 10
int main(int argc, char *argv[])
        char buf[BUFSIZ];
        xstring _x, *x = &_x;
        struct stat sb;
        int fd, span, lnlen;
        char *map, *p, *q;

        xstrInit(x, buf, sizeof(buf), 0);
        assert(sizeof(buf) > MAXLEN);

        if (argc != 2) return 1;

        if ((fd = open(argv[1], O_RDONLY)) == -1)
                err(1, "open");
        if (fstat(fd, &sb) == -1)
                err(1, "stat");
        if ((map = mmap(NULL, sb.st_size + 1, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0)) == MAP_FAILED)
                err(1, "mmap");
        map[sb.st_size] = '\n';

        for (p = map, lnlen = 0; p < map + sb.st_size; ) {
                span = strcspn(p, " \t\n") + 1;

                if (lnlen + span > MAXLEN) {
                        span = MAXLEN - lnlen;
                        xstrAddSubsT(x, p, span, "\n", 1, NULL);
                        xstrAddSubT(x, p, span);

                if (x->truncated) {
                        fputs(x->str, stdout);
                        continue; // p unchanged

                q = x->str + x->len - 1;
                if (lnlen + MARGIN > MAXLEN)
                        *q = '\n';

                lnlen = *q == '\n' ? 0 : lnlen + span;
                p += span;

        if (x->len)
                fputs(x->str, stdout);

        return 0;