//----------------------------------------------------------------------------- // 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 #include #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 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__*/