ring.c 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. #include <stddef.h>
  2. #include <string.h>
  3. #include "ring.h"
  4. void ring_rm_(void* data, size_t stride, size_t* len, size_t* first, size_t alloc, size_t i) {
  5. if(*len == 0) return;
  6. size_t end = (*first + *len - 1) % alloc;
  7. size_t n = (*first + i) % alloc;
  8. // simple case for removing the last element
  9. if(n == *len) {
  10. *len = ((*len - 1) + alloc) % alloc;
  11. return;
  12. }
  13. // simple case for removing the first element
  14. if(n == *first) {
  15. *first = (*first + 1) % alloc;
  16. (*len)--;
  17. return;
  18. }
  19. if(end < *first) { // the data wraps around
  20. if(n < end) { // easy case; move the end data backward
  21. void* dst = (char*)data + (n * stride);
  22. void* src = (char*)data + ((n + 1) * stride);
  23. memmove(dst, src, (end - n) * stride);
  24. }
  25. else if(n > *first) { // both ends must be adjusted
  26. // move the tail
  27. memmove(
  28. (char*)data + (n * stride),
  29. (char*)data + ((n + 1) * stride),
  30. (alloc - n - 1) * stride
  31. );
  32. // copy the head to the tail
  33. memcpy(
  34. (char*)data + ((alloc - 1) * stride),
  35. (char*)data,
  36. stride
  37. );
  38. // move the wrapped end back
  39. memmove(
  40. (char*)data,
  41. (char*)data + stride,
  42. (end) * stride
  43. );
  44. }
  45. }
  46. else { // all the data is sequential
  47. void* dst = (char*)data + (n * stride);
  48. void* src = (char*)data + ((n + 1) * stride);
  49. memmove(dst, src, (*len - n - 1) * stride);
  50. }
  51. (*len)--;
  52. }