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