• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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 #include "src/trace_processor/util/sql_argument.h"
18 
19 #include "perfetto/ext/base/string_utils.h"
20 
21 namespace perfetto {
22 namespace trace_processor {
23 namespace sql_argument {
24 
IsValidName(base::StringView str)25 bool IsValidName(base::StringView str) {
26   auto pred = [](char c) { return !(isalnum(c) || c == '_'); };
27   return std::find_if(str.begin(), str.end(), pred) == str.end();
28 }
29 
ParseType(base::StringView str)30 std::optional<Type> ParseType(base::StringView str) {
31   if (str == "BOOL") {
32     return Type::kBool;
33   } else if (str == "INT") {
34     return Type::kInt;
35   } else if (str == "UINT") {
36     return Type::kUint;
37   } else if (str == "LONG") {
38     return Type::kLong;
39   } else if (str == "FLOAT") {
40     return Type::kFloat;
41   } else if (str == "DOUBLE") {
42     return Type::kDouble;
43   } else if (str == "STRING") {
44     return Type::kString;
45   } else if (str == "PROTO") {
46     return Type::kProto;
47   } else if (str == "BYTES") {
48     return Type::kBytes;
49   }
50   return std::nullopt;
51 }
52 
TypeToHumanFriendlyString(sql_argument::Type type)53 const char* TypeToHumanFriendlyString(sql_argument::Type type) {
54   using Type = sql_argument::Type;
55   switch (type) {
56     case Type::kBool:
57       return "BOOL";
58     case Type::kInt:
59       return "INT";
60     case Type::kUint:
61       return "UINT";
62     case Type::kLong:
63       return "LONG";
64     case Type::kFloat:
65       return "FLOAT";
66     case Type::kDouble:
67       return "DOUBLE";
68     case Type::kString:
69       return "STRING";
70     case Type::kProto:
71       return "PROTO";
72     case Type::kBytes:
73       return "BYTES";
74   }
75   PERFETTO_FATAL("For GCC");
76 }
77 
TypeToSqlValueType(sql_argument::Type type)78 SqlValue::Type TypeToSqlValueType(sql_argument::Type type) {
79   using Type = sql_argument::Type;
80   switch (type) {
81     case Type::kBool:
82     case Type::kInt:
83     case Type::kUint:
84     case Type::kLong:
85       return SqlValue::kLong;
86     case Type::kFloat:
87     case Type::kDouble:
88       return SqlValue::kDouble;
89     case Type::kString:
90       return SqlValue::kString;
91     case Type::kProto:
92     case Type::kBytes:
93       return SqlValue::kBytes;
94   }
95   PERFETTO_FATAL("For GCC");
96 }
97 
ParseArgumentDefinitions(const std::string & args,std::vector<ArgumentDefinition> & out)98 base::Status ParseArgumentDefinitions(const std::string& args,
99                                       std::vector<ArgumentDefinition>& out) {
100   std::string trimmed_args = base::TrimWhitespace(args);
101   for (const auto& arg : base::SplitString(trimmed_args, ",")) {
102     const auto& arg_name_and_type =
103         (base::SplitString(base::TrimWhitespace(arg), " "));
104     if (arg_name_and_type.size() != 2) {
105       return base::ErrStatus(
106           "argument '%s' in function prototype should be of the form `name "
107           "TYPE`",
108           arg.c_str());
109     }
110 
111     const auto& arg_name = arg_name_and_type[0];
112     const auto& arg_type_str = arg_name_and_type[1];
113     if (!IsValidName(base::StringView(arg_name)))
114       return base::ErrStatus("argument '%s' is not alphanumeric", arg.c_str());
115 
116     auto opt_arg_type = ParseType(base::StringView(arg_type_str));
117     if (!opt_arg_type) {
118       return base::ErrStatus("unknown argument type in argument '%s'",
119                              arg.c_str());
120     }
121     out.emplace_back("$" + arg_name, *opt_arg_type);
122   }
123   return base::OkStatus();
124 }
125 
126 }  // namespace sql_argument
127 }  // namespace trace_processor
128 }  // namespace perfetto
129