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 14 using base::StringPiece; 15 using std::numeric_limits; 16 17 namespace net { 18 19 QuicDataWriter::QuicDataWriter(size_t size) 20 : buffer_(new char[size]), 21 capacity_(size), 22 length_(0) { 23 } 24 25 QuicDataWriter::~QuicDataWriter() { 26 delete[] buffer_; 27 } 28 29 char* QuicDataWriter::take() { 30 char* rv = buffer_; 31 buffer_ = NULL; 32 capacity_ = 0; 33 length_ = 0; 34 return rv; 35 } 36 37 bool QuicDataWriter::WriteUInt8(uint8 value) { 38 return WriteBytes(&value, sizeof(value)); 39 } 40 41 bool QuicDataWriter::WriteUInt16(uint16 value) { 42 return WriteBytes(&value, sizeof(value)); 43 } 44 45 bool QuicDataWriter::WriteUInt32(uint32 value) { 46 return WriteBytes(&value, sizeof(value)); 47 } 48 49 bool 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 55 bool QuicDataWriter::WriteUInt64(uint64 value) { 56 return WriteBytes(&value, sizeof(value)); 57 } 58 59 bool 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 98 bool 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 108 bool 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 120 char* 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 136 bool 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 148 bool 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 160 void 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 169 bool QuicDataWriter::WriteUInt8ToOffset(uint8 value, size_t offset) { 170 DCHECK_LT(offset, capacity_); 171 size_t latched_length = length_; 172 length_ = offset; 173 bool success = WriteUInt8(value); 174 DCHECK_LE(length_, latched_length); 175 length_ = latched_length; 176 return success; 177 } 178 179 bool QuicDataWriter::WriteUInt32ToOffset(uint32 value, size_t offset) { 180 DCHECK_LT(offset, capacity_); 181 size_t latched_length = length_; 182 length_ = offset; 183 bool success = WriteUInt32(value); 184 DCHECK_LE(length_, latched_length); 185 length_ = latched_length; 186 return success; 187 } 188 189 bool QuicDataWriter::WriteUInt48ToOffset(uint64 value, size_t offset) { 190 DCHECK_LT(offset, capacity_); 191 size_t latched_length = length_; 192 length_ = offset; 193 bool success = WriteUInt48(value); 194 DCHECK_LE(length_, latched_length); 195 length_ = latched_length; 196 return success; 197 } 198 199 } // namespace net 200