blob: d8eb444c7b2d39106a459edc875d493151eb769d [file] [log] [blame]
// Copyright 2014 The Chromium 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 "common/circular_buffer.h"
#include <algorithm>
#include "common/alog.h"
namespace arc {
CircularBuffer::CircularBuffer() : buffer_(NULL), start_(0),
end_(0), capacity_(0), size_(0) {}
CircularBuffer::~CircularBuffer() {
delete[] buffer_;
}
void CircularBuffer::clear() {
start_ = 0;
end_ = 0;
size_ = 0;
}
void CircularBuffer::set_capacity(size_t capacity) {
if (capacity < size_)
ALOGW("Truncating circular buffer will result in loss of data");
size_t new_size = std::min(size_, capacity);
if (new_size == 0) {
// As there is no data to copy, we will first delete the old buffer so we
// minimize peak memory consumption.
delete[] buffer_;
buffer_ = NULL;
}
char* new_buffer = new char[capacity];
ALOG_ASSERT(new_buffer != NULL);
if (new_size > 0) {
ALOG_ASSERT(buffer_ != NULL);
read(new_buffer, new_size);
}
delete[] buffer_;
start_ = 0;
end_ = new_size;
size_ = new_size;
buffer_ = new_buffer;
capacity_ = capacity;
}
size_t CircularBuffer::write(const char* buf, size_t len) {
len = std::min(len, capacity_ - size_);
if (len <= capacity_ - end_) {
memcpy(buffer_ + end_, buf, len);
end_ += len;
} else {
size_t end_size = capacity_ - end_;
size_t front_size = len - end_size;
memcpy(buffer_ + end_, buf, end_size);
memcpy(buffer_, buf + end_size, front_size);
end_ = front_size;
}
size_ += len;
ALOG_ASSERT(size_ <= capacity_);
ALOG_ASSERT(len <= capacity_);
return len;
}
size_t CircularBuffer::read(char* buf, size_t len) {
size_t end_size = capacity_ - start_;
len = std::min(len, size_);
if (len == 0)
return len;
ALOG_ASSERT(buffer_ != NULL);
if (len <= end_size) {
memcpy(buf, buffer_ + start_, len);
start_ += len;
if (start_ == capacity_)
start_ = 0;
} else {
size_t start_size = len - end_size;
memcpy(buf, buffer_ + start_, end_size);
memcpy(buf + end_size, buffer_, start_size);
start_ = start_size;
}
size_ -= len;
ALOG_ASSERT(size_ <= capacity_);
ALOG_ASSERT(len <= capacity_);
return len;
}
} // namespace arc