326 lines
7.0 KiB
C++
326 lines
7.0 KiB
C++
#ifndef N_LINEBUFFER_H
|
|
#define N_LINEBUFFER_H
|
|
//------------------------------------------------------------------------------
|
|
/**
|
|
@brief A ring buffer for strings.
|
|
|
|
@author
|
|
- RadonLabs GmbH
|
|
|
|
@since
|
|
- 2005.6.30
|
|
@remarks
|
|
- Áö¿Ï Ãß°¡
|
|
*/
|
|
|
|
#include "../ProgramCommon/Define.h"
|
|
|
|
//------------------------------------------------------------------------------
|
|
class nLineBuffer
|
|
{
|
|
public:
|
|
/// constructor
|
|
nLineBuffer();
|
|
/// destructor
|
|
~nLineBuffer();
|
|
/// write string to line buffer
|
|
void Put(const char*);
|
|
/// return pointer to line defined by line number
|
|
const char *GetLine(int) const;
|
|
/// get line number of first line
|
|
int GetHeadLine() const;
|
|
/// get line number of last line
|
|
int GetTailLine() const;
|
|
/// get line number of previous line
|
|
int GetNextLine(int) const;
|
|
/// get line number of next line
|
|
int GetPrevLine(int) const;
|
|
/// fill a user provided array with pointers to lines
|
|
int GetLines(const char** array, int arraySize) const;
|
|
|
|
private:
|
|
/// get next line number
|
|
int nextLine(int) const;
|
|
/// get previus line number
|
|
int prevLine(int) const;
|
|
|
|
/// private class to keep track of lines in buffer
|
|
class nLine
|
|
{
|
|
friend class nLineBuffer;
|
|
|
|
/// constructor
|
|
nLine();
|
|
/// set line pointer to external storage space
|
|
void Set(char* p, int len);
|
|
/// reset line pointer
|
|
void Reset();
|
|
/// append string to line
|
|
const char* Append(const char* s);
|
|
|
|
int line_len;
|
|
int act_pos;
|
|
char *line;
|
|
};
|
|
|
|
enum
|
|
{
|
|
N_LINE_LEN = 80,
|
|
N_NUM_LINES = 256,
|
|
};
|
|
char *c_buf;
|
|
nLine line_array[N_NUM_LINES];
|
|
int tail_line;
|
|
int head_line;
|
|
|
|
};
|
|
|
|
//------------------------------------------------------------------------------
|
|
/**
|
|
*/
|
|
inline
|
|
nLineBuffer::nLine::nLine() :
|
|
line(0),
|
|
line_len(0),
|
|
act_pos(0)
|
|
{
|
|
// empty
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
/**
|
|
*/
|
|
inline
|
|
void
|
|
nLineBuffer::nLine::Set(char* p, int len)
|
|
{
|
|
ASSERT(p);
|
|
this->line = p;
|
|
this->line[0] = 0;
|
|
this->line_len = len;
|
|
this->act_pos = 0;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
/**
|
|
*/
|
|
inline
|
|
void
|
|
nLineBuffer::nLine::Reset()
|
|
{
|
|
ASSERT(this->line);
|
|
this->line[0] = 0;
|
|
this->act_pos = 0;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
/**
|
|
Appends string until line full, new line or end of string is reached.
|
|
|
|
If new line, a pointer to the next char is returned, otherwise NULL.
|
|
A '\r' in the string rewinds the cursor to the start of the line. If
|
|
the string buffer is full, a 0 is appended in any case. Newlines are
|
|
not copied.
|
|
*/
|
|
inline
|
|
const char*
|
|
nLineBuffer::nLine::Append(const char *s)
|
|
{
|
|
ASSERT(s);
|
|
|
|
char c;
|
|
bool running = true;
|
|
do
|
|
{
|
|
// Zeile voll?
|
|
c = *s++;
|
|
if (act_pos >= (line_len-1))
|
|
{
|
|
line[line_len - 1] = 0;
|
|
running = false;
|
|
s--;
|
|
}
|
|
else
|
|
{
|
|
if (c == '\n')
|
|
{
|
|
line[act_pos] = 0;
|
|
running = false;
|
|
}
|
|
else if (c == '\r')
|
|
{
|
|
act_pos = 0;
|
|
line[act_pos] = 0;
|
|
}
|
|
else if (c == 0)
|
|
{
|
|
line[act_pos] = 0;
|
|
s = NULL;
|
|
running = false;
|
|
}
|
|
else
|
|
{
|
|
line[act_pos++] = c;
|
|
}
|
|
}
|
|
} while (running);
|
|
return s;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
/**
|
|
*/
|
|
inline
|
|
nLineBuffer::nLineBuffer()
|
|
{
|
|
int i;
|
|
this->c_buf = (char *) n_calloc(N_LINE_LEN, N_NUM_LINES);
|
|
ASSERT(this->c_buf);
|
|
for (i = 0; i < N_NUM_LINES; i++)
|
|
{
|
|
this->line_array[i].Set((this->c_buf + i*N_LINE_LEN), N_LINE_LEN);
|
|
}
|
|
this->tail_line = 0;
|
|
this->head_line = 0;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
/**
|
|
*/
|
|
inline
|
|
nLineBuffer::~nLineBuffer()
|
|
{
|
|
if (this->c_buf)
|
|
{
|
|
free(this->c_buf);
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
/**
|
|
*/
|
|
inline
|
|
int nLineBuffer::nextLine(int l) const
|
|
{
|
|
l++;
|
|
if (l >= N_NUM_LINES) l = 0;
|
|
return l;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
/**
|
|
*/
|
|
inline
|
|
int nLineBuffer::prevLine(int l) const
|
|
{
|
|
l--;
|
|
if (l < 0) l = N_NUM_LINES - 1;
|
|
return l;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
/**
|
|
*/
|
|
inline
|
|
void
|
|
nLineBuffer::Put(const char *s)
|
|
{
|
|
const char *cont = s;
|
|
while (cont && (*cont) && (cont = this->line_array[this->head_line].Append(cont)))
|
|
{
|
|
// Line ends with a newline (\n) so switch to next line
|
|
this->head_line = this->nextLine(this->head_line);
|
|
if (this->head_line == this->tail_line)
|
|
{
|
|
this->tail_line = this->nextLine(this->tail_line);
|
|
}
|
|
this->line_array[this->head_line].Reset();
|
|
}
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
/**
|
|
*/
|
|
inline
|
|
const char*
|
|
nLineBuffer::GetLine(int l) const
|
|
{
|
|
ASSERT(l >= 0);
|
|
ASSERT(l < N_NUM_LINES);
|
|
return this->line_array[l].line;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
/**
|
|
*/
|
|
inline
|
|
int
|
|
nLineBuffer::GetHeadLine() const
|
|
{
|
|
return this->head_line;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
/**
|
|
*/
|
|
inline
|
|
int
|
|
nLineBuffer::GetTailLine() const
|
|
{
|
|
return this->tail_line;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
/**
|
|
*/
|
|
inline
|
|
int
|
|
nLineBuffer::GetNextLine(int l) const
|
|
{
|
|
if (l == this->head_line) return -1;
|
|
return nextLine(l);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
/**
|
|
*/
|
|
inline
|
|
int
|
|
nLineBuffer::GetPrevLine(int l) const
|
|
{
|
|
if (l == this->tail_line) return -1;
|
|
return prevLine(l);
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
/**
|
|
Fills the user provided char pointer array with pointers to the N
|
|
latest lines in the line buffer. Return number of valid lines.
|
|
|
|
@param array an char pointer array to fill with pointers
|
|
@param arraySize the size of the char pointer array
|
|
@return number of valid lines
|
|
*/
|
|
inline
|
|
int
|
|
nLineBuffer::GetLines(const char** array, int arraySize) const
|
|
{
|
|
int i;
|
|
int numLines = 0;
|
|
for (i = this->GetHeadLine();
|
|
(i != -1) && (numLines < arraySize);
|
|
i = this->GetPrevLine(i))
|
|
{
|
|
const char *l = this->GetLine(i);
|
|
if (l)
|
|
{
|
|
if (*l) array[numLines++] = l;
|
|
}
|
|
else break;
|
|
}
|
|
return numLines;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
#endif
|