[ESPEasy p2p] Cleanup use of std::unique_ptr + p2p data structs

This commit is contained in:
TD-er
2025-10-24 00:06:30 +02:00
parent 015dd8b3fc
commit cb84df0b44
38 changed files with 293 additions and 231 deletions
@@ -49,18 +49,9 @@ private:
};
typedef std::unique_ptr<NetworkSettingsStruct> NetworkSettingsStruct_ptr_type;
/*
# ifdef USE_SECOND_HEAP
#define MakeNetworkSettings(T) HeapSelectIram ephemeral; NetworkSettingsStruct_ptr_type T(new (std::nothrow) NetworkSettingsStruct());
#else
*/
DEF_UP(NetworkSettingsStruct);
#define MakeNetworkSettings(T) void *calloc_ptr = special_calloc(1, sizeof(NetworkSettingsStruct)); \
NetworkSettingsStruct_ptr_type T(new (calloc_ptr) NetworkSettingsStruct());
// #endif
UP_NetworkSettingsStruct T(new (calloc_ptr) NetworkSettingsStruct());
// Check to see if MakeNetworkSettings was successful
#define AllocatedNetworkSettings() (NetworkSettings.get() != nullptr)
+1 -1
View File
@@ -104,7 +104,7 @@ bool CPlugin_001(CPlugin::Function function, struct EventStruct *event, String&
void *ptr = special_calloc(1, size);
if (ptr != nullptr) {
std::unique_ptr<C001_queue_element> element(new (ptr) C001_queue_element(event->ControllerIndex, event->TaskIndex, std::move(url)));
UP_C001_queue_element element(new (ptr) C001_queue_element(event->ControllerIndex, event->TaskIndex, std::move(url)));
success = C001_DelayHandler->addToQueue(std::move(element));
}
+1 -1
View File
@@ -63,7 +63,7 @@ bool CPlugin_003(CPlugin::Function function, struct EventStruct *event, String&
void *ptr = special_calloc(1, size);
if (ptr != nullptr) {
std::unique_ptr<C003_queue_element> element(
UP_C003_queue_element element(
new (ptr) C003_queue_element(
event->ControllerIndex,
event->TaskIndex,
+1 -1
View File
@@ -77,7 +77,7 @@ bool CPlugin_004(CPlugin::Function function, struct EventStruct *event, String&
void *ptr = special_calloc(1, size);
if (ptr != nullptr) {
std::unique_ptr<C004_queue_element> element(new (ptr) C004_queue_element(event));
UP_C004_queue_element element(new (ptr) C004_queue_element(event));
success = C004_DelayHandler->addToQueue(std::move(element));
}
+1 -1
View File
@@ -81,7 +81,7 @@ bool CPlugin_007(CPlugin::Function function, struct EventStruct *event, String&
void *ptr = special_calloc(1, size);
if (ptr != nullptr) {
std::unique_ptr<C007_queue_element> element(new (ptr) C007_queue_element(event));
UP_C007_queue_element element(new (ptr) C007_queue_element(event));
success = C007_DelayHandler->addToQueue(std::move(element));
}
+1 -1
View File
@@ -85,7 +85,7 @@ bool CPlugin_008(CPlugin::Function function, struct EventStruct *event, String&
void *ptr = special_calloc(1, size);
if (ptr != nullptr) {
std::unique_ptr<C008_queue_element> element(new (ptr) C008_queue_element(event, valueCount));
UP_C008_queue_element element(new (ptr) C008_queue_element(event, valueCount));
success = C008_DelayHandler->addToQueue(std::move(element));
}
+1 -1
View File
@@ -86,7 +86,7 @@ bool CPlugin_009(CPlugin::Function function, struct EventStruct *event, String&
void *ptr = special_calloc(1, size);
if (ptr != nullptr) {
std::unique_ptr<C009_queue_element> element(new (ptr) C009_queue_element(event));
UP_C009_queue_element element(new (ptr) C009_queue_element(event));
success = C009_DelayHandler->addToQueue(std::move(element));
}
Scheduler.scheduleNextDelayQueue(SchedulerIntervalTimer_e::TIMER_C009_DELAY_QUEUE, C009_DelayHandler->getNextScheduleTime());
+1 -1
View File
@@ -74,7 +74,7 @@ bool CPlugin_010(CPlugin::Function function, struct EventStruct *event, String&
void *ptr = special_calloc(1, size);
if (ptr != nullptr) {
std::unique_ptr<C010_queue_element> element(new (ptr) C010_queue_element(event, valueCount));
UP_C010_queue_element element(new (ptr) C010_queue_element(event, valueCount));
{
String pubname;
{
+5 -3
View File
@@ -34,6 +34,8 @@ struct C011_ConfigStruct
};
DEF_UP(C011_ConfigStruct);
// Forward declarations
bool load_C011_ConfigStruct(controllerIndex_t ControllerIndex,
@@ -153,7 +155,7 @@ bool CPlugin_011(CPlugin::Function function, struct EventStruct *event, String&
void *ptr = special_calloc(1, size);
if (ptr != nullptr) {
std::unique_ptr<C011_ConfigStruct> customConfig(new (ptr) C011_ConfigStruct);
UP_C011_ConfigStruct customConfig(new (ptr) C011_ConfigStruct);
if (customConfig) {
uint8_t choice = 0;
@@ -245,7 +247,7 @@ bool load_C011_ConfigStruct(controllerIndex_t ControllerIndex, String& HttpMetho
return false;
}
std::unique_ptr<C011_ConfigStruct>customConfig(new (ptr) C011_ConfigStruct);
UP_C011_ConfigStruct customConfig(new (ptr) C011_ConfigStruct);
if (!customConfig) {
return false;
@@ -280,7 +282,7 @@ boolean Create_schedule_HTTP_C011(struct EventStruct *event)
// Add a new element to the queue with the minimal payload
std::unique_ptr<C011_queue_element>element(new (ptr) C011_queue_element(event));
UP_C011_queue_element element(new (ptr) C011_queue_element(event));
bool success = C011_DelayHandler->addToQueue(std::move(element));
if (success) {
+1 -1
View File
@@ -67,7 +67,7 @@ bool CPlugin_012(CPlugin::Function function, struct EventStruct *event, String&
break;
}
std::unique_ptr<C012_queue_element> element(new (ptr) C012_queue_element(event, valueCount));
UP_C012_queue_element element(new (ptr) C012_queue_element(event, valueCount));
for (uint8_t x = 0; x < valueCount; x++)
{
+72 -67
View File
@@ -119,23 +119,25 @@ void C013_SendUDPTaskInfo(uint8_t destUnit, uint8_t sourceTaskIndex, uint8_t des
return;
}
struct C013_SensorInfoStruct infoReply;
infoReply.sourceUnit = Settings.Unit;
infoReply.sourceTaskIndex = sourceTaskIndex;
infoReply.destTaskIndex = destTaskIndex;
infoReply.deviceNumber = pluginID;
infoReply.destUnit = destUnit;
MakeC013_SensorInfo(infoReply);
if (!AllocatedC013_SensorInfo(infoReply)) return;
infoReply->sourceUnit = Settings.Unit;
infoReply->sourceTaskIndex = sourceTaskIndex;
infoReply->destTaskIndex = destTaskIndex;
infoReply->deviceNumber = pluginID;
infoReply->destUnit = destUnit;
if (destUnit == 0)
{
// Send to broadcast address
infoReply.destUnit = 255;
infoReply->destUnit = 255;
}
size_t sizeToSend{};
if (infoReply.prepareForSend(sizeToSend)) {
C013_sendUDP(infoReply.destUnit, reinterpret_cast<const uint8_t *>(&infoReply), sizeToSend);
if (infoReply->prepareForSend(sizeToSend)) {
C013_sendUDP(infoReply->destUnit, reinterpret_cast<const uint8_t *>(infoReply.get()), sizeToSend);
}
}
@@ -144,32 +146,33 @@ void C013_SendUDPTaskData(struct EventStruct *event, uint8_t destUnit, uint8_t d
if (!NetworkConnected(10)) {
return;
}
struct C013_SensorDataStruct dataReply;
MakeC013_SensorData(dataReply);
if (!dataReply) return;
dataReply.sourceUnit = Settings.Unit;
dataReply.sourceTaskIndex = event->TaskIndex;
dataReply.destTaskIndex = destTaskIndex;
dataReply.deviceNumber = Settings.getPluginID_for_task(event->TaskIndex);
dataReply->sourceUnit = Settings.Unit;
dataReply->sourceTaskIndex = event->TaskIndex;
dataReply->destTaskIndex = destTaskIndex;
dataReply->deviceNumber = Settings.getPluginID_for_task(event->TaskIndex);
// FIXME TD-er: We should check for sensorType and pluginID on both sides.
// For example sending different sensor type data from one dummy to another is probably not going to work well
dataReply.sensorType = event->getSensorType();
dataReply->sensorType = event->getSensorType();
const TaskValues_Data_t *taskValues = UserVar.getRawTaskValues_Data(event->TaskIndex);
if (taskValues != nullptr) {
memcpy(dataReply.taskValues_Data, taskValues->binary, sizeof(dataReply.taskValues_Data));
memcpy(dataReply->taskValues_Data, taskValues->binary, sizeof(dataReply->taskValues_Data));
}
dataReply.destUnit = destUnit;
dataReply->destUnit = destUnit;
if (destUnit == 0)
{
// Send to broadcast address
dataReply.destUnit = 255;
dataReply->destUnit = 255;
}
dataReply.prepareForSend();
C013_sendUDP(dataReply.destUnit, reinterpret_cast<const uint8_t *>(&dataReply), sizeof(C013_SensorDataStruct));
dataReply->prepareForSend();
C013_sendUDP(dataReply->destUnit, reinterpret_cast<const uint8_t *>(dataReply.get()), sizeof(C013_SensorDataStruct));
}
/*********************************************************************************************\
@@ -255,69 +258,71 @@ void C013_Receive(struct EventStruct *event) {
{
// Allocate this is a separate scope since C013_SensorInfoStruct is a HUGE object
// Should not be left allocated on the stack when calling PLUGIN_INIT and save, etc.
struct C013_SensorInfoStruct infoReply;
if (infoReply.setData(event->Data, event->Par2)) {
auto infoReply = C013_SensorInfoStruct::create(event->Data, event->Par2);
if (!infoReply) return;
{
// to prevent flash wear out (bugs in communication?) we can only write to an empty task
// so it will write only once and has to be cleared manually through webgui
// Also check the receiving end does support the plugin ID.
const pluginID_t currentPluginID = Settings.getPluginID_for_task(infoReply.destTaskIndex);
const pluginID_t currentPluginID = Settings.getPluginID_for_task(infoReply->destTaskIndex);
bool mustUpdateCurrentTask = false;
if (currentPluginID == infoReply.deviceNumber) {
if (currentPluginID == infoReply->deviceNumber) {
// Check to see if task already is set to receive from this host
if ((Settings.TaskDeviceDataFeed[infoReply.destTaskIndex] == infoReply.sourceUnit) &&
Settings.TaskDeviceEnabled[infoReply.destTaskIndex]) {
if ((Settings.TaskDeviceDataFeed[infoReply->destTaskIndex] == infoReply->sourceUnit) &&
Settings.TaskDeviceEnabled[infoReply->destTaskIndex]) {
mustUpdateCurrentTask = true;
}
}
if ((mustUpdateCurrentTask || !validPluginID_fullcheck(currentPluginID)) &&
supportedPluginID(infoReply.deviceNumber))
supportedPluginID(infoReply->deviceNumber))
{
taskClear(infoReply.destTaskIndex, false);
Settings.TaskDeviceNumber[infoReply.destTaskIndex] = infoReply.deviceNumber.value;
Settings.TaskDeviceDataFeed[infoReply.destTaskIndex] = infoReply.sourceUnit; // remote feed store unit nr sending the data
taskClear(infoReply->destTaskIndex, false);
Settings.TaskDeviceNumber[infoReply->destTaskIndex] = infoReply->deviceNumber.value;
Settings.TaskDeviceDataFeed[infoReply->destTaskIndex] = infoReply->sourceUnit; // remote feed store unit nr sending the data
if (mustUpdateCurrentTask) {
Settings.TaskDeviceEnabled[infoReply.destTaskIndex] = true;
Settings.TaskDeviceEnabled[infoReply->destTaskIndex] = true;
}
constexpr pluginID_t DUMMY_PLUGIN_ID{ 33 };
if ((infoReply.deviceNumber == DUMMY_PLUGIN_ID) && (infoReply.sensorType != Sensor_VType::SENSOR_TYPE_NONE)) {
if ((infoReply->deviceNumber == DUMMY_PLUGIN_ID) && (infoReply->sensorType != Sensor_VType::SENSOR_TYPE_NONE)) {
// Received a dummy device and the sensor type is actually set
Settings.TaskDevicePluginConfig[infoReply.destTaskIndex][0] = static_cast<int16_t>(infoReply.sensorType);
Settings.TaskDevicePluginConfig[infoReply->destTaskIndex][0] = static_cast<int16_t>(infoReply->sensorType);
}
for (controllerIndex_t x = 0; x < CONTROLLER_MAX; x++) {
Settings.TaskDeviceSendData[x][infoReply.destTaskIndex] = false;
Settings.TaskDeviceSendData[x][infoReply->destTaskIndex] = false;
}
safe_strncpy(ExtraTaskSettings.TaskDeviceName, infoReply.taskName, sizeof(infoReply.taskName));
safe_strncpy(ExtraTaskSettings.TaskDeviceName, infoReply->taskName, sizeof(infoReply->taskName));
for (uint8_t x = 0; x < VARS_PER_TASK; x++) {
safe_strncpy(ExtraTaskSettings.TaskDeviceValueNames[x], infoReply.ValueNames[x], sizeof(infoReply.ValueNames[x]));
safe_strncpy(ExtraTaskSettings.TaskDeviceValueNames[x], infoReply->ValueNames[x], sizeof(infoReply->ValueNames[x]));
}
if (infoReply.sourceNodeBuild >= 20871) {
ExtraTaskSettings.version = infoReply.ExtraTaskSettings_version;
if (infoReply->sourceNodeBuild >= 20871) {
ExtraTaskSettings.version = infoReply->ExtraTaskSettings_version;
for (uint8_t x = 0; x < VARS_PER_TASK; x++) {
// safe_strncpy(ExtraTaskSettings.TaskDeviceFormula[x], infoReply.TaskDeviceFormula[x], sizeof(infoReply.TaskDeviceFormula[x]));
ExtraTaskSettings.TaskDeviceValueDecimals[x] = infoReply.TaskDeviceValueDecimals[x];
ExtraTaskSettings.TaskDeviceMinValue[x] = infoReply.TaskDeviceMinValue[x];
ExtraTaskSettings.TaskDeviceMaxValue[x] = infoReply.TaskDeviceMaxValue[x];
ExtraTaskSettings.TaskDeviceErrorValue[x] = infoReply.TaskDeviceErrorValue[x];
ExtraTaskSettings.VariousBits[x] = infoReply.VariousBits[x];
// safe_strncpy(ExtraTaskSettings.TaskDeviceFormula[x], infoReply->TaskDeviceFormula[x], sizeof(infoReply->TaskDeviceFormula[x]));
ExtraTaskSettings.TaskDeviceValueDecimals[x] = infoReply->TaskDeviceValueDecimals[x];
ExtraTaskSettings.TaskDeviceMinValue[x] = infoReply->TaskDeviceMinValue[x];
ExtraTaskSettings.TaskDeviceMaxValue[x] = infoReply->TaskDeviceMaxValue[x];
ExtraTaskSettings.TaskDeviceErrorValue[x] = infoReply->TaskDeviceErrorValue[x];
ExtraTaskSettings.VariousBits[x] = infoReply->VariousBits[x];
}
for (uint8_t x = 0; x < PLUGIN_CONFIGVAR_MAX; ++x) {
Settings.TaskDevicePluginConfig[infoReply.destTaskIndex][x] = infoReply.TaskDevicePluginConfig[x];
Settings.TaskDevicePluginConfig[infoReply->destTaskIndex][x] = infoReply->TaskDevicePluginConfig[x];
}
}
ExtraTaskSettings.TaskIndex = infoReply.destTaskIndex;
taskIndex = infoReply.destTaskIndex;
ExtraTaskSettings.TaskIndex = infoReply->destTaskIndex;
taskIndex = infoReply->destTaskIndex;
mustSave = true;
}
}
@@ -346,16 +351,16 @@ void C013_Receive(struct EventStruct *event) {
case 5: // sensor data
{
struct C013_SensorDataStruct dataReply;
auto dataReply = C013_SensorDataStruct::create(event->Data, event->Par2);
if (!dataReply) return;
// FIXME TD-er: We should check for sensorType and pluginID on both sides.
// For example sending different sensor type data from one dummy to another is probably not going to work well
if (dataReply.setData(event->Data, event->Par2)) {
{
// only if this task has a remote feed, update values
const uint8_t remoteFeed = Settings.TaskDeviceDataFeed[dataReply.destTaskIndex];
const uint8_t remoteFeed = Settings.TaskDeviceDataFeed[dataReply->destTaskIndex];
if ((remoteFeed != 0) && (remoteFeed == dataReply.sourceUnit))
if ((remoteFeed != 0) && (remoteFeed == dataReply->sourceUnit))
{
// deviceNumber and sensorType were not present before build 2023-05-05. (build NR 20460)
// See:
@@ -365,45 +370,45 @@ void C013_Receive(struct EventStruct *event) {
// If the node is not present in the nodes list (e.g. it had not announced itself in the last 10 minutes or announcement was
// missed)
// Then we cannot be sure about its build.
const bool mustMatch = dataReply.sourceNodeBuild >= 20460;
const bool mustMatch = dataReply->sourceNodeBuild >= 20460;
if (mustMatch && !dataReply.matchesPluginID(Settings.getPluginID_for_task(dataReply.destTaskIndex))) {
if (mustMatch && !dataReply->matchesPluginID(Settings.getPluginID_for_task(dataReply->destTaskIndex))) {
// Mismatch in plugin ID from sending node
if (loglevelActiveFor(LOG_LEVEL_ERROR)) {
String log = concat(F("P2P data : PluginID mismatch for task "), dataReply.destTaskIndex + 1);
log += concat(F(" from unit "), dataReply.sourceUnit);
log += concat(F(" remote: "), dataReply.deviceNumber.value);
log += concat(F(" local: "), Settings.getPluginID_for_task(dataReply.destTaskIndex).value);
String log = concat(F("P2P data : PluginID mismatch for task "), dataReply->destTaskIndex + 1);
log += concat(F(" from unit "), dataReply->sourceUnit);
log += concat(F(" remote: "), dataReply->deviceNumber.value);
log += concat(F(" local: "), Settings.getPluginID_for_task(dataReply->destTaskIndex).value);
addLogMove(LOG_LEVEL_ERROR, log);
}
} else {
struct EventStruct TempEvent(dataReply.destTaskIndex);
struct EventStruct TempEvent(dataReply->destTaskIndex);
TempEvent.Source = EventValueSource::Enum::VALUE_SOURCE_UDP;
const Sensor_VType sensorType = TempEvent.getSensorType();
if (!mustMatch || dataReply.matchesSensorType(sensorType)) {
TaskValues_Data_t *taskValues = UserVar.getRawTaskValues_Data(dataReply.destTaskIndex);
if (!mustMatch || dataReply->matchesSensorType(sensorType)) {
TaskValues_Data_t *taskValues = UserVar.getRawTaskValues_Data(dataReply->destTaskIndex);
if (taskValues != nullptr) {
memcpy(taskValues->binary, dataReply.taskValues_Data, sizeof(dataReply.taskValues_Data));
memcpy(taskValues->binary, dataReply->taskValues_Data, sizeof(dataReply->taskValues_Data));
}
STOP_TIMER(C013_RECEIVE_SENSOR_DATA);
if (node_time.systemTimePresent() && (dataReply.timestamp_sec != 0)) {
if (node_time.systemTimePresent() && (dataReply->timestamp_sec != 0)) {
// Only use timestamp of remote unit when we got a system time ourselves
// If not, then the order of samples can get messed up.
// timestamp_fraq is 16 bit, so need to scale it to 32 bit
TempEvent.timestamp_frac = static_cast<uint32_t>(dataReply.timestamp_frac) << 16;
SensorSendTask(&TempEvent, dataReply.timestamp_sec);
TempEvent.timestamp_frac = static_cast<uint32_t>(dataReply->timestamp_frac) << 16;
SensorSendTask(&TempEvent, dataReply->timestamp_sec);
} else {
SensorSendTask(&TempEvent);
}
} else {
// Mismatch in sensor types
if (loglevelActiveFor(LOG_LEVEL_ERROR)) {
String log = concat(F("P2P data : SensorType mismatch for task "), dataReply.destTaskIndex + 1);
log += concat(F(" from unit "), dataReply.sourceUnit);
String log = concat(F("P2P data : SensorType mismatch for task "), dataReply->destTaskIndex + 1);
log += concat(F(" from unit "), dataReply->sourceUnit);
addLogMove(LOG_LEVEL_ERROR, log);
}
}
+1 -1
View File
@@ -193,7 +193,7 @@ bool CPlugin_015(CPlugin::Function function, struct EventStruct *event, String&
void *ptr = special_calloc(1, size);
if (ptr != nullptr) {
std::unique_ptr<C015_queue_element> element(new (ptr) C015_queue_element(event, valueCount));
UP_C015_queue_element element(new (ptr) C015_queue_element(event, valueCount));
success = C015_DelayHandler->addToQueue(std::move(element));
}
+1 -1
View File
@@ -71,7 +71,7 @@ bool CPlugin_017(CPlugin::Function function, struct EventStruct *event, String&
void *ptr = special_calloc(1, size);
if (ptr != nullptr) {
std::unique_ptr<C017_queue_element> element(new (ptr) C017_queue_element(event));
UP_C017_queue_element element(new (ptr) C017_queue_element(event));
success = C017_DelayHandler->addToQueue(std::move(element));
}
Scheduler.scheduleNextDelayQueue(SchedulerIntervalTimer_e::TIMER_C017_DELAY_QUEUE, C017_DelayHandler->getNextScheduleTime());
+4 -4
View File
@@ -134,7 +134,7 @@ bool CPlugin_018(CPlugin::Function function, struct EventStruct *event, String&
if (ptr == nullptr) {
break;
}
std::unique_ptr<C018_ConfigStruct> customConfig(new (ptr) C018_ConfigStruct);
UP_C018_ConfigStruct customConfig(new (ptr) C018_ConfigStruct);
if (!customConfig) {
break;
@@ -153,7 +153,7 @@ bool CPlugin_018(CPlugin::Function function, struct EventStruct *event, String&
if (ptr == nullptr) {
break;
}
std::unique_ptr<C018_ConfigStruct> customConfig(new (ptr) C018_ConfigStruct);
UP_C018_ConfigStruct customConfig(new (ptr) C018_ConfigStruct);
if (customConfig) {
customConfig->webform_save();
@@ -206,7 +206,7 @@ bool CPlugin_018(CPlugin::Function function, struct EventStruct *event, String&
break;
}
std::unique_ptr<C018_queue_element> element(new (ptr) C018_queue_element(event, C018_data->getSampleSetCount(event->TaskIndex)));
UP_C018_queue_element element(new (ptr) C018_queue_element(event, C018_data->getSampleSetCount(event->TaskIndex)));
success = C018_DelayHandler->addToQueue(std::move(element));
Scheduler.scheduleNextDelayQueue(SchedulerIntervalTimer_e::TIMER_C018_DELAY_QUEUE,
C018_DelayHandler->getNextScheduleTime());
@@ -329,7 +329,7 @@ bool C018_init(struct EventStruct *event) {
if (ptr == nullptr) {
return false;
}
std::unique_ptr<C018_ConfigStruct> customConfig(new (ptr) C018_ConfigStruct);
UP_C018_ConfigStruct customConfig(new (ptr) C018_ConfigStruct);
if (!customConfig) {
return false;
+3
View File
@@ -86,6 +86,9 @@
#define NR_ELEMENTS(ARR) (sizeof (ARR) / sizeof *(ARR))
//#define NR_ELEMENTS(ARR) sizeof(ARR) / sizeof(ARR[0])
// Shortcut to typedef an unique pointer of a given type
#define DEF_UP(T) typedef std::unique_ptr<T> UP_##T
constexpr unsigned FLOOR_LOG2(unsigned x)
{
@@ -146,7 +146,7 @@ bool ControllerDelayHandlerStruct::isDuplicate(const Queue_element_base& element
// Try to add to the queue, if permitted by "delete_oldest"
// Return true when item was added, or skipped as it was considered a duplicate
bool ControllerDelayHandlerStruct::addToQueue(std::unique_ptr<Queue_element_base>element) {
bool ControllerDelayHandlerStruct::addToQueue(UP_Queue_element_base element) {
if (!element) {
return false;
}
@@ -50,7 +50,7 @@ struct ControllerDelayHandlerStruct {
// Try to add to the queue, if permitted by "delete_oldest"
// Return true when item was added, or skipped as it was considered a duplicate
bool addToQueue(std::unique_ptr<Queue_element_base>element);
bool addToQueue(UP_Queue_element_base element);
// Get the next element.
// Remove front element when max_retries is reached.
@@ -76,7 +76,7 @@ struct ControllerDelayHandlerStruct {
TimingStatsElements timerstats_id,
SchedulerIntervalTimer_e timerID);
std::list<std::unique_ptr<Queue_element_base> >sendQueue;
std::list<UP_Queue_element_base >sendQueue;
mutable UnitLastMessageCount_map unitLastMessageCount;
unsigned long lastSend = 0;
unsigned int minTimeBetweenMessages = CONTROLLER_DELAY_QUEUE_DELAY_DFLT;
@@ -9,6 +9,9 @@
#include "../ControllerQueue/Queue_element_base.h"
#include "../DataStructs/ControllerSettingsStruct.h"
#include <memory> // For std::unique_ptr
#include <new> // for std::nothrow
// The most logical place to have these queue element handlers defined would be in their
// respective _Cxxx.ino file.
@@ -56,6 +59,7 @@
void process_c##NNN####M##_delay_queue(); \
bool init_c##NNN####M##_delay_queue(controllerIndex_t ControllerIndex); \
void exit_c##NNN####M##_delay_queue(); \
typedef std::unique_ptr<C##NNN####M##_queue_element> UP_C##NNN####M##_queue_element;
# ifdef USE_SECOND_HEAP
@@ -55,6 +55,8 @@ public:
bool _retained = false;
};
DEF_UP(MQTT_queue_element);
#endif // if FEATURE_MQTT
#endif // CONTROLLERQUEUE_MQTT_QUEUE_ELEMENT_H
@@ -36,4 +36,6 @@ public:
bool _processByController;
};
DEF_UP(Queue_element_base);
#endif // ifndef CONTROLLERQUEUE_QUEUE_ELEMENT_BASE_H
+1
View File
@@ -48,6 +48,7 @@ struct C018_ConfigStruct
uint32_t rx2_freq = 0;
};
DEF_UP(C018_ConfigStruct);
#endif // ifdef USES_C018
@@ -37,27 +37,40 @@ bool C013_SensorDataStruct::prepareForSend()
validTaskIndex(destTaskIndex);
}
bool C013_SensorDataStruct::setData(const uint8_t *data, size_t size)
UP_C013_SensorDataStruct C013_SensorDataStruct::create(const uint8_t *data, size_t size)
{
// First clear entire struct
memset(this, 0, sizeof(C013_SensorDataStruct));
{
UP_C013_SensorDataStruct invalid_res{};
if (size < 6) {
return false;
if (size < 6) {
return invalid_res;
}
if ((data[0] != 255) || // header
(data[1] != 5)) { // ID
return invalid_res;
}
constexpr unsigned len_upto_checksum = offsetof(C013_SensorDataStruct, checksum);
const ShortChecksumType tmpChecksum(
data,
size,
len_upto_checksum);
if (size >= (len_upto_checksum + 4)) {
// Data could have checksum, see if it is valid.
uint8_t buf[4];
memcpy(buf, data + len_upto_checksum, sizeof(buf));
const ShortChecksumType checksum_data(buf);
if (checksum_data.isSet()) {
if (!(tmpChecksum == checksum_data)) {
return invalid_res;
}
}
}
}
if ((data[0] != 255) || // header
(data[1] != 5)) { // ID
return false;
}
constexpr unsigned len_upto_checksum = offsetof(C013_SensorDataStruct, checksum);
const ShortChecksumType tmpChecksum(
data,
size,
len_upto_checksum);
// Need to keep track of different possible versions of data which still need to be supported.
// Really old versions of ESPEasy might send upto 80 bytes of uninitialized data
// meaning for sizes > 24 bytes we may need to check the version of ESPEasy running on the node.
@@ -74,25 +87,28 @@ bool C013_SensorDataStruct::setData(const uint8_t *data, size_t size)
}
}
MakeC013_SensorData(res);
if (!AllocatedC013_SensorData(res)) { return res; }
memcpy((uint8_t*)res.get(), data, size);
if (size <= 24) {
deviceNumber = INVALID_PLUGIN_ID;
sensorType = Sensor_VType::SENSOR_TYPE_NONE;
res->deviceNumber = INVALID_PLUGIN_ID;
res->sensorType = Sensor_VType::SENSOR_TYPE_NONE;
if (sourceNode != nullptr) {
sourceNodeBuild = sourceNode->build;
res->sourceNodeBuild = sourceNode->build;
}
}
memcpy(this, data, size);
if (checksum.isSet()) {
if (!(tmpChecksum == checksum)) {
return false;
}
if (!(validTaskIndex(res->sourceTaskIndex) &&
validTaskIndex(res->destTaskIndex)))
{
res.reset();
}
return validTaskIndex(sourceTaskIndex) &&
validTaskIndex(destTaskIndex);
return res;
}
bool C013_SensorDataStruct::matchesPluginID(pluginID_t pluginID) const
@@ -13,14 +13,15 @@
# include "../DataTypes/TaskValues_Data.h"
# include "../DataTypes/PluginID.h"
struct __attribute__((__packed__)) C013_SensorDataStruct;
DEF_UP(C013_SensorDataStruct);
// These structs are sent to other nodes, so make sure not to change order or offset in struct.
struct __attribute__((__packed__)) C013_SensorDataStruct
{
C013_SensorDataStruct() = default;
bool setData(const uint8_t *data,
size_t size);
static UP_C013_SensorDataStruct create(const uint8_t *data, size_t size);
bool prepareForSend();
@@ -54,6 +55,16 @@ struct __attribute__((__packed__)) C013_SensorDataStruct
uint32_t IDX = 0;
};
#include "../Helpers/Memory.h"
#define MakeC013_SensorData(T) void * calloc_ptr = special_calloc(1,sizeof(C013_SensorDataStruct)); UP_C013_SensorDataStruct T(new (calloc_ptr) C013_SensorDataStruct());
// Check to see if MakeC013_SensorData was successful
#define AllocatedC013_SensorData(T) (T.get() != nullptr)
#endif // ifdef USES_C013
#endif // ifndef DATASTRUCTS_C013_P2P_SENSORDATASTRUCTS_H
@@ -47,13 +47,13 @@ bool C013_SensorInfoStruct::prepareForSend(size_t& sizeToSend)
TaskDeviceErrorValue[x] = ExtraTaskSettings.TaskDeviceErrorValue[x];
VariousBits[x] = ExtraTaskSettings.VariousBits[x];
/*
ZERO_FILL(TaskDeviceFormula[x]);
/*
ZERO_FILL(TaskDeviceFormula[x]);
if (ExtraTaskSettings.TaskDeviceFormula[x][0] != 0) {
safe_strncpy(TaskDeviceFormula[x], ExtraTaskSettings.TaskDeviceFormula[x], sizeof(TaskDeviceFormula[x]));
}
*/
if (ExtraTaskSettings.TaskDeviceFormula[x][0] != 0) {
safe_strncpy(TaskDeviceFormula[x], ExtraTaskSettings.TaskDeviceFormula[x], sizeof(TaskDeviceFormula[x]));
}
*/
}
for (uint8_t x = 0; x < PLUGIN_CONFIGVAR_MAX; ++x) {
@@ -94,54 +94,70 @@ bool C013_SensorInfoStruct::prepareForSend(size_t& sizeToSend)
return true;
}
bool C013_SensorInfoStruct::setData(const uint8_t *data, size_t size)
UP_C013_SensorInfoStruct C013_SensorInfoStruct::create(const uint8_t *data, size_t size)
{
// First clear entire struct
memset(this, 0, sizeof(C013_SensorInfoStruct));
{
UP_C013_SensorInfoStruct invalid_res{};
if (size < 6) {
return false;
if (size < 6) {
return invalid_res;
}
if ((data[0] != 255) || // header
(data[1] != 3)) { // ID
return invalid_res;
}
// Before copying the data, compute the checksum of the entire packet
constexpr unsigned len_upto_checksum = offsetof(C013_SensorInfoStruct, checksum);
const ShortChecksumType tmpChecksum(
data,
size,
len_upto_checksum);
if (size >= (len_upto_checksum + 4)) {
// Data could have checksum, see if it is valid.
uint8_t buf[4];
memcpy(buf, data + len_upto_checksum, sizeof(buf));
const ShortChecksumType checksum_data(buf);
if (checksum_data.isSet()) {
if (!(tmpChecksum == checksum_data)) {
return invalid_res;
}
}
}
}
if ((data[0] != 255) || // header
(data[1] != 3)) { // ID
return false;
}
// Before copying the data, compute the checksum of the entire packet
constexpr unsigned len_upto_checksum = offsetof(C013_SensorInfoStruct, checksum);
const ShortChecksumType tmpChecksum(
data,
size,
len_upto_checksum);
// Need to keep track of different possible versions of data which still need to be supported.
if (size > sizeof(C013_SensorInfoStruct)) {
size = sizeof(C013_SensorInfoStruct);
}
MakeC013_SensorInfo(res);
if (!AllocatedC013_SensorInfo(res)) { return res; }
memcpy((uint8_t *)res.get(), data, size);
if (size <= 138) {
deviceNumber = INVALID_PLUGIN_ID;
sensorType = Sensor_VType::SENSOR_TYPE_NONE;
res->deviceNumber = INVALID_PLUGIN_ID;
res->sensorType = Sensor_VType::SENSOR_TYPE_NONE;
NodeStruct *sourceNode = Nodes.getNode(data[2]); // sourceUnit
if (sourceNode != nullptr) {
sourceNodeBuild = sourceNode->build;
res->sourceNodeBuild = sourceNode->build;
}
}
memcpy(this, data, size);
if (checksum.isSet()) {
if (!(tmpChecksum == checksum)) {
return false;
}
if (!(validTaskIndex(res->sourceTaskIndex) &&
validTaskIndex(res->destTaskIndex) &&
validPluginID(res->deviceNumber)))
{
res.reset();
}
return validTaskIndex(sourceTaskIndex) &&
validTaskIndex(destTaskIndex) &&
validPluginID(deviceNumber);
return res;
}
#endif // ifdef USES_C013
@@ -14,13 +14,18 @@
# include "../DataTypes/PluginID.h"
#include "../Helpers/Memory.h"
struct __attribute__((__packed__)) C013_SensorInfoStruct;
DEF_UP(C013_SensorInfoStruct);
// These structs are sent to other nodes, so make sure not to change order or offset in struct.
struct __attribute__((__packed__)) C013_SensorInfoStruct
{
C013_SensorInfoStruct() = default;
bool setData(const uint8_t *data,
size_t size);
static UP_C013_SensorInfoStruct create(const uint8_t *data, size_t size);
bool prepareForSend(size_t& sizeToSend);
@@ -60,6 +65,13 @@ struct __attribute__((__packed__)) C013_SensorInfoStruct
};
#define MakeC013_SensorInfo(T) void * calloc_ptr = special_calloc(1,sizeof(C013_SensorInfoStruct)); UP_C013_SensorInfoStruct T(new (calloc_ptr) C013_SensorInfoStruct());
// Check to see if MakeC013_SensorInfo was successful
#define AllocatedC013_SensorInfo(T) (T.get() != nullptr)
#endif // ifdef USES_C013
#endif // ifndef DATASTRUCTS_C013_P2P_SENSORINFOSTRUCTS_H
@@ -270,14 +270,8 @@ private:
#include "../Helpers/Memory.h"
typedef std::unique_ptr<ControllerSettingsStruct> ControllerSettingsStruct_ptr_type;
/*
# ifdef USE_SECOND_HEAP
#define MakeControllerSettings(T) HeapSelectIram ephemeral; ControllerSettingsStruct_ptr_type T(new (std::nothrow) ControllerSettingsStruct());
#else
*/
#define MakeControllerSettings(T) void * calloc_ptr = special_calloc(1,sizeof(ControllerSettingsStruct)); ControllerSettingsStruct_ptr_type T(new (calloc_ptr) ControllerSettingsStruct());
//#endif
DEF_UP(ControllerSettingsStruct);
#define MakeControllerSettings(T) void * calloc_ptr = special_calloc(1,sizeof(ControllerSettingsStruct)); UP_ControllerSettingsStruct T(new (calloc_ptr) ControllerSettingsStruct());
// Check to see if MakeControllerSettings was successful
#define AllocatedControllerSettings() (ControllerSettings.get() != nullptr)
@@ -35,9 +35,9 @@ struct NotificationSettingsStruct
//its safe to extend this struct, up to 4096 bytes, default values in config are 0
};
typedef std::unique_ptr<NotificationSettingsStruct> NotificationSettingsStruct_ptr_type;
DEF_UP(NotificationSettingsStruct);
#define MakeNotificationSettings(T) void * calloc_ptr = special_calloc(1,sizeof(NotificationSettingsStruct)); NotificationSettingsStruct_ptr_type T(new (calloc_ptr) NotificationSettingsStruct());
#define MakeNotificationSettings(T) void * calloc_ptr = special_calloc(1,sizeof(NotificationSettingsStruct)); UP_NotificationSettingsStruct T(new (calloc_ptr) NotificationSettingsStruct());
// Check to see if MakeNotificationSettings was successful
#define AllocatedNotificationSettings() (NotificationSettings.get() != nullptr)
+2 -2
View File
@@ -55,9 +55,9 @@ struct ProvisioningStruct
};
};
typedef std::unique_ptr<ProvisioningStruct> ProvisioningStruct_ptr_type;
DEF_UP(ProvisioningStruct);
#define MakeProvisioningSettings(T) void * calloc_ptr = special_calloc(1,sizeof(ProvisioningStruct)); ProvisioningStruct_ptr_type T(new (calloc_ptr) ProvisioningStruct());
#define MakeProvisioningSettings(T) void * calloc_ptr = special_calloc(1,sizeof(ProvisioningStruct)); UP_ProvisioningStruct T(new (calloc_ptr) ProvisioningStruct());
-2
View File
@@ -3,8 +3,6 @@
#include <WString.h>
#include <Print.h>
#include <memory>
// ********************************************************************************
// ValueStruct
// ********************************************************************************
+2 -2
View File
@@ -1101,7 +1101,7 @@ bool MQTTpublish(controllerIndex_t controller_idx,
if (ptr != nullptr) {
success =
MQTTDelayHandler->addToQueue(
std::unique_ptr<MQTT_queue_element>(
UP_MQTT_queue_element (
new (ptr) MQTT_queue_element(
controller_idx, taskIndex,
std::move(topic_str),
@@ -1135,7 +1135,7 @@ bool MQTTpublish(controllerIndex_t controller_idx,
if (ptr != nullptr) {
success =
MQTTDelayHandler->addToQueue(
std::unique_ptr<MQTT_queue_element>(
UP_MQTT_queue_element (
new (ptr) MQTT_queue_element(
controller_idx, taskIndex,
std::move(topic),
+10 -9
View File
@@ -10,7 +10,7 @@
class KeyValueWriter;
typedef std::unique_ptr<KeyValueWriter> Up_KeyValueWriter;
DEF_UP(KeyValueWriter);
// ********************************************************************************
// KeyValueWriter
@@ -44,7 +44,7 @@ public:
virtual void setFooter(const String& footer) { _footer = footer; }
virtual void setIsArray() { _isArray = true; }
virtual void setIsArray() { _isArray = true; }
virtual void clear();
@@ -53,14 +53,15 @@ public:
virtual void write(const KeyValueStruct& kv) = 0;
void writeLabels(const LabelType::Enum labels[], bool extendedValues = false);
void writeLabels(const LabelType::Enum labels[],
bool extendedValues = false);
virtual void writeNote(const String& note);
virtual void writeNote(const __FlashStringHelper *note);
// virtual void setParent(KeyValueWriter*parent) { _parent = parent; }
virtual int getLevel() const;
virtual int getLevel() const;
// When set to 'plainText', the writer will not try to insert writer specific
// markings, like <pre> or <br> for example for HTML output
@@ -83,13 +84,13 @@ public:
virtual void setOutputToString(PrintToString*printToStr) { _toString = printToStr; }
// Create writer of the same derived type, with this set as parent
virtual Up_KeyValueWriter createChild() = 0;
virtual Up_KeyValueWriter createChild(const String& header) = 0;
virtual Up_KeyValueWriter createChildArray(const String& header) = 0;
virtual UP_KeyValueWriter createChild() = 0;
virtual UP_KeyValueWriter createChild(const String& header) = 0;
virtual UP_KeyValueWriter createChildArray(const String& header) = 0;
// Create new writer of the same derived type, without parent
virtual Up_KeyValueWriter createNew() = 0;
virtual Up_KeyValueWriter createNew(const String& header) = 0;
virtual UP_KeyValueWriter createNew() = 0;
virtual UP_KeyValueWriter createNew(const String& header) = 0;
const String& get() const {
if (_toString == nullptr) { return EMPTY_STRING; }
+9 -11
View File
@@ -5,8 +5,6 @@
#include "../WebServer/HTML_wrappers.h"
#include <memory>
KeyValueWriter_JSON::KeyValueWriter_JSON(bool emptyHeader, PrintToString *toStr)
: KeyValueWriter(emptyHeader, toStr)
@@ -197,9 +195,9 @@ void KeyValueWriter_JSON::writeValue(const ValueStruct& val)
pr.print(to_json_value(str));
}
Up_KeyValueWriter KeyValueWriter_JSON::createChild()
UP_KeyValueWriter KeyValueWriter_JSON::createChild()
{
std::unique_ptr<KeyValueWriter_JSON> child(new (std::nothrow) KeyValueWriter_JSON(this, _toString));
UP_KeyValueWriter_JSON child(new (std::nothrow) KeyValueWriter_JSON(this, _toString));
child->_allowFormatOverrides = _allowFormatOverrides;
@@ -208,9 +206,9 @@ Up_KeyValueWriter KeyValueWriter_JSON::createChild()
// return std::make_unique<KeyValueWriter_JSON>(this, _toString);
}
Up_KeyValueWriter KeyValueWriter_JSON::createChild(const String& header)
UP_KeyValueWriter KeyValueWriter_JSON::createChild(const String& header)
{
std::unique_ptr<KeyValueWriter_JSON> child(new (std::nothrow) KeyValueWriter_JSON(header, this, _toString));
UP_KeyValueWriter_JSON child(new (std::nothrow) KeyValueWriter_JSON(header, this, _toString));
child->_allowFormatOverrides = _allowFormatOverrides;
@@ -219,7 +217,7 @@ Up_KeyValueWriter KeyValueWriter_JSON::createChild(const String& header)
// return std::make_unique<KeyValueWriter_JSON>(header, this, _toString);
}
Up_KeyValueWriter KeyValueWriter_JSON::createChildArray(const String& header)
UP_KeyValueWriter KeyValueWriter_JSON::createChildArray(const String& header)
{
auto child = createChild(header);
@@ -230,9 +228,9 @@ Up_KeyValueWriter KeyValueWriter_JSON::createChildArray(const String& header)
return child;
}
Up_KeyValueWriter KeyValueWriter_JSON::createNew()
UP_KeyValueWriter KeyValueWriter_JSON::createNew()
{
std::unique_ptr<KeyValueWriter_JSON> child(new (std::nothrow) KeyValueWriter_JSON(false, _toString));
UP_KeyValueWriter_JSON child(new (std::nothrow) KeyValueWriter_JSON(false, _toString));
child->_allowFormatOverrides = _allowFormatOverrides;
@@ -241,9 +239,9 @@ Up_KeyValueWriter KeyValueWriter_JSON::createNew()
// return std::make_unique<KeyValueWriter_JSON>(false, _toString);
}
Up_KeyValueWriter KeyValueWriter_JSON::createNew(const String& header)
UP_KeyValueWriter KeyValueWriter_JSON::createNew(const String& header)
{
std::unique_ptr<KeyValueWriter_JSON> child(new (std::nothrow) KeyValueWriter_JSON(header, _toString));
UP_KeyValueWriter_JSON child(new (std::nothrow) KeyValueWriter_JSON(header, _toString));
child->_allowFormatOverrides = _allowFormatOverrides;
+9 -6
View File
@@ -3,8 +3,9 @@
#include "../Helpers/KeyValueWriter.h"
#ifndef BUILD_NO_DEBUG
// # define USE_KWH_JSON_PRETTY_PRINT
#endif
#endif // ifndef BUILD_NO_DEBUG
class KeyValueWriter_JSON : public KeyValueWriter
{
@@ -47,13 +48,13 @@ public:
virtual void write(const KeyValueStruct& kv);
// Create writer of the same derived type, with this set as parent
virtual Up_KeyValueWriter createChild();
virtual Up_KeyValueWriter createChild(const String& header);
virtual Up_KeyValueWriter createChildArray(const String& header);
virtual UP_KeyValueWriter createChild();
virtual UP_KeyValueWriter createChild(const String& header);
virtual UP_KeyValueWriter createChildArray(const String& header);
// Create new writer of the same derived type, without parent
virtual Up_KeyValueWriter createNew();
virtual Up_KeyValueWriter createNew(const String& header);
virtual UP_KeyValueWriter createNew();
virtual UP_KeyValueWriter createNew(const String& header);
virtual bool dataOnlyOutput() const override {
// JSON is not intended to be human readable
@@ -83,3 +84,5 @@ protected:
}; // class KeyValueWriter_JSON
DEF_UP(KeyValueWriter_JSON);
+4 -4
View File
@@ -35,7 +35,7 @@ void add_ChartJS_array(KeyValueWriter& parent,
}
}
Up_KeyValueWriter add_ChartJS_chart_header(
UP_KeyValueWriter add_ChartJS_chart_header(
const __FlashStringHelper *chartType,
const __FlashStringHelper *id,
const ChartJS_title & chartTitle,
@@ -54,7 +54,7 @@ Up_KeyValueWriter add_ChartJS_chart_header(
onlyJSON);
}
Up_KeyValueWriter add_ChartJS_chart_header(
UP_KeyValueWriter add_ChartJS_chart_header(
const __FlashStringHelper *chartType,
const String & id,
const ChartJS_title & chartTitle,
@@ -79,7 +79,7 @@ Up_KeyValueWriter add_ChartJS_chart_header(
id_c_str,
id_c_str));
}
std::unique_ptr<KeyValueWriter_JSON> chartJSON(new (std::nothrow) KeyValueWriter_JSON(true));
UP_KeyValueWriter_JSON chartJSON(new (std::nothrow) KeyValueWriter_JSON(true));
if (chartJSON) {
chartJSON->allowFormatOverrides(false);
@@ -216,7 +216,7 @@ void add_ChartJS_dataset(
}
}
Up_KeyValueWriter add_ChartJS_dataset_header(KeyValueWriter& dataset, const ChartJS_dataset_config& config)
UP_KeyValueWriter add_ChartJS_dataset_header(KeyValueWriter& dataset, const ChartJS_dataset_config& config)
{
if (!config.label.isEmpty()) {
dataset.write({ F("label"), config.label });
+3 -3
View File
@@ -49,7 +49,7 @@
# include "../WebServer/Chart_JS_scale.h"
# include "../DataStructs/ChartJS_dataset_config.h"
Up_KeyValueWriter add_ChartJS_chart_header(
UP_KeyValueWriter add_ChartJS_chart_header(
const __FlashStringHelper *chartType,
const __FlashStringHelper *id,
const ChartJS_title & chartTitle,
@@ -58,7 +58,7 @@ Up_KeyValueWriter add_ChartJS_chart_header(
size_t nrSamples = 0,
bool onlyJSON = false);
Up_KeyValueWriter add_ChartJS_chart_header(
UP_KeyValueWriter add_ChartJS_chart_header(
const __FlashStringHelper *chartType,
const String & id,
const ChartJS_title & chartTitle,
@@ -103,7 +103,7 @@ void add_ChartJS_dataset(
const String & options = EMPTY_STRING);
Up_KeyValueWriter add_ChartJS_dataset_header(
UP_KeyValueWriter add_ChartJS_dataset_header(
KeyValueWriter & dataset,
const ChartJS_dataset_config& config);
+9 -9
View File
@@ -145,25 +145,25 @@ void KeyValueWriter_WebForm::write(const KeyValueStruct& kv)
}
}
Up_KeyValueWriter KeyValueWriter_WebForm::createChild()
UP_KeyValueWriter KeyValueWriter_WebForm::createChild()
{
std::unique_ptr<KeyValueWriter_WebForm> child(new (std::nothrow) KeyValueWriter_WebForm(this));
UP_KeyValueWriter_WebForm child(new (std::nothrow) KeyValueWriter_WebForm(this));
return std::move(child);
// return std::make_unique<KeyValueWriter_WebForm>(this);
}
Up_KeyValueWriter KeyValueWriter_WebForm::createChild(const String& header)
UP_KeyValueWriter KeyValueWriter_WebForm::createChild(const String& header)
{
std::unique_ptr<KeyValueWriter_WebForm> child(new (std::nothrow) KeyValueWriter_WebForm(header, this));
UP_KeyValueWriter_WebForm child(new (std::nothrow) KeyValueWriter_WebForm(header, this));
return std::move(child);
// return std::make_unique<KeyValueWriter_WebForm>(header, this);
}
Up_KeyValueWriter KeyValueWriter_WebForm::createChildArray(const String& header)
UP_KeyValueWriter KeyValueWriter_WebForm::createChildArray(const String& header)
{
auto child = createChild(header);
@@ -175,18 +175,18 @@ Up_KeyValueWriter KeyValueWriter_WebForm::createChildArray(const String& header)
return child;
}
Up_KeyValueWriter KeyValueWriter_WebForm::createNew()
UP_KeyValueWriter KeyValueWriter_WebForm::createNew()
{
std::unique_ptr<KeyValueWriter_WebForm> child(new (std::nothrow) KeyValueWriter_WebForm());
UP_KeyValueWriter_WebForm child(new (std::nothrow) KeyValueWriter_WebForm());
return std::move(child);
// return std::make_unique<KeyValueWriter_WebForm>();
}
Up_KeyValueWriter KeyValueWriter_WebForm::createNew(const String& header)
UP_KeyValueWriter KeyValueWriter_WebForm::createNew(const String& header)
{
std::unique_ptr<KeyValueWriter_WebForm> child(new (std::nothrow) KeyValueWriter_WebForm(header));
UP_KeyValueWriter_WebForm child(new (std::nothrow) KeyValueWriter_WebForm(header));
return std::move(child);
+8 -5
View File
@@ -39,13 +39,16 @@ public:
virtual void write(const KeyValueStruct& kv);
// Create writer of the same derived type, with this set as parent
virtual Up_KeyValueWriter createChild();
virtual Up_KeyValueWriter createChild(const String& header);
virtual Up_KeyValueWriter createChildArray(const String& header);
virtual UP_KeyValueWriter createChild();
virtual UP_KeyValueWriter createChild(const String& header);
virtual UP_KeyValueWriter createChildArray(const String& header);
// Create new writer of the same derived type, without parent
virtual Up_KeyValueWriter createNew();
virtual Up_KeyValueWriter createNew(const String& header);
virtual UP_KeyValueWriter createNew();
virtual UP_KeyValueWriter createNew(const String& header);
}; // class KeyValueWriter_WebForm
DEF_UP(KeyValueWriter_WebForm);
+1 -1
View File
@@ -606,7 +606,7 @@ void addRowLabelValue_copy(LabelType::Enum label) {
void addRowColspan(int colspan) {
addHtml(strformat(
F("<TR><TD colspan=%d>"),
F("<TR><TD colspan=\"%d\">"),
colspan));
}