1 // Copyright (C) 2019 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #ifndef IORAP_SRC_COMMON_CMD_UTILS_H_
16 #define IORAP_SRC_COMMON_CMD_UTILS_H_
17
18 #include <android-base/parsebool.h>
19 #include <android-base/properties.h>
20
21 #include <iostream>
22 #include <sstream>
23 #include <optional>
24 #include <vector>
25
26 namespace iorap::common {
27 // Create execve-compatible argv.
28 // The lifetime is tied to that of vector.
VecToArgv(const char * program_name,const std::vector<std::string> & vector)29 inline std::unique_ptr<const char*[]> VecToArgv(const char* program_name,
30 const std::vector<std::string>& vector) {
31 // include program name in argv[0]
32 // include a NULL sentinel in the end.
33 std::unique_ptr<const char*[]> ptr{new const char*[vector.size() + 2]};
34
35 // program name
36 ptr[0] = program_name;
37
38 // all the argv
39 for (size_t i = 0; i < vector.size(); ++i) {
40 ptr[i+1] = vector[i].c_str();
41 }
42
43 // null sentinel
44 ptr[vector.size() + 1] = nullptr;
45
46 return ptr;
47 }
48
49 // Appends an args to the argv.
50 template <class T>
AppendArgs(std::vector<std::string> & argv,const T & value)51 void AppendArgs(std::vector<std::string>& argv,
52 const T& value) {
53 std::stringstream ss;
54 ss << value;
55 argv.push_back(ss.str());
56 }
57
58 // Appends an args to the argv.
59 template <class T, class T2>
AppendArgs(std::vector<std::string> & argv,const T & value,const T2 & value2)60 void AppendArgs(std::vector<std::string>& argv,
61 const T& value,
62 const T2& value2) {
63 AppendArgs(argv, value);
64 AppendArgs(argv, value2);
65 }
66
67 // Appends a named argument to the argv.
68 //
69 // For example if <name> is "--property" and <value> is int(200):
70 // the string "--property=200" is appended to the argv.
71 template <class T, class T2>
AppendNamedArg(std::vector<std::string> & argv,const T & name,const T2 & value)72 void AppendNamedArg(std::vector<std::string>& argv,
73 const T& name,
74 const T2& value) {
75 std::stringstream ss;
76 ss << name;
77 ss << "=";
78 ss << value;
79
80 argv.push_back(ss.str());
81 }
82
83 // Appends args from a vector to the argv repeatedly to argv.
84 //
85 // For example, if <args> is "--timestamp" and <values> is [100, 200].
86 // The "--timestamp 100" and "--timestamp 200" are appended.
87 template <class T>
AppendArgsRepeatedly(std::vector<std::string> & argv,std::string args,const std::vector<T> & values)88 void AppendArgsRepeatedly(std::vector<std::string>& argv,
89 std::string args,
90 const std::vector<T>& values) {
91 for (const T& v : values) {
92 AppendArgs(argv, args, v);
93 }
94 }
95
96 // Appends args from a vector to the argv repeatedly to argv.
97 //
98 // For example, if values is [input1.pb, input2.pb],
99 // then the "input1.pb" and "input2.pb" are appended.
100 template <class T>
AppendArgsRepeatedly(std::vector<std::string> & argv,const std::vector<T> & values)101 void AppendArgsRepeatedly(std::vector<std::string>& argv,
102 const std::vector<T>& values) {
103 for (const T& v : values) {
104 AppendArgs(argv, v);
105 }
106 }
107
108 // Appends a named argument to the argv repeatedly with different values.
109 //
110 // For example if <name> is "--property" and <value> is [int(200), int(400)]:
111 // the strings "--property=200" and "--property=400" are both appended to the argv.
112 template <class T, class T2>
AppendNamedArgRepeatedly(std::vector<std::string> & argv,const T & name,const std::vector<T2> & values)113 void AppendNamedArgRepeatedly(std::vector<std::string>& argv,
114 const T& name,
115 const std::vector<T2>& values) {
116 for (const T2& v :values) {
117 AppendNamedArg(argv, name, v);
118 }
119 }
120
121 // Get the value of the property.
122 // Firstly, try to find the environment variable. If it does not exist,
123 // try to get the property. If neither, use the default value..
124 //
125 // For example, for prop foo.bar.baz, it will first check for
126 // FOO_BAR_BAZ environment variable.
GetEnvOrProperty(const std::string & prop,const std::string & default_val)127 inline std::string GetEnvOrProperty(const std::string& prop, const std::string& default_val) {
128 std::string env_str = prop;
129 // a.b.c -> a_b_c
130 std::replace(env_str.begin(), env_str.end(), '.', '_');
131 // a_b_c -> A_B_C
132 std::transform(env_str.begin(), env_str.end(), env_str.begin(), ::toupper);
133 char *env = getenv(env_str.c_str());
134 if (env) {
135 return std::string(env);
136 }
137 return ::android::base::GetProperty(prop, default_val);
138 }
139
140 // Get the boolean value of the property.
141 // Firstly, try to find the environment variable. If it does not exist,
142 // try to get the property. If neither, use the default value..
143 //
144 // For example, for prop foo.bar.baz, it will first check for
145 // FOO_BAR_BAZ environment variable.
GetBoolEnvOrProperty(const std::string & prop,bool default_val)146 inline bool GetBoolEnvOrProperty(const std::string& prop, bool default_val) {
147 std::string env_str = prop;
148 // a.b.c -> a_b_c
149 std::replace(env_str.begin(), env_str.end(), '.', '_');
150 // a_b_c -> A_B_C
151 std::transform(env_str.begin(), env_str.end(), env_str.begin(), ::toupper);
152 char *env = getenv(env_str.c_str());
153 if (env) {
154 using ::android::base::ParseBoolResult;
155
156 switch (::android::base::ParseBool(env)) {
157 case ParseBoolResult::kError:
158 break;
159 case ParseBoolResult::kFalse:
160 return false;
161 case ParseBoolResult::kTrue:
162 return true;
163 }
164 }
165 return ::android::base::GetBoolProperty(prop, default_val);
166 }
167
168 } // namespace iorap::common
169
170 #endif // IORAP_SRC_COMMON_CMD_UTILS_H_
171