portability fixes master
authorRalph Ronnquist <ralph.ronnquist@gmail.com>
Mon, 25 Jul 2022 04:49:07 +0000 (14:49 +1000)
committerRalph Ronnquist <ralph.ronnquist@gmail.com>
Mon, 25 Jul 2022 04:49:07 +0000 (14:49 +1000)
typing/ItemKeyFun.c

index 2b1d3725c43248ca5d3d9302ee82f5c9eff79280..6ca7ce0d3fffe5894f0d00e164a6a5c65d6e3427 100644 (file)
@@ -2,7 +2,6 @@
  * Trampoline functions for the ItemKeyFun callbacks.
  */
 
-#include <assert.h>
 #include <ItemKeyFun.h>
 
 /**
@@ -12,8 +11,8 @@
  */
 unsigned long ItemKeyFun_hashcode(void *this,void *key) {
     ItemKeyFun *type = (ItemKeyFun*) this;
-    assert( type );
-    return type->hashcode? type->hashcode( type, key ) : (unsigned long) key;
+    return (type && type->hashcode)? type->hashcode( type, key )
+       : (unsigned long) key;
 }
 
 /**
@@ -48,6 +47,39 @@ void ItemKeyFun_releasekey(void *this,void *key) {
     }
 }
 
+/**
+ * Write a value in hexadecimal form, with "0x" followed by digits, if
+ * it fits within the given limit. Returns characters written, which
+ * is either 0 or all.
+ */
+static int ItemKeyFun_puthexlong(char *p,unsigned long x,int limit) {
+    int n = 3;
+    if ( x ) {
+       unsigned long y = x;
+       char *q = p;
+       for ( ; y; y >>= 4, q++ );
+       n = q - p + 2;
+       if ( n >= limit ) {
+           return 0;
+       }
+       *(p++) = '0';
+       *(p++) = 'x';
+       for ( q++; x; x >>= 4, q-- ) {
+           *q = x & 0xf;
+       }
+       p += n - 2;
+    } else {
+       if ( 3 >= limit ) {
+           return 0;
+       }
+       *(p++) = '0';
+       *(p++) = 'x';
+       *(p++) = '0';
+    }
+    *(p++) = 0;
+    return n;
+}
+
 /**
  * \brief Trampoline function for the ItemKeyFun.tostring callback.
  */
@@ -56,8 +88,28 @@ int ItemKeyFun_tostring(void *this,void *item,char *buffer,int limit) {
     if( type && type->tostring ) {
        return type->tostring( type, item, buffer, limit );
     }
+    if ( limit < 14 ) {
+       return 0;
+    }
     void *key = ItemKeyFun_itemkey( this, item );
-    int n = snprintf( buffer, limit, "{%p/%p@%p}", type, key, item );
+    // Portable snprintf
+    void *code[] = { type, key, item };
     ItemKeyFun_releasekey( this, key );
+    char *tail = "/@}";
+    char *p = buffer;
+    int i, k, n = 2;
+    if ( n >= limit ) {
+       return 0;
+    }
+    *(p++) = '{';
+    for ( k = 0; k < 3; k++ ) {
+       i = ItemKeyFun_puthexlong( p, (unsigned long) code[ k ], limit - n );
+       n += i + 1;
+       if ( i == 0 || n >= limit ) {
+           return 0;
+       }
+       *(p++) = tail[k];
+    }
+    *(p++) = 0;
     return n;
 }