diff --git a/src/ipaddr/extension.c b/src/ipaddr/extension.c index 56addcab..64e79f9f 100644 --- a/src/ipaddr/extension.c +++ b/src/ipaddr/extension.c @@ -3,7 +3,234 @@ // IP address manipulation in SQLite. +// #include +// #include +// #include +// #include +// #include +// #include +// #include +// #include + +// #ifdef __FreeBSD__ +// #include +// #include +// #include +// #endif + +// #include "sqlite3ext.h" +// SQLITE_EXTENSION_INIT3 + +// struct ipaddress { +// int af; +// union { +// struct in6_addr ipv6; +// struct in_addr ipv4; +// }; +// unsigned masklen; +// }; + +// static struct ipaddress* parse_ipaddress(const char* address) { +// struct ipaddress* ip = NULL; +// unsigned char buf[sizeof(struct in6_addr)]; +// char* sep = strchr(address, '/'); +// unsigned long masklen = 0; +// if (sep) { +// char* end; +// errno = 0; +// masklen = strtoul(sep + 1, &end, 10); +// if (errno != 0 || sep + 1 == end || *end != '\0') +// return NULL; +// *sep = '\0'; +// } +// if (inet_pton(AF_INET, address, buf)) { +// if (sep && masklen > 32) +// goto end; + +// ip = sqlite3_malloc(sizeof(struct ipaddress)); +// memcpy(&ip->ipv4, buf, sizeof(struct in_addr)); +// ip->af = AF_INET; +// ip->masklen = sep ? masklen : 32; +// } else if (inet_pton(AF_INET6, address, buf)) { +// if (sep && masklen > 128) +// goto end; + +// ip = sqlite3_malloc(sizeof(struct ipaddress)); +// memcpy(&ip->ipv6, buf, sizeof(struct in6_addr)); +// ip->af = AF_INET6; +// ip->masklen = sep ? masklen : 128; +// } +// end: +// if (sep) +// *sep = '/'; +// return ip; +// } + +// static void ipaddr_ipfamily(sqlite3_context* context, int argc, sqlite3_value** argv) { +// assert(argc == 1); +// if (sqlite3_value_type(argv[0]) == SQLITE_NULL) { +// sqlite3_result_null(context); +// return; +// } +// const char* address = (char*)sqlite3_value_text(argv[0]); +// struct ipaddress* ip = parse_ipaddress(address); +// if (ip == NULL) { +// sqlite3_result_null(context); +// return; +// } +// sqlite3_result_int(context, ip->af == AF_INET ? 4 : 6); +// sqlite3_free(ip); +// } + +// static void ipaddr_iphost(sqlite3_context* context, int argc, sqlite3_value** argv) { +// assert(argc == 1); +// if (sqlite3_value_type(argv[0]) == SQLITE_NULL) { +// sqlite3_result_null(context); +// return; +// } +// const char* address = (char*)sqlite3_value_text(argv[0]); +// struct ipaddress* ip = parse_ipaddress(address); +// if (ip == NULL) { +// sqlite3_result_null(context); +// return; +// } +// if (ip->af == AF_INET) { +// char* result = sqlite3_malloc(INET_ADDRSTRLEN); +// inet_ntop(AF_INET, &ip->ipv4, result, INET_ADDRSTRLEN); +// sqlite3_result_text(context, result, -1, sqlite3_free); +// } else if (ip->af == AF_INET6) { +// char* result = sqlite3_malloc(INET6_ADDRSTRLEN); +// inet_ntop(AF_INET6, &ip->ipv6, result, INET6_ADDRSTRLEN); +// sqlite3_result_text(context, result, -1, sqlite3_free); +// } +// sqlite3_free(ip); +// } + +// static void ipaddr_ipmasklen(sqlite3_context* context, int argc, sqlite3_value** argv) { +// assert(argc == 1); +// if (sqlite3_value_type(argv[0]) == SQLITE_NULL) { +// sqlite3_result_null(context); +// return; +// } +// const char* address = (char*)sqlite3_value_text(argv[0]); +// struct ipaddress* ip = parse_ipaddress(address); +// if (ip == NULL) { +// sqlite3_result_null(context); +// return; +// } +// sqlite3_result_int(context, ip->masklen); +// return; +// } + +// static void ipaddr_ipnetwork(sqlite3_context* context, int argc, sqlite3_value** argv) { +// assert(argc == 1); +// if (sqlite3_value_type(argv[0]) == SQLITE_NULL) { +// sqlite3_result_null(context); +// return; +// } +// const char* address = (char*)sqlite3_value_text(argv[0]); +// struct ipaddress* ip = parse_ipaddress(address); +// if (ip == NULL) { +// sqlite3_result_null(context); +// return; +// } +// if (ip->af == AF_INET) { +// char buf[INET_ADDRSTRLEN]; +// ip->ipv4.s_addr = +// htonl(ntohl(ip->ipv4.s_addr) & ~(uint32_t)((1ULL << (32 - ip->masklen)) - 1)); +// inet_ntop(AF_INET, &ip->ipv4, buf, INET_ADDRSTRLEN); +// char* result = sqlite3_malloc(INET_ADDRSTRLEN + 3); +// sprintf(result, "%s/%u", buf, ip->masklen); +// sqlite3_result_text(context, result, -1, sqlite3_free); +// } else if (ip->af == AF_INET6) { +// char buf[INET6_ADDRSTRLEN]; +// for (unsigned i = 0; i < 16; i++) { +// if (ip->masklen / 8 < i) +// ip->ipv6.s6_addr[i] = 0; +// else if (ip->masklen / 8 == i) +// ip->ipv6.s6_addr[i] &= ~(ip->masklen % 8); +// } +// inet_ntop(AF_INET6, &ip->ipv6, buf, INET6_ADDRSTRLEN); +// char* result = sqlite3_malloc(INET6_ADDRSTRLEN + 4); +// sprintf(result, "%s/%u", buf, ip->masklen); +// sqlite3_result_text(context, result, -1, sqlite3_free); +// } +// sqlite3_free(ip); +// } + +// static void ipaddr_ipcontains(sqlite3_context* context, int argc, sqlite3_value** argv) { +// assert(argc == 2); +// if (sqlite3_value_type(argv[0]) == SQLITE_NULL || sqlite3_value_type(argv[1]) == SQLITE_NULL) { +// sqlite3_result_null(context); +// return; +// } + +// const char* address1 = (char*)sqlite3_value_text(argv[0]); +// struct ipaddress* ip1 = parse_ipaddress(address1); +// const char* address2 = (char*)sqlite3_value_text(argv[1]); +// struct ipaddress* ip2 = parse_ipaddress(address2); +// if (ip1 == NULL || ip2 == NULL) { +// sqlite3_result_null(context); +// goto end; +// } +// if (ip1->af != ip2->af || ip1->masklen > ip2->masklen) { +// sqlite3_result_int(context, 0); +// goto end; +// } + +// if (ip1->af == AF_INET) { +// ip1->ipv4.s_addr = +// htonl(ntohl(ip1->ipv4.s_addr) & ~(uint32_t)((1ULL << (32 - ip1->masklen)) - 1)); +// ip2->ipv4.s_addr = +// htonl(ntohl(ip2->ipv4.s_addr) & ~(uint32_t)((1ULL << (32 - ip1->masklen)) - 1)); +// sqlite3_result_int(context, ip1->ipv4.s_addr == ip2->ipv4.s_addr); +// goto end; +// } +// if (ip1->af == AF_INET6) { +// for (unsigned i = 0; i < 16; i++) { +// if (ip1->masklen / 8 < i) { +// ip1->ipv6.s6_addr[i] = 0; +// ip2->ipv6.s6_addr[i] = 0; +// } else if (ip1->masklen / 8 == i) { +// ip1->ipv6.s6_addr[i] &= ~(ip1->masklen % 8); +// ip2->ipv6.s6_addr[i] &= ~(ip1->masklen % 8); +// } +// if (ip1->ipv6.s6_addr[i] != ip2->ipv6.s6_addr[i]) { +// sqlite3_result_int(context, 0); +// goto end; +// } +// } +// sqlite3_result_int(context, 1); +// } +// end: +// sqlite3_free(ip1); +// sqlite3_free(ip2); +// } + +// int ipaddr_init(sqlite3* db) { +// static const int flags = SQLITE_UTF8 | SQLITE_INNOCUOUS | SQLITE_DETERMINISTIC; +// sqlite3_create_function(db, "ipfamily", 1, flags, 0, ipaddr_ipfamily, 0, 0); +// sqlite3_create_function(db, "iphost", 1, flags, 0, ipaddr_iphost, 0, 0); +// sqlite3_create_function(db, "ipmasklen", 1, flags, 0, ipaddr_ipmasklen, 0, 0); +// sqlite3_create_function(db, "ipnetwork", 1, flags, 0, ipaddr_ipnetwork, 0, 0); +// sqlite3_create_function(db, "ipcontains", 2, flags, 0, ipaddr_ipcontains, 0, 0); +// return SQLITE_OK; +// } + + +// Copyright (c) 2021 Vincent Bernat, MIT License +// https://github.com/nalgeon/sqlean + +// IP address manipulation in SQLite. + +#ifdef _WIN32 +#include +#include +#pragma comment(lib, "ws2_32.lib") +#else #include +#endif + #include #include #include @@ -30,6 +257,25 @@ struct ipaddress { unsigned masklen; }; +#ifdef _WIN32 +// Replacement for inet_ntop on Windows +const char* my_inet_ntop(int af, const void* src, char* dst, size_t size) { + if (af == AF_INET) { + struct sockaddr_in sa; + sa.sin_family = AF_INET; + memcpy(&sa.sin_addr, src, sizeof(struct in_addr)); + return InetNtopA(af, &sa.sin_addr, dst, size); + } else if (af == AF_INET6) { + struct sockaddr_in6 sa6; + sa6.sin6_family = AF_INET6; + memcpy(&sa6.sin6_addr, src, sizeof(struct in6_addr)); + return InetNtopA(af, &sa6.sin6_addr, dst, size); + } + return NULL; +} +#define inet_ntop my_inet_ntop +#endif + static struct ipaddress* parse_ipaddress(const char* address) { struct ipaddress* ip = NULL; unsigned char buf[sizeof(struct in6_addr)]; @@ -39,21 +285,18 @@ static struct ipaddress* parse_ipaddress(const char* address) { char* end; errno = 0; masklen = strtoul(sep + 1, &end, 10); - if (errno != 0 || sep + 1 == end || *end != '\0') - return NULL; + if (errno != 0 || sep + 1 == end || *end != '\0') return NULL; *sep = '\0'; } if (inet_pton(AF_INET, address, buf)) { - if (sep && masklen > 32) - goto end; + if (sep && masklen > 32) goto end; ip = sqlite3_malloc(sizeof(struct ipaddress)); memcpy(&ip->ipv4, buf, sizeof(struct in_addr)); ip->af = AF_INET; ip->masklen = sep ? masklen : 32; } else if (inet_pton(AF_INET6, address, buf)) { - if (sep && masklen > 128) - goto end; + if (sep && masklen > 128) goto end; ip = sqlite3_malloc(sizeof(struct ipaddress)); memcpy(&ip->ipv6, buf, sizeof(struct in6_addr)); @@ -61,8 +304,7 @@ static struct ipaddress* parse_ipaddress(const char* address) { ip->masklen = sep ? masklen : 128; } end: - if (sep) - *sep = '/'; + if (sep) *sep = '/'; return ip; } @@ -119,7 +361,7 @@ static void ipaddr_ipmasklen(sqlite3_context* context, int argc, sqlite3_value** return; } sqlite3_result_int(context, ip->masklen); - return; + sqlite3_free(ip); } static void ipaddr_ipnetwork(sqlite3_context* context, int argc, sqlite3_value** argv) { diff --git a/src/test_windirent.h b/src/test_windirent.h new file mode 100644 index 00000000..7a844804 --- /dev/null +++ b/src/test_windirent.h @@ -0,0 +1,159 @@ +/* +** 2015 November 30 +** +** The author disclaims copyright to this source code. In place of +** a legal notice, here is a blessing: +** +** May you do good and not evil. +** May you find forgiveness for yourself and forgive others. +** May you share freely, never taking more than you give. +** +************************************************************************* +** This file contains declarations for most of the opendir() family of +** POSIX functions on Win32 using the MSVCRT. +*/ + +#if defined(_WIN32) && defined(_MSC_VER) && !defined(SQLITE_WINDIRENT_H) +#define SQLITE_WINDIRENT_H + +/* +** We need several data types from the Windows SDK header. +*/ + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif + +#include "windows.h" + +/* +** We need several support functions from the SQLite core. +*/ + +#include "sqlite3.h" + +/* +** We need several things from the ANSI and MSVCRT headers. +*/ + +#include +#include +#include +#include +#include +#include +#include + +/* +** We may need several defines that should have been in "sys/stat.h". +*/ + +#ifndef S_ISREG +#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG) +#endif + +#ifndef S_ISDIR +#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR) +#endif + +#ifndef S_ISLNK +#define S_ISLNK(mode) (0) +#endif + +/* +** We may need to provide the "mode_t" type. +*/ + +#ifndef MODE_T_DEFINED + #define MODE_T_DEFINED + typedef unsigned short mode_t; +#endif + +/* +** We may need to provide the "ino_t" type. +*/ + +#ifndef INO_T_DEFINED + #define INO_T_DEFINED + typedef unsigned short ino_t; +#endif + +/* +** We need to define "NAME_MAX" if it was not present in "limits.h". +*/ + +#ifndef NAME_MAX +# ifdef FILENAME_MAX +# define NAME_MAX (FILENAME_MAX) +# else +# define NAME_MAX (260) +# endif +#endif + +/* +** We need to define "NULL_INTPTR_T" and "BAD_INTPTR_T". +*/ + +#ifndef NULL_INTPTR_T +# define NULL_INTPTR_T ((intptr_t)(0)) +#endif + +#ifndef BAD_INTPTR_T +# define BAD_INTPTR_T ((intptr_t)(-1)) +#endif + +/* +** We need to provide the necessary structures and related types. +*/ + +#ifndef DIRENT_DEFINED +#define DIRENT_DEFINED +typedef struct DIRENT DIRENT; +typedef DIRENT *LPDIRENT; +struct DIRENT { + ino_t d_ino; /* Sequence number, do not use. */ + unsigned d_attributes; /* Win32 file attributes. */ + char d_name[NAME_MAX + 1]; /* Name within the directory. */ +}; +#endif + +#ifndef DIR_DEFINED +#define DIR_DEFINED +typedef struct DIR DIR; +typedef DIR *LPDIR; +struct DIR { + intptr_t d_handle; /* Value returned by "_findfirst". */ + DIRENT d_first; /* DIRENT constructed based on "_findfirst". */ + DIRENT d_next; /* DIRENT constructed based on "_findnext". */ +}; +#endif + +/* +** Provide a macro, for use by the implementation, to determine if a +** particular directory entry should be skipped over when searching for +** the next directory entry that should be returned by the readdir() or +** readdir_r() functions. +*/ + +#ifndef is_filtered +# define is_filtered(a) ((((a).attrib)&_A_HIDDEN) || (((a).attrib)&_A_SYSTEM)) +#endif + +/* +** Provide the function prototype for the POSIX compatible getenv() +** function. This function is not thread-safe. +*/ + +extern const char *windirent_getenv(const char *name); + +/* +** Finally, we can provide the function prototypes for the opendir(), +** readdir(), readdir_r(), and closedir() POSIX functions. +*/ + +extern LPDIR opendir(const char *dirname); +extern LPDIRENT readdir(LPDIR dirp); +extern INT readdir_r(LPDIR dirp, LPDIRENT entry, LPDIRENT *result); +extern INT closedir(LPDIR dirp); + +#endif /* defined(WIN32) && defined(_MSC_VER) */ \ No newline at end of file diff --git a/src/time/duration.c b/src/time/duration.c index 802d418f..d143fd78 100644 --- a/src/time/duration.c +++ b/src/time/duration.c @@ -13,11 +13,12 @@ // Common durations. const Duration Nanosecond = 1; -const Duration Microsecond = 1000 * Nanosecond; -const Duration Millisecond = 1000 * Microsecond; -const Duration Second = 1000 * Millisecond; -const Duration Minute = 60 * Second; -const Duration Hour = 60 * Minute; +// i had to edit them manually due to msvc complaints +const Duration Microsecond = 1000 * 1; +const Duration Millisecond = 1000 * 1000 * 1; +const Duration Second = 1000 * 1000 * 1000 * 1; +const Duration Minute = 60 * 1000 * 1000 * 1000 * 1; +const Duration Hour = 60 * 60 * 1000 * 1000 * 1000 * 1; #pragma region Conversion diff --git a/src/time/duration.h b/src/time/duration.h new file mode 100644 index 00000000..168e579e --- /dev/null +++ b/src/time/duration.h @@ -0,0 +1,17 @@ +#ifndef DURATION_H +#define DURATION_H + +#include + +// Define Duration type +typedef int64_t Duration; + +// Declare access functions for constants +Duration get_nanosecond(); +Duration get_microsecond(); +Duration get_millisecond(); +Duration get_second(); +Duration get_minute(); +Duration get_hour(); + +#endif // DURATION_H diff --git a/src/time/time.c b/src/time/time.c index 4dce4b28..76b35f90 100644 --- a/src/time/time.c +++ b/src/time/time.c @@ -15,13 +15,13 @@ #pragma region Private -static const int64_t seconds_per_minute = 60; -static const int64_t seconds_per_hour = 60 * seconds_per_minute; -static const int64_t seconds_per_day = 24 * seconds_per_hour; -static const int64_t seconds_per_week = 7 * seconds_per_day; -static const int64_t days_per_400_years = 365 * 400 + 97; -static const int64_t days_per_100_years = 365 * 100 + 24; -static const int64_t days_per_4_years = 365 * 4 + 1; +#define seconds_per_minute 60 +#define seconds_per_hour (60 * seconds_per_minute) +#define seconds_per_day (24 * seconds_per_hour) +#define seconds_per_week (7 * seconds_per_day) +#define days_per_400_years (365 * 400 + 97) +#define days_per_100_years (365 * 100 + 24) +#define days_per_4_years (365 * 4 + 1) // The unsigned zero year for internal calculations. // Must be 1 mod 400, and times before it will not compute correctly, @@ -30,12 +30,11 @@ static const int64_t absolute_zero_year = -292277022399LL; // Offsets to convert between internal and absolute or Unix times. // = (absoluteZeroYear - internalYear) * 365.2425 * secondsPerDay -static const int64_t absolute_to_internal = -9223371966579724800LL; -static const int64_t internal_to_absolute = -absolute_to_internal; +#define absolute_to_internal (-9223371966579724800LL) +#define internal_to_absolute (-absolute_to_internal) -static const int64_t unix_to_internal = - (1969 * 365 + 1969 / 4 - 1969 / 100 + 1969 / 400) * seconds_per_day; -static const int64_t internal_to_unix = -unix_to_internal; +#define unix_to_internal ((int64_t)((1969LL * 365 + 1969LL / 4 - 1969LL / 100 + 1969LL / 400) * seconds_per_day)) +#define internal_to_unix (-unix_to_internal) // days_before[m] counts the number of days in a non-leap year // before month m begins. There is an entry for m=12, counting