Skip to content

Commit ff42b09

Browse files
Added functions to get the last and the Nth elements from a fifo.
1 parent c745160 commit ff42b09

File tree

4 files changed

+170
-11
lines changed

4 files changed

+170
-11
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
set(NLUTILS_VERSION 0.12.9)
1+
set(NLUTILS_VERSION 0.12.10)
22
set(NLUTILS_SO_VERSION 12)
33

44
cmake_minimum_required(VERSION 2.6)

include/fifo.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,23 @@ void *nl_fifo_get(struct nl_fifo *l);
6464
*/
6565
void *nl_fifo_peek(struct nl_fifo *l);
6666

67+
/*
68+
* Retrieves, but does not remove the most-recently-added (last) element from
69+
* the fifo. Returns NULL if the list is empty or an error occurs.
70+
*/
71+
void *nl_fifo_peek_last(struct nl_fifo *l);
72+
73+
/*
74+
* Retrieves, but does not remove the Nth-least-recently-added element (Nth
75+
* element in the list) from the fifo. Be aware that this is O(N). If the
76+
* index is negative, then indexing starts from the end, with -1 referring to
77+
* the most-recently-added (last) element.
78+
*
79+
* Returns NULL if the list is empty, the index is out of range, or an error
80+
* occurs.
81+
*/
82+
void *nl_fifo_peek_index(struct nl_fifo *l, ssize_t index);
83+
6784
/*
6885
* Removes the least-recently-added instance of the given element from the
6986
* fifo. Returns 0 if the element existed and was deleted, -1 if the element

src/fifo.c

Lines changed: 55 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -190,8 +190,8 @@ void *nl_fifo_get(struct nl_fifo *l)
190190
}
191191

192192
/*
193-
* Retrieves, but does not remove the least-recently-added element from the
194-
* fifo. Returns NULL if the list is empty or an error occurs.
193+
* Retrieves, but does not remove the least-recently-added (first) element from
194+
* the fifo. Returns NULL if the list is empty or an error occurs.
195195
*/
196196
void *nl_fifo_peek(struct nl_fifo *l)
197197
{
@@ -205,6 +205,59 @@ void *nl_fifo_peek(struct nl_fifo *l)
205205
return l->first->data;
206206
}
207207

208+
/*
209+
* Retrieves, but does not remove the most-recently-added (last) element from
210+
* the fifo. Returns NULL if the list is empty or an error occurs.
211+
*/
212+
void *nl_fifo_peek_last(struct nl_fifo *l)
213+
{
214+
if (CHECK_NULL(l)) {
215+
return NULL;
216+
}
217+
if (l->count == 0) {
218+
return NULL;
219+
}
220+
221+
return l->last->data;
222+
}
223+
224+
/*
225+
* Retrieves, but does not remove the Nth-least-recently-added element (Nth
226+
* element in the list) from the fifo. Be aware that this is O(N). If the
227+
* index is negative, then indexing starts from the end, with -1 referring to
228+
* the most-recently-added (last) element.
229+
*
230+
* Returns NULL if the list is empty, the index is out of range, or an error
231+
* occurs.
232+
*/
233+
void *nl_fifo_peek_index(struct nl_fifo *l, ssize_t index)
234+
{
235+
if (CHECK_NULL(l)) {
236+
return NULL;
237+
}
238+
if (l->count == 0) {
239+
return NULL;
240+
}
241+
242+
ssize_t normalized_index = index;
243+
if (normalized_index < 0) {
244+
normalized_index += l->count;
245+
}
246+
247+
if (normalized_index < 0 || normalized_index >= l->count) {
248+
ERROR_OUT("Index %zd is out of range 0..%u (or -%u..-1)\n",
249+
index, l->count - 1, l->count);
250+
return NULL;
251+
}
252+
253+
const struct nl_fifo_element *iter = NULL;
254+
for (ssize_t i = 0; i < normalized_index; i++) {
255+
nl_fifo_next(l, &iter);
256+
}
257+
258+
return nl_fifo_next(l, &iter);
259+
}
260+
208261
/*
209262
* Removes the least-recently-added instance of the given element from the
210263
* fifo. Returns 0 if the element existed and was deleted, -1 if the element

tests/fifo_test.c

Lines changed: 97 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -104,25 +104,46 @@ static int test_get(struct nl_fifo *fifo, const char *expected, unsigned int cou
104104
return error;
105105
}
106106

107-
static int test_peek(struct nl_fifo *fifo, char *expected, unsigned int count)
107+
static int test_peek(struct nl_fifo *fifo, char *expected, unsigned int count, int peek_last)
108108
{
109+
char *suffix = peek_last ? "_last" : "";
109110
char *result;
110111
unsigned int oldcount = fifo->count;
111112
int error = 0;
112113

113-
result = nl_fifo_peek(fifo);
114+
result = peek_last ? nl_fifo_peek_last(fifo) : nl_fifo_peek(fifo);
114115
if(result != expected) {
115-
ERROR_OUT("nl_fifo_peek() returned %s, expected %s.\n", result, expected);
116+
ERROR_OUT("nl_fifo_peek%s() returned %s, expected %s.\n",
117+
suffix, result, expected);
116118
error = -1;
117119
}
118120

119121
if(oldcount != fifo->count) {
120-
ERROR_OUT("Count changed from %d to %d after nl_fifo_peek().\n", oldcount, fifo->count);
122+
ERROR_OUT("Count changed from %d to %d after nl_fifo_peek%s().\n",
123+
oldcount, fifo->count, suffix);
121124
error = -1;
122125
}
123126

124127
if(fifo->count != count) {
125-
ERROR_OUT("Expected count of %d after nl_fifo_peek(), actually %d.\n", count, fifo->count);
128+
ERROR_OUT("Expected count of %d after nl_fifo_peek%s(), actually %d.\n", count, suffix, fifo->count);
129+
error = -1;
130+
}
131+
132+
return error;
133+
}
134+
135+
static int test_peek_index(struct nl_fifo *fifo, char *expected, ssize_t index)
136+
{
137+
int error = 0;
138+
unsigned int oldcount = fifo->count;
139+
char *result = nl_fifo_peek_index(fifo, index);
140+
if (result != expected) {
141+
ERROR_OUT("nl_fifo_peek_index(%zd) returned %s, expected %s.\n", index, result, expected);
142+
error = -1;
143+
}
144+
145+
if (oldcount != fifo->count) {
146+
ERROR_OUT("nl_fifo_peek_index(%zd) changed count from %d to %d (shouldn't have changed).\n", index, oldcount, fifo->count);
126147
error = -1;
127148
}
128149

@@ -594,20 +615,70 @@ int main(void)
594615
return -1;
595616
}
596617

597-
if(test_peek(f1, str1, 1)) {
618+
if(test_peek(f1, str1, 1, 0)) {
598619
ERR(f1, "Error peeking single-element FIFO.\n");
599620
return -1;
600621
}
622+
if(test_peek(f1, str1, 1, 1)) {
623+
ERR(f1, "Error peeking last element on single-element FIFO.\n");
624+
return -1;
625+
}
626+
627+
if (test_peek_index(f1, str1, 0)) {
628+
ERR(f1, "Error peeking at valid index on single-element FIFO.\n");
629+
return -1;
630+
}
631+
if (test_peek_index(f1, str1, -1)) {
632+
ERR(f1, "Error peeking at valid negative index on single-element FIFO.\n");
633+
return -1;
634+
}
635+
if (test_peek_index(f1, NULL, 1)) {
636+
ERR(f1, "Error peeking at invalid index on single-element FIFO.\n");
637+
return -1;
638+
}
639+
if (test_peek_index(f1, NULL, -2)) {
640+
ERR(f1, "Error peeking at invalid negative index on single-element FIFO.\n");
641+
return -1;
642+
}
601643

602644
if(test_put(f1, str2, 2)) {
603645
ERR(f1, "Error adding %s to FIFO.\n", str2);
604646
return -1;
605647
}
606648

607-
if(test_peek(f1, str1, 2)) {
649+
if(test_peek(f1, str1, 2, 0)) {
608650
ERR(f1, "Error peeking two-element FIFO.\n");
609651
return -1;
610652
}
653+
if(test_peek(f1, str2, 2, 1)) {
654+
ERR(f1, "Error peeking last element on two-element FIFO.\n");
655+
return -1;
656+
}
657+
658+
if (test_peek_index(f1, str1, 0)) {
659+
ERR(f1, "Error peeking at valid index on two-element FIFO.\n");
660+
return -1;
661+
}
662+
if (test_peek_index(f1, str2, 1)) {
663+
ERR(f1, "Error peeking at valid index on two-element FIFO.\n");
664+
return -1;
665+
}
666+
if (test_peek_index(f1, str2, -1)) {
667+
ERR(f1, "Error peeking at valid negative index on two-element FIFO.\n");
668+
return -1;
669+
}
670+
if (test_peek_index(f1, str1, -2)) {
671+
ERR(f1, "Error peeking at valid negative index on two-element FIFO.\n");
672+
return -1;
673+
}
674+
if (test_peek_index(f1, NULL, 2)) {
675+
ERR(f1, "Error peeking at invalid index on two-element FIFO.\n");
676+
return -1;
677+
}
678+
if (test_peek_index(f1, NULL, -3)) {
679+
ERR(f1, "Error peeking at invalid negative index on two-element FIFO.\n");
680+
return -1;
681+
}
611682

612683
if(!nl_fifo_remove(f1, NULL)) {
613684
ERR(f1, "No error removing NULL from a FIFO.\n");
@@ -808,10 +879,28 @@ int main(void)
808879
return -1;
809880
}
810881

811-
if(test_peek(f1, str1, i * 3 + 3)) {
882+
if(test_peek(f1, str1, i * 3 + 3, 0)) {
812883
ERR(f1, "Error peeking %s\n", str1);
813884
return -1;
814885
}
886+
887+
if(test_peek(f1, str3, i * 3 + 3, 1)) {
888+
ERR(f1, "Error peeking last element %s\n", str3);
889+
return -1;
890+
}
891+
}
892+
893+
// f1 should have a repeating sequence of str1, str2, str3, str1, etc.
894+
if (test_peek_index(f1, str1, 3) || test_peek_index(f1, str2, 31) || test_peek_index(f1, str3, 299) ||
895+
test_peek_index(f1, str3, -1) || test_peek_index(f1, str2, -5) || test_peek_index(f1, str1, -9) ||
896+
test_peek_index(f1, str1, -300)) {
897+
ERR(f1, "Error peeking at indexes in longer fifo");
898+
return -1;
899+
}
900+
901+
if (test_peek_index(f1, NULL, -301) || test_peek_index(f1, NULL, 300)) {
902+
ERR(f1, "Error peeking out-of-range indexes in longer fifo");
903+
return -1;
815904
}
816905

817906
for(i = 0; i < 12; i++) {

0 commit comments

Comments
 (0)