blob: 299be1e1ffc0bf4d99f8603ff6b646ad6519d43c [file] [log] [blame]
Inseob Kim5f8f32c2018-08-24 11:10:44 +09001/*
2 * Copyright (C) 2018 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#define LOG_TAG "sysprop_cpp_gen"
18
19#include "CppGen.h"
20
21#include <android-base/file.h>
22#include <android-base/logging.h>
23#include <android-base/stringprintf.h>
24#include <android-base/strings.h>
25#include <cerrno>
26#include <regex>
27#include <string>
28
29#include "CodeWriter.h"
30#include "Common.h"
31#include "sysprop.pb.h"
32
33namespace {
34
35constexpr const char* kIndent = " ";
36
37constexpr const char* kCppHeaderIncludes =
38 R"(#include <cstdint>
39#include <optional>
40#include <string>
41#include <vector>
42
43)";
44
45constexpr const char* kCppSourceIncludes =
Inseob Kim59bd6e32019-03-27 17:26:02 +090046 R"(#include <cctype>
47#include <cerrno>
48#include <cstdio>
49#include <cstring>
50#include <limits>
Inseob Kim5f8f32c2018-08-24 11:10:44 +090051#include <utility>
52
Inseob Kim5f8f32c2018-08-24 11:10:44 +090053#include <strings.h>
Inseob Kim698aba92018-09-18 20:39:46 +090054#include <sys/system_properties.h>
Inseob Kim5f8f32c2018-08-24 11:10:44 +090055
Inseob Kim5f8f32c2018-08-24 11:10:44 +090056#include <android-base/parseint.h>
Inseob Kim59bd6e32019-03-27 17:26:02 +090057#include <log/log.h>
Inseob Kim5f8f32c2018-08-24 11:10:44 +090058
59)";
60
61constexpr const char* kCppParsersAndFormatters =
62 R"(template <typename T> constexpr bool is_vector = false;
63
64template <typename T> constexpr bool is_vector<std::vector<T>> = true;
65
Inseob Kim5f8f32c2018-08-24 11:10:44 +090066template <> [[maybe_unused]] std::optional<bool> DoParse(const char* str) {
Inseob Kim44734d42018-08-30 17:11:05 +090067 static constexpr const char* kYes[] = {"1", "true"};
68 static constexpr const char* kNo[] = {"0", "false"};
Inseob Kim5f8f32c2018-08-24 11:10:44 +090069
70 for (const char* yes : kYes) {
71 if (strcasecmp(yes, str) == 0) return std::make_optional(true);
72 }
73
74 for (const char* no : kNo) {
75 if (strcasecmp(no, str) == 0) return std::make_optional(false);
76 }
77
78 return std::nullopt;
79}
80
81template <> [[maybe_unused]] std::optional<std::int32_t> DoParse(const char* str) {
82 std::int32_t ret;
Inseob Kim59bd6e32019-03-27 17:26:02 +090083 return android::base::ParseInt(str, &ret) ? std::make_optional(ret) : std::nullopt;
Inseob Kim5f8f32c2018-08-24 11:10:44 +090084}
85
86template <> [[maybe_unused]] std::optional<std::int64_t> DoParse(const char* str) {
87 std::int64_t ret;
Inseob Kim59bd6e32019-03-27 17:26:02 +090088 return android::base::ParseInt(str, &ret) ? std::make_optional(ret) : std::nullopt;
Inseob Kim5f8f32c2018-08-24 11:10:44 +090089}
90
91template <> [[maybe_unused]] std::optional<double> DoParse(const char* str) {
92 int old_errno = errno;
93 errno = 0;
94 char* end;
95 double ret = std::strtod(str, &end);
96 if (errno != 0) {
97 return std::nullopt;
98 }
99 if (str == end || *end != '\0') {
Inseob Kim59bd6e32019-03-27 17:26:02 +0900100 errno = EINVAL;
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900101 return std::nullopt;
102 }
103 errno = old_errno;
104 return std::make_optional(ret);
105}
106
107template <> [[maybe_unused]] std::optional<std::string> DoParse(const char* str) {
Inseob Kim14e51872018-10-25 14:27:33 +0900108 return *str == '\0' ? std::nullopt : std::make_optional(str);
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900109}
110
Inseob Kimdb7daa12018-12-12 18:04:40 +0900111template <typename Vec> [[maybe_unused]] Vec DoParseList(const char* str) {
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900112 Vec ret;
Inseob Kim59bd6e32019-03-27 17:26:02 +0900113 const char* p = str;
114 for (;;) {
115 const char* found = p;
116 while (*found != '\0' && *found != ',') {
117 ++found;
118 }
119 std::string value(p, found);
120 ret.emplace_back(DoParse<typename Vec::value_type>(value.c_str()));
121 if (*found == '\0') break;
122 p = found + 1;
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900123 }
Inseob Kimdb7daa12018-12-12 18:04:40 +0900124 return ret;
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900125}
126
Inseob Kimdb7daa12018-12-12 18:04:40 +0900127template <typename T> inline T TryParse(const char* str) {
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900128 if constexpr(is_vector<T>) {
129 return DoParseList<T>(str);
130 } else {
131 return DoParse<T>(str);
132 }
133}
134
Inseob Kimdb7daa12018-12-12 18:04:40 +0900135[[maybe_unused]] std::string FormatValue(const std::optional<std::int32_t>& value) {
136 return value ? std::to_string(*value) : "";
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900137}
138
Inseob Kimdb7daa12018-12-12 18:04:40 +0900139[[maybe_unused]] std::string FormatValue(const std::optional<std::int64_t>& value) {
140 return value ? std::to_string(*value) : "";
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900141}
142
Inseob Kimdb7daa12018-12-12 18:04:40 +0900143[[maybe_unused]] std::string FormatValue(const std::optional<double>& value) {
Inseob Kim59bd6e32019-03-27 17:26:02 +0900144 if (!value) return "";
145 char buf[1024];
146 std::sprintf(buf, "%.*g", std::numeric_limits<double>::max_digits10, *value);
147 return buf;
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900148}
149
Inseob Kimdb7daa12018-12-12 18:04:40 +0900150[[maybe_unused]] std::string FormatValue(const std::optional<bool>& value) {
151 return value ? (*value ? "true" : "false") : "";
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900152}
153
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900154template <typename T>
155[[maybe_unused]] std::string FormatValue(const std::vector<T>& value) {
156 if (value.empty()) return "";
157
158 std::string ret;
Inseob Kim9c5147d2019-03-06 11:36:36 +0900159 bool first = true;
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900160
161 for (auto&& element : value) {
Inseob Kim9c5147d2019-03-06 11:36:36 +0900162 if (!first) ret += ",";
163 else first = false;
Inseob Kimdb7daa12018-12-12 18:04:40 +0900164 if constexpr(std::is_same_v<T, std::optional<std::string>>) {
165 if (element) ret += *element;
Inseob Kimf18ca832018-08-31 16:07:45 +0900166 } else {
167 ret += FormatValue(element);
168 }
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900169 }
170
171 return ret;
172}
173
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900174template <typename T>
Inseob Kimdb7daa12018-12-12 18:04:40 +0900175T GetProp(const char* key) {
176 T ret;
Inseob Kim698aba92018-09-18 20:39:46 +0900177 auto pi = __system_property_find(key);
Inseob Kimdb7daa12018-12-12 18:04:40 +0900178 if (pi != nullptr) {
179 __system_property_read_callback(pi, [](void* cookie, const char*, const char* value, std::uint32_t) {
180 *static_cast<T*>(cookie) = TryParse<T>(value);
181 }, &ret);
182 }
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900183 return ret;
184}
185
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900186)";
187
188const std::regex kRegexDot{"\\."};
189const std::regex kRegexUnderscore{"_"};
190
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900191std::string GetCppEnumName(const sysprop::Property& prop);
192std::string GetCppPropTypeName(const sysprop::Property& prop);
193std::string GetCppNamespace(const sysprop::Properties& props);
194
Inseob Kim803bfb82019-02-15 18:40:45 +0900195std::string GenerateHeader(const sysprop::Properties& props,
196 sysprop::Scope scope);
197std::string GenerateSource(const sysprop::Properties& props,
198 const std::string& include_name);
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900199
200std::string GetCppEnumName(const sysprop::Property& prop) {
Inseob Kim14e51872018-10-25 14:27:33 +0900201 return ApiNameToIdentifier(prop.api_name()) + "_values";
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900202}
203
204std::string GetCppPropTypeName(const sysprop::Property& prop) {
205 switch (prop.type()) {
206 case sysprop::Boolean:
Inseob Kimdb7daa12018-12-12 18:04:40 +0900207 return "std::optional<bool>";
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900208 case sysprop::Integer:
Inseob Kimdb7daa12018-12-12 18:04:40 +0900209 return "std::optional<std::int32_t>";
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900210 case sysprop::Long:
Inseob Kimdb7daa12018-12-12 18:04:40 +0900211 return "std::optional<std::int64_t>";
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900212 case sysprop::Double:
Inseob Kimdb7daa12018-12-12 18:04:40 +0900213 return "std::optional<double>";
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900214 case sysprop::String:
Inseob Kimdb7daa12018-12-12 18:04:40 +0900215 return "std::optional<std::string>";
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900216 case sysprop::Enum:
Inseob Kimdb7daa12018-12-12 18:04:40 +0900217 return "std::optional<" + GetCppEnumName(prop) + ">";
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900218 case sysprop::BooleanList:
Inseob Kimdb7daa12018-12-12 18:04:40 +0900219 return "std::vector<std::optional<bool>>";
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900220 case sysprop::IntegerList:
Inseob Kimdb7daa12018-12-12 18:04:40 +0900221 return "std::vector<std::optional<std::int32_t>>";
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900222 case sysprop::LongList:
Inseob Kimdb7daa12018-12-12 18:04:40 +0900223 return "std::vector<std::optional<std::int64_t>>";
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900224 case sysprop::DoubleList:
Inseob Kimdb7daa12018-12-12 18:04:40 +0900225 return "std::vector<std::optional<double>>";
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900226 case sysprop::StringList:
Inseob Kimdb7daa12018-12-12 18:04:40 +0900227 return "std::vector<std::optional<std::string>>";
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900228 case sysprop::EnumList:
Inseob Kimdb7daa12018-12-12 18:04:40 +0900229 return "std::vector<std::optional<" + GetCppEnumName(prop) + ">>";
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900230 default:
231 __builtin_unreachable();
232 }
233}
234
235std::string GetCppNamespace(const sysprop::Properties& props) {
236 return std::regex_replace(props.module(), kRegexDot, "::");
237}
238
Inseob Kim803bfb82019-02-15 18:40:45 +0900239std::string GenerateHeader(const sysprop::Properties& props,
240 sysprop::Scope scope) {
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900241 CodeWriter writer(kIndent);
242
243 writer.Write("%s", kGeneratedFileFooterComments);
244
Inseob Kim803bfb82019-02-15 18:40:45 +0900245 writer.Write("#pragma once\n\n");
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900246 writer.Write("%s", kCppHeaderIncludes);
247
248 std::string cpp_namespace = GetCppNamespace(props);
249 writer.Write("namespace %s {\n\n", cpp_namespace.c_str());
250
Inseob Kimcb71b082019-02-08 21:04:49 +0900251 bool first = true;
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900252
Inseob Kimcb71b082019-02-08 21:04:49 +0900253 for (int i = 0; i < props.prop_size(); ++i) {
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900254 const sysprop::Property& prop = props.prop(i);
Inseob Kimcb71b082019-02-08 21:04:49 +0900255
256 // Scope: Internal > System > Public
257 if (prop.scope() > scope) continue;
258
259 if (!first) {
260 writer.Write("\n");
261 } else {
262 first = false;
263 }
264
Inseob Kim14e51872018-10-25 14:27:33 +0900265 std::string prop_id = ApiNameToIdentifier(prop.api_name());
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900266 std::string prop_type = GetCppPropTypeName(prop);
267
268 if (prop.type() == sysprop::Enum || prop.type() == sysprop::EnumList) {
269 writer.Write("enum class %s {\n", GetCppEnumName(prop).c_str());
270 writer.Indent();
271 for (const std::string& name :
272 android::base::Split(prop.enum_values(), "|")) {
Inseob Kimf346e502019-01-04 10:32:39 +0900273 writer.Write("%s,\n", ToUpper(name).c_str());
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900274 }
275 writer.Dedent();
276 writer.Write("};\n\n");
277 }
278
Inseob Kimdb7daa12018-12-12 18:04:40 +0900279 writer.Write("%s %s();\n", prop_type.c_str(), prop_id.c_str());
Inseob Kimcb71b082019-02-08 21:04:49 +0900280 if (prop.access() != sysprop::Readonly && scope == sysprop::Internal) {
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900281 writer.Write("bool %s(const %s& value);\n", prop_id.c_str(),
282 prop_type.c_str());
283 }
284 }
285
Inseob Kim803bfb82019-02-15 18:40:45 +0900286 writer.Write("\n} // namespace %s\n", cpp_namespace.c_str());
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900287
Inseob Kim803bfb82019-02-15 18:40:45 +0900288 return writer.Code();
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900289}
290
Inseob Kim803bfb82019-02-15 18:40:45 +0900291std::string GenerateSource(const sysprop::Properties& props,
292 const std::string& include_name) {
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900293 CodeWriter writer(kIndent);
294 writer.Write("%s", kGeneratedFileFooterComments);
Inseob Kimdbc2c802018-09-13 14:16:48 +0900295 writer.Write("#include <%s>\n\n", include_name.c_str());
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900296 writer.Write("%s", kCppSourceIncludes);
297
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900298 std::string cpp_namespace = GetCppNamespace(props);
299
Inseob Kimf18ca832018-08-31 16:07:45 +0900300 writer.Write("namespace {\n\n");
301 writer.Write("using namespace %s;\n\n", cpp_namespace.c_str());
Inseob Kimdb7daa12018-12-12 18:04:40 +0900302 writer.Write("template <typename T> T DoParse(const char* str);\n\n");
Inseob Kimf18ca832018-08-31 16:07:45 +0900303
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900304 for (int i = 0; i < props.prop_size(); ++i) {
305 const sysprop::Property& prop = props.prop(i);
306 if (prop.type() != sysprop::Enum && prop.type() != sysprop::EnumList) {
307 continue;
308 }
309
Inseob Kim14e51872018-10-25 14:27:33 +0900310 std::string prop_id = ApiNameToIdentifier(prop.api_name());
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900311 std::string enum_name = GetCppEnumName(prop);
312
313 writer.Write("constexpr const std::pair<const char*, %s> %s_list[] = {\n",
314 enum_name.c_str(), prop_id.c_str());
315 writer.Indent();
316 for (const std::string& name :
317 android::base::Split(prop.enum_values(), "|")) {
318 writer.Write("{\"%s\", %s::%s},\n", name.c_str(), enum_name.c_str(),
Inseob Kimf346e502019-01-04 10:32:39 +0900319 ToUpper(name).c_str());
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900320 }
321 writer.Dedent();
322 writer.Write("};\n\n");
323
324 writer.Write("template <>\n");
325 writer.Write("std::optional<%s> DoParse(const char* str) {\n",
326 enum_name.c_str());
327 writer.Indent();
328 writer.Write("for (auto [name, val] : %s_list) {\n", prop_id.c_str());
329 writer.Indent();
330 writer.Write("if (strcmp(str, name) == 0) {\n");
331 writer.Indent();
332 writer.Write("return val;\n");
333 writer.Dedent();
334 writer.Write("}\n");
335 writer.Dedent();
336 writer.Write("}\n");
337 writer.Write("return std::nullopt;\n");
338 writer.Dedent();
339 writer.Write("}\n\n");
340
Inseob Kim14e51872018-10-25 14:27:33 +0900341 if (prop.access() != sysprop::Readonly) {
Inseob Kimdb7daa12018-12-12 18:04:40 +0900342 writer.Write("std::string FormatValue(std::optional<%s> value) {\n",
343 enum_name.c_str());
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900344 writer.Indent();
Inseob Kimdb7daa12018-12-12 18:04:40 +0900345 writer.Write("if (!value) return \"\";\n");
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900346 writer.Write("for (auto [name, val] : %s_list) {\n", prop_id.c_str());
347 writer.Indent();
Inseob Kimdb7daa12018-12-12 18:04:40 +0900348 writer.Write("if (val == *value) {\n");
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900349 writer.Indent();
350 writer.Write("return name;\n");
351 writer.Dedent();
352 writer.Write("}\n");
353 writer.Dedent();
354 writer.Write("}\n");
Inseob Kimf18ca832018-08-31 16:07:45 +0900355
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900356 writer.Write(
Inseob Kim59bd6e32019-03-27 17:26:02 +0900357 "LOG_ALWAYS_FATAL(\"Invalid value %%d for property %s\", "
358 "static_cast<std::int32_t>(*value));\n",
Inseob Kim14e51872018-10-25 14:27:33 +0900359 prop.prop_name().c_str());
Inseob Kimf18ca832018-08-31 16:07:45 +0900360
361 writer.Write("__builtin_unreachable();\n");
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900362 writer.Dedent();
363 writer.Write("}\n\n");
364 }
365 }
Inseob Kimf18ca832018-08-31 16:07:45 +0900366 writer.Write("%s", kCppParsersAndFormatters);
Inseob Kimade45e22018-08-29 19:08:35 +0900367 writer.Write("} // namespace\n\n");
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900368
369 writer.Write("namespace %s {\n\n", cpp_namespace.c_str());
370
371 for (int i = 0; i < props.prop_size(); ++i) {
372 if (i > 0) writer.Write("\n");
373
374 const sysprop::Property& prop = props.prop(i);
Inseob Kim14e51872018-10-25 14:27:33 +0900375 std::string prop_id = ApiNameToIdentifier(prop.api_name());
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900376 std::string prop_type = GetCppPropTypeName(prop);
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900377
Inseob Kimdb7daa12018-12-12 18:04:40 +0900378 writer.Write("%s %s() {\n", prop_type.c_str(), prop_id.c_str());
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900379 writer.Indent();
Inseob Kim14e51872018-10-25 14:27:33 +0900380 writer.Write("return GetProp<%s>(\"%s\");\n", prop_type.c_str(),
381 prop.prop_name().c_str());
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900382 writer.Dedent();
383 writer.Write("}\n");
384
Inseob Kim14e51872018-10-25 14:27:33 +0900385 if (prop.access() != sysprop::Readonly) {
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900386 writer.Write("\nbool %s(const %s& value) {\n", prop_id.c_str(),
387 prop_type.c_str());
388 writer.Indent();
Inseob Kim9c5147d2019-03-06 11:36:36 +0900389
390 const char* format_expr = "FormatValue(value).c_str()";
391
392 // Specialized formatters here
393 if (prop.type() == sysprop::String) {
394 format_expr = "value ? value->c_str() : \"\"";
395 } else if (prop.integer_as_bool()) {
396 if (prop.type() == sysprop::Boolean) {
397 // optional<bool> -> optional<int>
398 format_expr = "FormatValue(std::optional<int>(value)).c_str()";
399 } else if (prop.type() == sysprop::BooleanList) {
400 // vector<optional<bool>> -> vector<optional<int>>
401 format_expr =
402 "FormatValue(std::vector<std::optional<int>>("
403 "value.begin(), value.end())).c_str()";
404 }
405 }
406
Inseob Kimb04d6192018-12-14 08:33:16 +0900407 writer.Write("return __system_property_set(\"%s\", %s) == 0;\n",
Inseob Kim9c5147d2019-03-06 11:36:36 +0900408 prop.prop_name().c_str(), format_expr);
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900409 writer.Dedent();
410 writer.Write("}\n");
411 }
412 }
413
Inseob Kimade45e22018-08-29 19:08:35 +0900414 writer.Write("\n} // namespace %s\n", cpp_namespace.c_str());
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900415
Inseob Kim803bfb82019-02-15 18:40:45 +0900416 return writer.Code();
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900417}
418
419} // namespace
420
421bool GenerateCppFiles(const std::string& input_file_path,
Inseob Kimcb71b082019-02-08 21:04:49 +0900422 const std::string& header_dir,
423 const std::string& system_header_dir,
Inseob Kimdbc2c802018-09-13 14:16:48 +0900424 const std::string& source_output_dir,
425 const std::string& include_name, std::string* err) {
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900426 sysprop::Properties props;
427
428 if (!ParseProps(input_file_path, &props, err)) {
429 return false;
430 }
431
Inseob Kimdbc2c802018-09-13 14:16:48 +0900432 std::string output_basename = android::base::Basename(input_file_path);
433
Inseob Kimcb71b082019-02-08 21:04:49 +0900434 for (auto&& [scope, dir] : {
435 std::pair(sysprop::Internal, header_dir),
436 std::pair(sysprop::System, system_header_dir),
437 }) {
Inseob Kimcb71b082019-02-08 21:04:49 +0900438 if (!IsDirectory(dir) && !CreateDirectories(dir)) {
439 *err = "Creating directory to " + dir + " failed: " + strerror(errno);
440 return false;
441 }
442
443 std::string path = dir + "/" + output_basename + ".h";
Inseob Kim803bfb82019-02-15 18:40:45 +0900444 std::string result = GenerateHeader(props, scope);
Inseob Kimcb71b082019-02-08 21:04:49 +0900445
446 if (!android::base::WriteStringToFile(result, path)) {
447 *err =
448 "Writing generated header to " + path + " failed: " + strerror(errno);
449 return false;
450 }
451 }
452
Inseob Kimdbc2c802018-09-13 14:16:48 +0900453 std::string source_path = source_output_dir + "/" + output_basename + ".cpp";
Inseob Kim803bfb82019-02-15 18:40:45 +0900454 std::string source_result = GenerateSource(props, include_name);
Inseob Kim5f8f32c2018-08-24 11:10:44 +0900455
456 if (!android::base::WriteStringToFile(source_result, source_path)) {
457 *err = "Writing generated source to " + source_path +
458 " failed: " + strerror(errno);
459 return false;
460 }
461
462 return true;
463}