<commit_before>/**
 * This file is part of the "libstx" project
 *   Copyright (c) 2014 <NAME>, Google Inc.
 *
 * libstx is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License v3.0. You should have received a
 * copy of the GNU General Public License along with this program. If not, see
 * <http://www.gnu.org/licenses/>.
 */
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include "stx/exception.h"
#include "stx/stringutil.h"
#include "stx/net/inetaddr.h"

namespace stx {

InetAddr InetAddr::resolve(const std::string& addr_str) {
  auto parts = StringUtil::split(addr_str, ":");
  unsigned port = 0;
  std::string hostname;
  std::string ip;

  switch (parts.size()) {
    case 2:
      port = std::stoi(parts[1]);
      /* fallthrough */

    case 1: {
      struct hostent* h = gethostbyname(parts[0].c_str());

      if (h == nullptr) {
        RAISEF(kResolveError, "gethostbyname($0) failed", parts[0]);
      }

      hostname = h->h_name;
      ip = inet_ntoa(*((struct in_addr *) h->h_addr));
      break;
    }

    default:
      RAISEF(kResolveError, "invalid address: $0", addr_str);
  }

  return InetAddr(hostname, ip, port);
}

InetAddr::InetAddr(
    const std::string& hostname,
    const std::string& ip,
    unsigned port) :
    hostname_(hostname),
    ip_(ip),
    port_(port) {}

InetAddr::InetAddr(
    const std::string& hostname,
    unsigned port) :
    hostname_(hostname),
    port_(port) {}
<commit_msg>thread-safe name resolution<commit_after>/**
 * This file is part of the "libstx" project
 *   Copyright (c) 2014 <NAME>, Google Inc.
 *
 * libstx is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License v3.0. You should have received a
 * copy of the GNU General Public License along with this program. If not, see
 * <http://www.gnu.org/licenses/>.
 */
#include <arpa/inet.h>
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include "stx/exception.h"
#include "stx/stringutil.h"
#include "stx/net/inetaddr.h"
#include "stx/sysconfig.h"

namespace stx {

InetAddr InetAddr::resolve(const std::string& addr_str) {
  auto parts = StringUtil::split(addr_str, ":");
  unsigned port = 0;
  std::string hostname;
  std::string ip;

  switch (parts.size()) {
    case 2:
      port = std::stoi(parts[1]);
      /* fallthrough */

    case 1: {
      auto hstr = parts[0].c_str();

#ifdef HAVE_GETHOSTBYNAME_R
      size_t buflen = 1024;
      auto buf = static_cast<char*>(malloc(buflen));
      if (buf == nullptr) {
        RAISE(kMallocError, "malloc() failed");
      }

      struct hostent* h;
      struct hostent ret;
      int err;
      while (gethostbyname_r(hstr, &ret, buf, buflen, &h, &err) == ERANGE) {
        buflen *= 2;
        buf = static_cast<char*>(realloc(buf, buflen));
        if (buf == nullptr) {
          RAISE(kMallocError, "malloc() failed");
        }
      }

      if (h) {
        hostname = h->h_name;
        ip = inet_ntoa(*((struct in_addr *) h->h_addr));
        free(buf);
      } else {
        free(buf);
        RAISEF(kResolveError, "gethostbyname($0) failed", parts[0]);
      }
#else
      struct hostent* h = gethostbyname(hstr);

      if (h == nullptr) {
        RAISEF(kResolveError, "gethostbyname($0) failed", parts[0]);
      }

      hostname = h->h_name;
      ip = inet_ntoa(*((struct in_addr *) h->h_addr));
#endif
      break;
    }

    default:
      RAISEF(kResolveError, "invalid address: $0", addr_str);
  }

  return InetAddr(hostname, ip, port);
}

InetAddr::InetAddr(
    const std::string& hostname,
    const std::string& ip,
    unsigned port) :
    hostname_(hostname),
    ip_(ip),
    port_(port) {}

InetAddr::InetAddr(
    const std::string& hostname,
    unsigned port) :
    hostname_(hostname),
    port_(port) {}

{'fraction_non_alphanumeric': 0.14648537711646997, 'fraction_numerical': 0.008978963571062083, 'mean_word_length': 2.9583756345177665, 'pattern_counts': {'":': 2, '<': 17, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2230742', 'n_tokens_mistral': 1394, 'n_tokens_neox': 1377, 'n_words': 351}