ArrayType.cpp revision f9d49f1468bd65595f6f0ae5f4d7300f4e95edf8
1/*
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 "ArrayType.h"
18
19#include <hidl-util/Formatter.h>
20#include <android-base/logging.h>
21
22namespace android {
23
24ArrayType::ArrayType(Type *elementType, const char *dimension)
25    : mElementType(elementType),
26      mDimension(dimension) {
27}
28
29void ArrayType::addNamedTypesToSet(std::set<const FQName> &set) const {
30    mElementType->addNamedTypesToSet(set);
31}
32
33std::string ArrayType::getCppType(StorageMode mode,
34                                  std::string *extra,
35                                  bool specifyNamespaces) const {
36    const std::string base = mElementType->getCppType(extra, specifyNamespaces);
37
38    *extra = "[" + mDimension + "]" + (*extra);
39
40    switch (mode) {
41        case StorageMode_Stack:
42            return base;
43
44        case StorageMode_Argument:
45        case StorageMode_Result:
46        {
47            *extra = " /* " + base + (*extra) + " */";
48
49            return "const " + base + "*";
50        }
51    }
52}
53
54std::string ArrayType::getJavaType() const {
55    return mElementType->getJavaType() + "[]";
56}
57
58void ArrayType::emitReaderWriter(
59        Formatter &out,
60        const std::string &name,
61        const std::string &parcelObj,
62        bool parcelObjIsPointer,
63        bool isReader,
64        ErrorMode mode) const {
65    std::string baseExtra;
66    std::string baseType = mElementType->getCppType(&baseExtra);
67
68    const std::string parentName = "_hidl_" + name + "_parent";
69
70    out << "size_t " << parentName << ";\n\n";
71
72    const std::string parcelObjDeref =
73        parcelObj + (parcelObjIsPointer ? "->" : ".");
74
75    if (isReader) {
76        out << name
77            << " = (const "
78            << baseType
79            << " *)"
80            << parcelObjDeref
81            << "readBuffer(&"
82            << parentName
83            << ");\n\n";
84
85        out << "if (" << name << " == nullptr) {\n";
86
87        out.indent();
88
89        out << "_hidl_err = ::android::UNKNOWN_ERROR;\n";
90        handleError2(out, mode);
91
92        out.unindent();
93        out << "}\n\n";
94    } else {
95        out << "_hidl_err = "
96            << parcelObjDeref
97            << "writeBuffer("
98            << name
99            << ", "
100            << mDimension
101            << " * sizeof("
102            << baseType
103            << baseExtra
104            << "), &"
105            << parentName
106            << ");\n";
107
108        handleError(out, mode);
109    }
110
111    emitReaderWriterEmbedded(
112            out,
113            0 /* depth */,
114            name,
115            isReader /* nameIsPointer */,
116            parcelObj,
117            parcelObjIsPointer,
118            isReader,
119            mode,
120            parentName,
121            "0 /* parentOffset */");
122}
123
124void ArrayType::emitReaderWriterEmbedded(
125        Formatter &out,
126        size_t depth,
127        const std::string &name,
128        bool nameIsPointer,
129        const std::string &parcelObj,
130        bool parcelObjIsPointer,
131        bool isReader,
132        ErrorMode mode,
133        const std::string &parentName,
134        const std::string &offsetText) const {
135    if (!mElementType->needsEmbeddedReadWrite()) {
136        return;
137    }
138
139    const std::string nameDeref = name + (nameIsPointer ? "->" : ".");
140
141    std::string baseExtra;
142    std::string baseType = mElementType->getCppType(&baseExtra);
143
144    std::string iteratorName = "_hidl_index_" + std::to_string(depth);
145
146    out << "for (size_t "
147        << iteratorName
148        << " = 0; "
149        << iteratorName
150        << " < "
151        << mDimension
152        << "; ++"
153        << iteratorName
154        << ") {\n";
155
156    out.indent();
157
158    mElementType->emitReaderWriterEmbedded(
159            out,
160            depth + 1,
161            name + "[" + iteratorName + "]",
162            false /* nameIsPointer */,
163            parcelObj,
164            parcelObjIsPointer,
165            isReader,
166            mode,
167            parentName,
168            offsetText
169                + " + " + iteratorName + " * sizeof("
170                + baseType
171                + baseExtra
172                + ")");
173
174    out.unindent();
175
176    out << "}\n\n";
177}
178
179bool ArrayType::needsEmbeddedReadWrite() const {
180    return mElementType->needsEmbeddedReadWrite();
181}
182
183void ArrayType::emitJavaReaderWriter(
184        Formatter &out,
185        const std::string &parcelObj,
186        const std::string &argName,
187        bool isReader) const {
188    if (mElementType->isCompoundType()) {
189        if (isReader) {
190            out << mElementType->getJavaType()
191                << ".readArrayFromParcel("
192                << parcelObj
193                << ", "
194                << mDimension
195                << ");\n";
196        } else {
197            out << mElementType->getJavaType()
198                << ".writeArrayToParcel("
199                << parcelObj
200                << ", "
201                << mDimension
202                << ", "
203                << argName
204                << ");\n";
205        }
206
207        return;
208    }
209
210    emitJavaReaderWriterWithSuffix(
211            out,
212            parcelObj,
213            argName,
214            isReader,
215            mElementType->getJavaSuffix() + "Array",
216            mDimension);
217}
218
219void ArrayType::emitJavaFieldInitializer(
220        Formatter &out, const std::string &fieldName) const {
221    out << "final "
222        << mElementType->getJavaType()
223        << "[] "
224        << fieldName
225        << " = new "
226        << mElementType->getJavaType()
227        << "["
228        << mDimension
229        << "];\n";
230}
231
232void ArrayType::emitJavaFieldReaderWriter(
233        Formatter &out,
234        const std::string &blobName,
235        const std::string &fieldName,
236        const std::string &offset,
237        bool isReader) const {
238    out << "for (int _hidl_index = 0; _hidl_index < "
239        << mDimension
240        << "; ++_hidl_index) {\n";
241
242    out.indent();
243
244    size_t elementAlign, elementSize;
245    mElementType->getAlignmentAndSize(&elementAlign, &elementSize);
246
247    mElementType->emitJavaFieldReaderWriter(
248            out,
249            blobName,
250            fieldName + "[_hidl_index]",
251            offset + " + _hidl_index * " + std::to_string(elementSize),
252            isReader);
253
254    out.unindent();
255    out << "}\n";
256}
257
258status_t ArrayType::emitVtsTypeDeclarations(Formatter &out) const {
259    out << "type: TYPE_ARRAY\n" << "vector_value: {\n";
260    out.indent();
261    out << "size: " << mDimension << "\n";
262    status_t err = mElementType->emitVtsTypeDeclarations(out);
263    if (err != OK) {
264        return err;
265    }
266    out.unindent();
267    out << "}\n";
268    return OK;
269}
270
271bool ArrayType::isJavaCompatible() const {
272    return mElementType->isJavaCompatible();
273}
274
275void ArrayType::getAlignmentAndSize(size_t *align, size_t *size) const {
276    mElementType->getAlignmentAndSize(align, size);
277
278    char *end;
279    unsigned long dim = strtoul(mDimension.c_str(), &end, 10);
280    CHECK(end > mDimension.c_str() && *end == '\0');
281
282    (*size) *= dim;
283}
284
285}  // namespace android
286
287