• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2019 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/sqlite/sqlite3_str_split.h"
18 
19 #include "src/trace_processor/sqlite/sqlite_utils.h"
20 
21 namespace perfetto {
22 namespace trace_processor {
23 
24 namespace {
25 constexpr char kDelimiterError[] =
26     "str_split: delimiter must be a non-empty string";
27 constexpr char kSplitFieldIndexError[] =
28     "str_split: field number must be a non-negative integer";
29 
sqlite_str_split(sqlite3_context * context,int argc,sqlite3_value ** argv)30 void sqlite_str_split(sqlite3_context* context,
31                       int argc,
32                       sqlite3_value** argv) {
33   PERFETTO_DCHECK(argc == 3);
34   if (sqlite3_value_type(argv[1]) != SQLITE_TEXT) {
35     sqlite3_result_error(context, kDelimiterError, -1);
36     return;
37   }
38   const char* delimiter =
39       reinterpret_cast<const char*>(sqlite3_value_text(argv[1]));
40   const size_t delimiter_len = strlen(delimiter);
41   if (delimiter_len == 0) {
42     sqlite3_result_error(context, kDelimiterError, -1);
43     return;
44   }
45   if (sqlite3_value_type(argv[2]) != SQLITE_INTEGER) {
46     sqlite3_result_error(context, kSplitFieldIndexError, -1);
47     return;
48   }
49   int fld = sqlite3_value_int(argv[2]);
50   if (fld < 0) {
51     sqlite3_result_error(context, kSplitFieldIndexError, -1);
52     return;
53   }
54   if (sqlite3_value_type(argv[0]) != SQLITE_TEXT) {
55     sqlite3_result_null(context);
56     return;
57   }
58   const char* in = reinterpret_cast<const char*>(sqlite3_value_text(argv[0]));
59   const char* next;
60   do {
61     next = strstr(in, delimiter);
62     if (fld == 0) {
63       int size = next != nullptr ? static_cast<int>(next - in)
64                                  : static_cast<int>(strlen(in));
65       sqlite3_result_text(context, in, size, sqlite_utils::kSqliteTransient);
66       return;
67     } else if (next == nullptr) {
68       break;
69     }
70     in = next + delimiter_len;
71     --fld;
72   } while (fld >= 0);
73   sqlite3_result_null(context);
74 }
75 }  // namespace
76 
sqlite3_str_split_init(sqlite3 * db)77 void sqlite3_str_split_init(sqlite3* db) {
78   PERFETTO_CHECK(sqlite3_create_function(db, "str_split", 3,
79                                          SQLITE_UTF8 | SQLITE_DETERMINISTIC,
80                                          nullptr, &sqlite_str_split, nullptr,
81                                          nullptr) == SQLITE_OK);
82 }
83 
84 }  // namespace trace_processor
85 }  // namespace perfetto
86