File: buffer.c

package info (click to toggle)
gensio 2.2.4-1
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 2,776 kB
  • sloc: ansic: 45,195; python: 2,718; cpp: 1,129; sh: 586; makefile: 420
file content (127 lines) | stat: -rw-r--r-- 2,468 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/*
 *  gensio - A library for abstracting stream I/O
 *  Copyright (C) 2018  Corey Minyard <minyard@acm.org>
 *
 *  SPDX-License-Identifier: LGPL-2.1-only
 */

#include "config.h"
#include <stdlib.h>
#include <string.h>
#include "buffer.h"

#include <gensio/gensio_err.h>

static int
do_write(buffer_do_write tdo_write, void *cb_data,
	 void  *buf, unsigned int buflen, unsigned int *written)
{
    int err = 0;
    unsigned int write_count;

    err = tdo_write(cb_data, buf, buflen, &write_count);
    if (!err)
	*written = write_count;

    return err;
}

int
buffer_write(buffer_do_write tdo_write, void *cb_data, struct sbuf *buf)
{
    int err;
    unsigned int write_count;
    int towrite1;
    int towrite2 = 0;

    if (buf->pos + buf->cursize > buf->maxsize) {
	towrite1 = buf->maxsize - buf->pos;
	towrite2 = buf->cursize - towrite1;
    } else {
	towrite1 = buf->cursize;
    }

    if (towrite1 > 0) {
	err = do_write(tdo_write, cb_data,
		       buf->buf + buf->pos, towrite1, &write_count);
	if (err)
	    return err;

	buf->pos += write_count;
	buf->cursize -= write_count;
	if (write_count < towrite1)
	    return 0;
    }

    if (towrite2 > 0) {
	/* We wrapped */
	buf->pos = 0;
	err = do_write(tdo_write, cb_data, buf->buf, towrite2, &write_count);
	if (err)
	    return err;
	buf->pos += write_count;
	buf->cursize -= write_count;
    }

    return 0;
}

unsigned int
buffer_output(struct sbuf *buf, const unsigned char *data, unsigned int len)
{
    int end;

    if (buffer_left(buf) < len)
	len = buffer_left(buf);

    end = buf->pos + buf->cursize;
    if (end > buf->maxsize)
	end -= buf->maxsize;
    if (end + len > buf->maxsize) {
	int availend = buf->maxsize - end;

	memcpy(buf->buf + end, data, availend);
	buf->cursize += availend;
	end = 0;
	len -= availend;
	data += availend;
    }
    memcpy(buf->buf + end, data, len);
    buf->cursize += len;

    return len;
}

unsigned int
buffer_outchar(struct sbuf *buf, unsigned char data)
{
    int end;

    if (buffer_left(buf) < 1)
	return 0;

    end = buf->pos + buf->cursize;
    if (end >= buf->maxsize)
	end -= buf->maxsize;
    buf->buf[end] = data;
    buf->cursize += 1;

    return 1;
}

int
buffer_init(struct sbuf *buf, unsigned char *data, unsigned int datasize)
{
    if (data) {
	buf->buf = data;
    } else {
	buf->buf = malloc(datasize);
	if (!buf->buf)
	    return GE_NOMEM;
    }
    buf->maxsize = datasize;
    buf->cursize = 0;
    buf->pos = 0;

    return 0;
}