4#include "Stroika/Foundation/StroikaPreComp.h"
9#include "Stroika/Foundation/Characters/String2Int.h"
11#include "Stroika/Foundation/Containers/Support/ReserveTweaks.h"
12#include "Stroika/Foundation/Execution/Exceptions.h"
13#include "Stroika/Foundation/Execution/Throw.h"
23using namespace Stroika::Foundation::IO;
25using namespace Stroika::Foundation::IO::Network::UniformResourceIdentification;
28 inline uint8_t ConvertReadSingleHexDigit_ (
char digit)
31 if (isupper (digit)) {
32 digit =
static_cast<char> (tolower (digit));
34 if (isdigit (digit)) {
35 return static_cast<uint8_t
> (digit -
'0');
37 else if (islower (digit)) {
39 Execution::Throw (kException_);
41 return static_cast<uint8_t
> (10 + (digit -
'a'));
44 Execution::Throw (kException_);
60void SchemeType::Validate ()
const
77optional<PortType> SchemeType::GetDefaultPort ()
const
82 {
"http"sv,
static_cast<PortType
> (80)},
83 {
"https"sv,
static_cast<PortType
> (443)},
84 {
"ldap"sv,
static_cast<PortType
> (389)},
85 {
"ldaps"sv,
static_cast<PortType
> (636)},
86 {
"ftp"sv,
static_cast<PortType
> (21)},
87 {
"ftps"sv,
static_cast<PortType
> (990)},
94 using namespace Characters;
95 return String::ThreeWayComparer{eCaseInsensitive}(
lhs,
rhs);
103pair<optional<String>, optional<InternetAddress>> Host::ParseRaw_ (
const String& raw)
105 Require (
not raw.empty ());
108 if (
raw[0].IsDigit ()) {
112 else if (
raw[0] ==
'[') {
115 if (
raw.Last () !=
']') {
128 if (fRegisteredName_) {
129 return Host{fRegisteredName_->ToLowerCase ()};
131 Assert (fInternetAddress_);
132 return Host{*fInternetAddress_};
135String Host::EncodeAsRawURL_ (
const String& registeredName)
146 switch (
ipAddr.GetAddressFamily ()) {
147 case InternetAddress::AddressFamily::V4: {
150 case InternetAddress::AddressFamily::V6: {
173 Require (
not raw.empty ());
175 return PCTDecode2String (
raw);
178String UserInfo::EncodeAsRawURL_ (
const String& decodedName)
296 size_t utfqLen = utf8Query.length ();
297 for (
size_t i = 0; i < utfqLen;) {
298 size_t e = utf8Query.find (
'&', i);
299 u8string elt = utf8Query.substr (i, e - i);
300 size_t brk = elt.find (
'=');
301 if (brk != string::npos) {
302 u8string val = elt.substr (brk + 1);
303 for (
auto p = val.begin (); p != val.end (); ++p) {
309 if (p + 2 < val.end ()) {
310 unsigned char newC = (ConvertReadSingleHexDigit_ (*(p + 1)) << 4) + ConvertReadSingleHexDigit_ (*(p + 2));
311 p = val.erase (p, p + 2);
312 *p =
static_cast<char> (newC);
327Query::Query (
const String& query)
329 InitURLQueryDecoder_ (&fMap_, query.
AsASCII<u8string> ());
332Query::Query (
const u8string& query)
334 InitURLQueryDecoder_ (&fMap_, query);
337void Query::RemoveFieldIfAny (
const String& idx)
342String Query::ComputeQueryString ()
const
345 for (
auto i = fMap_.begin (); i != fMap_.end (); ++i) {
346 Containers::Support::ReserveTweaks::Reserve4Add1 (result);
347 if (not result.empty ()) {
351 result += EncodeURLQueryStringField (i->fKey) + u8
"=" + EncodeURLQueryStringField (i->fValue);
363strong_ordering Query::TWC_ (
const Query& lhs,
const Query& rhs)
370 optional<String> lhsVal = lhs.GetMap ().Lookup (i);
371 optional<String> rhsVal = rhs.GetMap ().Lookup (i);
372 strong_ordering cmp = Common::StdCompat::compare_three_way{}(lhsVal, rhsVal);
373 if (cmp != strong_ordering::equal) {
377 return strong_ordering::equal;
385u8string UniformResourceIdentification::EncodeURLQueryStringField (
const String& s)
393 u8string utf8Query = s.
AsUTF8 ();
395 size_t sLength = utf8Query.length ();
396 result.reserve (sLength);
397 for (
size_t i = 0; i < sLength; ++i) {
398 Containers::Support::ReserveTweaks::Reserve4Add1 (result);
399 switch (utf8Query[i]) {
404 char8_t ccode = utf8Query[i];
405 if (isascii (ccode) and (isalnum (ccode) or (ccode ==
'-') or (ccode ==
'.') or (ccode ==
'_') or (ccode ==
'~'))) {
406 result +=
static_cast<char> (utf8Query[i]);
409 result += CString::Format (u8
"%%%.2x", ccode);
422u8string UniformResourceIdentification::PCTEncode (
const u8string& s,
const PCTEncodeOptions& options)
425 size_t sLength = s.length ();
426 result.reserve (sLength);
429 if (useOptions.allowFragOrQueryChars) {
430 useOptions.allowPChar =
true;
432 if (useOptions.allowPChar) {
433 useOptions.allowSubDelims =
true;
435 if (useOptions.allowPathCharacters) {
436 useOptions.allowSubDelims =
true;
443 if (isalpha (c) or isdigit (c)) {
454 if (useOptions.allowFragOrQueryChars) {
461 if (useOptions.allowPChar) {
468 if (useOptions.allowPathCharacters) {
474 if (useOptions.allowGenDelims) {
485 if (useOptions.allowSubDelims) {
502 Containers::Support::ReserveTweaks::Reserve4AddN (result, 3);
503 result += CString::Format (u8
"%%%.2x", c);
506 Containers::Support::ReserveTweaks::Reserve4Add1 (result);
515 return PCTEncode (s.
AsUTF8<u8string> (), options);
528u8string UniformResourceIdentification::PCTDecode (
const u8string& s)
531 result.reserve (s.length ());
532 for (
auto p = s.begin (); p != s.end (); ++p) {
535 if (p + 2 < s.end ()) {
536 unsigned char newC = (ConvertReadSingleHexDigit_ (*(p + 1)) << 4) + ConvertReadSingleHexDigit_ (*(p + 2));
558String UniformResourceIdentification::PCTDecode2String (
const u8string& s)
563String UniformResourceIdentification::PCTDecode2String (
const String& s)
573size_t std::hash<Stroika::Foundation::IO::Network::UniformResourceIdentification::Host>::operator() (
576 return hash<Characters::String>{}(arg.
As<
Characters::String> (UniformResourceIdentification::Host::eDecoded));
#define WeakAssertNotImplemented()
Similar to String, but intended to more efficiently construct a String. Mutable type (String is large...
String is like std::u32string, except it is much easier to use, often much more space efficient,...
nonvirtual T AsUTF8() const
nonvirtual String ToLowerCase() const
static constexpr size_t npos
nonvirtual String SubString(SZ from) const
nonvirtual T AsASCII() const
static String FromUTF8(span< CHAR_T > from)
nonvirtual optional< size_t > Find(Character c, CompareOptions co=eWithCase) const
nonvirtual bool Add(ArgByValueType< key_type > key, ArgByValueType< mapped_type > newElt, AddReplaceMode addReplaceMode=AddReplaceMode::eAddReplaces)
Set<T> is a container of T, where once an item is added, additionally adds () do nothing.
String ToString(T &&t, ARGS... args)
Return a debug-friendly, display version of the argument: not guaranteed parsable or usable except fo...
void Throw(T &&e2Throw)
identical to builtin C++ 'throw' except that it does helpful, type dependent DbgTrace() messages firs...