src/server/util/writer.c

Sat, 30 Mar 2024 12:35:29 +0100

author
Olaf Wintermann <olaf.wintermann@gmail.com>
date
Sat, 30 Mar 2024 12:35:29 +0100
changeset 514
922bfe380c8e
parent 415
d938228c382e
permissions
-rw-r--r--

merge

/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright 2018 Olaf Wintermann. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   1. Redistributions of source code must retain the above copyright
 *      notice, this list of conditions and the following disclaimer.
 *
 *   2. Redistributions in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "writer.h"

void writer_init(Writer *w, SYS_NETFD fd, char *buf, size_t len) {
    w->fd = fd;
    w->write = (wr_writefunc)net_write;
    w->buffer = buf;
    w->size = len;
    w->pos = 0;
    w->error = 0;
}

void writer_init_with_stream(Writer *w, void *stream, wr_writefunc writefunc, char *buf, size_t len) {
    w->fd = stream;
    w->write = writefunc;
    w->buffer = buf;
    w->size = len;
    w->pos = 0;
    w->error = 0;
}

int writer_flush(Writer *w) {
    if(w->error) {
        return w->error;
    }
    
    size_t pos = 0;
    size_t len = w->pos;
    
    while(len > 0) {
        //fwrite(w->buffer+pos, 1, len, stdout);
        //fflush(stdout);
        ssize_t r = w->write(w->fd, w->buffer + pos, len);
        if(r <= 0) {
            break;
        }
        len -= r;
        pos += r;
    }
    
    if(pos != w->pos) {
        w->error = 1;
        return 1;
    }
    
    w->pos = 0;
    return 0;
}

int writer_put(Writer *w, const char *s, size_t len) {
    if(w->error) {
        return w->error;
    }
    
    // available bytes
    size_t a = w->size - w->pos;
    if(a == 0) {
        if(writer_flush(w)) {
            return 1;
        }
    }
    
    size_t cplen = len > a ? a : len; // number of bytes we can copy
    memcpy(w->buffer+w->pos, s, cplen);
    w->pos += cplen;
    
    if(cplen < len) {
        // not all bytes copied -> call writer_put again
        // the number of available bytes is 0 then, therefore flush is called
        return writer_put(w, s + cplen, len - cplen);
    } else {
        return 0;
    }
}

int writer_puts(Writer *w, cxstring s) {
    return writer_put(w, s.ptr, s.length);
}

int writer_putc(Writer *w, char c) {
    if(w->pos == w->size) {
        if(writer_flush(w)) {
            return 1;
        }
    }
    w->buffer[w->pos++] = c;
    return 0;
}

int writer_fwrite(const void *s, size_t size, size_t nelem, Writer *out) {
    int w = writer_put(out, s, size*nelem);
    return w/size;
}

mercurial