X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=lib%2Futil.c;h=845f86c9756364f6a91f628723fac3ca0f84c915;hb=bdd534291ff72077390f7b1745c4443ad3833d99;hp=9b79c2559cec55dad99c818810ed4b524dd616c4;hpb=481da12c8da103ce6b36e06b6b95064c872446a7;p=sliver-openvswitch.git diff --git a/lib/util.c b/lib/util.c index 9b79c2559..845f86c97 100644 --- a/lib/util.c +++ b/lib/util.c @@ -67,7 +67,7 @@ ovs_assert_failure(const char *where, const char *function, case 0: VLOG_ABORT("%s: assertion %s failed in %s()", where, condition, function); - NOT_REACHED(); + OVS_NOT_REACHED(); case 1: fprintf(stderr, "%s: assertion %s failed in %s()", @@ -373,11 +373,22 @@ void set_program_name__(const char *argv0, const char *version, const char *date, const char *time) { - const char *slash = strrchr(argv0, '/'); +#ifdef _WIN32 + char *basename; + size_t max_len = strlen(argv0) + 1; + if (program_name) { + return; + } + basename = xmalloc(max_len); + _splitpath_s(argv0, NULL, 0, NULL, 0, basename, max_len, NULL, 0); + assert_single_threaded(); + program_name = basename; +#else + const char *slash = strrchr(argv0, '/'); assert_single_threaded(); - program_name = slash ? slash + 1 : argv0; +#endif free(program_version); @@ -473,11 +484,11 @@ ovs_hex_dump(FILE *stream, const void *buf_, size_t size, n = end - start; /* Print line. */ - fprintf(stream, "%08jx ", (uintmax_t) ROUND_DOWN(ofs, per_line)); + fprintf(stream, "%08"PRIxMAX" ", (uintmax_t) ROUND_DOWN(ofs, per_line)); for (i = 0; i < start; i++) fprintf(stream, " "); for (; i < end; i++) - fprintf(stream, "%02hhx%c", + fprintf(stream, "%02x%c", buf[i - start], i == per_line / 2 - 1? '-' : ' '); if (ascii) { @@ -537,24 +548,6 @@ str_to_llong(const char *s, int base, long long *x) } } -bool -str_to_uint(const char *s, int base, unsigned int *u) -{ - return str_to_int(s, base, (int *) u); -} - -bool -str_to_ulong(const char *s, int base, unsigned long *ul) -{ - return str_to_long(s, base, (long *) ul); -} - -bool -str_to_ullong(const char *s, int base, unsigned long long *ull) -{ - return str_to_llong(s, base, (long long *) ull); -} - /* Converts floating-point string 's' into a double. If successful, stores * the double in '*d' and returns true; on failure, stores 0 in '*d' and * returns false. @@ -848,57 +841,16 @@ english_list_delimiter(size_t index, size_t total) : " and "); } -/* Given a 32 bit word 'n', calculates floor(log_2('n')). This is equivalent - * to finding the bit position of the most significant one bit in 'n'. It is - * an error to call this function with 'n' == 0. */ -int -log_2_floor(uint32_t n) -{ - ovs_assert(n); - -#if !defined(UINT_MAX) || !defined(UINT32_MAX) -#error "Someone screwed up the #includes." -#elif __GNUC__ >= 4 && UINT_MAX == UINT32_MAX - return 31 - __builtin_clz(n); -#else - { - int log = 0; - -#define BIN_SEARCH_STEP(BITS) \ - if (n >= (1 << BITS)) { \ - log += BITS; \ - n >>= BITS; \ - } - BIN_SEARCH_STEP(16); - BIN_SEARCH_STEP(8); - BIN_SEARCH_STEP(4); - BIN_SEARCH_STEP(2); - BIN_SEARCH_STEP(1); -#undef BIN_SEARCH_STEP - return log; - } -#endif -} - -/* Given a 32 bit word 'n', calculates ceil(log_2('n')). It is an error to - * call this function with 'n' == 0. */ -int -log_2_ceil(uint32_t n) -{ - return log_2_floor(n) + !is_pow2(n); -} - /* Returns the number of trailing 0-bits in 'n'. Undefined if 'n' == 0. */ -#if !defined(UINT_MAX) || !defined(UINT32_MAX) -#error "Someone screwed up the #includes." -#elif __GNUC__ >= 4 && UINT_MAX == UINT32_MAX +#if __GNUC__ >= 4 /* Defined inline in util.h. */ #else +/* Returns the number of trailing 0-bits in 'n'. Undefined if 'n' == 0. */ int -raw_ctz(uint32_t n) +raw_ctz(uint64_t n) { - unsigned int k; - int count = 31; + uint64_t k; + int count = 63; #define CTZ_STEP(X) \ k = n << (X); \ @@ -906,6 +858,7 @@ raw_ctz(uint32_t n) count -= X; \ n = k; \ } + CTZ_STEP(32); CTZ_STEP(16); CTZ_STEP(8); CTZ_STEP(4); @@ -915,16 +868,33 @@ raw_ctz(uint32_t n) return count; } -#endif -/* Returns the number of 1-bits in 'x', between 0 and 32 inclusive. */ -unsigned int -popcount(uint32_t x) +/* Returns the number of leading 0-bits in 'n'. Undefined if 'n' == 0. */ +int +raw_clz64(uint64_t n) { - /* In my testing, this implementation is over twice as fast as any other - * portable implementation that I tried, including GCC 4.4 - * __builtin_popcount(), although nonportable asm("popcnt") was over 50% - * faster. */ + uint64_t k; + int count = 63; + +#define CLZ_STEP(X) \ + k = n >> (X); \ + if (k) { \ + count -= X; \ + n = k; \ + } + CLZ_STEP(32); + CLZ_STEP(16); + CLZ_STEP(8); + CLZ_STEP(4); + CLZ_STEP(2); + CLZ_STEP(1); +#undef CLZ_STEP + + return count; +} +#endif + +#if NEED_COUNT_1BITS_8 #define INIT1(X) \ ((((X) & (1 << 0)) != 0) + \ (((X) & (1 << 1)) != 0) + \ @@ -941,15 +911,10 @@ popcount(uint32_t x) #define INIT32(X) INIT16(X), INIT16((X) + 16) #define INIT64(X) INIT32(X), INIT32((X) + 32) - static const uint8_t popcount8[256] = { - INIT64(0), INIT64(64), INIT64(128), INIT64(192) - }; - - return (popcount8[x & 0xff] + - popcount8[(x >> 8) & 0xff] + - popcount8[(x >> 16) & 0xff] + - popcount8[x >> 24]); -} +const uint8_t count_1bits_8[256] = { + INIT64(0), INIT64(64), INIT64(128), INIT64(192) +}; +#endif /* Returns true if the 'n' bytes starting at 'p' are zeros. */ bool @@ -1406,7 +1371,7 @@ scan_float(const char *s, const struct scan_spec *spec, va_list *args) case SCAN_INTMAX_T: case SCAN_PTRDIFF_T: case SCAN_SIZE_T: - NOT_REACHED(); + OVS_NOT_REACHED(); } return s; } @@ -1511,7 +1476,7 @@ scan_chars(const char *s, const struct scan_spec *spec, va_list *args) /* This is an implementation of the standard sscanf() function, with the * following exceptions: * - * - It returns true if the entire template was successfully scanned and + * - It returns true if the entire format was successfully scanned and * converted, false if any conversion failed. * * - The standard doesn't define sscanf() behavior when an out-of-range value @@ -1528,15 +1493,15 @@ scan_chars(const char *s, const struct scan_spec *spec, va_list *args) * - %p is not supported. */ bool -ovs_scan(const char *s, const char *template, ...) +ovs_scan(const char *s, const char *format, ...) { const char *const start = s; bool ok = false; const char *p; va_list args; - va_start(args, template); - p = template; + va_start(args, format); + p = format; while (*p != '\0') { struct scan_spec spec; unsigned char c = *p++; @@ -1688,3 +1653,19 @@ exit: return ok; } +#ifdef _WIN32 + +/* Calls FormatMessage() with GetLastError() as an argument. Returns + * pointer to a buffer that receives the null-terminated string that specifies + * the formatted message and that has to be freed by the caller with + * LocalFree(). */ +char * +ovs_lasterror_to_string(void) +{ + char *buffer; + FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM + | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), 0, + (char *)&buffer, 0, NULL); + return buffer; +} +#endif