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