mirror of
https://github.com/openharmony/distributedschedule_dms_fwk.git
synced 2026-07-01 04:19:44 -04:00
511 lines
12 KiB
C++
511 lines
12 KiB
C++
/*
|
|
* Copyright (c) 2021 Huawei Device Co., Ltd.
|
|
* 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 "uri.h"
|
|
#include <regex>
|
|
#include <vector>
|
|
#include "hilog/log.h"
|
|
#include "string_ex.h"
|
|
|
|
using std::string;
|
|
using std::regex;
|
|
using OHOS::HiviewDFX::HiLog;
|
|
|
|
namespace OHOS {
|
|
namespace {
|
|
const string NOT_CACHED = "NOT VALID";
|
|
const string EMPTY = "";
|
|
const size_t NOT_FOUND = string::npos;
|
|
const int NOT_CALCULATED = -2;
|
|
const int PORT_NONE = -1;
|
|
const char SCHEME_SEPARATOR = ':';
|
|
const char SCHEME_FRAGMENT = '#';
|
|
const char LEFT_SEPARATOR = '/';
|
|
const char RIGHT_SEPARATOR = '\\';
|
|
const char QUERY_FLAG = '?';
|
|
const char USER_HOST_SEPARATOR = '@';
|
|
const char PORT_SEPARATOR = ':';
|
|
const size_t POS_INC = 1;
|
|
const size_t POS_INC_MORE = 2;
|
|
const size_t POS_INC_AGAIN = 3;
|
|
const regex SCHEME_REGEX("[a-zA-Z][a-zA-Z|\\d|+|-|.]*$");
|
|
const HiviewDFX::HiLogLabel LABEL = {LOG_CORE, 0xD001800, "URI"};
|
|
}; // namespace
|
|
|
|
Uri::Uri(const string& uriString)
|
|
{
|
|
cachedSsi_ = NOT_FOUND;
|
|
cachedFsi_ = NOT_FOUND;
|
|
port_ = NOT_CALCULATED;
|
|
|
|
if (uriString.empty()) {
|
|
HiLog::Error(LABEL, "Input empty!");
|
|
return;
|
|
}
|
|
|
|
uriString_ = uriString;
|
|
scheme_ = NOT_CACHED;
|
|
ssp_ = NOT_CACHED;
|
|
authority_ = NOT_CACHED;
|
|
host_ = NOT_CACHED;
|
|
userInfo_ = NOT_CACHED;
|
|
query_ = NOT_CACHED;
|
|
path_ = NOT_CACHED;
|
|
fragment_ = NOT_CACHED;
|
|
|
|
if (!CheckScheme()) {
|
|
uriString_ = EMPTY;
|
|
HiLog::Error(LABEL, "Scheme wrong!");
|
|
}
|
|
}
|
|
|
|
bool Uri::CheckScheme()
|
|
{
|
|
scheme_ = ParseScheme();
|
|
if (scheme_.empty()) {
|
|
return true;
|
|
}
|
|
return regex_match(scheme_, SCHEME_REGEX);
|
|
}
|
|
|
|
string Uri::GetScheme()
|
|
{
|
|
if (uriString_.empty()) {
|
|
return EMPTY;
|
|
}
|
|
|
|
if (scheme_ == NOT_CACHED) {
|
|
scheme_ = ParseScheme();
|
|
}
|
|
return scheme_;
|
|
}
|
|
|
|
string Uri::ParseScheme()
|
|
{
|
|
size_t ssi = FindSchemeSeparator();
|
|
return (ssi == NOT_FOUND) ? EMPTY : uriString_.substr(0, ssi);
|
|
}
|
|
|
|
string Uri::GetSchemeSpecificPart()
|
|
{
|
|
if (uriString_.empty()) {
|
|
return EMPTY;
|
|
}
|
|
|
|
return (ssp_ == NOT_CACHED) ? (ssp_ = ParseSsp()) : ssp_;
|
|
}
|
|
|
|
string Uri::ParseSsp()
|
|
{
|
|
size_t ssi = FindSchemeSeparator();
|
|
size_t fsi = FindFragmentSeparator();
|
|
|
|
size_t start = (ssi == NOT_FOUND) ? 0 : (ssi + 1);
|
|
size_t end = (fsi == NOT_FOUND) ? uriString_.size() : fsi;
|
|
|
|
// Return everything between ssi and fsi.
|
|
string ssp = EMPTY;
|
|
if (end > start) {
|
|
ssp = uriString_.substr(start, end - start);
|
|
}
|
|
|
|
return ssp;
|
|
}
|
|
|
|
string Uri::GetAuthority()
|
|
{
|
|
if (uriString_.empty()) {
|
|
return EMPTY;
|
|
}
|
|
|
|
if (authority_ == NOT_CACHED) {
|
|
authority_ = ParseAuthority();
|
|
}
|
|
return authority_;
|
|
}
|
|
|
|
string Uri::ParseAuthority()
|
|
{
|
|
size_t ssi = FindSchemeSeparator();
|
|
if (ssi == NOT_FOUND) {
|
|
return EMPTY;
|
|
}
|
|
|
|
size_t length = uriString_.length();
|
|
// If "//" follows the scheme separator, we have an authority.
|
|
if ((length > (ssi + POS_INC_MORE)) && (uriString_.at(ssi + POS_INC) == LEFT_SEPARATOR) &&
|
|
(uriString_.at(ssi + POS_INC_MORE) == LEFT_SEPARATOR)) {
|
|
// Look for the start of the path, query, or fragment, or the end of the string.
|
|
size_t start = ssi + POS_INC_AGAIN;
|
|
size_t end = start;
|
|
|
|
while (end < length) {
|
|
char ch = uriString_.at(end);
|
|
if ((ch == LEFT_SEPARATOR) || (ch == RIGHT_SEPARATOR) || (ch == QUERY_FLAG) ||
|
|
(ch == SCHEME_FRAGMENT)) {
|
|
break;
|
|
}
|
|
|
|
end++;
|
|
}
|
|
|
|
return uriString_.substr(start, end - start);
|
|
} else {
|
|
return EMPTY;
|
|
}
|
|
}
|
|
|
|
string Uri::GetUserInfo()
|
|
{
|
|
if (uriString_.empty()) {
|
|
return EMPTY;
|
|
}
|
|
|
|
if (userInfo_ == NOT_CACHED) {
|
|
userInfo_ = ParseUserInfo();
|
|
}
|
|
return userInfo_;
|
|
}
|
|
|
|
string Uri::ParseUserInfo()
|
|
{
|
|
string authority = GetAuthority();
|
|
if (authority.empty()) {
|
|
return EMPTY;
|
|
}
|
|
|
|
size_t end = authority.find_last_of(USER_HOST_SEPARATOR);
|
|
return (end == NOT_FOUND) ? EMPTY : authority.substr(0, end);
|
|
}
|
|
|
|
string Uri::GetHost()
|
|
{
|
|
if (uriString_.empty()) {
|
|
return EMPTY;
|
|
}
|
|
|
|
if (host_ == NOT_CACHED) {
|
|
host_ = ParseHost();
|
|
}
|
|
return host_;
|
|
}
|
|
|
|
string Uri::ParseHost()
|
|
{
|
|
string authority = GetAuthority();
|
|
if (authority.empty()) {
|
|
return EMPTY;
|
|
}
|
|
|
|
// Parse out user info and then port.
|
|
size_t userInfoSeparator = authority.find_last_of(USER_HOST_SEPARATOR);
|
|
size_t start = (userInfoSeparator == NOT_FOUND) ? 0 : (userInfoSeparator + 1);
|
|
size_t portSeparator = authority.find_first_of(PORT_SEPARATOR, start);
|
|
size_t end = (portSeparator == NOT_FOUND) ? authority.size() : portSeparator;
|
|
|
|
string host = EMPTY;
|
|
if (start < end) {
|
|
host = authority.substr(start, end - start);
|
|
}
|
|
|
|
return host;
|
|
}
|
|
|
|
int Uri::GetPort()
|
|
{
|
|
if (uriString_.empty()) {
|
|
return PORT_NONE;
|
|
}
|
|
|
|
if (port_ == NOT_CALCULATED) {
|
|
port_ = ParsePort();
|
|
}
|
|
return port_;
|
|
}
|
|
|
|
int Uri::ParsePort()
|
|
{
|
|
string authority = GetAuthority();
|
|
if (authority.empty()) {
|
|
return PORT_NONE;
|
|
}
|
|
|
|
// Make sure we look for the port separtor *after* the user info separator.
|
|
size_t userInfoSeparator = authority.find_last_of(USER_HOST_SEPARATOR);
|
|
size_t start = (userInfoSeparator == NOT_FOUND) ? 0 : (userInfoSeparator + 1);
|
|
size_t portSeparator = authority.find_first_of(PORT_SEPARATOR, start);
|
|
if (portSeparator == NOT_FOUND) {
|
|
return PORT_NONE;
|
|
}
|
|
|
|
start = portSeparator + 1;
|
|
string portString = authority.substr(start);
|
|
|
|
int value = PORT_NONE;
|
|
return StrToInt(portString, value) ? value : PORT_NONE;
|
|
}
|
|
|
|
string Uri::GetQuery()
|
|
{
|
|
if (uriString_.empty()) {
|
|
return EMPTY;
|
|
}
|
|
|
|
if (query_ == NOT_CACHED) {
|
|
query_ = ParseQuery();
|
|
}
|
|
return query_;
|
|
}
|
|
|
|
string Uri::ParseQuery()
|
|
{
|
|
size_t ssi = FindSchemeSeparator();
|
|
if (ssi == NOT_FOUND) {
|
|
ssi = 0;
|
|
}
|
|
size_t qsi = uriString_.find_first_of(QUERY_FLAG, ssi);
|
|
if (qsi == NOT_FOUND) {
|
|
return EMPTY;
|
|
}
|
|
|
|
size_t start = qsi + 1;
|
|
size_t fsi = FindFragmentSeparator();
|
|
if (fsi == NOT_FOUND) {
|
|
return uriString_.substr(start);
|
|
}
|
|
|
|
if (fsi < qsi) {
|
|
// Invalid.
|
|
return EMPTY;
|
|
}
|
|
|
|
return uriString_.substr(start, fsi - start);
|
|
}
|
|
|
|
string Uri::GetPath()
|
|
{
|
|
if (uriString_.empty()) {
|
|
return EMPTY;
|
|
}
|
|
|
|
if (path_ == NOT_CACHED) {
|
|
path_ = ParsePath();
|
|
}
|
|
return path_;
|
|
}
|
|
|
|
void Uri::GetPathSegments(std::vector<std::string>& segments)
|
|
{
|
|
if (uriString_.empty()) {
|
|
return;
|
|
}
|
|
if (path_ == NOT_CACHED) {
|
|
path_ = ParsePath();
|
|
}
|
|
|
|
size_t previous = 0;
|
|
size_t current;
|
|
while ((current = path_.find(LEFT_SEPARATOR, previous)) != std::string::npos) {
|
|
if (previous < current) {
|
|
segments.emplace_back(path_.substr(previous, current - previous));
|
|
}
|
|
previous = current + POS_INC;
|
|
}
|
|
// Add in the final path segment.
|
|
if (previous < path_.length()) {
|
|
segments.emplace_back(path_.substr(previous));
|
|
}
|
|
}
|
|
|
|
string Uri::ParsePath()
|
|
{
|
|
size_t ssi = FindSchemeSeparator();
|
|
// If the URI is absolute.
|
|
if (ssi != NOT_FOUND) {
|
|
// Is there anything after the ':'?
|
|
if ((ssi + 1) == uriString_.length()) {
|
|
// Opaque URI.
|
|
return EMPTY;
|
|
}
|
|
|
|
// A '/' after the ':' means this is hierarchical.
|
|
if (uriString_.at(ssi + 1) != LEFT_SEPARATOR) {
|
|
// Opaque URI.
|
|
return EMPTY;
|
|
}
|
|
} else {
|
|
// All relative URIs are hierarchical.
|
|
}
|
|
|
|
return ParsePath(ssi);
|
|
}
|
|
|
|
string Uri::ParsePath(size_t ssi)
|
|
{
|
|
size_t length = uriString_.length();
|
|
|
|
// Find start of path.
|
|
size_t pathStart = (ssi == NOT_FOUND) ? 0 : (ssi + POS_INC);
|
|
if ((length > (pathStart + POS_INC)) && (uriString_.at(pathStart) == LEFT_SEPARATOR) &&
|
|
(uriString_.at(pathStart + POS_INC) == LEFT_SEPARATOR)) {
|
|
// Skip over authority to path.
|
|
pathStart += POS_INC_MORE;
|
|
|
|
while (pathStart < length) {
|
|
char ch = uriString_.at(pathStart);
|
|
if ((ch == QUERY_FLAG) || (ch == SCHEME_FRAGMENT)) {
|
|
return EMPTY;
|
|
}
|
|
|
|
if ((ch == LEFT_SEPARATOR) || (ch == RIGHT_SEPARATOR)) {
|
|
break;
|
|
}
|
|
|
|
pathStart++;
|
|
}
|
|
}
|
|
|
|
// Find end of path.
|
|
size_t pathEnd = pathStart;
|
|
while (pathEnd < length) {
|
|
char ch = uriString_.at(pathEnd);
|
|
if ((ch == QUERY_FLAG) || (ch == SCHEME_FRAGMENT)) {
|
|
break;
|
|
}
|
|
|
|
pathEnd++;
|
|
}
|
|
|
|
return uriString_.substr(pathStart, pathEnd - pathStart);
|
|
}
|
|
|
|
string Uri::GetFragment()
|
|
{
|
|
if (uriString_.empty()) {
|
|
return EMPTY;
|
|
}
|
|
|
|
if (fragment_ == NOT_CACHED) {
|
|
fragment_ = ParseFragment();
|
|
}
|
|
return fragment_;
|
|
}
|
|
|
|
string Uri::ParseFragment()
|
|
{
|
|
size_t fsi = FindFragmentSeparator();
|
|
return (fsi == NOT_FOUND) ? EMPTY : uriString_.substr(fsi + 1);
|
|
}
|
|
|
|
size_t Uri::FindSchemeSeparator()
|
|
{
|
|
if (cachedSsi_ == NOT_FOUND) {
|
|
cachedSsi_ = uriString_.find_first_of(SCHEME_SEPARATOR);
|
|
}
|
|
return cachedSsi_;
|
|
}
|
|
|
|
size_t Uri::FindFragmentSeparator()
|
|
{
|
|
if (cachedFsi_ == NOT_FOUND) {
|
|
cachedFsi_ = uriString_.find_first_of(SCHEME_FRAGMENT, FindSchemeSeparator());
|
|
}
|
|
return cachedFsi_;
|
|
}
|
|
|
|
bool Uri::IsHierarchical()
|
|
{
|
|
if (uriString_.empty()) {
|
|
return false;
|
|
}
|
|
|
|
size_t ssi = FindSchemeSeparator();
|
|
if (ssi == NOT_FOUND) {
|
|
// All relative URIs are hierarchical.
|
|
return true;
|
|
}
|
|
|
|
if (uriString_.length() == (ssi + 1)) {
|
|
// No ssp.
|
|
return false;
|
|
}
|
|
|
|
// If the ssp starts with a '/', this is hierarchical.
|
|
return (uriString_.at(ssi + 1) == LEFT_SEPARATOR);
|
|
}
|
|
|
|
bool Uri::IsOpaque()
|
|
{
|
|
if (uriString_.empty()) {
|
|
return false;
|
|
}
|
|
|
|
return !IsHierarchical();
|
|
}
|
|
|
|
bool Uri::IsAbsolute()
|
|
{
|
|
if (uriString_.empty()) {
|
|
return false;
|
|
}
|
|
|
|
return !IsRelative();
|
|
}
|
|
|
|
bool Uri::IsRelative()
|
|
{
|
|
if (uriString_.empty()) {
|
|
return false;
|
|
}
|
|
|
|
// Note: We return true if the index is 0
|
|
return FindSchemeSeparator() == NOT_FOUND;
|
|
}
|
|
|
|
bool Uri::Equals(const Uri& other) const
|
|
{
|
|
return ToString() == other.ToString();
|
|
}
|
|
|
|
int Uri::CompareTo(const Uri& other) const
|
|
{
|
|
return ToString().compare(other.ToString());
|
|
}
|
|
|
|
string Uri::ToString() const
|
|
{
|
|
return uriString_;
|
|
}
|
|
|
|
bool Uri::operator==(const Uri& other) const
|
|
{
|
|
return ToString() == other.ToString();
|
|
}
|
|
|
|
bool Uri::Marshalling(Parcel& parcel) const
|
|
{
|
|
if (IsAsciiString(uriString_)) {
|
|
return parcel.WriteString16(Str8ToStr16(uriString_));
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
Uri* Uri::Unmarshalling(Parcel& parcel)
|
|
{
|
|
return new Uri(Str16ToStr8(parcel.ReadString16()));
|
|
}
|
|
} // namespace OHOS
|