Types: Added SilcCompare generic comparison function
[runtime.git] / lib / silcutil / silctypes.h
1 /*
2
3   silctypes.h
4
5   Author: Pekka Riikonen <priikone@silcnet.org>
6
7   Copyright (C) 2002 - 2008 Pekka Riikonen
8
9   This program is free software; you can redistribute it and/or modify
10   it under the terms of the GNU General Public License as published by
11   the Free Software Foundation; version 2 of the License.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18 */
19
20 /****h* silcutil/Types and Definitions
21  *
22  * DESCRIPTION
23  *
24  * This header file includes basic types and definitions, and various system
25  * specific macros and functions used in SILC Toolkits.  Application programmer
26  * may use them when needed.
27  *
28  ***/
29
30 #ifndef SILCTYPES_H
31 #define SILCTYPES_H
32
33 /* The bool macro is deprecated.  Use SilcBool instead. */
34 #ifdef SILC_MACOSX
35 #define bool _Bool
36 #endif
37 #ifndef __cplusplus
38 #ifndef bool
39 #define bool unsigned char
40 #endif
41 #endif
42
43 #if SILC_SIZEOF_SHORT > 2
44 #error "size of the short must be 2 bytes"
45 #endif
46
47 /****d* silcutil/SilcBool
48  *
49  * NAME
50  *
51  *    typedef unigned char SilcBool;
52  *
53  * DESCRIPTION
54  *
55  *    Boolean value, and is always 8-bits.  Represents value 0 or 1.
56  *
57  ***/
58 typedef unsigned char SilcBool;
59
60 /****d* silcutil/TRUE
61  *
62  * NAME
63  *
64  *    #define TRUE ...
65  *
66  * DESCRIPTION
67  *
68  *    Boolean true value indicator.
69  *
70  * SOURCE
71  */
72 #ifndef TRUE
73 #define TRUE 1
74 #endif
75 /***/
76
77 /****d* silcutil/FALSE
78  *
79  * NAME
80  *
81  *    #define FALSE ...
82  *
83  * DESCRIPTION
84  *
85  *    Boolean false value indicator.
86  *
87  * SOURCE
88  */
89 #ifndef FALSE
90 #define FALSE 0
91 #endif
92 /***/
93
94 /****d* silcutil/SilcUInt8
95  *
96  * NAME
97  *
98  *    typedef unsigned char SilcUInt8;
99  *
100  * DESCRIPTION
101  *
102  *    8-bit unsigned integer.
103  *
104  * SOURCE
105  */
106 typedef unsigned char SilcUInt8;
107 /***/
108
109 /****d* silcutil/SilcInt8
110  *
111  * NAME
112  *
113  *    typedef signed char SilcInt8;
114  *
115  * DESCRIPTION
116  *
117  *    8-bit signed integer.
118  *
119  * SOURCE
120  */
121 typedef signed char SilcInt8;
122 /***/
123
124 /****d* silcutil/SilcUInt16
125  *
126  * NAME
127  *
128  *    typedef unsigned short SilcUInt16;
129  *
130  * DESCRIPTION
131  *
132  *    16-bit unsigned integer.  Guaranteed to be 16-bits.
133  *
134  * SOURCE
135  */
136 typedef unsigned short SilcUInt16;
137 /***/
138
139 /****d* silcutil/SilcInt16
140  *
141  * NAME
142  *
143  *    typedef signed short SilcInt16;
144  *
145  * DESCRIPTION
146  *
147  *    16-bit signed integer.  Guaranteed to be 16-bits.
148  *
149  * SOURCE
150  */
151 typedef signed short SilcInt16;
152 /***/
153
154 /****d* silcutil/SilcUInt32
155  *
156  * NAME
157  *
158  *    typedef unsigned long SilcUInt32;
159  *
160  * DESCRIPTION
161  *
162  *    32-bit unsigned integer.  Guaranteed to be 32-bits.
163  *
164  * SOURCE
165  */
166 #if SILC_SIZEOF_LONG == 4
167 typedef unsigned long SilcUInt32;
168 typedef signed long SilcInt32;
169 #else
170 #if SILC_SIZEOF_INT == 4
171 typedef unsigned int SilcUInt32;
172 typedef signed int SilcInt32;
173 #else
174 #if SILC_SIZEOF_LONG_LONG >= 4
175 #ifndef WIN32
176 typedef unsigned long long SilcUInt32;
177 typedef signed long long SilcInt32;
178 #endif
179 #endif
180 #endif
181 #endif
182 /***/
183
184 /****d* silcutil/SilcInt32
185  *
186  * NAME
187  *
188  *    typedef signed long SilcInt32;
189  *
190  * DESCRIPTION
191  *
192  *    32-bit signed integer.  Guaranteed to be 32-bits.
193  *
194  ***/
195
196 /****d* silcutil/SilcUInt64
197  *
198  * NAME
199  *
200  *    typedef unsigned long long SilcUInt64;
201  *
202  * DESCRIPTION
203  *
204  *    64-bit unsigned integer.  Guaranteed to be 64-bits on systems that
205  *    support it.
206  *
207  * SOURCE
208  */
209 #if SILC_SIZEOF_LONG >= 8
210 typedef unsigned long SilcUInt64;
211 typedef signed long SilcInt64;
212 #else
213 #if SILC_SIZEOF_LONG_LONG >= 8
214 #ifndef WIN32
215 typedef unsigned long long SilcUInt64;
216 typedef signed long long SilcInt64;
217 #else
218 typedef unsigned __int64 SilcUInt64;
219 typedef signed __int64 SilcInt64;
220 #endif
221 #else
222 typedef SilcUInt32 SilcUInt64;
223 typedef SilcInt32 SilcInt64;
224 #endif
225 #endif
226 /***/
227
228 /****d* silcutil/SilcInt64
229  *
230  * NAME
231  *
232  *    typedef signed long long SilcInt64;
233  *
234  * DESCRIPTION
235  *
236  *    64-bit signed integer.  Guaranteed to be 64-bits on systems that
237  *    support it.
238  *
239  ***/
240
241 /****d* silcutil/SilcFloat32
242  *
243  * NAME
244  *
245  *    typedef float SilcFloat32;
246  *
247  * DESCRIPTION
248  *
249  *    32-bit floating point number.
250  *
251  ***/
252 typedef float SilcFloat32;
253
254 /****d* silcutil/SilcFloat64
255  *
256  * NAME
257  *
258  *    typedef double SilcFloat64;
259  *
260  * DESCRIPTION
261  *
262  *    64-bit floating point number.
263  *
264  ***/
265 typedef double SilcFloat64;
266
267 #if SILC_SIZEOF_VOID_P < 4
268 typedef SilcUInt32 * void *;
269 #endif
270
271 /****d* silcutil/SilcSocket
272  *
273  * NAME
274  *
275  *    SilcSocket
276  *
277  * DESCRIPTION
278  *
279  *    Platform specific socket.  On POSIX compliant systems this is simply
280  *    an integer, representing the socket. On other systems it is platform
281  *    specific socket context.  Access it only through routines that can
282  *    handle SilcSocket types.
283  *
284  * SOURCE
285  */
286 #if defined(SILC_UNIX)
287 typedef int SilcSocket;
288 #elif defined(SILC_WIN32)
289 typedef SOCKET SilcSocket;
290 #elif defined(SILC_SYMBIAN)
291 typedef void * SilcSocket;
292 #endif
293 /***/
294
295 /****d* silcutil/SilcParam
296  *
297  * NAME
298  *
299  *    typedef SilcUInt32 SilcParam;
300  *
301  * DESCRIPTION
302  *
303  *    A generic parameters that describe the type of an parameter or argument.
304  *    They can be used to describe function arguments, buffer encoding format,
305  *    etc.
306  *
307  * SOURCE
308  */
309 typedef SilcUInt32 SilcParam;
310
311 #define SILC_PARAM_SINT8         1              /* SilcInt8 */
312 #define SILC_PARAM_UINT8         2              /* SilcUInt8 */
313 #define SILC_PARAM_SINT16        3              /* SilcInt16 */
314 #define SILC_PARAM_UINT16        4              /* SilcUInt16 */
315 #define SILC_PARAM_SINT32        5              /* SilcInt32 */
316 #define SILC_PARAM_UINT32        6              /* SilcUInt32 */
317 #define SILC_PARAM_SINT64        7              /* SilcInt64 */
318 #define SILC_PARAM_UINT64        8              /* SilcUInt64 */
319 #define SILC_PARAM_SICHAR        9              /* signed char * */
320 #define SILC_PARAM_UICHAR        10             /* unsigned char * */
321 #define SILC_PARAM_BUFFER        11             /* SilcBuffer */
322 #define SILC_PARAM_PTR           12             /* void * */
323 #define SILC_PARAM_END           0xfeeefff1     /* End of parameters */
324 /***/
325
326 /* Internal parameter types, not publicly documented, used mainly by the
327    SILC Buffer Format API (silcbuffmt.h). */
328 #define SILC_PARAM_UI8_STRING    100            /* String (max len 8-bits) */
329 #define SILC_PARAM_UI16_STRING   101            /* String (max len 16-bits) */
330 #define SILC_PARAM_UI32_STRING   102            /* String (max len 32-bits) */
331 #define SILC_PARAM_UI8_NSTRING   103            /* String (max len 8-bits) */
332 #define SILC_PARAM_UI16_NSTRING  104            /* String (max len 16-bits) */
333 #define SILC_PARAM_UI32_NSTRING  105            /* String (max len 32-bits) */
334 #define SILC_PARAM_OFFSET        106
335 #define SILC_PARAM_ADVANCE       107
336 #define SILC_PARAM_FUNC          108
337 #define SILC_PARAM_REGEX         109
338 #define SILC_PARAM_OFFSET_START  110
339 #define SILC_PARAM_OFFSET_END    111
340 #define SILC_PARAM_DELETE        112
341 #define SILC_PARAM_ALLOC         0x00010000     /* Allocate, bitmask */
342 #define SILC_PARAM_REPLACE       0x00020000     /* Replace, bitmask */
343
344 /****d* silcutil/SilcCompareValue
345  *
346  * NAME
347  *
348  *    typedef enum { ... } SilcCompareValue
349  *
350  * DESCRIPTION
351  *
352  *    Values that can be returned by the SilcCompare function.  Note that
353  *    not all routines may respect all of the return values.
354  *
355  * SOURCE
356  */
357 typedef enum {
358   SILC_COMPARE_LESS_THAN_EQUAL_TO    = -2,  /* Value 1 <= value 2 */
359   SILC_COMPARE_LESS_THAN             = -1,  /* Value 1 < value 2 */
360   SILC_COMPARE_EQUAL_TO              = 0,   /* Value 1 == value 2 */
361   SILC_COMPARE_GREATER_THAN          = 1,   /* Value 1 > value 2 */
362   SILC_COMPARE_GREATER_THAN_EQUAL_TO = 2,   /* Value 1 >= value 2 */
363   SILC_COMPARE_STOP                  = 3,   /* Stop comparison */
364 } SilcCompareValue;
365 /***/
366
367 /****f* silcutil/SilcCompare
368  *
369  * SYNOPSIS
370  *
371  *    typedef SilcCompareValue (*SilcCompare)(void *value1, void *value2,
372  *                                            void *context);
373  *
374  * DESCRIPTION
375  *
376  *   A comparison function used by many routines in SILC Runtime Toolkit.
377  *
378  ***/
379 typedef SilcCompareValue (*SilcCompare)(void *value1, void *value2,
380                                         void *context);
381
382 /* Macros */
383
384 #if (defined(SILC_I486) || defined(SILC_X86_64)) && defined(__GNUC__)
385 #define SILC_GET_WORD(cp)                                               \
386 ({                                                                      \
387   SilcUInt32 _result_;                                                  \
388   asm volatile ("movl (%1), %0; bswapl %0"                              \
389                 : "=q" (_result_) : "q" (cp));                          \
390   _result_;                                                             \
391 })
392 #else
393 #define SILC_GET_WORD(cp) ((SilcUInt32)(SilcUInt8)(cp)[0]) << 24        \
394                     | ((SilcUInt32)(SilcUInt8)(cp)[1] << 16)            \
395                     | ((SilcUInt32)(SilcUInt8)(cp)[2] << 8)             \
396                     | ((SilcUInt32)(SilcUInt8)(cp)[3])
397 #endif /* (SILC_I486 || SILC_X86_64) && __GNUC__ */
398
399 /****d* silcutil/SILC_MAX
400  *
401  * NAME
402  *
403  *    #define SILC_MAX(a, b)
404  *
405  * DESCRIPTION
406  *
407  *    Return `a' if it is bigger than `b', otherwise return `b'.
408  *
409  ***/
410 #define SILC_MAX(a, b) ((a) > (b) ? (a) : (b))
411
412 /****d* silcutil/SILC_MIN
413  *
414  * NAME
415  *
416  *    #define SILC_MIN(a, b)
417  *
418  * DESCRIPTION
419  *
420  *    Return `a' if it is smaller than `b', otherwise return `b'.
421  *
422  ***/
423 #define SILC_MIN(a, b) ((a) < (b) ? (a) : (b))
424
425 /****d* silcutil/SILC_GET16_MSB
426  *
427  * NAME
428  *
429  *    #define SILC_GET16_MSB(dest, src)
430  *
431  * DESCRIPTION
432  *
433  *    Return two 8-bit bytes, most significant bytes first.
434  *
435  * SOURCE
436  */
437 #if (defined(SILC_I386) || defined(SILC_X86_64)) && defined(__GNUC__)
438 #define SILC_GET16_MSB(l, cp)                           \
439 asm volatile ("movw (%1), %w0; rolw $8, %w0"            \
440               : "=q" (l) : "q" (cp) : "memory", "cc");
441 #else
442 #define SILC_GET16_MSB(l, cp)                           \
443 do {                                                    \
444   (l) = ((SilcUInt32)(SilcUInt8)(cp)[0] << 8)           \
445     | ((SilcUInt32)(SilcUInt8)(cp)[1]);                 \
446 } while(0)
447 #endif /* (SILC_I386 || SILC_X86_64) && __GNUC__ */
448 /***/
449
450 /****d* silcutil/SILC_GET32_MSB
451  *
452  * NAME
453  *
454  *    #define SILC_GET32_MSB(dest, src)
455  *
456  * DESCRIPTION
457  *
458  *    Return four 8-bit bytes, most significant bytes first.
459  *
460  * SOURCE
461  */
462 #if (defined(SILC_I486) || defined(SILC_X86_64)) && defined(__GNUC__)
463 #define SILC_GET32_MSB(l, cp)                           \
464 asm volatile ("movl (%1), %0; bswapl %0"                \
465               : "=q" (l) : "q" (cp) : "memory", "cc");
466 #else
467 #define SILC_GET32_MSB(l, cp)                           \
468 do {                                                    \
469   (l) = ((SilcUInt32)(SilcUInt8)(cp)[0]) << 24          \
470     | ((SilcUInt32)(SilcUInt8)(cp)[1] << 16)            \
471     | ((SilcUInt32)(SilcUInt8)(cp)[2] << 8)             \
472     | ((SilcUInt32)(SilcUInt8)(cp)[3]);                 \
473 } while(0)
474 #endif /* (SILC_I486 || SILC_X86_64) && __GNUC__ */
475 /***/
476
477 /* Same as upper but XOR the result always. Special purpose macro. */
478 #if (defined(SILC_I486) || defined(SILC_X86_64)) && defined(__GNUC__)
479 #define SILC_GET32_X_MSB(l, cp)                                         \
480 do {                                                                    \
481   register volatile SilcUInt32 _x_;                                     \
482   asm volatile ("movl %1, %3; movl (%2), %0;\n\t"                       \
483                 "bswapl %0; xorl %3, %0"                                \
484                 : "=r" (l) : "0" (l), "r" (cp), "r" (_x_)               \
485                 : "memory", "cc");                                      \
486 } while(0)
487 #else
488 #define SILC_GET32_X_MSB(l, cp)                         \
489   (l) ^= ((SilcUInt32)(SilcUInt8)(cp)[0]) << 24         \
490     | ((SilcUInt32)(SilcUInt8)(cp)[1] << 16)            \
491     | ((SilcUInt32)(SilcUInt8)(cp)[2] << 8)             \
492     | ((SilcUInt32)(SilcUInt8)(cp)[3]);
493 #endif /* (SILC_I486 || SILC_X86_64) && __GNUC__ */
494
495 /****d* silcutil/SILC_GET64_MSB
496  *
497  * NAME
498  *
499  *    #define SILC_GET64_MSB(dest, src)
500  *
501  * DESCRIPTION
502  *
503  *    Return eight 8-bit bytes, most significant bytes first.
504  *
505  * SOURCE
506  */
507 #if defined(SILC_X86_64) && defined(__GNUC__)
508 #define SILC_GET64_MSB(l, cp)                                   \
509 asm volatile ("movq (%1), %0; bswapq %0"                        \
510               : "=r" (l) : "r" (cp) : "memory", "cc");
511 #else
512 #define SILC_GET64_MSB(l, cp)                                   \
513 do {                                                            \
514   (l) = ((((SilcUInt64)SILC_GET_WORD((cp))) << 32) |            \
515          ((SilcUInt64)SILC_GET_WORD((cp) + 4)));                \
516 } while(0)
517 #endif /* SILC_X86_64 && __GNUC__ */
518 /***/
519
520 /****d* silcutil/SILC_GET16_LSB
521  *
522  * NAME
523  *
524  *    #define SILC_GET16_MSB(dest, src)
525  *
526  * DESCRIPTION
527  *
528  *    Return two 8-bit bytes, least significant bytes first.
529  *
530  * SOURCE
531  */
532 #if defined(SILC_I386) || defined(SILC_X86_64)
533 #define SILC_GET16_LSB(l, cp) (l) = (*(SilcUInt16 *)(cp))
534 #else
535 #define SILC_GET16_LSB(l, cp)                           \
536 do {                                                    \
537   (l) = ((SilcUInt32)(SilcUInt8)(cp)[0])                \
538     | ((SilcUInt32)(SilcUInt8)(cp)[1] << 8);            \
539 } while(0)
540 #endif /* SILC_I386 || SILC_X86_64 */
541 /***/
542
543 /****d* silcutil/SILC_GET32_LSB
544  *
545  * NAME
546  *
547  *    #define SILC_GET32_LSB(dest, src)
548  *
549  * DESCRIPTION
550  *
551  *    Return four 8-bit bytes, least significant bytes first.
552  *
553  * SOURCE
554  */
555 #if defined(SILC_I386) || defined(SILC_X86_64)
556 #define SILC_GET32_LSB(l, cp) (l) = (*(SilcUInt32 *)(cp))
557 #else
558 #define SILC_GET32_LSB(l, cp)                           \
559 do {                                                    \
560   (l) = ((SilcUInt32)(SilcUInt8)(cp)[0])                \
561     | ((SilcUInt32)(SilcUInt8)(cp)[1] << 8)             \
562     | ((SilcUInt32)(SilcUInt8)(cp)[2] << 16)            \
563     | ((SilcUInt32)(SilcUInt8)(cp)[3] << 24);           \
564 } while(0)
565 #endif /* SILC_I386 || SILC_X86_64 */
566 /***/
567
568 /* Same as upper but XOR the result always. Special purpose macro. */
569 #if defined(SILC_I386) || defined(SILC_X86_64)
570 #define SILC_GET32_X_LSB(l, cp) (l) ^= (*(SilcUInt32 *)(cp))
571 #else
572 #define SILC_GET32_X_LSB(l, cp)                         \
573   (l) ^= ((SilcUInt32)(SilcUInt8)(cp)[0])               \
574     | ((SilcUInt32)(SilcUInt8)(cp)[1] << 8)             \
575     | ((SilcUInt32)(SilcUInt8)(cp)[2] << 16)            \
576     | ((SilcUInt32)(SilcUInt8)(cp)[3] << 24)
577 #endif /* SILC_I386 || SILC_X86_64 */
578
579 /****d* silcutil/SILC_PUT16_MSB
580  *
581  * NAME
582  *
583  *    #define SILC_PUT16_MSB(dest, src)
584  *
585  * DESCRIPTION
586  *
587  *    Put two 8-bit bytes, most significant bytes first.
588  *
589  * SOURCE
590  */
591 #if (defined(SILC_I386) || defined(SILC_X86_64)) && defined(__GNUC__)
592 #define SILC_PUT16_MSB(l, cp)                           \
593 asm volatile ("rolw $8, %w1; movw %w1, (%0)"            \
594               : : "q" (cp), "q" (l) : "memory", "cc");
595 #else
596 #define SILC_PUT16_MSB(l, cp)                   \
597 do {                                            \
598   (cp)[0] = (SilcUInt8)((l) >> 8);              \
599   (cp)[1] = (SilcUInt8)(l);                     \
600 } while(0)
601 #endif /* (SILC_I386 || SILC_X86_64) && __GNUC__ */
602 /***/
603
604 /****d* silcutil/SILC_PUT32_MSB
605  *
606  * NAME
607  *
608  *    #define SILC_PUT32_MSB(dest, src)
609  *
610  * DESCRIPTION
611  *
612  *    Put four 8-bit bytes, most significant bytes first.
613  *
614  * SOURCE
615  */
616 #if (defined(SILC_I486) || defined(SILC_X86_64)) && defined(__GNUC__)
617 #define SILC_PUT32_MSB(l, cp)                           \
618 asm volatile ("bswapl %1; movl %1, (%0); bswapl %1"     \
619               : : "q" (cp), "q" (l) : "memory", "cc");
620 #else
621 #define SILC_PUT32_MSB(l, cp)                   \
622 do {                                            \
623   (cp)[0] = (SilcUInt8)((l) >> 24);             \
624   (cp)[1] = (SilcUInt8)((l) >> 16);             \
625   (cp)[2] = (SilcUInt8)((l) >> 8);              \
626   (cp)[3] = (SilcUInt8)(l);                     \
627 } while(0)
628 #endif /* (SILC_I486 || SILC_X86_64) && __GNUC__ */
629 /***/
630
631 /****d* silcutil/SILC_PUT64_MSB
632  *
633  * NAME
634  *
635  *    #define SILC_PUT64_MSB(dest, src)
636  *
637  * DESCRIPTION
638  *
639  *    Put eight 8-bit bytes, most significant bytes first.
640  *
641  * SOURCE
642  */
643 #if defined(SILC_X86_64) && defined(__GNUC__)
644 #define SILC_PUT64_MSB(l, cp)                           \
645 asm volatile ("bswapq %1; movq %1, (%0); bswapq %1"     \
646               : : "r" (cp), "r" (l) : "memory", "cc");
647 #else
648 #define SILC_PUT64_MSB(l, cp)                                   \
649 do {                                                            \
650   SILC_PUT32_MSB((SilcUInt32)((SilcUInt64)(l) >> 32), (cp));    \
651   SILC_PUT32_MSB((SilcUInt32)(l), (cp) + 4);                    \
652 } while(0)
653 #endif /* SILC_X86_64 && __GNUC__ */
654 /***/
655
656 /****d* silcutil/SILC_PUT16_LSB
657  *
658  * NAME
659  *
660  *    #define SILC_PUT16_LSB(dest, src)
661  *
662  * DESCRIPTION
663  *
664  *    Put two 8-bit bytes, least significant bytes first.
665  *
666  * SOURCE
667  */
668 #if defined(SILC_I386) || defined(SILC_X86_64)
669 #define SILC_PUT16_LSB(l, cp) (*(SilcUInt16 *)(cp)) = (l)
670 #else
671 #define SILC_PUT16_LSB(l, cp)                   \
672 do  {                                           \
673   (cp)[0] = (SilcUInt8)(l);                     \
674   (cp)[1] = (SilcUInt8)((l) >> 8);              \
675 } while(0)
676 #endif /* SILC_I386 || SILC_X86_64 */
677 /***/
678
679 /****d* silcutil/SILC_PUT32_LSB
680  *
681  * NAME
682  *
683  *    #define SILC_PUT32_LSB(dest, src)
684  *
685  * DESCRIPTION
686  *
687  *    Put four 8-bit bytes, least significant bytes first.
688  *
689  * SOURCE
690  */
691 #if defined(SILC_I386) || defined(SILC_X86_64)
692 #define SILC_PUT32_LSB(l, cp) (*(SilcUInt32 *)(cp)) = (l)
693 #else
694 #define SILC_PUT32_LSB(l, cp)                   \
695 do {                                            \
696   (cp)[0] = (SilcUInt8)(l);                     \
697   (cp)[1] = (SilcUInt8)((l) >> 8);              \
698   (cp)[2] = (SilcUInt8)((l) >> 16);             \
699   (cp)[3] = (SilcUInt8)((l) >> 24);             \
700 } while(0)
701 #endif /* SILC_I386 || SILC_X86_64 */
702 /***/
703
704 /****d* silcutil/SILC_SWAB_16
705  *
706  * NAME
707  *
708  *    #define SILC_SWAB_16(integer)
709  *
710  * DESCRIPTION
711  *
712  *    Swabs 16-bit unsigned integer byte order.  Returns the new value.
713  *
714  * SOURCE
715  */
716 #if (defined(SILC_I386) || defined(SILC_X86_64)) && defined(__GNUC__)
717 #define SILC_SWAB_16(l)                         \
718 ({                                              \
719   SilcUInt16 _result_;                          \
720   asm volatile ("movw %w1, %w0; rolw $8, %w0"   \
721                 : "=q" (_result_) : "q" (l));   \
722   _result_;                                     \
723 })
724 #else
725 #define SILC_SWAB_16(l)                                         \
726   ((SilcUInt16)(((SilcUInt16)(l) & (SilcUInt16)0x00FFU) << 8) | \
727                (((SilcUInt16)(l) & (SilcUInt16)0xFF00U) >> 8))
728 #endif /* (SILC_I386 || SILC_X86_64) && __GNUC__ */
729 /***/
730
731 /****d* silcutil/SILC_SWAB_32
732  *
733  * NAME
734  *
735  *    #define SILC_SWAB_32(integer)
736  *
737  * DESCRIPTION
738  *
739  *    Swabs 32-bit unsigned integer byte order.  Returns the new value.
740  *
741  * SOURCE
742  */
743 #if (defined(SILC_I486) || defined(SILC_X86_64)) && defined(__GNUC__)
744 #define SILC_SWAB_32(l)                         \
745 ({                                              \
746   SilcUInt32 _result_;                          \
747   asm volatile ("movl %1, %0; bswapl %0"        \
748                 : "=q" (_result_) : "q" (l));   \
749   _result_;                                     \
750 })
751 #else
752 #define SILC_SWAB_32(l)                                                 \
753   ((SilcUInt32)(((SilcUInt32)(l) & (SilcUInt32)0x000000FFUL) << 24) |   \
754                (((SilcUInt32)(l) & (SilcUInt32)0x0000FF00UL) << 8)  |   \
755                (((SilcUInt32)(l) & (SilcUInt32)0x00FF0000UL) >> 8)  |   \
756                (((SilcUInt32)(l) & (SilcUInt32)0xFF000000UL) >> 24))
757 #endif /* (SILC_I486 || SILC_X86_64) && __GNUC__ */
758 /***/
759
760 /****d* silcutil/SILC_PTR_TO_32
761  *
762  * NAME
763  *
764  *    #define SILC_PTR_TO_32(ptr)
765  *
766  * DESCRIPTION
767  *
768  *    Type casts a pointer's value into a 32-bit integer.  Use this to
769  *    avoid compiler warnings when type casting pointers to integers
770  *    of different size.
771  *
772  * SOURCE
773  */
774 #if SILC_SIZEOF_VOID_P < 8
775 #define SILC_PTR_TO_32(_ptr__) ((SilcUInt32)(_ptr__))
776 #else
777 #define SILC_PTR_TO_32(_ptr__)                                          \
778   ((SilcUInt32)((SilcUInt64)(_ptr__) & (SilcUInt32)0xFFFFFFFFUL))
779 #endif
780 /***/
781
782 /****d* silcutil/SILC_PTR_TO_64
783  *
784  * NAME
785  *
786  *    #define SILC_PTR_TO_64(ptr)
787  *
788  * DESCRIPTION
789  *
790  *    Type casts a pointer's value into a 64-bit integer.  Use this to
791  *    avoid compiler warnings when type casting pointers to integers
792  *    of different size.
793  *
794  * SOURCE
795  */
796 #if SILC_SIZEOF_VOID_P < 8
797 #define SILC_PTR_TO_64(_ptr__) ((SilcUInt64)((SilcUInt32)(_ptr__)))
798 #else
799 #define SILC_PTR_TO_64(_ptr__) ((SilcUInt64)((SilcUInt64)(_ptr__)))
800 #endif
801 /***/
802
803 /****d* silcutil/SILC_32_TO_PTR
804  *
805  * NAME
806  *
807  *    #define SILC_32_TO_PTR(ptr)
808  *
809  * DESCRIPTION
810  *
811  *    Type casts a 32-bit integer value into a pointer.  Use this to
812  *    avoid compiler warnings when type casting integers to pointers of
813  *    different size.
814  *
815  * SOURCE
816  */
817 #if SILC_SIZEOF_VOID_P < 8
818 #define SILC_32_TO_PTR(_ival__) ((void *)((SilcUInt32)(_ival__)))
819 #else
820 #define SILC_32_TO_PTR(_ival__) ((void *)((SilcUInt64)(_ival__)))
821 #endif
822 /***/
823
824 /****d* silcutil/SILC_64_TO_PTR
825  *
826  * NAME
827  *
828  *    #define SILC_64_TO_PTR(ptr)
829  *
830  * DESCRIPTION
831  *
832  *    Type casts a 64-bit integer value into a pointer.  Use this to
833  *    avoid compiler warnings when type casting integers to pointers of
834  *    different size.
835  *
836  * SOURCE
837  */
838 #if SILC_SIZEOF_VOID_P < 8
839 #define SILC_64_TO_PTR(_ival__)                                         \
840   ((void *)((SilcUInt32)((SilcUInt64)(_ival__) & (SilcUInt32)0xFFFFFFFFUL)))
841 #else
842 #define SILC_64_TO_PTR(_ival__) ((void *)((SilcUInt64)(_ival__)))
843 #endif
844 /***/
845
846 /****d* silcutil/SILC_ASSERT
847  *
848  * NAME
849  *
850  *    #define SILC_ASSERT(experssion)
851  *
852  * DESCRIPTION
853  *
854  *    Assert macro that prints error message to stderr and calls abort()
855  *    if the `expression' is false (ie. compares equal to zero).  If
856  *    SILC_DEBUG is not defined this macro has no effect.
857  *
858  * SOURCE
859  */
860 #if defined(SILC_DEBUG)
861 #define SILC_ASSERT(expr) assert((expr));
862 #else
863 #define SILC_ASSERT(expr) do { } while(0)
864 #endif /* SILC_DEBUG */
865 /***/
866
867 /****d* silcutil/SILC_VERIFY
868  *
869  * NAME
870  *
871  *    #define SILC_VERIFY(experssion)
872  *
873  * DESCRIPTION
874  *
875  *    Verification macro that prints error message to stderr and calls
876  *    abort() if the `expression' is false (ie. compares equal to zero)
877  *    on debug builds (SILC_DEBUG defined), and prints error message to
878  *    stderr on release builds (SILC_DEBUG undefined) but does not abort().
879  *    This macro is always compiled even if debugging (SILC_DEBUG) is not
880  *    defined.
881  *
882  * SOURCE
883  */
884 #if defined(SILC_DEBUG)
885 #define SILC_VERIFY(expr) assert((expr));
886 #else
887 #define SILC_VERIFY(expr)                                               \
888   if (silc_unlikely(!(expr))) {                                         \
889     SILC_LOG_ERROR(("SILC_VERIFY %s:%s:%d",                             \
890                     __FILE__, __FUNCTION__, __LINE__));                 \
891     silc_set_errno_reason_nofail(SILC_ERR_ASSERT, "SILC_VERIFY %s:%s:%d", \
892                                  __FILE__, __FUNCTION__, __LINE__);     \
893   }
894 #endif /* SILC_DEBUG */
895 /***/
896
897 /****d* silcutil/silc_rol
898  *
899  * NAME
900  *
901  *    static inline SilcUInt32 silc_rol(SilcUInt32 val, int num);
902  *
903  * DESCRIPTION
904  *
905  *    Rotate 32-bit integer's bits to left `num' times.  Bits pushed to the
906  *    left will appear from the right side of the integer, thus rotating.
907  *    Returns the rotated value.
908  *
909  ***/
910 static inline SilcUInt32 silc_rol(SilcUInt32 val, int num)
911 {
912 #if (defined(SILC_I386) || defined(SILC_X86_64)) && defined(__GNUC__)
913   asm volatile ("roll %%cl, %0"
914                 : "=r" (val) : "0" (val), "c" (num));
915   return val;
916 #else
917   return ((val << (SilcUInt32)num) | (val >> (32 - (SilcUInt32)num)));
918 #endif /* (SILC_I486 || SILC_X86_64) && __GNUC__ */
919 }
920
921 /****d* silcutil/silc_rolc
922  *
923  * NAME
924  *
925  *    static inline SilcUInt32 silc_rolc(SilcUInt32 val, const int num);
926  *
927  * DESCRIPTION
928  *
929  *    Rotate 32-bit integer's bits to left `num' times.  Bits pushed to the
930  *    left will appear from the right side of the integer, thus rotating.
931  *    Returns the rotated value.
932  *
933  ***/
934 static inline SilcUInt32 silc_rolc(SilcUInt32 val, const int num)
935 {
936 #if (defined(SILC_I386) || defined(SILC_X86_64)) && defined(__GNUC__)
937   asm volatile ("roll %2, %0"
938                 : "=r" (val) : "0" (val), "I" (num));
939   return val;
940 #else
941   return ((val << (SilcUInt32)num) | (val >> (32 - (SilcUInt32)num)));
942 #endif /* (SILC_I486 || SILC_X86_64) && __GNUC__ */
943 }
944
945 /****d* silcutil/silc_ror
946  *
947  * NAME
948  *
949  *    static inline SilcUInt32 silc_ror(SilcUInt32 val, int num);
950  *
951  * DESCRIPTION
952  *
953  *    Rotate 32-bit integer's bits to right `num' times.  Bits pushed to the
954  *    right will appear from the left side of the integer, thus rotating.
955  *    Returns the rotated value.
956  *
957  ***/
958 static inline SilcUInt32 silc_ror(SilcUInt32 val, int num)
959 {
960 #if (defined(SILC_I386) || defined(SILC_X86_64)) && defined(__GNUC__)
961   asm volatile ("rorl %%cl, %0"
962                 : "=r" (val) : "0" (val), "c" (num));
963   return val;
964 #else
965   return ((val >> (SilcUInt32)num) | (val << (32 - (SilcUInt32)num)));
966 #endif /* (SILC_I486 || SILC_X86_64) && __GNUC__ */
967 }
968
969 /****d* silcutil/silc_rorc
970  *
971  * NAME
972  *
973  *    static inline SilcUInt32 silc_ror(SilcUInt32 val, const int num);
974  *
975  * DESCRIPTION
976  *
977  *    Rotate 32-bit integer's bits to right `num' times.  Bits pushed to the
978  *    right will appear from the left side of the integer, thus rotating.
979  *    Returns the rotated value.
980  *
981  ***/
982 static inline SilcUInt32 silc_rorc(SilcUInt32 val, const int num)
983 {
984 #if (defined(SILC_I386) || defined(SILC_X86_64)) && defined(__GNUC__)
985   asm volatile ("rorl %2, %0"
986                 : "=r" (val) : "0" (val), "I" (num));
987   return val;
988 #else
989   return ((val >> (SilcUInt32)num) | (val << (32 - (SilcUInt32)num)));
990 #endif /* (SILC_I486 || SILC_X86_64) && __GNUC__ */
991 }
992
993 /****d* silcutil/silc_rol64
994  *
995  * NAME
996  *
997  *    static inline SilcUInt64 silc_rol64(SilcUInt64 val, int num);
998  *
999  * DESCRIPTION
1000  *
1001  *    Rotate 64-bit integer's bits to left `num' times.  Bits pushed to the
1002  *    left will appear from the right side of the integer, thus rotating.
1003  *    Returns the rotated value.
1004  *
1005  ***/
1006 static inline SilcUInt64 silc_rol64(SilcUInt64 val, int num)
1007 {
1008 #if defined(SILC_X86_64) && defined(__GNUC__)
1009   asm volatile ("rolq %%cl, %0"
1010                 : "=r" (val) : "0" (val), "c" (num));
1011   return val;
1012 #else
1013   return ((val << (SilcUInt64)num) | (val >> (64 - (SilcUInt64)num)));
1014 #endif /* SILC_X86_64 && __GNUC__ */
1015 }
1016
1017 /****d* silcutil/silc_rolc64
1018  *
1019  * NAME
1020  *
1021  *    static inline SilcUInt64 silc_rolc64(SilcUInt64 val, const int num);
1022  *
1023  * DESCRIPTION
1024  *
1025  *    Rotate 64-bit integer's bits to left `num' times.  Bits pushed to the
1026  *    left will appear from the right side of the integer, thus rotating.
1027  *    Returns the rotated value.
1028  *
1029  ***/
1030 static inline SilcUInt64 silc_rolc64(SilcUInt64 val, const int num)
1031 {
1032 #if defined(SILC_X86_64) && defined(__GNUC__)
1033   asm volatile ("rolq %2, %0"
1034                 : "=r" (val) : "0" (val), "J" (num));
1035   return val;
1036 #else
1037   return ((val << (SilcUInt64)num) | (val >> (64 - (SilcUInt64)num)));
1038 #endif /* SILC_X86_64 && __GNUC__ */
1039 }
1040
1041 /****d* silcutil/silc_ror64
1042  *
1043  * NAME
1044  *
1045  *    static inline SilcUInt64 silc_ror64(SilcUInt64 val, int num);
1046  *
1047  * DESCRIPTION
1048  *
1049  *    Rotate 64-bit integer's bits to right `num' times.  Bits pushed to the
1050  *    right will appear from the left side of the integer, thus rotating.
1051  *    Returns the rotated value.
1052  *
1053  ***/
1054 static inline SilcUInt64 silc_ror64(SilcUInt64 val, int num)
1055 {
1056 #if defined(SILC_X86_64) && defined(__GNUC__)
1057   asm volatile ("rorq %%cl, %0"
1058                 : "=r" (val) : "0" (val), "c" (num));
1059   return val;
1060 #else
1061   return ((val >> (SilcUInt64)num) | (val << (64 - (SilcUInt64)num)));
1062 #endif /* SILC_X86_64 && __GNUC__ */
1063 }
1064
1065 /****d* silcutil/silc_rorc64
1066  *
1067  * NAME
1068  *
1069  *    static inline SilcUInt64 silc_rorc64(SilcUInt64 val, const int num);
1070  *
1071  * DESCRIPTION
1072  *
1073  *    Rotate 64-bit integer's bits to right `num' times.  Bits pushed to the
1074  *    right will appear from the left side of the integer, thus rotating.
1075  *    Returns the rotated value.
1076  *
1077  ***/
1078 static inline SilcUInt64 silc_rorc64(SilcUInt64 val, const int num)
1079 {
1080 #if defined(SILC_X86_64) && defined(__GNUC__)
1081   asm volatile ("rorq %2, %0"
1082                 : "=r" (val) : "0" (val), "J" (num));
1083   return val;
1084 #else
1085   return ((val >> (SilcUInt64)num) | (val << (64 - (SilcUInt64)num)));
1086 #endif /* SILC_X86_64 && __GNUC__ */
1087 }
1088
1089 /****d* silcutil/silc_offsetof
1090  *
1091  * NAME
1092  *
1093  *    #define silc_offsetof(TYPE, MEMBER)
1094  *
1095  * DESCRIPTION
1096  *
1097  *    offsetof() macro replacement.  Use this instead of offsetof().
1098  *
1099  ***/
1100 #define silc_offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
1101
1102 /****d* silcutil/silc_attribute
1103  *
1104  * NAME
1105  *
1106  *    #define silc_attribute(attrlist)
1107  *
1108  * DESCRIPTION
1109  *
1110  *    Compiler attributes.  If compiler doesn't support attributes this macro
1111  *    doesn't do anything.  Currently this works only with GCC compiler.
1112  *    See GCC documentation for specified attributes.
1113  *
1114  * EXAMPLE
1115  *
1116  *    int printf(const char *fmt, ...) silc_attribute((format(printf, 1, 2)));
1117  *
1118  ***/
1119 #if defined(__GNUC__)
1120 #define silc_attribute(attrlist) __attribute__ (attrlist)
1121 #else
1122 #define silc_attribute(attrlist)
1123 #endif /* __GNUC__ */
1124
1125 /****d* silcutil/silc_likely
1126  *
1127  * NAME
1128  *
1129  *    #define silc_likely(expression)
1130  *
1131  * DESCRIPTION
1132  *
1133  *    Branch prediction macro.  It specifies that it is likely that the branch
1134  *    where silc_likely is applied is taken.  Compiler will optimize the
1135  *    code based on this prediction.  Never use this before you have profiled
1136  *    the code first.
1137  *
1138  ***/
1139
1140 /****d* silcutil/silc_unlikely
1141  *
1142  * NAME
1143  *
1144  *    #define silc_unlikely(expression)
1145  *
1146  * DESCRIPTION
1147  *
1148  *    Branch prediction macro.  It specifies that it is unlikely that the
1149  *    branch where silc_unlikely is applied is taken.  Compiler will optimize
1150  *    the code based on this prediction.  Never use this before you have
1151  *    profiled the code first.
1152  *
1153  ***/
1154 #if __GNUC__ >= 3
1155 #define silc_likely(expr) __builtin_expect(!!(expr), 1)
1156 #define silc_unlikely(expr) __builtin_expect(!!(expr), 0)
1157 #else
1158 #define silc_likely(expr) (expr)
1159 #define silc_unlikely(expr) (expr)
1160 #endif /* __GNUC__ >= 3 */
1161
1162 /* Prefetch operations.  Use these to prefetch data to CPU cache before
1163    reading or writing if you think that the data will be needed soon after
1164    prefetching. */
1165
1166 /****d* silcutil/silc_prefetch
1167  *
1168  * NAME
1169  *
1170  *    static inline void silc_prefetch(void *addr, int rw, int locality);
1171  *
1172  * DESCRIPTION
1173  *
1174  *    Simple prefetch.  Loads memory from specified address to CPU cache.
1175  *    The amount of data loaded is CPU dependant (cache line length).  The
1176  *    `rw' argument defines the reason for prefetch: 0=read, 1=write.  The
1177  *    `locality' argument defines the locality of the prefetch, 0=non-temporal
1178  *    (non-temporal cache, cache closest to CPU, data will not stay long in
1179  *    the cache), 1=temporal (L2+ cache), 2=temporal (L2, L3+ cache),
1180  *    3=temporal (fetch to all caches, data stays longer time in cache).
1181  *
1182  * NOTES
1183  *
1184  *    This produces only a hint for CPU.  CPU doesn't have to actually
1185  *    prefetch the data.  Use silc_prefetch_block to ensure CPU always
1186  *    prefetches.
1187  *
1188  ***/
1189
1190 static inline silc_attribute((always_inline))
1191 void silc_prefetch(void *addr, int rw, int locality)
1192 {
1193 #if __GNUC__ > 3
1194   __builtin_prefetch(addr, rw, locality);
1195 #endif /* __GNUC__ */
1196 }
1197
1198 /****d* silcutil/silc_prefetch_block
1199  *
1200  * NAME
1201  *
1202  *    static inline void silc_prefetch_block(void *addr,
1203  *                                           int prefetch_length,
1204  *                                           const int cache_line_length)
1205  *
1206  * DESCRIPTION
1207  *
1208  *    Enforced block prefetch.  This function loads the specified amount
1209  *    `prefetch_length' of memory from the specified address `addr' to CPU
1210  *    cache with each loaded cache line being the size of `cache_line_length'.
1211  *    If you don't know the cache line size use 64 bytes.  Note that, the
1212  *    `cache_line_length' is a const int.  In this context this mean its
1213  *    value must not come from a variable but must be a constant (the code
1214  *    won't compile if it comes from a variable).
1215  *
1216  *    The `prefetch_length' must be multiple of twice of the
1217  *    `cache_line_length' or 128 if you don't know the cache line size, hence
1218  *    the minimum length for `prefetch_length' is 128 bytes when the
1219  *    `cache_line_length' is 64 bytes.  Shorter cache line length (32 bytes)
1220  *    can be used too.
1221  *
1222  *    You should use the correct `cache_line_length' value for your CPU or
1223  *    the value of the CPU for which you want to optimize your code.  Intel
1224  *    CPUs usually have cache size of 32 or 64 bytes.  The most optimal
1225  *    prefetch is achieved if the `cache_line_length' is the actual CPU cache
1226  *    line size.  Always do performance testing with and without prefetching
1227  *    to make sure the prefetch actually helps.  If used improperly, it may
1228  *    slow down your program.
1229  *
1230  *    The difference to silc_prefetch is that this function always performs
1231  *    the prefetch and has the ability to prefetch more than one cache line
1232  *    worth of memory, whereas silc_prefetch can prefetch only one cache line
1233  *    and may not do the prefetch at all.
1234  *
1235  ***/
1236
1237 static inline silc_attribute((always_inline))
1238 void silc_prefetch_block(void *addr,
1239                          int prefetch_length,
1240                          const int cache_line_length)
1241 {
1242 #if 0
1243   SILC_ASSERT(cache_line_length >= 32);
1244   SILC_ASSERT(cache_line_length % 32 == 0);
1245   SILC_ASSERT(prefetch_length >= cache_line_length);
1246   SILC_ASSERT(prefetch_length % (cache_line_length * 2) == 0);
1247 #endif
1248
1249 #if SILC_SIZEOF_VOID_P < 8
1250 #define SILC_PREFETCH_UINT SilcUInt32
1251 #else
1252 #define SILC_PREFETCH_UINT SilcUInt64
1253 #endif /* SILC_SIZEOF_VOID_P < 8 */
1254
1255 #if defined(__GNUC__) && (defined(SILC_I386) || defined(SILC_X86_64))
1256
1257   /* Assembler implementation.
1258
1259      The idea here is to simply enforce the CPU to load the requested amount
1260      of bytes to cache.  We simply mov data from the memory to a register.
1261      Each mov will load a full cache line worth of data from the memory.
1262
1263      We expect the `cache_line_length' to be the actual cache line size.
1264      It doesn't matter if it is.  If it is smaller the prefetch is a bit
1265      slower as there is redundancy.  If it is larger we skip some of the
1266      data and don't prefetch everything.
1267
1268      The loop is unrolled to handle two mov's at once, this why we expect
1269      the `prefetch_length' to be multiple of twice the length of
1270      `cache_line_length`.  We also mov the data from end to beginning instead
1271      of from the beginning to assure CPU doesn't prefetch the data before
1272      we actually want to do it.
1273
1274      This technique is described by AMD in:
1275      http://cdrom.amd.com/devconn/events/AMD_block_prefetch_paper.pdf */
1276
1277   {
1278     SILC_PREFETCH_UINT temp;
1279
1280 #define SILC_PREFETCH_ASM(ip, rp)                                       \
1281     asm volatile ("1:                                   \n\t"           \
1282                   "mov" ip " -%c4(%2, %" rp "3), %0     \n\t"           \
1283                   "mov" ip " -%c5(%2, %" rp "3), %0     \n\t"           \
1284                   "sub" ip " %5, %" rp "3               \n\t"           \
1285                   "jnz 1b                               "               \
1286                   : "=&r" (temp), "=r" (prefetch_length)                \
1287                   : "r" (addr), "1" (prefetch_length),                  \
1288                     "Z" (cache_line_length),                            \
1289                     "Z" (cache_line_length * 2)                         \
1290                   : "memory", "cc");
1291
1292 #if defined(SILC_I386)
1293     /* 32-bit prefetch */
1294     SILC_PREFETCH_ASM("l", "");
1295 #else
1296     /* 64-bit prefetch */
1297     SILC_PREFETCH_ASM("q", "q");
1298 #endif /* SILC_I386 */
1299   }
1300
1301 #else
1302   /* C implementation.  Yes, you can do it in C too.  In fact, we'll try to
1303      make the compiler generate nearly identical code to the above assembler
1304      code.  Note that, the memory access must be volatile, otherwise the
1305      compiler will optimize them away because the temp variable isn't actually
1306      used for anything.  This should be as fast as the assembler code above,
1307      unless the compiler decides to start meddling with it (don't use
1308      -funroll-loops with this code). */
1309
1310   {
1311     register unsigned char *a = addr;
1312     register int len = prefetch_length;
1313     register SILC_PREFETCH_UINT temp;
1314
1315     do {
1316       temp = *(SILC_PREFETCH_UINT volatile *)
1317         (a + (len - cache_line_length));
1318       temp = *(SILC_PREFETCH_UINT volatile *)
1319         (a + (len - (cache_line_length * 2)));
1320       len -= (cache_line_length * 2);
1321     } while (len != 0);
1322   }
1323 #endif /* __GNUC__ */
1324 #undef SILC_PREFETCH_UINT
1325 #undef SILC_PREFETCH_ASM
1326 }
1327
1328 #endif /* SILCTYPES_H */