(root)/
coreutils-9.4/
lib/
argv-iter.c
       1  /* Iterate over arguments from argv or --files0-from=FILE
       2     Copyright (C) 2008-2023 Free Software Foundation, Inc.
       3  
       4     This program is free software: you can redistribute it and/or modify
       5     it under the terms of the GNU General Public License as published by
       6     the Free Software Foundation, either version 3 of the License, or
       7     (at your option) any later version.
       8  
       9     This program is distributed in the hope that it will be useful,
      10     but WITHOUT ANY WARRANTY; without even the implied warranty of
      11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12     GNU General Public License for more details.
      13  
      14     You should have received a copy of the GNU General Public License
      15     along with this program.  If not, see <https://www.gnu.org/licenses/>.  */
      16  
      17  /* Written by Jim Meyering.  */
      18  
      19  #include <config.h>
      20  #include "argv-iter.h"
      21  
      22  #include <stdlib.h>
      23  #include <string.h>
      24  
      25  struct argv_iterator
      26  {
      27    /* Test FP to determine whether in read-mode or argv-mode. */
      28    /* file-mode: fp records position */
      29    FILE *fp;
      30    size_t item_idx;
      31    char *tok;
      32    size_t buf_len;
      33  
      34    /* argv-mode: record just argv and current pointer */
      35    char **arg_list;
      36    char **p;
      37  };
      38  
      39  struct argv_iterator *
      40  argv_iter_init_argv (char **argv)
      41  {
      42    struct argv_iterator *ai = malloc (sizeof *ai);
      43    if (!ai)
      44      return NULL;
      45    ai->fp = NULL;
      46    ai->arg_list = argv;
      47    ai->p = argv;
      48    return ai;
      49  }
      50  
      51  /* Initialize to read from the stream, FP.
      52     The input is expected to contain a list of NUL-delimited tokens.  */
      53  struct argv_iterator *
      54  argv_iter_init_stream (FILE *fp)
      55  {
      56    struct argv_iterator *ai = malloc (sizeof *ai);
      57    if (!ai)
      58      return NULL;
      59    ai->fp = fp;
      60    ai->tok = NULL;
      61    ai->buf_len = 0;
      62  
      63    ai->item_idx = 0;
      64    ai->arg_list = NULL;
      65    return ai;
      66  }
      67  
      68  char *
      69  argv_iter (struct argv_iterator *ai, enum argv_iter_err *err)
      70  {
      71    if (ai->fp)
      72      {
      73        ssize_t len = getdelim (&ai->tok, &ai->buf_len, '\0', ai->fp);
      74        if (len < 0)
      75          {
      76            *err = feof (ai->fp) ? AI_ERR_EOF : AI_ERR_READ;
      77            return NULL;
      78          }
      79  
      80        *err = AI_ERR_OK;
      81        ai->item_idx++;
      82        return ai->tok;
      83      }
      84    else
      85      {
      86        if (*(ai->p) == NULL)
      87          {
      88            *err = AI_ERR_EOF;
      89            return NULL;
      90          }
      91        else
      92          {
      93            *err = AI_ERR_OK;
      94            return *(ai->p++);
      95          }
      96      }
      97  }
      98  
      99  size_t
     100  argv_iter_n_args (struct argv_iterator const *ai)
     101  {
     102    return ai->fp ? ai->item_idx : ai->p - ai->arg_list;
     103  }
     104  
     105  void
     106  argv_iter_free (struct argv_iterator *ai)
     107  {
     108    if (ai->fp)
     109      free (ai->tok);
     110    free (ai);
     111  }