-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathCDIXMLGenerator.hxx
126 lines (118 loc) · 4.8 KB
/
CDIXMLGenerator.hxx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/** \copyright
* Copyright (c) 2018, Balazs Racz
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* \file CDIXMLGenerator.hxx
*
* Standalone CDI XML generation class.
*
* @author Balazs Racz, Mike Dunston
* @date 24 July 2018
*/
#ifndef _CDIXMLGENERATOR_HXX_
#define _CDIXMLGENERATOR_HXX_
#include "openlcb/SimpleStack.hxx"
#include "utils/FileUtils.hxx"
/// Standalone utility class for generating the XML representation of the node
/// configuration structure. This is primarily used in Arduino environments.
class CDIXMLGenerator
{
public:
/// Creates the XML representation of the configuration structure and saves
/// it to a file on the filesystem. Must be called after SPIFFS.begin() but
/// before calling the {\link create_config_file_if_needed} method. The
/// config file will be re-written whenever there was a change in the
/// contents. It is also necessary to declare the static compiled-in CDI to
/// be empty:
/// ```
/// namespace openlcb {
/// // This will stop openlcb from exporting the CDI memory space
/// // upon start.
/// extern const char CDI_DATA[] = "";
/// } // namespace openlcb
/// ```
/// @param cfg is the global configuration instance (usually called cfg).
/// @param filename is where the xml file can be stored on the
/// filesystem. For example "/spiffs/cdi.xml".
/// @return true if the configuration xml file was modified by this method,
/// false if the file was already up-to-date.
template <class ConfigDef>
static bool create_config_descriptor_xml(
const ConfigDef &config, const char *filename,
openlcb::SimpleStackBase *stack = nullptr)
{
string cdi_string;
ConfigDef cfg(config.offset());
cfg.config_renderer().render_cdi(&cdi_string);
cdi_string += '\0';
bool need_write = false;
LOG(INFO, "[CDI] Checking %s...", filename);
FILE *ff = fopen(filename, "rb");
if (!ff)
{
LOG(INFO, "[CDI] File %s does not exist", filename);
need_write = true;
}
else
{
fclose(ff);
string current_str = read_file_to_string(filename);
if (current_str != cdi_string)
{
LOG(INFO, "[CDI] File %s is not up-to-date", filename);
need_write = true;
}
else
{
LOG(INFO, "[CDI] File %s appears up-to-date (len %u vs %u)",
filename, current_str.size(), cdi_string.size());
}
}
if (need_write)
{
LOG(INFO, "[CDI] Updating %s (len %u)", filename,
cdi_string.size());
write_string_to_file(filename, cdi_string);
}
if (stack)
{
LOG(INFO, "[CDI] Registering CDI with stack...");
// Creates list of event IDs for factory reset.
auto *v = new vector<uint16_t>();
cfg.handle_events([v](unsigned o) { v->push_back(o); });
v->push_back(0);
stack->set_event_offsets(v);
// We leak v because it has to stay alive for the entire lifetime
// of the stack.
// Add the file memory space to the stack.
openlcb::MemorySpace *space =
new openlcb::ROFileMemorySpace(filename);
stack->memory_config_handler()->registry()->insert(
stack->node(), openlcb::MemoryConfigDefs::SPACE_CDI, space);
}
return need_write;
}
};
#endif // _CDIXMLGENERATOR_HXX_