/* 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));
}
