C++程序  |  235行  |  7.33 KB

/*
 * 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;
}