#include "VarBuffer.h" VarBuffer::VarBuffer(unsigned long length, bool bReadWait, bool bWriteWait) : m_iBufferLength(length) , m_pBuffer(nullptr) , m_iReadIndex(0) , m_iWriteIndex(0) , m_bIsOneCycle(true) , m_bReadWait(bReadWait) , m_bWriteWait(bWriteWait) { m_pBuffer = new unsigned char[length]; } VarBuffer::~VarBuffer() { if (nullptr != m_pBuffer) delete m_pBuffer; } // detect the frame length, frame length is an unsigned short unsigned short VarBuffer::GetFrameLength() { int diff = m_iBufferLength - m_iReadIndex; if (diff >= 6 && m_pBuffer[m_iReadIndex] == 0xEB && m_pBuffer[m_iReadIndex + 1] == 0x90) return m_pBuffer[m_iReadIndex + 5] * 256 + m_pBuffer[m_iReadIndex + 4]; else if (diff < 6 && m_pBuffer[m_iReadIndex % m_iBufferLength] == 0xEB && m_pBuffer[(m_iReadIndex + 1) % m_iBufferLength] == 0x90) return m_pBuffer[(m_iReadIndex + 5) % m_iBufferLength] * 256 + m_pBuffer[(m_iReadIndex + 4) % m_iBufferLength]; else throw "GET FRAME LENGTH ERROR: didn't read the right frame head"; } // verify the to-be-written frame length, frame length is an unsigned short bool VarBuffer::verifyFrameLength(unsigned char* buf, unsigned short length) { if (buf[0] != 0xEB || buf[1] != 0x90) { return false; } if (*(reinterpret_cast(buf + VarHeadLength)) != length) { // printf("%x, %x, %x \n", buf[2], buf[3]*256, length); return false; } return true; } // read data from memory to an output buffer // two arguments: the point and the length of output buffer // correct: return frame length // error: return -1 unsigned short VarBuffer::read(unsigned char* buf, unsigned short length) { int frameLength = 0; { QMutexLocker locker(&m_mutex); while (IsEmpty(0)) { if (m_bReadWait) { // add wait here, to wait for sufficient data to read m_condRead.wait(&m_mutex); } else { return 0; } } frameLength = GetFrameLength(); if (frameLength > length) { // throw "READ ERROR: the frame data length is larger than output data buffer"; return -1; } for (int i = 0; i < frameLength; i++) { buf[i] = m_pBuffer[m_iReadIndex]; m_iReadIndex++; if (m_iReadIndex >= m_iBufferLength) { m_iReadIndex = 0; m_bIsOneCycle = true; } } } m_condWrite.wakeOne(); return frameLength; } // write one frame data to memory // one argument: the length of frame to write in (unsigned short) int VarBuffer::write(unsigned char* buf, unsigned short length) { if (length < MIN_FRAME_LENGTH || length > m_iBufferLength) { return -1; } { QMutexLocker locker(&m_mutex); while (IsFull(length)) { if (m_bWriteWait) { // add wait here, to wait for sufficient data to read m_condWrite.wait(&m_mutex); } else { return 0; } } for (int i = 0; i < length; i++) { m_pBuffer[m_iWriteIndex] = buf[i]; m_iWriteIndex++; if (m_iWriteIndex == m_iBufferLength) { m_iWriteIndex = 0; m_bIsOneCycle = false; } } } m_condRead.wakeOne(); return length; } // memory is full, no place to write // tow different situations: readIndex and writeIndex is in one cycle or not // one argument: the length of frame bool VarBuffer::IsFull(unsigned short length) { if (m_bIsOneCycle == true) { return m_iWriteIndex + length > m_iReadIndex + m_iBufferLength; } return m_iWriteIndex + length > m_iReadIndex; } // memory is empty, no data to read // tow different situations: readIndex and writeIndex is in one cycle or not bool VarBuffer::IsEmpty(unsigned short length) { if (m_bIsOneCycle == true) { return m_iReadIndex + length >= m_iWriteIndex; // return m_iReadIndex == m_iWriteIndex; } return m_iReadIndex + length >= m_iWriteIndex + m_iBufferLength; // return m_iReadIndex == m_iWriteIndex + m_iBufferLength; }