/* Python memory buffer interface for reading inferior memory.

   Copyright (C) 2009-2026 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 <http://www.gnu.org/licenses/>.  */

#include "python-internal.h"

struct membuf_object {
  PyObject_HEAD

  /* Pointer to the raw data, and array of gdb_bytes.  */
  void *buffer;

  /* The address from where the data was read, held for mbpy_str.  */
  CORE_ADDR addr;

  /* The number of octets in BUFFER.  */
  CORE_ADDR length;
};

extern PyTypeObject membuf_object_type;

/* Wrap BUFFER, ADDRESS, and LENGTH into a gdb.Membuf object.  ADDRESS is
   the address within the inferior that the contents of BUFFER were read,
   and LENGTH is the number of octets in BUFFER.  */

PyObject *
gdbpy_buffer_to_membuf (gdb::unique_xmalloc_ptr<gdb_byte> buffer,
			CORE_ADDR address,
			ULONGEST length)
{
  gdbpy_ref<membuf_object> membuf_obj (PyObject_New (membuf_object,
						     &membuf_object_type));
  if (membuf_obj == nullptr)
    return nullptr;

  membuf_obj->buffer = buffer.release ();
  membuf_obj->addr = address;
  membuf_obj->length = length;

  return PyMemoryView_FromObject ((PyObject *) membuf_obj.get ());
}

/* Destructor for gdb.Membuf objects.  */

static void
mbpy_dealloc (PyObject *self)
{
  xfree (((membuf_object *) self)->buffer);
  Py_TYPE (self)->tp_free (self);
}

/* Return a description of the gdb.Membuf object.  */

static PyObject *
mbpy_str (PyObject *self)
{
  membuf_object *membuf_obj = (membuf_object *) self;

  return PyUnicode_FromFormat (_("Memory buffer for address %s, \
which is %s bytes long."),
			       paddress (gdbpy_enter::get_gdbarch (),
					 membuf_obj->addr),
			       pulongest (membuf_obj->length));
}

static int
get_buffer (PyObject *self, Py_buffer *buf, int flags)
{
  membuf_object *membuf_obj = (membuf_object *) self;
  int ret;

  ret = PyBuffer_FillInfo (buf, self, membuf_obj->buffer,
			   membuf_obj->length, 0,
			   PyBUF_CONTIG);

  /* Despite the documentation saying this field is a "const char *",
     in Python 3.4 at least, it's really a "char *".  */
  buf->format = (char *) "c";

  return ret;
}

/* General Python initialization callback.  */

static int
gdbpy_initialize_membuf ()
{
  membuf_object_type.tp_new = PyType_GenericNew;
  return gdbpy_type_ready (&membuf_object_type);
}

GDBPY_INITIALIZE_FILE (gdbpy_initialize_membuf);



static PyBufferProcs buffer_procs =
{
  get_buffer
};

PyTypeObject membuf_object_type = {
  PyVarObject_HEAD_INIT (nullptr, 0)
  "gdb.Membuf",			  /*tp_name*/
  sizeof (membuf_object),	  /*tp_basicsize*/
  0,				  /*tp_itemsize*/
  mbpy_dealloc,			  /*tp_dealloc*/
  0,				  /*tp_print*/
  0,				  /*tp_getattr*/
  0,				  /*tp_setattr*/
  0,				  /*tp_compare*/
  0,				  /*tp_repr*/
  0,				  /*tp_as_number*/
  0,				  /*tp_as_sequence*/
  0,				  /*tp_as_mapping*/
  0,				  /*tp_hash */
  0,				  /*tp_call*/
  mbpy_str,			  /*tp_str*/
  0,				  /*tp_getattro*/
  0,				  /*tp_setattro*/
  &buffer_procs,		  /*tp_as_buffer*/
  Py_TPFLAGS_DEFAULT,		  /*tp_flags*/
  "GDB memory buffer object", 	  /*tp_doc*/
  0,				  /* tp_traverse */
  0,				  /* tp_clear */
  0,				  /* tp_richcompare */
  0,				  /* tp_weaklistoffset */
  0,				  /* tp_iter */
  0,				  /* tp_iternext */
  0,				  /* tp_methods */
  0,				  /* tp_members */
  0,				  /* tp_getset */
  0,				  /* tp_base */
  0,				  /* tp_dict */
  0,				  /* tp_descr_get */
  0,				  /* tp_descr_set */
  0,				  /* tp_dictoffset */
  0,				  /* tp_init */
  0,				  /* tp_alloc */
};
