blob: 4416d84428e28bd270f1ceefbe5a5996df9c97fa [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
QUICHE team5be974e2020-12-29 18:35:24 -05005#include "common/quiche_data_writer.h"
dmcardle2b64f502020-01-07 15:22:36 -08006
7#include <algorithm>
8#include <limits>
9
vasilvv6950cd82020-12-03 15:33:04 -080010#include "absl/strings/str_cat.h"
vasilvv652cd422020-10-09 15:50:02 -070011#include "absl/strings/string_view.h"
QUICHE team5be974e2020-12-29 18:35:24 -050012#include "common/quiche_endian.h"
dmcardle2b64f502020-01-07 15:22:36 -080013
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
vasilvv652cd422020-10-09 15:50:02 -070068bool QuicheDataWriter::WriteStringPiece16(absl::string_view val) {
dmcardle2b64f502020-01-07 15:22:36 -080069 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
vasilvv652cd422020-10-09 15:50:02 -070078bool QuicheDataWriter::WriteStringPiece(absl::string_view val) {
dmcardle2b64f502020-01-07 15:22:36 -080079 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
vasilvvb38e0232021-02-02 15:20:07 -080092 QUICHE_DCHECK_LE(length, std::numeric_limits<uint32_t>::max());
dmcardle2b64f502020-01-07 15:22:36 -080093#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() {
vasilvvb38e0232021-02-02 15:20:07 -0800123 QUICHE_DCHECK_LE(length_, capacity_);
dmcardle2b64f502020-01-07 15:22:36 -0800124 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 {
vasilvv6950cd82020-12-03 15:33:04 -0800148 return absl::StrCat(" { capacity: ", capacity_, ", length: ", length_, " }");
dmcardle2b64f502020-01-07 15:22:36 -0800149}
150
151} // namespace quiche