xref: /netbsd-src/external/gpl3/gdb.old/dist/gdbsupport/buildargv.h (revision 32d1c65c71fbdb65a012e8392a62a757dd6853e9)
1 /* RAII wrapper for buildargv
2 
3    Copyright (C) 2021-2023 Free Software Foundation, Inc.
4 
5    This file is part of GDB.
6 
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11 
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16 
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19 
20 #ifndef GDBSUPPORT_BUILDARGV_H
21 #define GDBSUPPORT_BUILDARGV_H
22 
23 #include "libiberty.h"
24 
25 /* A wrapper for an array of char* that was allocated in the way that
26    'buildargv' does, and should be freed with 'freeargv'.  */
27 
28 class gdb_argv
29 {
30 public:
31 
32   /* A constructor that initializes to NULL.  */
33 
34   gdb_argv ()
35     : m_argv (NULL)
36   {
37   }
38 
39   /* A constructor that calls buildargv on STR.  STR may be NULL, in
40      which case this object is initialized with a NULL array.  */
41 
42   explicit gdb_argv (const char *str)
43     : m_argv (NULL)
44   {
45     reset (str);
46   }
47 
48   /* A constructor that takes ownership of an existing array.  */
49 
50   explicit gdb_argv (char **array)
51     : m_argv (array)
52   {
53   }
54 
55   gdb_argv (const gdb_argv &) = delete;
56   gdb_argv &operator= (const gdb_argv &) = delete;
57 
58   gdb_argv &operator= (gdb_argv &&other)
59   {
60     freeargv (m_argv);
61     m_argv = other.m_argv;
62     other.m_argv = nullptr;
63     return *this;
64   }
65 
66   gdb_argv (gdb_argv &&other)
67   {
68     m_argv = other.m_argv;
69     other.m_argv = nullptr;
70   }
71 
72   ~gdb_argv ()
73   {
74     freeargv (m_argv);
75   }
76 
77   /* Call buildargv on STR, storing the result in this object.  Any
78      previous state is freed.  STR may be NULL, in which case this
79      object is reset with a NULL array.  If buildargv fails due to
80      out-of-memory, call malloc_failure.  Therefore, the value is
81      guaranteed to be non-NULL, unless the parameter itself is
82      NULL.  */
83 
84   void reset (const char *str)
85   {
86     char **argv = buildargv (str);
87     freeargv (m_argv);
88     m_argv = argv;
89   }
90 
91   /* Return the underlying array.  */
92 
93   char **get ()
94   {
95     return m_argv;
96   }
97 
98   const char * const * get () const
99   {
100     return m_argv;
101   }
102 
103   /* Return the underlying array, transferring ownership to the
104      caller.  */
105 
106   ATTRIBUTE_UNUSED_RESULT char **release ()
107   {
108     char **result = m_argv;
109     m_argv = NULL;
110     return result;
111   }
112 
113   /* Return the number of items in the array.  */
114 
115   int count () const
116   {
117     return countargv (m_argv);
118   }
119 
120   /* Index into the array.  */
121 
122   char *operator[] (int arg)
123   {
124     gdb_assert (m_argv != NULL);
125     return m_argv[arg];
126   }
127 
128   /* Return the arguments array as an array view.  */
129 
130   gdb::array_view<char *> as_array_view ()
131   {
132     return gdb::array_view<char *> (this->get (), this->count ());
133   }
134 
135   gdb::array_view<const char * const> as_array_view () const
136   {
137     return gdb::array_view<const char * const> (this->get (), this->count ());
138   }
139 
140   /* Append arguments to this array.  */
141   void append (gdb_argv &&other)
142   {
143     int size = count ();
144     int argc = other.count ();
145     m_argv = XRESIZEVEC (char *, m_argv, (size + argc + 1));
146 
147     for (int argi = 0; argi < argc; argi++)
148       {
149 	/* Transfer ownership of the string.  */
150 	m_argv[size++] = other.m_argv[argi];
151 	/* Ensure that destruction of OTHER works correctly.  */
152 	other.m_argv[argi] = nullptr;
153       }
154     m_argv[size] = nullptr;
155   }
156 
157   /* Append arguments to this array.  */
158   void append (const gdb_argv &other)
159   {
160     int size = count ();
161     int argc = other.count ();
162     m_argv = XRESIZEVEC (char *, m_argv, (size + argc + 1));
163 
164     for (int argi = 0; argi < argc; argi++)
165       m_argv[size++] = xstrdup (other.m_argv[argi]);
166     m_argv[size] = nullptr;
167   }
168 
169   /* The iterator type.  */
170 
171   typedef char **iterator;
172 
173   /* Return an iterator pointing to the start of the array.  */
174 
175   iterator begin ()
176   {
177     return m_argv;
178   }
179 
180   /* Return an iterator pointing to the end of the array.  */
181 
182   iterator end ()
183   {
184     return m_argv + count ();
185   }
186 
187   bool operator!= (std::nullptr_t)
188   {
189     return m_argv != NULL;
190   }
191 
192   bool operator== (std::nullptr_t)
193   {
194     return m_argv == NULL;
195   }
196 
197 private:
198 
199   /* The wrapped array.  */
200 
201   char **m_argv;
202 };
203 
204 #endif /* GDBSUPPORT_BUILDARGV_H */
205