Skip to content

Commit

Permalink
Propose TemplatePrinter (hoeken#56)
Browse files Browse the repository at this point in the history
* Added TemplatePrinter from @Chris--A  (properly this time)
  • Loading branch information
Chris--A authored and Michael Haberler committed Aug 7, 2024
1 parent 0348ac3 commit 3aa82f8
Show file tree
Hide file tree
Showing 2 changed files with 141 additions and 0 deletions.
90 changes: 90 additions & 0 deletions src/TemplatePrinter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/************************************************************
TemplatePrinter Class
A basic templating engine for a stream of text.
This wraps the Arduino Print interface and writes to any
Print interface.
Written by Christopher Andrews (https://github.com/Chris--A)
************************************************************/

#include "TemplatePrinter.h"

void TemplatePrinter::resetParam(bool flush){
if(flush && _inParam){
_stream.write(_delimiter);

if(_paramPos)
_stream.print(_paramBuffer);
}

memset(_paramBuffer, 0, sizeof(_paramBuffer));
_paramPos = 0;
_inParam = false;
}


void TemplatePrinter::flush(){
resetParam(true);
_stream.flush();
}

size_t TemplatePrinter::write(uint8_t data){

if(data == _delimiter){

// End of parameter, send to callback
if(_inParam){

// On false, return the parameter place holder as is: not a parameter
// Bug fix: ignore parameters that are zero length.
if(!_paramPos || !_cb(_stream, _paramBuffer)){
resetParam(true);
_stream.write(data);
}else{
resetParam(false);
}

// Start collecting parameter
}else{
_inParam = true;
}
}else{

// Are we collecting
if(_inParam){

// Is param still valid
if(isalnum(data) || data == '_'){

// Total param len must be 63, 1 for null.
if(_paramPos < sizeof(_paramBuffer) - 1){
_paramBuffer[_paramPos++] = data;

// Not a valid param
}else{
resetParam(true);
}
}else{
resetParam(true);
_stream.write(data);
}

// Just output
}else{
_stream.write(data);
}
}
return 1;
}

size_t TemplatePrinter::copyFrom(Stream &stream){
size_t count = 0;

while(stream.available())
count += this->write(stream.read());

return count;
}
51 changes: 51 additions & 0 deletions src/TemplatePrinter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#ifndef TemplatePrinter_h
#define TemplatePrinter_h

#include "PsychicCore.h"
#include <Print.h>

/************************************************************
TemplatePrinter Class
A basic templating engine for a stream of text.
This wraps the Arduino Print interface and writes to any
Print interface.
Written by Christopher Andrews (https://github.com/Chris--A)
************************************************************/

class TemplatePrinter;

typedef std::function<bool(Print &output, const char *parameter)> TemplateCallback;
typedef std::function<void(TemplatePrinter &printer)> TemplateSourceCallback;

class TemplatePrinter : public Print{
private:
bool _inParam;
char _paramBuffer[64];
uint8_t _paramPos;
Print &_stream;
TemplateCallback _cb;
char _delimiter;

void resetParam(bool flush);

public:
using Print::write;

static void start(Print &stream, TemplateCallback cb, TemplateSourceCallback entry){
TemplatePrinter printer(stream, cb);
entry(printer);
}

TemplatePrinter(Print &stream, TemplateCallback cb, const char delimeter = '%') : _stream(stream), _cb(cb), _delimiter(delimeter) { resetParam(false); }
~TemplatePrinter(){ flush(); }

void flush() override;
size_t write(uint8_t data) override;
size_t copyFrom(Stream &stream);
};

#endif

0 comments on commit 3aa82f8

Please sign in to comment.