Home | History | Annotate | Download | only in trace_processor
      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/sqlite3_str_split.h"
     18 
     19 #include "src/trace_processor/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 
     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 
     77 void sqlite3_str_split_init(sqlite3* db) {
     78   PERFETTO_CHECK(sqlite3_create_function(db, "str_split", 3,
     79                                          SQLITE_UTF8 | SQLITE_DETERMINISTIC, 0,
     80                                          &sqlite_str_split, 0, 0) == SQLITE_OK);
     81 }
     82 
     83 }  // namespace trace_processor
     84 }  // namespace perfetto
     85