Skip to content

Commit

Permalink
oh yes! finally no segfa... Aborted (core dumped)
Browse files Browse the repository at this point in the history
  • Loading branch information
sekomer committed Mar 9, 2023
1 parent 74c5b99 commit 4bf5803
Show file tree
Hide file tree
Showing 13 changed files with 301 additions and 107 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ include_directories(${Python_INCLUDE_DIRS})

include_directories(/usr/include/python3.8)

add_library(_structura SHARED src/ringbuffer.c src/structura.c src/stack.c src/linked.c)
add_library(_structura SHARED src/structura.c src/ring.c src/stack.c src/linked.c)

set_target_properties(
structura
Expand Down
2 changes: 1 addition & 1 deletion build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ check_error $? "Failed to remove wheelhouse"

# upload if --upload is specified
if [ "$1" == "--upload" ]; then
sudo twine upload dist/*
twine upload dist/*
check_error $? "Failed to upload package"
fi

Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

def main():
setup(name="structura",
version="0.1.2",
version="0.2.0",
description="C extension module for common data structures",
author="alperen serkan aksoz",
author_email="[email protected]",
Expand Down
2 changes: 1 addition & 1 deletion src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ include_directories(${PROJECT_SOURCE_DIR}/include)
# Add all the source files
set(SOURCES
structura.c
ringbuffer.c
ring.c
stack.c
linked.c
)
Expand Down
120 changes: 86 additions & 34 deletions src/linked.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ Linked_append(Linked *self, PyObject *args)
if (!PyArg_ParseTuple(args, "O", &data))
return NULL;

// TODO: CHECK IF THIS IS NEEDED OR NOT
Py_IncRef(data);

node = (LinkedNode *)PyMem_Malloc(sizeof(LinkedNode));
Expand All @@ -58,6 +57,7 @@ Linked_append(Linked *self, PyObject *args)

self->size++;

Py_DecRef(data);
Py_RETURN_NONE;
}

Expand All @@ -71,7 +71,6 @@ Linked_prepend(Linked *self, PyObject *args)
if (!PyArg_ParseTuple(args, "O", &data))
return NULL;

// TODO: CHECK IF THIS IS NEEDED OR NOT
Py_IncRef(data);

node = (LinkedNode *)PyMem_Malloc(sizeof(LinkedNode));
Expand All @@ -89,6 +88,7 @@ Linked_prepend(Linked *self, PyObject *args)

self->size++;

Py_DecRef(data);
Py_RETURN_NONE;
}

Expand All @@ -99,10 +99,7 @@ Linked_pop(Linked *self, PyObject *args)
LinkedNode *node;

if (self->size == 0)
{
PyErr_SetString(PyExc_IndexError, "pop from empty list");
return NULL;
}
Py_RETURN_NONE;

node = self->tail;
data = node->data;
Expand All @@ -118,18 +115,18 @@ Linked_pop(Linked *self, PyObject *args)
return data;
}

// pop first and return it
static PyObject *
Linked_pop_first(Linked *self, PyObject *args)
Linked_popleft(Linked *self, PyObject *args)
{
PyObject *data;
LinkedNode *node;

if (self->size == 0)
{
PyErr_SetString(PyExc_IndexError, "pop from empty list");
return NULL;
}
Py_RETURN_NONE;

node = self->head;
data = node->data;

self->head = node->next;
if (self->head != NULL)
Expand All @@ -139,42 +136,93 @@ Linked_pop_first(Linked *self, PyObject *args)

self->size--;

Py_RETURN_NONE;
return data;
}

static PyObject *
Linked_delete_at(Linked *self, PyObject *args)
Linked_popat(Linked *self, PyObject *args)
{
PyObject *index_obj;
PyObject *data;
LinkedNode *node;

if (!PyArg_ParseTuple(args, "O", &index_obj))
long index;
if (!PyArg_ParseTuple(args, "l", &index))
return NULL;

Py_IncRef(index_obj);
long index = PyLong_AsLong(index_obj);

if (index < 0 || index >= self->size)
{
PyErr_SetString(PyExc_IndexError, "index out of range");
return NULL;
}
Py_RETURN_NONE;

node = self->head;
if (index == 0)
return Linked_popleft(self, args);

if (index == self->size - 1)
return Linked_pop(self, args);

node = self->head;
for (long i = 0; i < index; i++)
node = node->next;

if (node->prev != NULL)
node->prev->next = node->next;
if (node->next != NULL)
node->next->prev = node->prev;
data = node->data;

// patch the linked list
node->prev->next = node->next;
node->next->prev = node->prev;

// PyMem_Free(node);
PyMem_Free(node);

self->size--;

Py_RETURN_NONE;
return data;
}

static PyObject *
Linked_remove(Linked *self, PyObject *args)
{
PyObject *data;
LinkedNode *node;

if (!PyArg_ParseTuple(args, "O", &data))
return NULL;

Py_IncRef(data);

if (self->size == 0)
{
Py_DecRef(data);
Py_RETURN_FALSE;
}

node = self->head;
while (node != NULL)
{
if (PyObject_RichCompareBool(node->data, data, Py_EQ) == 1)
{
// patch the linked list
if (node->prev != NULL)
node->prev->next = node->next;
if (node->next != NULL)
node->next->prev = node->prev;

/* holy blocks solves fucking bugs */
if (node == self->head)
self->head = node->next;
if (node == self->tail)
self->tail = node->prev;
/* end_holy */

PyMem_Free(node);

self->size--;

Py_DecRef(data);
Py_RETURN_TRUE;
}

node = node->next;
}

Py_DecRef(data);
Py_RETURN_FALSE;
}

static PyObject *
Expand All @@ -186,7 +234,6 @@ Linked_find(Linked *self, PyObject *args)
if (!PyArg_ParseTuple(args, "O", &data))
return NULL;

// TODO: CHECK IF THIS IS NEEDED OR NOT
Py_IncRef(data);

node = self->head;
Expand All @@ -195,12 +242,16 @@ Linked_find(Linked *self, PyObject *args)
while (node != NULL)
{
if (PyObject_RichCompareBool(node->data, data, Py_EQ) == 1)
{
Py_DecRef(data);
return PyLong_FromLong(index);
}

node = node->next;
index++;
}

Py_DecRef(data);
Py_RETURN_NONE;
}

Expand All @@ -213,7 +264,7 @@ Linked_size(Linked *self, PyObject *args)
static PyObject *
Linked_head(Linked *self, PyObject *args)
{
if (self->head == NULL)
if (self->head == NULL || self->size == 0)
Py_RETURN_NONE;

PyObject *head = self->head->data;
Expand All @@ -225,7 +276,7 @@ Linked_head(Linked *self, PyObject *args)
static PyObject *
Linked_tail(Linked *self, PyObject *args)
{
if (self->tail == NULL)
if (self->tail == NULL || self->size == 0)
Py_RETURN_NONE;

PyObject *tail = self->tail->data;
Expand All @@ -238,8 +289,9 @@ static PyMethodDef Linked_methods[] = {
{"append", (PyCFunction)Linked_append, METH_VARARGS, "Append an item to the end of the list"},
{"prepend", (PyCFunction)Linked_prepend, METH_VARARGS, "Append an item to the beginning of the list"},
{"pop", (PyCFunction)Linked_pop, METH_NOARGS, "Remove and return the last item"},
{"pop_first", (PyCFunction)Linked_pop_first, METH_NOARGS, "Remove and return the first item"},
{"delete_at", (PyCFunction)Linked_delete_at, METH_VARARGS, "Delete an item at a given index"},
{"popleft", (PyCFunction)Linked_popleft, METH_NOARGS, "Remove and return the first item"},
{"popat", (PyCFunction)Linked_popat, METH_VARARGS, "Delete an item at a given index"},
{"remove", (PyCFunction)Linked_remove, METH_VARARGS, "Remove the first occurence of an item"},
{"find", (PyCFunction)Linked_find, METH_VARARGS, "Find first occurence of an item and return its index, None otherwise"},
{"size", (PyCFunction)Linked_size, METH_NOARGS, "Return the size of the list"},
{"head", (PyCFunction)Linked_head, METH_NOARGS, "Return the first item"},
Expand Down
10 changes: 5 additions & 5 deletions src/ringbuffer.c → src/ring.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ RingBuffer_is_full(RingBuffer const *self)
static PyObject *
RingBuffer_enqueue(RingBuffer *self, PyObject *args)
{
// its only works with integers, solve that and make it work with any type
PyObject *item = NULL;

if (!PyArg_ParseTuple(args, "O", &item))
Expand All @@ -105,6 +104,7 @@ RingBuffer_enqueue(RingBuffer *self, PyObject *args)
self->size++;
}

// TODO: research, should i decref here?
Py_RETURN_NONE;
}

Expand All @@ -122,16 +122,16 @@ RingBuffer_dequeue(RingBuffer *self)
return item;
}

// TODO: FIX THE SEGMENTATION FAULT
// PROBABLY THE PROBLEM IS WE ARE STORING PYTHON OBJECTS
// WE ARE HOLDING REFERENCES TO THEM INSTEAD OF COPYING THEM
static PyObject *
RingBuffer_peek(RingBuffer const *self)
{
if (self->size == 0)
Py_RETURN_NONE;

return self->items[self->head];
PyObject *item = self->items[self->head];
Py_INCREF(item);

return item;
}

static PyObject *
Expand Down
17 changes: 7 additions & 10 deletions src/stack.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,13 @@ Stack_new(PyTypeObject *type, PyObject *args, PyObject *kwds)

static int Stack_init(Stack *self, PyObject *args)
{
PyObject *capacity = NULL;
long capacity;

// get capacity from args
if (!PyArg_ParseTuple(args, "O", &capacity))
if (!PyArg_ParseTuple(args, "l", &capacity))
return -1;

if (!PyLong_Check(capacity))
{
PyErr_SetString(PyExc_TypeError, "[TypeError] Capacity must be an integer");
return -1;
}

self->capacity = PyLong_AsLong(capacity);
self->capacity = capacity;
self->items = (PyObject **)PyMem_Malloc(self->capacity * sizeof(PyObject *));

if (self->items == NULL)
Expand Down Expand Up @@ -97,7 +91,10 @@ static PyObject *Stack_peek(Stack const *self)
return NULL;
}

return self->items[self->top];
PyObject *item = self->items[self->top];
Py_INCREF(item);

return item;
}

static PyObject *Stack_is_empty(Stack const *self)
Expand Down
Loading

0 comments on commit 4bf5803

Please sign in to comment.