/* RAII wrapper for buildargv Copyright (C) 2021-2023 Free Software Foundation, Inc. This file is part of GDB. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #ifndef GDBSUPPORT_BUILDARGV_H #define GDBSUPPORT_BUILDARGV_H #include "libiberty.h" /* A wrapper for an array of char* that was allocated in the way that 'buildargv' does, and should be freed with 'freeargv'. */ class gdb_argv { public: /* A constructor that initializes to NULL. */ gdb_argv () : m_argv (NULL) { } /* A constructor that calls buildargv on STR. STR may be NULL, in which case this object is initialized with a NULL array. */ explicit gdb_argv (const char *str) : m_argv (NULL) { reset (str); } /* A constructor that takes ownership of an existing array. */ explicit gdb_argv (char **array) : m_argv (array) { } gdb_argv (const gdb_argv &) = delete; gdb_argv &operator= (const gdb_argv &) = delete; gdb_argv &operator= (gdb_argv &&other) { freeargv (m_argv); m_argv = other.m_argv; other.m_argv = nullptr; return *this; } gdb_argv (gdb_argv &&other) { m_argv = other.m_argv; other.m_argv = nullptr; } ~gdb_argv () { freeargv (m_argv); } /* Call buildargv on STR, storing the result in this object. Any previous state is freed. STR may be NULL, in which case this object is reset with a NULL array. If buildargv fails due to out-of-memory, call malloc_failure. Therefore, the value is guaranteed to be non-NULL, unless the parameter itself is NULL. */ void reset (const char *str) { char **argv = buildargv (str); freeargv (m_argv); m_argv = argv; } /* Return the underlying array. */ char **get () { return m_argv; } const char * const * get () const { return m_argv; } /* Return the underlying array, transferring ownership to the caller. */ ATTRIBUTE_UNUSED_RESULT char **release () { char **result = m_argv; m_argv = NULL; return result; } /* Return the number of items in the array. */ int count () const { return countargv (m_argv); } /* Index into the array. */ char *operator[] (int arg) { gdb_assert (m_argv != NULL); return m_argv[arg]; } /* Return the arguments array as an array view. */ gdb::array_view as_array_view () { return gdb::array_view (this->get (), this->count ()); } gdb::array_view as_array_view () const { return gdb::array_view (this->get (), this->count ()); } /* Append arguments to this array. */ void append (gdb_argv &&other) { int size = count (); int argc = other.count (); m_argv = XRESIZEVEC (char *, m_argv, (size + argc + 1)); for (int argi = 0; argi < argc; argi++) { /* Transfer ownership of the string. */ m_argv[size++] = other.m_argv[argi]; /* Ensure that destruction of OTHER works correctly. */ other.m_argv[argi] = nullptr; } m_argv[size] = nullptr; } /* Append arguments to this array. */ void append (const gdb_argv &other) { int size = count (); int argc = other.count (); m_argv = XRESIZEVEC (char *, m_argv, (size + argc + 1)); for (int argi = 0; argi < argc; argi++) m_argv[size++] = xstrdup (other.m_argv[argi]); m_argv[size] = nullptr; } /* The iterator type. */ typedef char **iterator; /* Return an iterator pointing to the start of the array. */ iterator begin () { return m_argv; } /* Return an iterator pointing to the end of the array. */ iterator end () { return m_argv + count (); } bool operator!= (std::nullptr_t) { return m_argv != NULL; } bool operator== (std::nullptr_t) { return m_argv == NULL; } private: /* The wrapped array. */ char **m_argv; }; #endif /* GDBSUPPORT_BUILDARGV_H */