11/*
22 * C utilities
3- *
3+ *
44 * Copyright (c) 2017 Fabrice Bellard
55 * Copyright (c) 2018 Charlie Gordon
66 *
2626#define CUTILS_H
2727
2828#include <stdlib.h>
29+ #include <string.h>
2930#include <inttypes.h>
3031
31- /* set if CPU is big endian */
32- #undef WORDS_BIGENDIAN
33-
3432#define likely (x ) __builtin_expect(!!(x), 1)
3533#define unlikely (x ) __builtin_expect(!!(x), 0)
3634#define force_inline inline __attribute__((always_inline))
4846#ifndef countof
4947#define countof (x ) (sizeof(x) / sizeof((x)[0]))
5048#endif
49+ #ifndef container_of
50+ /* return the pointer of type 'type *' containing 'ptr' as field 'member' */
51+ #define container_of (ptr , type , member ) ((type *)((uint8_t *)(ptr) - offsetof(type, member)))
52+ #endif
53+
54+ #if !defined(_MSC_VER ) && defined(__STDC_VERSION__ ) && __STDC_VERSION__ >= 199901L
55+ #define minimum_length (n ) static n
56+ #else
57+ #define minimum_length (n ) n
58+ #endif
5159
5260typedef int BOOL ;
5361
@@ -63,6 +71,12 @@ char *pstrcat(char *buf, int buf_size, const char *s);
6371int strstart (const char * str , const char * val , const char * * ptr );
6472int has_suffix (const char * str , const char * suffix );
6573
74+ /* Prevent UB when n == 0 and (src == NULL or dest == NULL) */
75+ static inline void memcpy_no_ub (void * dest , const void * src , size_t n ) {
76+ if (n )
77+ memcpy (dest , src , n );
78+ }
79+
6680static inline int max_int (int a , int b )
6781{
6882 if (a > b )
@@ -207,28 +221,34 @@ static inline void put_u8(uint8_t *tab, uint8_t val)
207221 * tab = val ;
208222}
209223
224+ #ifndef bswap16
210225static inline uint16_t bswap16 (uint16_t x )
211226{
212227 return (x >> 8 ) | (x << 8 );
213228}
229+ #endif
214230
231+ #ifndef bswap32
215232static inline uint32_t bswap32 (uint32_t v )
216233{
217234 return ((v & 0xff000000 ) >> 24 ) | ((v & 0x00ff0000 ) >> 8 ) |
218235 ((v & 0x0000ff00 ) << 8 ) | ((v & 0x000000ff ) << 24 );
219236}
237+ #endif
220238
239+ #ifndef bswap64
221240static inline uint64_t bswap64 (uint64_t v )
222241{
223- return ((v & ((uint64_t )0xff << (7 * 8 ))) >> (7 * 8 )) |
224- ((v & ((uint64_t )0xff << (6 * 8 ))) >> (5 * 8 )) |
225- ((v & ((uint64_t )0xff << (5 * 8 ))) >> (3 * 8 )) |
226- ((v & ((uint64_t )0xff << (4 * 8 ))) >> (1 * 8 )) |
227- ((v & ((uint64_t )0xff << (3 * 8 ))) << (1 * 8 )) |
228- ((v & ((uint64_t )0xff << (2 * 8 ))) << (3 * 8 )) |
229- ((v & ((uint64_t )0xff << (1 * 8 ))) << (5 * 8 )) |
242+ return ((v & ((uint64_t )0xff << (7 * 8 ))) >> (7 * 8 )) |
243+ ((v & ((uint64_t )0xff << (6 * 8 ))) >> (5 * 8 )) |
244+ ((v & ((uint64_t )0xff << (5 * 8 ))) >> (3 * 8 )) |
245+ ((v & ((uint64_t )0xff << (4 * 8 ))) >> (1 * 8 )) |
246+ ((v & ((uint64_t )0xff << (3 * 8 ))) << (1 * 8 )) |
247+ ((v & ((uint64_t )0xff << (2 * 8 ))) << (3 * 8 )) |
248+ ((v & ((uint64_t )0xff << (1 * 8 ))) << (5 * 8 )) |
230249 ((v & ((uint64_t )0xff << (0 * 8 ))) << (7 * 8 ));
231250}
251+ #endif
232252
233253/* XXX: should take an extra argument to pass slack information to the caller */
234254typedef void * DynBufReallocFunc (void * opaque , void * ptr , size_t size );
@@ -278,6 +298,36 @@ static inline void dbuf_set_error(DynBuf *s)
278298int unicode_to_utf8 (uint8_t * buf , unsigned int c );
279299int unicode_from_utf8 (const uint8_t * p , int max_len , const uint8_t * * pp );
280300
301+ static inline BOOL is_surrogate (uint32_t c )
302+ {
303+ return (c >> 11 ) == (0xD800 >> 11 ); // 0xD800-0xDFFF
304+ }
305+
306+ static inline BOOL is_hi_surrogate (uint32_t c )
307+ {
308+ return (c >> 10 ) == (0xD800 >> 10 ); // 0xD800-0xDBFF
309+ }
310+
311+ static inline BOOL is_lo_surrogate (uint32_t c )
312+ {
313+ return (c >> 10 ) == (0xDC00 >> 10 ); // 0xDC00-0xDFFF
314+ }
315+
316+ static inline uint32_t get_hi_surrogate (uint32_t c )
317+ {
318+ return (c >> 10 ) - (0x10000 >> 10 ) + 0xD800 ;
319+ }
320+
321+ static inline uint32_t get_lo_surrogate (uint32_t c )
322+ {
323+ return (c & 0x3FF ) | 0xDC00 ;
324+ }
325+
326+ static inline uint32_t from_surrogate (uint32_t hi , uint32_t lo )
327+ {
328+ return 0x10000 + 0x400 * (hi - 0xD800 ) + (lo - 0xDC00 );
329+ }
330+
281331static inline int from_hex (int c )
282332{
283333 if (c >= '0' && c <= '9' )
@@ -294,4 +344,80 @@ void rqsort(void *base, size_t nmemb, size_t size,
294344 int (* cmp )(const void * , const void * , void * ),
295345 void * arg );
296346
347+ static inline uint64_t float64_as_uint64 (double d )
348+ {
349+ union {
350+ double d ;
351+ uint64_t u64 ;
352+ } u ;
353+ u .d = d ;
354+ return u .u64 ;
355+ }
356+
357+ static inline double uint64_as_float64 (uint64_t u64 )
358+ {
359+ union {
360+ double d ;
361+ uint64_t u64 ;
362+ } u ;
363+ u .u64 = u64 ;
364+ return u .d ;
365+ }
366+
367+ static inline double fromfp16 (uint16_t v )
368+ {
369+ double d ;
370+ uint32_t v1 ;
371+ v1 = v & 0x7fff ;
372+ if (unlikely (v1 >= 0x7c00 ))
373+ v1 += 0x1f8000 ; /* NaN or infinity */
374+ d = uint64_as_float64 (((uint64_t )(v >> 15 ) << 63 ) | ((uint64_t )v1 << (52 - 10 )));
375+ return d * 0x1p1008 ;
376+ }
377+
378+ static inline uint16_t tofp16 (double d )
379+ {
380+ uint64_t a , addend ;
381+ uint32_t v , sgn ;
382+ int shift ;
383+
384+ a = float64_as_uint64 (d );
385+ sgn = a >> 63 ;
386+ a = a & 0x7fffffffffffffff ;
387+ if (unlikely (a > 0x7ff0000000000000 )) {
388+ /* nan */
389+ v = 0x7c01 ;
390+ } else if (a < 0x3f10000000000000 ) { /* 0x1p-14 */
391+ /* subnormal f16 number or zero */
392+ if (a <= 0x3e60000000000000 ) { /* 0x1p-25 */
393+ v = 0x0000 ; /* zero */
394+ } else {
395+ shift = 1051 - (a >> 52 );
396+ a = ((uint64_t )1 << 52 ) | (a & (((uint64_t )1 << 52 ) - 1 ));
397+ addend = ((a >> shift ) & 1 ) + (((uint64_t )1 << (shift - 1 )) - 1 );
398+ v = (a + addend ) >> shift ;
399+ }
400+ } else {
401+ /* normal number or infinity */
402+ a -= 0x3f00000000000000 ; /* adjust the exponent */
403+ /* round */
404+ addend = ((a >> (52 - 10 )) & 1 ) + (((uint64_t )1 << (52 - 11 )) - 1 );
405+ v = (a + addend ) >> (52 - 10 );
406+ /* overflow ? */
407+ if (unlikely (v > 0x7c00 ))
408+ v = 0x7c00 ;
409+ }
410+ return v | (sgn << 15 );
411+ }
412+
413+ static inline int isfp16nan (uint16_t v )
414+ {
415+ return (v & 0x7FFF ) > 0x7C00 ;
416+ }
417+
418+ static inline int isfp16zero (uint16_t v )
419+ {
420+ return (v & 0x7FFF ) == 0 ;
421+ }
422+
297423#endif /* CUTILS_H */
0 commit comments