ArrayType.cpp revision 6a082c63904f274c45d5eede313e0ef77ec70f86
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 22#include "ConstantExpression.h" 23 24namespace android { 25 26ArrayType::ArrayType(ArrayType *srcArray, ConstantExpression *size) 27 : mElementType(srcArray->mElementType), 28 mSizes(srcArray->mSizes) { 29 prependDimension(size); 30} 31 32ArrayType::ArrayType(Type *elementType, ConstantExpression *size) 33 : mElementType(elementType) { 34 prependDimension(size); 35} 36 37void ArrayType::prependDimension(ConstantExpression *size) { 38 mSizes.insert(mSizes.begin(), size); 39} 40 41void ArrayType::appendDimension(ConstantExpression *size) { 42 mSizes.push_back(size); 43} 44 45size_t ArrayType::countDimensions() const { 46 return mSizes.size(); 47} 48 49void ArrayType::addNamedTypesToSet(std::set<const FQName> &set) const { 50 mElementType->addNamedTypesToSet(set); 51} 52 53bool ArrayType::isArray() const { 54 return true; 55} 56 57bool ArrayType::canCheckEquality() const { 58 return mElementType->canCheckEquality(); 59} 60 61Type *ArrayType::getElementType() const { 62 return mElementType; 63} 64 65std::string ArrayType::getCppType(StorageMode mode, 66 bool specifyNamespaces) const { 67 const std::string base = mElementType->getCppStackType(specifyNamespaces); 68 69 std::string space = specifyNamespaces ? "::android::hardware::" : ""; 70 std::string arrayType = space + "hidl_array<" + base; 71 72 for (size_t i = 0; i < mSizes.size(); ++i) { 73 arrayType += ", "; 74 arrayType += mSizes[i]->cppValue(); 75 76 if (!mSizes[i]->descriptionIsTrivial()) { 77 arrayType += " /* "; 78 arrayType += mSizes[i]->description(); 79 arrayType += " */"; 80 } 81 } 82 83 arrayType += ">"; 84 85 switch (mode) { 86 case StorageMode_Stack: 87 return arrayType; 88 89 case StorageMode_Argument: 90 return "const " + arrayType + "&"; 91 92 case StorageMode_Result: 93 return "const " + arrayType + "*"; 94 } 95 96 CHECK(!"Should not be here"); 97} 98 99std::string ArrayType::getJavaType(bool forInitializer) const { 100 std::string base = 101 mElementType->getJavaType(forInitializer); 102 103 for (size_t i = 0; i < mSizes.size(); ++i) { 104 base += "["; 105 106 if (forInitializer) { 107 base += mSizes[i]->javaValue(); 108 } 109 110 if (!forInitializer || !mSizes[i]->descriptionIsTrivial()) { 111 if (forInitializer) 112 base += " "; 113 base += "/* " + mSizes[i]->description() + " */"; 114 } 115 116 base += "]"; 117 } 118 119 return base; 120} 121 122std::string ArrayType::getJavaWrapperType() const { 123 return mElementType->getJavaWrapperType(); 124} 125 126std::string ArrayType::getVtsType() const { 127 return "TYPE_ARRAY"; 128} 129 130void ArrayType::emitReaderWriter( 131 Formatter &out, 132 const std::string &name, 133 const std::string &parcelObj, 134 bool parcelObjIsPointer, 135 bool isReader, 136 ErrorMode mode) const { 137 std::string baseType = mElementType->getCppStackType(); 138 139 const std::string parentName = "_hidl_" + name + "_parent"; 140 141 out << "size_t " << parentName << ";\n\n"; 142 143 const std::string parcelObjDeref = 144 parcelObj + (parcelObjIsPointer ? "->" : "."); 145 146 if (isReader) { 147 out << "_hidl_err = " 148 << parcelObjDeref 149 << "readBuffer(&" 150 << parentName 151 << ", " 152 << " reinterpret_cast<const void **>(" 153 << "&" << name 154 << "));\n\n"; 155 156 handleError(out, mode); 157 } else { 158 size_t numArrayElements = 1; 159 for (auto size : mSizes) { 160 numArrayElements *= size->castSizeT(); 161 } 162 163 out << "_hidl_err = " 164 << parcelObjDeref 165 << "writeBuffer(" 166 << name 167 << ".data(), " 168 << numArrayElements 169 << " * sizeof(" 170 << baseType 171 << "), &" 172 << parentName 173 << ");\n"; 174 175 handleError(out, mode); 176 } 177 178 emitReaderWriterEmbedded( 179 out, 180 0 /* depth */, 181 name, 182 name /* sanitizedName */, 183 isReader /* nameIsPointer */, 184 parcelObj, 185 parcelObjIsPointer, 186 isReader, 187 mode, 188 parentName, 189 "0 /* parentOffset */"); 190} 191 192void ArrayType::emitReaderWriterEmbedded( 193 Formatter &out, 194 size_t depth, 195 const std::string &name, 196 const std::string &sanitizedName, 197 bool nameIsPointer, 198 const std::string &parcelObj, 199 bool parcelObjIsPointer, 200 bool isReader, 201 ErrorMode mode, 202 const std::string &parentName, 203 const std::string &offsetText) const { 204 if (!mElementType->needsEmbeddedReadWrite()) { 205 return; 206 } 207 208 const std::string nameDeref = name + (nameIsPointer ? "->" : "."); 209 210 std::string baseType = mElementType->getCppStackType(); 211 212 std::string iteratorName = "_hidl_index_" + std::to_string(depth); 213 214 out << "for (size_t " 215 << iteratorName 216 << " = 0; " 217 << iteratorName 218 << " < " 219 << dimension() 220 << "; ++" 221 << iteratorName 222 << ") {\n"; 223 224 out.indent(); 225 226 mElementType->emitReaderWriterEmbedded( 227 out, 228 depth + 1, 229 nameDeref + "data()[" + iteratorName + "]", 230 sanitizedName + "_indexed", 231 false /* nameIsPointer */, 232 parcelObj, 233 parcelObjIsPointer, 234 isReader, 235 mode, 236 parentName, 237 offsetText 238 + " + " + iteratorName + " * sizeof(" 239 + baseType 240 + ")"); 241 242 out.unindent(); 243 244 out << "}\n\n"; 245} 246 247void ArrayType::emitResolveReferences( 248 Formatter &out, 249 const std::string &name, 250 bool nameIsPointer, 251 const std::string &parcelObj, 252 bool parcelObjIsPointer, 253 bool isReader, 254 ErrorMode mode) const { 255 emitResolveReferencesEmbedded( 256 out, 257 0 /* depth */, 258 name, 259 name /* sanitizedName */, 260 nameIsPointer, 261 parcelObj, 262 parcelObjIsPointer, 263 isReader, 264 mode, 265 "_hidl_" + name + "_parent", 266 "0 /* parentOffset */"); 267} 268 269void ArrayType::emitResolveReferencesEmbedded( 270 Formatter &out, 271 size_t depth, 272 const std::string &name, 273 const std::string &sanitizedName, 274 bool nameIsPointer, 275 const std::string &parcelObj, 276 bool parcelObjIsPointer, 277 bool isReader, 278 ErrorMode mode, 279 const std::string &parentName, 280 const std::string &offsetText) const { 281 CHECK(needsResolveReferences() && mElementType->needsResolveReferences()); 282 283 const std::string nameDeref = name + (nameIsPointer ? "->" : "."); 284 285 std::string baseType = mElementType->getCppStackType(); 286 287 std::string iteratorName = "_hidl_index_" + std::to_string(depth); 288 289 out << "for (size_t " 290 << iteratorName 291 << " = 0; " 292 << iteratorName 293 << " < " 294 << dimension() 295 << "; ++" 296 << iteratorName 297 << ") {\n"; 298 299 out.indent(); 300 301 mElementType->emitResolveReferencesEmbedded( 302 out, 303 depth + 1, 304 nameDeref + "data()[" + iteratorName + "]", 305 sanitizedName + "_indexed", 306 false /* nameIsPointer */, 307 parcelObj, 308 parcelObjIsPointer, 309 isReader, 310 mode, 311 parentName, 312 offsetText + " + " + iteratorName + " * sizeof(" 313 + baseType 314 + ")"); 315 316 out.unindent(); 317 318 out << "}\n\n"; 319} 320 321 322bool ArrayType::needsEmbeddedReadWrite() const { 323 return mElementType->needsEmbeddedReadWrite(); 324} 325 326bool ArrayType::needsResolveReferences() const { 327 return mElementType->needsResolveReferences(); 328} 329 330bool ArrayType::resultNeedsDeref() const { 331 return true; 332} 333 334void ArrayType::emitJavaReaderWriter( 335 Formatter &out, 336 const std::string &parcelObj, 337 const std::string &argName, 338 bool isReader) const { 339 if (isReader) { 340 out << "new " 341 << getJavaType(true /* forInitializer */) 342 << ";\n"; 343 } 344 345 out << "{\n"; 346 out.indent(); 347 348 out << "android.os.HwBlob _hidl_blob = "; 349 350 if (isReader) { 351 out << parcelObj 352 << ".readBuffer();\n"; 353 } else { 354 size_t align, size; 355 getAlignmentAndSize(&align, &size); 356 357 out << "new android.os.HwBlob(" 358 << size 359 << " /* size */);\n"; 360 } 361 362 emitJavaFieldReaderWriter( 363 out, 364 0 /* depth */, 365 parcelObj, 366 "_hidl_blob", 367 argName, 368 "0 /* offset */", 369 isReader); 370 371 if (!isReader) { 372 out << parcelObj << ".writeBuffer(_hidl_blob);\n"; 373 } 374 375 out.unindent(); 376 out << "}\n"; 377} 378 379void ArrayType::emitJavaFieldInitializer( 380 Formatter &out, const std::string &fieldName) const { 381 std::string typeName = getJavaType(false /* forInitializer */); 382 std::string initName = getJavaType(true /* forInitializer */); 383 384 out << "final " 385 << typeName 386 << " " 387 << fieldName 388 << " = new " 389 << initName 390 << ";\n"; 391} 392 393void ArrayType::emitJavaFieldReaderWriter( 394 Formatter &out, 395 size_t depth, 396 const std::string &parcelName, 397 const std::string &blobName, 398 const std::string &fieldName, 399 const std::string &offset, 400 bool isReader) const { 401 out << "{\n"; 402 out.indent(); 403 404 std::string offsetName = "_hidl_array_offset_" + std::to_string(depth); 405 out << "long " << offsetName << " = " << offset << ";\n"; 406 407 std::string indexString; 408 for (size_t dim = 0; dim < mSizes.size(); ++dim) { 409 std::string iteratorName = 410 "_hidl_index_" + std::to_string(depth) + "_" + std::to_string(dim); 411 412 out << "for (int " 413 << iteratorName 414 << " = 0; " 415 << iteratorName 416 << " < " 417 << mSizes[dim]->javaValue() 418 << "; ++" 419 << iteratorName 420 << ") {\n"; 421 422 out.indent(); 423 424 indexString += "[" + iteratorName + "]"; 425 } 426 427 if (isReader && mElementType->isCompoundType()) { 428 std::string typeName = 429 mElementType->getJavaType(false /* forInitializer */); 430 431 out << fieldName 432 << indexString 433 << " = new " 434 << typeName 435 << "();\n"; 436 } 437 438 mElementType->emitJavaFieldReaderWriter( 439 out, 440 depth + 1, 441 parcelName, 442 blobName, 443 fieldName + indexString, 444 offsetName, 445 isReader); 446 447 size_t elementAlign, elementSize; 448 mElementType->getAlignmentAndSize(&elementAlign, &elementSize); 449 450 out << offsetName << " += " << std::to_string(elementSize) << ";\n"; 451 452 for (size_t dim = 0; dim < mSizes.size(); ++dim) { 453 out.unindent(); 454 out << "}\n"; 455 } 456 457 out.unindent(); 458 out << "}\n"; 459} 460 461status_t ArrayType::emitVtsTypeDeclarations(Formatter &out) const { 462 out << "type: " << getVtsType() << "\n"; 463 out << "vector_value: {\n"; 464 out.indent(); 465 out << "vector_size: " << mSizes[0]->value() << "\n"; 466 // Simple array case. 467 if (mSizes.size() == 1) { 468 status_t err = mElementType->emitVtsTypeDeclarations(out); 469 if (err != OK) { 470 return err; 471 } 472 } else { // Multi-dimension array case. 473 for (size_t index = 1; index < mSizes.size(); index++) { 474 out << "type: " << getVtsType() << "\n"; 475 out << "vector_value: {\n"; 476 out.indent(); 477 out << "vector_size: " << mSizes[index]->value() << "\n"; 478 if (index == mSizes.size() - 1) { 479 status_t err = mElementType->emitVtsTypeDeclarations(out); 480 if (err != OK) { 481 return err; 482 } 483 } 484 } 485 } 486 for (size_t index = 0; index < mSizes.size(); index++) { 487 out.unindent(); 488 out << "}\n"; 489 } 490 return OK; 491} 492 493bool ArrayType::isJavaCompatible() const { 494 return mElementType->isJavaCompatible(); 495} 496 497void ArrayType::getAlignmentAndSize(size_t *align, size_t *size) const { 498 mElementType->getAlignmentAndSize(align, size); 499 500 for (auto sizeInDimension : mSizes) { 501 (*size) *= sizeInDimension->castSizeT(); 502 } 503} 504 505size_t ArrayType::dimension() const { 506 size_t numArrayElements = 1; 507 for (auto size : mSizes) { 508 numArrayElements *= size->castSizeT(); 509 } 510 return numArrayElements; 511} 512 513} // namespace android 514 515