LCOV - code coverage report
Current view: top level - src/impl - url.cc (source / functions) Hit Total Coverage
Test: vlink Lines: 192 201 95.5 %
Date: 2026-07-26 14:05:51 Functions: 30 31 96.8 %
Branches: 193 277 69.7 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (C) 2026 by Thun Lu. All rights reserved.
       3                 :            :  * Author: Thun Lu <thun.lu@zohomail.cn>
       4                 :            :  * Repo:   https://github.com/thun-res/vlink
       5                 :            :  *  _    __   __      _           __
       6                 :            :  * | |  / /  / /     (_) ____    / /__
       7                 :            :  * | | / /  / /     / / / __ \  / //_/
       8                 :            :  * | |/ /  / /___  / / / / / / / ,<
       9                 :            :  * |___/  /_____/ /_/ /_/ /_/ /_/|_|
      10                 :            :  *
      11                 :            :  * Licensed under the Apache License, Version 2.0 (the "License");
      12                 :            :  * you may not use this file except in compliance with the License.
      13                 :            :  * You may obtain a copy of the License at
      14                 :            :  *
      15                 :            :  *     http://www.apache.org/licenses/LICENSE-2.0
      16                 :            :  *
      17                 :            :  * Unless required by applicable law or agreed to in writing, software
      18                 :            :  * distributed under the License is distributed on an "AS IS" BASIS,
      19                 :            :  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
      20                 :            :  * See the License for the specific language governing permissions and
      21                 :            :  * limitations under the License.
      22                 :            :  */
      23                 :            : 
      24                 :            : #include "./impl/url.h"
      25                 :            : 
      26                 :            : #include <algorithm>
      27                 :            : #include <atomic>
      28                 :            : #include <cctype>
      29                 :            : #include <map>
      30                 :            : #include <memory>
      31                 :            : #include <mutex>
      32                 :            : #include <shared_mutex>
      33                 :            : #include <string>
      34                 :            : #include <string_view>
      35                 :            : #include <unordered_map>
      36                 :            : #include <utility>
      37                 :            : 
      38                 :            : #include "./base/helpers.h"
      39                 :            : #include "./base/plugin.h"
      40                 :            : #include "./base/utils.h"
      41                 :            : #include "./extension/url_remap.h"
      42                 :            : #include "./impl/conf_plugin_interface.h"
      43                 :            : #include "./impl/url_parser.h"
      44                 :            : 
      45                 :            : #define VLINK_URL_USE_REMAP 1
      46                 :            : #define VLINK_URL_USE_PLUGIN 1
      47                 :            : 
      48                 :            : namespace vlink {
      49                 :            : 
      50                 :            : [[maybe_unused]] static constexpr uint16_t kMaxUrlLength = 120U;
      51                 :            : 
      52                 :         68 : [[maybe_unused]] inline static bool equals_ignore_case(std::string_view left, std::string_view right) noexcept {
      53   [ +  +  +  + ]:         73 :   return left.size() == right.size() &&
      54                 :          5 :          std::equal(left.begin(), left.end(), right.begin(), [](unsigned char left_char, unsigned char right_char) {
      55                 :         17 :            return std::tolower(left_char) == std::tolower(right_char);
      56                 :         68 :          });
      57                 :            : }
      58                 :            : 
      59                 :        609 : [[maybe_unused]] inline static TransportType get_transport_for_str(const std::string& str) noexcept {
      60         [ +  + ]:        609 :   if (str == "intra") {
      61                 :        248 :     return TransportType::kIntra;
      62                 :            :   }
      63                 :            : 
      64                 :            : #if !defined(__ANDROID__)
      65                 :            : 
      66         [ +  + ]:        361 :   if (str == "shm") {
      67                 :         96 :     return TransportType::kShm;
      68                 :            :   }
      69                 :            : 
      70         [ +  + ]:        265 :   if (str == "shm2") {
      71                 :          1 :     return TransportType::kShm2;
      72                 :            :   }
      73                 :            : #endif
      74                 :            : 
      75         [ +  + ]:        264 :   if (str == "zenoh") {
      76                 :          1 :     return TransportType::kZenoh;
      77                 :            :   }
      78                 :            : 
      79   [ +  +  -  +  :        263 :   if (str == "dds" || str == "ddsf") {
                   +  + ]
      80                 :        136 :     return TransportType::kDds;
      81                 :            :   }
      82                 :            : 
      83         [ +  + ]:        127 :   if (str == "ddsc") {
      84                 :         92 :     return TransportType::kDdsc;
      85                 :            :   }
      86                 :            : 
      87         [ +  + ]:         35 :   if (str == "ddsr") {
      88                 :          1 :     return TransportType::kDdsr;
      89                 :            :   }
      90                 :            : 
      91         [ +  + ]:         34 :   if (str == "someip") {
      92                 :          1 :     return TransportType::kSomeip;
      93                 :            :   }
      94                 :            : 
      95         [ +  + ]:         33 :   if (str == "mqtt") {
      96                 :          1 :     return TransportType::kMqtt;
      97                 :            :   }
      98                 :            : 
      99         [ +  + ]:         32 :   if (str == "fdbus") {
     100                 :          1 :     return TransportType::kFdbus;
     101                 :            :   }
     102                 :            : 
     103                 :         31 :   return TransportType::kUnknown;
     104                 :            : }
     105                 :            : 
     106                 :          1 : [[maybe_unused]] inline static TransportType get_dds_transport_for_str(const std::string& str) noexcept {
     107   [ +  -  -  +  :          1 :   if (str == "dds" || str == "ddsf") {
                   -  + ]
     108                 :          0 :     return TransportType::kDds;
     109                 :            :   }
     110                 :            : 
     111         [ +  - ]:          1 :   if (str == "ddsc") {
     112                 :          1 :     return TransportType::kDdsc;
     113                 :            :   }
     114                 :            : 
     115         [ #  # ]:          0 :   if (str == "ddsr") {
     116                 :          0 :     return TransportType::kDdsr;
     117                 :            :   }
     118                 :            : 
     119                 :          0 :   return TransportType::kUnknown;
     120                 :            : }
     121                 :            : 
     122                 :        602 : [[maybe_unused]] inline static bool is_dds_type(const TransportType& transport) noexcept {
     123   [ +  +  +  +  :        602 :   return transport == TransportType::kDds || transport == TransportType::kDdsc || transport == TransportType::kDdsr;
                   +  + ]
     124                 :            : }
     125                 :            : 
     126                 :         21 : [[maybe_unused]] inline static const char* get_module_for_transport(TransportType type) noexcept {
     127   [ +  +  +  +  :         21 :   switch (type) {
          +  +  +  +  +  
                   +  - ]
     128                 :          3 :     case TransportType::kIntra:
     129                 :          3 :       return "intra";
     130                 :            : 
     131                 :            : #if !defined(__ANDROID__)
     132                 :            : 
     133                 :          2 :     case TransportType::kShm:
     134                 :          2 :       return "shm";
     135                 :            : 
     136                 :          2 :     case TransportType::kShm2:
     137                 :          2 :       return "shm2";
     138                 :            : #endif
     139                 :            : 
     140                 :          2 :     case TransportType::kZenoh:
     141                 :          2 :       return "zenoh";
     142                 :            : 
     143                 :          2 :     case TransportType::kDds:
     144                 :          2 :       return "dds";
     145                 :            : 
     146                 :          2 :     case TransportType::kDdsc:
     147                 :          2 :       return "ddsc";
     148                 :            : 
     149                 :          2 :     case TransportType::kDdsr:
     150                 :          2 :       return "ddsr";
     151                 :            : 
     152                 :          2 :     case TransportType::kSomeip:
     153                 :          2 :       return "someip";
     154                 :            : 
     155                 :          2 :     case TransportType::kMqtt:
     156                 :          2 :       return "mqtt";
     157                 :            : 
     158                 :          2 :     case TransportType::kFdbus:
     159                 :          2 :       return "fdbus";
     160                 :            : 
     161                 :          0 :     default:
     162                 :            :       return nullptr;  // LCOV_EXCL_LINE GCOVR_EXCL_LINE
     163                 :            :   }
     164                 :            : }
     165                 :            : 
     166                 :         15 : [[maybe_unused]] inline static bool is_intra_url(std::string_view url) noexcept {
     167                 :         15 :   return Helpers::has_startwith(url, "intra://");
     168                 :            : }
     169                 :            : 
     170                 :         15 : [[maybe_unused]] inline static bool is_shm_url(std::string_view url) noexcept {
     171   [ +  +  +  + ]:         15 :   return Helpers::has_startwith(url, "shm://") || Helpers::has_startwith(url, "shm2://");
     172                 :            : }
     173                 :            : 
     174                 :        616 : [[maybe_unused]] inline static int get_sort_index_for_url(std::string_view url) {
     175         [ +  + ]:        616 :   if (url.empty()) {
     176                 :          3 :     return -1;
     177                 :            :   }
     178                 :            : 
     179         [ +  + ]:        613 :   if (Helpers::has_startwith(url, "intra://")) {
     180                 :         64 :     return static_cast<int>(TransportType::kIntra);
     181                 :            :   }
     182                 :            : 
     183                 :            : #if !defined(__ANDROID__)
     184                 :            : 
     185         [ +  + ]:        549 :   if (Helpers::has_startwith(url, "shm://")) {
     186                 :         41 :     return static_cast<int>(TransportType::kShm);
     187                 :            :   }
     188                 :            : 
     189         [ +  + ]:        508 :   if (Helpers::has_startwith(url, "shm2://")) {
     190                 :          2 :     return static_cast<int>(TransportType::kShm2);
     191                 :            :   }
     192                 :            : #endif
     193                 :            : 
     194         [ +  + ]:        506 :   if (Helpers::has_startwith(url, "zenoh://")) {
     195                 :          3 :     return static_cast<int>(TransportType::kZenoh);
     196                 :            :   }
     197                 :            : 
     198   [ +  +  +  +  :        503 :   if (Helpers::has_startwith(url, "dds://") || Helpers::has_startwith(url, "ddsf://")) {
                   +  + ]
     199                 :        468 :     return static_cast<int>(TransportType::kDds);
     200                 :            :   }
     201                 :            : 
     202         [ +  + ]:         35 :   if (Helpers::has_startwith(url, "ddsc://")) {
     203                 :         27 :     return static_cast<int>(TransportType::kDdsc);
     204                 :            :   }
     205                 :            : 
     206         [ +  + ]:          8 :   if (Helpers::has_startwith(url, "ddsr://")) {
     207                 :          1 :     return static_cast<int>(TransportType::kDdsr);
     208                 :            :   }
     209                 :            : 
     210         [ +  + ]:          7 :   if (Helpers::has_startwith(url, "someip://")) {
     211                 :          2 :     return static_cast<int>(TransportType::kSomeip);
     212                 :            :   }
     213                 :            : 
     214         [ +  + ]:          5 :   if (Helpers::has_startwith(url, "mqtt://")) {
     215                 :          1 :     return static_cast<int>(TransportType::kMqtt);
     216                 :            :   }
     217                 :            : 
     218         [ +  + ]:          4 :   if (Helpers::has_startwith(url, "fdbus://")) {
     219                 :          2 :     return static_cast<int>(TransportType::kFdbus);
     220                 :            :   }
     221                 :            : 
     222                 :          2 :   return 0;
     223                 :            : }
     224                 :            : 
     225                 :            : // GlobalModulesManager
     226                 :            : class GlobalModulesManager final {
     227                 :            :  public:
     228                 :        106 :   static GlobalModulesManager& get() {
     229   [ +  +  +  +  :        106 :     static GlobalModulesManager manager;
             +  -  -  - ]
     230                 :        106 :     return manager;
     231                 :            :   }
     232                 :            : 
     233                 :         45 :   std::shared_ptr<ConfPluginInterface> get_or_load_interface(TransportType type) {
     234                 :            :     {
     235         [ +  - ]:         45 :       std::shared_lock lock(mtx_);
     236                 :            : 
     237         [ +  - ]:         45 :       auto iter = ptr_map_.find(type);
     238                 :            : 
     239         [ +  + ]:         45 :       if VLIKELY (iter != ptr_map_.end()) {
     240                 :         11 :         return iter->second;
     241                 :            :       }
     242         [ +  + ]:         45 :     }
     243                 :            : 
     244         [ +  + ]:         34 :     if VLIKELY (!plugin_autoload_enabled_) {
     245                 :         13 :       return nullptr;
     246                 :            :     }
     247                 :            : 
     248                 :         21 :     const char* module_name = get_module_for_transport(type);
     249                 :            : 
     250         [ -  + ]:         21 :     if VUNLIKELY (module_name == nullptr) {
     251                 :            :       return nullptr;  // LCOV_EXCL_LINE GCOVR_EXCL_LINE
     252                 :            :     }
     253                 :            : 
     254         [ +  - ]:         21 :     std::lock_guard lock(mtx_);
     255                 :            : 
     256         [ +  - ]:         21 :     auto iter = ptr_map_.find(type);
     257                 :            : 
     258         [ -  + ]:         21 :     if VUNLIKELY (iter != ptr_map_.end()) {
     259                 :            :       return iter->second;  // LCOV_EXCL_LINE GCOVR_EXCL_LINE
     260                 :            :     }
     261                 :            : 
     262   [ +  -  +  - ]:         42 :     const std::string lib_name = std::string("vlink-") + module_name;
     263   [ +  -  +  -  :         42 :     auto ptr = plugin_.load<ConfPluginInterface>(lib_name, 1, 0);
             +  -  +  - ]
     264                 :            : 
     265         [ +  + ]:         21 :     if VUNLIKELY (!ptr) {
     266                 :         12 :       return nullptr;
     267                 :            :     }
     268                 :            : 
     269         [ +  - ]:          9 :     const auto plugin_type = ptr->get_transport_type();
     270                 :            : 
     271                 :            :     // LCOV_EXCL_START GCOVR_EXCL_START
     272                 :            :     if VUNLIKELY (plugin_type != type) {
     273                 :            :       VLOG_E("Plugin transport mismatch, libname: ", lib_name, ", expected: ", static_cast<int>(type),
     274                 :            :              ", actual: ", static_cast<int>(plugin_type), ".");
     275                 :            :       (void)plugin_.unload<ConfPluginInterface>(lib_name);
     276                 :            :       return nullptr;
     277                 :            :     }
     278                 :            :     // LCOV_EXCL_STOP GCOVR_EXCL_STOP
     279                 :            : 
     280         [ +  - ]:          9 :     return ptr_map_.emplace(type, std::move(ptr)).first->second;
     281                 :         21 :   }
     282                 :            : 
     283                 :         61 :   void init(uint16_t transport_enable_flags) {
     284                 :            :     (void)transport_enable_flags;
     285                 :            : 
     286   [ +  +  +  +  :         61 :     if VLIKELY (url_plugins_env_.empty() || plugin_autoload_enabled_ || equals_ignore_case(url_plugins_env_, "none")) {
          +  +  +  +  +  
                      + ]
     287                 :         57 :       return;
     288                 :            :     }
     289                 :            : 
     290                 :          4 :     auto plugins_list = Helpers::split_any(url_plugins_env_);
     291                 :            : 
     292         [ +  - ]:          4 :     std::lock_guard lock(mtx_);
     293                 :            : 
     294                 :            :     // plugin_.set_log_level(Logger::kWarn);
     295                 :            : 
     296   [ +  -  +  + ]:         10 :     for (auto libname : plugins_list) {
     297   [ +  -  +  - ]:          6 :       Helpers::replace_string(libname, "vlink-", "");
     298                 :            : 
     299                 :          6 :       const auto expected_type = get_transport_for_str(libname);
     300                 :            : 
     301         [ +  + ]:          6 :       if VUNLIKELY (expected_type == TransportType::kUnknown) {
     302   [ +  -  +  - ]:          4 :         VLOG_E("Unsupported plugin module, libname: ", libname, ".");
     303                 :          2 :         continue;
     304                 :          2 :       }
     305                 :            : 
     306         [ +  - ]:          4 :       const std::string plugin_lib_name = "vlink-" + libname;
     307   [ +  -  +  -  :          8 :       auto ptr = plugin_.load<ConfPluginInterface>(plugin_lib_name, 1, 0);
             +  -  +  - ]
     308                 :            : 
     309         [ +  - ]:          4 :       if VLIKELY (ptr) {
     310         [ +  - ]:          4 :         const auto plugin_type = ptr->get_transport_type();
     311                 :            : 
     312                 :            :         // LCOV_EXCL_START GCOVR_EXCL_START
     313                 :            :         if VUNLIKELY (plugin_type != expected_type) {
     314                 :            :           VLOG_E("Plugin transport mismatch, libname: ", plugin_lib_name,
     315                 :            :                  ", expected: ", static_cast<int>(expected_type), ", actual: ", static_cast<int>(plugin_type), ".");
     316                 :            :           (void)plugin_.unload<ConfPluginInterface>(plugin_lib_name);
     317                 :            :           continue;
     318                 :            :         }
     319                 :            :         // LCOV_EXCL_STOP GCOVR_EXCL_STOP
     320                 :            : 
     321         [ +  - ]:          4 :         ptr_map_.emplace(expected_type, std::move(ptr));
     322                 :            :       }
     323   [ +  -  +  -  :          6 :     }
                   +  + ]
     324                 :          4 :   }
     325                 :            : 
     326                 :            :  private:
     327                 :         63 :   GlobalModulesManager()
     328   [ +  -  +  - ]:         63 :       : url_plugins_env_(Utils::get_env("VLINK_URL_PLUGINS")),
     329         [ +  - ]:         63 :         plugin_autoload_enabled_(equals_ignore_case(url_plugins_env_, "auto")) {}
     330                 :            : 
     331                 :        126 :   ~GlobalModulesManager() {
     332                 :         63 :     std::lock_guard lock(mtx_);
     333                 :         63 :     ptr_map_.clear();
     334                 :         63 :     plugin_.clear();
     335                 :         63 :   }
     336                 :            : 
     337                 :            :   const std::string url_plugins_env_;
     338                 :            :   const bool plugin_autoload_enabled_{false};
     339                 :            :   Plugin plugin_;
     340                 :            :   std::unordered_map<TransportType, std::shared_ptr<ConfPluginInterface>> ptr_map_;
     341                 :            :   mutable std::shared_mutex mtx_;
     342                 :            : 
     343                 :            :   VLINK_DISALLOW_COPY_AND_ASSIGN(GlobalModulesManager)
     344                 :            : };
     345                 :            : 
     346                 :            : // GlobalUrlRemap
     347                 :            : class GlobalUrlRemap final : public UrlRemap {
     348                 :            :  public:
     349                 :        605 :   static GlobalUrlRemap& get() {
     350   [ +  +  +  -  :        605 :     static GlobalUrlRemap remap;
             +  -  -  - ]
     351                 :        605 :     return remap;
     352                 :            :   }
     353                 :            : 
     354                 :        605 :   std::string convert_thread_safe(const std::string& url) noexcept {
     355                 :        605 :     std::lock_guard lock(mtx_);
     356                 :        605 :     return convert(url);
     357                 :        605 :   }
     358                 :            : 
     359                 :            :  private:
     360                 :         52 :   GlobalUrlRemap() {
     361   [ +  -  +  - ]:         52 :     const auto& url_remap_env = Utils::get_env("VLINK_URL_REMAP", "");
     362                 :            : 
     363         [ +  - ]:         52 :     if (url_remap_env.empty()) {
     364                 :         52 :       return;
     365                 :            :     }
     366                 :            : 
     367                 :          0 :     set_enable_log(true);
     368                 :            : 
     369                 :          0 :     load(url_remap_env);
     370         [ -  + ]:         52 :   }
     371                 :            : 
     372                 :         52 :   ~GlobalUrlRemap() = default;
     373                 :            : 
     374                 :            :   std::mutex mtx_;
     375                 :            : 
     376                 :            :   VLINK_DISALLOW_COPY_AND_ASSIGN(GlobalUrlRemap)
     377                 :            : };
     378                 :            : 
     379                 :            : // Protocol
     380                 :        605 : Protocol::Protocol(const std::string& address) {
     381         [ -  + ]:        605 :   if VUNLIKELY (address.length() > kMaxUrlLength) {
     382   [ #  #  #  # ]:          0 :     CLOG_F("The URL length exceeds the character limit (Target length: %zu, Max length: %u).", address.length(),
     383                 :            :            kMaxUrlLength);
     384                 :          0 :     return;
     385                 :            :   }
     386                 :            : 
     387                 :            : #if VLINK_URL_USE_REMAP
     388         [ +  - ]:        605 :   std::string real_address = GlobalUrlRemap::get().convert_thread_safe(address);
     389                 :            : 
     390         [ +  + ]:        605 :   UrlParser parser(real_address);
     391                 :        602 :   str = std::move(real_address);
     392                 :            : #else
     393                 :            :   UrlParser parser(address);
     394                 :            :   str = address;
     395                 :            : #endif
     396                 :            : 
     397         [ +  - ]:        602 :   transport = get_transport_for_str(parser.get_transport());
     398                 :            : 
     399         [ +  + ]:        602 :   if (is_dds_type(transport)) {
     400   [ +  -  +  - ]:        454 :     const auto dds_bind_transport_str = Utils::get_env("VLINK_DDS_BIND", "");
     401                 :            : 
     402         [ +  + ]:        227 :     if VUNLIKELY (!dds_bind_transport_str.empty()) {
     403                 :          1 :       TransportType dds_bind_transport = get_dds_transport_for_str(dds_bind_transport_str);
     404                 :            : 
     405         [ +  - ]:          1 :       if VLIKELY (dds_bind_transport != TransportType::kUnknown) {
     406                 :            :         static std::atomic_bool dds_bind_print{false};
     407                 :            : 
     408         [ +  - ]:          1 :         if (!dds_bind_print.exchange(true, std::memory_order_relaxed)) {
     409   [ +  -  +  - ]:          2 :           CLOG_I("Bind [dds] to [%s].", dds_bind_transport_str.c_str());
     410                 :            :         }
     411                 :            : 
     412                 :          1 :         transport = dds_bind_transport;
     413                 :            :       }
     414                 :            :     }
     415         [ +  + ]:        602 :   } else if (transport == TransportType::kIntra) {
     416   [ +  -  +  - ]:        490 :     const auto intra_bind_transport_str = Utils::get_env("VLINK_INTRA_BIND", "");
     417                 :            : 
     418         [ +  + ]:        245 :     if (!intra_bind_transport_str.empty()) {
     419                 :          1 :       TransportType intra_bind_transport = get_transport_for_str(intra_bind_transport_str);
     420                 :            : 
     421   [ +  -  +  -  :          1 :       if VLIKELY (intra_bind_transport != TransportType::kIntra && intra_bind_transport != TransportType::kUnknown) {
                   +  - ]
     422                 :            :         static std::atomic_bool intra_bind_print{false};
     423                 :            : 
     424         [ +  - ]:          1 :         if (!intra_bind_print.exchange(true, std::memory_order_relaxed)) {
     425   [ +  -  +  - ]:          2 :           CLOG_I("Bind [intra] to [%s].", intra_bind_transport_str.c_str());
     426                 :            :         }
     427                 :            : 
     428                 :          1 :         transport = intra_bind_transport;
     429                 :            :       }
     430                 :            :     }
     431                 :        245 :   }
     432                 :            : 
     433         [ +  - ]:        602 :   host = std::move(const_cast<std::string&>(parser.get_host()));
     434         [ +  - ]:        602 :   path = std::move(const_cast<std::string&>(parser.get_path()));
     435         [ +  - ]:        602 :   dictionary = std::move(const_cast<std::map<std::string, std::string>&>(parser.get_query_dictionary()));
     436         [ +  - ]:        602 :   fragment = std::move(const_cast<std::string&>(parser.get_fragment()));
     437                 :        620 : }
     438                 :            : 
     439                 :            : // Url
     440                 :        613 : void Url::init_plugins(uint16_t transport_enable_flags) {
     441                 :            : #if VLINK_URL_USE_PLUGIN
     442   [ +  +  +  -  :        613 :   static auto& manager_instance = GlobalModulesManager::get();
             +  -  -  - ]
     443                 :            : 
     444                 :            :   static std::once_flag flag;
     445                 :            : 
     446         [ +  - ]:        674 :   std::call_once(flag, [transport_enable_flags]() { manager_instance.init(transport_enable_flags); });
     447                 :            : #else
     448                 :            :   (void)transport_enable_flags;
     449                 :            : #endif
     450                 :        613 : }
     451                 :            : 
     452                 :         76 : std::unique_ptr<Conf> Url::load_for_plugin(TransportType type) {
     453                 :            : #if VLINK_URL_USE_PLUGIN
     454         [ +  + ]:         76 :   if VUNLIKELY (type == TransportType::kUnknown) {
     455                 :         31 :     return nullptr;
     456                 :            :   }
     457                 :            : 
     458   [ +  -  +  - ]:         45 :   auto ptr = GlobalModulesManager::get().get_or_load_interface(type);
     459                 :            : 
     460         [ +  + ]:         45 :   if VUNLIKELY (!ptr) {
     461                 :         25 :     return nullptr;
     462                 :            :   }
     463                 :            : 
     464                 :            :   return ptr->create();  // LCOV_EXCL_LINE GCOVR_EXCL_LINE
     465                 :            : #else
     466                 :            :   (void)type;
     467                 :            : 
     468                 :            :   return nullptr;
     469                 :            : #endif
     470                 :         45 : }
     471                 :            : 
     472                 :        616 : int Url::get_sort_index(std::string_view url) { return get_sort_index_for_url(url); }
     473                 :            : 
     474   [ +  +  +  + ]:         10 : bool Url::is_local_type(std::string_view url) { return is_intra_url(url) || is_shm_url(url); }
     475                 :            : 
     476                 :          5 : bool Url::is_intra_type(std::string_view url) { return is_intra_url(url); }
     477                 :            : 
     478                 :          6 : bool Url::is_shm_type(std::string_view url) { return is_shm_url(url); }
     479                 :            : 
     480                 :          2 : std::ostream& operator<<(std::ostream& ostream, const Url& conf) noexcept {
     481                 :            :   ostream << "Url:"
     482                 :          2 :           << "[type]" << +conf.get_impl_type() << "[str]" << conf.protocol_.str;
     483                 :            : 
     484                 :          2 :   return ostream;
     485                 :            : }
     486                 :            : 
     487                 :            : }  // namespace vlink

Generated by: LCOV version 1.14