📄 data_lgr.cpp
字号:
//*************************************************************************************
// DATA_LGR.CPP
// This file contains the implementation for the data logger class. The logger
// holds data in a linear, circular, or expanding buffer.
//
// Version
// 1-21-95 JR Original version
// 2-02-95 JR Circular array added
// 2-12-95 JR Bug fix (already)
// 7-18-95 JR Uses new version of base_obj.cpp with new list objects
//*************************************************************************************
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <values.h> // Use maximum numbers defined here as error indicators
#include "base_obj.hpp"
#include "data_lgr.hpp"
//=====================================================================================
// Class: CQueueArray
// This is an array which is of fixed size and stores data in increasing, linear
// order as it is received. There is a read pointer and a write pointer; the
// read pointer follows the write pointer so that the array acts as a FIFO (First
// In, First Out) storage element. Because any kind of data must be able to be
// stored in this array, access is through data pointers.
//=====================================================================================
//-------------------------------------------------------------------------------------
// Constructor: CQueueArray
// This constructor calls that of CBasicArray, then starts the data pointers at 0.
CQueueArray::CQueueArray (unsigned aDataSize, unsigned aArraySize)
: CBasicArray (aDataSize, aArraySize)
{
WriteIndex = 0; // Set the read and write indices to 0 'cause
ReadIndex = 0; // there isn't any data yet
PointsTaken = 0; // Note that we haven't taken any data yet
}
//-------------------------------------------------------------------------------------
// Destructor: ~CQueueArray
// This destructor, uh,...?
CQueueArray::~CQueueArray (void)
{
// for (CListNode* pCur = pFirst; pCur != NULL; pCur = pCur->pNextNode)
// delete (pCur->pNodeData);
}
//-------------------------------------------------------------------------------------
// Function: WritePointer
// When you're going to write some data to the array, use this function to get a
// write pointer. It will automatically increment the index to the next item,
// so don't use it in vain or you'll leave gaps in your data.
void* CQueueArray::WritePointer (void)
{
// Check if the write index is within array bounds; if not return NULL
if (WriteIndex >= TotalSize)
return (NULL);
// If the index is within bounds, get a copy of the pointer which can be returned
void* ThePtr = operator[] (WriteIndex);
// Next increment the index so it points to the next item, if there is one
++WriteIndex;
++PointsTaken;
// Finally return the pointer we found before incrementing
return (ThePtr);
}
//-------------------------------------------------------------------------------------
// Function: ReadPointer
// The read pointer works like the write pointer except that you can't read data
// which hasn't been written; so the reader's not allowed to catch the writer.
void* CQueueArray::ReadPointer (void)
{
// Check that the read index is less than the write index; if not, we're trying
// to read before writing, so return NULL
if (ReadIndex >= WriteIndex)
return (NULL);
// If the read index is OK, get a copy of the pointer and return it
void* ThePtr = operator[] (ReadIndex);
++ReadIndex;
return (ThePtr);
}
//-------------------------------------------------------------------------------------
// Function: Flush
// The flushing of a queue is simple: just set the read and write indices to 0 so
// that new data can be written and read. The data array has been allocated
// already, so just leave it.
void CQueueArray::Flush (void)
{
WriteIndex = 0;
ReadIndex = 0;
PointsTaken = 0;
}
//-------------------------------------------------------------------------------------
// Function: Rewind
// This function resets the read pointer to the beginning of the data, thereby
// allowing the array to be read again from its 'full' state.
void CQueueArray::Rewind (void)
{
ReadIndex = 0;
}
//=====================================================================================
// Class: CExpandingArray
// This variation on the queue array "expands" - i.e. allocates some new memory
// for more data - whenever it overflows. Otherwise, it's used just the same as
// the fixed-size queue.
//=====================================================================================
//-------------------------------------------------------------------------------------
// Constructor: CExpandingArray
// This constructor starts up the array with one buffer allocated and the read
// and write pointers set to the 0-th element...well actually the constructor
// for CQueueArray does all that.
CExpandingArray::CExpandingArray (unsigned aDataSize, unsigned aArraySize)
: CQueueArray (aDataSize, aArraySize)
{
}
//-------------------------------------------------------------------------------------
// Destructor: ~CExpandingArray
// This thing frees up memory.
CExpandingArray::~CExpandingArray (void)
{
}
//-------------------------------------------------------------------------------------
// Function: WritePointer
// When you're going to write some data to the array, use this function to get a
// write pointer. It will automatically increment the index to the next item,
// so don't use it in vain or you'll leave gaps in your data.
void* CExpandingArray::WritePointer (void)
{
// If the write index is greater than the current size of the array, we must
// allocate another buffer
if (WriteIndex >= TotalSize)
{
if (Expand () == 0) // A zero means we can't allocate more
return (NULL);
}
// If the index is within bounds, get a copy of the pointer which can be returned
void* ThePtr = operator[] (WriteIndex);
// Next increment the index so it points to the next item, if there is one
++WriteIndex;
++PointsTaken;
// Finally return the pointer we found before incrementing
return (ThePtr);
}
//-------------------------------------------------------------------------------------
// Function: ReadPointer
// The read pointer works like the write pointer except that if there's nothing
// to read, the array isn't expanded - the function just returns NULL.
void* CExpandingArray::ReadPointer (void)
{
// Check that the read index is less than the write index; if not, we're trying
// to read before writing, so return NULL
if (ReadIndex >= WriteIndex)
return (NULL);
// If the read index is OK, get a copy of the pointer and return it
void* ThePtr = operator[] (ReadIndex);
++ReadIndex;
return (ThePtr);
}
//-------------------------------------------------------------------------------------
// Function: Flush
// To flushing of an expanding buffer requires that we set the read and write
// indices to 0 so that new data can be written and read and call the CBasicArray
// Flush() method to delete the buffers full of data and allocate a new one.
void CExpandingArray::Flush (void)
{
WriteIndex = 0;
ReadIndex = 0;
PointsTaken = 0;
CBasicArray::Flush ();
}
//-------------------------------------------------------------------------------------
// Function: Rewind
// This function resets the read pointer to the beginning of the data, thereby
// allowing the array to be read again from its 'full' state.
void CExpandingArray::Rewind (void)
{
ReadIndex = 0;
}
//=====================================================================================
// Class: CCircularArray
// When you need a buffer of fixed size which will keep a record of the most
// recent events, you need a ring buffer. This class implements a ring buffer as
// a descendent of the fixed-size basic array with pointers that wrap around and
// around and write over old data, always keeping the most recent data available.
//=====================================================================================
//-------------------------------------------------------------------------------------
// Constructor: CCircularArray
// This constructor starts up the array with a buffer allocated and the read
// and write pointers set to the 0-th element...well actually the constructor
// for CBasicArray does all that.
CCircularArray::CCircularArray (unsigned aDataSize, unsigned aArraySize)
: CBasicArray (aDataSize, aArraySize)
{
WriteIndex = 0; // Set the read and write indices to 0 'cause
ReadIndex = 0; // there isn't any data yet
PointsTaken = 0; // Same for the points-taken counter
MaxPointsTaken = 0; // Ditto again for maximum points counter
}
//-------------------------------------------------------------------------------------
// Destructor: ~CCircularArray
// This destructor, as usual, frees up the memory used by the array.
CCircularArray::~CCircularArray (void)
{
}
//-------------------------------------------------------------------------------------
// Function: WritePointer
// Whenever there's data to be written, call this function to get a pointer to a
// place to put it. It will give you a pointer and increment the write index to
// the next location, whether there's data there or not.
void* CCircularArray::WritePointer (void)
{
// Get the pointer which we're going to return to the calling function
void* ThePtr = operator[] (WriteIndex);
// If the buffer's full and we're writing over old data, push the read index
// along in front of the write index so that it still points to the oldest data
if (PointsTaken >= TotalSize)
{
if (++ReadIndex >= TotalSize)
ReadIndex = 0;
}
// Now move the write index. Note that with a full buffer which isn't being read
// the read and write indices end up moving together
if (++WriteIndex >= TotalSize)
WriteIndex = 0;
// If we haven't filled the array, increment the numbers of data points taken
if (PointsTaken < TotalSize)
PointsTaken++;
if (MaxPointsTaken < TotalSize)
MaxPointsTaken++;
return (ThePtr);
}
//-------------------------------------------------------------------------------------
// Function: ReadPointer
// The read pointer always "follows" the write pointer around the ring; it must
// never overtake the write pointer or you might read unwritten data.
void* CCircularArray::ReadPointer (void)
{
// Check if there's data available (that is, more data has been written than
// read) by looking at PointsTaken. If there's no new data, return NULL
if (PointsTaken == 0)
return (NULL);
// If we get here, there is new data, so get a pointer to it
void* ThePtr = operator[] (ReadIndex);
// Now advance the read index and decrement the points-taken counter. Next time
// we want to read data, we'll check if this counter is 0 again
if (++ReadIndex >= TotalSize)
ReadIndex = 0;
PointsTaken--;
return (ThePtr);
}
//-------------------------------------------------------------------------------------
// Function: Flush
// In order to flush a circular array, just set the indices to 0 so you can over-
// write the old data.
void CCircularArray::Flush (void)
{
WriteIndex = 0;
ReadIndex = 0;
PointsTaken = 0;
}
//-------------------------------------------------------------------------------------
// Function: Rewind
// This function resets the read pointer to the beginning of the data, thereby
// allowing the array to be read again from its 'full' state. For a circular
// array, the beginning of the data is the oldest data. If the buffer's not yet
// full, the oldest data is at location 0; else it's pointed to by the write
// index, because the write index points to where the next new data will go.
void CCircularArray::Rewind (void)
{
if (MaxPointsTaken < TotalSize)
ReadIndex = 0;
else
ReadIndex = WriteIndex;
PointsTaken = MaxPointsTaken;
}
//=====================================================================================
// Class: CLogArray
// This class implements a somewhat automatic array which stores data to be
// logged in a file. The log array keeps a pointer to one of the CBasicArray
// descendents, using the one appropriate for the user's choice of array type:
// linear, expanding, or circular.
//=====================================================================================
//-------------------------------------------------------------------------------------
// Constructor: CLogArray
// This constructor sets up a logging array of the given type with a starting
// buffer of the given size.
CLogArray::CLogArray (LogDataType aDaType, LogArrayType aArType, unsigned aBufferSize)
{
int DataSize; // How many bytes per data item?
ErrorString = new CString (128); // String to hold error messages
HeaderLine = new CString (64); // String holds column's header
DataType = aDaType; // Save the data type information
ArrayType = aArType; // Save array type info. also
// Depending on the type of data the user wants to store, set the size of each
// data item in bytes
switch (aDaType)
{
case LOG_INT:
DataSize = sizeof (int);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -