/*
* 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 <algorithm>
#include <iostream>
#include <sstream>
#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, "<li>", "- ");
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<string>* 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);
}