blob: dcb3addc31f4b657b3ccabc21d86d6f39cc44c27 [file] [log] [blame]
// Copyright (C) 2016 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "emugl/common/stringparsing.h"
#include <algorithm>
// Replaces |rm| with |rep| in |str|.
// Example: rm = "a", rep = "bb", str = "abcd" returns "bbbcd"
std::string replace_with(const std::string& rm,
const std::string& rep,
const std::string& str) {
std::string res;
size_t p = 0;
while (p < str.size()) {
size_t match_pos = str.find(rm, p);
if (match_pos != std::string::npos) {
res.append(str.substr(p, match_pos - p));
res.append(rep);
p = match_pos + rm.size();
} else {
res.append(str.substr(p, str.size() - p));
p = str.size();
}
}
return res;
}
// Removes everything between "in" and "out" characters
// including the in/out characters themselves.
// Only cares about full matches.
// Only one level deep.
// Example: src = "a (1 2)b(3)",
// in = "(", out = ")"
// returns "a b"
// Example: src = "a (1 2 (3))"
// in = "(", out = ")"
// returns "a )"
std::string remove_in_out(const std::string& src,
const std::string& in,
const std::string& out,
bool* err) {
std::string res;
size_t p = 0;
while (p < src.size()) {
bool found_match = false;
size_t in_pos = src.find(in, p);
size_t out_pos;
if (in_pos != std::string::npos) {
out_pos = src.find(out, in_pos + in.size());
if (out_pos != std::string::npos) {
found_match = true;
} else {
*err = true;
return src;
}
} else {
out_pos = src.find(out, p);
if (out_pos != std::string::npos) {
*err = true;
return src;
}
}
if (found_match) {
res.append(src.substr(p, in_pos - p));
p = out_pos + out.size();
} else {
res.append(src.substr(p, src.size() - p));
p = src.size();
}
}
return res;
}
// Isolates everything between "in" and "out" characters,
// not including the in/out characters themselves.
// Only cares about full matches.
// Only one level deep.
// Example: src = "a (1 2)b(3)",
// in = "(", out = ")"
// returns vector with ["1 2", "3"]
// Example: src = "a (1 2 (3))"
// in = "(", out = ")"
// returns vector with ["1 2 (3"]
std::vector<std::string> isolate_in_out(
const std::string& src,
const std::string& in,
const std::string& out,
bool* err) {
std::vector<std::string> err_res;
std::vector<std::string> res;
size_t p = 0;
while (p < src.size()) {
bool found_match = false;
size_t in_pos = src.find(in, p);
size_t out_pos;
if (in_pos != std::string::npos) {
out_pos = src.find(out, in_pos + in.size());
if (out_pos != std::string::npos) {
found_match = true;
res.push_back(src.substr(in_pos + in.size(), out_pos - in_pos - in.size()));
} else {
*err = true;
return err_res;
}
} else {
out_pos = src.find(out, p);
if (out_pos != std::string::npos) {
*err = true;
return err_res;
}
}
if (found_match) {
p = out_pos + out.size();
} else {
p = src.size();
}
}
return res;
}
// Splits a string |src| delimited by |delim|.
// Example: delim = ",", src = "1,2,3"
// returns vector with ["1","2","3"]
std::vector<std::string> split(const std::string& delim,
const std::string& src) {
std::vector<std::string> res;
const size_t notfound = std::string::npos;
size_t delim_size = delim.size();
size_t p = 0;
size_t delim_loc = src.size();
while (p < src.size()) {
delim_loc = src.find(delim, p);
if (delim_loc != notfound) {
res.push_back(src.substr(p, delim_loc - p));
p = delim_loc + delim_size;
delim_loc = p;
} else {
res.push_back(src.substr(p, src.size() - p));
p = src.size();
}
}
return res;
}
// Attempts to find any string in to_find in src.
// Returns the position of the last match, or std::string::npos
// Example: src = "abcdef", to_find = ["b", "c", "d"]
// returns 3
size_t multi_find(const std::string& src,
const std::vector<std::string>& to_find) {
size_t res = std::string::npos;
for (size_t i = 0; i < to_find.size(); i++) {
size_t p = src.find(to_find[i]);
if (p != std::string::npos) {
res = p;
}
}
return res;
}