/* * Copyright (C) 2015 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include "Utilities.h" using namespace std; const char LEGAL_NOTICE[] = "/*\n" " * Copyright (C) 2016 The Android Open Source Project\n" " *\n" " * Licensed under the Apache License, Version 2.0 (the \"License\");\n" " * you may not use this file except in compliance with the License.\n" " * You may obtain a copy of the License at\n" " *\n" " * http://www.apache.org/licenses/LICENSE-2.0\n" " *\n" " * Unless required by applicable law or agreed to in writing, software\n" " * distributed under the License is distributed on an \"AS IS\" BASIS,\n" " * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n" " * See the License for the specific language governing permissions and\n" " * limitations under the License.\n" " */\n\n"; const char AUTO_GENERATED_WARNING[] = "Don't edit this file! It is auto-generated by frameworks/rs/api/generate.sh."; string capitalize(const string& source) { int length = source.length(); string result; bool capitalize = true; for (int s = 0; s < length; s++) { if (source[s] == '_') { capitalize = true; } else if (capitalize) { result += toupper(source[s]); capitalize = false; } else { result += source[s]; } } return result; } void trimSpaces(string* s) { const size_t end = s->find_last_not_of(" "); if (end == string::npos) { // All spaces s->erase(); return; } else { s->erase(end + 1); } const size_t start = s->find_first_not_of(" "); if (start > 0) { s->erase(0, start); } } string stringReplace(string s, string match, string rep) { while (1) { // This is not efficient but we don't care, as this program runs very rarely. size_t p = s.find(match); if (p == string::npos) break; s.erase(p, match.size()); s.insert(p, rep); } return s; } bool charRemoved(char c, string* s) { size_t p = s->find(c); if (p != string::npos) { s->erase(p, 1); return true; } return false; } string stripHtml(const string& html) { string in = stringReplace(html, "
  • ", "- "); string out; for (size_t start = 0; start < in.size(); start++) { size_t lt = in.find('<', start); if (lt == string::npos) { out += in.substr(start); break; } out += in.substr(start, lt - start); if (isalpha(in[lt + 1]) || in[lt + 1] == '/') { // It's an HTML tag. Search for the end. start = in.find('>', lt + 1); if (start == string::npos) { break; } } else { out += '<'; } } out = stringReplace(out, ">", ">"); out = stringReplace(out, "<", "<"); out = stringReplace(out, " ", " "); out = stringReplace(out, "&", "&"); return out; } string hashString(const string& s) { long hash = 0; for (size_t i = 0; i < s.length(); i++) { hash = hash * 43 + s[i]; } stringstream stream; stream << "0x" << std::hex << hash << "l"; return stream.str(); } bool testAndSet(const string& flag, set* set) { if (set->find(flag) == set->end()) { set->insert(flag); return false; } return true; } double maxDoubleForInteger(int numberOfIntegerBits, int mantissaSize) { /* Double has only 52 bits of precision (53 implied). So for longs, we want * to create smaller values to avoid a round up. Same for floats and halfs. */ int lowZeroBits = max(0, numberOfIntegerBits - mantissaSize); uint64_t l = (0xffffffffffffffff >> (64 - numberOfIntegerBits + lowZeroBits)) << lowZeroBits; return (double)l; } // Add the value to the stream, prefixed with a ", " if needed. static void addCommaSeparated(const string& value, ostringstream* stream, bool* needComma) { if (value.empty()) { return; } if (*needComma) { *stream << ", "; } *stream << value; *needComma = true; } string makeAttributeTag(const string& userAttribute, const string& additionalAttribute, unsigned int deprecatedApiLevel, const string& deprecatedMessage) { ostringstream stream; bool needComma = false; if (userAttribute[0] == '=') { /* If starts with an equal, we don't automatically add additionalAttribute. * This is because of the error we made defining rsUnpackColor8888(). */ addCommaSeparated(userAttribute.substr(1), &stream, &needComma); } else { addCommaSeparated(userAttribute, &stream, &needComma); addCommaSeparated(additionalAttribute, &stream, &needComma); } if (deprecatedApiLevel > 0) { stream << "\n#if (defined(RS_VERSION) && (RS_VERSION >= " << deprecatedApiLevel << "))\n"; addCommaSeparated("deprecated", &stream, &needComma); if (!deprecatedMessage.empty()) { // Remove any @ that's used for generating documentation cross references. string s = deprecatedMessage; s.erase(std::remove(s.begin(), s.end(), '@'), s.end()); stream << "(\"" << s << "\")"; } stream << "\n#endif\n"; } if (stream.tellp() == 0) { return ""; } return " __attribute__((" + stream.str() + "))"; } // Opens the stream. Reports an error if it can't. bool GeneratedFile::start(const string& directory, const string& name) { const string path = directory + "/" + name; open(path.c_str(), ios::out | ios::trunc); if (!is_open()) { cerr << "Error. Can't open the output file: " << path << "\n"; return false; } return true; } void GeneratedFile::writeNotices() { *this << LEGAL_NOTICE; *this << "// " << AUTO_GENERATED_WARNING << "\n\n"; } void GeneratedFile::increaseIndent() { mIndent.append(string(TAB_SIZE, ' ')); } void GeneratedFile::decreaseIndent() { mIndent.erase(0, TAB_SIZE); }