Home | History | Annotate | Line # | Download | only in gdbsupport
      1 /* RAII wrapper for buildargv
      2 
      3    Copyright (C) 2021-2024 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