| // Copyright 2017 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <assert.h> |
| #include <string.h> |
| |
| #include "pty-fifo.h" |
| |
| static_assert((PTY_FIFO_SIZE & (PTY_FIFO_SIZE - 1)) == 0, "fifo size not power of two"); |
| |
| #define PTY_FIFO_MASK (PTY_FIFO_SIZE - 1) |
| |
| size_t pty_fifo_write(pty_fifo_t* fifo, const void* data, size_t len, bool atomic) { |
| size_t avail = PTY_FIFO_SIZE - (fifo->head - fifo->tail); |
| if (avail < len) { |
| if (atomic) { |
| return 0; |
| } |
| len = avail; |
| } |
| |
| size_t offset = fifo->head & PTY_FIFO_MASK; |
| |
| avail = PTY_FIFO_SIZE - offset; |
| if (len <= avail) { |
| memcpy(fifo->data + offset, data, len); |
| } else { |
| memcpy(fifo->data + offset, data, avail); |
| auto p = static_cast<const uint8_t*>(data); |
| memcpy(fifo->data, p + avail, len - avail); |
| } |
| |
| fifo->head += static_cast<uint32_t>(len); |
| return len; |
| } |
| |
| size_t pty_fifo_read(pty_fifo_t* fifo, void* data, size_t len) { |
| size_t avail = fifo->head - fifo->tail; |
| if (avail < len) { |
| len = avail; |
| } |
| |
| size_t offset = fifo->tail & PTY_FIFO_MASK; |
| |
| avail = PTY_FIFO_SIZE - offset; |
| if (len <= avail) { |
| memcpy(data, fifo->data + offset, len); |
| } else { |
| memcpy(data, fifo->data + offset, avail); |
| auto p = static_cast<uint8_t*>(data); |
| memcpy(p + avail, fifo->data, len - avail); |
| } |
| |
| fifo->tail += static_cast<uint32_t>(len); |
| return len; |
| } |