/*
* Get the range of items in a list from 'start' to 'end'.
* This function allocates memory. An array of pointers and all the strings pointed to by it
* are dynamically allocated. redis_free_array_results() has to be called to free this
* allocated memory by the caller.
* */
int redis_list_get_range(char *key, int start, int end, char ***items, int *items_count) {
/*
* The Redis protocol is elegantly simple. The following is a response for an array
* that has 3 elements (strings):
* Example response:
* *3\r\n$5\r\nHello\r\n$6\r\nLovely\r\n\$5\r\nWorld\r\n
*
* What it means:
* *3 -> Array with 3 items
* $5 -> string with 5 characters
* Hello -> actual string
* $6 -> string with 6 characters
* Lovely -> actual string
* $5 -> string with 5 characters
* World -> actual string
*
* A '\r\n' (carriage return + line feed) sequence is used as the delimiter.
* Now, you should be able to understand why we're doing what we're doing in this function
* */
char cmd_buf[1024]="", start_str[16], end_str[16];
sprintf(start_str, "%d", start);
sprintf(end_str, "%d", end);
sprintf(cmd_buf, "*4\r\n$6\r\nLRANGE\r\n$%ld\r\n%s\r\n$%ld\r\n%s\r\n$%ld\r\n%s\r\n", strlen(key), key, strlen(start_str), start_str, strlen(end_str), end_str);
write(redis_socket_fd, cmd_buf, strlen(cmd_buf));
/* Find out the length of the array */
char ch;
read(redis_socket_fd, &ch, 1);
if (ch != '*')
return -1;
int returned_items = 0;
while (1) {
read(redis_socket_fd, &ch, 1);
if (ch == '\r') {
/* Read the next '\n' character */
read(redis_socket_fd, &ch, 1);
break;
}
returned_items = (returned_items * 10) + (ch - '0');
}
/* Allocate the array that will hold a pointer each for
* every element in the returned list */
*items_count = returned_items;
char **items_holder = malloc(sizeof(char *) * returned_items);
*items = items_holder;
/*
* We now know the length of the array. Let's loop that many iterations
* and grab those strings, allocating a new chunk of memory for each one.
* */
for (int i = 0; i < returned_items; i++) {
/* read the first '$' */
read(redis_socket_fd, &ch, 1);
int str_size = 0;
while (1) {
read(redis_socket_fd, &ch, 1);
if (ch == '\r') {
/* Read the next '\n' character */
read(redis_socket_fd, &ch, 1);
break;
}
str_size = (str_size * 10) + (ch - '0');
}
char *str = malloc(sizeof(char) * str_size + 1);
items_holder[i] = str;
read(redis_socket_fd, str, str_size);
str[str_size] = '\0';
/* Read the '\r\n' chars */
read(redis_socket_fd, &ch, 1);
read(redis_socket_fd, &ch, 1);
}
}