ArrayType.cpp revision 60d3b22101e911242d2d41c8dc8309e8706f1fe1
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 321void ArrayType::emitJavaDump( 322 Formatter &out, 323 const std::string &streamName, 324 const std::string &name) const { 325 out << streamName << ".append(java.util.Arrays." 326 << (countDimensions() > 1 ? "deepToString" : "toString") 327 << "(" 328 << name << "));\n"; 329} 330 331 332bool ArrayType::needsEmbeddedReadWrite() const { 333 return mElementType->needsEmbeddedReadWrite(); 334} 335 336bool ArrayType::needsResolveReferences() const { 337 return mElementType->needsResolveReferences(); 338} 339 340bool ArrayType::resultNeedsDeref() const { 341 return true; 342} 343 344void ArrayType::emitJavaReaderWriter( 345 Formatter &out, 346 const std::string &parcelObj, 347 const std::string &argName, 348 bool isReader) const { 349 if (isReader) { 350 out << "new " 351 << getJavaType(true /* forInitializer */) 352 << ";\n"; 353 } 354 355 out << "{\n"; 356 out.indent(); 357 358 out << "android.os.HwBlob _hidl_blob = "; 359 360 if (isReader) { 361 out << parcelObj 362 << ".readBuffer();\n"; 363 } else { 364 size_t align, size; 365 getAlignmentAndSize(&align, &size); 366 367 out << "new android.os.HwBlob(" 368 << size 369 << " /* size */);\n"; 370 } 371 372 emitJavaFieldReaderWriter( 373 out, 374 0 /* depth */, 375 parcelObj, 376 "_hidl_blob", 377 argName, 378 "0 /* offset */", 379 isReader); 380 381 if (!isReader) { 382 out << parcelObj << ".writeBuffer(_hidl_blob);\n"; 383 } 384 385 out.unindent(); 386 out << "}\n"; 387} 388 389void ArrayType::emitJavaFieldInitializer( 390 Formatter &out, const std::string &fieldName) const { 391 std::string typeName = getJavaType(false /* forInitializer */); 392 std::string initName = getJavaType(true /* forInitializer */); 393 394 out << "final " 395 << typeName 396 << " " 397 << fieldName 398 << " = new " 399 << initName 400 << ";\n"; 401} 402 403void ArrayType::emitJavaFieldReaderWriter( 404 Formatter &out, 405 size_t depth, 406 const std::string &parcelName, 407 const std::string &blobName, 408 const std::string &fieldName, 409 const std::string &offset, 410 bool isReader) const { 411 out << "{\n"; 412 out.indent(); 413 414 std::string offsetName = "_hidl_array_offset_" + std::to_string(depth); 415 out << "long " << offsetName << " = " << offset << ";\n"; 416 417 std::string indexString; 418 for (size_t dim = 0; dim < mSizes.size(); ++dim) { 419 std::string iteratorName = 420 "_hidl_index_" + std::to_string(depth) + "_" + std::to_string(dim); 421 422 out << "for (int " 423 << iteratorName 424 << " = 0; " 425 << iteratorName 426 << " < " 427 << mSizes[dim]->javaValue() 428 << "; ++" 429 << iteratorName 430 << ") {\n"; 431 432 out.indent(); 433 434 indexString += "[" + iteratorName + "]"; 435 } 436 437 if (isReader && mElementType->isCompoundType()) { 438 std::string typeName = 439 mElementType->getJavaType(false /* forInitializer */); 440 441 out << fieldName 442 << indexString 443 << " = new " 444 << typeName 445 << "();\n"; 446 } 447 448 mElementType->emitJavaFieldReaderWriter( 449 out, 450 depth + 1, 451 parcelName, 452 blobName, 453 fieldName + indexString, 454 offsetName, 455 isReader); 456 457 size_t elementAlign, elementSize; 458 mElementType->getAlignmentAndSize(&elementAlign, &elementSize); 459 460 out << offsetName << " += " << std::to_string(elementSize) << ";\n"; 461 462 for (size_t dim = 0; dim < mSizes.size(); ++dim) { 463 out.unindent(); 464 out << "}\n"; 465 } 466 467 out.unindent(); 468 out << "}\n"; 469} 470 471status_t ArrayType::emitVtsTypeDeclarations(Formatter &out) const { 472 out << "type: " << getVtsType() << "\n"; 473 out << "vector_size: " << mSizes[0]->value() << "\n"; 474 out << "vector_value: {\n"; 475 out.indent(); 476 // Simple array case. 477 if (mSizes.size() == 1) { 478 status_t err = mElementType->emitVtsTypeDeclarations(out); 479 if (err != OK) { 480 return err; 481 } 482 } else { // Multi-dimension array case. 483 for (size_t index = 1; index < mSizes.size(); index++) { 484 out << "type: " << getVtsType() << "\n"; 485 out << "vector_size: " << mSizes[index]->value() << "\n"; 486 out << "vector_value: {\n"; 487 out.indent(); 488 if (index == mSizes.size() - 1) { 489 status_t err = mElementType->emitVtsTypeDeclarations(out); 490 if (err != OK) { 491 return err; 492 } 493 } 494 } 495 } 496 for (size_t index = 0; index < mSizes.size(); index++) { 497 out.unindent(); 498 out << "}\n"; 499 } 500 return OK; 501} 502 503bool ArrayType::isJavaCompatible() const { 504 return mElementType->isJavaCompatible(); 505} 506 507bool ArrayType::containsPointer() const { 508 return mElementType->containsPointer(); 509} 510 511void ArrayType::getAlignmentAndSize(size_t *align, size_t *size) const { 512 mElementType->getAlignmentAndSize(align, size); 513 514 for (auto sizeInDimension : mSizes) { 515 (*size) *= sizeInDimension->castSizeT(); 516 } 517} 518 519size_t ArrayType::dimension() const { 520 size_t numArrayElements = 1; 521 for (auto size : mSizes) { 522 numArrayElements *= size->castSizeT(); 523 } 524 return numArrayElements; 525} 526 527} // namespace android 528 529