blob: 093b04d0f69fb27aa40a8d8bbb91b283cdfe8996 [file] [log] [blame]
// Copyright 2017 Google Inc. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "nb/multipart_allocator.h"
#include <algorithm>
#include "starboard/log.h"
#include "starboard/memory.h"
namespace nb {
MultipartAllocator::Allocations::Allocations(void* buffer, int buffer_size)
: number_of_buffers_(1),
buffers_(&buffer_),
buffer_sizes_(&buffer_size_),
buffer_(buffer),
buffer_size_(buffer_size) {
SB_DCHECK(buffer != NULL);
SB_DCHECK(buffer_size > 0);
}
MultipartAllocator::Allocations::Allocations(int number_of_buffers,
void** buffers,
const int* buffer_sizes)
: number_of_buffers_(0), buffers_(NULL), buffer_sizes_(NULL) {
SB_DCHECK(number_of_buffers > 0);
SB_DCHECK(buffers != NULL);
SB_DCHECK(buffer_sizes != NULL);
Assign(number_of_buffers, buffers, buffer_sizes);
for (int i = 0; i < number_of_buffers_; ++i) {
SB_DCHECK(buffers_[i] != NULL);
SB_DCHECK(buffer_sizes_[i] > 0);
}
}
MultipartAllocator::Allocations::Allocations(const Allocations& that)
: number_of_buffers_(0), buffers_(NULL), buffer_sizes_(NULL) {
Assign(that.number_of_buffers_, that.buffers_, that.buffer_sizes_);
}
MultipartAllocator::Allocations::~Allocations() {
Destroy();
}
MultipartAllocator::Allocations& MultipartAllocator::Allocations::operator=(
const Allocations& that) {
Destroy();
Assign(that.number_of_buffers_, that.buffers_, that.buffer_sizes_);
return *this;
}
int MultipartAllocator::Allocations::size() const {
int size = 0;
for (size_t i = 0; i < number_of_buffers_; ++i) {
size += buffer_sizes_[i];
}
return size;
}
void MultipartAllocator::Allocations::ShrinkTo(int size) {
for (size_t i = 0; i < number_of_buffers_; ++i) {
if (size >= buffer_sizes_[i]) {
size -= buffer_sizes_[i];
} else {
buffer_sizes_[i] = size;
size = 0;
++i;
while (i < number_of_buffers_) {
buffer_sizes_[i] = 0;
++i;
}
break;
}
}
SB_DCHECK(size == 0);
}
void MultipartAllocator::Allocations::Write(int destination_offset,
const void* src,
int size) {
size_t buffer_index = 0;
const uint8_t* src_in_uint8 = static_cast<const uint8_t*>(src);
while (size > 0) {
if (buffer_index >= number_of_buffers_) {
SB_NOTREACHED();
return;
}
if (buffer_sizes_[buffer_index] <= destination_offset) {
destination_offset -= buffer_sizes_[buffer_index];
} else {
int bytes_to_copy =
std::min(size, buffer_sizes_[buffer_index] - destination_offset);
uint8_t* destination_in_uint8 =
static_cast<uint8_t*>(buffers_[buffer_index]);
SbMemoryCopy(destination_in_uint8 + destination_offset, src_in_uint8,
bytes_to_copy);
destination_offset = 0;
src_in_uint8 += bytes_to_copy;
size -= bytes_to_copy;
}
++buffer_index;
}
}
void MultipartAllocator::Allocations::Read(void* destination) const {
uint8_t* destination_in_uint8 = static_cast<uint8_t*>(destination);
for (size_t i = 0; i < number_of_buffers_; ++i) {
SbMemoryCopy(destination_in_uint8, buffers_[i], buffer_sizes_[i]);
destination_in_uint8 += buffer_sizes_[i];
}
}
void MultipartAllocator::Allocations::Assign(int number_of_buffers,
void** buffers,
const int* buffer_sizes) {
SB_DCHECK(number_of_buffers_ == 0);
SB_DCHECK(buffers_ == NULL);
SB_DCHECK(buffer_sizes_ == NULL);
number_of_buffers_ = number_of_buffers;
if (number_of_buffers_ == 0) {
buffers_ = NULL;
buffer_sizes_ = NULL;
return;
}
if (number_of_buffers_ == 1) {
buffers_ = &buffer_;
buffer_sizes_ = &buffer_size_;
buffer_ = buffers[0];
buffer_size_ = buffer_sizes[0];
return;
}
buffers_ = new void*[number_of_buffers_];
buffer_sizes_ = new int[number_of_buffers_];
SbMemoryCopy(buffers_, buffers, sizeof(*buffers_) * number_of_buffers_);
SbMemoryCopy(buffer_sizes_, buffer_sizes,
sizeof(*buffer_sizes_) * number_of_buffers_);
}
void MultipartAllocator::Allocations::Destroy() {
if (number_of_buffers_ > 1) {
delete[] buffers_;
delete[] buffer_sizes_;
}
number_of_buffers_ = 0;
buffers_ = NULL;
buffer_sizes_ = NULL;
}
} // namespace nb