[C++ hidl-gen] Fix multi-dimensional arrays, vectors of arrays.
Bug: 31438033
Change-Id: I254e8bfeb8fbf665dd3836825aa271603be6d14c
diff --git a/ArrayType.cpp b/ArrayType.cpp
index 6862262..2ca27ec 100644
--- a/ArrayType.cpp
+++ b/ArrayType.cpp
@@ -35,20 +35,17 @@
bool specifyNamespaces) const {
const std::string base = mElementType->getCppType(extra, specifyNamespaces);
- CHECK(extra->empty());
-
- *extra = "[" + mDimension + "]";
+ *extra = "[" + mDimension + "]" + (*extra);
switch (mode) {
case StorageMode_Stack:
return base;
case StorageMode_Argument:
- return "const " + base;
-
case StorageMode_Result:
{
- extra->clear();
+ *extra = " /* " + base + (*extra) + " */";
+
return "const " + base + "*";
}
}
@@ -103,6 +100,7 @@
<< mDimension
<< " * sizeof("
<< baseType
+ << baseExtra
<< "), &"
<< parentName
<< ");\n";
@@ -112,6 +110,7 @@
emitReaderWriterEmbedded(
out,
+ 0 /* depth */,
name,
isReader /* nameIsPointer */,
parcelObj,
@@ -124,6 +123,7 @@
void ArrayType::emitReaderWriterEmbedded(
Formatter &out,
+ size_t depth,
const std::string &name,
bool nameIsPointer,
const std::string &parcelObj,
@@ -141,22 +141,35 @@
std::string baseExtra;
std::string baseType = mElementType->getCppType(&baseExtra);
- out << "for (size_t _hidl_index = 0; _hidl_index < "
+ std::string iteratorName = "_hidl_index_" + std::to_string(depth);
+
+ out << "for (size_t "
+ << iteratorName
+ << " = 0; "
+ << iteratorName
+ << " < "
<< mDimension
- << "; ++_hidl_index) {\n";
+ << "; ++"
+ << iteratorName
+ << ") {\n";
out.indent();
mElementType->emitReaderWriterEmbedded(
out,
- name + "[_hidl_index]",
+ depth + 1,
+ name + "[" + iteratorName + "]",
false /* nameIsPointer */,
parcelObj,
parcelObjIsPointer,
isReader,
mode,
parentName,
- offsetText + " + _hidl_index * sizeof(" + baseType + ")");
+ offsetText
+ + " + " + iteratorName + " * sizeof("
+ + baseType
+ + baseExtra
+ + ")");
out.unindent();
diff --git a/ArrayType.h b/ArrayType.h
index 26e47de..7a39716 100644
--- a/ArrayType.h
+++ b/ArrayType.h
@@ -45,6 +45,7 @@
void emitReaderWriterEmbedded(
Formatter &out,
+ size_t depth,
const std::string &name,
bool nameIsPointer,
const std::string &parcelObj,
diff --git a/CompoundType.cpp b/CompoundType.cpp
index b3f4269..8a692c1 100644
--- a/CompoundType.cpp
+++ b/CompoundType.cpp
@@ -142,6 +142,7 @@
emitReaderWriterEmbedded(
out,
+ 0 /* depth */,
name,
isReader /* nameIsPointer */,
parcelObj,
@@ -154,6 +155,7 @@
void CompoundType::emitReaderWriterEmbedded(
Formatter &out,
+ size_t /* depth */,
const std::string &name,
bool nameIsPointer,
const std::string &parcelObj,
@@ -577,6 +579,7 @@
field->type().emitReaderWriterEmbedded(
out,
+ 0 /* depth */,
field->name(),
false /* nameIsPointer */,
"parcel",
diff --git a/CompoundType.h b/CompoundType.h
index 42e3b33..b59bbd2 100644
--- a/CompoundType.h
+++ b/CompoundType.h
@@ -54,6 +54,7 @@
void emitReaderWriterEmbedded(
Formatter &out,
+ size_t depth,
const std::string &name,
bool nameIsPointer,
const std::string &parcelObj,
diff --git a/HandleType.cpp b/HandleType.cpp
index 178a2c7..1ab2e69 100644
--- a/HandleType.cpp
+++ b/HandleType.cpp
@@ -84,6 +84,7 @@
void HandleType::emitReaderWriterEmbedded(
Formatter &out,
+ size_t /* depth */,
const std::string &name,
bool nameIsPointer,
const std::string &parcelObj,
diff --git a/HandleType.h b/HandleType.h
index 386adbb..94b040d 100644
--- a/HandleType.h
+++ b/HandleType.h
@@ -42,6 +42,7 @@
void emitReaderWriterEmbedded(
Formatter &out,
+ size_t depth,
const std::string &name,
bool nameIsPointer,
const std::string &parcelObj,
diff --git a/PredefinedType.cpp b/PredefinedType.cpp
index c1468ab..ad9698c 100644
--- a/PredefinedType.cpp
+++ b/PredefinedType.cpp
@@ -105,6 +105,7 @@
emitReaderWriterEmbedded(
out,
+ 0 /* depth */,
name,
isReader /* nameIsPointer */,
parcelObj,
@@ -117,6 +118,7 @@
void PredefinedType::emitReaderWriterEmbedded(
Formatter &out,
+ size_t /* depth */,
const std::string &name,
bool nameIsPointer,
const std::string &parcelObj,
diff --git a/PredefinedType.h b/PredefinedType.h
index 965b786..84c9441 100644
--- a/PredefinedType.h
+++ b/PredefinedType.h
@@ -41,6 +41,7 @@
void emitReaderWriterEmbedded(
Formatter &out,
+ size_t depth,
const std::string &name,
bool nameIsPointer,
const std::string &parcelObj,
diff --git a/StringType.cpp b/StringType.cpp
index ea00ddc..d5dba42 100644
--- a/StringType.cpp
+++ b/StringType.cpp
@@ -104,6 +104,7 @@
emitReaderWriterEmbedded(
out,
+ 0 /* depth */,
name,
isReader /* nameIsPointer */,
parcelObj,
@@ -116,6 +117,7 @@
void StringType::emitReaderWriterEmbedded(
Formatter &out,
+ size_t /* depth */,
const std::string &name,
bool nameIsPointer,
const std::string &parcelObj,
diff --git a/StringType.h b/StringType.h
index 9b7cb04..9062d90 100644
--- a/StringType.h
+++ b/StringType.h
@@ -44,6 +44,7 @@
void emitReaderWriterEmbedded(
Formatter &out,
+ size_t depth,
const std::string &name,
bool nameIsPointer,
const std::string &parcelObj,
diff --git a/Type.cpp b/Type.cpp
index 9fea80f..8abffd6 100644
--- a/Type.cpp
+++ b/Type.cpp
@@ -94,6 +94,7 @@
void Type::emitReaderWriterEmbedded(
Formatter &,
+ size_t,
const std::string &,
bool,
const std::string &,
diff --git a/Type.h b/Type.h
index 0f3812b..3e276c2 100644
--- a/Type.h
+++ b/Type.h
@@ -98,6 +98,7 @@
virtual void emitReaderWriterEmbedded(
Formatter &out,
+ size_t depth,
const std::string &name,
bool nameIsPointer,
const std::string &parcelObj,
diff --git a/VectorType.cpp b/VectorType.cpp
index 9ddb171..8e2c599 100644
--- a/VectorType.cpp
+++ b/VectorType.cpp
@@ -36,9 +36,10 @@
std::string(specifyNamespaces ? "::android::hardware::" : "")
+ "hidl_vec<"
+ mElementType->getCppType(extra, specifyNamespaces)
+ + (*extra)
+ ">";
- CHECK(extra->empty());
+ extra->clear();
switch (mode) {
case StorageMode_Stack:
@@ -77,6 +78,7 @@
out << name
<< " = (const ::android::hardware::hidl_vec<"
<< baseType
+ << baseExtra
<< "> *)"
<< parcelObjDeref
<< "readBuffer(&"
@@ -108,6 +110,7 @@
emitReaderWriterEmbedded(
out,
+ 0 /* depth */,
name,
isReader /* nameIsPointer */,
parcelObj,
@@ -118,8 +121,19 @@
"0 /* parentOffset */");
}
+// Remove any trailing array indices from the given name, i.e. foo[2][3] => foo
+static std::string StripIndex(const std::string &name) {
+ size_t pos = name.find("[");
+ if (pos == std::string::npos) {
+ return name;
+ }
+
+ return name.substr(0, pos);
+}
+
void VectorType::emitReaderWriterEmbedded(
Formatter &out,
+ size_t depth,
const std::string &name,
bool nameIsPointer,
const std::string &parcelObj,
@@ -131,7 +145,7 @@
std::string baseExtra;
std::string baseType = Type::getCppType(&baseExtra);
- const std::string childName = "_hidl_" + name + "_child";
+ const std::string childName = "_hidl_" + StripIndex(name) + "_child";
out << "size_t " << childName << ";\n\n";
emitReaderWriterEmbeddedForTypeName(
@@ -155,22 +169,32 @@
baseType = mElementType->getCppType(&baseExtra);
- out << "for (size_t _hidl_index = 0; _hidl_index < "
+ std::string iteratorName = "_hidl_index_" + std::to_string(depth);
+
+ out << "for (size_t "
+ << iteratorName
+ << " = 0; "
+ << iteratorName
+ << " < "
<< nameDeref
- << "size(); ++_hidl_index) {\n";
+ << "size(); ++"
+ << iteratorName
+ << ") {\n";
out.indent();
mElementType->emitReaderWriterEmbedded(
out,
- (nameIsPointer ? "(*" + name + ")" : name) + "[_hidl_index]",
+ depth + 1,
+ (nameIsPointer ? "(*" + name + ")" : name)
+ + "[" + iteratorName + "]",
false /* nameIsPointer */,
parcelObj,
parcelObjIsPointer,
isReader,
mode,
childName,
- "_hidl_index * sizeof(" + baseType + ")");
+ iteratorName + " * sizeof(" + baseType + baseExtra + ")");
out.unindent();
diff --git a/VectorType.h b/VectorType.h
index fb77b3d..6655530 100644
--- a/VectorType.h
+++ b/VectorType.h
@@ -43,6 +43,7 @@
void emitReaderWriterEmbedded(
Formatter &out,
+ size_t depth,
const std::string &name,
bool nameIsPointer,
const std::string &parcelObj,
diff --git a/test/main.cpp b/test/main.cpp
index 17170af..00b8cf6 100644
--- a/test/main.cpp
+++ b/test/main.cpp
@@ -162,6 +162,13 @@
const hidl_vec<hidl_string> &vector,
haveAStringVec_cb _cb) override;
+ Return<void> transposeMe(
+ const float *in /* float[3][5] */, transposeMe_cb _cb) override;
+
+ Return<void> callingDrWho(
+ const MultiDimensional &in,
+ callingDrWho_cb _hidl_cb) override;
+
Return<void> thisIsNew() override;
};
@@ -343,6 +350,101 @@
return Void();
}
+static std::string FloatArray2DToString(const float *x, size_t n1, size_t n2) {
+ std::string s;
+ s += "[";
+ for (size_t i = 0; i < n1; ++i) {
+ if (i > 0) {
+ s += ", ";
+ }
+
+ s += "[";
+ for (size_t j = 0; j < n2; ++j) {
+ if (j > 0) {
+ s += ", ";
+ }
+ s += std::to_string(x[i * n2 + j]);
+ }
+ s += "]";
+ }
+ s += "]";
+
+ return s;
+}
+
+Return<void> Bar::transposeMe(
+ const float *in /* float[3][5] */, transposeMe_cb _cb) {
+ ALOGI("SERVER(Bar) transposeMe(%s)",
+ FloatArray2DToString(in, 3, 5).c_str());
+
+ float out[5][3];
+ for (size_t i = 0; i < 5; ++i) {
+ for (size_t j = 0; j < 3; ++j) {
+ out[i][j] = in[5 * j + i];
+ }
+ }
+
+ _cb(&out[0][0]);
+
+ return Void();
+}
+
+static std::string QuuxToString(const IFoo::Quux &val) {
+ std::string s;
+
+ s = "Quux(first='";
+ s += val.first.c_str();
+ s += "', last='";
+ s += val.last.c_str();
+ s += "')";
+
+ return s;
+}
+
+static std::string MultiDimensionalToString(const IFoo::MultiDimensional &val) {
+ std::string s;
+
+ s += "MultiDimensional(";
+
+ s += "quuxMatrix=[";
+ for (size_t i = 0; i < 5; ++i) {
+ if (i > 0) {
+ s += ", ";
+ }
+
+ s += "[";
+ for (size_t j = 0; j < 3; ++j) {
+ if (j > 0) {
+ s += ", ";
+ }
+
+ s += QuuxToString(val.quuxMatrix[i][j]);
+ }
+ }
+ s += "]";
+
+ s += ")";
+
+ return s;
+}
+
+Return<void> Bar::callingDrWho(
+ const MultiDimensional &in, callingDrWho_cb _hidl_cb) {
+ ALOGI("SERVER(Bar) callingDrWho(%s)", MultiDimensionalToString(in).c_str());
+
+ MultiDimensional out;
+ for (size_t i = 0; i < 5; ++i) {
+ for (size_t j = 0; j < 3; ++j) {
+ out.quuxMatrix[i][j].first = in.quuxMatrix[4 - i][2 - j].last;
+ out.quuxMatrix[i][j].last = in.quuxMatrix[4 - i][2 - j].first;
+ }
+ }
+
+ _hidl_cb(out);
+
+ return Void();
+}
+
Return<void> Bar::thisIsNew() {
ALOGI("SERVER(Bar) thisIsNew");
@@ -653,6 +755,66 @@
ALOGI("CLIENT haveAStringVec returned.");
}
+TEST_F(HidlTest, FooTransposeMeTest) {
+ float in[3][5];
+ float k = 1.0f;
+ for (size_t i = 0; i < 3; ++i) {
+ for (size_t j = 0; j < 5; ++j, ++k) {
+ in[i][j] = k;
+ }
+ }
+
+ ALOGI("CLIENT call transposeMe(%s).",
+ FloatArray2DToString(&in[0][0], 3, 5).c_str());
+
+ EXPECT_OK(foo->transposeMe(
+ &in[0][0],
+ [&](const auto &out) {
+ ALOGI("CLIENT transposeMe returned %s.",
+ FloatArray2DToString(out, 5, 3).c_str());
+
+ for (size_t i = 0; i < 3; ++i) {
+ for (size_t j = 0; j < 5; ++j) {
+ EXPECT_EQ(out[3 * j + i], in[i][j]);
+ }
+ }
+ }));
+}
+
+TEST_F(HidlTest, FooCallingDrWhoTest) {
+ IFoo::MultiDimensional in;
+
+ size_t k = 0;
+ for (size_t i = 0; i < 5; ++i) {
+ for (size_t j = 0; j < 3; ++j, ++k) {
+ in.quuxMatrix[i][j].first = ("First " + std::to_string(k)).c_str();
+ in.quuxMatrix[i][j].last = ("Last " + std::to_string(15-k)).c_str();
+ }
+ }
+
+ ALOGI("CLIENT call callingDrWho(%s).",
+ MultiDimensionalToString(in).c_str());
+
+ EXPECT_OK(foo->callingDrWho(
+ in,
+ [&](const auto &out) {
+ ALOGI("CLIENT callingDrWho returned %s.",
+ MultiDimensionalToString(out).c_str());
+
+ for (size_t i = 0; i < 5; ++i) {
+ for (size_t j = 0; j < 3; ++j) {
+ EXPECT_STREQ(
+ out.quuxMatrix[i][j].first.c_str(),
+ in.quuxMatrix[4-i][2-j].last.c_str());
+
+ EXPECT_STREQ(
+ out.quuxMatrix[i][j].last.c_str(),
+ in.quuxMatrix[4-i][2-j].first.c_str());
+ }
+ }
+ }));
+}
+
TEST_F(HidlTest, BarThisIsNewTest) {
// Now the tricky part, get access to the derived interface.
ALOGI("CLIENT call thisIsNew.");