blob: 4488f722ec5c20c327afcfb74387f4d9c1bf1577 [file] [log] [blame]
dmcardle2b64f502020-01-07 15:22:36 -08001// 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/third_party/quiche/src/common/quiche_data_writer.h"
6
7#include <algorithm>
8#include <limits>
9
10#include "net/third_party/quiche/src/common/platform/api/quiche_endian.h"
11#include "net/third_party/quiche/src/common/platform/api/quiche_str_cat.h"
12#include "net/third_party/quiche/src/common/platform/api/quiche_string_piece.h"
13
14namespace quiche {
15
16QuicheDataWriter::QuicheDataWriter(size_t size, char* buffer)
17 : QuicheDataWriter(size, buffer, quiche::NETWORK_BYTE_ORDER) {}
18
19QuicheDataWriter::QuicheDataWriter(size_t size,
20 char* buffer,
21 quiche::Endianness endianness)
22 : buffer_(buffer), capacity_(size), length_(0), endianness_(endianness) {}
23
24QuicheDataWriter::~QuicheDataWriter() {}
25
26char* QuicheDataWriter::data() {
27 return buffer_;
28}
29
30bool QuicheDataWriter::WriteUInt8(uint8_t value) {
31 return WriteBytes(&value, sizeof(value));
32}
33
34bool QuicheDataWriter::WriteUInt16(uint16_t value) {
35 if (endianness_ == quiche::NETWORK_BYTE_ORDER) {
36 value = quiche::QuicheEndian::HostToNet16(value);
37 }
38 return WriteBytes(&value, sizeof(value));
39}
40
41bool QuicheDataWriter::WriteUInt32(uint32_t value) {
42 if (endianness_ == quiche::NETWORK_BYTE_ORDER) {
43 value = quiche::QuicheEndian::HostToNet32(value);
44 }
45 return WriteBytes(&value, sizeof(value));
46}
47
48bool QuicheDataWriter::WriteUInt64(uint64_t value) {
49 if (endianness_ == quiche::NETWORK_BYTE_ORDER) {
50 value = quiche::QuicheEndian::HostToNet64(value);
51 }
52 return WriteBytes(&value, sizeof(value));
53}
54
55bool QuicheDataWriter::WriteBytesToUInt64(size_t num_bytes, uint64_t value) {
56 if (num_bytes > sizeof(value)) {
57 return false;
58 }
59 if (endianness_ == quiche::HOST_BYTE_ORDER) {
60 return WriteBytes(&value, num_bytes);
61 }
62
63 value = quiche::QuicheEndian::HostToNet64(value);
64 return WriteBytes(reinterpret_cast<char*>(&value) + sizeof(value) - num_bytes,
65 num_bytes);
66}
67
68bool QuicheDataWriter::WriteStringPiece16(quiche::QuicheStringPiece val) {
69 if (val.size() > std::numeric_limits<uint16_t>::max()) {
70 return false;
71 }
72 if (!WriteUInt16(static_cast<uint16_t>(val.size()))) {
73 return false;
74 }
75 return WriteBytes(val.data(), val.size());
76}
77
78bool QuicheDataWriter::WriteStringPiece(quiche::QuicheStringPiece val) {
79 return WriteBytes(val.data(), val.size());
80}
81
82char* QuicheDataWriter::BeginWrite(size_t length) {
83 if (length_ > capacity_) {
84 return nullptr;
85 }
86
87 if (capacity_ - length_ < length) {
88 return nullptr;
89 }
90
91#ifdef ARCH_CPU_64_BITS
92 DCHECK_LE(length, std::numeric_limits<uint32_t>::max());
93#endif
94
95 return buffer_ + length_;
96}
97
98bool QuicheDataWriter::WriteBytes(const void* data, size_t data_len) {
99 char* dest = BeginWrite(data_len);
100 if (!dest) {
101 return false;
102 }
103
104 memcpy(dest, data, data_len);
105
106 length_ += data_len;
107 return true;
108}
109
110bool QuicheDataWriter::WriteRepeatedByte(uint8_t byte, size_t count) {
111 char* dest = BeginWrite(count);
112 if (!dest) {
113 return false;
114 }
115
116 memset(dest, byte, count);
117
118 length_ += count;
119 return true;
120}
121
122void QuicheDataWriter::WritePadding() {
123 DCHECK_LE(length_, capacity_);
124 if (length_ > capacity_) {
125 return;
126 }
127 memset(buffer_ + length_, 0x00, capacity_ - length_);
128 length_ = capacity_;
129}
130
131bool QuicheDataWriter::WritePaddingBytes(size_t count) {
132 return WriteRepeatedByte(0x00, count);
133}
134
135bool QuicheDataWriter::WriteTag(uint32_t tag) {
136 return WriteBytes(&tag, sizeof(tag));
137}
138
139bool QuicheDataWriter::Seek(size_t length) {
140 if (!BeginWrite(length)) {
141 return false;
142 }
143 length_ += length;
144 return true;
145}
146
147std::string QuicheDataWriter::DebugString() const {
148 return quiche::QuicheStrCat(" { capacity: ", capacity_, ", length: ", length_,
149 " }");
150}
151
152} // namespace quiche