| // 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. |
| |
| package templates |
| |
| const Table = ` |
| {{- define "TableForwardDeclaration" }} |
| class {{ .Name }}; |
| {{- end }} |
| |
| {{- define "TableDeclaration" }} |
| {{range .DocComments}} |
| //{{ . }} |
| {{- end}} |
| class {{ .Name }} { |
| public: |
| static const fidl_type_t* FidlType; |
| {{- range .Members }} |
| {{range .DocComments}} |
| //{{ . }} |
| {{- end}} |
| const {{ .Type.Decl }}* {{ .Name }}() const { |
| return {{ .FieldPresenceName }} ? &{{ .FieldDataName }}.value : nullptr; |
| } |
| bool {{ .MethodHasName }}() const { |
| return {{ .FieldPresenceName }}; |
| } |
| {{range .DocComments}} |
| //{{ . }} |
| {{- end}} |
| {{ .Type.Decl }}* mutable_{{ .Name }}() { |
| if (!{{ .FieldPresenceName }}) { |
| {{ .FieldPresenceName }} = true; |
| Construct(&{{ .FieldDataName }}.value); |
| } |
| return &{{ .FieldDataName }}.value; |
| } |
| void set_{{ .Name }}({{ .Type.Decl }} value) { |
| if (!{{ .FieldPresenceName }}) { |
| {{ .FieldPresenceName }} = true; |
| Construct(&{{ .FieldDataName }}.value, std::move(value)); |
| } else { |
| {{ .FieldDataName }}.value = std::move(value); |
| } |
| } |
| void {{ .MethodClearName }}() { |
| if (!{{ .FieldPresenceName }}) { |
| return; |
| } |
| {{ .FieldPresenceName }} = false; |
| Destruct(&{{ .FieldDataName }}.value); |
| } |
| {{- end }} |
| |
| {{ .Name }}(); |
| {{ .Name }}({{ .Name }}&& other); |
| ~{{ .Name }}(); |
| {{ .Name }}& operator=({{ .Name }}&& other); |
| |
| static inline ::std::unique_ptr<{{ .Name }}> New() { return ::std::make_unique<{{ .Name }}>(); } |
| |
| void Encode(::fidl::Encoder* encoder, size_t offset); |
| static void Decode(::fidl::Decoder* decoder, {{ .Name }}* value, size_t offset); |
| zx_status_t Clone({{ .Name }}* result) const; |
| |
| private: |
| template <class T, class... Args> |
| void Construct(T* p, Args&&... args) { |
| new (p) T(std::forward<Args>(args)...); |
| } |
| |
| template <class T> |
| void Destruct(T* p) { |
| p->~T(); |
| } |
| |
| {{- range .Members }} |
| bool {{ .FieldPresenceName }} : 1; |
| {{- end }} |
| |
| {{- range .Members }} |
| {{/* The raw values of a table field are placed inside a union to ensure |
| that they're not initialized (since table fields are optional by |
| default). Placement new must be used to initialize the value. */ -}} |
| union {{ .ValueUnionName }} { |
| {{ .ValueUnionName }}() {} |
| ~{{ .ValueUnionName }}() {} |
| |
| {{ .Type.Decl }} value; |
| }; |
| {{ .ValueUnionName }} {{ .FieldDataName }}; |
| {{- end }} |
| }; |
| |
| bool operator==(const {{ .Name }}& lhs, const {{ .Name }}& rhs); |
| inline bool operator!=(const {{ .Name }}& lhs, const {{ .Name }}& rhs) { |
| return !(lhs == rhs); |
| } |
| |
| using {{ .Name }}Ptr = ::std::unique_ptr<{{ .Name }}>; |
| {{- end }} |
| |
| {{- define "TableDefinition" }} |
| extern "C" const fidl_type_t {{ .TableType }}; |
| const fidl_type_t* {{ .Name }}::FidlType = &{{ .TableType }}; |
| |
| {{ .Name }}::{{ .Name }}() : |
| {{- range $index, $element := .Members }} |
| {{if $index}},{{end}} |
| has_{{ $element.Name }}_(false) |
| {{- end }} { |
| } |
| |
| {{ .Name }}::{{ .Name }}({{ .Name }}&& other) { |
| {{- range .Members }} |
| {{ .FieldPresenceName }} = other.{{ .FieldPresenceName }}; |
| if ({{ .FieldPresenceName }}) { |
| Construct(&{{ .FieldDataName }}.value, std::move(other.{{ .FieldDataName }}.value)); |
| } |
| {{- end }} |
| } |
| |
| {{ .Name }}::~{{ .Name }}() { |
| {{- range .Members }} |
| if ({{ .FieldPresenceName }}) { |
| Destruct(&{{ .FieldDataName }}.value); |
| } |
| {{- end }} |
| } |
| |
| {{ .Name }}& {{ .Name }}::operator=({{ .Name }}&& other) { |
| {{- range .Members }} |
| if (other.{{ .FieldPresenceName }}) { |
| if ({{ .FieldPresenceName }}) { |
| {{ .FieldDataName }}.value = std::move(other.{{ .FieldDataName }}.value); |
| } else { |
| {{ .FieldPresenceName }} = true; |
| Construct(&{{ .FieldDataName }}.value, std::move(other.{{ .FieldDataName }}.value)); |
| } |
| } else if ({{ .FieldPresenceName }}) { |
| {{ .FieldPresenceName }} = false; |
| Destruct(&{{ .FieldDataName }}.value); |
| } |
| {{- end }} |
| return *this; |
| } |
| |
| void {{ .Name }}::Encode(::fidl::Encoder* encoder, size_t offset) { |
| size_t max_ordinal = 0; |
| {{- range .Members }} |
| if ({{ .FieldPresenceName }}) max_ordinal = {{ .Ordinal }}; |
| {{- end }} |
| ::fidl::EncodeVectorPointer(encoder, max_ordinal, offset); |
| if (max_ordinal == 0) return; |
| size_t base = encoder->Alloc(max_ordinal * 2 * sizeof(uint64_t)); |
| {{- range .Members }} |
| if ({{ .FieldPresenceName }}) { |
| const size_t length_before = encoder->CurrentLength(); |
| const size_t handles_before = encoder->CurrentHandleCount(); |
| ::fidl::Encode( |
| encoder, |
| &{{ .FieldDataName }}.value, |
| encoder->Alloc(::fidl::CodingTraits<{{ .Type.Decl }}>::encoded_size)); |
| size_t envelope_base = base + ({{ .Ordinal }} - 1) * 2 * sizeof(uint64_t); |
| uint64_t num_bytes_then_num_handles = |
| (encoder->CurrentLength() - length_before) | |
| ((encoder->CurrentHandleCount() - handles_before) << 32); |
| ::fidl::Encode(encoder, &num_bytes_then_num_handles, envelope_base); |
| *encoder->GetPtr<uintptr_t>(envelope_base + sizeof(uint64_t)) = FIDL_ALLOC_PRESENT; |
| } |
| {{- end }} |
| } |
| |
| void {{ .Name }}::Decode(::fidl::Decoder* decoder, {{ .Name }}* value, size_t offset) { |
| fidl_vector_t* encoded = decoder->GetPtr<fidl_vector_t>(offset); |
| size_t base; |
| size_t count; |
| if (!encoded->data) { |
| goto clear_all; |
| } |
| |
| base = decoder->GetOffset(encoded->data); |
| count = encoded->count; |
| |
| {{- range .Members }} |
| if (count >= {{ .Ordinal }}) { |
| size_t envelope_base = base + ({{ .Ordinal }} - 1) * 2 * sizeof(uint64_t); |
| uint64_t presence; |
| ::fidl::Decode(decoder, &presence, envelope_base + sizeof(uint64_t)); |
| if (presence != 0) { |
| ::fidl::Decode(decoder, value->mutable_{{ .Name }}(), decoder->GetOffset(presence)); |
| } else { |
| value->{{ .MethodClearName }}(); |
| } |
| } else { |
| goto done_{{ .Ordinal }}; |
| } |
| {{- end }} |
| |
| return; |
| |
| // Clear unset values. |
| clear_all: |
| {{- range .Members }} |
| done_{{ .Ordinal }}: |
| value->{{ .MethodClearName }}(); |
| {{- end }} |
| return; |
| } |
| |
| zx_status_t {{ .Name }}::Clone({{ .Name }}* result) const { |
| {{- range .Members }} |
| if ({{ .FieldPresenceName }}) { |
| zx_status_t _status = ::fidl::Clone({{ .FieldDataName }}.value, result->mutable_{{ .Name }}()); |
| if (_status != ZX_OK) |
| return _status; |
| } else { |
| result->{{ .MethodClearName }}(); |
| } |
| {{- end }} |
| return ZX_OK; |
| } |
| |
| bool operator==(const {{ .Name }}& lhs, const {{ .Name }}& rhs) { |
| {{- range .Members }} |
| if (lhs.{{ .MethodHasName }}()) { |
| if (!rhs.{{ .MethodHasName }}()) { |
| return false; |
| } |
| if (!::fidl::Equals(*lhs.{{ .Name }}(), *rhs.{{ .Name }}())) { |
| return false; |
| } |
| } else if (rhs.{{ .MethodHasName }}()) { |
| return false; |
| } |
| {{- end }} |
| return true; |
| } |
| {{- end }} |
| |
| {{- define "TableTraits" }} |
| template <> |
| struct CodingTraits<{{ .Namespace }}::{{ .Name }}> |
| : public EncodableCodingTraits<{{ .Namespace }}::{{ .Name }}, {{ .Size }}> {}; |
| |
| inline zx_status_t Clone(const {{ .Namespace }}::{{ .Name }}& value, |
| {{ .Namespace }}::{{ .Name }}* result) { |
| return value.Clone(result); |
| } |
| {{- end }} |
| ` |