summaryrefslogtreecommitdiff
path: root/src/std/containers/ring_queue.c
blob: 8bfc10b9dd90b901ebfb64fe081b8c9170ed733c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#include "ring_queue.h"

#include <stdlib.h>
#include <string.h>
#include "defines.h"

ring_queue* ring_queue_new(size_t type_size, size_t capacity, void* memory) {
  ring_queue* q = malloc(sizeof(ring_queue));
  q->len = 0;
  q->capacity = capacity;
  q->type_size = type_size;
  q->head = 0;
  q->tail = -1;

  if (memory) {
    // caller owns the memory
    q->owns_memory = false;
    q->data = memory;
  } else {
    // ring queue should own the memory
    q->owns_memory = true;
    q->data = malloc(capacity * type_size);
  }

  return q;
}

void ring_queue_free(ring_queue* queue) {
  if (queue) {
    if (queue->owns_memory) {
      free(queue->data);
    }
    free(queue);
  }
}

bool ring_queue_enqueue(ring_queue* queue, const void* value) {
  if (queue->len == queue->capacity) {
    return false;
  }

  queue->tail = (queue->tail + 1) % queue->capacity;
  memcpy(queue->data + (queue->tail * queue->type_size), value, queue->type_size);
  queue->len++;
  return true;
}

bool ring_queue_dequeue(ring_queue* queue, void* out_value) {
  if (queue->len == 0) {
    // queue is empty
    return false;
  }

  memcpy(out_value, queue->data + (queue->head * queue->type_size), queue->type_size);
  queue->head = (queue->head + 1) % queue->capacity;
  queue->len--;
  return true;
}

bool ring_queue_peek(const ring_queue* queue, void* out_value) {
  if (queue->len == 0) {
    // queue is empty
    return false;
  }

  memcpy(out_value, queue->data + (queue->head * queue->type_size), queue->type_size);
  return true;
}