@@ -194,33 +194,89 @@ bool Address::operator==(Address const &other) const {
194194 }
195195}
196196
197- std::string Address::str () const {
198- char buffer[INET6_ADDRSTRLEN];
199-
200- if (!inet_ntop (_family, addr (), buffer, INET6_ADDRSTRLEN))
201- throw std::runtime_error (std::string (" Address::str(): " ) +
202- std::strerror (errno));
203- if (_family == AF_INET6) {
204- std::string result (" [" );
205- result.append (buffer);
206- result.push_back (' ]' );
207- return result;
197+ static std::ostream &operator <<(std::ostream &os, in_addr const &src) {
198+ int32_t hostByteOrder = ntohl (src.s_addr );
199+ os << (hostByteOrder >> 24 & 0xFF ) << ' .' ;
200+ os << (hostByteOrder >> 16 & 0xFF ) << ' .' ;
201+ os << (hostByteOrder >> 8 & 0xFF ) << ' .' ;
202+ os << (hostByteOrder & 0xFF );
203+ return os;
204+ }
205+
206+ static std::pair<unsigned int , unsigned int > allZeroFields (
207+ unsigned char const *addr) {
208+ unsigned int currentStart = 0 ;
209+ unsigned int currentSize = 0 ;
210+ std::pair<unsigned int , unsigned int > result;
211+ unsigned int bestSize = 0 ;
212+
213+ for (unsigned int i = 0 ; i < 8 ; ++i) {
214+ unsigned int pos = i * 2 ;
215+ if (addr[pos] != 0 || addr[pos + 1 ] != 0 ) {
216+ currentSize = 0 ;
217+ continue ;
218+ }
219+ if (currentSize == 0 ) {
220+ currentSize = 1 ;
221+ currentStart = pos;
222+ } else {
223+ ++currentSize;
224+ }
225+ if (currentSize > bestSize) {
226+ bestSize = currentSize;
227+ result.first = currentStart;
228+ }
208229 }
209- return std::string (buffer);
230+
231+ if (bestSize) {
232+ result.second = result.first + bestSize * 2 ;
233+ result.second -= 1 ;
234+ if (result.second - result.first == 1 ) result.second = 0 ;
235+ }
236+ return result;
210237}
211238
212- /* *
213- * @throw std::runtime_error() if addr.family() is not AF_INET or AF_INET6
214- */
215- std::ostream &operator <<(std::ostream &os, Address const &addr) {
216- char buffer[INET6_ADDRSTRLEN];
239+ static std::ostream &operator <<(std::ostream &os, in6_addr const &src) {
240+ unsigned char const *addr = reinterpret_cast <unsigned char const *>(&src);
217241
218- if (!inet_ntop (addr.family (), addr.addr (), buffer, INET6_ADDRSTRLEN))
219- throw std::runtime_error (std::string (" <<Address: " ) + std::strerror (errno));
220- if (addr.family () == AF_INET) {
221- os << buffer << " :" << addr.port ();
222- } else {
223- os << " [" << buffer << " ]:" << addr.port ();
242+ os << ' [' ;
243+ if ((IN6_IS_ADDR_V4COMPAT (addr) && (addr[12 ] != 0 || addr[13 ] != 0 )) ||
244+ IN6_IS_ADDR_V4MAPPED (addr)) {
245+ addr[10 ] == 255 ? os << " ::ffff:" : os << " ::" ;
246+ os << *reinterpret_cast <in_addr const *>(&addr[12 ]);
247+ os << ' ]' ;
248+ return os;
224249 }
250+
251+ std::pair<unsigned int , unsigned int > zeroField = allZeroFields (addr);
252+ std::ios_base::fmtflags flags =
253+ os.setf (std::ios_base::hex, std::ios_base::basefield);
254+
255+ for (size_t i = 0 ; i < 16 ; ++i) {
256+ bool first = (i % 2 == 0 );
257+
258+ if (zeroField.second == 0 || i < zeroField.first || i > zeroField.second ) {
259+ if (!first) {
260+ if (addr[i - 1 ] != 0 ) os << std::setw (2 ) << std::setfill (' 0' );
261+ os << (int )addr[i];
262+ if (i != 15 ) os << ' :' ;
263+ } else if (addr[i] != 0 ) {
264+ os << (int )addr[i];
265+ }
266+ } else if (i == zeroField.second || (i == 0 && zeroField.first == 0 )) {
267+ os << ' :' ;
268+ }
269+ }
270+ os.flags (flags);
271+ os << ' ]' ;
272+ return os;
273+ }
274+
275+ std::ostream &operator <<(std::ostream &os, Address const &addr) {
276+ if (addr.family () == AF_INET6)
277+ os << *reinterpret_cast <in6_addr const *>(addr.addr ());
278+ else
279+ os << *reinterpret_cast <in_addr const *>(addr.addr ());
280+ os << ' :' << addr.port ();
225281 return os;
226282}
0 commit comments