1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236
|
/**
* @file helpers.h
* @brief Definitions for helper functions used within Ada.
*/
#ifndef ADA_HELPERS_H
#define ADA_HELPERS_H
#include "ada/common_defs.h"
#include "ada/url_base.h"
#include <string>
#include <string_view>
#include <optional>
#if ADA_DEVELOPMENT_CHECKS
#include <iostream>
#endif // ADA_DEVELOPMENT_CHECKS
/**
* These functions are not part of our public API and may
* change at any time.
*
* @private
* @namespace ada::helpers
* @brief Includes the definitions for helper functions
*/
namespace ada::helpers {
/**
* @private
*/
template <typename out_iter>
void encode_json(std::string_view view, out_iter out);
/**
* @private
* This function is used to prune a fragment from a url, and returning the
* removed string if input has fragment.
*
* @details prune_hash seeks the first '#' and returns everything after it
* as a string_view, and modifies (in place) the input so that it points at
* everything before the '#'. If no '#' is found, the input is left unchanged
* and std::nullopt is returned.
*
* @attention The function is non-allocating and it does not throw.
* @returns Note that the returned string_view might be empty!
*/
ada_really_inline std::optional<std::string_view> prune_hash(
std::string_view& input) noexcept;
/**
* @private
* Defined by the URL specification, shorten a URLs paths.
* @see https://url.spec.whatwg.org/#shorten-a-urls-path
* @returns Returns true if path is shortened.
*/
ada_really_inline bool shorten_path(std::string& path,
ada::scheme::type type) noexcept;
/**
* @private
* Defined by the URL specification, shorten a URLs paths.
* @see https://url.spec.whatwg.org/#shorten-a-urls-path
* @returns Returns true if path is shortened.
*/
ada_really_inline bool shorten_path(std::string_view& path,
ada::scheme::type type) noexcept;
/**
* @private
*
* Parse the path from the provided input and append to the existing
* (possibly empty) path. The input cannot contain tabs and spaces: it
* is the user's responsibility to check.
*
* The input is expected to be UTF-8.
*
* @see https://url.spec.whatwg.org/
*/
ada_really_inline void parse_prepared_path(std::string_view input,
ada::scheme::type type,
std::string& path);
/**
* @private
* Remove and mutate all ASCII tab or newline characters from an input.
*/
ada_really_inline void remove_ascii_tab_or_newline(std::string& input) noexcept;
/**
* @private
* Return the substring from input going from index pos to the end.
* This function cannot throw.
*/
ada_really_inline constexpr std::string_view substring(std::string_view input,
size_t pos) noexcept;
/**
* @private
* Returns true if the string_view points within the string.
*/
bool overlaps(std::string_view input1, const std::string& input2) noexcept;
/**
* @private
* Return the substring from input going from index pos1 to the pos2 (non
* included). The length of the substring is pos2 - pos1.
*/
ada_really_inline constexpr std::string_view substring(std::string_view input,
size_t pos1,
size_t pos2) noexcept {
#if ADA_DEVELOPMENT_CHECKS
if (pos2 < pos1) {
std::cerr << "Negative-length substring: [" << pos1 << " to " << pos2 << ")"
<< std::endl;
abort();
}
#endif
return input.substr(pos1, pos2 - pos1);
}
/**
* @private
* Modify the string_view so that it has the new size pos, assuming that pos <=
* input.size(). This function cannot throw.
*/
ada_really_inline void resize(std::string_view& input, size_t pos) noexcept;
/**
* @private
* Returns a host's delimiter location depending on the state of the instance,
* and whether a colon was found outside brackets. Used by the host parser.
*/
ada_really_inline std::pair<size_t, bool> get_host_delimiter_location(
bool is_special, std::string_view& view) noexcept;
/**
* @private
* Removes leading and trailing C0 control and whitespace characters from
* string.
*/
void trim_c0_whitespace(std::string_view& input) noexcept;
/**
* @private
* @see
* https://url.spec.whatwg.org/#potentially-strip-trailing-spaces-from-an-opaque-path
*/
template <class url_type>
ada_really_inline void strip_trailing_spaces_from_opaque_path(
url_type& url) noexcept;
/**
* @private
* Finds the delimiter of a view in authority state.
*/
ada_really_inline size_t
find_authority_delimiter_special(std::string_view view) noexcept;
/**
* @private
* Finds the delimiter of a view in authority state.
*/
ada_really_inline size_t
find_authority_delimiter(std::string_view view) noexcept;
/**
* @private
*/
template <typename T, typename... Args>
inline void inner_concat(std::string& buffer, T t) {
buffer.append(t);
}
/**
* @private
*/
template <typename T, typename... Args>
inline void inner_concat(std::string& buffer, T t, Args... args) {
buffer.append(t);
return inner_concat(buffer, args...);
}
/**
* @private
* Concatenate the arguments and return a string.
* @returns a string
*/
template <typename... Args>
std::string concat(Args... args) {
std::string answer;
inner_concat(answer, args...);
return answer;
}
/**
* @private
* @return Number of leading zeroes.
*/
inline int leading_zeroes(uint32_t input_num) noexcept {
#if ADA_REGULAR_VISUAL_STUDIO
unsigned long leading_zero(0);
unsigned long in(input_num);
return _BitScanReverse(&leading_zero, in) ? int(31 - leading_zero) : 32;
#else
return __builtin_clz(input_num);
#endif // ADA_REGULAR_VISUAL_STUDIO
}
/**
* @private
* Counts the number of decimal digits necessary to represent x.
* faster than std::to_string(x).size().
* @return digit count
*/
inline int fast_digit_count(uint32_t x) noexcept {
auto int_log2 = [](uint32_t z) -> int {
return 31 - ada::helpers::leading_zeroes(z | 1);
};
// Compiles to very few instructions. Note that the
// table is static and thus effectively a constant.
// We leave it inside the function because it is meaningless
// outside of it (this comes at no performance cost).
const static uint64_t table[] = {
4294967296, 8589934582, 8589934582, 8589934582, 12884901788,
12884901788, 12884901788, 17179868184, 17179868184, 17179868184,
21474826480, 21474826480, 21474826480, 21474826480, 25769703776,
25769703776, 25769703776, 30063771072, 30063771072, 30063771072,
34349738368, 34349738368, 34349738368, 34349738368, 38554705664,
38554705664, 38554705664, 41949672960, 41949672960, 41949672960,
42949672960, 42949672960};
return int((x + table[int_log2(x)]) >> 32);
}
} // namespace ada::helpers
#endif // ADA_HELPERS_H
|