VLink 2.0.0
A high-performance communication middleware
Loading...
Searching...
No Matches
url_remap.h
Go to the documentation of this file.
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/**
25 * @file url_remap.h
26 * @brief JSON-driven URL remapping for VLink topic address translation.
27 *
28 * @details
29 * @c UrlRemap loads a JSON configuration file that maps source URL patterns to
30 * target URL strings, enabling topic renaming at runtime without recompiling.
31 *
32 * The JSON format is a flat object of key/value pairs:
33 * @code
34 * {
35 * "intra://sensor/lidar": "dds://vehicle/lidar",
36 * "shm://camera/front": "zenoh://camera/front"
37 * }
38 * @endcode
39 *
40 * @par Matching algorithm
41 * For each call to @c convert(), the remap list is searched in order. The first
42 * entry whose key is found as a substring of the input URL is selected, and its
43 * value is returned as the remapped URL. Results are cached in an internal
44 * @c unordered_map to avoid repeated linear scans.
45 *
46 * @par Lifecycle
47 * @code
48 * vlink::UrlRemap remap;
49 * remap.load("/etc/vlink/remap.json");
50 *
51 * std::string topic = remap.convert("intra://sensor/lidar");
52 * // topic == "dds://vehicle/lidar"
53 *
54 * remap.reload("/etc/vlink/new_remap.json");
55 * @endcode
56 *
57 * @note
58 * - @c load() returns @c false (and sets the error string) if the file does not
59 * exist, cannot be parsed, or is already loaded.
60 * - @c unload() clears the remap table and the result cache.
61 * - @c convert() returns the original URL unchanged if @c is_valid() is @c false
62 * or no matching rule is found.
63 */
64
65#pragma once
66
67#include <string>
68#include <unordered_map>
69#include <vector>
70
71#include "../base/macros.h"
72
73namespace vlink {
74
75/**
76 * @class UrlRemap
77 * @brief Loads a JSON remap file and translates VLink URL strings at runtime.
78 *
79 * @details
80 * Not thread-safe. All methods should be called from a single thread, or
81 * the caller must provide external synchronisation.
82 */
84 public:
85 /**
86 * @brief Constructs an empty, invalid @c UrlRemap. No file is loaded.
87 */
88 UrlRemap() noexcept;
89
90 /**
91 * @brief Destructor.
92 */
93 ~UrlRemap() noexcept;
94
95 /**
96 * @brief Loads and parses a JSON remap configuration from @p file_path.
97 *
98 * @details
99 * The file must be a flat JSON object with string keys and string values.
100 * Calling @c load() on an already-loaded instance returns @c false without
101 * modifying state (call @c unload() or @c reload() first).
102 *
103 * @param file_path Absolute or relative path to the JSON file.
104 * @return @c true on success; @c false if the file is missing, unreadable,
105 * or contains invalid JSON. The error description is accessible via
106 * @c get_error_string().
107 */
108 bool load(const std::string& file_path) noexcept;
109
110 /**
111 * @brief Clears the remap table and marks the instance as invalid.
112 *
113 * @details
114 * Also clears the conversion result cache. Does nothing and returns @c false
115 * if the instance is not currently loaded.
116 *
117 * @return @c true if the table was cleared; @c false if already unloaded.
118 */
119 bool unload() noexcept;
120
121 /**
122 * @brief Unloads the current configuration and loads a new one atomically.
123 *
124 * @details
125 * Equivalent to calling @c unload() followed by @c load(@p file_path).
126 *
127 * @param file_path Path to the new JSON remap file.
128 * @return @c true if the new file was loaded successfully.
129 */
130 bool reload(const std::string& file_path) noexcept;
131
132 /**
133 * @brief Translates @p url according to the loaded remap rules.
134 *
135 * @details
136 * Checks an internal cache first for O(1) repeated lookups. If not cached,
137 * iterates the ordered remap list and returns the first matching target.
138 * The result is cached before returning.
139 *
140 * Returns @p url unchanged if:
141 * - The remap table is not loaded (@c is_valid() is @c false).
142 * - No rule matches.
143 *
144 * @param url Input URL string.
145 * @return Remapped URL, or the original @p url if no rule matches.
146 */
147 const std::string& convert(const std::string& url) noexcept;
148
149 /**
150 * @brief Enables or disables logging of each URL conversion.
151 *
152 * @param enable_log If @c true, each successful remap is logged at INFO level.
153 */
154 void set_enable_log(bool enable_log) noexcept;
155
156 /**
157 * @brief Returns whether conversion logging is currently enabled.
158 *
159 * @return @c true if logging is enabled.
160 */
161 [[nodiscard]] bool is_enable_log() const noexcept;
162
163 /**
164 * @brief Returns whether a remap file has been successfully loaded.
165 *
166 * @return @c true if @c load() or @c reload() succeeded.
167 */
168 [[nodiscard]] bool is_valid() const noexcept;
169
170 /**
171 * @brief Returns the human-readable error description from the last failed operation.
172 *
173 * @details
174 * Populated by @c load() on failure. Cleared on @c unload() and on successful @c load().
175 *
176 * @return Error string, or an empty string if no error has occurred.
177 */
178 [[nodiscard]] const std::string& get_error_string() const noexcept;
179
180 private:
181 bool is_enable_log_{false};
182 bool is_valid_{false};
183
184 std::string error_string_;
185
186 std::vector<std::pair<std::string, std::string>> remap_list_;
187 std::unordered_map<std::string, std::string> cache_map_;
188
190};
191
192////////////////////////////////////////////////////////////////
193/// Details
194////////////////////////////////////////////////////////////////
195
196inline void UrlRemap::set_enable_log(bool enable_log) noexcept { is_enable_log_ = enable_log; }
197
198inline bool UrlRemap::is_enable_log() const noexcept { return is_enable_log_; }
199
200inline bool UrlRemap::is_valid() const noexcept { return is_valid_; }
201
202inline const std::string& UrlRemap::get_error_string() const noexcept { return error_string_; }
203
204} // namespace vlink
Platform-independent macro definitions for the VLink library.
#define VLINK_EXPORT
Definition macros.h:85
#define VLINK_DISALLOW_COPY_AND_ASSIGN(classname)
Deletes the copy constructor and copy-assignment operator of classname.
Definition macros.h:184
STL namespace.