#include <config.h>
#include <algorithm>
#include <string>
#include <vector>
#include <xercesc/sax/HandlerBase.hpp>
#include <xercesc/sax/AttributeList.hpp>
#include <xercesc/sax/SAXParseException.hpp>
#include <xercesc/sax/SAXException.hpp>
#include <utils/common/StringUtils.h>
#include <utils/common/StringTokenizer.h>
#include <utils/common/UtilExceptions.h>
#include <utils/common/FileHelpers.h>
#include <utils/common/MsgHandler.h>
#include <utils/common/ToString.h>
#include "OptionsIO.h"
#include "OptionsCont.h"
#include "OptionsLoader.h"
OptionsLoader::OptionsLoader(OptionsCont& customOptions, const bool rootOnly) :
myRootOnly(rootOnly),
myOptions(customOptions),
myItem() {
}
OptionsLoader::~OptionsLoader() {}
void OptionsLoader::startElement(const XMLCh* const name, XERCES_CPP_NAMESPACE::AttributeList& attributes) {
myFoundValue = false;
myItem = StringUtils::transcode(name);
if (!myRootOnly) {
for (int i = 0; i < (int)attributes.getLength(); i++) {
const std::string& key = StringUtils::transcode(attributes.getName(i));
const std::string& value = StringUtils::transcode(attributes.getValue(i));
if (key == "value" || key == "v") {
setValue(myItem, value);
myFoundValue = true;
} else if (key != "xmlns:xsi"
&& key != "xsi:noNamespaceSchemaLocation"
&& key != "synonymes"
&& key != "deprecated"
&& key != "type"
&& key != "help"
&& (key != "version" && myItem != "net")) {
WRITE_WARNINGF(TL("Ignoring attribute '%' for option '%'"), key, myItem);
}
}
myValue = "";
}
}
void OptionsLoader::setValue(const std::string& key, const std::string& value) {
if (value.length() > 0) {
try {
if (!setSecure(myOptions, key, value)) {
WRITE_ERRORF(TL("Could not set option '%' (probably defined twice)."), key);
myError = true;
}
} catch (ProcessError& e) {
WRITE_ERROR(e.what());
myError = true;
}
}
}
void OptionsLoader::characters(const XMLCh* const chars, const XERCES3_SIZE_t length) {
myValue = myValue + StringUtils::transcode(chars, (int) length);
}
bool
OptionsLoader::setSecure(OptionsCont& options, const std::string& name, const std::string& value) const {
if (options.isWriteable(name)) {
options.set(name, value);
return true;
}
return false;
}
void
OptionsLoader::endElement(const XMLCh* const ) {
if (myItem.length() == 0 || myValue.length() == 0) {
if (!myFoundValue) {
WRITE_ERRORF(TL("Could not set option '%' because attribute 'value' is missing."), myItem);
}
return;
}
if (myValue.find_first_not_of("\n\t \a") == std::string::npos) {
return;
}
setValue(myItem, myValue);
myItem = "";
myValue = "";
}
void
OptionsLoader::warning(const XERCES_CPP_NAMESPACE::SAXParseException& exception) {
WRITE_WARNING(StringUtils::transcode(exception.getMessage()));
WRITE_WARNING(" (At line/column " \
+ toString(exception.getLineNumber() + 1) + '/' \
+ toString(exception.getColumnNumber()) + ").");
myError = true;
}
void
OptionsLoader::error(const XERCES_CPP_NAMESPACE::SAXParseException& exception) {
WRITE_ERROR(StringUtils::transcode(exception.getMessage()));
WRITE_ERROR(" (At line/column "
+ toString(exception.getLineNumber() + 1) + '/'
+ toString(exception.getColumnNumber()) + ").");
myError = true;
}
void
OptionsLoader::fatalError(const XERCES_CPP_NAMESPACE::SAXParseException& exception) {
WRITE_ERROR(StringUtils::transcode(exception.getMessage()));
WRITE_ERROR(" (At line/column "
+ toString(exception.getLineNumber() + 1) + '/'
+ toString(exception.getColumnNumber()) + ").");
myError = true;
}
bool
OptionsLoader::errorOccurred() const {
return myError;
}