summaryrefslogtreecommitdiff
path: root/src/lacbytequeue.c
blob: b8965db9cca18d1d3947d3c63e23bea3d748fed3 (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
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
struct _LacByteQueue
{
    guint	allocated;

    guint8 *	data;
    guint8 *	head;
    guint8 *	tail;
};

enum {
    INITIAL_SIZE = 256
};

LacByteQueue *
lac_byte_queue_new (void)
{
    LacByteQueue *byte_queue = g_new (LacByteQueue, 1);

    byte_queue->allocated = INITIAL_SIZE;

    byte_queue->data = g_new (guint8, INITIAL_SIZE);
    byte_queue->head = byte_queue->data;
    byte_queue->tail = byte_queue->data;

    return byte_queue;
}

guint
lac_byte_queue_get_length (LacByteQueue *byte_queue)
{
    return byte_queue->tail - byte_queue->head;
}

static guint
lac_byte_queue_get_capacity (LacByteQueue *byte_queue)
{
    return byte_queue->allocated - lac_byte_queue_get_length (byte_queue);
}

static guint
power_of_two_bigger_than (guint n)
{
    guint result = 1;

    while (result <= n)
	result *= 2;

    return result;
}

static void
lac_byte_queue_ensure_capacity (LacByteQueue *byte_queue, guint needed)
{
    guint new_size;
    
    if (needed <= lac_byte_queue_get_capacity (byte_queue))
	return;

    new_size = power_of_two_bigger_than (needed);
}

void
lac_byte_queue_append (LacByteQueue *byte_queue, guint8 *data, guint length)
{
    guint needed_capacity = lac_byte_queue_get_length (byte_queue) + length;
    
    lac_byte_queue_ensure_capacity (byte_queue, needed_capacity);

    if (byte_queue->head >= byte_queue->tail)
    {
	guint bytes_to_copy = MIN (
	    byte_queue->data + byte_queue->allocated - byte_queue->head,
	    length);

	memcpy (byte_queue->head, data, bytes_to_copy);

	byte_queue->head += bytes_to_copy;
	length -= bytes_to_copy;
	data += bytes_to_copy;
	
	if (byte_queue->head == byte_queue->data + byte_queue->allocated)
	    byte_queue->head = byte_queue->data;
    }

    if (length > 0)
    {
	memcpy (byte_queue->head, data, length);

	byte_queue->head += length;
    }
}