blob: e364163225fb67ec77e2cb1e666ace6ff93e537e [file] [log] [blame]
// Copyright (C) 2019 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.
#ifndef IORAP_SRC_DB_APP_COMPONENT_NAME_H_
#define IORAP_SRC_DB_APP_COMPONENT_NAME_H_
namespace iorap::db {
struct AppComponentName {
std::string package;
std::string activity_name;
// Turns the activity name to the fully qualified name.
// For example, if the activity name is ".MainActivity" and the package is
// foo.bar. Then the fully qualified name is foo.bar.MainActivity.
AppComponentName Canonicalize() const {
if (!activity_name.empty() && activity_name[0] == '.') {
return {package, package + activity_name};
}
return {package, activity_name};
}
static bool HasAppComponentName(const std::string& s) {
return s.find('/') != std::string::npos;
}
// "com.foo.bar/.A" -> {"com.foo.bar", ".A"}
static AppComponentName FromString(const std::string& s) {
constexpr const char delimiter = '/';
if (!HasAppComponentName(s)) {
return {std::move(s), ""};
}
std::string package = s.substr(0, s.find(delimiter));
std::string activity_name = s;
activity_name.erase(0, s.find(delimiter) + sizeof(delimiter));
return {std::move(package), std::move(activity_name)};
}
// {"com.foo.bar", ".A"} -> "com.foo.bar/.A"
std::string ToString() const {
return package + "/" + activity_name;
}
/*
* '/' is encoded into %2F
* '%' is encoded into %25
*
* This allows the component name to be be used as a file name
* ('/' is illegal due to being a path separator) with minimal
* munging.
*/
// "com.foo.bar%2F.A%25" -> {"com.foo.bar", ".A%"}
static AppComponentName FromUrlEncodedString(const std::string& s) {
std::string cpy = s;
Replace(cpy, "%2F", "/");
Replace(cpy, "%25", "%");
return FromString(cpy);
}
// {"com.foo.bar", ".A%"} -> "com.foo.bar%2F.A%25"
std::string ToUrlEncodedString() const {
std::string s = ToString();
Replace(s, "%", "%25");
Replace(s, "/", "%2F");
return s;
}
/*
* '/' is encoded into @@
* '%' is encoded into ^^
*
* Two purpose:
* 1. This allows the package name to be used as a file name
* ('/' is illegal due to being a path separator) with minimal
* munging.
* 2. This allows the package name to be used in .mk file because
* '%' is a special char and cannot be easily escaped in Makefile.
*
* This is a workround for test purpose.
* Only package name is used because activity name varies on
* different testing framework.
* Hopefully, the double "@@" and "^^" are not used in other cases.
*/
// {"com.foo.bar", ".A%"} -> "com.foo.bar"
std::string ToMakeFileSafeEncodedPkgString() const {
std::string s = package;
Replace(s, "/", "@@");
Replace(s, "%", "^^");
return s;
}
private:
static bool Replace(std::string& str, const std::string& from, const std::string& to) {
// TODO: call in a loop to replace all occurrences, not just the first one.
const size_t start_pos = str.find(from);
if (start_pos == std::string::npos) {
return false;
}
str.replace(start_pos, from.length(), to);
return true;
}
};
inline std::ostream& operator<<(std::ostream& os, const AppComponentName& name) {
os << name.ToString();
return os;
}
} // namespace iorap::db
#endif // IORAP_SRC_DB_APP_COMPONENT_NAME_H_