mirror of
https://github.com/ksherlock/TwoTerm.git
synced 2025-02-13 17:30:31 +00:00
ring buffer to debug stuff.
git-svn-id: svn://qnap.local/TwoTerm/trunk@3148 5590a31f-7b70-45f8-8c82-aa3a8e5f4507
This commit is contained in:
parent
b218387855
commit
695fb8ce36
@ -16,6 +16,8 @@
|
||||
|
||||
#include "Screen.h"
|
||||
|
||||
#include "ring_buffer.h"
|
||||
|
||||
@class EmulatorView;
|
||||
|
||||
class ViewScreen: public Screen
|
||||
@ -73,6 +75,7 @@ private:
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
||||
ring_buffer<256> _debug_buffer;
|
||||
ViewScreen _screen;
|
||||
|
||||
#endif
|
||||
@ -99,6 +102,8 @@ private:
|
||||
|
||||
-(IBAction)paste: (id)sender;
|
||||
-(IBAction)copy: (id)sender;
|
||||
-(IBAction)copyDebugData:(id)sender;
|
||||
-(IBAction)clearDebugData:(id)sender;
|
||||
|
||||
|
||||
-(void)processData: (const uint8_t *)data size: (size_t)size;
|
||||
@ -115,4 +120,4 @@ private:
|
||||
-(void)startCursorTimer;
|
||||
|
||||
|
||||
@end
|
||||
@end
|
||||
|
@ -280,6 +280,10 @@
|
||||
return YES;
|
||||
}
|
||||
|
||||
-(BOOL)resignFirstResponder {
|
||||
return [super resignFirstResponder];
|
||||
}
|
||||
|
||||
-(void)drawRect:(NSRect)dirtyRect
|
||||
{
|
||||
//NSLog(@"drawRect:");
|
||||
@ -534,6 +538,56 @@
|
||||
|
||||
}
|
||||
|
||||
-(IBAction)clearDebugData:(id)sender:(id)sender {
|
||||
_debug_buffer.clear();
|
||||
}
|
||||
|
||||
|
||||
-(IBAction)copyDebugData:(id)sender {
|
||||
|
||||
/* copy _debug_data to clipboard */
|
||||
|
||||
std::vector<uint8_t> bytes = _debug_buffer.read();
|
||||
|
||||
std::string ascii;
|
||||
std::string hex;
|
||||
ascii.reserve(bytes.size());
|
||||
hex.reserve(bytes.size()*3);
|
||||
|
||||
std::transform(bytes.begin(), bytes.end(), std::back_inserter(ascii), [](uint8_t c){
|
||||
if (isascii(c) && isprint(c)) return (char)c;
|
||||
return (char)'.';
|
||||
});
|
||||
|
||||
for (uint8_t c : bytes) {
|
||||
constexpr const static char hh[] = "0123456789abcdef";
|
||||
hex.push_back(hh[c >> 4]);
|
||||
hex.push_back(hh[c & 0x0f]);
|
||||
hex.push_back(' ');
|
||||
}
|
||||
|
||||
|
||||
std::string rv;
|
||||
int offset = 0;
|
||||
while (offset < bytes.size()) {
|
||||
int max = bytes.size() - offset;
|
||||
if (max > 16) max = 16;
|
||||
|
||||
rv.append(hex.data() + offset * 3, max * 3);
|
||||
if (max < 16) rv.append((16 - max) * 3, ' ');
|
||||
rv.push_back(' ');
|
||||
rv.append(ascii.data() + offset, max);
|
||||
rv.push_back('\n');
|
||||
|
||||
offset += max;
|
||||
}
|
||||
|
||||
NSPasteboard *pb;
|
||||
pb = [NSPasteboard generalPasteboard];
|
||||
[pb clearContents];
|
||||
[pb setData: [NSData dataWithBytes: rv.data() length: rv.length()] forType: NSStringPboardType];
|
||||
}
|
||||
|
||||
-(void)processData:(const uint8_t *)buffer size:(size_t)size {
|
||||
|
||||
typedef void (*ProcessCharFX)(id, SEL, uint8_t, Screen *, OutputChannel *);
|
||||
@ -550,6 +604,7 @@
|
||||
#endif
|
||||
|
||||
|
||||
_debug_buffer.write(buffer, size);
|
||||
|
||||
if ([_emulator respondsToSelector: @selector(processData:length:screen:output:)]) {
|
||||
|
||||
@ -734,6 +789,8 @@
|
||||
return _fd >= 1;
|
||||
}
|
||||
if (cmd == @selector(copy:)) return NO;
|
||||
if (cmd == @selector(copyDebugData:)) return YES;
|
||||
if (cmd == @selector(clearDebugData:)) return YES;
|
||||
|
||||
return NO;
|
||||
//return [super validateUserInterfaceItem: anItem];
|
||||
|
116
cpp/ring_buffer.h
Normal file
116
cpp/ring_buffer.h
Normal file
@ -0,0 +1,116 @@
|
||||
//
|
||||
// ring_buffer.h
|
||||
// 2Term
|
||||
//
|
||||
// Created by Kelvin Sherlock on 1/25/2017.
|
||||
//
|
||||
//
|
||||
|
||||
#ifndef ring_buffer_h
|
||||
#define ring_buffer_h
|
||||
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
|
||||
|
||||
template<size_t Size>
|
||||
class ring_buffer {
|
||||
|
||||
static_assert((Size & ~(Size - 1)) == Size, "Size must be power of 2");
|
||||
|
||||
public:
|
||||
|
||||
|
||||
void write(uint8_t x) {
|
||||
_buffer[_ptr] = x;
|
||||
_ptr = (_ptr + 1) & ~(Size-1);
|
||||
if (_capacity) --_capacity;
|
||||
}
|
||||
|
||||
void write(const uint8_t *data, size_t dsize) {
|
||||
if (!dsize) return;
|
||||
|
||||
// simple replace.
|
||||
if (dsize >= Size) {
|
||||
_ptr = _capacity = 0;
|
||||
memcpy(_buffer, data + dsize - Size, Size);
|
||||
|
||||
assert(_redzone == 0);
|
||||
return;
|
||||
}
|
||||
|
||||
// simple append.
|
||||
if (_capacity >= dsize) {
|
||||
memcpy(_buffer + _ptr, data, _capacity);
|
||||
_ptr += dsize;
|
||||
_capacity -= dsize;
|
||||
|
||||
assert(_redzone == 0);
|
||||
|
||||
return;
|
||||
}
|
||||
// no capacity left.. overwrite.
|
||||
// dsize < Size.
|
||||
|
||||
_capacity = 0;
|
||||
int amt = Size - _ptr;
|
||||
|
||||
if (amt > dsize) {
|
||||
memcpy(_buffer + _ptr, data, dsize);
|
||||
_ptr += dsize;
|
||||
|
||||
assert(_redzone == 0);
|
||||
return;
|
||||
}
|
||||
|
||||
//amt = dsize;
|
||||
memcpy(_buffer + _ptr, data, amt);
|
||||
data += amt;
|
||||
dsize -= amt;
|
||||
memcpy(_buffer, data, dsize);
|
||||
_ptr = dsize;
|
||||
_capacity = 0;
|
||||
|
||||
assert(_redzone == 0);
|
||||
}
|
||||
|
||||
|
||||
std::vector<uint8_t> read() const {
|
||||
std::vector<uint8_t> rv;
|
||||
if (_capacity) {
|
||||
rv.assign(_buffer, _buffer + _ptr);
|
||||
return rv;
|
||||
}
|
||||
// _ptr ... end, 0 .. _ptr
|
||||
rv.assign(_buffer + _ptr, _buffer + Size);
|
||||
if (_ptr) rv.insert(rv.end(), _buffer, _buffer + _ptr);
|
||||
return rv;
|
||||
}
|
||||
|
||||
size_t size() const {
|
||||
return Size - _capacity;
|
||||
}
|
||||
|
||||
bool empty() const {
|
||||
return _capacity == Size;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
_ptr = 0;
|
||||
_capacity = Size;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
size_t _capacity = Size;
|
||||
size_t _ptr = 0;
|
||||
uint8_t _buffer[Size];
|
||||
uint64_t _redzone = 0;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* ring_buffer_h */
|
Loading…
x
Reference in New Issue
Block a user