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