/*
* Copyright 2012, 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.
*/
//===----------------------------------------------------------------------===//
// This file implements RSInfo::write()
//===----------------------------------------------------------------------===//
#include "bcc/Renderscript/RSInfo.h"
#include "bcc/Support/Log.h"
#include "bcc/Support/OutputFile.h"
using namespace bcc;
namespace {
template<typename ItemType, typename ItemContainer> inline bool
helper_adapt_list_item(ItemType &pResult, const RSInfo &pInfo,
const typename ItemContainer::const_iterator &pItem);
template<> inline bool
helper_adapt_list_item<rsinfo::DependencyTableItem, RSInfo::DependencyTableTy>(
rsinfo::DependencyTableItem &pResult,
const RSInfo &pInfo,
const RSInfo::DependencyTableTy::const_iterator &pItem) {
pResult.id = pInfo.getStringIdxInPool(pItem->first);
pResult.sha1 =
pInfo.getStringIdxInPool(reinterpret_cast<const char *>(pItem->second));
if (pResult.id == rsinfo::gInvalidStringIndex) {
ALOGE("RS dependency table contains invalid source id string '%s'.",
pItem->first);
return false;
}
if (pResult.sha1 == rsinfo::gInvalidStringIndex) {
ALOGE("RS dependency table contains invalid SHA-1 checksum string in '%s'.",
pItem->first);
return false;
}
return true;
}
template<> inline bool
helper_adapt_list_item<rsinfo::PragmaItem, RSInfo::PragmaListTy>(
rsinfo::PragmaItem &pResult,
const RSInfo &pInfo,
const RSInfo::PragmaListTy::const_iterator &pItem) {
pResult.key = pInfo.getStringIdxInPool(pItem->first);
pResult.value = pInfo.getStringIdxInPool(pItem->second);
if (pResult.key == rsinfo::gInvalidStringIndex) {
ALOGE("RS pragma list contains invalid string '%s' for key.", pItem->first);
return false;
}
if (pResult.value == rsinfo::gInvalidStringIndex) {
ALOGE("RS pragma list contains invalid string '%s' for value.",
pItem->second);
return false;
}
return true;
}
template<> inline bool
helper_adapt_list_item<rsinfo::ObjectSlotItem, RSInfo::ObjectSlotListTy>(
rsinfo::ObjectSlotItem &pResult,
const RSInfo &pInfo,
const RSInfo::ObjectSlotListTy::const_iterator &pItem) {
pResult.slot = *pItem;
return true;
}
template<> inline bool
helper_adapt_list_item<rsinfo::ExportVarNameItem, RSInfo::ExportVarNameListTy>(
rsinfo::ExportVarNameItem &pResult,
const RSInfo &pInfo,
const RSInfo::ExportVarNameListTy::const_iterator &pItem) {
pResult.name = pInfo.getStringIdxInPool(*pItem);
if (pResult.name == rsinfo::gInvalidStringIndex) {
ALOGE("RS export vars contains invalid string '%s' for name.", *pItem);
return false;
}
return true;
}
template<> inline bool
helper_adapt_list_item<rsinfo::ExportFuncNameItem,
RSInfo::ExportFuncNameListTy>(
rsinfo::ExportFuncNameItem &pResult,
const RSInfo &pInfo,
const RSInfo::ExportFuncNameListTy::const_iterator &pItem) {
pResult.name = pInfo.getStringIdxInPool(*pItem);
if (pResult.name == rsinfo::gInvalidStringIndex) {
ALOGE("RS export funcs contains invalid string '%s' for name.", *pItem);
return false;
}
return true;
}
template<> inline bool
helper_adapt_list_item<rsinfo::ExportForeachFuncItem,
RSInfo::ExportForeachFuncListTy>(
rsinfo::ExportForeachFuncItem &pResult,
const RSInfo &pInfo,
const RSInfo::ExportForeachFuncListTy::const_iterator &pItem) {
pResult.name = pInfo.getStringIdxInPool(pItem->first);
pResult.signature = pItem->second;
if (pResult.name == rsinfo::gInvalidStringIndex) {
ALOGE("RS export foreach contains invalid string '%s' for name.",
pItem->first);
return false;
}
return true;
}
template<typename ItemType, typename ItemContainer>
inline bool helper_write_list(OutputFile &pOutput,
const RSInfo &pInfo,
const rsinfo::ListHeader &pHeader,
ItemContainer &pList) {
ItemType item;
for (typename ItemContainer::const_iterator item_iter = pList.begin(),
item_end = pList.end(); item_iter != item_end; item_iter++) {
// Convert each entry in the pList to ItemType.
if (!helper_adapt_list_item<ItemType, ItemContainer>(item,
pInfo,
item_iter)) {
return false;
}
// And write out an item.
if (pOutput.write(&item, sizeof(item)) != sizeof(item)) {
ALOGE("Cannot write out item of %s for RSInfo file %s! (%s)",
rsinfo::GetItemTypeName<ItemType>(), pOutput.getName().c_str(),
pOutput.getErrorMessage().c_str());
return false;
}
}
return true;
}
} // end anonymous namespace
bool RSInfo::write(OutputFile &pOutput) {
off_t initial_offset = pOutput.tell();
const char *output_filename = pOutput.getName().c_str();
if (pOutput.hasError()) {
ALOGE("Invalid RS info file %s for output! (%s)",
output_filename, pOutput.getErrorMessage().c_str());
return false;
}
// Layout.
if (!layout(initial_offset)) {
return false;
}
// Write header.
if (pOutput.write(&mHeader, sizeof(mHeader)) != sizeof(mHeader)) {
ALOGE("Cannot write out the header for RSInfo file %s! (%s)",
output_filename, pOutput.getErrorMessage().c_str());
return false;
}
// Write string pool.
if (static_cast<size_t>(pOutput.write(mStringPool, mHeader.strPoolSize))
!= mHeader.strPoolSize) {
ALOGE("Cannot write out the string pool for RSInfo file %s! (%s)",
output_filename, pOutput.getErrorMessage().c_str());
return false;
}
// Write dependencyTable.
if (!helper_write_list<rsinfo::DependencyTableItem, DependencyTableTy>
(pOutput, *this, mHeader.dependencyTable, mDependencyTable)) {
return false;
}
// Write pragmaList.
if (!helper_write_list<rsinfo::PragmaItem, PragmaListTy>
(pOutput, *this, mHeader.pragmaList, mPragmas)) {
return false;
}
// Write objectSlotList.
if (!helper_write_list<rsinfo::ObjectSlotItem, ObjectSlotListTy>
(pOutput, *this, mHeader.objectSlotList, mObjectSlots)) {
return false;
}
// Write exportVarNameList.
if (!helper_write_list<rsinfo::ExportVarNameItem, ExportVarNameListTy>
(pOutput, *this, mHeader.exportVarNameList, mExportVarNames)) {
return false;
}
// Write exportFuncNameList.
if (!helper_write_list<rsinfo::ExportFuncNameItem, ExportFuncNameListTy>
(pOutput, *this, mHeader.exportFuncNameList, mExportFuncNames)) {
return false;
}
// Write exportForeachFuncList.
if (!helper_write_list<rsinfo::ExportForeachFuncItem, ExportForeachFuncListTy>
(pOutput, *this, mHeader.exportForeachFuncList, mExportForeachFuncs)) {
return false;
}
return true;
}