• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2020 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 //#define LOG_NDEBUG 0
18 #define LOG_TAG "MediaMetricsService::stringutils"
19 #include <utils/Log.h>
20 
21 #include "StringUtils.h"
22 
23 namespace android::mediametrics::stringutils {
24 
tokenizer(std::string::const_iterator & it,const std::string::const_iterator & end,const char * reserved)25 std::string tokenizer(std::string::const_iterator& it,
26         const std::string::const_iterator& end, const char *reserved)
27 {
28     // consume leading white space
29     for (; it != end && std::isspace(*it); ++it);
30     if (it == end) return {};
31 
32     auto start = it;
33     // parse until we hit a reserved keyword or space
34     if (strchr(reserved, *it)) return {start, ++it};
35     for (;;) {
36         ++it;
37         if (it == end || std::isspace(*it) || strchr(reserved, *it)) return {start, it};
38     }
39 }
40 
split(const std::string & flags,const char * delim)41 std::vector<std::string> split(const std::string& flags, const char *delim)
42 {
43     std::vector<std::string> result;
44     for (auto it = flags.begin(); ; ) {
45         auto flag = tokenizer(it, flags.end(), delim);
46         if (flag.empty() || !std::isalnum(flag[0])) return result;
47         result.emplace_back(std::move(flag));
48 
49         // look for the delimeter and discard
50         auto token = tokenizer(it, flags.end(), delim);
51         if (token.size() != 1 || strchr(delim, token[0]) == nullptr) return result;
52     }
53 }
54 
getDeviceAddressPairs(const std::string & devices)55 std::vector<std::pair<std::string, std::string>> getDeviceAddressPairs(const std::string& devices)
56 {
57     std::vector<std::pair<std::string, std::string>> result;
58 
59     // Currently, the device format is EXACTLY
60     // (device1, addr1)|(device2, addr2)|...
61 
62     static constexpr char delim[] = "()|,";
63     for (auto it = devices.begin(); ; ) {
64         auto token = tokenizer(it, devices.end(), delim);
65         if (token != "(") return result;
66 
67         auto device = tokenizer(it, devices.end(), delim);
68         if (device.empty() || !std::isalnum(device[0])) return result;
69 
70         token = tokenizer(it, devices.end(), delim);
71         if (token != ",") return result;
72 
73         // special handling here for empty addresses
74         auto address = tokenizer(it, devices.end(), delim);
75         if (address.empty() || !std::isalnum(device[0])) return result;
76         if (address == ")") {  // no address, just the ")"
77             address.clear();
78         } else {
79             token = tokenizer(it, devices.end(), delim);
80             if (token != ")") return result;
81         }
82 
83         result.emplace_back(std::move(device), std::move(address));
84 
85         token = tokenizer(it, devices.end(), delim);
86         if (token != "|") return result;  // this includes end of string detection
87     }
88 }
89 
replace(std::string & str,const char * targetChars,const char replaceChar)90 size_t replace(std::string &str, const char *targetChars, const char replaceChar)
91 {
92     size_t replaced = 0;
93     for (char &c : str) {
94         if (strchr(targetChars, c) != nullptr) {
95             c = replaceChar;
96             ++replaced;
97         }
98     }
99     return replaced;
100 }
101 
102 } // namespace android::mediametrics::stringutils
103