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