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 "common.h"
00054
00055 #include "vmm.h"
00056
00057 #define SIZE_FIELD_MAX 64
00058 #define GUID_RAW_SIZE 16
00059 #define GUID_HEX_SIZE 32
00060 #define GUID_BASE32_SIZE 26
00062 typedef struct short_string {
00063 gchar str[SIZE_FIELD_MAX];
00064 } short_string_t;
00065
00069 #ifndef USE_GLIB2
00070
00071 #ifndef HAS_STRLCPY
00072 size_t strlcpy(gchar *dst, const gchar *src, size_t dst_size);
00073 #endif
00074
00075 #ifndef HAS_STRLCAT
00076 size_t strlcat(gchar *dst, const gchar *src, size_t dst_size);
00077 #endif
00078
00079 #define g_string_printf g_string_sprintf
00080 #define g_strlcpy strlcpy
00081 #define g_strlcat strlcat
00082 #endif
00083
00084 size_t concat_strings(gchar *dst, size_t size,
00085 const gchar *s, ...) G_GNUC_NULL_TERMINATED;
00086 size_t w_concat_strings(gchar **dst,
00087 const gchar *first, ...) G_GNUC_NULL_TERMINATED;
00088
00089 gint ascii_strcasecmp(const gchar *s1, const gchar *s2);
00090 gint ascii_strncasecmp(const gchar *s1, const gchar *s2, size_t len);
00091
00099 static inline guchar
00100 hex_digit(guchar x)
00101 {
00102 extern const char hex_alphabet_lower[];
00103 return hex_alphabet_lower[x & 0xf];
00104 }
00105
00112 static inline gint
00113 hex2int_inline(guchar c)
00114 {
00115 extern const gint8 *hex2int_tab;
00116 return hex2int_tab[c];
00117 }
00118
00125 static inline gint
00126 dec2int_inline(guchar c)
00127 {
00128 extern const gint8 *dec2int_tab;
00129 return dec2int_tab[c];
00130 }
00131
00138 static inline gint
00139 alnum2int_inline(guchar c)
00140 {
00141 extern const gint8 *alnum2int_tab;
00142 return alnum2int_tab[c];
00143 }
00144
00153 static inline G_GNUC_CONST WARN_UNUSED_RESULT gboolean
00154 is_ascii_blank(gint c)
00155 {
00156 return c == 32 || c == 9;
00157 }
00158
00159 static inline G_GNUC_CONST WARN_UNUSED_RESULT gboolean
00160 is_ascii_cntrl(gint c)
00161 {
00162 return (c >= 0 && c <= 31) || c == 127;
00163 }
00164
00165 static inline G_GNUC_CONST WARN_UNUSED_RESULT gboolean
00166 is_ascii_digit(gint c)
00167 {
00168 return c >= 48 && c <= 57;
00169 }
00170
00171 static inline G_GNUC_CONST WARN_UNUSED_RESULT gboolean
00172 is_ascii_xdigit(gint c)
00173 {
00174 return -1 != hex2int_inline(c) && !(c & ~0x7f);
00175 }
00176
00177 static inline G_GNUC_CONST WARN_UNUSED_RESULT gboolean
00178 is_ascii_upper(gint c)
00179 {
00180 return c >= 65 && c <= 90;
00181 }
00182
00183 static inline G_GNUC_CONST WARN_UNUSED_RESULT gboolean
00184 is_ascii_lower(gint c)
00185 {
00186 return c >= 97 && c <= 122;
00187 }
00188
00189 static inline G_GNUC_CONST WARN_UNUSED_RESULT gboolean
00190 is_ascii_alpha(gint c)
00191 {
00192 return is_ascii_upper(c) || is_ascii_lower(c);
00193 }
00194
00195 static inline G_GNUC_CONST WARN_UNUSED_RESULT gboolean
00196 is_ascii_alnum(gint c)
00197 {
00198 return -1 != alnum2int_inline(c) && !(c & ~0x7f);
00199 }
00200
00201 static inline G_GNUC_CONST WARN_UNUSED_RESULT gboolean
00202 is_ascii_space(gint c)
00203 {
00204 return c == 32 || (c >= 9 && c <= 13);
00205 }
00206
00207 static inline G_GNUC_CONST WARN_UNUSED_RESULT gboolean
00208 is_ascii_graph(gint c)
00209 {
00210 return c >= 33 && c <= 126;
00211 }
00212
00213 static inline G_GNUC_CONST WARN_UNUSED_RESULT gboolean
00214 is_ascii_print(gint c)
00215 {
00216 return is_ascii_graph(c) || c == 32;
00217 }
00218
00219 static inline G_GNUC_CONST WARN_UNUSED_RESULT gboolean
00220 is_ascii_punct(gint c)
00221 {
00222 return c >= 33 && c <= 126 && !is_ascii_alnum(c);
00223 }
00224
00225 static inline G_GNUC_CONST WARN_UNUSED_RESULT gint
00226 ascii_toupper(gint c)
00227 {
00228 return is_ascii_lower(c) ? c - 32 : c;
00229 }
00230
00231 static inline G_GNUC_CONST WARN_UNUSED_RESULT gint
00232 ascii_tolower(gint c)
00233 {
00234 return is_ascii_upper(c) ? c + 32 : c;
00235 }
00236
00237 #if !GLIB_CHECK_VERSION(2,4,0)
00238 static inline WARN_UNUSED_RESULT const gchar *
00239 g_strip_context(const gchar *id, const gchar *val)
00240 {
00241 const gchar *s;
00242
00243 s = id != val ? NULL : strchr(id, '|');
00244 return s ? ++s : val;
00245 }
00246 #endif
00247
00253 static inline WARN_UNUSED_RESULT gchar *
00254 skip_ascii_spaces(const gchar *s)
00255 {
00256 while (is_ascii_space(*s))
00257 s++;
00258
00259 return deconstify_gchar(s);
00260 }
00261
00267 static inline WARN_UNUSED_RESULT gchar *
00268 skip_ascii_non_spaces(const gchar *s)
00269 {
00270 while ('\0' != *s && !is_ascii_space(*s))
00271 s++;
00272
00273 return deconstify_gchar(s);
00274 }
00275
00282 static inline WARN_UNUSED_RESULT gchar *
00283 skip_ascii_alnum(const gchar *s)
00284 {
00285 while (is_ascii_alnum(*s))
00286 s++;
00287
00288 return deconstify_gchar(s);
00289 }
00290
00296 static inline WARN_UNUSED_RESULT gchar *
00297 skip_ascii_blanks(const gchar *s)
00298 {
00299 while (is_ascii_blank(*s))
00300 s++;
00301
00302 return deconstify_gchar(s);
00303 }
00304
00305 static inline WARN_UNUSED_RESULT gchar *
00306 skip_dir_separators(const gchar *s)
00307 {
00308 while ('/' == s[0] || G_DIR_SEPARATOR == s[0])
00309 s++;
00310
00311 return deconstify_gchar(s);
00312 }
00313
00314
00315
00316
00317 #define CONST_STRLEN(x) (sizeof(x) - 1)
00318
00319
00320
00321
00322 typedef guint16 flag_t;
00323 #define set_flags(r,f) (r |= (f))
00324 #define clear_flags(r,f) (r &= ~(f))
00325
00326
00327
00328
00329
00330 #define UINT8_HEX_BUFLEN (sizeof "FF")
00331 #define UINT8_DEC_BUFLEN (sizeof "255")
00332 #define UINT16_HEX_BUFLEN (sizeof "01234")
00333 #define UINT16_DEC_BUFLEN (sizeof "65535")
00334 #define UINT32_HEX_BUFLEN (sizeof "012345678")
00335 #define UINT32_DEC_BUFLEN (sizeof "4294967295")
00336 #define UINT64_HEX_BUFLEN (sizeof "0123456789ABCDEF")
00337 #define UINT64_DEC_BUFLEN (sizeof "18446744073709551615")
00338 #define IPV4_ADDR_BUFLEN (sizeof "255.255.255.255")
00339 #define IPV6_ADDR_BUFLEN \
00340 (sizeof "0001:0203:0405:0607:0809:1011:255.255.255.255")
00341 #define TIMESTAMP_BUF_LEN (sizeof "9999-12-31 23:59:61")
00342 #define OFF_T_DEC_BUFLEN (sizeof(off_t) * CHAR_BIT)
00343 #define TIME_T_DEC_BUFLEN (sizeof(time_t) * CHAR_BIT)
00344
00345 #define HOST_ADDR_BUFLEN (MAX(IPV4_ADDR_BUFLEN, IPV6_ADDR_BUFLEN))
00346 #define HOST_ADDR_PORT_BUFLEN (HOST_ADDR_BUFLEN + sizeof ":[65535]")
00347
00348 gboolean parse_ipv6_addr(const gchar *s, uint8_t *dst, const gchar **endptr);
00349 const gchar *ipv6_to_string(const guint8 *ipv6);
00350 size_t ipv6_to_string_buf(const guint8 *ipv6, gchar *dst, size_t size);
00351
00352
00353
00354
00355 guint32 string_to_ip(const gchar *);
00356 gboolean string_to_ip_strict(const gchar *s, guint32 *addr, const gchar **ep);
00357 gboolean string_to_ip_and_mask(const gchar *str, guint32 *ip, guint32 *netmask);
00358 gboolean string_to_ip_port(const gchar *str, guint32 *ip, guint16 *port);
00359 const gchar *ip_to_string(guint32);
00360 size_t ipv4_to_string_buf(guint32 ip, gchar *buf, size_t size);
00361 const gchar *hostname_port_to_string(const gchar *hostname, guint16 port);
00362 const gchar *local_hostname(void);
00363 #define port_is_valid(port) (port != 0)
00364
00365
00366
00367
00368 const gchar *timestamp_to_string(time_t date);
00369 const gchar *timestamp_utc_to_string(time_t date);
00370 const gchar *timestamp_rfc822_to_string(time_t date);
00371 const gchar *timestamp_rfc822_to_string2(time_t date);
00372 const gchar *timestamp_rfc1123_to_string(time_t date);
00373
00374 size_t timestamp_to_string_buf(time_t date, gchar *dst, size_t size);
00375 size_t time_locale_to_string_buf(time_t date, gchar *dst, size_t size);
00376
00377 short_string_t timestamp_get_string(time_t date);
00378
00379
00380
00381
00382
00383
00384 #if defined(USE_DIFFTIME)
00385 typedef gint64 time_delta_t;
00386
00387 static inline time_delta_t
00388 delta_time(time_t t1, time_t t0)
00389 {
00390 return difftime(t1, t0);
00391 }
00392 #else
00393 typedef time_t time_delta_t;
00394
00395 static inline time_delta_t
00396 delta_time(time_t t1, time_t t0)
00397 {
00398 return t1 - t0;
00399 }
00400
00401 static inline void
00402 time_t_check(void)
00403 {
00404
00405
00406 STATIC_ASSERT((time_t) -1 < 0);
00407 }
00408 #endif
00409
00416 static inline time_t
00417 time_advance(time_t t, gulong delta)
00418 {
00419
00420
00421
00422
00423
00424
00425 do {
00426 glong d;
00427
00428 d = MIN(delta, (gulong) LONG_MAX);
00429 if (d >= TIME_T_MAX - t) {
00430 t = TIME_T_MAX;
00431 break;
00432 }
00433 t += d;
00434 delta -= d;
00435 } while (delta > 0);
00436
00437 return t;
00438 }
00439
00440
00441
00442
00443 const gchar *short_time(time_delta_t s);
00444 const gchar *short_time_ascii(time_delta_t t);
00445 const gchar *short_uptime(time_delta_t s);
00446 const gchar *compact_time(time_delta_t t);
00447
00448
00449
00450
00451 const gchar *short_size(guint64 size, gboolean metric);
00452 const gchar *short_html_size(guint64 size, gboolean metric);
00453 const gchar *short_kb_size(guint64 size, gboolean metric);
00454 const gchar *short_rate(guint64 rate, gboolean metric);
00455 const gchar *compact_size(guint64 size, gboolean metric);
00456 const gchar *compact_rate(guint64 rate, gboolean metric);
00457 const gchar *compact_kb_size(guint32 size, gboolean metric);
00458 gchar *short_value(gchar *buf, size_t size, guint64 v, gboolean metric);
00459 gchar *compact_value(gchar *buf, size_t size, guint64 v, gboolean metric);
00460
00461 short_string_t short_rate_get_string(guint64 rate, gboolean metric);
00462
00463
00464
00465
00466 typedef struct sha1 {
00467 gchar data[SHA1_RAW_SIZE];
00468 } sha1_t;
00469
00470 const gchar *sha1_to_string(const struct sha1 sha1);
00471 const gchar *sha1_to_urn_string(const struct sha1 *sha1);
00472 gchar *sha1_to_base32_buf(const struct sha1 *sha1, gchar *dst, size_t size);
00473 const gchar *sha1_base32(const struct sha1 *sha1);
00474 const struct sha1 *base32_sha1(const gchar *base32);
00475
00476 static inline int
00477 sha1_cmp(const struct sha1 *a, const struct sha1 *b)
00478 {
00479 return memcmp(a, b, SHA1_RAW_SIZE);
00480 }
00481
00482
00483
00484
00485 typedef struct tth {
00486 gchar data[TTH_RAW_SIZE];
00487 } tth_t;
00488
00489 const gchar *tth_base32(const struct tth *tth);
00490 const struct tth *base32_tth(const gchar *base32);
00491
00492
00493 const gchar *bitprint_to_urn_string(const struct sha1 *, const struct tth *);
00494
00495
00496
00497
00498 const gchar *guid_hex_str(const gchar *guid);
00499 gboolean hex_to_guid(const gchar *hexguid, gchar *guid);
00500 size_t guid_to_string_buf(const gchar *guid, gchar *dst, size_t size);
00501 const gchar *guid_to_string(const gchar *guid);
00502
00503
00504
00505
00506 gchar *guid_base32_str(const gchar *guid);
00507 gchar *base32_to_guid(const gchar *base32);
00508
00509
00510
00511
00512 gboolean is_absolute_path(const char *pathname);
00513 gboolean is_directory(const gchar *pathname);
00514 gboolean is_regular(const gchar *pathname);
00515 gboolean is_symlink(const gchar *pathname);
00516 gboolean file_exists(const gchar *pathname);
00517 gboolean file_does_not_exist(const gchar *pathname);
00518 guint32 next_pow2(guint32 n);
00519
00520 #define IS_POWER_OF_2(x) ((x) && 0 == ((x) & ((x) - 1)))
00521
00527 static inline G_GNUC_CONST gboolean
00528 is_pow2(guint32 value)
00529 #ifdef HAS_BUILTIN_POPCOUNT
00530 {
00531 return 1 == __builtin_popcount(value);
00532 }
00533 #else
00534 {
00535 return IS_POWER_OF_2(value);
00536 }
00537 #endif
00538
00539
00540
00541
00542 void random_init(void);
00543 guint32 random_value(guint32 max) WARN_UNUSED_RESULT;
00544 guint32 random_raw(void) WARN_UNUSED_RESULT;
00545 void guid_random_fill(gchar *xuid);
00546
00547
00548
00549
00550 void misc_init(void);
00551 size_t str_chomp(gchar *str, size_t len);
00552 gint hex2int(guchar c);
00553 gboolean is_printable(const gchar *buf, gint len);
00554 void dump_hex(FILE *, const gchar *, gconstpointer, gint);
00555 void locale_strlower(gchar *, const gchar *);
00556 void ascii_strlower(gchar *dst, const gchar *src);
00557 gint strcmp_delimit(const gchar *a, const gchar *b, const gchar *delimit);
00558 gint ascii_strcasecmp_delimit(const gchar *a, const gchar *b,
00559 const gchar *delimit);
00560 size_t filename_shrink(const gchar *filename, gchar *buf, size_t size);
00561 char *unique_filename(const gchar *path, const gchar *file, const gchar *ext,
00562 gboolean (*name_is_uniq)(const gchar *pathname));
00563 gchar *hex_escape(const gchar *name, gboolean strict);
00564 gchar *control_escape(const gchar *s);
00565 const gchar *lazy_string_to_printf_escape(const gchar *src);
00566 gint highest_bit_set(guint32 n) G_GNUC_CONST;
00567 gfloat force_range(gfloat value, gfloat min, gfloat max);
00568 gchar *absolute_pathname(const gchar *file);
00569 gchar *make_pathname(const gchar *dir, const gchar *file);
00570 gchar *short_filename(gchar *fullname);
00571 gchar *data_hex_str(const gchar *data, size_t len);
00572
00573 #if defined(S_IROTH) && defined(S_IXOTH)
00574
00575 #define DEFAULT_DIRECTORY_MODE (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH)
00576 #else
00577
00578 #define DEFAULT_DIRECTORY_MODE (S_IRWXU | S_IRGRP | S_IXGRP)
00579 #endif
00580
00581 gint create_directory(const gchar *dir, mode_t mode);
00582 gint compat_mkdir(const gchar *path, mode_t mode);
00583 gboolean filepath_exists(const gchar *dir, const gchar *file);
00584 const gchar * filepath_basename(const gchar *pathname);
00585 gchar * filepath_directory(const gchar *pathname);
00586 guint16 parse_uint16(const gchar *, gchar const **, guint, gint *)
00587 NON_NULL_PARAM((1, 4));
00588 guint32 parse_uint32(const gchar *, gchar const **, guint, gint *)
00589 NON_NULL_PARAM((1, 4));
00590 guint64 parse_uint64(const gchar *, gchar const **, guint, gint *)
00591 NON_NULL_PARAM((1, 4));
00592 size_t uint32_to_string_buf(guint32 v, gchar *dst, size_t size);
00593 size_t uint64_to_string_buf(guint64 v, gchar *dst, size_t size);
00594 size_t off_t_to_string_buf(off_t v, gchar *dst, size_t size);
00595 size_t time_t_to_string_buf(time_t v, gchar *dst, size_t size);
00596 const gchar *uint32_to_string(guint32 v);
00597 const gchar *uint64_to_string(guint64 v);
00598 const gchar *uint64_to_string2(guint64 v);
00599 const gchar *off_t_to_string(off_t v);
00600 const gchar *time_t_to_string(time_t v);
00601 const gchar *filesize_to_string(filesize_t v);
00602 gint parse_major_minor(const gchar *src, gchar const **endptr,
00603 guint *major, guint *minor);
00604 gchar *is_strprefix(const gchar *s, const gchar *prefix) WARN_UNUSED_RESULT;
00605 gchar *is_strcaseprefix(const gchar *s, const gchar *prefix) WARN_UNUSED_RESULT;
00606 size_t html_escape(const gchar *src, gchar *dst, size_t dst_size);
00607 guint32 html_decode_entity(const gchar *src, const gchar **endptr);
00608 gint canonize_path(gchar *dst, const gchar *path);
00609 guint compat_max_fd(void);
00610 void close_file_descriptors(const int first_fd);
00611 gboolean compat_is_superuser(void);
00612 int compat_daemonize(const char *directory);
00613 void set_close_on_exec(gint fd);
00614 void compat_fadvise_sequential(int fd, off_t offset, off_t size);
00615 void *compat_memmem(const void *data, size_t data_size,
00616 const void *pattern, size_t pattern_size);
00617
00618 int get_non_stdio_fd(int fd);
00619
00620 typedef void (*signal_handler_t)(gint signo);
00621 signal_handler_t set_signal(gint signo, signal_handler_t handler);
00622
00623 gchar *ascii_strcasestr(const gchar *haystack, const gchar *needle);
00624 gchar *normalize_dir_separators(const gchar *s);
00625 size_t memcmp_diff(const void *a, const void *b, size_t n);
00626 guint32 cpu_noise(void);
00627
00628 static inline guint
00629 pointer_hash_func(const void *p)
00630 {
00631 size_t v = (size_t) p;
00632 return (((guint64) 0x4F1BBCDCUL * v) >> 32) ^ v;
00633 }
00634
00635 static inline guint
00636 str_case_hash_func(gconstpointer key)
00637 {
00638 const guchar *s = key;
00639 gulong c, hash = 0;
00640
00641 while ((c = ascii_tolower(*s++))) {
00642 hash ^= (hash << 8) | c;
00643 }
00644 return hash ^ (((guint64) 1048573 * hash) >> 32);
00645 }
00646
00647 static inline gint
00648 str_case_eq_func(gconstpointer a, gconstpointer b)
00649 {
00650 return 0 == ascii_strcasecmp(a, b);
00651 }
00652
00662 static inline size_t
00663 clamp_strlen(const gchar *src, size_t src_size)
00664 {
00665 const gchar *p;
00666
00667 p = memchr(src, '\0', src_size);
00668 return (p ? p : &src[src_size]) - src;
00669 }
00670
00671 static inline const gchar *
00672 NULL_STRING(const gchar *s)
00673 {
00674 return NULL != s ? s : "(null)";
00675 }
00676
00677 static inline const gchar *
00678 EMPTY_STRING(const gchar *s)
00679 {
00680 return NULL != s ? s : "";
00681 }
00682
00690 static inline G_GNUC_CONST guint32
00691 swap_guint32(guint32 i)
00692 {
00693 guint32 a;
00694 guint32 b;
00695
00696 a = (i & 0x00ff00ff) << 8;
00697 b = (i & 0xff00ff00) >> 8;
00698 i = a | b;
00699 i = (i << 16) | (i >> 16);
00700
00701 return i;
00702 }
00703
00712 static inline G_GNUC_CONST WARN_UNUSED_RESULT guint8
00713 netmask_to_cidr(guint32 netmask)
00714 #ifdef HAVE_BUILTIN_POPCOUNT
00715 {
00716 __builtin_popcount(netmask);
00717 }
00718 #else
00719 {
00720 guint8 bits = 32;
00721
00722 while (0 == (netmask & 0x1)) {
00723 netmask >>= 1;
00724 bits--;
00725 }
00726 return bits;
00727 }
00728 #endif
00729
00737 static inline G_GNUC_CONST WARN_UNUSED_RESULT guint32
00738 cidr_to_netmask(guint bits)
00739 {
00740 return (guint32)-1 << (32 - bits);
00741 }
00742
00746 static inline size_t
00747 round_size(size_t align, size_t n)
00748 {
00749 size_t m = n % align;
00750 return m ? n + (align - m) : MAX(n, align);
00751 }
00752
00753
00754
00755
00756
00757 struct stat;
00758
00759 extern gint do_errno;
00760
00761 gint do_stat(const gchar *path, struct stat *buf);
00762
00763 static inline gboolean
00764 is_temporary_error(gint error)
00765 {
00766 switch (error) {
00767 case EAGAIN:
00768 #if defined(EWOULDBLOCK) && EAGAIN != EWOULDBLOCK
00769 case EWOULDBLOCK:
00770 #endif
00771 case EINTR:
00772 return TRUE;
00773 }
00774 return FALSE;
00775 }
00776
00777
00778 gint seek_to_filepos(gint fd, filesize_t pos);
00779
00780 guint filesize_per_100(filesize_t size, filesize_t part);
00781 guint filesize_per_1000(filesize_t size, filesize_t part);
00782 guint filesize_per_10000(filesize_t size, filesize_t part);
00783
00784
00785
00786
00787
00788 typedef void (*cidr_split_t)(guint32 ip, guint bits, gpointer udata);
00789
00790 void ip_range_split(
00791 guint32 lower_ip, guint32 upper_ip, cidr_split_t cb, gpointer udata);
00792
00806 #define BINARY_SEARCH(bs_type, bs_key, bs_size, bs_cmp, bs_get_key, bs_found) \
00807 G_STMT_START { \
00808 size_t bs_index, bs_j = 0, bs_k; \
00809 for (bs_k = (bs_size); bs_k != 0; bs_k >>= 1) { \
00810 bs_type bs_item; \
00811 gint bs_cmp_result; \
00812 \
00813 bs_index = bs_j + (bs_k >> 1); \
00814 bs_item = bs_get_key(bs_index); \
00815 bs_cmp_result = bs_cmp(bs_item, bs_key); \
00816 if (0 == bs_cmp_result) { \
00817 bs_found(bs_index); \
00818 break; \
00819 } else if (bs_cmp_result < 0) { \
00820 bs_j = bs_index + 1; \
00821 bs_k--; \
00822 } \
00823 } \
00824 } G_STMT_END
00825
00838 #define BINARY_ARRAY_SORTED(bs_array, bs_type, bs_field, bs_cmp, bs_field2str) \
00839 G_STMT_START { \
00840 size_t bs_index; \
00841 size_t bs_size = G_N_ELEMENTS(bs_array); \
00842 \
00843 for (bs_index = 1; bs_index < bs_size; bs_index++) { \
00844 const bs_type *prev = &bs_array[bs_index - 1]; \
00845 const bs_type *e = &bs_array[bs_index]; \
00846 \
00847 if (bs_cmp(prev->bs_field, e->bs_field) >= 0) \
00848 g_error(STRINGIFY(bs_array) "[] unsorted (near item \"%s\")", \
00849 bs_field2str(e->bs_field)); \
00850 } \
00851 } G_STMT_END
00852
00853 static inline const char *
00854 print_number(char *dst, size_t size, unsigned long value)
00855 {
00856 char *p = &dst[size];
00857
00858 if (size > 0) {
00859 *--p = '\0';
00860 }
00861 while (p != dst) {
00862 *--p = (value % 10) + '0';
00863 value /= 10;
00864 if (0 == value)
00865 break;
00866 }
00867 return p;
00868 }
00869
00870 #endif
00871
00872