15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/browser/speech/chunked_byte_buffer.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/lazy_instance.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const size_t kHeaderLength = sizeof(uint32); 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)COMPILE_ASSERT(sizeof(size_t) >= kHeaderLength, 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ChunkedByteBufferNotSupportedOnThisArchitecture); 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)uint32 ReadBigEndian32(const uint8* buffer) { 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return (static_cast<uint32>(buffer[3])) | 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (static_cast<uint32>(buffer[2]) << 8) | 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (static_cast<uint32>(buffer[1]) << 16) | 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (static_cast<uint32>(buffer[0]) << 24); 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace content { 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ChunkedByteBuffer::ChunkedByteBuffer() 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : partial_chunk_(new Chunk()), 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) total_bytes_stored_(0) { 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ChunkedByteBuffer::~ChunkedByteBuffer() { 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Clear(); 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ChunkedByteBuffer::Append(const uint8* start, size_t length) { 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t remaining_bytes = length; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const uint8* next_data = start; 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (remaining_bytes > 0) { 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(partial_chunk_ != NULL); 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t insert_length = 0; 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool header_completed = false; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool content_completed = false; 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::vector<uint8>* insert_target; 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (partial_chunk_->header.size() < kHeaderLength) { 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const size_t bytes_to_complete_header = 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kHeaderLength - partial_chunk_->header.size(); 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) insert_length = std::min(bytes_to_complete_header, remaining_bytes); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) insert_target = &partial_chunk_->header; 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) header_completed = (remaining_bytes >= bytes_to_complete_header); 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_LT(partial_chunk_->content->size(), 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) partial_chunk_->ExpectedContentLength()); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const size_t bytes_to_complete_chunk = 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) partial_chunk_->ExpectedContentLength() - 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) partial_chunk_->content->size(); 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) insert_length = std::min(bytes_to_complete_chunk, remaining_bytes); 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) insert_target = partial_chunk_->content.get(); 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) content_completed = (remaining_bytes >= bytes_to_complete_chunk); 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_GT(insert_length, 0U); 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_LE(insert_length, remaining_bytes); 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_LE(next_data + insert_length, start + length); 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) insert_target->insert(insert_target->end(), 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_data, 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_data + insert_length); 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) next_data += insert_length; 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) remaining_bytes -= insert_length; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (header_completed) { 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(partial_chunk_->header.size(), kHeaderLength); 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (partial_chunk_->ExpectedContentLength() == 0) { 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Handle zero-byte chunks. 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chunks_.push_back(partial_chunk_.release()); 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) partial_chunk_.reset(new Chunk()); 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) partial_chunk_->content->reserve( 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) partial_chunk_->ExpectedContentLength()); 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (content_completed) { 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(partial_chunk_->content->size(), 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) partial_chunk_->ExpectedContentLength()); 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chunks_.push_back(partial_chunk_.release()); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) partial_chunk_.reset(new Chunk()); 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(next_data, start + length); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) total_bytes_stored_ += length; 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ChunkedByteBuffer::Append(const std::string& string) { 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Append(reinterpret_cast<const uint8*>(string.data()), string.size()); 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ChunkedByteBuffer::HasChunks() const { 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return !chunks_.empty(); 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)scoped_ptr< std::vector<uint8> > ChunkedByteBuffer::PopChunk() { 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (chunks_.empty()) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return scoped_ptr< std::vector<uint8> >(); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<Chunk> chunk(*chunks_.begin()); 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chunks_.weak_erase(chunks_.begin()); 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(chunk->header.size(), kHeaderLength); 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(chunk->content->size(), chunk->ExpectedContentLength()); 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) total_bytes_stored_ -= chunk->content->size(); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) total_bytes_stored_ -= kHeaderLength; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return chunk->content.Pass(); 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ChunkedByteBuffer::Clear() { 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chunks_.clear(); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) partial_chunk_.reset(new Chunk()); 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) total_bytes_stored_ = 0; 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ChunkedByteBuffer::Chunk::Chunk() 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : content(new std::vector<uint8>()) { 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ChunkedByteBuffer::Chunk::~Chunk() { 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)size_t ChunkedByteBuffer::Chunk::ExpectedContentLength() const { 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK_EQ(header.size(), kHeaderLength); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return static_cast<size_t>(ReadBigEndian32(&header[0])); 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace content 137