dmcardle | 2b64f50 | 2020-01-07 15:22:36 -0800 | [diff] [blame] | 1 | // Copyright (c) 2020 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 | #ifndef QUICHE_COMMON_QUICHE_DATA_WRITER_H_ |
| 6 | #define QUICHE_COMMON_QUICHE_DATA_WRITER_H_ |
| 7 | |
| 8 | #include <cstddef> |
| 9 | #include <cstdint> |
vasilvv | 0a09b8f | 2020-04-27 08:08:55 -0700 | [diff] [blame] | 10 | #include <cstring> |
dmcardle | 2b64f50 | 2020-01-07 15:22:36 -0800 | [diff] [blame] | 11 | #include <limits> |
| 12 | |
vasilvv | 652cd42 | 2020-10-09 15:50:02 -0700 | [diff] [blame] | 13 | #include "absl/strings/string_view.h" |
QUICHE team | 5be974e | 2020-12-29 18:35:24 -0500 | [diff] [blame] | 14 | #include "common/platform/api/quiche_export.h" |
| 15 | #include "common/platform/api/quiche_logging.h" |
| 16 | #include "common/quiche_endian.h" |
dmcardle | 2b64f50 | 2020-01-07 15:22:36 -0800 | [diff] [blame] | 17 | |
| 18 | namespace quiche { |
| 19 | |
| 20 | // This class provides facilities for packing binary data. |
| 21 | // |
| 22 | // The QuicheDataWriter supports appending primitive values (int, string, etc) |
| 23 | // to a frame instance. The internal memory buffer is exposed as the "data" |
| 24 | // of the QuicheDataWriter. |
| 25 | class QUICHE_EXPORT_PRIVATE QuicheDataWriter { |
| 26 | public: |
| 27 | // Creates a QuicheDataWriter where |buffer| is not owned |
| 28 | // using NETWORK_BYTE_ORDER endianness. |
| 29 | QuicheDataWriter(size_t size, char* buffer); |
| 30 | // Creates a QuicheDataWriter where |buffer| is not owned |
| 31 | // using the specified endianness. |
| 32 | QuicheDataWriter(size_t size, char* buffer, quiche::Endianness endianness); |
| 33 | QuicheDataWriter(const QuicheDataWriter&) = delete; |
| 34 | QuicheDataWriter& operator=(const QuicheDataWriter&) = delete; |
| 35 | |
| 36 | ~QuicheDataWriter(); |
| 37 | |
| 38 | // Returns the size of the QuicheDataWriter's data. |
| 39 | size_t length() const { return length_; } |
| 40 | |
| 41 | // Retrieves the buffer from the QuicheDataWriter without changing ownership. |
| 42 | char* data(); |
| 43 | |
| 44 | // Methods for adding to the payload. These values are appended to the end |
| 45 | // of the QuicheDataWriter payload. |
| 46 | |
| 47 | // Writes 8/16/32/64-bit unsigned integers. |
| 48 | bool WriteUInt8(uint8_t value); |
| 49 | bool WriteUInt16(uint16_t value); |
| 50 | bool WriteUInt32(uint32_t value); |
| 51 | bool WriteUInt64(uint64_t value); |
| 52 | |
| 53 | // Writes least significant |num_bytes| of a 64-bit unsigned integer in the |
| 54 | // correct byte order. |
| 55 | bool WriteBytesToUInt64(size_t num_bytes, uint64_t value); |
| 56 | |
vasilvv | 652cd42 | 2020-10-09 15:50:02 -0700 | [diff] [blame] | 57 | bool WriteStringPiece(absl::string_view val); |
| 58 | bool WriteStringPiece16(absl::string_view val); |
dmcardle | 2b64f50 | 2020-01-07 15:22:36 -0800 | [diff] [blame] | 59 | bool WriteBytes(const void* data, size_t data_len); |
| 60 | bool WriteRepeatedByte(uint8_t byte, size_t count); |
| 61 | // Fills the remaining buffer with null characters. |
| 62 | void WritePadding(); |
| 63 | // Write padding of |count| bytes. |
| 64 | bool WritePaddingBytes(size_t count); |
| 65 | |
| 66 | // Write tag as a 32-bit unsigned integer to the payload. As tags are already |
| 67 | // converted to big endian (e.g., CHLO is 'C','H','L','O') in memory by TAG or |
| 68 | // MakeQuicTag and tags are written in byte order, so tags on the wire are |
| 69 | // in big endian. |
| 70 | bool WriteTag(uint32_t tag); |
| 71 | |
| 72 | // Advance the writer's position for writing by |length| bytes without writing |
| 73 | // anything. This method only makes sense to be used on a buffer that has |
| 74 | // already been written to (and is having certain parts rewritten). |
| 75 | bool Seek(size_t length); |
| 76 | |
| 77 | size_t capacity() const { return capacity_; } |
| 78 | |
| 79 | size_t remaining() const { return capacity_ - length_; } |
| 80 | |
| 81 | std::string DebugString() const; |
| 82 | |
| 83 | protected: |
| 84 | // Returns the location that the data should be written at, or nullptr if |
| 85 | // there is not enough room. Call EndWrite with the returned offset and the |
| 86 | // given length to pad out for the next write. |
| 87 | char* BeginWrite(size_t length); |
| 88 | |
| 89 | quiche::Endianness endianness() const { return endianness_; } |
| 90 | |
| 91 | char* buffer() const { return buffer_; } |
| 92 | |
| 93 | void IncreaseLength(size_t delta) { |
vasilvv | b38e023 | 2021-02-02 15:20:07 -0800 | [diff] [blame] | 94 | QUICHE_DCHECK_LE(length_, std::numeric_limits<size_t>::max() - delta); |
| 95 | QUICHE_DCHECK_LE(length_, capacity_ - delta); |
dmcardle | 2b64f50 | 2020-01-07 15:22:36 -0800 | [diff] [blame] | 96 | length_ += delta; |
| 97 | } |
| 98 | |
| 99 | private: |
| 100 | // TODO(fkastenholz, b/73004262) change buffer_, et al, to be uint8_t, not |
| 101 | // char. |
| 102 | char* buffer_; |
| 103 | size_t capacity_; // Allocation size of payload (or -1 if buffer is const). |
| 104 | size_t length_; // Current length of the buffer. |
| 105 | |
| 106 | // The endianness to write integers and floating numbers. |
| 107 | quiche::Endianness endianness_; |
| 108 | }; |
| 109 | |
| 110 | } // namespace quiche |
| 111 | |
| 112 | #endif // QUICHE_COMMON_QUICHE_DATA_WRITER_H_ |