diff options
Diffstat (limited to 'src/emu/debug/textbuf.cpp')
-rw-r--r-- | src/emu/debug/textbuf.cpp | 332 |
1 files changed, 182 insertions, 150 deletions
diff --git a/src/emu/debug/textbuf.cpp b/src/emu/debug/textbuf.cpp index 279ce8dead6..c70f8660185 100644 --- a/src/emu/debug/textbuf.cpp +++ b/src/emu/debug/textbuf.cpp @@ -2,15 +2,16 @@ // copyright-holders:Aaron Giles /*************************************************************************** - textbuf.c + textbuf.cpp Debugger text buffering engine. ***************************************************************************/ -#include "corealloc.h" #include "textbuf.h" +#include <new> + /*************************************************************************** @@ -27,47 +28,46 @@ struct text_buffer { - char * buffer; - s32 * lineoffs; - s32 bufsize; - s32 bufstart; - s32 bufend; - s32 linesize; - s32 linestart; - s32 lineend; - u32 linestartseq; - s32 maxwidth; -}; - - - -/*************************************************************************** - INLINE FUNCTIONS -***************************************************************************/ - -/*------------------------------------------------- - buffer_used - return the number of bytes - currently held in the buffer --------------------------------------------------*/ - -static inline s32 buffer_used(text_buffer *text) -{ - s32 used = text->bufend - text->bufstart; - if (used < 0) - used += text->bufsize; - return used; -} + text_buffer(u32 bytes, u32 lines) noexcept + : buffer(new (std::nothrow) char [bytes]) + , lineoffs(new (std::nothrow) s32 [lines]) + , bufsize(buffer ? bytes : 0) + , linesize(lineoffs ? lines : 0) + { + } + std::unique_ptr<char []> const buffer; + std::unique_ptr<s32 []> const lineoffs; + s32 const bufsize; + s32 bufstart = 0; + s32 bufend = 0; + s32 const linesize; + s32 linestart = 0; + s32 lineend = 0; + u32 linestartseq = 0; + s32 maxwidth = 0; + + /*------------------------------------------------- + buffer_used - return the number of bytes + currently held in the buffer + -------------------------------------------------*/ + + s32 buffer_used() const noexcept + { + s32 const used(bufend - bufstart); + return (used < 0) ? (used + bufsize) : used; + } -/*------------------------------------------------- - buffer_space - return the number of bytes - available in the buffer --------------------------------------------------*/ + /*------------------------------------------------- + buffer_space - return the number of bytes + available in the buffer + -------------------------------------------------*/ -static inline s32 buffer_space(text_buffer *text) -{ - return text->bufsize - buffer_used(text); -} + s32 buffer_space() const noexcept + { + return bufsize - buffer_used(); + } +}; @@ -81,36 +81,19 @@ static inline s32 buffer_space(text_buffer *text) text_buffer_alloc - allocate a new text buffer -------------------------------------------------*/ -text_buffer *text_buffer_alloc(u32 bytes, u32 lines) +text_buffer_ptr text_buffer_alloc(u32 bytes, u32 lines) { - text_buffer *text; + // allocate memory for the text buffer object + text_buffer_ptr text(new (std::nothrow) text_buffer(bytes, lines)); - /* allocate memory for the text buffer object */ - text = global_alloc_nothrow(text_buffer); if (!text) return nullptr; - /* allocate memory for the buffer itself */ - text->buffer = global_alloc_array_nothrow(char, bytes); - if (!text->buffer) - { - global_free(text); - return nullptr; - } - - /* allocate memory for the lines array */ - text->lineoffs = global_alloc_array_nothrow(s32, lines); - if (!text->lineoffs) - { - global_free_array(text->buffer); - global_free(text); + if (!text->buffer || !text->lineoffs) return nullptr; - } - /* initialize the buffer description */ - text->bufsize = bytes; - text->linesize = lines; - text_buffer_clear(text); + // initialize the buffer description + text_buffer_clear(*text); return text; } @@ -121,13 +104,9 @@ text_buffer *text_buffer_alloc(u32 bytes, u32 lines) text buffer -------------------------------------------------*/ -void text_buffer_free(text_buffer *text) +void text_buffer_deleter::operator()(text_buffer *text) const { - if (text->lineoffs) - global_free_array(text->lineoffs); - if (text->buffer) - global_free_array(text->buffer); - global_free(text); + delete text; } @@ -135,21 +114,21 @@ void text_buffer_free(text_buffer *text) text_buffer_clear - clear a text buffer -------------------------------------------------*/ -void text_buffer_clear(text_buffer *text) +void text_buffer_clear(text_buffer &text) { - /* reset all the buffer pointers and other bits */ - text->bufstart = 0; - text->bufend = 0; + // reset all the buffer pointers and other bits + text.bufstart = 0; + text.bufend = 0; - text->linestart = 0; - text->lineend = 0; - text->linestartseq = 0; + text.linestart = 0; + text.lineend = 0; + text.linestartseq = 0; - text->maxwidth = 0; + text.maxwidth = 0; - /* create the initial line */ - text->lineoffs[0] = 0; - text->buffer[text->lineoffs[0]] = 0; + // create the initial line + text.lineoffs[0] = 0; + text.buffer[text.lineoffs[0]] = 0; } @@ -160,109 +139,107 @@ void text_buffer_clear(text_buffer *text) ***************************************************************************/ -/*------------------------------------------------- - text_buffer_print - print data to the text - buffer --------------------------------------------------*/ +//------------------------------------------------- +// text_buffer_print - print data to the text +// buffer +//------------------------------------------------- -void text_buffer_print(text_buffer *text, const char *data) +void text_buffer_print(text_buffer &text, std::string_view data) { - text_buffer_print_wrap(text, data, 10000); + text_buffer_print_wrap(text, data, MAX_LINE_LENGTH); } -/*------------------------------------------------- - text_buffer_print_wrap - print data to the - text buffer with word wrapping to a given - column --------------------------------------------------*/ +//------------------------------------------------- +// text_buffer_print_wrap - print data to the +// text buffer with word wrapping to a given +// column +//------------------------------------------------- -void text_buffer_print_wrap(text_buffer *text, const char *data, int wrapcol) +void text_buffer_print_wrap(text_buffer &text, std::string_view data, int wrapcol) { - s32 stopcol = (wrapcol < MAX_LINE_LENGTH) ? wrapcol : MAX_LINE_LENGTH; - s32 needed_space; + s32 const stopcol = (wrapcol < MAX_LINE_LENGTH) ? wrapcol : MAX_LINE_LENGTH; - /* we need to ensure there is enough space for this string plus enough for the max line length */ - needed_space = s32(strlen(data)) + MAX_LINE_LENGTH; + // we need to ensure there is enough space for this string plus enough for the max line length + s32 const needed_space = s32(data.length()) + MAX_LINE_LENGTH; - /* make space in the buffer if we need to */ - while (buffer_space(text) < needed_space && text->linestart != text->lineend) + // make space in the buffer if we need to + while (text.buffer_space() < needed_space && text.linestart != text.lineend) { - text->linestartseq++; - if (++text->linestart >= text->linesize) - text->linestart = 0; - text->bufstart = text->lineoffs[text->linestart]; + text.linestartseq++; + if (++text.linestart >= text.linesize) + text.linestart = 0; + text.bufstart = text.lineoffs[text.linestart]; } - /* now add the data */ - for ( ; *data; data++) + // now add the data + for (int ch : data) { - int ch = *data; int linelen; - /* a CR resets our position */ + // a CR resets our position if (ch == '\r') - text->bufend = text->lineoffs[text->lineend]; + text.bufend = text.lineoffs[text.lineend]; - /* non-CR data is just characters */ + // non-CR data is just characters else if (ch != '\n') - text->buffer[text->bufend++] = ch; + text.buffer[text.bufend++] = ch; - /* an explicit newline or line-too-long condition inserts a newline */ - linelen = text->bufend - text->lineoffs[text->lineend]; + // an explicit newline or line-too-long condition inserts a newline */ + linelen = text.bufend - text.lineoffs[text.lineend]; if (ch == '\n' || linelen >= stopcol) { int overflow = 0; - /* if we're wrapping, back off until we hit a space */ + // if we're wrapping, back off until we hit a space if (linelen >= wrapcol) { - /* scan backwards, removing characters along the way */ + // scan backwards, removing characters along the way overflow = 1; - while (overflow < linelen && text->buffer[text->bufend - overflow] != ' ') + while (overflow < linelen && text.buffer[text.bufend - overflow] != ' ') overflow++; - /* if we found a space, take it; otherwise, reset and pretend we didn't try */ + // if we found a space, take it; otherwise, reset and pretend we didn't try if (overflow < linelen) linelen -= overflow; else overflow = 0; } - /* did we beat the max width */ - if (linelen > text->maxwidth) - text->maxwidth = linelen; + // did we beat the max width + if (linelen > text.maxwidth) + text.maxwidth = linelen; - /* append a terminator */ + // append a terminator if (overflow == 0) - text->buffer[text->bufend++] = 0; + text.buffer[text.bufend++] = 0; else - text->buffer[text->bufend - overflow] = 0; + text.buffer[text.bufend - overflow] = 0; - /* determine what the next line will be */ - if (++text->lineend >= text->linesize) - text->lineend = 0; + // determine what the next line will be + if (++text.lineend >= text.linesize) + text.lineend = 0; - /* if we're out of lines, consume the next one */ - if (text->lineend == text->linestart) + // if we're out of lines, consume the next one + if (text.lineend == text.linestart) { - text->linestartseq++; - if (++text->linestart >= text->linesize) - text->linestart = 0; - text->bufstart = text->lineoffs[text->linestart]; + text.linestartseq++; + if (++text.linestart >= text.linesize) + text.linestart = 0; + text.bufstart = text.lineoffs[text.linestart]; } - /* if we don't have enough room in the buffer for a max line, wrap to the start */ - if (text->bufend + MAX_LINE_LENGTH + 1 >= text->bufsize) - text->bufend = 0; + // if we don't have enough room in the buffer for a max line, wrap to the start + if (text.bufend + MAX_LINE_LENGTH + 1 >= text.bufsize) + text.bufend = 0; - /* create a new empty line */ - text->lineoffs[text->lineend] = text->bufend - (overflow ? (overflow - 1) : 0); + // create a new empty line + text.lineoffs[text.lineend] = text.bufend - (overflow ? (overflow - 1) : 0); } } - /* nullptr terminate what we have on this line */ - text->buffer[text->bufend] = 0; + // null terminate what we have on this line + text.buffer[text.bufend] = 0; } @@ -278,9 +255,9 @@ void text_buffer_print_wrap(text_buffer *text, const char *data, int wrapcol) width of all lines seen so far -------------------------------------------------*/ -u32 text_buffer_max_width(text_buffer *text) +u32 text_buffer_max_width(text_buffer const &text) { - return text->maxwidth; + return text.maxwidth; } @@ -289,12 +266,10 @@ u32 text_buffer_max_width(text_buffer *text) lines in the text buffer -------------------------------------------------*/ -u32 text_buffer_num_lines(text_buffer *text) +u32 text_buffer_num_lines(text_buffer const &text) { - s32 lines = text->lineend + 1 - text->linestart; - if (lines <= 0) - lines += text->linesize; - return lines; + s32 const lines = text.lineend + 1 - text.linestart; + return (lines <= 0) ? (lines + text.linesize) : lines; } @@ -303,9 +278,9 @@ u32 text_buffer_num_lines(text_buffer *text) line index into a sequence number -------------------------------------------------*/ -u32 text_buffer_line_index_to_seqnum(text_buffer *text, u32 index) +u32 text_buffer_line_index_to_seqnum(text_buffer const &text, u32 index) { - return text->linestartseq + index; + return text.linestartseq + index; } @@ -314,11 +289,68 @@ u32 text_buffer_line_index_to_seqnum(text_buffer *text, u32 index) an indexed line in the buffer -------------------------------------------------*/ -const char *text_buffer_get_seqnum_line(text_buffer *text, u32 seqnum) +const char *text_buffer_get_seqnum_line(text_buffer const &text, u32 seqnum) { - u32 numlines = text_buffer_num_lines(text); - u32 index = seqnum - text->linestartseq; + u32 const numlines = text_buffer_num_lines(text); + u32 const index = seqnum - text.linestartseq; if (index >= numlines) return nullptr; - return &text->buffer[text->lineoffs[(text->linestart + index) % text->linesize]]; + return &text.buffer[text.lineoffs[(text.linestart + index) % text.linesize]]; +} + +/*--------------------------------------------------------------------- + text_buffer_lines::text_buffer_line_iterator::operator* + Gets the line that the iterator currently points to. +-----------------------------------------------------------------------*/ + +std::string_view text_buffer_lines::text_buffer_line_iterator::operator*() const +{ + char const *const line = &m_buffer.buffer[m_buffer.lineoffs[m_lineptr]]; + + auto next_lineptr = m_lineptr + 1; + if (next_lineptr == m_buffer.linesize) + next_lineptr = 0; + + char const *const nextline = &m_buffer.buffer[m_buffer.lineoffs[next_lineptr]]; + + // -1 for the '\0' at the end of line + ptrdiff_t difference = (nextline - line) - 1; + + if (difference < 0) + difference += m_buffer.bufsize; + + return std::string_view{ line, std::string_view::size_type(difference) }; +} + +/*--------------------------------------------------------------------- + text_buffer_lines::text_buffer_line_iterator::operator++ + Moves to the next line. +-----------------------------------------------------------------------*/ + +text_buffer_lines::text_buffer_line_iterator &text_buffer_lines::text_buffer_line_iterator::operator++() +{ + if (++m_lineptr == m_buffer.linesize) + m_lineptr = 0; + + return *this; +} + +/*------------------------------------------------------ + text_buffer_lines::begin() + Returns an iterator that points to the first line. +--------------------------------------------------------*/ + +text_buffer_lines::iterator text_buffer_lines::begin() const +{ + return text_buffer_line_iterator(m_buffer, m_buffer.linestart); +} + +/*----------------------------------------------------------- + text_buffer_lines::begin() + Returns an iterator that points just past the last line. +-------------------------------------------------------------*/ + +text_buffer_lines::iterator text_buffer_lines::end() const +{ + return text_buffer_line_iterator(m_buffer, m_buffer.lineend); } |