1// Copyright (c) 2013 The Chromium 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 "nacl_io/fifo_char.h"
6
7#include <stdlib.h>
8#include <string.h>
9
10#include <algorithm>
11
12namespace nacl_io {
13
14FIFOChar::FIFOChar(size_t size)
15    : buffer_(NULL), size_(size), avail_(0), tail_(0) {
16  if (size)
17    buffer_ = new char[size];
18}
19
20FIFOChar::~FIFOChar() {
21  delete[] buffer_;
22}
23
24bool FIFOChar::IsEmpty() {
25  return avail_ == 0;
26}
27
28bool FIFOChar::IsFull() {
29  return avail_ >= size_;
30}
31
32bool FIFOChar::Resize(size_t len) {
33  // Can not resize smaller than the current size
34  if (len < avail_)
35    return false;
36
37  // Read current data into new buffer
38  char* data = new char[len];
39  avail_ = Read(data, avail_);
40
41  // Replace buffer
42  delete[] buffer_;
43  buffer_ = data;
44  size_ = len;
45  return true;
46}
47
48size_t FIFOChar::ReadAvailable() {
49  return avail_;
50}
51
52size_t FIFOChar::WriteAvailable() {
53  return size_ - avail_;
54}
55
56size_t FIFOChar::Peek(void* buf, size_t len) {
57  char* ptr = static_cast<char*>(buf);
58
59  size_t out = 0;
60  len = std::min(len, avail_);
61
62  size_t offs = tail_;
63  while (len > 0) {
64    size_t read_len = std::min(len, size_ - offs);
65    memcpy(ptr, &buffer_[offs], read_len);
66
67    ptr += read_len;
68    offs += read_len;
69
70    if (offs == size_)
71      offs = 0;
72
73    out += read_len;
74    len -= read_len;
75  }
76
77  return out;
78}
79
80size_t FIFOChar::Read(void* buf, size_t len) {
81  size_t read_len = Peek(buf, len);
82  if (read_len > 0) {
83    avail_ -= read_len;
84    tail_ = (tail_ + read_len) % size_;
85  }
86  return read_len;
87}
88
89size_t FIFOChar::Write(const void* buf, size_t len) {
90  const char* ptr = static_cast<const char*>(buf);
91  size_t out = 0;
92  size_t room = size_ - avail_;
93  len = std::min(len, room);
94
95  size_t offs = (tail_ + avail_) % size_;
96  while (len > 0) {
97    size_t write_len = std::min(len, size_ - offs);
98    memcpy(&buffer_[offs], ptr, write_len);
99
100    ptr += write_len;
101    offs += write_len;
102    if (offs == size_)
103      offs = 0;
104
105    out += write_len;
106    len -= write_len;
107  }
108
109  avail_ += out;
110  return out;
111}
112
113}  // namespace nacl_io
114