blob: db9ecea91b638bc960c4fc4d3a0352ba902ef252 [file] [log] [blame]
// Copyright 2019 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 "fifo.h"
#include <string.h>
static_assert((Fifo::kSize & (Fifo::kSize - 1)) == 0, "fifo size not power of two");
namespace {
constexpr uint32_t kFifoMask = Fifo::kSize - 1;
} // namespace
size_t Fifo::Write(const void* buf, size_t len, bool atomic) {
size_t avail = kSize - (head_ - tail_);
if (avail < len) {
if (atomic) {
return 0;
}
len = avail;
}
size_t offset = head_ & kFifoMask;
avail = kSize - offset;
if (len <= avail) {
memcpy(data_.data() + offset, buf, len);
} else {
memcpy(data_.data() + offset, buf, avail);
memcpy(data_.data(), reinterpret_cast<const uint8_t*>(buf) + avail, len - avail);
}
head_ += static_cast<uint32_t>(len);
return len;
}
size_t Fifo::Read(void* buf, size_t len) {
size_t avail = head_ - tail_;
if (avail < len) {
len = avail;
}
size_t offset = tail_ & kFifoMask;
avail = kSize - offset;
if (len <= avail) {
memcpy(buf, data_.data() + offset, len);
} else {
memcpy(buf, data_.data() + offset, avail);
memcpy(reinterpret_cast<uint8_t*>(buf) + avail, data_.data(), len - avail);
}
tail_ += static_cast<uint32_t>(len);
return len;
}