2
3
4
5
6
7
8
9
10
11
13#ifndef IPADDRESS_IPV6_ADDRESS_HPP
14#define IPADDRESS_IPV6_ADDRESS_HPP
24struct ipv6_set_scope {
25 template <
typename Str>
27 #if IPADDRESS_IPV6_SCOPE_MAX_LENGTH
> 0
30 change(result, scope, code, index);
31 #ifndef IPADDRESS_NO_EXCEPTIONS
33 raise_error(code, index, scope.data(), scope.size());
39 template <
typename Str>
41 #if IPADDRESS_IPV6_SCOPE_MAX_LENGTH
> 0
43 change(result, scope, code, index);
47 template <
typename Str>
49 #if IPADDRESS_IPV6_SCOPE_MAX_LENGTH
> 0
50 if (scope.size() > IPADDRESS_IPV6_SCOPE_MAX_LENGTH) {
54 char str[IPADDRESS_IPV6_SCOPE_MAX_LENGTH + 1] = {};
55 auto it = scope.data();
56 auto end = it + scope.size();
57 uint32_t error_symbol = 0;
60 for (
int i = 0; it < end; ++i) {
61 auto c = internal::next_char_or_error(it, end, code, error_symbol);
66 if (internal::is_invalid_scope_id_symbol(c)) {
72 const auto fixed_scope = make_fixed_string(str, code);
83
84
85
86
87
88
92
93
94
95
103
104
105
106
108 return std::string(_scope_id.begin(), _scope_id.end());
112
113
114
115
117 return _scope_id_value;
121
122
123
124
126 return !_scope_id.empty();
130
131
132
133
139
140
141
142
148
149
150
151
157
158
159
160
166
167
168
169
170
172 return _scope_id == rhs._scope_id;
176
177
178
179
180
182 return !(*
this == rhs);
185#ifdef IPADDRESS_HAS_SPACESHIP_OPERATOR
188
189
190
191
192
193 IPADDRESS_NODISCARD IPADDRESS_CONSTEXPR IPADDRESS_FORCE_INLINE std::strong_ordering operator<=>(
const scope& rhs)
const IPADDRESS_NOEXCEPT {
194 return _scope_id <=> rhs._scope_id;
200
201
202
203
204
206 return _scope_id < rhs._scope_id;
210
211
212
213
214
220
221
222
223
224
226 return !(rhs
< *
this);
230
231
232
233
234
236 return !(*
this < rhs);
243 if (!_scope_id.empty()) {
246 const auto scope_id_size = _scope_id.size();
247 for (size_t i = 0; i < scope_id_size; ++i) {
248 const auto c = _scope_id[i];
249 if (c >=
'0' && c <=
'9') {
250 value = value * 10 + (c -
'0');
256 _scope_id_value = _has_value ? value : 0;
260 fixed_string<IPADDRESS_IPV6_SCOPE_MAX_LENGTH> _scope_id;
261 uint32_t _scope_id_value = 0;
262 bool _has_value =
false;
266
267
268
269
270
271
278
279
280
281
282
283
284
285
288 #if IPADDRESS_IPV6_SCOPE_MAX_LENGTH
> 0
291 make_fixed_string(
"")
297
298
299
300
301
302
303
304
305
306
307 template <
typename T, size_t N>
309 #if IPADDRESS_IPV6_SCOPE_MAX_LENGTH
> 0
310 static_assert(N <= IPADDRESS_IPV6_SCOPE_MAX_LENGTH + 1,
"scope id is too long");
311 #ifdef IPADDRESS_NO_EXCEPTIONS
312 auto code = error_code::no_error;
313 const auto result = make_fixed_string(scope_id, code);
314 if (code == error_code::no_error) {
315 internal::ipv6_set_scope<ipv6_address_base>::change(_data.scope_id, result);
318 internal::ipv6_set_scope<ipv6_address_base>::change(_data.scope_id, make_fixed_string(scope_id));
324
325
326
327
328
329
330
331
332
333
334
335 template <
typename T, size_t N>
337 #if IPADDRESS_IPV6_SCOPE_MAX_LENGTH
> 0
338 static_assert(N <= IPADDRESS_IPV6_SCOPE_MAX_LENGTH + 1,
"scope id is too long");
339 const auto fixed_scope = make_fixed_string(scope_id, code);
341 internal::ipv6_set_scope<ipv6_address_base>::change(_data.scope_id, fixed_scope, code);
346#if IPADDRESS_CPP_VERSION
>= 17
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
365 #if IPADDRESS_IPV6_SCOPE_MAX_LENGTH > 0
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
387 #if IPADDRESS_IPV6_SCOPE_MAX_LENGTH > 0
392#if __cpp_char8_t >= 201811L
395
396
397
398
399
400
401
402
403
404
406 #if IPADDRESS_IPV6_SCOPE_MAX_LENGTH > 0
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
430 #if IPADDRESS_IPV6_SCOPE_MAX_LENGTH > 0
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
452 #if IPADDRESS_IPV6_SCOPE_MAX_LENGTH > 0
458
459
460
461
462
463
464
465
466
467
468
469
470
471
473 #if IPADDRESS_IPV6_SCOPE_MAX_LENGTH > 0
479
480
481
482
483
484
485
486
487
488
489
490
491
492
494 #if IPADDRESS_IPV6_SCOPE_MAX_LENGTH > 0
499#if __cpp_char8_t >= 201811L
502
503
504
505
506
507
508
509
510
512 #if IPADDRESS_IPV6_SCOPE_MAX_LENGTH > 0
520
521
522
523
524
525
526
527
528
529
530
531
532
533
535 #if IPADDRESS_IPV6_SCOPE_MAX_LENGTH > 0
541
542
543
544
545
546
547
548
549
550
551
552
553
554
556 #if IPADDRESS_IPV6_SCOPE_MAX_LENGTH > 0
564
565
566
567
568
570 #if IPADDRESS_IPV6_SCOPE_MAX_LENGTH
> 0
571 internal::ipv6_set_scope<ipv6_address_base>::change(_data.scope_id, scope_id);
576
577
578
579
580
582 #if IPADDRESS_IPV6_SCOPE_MAX_LENGTH
> 0
583 internal::ipv6_set_scope<ipv6_address_base>::change(_data.scope_id, scope_id);
588
589
590
591
592
594 #if IPADDRESS_IPV6_SCOPE_MAX_LENGTH
> 0
595 internal::ipv6_set_scope<ipv6_address_base>::change(_data.scope_id, scope_id);
600
601
602
603
604
606 #if IPADDRESS_IPV6_SCOPE_MAX_LENGTH
> 0
607 internal::ipv6_set_scope<ipv6_address_base>::change(_data.scope_id, scope_id);
612
613
614
615
616
618 #if IPADDRESS_IPV6_SCOPE_MAX_LENGTH
> 0
619 internal::ipv6_set_scope<ipv6_address_base>::change(_data.scope_id, scope_id, code);
624
625
626
627
628
630 #if IPADDRESS_IPV6_SCOPE_MAX_LENGTH
> 0
631 internal::ipv6_set_scope<ipv6_address_base>::change(_data.scope_id, scope_id, code);
636
637
638
639
640
642 #if IPADDRESS_IPV6_SCOPE_MAX_LENGTH
> 0
643 internal::ipv6_set_scope<ipv6_address_base>::change(_data.scope_id, scope_id, code);
648
649
650
651
652
654 #if IPADDRESS_IPV6_SCOPE_MAX_LENGTH
> 0
655 internal::ipv6_set_scope<ipv6_address_base>::change(_data.scope_id, scope_id, code);
662
663
664
665
666
669 auto& bytes = result._data.bytes;
676 for (
int i = 0, s = shift; i < 8; ++i, s += inc) {
677 bytes[i] = uint8_t(ip.upper() >> s);
678 bytes[i + 8] = uint8_t(ip.lower() >> s);
684
685
686
687
688
690 const auto& bytes = _data.bytes;
699 for (
int i = 0, s = shift; i < 8; ++i, s += inc) {
700 upper |= uint64_t(bytes[i]) << s;
701 lower |= uint64_t(bytes[i + 8]) << s;
703 return uint_type(upper, lower);
707
708
709
710
711
717
718
719
720
721
723 const auto& b = bytes();
724 if (b[10] != 0xFF || b[11] != 0xFF) {
727 ipv4_address::base_type ipv4_bytes = { b[12], b[13], b[14], b[15] };
728 return ipv4_address(ipv4_bytes);
732
733
734
735
736
737
739 const auto& b = bytes();
740 if (b[0] != 0x20 || b[1] != 0x02) {
743 ipv4_address::base_type ipv4_bytes = { b[2], b[3], b[4], b[5] };
744 return ipv4_address(ipv4_bytes);
748
749
750
751
752
753
754
755
757 const auto& b = bytes();
758 if (b[0] != 0x20 || b[1] != 0x01 || b[2] != 0x00 || b[3] != 0x00) {
761 ipv4_address::base_type server_bytes = { b[4], b[5], b[6], b[7] };
762 ipv4_address::base_type client_bytes = { uint8_t(~b[12]), uint8_t(~b[13]), uint8_t(~b[14]), uint8_t(~b[15]) };
763 return std::make_pair(ipv4_address(server_bytes), ipv4_address(client_bytes));
767
768
769
770
771
772
782 lhs._data.bytes.swap(rhs._data.bytes);
783 #if IPADDRESS_IPV6_SCOPE_MAX_LENGTH
> 0
784 lhs._data.scope_id.swap(rhs._data.scope_id);
789 return internal::calc_hash(
790 #if IPADDRESS_IPV6_SCOPE_MAX_LENGTH
> 0
791 _data.scope_id.hash(),
795 size_t(bytes[0]), size_t(bytes[1]), size_t(bytes[2]), size_t(bytes[3]),
796 size_t(bytes[4]), size_t(bytes[5]), size_t(bytes[6]), size_t(bytes[7]),
797 size_t(bytes[8]), size_t(bytes[9]), size_t(bytes[10]), size_t(bytes[11]),
798 size_t(bytes[12]), size_t(bytes[13]), size_t(bytes[14]), size_t(bytes[15]));
802 return lhs._data.bytes == rhs._data.bytes
804 #if IPADDRESS_IPV6_SCOPE_MAX_LENGTH
> 0
805 && lhs._data.scope_id.compare(rhs._data.scope_id) == 0
811 return lhs._data.bytes < rhs._data.bytes
813 #if IPADDRESS_IPV6_SCOPE_MAX_LENGTH
> 0
814 ?
true : lhs._data.scope_id.compare(rhs._data.scope_id) < 0;
819#ifdef IPADDRESS_HAS_SPACESHIP_OPERATOR
822 #if IPADDRESS_IPV6_SCOPE_MAX_LENGTH > 0
826 }
else if (
scope == 0) {
842 return base_v6<ipv6_address_base>::ip_to_chars(bytes,
844 #if IPADDRESS_IPV6_SCOPE_MAX_LENGTH
> 0
847 make_fixed_string(
""),
865 #if IPADDRESS_IPV6_SCOPE_MAX_LENGTH
> 0
872
873
874
875
876
877
878
881#ifdef IPADDRESS_NONTYPE_TEMPLATE_PARAMETER
884
885
886
887
888
889 IPADDRESS_EXPORT
template <fixed_string FixedString>
890 IPADDRESS_NODISCARD IPADDRESS_CONSTEVAL IPADDRESS_FORCE_INLINE ipv6_address operator
""_ipv6() IPADDRESS_NOEXCEPT {
891 return ipv6_address::parse<FixedString>();
897
898
899
900
901
902
904 return internal::parse_ip_from_literal<ipv6_address_base,
char, ipv6_address::base_max_string_len>(address, size);
908
909
910
911
912
913
915 return internal::parse_ip_from_literal<ipv6_address_base,
wchar_t, ipv6_address::base_max_string_len>(address, size);
919
920
921
922
923
924
926 return internal::parse_ip_from_literal<ipv6_address_base,
char16_t, ipv6_address::base_max_string_len>(address, size);
930
931
932
933
934
935
937 return internal::parse_ip_from_literal<ipv6_address_base,
char32_t, ipv6_address::base_max_string_len>(address, size);
A template class providing the base functionality for IPv6 addresses.
Definition base-v6.hpp:42
A template base class for IP address representations.
Definition ip-address-base.hpp:56
Template base class for representing a network of IP addresses.
Definition ip-network-base.hpp:32
Represents the base class for IPv6 address manipulation.
Definition ipv6-address.hpp:272
constexpr inline bool is_site_local() const noexcept
Checks if the IPv6 address is a site-local address.
Definition ip-networks.hpp:397
constexpr inline uint_type to_uint() const noexcept
Converts the IPv6 address to an unsigned integer.
Definition ipv6-address.hpp:689
constexpr inline void set_scope_id(const T(&scope_id)[N], error_code &code) noexcept
Sets the scope identifier of the IPv6 address and reports any errors encountered.
Definition ipv6-address.hpp:336
constexpr inline scope get_scope_id() const noexcept
Retrieves the scope identifier of the IPv6 address.
Definition ipv6-address.hpp:286
constexpr inline const base_type & bytes() const noexcept
Provides access to the underlying bytes of the IPv6 address.
Definition ipv6-address.hpp:712
constexpr inline void set_scope_id(const T(&scope_id)[N])
Sets the scope identifier of the IPv6 address.
Definition ipv6-address.hpp:308
constexpr inline optional< std::pair< ipv4_address, ipv4_address > > teredo() const noexcept
Determines if the IPv6 address is a Teredo address.
Definition ipv6-address.hpp:756
constexpr inline optional< ipv4_address > ipv4_mapped() const noexcept
Determines if the IPv6 address is an IPv4-mapped address.
Definition ipv6-address.hpp:722
constexpr inline optional< ipv4_address > sixtofour() const noexcept
Determines if the IPv6 address is a 6to4 address.
Definition ipv6-address.hpp:738
static constexpr inline ip_address_base< ipv6_address_base > from_uint(uint_type ip) noexcept
Creates an IPv6 address from an unsigned integer using a template parameter.
Definition ipv6-address.hpp:667
A template class to manage an optional contained value.
Definition optional.hpp:35
constexpr inline bool operator!=(const scope &rhs) const noexcept
Compares two scope objects for inequality.
Definition ipv6-address.hpp:181
inline operator std::string() const
Converts the scope object to a string representation.
Definition ipv6-address.hpp:152
constexpr inline scope(const fixed_string< IPADDRESS_IPV6_SCOPE_MAX_LENGTH > &scope_id) noexcept
Constructs a scope object with a given scope identifier.
Definition ipv6-address.hpp:96
inline std::string get_string() const
Retrieves the scope identifier as a string.
Definition ipv6-address.hpp:107
constexpr inline bool operator>(const scope &rhs) const noexcept
Checks if one scope object is greater than another.
Definition ipv6-address.hpp:215
constexpr inline operator uint32_t() const noexcept
Converts the scope object to a numeric representation.
Definition ipv6-address.hpp:161
constexpr inline bool has_uint32() const noexcept
Checks if the scope identifier has a numeric representation.
Definition ipv6-address.hpp:134
constexpr inline bool operator>=(const scope &rhs) const noexcept
Checks if one scope object is greater than or equal to another.
Definition ipv6-address.hpp:235
constexpr inline bool operator<=(const scope &rhs) const noexcept
Checks if one scope object is less than or equal to another.
Definition ipv6-address.hpp:225
constexpr inline bool has_string() const noexcept
Checks if the scope identifier has a string representation.
Definition ipv6-address.hpp:125
constexpr inline uint32_t get_uint32() const noexcept
Retrieves the scope identifier as a numeric value.
Definition ipv6-address.hpp:116
constexpr inline bool operator==(const scope &rhs) const noexcept
Compares two scope objects for equality.
Definition ipv6-address.hpp:171
constexpr inline bool operator<(const scope &rhs) const noexcept
Checks if one scope object is less than another.
Definition ipv6-address.hpp:205
constexpr inline operator bool() const noexcept
Converts the scope object to a boolean value based on the presence of a scope representation.
Definition ipv6-address.hpp:143
#define IPADDRESS_NOEXCEPT_WHEN_NO_EXCEPTIONS
Definition config.hpp:93
#define IPADDRESS_EXPORT
Definition config.hpp:42
#define IPADDRESS_NODISCARD
Definition config.hpp:98
#define IPADDRESS_FORCE_INLINE
Definition config.hpp:112
#define IPADDRESS_NAMESPACE
Definition config.hpp:38
#define IPADDRESS_NOEXCEPT
Definition config.hpp:89
#define IPADDRESS_NODISCARD_WHEN_NO_EXCEPTIONS
Definition config.hpp:102
constexpr inline bool is_little_endian() noexcept
Checks if the system is little-endian.
Definition endian.hpp:110
error_code
Enumeration of error codes for IP address parsing and validation.
Definition errors.hpp:52
@ invalid_scope_id
The scope ID in the IPv6 address is invalid.
@ no_error
Indicates the absence of any errors.
@ scope_id_is_too_long
The scope ID in the IPv6 address exceeds the maximum length.
Fixed size string class.
Definition fixed-string.hpp:29