25
#include "PreCompiled.h"
31
#include <xercesc/dom/DOM.hpp>
32
#include <xercesc/framework/LocalFileFormatTarget.hpp>
33
#include <xercesc/framework/LocalFileInputSource.hpp>
34
#include <xercesc/framework/MemBufFormatTarget.hpp>
35
#include <xercesc/framework/MemBufInputSource.hpp>
36
#include <xercesc/parsers/XercesDOMParser.hpp>
37
#include <xercesc/sax/ErrorHandler.hpp>
38
#include <xercesc/sax/SAXParseException.hpp>
48
#include <boost/algorithm/string.hpp>
51
#include "Parameter.inl"
56
FC_LOG_LEVEL_INIT("Parameter", true, true)
59
XERCES_CPP_NAMESPACE_USE
76
class DOMTreeErrorReporter: public ErrorHandler
82
void warning(const SAXParseException& toCatch) override;
83
void error(const SAXParseException& toCatch) override;
84
void fatalError(const SAXParseException& toCatch) override;
85
void resetErrors() override;
90
bool getSawErrors() const;
100
bool fSawErrors {false};
104
class DOMPrintFilter: public DOMLSSerializerFilter
108
explicit DOMPrintFilter(ShowType whatToShow = DOMNodeFilter::SHOW_ALL);
112
~DOMPrintFilter() override = default;
116
FilterAction acceptNode(const XERCES_CPP_NAMESPACE_QUALIFIER DOMNode* node) const override;
119
ShowType getWhatToShow() const override
125
DOMPrintFilter(const DOMPrintFilter&) = delete;
126
DOMPrintFilter(DOMPrintFilter&&) = delete;
127
DOMPrintFilter& operator=(const DOMPrintFilter&) = delete;
128
DOMPrintFilter& operator=(DOMPrintFilter&&) = delete;
130
ShowType fWhatToShow;
133
class DOMPrintErrorHandler: public DOMErrorHandler
136
DOMPrintErrorHandler() = default;
137
~DOMPrintErrorHandler() override = default;
140
bool handleError(const DOMError& domError) override;
145
DOMPrintErrorHandler(const DOMPrintErrorHandler&) = delete;
146
DOMPrintErrorHandler(DOMPrintErrorHandler&&) = delete;
147
void operator=(const DOMPrintErrorHandler&) = delete;
148
void operator=(DOMPrintErrorHandler&&) = delete;
152
inline bool DOMTreeErrorReporter::getSawErrors() const
170
ParameterGrp::ParameterGrp(XERCES_CPP_NAMESPACE_QUALIFIER DOMElement* GroupNode,
172
ParameterGrp* Parent)
174
, Subject<const char*>()
175
, _pGroupNode(GroupNode)
182
_Manager = _Parent->_Manager;
190
ParameterGrp::~ParameterGrp()
192
for (auto& v : _GroupMap) {
193
v.second->_Parent = nullptr;
194
v.second->_Manager = nullptr;
196
if (_Detached && _pGroupNode) {
197
_pGroupNode->release();
204
void ParameterGrp::copyTo(Base::Reference<ParameterGrp> Grp)
217
void ParameterGrp::insertTo(Base::Reference<ParameterGrp> Grp)
224
std::vector<Base::Reference<ParameterGrp>> Grps = GetGroups();
225
std::vector<Base::Reference<ParameterGrp>>::iterator It1;
226
for (It1 = Grps.begin(); It1 != Grps.end(); ++It1) {
227
(*It1)->insertTo(Grp->GetGroup((*It1)->GetGroupName()));
231
std::vector<std::pair<std::string, std::string>> StringMap = GetASCIIMap();
232
std::vector<std::pair<std::string, std::string>>::iterator It2;
233
for (It2 = StringMap.begin(); It2 != StringMap.end(); ++It2) {
234
Grp->SetASCII(It2->first.c_str(), It2->second.c_str());
238
std::vector<std::pair<std::string, bool>> BoolMap = GetBoolMap();
239
std::vector<std::pair<std::string, bool>>::iterator It3;
240
for (It3 = BoolMap.begin(); It3 != BoolMap.end(); ++It3) {
241
Grp->SetBool(It3->first.c_str(), It3->second);
245
std::vector<std::pair<std::string, long>> IntMap = GetIntMap();
246
std::vector<std::pair<std::string, long>>::iterator It4;
247
for (It4 = IntMap.begin(); It4 != IntMap.end(); ++It4) {
248
Grp->SetInt(It4->first.c_str(), It4->second);
252
std::vector<std::pair<std::string, double>> FloatMap = GetFloatMap();
253
std::vector<std::pair<std::string, double>>::iterator It5;
254
for (It5 = FloatMap.begin(); It5 != FloatMap.end(); ++It5) {
255
Grp->SetFloat(It5->first.c_str(), It5->second);
259
std::vector<std::pair<std::string, unsigned long>> UIntMap = GetUnsignedMap();
260
std::vector<std::pair<std::string, unsigned long>>::iterator It6;
261
for (It6 = UIntMap.begin(); It6 != UIntMap.end(); ++It6) {
262
Grp->SetUnsigned(It6->first.c_str(), It6->second);
266
void ParameterGrp::exportTo(const char* FileName)
268
auto Mngr = ParameterManager::Create();
270
Mngr->CreateDocument();
273
insertTo(Base::Reference<ParameterGrp>(Mngr));
275
Mngr->SaveDocument(FileName);
278
void ParameterGrp::importFrom(const char* FileName)
280
auto Mngr = ParameterManager::Create();
282
if (Mngr->LoadDocument(FileName) != 1) {
283
throw FileException("ParameterGrp::import() cannot load document", FileName);
286
Mngr->copyTo(Base::Reference<ParameterGrp>(this));
289
void ParameterGrp::insert(const char* FileName)
291
auto Mngr = ParameterManager::Create();
293
if (Mngr->LoadDocument(FileName) != 1) {
294
throw FileException("ParameterGrp::import() cannot load document", FileName);
297
Mngr->insertTo(Base::Reference<ParameterGrp>(this));
300
void ParameterGrp::revert(const char* FileName)
302
auto Mngr = ParameterManager::Create();
304
if (Mngr->LoadDocument(FileName) != 1) {
305
throw FileException("ParameterGrp::revert() cannot load document", FileName);
308
revert(Base::Reference<ParameterGrp>(Mngr));
311
void ParameterGrp::revert(Base::Reference<ParameterGrp> Grp)
317
for (auto& grp : Grp->GetGroups()) {
318
if (HasGroup(grp->GetGroupName())) {
319
GetGroup(grp->GetGroupName())->revert(grp);
323
for (const auto& v : Grp->GetASCIIMap()) {
324
if (GetASCII(v.first.c_str(), v.second.c_str()) == v.second) {
325
RemoveASCII(v.first.c_str());
329
for (const auto& v : Grp->GetBoolMap()) {
330
if (GetBool(v.first.c_str(), v.second) == v.second) {
331
RemoveBool(v.first.c_str());
335
for (const auto& v : Grp->GetIntMap()) {
336
if (GetInt(v.first.c_str(), v.second) == v.second) {
337
RemoveInt(v.first.c_str());
341
for (const auto& v : Grp->GetUnsignedMap()) {
342
if (GetUnsigned(v.first.c_str(), v.second) == v.second) {
343
RemoveUnsigned(v.first.c_str());
347
for (const auto& v : Grp->GetFloatMap()) {
348
if (GetFloat(v.first.c_str(), v.second) == v.second) {
349
RemoveFloat(v.first.c_str());
354
XERCES_CPP_NAMESPACE_QUALIFIER DOMElement*
355
ParameterGrp::CreateElement(XERCES_CPP_NAMESPACE_QUALIFIER DOMElement* Start,
359
if (XMLString::compareString(Start->getNodeName(), XStr("FCParamGroup").unicodeForm()) != 0
360
&& XMLString::compareString(Start->getNodeName(), XStr("FCParameters").unicodeForm())
362
Base::Console().Warning("CreateElement: %s cannot have the element %s of type %s\n",
363
StrX(Start->getNodeName()).c_str(),
369
if (_Detached && _Parent) {
371
_Parent->_GetGroup(_cName.c_str());
374
XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument* pDocument = Start->getOwnerDocument();
376
auto pcElem = pDocument->createElement(XStr(Type).unicodeForm());
377
pcElem->setAttribute(XStr("Name").unicodeForm(), XStr(Name).unicodeForm());
378
Start->appendChild(pcElem);
383
Base::Reference<ParameterGrp> ParameterGrp::GetGroup(const char* Name)
386
throw Base::ValueError("Empty group name");
389
Base::Reference<ParameterGrp> hGrp = this;
390
std::vector<std::string> tokens;
391
boost::split(tokens, Name, boost::is_any_of("/"));
392
for (auto& token : tokens) {
397
hGrp = hGrp->_GetGroup(token.c_str());
401
hGrp = new ParameterGrp();
407
throw Base::ValueError("Empty group name");
412
Base::Reference<ParameterGrp> ParameterGrp::_GetGroup(const char* Name)
414
Base::Reference<ParameterGrp> rParamGrp;
416
if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) {
417
FC_WARN("Adding group " << Name << " in an orphan group " << _cName);
422
if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) {
423
FC_WARN("Adding group " << Name << " while clearing " << GetPath());
428
DOMElement* pcTemp {};
431
pcTemp = FindElement(_pGroupNode, "FCParamGroup", Name);
434
if (!(rParamGrp = _GroupMap[Name]).isValid()) {
436
pcTemp = CreateElement(_pGroupNode, "FCParamGroup", Name);
439
rParamGrp = Base::Reference<ParameterGrp>(new ParameterGrp(pcTemp, Name, this));
440
_GroupMap[Name] = rParamGrp;
443
_pGroupNode->appendChild(rParamGrp->_pGroupNode);
444
rParamGrp->_Detached = false;
445
if (this->_Detached && this->_Parent) {
448
this->_Parent->_GetGroup(_cName.c_str());
452
if (!pcTemp && !this->_Detached) {
453
_Notify(ParamType::FCGroup, Name, Name);
459
std::string ParameterGrp::GetPath() const
462
if (_Parent && _Parent != _Manager) {
463
path = _Parent->GetPath();
465
if (!path.empty() && !_cName.empty()) {
472
std::vector<Base::Reference<ParameterGrp>> ParameterGrp::GetGroups()
474
Base::Reference<ParameterGrp> rParamGrp;
475
std::vector<Base::Reference<ParameterGrp>> vrParamGrp;
483
DOMElement* pcTemp = FindElement(_pGroupNode, "FCParamGroup");
486
StrX(pcTemp->getAttributes()->getNamedItem(XStr("Name").unicodeForm())->getNodeValue())
489
if (!(rParamGrp = _GroupMap[Name]).isValid()) {
490
rParamGrp = Base::Reference<ParameterGrp>(new ParameterGrp(pcTemp, Name.c_str(), this));
491
_GroupMap[Name] = rParamGrp;
493
vrParamGrp.push_back(rParamGrp);
495
pcTemp = FindNextElement(pcTemp, "FCParamGroup");
502
bool ParameterGrp::IsEmpty() const
504
return !(_pGroupNode && _pGroupNode->getFirstChild());
508
bool ParameterGrp::HasGroup(const char* Name) const
510
if (_GroupMap.find(Name) != _GroupMap.end()) {
514
if (_pGroupNode && FindElement(_pGroupNode, "FCParamGroup", Name) != nullptr) {
521
const char* ParameterGrp::TypeName(ParamType Type)
524
case ParamType::FCBool:
526
case ParamType::FCInt:
528
case ParamType::FCUInt:
530
case ParamType::FCText:
532
case ParamType::FCFloat:
534
case ParamType::FCGroup:
535
return "FCParamGroup";
541
ParameterGrp::ParamType ParameterGrp::TypeValue(const char* Name)
544
if (boost::equals(Name, "FCBool")) {
545
return ParamType::FCBool;
547
if (boost::equals(Name, "FCInt")) {
548
return ParamType::FCInt;
550
if (boost::equals(Name, "FCUInt")) {
551
return ParamType::FCUInt;
553
if (boost::equals(Name, "FCText")) {
554
return ParamType::FCText;
556
if (boost::equals(Name, "FCFloat")) {
557
return ParamType::FCFloat;
559
if (boost::equals(Name, "FCParamGroup")) {
560
return ParamType::FCGroup;
563
return ParamType::FCInvalid;
566
void ParameterGrp::SetAttribute(ParamType Type, const char* Name, const char* Value)
569
case ParamType::FCBool:
570
case ParamType::FCInt:
571
case ParamType::FCUInt:
572
case ParamType::FCFloat:
573
return _SetAttribute(Type, Name, Value);
574
case ParamType::FCText:
575
return SetASCII(Name, Value);
576
case ParamType::FCGroup:
577
RenameGrp(Name, Value);
584
void ParameterGrp::RemoveAttribute(ParamType Type, const char* Name)
587
case ParamType::FCBool:
588
return RemoveBool(Name);
589
case ParamType::FCInt:
590
return RemoveInt(Name);
591
case ParamType::FCUInt:
592
return RemoveUnsigned(Name);
593
case ParamType::FCText:
594
return RemoveASCII(Name);
595
case ParamType::FCFloat:
596
return RemoveFloat(Name);
597
case ParamType::FCGroup:
598
return RemoveGrp(Name);
604
const char* ParameterGrp::GetAttribute(ParamType Type,
607
const char* Default) const
613
const char* T = TypeName(Type);
618
DOMElement* pcElem = FindElement(_pGroupNode, T, Name);
623
if (Type == ParamType::FCText) {
624
Value = GetASCII(Name, Default);
626
else if (Type != ParamType::FCGroup) {
627
Value = StrX(pcElem->getAttribute(XStr("Value").unicodeForm())).c_str();
629
return Value.c_str();
632
std::vector<std::pair<std::string, std::string>>
633
ParameterGrp::GetAttributeMap(ParamType Type, const char* sFilter) const
635
std::vector<std::pair<std::string, std::string>> res;
640
const char* T = TypeName(Type);
647
DOMElement* pcTemp = FindElement(_pGroupNode, T);
649
Name = StrX(static_cast<DOMElement*>(pcTemp)
651
->getNamedItem(XStr("Name").unicodeForm())
655
if (!sFilter || Name.find(sFilter) != std::string::npos) {
656
if (Type == ParamType::FCGroup) {
657
res.emplace_back(Name, std::string());
660
res.emplace_back(Name,
661
StrX(static_cast<DOMElement*>(pcTemp)->getAttribute(
662
XStr("Value").unicodeForm()))
666
pcTemp = FindNextElement(pcTemp, T);
671
void ParameterGrp::_Notify(ParamType Type, const char* Name, const char* Value)
674
_Manager->signalParamChanged(this, Type, Name, Value);
678
void ParameterGrp::_SetAttribute(ParamType T, const char* Name, const char* Value)
680
const char* Type = TypeName(T);
685
if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) {
686
FC_WARN("Setting attribute " << Type << ":" << Name << " in an orphan group "
692
if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) {
693
FC_WARN("Adding attribute " << Type << ":" << Name << " while clearing " << GetPath());
699
DOMElement* pcElem = FindOrCreateElement(_pGroupNode, Type, Name);
703
if (strcmp(StrX(pcElem->getAttribute(attr.unicodeForm())).c_str(), Value) != 0) {
704
pcElem->setAttribute(attr.unicodeForm(), XStr(Value).unicodeForm());
706
_Notify(T, Name, Value);
714
bool ParameterGrp::GetBool(const char* Name, bool bPreset) const
721
DOMElement* pcElem = FindElement(_pGroupNode, "FCBool", Name);
728
return (strcmp(StrX(pcElem->getAttribute(XStr("Value").unicodeForm())).c_str(), "1") == 0);
731
void ParameterGrp::SetBool(const char* Name, bool bValue)
733
_SetAttribute(ParamType::FCBool, Name, bValue ? "1" : "0");
736
std::vector<bool> ParameterGrp::GetBools(const char* sFilter) const
738
std::vector<bool> vrValues;
745
DOMElement* pcTemp = FindElement(_pGroupNode, "FCBool");
747
Name = StrX(pcTemp->getAttribute(XStr("Name").unicodeForm())).c_str();
749
if (!sFilter || Name.find(sFilter) != std::string::npos) {
750
if (strcmp(StrX(pcTemp->getAttribute(XStr("Value").unicodeForm())).c_str(), "1") != 0) {
751
vrValues.push_back(false);
754
vrValues.push_back(true);
757
pcTemp = FindNextElement(pcTemp, "FCBool");
763
std::vector<std::pair<std::string, bool>> ParameterGrp::GetBoolMap(const char* sFilter) const
765
std::vector<std::pair<std::string, bool>> vrValues;
772
DOMElement* pcTemp = FindElement(_pGroupNode, "FCBool");
774
Name = StrX(pcTemp->getAttribute(XStr("Name").unicodeForm())).c_str();
776
if (!sFilter || Name.find(sFilter) != std::string::npos) {
777
if (strcmp(StrX(pcTemp->getAttribute(XStr("Value").unicodeForm())).c_str(), "1") != 0) {
778
vrValues.emplace_back(Name, false);
781
vrValues.emplace_back(Name, true);
784
pcTemp = FindNextElement(pcTemp, "FCBool");
790
long ParameterGrp::GetInt(const char* Name, long lPreset) const
797
DOMElement* pcElem = FindElement(_pGroupNode, "FCInt", Name);
803
return atol(StrX(pcElem->getAttribute(XStr("Value").unicodeForm())).c_str());
806
void ParameterGrp::SetInt(const char* Name, long lValue)
809
sprintf(cBuf, "%li", lValue);
810
_SetAttribute(ParamType::FCInt, Name, cBuf);
813
std::vector<long> ParameterGrp::GetInts(const char* sFilter) const
815
std::vector<long> vrValues;
822
DOMElement* pcTemp = FindElement(_pGroupNode, "FCInt");
824
Name = StrX(pcTemp->getAttribute(XStr("Name").unicodeForm())).c_str();
826
if (!sFilter || Name.find(sFilter) != std::string::npos) {
828
atol(StrX(pcTemp->getAttribute(XStr("Value").unicodeForm())).c_str()));
830
pcTemp = FindNextElement(pcTemp, "FCInt");
836
std::vector<std::pair<std::string, long>> ParameterGrp::GetIntMap(const char* sFilter) const
838
std::vector<std::pair<std::string, long>> vrValues;
845
DOMElement* pcTemp = FindElement(_pGroupNode, "FCInt");
847
Name = StrX(pcTemp->getAttribute(XStr("Name").unicodeForm())).c_str();
849
if (!sFilter || Name.find(sFilter) != std::string::npos) {
850
vrValues.emplace_back(
852
(atol(StrX(pcTemp->getAttribute(XStr("Value").unicodeForm())).c_str())));
854
pcTemp = FindNextElement(pcTemp, "FCInt");
860
unsigned long ParameterGrp::GetUnsigned(const char* Name, unsigned long lPreset) const
867
DOMElement* pcElem = FindElement(_pGroupNode, "FCUInt", Name);
873
return strtoul(StrX(pcElem->getAttribute(XStr("Value").unicodeForm())).c_str(), nullptr, 10);
876
void ParameterGrp::SetUnsigned(const char* Name, unsigned long lValue)
879
sprintf(cBuf, "%lu", lValue);
880
_SetAttribute(ParamType::FCUInt, Name, cBuf);
883
std::vector<unsigned long> ParameterGrp::GetUnsigneds(const char* sFilter) const
885
std::vector<unsigned long> vrValues;
892
DOMElement* pcTemp = FindElement(_pGroupNode, "FCUInt");
894
Name = StrX(pcTemp->getAttribute(XStr("Name").unicodeForm())).c_str();
896
if (!sFilter || Name.find(sFilter) != std::string::npos) {
898
strtoul(StrX(pcTemp->getAttribute(XStr("Value").unicodeForm())).c_str(),
902
pcTemp = FindNextElement(pcTemp, "FCUInt");
908
std::vector<std::pair<std::string, unsigned long>>
909
ParameterGrp::GetUnsignedMap(const char* sFilter) const
911
std::vector<std::pair<std::string, unsigned long>> vrValues;
918
DOMElement* pcTemp = FindElement(_pGroupNode, "FCUInt");
920
Name = StrX(pcTemp->getAttribute(XStr("Name").unicodeForm())).c_str();
922
if (!sFilter || Name.find(sFilter) != std::string::npos) {
923
vrValues.emplace_back(
925
(strtoul(StrX(pcTemp->getAttribute(XStr("Value").unicodeForm())).c_str(),
929
pcTemp = FindNextElement(pcTemp, "FCUInt");
935
double ParameterGrp::GetFloat(const char* Name, double dPreset) const
942
DOMElement* pcElem = FindElement(_pGroupNode, "FCFloat", Name);
948
return atof(StrX(pcElem->getAttribute(XStr("Value").unicodeForm())).c_str());
951
void ParameterGrp::SetFloat(const char* Name, double dValue)
954
sprintf(cBuf, "%.12f", dValue);
955
_SetAttribute(ParamType::FCFloat, Name, cBuf);
958
std::vector<double> ParameterGrp::GetFloats(const char* sFilter) const
960
std::vector<double> vrValues;
967
DOMElement* pcTemp = FindElement(_pGroupNode, "FCFloat");
969
Name = StrX(pcTemp->getAttribute(XStr("Name").unicodeForm())).c_str();
971
if (!sFilter || Name.find(sFilter) != std::string::npos) {
973
atof(StrX(pcTemp->getAttribute(XStr("Value").unicodeForm())).c_str()));
975
pcTemp = FindNextElement(pcTemp, "FCFloat");
981
std::vector<std::pair<std::string, double>> ParameterGrp::GetFloatMap(const char* sFilter) const
983
std::vector<std::pair<std::string, double>> vrValues;
990
DOMElement* pcTemp = FindElement(_pGroupNode, "FCFloat");
992
Name = StrX(pcTemp->getAttribute(XStr("Name").unicodeForm())).c_str();
994
if (!sFilter || Name.find(sFilter) != std::string::npos) {
995
vrValues.emplace_back(
997
(atof(StrX(pcTemp->getAttribute(XStr("Value").unicodeForm())).c_str())));
999
pcTemp = FindNextElement(pcTemp, "FCFloat");
1006
void ParameterGrp::SetASCII(const char* Name, const char* sValue)
1009
if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) {
1010
FC_WARN("Setting attribute "
1011
<< "FCText:" << Name << " in an orphan group " << _cName);
1016
if (FC_LOG_INSTANCE.isEnabled(FC_LOGLEVEL_LOG)) {
1017
FC_WARN("Adding attribute "
1018
<< "FCText:" << Name << " while clearing " << GetPath());
1024
DOMElement* pcElem = FindElement(_pGroupNode, "FCText", Name);
1026
pcElem = CreateElement(_pGroupNode, "FCText", Name);
1031
DOMNode* pcElem2 = pcElem->getFirstChild();
1033
XERCES_CPP_NAMESPACE_QUALIFIER DOMDocument* pDocument = _pGroupNode->getOwnerDocument();
1034
DOMText* pText = pDocument->createTextNode(XUTF8Str(sValue).unicodeForm());
1035
pcElem->appendChild(pText);
1036
if (isNew || sValue[0] != 0) {
1037
_Notify(ParamType::FCText, Name, sValue);
1040
else if (strcmp(StrXUTF8(pcElem2->getNodeValue()).c_str(), sValue) != 0) {
1041
pcElem2->setNodeValue(XUTF8Str(sValue).unicodeForm());
1042
_Notify(ParamType::FCText, Name, sValue);
1049
std::string ParameterGrp::GetASCII(const char* Name, const char* pPreset) const
1052
return pPreset ? pPreset : "";
1056
DOMElement* pcElem = FindElement(_pGroupNode, "FCText", Name);
1065
DOMNode* pcElem2 = pcElem->getFirstChild();
1067
return {StrXUTF8(pcElem2->getNodeValue()).c_str()};
1072
std::vector<std::string> ParameterGrp::GetASCIIs(const char* sFilter) const
1074
std::vector<std::string> vrValues;
1081
DOMElement* pcTemp = FindElement(_pGroupNode, "FCText");
1083
Name = StrXUTF8(pcTemp->getAttribute(XStr("Name").unicodeForm())).c_str();
1085
if (!sFilter || Name.find(sFilter) != std::string::npos) {
1087
DOMNode* pcElem2 = pcTemp->getFirstChild();
1089
vrValues.emplace_back(StrXUTF8(pcElem2->getNodeValue()).c_str());
1092
vrValues.emplace_back("");
1095
pcTemp = FindNextElement(pcTemp, "FCText");
1101
std::vector<std::pair<std::string, std::string>>
1102
ParameterGrp::GetASCIIMap(const char* sFilter) const
1104
std::vector<std::pair<std::string, std::string>> vrValues;
1111
DOMElement* pcTemp = FindElement(_pGroupNode, "FCText");
1113
Name = StrXUTF8(pcTemp->getAttribute(XStr("Name").unicodeForm())).c_str();
1115
if (!sFilter || Name.find(sFilter) != std::string::npos) {
1117
DOMNode* pcElem2 = pcTemp->getFirstChild();
1119
vrValues.emplace_back(Name, std::string(StrXUTF8(pcElem2->getNodeValue()).c_str()));
1122
vrValues.emplace_back(
1127
pcTemp = FindNextElement(pcTemp, "FCText");
1136
void ParameterGrp::RemoveASCII(const char* Name)
1143
DOMElement* pcElem = FindElement(_pGroupNode, "FCText", Name);
1149
DOMNode* node = _pGroupNode->removeChild(pcElem);
1153
_Notify(ParamType::FCText, Name, nullptr);
1157
void ParameterGrp::RemoveBool(const char* Name)
1164
DOMElement* pcElem = FindElement(_pGroupNode, "FCBool", Name);
1170
DOMNode* node = _pGroupNode->removeChild(pcElem);
1174
_Notify(ParamType::FCBool, Name, nullptr);
1179
void ParameterGrp::RemoveFloat(const char* Name)
1186
DOMElement* pcElem = FindElement(_pGroupNode, "FCFloat", Name);
1192
DOMNode* node = _pGroupNode->removeChild(pcElem);
1196
_Notify(ParamType::FCFloat, Name, nullptr);
1200
void ParameterGrp::RemoveInt(const char* Name)
1207
DOMElement* pcElem = FindElement(_pGroupNode, "FCInt", Name);
1213
DOMNode* node = _pGroupNode->removeChild(pcElem);
1217
_Notify(ParamType::FCInt, Name, nullptr);
1221
void ParameterGrp::RemoveUnsigned(const char* Name)
1228
DOMElement* pcElem = FindElement(_pGroupNode, "FCUInt", Name);
1234
DOMNode* node = _pGroupNode->removeChild(pcElem);
1238
_Notify(ParamType::FCUInt, Name, nullptr);
1242
void ParameterGrp::RemoveGrp(const char* Name)
1248
auto it = _GroupMap.find(Name);
1249
if (it == _GroupMap.end()) {
1258
it->second->Clear(false);
1259
if (!it->second->_Detached) {
1260
it->second->_Detached = true;
1261
_pGroupNode->removeChild(it->second->_pGroupNode);
1263
if (it->second->ShouldRemove()) {
1264
it->second->_Parent = nullptr;
1265
it->second->_Manager = nullptr;
1266
_GroupMap.erase(it);
1273
bool ParameterGrp::RenameGrp(const char* OldName, const char* NewName)
1279
auto it = _GroupMap.find(OldName);
1280
if (it == _GroupMap.end()) {
1283
auto jt = _GroupMap.find(NewName);
1284
if (jt != _GroupMap.end()) {
1289
_GroupMap[NewName] = _GroupMap[OldName];
1290
_GroupMap.erase(OldName);
1291
_GroupMap[NewName]->_cName = NewName;
1294
DOMElement* pcElem = FindElement(_pGroupNode, "FCParamGroup", OldName);
1296
pcElem->setAttribute(XStr("Name").unicodeForm(), XStr(NewName).unicodeForm());
1299
_Notify(ParamType::FCGroup, NewName, OldName);
1303
void ParameterGrp::Clear(bool notify)
1309
Base::StateLocker guard(_Clearing);
1313
_Notify(ParamType::FCGroup, nullptr, nullptr);
1316
for (auto it = _GroupMap.begin(); it != _GroupMap.end();) {
1322
it->second->Clear(notify);
1323
if (!it->second->_Detached) {
1324
it->second->_Detached = true;
1325
_pGroupNode->removeChild(it->second->_pGroupNode);
1327
if (!it->second->ShouldRemove()) {
1331
it->second->_Parent = nullptr;
1332
it->second->_Manager = nullptr;
1333
it = _GroupMap.erase(it);
1338
std::vector<std::pair<ParamType, std::string>> params;
1339
for (DOMNode *child = _pGroupNode->getFirstChild(), *next = child; child != nullptr;
1341
next = next->getNextSibling();
1342
ParamType type = TypeValue(StrX(child->getNodeName()).c_str());
1343
if (type != ParamType::FCInvalid && type != ParamType::FCGroup) {
1344
params.emplace_back(type,
1345
StrX(child->getAttributes()
1346
->getNamedItem(XStr("Name").unicodeForm())
1350
DOMNode* node = _pGroupNode->removeChild(child);
1354
for (auto& v : params) {
1355
_Notify(v.first, v.second.c_str(), nullptr);
1357
Notify(v.second.c_str());
1368
bool ParameterGrp::ShouldRemove() const
1370
if (this->getRefCount() > 1) {
1374
return std::all_of(_GroupMap.cbegin(), _GroupMap.cend(), [](const auto& it) {
1375
return it.second->ShouldRemove();
1379
XERCES_CPP_NAMESPACE_QUALIFIER DOMElement*
1380
ParameterGrp::FindElement(XERCES_CPP_NAMESPACE_QUALIFIER DOMElement* Start,
1382
const char* Name) const
1384
if (XMLString::compareString(Start->getNodeName(), XStr("FCParamGroup").unicodeForm()) != 0
1385
&& XMLString::compareString(Start->getNodeName(), XStr("FCParameters").unicodeForm())
1387
Base::Console().Warning("FindElement: %s cannot have the element %s of type %s\n",
1388
StrX(Start->getNodeName()).c_str(),
1393
for (DOMNode* clChild = Start->getFirstChild(); clChild != nullptr;
1394
clChild = clChild->getNextSibling()) {
1395
if (clChild->getNodeType() == DOMNode::ELEMENT_NODE) {
1397
if (!strcmp(Type, StrX(clChild->getNodeName()).c_str())) {
1398
if (clChild->getAttributes()->getLength() > 0) {
1400
DOMNode* attr = FindAttribute(clChild, "Name");
1401
if (attr && !strcmp(Name, StrX(attr->getNodeValue()).c_str())) {
1402
return static_cast<DOMElement*>(clChild);
1406
return static_cast<DOMElement*>(clChild);
1415
XERCES_CPP_NAMESPACE_QUALIFIER DOMElement*
1416
ParameterGrp::FindNextElement(XERCES_CPP_NAMESPACE_QUALIFIER DOMNode* Prev, const char* Type) const
1418
DOMNode* clChild = Prev;
1423
while ((clChild = clChild->getNextSibling()) != nullptr) {
1424
if (clChild->getNodeType() == DOMNode::ELEMENT_NODE) {
1426
if (!strcmp(Type, StrX(clChild->getNodeName()).c_str())) {
1427
return static_cast<DOMElement*>(clChild);
1434
XERCES_CPP_NAMESPACE_QUALIFIER DOMElement*
1435
ParameterGrp::FindOrCreateElement(XERCES_CPP_NAMESPACE_QUALIFIER DOMElement* Start,
1440
DOMElement* pcElem = FindElement(Start, Type, Name);
1445
return CreateElement(Start, Type, Name);
1448
XERCES_CPP_NAMESPACE_QUALIFIER DOMNode*
1449
ParameterGrp::FindAttribute(XERCES_CPP_NAMESPACE_QUALIFIER DOMNode* Node, const char* Name) const
1451
DOMNamedNodeMap* attr = Node->getAttributes();
1453
return attr->getNamedItem(XStr(Name).unicodeForm());
1458
std::vector<std::pair<ParameterGrp::ParamType, std::string>>
1459
ParameterGrp::GetParameterNames(const char* sFilter) const
1461
std::vector<std::pair<ParameterGrp::ParamType, std::string>> res;
1468
for (DOMNode* clChild = _pGroupNode->getFirstChild(); clChild != nullptr;
1469
clChild = clChild->getNextSibling()) {
1470
if (clChild->getNodeType() == DOMNode::ELEMENT_NODE) {
1471
StrX type(clChild->getNodeName());
1472
ParamType Type = TypeValue(type.c_str());
1473
if (Type != ParamType::FCInvalid && Type != ParamType::FCGroup) {
1474
if (clChild->getAttributes()->getLength() > 0) {
1475
StrX name(clChild->getAttributes()
1476
->getNamedItem(XStr("Name").unicodeForm())
1478
if (!sFilter || strstr(name.c_str(), sFilter)) {
1479
res.emplace_back(Type, name.c_str());
1488
void ParameterGrp::NotifyAll()
1491
std::vector<std::pair<std::string, long>> IntMap = GetIntMap();
1492
for (const auto& it : IntMap) {
1493
Notify(it.first.c_str());
1497
std::vector<std::pair<std::string, bool>> BoolMap = GetBoolMap();
1498
for (const auto& it : BoolMap) {
1499
Notify(it.first.c_str());
1503
std::vector<std::pair<std::string, double>> FloatMap = GetFloatMap();
1504
for (const auto& it : FloatMap) {
1505
Notify(it.first.c_str());
1509
std::vector<std::pair<std::string, std::string>> StringMap = GetASCIIMap();
1510
for (const auto& it : StringMap) {
1511
Notify(it.first.c_str());
1515
std::vector<std::pair<std::string, unsigned long>> UIntMap = GetUnsignedMap();
1516
for (const auto& it : UIntMap) {
1517
Notify(it.first.c_str());
1521
void ParameterGrp::_Reset()
1523
_pGroupNode = nullptr;
1524
for (auto& v : _GroupMap) {
1533
ParameterSerializer::ParameterSerializer(const std::string& fn)
1537
ParameterSerializer::~ParameterSerializer() = default;
1539
void ParameterSerializer::SaveDocument(const ParameterManager& mgr)
1541
mgr.SaveDocument(filename.c_str());
1544
int ParameterSerializer::LoadDocument(ParameterManager& mgr)
1546
return mgr.LoadDocument(filename.c_str());
1549
bool ParameterSerializer::LoadOrCreateDocument(ParameterManager& mgr)
1551
return mgr.LoadOrCreateDocument(filename.c_str());
1559
static XercesDOMParser::ValSchemes gValScheme = XercesDOMParser::Val_Auto;
1566
ParameterManager::ParameterManager()
1614
gDoNamespaces = false;
1616
gSchemaFullChecking = false;
1619
gOutputEncoding = nullptr;
1620
gMyEOLSequence = nullptr;
1622
gSplitCdataSections = true;
1623
gDiscardDefaultContent = true;
1625
gFormatPrettyPrint = true;
1631
ParameterManager::~ParameterManager()
1635
delete paramSerializer;
1638
Base::Reference<ParameterManager> ParameterManager::Create()
1640
return {new ParameterManager()};
1643
void ParameterManager::Init()
1645
static bool Init = false;
1648
XMLPlatformUtils::Initialize();
1650
catch (const XMLException& toCatch) {
1651
#if defined(FC_OS_LINUX) || defined(FC_OS_CYGWIN)
1652
std::ostringstream err;
1654
std::stringstream err;
1656
char* pMsg = XMLString::transcode(toCatch.getMessage());
1657
err << "Error during Xerces-c Initialization.\n"
1658
<< " Exception message:" << pMsg;
1659
XMLString::release(&pMsg);
1660
throw XMLBaseException(err.str().c_str());
1666
void ParameterManager::Terminate()
1668
XMLTools::terminate();
1669
XMLPlatformUtils::Terminate();
1675
void ParameterManager::SetSerializer(ParameterSerializer* ps)
1677
if (paramSerializer != ps) {
1678
delete paramSerializer;
1680
paramSerializer = ps;
1683
bool ParameterManager::HasSerializer() const
1685
return (paramSerializer != nullptr);
1688
const std::string& ParameterManager::GetSerializeFileName() const
1690
static const std::string _dummy;
1691
return paramSerializer ? paramSerializer->GetFileName() : _dummy;
1694
int ParameterManager::LoadDocument()
1696
if (paramSerializer) {
1697
return paramSerializer->LoadDocument(*this);
1703
bool ParameterManager::LoadOrCreateDocument()
1705
if (paramSerializer) {
1706
return paramSerializer->LoadOrCreateDocument(*this);
1712
void ParameterManager::SaveDocument() const
1714
if (paramSerializer) {
1715
paramSerializer->SaveDocument(*this);
1722
bool ParameterManager::LoadOrCreateDocument(const char* sFileName)
1724
Base::FileInfo file(sFileName);
1725
if (file.exists()) {
1726
LoadDocument(sFileName);
1734
int ParameterManager::LoadDocument(const char* sFileName)
1736
Base::FileInfo file(sFileName);
1739
#if defined(FC_OS_WIN32)
1740
LocalFileInputSource inputSource(
1741
reinterpret_cast<const XMLCh*>(file.toStdWString().c_str()));
1743
LocalFileInputSource inputSource(XStr(file.filePath().c_str()).unicodeForm());
1745
return LoadDocument(inputSource);
1747
catch (const Base::Exception& e) {
1748
std::cerr << e.what() << std::endl;
1752
std::cerr << "An error occurred during parsing\n " << std::endl;
1757
int ParameterManager::LoadDocument(const XERCES_CPP_NAMESPACE_QUALIFIER InputSource& inputSource)
1764
XercesDOMParser* parser = new XercesDOMParser;
1765
parser->setValidationScheme(gValScheme);
1766
parser->setDoNamespaces(gDoNamespaces);
1767
parser->setDoSchema(gDoSchema);
1768
parser->setValidationSchemaFullChecking(gSchemaFullChecking);
1769
parser->setCreateEntityReferenceNodes(gDoCreate);
1771
DOMTreeErrorReporter* errReporter = new DOMTreeErrorReporter();
1772
parser->setErrorHandler(errReporter);
1778
bool errorsOccured = false;
1780
parser->parse(inputSource);
1783
catch (const XMLException& e) {
1784
std::cerr << "An error occurred during parsing\n Message: " << StrX(e.getMessage())
1786
errorsOccured = true;
1789
catch (const DOMException& e) {
1790
std::cerr << "A DOM error occurred during parsing\n DOMException code: " << e.code
1792
errorsOccured = true;
1796
std::cerr << "An error occurred during parsing\n " << std::endl;
1797
errorsOccured = true;
1800
if (errorsOccured) {
1806
_pDocument = parser->adoptDocument();
1811
throw XMLBaseException("Malformed Parameter document: Invalid document");
1814
DOMElement* rootElem = _pDocument->getDocumentElement();
1816
throw XMLBaseException("Malformed Parameter document: Root group not found");
1819
_pGroupNode = FindElement(rootElem, "FCParamGroup", "Root");
1822
throw XMLBaseException("Malformed Parameter document: Root group not found");
1828
void ParameterManager::SaveDocument(const char* sFileName) const
1830
Base::FileInfo file(sFileName);
1840
#if defined(FC_OS_WIN32)
1841
XMLFormatTarget* myFormTarget =
1842
new LocalFileFormatTarget(reinterpret_cast<const XMLCh*>(file.toStdWString().c_str()));
1844
XMLFormatTarget* myFormTarget = new LocalFileFormatTarget(file.filePath().c_str());
1846
SaveDocument(myFormTarget);
1847
delete myFormTarget;
1849
catch (XMLException& e) {
1850
std::cerr << "An error occurred during creation of output transcoder. Msg is:" << std::endl
1851
<< StrX(e.getMessage()) << std::endl;
1855
void ParameterManager::SaveDocument(XMLFormatTarget* pFormatTarget) const
1858
std::unique_ptr<DOMPrintFilter> myFilter;
1859
std::unique_ptr<DOMErrorHandler> myErrorHandler;
1863
XMLString::transcode("LS", tempStr, 99);
1864
DOMImplementation* impl = DOMImplementationRegistry::getDOMImplementation(tempStr);
1865
DOMLSSerializer* theSerializer =
1866
static_cast<DOMImplementationLS*>(impl)->createLSSerializer();
1869
theSerializer->setNewLine(gMyEOLSequence);
1876
DOMLSOutput* theOutput = static_cast<DOMImplementationLS*>(impl)->createLSOutput();
1877
theOutput->setEncoding(gOutputEncoding);
1880
myFilter = std::make_unique<DOMPrintFilter>(
1881
DOMNodeFilter::SHOW_ELEMENT | DOMNodeFilter::SHOW_ATTRIBUTE
1882
| DOMNodeFilter::SHOW_DOCUMENT_TYPE | DOMNodeFilter::SHOW_TEXT);
1883
theSerializer->setFilter(myFilter.get());
1887
myErrorHandler = std::make_unique<DOMPrintErrorHandler>();
1888
DOMConfiguration* config = theSerializer->getDomConfig();
1889
config->setParameter(XMLUni::fgDOMErrorHandler, myErrorHandler.get());
1892
if (config->canSetParameter(XMLUni::fgDOMWRTSplitCdataSections, gSplitCdataSections)) {
1893
config->setParameter(XMLUni::fgDOMWRTSplitCdataSections, gSplitCdataSections);
1896
if (config->canSetParameter(XMLUni::fgDOMWRTDiscardDefaultContent,
1897
gDiscardDefaultContent)) {
1898
config->setParameter(XMLUni::fgDOMWRTDiscardDefaultContent, gDiscardDefaultContent);
1901
if (config->canSetParameter(XMLUni::fgDOMWRTFormatPrettyPrint, gFormatPrettyPrint)) {
1902
config->setParameter(XMLUni::fgDOMWRTFormatPrettyPrint, gFormatPrettyPrint);
1905
theOutput->setByteStream(pFormatTarget);
1906
theSerializer->write(_pDocument, theOutput);
1908
theOutput->release();
1911
theSerializer->release();
1913
catch (XMLException& e) {
1914
std::cerr << "An error occurred during creation of output transcoder. Msg is:" << std::endl
1915
<< StrX(e.getMessage()) << std::endl;
1919
void ParameterManager::CreateDocument()
1922
DOMImplementation* impl =
1923
DOMImplementationRegistry::getDOMImplementation(XStr("Core").unicodeForm());
1925
_pDocument = impl->createDocument(nullptr,
1926
XStr("FCParameters").unicodeForm(),
1930
DOMElement* rootElem = _pDocument->getDocumentElement();
1931
_pGroupNode = _pDocument->createElement(XStr("FCParamGroup").unicodeForm());
1932
_pGroupNode->setAttribute(XStr("Name").unicodeForm(), XStr("Root").unicodeForm());
1933
rootElem->appendChild(_pGroupNode);
1936
void ParameterManager::CheckDocument() const
1950
MemBufFormatTarget myFormTarget;
1951
SaveDocument(&myFormTarget);
1955
MemBufInputSource xmlFile(myFormTarget.getRawBuffer(), myFormTarget.getLen(), "(memory)");
1959
std::string xsdStr(xmlSchemeString);
1960
MemBufInputSource xsdFile(reinterpret_cast<const XMLByte*>(xsdStr.c_str()),
1967
XercesDOMParser parser;
1968
Grammar* grammar = parser.loadGrammar(xsdFile, Grammar::SchemaGrammarType, true);
1970
Base::Console().Error("Grammar file cannot be loaded.\n");
1974
parser.setExternalNoNamespaceSchemaLocation("Parameter.xsd");
1977
parser.cacheGrammarFromParse(true);
1978
parser.setValidationScheme(XercesDOMParser::Val_Auto);
1979
parser.setDoNamespaces(true);
1980
parser.setDoSchema(true);
1982
DOMTreeErrorReporter errHandler;
1983
parser.setErrorHandler(&errHandler);
1984
parser.parse(xmlFile);
1986
if (parser.getErrorCount() > 0) {
1987
Base::Console().Error("Unexpected XML structure detected: %zu errors\n",
1988
parser.getErrorCount());
1991
catch (XMLException& e) {
1992
std::cerr << "An error occurred while checking document. Msg is:" << std::endl
1993
<< StrX(e.getMessage()) << std::endl;
2003
void DOMTreeErrorReporter::warning(const SAXParseException& )
2010
void DOMTreeErrorReporter::error(const SAXParseException& toCatch)
2013
std::cerr << "Error at file \"" << StrX(toCatch.getSystemId()) << "\", line "
2014
<< toCatch.getLineNumber() << ", column " << toCatch.getColumnNumber()
2015
<< "\n Message: " << StrX(toCatch.getMessage()) << std::endl;
2018
void DOMTreeErrorReporter::fatalError(const SAXParseException& toCatch)
2021
std::cerr << "Fatal Error at file \"" << StrX(toCatch.getSystemId()) << "\", line "
2022
<< toCatch.getLineNumber() << ", column " << toCatch.getColumnNumber()
2023
<< "\n Message: " << StrX(toCatch.getMessage()) << std::endl;
2026
void DOMTreeErrorReporter::resetErrors()
2036
DOMPrintFilter::DOMPrintFilter(ShowType whatToShow)
2037
: fWhatToShow(whatToShow)
2040
DOMPrintFilter::FilterAction DOMPrintFilter::acceptNode(const DOMNode* node) const
2042
if (XMLString::compareString(node->getNodeName(), XStr("FCParameters").unicodeForm()) == 0) {
2045
const DOMNodeList* children = node->getChildNodes();
2046
for (XMLSize_t i = 0; i < children->getLength(); i++) {
2047
DOMNode* child = children->item(i);
2048
if (child->getNodeType() == DOMNode::TEXT_NODE) {
2049
child->setNodeValue(XStr("\n").unicodeForm());
2054
switch (node->getNodeType()) {
2055
case DOMNode::TEXT_NODE: {
2059
auto parent = node->getParentNode();
2061
&& XMLString::compareString(parent->getNodeName(),
2062
XStr("FCParamGroup").unicodeForm())
2064
return DOMNodeFilter::FILTER_REJECT;
2066
return DOMNodeFilter::FILTER_ACCEPT;
2068
case DOMNode::DOCUMENT_TYPE_NODE:
2069
case DOMNode::DOCUMENT_NODE: {
2070
return DOMNodeFilter::FILTER_REJECT;
2073
return DOMNodeFilter::FILTER_ACCEPT;
2084
bool DOMPrintErrorHandler::handleError(const DOMError& domError)
2087
char* msg = XMLString::transcode(domError.getMessage());
2088
std::cout << msg << std::endl;
2089
XMLString::release(&msg);