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