/* Various utility functions.
- Copyright (C) 2003 Free Software Foundation, Inc.
+ Copyright (C) 2005 Free Software Foundation, Inc.
This file is part of GNU Wget.
return copy;
}
-/* Return a count of how many times CHR occurs in STRING. */
-
-int
-count_char (const char *string, char chr)
-{
- const char *p;
- int count = 0;
- for (p = string; *p; p++)
- if (*p == chr)
- ++count;
- return count;
-}
-
/* Copy the string formed by two pointers (one on the beginning, other
on the char after the last char) to a new, malloc-ed location.
0-terminate it. */
}
return NULL; /* unreached */
}
+
+/* Concatenate the NULL-terminated list of string arguments into
+ freshly allocated space. */
+
+char *
+concat_strings (const char *str0, ...)
+{
+ va_list args;
+ int saved_lengths[5]; /* inspired by Apache's apr_pstrcat */
+ char *ret, *p;
+
+ const char *next_str;
+ int total_length = 0;
+ int argcount;
+
+ /* Calculate the length of and allocate the resulting string. */
+
+ argcount = 0;
+ VA_START (args, str0);
+ for (next_str = str0; next_str != NULL; next_str = va_arg (args, char *))
+ {
+ int len = strlen (next_str);
+ if (argcount < countof (saved_lengths))
+ saved_lengths[argcount++] = len;
+ total_length += len;
+ }
+ va_end (args);
+ p = ret = xmalloc (total_length + 1);
+
+ /* Copy the strings into the allocated space. */
+
+ argcount = 0;
+ VA_START (args, str0);
+ for (next_str = str0; next_str != NULL; next_str = va_arg (args, char *))
+ {
+ int len;
+ if (argcount < countof (saved_lengths))
+ len = saved_lengths[argcount++];
+ else
+ len = strlen (next_str);
+ memcpy (p, next_str, len);
+ p += len;
+ }
+ va_end (args);
+ *p = '\0';
+
+ return ret;
+}
\f
/* Return pointer to a static char[] buffer in which zero-terminated
string-representation of TM (in form hh:mm:ss) is printed.
return NULL;
return fdopen (fd, binary ? "wb" : "w");
#else /* not O_EXCL */
+ /* Manually check whether the file exists. This is prone to race
+ conditions, but systems without O_EXCL haven't deserved
+ better. */
+ if (file_exists_p (fname))
+ {
+ errno = EEXIST;
+ return NULL;
+ }
return fopen (fname, binary ? "wb" : "w");
#endif /* not O_EXCL */
}
xfree (v2);
return v1;
}
-
-/* A set of simple-minded routines to store strings in a linked list.
- This used to also be used for searching, but now we have hash
- tables for that. */
-
-/* It's a shame that these simple things like linked lists and hash
- tables (see hash.c) need to be implemented over and over again. It
- would be nice to be able to use the routines from glib -- see
- www.gtk.org for details. However, that would make Wget depend on
- glib, and I want to avoid dependencies to external libraries for
- reasons of convenience and portability (I suspect Wget is more
- portable than anything ever written for Gnome). */
-
-/* Append an element to the list. If the list has a huge number of
- elements, this can get slow because it has to find the list's
- ending. If you think you have to call slist_append in a loop,
- think about calling slist_prepend() followed by slist_nreverse(). */
-
-slist *
-slist_append (slist *l, const char *s)
-{
- slist *newel = xnew (slist);
- slist *beg = l;
-
- newel->string = xstrdup (s);
- newel->next = NULL;
-
- if (!l)
- return newel;
- /* Find the last element. */
- while (l->next)
- l = l->next;
- l->next = newel;
- return beg;
-}
-
-/* Prepend S to the list. Unlike slist_append(), this is O(1). */
-
-slist *
-slist_prepend (slist *l, const char *s)
-{
- slist *newel = xnew (slist);
- newel->string = xstrdup (s);
- newel->next = l;
- return newel;
-}
-
-/* Destructively reverse L. */
-
-slist *
-slist_nreverse (slist *l)
-{
- slist *prev = NULL;
- while (l)
- {
- slist *next = l->next;
- l->next = prev;
- prev = l;
- l = next;
- }
- return prev;
-}
-
-/* Is there a specific entry in the list? */
-int
-slist_contains (slist *l, const char *s)
-{
- for (; l; l = l->next)
- if (!strcmp (l->string, s))
- return 1;
- return 0;
-}
-
-/* Free the whole slist. */
-void
-slist_free (slist *l)
-{
- while (l)
- {
- slist *n = l->next;
- xfree (l->string);
- xfree (l);
- l = n;
- }
-}
\f
/* Sometimes it's useful to create "sets" of strings, i.e. special
hash tables where you want to store strings as keys and merely
return hash_table_contains (ht, s);
}
+static int
+string_set_to_array_mapper (void *key, void *value_ignored, void *arg)
+{
+ char ***arrayptr = (char ***) arg;
+ *(*arrayptr)++ = (char *) key;
+ return 0;
+}
+
+/* Convert the specified string set to array. ARRAY should be large
+ enough to hold hash_table_count(ht) char pointers. */
+
+void string_set_to_array (struct hash_table *ht, char **array)
+{
+ hash_table_map (ht, string_set_to_array_mapper, &array);
+}
+
static int
string_set_free_mapper (void *key, void *value_ignored, void *arg_ignored)
{
}
\f
-/* Engine for legible and legible_large_int; add thousand separators
- to numbers printed in strings. */
+/* Add thousand separators to a number already in string form. Used
+ by with_thousand_seps and with_thousand_seps_large. */
static char *
-legible_1 (const char *repr)
+add_thousand_seps (const char *repr)
{
static char outbuf[48];
int i, i1, mod;
return outbuf;
}
-/* Legible -- return a static pointer to the legibly printed wgint. */
+/* Return a static pointer to the number printed with thousand
+ separators inserted at the right places. */
char *
-legible (wgint l)
+with_thousand_seps (wgint l)
{
char inbuf[24];
/* Print the number into the buffer. */
number_to_string (inbuf, l);
- return legible_1 (inbuf);
+ return add_thousand_seps (inbuf);
}
/* Write a string representation of LARGE_INT NUMBER into the provided
- buffer. The buffer should be able to accept 24 characters,
- including the terminating zero.
+ buffer.
It would be dangerous to use sprintf, because the code wouldn't
work on a machine with gcc-provided long long support, but without
- libc support for "%lld". However, such platforms will typically
- not have snprintf and will use our version, which does support
- "%lld" where long longs are available. */
+ libc support for "%lld". However, such old systems platforms
+ typically lack snprintf and will end up using our version, which
+ does support "%lld" whereever long longs are available. */
static void
-large_int_to_string (char *buffer, LARGE_INT number)
+large_int_to_string (char *buffer, int bufsize, LARGE_INT number)
{
- snprintf (buffer, 24, LARGE_INT_FMT, number);
+ snprintf (buffer, bufsize, LARGE_INT_FMT, number);
}
-/* The same as legible(), but works on LARGE_INT. */
+/* The same as with_thousand_seps, but works on LARGE_INT. */
char *
-legible_large_int (LARGE_INT l)
+with_thousand_seps_large (LARGE_INT l)
{
char inbuf[48];
- large_int_to_string (inbuf, l);
- return legible_1 (inbuf);
+ large_int_to_string (inbuf, sizeof (inbuf), l);
+ return add_thousand_seps (inbuf);
}
-/* Count the digits in an integer number. */
+/* N, a byte quantity, is converted to a human-readable abberviated
+ form a la sizes printed by `ls -lh'. The result is written to a
+ static buffer, a pointer to which is returned.
+
+ Unlike `with_thousand_seps', this approximates to the nearest unit.
+ Quoting GNU libit: "Most people visually process strings of 3-4
+ digits effectively, but longer strings of digits are more prone to
+ misinterpretation. Hence, converting to an abbreviated form
+ usually improves readability."
+
+ This intentionally uses kilobyte (KB), megabyte (MB), etc. in their
+ original computer science meaning of "multiples of 1024".
+ Multiples of 1000 would be useless since Wget already adds thousand
+ separators for legibility. We don't use the "*bibyte" names
+ invented in 1998, and seldom used in practice. Wikipedia's entry
+ on kilobyte discusses this in some detail. */
+
+char *
+human_readable (wgint n)
+{
+ /* These suffixes are compatible with those of GNU `ls -lh'. */
+ static char powers[] =
+ {
+ 'K', /* kilobyte, 2^10 bytes */
+ 'M', /* megabyte, 2^20 bytes */
+ 'G', /* gigabyte, 2^30 bytes */
+ 'T', /* terabyte, 2^40 bytes */
+ 'P', /* petabyte, 2^50 bytes */
+ 'E', /* exabyte, 2^60 bytes */
+ };
+ static char buf[8];
+ int i;
+
+ /* If the quantity is smaller than 1K, just print it. */
+ if (n < 1024)
+ {
+ snprintf (buf, sizeof (buf), "%d", (int) n);
+ return buf;
+ }
+
+ /* Loop over powers, dividing N with 1024 in each iteration. This
+ works unchanged for all sizes of wgint, while still avoiding
+ non-portable `long double' arithmetic. */
+ for (i = 0; i < countof (powers); i++)
+ {
+ /* At each iteration N is greater than the *subsequent* power.
+ That way N/1024.0 produces a decimal number in the units of
+ *this* power. */
+ if ((n >> 10) < 1024 || i == countof (powers) - 1)
+ {
+ /* Must cast to long first because MS VC can't directly cast
+ __int64 to double. (This is safe because N is known to
+ be <2**20.) */
+ double val = (double) (long) n / 1024.0;
+ /* Print values smaller than 10 with one decimal digits, and
+ others without any decimals. */
+ snprintf (buf, sizeof (buf), "%.*f%c",
+ val < 10 ? 1 : 0, val, powers[i]);
+ return buf;
+ }
+ n >>= 10;
+ }
+ return NULL; /* unreached */
+}
+
+/* Count the digits in the provided number. Used to allocate space
+ when printing numbers. */
+
int
numdigit (wgint number)
{
int cnt = 1;
if (number < 0)
- {
- number = -number;
- ++cnt;
- }
- while ((number /= 10) > 0)
+ ++cnt; /* accomodate '-' */
+ while ((number /= 10) != 0)
++cnt;
return cnt;
}
-#define ONE_DIGIT(figure) *p++ = n / (figure) + '0'
-#define ONE_DIGIT_ADVANCE(figure) (ONE_DIGIT (figure), n %= (figure))
-
-#define DIGITS_1(figure) ONE_DIGIT (figure)
-#define DIGITS_2(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_1 ((figure) / 10)
-#define DIGITS_3(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_2 ((figure) / 10)
-#define DIGITS_4(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_3 ((figure) / 10)
-#define DIGITS_5(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_4 ((figure) / 10)
-#define DIGITS_6(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_5 ((figure) / 10)
-#define DIGITS_7(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_6 ((figure) / 10)
-#define DIGITS_8(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_7 ((figure) / 10)
-#define DIGITS_9(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_8 ((figure) / 10)
-#define DIGITS_10(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_9 ((figure) / 10)
-
-/* DIGITS_<11-20> are only used on machines with 64-bit numbers. */
-
-#define DIGITS_11(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_10 ((figure) / 10)
-#define DIGITS_12(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_11 ((figure) / 10)
-#define DIGITS_13(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_12 ((figure) / 10)
-#define DIGITS_14(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_13 ((figure) / 10)
-#define DIGITS_15(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_14 ((figure) / 10)
-#define DIGITS_16(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_15 ((figure) / 10)
-#define DIGITS_17(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_16 ((figure) / 10)
-#define DIGITS_18(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_17 ((figure) / 10)
-#define DIGITS_19(figure) ONE_DIGIT_ADVANCE (figure); DIGITS_18 ((figure) / 10)
-
-/* It is annoying that we have three different syntaxes for 64-bit constants:
- - nnnL for 64-bit systems, where they are of type long;
- - nnnLL for 32-bit systems that support long long;
- - nnnI64 for MS compiler on Windows, which doesn't support long long. */
-
-#if SIZEOF_LONG > 4
-/* If long is large enough, use long constants. */
-# define C10000000000 10000000000L
-# define C100000000000 100000000000L
-# define C1000000000000 1000000000000L
-# define C10000000000000 10000000000000L
-# define C100000000000000 100000000000000L
-# define C1000000000000000 1000000000000000L
-# define C10000000000000000 10000000000000000L
-# define C100000000000000000 100000000000000000L
-# define C1000000000000000000 1000000000000000000L
-#else
-# if SIZEOF_LONG_LONG != 0
-/* Otherwise, if long long is available, use long long constants. */
-# define C10000000000 10000000000LL
-# define C100000000000 100000000000LL
-# define C1000000000000 1000000000000LL
-# define C10000000000000 10000000000000LL
-# define C100000000000000 100000000000000LL
-# define C1000000000000000 1000000000000000LL
-# define C10000000000000000 10000000000000000LL
-# define C100000000000000000 100000000000000000LL
-# define C1000000000000000000 1000000000000000000LL
-# else
-# if defined(WINDOWS)
-/* Use __int64 constants under Windows. */
-# define C10000000000 10000000000I64
-# define C100000000000 100000000000I64
-# define C1000000000000 1000000000000I64
-# define C10000000000000 10000000000000I64
-# define C100000000000000 100000000000000I64
-# define C1000000000000000 1000000000000000I64
-# define C10000000000000000 10000000000000000I64
-# define C100000000000000000 100000000000000000I64
-# define C1000000000000000000 1000000000000000000I64
-# endif
-# endif
-#endif
+#define PR(mask) *p++ = n / (mask) + '0'
+
+/* DIGITS_<D> is used to print a D-digit number and should be called
+ with mask==10^(D-1). It prints n/mask (the first digit), reducing
+ n to n%mask (the remaining digits), and calling DIGITS_<D-1>.
+ Recursively this continues until DIGITS_1 is invoked. */
+
+#define DIGITS_1(mask) PR (mask)
+#define DIGITS_2(mask) PR (mask), n %= (mask), DIGITS_1 ((mask) / 10)
+#define DIGITS_3(mask) PR (mask), n %= (mask), DIGITS_2 ((mask) / 10)
+#define DIGITS_4(mask) PR (mask), n %= (mask), DIGITS_3 ((mask) / 10)
+#define DIGITS_5(mask) PR (mask), n %= (mask), DIGITS_4 ((mask) / 10)
+#define DIGITS_6(mask) PR (mask), n %= (mask), DIGITS_5 ((mask) / 10)
+#define DIGITS_7(mask) PR (mask), n %= (mask), DIGITS_6 ((mask) / 10)
+#define DIGITS_8(mask) PR (mask), n %= (mask), DIGITS_7 ((mask) / 10)
+#define DIGITS_9(mask) PR (mask), n %= (mask), DIGITS_8 ((mask) / 10)
+#define DIGITS_10(mask) PR (mask), n %= (mask), DIGITS_9 ((mask) / 10)
+
+/* DIGITS_<11-20> are only used on machines with 64-bit wgints. */
+
+#define DIGITS_11(mask) PR (mask), n %= (mask), DIGITS_10 ((mask) / 10)
+#define DIGITS_12(mask) PR (mask), n %= (mask), DIGITS_11 ((mask) / 10)
+#define DIGITS_13(mask) PR (mask), n %= (mask), DIGITS_12 ((mask) / 10)
+#define DIGITS_14(mask) PR (mask), n %= (mask), DIGITS_13 ((mask) / 10)
+#define DIGITS_15(mask) PR (mask), n %= (mask), DIGITS_14 ((mask) / 10)
+#define DIGITS_16(mask) PR (mask), n %= (mask), DIGITS_15 ((mask) / 10)
+#define DIGITS_17(mask) PR (mask), n %= (mask), DIGITS_16 ((mask) / 10)
+#define DIGITS_18(mask) PR (mask), n %= (mask), DIGITS_17 ((mask) / 10)
+#define DIGITS_19(mask) PR (mask), n %= (mask), DIGITS_18 ((mask) / 10)
/* SPRINTF_WGINT is used by number_to_string to handle pathological
- cases and to portably support strange sizes of wgint. */
+ cases and to portably support strange sizes of wgint. Ideally this
+ would just use "%j" and intmax_t, but many systems don't support
+ it, so it's used only if nothing else works. */
#if SIZEOF_LONG >= SIZEOF_WGINT
-# define SPRINTF_WGINT(buf, n) sprintf(buf, "%ld", (long) (n))
+# define SPRINTF_WGINT(buf, n) sprintf (buf, "%ld", (long) (n))
#else
# if SIZEOF_LONG_LONG >= SIZEOF_WGINT
-# define SPRINTF_WGINT(buf, n) sprintf(buf, "%lld", (long long) (n))
+# define SPRINTF_WGINT(buf, n) sprintf (buf, "%lld", (long long) (n))
# else
# ifdef WINDOWS
-# define SPRINTF_WGINT(buf, n) sprintf(buf, "%I64", (__int64) (n))
+# define SPRINTF_WGINT(buf, n) sprintf (buf, "%I64", (__int64) (n))
+# else
+# define SPRINTF_WGINT(buf, n) sprintf (buf, "%j", (intmax_t) (n))
# endif
# endif
#endif
+/* Shorthand for casting to wgint. */
+#define W wgint
+
/* Print NUMBER to BUFFER in base 10. This is equivalent to
- `sprintf(buffer, "%lld", (long long) number)', only much faster and
- portable to machines without long long.
+ `sprintf(buffer, "%lld", (long long) number)', only typically much
+ faster and portable to machines without long long.
The speedup may make a difference in programs that frequently
convert numbers to strings. Some implementations of sprintf,
{
if (n < -WGINT_MAX)
{
- /* We cannot print a '-' and assign -n to n because -n would
- overflow. Let sprintf deal with this border case. */
+ /* -n would overflow. Have sprintf deal with this. */
SPRINTF_WGINT (buffer, n);
p += strlen (buffer);
return p;
n = -n;
}
- if (n < 10) { DIGITS_1 (1); }
- else if (n < 100) { DIGITS_2 (10); }
- else if (n < 1000) { DIGITS_3 (100); }
- else if (n < 10000) { DIGITS_4 (1000); }
- else if (n < 100000) { DIGITS_5 (10000); }
- else if (n < 1000000) { DIGITS_6 (100000); }
- else if (n < 10000000) { DIGITS_7 (1000000); }
- else if (n < 100000000) { DIGITS_8 (10000000); }
- else if (n < 1000000000) { DIGITS_9 (100000000); }
+ /* Use the DIGITS_ macro appropriate for N's number of digits. That
+ way printing any N is fully open-coded without a loop or jump.
+ (Also see description of DIGITS_*.) */
+
+ if (n < 10) DIGITS_1 (1);
+ else if (n < 100) DIGITS_2 (10);
+ else if (n < 1000) DIGITS_3 (100);
+ else if (n < 10000) DIGITS_4 (1000);
+ else if (n < 100000) DIGITS_5 (10000);
+ else if (n < 1000000) DIGITS_6 (100000);
+ else if (n < 10000000) DIGITS_7 (1000000);
+ else if (n < 100000000) DIGITS_8 (10000000);
+ else if (n < 1000000000) DIGITS_9 (100000000);
#if SIZEOF_WGINT == 4
- /* wgint is four bytes long: we're done. */
- /* ``if (1)'' serves only to preserve editor indentation. */
- else if (1) { DIGITS_10 (1000000000); }
+ /* wgint is 32 bits wide: no number has more than 10 digits. */
+ else DIGITS_10 (1000000000);
#else
- /* wgint is 64 bits long -- make sure to process all the digits. */
- else if (n < C10000000000) { DIGITS_10 (1000000000); }
- else if (n < C100000000000) { DIGITS_11 (C10000000000); }
- else if (n < C1000000000000) { DIGITS_12 (C100000000000); }
- else if (n < C10000000000000) { DIGITS_13 (C1000000000000); }
- else if (n < C100000000000000) { DIGITS_14 (C10000000000000); }
- else if (n < C1000000000000000) { DIGITS_15 (C100000000000000); }
- else if (n < C10000000000000000) { DIGITS_16 (C1000000000000000); }
- else if (n < C100000000000000000) { DIGITS_17 (C10000000000000000); }
- else if (n < C1000000000000000000) { DIGITS_18 (C100000000000000000); }
- else { DIGITS_19 (C1000000000000000000); }
+ /* wgint is 64 bits wide: handle numbers with more than 9 decimal
+ digits. Constants are constructed by compile-time multiplication
+ to avoid dealing with different notations for 64-bit constants
+ (nnnL, nnnLL, and nnnI64, depending on the compiler). */
+ else if (n < 10*(W)1000000000) DIGITS_10 (1000000000);
+ else if (n < 100*(W)1000000000) DIGITS_11 (10*(W)1000000000);
+ else if (n < 1000*(W)1000000000) DIGITS_12 (100*(W)1000000000);
+ else if (n < 10000*(W)1000000000) DIGITS_13 (1000*(W)1000000000);
+ else if (n < 100000*(W)1000000000) DIGITS_14 (10000*(W)1000000000);
+ else if (n < 1000000*(W)1000000000) DIGITS_15 (100000*(W)1000000000);
+ else if (n < 10000000*(W)1000000000) DIGITS_16 (1000000*(W)1000000000);
+ else if (n < 100000000*(W)1000000000) DIGITS_17 (10000000*(W)1000000000);
+ else if (n < 1000000000*(W)1000000000) DIGITS_18 (100000000*(W)1000000000);
+ else DIGITS_19 (1000000000*(W)1000000000);
#endif
*p = '\0';
return p;
}
-#undef ONE_DIGIT
-#undef ONE_DIGIT_ADVANCE
-
+#undef PR
+#undef W
#undef DIGITS_1
#undef DIGITS_2
#undef DIGITS_3
only one of the above constants will be defined. Virtually all
modern Unix systems will define TIMER_GETTIMEOFDAY; Windows will
use TIMER_WINDOWS. TIMER_TIME is a catch-all method for
- non-Windows systems without gettimeofday.
-
- #### Perhaps we should also support ftime(), which exists on old
- BSD 4.2-influenced systems? (It also existed under MS DOS Borland
- C, if memory serves me.) */
+ non-Windows systems without gettimeofday. */
#ifdef WINDOWS
# define TIMER_WINDOWS
#endif
#ifdef TIMER_WINDOWS
-typedef ULARGE_INTEGER wget_sys_time;
+typedef union {
+ DWORD lores; /* In case GetTickCount is used */
+ LARGE_INTEGER hires; /* In case high-resolution timer is used */
+} wget_sys_time;
#endif
struct wget_timer {
time, yields elapsed time. */
wget_sys_time start;
- /* The most recent elapsed time, calculated by wtimer_elapsed().
+ /* The most recent elapsed time, calculated by wtimer_update().
Measured in milliseconds. */
double elapsed_last;
double elapsed_pre_start;
};
+#ifdef TIMER_WINDOWS
+
+/* Whether high-resolution timers are used. Set by wtimer_initialize_once
+ the first time wtimer_allocate is called. */
+static int using_hires_timers;
+
+/* Frequency of high-resolution timers -- number of updates per
+ millisecond. Calculated the first time wtimer_allocate is called
+ provided that high-resolution timers are available. */
+static double hires_millisec_freq;
+
+/* The first time a timer is created, determine whether to use
+ high-resolution timers. */
+
+static void
+wtimer_initialize_once (void)
+{
+ static int init_done;
+ if (!init_done)
+ {
+ LARGE_INTEGER freq;
+ init_done = 1;
+ freq.QuadPart = 0;
+ QueryPerformanceFrequency (&freq);
+ if (freq.QuadPart != 0)
+ {
+ using_hires_timers = 1;
+ hires_millisec_freq = (double) freq.QuadPart / 1000.0;
+ }
+ }
+}
+#endif /* TIMER_WINDOWS */
+
/* Allocate a timer. Calling wtimer_read on the timer will return
zero. It is not legal to call wtimer_update with a freshly
allocated timer -- use wtimer_reset first. */
{
struct wget_timer *wt = xnew (struct wget_timer);
xzero (*wt);
+
+#ifdef TIMER_WINDOWS
+ wtimer_initialize_once ();
+#endif
+
return wt;
}
#endif
#ifdef TIMER_WINDOWS
- /* We use GetSystemTime to get the elapsed time. MSDN warns that
- system clock adjustments can skew the output of GetSystemTime
- when used as a timer and gives preference to GetTickCount and
- high-resolution timers. But GetTickCount can overflow, and hires
- timers are typically used for profiling, not for regular time
- measurement. Since we handle clock skew anyway, we just use
- GetSystemTime. */
- FILETIME ft;
- SYSTEMTIME st;
- GetSystemTime (&st);
-
- /* As recommended by MSDN, we convert SYSTEMTIME to FILETIME, copy
- FILETIME to ULARGE_INTEGER, and use regular 64-bit integer
- arithmetic on that. */
- SystemTimeToFileTime (&st, &ft);
- wst->HighPart = ft.dwHighDateTime;
- wst->LowPart = ft.dwLowDateTime;
+ if (using_hires_timers)
+ {
+ QueryPerformanceCounter (&wst->hires);
+ }
+ else
+ {
+ /* Where hires counters are not available, use GetTickCount rather
+ GetSystemTime, because it is unaffected by clock skew and simpler
+ to use. Note that overflows don't affect us because we never use
+ absolute values of the ticker, only the differences. */
+ wst->lores = GetTickCount ();
+ }
#endif
}
/* Reset timer WT. This establishes the starting point from which
- wtimer_elapsed() will return the number of elapsed milliseconds.
- It is allowed to reset a previously used timer.
-
- If a non-zero value is used as START, the timer's values will be
- offset by START. */
+ wtimer_read() will return the number of elapsed milliseconds.
+ It is allowed to reset a previously used timer. */
void
wtimer_reset (struct wget_timer *wt)
#endif
#ifdef WINDOWS
- /* VC++ 6 doesn't support direct cast of uint64 to double. To work
- around this, we subtract, then convert to signed, then finally to
- double. */
- return (double)(signed __int64)(wst1->QuadPart - wst2->QuadPart) / 10000;
+ if (using_hires_timers)
+ return (wst1->hires.QuadPart - wst2->hires.QuadPart) / hires_millisec_freq;
+ else
+ return wst1->lores - wst2->lores;
#endif
}
#endif
#ifdef TIMER_WINDOWS
- /* According to MSDN, GetSystemTime returns a broken-down time
- structure the smallest member of which are milliseconds. */
- return 1;
+ if (using_hires_timers)
+ return 1.0 / hires_millisec_freq;
+ else
+ return 10; /* according to MSDN */
#endif
}
\f
int rnd3 = random_number (1000);
return rnd1 / 1000.0 + rnd2 / 1000000.0 + rnd3 / 1000000000.0;
}
-
-#if 0
-/* A debugging function for checking whether an MD5 library works. */
-
-#include "gen-md5.h"
-
-char *
-debug_test_md5 (char *buf)
-{
- unsigned char raw[16];
- static char res[33];
- unsigned char *p1;
- char *p2;
- int cnt;
- ALLOCA_MD5_CONTEXT (ctx);
-
- gen_md5_init (ctx);
- gen_md5_update ((unsigned char *)buf, strlen (buf), ctx);
- gen_md5_finish (ctx, raw);
-
- p1 = raw;
- p2 = res;
- cnt = 16;
- while (cnt--)
- {
- *p2++ = XNUM_TO_digit (*p1 >> 4);
- *p2++ = XNUM_TO_digit (*p1 & 0xf);
- ++p1;
- }
- *p2 = '\0';
-
- return res;
-}
-#endif
\f
/* Implementation of run_with_timeout, a generic timeout-forcing
routine for systems with Unix-like signal handling. */
struct itimerval itv;
xzero (itv);
itv.it_value.tv_sec = (long) timeout;
- itv.it_value.tv_usec = 1000000L * (timeout - (long)timeout);
+ itv.it_value.tv_usec = 1000000 * (timeout - (long)timeout);
if (itv.it_value.tv_sec == 0 && itv.it_value.tv_usec == 0)
/* Ensure that we wait for at least the minimum interval.
Specifying zero would mean "wait forever". */
* It works with both SYSV and BSD signals because it doesn't
depend on the default setting of SA_RESTART.
- * It doesn't special handler setup beyond a simple call to
- signal(). (It does use sigsetjmp/siglongjmp, but they're
+ * It doesn't require special handler setup beyond a simple call
+ to signal(). (It does use sigsetjmp/siglongjmp, but they're
optional.)
The only downside is that, if FUN allocates internal resources that
#ifdef HAVE_NANOSLEEP
/* nanosleep is the preferred interface because it offers high
accuracy and, more importantly, because it allows us to reliably
- restart after having been interrupted by a signal such as
- SIGWINCH. */
+ restart receiving a signal such as SIGWINCH. (There was an
+ actual Debian bug report about --limit-rate malfunctioning while
+ the terminal was being resized.) */
struct timespec sleep, remaining;
sleep.tv_sec = (long) seconds;
- sleep.tv_nsec = 1000000000L * (seconds - (long) seconds);
+ sleep.tv_nsec = 1000000000 * (seconds - (long) seconds);
while (nanosleep (&sleep, &remaining) < 0 && errno == EINTR)
/* If nanosleep has been interrupted by a signal, adjust the
sleeping period and return to sleep. */
sleep (seconds);
seconds -= (long) seconds;
}
- usleep (seconds * 1000000L);
+ usleep (seconds * 1000000);
#else /* not HAVE_USLEEP */
#ifdef HAVE_SELECT
+ /* Note that, although Windows supports select, this sleeping
+ strategy doesn't work there because Winsock's select doesn't
+ implement timeout when it is passed NULL pointers for all fd
+ sets. (But it does work under Cygwin, which implements its own
+ select.) */
struct timeval sleep;
sleep.tv_sec = (long) seconds;
- sleep.tv_usec = 1000000L * (seconds - (long) seconds);
+ sleep.tv_usec = 1000000 * (seconds - (long) seconds);
select (0, NULL, NULL, NULL, &sleep);
/* If select returns -1 and errno is EINTR, it means we were
interrupted by a signal. But without knowing how long we've
}
#endif /* not WINDOWS */
+
+/* Encode the string S of length LENGTH to base64 format and place it
+ to STORE. STORE will be 0-terminated, and must point to a writable
+ buffer of at least 1+BASE64_LENGTH(length) bytes. */
+
+void
+base64_encode (const char *s, char *store, int length)
+{
+ /* Conversion table. */
+ static char tbl[64] = {
+ 'A','B','C','D','E','F','G','H',
+ 'I','J','K','L','M','N','O','P',
+ 'Q','R','S','T','U','V','W','X',
+ 'Y','Z','a','b','c','d','e','f',
+ 'g','h','i','j','k','l','m','n',
+ 'o','p','q','r','s','t','u','v',
+ 'w','x','y','z','0','1','2','3',
+ '4','5','6','7','8','9','+','/'
+ };
+ int i;
+ unsigned char *p = (unsigned char *)store;
+
+ /* Transform the 3x8 bits to 4x6 bits, as required by base64. */
+ for (i = 0; i < length; i += 3)
+ {
+ *p++ = tbl[s[0] >> 2];
+ *p++ = tbl[((s[0] & 3) << 4) + (s[1] >> 4)];
+ *p++ = tbl[((s[1] & 0xf) << 2) + (s[2] >> 6)];
+ *p++ = tbl[s[2] & 0x3f];
+ s += 3;
+ }
+ /* Pad the result if necessary... */
+ if (i == length + 1)
+ *(p - 1) = '=';
+ else if (i == length + 2)
+ *(p - 1) = *(p - 2) = '=';
+ /* ...and zero-terminate it. */
+ *p = '\0';
+}
+
+#define IS_ASCII(c) (((c) & 0x80) == 0)
+#define IS_BASE64(c) ((IS_ASCII (c) && base64_char_to_value[c] >= 0) || c == '=')
+
+/* Get next character from the string, except that non-base64
+ characters are ignored, as mandated by rfc2045. */
+#define NEXT_BASE64_CHAR(c, p) do { \
+ c = *p++; \
+} while (c != '\0' && !IS_BASE64 (c))
+
+/* Decode data from BASE64 (assumed to be encoded as base64) into
+ memory pointed to by TO. TO should be large enough to accomodate
+ the decoded data, which is guaranteed to be less than
+ strlen(base64).
+
+ Since TO is assumed to contain binary data, it is not
+ NUL-terminated. The function returns the length of the data
+ written to TO. -1 is returned in case of error caused by malformed
+ base64 input. */
+
+int
+base64_decode (const char *base64, char *to)
+{
+ /* Table of base64 values for first 128 characters. */
+ static short base64_char_to_value[128] =
+ {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0- 9 */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 10- 19 */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 20- 29 */
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 30- 39 */
+ -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, /* 40- 49 */
+ 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, /* 50- 59 */
+ -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, /* 60- 69 */
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 70- 79 */
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, /* 80- 89 */
+ 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, /* 90- 99 */
+ 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, /* 100-109 */
+ 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, /* 110-119 */
+ 49, 50, 51, -1, -1, -1, -1, -1 /* 120-127 */
+ };
+
+ const char *p = base64;
+ char *q = to;
+
+ while (1)
+ {
+ unsigned char c;
+ unsigned long value;
+
+ /* Process first byte of a quadruplet. */
+ NEXT_BASE64_CHAR (c, p);
+ if (!c)
+ break;
+ if (c == '=')
+ return -1; /* illegal '=' while decoding base64 */
+ value = base64_char_to_value[c] << 18;
+
+ /* Process scond byte of a quadruplet. */
+ NEXT_BASE64_CHAR (c, p);
+ if (!c)
+ return -1; /* premature EOF while decoding base64 */
+ if (c == '=')
+ return -1; /* illegal `=' while decoding base64 */
+ value |= base64_char_to_value[c] << 12;
+ *q++ = value >> 16;
+
+ /* Process third byte of a quadruplet. */
+ NEXT_BASE64_CHAR (c, p);
+ if (!c)
+ return -1; /* premature EOF while decoding base64 */
+
+ if (c == '=')
+ {
+ NEXT_BASE64_CHAR (c, p);
+ if (!c)
+ return -1; /* premature EOF while dcoding base64 */
+ if (c != '=')
+ return -1; /* padding `=' expected but not found */
+ continue;
+ }
+
+ value |= base64_char_to_value[c] << 6;
+ *q++ = 0xff & value >> 8;
+
+ /* Process fourth byte of a quadruplet. */
+ NEXT_BASE64_CHAR (c, p);
+ if (!c)
+ return -1; /* premature EOF while dcoding base64 */
+ if (c == '=')
+ continue;
+
+ value |= base64_char_to_value[c];
+ *q++ = 0xff & value;
+ }
+
+ return q - to;
+}
+
+#undef IS_ASCII
+#undef IS_BASE64
+#undef NEXT_BASE64_CHAR