18bf80f4bSopenharmony_ci/* 28bf80f4bSopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd. 38bf80f4bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 48bf80f4bSopenharmony_ci * you may not use this file except in compliance with the License. 58bf80f4bSopenharmony_ci * You may obtain a copy of the License at 68bf80f4bSopenharmony_ci * 78bf80f4bSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 88bf80f4bSopenharmony_ci * 98bf80f4bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 108bf80f4bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 118bf80f4bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 128bf80f4bSopenharmony_ci * See the License for the specific language governing permissions and 138bf80f4bSopenharmony_ci * limitations under the License. 148bf80f4bSopenharmony_ci */ 158bf80f4bSopenharmony_ci 168bf80f4bSopenharmony_ci#ifndef SCENEPLUGIN_ASSETLOADER_H 178bf80f4bSopenharmony_ci#define SCENEPLUGIN_ASSETLOADER_H 188bf80f4bSopenharmony_ci 198bf80f4bSopenharmony_ci#include <scene_plugin/interface/intf_asset_loader.h> 208bf80f4bSopenharmony_ci 218bf80f4bSopenharmony_ci#include <3d/intf_graphics_context.h> 228bf80f4bSopenharmony_ci#include <base/containers/string_view.h> 238bf80f4bSopenharmony_ci#include <base/containers/unordered_map.h> 248bf80f4bSopenharmony_ci#include <base/math/mathf.h> 258bf80f4bSopenharmony_ci#include <render/intf_render_context.h> 268bf80f4bSopenharmony_ci 278bf80f4bSopenharmony_ciSCENE_BEGIN_NAMESPACE() 288bf80f4bSopenharmony_ci 298bf80f4bSopenharmony_ciclass AssetManager; 308bf80f4bSopenharmony_ci 318bf80f4bSopenharmony_ciIAssetLoader::Ptr CreateAssetLoader(AssetManager& assetManager, RENDER_NS::IRenderContext& renderContext, 328bf80f4bSopenharmony_ci CORE3D_NS::IGraphicsContext& graphicsContext, IEntityCollection& ec, BASE_NS::string_view src, 338bf80f4bSopenharmony_ci BASE_NS::string_view contextUri); 348bf80f4bSopenharmony_ci 358bf80f4bSopenharmony_cistruct PathUtil { 368bf80f4bSopenharmony_cipublic: 378bf80f4bSopenharmony_ci static BASE_NS::string NormalizePath(BASE_NS::string_view path) 388bf80f4bSopenharmony_ci { 398bf80f4bSopenharmony_ci BASE_NS::string res; 408bf80f4bSopenharmony_ci if (path[0] != '/') { 418bf80f4bSopenharmony_ci res.reserve(path.size() + 1); 428bf80f4bSopenharmony_ci res.push_back('/'); 438bf80f4bSopenharmony_ci } else { 448bf80f4bSopenharmony_ci res.reserve(path.size()); 458bf80f4bSopenharmony_ci } 468bf80f4bSopenharmony_ci while (!path.empty()) { 478bf80f4bSopenharmony_ci if (path[0] == '/') { 488bf80f4bSopenharmony_ci if (res.empty()) { 498bf80f4bSopenharmony_ci res.push_back('/'); 508bf80f4bSopenharmony_ci } 518bf80f4bSopenharmony_ci path = path.substr(1); 528bf80f4bSopenharmony_ci continue; 538bf80f4bSopenharmony_ci } 548bf80f4bSopenharmony_ci auto pos = path.find_first_of("/", 0); 558bf80f4bSopenharmony_ci BASE_NS::string_view sub = path.substr(0, pos); 568bf80f4bSopenharmony_ci if (sub == ".") { 578bf80f4bSopenharmony_ci path = path.substr(pos); 588bf80f4bSopenharmony_ci continue; 598bf80f4bSopenharmony_ci } else if (sub == "..") { 608bf80f4bSopenharmony_ci if ((!res.empty()) && (res.back() == '/')) { 618bf80f4bSopenharmony_ci res.resize(res.size() - 1); 628bf80f4bSopenharmony_ci } 638bf80f4bSopenharmony_ci if (auto p = res.find_last_of('/'); BASE_NS::string::npos != p) { 648bf80f4bSopenharmony_ci res.resize(p); 658bf80f4bSopenharmony_ci } else { 668bf80f4bSopenharmony_ci if (res.empty()) { 678bf80f4bSopenharmony_ci // trying to back out of root. (ie. invalid path) 688bf80f4bSopenharmony_ci return ""; 698bf80f4bSopenharmony_ci } 708bf80f4bSopenharmony_ci res.clear(); 718bf80f4bSopenharmony_ci } 728bf80f4bSopenharmony_ci if (pos == BASE_NS::string::npos) { 738bf80f4bSopenharmony_ci res.push_back('/'); 748bf80f4bSopenharmony_ci break; 758bf80f4bSopenharmony_ci } 768bf80f4bSopenharmony_ci } else { 778bf80f4bSopenharmony_ci res.append(sub); 788bf80f4bSopenharmony_ci } 798bf80f4bSopenharmony_ci if (pos == BASE_NS::string::npos) { 808bf80f4bSopenharmony_ci break; 818bf80f4bSopenharmony_ci } else { 828bf80f4bSopenharmony_ci res.push_back('/'); 838bf80f4bSopenharmony_ci } 848bf80f4bSopenharmony_ci path = path.substr(pos); 858bf80f4bSopenharmony_ci } 868bf80f4bSopenharmony_ci if (res[0] != '/') { 878bf80f4bSopenharmony_ci res.insert(0, "/"); 888bf80f4bSopenharmony_ci } 898bf80f4bSopenharmony_ci return res; 908bf80f4bSopenharmony_ci } 918bf80f4bSopenharmony_ci 928bf80f4bSopenharmony_ci static BASE_NS::string GetParentPath(BASE_NS::string_view path) 938bf80f4bSopenharmony_ci { 948bf80f4bSopenharmony_ci if (path.size() > 1 && path[path.size() - 1] == '/' && path[path.size() - 2] != '/') { // 2 array index 958bf80f4bSopenharmony_ci // Allow (ignore) trailing '/' for folders. 968bf80f4bSopenharmony_ci path = path.substr(0, path.size() - 1); 978bf80f4bSopenharmony_ci } 988bf80f4bSopenharmony_ci 998bf80f4bSopenharmony_ci const size_t separatorPos = path.rfind('/'); 1008bf80f4bSopenharmony_ci if (separatorPos == BASE_NS::string::npos) { 1018bf80f4bSopenharmony_ci return ""; 1028bf80f4bSopenharmony_ci } else { 1038bf80f4bSopenharmony_ci return BASE_NS::string(path.substr(0, separatorPos + 1)); 1048bf80f4bSopenharmony_ci } 1058bf80f4bSopenharmony_ci } 1068bf80f4bSopenharmony_ci 1078bf80f4bSopenharmony_ci static BASE_NS::string ResolvePath(BASE_NS::string_view parent, BASE_NS::string_view uri, bool allowQueryString) 1088bf80f4bSopenharmony_ci { 1098bf80f4bSopenharmony_ci size_t queryPos = allowQueryString ? BASE_NS::string::npos : uri.find('?'); 1108bf80f4bSopenharmony_ci BASE_NS::string_view path = (BASE_NS::string::npos != queryPos) ? uri.substr(0, queryPos) : uri; 1118bf80f4bSopenharmony_ci 1128bf80f4bSopenharmony_ci if (parent.empty()) { 1138bf80f4bSopenharmony_ci return BASE_NS::string(path); 1148bf80f4bSopenharmony_ci } 1158bf80f4bSopenharmony_ci 1168bf80f4bSopenharmony_ci if (path.empty()) { 1178bf80f4bSopenharmony_ci return BASE_NS::string(parent); 1188bf80f4bSopenharmony_ci } 1198bf80f4bSopenharmony_ci 1208bf80f4bSopenharmony_ci if (path[0] == '/') { 1218bf80f4bSopenharmony_ci path = path.substr(1); 1228bf80f4bSopenharmony_ci } else if (path.find("://") != path.npos) { 1238bf80f4bSopenharmony_ci return BASE_NS::string(path); 1248bf80f4bSopenharmony_ci } 1258bf80f4bSopenharmony_ci 1268bf80f4bSopenharmony_ci // NOTE: Resolve always assumes the parent path is a directory even if there is no '/' in the end 1278bf80f4bSopenharmony_ci if (parent.back() == '/') { 1288bf80f4bSopenharmony_ci return parent + path; 1298bf80f4bSopenharmony_ci } else { 1308bf80f4bSopenharmony_ci return parent + "/" + path; 1318bf80f4bSopenharmony_ci } 1328bf80f4bSopenharmony_ci } 1338bf80f4bSopenharmony_ci 1348bf80f4bSopenharmony_ci static BASE_NS::string GetRelativePath(BASE_NS::string_view path, BASE_NS::string_view relativeTo) 1358bf80f4bSopenharmony_ci { 1368bf80f4bSopenharmony_ci // remove the common prefix 1378bf80f4bSopenharmony_ci { 1388bf80f4bSopenharmony_ci int lastSeparator = -1; 1398bf80f4bSopenharmony_ci 1408bf80f4bSopenharmony_ci for (size_t i = 0, iMax = BASE_NS::Math::min(path.size(), relativeTo.size()); i < iMax; ++i) { 1418bf80f4bSopenharmony_ci if (path[i] != relativeTo[i]) { 1428bf80f4bSopenharmony_ci break; 1438bf80f4bSopenharmony_ci } 1448bf80f4bSopenharmony_ci if (path[i] == '/') { 1458bf80f4bSopenharmony_ci lastSeparator = int(i); 1468bf80f4bSopenharmony_ci } 1478bf80f4bSopenharmony_ci } 1488bf80f4bSopenharmony_ci 1498bf80f4bSopenharmony_ci path.remove_prefix(lastSeparator + 1); 1508bf80f4bSopenharmony_ci relativeTo.remove_prefix(lastSeparator + 1); 1518bf80f4bSopenharmony_ci } 1528bf80f4bSopenharmony_ci 1538bf80f4bSopenharmony_ci if (path[1] == ':' && relativeTo[1] == ':' && path[0] != relativeTo[0]) { 1548bf80f4bSopenharmony_ci // files are on different drives 1558bf80f4bSopenharmony_ci return BASE_NS::string(path); 1568bf80f4bSopenharmony_ci } 1578bf80f4bSopenharmony_ci 1588bf80f4bSopenharmony_ci // count and remove the directories left in relative_to 1598bf80f4bSopenharmony_ci auto directoriesCount = 0; 1608bf80f4bSopenharmony_ci { 1618bf80f4bSopenharmony_ci auto nextSeparator = relativeTo.find('/'); 1628bf80f4bSopenharmony_ci while (nextSeparator != BASE_NS::string::npos) { 1638bf80f4bSopenharmony_ci relativeTo.remove_prefix(nextSeparator + 1); 1648bf80f4bSopenharmony_ci nextSeparator = relativeTo.find('/'); 1658bf80f4bSopenharmony_ci ++directoriesCount; 1668bf80f4bSopenharmony_ci } 1678bf80f4bSopenharmony_ci } 1688bf80f4bSopenharmony_ci 1698bf80f4bSopenharmony_ci BASE_NS::string relativePath = ""; 1708bf80f4bSopenharmony_ci for (auto i = 0, iMax = directoriesCount; i < iMax; ++i) { 1718bf80f4bSopenharmony_ci relativePath.append("../"); 1728bf80f4bSopenharmony_ci } 1738bf80f4bSopenharmony_ci 1748bf80f4bSopenharmony_ci relativePath.append(path); 1758bf80f4bSopenharmony_ci 1768bf80f4bSopenharmony_ci return relativePath; 1778bf80f4bSopenharmony_ci } 1788bf80f4bSopenharmony_ci 1798bf80f4bSopenharmony_ci static BASE_NS::string GetFilename(BASE_NS::string_view path) 1808bf80f4bSopenharmony_ci { 1818bf80f4bSopenharmony_ci if (!path.empty() && path[path.size() - 1] == '/') { 1828bf80f4bSopenharmony_ci // Return a name also for folders. 1838bf80f4bSopenharmony_ci path = path.substr(0, path.size() - 1); 1848bf80f4bSopenharmony_ci } 1858bf80f4bSopenharmony_ci 1868bf80f4bSopenharmony_ci size_t cutPos = path.find_last_of("\\/"); 1878bf80f4bSopenharmony_ci if (BASE_NS::string::npos != cutPos) { 1888bf80f4bSopenharmony_ci return BASE_NS::string(path.substr(cutPos + 1)); 1898bf80f4bSopenharmony_ci } else { 1908bf80f4bSopenharmony_ci return BASE_NS::string(path); 1918bf80f4bSopenharmony_ci } 1928bf80f4bSopenharmony_ci } 1938bf80f4bSopenharmony_ci 1948bf80f4bSopenharmony_ci static BASE_NS::string GetExtension(BASE_NS::string_view path) 1958bf80f4bSopenharmony_ci { 1968bf80f4bSopenharmony_ci size_t fileExtCut = path.rfind('.'); 1978bf80f4bSopenharmony_ci if (fileExtCut != BASE_NS::string::npos) { 1988bf80f4bSopenharmony_ci size_t queryCut = path.find('?', fileExtCut); 1998bf80f4bSopenharmony_ci if (queryCut != BASE_NS::string::npos) { 2008bf80f4bSopenharmony_ci return BASE_NS::string(path.substr(fileExtCut + 1, queryCut)); 2018bf80f4bSopenharmony_ci } else { 2028bf80f4bSopenharmony_ci return BASE_NS::string(path.substr(fileExtCut + 1, queryCut)); 2038bf80f4bSopenharmony_ci } 2048bf80f4bSopenharmony_ci } 2058bf80f4bSopenharmony_ci return ""; 2068bf80f4bSopenharmony_ci } 2078bf80f4bSopenharmony_ci 2088bf80f4bSopenharmony_ci static BASE_NS::string GetBaseName(BASE_NS::string_view path) 2098bf80f4bSopenharmony_ci { 2108bf80f4bSopenharmony_ci auto filename = GetFilename(path); 2118bf80f4bSopenharmony_ci size_t fileExtCut = filename.rfind("."); 2128bf80f4bSopenharmony_ci if (BASE_NS::string::npos != fileExtCut) { 2138bf80f4bSopenharmony_ci filename.erase(fileExtCut); 2148bf80f4bSopenharmony_ci } 2158bf80f4bSopenharmony_ci return filename; 2168bf80f4bSopenharmony_ci } 2178bf80f4bSopenharmony_ci 2188bf80f4bSopenharmony_ci static BASE_NS::unordered_map<BASE_NS::string, BASE_NS::string> GetUriParameters(BASE_NS::string_view uri) 2198bf80f4bSopenharmony_ci { 2208bf80f4bSopenharmony_ci const size_t queryPos = uri.find('?'); 2218bf80f4bSopenharmony_ci if (queryPos != BASE_NS::string::npos) { 2228bf80f4bSopenharmony_ci BASE_NS::unordered_map<BASE_NS::string, BASE_NS::string> params; 2238bf80f4bSopenharmony_ci size_t paramStartPos = queryPos; 2248bf80f4bSopenharmony_ci while (paramStartPos < uri.size()) { 2258bf80f4bSopenharmony_ci size_t paramValuePos = uri.find('=', paramStartPos + 1); 2268bf80f4bSopenharmony_ci size_t paramEndPos = uri.find('&', paramStartPos + 1); 2278bf80f4bSopenharmony_ci if (paramEndPos == BASE_NS::string::npos) { 2288bf80f4bSopenharmony_ci paramEndPos = uri.size(); 2298bf80f4bSopenharmony_ci } 2308bf80f4bSopenharmony_ci if (paramValuePos != BASE_NS::string::npos && paramValuePos < paramEndPos) { 2318bf80f4bSopenharmony_ci auto key = uri.substr(paramStartPos + 1, paramValuePos - paramStartPos - 1); 2328bf80f4bSopenharmony_ci auto value = uri.substr(paramValuePos + 1, paramEndPos - paramValuePos - 1); 2338bf80f4bSopenharmony_ci params[key] = value; 2348bf80f4bSopenharmony_ci } else { 2358bf80f4bSopenharmony_ci auto key = uri.substr(paramStartPos + 1, paramEndPos - paramStartPos - 1); 2368bf80f4bSopenharmony_ci params[key] = key; 2378bf80f4bSopenharmony_ci } 2388bf80f4bSopenharmony_ci paramStartPos = paramEndPos; 2398bf80f4bSopenharmony_ci } 2408bf80f4bSopenharmony_ci return params; 2418bf80f4bSopenharmony_ci } 2428bf80f4bSopenharmony_ci return {}; 2438bf80f4bSopenharmony_ci } 2448bf80f4bSopenharmony_ci 2458bf80f4bSopenharmony_ci static BASE_NS::string ResolveUri( 2468bf80f4bSopenharmony_ci BASE_NS::string_view contextUri, BASE_NS::string_view uri, bool allowQueryString = true) 2478bf80f4bSopenharmony_ci { 2488bf80f4bSopenharmony_ci return ResolvePath(GetParentPath(contextUri), uri, allowQueryString); 2498bf80f4bSopenharmony_ci } 2508bf80f4bSopenharmony_ci}; 2518bf80f4bSopenharmony_ci 2528bf80f4bSopenharmony_ciSCENE_END_NAMESPACE() 2538bf80f4bSopenharmony_ci 2548bf80f4bSopenharmony_ci#endif // SCENEPLUGIN_ASSETLOADER_H 255