You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

108 lines
3.4 KiB

//-----------------------------------------------------------------------------
// 2022 Ahoy, https://www.mikrocontroller.net/topic/525778
// Creative Commons - http://creativecommons.org/licenses/by-nc-sa/3.0/de/
//-----------------------------------------------------------------------------
#ifndef __TMPL_PROC__
#define __TMPL_PROC__
// HTML template processor, searches keywords and calls callback
// inspired by: https://github.com/plapointe6/EspHtmlTemplateProcessor
#include "dbg.h"
#include <string.h>
#include <functional>
#include "ESPAsyncWebServer.h"
#define MAX_BUFFER_SIZE 256
#define MAX_KEY_LEN 20
enum { ST_NONE = 0, ST_BUF, ST_PROC, ST_START, ST_KEY };
typedef std::function<String(char* key)> TmplCb;
class tmplProc {
public:
tmplProc(AsyncWebServerRequest *request, uint32_t bufStartSize = 1000) {
// Note: don't choose the bufStartSize to small. A too small start
// size will result in fractioned memory and maybe in a zero
// increase -> fail (Arduino - cbuf.cpp)
mRequest = request;
mResponse = request->beginResponseStream("text/html", bufStartSize);
}
~tmplProc() {}
void process(const char* tmpl, const uint32_t tmplLen, TmplCb cb) {
char* buf = new char[MAX_BUFFER_SIZE];
char* p = buf;
uint32_t len = 0, pos = 0, i = 0;
uint8_t state = ST_BUF;
bool complete = false;
while (i < tmplLen) {
switch (state) {
default:
DPRINTLN(DBG_DEBUG, F("unknown state"));
break;
case ST_BUF:
if(0 != i) {
buf[pos] = '\0';
mResponse->print(p);
}
pos = 0;
len = ((tmplLen - i) > MAX_BUFFER_SIZE) ? MAX_BUFFER_SIZE : (tmplLen - i);
if((len + i) == tmplLen)
complete = true;
memcpy_P(buf, &tmpl[i], len);
if(len < MAX_BUFFER_SIZE)
buf[len] = '\0';
p = buf;
state = ST_PROC;
break;
case ST_PROC:
if(((pos + MAX_KEY_LEN) >= len) && !complete)
state = ST_BUF;
else if(buf[pos] == '{')
state = ST_START;
break;
case ST_START:
if(buf[pos] == '#') {
if(pos != 0)
buf[pos-1] = '\0';
mResponse->print(p);
p = &buf[pos+1];
state = ST_KEY;
}
else
state = ST_PROC;
break;
case ST_KEY:
if(buf[pos] == '}') {
buf[pos] = '\0';
mResponse->print((cb)(p));
p = &buf[pos+1];
state = ST_PROC;
}
break;
}
if(ST_BUF != state) {
pos++;
i++;
}
}
mResponse->print(p);
delete[] buf;
mRequest->send(mResponse);
}
private:
AsyncWebServerRequest *mRequest;
AsyncResponseStream *mResponse;
};
#endif /*__TMPL_PROC__*/