1/*
2 * Copyright 2012, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//===----------------------------------------------------------------------===//
18// This file implements RSInfo::write()
19//===----------------------------------------------------------------------===//
20
21#include "bcc/Renderscript/RSInfo.h"
22
23#include "bcc/Support/Log.h"
24#include "bcc/Support/OutputFile.h"
25
26using namespace bcc;
27
28namespace {
29
30template<typename ItemType, typename ItemContainer> inline bool
31helper_adapt_list_item(ItemType &pResult, const RSInfo &pInfo,
32                       const typename ItemContainer::const_iterator &pItem);
33
34template<> inline bool
35helper_adapt_list_item<rsinfo::DependencyTableItem, RSInfo::DependencyTableTy>(
36    rsinfo::DependencyTableItem &pResult,
37    const RSInfo &pInfo,
38    const RSInfo::DependencyTableTy::const_iterator &pItem) {
39  pResult.id = pInfo.getStringIdxInPool(pItem->first);
40  pResult.sha1 =
41      pInfo.getStringIdxInPool(reinterpret_cast<const char *>(pItem->second));
42
43  if (pResult.id == rsinfo::gInvalidStringIndex) {
44    ALOGE("RS dependency table contains invalid source id string '%s'.",
45          pItem->first);
46    return false;
47  }
48
49  if (pResult.sha1 == rsinfo::gInvalidStringIndex) {
50    ALOGE("RS dependency table contains invalid SHA-1 checksum string in '%s'.",
51          pItem->first);
52    return false;
53  }
54
55  return true;
56}
57
58template<> inline bool
59helper_adapt_list_item<rsinfo::PragmaItem, RSInfo::PragmaListTy>(
60    rsinfo::PragmaItem &pResult,
61    const RSInfo &pInfo,
62    const RSInfo::PragmaListTy::const_iterator &pItem) {
63  pResult.key = pInfo.getStringIdxInPool(pItem->first);
64  pResult.value = pInfo.getStringIdxInPool(pItem->second);
65
66  if (pResult.key == rsinfo::gInvalidStringIndex) {
67    ALOGE("RS pragma list contains invalid string '%s' for key.", pItem->first);
68    return false;
69  }
70
71  if (pResult.value == rsinfo::gInvalidStringIndex) {
72    ALOGE("RS pragma list contains invalid string '%s' for value.",
73          pItem->second);
74    return false;
75  }
76
77  return true;
78}
79
80template<> inline bool
81helper_adapt_list_item<rsinfo::ObjectSlotItem, RSInfo::ObjectSlotListTy>(
82    rsinfo::ObjectSlotItem &pResult,
83    const RSInfo &pInfo,
84    const RSInfo::ObjectSlotListTy::const_iterator &pItem) {
85  pResult.slot = *pItem;
86  return true;
87}
88
89template<> inline bool
90helper_adapt_list_item<rsinfo::ExportVarNameItem, RSInfo::ExportVarNameListTy>(
91    rsinfo::ExportVarNameItem &pResult,
92    const RSInfo &pInfo,
93    const RSInfo::ExportVarNameListTy::const_iterator &pItem) {
94  pResult.name = pInfo.getStringIdxInPool(*pItem);
95
96  if (pResult.name == rsinfo::gInvalidStringIndex) {
97    ALOGE("RS export vars contains invalid string '%s' for name.", *pItem);
98    return false;
99  }
100
101  return true;
102}
103
104template<> inline bool
105helper_adapt_list_item<rsinfo::ExportFuncNameItem,
106                       RSInfo::ExportFuncNameListTy>(
107    rsinfo::ExportFuncNameItem &pResult,
108    const RSInfo &pInfo,
109    const RSInfo::ExportFuncNameListTy::const_iterator &pItem) {
110  pResult.name = pInfo.getStringIdxInPool(*pItem);
111
112  if (pResult.name == rsinfo::gInvalidStringIndex) {
113    ALOGE("RS export funcs contains invalid string '%s' for name.", *pItem);
114    return false;
115  }
116
117  return true;
118}
119
120template<> inline bool
121helper_adapt_list_item<rsinfo::ExportForeachFuncItem,
122                       RSInfo::ExportForeachFuncListTy>(
123    rsinfo::ExportForeachFuncItem &pResult,
124    const RSInfo &pInfo,
125    const RSInfo::ExportForeachFuncListTy::const_iterator &pItem) {
126  pResult.name = pInfo.getStringIdxInPool(pItem->first);
127  pResult.signature = pItem->second;
128
129  if (pResult.name == rsinfo::gInvalidStringIndex) {
130    ALOGE("RS export foreach contains invalid string '%s' for name.",
131          pItem->first);
132    return false;
133  }
134
135  return true;
136}
137
138template<typename ItemType, typename ItemContainer>
139inline bool helper_write_list(OutputFile &pOutput,
140                              const RSInfo &pInfo,
141                              const rsinfo::ListHeader &pHeader,
142                              ItemContainer &pList) {
143  ItemType item;
144
145  for (typename ItemContainer::const_iterator item_iter = pList.begin(),
146          item_end = pList.end(); item_iter != item_end; item_iter++) {
147    // Convert each entry in the pList to ItemType.
148    if (!helper_adapt_list_item<ItemType, ItemContainer>(item,
149                                                         pInfo,
150                                                         item_iter)) {
151      return false;
152    }
153    // And write out an item.
154    if (pOutput.write(&item, sizeof(item)) != sizeof(item)) {
155      ALOGE("Cannot write out item of %s for RSInfo file %s! (%s)",
156            rsinfo::GetItemTypeName<ItemType>(), pOutput.getName().c_str(),
157            pOutput.getErrorMessage().c_str());
158      return false;
159    }
160  }
161
162  return true;
163}
164
165} // end anonymous namespace
166
167bool RSInfo::write(OutputFile &pOutput) {
168  off_t initial_offset = pOutput.tell();
169  const char *output_filename = pOutput.getName().c_str();
170
171  if (pOutput.hasError()) {
172    ALOGE("Invalid RS info file %s for output! (%s)",
173          output_filename, pOutput.getErrorMessage().c_str());
174    return false;
175  }
176
177  // Layout.
178  if (!layout(initial_offset)) {
179    return false;
180  }
181
182  // Write header.
183  if (pOutput.write(&mHeader, sizeof(mHeader)) != sizeof(mHeader)) {
184    ALOGE("Cannot write out the header for RSInfo file %s! (%s)",
185          output_filename, pOutput.getErrorMessage().c_str());
186    return false;
187  }
188
189  // Write string pool.
190  if (static_cast<size_t>(pOutput.write(mStringPool, mHeader.strPoolSize))
191          != mHeader.strPoolSize) {
192    ALOGE("Cannot write out the string pool for RSInfo file %s! (%s)",
193          output_filename, pOutput.getErrorMessage().c_str());
194    return false;
195  }
196
197  // Write dependencyTable.
198  if (!helper_write_list<rsinfo::DependencyTableItem, DependencyTableTy>
199        (pOutput, *this, mHeader.dependencyTable, mDependencyTable)) {
200    return false;
201  }
202
203  // Write pragmaList.
204  if (!helper_write_list<rsinfo::PragmaItem, PragmaListTy>
205        (pOutput, *this, mHeader.pragmaList, mPragmas)) {
206    return false;
207  }
208
209  // Write objectSlotList.
210  if (!helper_write_list<rsinfo::ObjectSlotItem, ObjectSlotListTy>
211        (pOutput, *this, mHeader.objectSlotList, mObjectSlots)) {
212    return false;
213  }
214
215  // Write exportVarNameList.
216  if (!helper_write_list<rsinfo::ExportVarNameItem, ExportVarNameListTy>
217        (pOutput, *this, mHeader.exportVarNameList, mExportVarNames)) {
218    return false;
219  }
220
221  // Write exportFuncNameList.
222  if (!helper_write_list<rsinfo::ExportFuncNameItem, ExportFuncNameListTy>
223        (pOutput, *this, mHeader.exportFuncNameList, mExportFuncNames)) {
224    return false;
225  }
226
227  // Write exportForeachFuncList.
228  if (!helper_write_list<rsinfo::ExportForeachFuncItem, ExportForeachFuncListTy>
229        (pOutput, *this, mHeader.exportForeachFuncList, mExportForeachFuncs)) {
230    return false;
231  }
232
233  return true;
234}
235