blob: 546325ba4bc34a9ccc3a236a97adfb75a4900a10 [file] [log] [blame]
Yifan Hongbf459bc2016-08-23 16:50:37 -07001/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "RefType.h"
18
Yifan Hong51f9c8a2016-12-05 18:47:33 -080019#include "ArrayType.h"
20#include "CompoundType.h"
21
Yifan Hongbf459bc2016-08-23 16:50:37 -070022#include <hidl-util/Formatter.h>
23#include <android-base/logging.h>
24
25namespace android {
26
27RefType::RefType() {
28}
29
Steven Moreland30bb6a82016-11-30 09:18:34 -080030std::string RefType::typeName() const {
31 return "ref" + (mElementType == nullptr ? "" : (" of " + mElementType->typeName()));
32}
33
34bool RefType::isCompatibleElementType(Type *elementType) const {
Yifan Hong51f9c8a2016-12-05 18:47:33 -080035 if (elementType->isScalar()) {
36 return true;
37 }
38 if (elementType->isString()) {
39 return true;
40 }
41 if (elementType->isEnum()) {
42 return true;
43 }
44 if (elementType->isBitField()) {
45 return true;
46 }
47 if (elementType->isCompoundType()
48 && static_cast<CompoundType *>(elementType)->style() == CompoundType::STYLE_STRUCT) {
49 return true;
50 }
51 if (elementType->isTemplatedType()) {
52 return this->isCompatibleElementType(static_cast<TemplatedType *>(elementType)->getElementType());
53 }
54 if (elementType->isArray()) {
55 return this->isCompatibleElementType(static_cast<ArrayType *>(elementType)->getElementType());
56 }
57 return false;
Steven Moreland30bb6a82016-11-30 09:18:34 -080058}
59
Yifan Hongbf459bc2016-08-23 16:50:37 -070060/* return something like "T const *".
61 * The reason we don't return "const T *" is to handle cases like
62 * ref<ref<ref<T>>> t_3ptr;
63 * in this case the const's will get stacked on the left (const const const T *** t_3ptr)
64 * but in this implementation it would be clearer (T const* const* const* t_3ptr) */
Yifan Hong3b320f82016-11-01 15:15:54 -070065std::string RefType::getCppType(StorageMode /*mode*/, bool specifyNamespaces) const {
66 return mElementType->getCppStackType(specifyNamespaces)
67 + " const*";
Yifan Hongbf459bc2016-08-23 16:50:37 -070068}
69
70void RefType::addNamedTypesToSet(std::set<const FQName> &set) const {
71 mElementType->addNamedTypesToSet(set);
72}
73
74void RefType::emitReaderWriter(
75 Formatter &,
76 const std::string &,
77 const std::string &,
78 bool,
79 bool,
80 ErrorMode) const {
81 // RefType doesn't get read / written at this stage.
82 return;
83}
84
85void RefType::emitResolveReferences(
86 Formatter &out,
87 const std::string &name,
88 bool nameIsPointer,
89 const std::string &parcelObj,
90 bool parcelObjIsPointer,
91 bool isReader,
92 ErrorMode mode) const {
93
94 emitResolveReferencesEmbedded(
95 out,
96 0 /* depth */,
97 name,
98 name /* sanitizedName */,
99 nameIsPointer,
100 parcelObj,
101 parcelObjIsPointer,
102 isReader,
103 mode,
104 "", // parentName
105 ""); // offsetText
106}
107
108void RefType::emitResolveReferencesEmbedded(
109 Formatter &out,
110 size_t /* depth */,
111 const std::string &name,
112 const std::string &sanitizedName,
113 bool /*nameIsPointer*/,
114 const std::string &parcelObj,
115 bool parcelObjIsPointer,
116 bool isReader,
117 ErrorMode mode,
118 const std::string &parentName,
119 const std::string &offsetText) const {
120
Yifan Hong3b320f82016-11-01 15:15:54 -0700121 std::string elementType = mElementType->getCppStackType();
Yifan Hongbf459bc2016-08-23 16:50:37 -0700122
Yifan Hong3b320f82016-11-01 15:15:54 -0700123 std::string baseType = getCppStackType();
Yifan Hongbf459bc2016-08-23 16:50:37 -0700124
125 const std::string parcelObjDeref =
126 parcelObjIsPointer ? ("*" + parcelObj) : parcelObj;
127
128 const std::string parcelObjPointer =
129 parcelObjIsPointer ? parcelObj : ("&" + parcelObj);
130
131 // as if nameIsPointer is false. Pointers are always pass by values,
132 // so name is always the pointer value itself. Hence nameIsPointer = false.
133 const std::string namePointer = "&" + name;
134 const std::string handleName = "_hidl_" + sanitizedName + "__ref_handle";
135 const std::string resolveBufName = "_hidl_" + sanitizedName + "__ref_resolve_buf";
136
137 bool isEmbedded = (!parentName.empty() && !offsetText.empty());
138
139 out << "size_t " << handleName << ";\n"
140 << "bool " << resolveBufName << ";\n\n";
141
142 out << "_hidl_err = ";
143
144 if (isReader) {
145 out << "::android::hardware::read"
146 << (isEmbedded ? "Embedded" : "")
147 << "ReferenceFromParcel<"
148 << elementType
149 << ">(const_cast<"
150 << baseType
Yifan Hong3b320f82016-11-01 15:15:54 -0700151 << " *>("
Yifan Hongbf459bc2016-08-23 16:50:37 -0700152 << namePointer
153 << "),";
154 } else {
155 out << "::android::hardware::write"
156 << (isEmbedded ? "Embedded" : "")
157 << "ReferenceToParcel<"
158 << elementType
159 << ">("
160 << name
161 << ",";
162 }
163
164 out.indent();
165 out.indent();
166
167 out << (isReader ? parcelObjDeref : parcelObjPointer);
168 if(isEmbedded)
169 out << ",\n"
170 << parentName
171 << ",\n"
172 << offsetText;
173
174 out << ",\n&" + handleName;
175 out << ",\n&" + resolveBufName;
176 out << ");\n\n";
177
178 out.unindent();
179 out.unindent();
180
181 handleError(out, mode);
182
183 if(!mElementType->needsResolveReferences() && !mElementType->needsEmbeddedReadWrite())
184 return; // no need to deal with element type recursively.
185
186 out << "if(" << resolveBufName << ") {\n";
187 out.indent();
188
189 if(mElementType->needsEmbeddedReadWrite()) {
190 mElementType->emitReaderWriterEmbedded(
191 out,
192 0 /* depth */,
193 name,
Yifan Hong244e82d2016-11-11 11:13:57 -0800194 sanitizedName,
Yifan Hongbf459bc2016-08-23 16:50:37 -0700195 true /* nameIsPointer */, // for element type, name is a pointer.
196 parcelObj,
197 parcelObjIsPointer,
198 isReader,
199 mode,
200 handleName,
201 "0 /* parentOffset */");
202 }
203
204 if(mElementType->needsResolveReferences()) {
205 mElementType->emitResolveReferencesEmbedded(
206 out,
207 0 /* depth */,
208 "(*" + name + ")",
209 sanitizedName + "_deref",
210 false /* nameIsPointer */,
211 // must deref it and say false here, otherwise pointer to pointers don't work
212 parcelObj,
213 parcelObjIsPointer,
214 isReader,
215 mode,
216 handleName,
217 "0 /* parentOffset */");
218 }
219
220 out.unindent();
221 out << "}\n\n";
222}
223
Yifan Hongbf459bc2016-08-23 16:50:37 -0700224bool RefType::needsResolveReferences() const {
225 return true;
226}
227
228bool RefType::needsEmbeddedReadWrite() const {
229 return false;
230}
231
232bool RefType::resultNeedsDeref() const {
233 return false;
234}
235
236status_t RefType::emitVtsTypeDeclarations(Formatter &out) const {
237 out << "type: TYPE_REF\n" << "ref_value: {\n";
238 out.indent();
239 status_t err = mElementType->emitVtsTypeDeclarations(out);
240 if (err != OK) {
241 return err;
242 }
243 out.unindent();
244 out << "}\n";
245 return OK;
246}
247
248status_t RefType::emitVtsAttributeType(Formatter &out) const {
249 out << "type: TYPE_REF\n" << "ref_value: {\n";
250 out.indent();
251 status_t status = mElementType->emitVtsAttributeType(out);
252 if (status != OK) {
253 return status;
254 }
255 out.unindent();
256 out << "}\n";
257 return OK;
258}
259
260bool RefType::isJavaCompatible() const {
261 return false;
262}
263
264} // namespace android
265