1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "net/quic/quic_data_writer.h"
6
7#include <algorithm>
8#include <limits>
9#include <string>
10
11#include "base/basictypes.h"
12#include "base/logging.h"
13
14using base::StringPiece;
15using std::numeric_limits;
16
17namespace net {
18
19QuicDataWriter::QuicDataWriter(size_t size)
20    : buffer_(new char[size]),
21      capacity_(size),
22      length_(0) {
23}
24
25QuicDataWriter::~QuicDataWriter() {
26  delete[] buffer_;
27}
28
29char* QuicDataWriter::take() {
30  char* rv = buffer_;
31  buffer_ = NULL;
32  capacity_ = 0;
33  length_ = 0;
34  return rv;
35}
36
37bool QuicDataWriter::WriteUInt8(uint8 value) {
38  return WriteBytes(&value, sizeof(value));
39}
40
41bool QuicDataWriter::WriteUInt16(uint16 value) {
42  return WriteBytes(&value, sizeof(value));
43}
44
45bool QuicDataWriter::WriteUInt32(uint32 value) {
46  return WriteBytes(&value, sizeof(value));
47}
48
49bool QuicDataWriter::WriteUInt48(uint64 value) {
50  uint32 hi = value >> 32;
51  uint32 lo = value & GG_UINT64_C(0x00000000FFFFFFFF);
52  return WriteUInt32(lo) && WriteUInt16(hi);
53}
54
55bool QuicDataWriter::WriteUInt64(uint64 value) {
56  return WriteBytes(&value, sizeof(value));
57}
58
59bool QuicDataWriter::WriteUFloat16(uint64 value) {
60  uint16 result;
61  if (value < (GG_UINT64_C(1) << kUFloat16MantissaEffectiveBits)) {
62    // Fast path: either the value is denormalized, or has exponent zero.
63    // Both cases are represented by the value itself.
64    result = value;
65  } else if (value >= kUFloat16MaxValue) {
66    // Value is out of range; clamp it to the maximum representable.
67    result = numeric_limits<uint16>::max();
68  } else {
69    // The highest bit is between position 13 and 42 (zero-based), which
70    // corresponds to exponent 1-30. In the output, mantissa is from 0 to 10,
71    // hidden bit is 11 and exponent is 11 to 15. Shift the highest bit to 11
72    // and count the shifts.
73    uint16 exponent = 0;
74    for (uint16 offset = 16; offset > 0; offset /= 2) {
75      // Right-shift the value until the highest bit is in position 11.
76      // For offset of 16, 8, 4, 2 and 1 (binary search over 1-30),
77      // shift if the bit is at or above 11 + offset.
78      if (value >= (GG_UINT64_C(1) << (kUFloat16MantissaBits + offset))) {
79        exponent += offset;
80        value >>= offset;
81      }
82    }
83
84    DCHECK_GE(exponent, 1);
85    DCHECK_LE(exponent, kUFloat16MaxExponent);
86    DCHECK_GE(value, GG_UINT64_C(1) << kUFloat16MantissaBits);
87    DCHECK_LT(value, GG_UINT64_C(1) << kUFloat16MantissaEffectiveBits);
88
89    // Hidden bit (position 11) is set. We should remove it and increment the
90    // exponent. Equivalently, we just add it to the exponent.
91    // This hides the bit.
92    result = value + (exponent << kUFloat16MantissaBits);
93  }
94
95  return WriteBytes(&result, sizeof(result));
96}
97
98bool QuicDataWriter::WriteStringPiece16(StringPiece val) {
99  if (val.length() > numeric_limits<uint16>::max()) {
100    return false;
101  }
102  if (!WriteUInt16(val.size())) {
103    return false;
104  }
105  return WriteBytes(val.data(), val.size());
106}
107
108bool QuicDataWriter::WriteIOVector(const IOVector& data) {
109  char *dest = BeginWrite(data.TotalBufferSize());
110  if (!dest) {
111    return false;
112  }
113  for (size_t i = 0; i < data.Size(); ++i) {
114    WriteBytes(data.iovec()[i].iov_base,  data.iovec()[i].iov_len);
115  }
116
117  return true;
118}
119
120char* QuicDataWriter::BeginWrite(size_t length) {
121  if (length_ > capacity_) {
122    return NULL;
123  }
124
125  if (capacity_ - length_ < length) {
126    return NULL;
127  }
128
129#ifdef ARCH_CPU_64_BITS
130  DCHECK_LE(length, numeric_limits<uint32>::max());
131#endif
132
133  return buffer_ + length_;
134}
135
136bool QuicDataWriter::WriteBytes(const void* data, size_t data_len) {
137  char* dest = BeginWrite(data_len);
138  if (!dest) {
139    return false;
140  }
141
142  memcpy(dest, data, data_len);
143
144  length_ += data_len;
145  return true;
146}
147
148bool QuicDataWriter::WriteRepeatedByte(uint8 byte, size_t count) {
149  char* dest = BeginWrite(count);
150  if (!dest) {
151    return false;
152  }
153
154  memset(dest, byte, count);
155
156  length_ += count;
157  return true;
158}
159
160void QuicDataWriter::WritePadding() {
161  DCHECK_LE(length_, capacity_);
162  if (length_ > capacity_) {
163    return;
164  }
165  memset(buffer_ + length_, 0x00, capacity_ - length_);
166  length_ = capacity_;
167}
168
169bool QuicDataWriter::WriteUInt8ToOffset(uint8 value, size_t offset) {
170  if (offset >= capacity_) {
171    LOG(DFATAL) << "offset: " << offset << " >= capacity: " << capacity_;
172    return false;
173  }
174  size_t latched_length = length_;
175  length_ = offset;
176  bool success = WriteUInt8(value);
177  DCHECK_LE(length_, latched_length);
178  length_ = latched_length;
179  return success;
180}
181
182bool QuicDataWriter::WriteUInt32ToOffset(uint32 value, size_t offset) {
183  DCHECK_LT(offset, capacity_);
184  size_t latched_length = length_;
185  length_ = offset;
186  bool success = WriteUInt32(value);
187  DCHECK_LE(length_, latched_length);
188  length_ = latched_length;
189  return success;
190}
191
192bool QuicDataWriter::WriteUInt48ToOffset(uint64 value, size_t offset) {
193  DCHECK_LT(offset, capacity_);
194  size_t latched_length = length_;
195  length_ = offset;
196  bool success = WriteUInt48(value);
197  DCHECK_LE(length_, latched_length);
198  length_ = latched_length;
199  return success;
200}
201
202}  // namespace net
203