Home | History | Annotate | Download | only in quic
      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   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 
    182 bool 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 
    192 bool 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