00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00050 #ifndef _misc_h_
00051 #define _misc_h_
00052
00053 #include "config.h"
00054
00055 #include <time.h>
00056 #include <stdio.h>
00057 #include <ctype.h>
00058
00059 #include <glib.h>
00060
00061 #define SIZE_FIELD_MAX 64
00062 #define GUID_RAW_SIZE 16
00063 #define GUID_HEX_SIZE 32
00068 #ifndef USE_GLIB2
00069
00070 #ifndef HAS_STRLCPY
00071 size_t strlcpy(gchar *dst, const gchar *src, size_t dst_size);
00072 #endif
00073
00074 #ifndef HAS_STRLCAT
00075 size_t strlcat(gchar *dst, const gchar *src, size_t dst_size);
00076 #endif
00077
00078 #define g_string_printf g_string_sprintf
00079 #define g_strlcpy strlcpy
00080 #define g_strlcat strlcat
00081 #endif
00082
00083 size_t concat_strings(gchar *dst, size_t size,
00084 const gchar *s, ...) WARN_NEED_SENTINEL;
00085 size_t w_concat_strings(gchar **dst,
00086 const gchar *first, ...) WARN_NEED_SENTINEL;
00087
00093 static inline G_GNUC_CONST WARN_UNUSED_RESULT gchar *
00094 deconstify_gchar(const gchar *p)
00095 {
00096 return (gchar *) p;
00097 }
00098
00099 static inline G_GNUC_CONST WARN_UNUSED_RESULT guint32 *
00100 deconstify_guint32(const guint32 *p)
00101 {
00102 return (guint32 *) p;
00103 }
00104
00105 static inline G_GNUC_CONST WARN_UNUSED_RESULT gpointer
00106 deconstify_gpointer(gconstpointer p)
00107 {
00108 return (gpointer) p;
00109 }
00110
00111 static inline G_GNUC_CONST WARN_UNUSED_RESULT gconstpointer
00112 cast_to_gconstpointer(gconstpointer p)
00113 {
00114 return p;
00115 }
00116
00117 static inline G_GNUC_CONST WARN_UNUSED_RESULT gpointer
00118 cast_to_gpointer(gpointer p)
00119 {
00120 return p;
00121 }
00122
00123 static inline G_GNUC_CONST WARN_UNUSED_RESULT gchar *
00124 cast_to_gchar_ptr(gpointer p)
00125 {
00126 return p;
00127 }
00128
00129 static inline G_GNUC_CONST WARN_UNUSED_RESULT guchar *
00130 cast_to_guchar_ptr(gpointer p)
00131 {
00132 return p;
00133 }
00134
00135 typedef void (*func_ptr_t)(void);
00136
00137 static inline G_GNUC_CONST WARN_UNUSED_RESULT gpointer
00138 cast_func_to_gpointer(func_ptr_t f)
00139 {
00140 union {
00141 func_ptr_t f;
00142 gpointer p;
00143 } u;
00144
00145 u.f = f;
00146 return u.p;
00147 }
00148
00149 static inline G_GNUC_CONST WARN_UNUSED_RESULT func_ptr_t
00150 cast_gpointer_to_func(gconstpointer p)
00151 {
00152 union {
00153 func_ptr_t f;
00154 gconstpointer p;
00155 } u;
00156
00157 u.p = p;
00158 return u.f;
00159 }
00160
00161 gint ascii_strcasecmp(const gchar *s1, const gchar *s2);
00162 gint ascii_strncasecmp(const gchar *s1, const gchar *s2, size_t len);
00163
00170 static inline gint
00171 hex2int_inline(guchar c)
00172 {
00173 extern const gint8 *hex2int_tab;
00174 return hex2int_tab[c];
00175 }
00176
00183 static inline gint
00184 dec2int_inline(guchar c)
00185 {
00186 extern const gint8 *dec2int_tab;
00187 return dec2int_tab[c];
00188 }
00189
00196 static inline gint
00197 alnum2int_inline(guchar c)
00198 {
00199 extern const gint8 *alnum2int_tab;
00200 return alnum2int_tab[c];
00201 }
00202
00211 static inline G_GNUC_CONST WARN_UNUSED_RESULT gboolean
00212 is_ascii_blank(gint c)
00213 {
00214 return c == 32 || c == 9;
00215 }
00216
00217 static inline G_GNUC_CONST WARN_UNUSED_RESULT gboolean
00218 is_ascii_cntrl(gint c)
00219 {
00220 return (c >= 0 && c <= 31) || c == 127;
00221 }
00222
00223 static inline G_GNUC_CONST WARN_UNUSED_RESULT gboolean
00224 is_ascii_digit(gint c)
00225 {
00226 return c >= 48 && c <= 57;
00227 }
00228
00229 static inline G_GNUC_CONST WARN_UNUSED_RESULT gboolean
00230 is_ascii_xdigit(gint c)
00231 {
00232 return -1 != hex2int_inline(c) && !(c & ~0x7f);
00233 }
00234
00235 static inline G_GNUC_CONST WARN_UNUSED_RESULT gboolean
00236 is_ascii_upper(gint c)
00237 {
00238 return c >= 65 && c <= 90;
00239 }
00240
00241 static inline G_GNUC_CONST WARN_UNUSED_RESULT gboolean
00242 is_ascii_lower(gint c)
00243 {
00244 return c >= 97 && c <= 122;
00245 }
00246
00247 static inline G_GNUC_CONST WARN_UNUSED_RESULT gboolean
00248 is_ascii_alpha(gint c)
00249 {
00250 return is_ascii_upper(c) || is_ascii_lower(c);
00251 }
00252
00253 static inline G_GNUC_CONST WARN_UNUSED_RESULT gboolean
00254 is_ascii_alnum(gint c)
00255 {
00256 return -1 != alnum2int_inline(c) && !(c & ~0x7f);
00257 }
00258
00259 static inline G_GNUC_CONST WARN_UNUSED_RESULT gboolean
00260 is_ascii_space(gint c)
00261 {
00262 return c == 32 || (c >= 9 && c <= 13);
00263 }
00264
00265 static inline G_GNUC_CONST WARN_UNUSED_RESULT gboolean
00266 is_ascii_graph(gint c)
00267 {
00268 return c >= 33 && c <= 126;
00269 }
00270
00271 static inline G_GNUC_CONST WARN_UNUSED_RESULT gboolean
00272 is_ascii_print(gint c)
00273 {
00274 return is_ascii_graph(c) || c == 32;
00275 }
00276
00277 static inline G_GNUC_CONST WARN_UNUSED_RESULT gboolean
00278 is_ascii_punct(gint c)
00279 {
00280 return c >= 33 && c <= 126 && !is_ascii_alnum(c);
00281 }
00282
00283 static inline G_GNUC_CONST WARN_UNUSED_RESULT gint
00284 ascii_toupper(gint c)
00285 {
00286 return is_ascii_lower(c) ? c - 32 : c;
00287 }
00288
00289 static inline G_GNUC_CONST WARN_UNUSED_RESULT gint
00290 ascii_tolower(gint c)
00291 {
00292 return is_ascii_upper(c) ? c + 32 : c;
00293 }
00294
00295 #if !GLIB_CHECK_VERSION(2,4,0)
00296 static inline WARN_UNUSED_RESULT const gchar *
00297 g_strip_context(const gchar *id, const gchar *val)
00298 {
00299 const gchar *s;
00300
00301 s = id != val ? NULL : strchr(id, '|');
00302 return s ? ++s : val;
00303 }
00304 #endif
00305
00311 static inline WARN_UNUSED_RESULT gchar *
00312 skip_ascii_spaces(const gchar *s)
00313 {
00314 while (is_ascii_space(*s))
00315 s++;
00316
00317 return deconstify_gchar(s);
00318 }
00319
00325 static inline WARN_UNUSED_RESULT gchar *
00326 skip_ascii_blanks(const gchar *s)
00327 {
00328 while (is_ascii_blank(*s))
00329 s++;
00330
00331 return deconstify_gchar(s);
00332 }
00333
00334
00335
00336
00337 #define CONST_STRLEN(x) (sizeof(x) - 1)
00338
00339
00340
00341
00342 #ifndef G_N_ELEMENTS
00343 #define G_N_ELEMENTS(arr) (sizeof (arr) / sizeof ((arr)[0]))
00344 #endif
00345
00346
00347
00348
00349 typedef guint16 flag_t;
00350 #define set_flags(r,f) (r |= (f))
00351 #define clear_flags(r,f) (r &= ~(f))
00352
00353
00354
00355
00356
00357 #define UINT8_HEX_BUFLEN (sizeof "FF")
00358 #define UINT8_DEC_BUFLEN (sizeof "255")
00359 #define UINT16_HEX_BUFLEN (sizeof "01234")
00360 #define UINT16_DEC_BUFLEN (sizeof "65535")
00361 #define UINT32_HEX_BUFLEN (sizeof "012345678")
00362 #define UINT32_DEC_BUFLEN (sizeof "4294967295")
00363 #define UINT64_HEX_BUFLEN (sizeof "0123456789ABCDEF")
00364 #define UINT64_DEC_BUFLEN (sizeof "18446744073709551615")
00365 #define IPV4_ADDR_BUFLEN (sizeof "255.255.255.255")
00366 #define IPV6_ADDR_BUFLEN \
00367 (sizeof "0001:0203:0405:0607:0809:1011:255.255.255.255")
00368 #define TIMESTAMP_BUF_LEN (sizeof "9999-12-31 23:59:61")
00369
00370 gboolean parse_ipv6_addr(const gchar *s, uint8_t *dst, const gchar **endptr);
00371 const gchar *ipv6_to_string(const guint8 *ipv6);
00372 size_t ipv6_to_string_buf(const guint8 *ipv6, gchar *dst, size_t size);
00373
00374
00375
00376
00377 guint32 string_to_ip(const gchar *);
00378 gboolean string_to_ip_strict(const gchar *s, guint32 *addr, const gchar **ep);
00379 gboolean string_to_ip_and_mask(const gchar *str, guint32 *ip, guint32 *netmask);
00380 gboolean string_to_ip_port(const gchar *str, guint32 *ip, guint16 *port);
00381 const gchar *ip_to_string(guint32);
00382 const gchar *ip_to_string2(guint32);
00383 size_t ip_to_string_buf(guint32 ip, gchar *buf, size_t size);
00384 const gchar *ip_port_to_string(guint32, guint16);
00385 const gchar *hostname_port_to_string(const gchar *hostname, guint16 port);
00386 const gchar *local_hostname(void);
00387 #define port_is_valid(port) (port != 0)
00388
00389
00390
00391
00392 const gchar *timestamp_to_string(time_t date);
00393 const gchar *timestamp_utc_to_string(time_t date);
00394 const gchar *timestamp_rfc822_to_string(time_t date);
00395 const gchar *timestamp_rfc822_to_string2(time_t date);
00396 const gchar *timestamp_rfc1123_to_string(time_t date);
00397
00398 size_t timestamp_to_string_buf(time_t date, gchar *dst, size_t size);
00399 size_t time_locale_to_string_buf(time_t date, gchar *dst, size_t size);
00400
00401
00402
00403 gchar *short_time(gint s);
00404 gchar *short_uptime(gint s);
00405
00406
00407
00408 #if !defined(LINUX_SYSTEM) && \
00409 !defined(__FreeBSD__) && \
00410 !defined(__NetBSD__) && \
00411 !defined(__OpenBSD__)
00412 #define USE_DIFFTIME
00413 #endif
00414
00415
00416
00417 #if defined(USE_DIFFTIME)
00418 #define delta_time(a, b) ((gint64) difftime((a), (b)))
00419 #else
00420 #define delta_time(a, b) ((gint64) ((a) - (b)))
00421 #endif
00422
00423
00424
00425
00426 const gchar *short_size(guint64 size);
00427 const gchar *short_html_size(guint64 size);
00428 const gchar *short_kb_size(guint64 size);
00429 const gchar *short_rate(guint64 rate);
00430 const gchar *compact_size(guint64 size);
00431 const gchar *compact_rate(guint64 rate);
00432 const gchar *compact_kb_size(guint32 size);
00433 gchar *short_value(gchar *buf, size_t size, guint64 v);
00434 gchar *compact_value(gchar *buf, size_t size, guint64 v);
00435
00436
00437
00438
00439 gchar *sha1_base32(const gchar *sha1);
00440 gchar *base32_sha1(const gchar *base32);
00441
00442
00443
00444
00445 gchar *guid_hex_str(const gchar *guid);
00446 gboolean hex_to_guid(const gchar *hexguid, gchar *guid);
00447
00448
00449
00450
00451 gchar *guid_base32_str(const gchar *guid);
00452 gchar *base32_to_guid(const gchar *base32);
00453
00454
00455
00456
00457 gboolean is_absolute_path(const char *);
00458 gboolean is_directory(const gchar *);
00459 gboolean is_regular(const gchar *);
00460 gboolean is_symlink(const gchar *);
00461 gboolean file_exists(const gchar *);
00462 guint32 next_pow2(guint32 n);
00463
00470 static inline G_GNUC_CONST gboolean
00471 is_pow2(guint32 value)
00472 #ifdef HAVE_BUILTIN_POPCOUNT
00473 {
00474 return 0 == __builtin_popcount(value);
00475 }
00476 #else
00477 {
00478 return value && !(value & (value - 1));
00479 }
00480 #endif
00481
00482
00483
00484
00485 void random_init(void);
00486 guint32 random_value(guint32 max) WARN_UNUSED_RESULT;
00487 void guid_random_fill(gchar *xuid);
00488
00489
00490
00491
00492 void misc_init(void);
00493 gint str_chomp(gchar *str, gint len);
00494 gint hex2int(guchar c);
00495 gboolean is_printable(const gchar *buf, gint len);
00496 void dump_hex(FILE *, const gchar *, gconstpointer, gint);
00497 void locale_strlower(gchar *, const gchar *);
00498 void ascii_strlower(gchar *dst, const gchar *src);
00499 gint strcmp_delimit(const gchar *a, const gchar *b, const gchar *delimit);
00500 gint strcasecmp_delimit(const gchar *a, const gchar *b, const gchar *delimit);
00501 char *unique_filename(const gchar *path, const gchar *file, const gchar *ext);
00502 gchar *hex_escape(const gchar *name, gboolean strict);
00503 gchar *control_escape(const gchar *s);
00504 const gchar *lazy_string_to_printf_escape(const gchar *src);
00505 gint highest_bit_set(guint32 n) G_GNUC_CONST;
00506 gfloat force_range(gfloat value, gfloat min, gfloat max);
00507 gchar *make_pathname(const gchar *dir, const gchar *file);
00508 gchar *short_filename(gchar *fullname);
00509 gchar *data_hex_str(const gchar *data, size_t len);
00510 gint create_directory(const gchar *dir);
00511 gboolean filepath_exists(const gchar *dir, const gchar *file);
00512 guint16 parse_uint16(const gchar *, gchar const **, guint, gint *)
00513 NON_NULL_PARAM((1, 4));
00514 guint32 parse_uint32(const gchar *, gchar const **, guint, gint *)
00515 NON_NULL_PARAM((1, 4));
00516 guint64 parse_uint64(const gchar *, gchar const **, guint, gint *)
00517 NON_NULL_PARAM((1, 4));
00518 size_t uint32_to_string_buf(guint64 v, gchar *dst, size_t size);
00519 size_t uint64_to_string_buf(guint64 v, gchar *dst, size_t size);
00520 const gchar *uint32_to_string(guint32 v);
00521 const gchar *uint64_to_string(guint64 v);
00522 const gchar *uint64_to_string2(guint64 v);
00523 gint parse_major_minor(const gchar *src, gchar const **endptr,
00524 guint *major, guint *minor);
00525 gchar *is_strprefix(const gchar *s, const gchar *prefix) WARN_UNUSED_RESULT;
00526 gchar *is_strcaseprefix(const gchar *s, const gchar *prefix) WARN_UNUSED_RESULT;
00527 size_t html_escape(const gchar *src, gchar *dst, size_t dst_size);
00528 gint canonize_path(gchar *dst, const gchar *path);
00529 guint compat_max_fd(void);
00530 gint compat_mkdir(const gchar *path, mode_t mode);
00531 size_t compat_pagesize(void);
00532 gpointer compat_page_align(size_t size);
00533 void compat_page_free(gpointer p, size_t size);
00534 gboolean compat_is_superuser(void);
00535
00536 typedef void (*signal_handler_t)(gint signo);
00537 signal_handler_t set_signal(gint signo, signal_handler_t handler);
00538
00539 gchar *ascii_strcasestr(const gchar *haystack, const gchar *needle);
00540
00541 #define NULL_STRING(s) (NULL != (s) ? (s) : "(null)")
00542 #define EMPTY_STRING(s) (NULL != (s) ? (s) : "")
00543
00551 static inline G_GNUC_CONST guint32
00552 swap_guint32(guint32 i)
00553 {
00554 gint a = i & 0x000000ff;
00555 gint b = (i & 0x0000ff00) >> 8;
00556 gint c = (i & 0x00ff0000) >> 16;
00557 gint d = (i & 0xff000000) >> 24;
00558
00559 return d + (c << 8) + (b << 16) + (a << 24);
00560 }
00561
00570 static inline G_GNUC_CONST WARN_UNUSED_RESULT guint8
00571 netmask_to_cidr(guint32 netmask)
00572 #ifdef HAVE_BUILTIN_POPCOUNT
00573 {
00574 __builtin_popcount(netmask);
00575 }
00576 #else
00577 {
00578 guint8 bits = 32;
00579
00580 while (0 == (netmask & 0x1)) {
00581 netmask >>= 1;
00582 bits--;
00583 }
00584 return bits;
00585 }
00586 #endif
00587
00591 static inline size_t
00592 round_size(size_t align, size_t n)
00593 {
00594 size_t m = n % align;
00595 return m ? n + (align - m) : MAX(n, align);
00596 }
00597
00598
00599
00600
00601
00602 struct stat;
00603
00604 extern gint do_errno;
00605
00606 gint do_stat(const gchar *path, struct stat *buf);
00607
00608
00609
00610
00611
00612 typedef void (*cidr_split_t)(guint32 ip, guint bits, gpointer udata);
00613
00614 void ip_range_split(
00615 guint32 lower_ip, guint32 upper_ip, cidr_split_t cb, gpointer udata);
00616
00630 #define BINARY_SEARCH(bs_type, bs_key, bs_size, bs_cmp, bs_get_key, bs_found) \
00631 G_STMT_START { \
00632 size_t bs_index, bs_j = 0, bs_k; \
00633 for (bs_k = (bs_size); bs_k != 0; bs_k >>= 1) { \
00634 bs_type bs_item; \
00635 gint bs_cmp_result; \
00636 \
00637 bs_index = bs_j + (bs_k >> 1); \
00638 bs_item = bs_get_key(bs_index); \
00639 bs_cmp_result = bs_cmp(bs_item, bs_key); \
00640 if (0 == bs_cmp_result) { \
00641 bs_found(bs_index); \
00642 break; \
00643 } else if (bs_cmp_result < 0) { \
00644 bs_j = bs_index + 1; \
00645 bs_k--; \
00646 } \
00647 } \
00648 } G_STMT_END
00649
00662 #define BINARY_ARRAY_SORTED(bs_array, bs_type, bs_field, bs_cmp, bs_field2str) \
00663 G_STMT_START { \
00664 size_t bs_index; \
00665 size_t bs_size = G_N_ELEMENTS(bs_array); \
00666 \
00667 for (bs_index = 1; bs_index < bs_size; bs_index++) { \
00668 const bs_type *prev = &bs_array[bs_index - 1]; \
00669 const bs_type *e = &bs_array[bs_index]; \
00670 \
00671 if (bs_cmp(prev->bs_field, e->bs_field) >= 0) \
00672 g_error(STRINGIFY(bs_array) "[] unsorted (near item \"%s\")", \
00673 bs_field2str(e->bs_field)); \
00674 } \
00675 } G_STMT_END
00676
00677 #endif
00678
00679