1c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Copyright (c) 2009 The Chromium Authors. All rights reserved. 2c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Use of this source code is governed by a BSD-style license that can be 3c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// found in the LICENSE file. 4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <limits> 6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "flip_frame_builder.h" // cross-google3 directory naming. 8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "flip_protocol.h" 9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace flip { 11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 12c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// We mark a read only FlipFrameBuilder with a special capacity_. 13c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic const size_t kCapacityReadOnly = std::numeric_limits<size_t>::max(); 14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottFlipFrameBuilder::FlipFrameBuilder() 16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott : buffer_(NULL), 17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott capacity_(0), 18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott length_(0), 19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott variable_buffer_offset_(0) { 20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott Resize(kInitialPayload); 21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottFlipFrameBuilder::FlipFrameBuilder(const char* data, int data_len) 24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott : buffer_(const_cast<char*>(data)), 25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott capacity_(kCapacityReadOnly), 26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott length_(data_len), 27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott variable_buffer_offset_(0) { 28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottFlipFrameBuilder::~FlipFrameBuilder() { 31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (capacity_ != kCapacityReadOnly) 32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delete[] buffer_; 33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool FlipFrameBuilder::ReadUInt16(void** iter, uint16* result) const { 36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(iter); 37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!*iter) 38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *iter = const_cast<char*>(buffer_); 39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!IteratorHasRoomFor(*iter, sizeof(*result))) 41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *result = ntohs(*(reinterpret_cast<uint16*>(*iter))); 44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott UpdateIter(iter, sizeof(*result)); 46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool FlipFrameBuilder::ReadUInt32(void** iter, uint32* result) const { 50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(iter); 51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!*iter) 52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *iter = const_cast<char*>(buffer_); 53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!IteratorHasRoomFor(*iter, sizeof(*result))) 55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *result = ntohl(*(reinterpret_cast<uint32*>(*iter))); 58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott UpdateIter(iter, sizeof(*result)); 60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool FlipFrameBuilder::ReadString(void** iter, std::string* result) const { 64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(iter); 65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott uint16 len; 67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!ReadUInt16(iter, &len)) 68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!IteratorHasRoomFor(*iter, len)) 71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char* chars = reinterpret_cast<char*>(*iter); 74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result->assign(chars, len); 75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott UpdateIter(iter, len); 77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 79c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool FlipFrameBuilder::ReadBytes(void** iter, const char** data, 81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott uint16 length) const { 82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(iter); 83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(data); 84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!IteratorHasRoomFor(*iter, length)) 86c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 87c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott *data = reinterpret_cast<const char*>(*iter); 89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott UpdateIter(iter, length); 91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool FlipFrameBuilder::ReadData(void** iter, const char** data, 95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott uint16* length) const { 96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(iter); 97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(data); 98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(length); 99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!ReadUInt16(iter, length)) 101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ReadBytes(iter, data, *length); 104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottchar* FlipFrameBuilder::BeginWrite(size_t length) { 107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t offset = length_; 108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott size_t needed_size = length_ + length; 109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (needed_size > capacity_ && !Resize(std::max(capacity_ * 2, needed_size))) 110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return NULL; 111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#ifdef ARCH_CPU_64_BITS 113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_LE(length, std::numeric_limits<uint32>::max()); 114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#endif 115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return buffer_ + offset; 117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid FlipFrameBuilder::EndWrite(char* dest, int length) { 120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool FlipFrameBuilder::WriteBytes(const void* data, uint16 data_len) { 123c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(capacity_ != kCapacityReadOnly); 124c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char* dest = BeginWrite(data_len); 126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!dest) 127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 129c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memcpy(dest, data, data_len); 130c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EndWrite(dest, data_len); 132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott length_ += data_len; 133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool FlipFrameBuilder::WriteString(const std::string& value) { 137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (value.size() > 0xffff) 138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!WriteUInt16(static_cast<int>(value.size()))) 141c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 142c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return WriteBytes(value.data(), static_cast<uint16>(value.size())); 144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottchar* FlipFrameBuilder::BeginWriteData(uint16 length) { 147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK_EQ(variable_buffer_offset_, 0U) << 148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott "There can only be one variable buffer in a FlipFrameBuilder"; 149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!WriteUInt16(length)) 151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char *data_ptr = BeginWrite(length); 154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!data_ptr) 155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return NULL; 156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott variable_buffer_offset_ = data_ptr - buffer_ - sizeof(int); 158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // EndWrite doesn't necessarily have to be called after the write operation, 160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // so we call it here to pad out what the caller will eventually write. 161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott EndWrite(data_ptr, length); 162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return data_ptr; 163c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool FlipFrameBuilder::Resize(size_t new_capacity) { 166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (new_capacity < capacity_) 167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char* p = new char[new_capacity]; 170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (buffer_) { 171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott memcpy(p, buffer_, capacity_); 172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott delete[] buffer_; 173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!p && new_capacity > 0) 175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return false; 176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott buffer_ = p; 177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott capacity_ = new_capacity; 178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return true; 179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} // namespace flip 182