text: /*
   * twemproxy - A fast and lightweight proxy for memcached protocol.
   * Copyright (C) 2011 Twitter, Inc.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   * http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  
  #ifndef _NC_UTIL_H_
  #define _NC_UTIL_H_
  
  #include <stdarg.h>
  
  #define LF                  (uint8_t) 10
  #define CR                  (uint8_t) 13
  #define CRLF                "\x0d\x0a"
  #define CRLF_LEN            (sizeof("\x0d\x0a") - 1)
  
  #define NELEMS(a)           ((sizeof(a)) / sizeof((a)[0]))
  
  #define MIN(a, b)           ((a) < (b) ? (a) : (b))
  #define MAX(a, b)           ((a) > (b) ? (a) : (b))
  
  #define SQUARE(d)           ((d) * (d))
  #define VAR(s, s2, n)       (((n) < 2) ? 0.0 : ((s2) - SQUARE(s)/(n)) / ((n) - 1))
  #define STDDEV(s, s2, n)    (((n) < 2) ? 0.0 : sqrt(VAR((s), (s2), (n))))
  
  #define NC_INET4_ADDRSTRLEN (sizeof("255.255.255.255") - 1)
  #define NC_INET6_ADDRSTRLEN \
      (sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") - 1)
  #define NC_INET_ADDRSTRLEN  MAX(NC_INET4_ADDRSTRLEN, NC_INET6_ADDRSTRLEN)
  #define NC_UNIX_ADDRSTRLEN  \
      (sizeof(struct sockaddr_un) - offsetof(struct sockaddr_un, sun_path))
  
  #define NC_MAXHOSTNAMELEN   256
  
  /*
   * Length of 1 byte, 2 bytes, 4 bytes, 8 bytes and largest integral
   * type (uintmax_t) in ascii, including the null terminator '\0'
   *
   * From stdint.h, we have:
   * # define UINT8_MAX	(255)
   * # define UINT16_MAX	(65535)
   * # define UINT32_MAX	(4294967295U)
   * # define UINT64_MAX	(__UINT64_C(18446744073709551615))
   */
  #define NC_UINT8_MAXLEN     (3 + 1)
  #define NC_UINT16_MAXLEN    (5 + 1)
  #define NC_UINT32_MAXLEN    (10 + 1)
  #define NC_UINT64_MAXLEN    (20 + 1)
  #define NC_UINTMAX_MAXLEN   NC_UINT64_MAXLEN
  
  /*
   * Make data 'd' or pointer 'p', n-byte aligned, where n is a power of 2
   * of 2.
   */
  #define NC_ALIGNMENT        sizeof(unsigned long) /* platform word */
  #define NC_ALIGN(d, n)      (((d) + (n - 1)) & ~(n - 1))
  #define NC_ALIGN_PTR(p, n)  \
      (void *) (((uintptr_t) (p) + ((uintptr_t) n - 1)) & ~((uintptr_t) n - 1))
  
  /*
   * Wrapper to workaround well known, safe, implicit type conversion when
   * invoking system calls.
   */
  #define nc_gethostname(_name, _len) \
      gethostname((char *)_name, (size_t)_len)
  
  #define nc_atoi(_line, _n)          \
      _nc_atoi((uint8_t *)_line, (size_t)_n)
  
  int nc_set_blocking(int sd);
  int nc_set_nonblocking(int sd);
  int nc_set_reuseaddr(int sd);
  int nc_set_tcpnodelay(int sd);
  int nc_set_linger(int sd, int timeout);
  int nc_set_sndbuf(int sd, int size);
  int nc_set_rcvbuf(int sd, int size);
  int nc_set_tcpkeepalive(int sd);
  int nc_get_soerror(int sd);
  int nc_get_sndbuf(int sd);
  int nc_get_rcvbuf(int sd);
  
  int _nc_atoi(uint8_t *line, size_t n);
  bool nc_valid_port(int n);
  
  /*
   * Memory allocation and free wrappers.
   *
   * These wrappers enables us to loosely detect double free, dangling
   * pointer access and zero-byte alloc.
   */
  #define nc_alloc(_s)                    \
      _nc_alloc((size_t)(_s), __FILE__, __LINE__)
  
  #define nc_zalloc(_s)                   \
      _nc_zalloc((size_t)(_s), __FILE__, __LINE__)
  
  #define nc_calloc(_n, _s)               \
      _nc_calloc((size_t)(_n), (size_t)(_s), __FILE__, __LINE__)
  
  #define nc_realloc(_p, _s)              \
      _nc_realloc(_p, (size_t)(_s), __FILE__, __LINE__)
  
  #define nc_free(_p) do {                \
      _nc_free(_p, __FILE__, __LINE__);   \
      (_p) = NULL;                        \
  } while (0)
  
  void *_nc_alloc(size_t size, const char *name, int line);
  void *_nc_zalloc(size_t size, const char *name, int line);
  void *_nc_calloc(size_t nmemb, size_t size, const char *name, int line);
  void *_nc_realloc(void *ptr, size_t size, const char *name, int line);
  void _nc_free(void *ptr, const char *name, int line);
  
  /*
   * Wrappers to send or receive n byte message on a blocking
   * socket descriptor.
   */
  #define nc_sendn(_s, _b, _n)    \
      _nc_sendn(_s, _b, (size_t)(_n))
  
  #define nc_recvn(_s, _b, _n)    \
      _nc_recvn(_s, _b, (size_t)(_n))
  
  /*
   * Wrappers to read or write data to/from (multiple) buffers
   * to a file or socket descriptor.
   */
  #define nc_read(_d, _b, _n)     \
      read(_d, _b, (size_t)(_n))
  
  #define nc_readv(_d, _b, _n)    \
      readv(_d, _b, (int)(_n))
  
  #define nc_write(_d, _b, _n)    \
      write(_d, _b, (size_t)(_n))
  
  #define nc_writev(_d, _b, _n)   \
      writev(_d, _b, (int)(_n))
  
  ssize_t _nc_sendn(int sd, const void *vptr, size_t n);
  ssize_t _nc_recvn(int sd, void *vptr, size_t n);
  
  /*
   * Wrappers for defining custom assert based on whether macro
   * NC_ASSERT_PANIC or NC_ASSERT_LOG was defined at the moment
   * ASSERT was called.
   */
  #ifdef NC_ASSERT_PANIC
  
  #define ASSERT(_x) do {                         \
      if (!(_x)) {                                \
          nc_assert(#_x, __FILE__, __LINE__, 1);  \
      }                                           \
  } while (0)
  
  #define NOT_REACHED() ASSERT(0)
  
  #elif NC_ASSERT_LOG
  
  #define ASSERT(_x) do {                         \
      if (!(_x)) {                                \
          nc_assert(#_x, __FILE__, __LINE__, 0);  \
      }                                           \
  } while (0)
  
  #define NOT_REACHED() ASSERT(0)
  
  #else
  
  #define ASSERT(_x)
  
  #define NOT_REACHED()
  
  #endif
  
  void nc_assert(const char *cond, const char *file, int line, int panic);
  void nc_stacktrace(int skip_count);
  void nc_stacktrace_fd(int fd);
  
  int _scnprintf(char *buf, size_t size, const char *fmt, ...);
  int _vscnprintf(char *buf, size_t size, const char *fmt, va_list args);
  int64_t nc_usec_now(void);
  int64_t nc_msec_now(void);
  
  /*
   * Address resolution for internet (ipv4 and ipv6) and unix domain
   * socket address.
   */
  
  struct sockinfo {
      int       family;              /* socket address family */
      socklen_t addrlen;             /* socket address length */
      union {
          struct sockaddr_in  in;    /* ipv4 socket address */
          struct sockaddr_in6 in6;   /* ipv6 socket address */
          struct sockaddr_un  un;    /* unix domain address */
      } addr;
  };
  
  int nc_resolve(struct string *name, int port, struct sockinfo *si);
  char *nc_unresolve_addr(struct sockaddr *addr, socklen_t addrlen);
  char *nc_unresolve_peer_desc(int sd);
  char *nc_unresolve_desc(int sd);
  
  int nc_get_addr_info( struct string *name,int port ,struct sockinfo ** si , int * sockinfo_num  );
  int nc_free_addr_info(struct sockinfo ** si) ;
  void print_log_addr_info(struct sockinfo * si );
  
  #endif
  