| // Copyright 2018 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef LIB_FIDL_CPP_BUILDER_H_ |
| #define LIB_FIDL_CPP_BUILDER_H_ |
| |
| #include <lib/fidl/cpp/message_part.h> |
| #include <stdalign.h> |
| #include <stdint.h> |
| #include <zircon/compiler.h> |
| #include <zircon/fidl.h> |
| #include <zircon/types.h> |
| |
| #include <new> // For placement new. |
| |
| namespace fidl { |
| |
| // Builder helps FIDL clients store decoded objects in a buffer. |
| // |
| // Objects are allocated sequentially in the buffer with appropriate alignment |
| // for in-place encoding. The client is responsible for ordering the objects in |
| // the buffer appropriately. |
| class Builder { |
| public: |
| // Creates a buffer without any storage. |
| Builder(); |
| |
| // Creates a buffer that stores objects in the given memory. |
| // |
| // The constructed |Builder| object does not take ownership of the given |
| // storage. |
| Builder(void* buffer, uint32_t capacity); |
| ~Builder(); |
| |
| Builder(const Builder& other) = delete; |
| Builder& operator=(const Builder& other) = delete; |
| |
| Builder(Builder&& other); |
| Builder& operator=(Builder&& other); |
| |
| // Allocates storage in the buffer of sufficient size to store an object of |
| // type |T|. The object must have alignment constraints that are compatible |
| // with FIDL messages. |
| // |
| // If there is insufficient storage in the builder's buffer, this method |
| // returns nullptr. |
| template <typename T> |
| T* New() { |
| static_assert(alignof(T) <= FIDL_ALIGNMENT, ""); |
| static_assert(sizeof(T) <= ZX_CHANNEL_MAX_MSG_BYTES, ""); |
| if (void* ptr = Allocate(sizeof(T))) |
| return new (ptr) T; |
| return nullptr; |
| } |
| |
| // Allocates storage in the buffer of sufficient size to store |count| |
| // objects of type |T|. The object must have alignment constraints that are |
| // compatible with FIDL messages. |
| // |
| // If there is insufficient storage in the builder's buffer, this method |
| // returns nullptr. |
| template <typename T> |
| T* NewArray(uint32_t count) { |
| static_assert(alignof(T) <= FIDL_ALIGNMENT, ""); |
| static_assert(sizeof(T) <= ZX_CHANNEL_MAX_MSG_BYTES, ""); |
| if (sizeof(T) * static_cast<uint64_t>(count) > UINT32_MAX) |
| return nullptr; |
| if (void* ptr = Allocate(static_cast<uint32_t>(sizeof(T) * count))) |
| return new (ptr) T[count]; |
| return nullptr; |
| } |
| |
| // Completes the building and returns a |MesssagePart| containing the |
| // allocated objects. |
| // |
| // The allocated objects are placed in the returned buffer in the order in |
| // which they were allocated, with appropriate alignment for a FIDL message. |
| // The returned buffer's capacity corresponds to the capacity originally |
| // provided to this builder in its constructor. |
| BytePart Finalize(); |
| |
| // Attaches the given storage to the |Builder|. |
| // |
| // The |Builder| object does not take ownership of the given storage. The |
| // next object will be allocated at the start of the buffer. |
| void Reset(void* buffer, uint32_t capacity); |
| |
| protected: |
| uint8_t* buffer() const { return buffer_; } |
| uint32_t capacity() const { return capacity_; } |
| |
| private: |
| // Returns |size| bytes of zeroed memory aligned to at least FIDL_ALIGNMENT |
| void* Allocate(uint32_t size); |
| |
| uint32_t capacity_; |
| uint32_t at_; |
| uint8_t* buffer_; |
| }; |
| |
| } // namespace fidl |
| |
| #endif // LIB_FIDL_CPP_BUILDER_H_ |