blob: 50525bcb6ed16b226af1f48adf1fd482cc32b3a1 [file] [log] [blame]
Andy Hung1ea842e2020-05-18 10:47:31 -07001/*
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
23namespace android::mediametrics::stringutils {
24
25std::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
41std::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
55std::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
90size_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