net: NetworkMonitorImplOsx: optimize conversion from CFString

Change-Id: I82abccb01997aa53fe9b30ea4edbe23d8ac9158a
Refs: #3817
diff --git a/src/net/detail/network-monitor-impl-osx.cpp b/src/net/detail/network-monitor-impl-osx.cpp
index da162d3..16b32bb 100644
--- a/src/net/detail/network-monitor-impl-osx.cpp
+++ b/src/net/detail/network-monitor-impl-osx.cpp
@@ -63,7 +63,9 @@
 #include <net/if_dl.h>     // for struct sockaddr_dl
 #include <net/if_types.h>  // for IFT_* constants
 
-#include <boost/asio.hpp>
+#include <boost/asio/io_service.hpp>
+#include <boost/asio/ip/address.hpp>
+#include <boost/asio/ip/udp.hpp>
 
 namespace ndn {
 namespace net {
@@ -197,19 +199,23 @@
 }
 
 static std::string
-convertToStdString(CFStringRef cfString)
+convertToStdString(CFStringRef cfStr)
 {
-  const char* cStr = CFStringGetCStringPtr(cfString, kCFStringEncodingASCII);
+  const char* cStr = CFStringGetCStringPtr(cfStr, kCFStringEncodingASCII);
   if (cStr != nullptr) {
+    // fast path
     return cStr;
   }
 
-  size_t stringSize = CFStringGetLength(cfString);
-  char* buffer = new char[stringSize + 1];
-  CFStringGetCString(cfString, buffer, sizeof(buffer), kCFStringEncodingASCII);
-  std::string retval = buffer;
-  delete[] buffer;
-  return retval;
+  // reserve space for the string + null terminator
+  std::string str(CFStringGetLength(cfStr) + 1, '\0');
+  if (!CFStringGetCString(cfStr, &str.front(), str.size(), kCFStringEncodingASCII)) {
+    BOOST_THROW_EXCEPTION(NetworkMonitorImplOsx::Error("CFString conversion failed"));
+  }
+
+  // drop the null terminator, std::string doesn't need it
+  str.pop_back();
+  return str;
 }
 
 std::set<std::string>
diff --git a/tests/integrated/network-monitor.cpp b/tests/integrated/network-monitor.cpp
index eb23e5b..45cb57b 100644
--- a/tests/integrated/network-monitor.cpp
+++ b/tests/integrated/network-monitor.cpp
@@ -1,5 +1,5 @@
 /* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
-/**
+/*
  * Copyright (c) 2013-2017 Regents of the University of California.
  *
  * This file is part of ndn-cxx library (NDN C++ library with eXperimental eXtensions).
@@ -27,9 +27,9 @@
 
 #include "net/network-address.hpp"
 #include "net/network-interface.hpp"
-#include "util/time.hpp"
-
 #include "net/detail/link-type-helper.hpp"
+#include "util/string-helper.hpp"
+#include "util/time.hpp"
 
 #include "boost-test.hpp"
 
@@ -56,7 +56,7 @@
   boost::asio::io_service io;
   NetworkMonitor monitor(io);
 
-  std::cout << "capabilities=" << monitor.getCapabilities() << std::endl;
+  std::cout << "capabilities=" << AsHex{monitor.getCapabilities()} << std::endl;
 
   monitor.onNetworkStateChanged.connect([] {
     logEvent() << "onNetworkStateChanged" << std::endl;
@@ -71,7 +71,7 @@
 
   monitor.onInterfaceAdded.connect([] (const shared_ptr<const NetworkInterface>& ni) {
     logEvent(ni) << "onInterfaceAdded\n" << *ni;
-    logEvent(ni) << "link-type: " << detail::getLinkType(ni->getName()) << "\n";
+    logEvent(ni) << "link-type: " << detail::getLinkType(ni->getName()) << std::endl;
 
     ni->onAddressAdded.connect([ni] (const NetworkAddress& address) {
       logEvent(ni) << "onAddressAdded " << address << std::endl;
@@ -83,7 +83,7 @@
 
     ni->onStateChanged.connect([ni] (InterfaceState oldState, InterfaceState newState) {
       logEvent(ni) << "onStateChanged " << oldState << " -> " << newState << std::endl;
-      logEvent(ni) << "link-type: " << detail::getLinkType(ni->getName()) << "\n";
+      logEvent(ni) << "link-type: " << detail::getLinkType(ni->getName()) << std::endl;
     });
 
     ni->onMtuChanged.connect([ni] (uint32_t oldMtu, uint32_t newMtu) {