Add helper functions to create allocations
Bug: 23535985
- Adds high-level helper functions such as rsCreateAllocation_char4 etc
to the API.
- To accomplish this, adds "#RST_i" pattern replacement to the
generator. Similar to replacement of #1 with the equivalent parameter
in the spec, the generator now replaces '#RST_i' patterns with the RS
type equivalent of the parameter. For e.g.:
"
...
t: i8, i16 # assume this is the first "replaceable" list in this spec
...
inline:
rsCreateElement(RS_TYPE_#RST_1)
"
will generate
- "rsCreateElement(RS_TYPE_SIGNED_8)" and
- "rsCreateElement(RS_TYPE_SIGNED_16)"
respectively.
Change-Id: I162e3f3b9d89d477bf85e12dd300fd5b949dbd4b
diff --git a/api/Specification.cpp b/api/Specification.cpp
index 28e5231..785f358 100644
--- a/api/Specification.cpp
+++ b/api/Specification.cpp
@@ -52,6 +52,11 @@
static const char kTagUnreleased[] = "UNRELEASED";
+// Patterns that get substituted with C type or RS Data type names in function
+// names, arguments, return types, and inlines.
+static const string kCTypePatterns[] = {"#1", "#2", "#3", "#4"};
+static const string kRSTypePatterns[] = {"#RST_1", "#RST_2", "#RST_3", "#RST_4"};
+
// The singleton of the collected information of all the spec files.
SystemSpecification systemSpecification;
@@ -101,6 +106,15 @@
return result;
}
+// Returns true if each entry in typeVector is an RS numerical type
+static bool isRSTValid(const vector<string> &typeVector) {
+ for (auto type: typeVector) {
+ if (findCType(type) == -1)
+ return false;
+ }
+ return true;
+}
+
void ParameterDefinition::parseParameterDefinition(const string& type, const string& name,
const string& testOption, int lineNumber,
bool isReturn, Scanner* scanner) {
@@ -431,20 +445,34 @@
}
}
+string FunctionSpecification::expandRSTypeInString(const string &s,
+ const string &pattern,
+ const string &cTypeStr) const {
+ // Find index of numerical type corresponding to cTypeStr. The case where
+ // pattern is found in s but cTypeStr is not a numerical type is checked in
+ // checkRSTPatternValidity.
+ int typeIdx = findCType(cTypeStr);
+ if (typeIdx == -1) {
+ return s;
+ }
+ // If index exists, perform replacement.
+ return stringReplace(s, pattern, TYPES[typeIdx].rsDataType);
+}
+
string FunctionSpecification::expandString(string s,
int replacementIndexes[MAX_REPLACEABLES]) const {
- if (mReplaceables.size() > 0) {
- s = stringReplace(s, "#1", mReplaceables[0][replacementIndexes[0]]);
+
+
+ for (unsigned idx = 0; idx < mReplaceables.size(); idx ++) {
+ string toString = mReplaceables[idx][replacementIndexes[idx]];
+
+ // replace #RST_i patterns with RS datatype corresponding to toString
+ s = expandRSTypeInString(s, kRSTypePatterns[idx], toString);
+
+ // replace #i patterns with C type from mReplaceables
+ s = stringReplace(s, kCTypePatterns[idx], toString);
}
- if (mReplaceables.size() > 1) {
- s = stringReplace(s, "#2", mReplaceables[1][replacementIndexes[1]]);
- }
- if (mReplaceables.size() > 2) {
- s = stringReplace(s, "#3", mReplaceables[2][replacementIndexes[2]]);
- }
- if (mReplaceables.size() > 3) {
- s = stringReplace(s, "#4", mReplaceables[3][replacementIndexes[3]]);
- }
+
return s;
}
@@ -542,6 +570,24 @@
return true;
}
+void FunctionSpecification::checkRSTPatternValidity(const string &inlineStr, bool allow,
+ Scanner *scanner) {
+ for (int i = 0; i < MAX_REPLACEABLES; i ++) {
+ bool patternFound = inlineStr.find(kRSTypePatterns[i]) != string::npos;
+
+ if (patternFound) {
+ if (!allow) {
+ scanner->error() << "RST_i pattern not allowed here\n";
+ }
+ else if (mIsRSTAllowed[i] == false) {
+ scanner->error() << "Found pattern \"" << kRSTypePatterns[i]
+ << "\" in spec. But some entry in the corresponding"
+ << " parameter list cannot be translated to an RS type\n";
+ }
+ }
+ }
+}
+
void FunctionSpecification::scanFunctionSpecification(Scanner* scanner, SpecFile* specFile,
unsigned int maxApiLevel) {
// Some functions like convert have # part of the name. Truncate at that point.
@@ -596,21 +642,35 @@
t.push_back("4");
}
spec->mReplaceables.push_back(t);
+ // RST_i pattern not applicable for width.
+ spec->mIsRSTAllowed.push_back(false);
}
while (scanner->findOptionalTag("t:")) {
spec->mReplaceables.push_back(convertToTypeVector(scanner->getValue()));
+ spec->mIsRSTAllowed.push_back(isRSTValid(spec->mReplaceables.back()));
}
+ // Disallow RST_* pattern in function name
+ // FIXME the line number for this error would be wrong
+ spec->checkRSTPatternValidity(unexpandedName, false, scanner);
+
if (scanner->findTag("ret:")) {
ParameterEntry* p = scanner->parseArgString(true);
function->addReturn(p, scanner);
spec->mReturn = p;
+
+ // Disallow RST_* pattern in return type
+ spec->checkRSTPatternValidity(p->type, false, scanner);
}
while (scanner->findOptionalTag("arg:")) {
ParameterEntry* p = scanner->parseArgString(false);
function->addParameter(p, scanner);
spec->mParameters.push_back(p);
+
+ // Disallow RST_* pattern in parameter type or testOption
+ spec->checkRSTPatternValidity(p->type, false, scanner);
+ spec->checkRSTPatternValidity(p->testOption, false, scanner);
}
function->scanDocumentationTags(scanner, created, specFile);
@@ -619,6 +679,9 @@
scanner->checkNoValue();
while (scanner->findOptionalTag("")) {
spec->mInline.push_back(scanner->getValue());
+
+ // Allow RST_* pattern in inline definitions
+ spec->checkRSTPatternValidity(spec->mInline.back(), true, scanner);
}
}
if (scanner->findOptionalTag("test:")) {