portability fixes
[rrq/rrqmisc.git] / typing / ItemKeyFun.c
1 /**
2  * Trampoline functions for the ItemKeyFun callbacks.
3  */
4
5 #include <ItemKeyFun.h>
6
7 /**
8  * \brief Trampoline function for the ItemKeyFun.hashcode callback.
9  *
10  * The default is to use the pointer itself.
11  */
12 unsigned long ItemKeyFun_hashcode(void *this,void *key) {
13     ItemKeyFun *type = (ItemKeyFun*) this;
14     return (type && type->hashcode)? type->hashcode( type, key )
15         : (unsigned long) key;
16 }
17
18 /**
19  * \brief Trampoline function for the ItemKeyFun.itemkey callback.
20  */
21 void *ItemKeyFun_itemkey(void *this,void *item) {
22     ItemKeyFun *type = (ItemKeyFun*) this;
23     return ( type && type->itemkey )? type->itemkey( type, item ) : item;
24 }
25
26 /**
27  * \brief Trampoline function for the ItemKeyFun.haskey callback.
28  */
29 int ItemKeyFun_haskey(void *this,void *item,void *key) {
30     ItemKeyFun *type = (ItemKeyFun*) this;
31     if ( type && type->haskey ) {
32         return type->haskey( this, item, key );
33     }
34     void *ikey = ItemKeyFun_itemkey( this, item );
35     int n = ikey == key;
36     ItemKeyFun_releasekey( this, ikey );
37     return n;
38 }
39
40 /**
41  * \brief Trampoline function for the ItemKeyFun.releasekey callback.
42  */
43 void ItemKeyFun_releasekey(void *this,void *key) {
44     ItemKeyFun *type = (ItemKeyFun*) this;
45     if( type && type->releasekey ) {
46         type->releasekey( type, key );
47     }
48 }
49
50 /**
51  * Write a value in hexadecimal form, with "0x" followed by digits, if
52  * it fits within the given limit. Returns characters written, which
53  * is either 0 or all.
54  */
55 static int ItemKeyFun_puthexlong(char *p,unsigned long x,int limit) {
56     int n = 3;
57     if ( x ) {
58         unsigned long y = x;
59         char *q = p;
60         for ( ; y; y >>= 4, q++ );
61         n = q - p + 2;
62         if ( n >= limit ) {
63             return 0;
64         }
65         *(p++) = '0';
66         *(p++) = 'x';
67         for ( q++; x; x >>= 4, q-- ) {
68             *q = x & 0xf;
69         }
70         p += n - 2;
71     } else {
72         if ( 3 >= limit ) {
73             return 0;
74         }
75         *(p++) = '0';
76         *(p++) = 'x';
77         *(p++) = '0';
78     }
79     *(p++) = 0;
80     return n;
81 }
82
83 /**
84  * \brief Trampoline function for the ItemKeyFun.tostring callback.
85  */
86 int ItemKeyFun_tostring(void *this,void *item,char *buffer,int limit) {
87     ItemKeyFun *type = (ItemKeyFun*) this;
88     if( type && type->tostring ) {
89         return type->tostring( type, item, buffer, limit );
90     }
91     if ( limit < 14 ) {
92         return 0;
93     }
94     void *key = ItemKeyFun_itemkey( this, item );
95     // Portable snprintf
96     void *code[] = { type, key, item };
97     ItemKeyFun_releasekey( this, key );
98     char *tail = "/@}";
99     char *p = buffer;
100     int i, k, n = 2;
101     if ( n >= limit ) {
102         return 0;
103     }
104     *(p++) = '{';
105     for ( k = 0; k < 3; k++ ) {
106         i = ItemKeyFun_puthexlong( p, (unsigned long) code[ k ], limit - n );
107         n += i + 1;
108         if ( i == 0 || n >= limit ) {
109             return 0;
110         }
111         *(p++) = tail[k];
112     }
113     *(p++) = 0;
114     return n;
115 }