1/* Iterate over arguments from argv or --files0-from=FILE
2   Copyright (C) 2008-2010 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 <http://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
25struct 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
39struct argv_iterator *
40argv_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.  */
53struct argv_iterator *
54argv_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
68char *
69argv_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
99size_t
100argv_iter_n_args (struct argv_iterator const *ai)
101{
102  return ai->fp ? ai->item_idx : ai->p - ai->arg_list;
103}
104
105void
106argv_iter_free (struct argv_iterator *ai)
107{
108  if (ai->fp)
109    free (ai->tok);
110  free (ai);
111}
112