#pragma once #if defined TARGET_HAS_ThirdPartyGUSBampCAPI_Linux #include #include #ifndef MIN #define MIN(a, b) (((a) < (b)) ? (a) : (b)) #endif #ifndef MAX #define MAX(a, b) (((a) > (b)) ? (a) : (b)) #endif template class Queue { T* buffer = nullptr; int head = 0, tail = 0, size = 0; public: Queue() { } Queue(T* array, const int len) { size = len; buffer = array; } void SetBuffer(T* array, const int len) { size = len; head = tail = 0; buffer = array; } int Get(T* elements, int len) { // Trim the length if necessary to only as large as the number of available elements in the buffer len = MIN(len, Avail()); int nonwrapped = MIN((size - tail), len); const int wrapped = len - nonwrapped; // memcpy the data starting at the head all the way up to the last element *(storage - 1) memcpy(elements, (buffer + tail), nonwrapped * sizeof(T)); // If there's still data to copy memcpy whatever remains, starting at the first element *(begin) until the end of data. The first step will have ensured // that we don't crash into the tail during this process. memcpy((elements + nonwrapped), buffer, wrapped * sizeof(T)); // Recalculate head tail = (tail + nonwrapped + wrapped) % size; return len; } // Returns the number of bytes actually placed in the array int Put(const T* elements, int len) { // Trim the length if necessary to only as large as the nuber of free elements in the buffer len = MIN(len, Free()); // Figure out how much to append to the end of the buffer and how much will overlap onto the start int nonwrapped = MIN((size - head), len); const int wrapped = len - nonwrapped; // memcpy the data starting at the head all the way up to the last element *(storage - 1) memcpy((buffer + head), elements, nonwrapped * sizeof(T)); // If there's still data to copy memcpy whatever remains onto the beginning of the array memcpy(buffer, (elements + nonwrapped), wrapped * sizeof(T)); // Re-recalculate head head = (head + nonwrapped + wrapped) % size; return len; } // Expand the size of queue without actually modifying any of the contents - useful for copying directly onto the queu buffer int Pad(int len) { // Trim the length if necessary to only as large as the nuber of free elements in the buffer len = MIN(len, Free()); // Figure out how much to append to the end of the buffer and how much will overlap onto the start const int nonwrapped = MIN((size - head), len), wrapped = len - nonwrapped; // Re-recalculate head head = (head + nonwrapped + wrapped) % size; return len; } // Removes the oldest entry from the Queue void Pop() { if (Avail()) tail = (tail + 1) % size; } // Returns the oldest element in the array (the one added before any other) T& Tail() { return buffer[tail]; } // Returns the newest element in the array (the one added after every other) T& Head() { return buffer[(head + size - 1) % size]; } T& operator[](int n) { return buffer[tail + n % size]; } void Clear() { head = tail = 0; } int Avail() const { return (size + head - tail) % size; } int Free() const { return (size - 1 - Avail()); } // Gets the number of free elements that can be stored contiguously int FreeContiguous() { return head < tail ? tail - head - 1 : MIN(size - head, Free()); } // Gets a pointer to the next free address in the buffer T* NextFreeAddress() { return buffer + head; } }; #endif // TARGET_HAS_ThirdPartyGUSBampCAPI_Linux