1// Copyright 2017 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <assert.h>
6#include <string.h>
7
8#include "pty-fifo.h"
9
10static_assert((PTY_FIFO_SIZE & (PTY_FIFO_SIZE - 1)) == 0, "fifo size not power of two");
11
12#define PTY_FIFO_MASK (PTY_FIFO_SIZE - 1)
13
14size_t pty_fifo_write(pty_fifo_t* fifo, const void* data, size_t len, bool atomic) {
15    size_t avail = PTY_FIFO_SIZE - (fifo->head - fifo->tail);
16    if (avail < len) {
17        if (atomic) {
18            return 0;
19        }
20        len = avail;
21    }
22
23    size_t offset = fifo->head & PTY_FIFO_MASK;
24
25    avail = PTY_FIFO_SIZE - offset;
26    if (len <= avail) {
27        memcpy(fifo->data + offset, data, len);
28    } else {
29        memcpy(fifo->data + offset, data, avail);
30        memcpy(fifo->data, data + avail, len - avail);
31    }
32
33    fifo->head += len;
34    return len;
35}
36
37size_t pty_fifo_read(pty_fifo_t* fifo, void* data, size_t len) {
38    size_t avail = fifo->head - fifo->tail;
39    if (avail < len) {
40        len = avail;
41    }
42
43    size_t offset = fifo->tail & PTY_FIFO_MASK;
44
45    avail = PTY_FIFO_SIZE - offset;
46    if (len <= avail) {
47        memcpy(data, fifo->data + offset, len);
48    } else {
49        memcpy(data, fifo->data + offset, avail);
50        memcpy(data + avail, fifo->data, len - avail);
51    }
52
53    fifo->tail += len;
54    return len;
55}
56
57