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