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