Files
DFTE/include/DeviceFrameworkPlaceholderRegistry.h
T
alex 2a1ef2de63 Add DYNAMIC_DATA placeholder for raw streamed template content
Support registering dynamic String/progmem data without re-parsing as
nested templates, used by WiFiManager for composed portal stylesheets.
2026-05-04 22:03:42 +10:00

149 lines
6.0 KiB
C++

#ifndef DEVICEFRAMEWORK_PLACEHOLDER_REGISTRY_H
#define DEVICEFRAMEWORK_PLACEHOLDER_REGISTRY_H
#include <Arduino.h>
#include <stdio.h>
#include "DeviceFrameworkTemplateTypes.h"
// Fallback defaults when DeviceFrameworkConfig is not available (standalone usage)
// Always use internal macro names (DFTE_*) to avoid conflicts with DeviceFrameworkConfig extern declarations
// When DeviceFrameworkConfig is included, extern variables are declared with CONFIG_* names
// We use DFTE_* internal names for compile-time constants (constexpr) and default parameter values
// NEVER define CONFIG_* macros here to avoid conflicts with extern declarations in DeviceFrameworkConfig
#ifndef DFTE_PLACEHOLDER_NAME_SIZE_DEFAULT
#define DFTE_PLACEHOLDER_NAME_SIZE_DEFAULT 24
#endif
#ifndef DFTE_MAX_PLACEHOLDERS_DEFAULT
#define DFTE_MAX_PLACEHOLDERS_DEFAULT 16
#endif
#ifndef DFTE_PROGMEM_CHUNK_SIZE_DEFAULT
#define DFTE_PROGMEM_CHUNK_SIZE_DEFAULT 512
#endif
#ifndef DFTE_RAM_CHUNK_SIZE_DEFAULT
#define DFTE_RAM_CHUNK_SIZE_DEFAULT 128
#endif
// Use DeviceFramework config defaults at compile-time if available, otherwise use internal defaults
#ifdef DEVICEFRAMEWORK_CONFIG_H
// DeviceFramework is present - use config defaults
// DeviceFrameworkConfig.h must be included before this file to access CONFIG_*_default macros
#ifdef CONFIG_templateProgmemChunkSize_default
#define DFTE_PROGMEM_CHUNK_SIZE CONFIG_templateProgmemChunkSize_default
#else
#define DFTE_PROGMEM_CHUNK_SIZE DFTE_PROGMEM_CHUNK_SIZE_DEFAULT
#endif
#ifdef CONFIG_templateRamChunkSize_default
#define DFTE_RAM_CHUNK_SIZE CONFIG_templateRamChunkSize_default
#else
#define DFTE_RAM_CHUNK_SIZE DFTE_RAM_CHUNK_SIZE_DEFAULT
#endif
#else
// Standalone usage - use internal defaults
#define DFTE_PROGMEM_CHUNK_SIZE DFTE_PROGMEM_CHUNK_SIZE_DEFAULT
#define DFTE_RAM_CHUNK_SIZE DFTE_RAM_CHUNK_SIZE_DEFAULT
#endif
/**
* DeviceFramework Placeholder Registry
* Manages runtime registration of template placeholders
* Registry starts empty - users must register their placeholders
*/
class DeviceFrameworkPlaceholderRegistry {
public:
/**
* Constructor with optional max placeholders parameter
* @param maxPlaceholders Maximum number of placeholders (defaults to DFTE_MAX_PLACEHOLDERS_DEFAULT)
* Allows creating multiple registries with different sizes
* When using with DeviceFramework, pass getConfigMaxTemplatePlaceholders() for runtime config
*/
explicit DeviceFrameworkPlaceholderRegistry(uint16_t maxPlaceholders = DFTE_MAX_PLACEHOLDERS_DEFAULT);
~DeviceFrameworkPlaceholderRegistry();
// Prevent copying
DeviceFrameworkPlaceholderRegistry(const DeviceFrameworkPlaceholderRegistry&) = delete;
DeviceFrameworkPlaceholderRegistry& operator=(const DeviceFrameworkPlaceholderRegistry&) = delete;
/**
* Register a PROGMEM data placeholder
* @param name Placeholder name (e.g., "%CSS%")
* @param progmemData Pointer to PROGMEM data
* @return true if registered successfully, false if registry full
*/
bool registerProgmemData(const char* name, const char* progmemData);
/**
* Register a PROGMEM template placeholder (nested template)
* @param name Placeholder name (e.g., "%HEADER%")
* @param progmemTemplate Pointer to PROGMEM template
* @return true if registered successfully
*/
bool registerProgmemTemplate(const char* name, const char* progmemTemplate);
/**
* Register a RAM data placeholder with getter function
* @param name Placeholder name (e.g., "%PAGE_TITLE%")
* @param getter Function that returns current value
* @return true if registered successfully
*/
bool registerRamData(const char* name, PlaceholderDataGetter getter);
bool registerDynamicData(const char* name, const DynamicDataDescriptor* descriptor);
bool registerDynamicTemplate(const char* name, const DynamicTemplateDescriptor* descriptor);
bool registerConditional(const char* name, const ConditionalDescriptor* descriptor);
bool registerIterator(const char* name, const IteratorDescriptor* descriptor);
/**
* Clear all registered placeholders
*/
void clear();
/**
* Get number of registered placeholders
*/
int getCount() const { return count; }
/**
* Get maximum number of placeholders
*/
uint16_t getMaxPlaceholders() const { return maxPlaceholders; }
/**
* Find placeholder entry by name
* @return PlaceholderEntry pointer or nullptr if not found
*/
const PlaceholderEntry* getPlaceholder(const char* name) const;
/**
* Render placeholder content at given offset
*/
size_t renderPlaceholder(const PlaceholderEntry* entry, size_t offset,
uint8_t* buffer, size_t maxLen) const;
// Static helper functions for length calculation
static size_t getProgmemLength(const void* data);
static size_t getRamLength(const void* data);
static size_t getDynamicDataLength(const DynamicDataDescriptor* descriptor, const char* data);
static size_t getDynamicTemplateLength(const DynamicTemplateDescriptor* descriptor, const char* templateData);
private:
static constexpr uint16_t MAX_PLACEHOLDER_NAME_SIZE = DFTE_PLACEHOLDER_NAME_SIZE;
PlaceholderEntry* placeholders; // Dynamically allocated array
uint16_t maxPlaceholders; // Configurable size
int count;
bool validatePlaceholderName(const char* name) const;
static size_t copyProgmemData(const char* source, size_t offset,
uint8_t* dest, size_t maxLen);
static size_t copyRamData(PlaceholderDataGetter getter, size_t offset,
uint8_t* dest, size_t maxLen);
static size_t copyDynamicData(const DynamicDataDescriptor* descriptor, size_t offset,
uint8_t* dest, size_t maxLen);
};
#endif // DEVICEFRAMEWORK_PLACEHOLDER_REGISTRY_H