1- /* auto-generated on 2023-02-07 17:26:54 -0500. Do not edit! */
1+ /* auto-generated on 2023-02-22 14:24:01 -0500. Do not edit! */
22// dofile: invoked with prepath=/Users/yagiz/Developer/url-parser/src, filename=ada.cpp
33/* begin file src/ada.cpp */
44#include " ada.h"
@@ -635,33 +635,37 @@ namespace ada::serializers {
635635 }
636636
637637 std::string ipv6 (const std::array<uint16_t , 8 >& address) noexcept {
638- size_t compress_length = 0 ;
639- size_t compress = 0 ;
638+ size_t compress_length = 0 ; // The length of a long sequence of zeros.
639+ size_t compress = 0 ; // The start of a long sequence of zeros.
640640 find_longest_sequence_of_ipv6_pieces (address, compress, compress_length);
641641
642642 if (compress_length <= 1 ) {
643643 // Optimization opportunity: Find a faster way then snprintf for imploding and return here.
644644 compress = compress_length = 8 ;
645645 }
646646
647- std::string output{} ;
647+ std::string output ( 4 * 8 + 7 + 2 , ' \0 ' ) ;
648648 size_t piece_index = 0 ;
649- char buf[5 ];
650-
649+ char *point = output.data ();
650+ char *point_end = output.data () + output.size ();
651+ *point++ = ' [' ;
651652 while (true ) {
652653 if (piece_index == compress) {
653- output.append (" ::" , piece_index == 0 ? 2 : 1 );
654- if ((piece_index = piece_index + compress_length) == 8 ) break ;
654+ *point++ = ' :' ;
655+ // If we skip a value initially, we need to write '::', otherwise
656+ // a single ':' will do since it follows a previous ':'.
657+ if (piece_index == 0 ) { *point++ = ' :' ; }
658+ piece_index += compress_length;
659+ if (piece_index == 8 ) { break ; }
655660 }
656-
657- // Optimization opportunity: Get rid of snprintf.
658- snprintf (buf, 5 , " %x" , address[piece_index]);
659- output += buf;
660- if (++piece_index == 8 ) break ;
661- output.push_back (' :' );
661+ point = std::to_chars (point, point_end, address[piece_index], 16 ).ptr ;
662+ piece_index++;
663+ if (piece_index == 8 ) { break ; }
664+ *point++ = ' :' ;
662665 }
663-
664- return " [" + output + " ]" ;
666+ *point++ = ' ]' ;
667+ output.resize (point - output.data ());
668+ return output;
665669 }
666670
667671 std::string ipv4 (const uint64_t address) noexcept {
@@ -1651,7 +1655,16 @@ namespace ada {
16511655 if (trimmed.empty ()) { port = std::nullopt ; return true ; }
16521656 // Input should not start with control characters.
16531657 if (ada::unicode::is_c0_control_or_space (trimmed.front ())) { return false ; }
1654- return parse_port (trimmed);
1658+ // Input should contain at least one ascii digit.
1659+ if (input.find_first_of (" 0123456789" ) == std::string_view::npos) { return false ; }
1660+
1661+ // Revert changes if parse_port fails.
1662+ std::optional<uint16_t > previous_port = port;
1663+ parse_port (trimmed);
1664+ if (is_valid) { return true ; }
1665+ port = previous_port;
1666+ is_valid = true ;
1667+ return false ;
16551668 }
16561669
16571670 void url::set_hash (const std::string_view input) {
@@ -1692,7 +1705,7 @@ namespace ada {
16921705 return parse_path (input);
16931706 }
16941707
1695- bool url::set_host (const std::string_view input) {
1708+ bool url::set_host_or_hostname (const std::string_view input, bool override_hostname ) {
16961709 if (has_opaque_path) { return false ; }
16971710
16981711 std::optional<std::string> previous_host = host;
@@ -1713,7 +1726,7 @@ namespace ada {
17131726 // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
17141727 // Note: we cannot access *pointer safely if (pointer == pointer_end).
17151728 if ((pointer != new_host.end ()) && (*pointer == ' :' ) && !inside_brackets) {
1716- // TODO: The next 2 lines is the only difference between set_host and set_hostname. Let's simplify it.
1729+ if (override_hostname) { return false ; }
17171730 std::string_view buffer (&*(pointer + 1 ));
17181731 if (!buffer.empty ()) { set_port (buffer); }
17191732 }
@@ -1761,70 +1774,12 @@ namespace ada {
17611774 return true ;
17621775 }
17631776
1764- bool url::set_hostname (const std::string_view input) {
1765- if (has_opaque_path) { return false ; }
1766-
1767- std::optional<std::string> previous_host = host;
1768-
1769- std::string_view::iterator input_pointer_end = std::find (input.begin (), input.end (), ' #' );
1770- std::string _host (input.data (), std::distance (input.begin (), input_pointer_end));
1771- helpers::remove_ascii_tab_or_newline (_host);
1772- std::string_view new_host (_host);
1773-
1774- // If url's scheme is "file", then set state to file host state, instead of host state.
1775- if (get_scheme_type () != ada::scheme::type::FILE) {
1776- std::string_view host_view (_host.data (), _host.length ());
1777- bool inside_brackets{false };
1778- size_t location = helpers::get_host_delimiter_location (*this , host_view, inside_brackets);
1779- std::string_view::iterator pointer = (location != std::string_view::npos) ? new_host.begin () + location : new_host.end ();
1780-
1781- // Otherwise, if c is U+003A (:) and insideBrackets is false, then:
1782- // Note: we cannot access *pointer safely if (pointer == pointer_end).
1783- if ((pointer != new_host.end ()) && (*pointer == ' :' ) && !inside_brackets) {
1784- // If buffer is the empty string, validation error, return failure.
1785- return false ;
1786- }
1787- // If url is special and host_view is the empty string, validation error, return failure.
1788- else if (host_view.empty () && is_special ()) {
1789- return false ;
1790- }
1791- // Otherwise, if state override is given, host_view is the empty string,
1792- // and either url includes credentials or url’s port is non-null, return.
1793- else if (host_view.empty () && (includes_credentials () || port.has_value ())) {
1794- return true ;
1795- }
1796-
1797- // Let host be the result of host parsing host_view with url is not special.
1798- if (host_view.empty ()) {
1799- host = " " ;
1800- return true ;
1801- }
1802-
1803- bool succeeded = parse_host (host_view);
1804- if (!succeeded) { host = previous_host; }
1805- return succeeded;
1806- }
1807-
1808- size_t location = new_host.find_first_of (" /\\ ?" );
1809- if (location != std::string_view::npos) { new_host.remove_suffix (new_host.length () - location); }
1810-
1811- if (new_host.empty ()) {
1812- // Set url’s host to the empty string.
1813- host = " " ;
1814- }
1815- else {
1816- // Let host be the result of host parsing buffer with url is not special.
1817- if (!parse_host (new_host)) {
1818- host = previous_host;
1819- return false ;
1820- }
1777+ bool url::set_host (const std::string_view input) {
1778+ return set_host_or_hostname (input, false );
1779+ }
18211780
1822- // If host is "localhost", then set host to the empty string.
1823- if (host.has_value () && host.value () == " localhost" ) {
1824- host = " " ;
1825- }
1826- }
1827- return true ;
1781+ bool url::set_hostname (const std::string_view input) {
1782+ return set_host_or_hostname (input, true );
18281783 }
18291784
18301785 bool url::set_protocol (const std::string_view input) {
@@ -1849,15 +1804,16 @@ namespace ada {
18491804 ada::result out = ada::parse (input);
18501805
18511806 if (out) {
1852- set_protocol (out->get_protocol ());
1853- set_username (out->get_username ());
1854- set_password (out->get_password ());
1855- set_host (out->get_host ());
1856- set_hostname (out->get_hostname ());
1857- set_port (out->get_port ());
1858- set_pathname (out->get_pathname ());
1859- set_hash (out->get_hash ());
1860- set_search (out->get_search ());
1807+ username = out->username ;
1808+ password = out->password ;
1809+ host = out->host ;
1810+ port = out->port ;
1811+ path = out->path ;
1812+ query = out->query ;
1813+ fragment = out->fragment ;
1814+ type = out->type ;
1815+ non_special_scheme = out->non_special_scheme ;
1816+ has_opaque_path = out->has_opaque_path ;
18611817 }
18621818
18631819 return out.has_value ();
@@ -1989,7 +1945,8 @@ namespace ada::parser {
19891945 case ada::state::NO_SCHEME: {
19901946 ada_log (" NO_SCHEME " , helpers::substring (url_data, input_position));
19911947 // If base is null, or base has an opaque path and c is not U+0023 (#), validation error, return failure.
1992- if (base_url == nullptr || (base_url->has_opaque_path && (input_position != input_size))) {
1948+ // SCHEME state updates the state to NO_SCHEME and validates url_data is not empty.
1949+ if (base_url == nullptr || (base_url->has_opaque_path && url_data[input_position] != ' #' )) {
19931950 ada_log (" NO_SCHEME validation error" );
19941951 url.is_valid = false ;
19951952 return url;
0 commit comments