/* Copyright (C) 2006-2010 David Sugar, Tycho Softworks.
 *
 * This file is part of libcpr.
 *
 * libcpr is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published
 * by the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * libcpr is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with libcpr.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef _CPR_H_
#define _CPR_H_

#if defined(__GNUC__) && (__GNUC < 3) && !defined(_GNU_SOURCE)
#define _GNU_SOURCE
#endif

#if __GNUC__ > 3 || (__GNUC__ == 3 && (__GNU_MINOR__ > 3))
#define __PRINTF(x,y)   __attribute__ ((format (printf, x, y)))
#define __SCANF(x, y) __attribute__ ((format (scanf, x, y)))
#define __MALLOC      __attribute__ ((malloc))
#endif

#ifndef __MALLOC
#define __PRINTF(x, y)
#define __SCANF(x, y)
#define __MALLOC
#endif

#ifndef DEBUG
#ifndef NDEBUG
#define NDEBUG
#endif
#endif

#ifdef  DEBUG
#ifdef  NDEBUG
#undef  NDEBUG
#endif
#endif

#if defined(_MSC_VER) || defined(WIN32) || defined(_WIN32)
#define _MSWINDOWS_

#if defined(_M_X64) || defined(_M_ARM)
#define _MSCONDITIONALS_
#ifndef _WIN32_WINNT
#define _WIN32_WINNT    0x0600
#endif
#endif

#ifdef  _MSC_VER
#pragma warning(disable: 4251)
#pragma warning(disable: 4996)
#pragma warning(disable: 4355)
#pragma warning(disable: 4290)
#pragma warning(disable: 4291)
#endif

#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0501
#endif

#ifndef WINVER
#define WINVER _WIN32_WINNT
#endif

#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif

#include <winsock2.h>
#include <ws2tcpip.h>

#if defined(_MSC_VER)
typedef signed long ssize_t;
typedef int pid_t;
#endif

#include <process.h>
#ifndef __EXPORT
#ifdef  CPR_STATIC
#define __EXPORT
#else
#define __EXPORT    __declspec(dllimport)
#endif
#endif

#define _UWIN

#include <sys/stat.h>
#include <io.h>

typedef char *caddr_t;
typedef HANDLE fd_t;
typedef SOCKET socket_t;

#ifdef  _MSC_VER
typedef struct timespec {
    time_t tv_sec;
    long  tv_nsec;
} timespec_t;
#endif

#else

#ifndef __EXPORT
#define __EXPORT
#endif

typedef int socket_t;
typedef int fd_t;
#define INVALID_SOCKET -1
#define INVALID_HANDLE_VALUE -1
#include <signal.h>

#endif

#ifdef _MSC_VER
typedef signed __int8 int8_t;
typedef unsigned __int8 uint8_t;
typedef signed __int16 int16_t;
typedef unsigned __int16 uint16_t;
typedef signed __int32 int32_t;
typedef unsigned __int32 uint32_t;
typedef signed __int64 int64_t;
typedef unsigned __int64 uint64_t;
typedef char *caddr_t;

#include <stdio.h>
#define snprintf _snprintf
#define vsnprintf _vsnprintf

#else

#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <stdint.h>
#include <unistd.h>
#include <stdio.h>

#endif

#ifndef _GNU_SOURCE
typedef void (*sighandler_t)(int);  /**< Convenient typedef for signal handlers. */
#endif
typedef unsigned long timeout_t;    /**< Typedef for millisecond timer values. */

#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include <ctype.h>
#include <time.h>
#include <limits.h>
#include <errno.h>

#ifdef  _MSWINDOWS_
#ifndef ENETDOWN
#define ENETDOWN        ((int)(WSAENETDOWN))
#endif
#ifndef EINPROGRESS
#define EINPROGRESS     ((int)(WSAEINPROGRESS))
#endif
#ifndef ENOPROTOOPT
#define ENOPROTOOPT     ((int)(WSAENOPROTOOPT))
#endif
#ifndef EADDRINUSE
#define EADDRINUSE      ((int)(WSAEADDRINUSE))
#endif
#ifndef EADDRNOTAVAIL
#define EADDRNOTAVAIL   ((int)(WSAEADDRNOTAVAIL))
#endif
#ifndef ENETUNREACH
#define ENETUNREACH     ((int)(WSAENETUNREACH))
#endif
#ifndef EHOSTUNREACH
#define EHOSTUNREACH    ((int)(WSAEHOSTUNREACH))
#endif
#ifndef EHOSTDOWN
#define EHOSTDOWN       ((int)(WSAEHOSTDOWN))
#endif
#ifndef ENETRESET
#define ENETRESET       ((int)(WSAENETRESET))
#endif
#ifndef ECONNABORTED
#define ECONNABORTED    ((int)(WSAECONNABORTED))
#endif
#ifndef ECONNRESET
#define ECONNRESET      ((int)(WSAECONNRESET))
#endif
#ifndef EISCONN
#define EISCONN         ((int)(WSAEISCONN))
#endif
#ifndef ENOTCONN
#define ENOTCONN        ((int)(WSAENOTCONN))
#endif
#ifndef ESHUTDOWN
#define ESHUTDOWN       ((int)(WSAESHUTDOWN))
#endif
#ifndef ETIMEDOUT
#define ETIMEDOUT       ((int)(WSAETIMEDOUT))
#endif
#ifndef ECONNREFUSED
#define ECONNREFUSED    ((int)(WSAECONNREFUSED))
#endif
#endif

#ifndef DEBUG
#ifndef NDEBUG
#define NDEBUG
#endif
#endif

#ifdef  DEBUG
#ifdef  NDEBUG
#undef  NDEBUG
#endif
#endif

#include <assert.h>
#ifdef  DEBUG
#define crit(x, text)   assert(x)
#else
#define crit(x, text) if(!(x)) cpr_runtime_error(text)
#endif

#define A_RANDOM    0x01
#define A_STREAM    0x02
#define A_NONE      0x00

#ifdef __cplusplus
extern "C" {
#endif

__EXPORT void *cpr_newp(void **handle, size_t size);
__EXPORT void cpr_freep(void **handle);

__EXPORT int cpr_collate(const char *str1, const char *str2);
__EXPORT size_t cpr_strlen(const char *str);
__EXPORT bool cpr_strcheck(const char *str, size_t min, size_t max);
__EXPORT int cpr_strcmp(const char *str1, const char *str2);
__EXPORT int cpr_strncmp(const char *str1, const char *str2, size_t len);
__EXPORT int cpr_stricmp(const char *str1, const char *str2);
__EXPORT int cpr_strnicmp(const char *str1, const char *str2, size_t len);
__EXPORT size_t cpr_strset(char *buffer, size_t size, const char *str);
__EXPORT size_t cpr_stradd(char *buffer, size_t size, const char *str);
__EXPORT char *cpr_strdup(const char *src);
__EXPORT char *cpr_strlwr(char *src);
__EXPORT char *crp_strupr(char *src);
__EXPORT void cpr_erase(char *src);
__EXPORT char *cpr_token(char *text, char **token, const char *clist, const char *quote, const char *eol);
__EXPORT char *cpr_unquote(char *str, const char *clist);

__EXPORT int cpr_errno(void);
__EXPORT fd_t cpr_nullfile(void);
__EXPORT int cpr_inherit(fd_t *file, bool enable);
__EXPORT int cpr_pipe(fd_t files[2], size_t bufsize);

__EXPORT int cpr_timeofday(struct timeval *tv);
__EXPORT int cpr_timeout(struct timespec *ts, timeout_t timeout);

__EXPORT bool cpr_isdir(const char *path);
__EXPORT bool cpr_isfile(const char *path);
__EXPORT bool cpr_islink(const char *path);

#ifdef __cplusplus
}
#endif

#endif
