/* Copyright (C) 2013-2023 Free Software Foundation, Inc.

   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 <http://www.gnu.org/licenses/>.  */

#include "defs.h"
#include "python-internal.h"
#include "varobj.h"
#include "varobj-iter.h"
#include "valprint.h"

/* A dynamic varobj iterator "class" for python pretty-printed
   varobjs.  This inherits struct varobj_iter.  */

struct py_varobj_iter : public varobj_iter
{
  py_varobj_iter (struct varobj *var, gdbpy_ref<> &&pyiter,
		  const value_print_options *opts);
  ~py_varobj_iter () override;

  std::unique_ptr<varobj_item> next () override;

private:

  /* The varobj this iterator is listing children for.  */
  struct varobj *m_var;

  /* The next raw index we will try to check is available.  If it is
     equal to number_of_children, then we've already iterated the
     whole set.  */
  int m_next_raw_index = 0;

  /* The python iterator returned by the printer's 'children' method,
     or NULL if not available.  */
  PyObject *m_iter;

  /* The print options to use.  */
  value_print_options m_opts;
};

/* Implementation of the 'dtor' method of pretty-printed varobj
   iterators.  */

py_varobj_iter::~py_varobj_iter ()
{
  gdbpy_enter_varobj enter_py (m_var);
  Py_XDECREF (m_iter);
}

/* Implementation of the 'next' method of pretty-printed varobj
   iterators.  */

std::unique_ptr<varobj_item>
py_varobj_iter::next ()
{
  PyObject *py_v;
  varobj_item *vitem;
  const char *name = NULL;

  if (!gdb_python_initialized)
    return NULL;

  gdbpy_enter_varobj enter_py (m_var);

  scoped_restore set_options = make_scoped_restore (&gdbpy_current_print_options,
						    &m_opts);

  gdbpy_ref<> item (PyIter_Next (m_iter));

  if (item == NULL)
    {
      /* Normal end of iteration.  */
      if (!PyErr_Occurred ())
	return NULL;

      /* If we got a memory error, just use the text as the item.  */
      if (PyErr_ExceptionMatches (gdbpy_gdb_memory_error))
	{
	  gdbpy_err_fetch fetched_error;
	  gdb::unique_xmalloc_ptr<char> value_str = fetched_error.to_string ();
	  if (value_str == NULL)
	    {
	      gdbpy_print_stack ();
	      return NULL;
	    }

	  std::string name_str = string_printf ("<error at %d>",
						m_next_raw_index++);
	  item.reset (Py_BuildValue ("(ss)", name_str.c_str (),
				     value_str.get ()));
	  if (item == NULL)
	    {
	      gdbpy_print_stack ();
	      return NULL;
	    }
	}
      else
	{
	  /* Any other kind of error.  */
	  gdbpy_print_stack ();
	  return NULL;
	}
    }

  if (!PyArg_ParseTuple (item.get (), "sO", &name, &py_v))
    {
      gdbpy_print_stack ();
      error (_("Invalid item from the child list"));
    }

  vitem = new varobj_item ();
  vitem->value = release_value (convert_value_from_python (py_v));
  if (vitem->value == NULL)
    gdbpy_print_stack ();
  vitem->name = name;

  m_next_raw_index++;
  return std::unique_ptr<varobj_item> (vitem);
}

/* Constructor of pretty-printed varobj iterators.  VAR is the varobj
   whose children the iterator will be iterating over.  PYITER is the
   python iterator actually responsible for the iteration.  */

py_varobj_iter::py_varobj_iter (struct varobj *var, gdbpy_ref<> &&pyiter,
				const value_print_options *opts)
  : m_var (var),
    m_iter (pyiter.release ()),
    m_opts (*opts)
{
}

/* Return a new pretty-printed varobj iterator suitable to iterate
   over VAR's children.  */

std::unique_ptr<varobj_iter>
py_varobj_get_iterator (struct varobj *var, PyObject *printer,
			const value_print_options *opts)
{
  gdbpy_enter_varobj enter_py (var);

  if (!PyObject_HasAttr (printer, gdbpy_children_cst))
    return NULL;

  scoped_restore set_options = make_scoped_restore (&gdbpy_current_print_options,
						    opts);

  gdbpy_ref<> children (PyObject_CallMethodObjArgs (printer, gdbpy_children_cst,
						    NULL));
  if (children == NULL)
    {
      gdbpy_print_stack ();
      error (_("Null value returned for children"));
    }

  gdbpy_ref<> iter (PyObject_GetIter (children.get ()));
  if (iter == NULL)
    {
      gdbpy_print_stack ();
      error (_("Could not get children iterator"));
    }

  return std::unique_ptr<varobj_iter> (new py_varobj_iter (var,
							   std::move (iter),
							   opts));
}
