diff --git a/src/basic.cpp b/src/basic.cpp index 75cd31d..63713d4 100644 --- a/src/basic.cpp +++ b/src/basic.cpp @@ -1,4 +1,8 @@ -#define panicf(...) (fprintf(stderr, __VA_ARGS__), fprintf(stderr, "\n"), exit(1)) +#define lengthof(x) (sizeof((x)) / sizeof((x)[0])) + +#define panicf(...) (fprintf(stderr, "%s:%d: ", __FILE__, __LINE__), fprintf(stderr, __VA_ARGS__), fprintf(stderr, "\n"), exit(1)) +#define debugf(...) (printf("%s:%d: ", __FILE__, __LINE__), printf(__VA_ARGS__), printf("\n")) +#define assert(x) ((!(x)) && (panicf("%s:%d: assertion failed " #x, __FILE__, __LINE__), 0)) template struct DEFER_ExitScope { @@ -20,3 +24,48 @@ class DEFER_ExitScopeHelp { #define DEFER_CONCAT_INTERNAL(x, y) x##y #define DEFER_CONCAT(x, y) DEFER_CONCAT_INTERNAL(x, y) #define defer const auto DEFER_CONCAT(defer__, __LINE__) = DEFER_ExitScopeHelp() + [&]() + +char* strf(const char* format, ...) { // @leak + va_list args; + va_start(args, format); + va_list args_copy; + va_copy(args_copy, args); + int size = vsnprintf(NULL, 0, format, args_copy) + 1; + va_end(args_copy); + char* buffer = (char *)malloc(size); + assert(buffer); + vsnprintf(buffer, size, format, args); + va_end(args); + return buffer; +} + +template +struct Slice { + T *data; + int len; +}; + +#define PLEN(x) {(x), lengthof(x)} + +struct EnumValue { + int value; + const char *name; +}; + +#define ENUM_VALUE(x) {x, #x} +const char *serialize(Slice table, int value) { + for (int i = 0; i < table.len; i += 1) { + EnumValue *it = table.data + i; + if (it->value == value) return it->name; + } + return ""; +} + +char *serialize_flags(Slice table, int n) { // @leak + char *result = strf("%d", n); + for (int i = 0; i < table.len; i += 1) { + auto *it = table.data + i; + if (n & it->value) result = strf("%s %s", result, it->name); + } + return result; +} \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp index 668f710..446c8fb 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -12,31 +12,7 @@ #include #include #pragma comment(lib, "ws2_32") - -#define panicf(...) (fprintf(stderr, "%s:%d: ", __FILE__, __LINE__), fprintf(stderr, __VA_ARGS__), fprintf(stderr, "\n"), exit(1)) -#define debugf(...) (printf("%s:%d: ", __FILE__, __LINE__), printf(__VA_ARGS__), printf("\n")) -#define assert(x) ((!(x)) && (panicf("%s:%d: assertion failed " #x, __FILE__, __LINE__), 0)) - -template -struct DEFER_ExitScope { - T lambda; - DEFER_ExitScope(T lambda) : lambda(lambda) {} - ~DEFER_ExitScope() { lambda(); } - DEFER_ExitScope(const DEFER_ExitScope &i) : lambda(i.lambda){}; - - private: - DEFER_ExitScope &operator=(const DEFER_ExitScope &); -}; - -class DEFER_ExitScopeHelp { - public: - template - DEFER_ExitScope operator+(T t) { return t; } -}; - -#define DEFER_CONCAT_INTERNAL(x, y) x##y -#define DEFER_CONCAT(x, y) DEFER_CONCAT_INTERNAL(x, y) -#define defer const auto DEFER_CONCAT(defer__, __LINE__) = DEFER_ExitScopeHelp() + [&]() +#include "basic.cpp" char *serialize_error_code(DWORD errorCode) { char* message = NULL; @@ -58,98 +34,49 @@ char *serialize_error_code(DWORD errorCode) { if (newline) *newline = '\0'; } - return message; // Remember to LocalFree() this later! + return message; // @leak - LocalFree } -char* strf(const char* format, ...) { - va_list args; - va_start(args, format); - va_list args_copy; - va_copy(args_copy, args); - int size = vsnprintf(NULL, 0, format, args_copy) + 1; - va_end(args_copy); - char* buffer = (char *)malloc(size); - assert(buffer); - vsnprintf(buffer, size, format, args); - va_end(args); - return buffer; -} - -#define lengthof(x) (sizeof((x)) / sizeof((x)[0])) - -struct EnumValue { - int value; - const char *name; -}; -#define ENUM_VALUE(x) {x, #x} -const char *serialize(EnumValue *table, int table_size, int value) { - for (int i = 0; i < table_size; i += 1) { - EnumValue *it = table + i; - if (it->value == value) return it->name; - } - return ""; -} - -EnumValue ai_flag_table[] = { +EnumValue _ai_flags_table[] = { ENUM_VALUE(AI_PASSIVE), ENUM_VALUE(AI_CANONNAME), ENUM_VALUE(AI_NUMERICHOST), }; +Slice ai_flags_table = PLEN(_ai_flags_table); -char *serialize_ai_flags(int n) { - char *result = strf("%d", n); - for (int i = 0; i < lengthof(ai_flag_table); i += 1) { - auto *it = ai_flag_table + i; - if (n & it->value) result = strf("%s %s", result, it->name); - } - return result; -} - -struct { - const char *name; - int value; - const char *desc; -} ai_family_table[] = { - {"AF_UNSPEC", 0, "The address family is unspecified"}, - {"AF_INET", 2, "The Internet Protocol version 4 (IPv4) address family."}, - {"AF_NETBIOS", 17, "The NetBIOS address family. This address family is only supported if a Windows Sockets provider for NetBIOS is installed."}, - {"AF_INET6", 23, "The Internet Protocol version 6 (IPv6) address family."}, - {"AF_IRDA", 26, "The Infrared Data Association (IrDA) address family. This address family is only supported if the computer has an infrared port and driver installed."}, - {"AF_BTH", 32, "The Bluetooth address family. This address family is only supported if a Bluetooth adapter is installed on Windows Server 2003 or later."}, +EnumValue _ai_family_table[] = { + {0, "AF_UNSPEC"}, + {2, "AF_INET"}, + {17, "AF_NETBIOS"}, + {23, "AF_INET6"}, + {26, "AF_IRDA"}, + {32, "AF_BTH"}, }; +Slice ai_family_table = PLEN(_ai_family_table); -const char *serialize_ai_family(int n) { - for (int i = 0; i < lengthof(ai_family_table); i += 1) { - auto *it = ai_family_table + i; - if (it->value == n) { - return it->name; - } - } - return ""; -} - - -EnumValue ai_socktype_table[] = { +EnumValue _ai_socktype_table[] = { ENUM_VALUE(SOCK_STREAM), ENUM_VALUE(SOCK_DGRAM), ENUM_VALUE(SOCK_RAW), ENUM_VALUE(SOCK_RDM), ENUM_VALUE(SOCK_SEQPACKET), }; +Slice ai_socktype_table = PLEN(_ai_socktype_table); -EnumValue ai_protocol_table[] = { +EnumValue _ai_protocol_table[] = { ENUM_VALUE(IPPROTO_TCP), ENUM_VALUE(IPPROTO_UDP), ENUM_VALUE(IPPROTO_PGM), }; +Slice ai_protocol_table = PLEN(_ai_protocol_table); void serialize_addrinfo(struct addrinfo* in) { for (struct addrinfo* p = in; p != NULL; p = p->ai_next) { printf("addrinfo %p {\n", p); - printf(" ai_flags = %s(%d)\n", serialize_ai_flags(p->ai_flags), p->ai_flags); - printf(" ai_family = %s(%d)\n", serialize_ai_family(p->ai_family), p->ai_family); - printf(" ai_socktype = %s(%d)\n", serialize(ai_socktype_table, lengthof(ai_socktype_table), p->ai_socktype), p->ai_socktype); - printf(" ai_protocol = %s(%d)\n", serialize(ai_protocol_table, lengthof(ai_protocol_table), p->ai_protocol), p->ai_protocol); + printf(" ai_flags = %s(%d)\n", serialize_flags(ai_flags_table, p->ai_flags), p->ai_flags); + printf(" ai_family = %s(%d)\n", serialize(ai_family_table, p->ai_family), p->ai_family); + printf(" ai_socktype = %s(%d)\n", serialize(ai_socktype_table, p->ai_socktype), p->ai_socktype); + printf(" ai_protocol = %s(%d)\n", serialize(ai_protocol_table, p->ai_protocol), p->ai_protocol); printf(" ai_addrlen = %zu\n", p->ai_addrlen); printf(" ai_canonname = \"%s\"\n", p->ai_canonname ? p->ai_canonname : "");