⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 utils.c

📁 wget讓你可以在console介面下
💻 C
📖 第 1 页 / 共 4 页
字号:
}/* Free the pointers in a NULL-terminated vector of pointers, then   free the pointer itself.  */voidfree_vec (char **vec){  if (vec)    {      char **p = vec;      while (*p)	xfree (*p++);      xfree (vec);    }}/* Append vector V2 to vector V1.  The function frees V2 and   reallocates V1 (thus you may not use the contents of neither   pointer after the call).  If V1 is NULL, V2 is returned.  */char **merge_vecs (char **v1, char **v2){  int i, j;  if (!v1)    return v2;  if (!v2)    return v1;  if (!*v2)    {      /* To avoid j == 0 */      xfree (v2);      return v1;    }  /* Count v1.  */  for (i = 0; v1[i]; i++);  /* Count v2.  */  for (j = 0; v2[j]; j++);  /* Reallocate v1.  */  v1 = (char **)xrealloc (v1, (i + j + 1) * sizeof (char **));  memcpy (v1 + i, v2, (j + 1) * sizeof (char *));  xfree (v2);  return v1;}/* Append a freshly allocated copy of STR to VEC.  If VEC is NULL, it   is allocated as needed.  Return the new value of the vector. */char **vec_append (char **vec, const char *str){  int cnt;			/* count of vector elements, including				   the one we're about to append */  if (vec != NULL)    {      for (cnt = 0; vec[cnt]; cnt++)	;      ++cnt;    }  else    cnt = 1;  /* Reallocate the array to fit the new element and the NULL. */  vec = xrealloc (vec, (cnt + 1) * sizeof (char *));  /* Append a copy of STR to the vector. */  vec[cnt - 1] = xstrdup (str);  vec[cnt] = NULL;  return vec;}/* Sometimes it's useful to create "sets" of strings, i.e. special   hash tables where you want to store strings as keys and merely   query for their existence.  Here is a set of utility routines that   makes that transparent.  */voidstring_set_add (struct hash_table *ht, const char *s){  /* First check whether the set element already exists.  If it does,     do nothing so that we don't have to free() the old element and     then strdup() a new one.  */  if (hash_table_contains (ht, s))    return;  /* We use "1" as value.  It provides us a useful and clear arbitrary     value, and it consumes no memory -- the pointers to the same     string "1" will be shared by all the key-value pairs in all `set'     hash tables.  */  hash_table_put (ht, xstrdup (s), "1");}/* Synonym for hash_table_contains... */intstring_set_contains (struct hash_table *ht, const char *s){  return hash_table_contains (ht, s);}static intstring_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 intstring_set_free_mapper (void *key, void *value_ignored, void *arg_ignored){  xfree (key);  return 0;}voidstring_set_free (struct hash_table *ht){  hash_table_map (ht, string_set_free_mapper, NULL);  hash_table_destroy (ht);}static intfree_keys_and_values_mapper (void *key, void *value, void *arg_ignored){  xfree (key);  xfree (value);  return 0;}/* Another utility function: call free() on all keys and values of HT.  */voidfree_keys_and_values (struct hash_table *ht){  hash_table_map (ht, free_keys_and_values_mapper, NULL);}static voidget_grouping_data (const char **sep, const char **grouping){  static const char *cached_sep;  static const char *cached_grouping;  static int initialized;  if (!initialized)    {      /* If locale.h is present and defines LC_NUMERIC, assume C89	 struct lconv with "thousand_sep" and "grouping" members.  */#ifdef LC_NUMERIC      /* Get the grouping info from the locale. */      struct lconv *lconv;      const char *oldlocale = setlocale (LC_NUMERIC, NULL);      /* Temporarily switch to the current locale */      setlocale (LC_NUMERIC, "");      lconv = localeconv ();      cached_sep = xstrdup (lconv->thousands_sep);      cached_grouping = xstrdup (lconv->grouping);      /* Restore the locale to previous setting. */      setlocale (LC_NUMERIC, oldlocale);      if (!*cached_sep)#endif	/* Force separator for locales that specify no separators	   ("C", "hr", and probably many more.) */	cached_sep = ",", cached_grouping = "\x03";      initialized = 1;    }  *sep = cached_sep;  *grouping = cached_grouping;}/* Add thousand separators to a number already in string form.  Used   by with_thousand_seps and with_thousand_seps_sum.  */char *add_thousand_seps (const char *repr){  static char outbuf[48];  char *p = outbuf + sizeof outbuf;  const char *in = strchr (repr, '\0');  const char *instart = repr + (*repr == '-'); /* don't group sign */  /* Info received from locale */  const char *grouping, *sep;  int seplen;  /* State information */  int i = 0, groupsize;  const char *atgroup;  /* Initialize grouping data. */  get_grouping_data (&sep, &grouping);  seplen = strlen (sep);  atgroup = grouping;  groupsize = *atgroup++;  /* Write the number into the buffer, backwards, inserting the     separators as necessary.  */  *--p = '\0';  while (1)    {      *--p = *--in;      if (in == instart)	break;      /* Prepend SEP to every groupsize'd digit and get new groupsize.  */      if (++i == groupsize)	{	  if (seplen == 1)	    *--p = *sep;	  else	    memcpy (p -= seplen, sep, seplen);	  i = 0;	  if (*atgroup)	    groupsize = *atgroup++;	}    }  if (*repr == '-')    *--p = '-';  return p;}/* Return a printed representation of N with thousand separators.   This should respect locale settings, with the exception of the "C"   locale which mandates no separator, but we use one anyway.   Unfortunately, we cannot use %'d (in fact it would be %'j) to get   the separators because it's too non-portable, and it's hard to test   for this feature at configure time.  Besides, it wouldn't work in   the "C" locale, which many Unix users still work in.  */char *with_thousand_seps (wgint l){  char inbuf[24];  /* Print the number into the buffer.  */  number_to_string (inbuf, l);  return add_thousand_seps (inbuf);}/* When SUM_SIZE_INT is wgint, with_thousand_seps_large is #defined to   with_thousand_seps.  The function below is used on non-LFS systems   where SUM_SIZE_INT typedeffed to double.  */#ifndef with_thousand_seps_sumchar *with_thousand_seps_sum (SUM_SIZE_INT l){  char inbuf[32];  snprintf (inbuf, sizeof (inbuf), "%.0f", l);  return add_thousand_seps (inbuf);}#endif /* not with_thousand_seps_sum *//* 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 "powers of 1024".  Powers of   1000 would be useless since Wget already displays sizes with   thousand separators.  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)	{	  double val = 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.  */intnumdigit (wgint number){  int cnt = 1;  if (number < 0)    ++cnt;			/* accomodate '-' */  while ((number /= 10) != 0)    ++cnt;  return cnt;}#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.  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))#else# if SIZEOF_LONG_LONG >= SIZEOF_WGINT#   define SPRINTF_WGINT(buf, n) sprintf (buf, "%lld", (long long) (n))# else#  ifdef WINDOWS#   define SPRINTF_WGINT(buf, n) sprintf (buf, "%I64d", (__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 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,   particularly the one in GNU libc, have been known to be extremely   slow when converting integers to strings.   Return the pointer to the location where the terminating zero was   printed.  (Equivalent to calling buffer+strlen(buffer) after the   function is done.)   BUFFER should be big enough to accept as many bytes as you expect   the number to take up.  On machines with 64-bit longs the maximum   needed size is 24 bytes.  That includes the digits needed for the   largest 64-bit number, the `-' sign in case it's negative, and the   terminating '\0'.  */char *number_to_string (char *buffer, wgint number){  char *p = buffer;  wgint n = number;#if (SIZEOF_WGINT != 4) && (SIZEOF_WGINT != 8)  /* We are running in a strange or misconfigured environment.  Let     sprintf cope with it.  */  SPRINTF_WGINT (buffer, n);  p += strlen (buffer);#else  /* (SIZEOF_WGINT == 4) || (SIZEOF_WGINT == 8) */  if (n < 0)    {      if (n < -WGINT_MAX)	{	  /* -n would overflow.  Have sprintf deal with this.  */	  SPRINTF_WGINT (buffer, n);	  p += strlen (buffer);	  return p;	}      *p++ = '-';      n = -n;    }  /* 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 32 bits wide: no number has more than 10 digits. */  else                                   DIGITS_10 (1000000000);#else  /* 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';#endif /* (SIZEOF_WGINT == 4) || (SIZEOF_WGINT == 8) */  return p;}#undef PR#undef W#undef DIGITS_1#undef DIGITS_2#undef DIGITS_3#undef DIGITS_4#undef DIGITS_5#undef DIGITS_6#undef DIGITS_7#undef DIGITS_8#undef DIGITS_9#undef DIGITS_10#undef DIGITS_11#undef DIGITS_12#undef DIGITS_13#undef DIGITS_14#undef DIGITS_15#undef DIGITS_16#undef DIGITS_17#undef DIGITS_18#undef DIGITS_19#define RING_SIZE 3/* Print NUMBER to a statically allocated string and return a pointer   to the printed representation.   This function is intended to be used in conjunction with printf.   It is hard to portably print wgint values:    a) you cannot use printf("%ld", number) because wgint can be long       long on 32-bit machines with LFS.    b) you cannot use printf("%lld", number) because NUMBER could be       long on 32-bit machines without LFS, or on 64-bit machines,       which do not require LFS.  Also, Windows doesn't support %lld.    c) you cannot use printf("%j", (int_max_t) number) because not all       versions of printf support "%j", the most notable being the one       on Windows.    d) you cannot #define WGINT_FMT to the appropriate format and use       printf(WGINT_FMT, number) because that would break translations       for user-visible messages, such as printf("Downloaded: %d       bytes\n", number).   What you should use instead is printf("%s", number_to_static_string   (number)).   CAVEAT: since the function returns pointers to static data, you   must be careful to copy its result before calling it again.   However, to make it more useful with printf, the function maintains   an internal ring of static buffers to return.  That way things like   printf("%s %s", number_to_static_string (num1),   number_to_static_string (num2)) work as expected.  Three buffers

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -