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