SDL_net: Added SDLNet_CompareAddresses.

From b359745169616b7f4132cac397e723f70fb64ab3 Mon Sep 17 00:00:00 2001
From: "Ryan C. Gordon" <[EMAIL REDACTED]>
Date: Sun, 13 Aug 2023 19:07:56 -0400
Subject: [PATCH] Added SDLNet_CompareAddresses.

This is generally useful for "are these two addresses the same thing?"
but also suitable for using as a compare callback for SDL_qsort.
---
 SDL_net.c | 34 ++++++++++++++++++++++++++++++++++
 SDL_net.h |  2 +-
 2 files changed, 35 insertions(+), 1 deletion(-)

diff --git a/SDL_net.c b/SDL_net.c
index afbc962..17542e3 100644
--- a/SDL_net.c
+++ b/SDL_net.c
@@ -373,6 +373,40 @@ const char *SDLNet_GetAddressString(SDLNet_Address *addr)
     return addr ? (const char *) SDL_AtomicGetPtr((void **) &addr->human_readable) : NULL;
 }
 
+int SDLNet_CompareAddresses(const SDLNet_Address *sdlneta, const SDLNet_Address *sdlnetb)
+{
+    const struct addrinfo *a;
+    const struct addrinfo *b;
+
+    if (sdlneta == sdlnetb) {  // same pointer?
+        return 0;
+    } else if (sdlneta && !sdlnetb) {
+        return -1;
+    } else if (!sdlneta && sdlnetb) {
+        return 1;
+    }
+
+    a = sdlneta->ainfo;
+    b = sdlnetb->ainfo;
+    if (a == b) {  // same pointer?
+        return 0;
+    } else if (a && !b) {
+        return -1;
+    } else if (!a && b) {
+        return 1;
+    } else if (a->ai_family < b->ai_family) {
+        return -1;
+    } else if (a->ai_family > b->ai_family) {
+        return 1;
+    } else if (a->ai_addrlen < b->ai_addrlen) {
+        return -1;
+    } else if (a->ai_addrlen > b->ai_addrlen) {
+        return 1;
+    }
+
+    return SDL_memcmp(a->ai_addr, b->ai_addr, a->ai_addrlen);
+}
+
 SDLNet_Address *SDLNet_RefAddress(SDLNet_Address *addr)
 {
     if (addr) {
diff --git a/SDL_net.h b/SDL_net.h
index b803b26..2cf34d1 100644
--- a/SDL_net.h
+++ b/SDL_net.h
@@ -32,7 +32,7 @@ extern DECLSPEC const char * SDLCALL SDLNet_GetAddressString(SDLNet_Address *add
 extern DECLSPEC SDLNet_Address *SDLCALL SDLNet_RefAddress(SDLNet_Address *address);  /* +1 refcount; SDLNet_ResolveHost starts at 1. Returns `address` for convenience. */
 extern DECLSPEC void SDLCALL SDLNet_UnrefAddress(SDLNet_Address *address);  /* when totally unref'd, gets freed. */
 extern DECLSPEC void SDLCALL SDLNet_SimulateAddressResolutionLoss(int percent_loss);  /* make resolutions delay at random, fail some percent of them. */
-
+extern DECLSPEC int SDLCALL SDLNet_CompareAddresses(const SDLNet_Address *a, const SDLNet_Address *b);  /* can be used with SDL_qsort. */
 extern DECLSPEC SDLNet_Address **SDLCALL SDLNet_GetLocalAddresses(int *num_addresses);  /* returns NULL-terminated array of SDLNet_Address*, of all known interfaces. */
 extern DECLSPEC void SDLCALL SDLNet_FreeLocalAddresses(SDLNet_Address **addresses);  /* unrefs each address, frees array. */