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

📄 utils.c

📁 Wget很好的处理了http和ftp的下载,很值得学习的经典代码
💻 C
📖 第 1 页 / 共 5 页
字号:
  if (suf[0] && !strcasecmp (suf + 1, "html"))    return true;  return false;}/* Read a line from FP and return the pointer to freshly allocated   storage.  The storage space is obtained through malloc() and should   be freed with free() when it is no longer needed.   The length of the line is not limited, except by available memory.   The newline character at the end of line is retained.  The line is   terminated with a zero character.   After end-of-file is encountered without anything being read, NULL   is returned.  NULL is also returned on error.  To distinguish   between these two cases, use the stdio function ferror().  */char *read_whole_line (FILE *fp){  int length = 0;  int bufsize = 82;  char *line = xmalloc (bufsize);  while (fgets (line + length, bufsize - length, fp))    {      length += strlen (line + length);      if (length == 0)        /* Possible for example when reading from a binary file where           a line begins with \0.  */        continue;      if (line[length - 1] == '\n')        break;      /* fgets() guarantees to read the whole line, or to use up the         space we've given it.  We can double the buffer         unconditionally.  */      bufsize <<= 1;      line = xrealloc (line, bufsize);    }  if (length == 0 || ferror (fp))    {      xfree (line);      return NULL;    }  if (length + 1 < bufsize)    /* Relieve the memory from our exponential greediness.  We say       `length + 1' because the terminating \0 is not included in       LENGTH.  We don't need to zero-terminate the string ourselves,       though, because fgets() does that.  */    line = xrealloc (line, length + 1);  return line;}/* Read FILE into memory.  A pointer to `struct file_memory' are   returned; use struct element `content' to access file contents, and   the element `length' to know the file length.  `content' is *not*   zero-terminated, and you should *not* read or write beyond the [0,   length) range of characters.   After you are done with the file contents, call read_file_free to   release the memory.   Depending on the operating system and the type of file that is   being read, read_file() either mmap's the file into memory, or   reads the file into the core using read().   If file is named "-", fileno(stdin) is used for reading instead.   If you want to read from a real file named "-", use "./-" instead.  */struct file_memory *read_file (const char *file){  int fd;  struct file_memory *fm;  long size;  bool inhibit_close = false;  /* Some magic in the finest tradition of Perl and its kin: if FILE     is "-", just use stdin.  */  if (HYPHENP (file))    {      fd = fileno (stdin);      inhibit_close = true;      /* Note that we don't inhibit mmap() in this case.  If stdin is         redirected from a regular file, mmap() will still work.  */    }  else    fd = open (file, O_RDONLY);  if (fd < 0)    return NULL;  fm = xnew (struct file_memory);#ifdef HAVE_MMAP  {    struct_fstat buf;    if (fstat (fd, &buf) < 0)      goto mmap_lose;    fm->length = buf.st_size;    /* NOTE: As far as I know, the callers of this function never       modify the file text.  Relying on this would enable us to       specify PROT_READ and MAP_SHARED for a marginal gain in       efficiency, but at some cost to generality.  */    fm->content = mmap (NULL, fm->length, PROT_READ | PROT_WRITE,                        MAP_PRIVATE, fd, 0);    if (fm->content == (char *)MAP_FAILED)      goto mmap_lose;    if (!inhibit_close)      close (fd);    fm->mmap_p = 1;    return fm;  } mmap_lose:  /* The most common reason why mmap() fails is that FD does not point     to a plain file.  However, it's also possible that mmap() doesn't     work for a particular type of file.  Therefore, whenever mmap()     fails, we just fall back to the regular method.  */#endif /* HAVE_MMAP */  fm->length = 0;  size = 512;                   /* number of bytes fm->contents can                                   hold at any given time. */  fm->content = xmalloc (size);  while (1)    {      wgint nread;      if (fm->length > size / 2)        {          /* #### I'm not sure whether the whole exponential-growth             thing makes sense with kernel read.  On Linux at least,             read() refuses to read more than 4K from a file at a             single chunk anyway.  But other Unixes might optimize it             better, and it doesn't *hurt* anything, so I'm leaving             it.  */          /* Normally, we grow SIZE exponentially to make the number             of calls to read() and realloc() logarithmic in relation             to file size.  However, read() can read an amount of data             smaller than requested, and it would be unreasonable to             double SIZE every time *something* was read.  Therefore,             we double SIZE only when the length exceeds half of the             entire allocated size.  */          size <<= 1;          fm->content = xrealloc (fm->content, size);        }      nread = read (fd, fm->content + fm->length, size - fm->length);      if (nread > 0)        /* Successful read. */        fm->length += nread;      else if (nread < 0)        /* Error. */        goto lose;      else        /* EOF */        break;    }  if (!inhibit_close)    close (fd);  if (size > fm->length && fm->length != 0)    /* Due to exponential growth of fm->content, the allocated region       might be much larger than what is actually needed.  */    fm->content = xrealloc (fm->content, fm->length);  fm->mmap_p = 0;  return fm; lose:  if (!inhibit_close)    close (fd);  xfree (fm->content);  xfree (fm);  return NULL;}/* Release the resources held by FM.  Specifically, this calls   munmap() or xfree() on fm->content, depending whether mmap or   malloc/read were used to read in the file.  It also frees the   memory needed to hold the FM structure itself.  */voidread_file_free (struct file_memory *fm){#ifdef HAVE_MMAP  if (fm->mmap_p)    {      munmap (fm->content, fm->length);    }  else#endif    {      xfree (fm->content);    }  xfree (fm);}/* 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 = 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);}/* 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_iterator iter;  for (hash_table_iterate (ht, &iter); hash_table_iter_next (&iter); )    *array++ = iter.key;}/* Free the string set.  This frees both the storage allocated for   keys and the actual hash table.  (hash_table_destroy would only   destroy the hash table.)  */voidstring_set_free (struct hash_table *ht){  hash_table_iterator iter;  for (hash_table_iterate (ht, &iter); hash_table_iter_next (&iter); )    xfree (iter.key);  hash_table_destroy (ht);}/* Utility function: simply call xfree() on all keys and values of HT.  */voidfree_keys_and_values (struct hash_table *ht){  hash_table_iterator iter;  for (hash_table_iterate (ht, &iter); hash_table_iter_next (&iter); )    {      xfree (iter.key);      xfree (iter.value);    }}/* Get digit grouping data for thousand separors by calling   localeconv().  The data includes separator string and grouping info   and is cached after the first call to the function.   In locales that don't set a thousand separator (such as the "C"   locale), this forces it to be ",".  We are now only showing   thousand separators in one place, so this shouldn't be a problem in   practice.  */static voidget_grouping_data (const char **sep, const char **grouping){  static const char *cached_sep;  static const char *cached_grouping;  static bool initialized;  if (!initialized)    {      /* Get the grouping info from the locale. */      struct lconv *lconv = localeconv ();      cached_sep = lconv->thousands_sep;      cached_grouping = lconv->grouping;#if ! USE_NLS_PROGRESS_BAR      /* We can't count column widths, so ensure that the separator       * is single-byte only (let check below determine what byte). */      if (strlen(cached_sep) > 1)        cached_sep = "";#endif      if (!*cached_sep)        {          /* Many locales (such as "C" or "hr_HR") don't specify             grouping, which we still want to use it for legibility.             In those locales set the sep char to ',', unless that             character is used for decimal point, in which case set it             to ".".  */          if (*lconv->decimal_point != ',')            cached_sep = ",";          else            cached_sep = ".";          cached_grouping = "\x03";        }      initialized = true;    }  *sep = cached_sep;  *grouping = cached_grouping;}/* 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 display   separators in the "C" locale, still used by many Unix users.  */const char *with_thousand_seps (wgint n){  static char outbuf[48];  char *p = outbuf + sizeof outbuf;  /* Info received from locale */  const char *grouping, *sep;  int seplen;  /* State information */  int i = 0, groupsize;  const char *atgroup;  bool negative = n < 0;  /* Initialize grouping data. */  get_grouping_data (&sep, &grouping);  seplen = strlen (sep);  atgroup = grouping;  groupsize = *atgroup++;  /* This would overflow on WGINT_MIN, but printing negative numbers     is not an important goal of this fuinction.  */  if (negative)    n = -n;  /* Write the number into the buffer, backwards, inserting the     separators as necessary.  */  *--p = '\0';  while (1)    {      *--p = n % 10 + '0';      n /= 10;      if (n == 0)        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 (negative)    *--p = '-';

⌨️ 快捷键说明

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