1
0
mirror of https://github.com/bdring/Grbl_Esp32.git synced 2025-09-02 10:53:01 +02:00

clang-format Configuration/

This commit is contained in:
Mitch Bradley
2021-05-20 10:02:42 -10:00
parent 596510965f
commit ab61f96012
18 changed files with 255 additions and 339 deletions

View File

@@ -4,8 +4,7 @@
#include <cstring> #include <cstring>
namespace Configuration namespace Configuration {
{
void AfterParse::handleDetail(const char* name, Configurable* value) { void AfterParse::handleDetail(const char* name, Configurable* value) {
value->afterParse(); value->afterParse();
value->handle(*this); value->handle(*this);

View File

@@ -5,28 +5,26 @@
#include "../Pin.h" #include "../Pin.h"
#include "HandlerBase.h" #include "HandlerBase.h"
namespace Configuration namespace Configuration {
{
class Configurable; class Configurable;
class AfterParse : public HandlerBase class AfterParse : public HandlerBase {
{
AfterParse(const AfterParse&) = delete; AfterParse(const AfterParse&) = delete;
AfterParse& operator=(const AfterParse&) = delete; AfterParse& operator=(const AfterParse&) = delete;
protected: protected:
void handleDetail(const char* name, Configurable* value) override; void handleDetail(const char* name, Configurable* value) override;
bool matchesUninitialized(const char* name) override { return false; } bool matchesUninitialized(const char* name) override { return false; }
HandlerType handlerType() override { return HandlerType::AfterParse; } HandlerType handlerType() override { return HandlerType::AfterParse; }
public: public:
AfterParse() = default; AfterParse() = default;
void handle(const char* name, bool& value) override { } void handle(const char* name, bool& value) override {}
void handle(const char* name, int& value) override { } void handle(const char* name, int& value) override {}
void handle(const char* name, float& value) override { } void handle(const char* name, float& value) override {}
void handle(const char* name, double& value) override { } void handle(const char* name, double& value) override {}
void handle(const char* name, StringRange& value) override { } void handle(const char* name, StringRange& value) override {}
void handle(const char* name, Pin& value) override { } void handle(const char* name, Pin& value) override {}
}; };
} }

View File

@@ -3,14 +3,12 @@
#include "Generator.h" #include "Generator.h"
#include "Parser.h" #include "Parser.h"
namespace Configuration namespace Configuration {
{
class HandlerBase; class HandlerBase;
class Configurable class Configurable {
{
Configurable(const Configurable&) = delete; Configurable(const Configurable&) = delete;
Configurable(Configurable&&) = default; Configurable(Configurable&&) = default;
Configurable& operator=(const Configurable&) = delete; Configurable& operator=(const Configurable&) = delete;
Configurable& operator=(Configurable&&) = default; Configurable& operator=(Configurable&&) = default;
@@ -18,7 +16,7 @@ namespace Configuration
public: public:
Configurable() = default; Configurable() = default;
virtual void validate() const = 0; virtual void validate() const = 0;
virtual void handle(HandlerBase& handler) = 0; virtual void handle(HandlerBase& handler) = 0;
virtual void afterParse() {} virtual void afterParse() {}
// virtual const char* name() const = 0; // virtual const char* name() const = 0;

View File

@@ -5,27 +5,21 @@
#include <cstring> #include <cstring>
#include <cstdio> #include <cstdio>
namespace Configuration namespace Configuration {
{ void Generator::enter(const char* name) {
void Generator::enter(const char* name)
{
indent(); indent();
dst_ << name << ":\n"; dst_ << name << ":\n";
indent_++; indent_++;
} }
void Generator::add(Configuration::Configurable* configurable) void Generator::add(Configuration::Configurable* configurable) {
{ if (configurable != nullptr) {
if (configurable != nullptr)
{
configurable->handle(*this); configurable->handle(*this);
} }
} }
void Generator::leave() void Generator::leave() {
{ if (!lastIsNewline_) {
if (!lastIsNewline_)
{
dst_ << '\n'; dst_ << '\n';
lastIsNewline_ = true; lastIsNewline_ = true;
} }
@@ -39,4 +33,4 @@ namespace Configuration
leave(); leave();
} }
} }

View File

@@ -7,23 +7,20 @@
#include "../StringStream.h" #include "../StringStream.h"
#include "HandlerBase.h" #include "HandlerBase.h"
namespace Configuration namespace Configuration {
{
class Configurable; class Configurable;
class Generator : public HandlerBase class Generator : public HandlerBase {
{
Generator(const Generator&) = delete; Generator(const Generator&) = delete;
Generator& operator=(const Generator&) = delete; Generator& operator=(const Generator&) = delete;
int indent_; int indent_;
SimpleOutputStream& dst_; SimpleOutputStream& dst_;
bool lastIsNewline_ = false; bool lastIsNewline_ = false;
inline void indent() { inline void indent() {
lastIsNewline_ = false; lastIsNewline_ = false;
for (int i = 0; i < indent_ * 2; ++i) for (int i = 0; i < indent_ * 2; ++i) {
{
dst_ << ' '; dst_ << ' ';
} }
} }
@@ -31,10 +28,10 @@ namespace Configuration
void enter(const char* name); void enter(const char* name);
void add(Configuration::Configurable* configurable); void add(Configuration::Configurable* configurable);
void leave(); void leave();
protected: protected:
void handleDetail(const char* name, Configurable* value) override; void handleDetail(const char* name, Configurable* value) override;
bool matchesUninitialized(const char* name) override { return false; } bool matchesUninitialized(const char* name) override { return false; }
HandlerType handlerType() override { return HandlerType::Generator; } HandlerType handlerType() override { return HandlerType::Generator; }
public: public:

View File

@@ -6,8 +6,7 @@
namespace Configuration { namespace Configuration {
template <typename BaseType> template <typename BaseType>
class GenericFactory class GenericFactory {
{
static GenericFactory& instance() { static GenericFactory& instance() {
static GenericFactory instance_; static GenericFactory instance_;
return instance_; return instance_;
@@ -28,37 +27,26 @@ namespace Configuration {
BuilderBase& operator=(const BuilderBase& o) = delete; BuilderBase& operator=(const BuilderBase& o) = delete;
virtual BaseType* create() const = 0; virtual BaseType* create() const = 0;
const char* name() const { return name_; } const char* name() const { return name_; }
virtual ~BuilderBase() = default; virtual ~BuilderBase() = default;
}; };
std::vector<BuilderBase*> builders_; std::vector<BuilderBase*> builders_;
inline static void registerBuilder(BuilderBase* builder) inline static void registerBuilder(BuilderBase* builder) { instance().builders_.push_back(builder); }
{
instance().builders_.push_back(builder);
}
public: public:
template <typename DerivedType> template <typename DerivedType>
class InstanceBuilder : public BuilderBase class InstanceBuilder : public BuilderBase {
{
public: public:
InstanceBuilder(const char* name) : BuilderBase(name) { InstanceBuilder(const char* name) : BuilderBase(name) { instance().registerBuilder(this); }
instance().registerBuilder(this);
}
BaseType* create() const override BaseType* create() const override { return new DerivedType(); }
{
return new DerivedType();
}
}; };
static void handle(Configuration::HandlerBase& handler, BaseType*& inst) static void handle(Configuration::HandlerBase& handler, BaseType*& inst) {
{ if (inst == nullptr) {
if (inst == nullptr)
{
for (auto it : instance().builders_) { for (auto it : instance().builders_) {
if (handler.matchesUninitialized(it->name())) { if (handler.matchesUninitialized(it->name())) {
inst = it->create(); inst = it->create();
@@ -67,11 +55,9 @@ namespace Configuration {
return; return;
} }
} }
} } else {
else
{
handler.handleDetail(inst->name(), inst); handler.handleDetail(inst->name(), inst);
} }
} }
}; };
} }

View File

@@ -4,36 +4,32 @@
#include "../Pin.h" #include "../Pin.h"
#include "../StringRange.h" #include "../StringRange.h"
namespace Configuration namespace Configuration {
{
class Configurable; class Configurable;
template <typename BaseType> template <typename BaseType>
class GenericFactory; class GenericFactory;
class HandlerBase class HandlerBase {
{
protected: protected:
virtual void handleDetail(const char* name, Configurable* value) = 0; virtual void handleDetail(const char* name, Configurable* value) = 0;
virtual bool matchesUninitialized(const char* name) = 0; virtual bool matchesUninitialized(const char* name) = 0;
template <typename BaseType> template <typename BaseType>
friend class GenericFactory; friend class GenericFactory;
public: public:
virtual void handle(const char* name, bool& value) = 0; virtual void handle(const char* name, bool& value) = 0;
virtual void handle(const char* name, int& value) = 0; virtual void handle(const char* name, int& value) = 0;
virtual void handle(const char* name, double& value) = 0; virtual void handle(const char* name, double& value) = 0;
virtual void handle(const char* name, float& value) = 0; virtual void handle(const char* name, float& value) = 0;
virtual void handle(const char* name, StringRange& value) = 0; virtual void handle(const char* name, StringRange& value) = 0;
virtual void handle(const char* name, Pin& value) = 0; virtual void handle(const char* name, Pin& value) = 0;
virtual void handle(const char* name, String& value) virtual void handle(const char* name, String& value) {
{
StringRange range; StringRange range;
handle(name, range); handle(name, range);
if (range.begin() != nullptr) if (range.begin() != nullptr) {
{
value = range.str(); value = range.str();
} }
} }
@@ -42,15 +38,12 @@ namespace Configuration
template <typename T> template <typename T>
void handle(const char* name, T*& value) { void handle(const char* name, T*& value) {
if (handlerType() == HandlerType::Parser) if (handlerType() == HandlerType::Parser) {
{ if (value == nullptr && matchesUninitialized(name)) {
if (value == nullptr && matchesUninitialized(name))
{
value = new T(); value = new T();
handleDetail(name, value); handleDetail(name, value);
} }
} } else {
else {
if (value != nullptr) { if (value != nullptr) {
handleDetail(name, value); handleDetail(name, value);
} }
@@ -58,6 +51,8 @@ namespace Configuration
} }
template <typename T> template <typename T>
void handle(const char* name, T& value) { handleDetail(name, &value); } void handle(const char* name, T& value) {
handleDetail(name, &value);
}
}; };
} }

View File

@@ -1,13 +1,5 @@
#pragma once #pragma once
namespace Configuration namespace Configuration {
{ enum struct HandlerType { Parser, AfterParse, Runtime, Generator, Validator };
enum struct HandlerType
{
Parser,
AfterParse,
Runtime,
Generator,
Validator
};
} }

View File

@@ -2,24 +2,20 @@
#include "LegacySettingRegistry.h" #include "LegacySettingRegistry.h"
namespace Configuration namespace Configuration {
{ class LegacySettingHandler {
class LegacySettingHandler
{
public: public:
inline LegacySettingHandler() { inline LegacySettingHandler() { LegacySettingRegistry::registerHandler(this); }
LegacySettingRegistry::registerHandler(this);
}
LegacySettingHandler(const LegacySettingHandler&) = delete; LegacySettingHandler(const LegacySettingHandler&) = delete;
LegacySettingHandler(LegacySettingHandler&&) = delete; LegacySettingHandler(LegacySettingHandler&&) = delete;
LegacySettingHandler& operator=(const LegacySettingHandler&) = delete; LegacySettingHandler& operator=(const LegacySettingHandler&) = delete;
LegacySettingHandler& operator=(LegacySettingHandler&&) = delete; LegacySettingHandler& operator=(LegacySettingHandler&&) = delete;
virtual int index() = 0; virtual int index() = 0;
virtual void handle(const char* value) = 0; virtual void handle(const char* value) = 0;
virtual ~LegacySettingHandler() { virtual ~LegacySettingHandler() {
// Remove from factory? We shouldn't remove handlers... // Remove from factory? We shouldn't remove handlers...
} }
}; };
} }

View File

@@ -2,17 +2,10 @@
#include "LegacySettingHandler.h" #include "LegacySettingHandler.h"
namespace Configuration namespace Configuration {
{ bool LegacySettingRegistry::isLegacySetting(const char* str) { return str[0] == '$' && (str[1] >= '0' && str[1] <= '9'); }
bool LegacySettingRegistry::isLegacySetting(const char* str)
{
return str[0] == '$' && (str[1] >= '0' && str[1] <= '9');
}
void LegacySettingRegistry::registerHandler(LegacySettingHandler* handler) void LegacySettingRegistry::registerHandler(LegacySettingHandler* handler) { instance().handlers_.push_back(handler); }
{
instance().handlers_.push_back(handler);
}
bool LegacySettingRegistry::tryHandleLegacy(const char* str) { bool LegacySettingRegistry::tryHandleLegacy(const char* str) {
if (isLegacySetting(str)) { if (isLegacySetting(str)) {
@@ -21,8 +14,7 @@ namespace Configuration
int value = 0; int value = 0;
++str; ++str;
while (*str && *str >= '0' && *str <= '9') while (*str && *str >= '0' && *str <= '9') {
{
value = value * 10 + (*str - '0'); value = value * 10 + (*str - '0');
++str; ++str;
} }
@@ -31,13 +23,11 @@ namespace Configuration
++str; ++str;
handleLegacy(value, str); handleLegacy(value, str);
} } else {
else {
log_warn("Incorrect setting '" << start << "': cannot find '='."); log_warn("Incorrect setting '" << start << "': cannot find '='.");
} }
return true; return true;
} } else {
else {
return false; return false;
} }
} }
@@ -45,8 +35,7 @@ namespace Configuration
void LegacySettingRegistry::handleLegacy(int index, const char* value) { void LegacySettingRegistry::handleLegacy(int index, const char* value) {
bool handled = false; bool handled = false;
for (auto it : instance().handlers_) { for (auto it : instance().handlers_) {
if (it->index() == index) if (it->index() == index) {
{
handled = true; handled = true;
it->handle(value); it->handle(value);
} }

View File

@@ -6,8 +6,7 @@
namespace Configuration { namespace Configuration {
class LegacySettingHandler; class LegacySettingHandler;
class LegacySettingRegistry class LegacySettingRegistry {
{
static LegacySettingRegistry& instance() { static LegacySettingRegistry& instance() {
static LegacySettingRegistry instance_; static LegacySettingRegistry instance_;
return instance_; return instance_;

View File

@@ -17,8 +17,7 @@ namespace Configuration {
// Attempt to use the correct position in the parser: // Attempt to use the correct position in the parser:
if (current_.keyEnd_) { if (current_.keyEnd_) {
throw ParseException(start_, current_.keyEnd_, description); throw ParseException(start_, current_.keyEnd_, description);
} } else {
else {
Tokenizer::ParseError(description); Tokenizer::ParseError(description);
} }
} }
@@ -73,7 +72,7 @@ namespace Configuration {
// At this point, we just know the indent is smaller. We don't know if we're in // At this point, we just know the indent is smaller. We don't know if we're in
// the *right* section tho. // the *right* section tho.
auto last = indentStack_.top(); auto last = indentStack_.top();
indent_ = last; indent_ = last;
indentStack_.pop(); indentStack_.pop();
if (last == token_.indent_) { if (last == token_.indent_) {
@@ -92,21 +91,21 @@ namespace Configuration {
} }
return StringRange(current_.sValueStart_, current_.sValueEnd_); return StringRange(current_.sValueStart_, current_.sValueEnd_);
} }
bool Parser::boolValue() const { bool Parser::boolValue() const {
if (current_.kind_ != TokenKind::Boolean) { if (current_.kind_ != TokenKind::Boolean) {
parseError("Expected a boolean value (e.g. true or value)"); parseError("Expected a boolean value (e.g. true or value)");
} }
return current_.bValue_; return current_.bValue_;
} }
int Parser::intValue() const { int Parser::intValue() const {
if (current_.kind_ != TokenKind::IntegerValue) { if (current_.kind_ != TokenKind::IntegerValue) {
parseError("Expected an integer value (e.g. 123456)"); parseError("Expected an integer value (e.g. 123456)");
} }
return current_.iValue_; return current_.iValue_;
} }
double Parser::doubleValue() const { double Parser::doubleValue() const {
if (current_.kind_ != TokenKind::FloatingPoint) { if (current_.kind_ != TokenKind::FloatingPoint) {
parseError("Expected a float value (e.g. 123.456)"); parseError("Expected a float value (e.g. 123.456)");
@@ -114,8 +113,7 @@ namespace Configuration {
return current_.fValue_; return current_.fValue_;
} }
Pin Parser::pinValue() const Pin Parser::pinValue() const {
{
if (current_.kind_ != TokenKind::String) { if (current_.kind_ != TokenKind::String) {
parseError("Expected a string value (e.g. 'foo')"); parseError("Expected a string value (e.g. 'foo')");
} }

View File

@@ -15,7 +15,7 @@ namespace Configuration {
std::stack<int> indentStack_; std::stack<int> indentStack_;
TokenData current_; TokenData current_;
int indent_ = 0; int indent_ = 0;
void parseError(const char* description) const; void parseError(const char* description) const;
@@ -39,16 +39,15 @@ namespace Configuration {
void leave(); void leave();
inline bool is(const char* expected) const { inline bool is(const char* expected) const {
return current_.keyStart_ != nullptr && return current_.keyStart_ != nullptr && !strncmp(expected, current_.keyStart_, size_t(current_.keyEnd_ - current_.keyStart_));
!strncmp(expected, current_.keyStart_, size_t(current_.keyEnd_ - current_.keyStart_));
} }
inline StringRange key() const { return StringRange(current_.keyStart_, current_.keyEnd_); } inline StringRange key() const { return StringRange(current_.keyStart_, current_.keyEnd_); }
StringRange stringValue() const; StringRange stringValue() const;
bool boolValue() const; bool boolValue() const;
int intValue() const; int intValue() const;
double doubleValue() const; double doubleValue() const;
Pin pinValue() const; Pin pinValue() const;
}; };
} }

View File

@@ -2,20 +2,15 @@
#include <cstdlib> #include <cstdlib>
namespace Configuration namespace Configuration {
{ void RuntimeSetting::handleDetail(const char* name, Configuration::Configurable* value) {
void RuntimeSetting::handleDetail(const char* name, Configuration::Configurable* value) if (is(name) && this->value() == nullptr) {
{
if (is(name) && this->value() == nullptr)
{
auto previous = start_; auto previous = start_;
// Figure out next node // Figure out next node
auto next = start_; auto next = start_;
for (; *next && *next != '=' && *next != '/'; ++next) for (; *next && *next != '=' && *next != '/'; ++next) {}
{
}
// Do we have a child? // Do we have a child?
if (*next == '/') { if (*next == '/') {
++next; ++next;
@@ -30,35 +25,27 @@ namespace Configuration
} }
} }
void RuntimeSetting::handle(const char* name, int& value) void RuntimeSetting::handle(const char* name, int& value) {
{ if (is(name) && this->value() != nullptr) {
if (is(name) && this->value() != nullptr)
{
value = atoi(this->value()); value = atoi(this->value());
} }
} }
void RuntimeSetting::handle(const char* name, double& value) void RuntimeSetting::handle(const char* name, double& value) {
{ if (is(name) && this->value() != nullptr) {
if (is(name) && this->value() != nullptr)
{
char* floatEnd; char* floatEnd;
value = strtod(this->value(), &floatEnd); value = strtod(this->value(), &floatEnd);
} }
} }
void RuntimeSetting::handle(const char* name, StringRange& value) void RuntimeSetting::handle(const char* name, StringRange& value) {
{ if (is(name) && this->value() != nullptr) {
if (is(name) && this->value() != nullptr)
{
value = this->value(); value = this->value();
} }
} }
void RuntimeSetting::handle(const char* name, Pin& value) void RuntimeSetting::handle(const char* name, Pin& value) {
{ if (is(name) && this->value() != nullptr) {
if (is(name) && this->value() != nullptr)
{
value = Pin::create(StringRange(this->value())); value = Pin::create(StringRange(this->value()));
} }
} }

View File

@@ -3,30 +3,28 @@
#include "HandlerBase.h" #include "HandlerBase.h"
#include "Configurable.h" #include "Configurable.h"
namespace Configuration namespace Configuration {
{ class RuntimeSetting : public Configuration::HandlerBase {
class RuntimeSetting : public Configuration::HandlerBase
{
private: private:
const char* setting_; // $foo/bar=12 const char* setting_; // $foo/bar=12
const char* start_; const char* start_;
bool is(const char* name) const { bool is(const char* name) const {
if (start_ != nullptr) { if (start_ != nullptr) {
auto len = strlen(name); auto len = strlen(name);
return !strncmp(name, start_, len) && (start_[len] == '=' || start_[len] == '/'); return !strncmp(name, start_, len) && (start_[len] == '=' || start_[len] == '/');
} } else {
else {
return false; return false;
} }
} }
const char* value() const const char* value() const {
{ for (const char* it = start_; *it; ++it) {
for (const char* it = start_; *it; ++it) if (*it == '/') {
{ return nullptr;
if (*it == '/') { return nullptr; } } else if (*it == '=') {
else if (*it == '=') { return it + 1; } return it + 1;
}
} }
return nullptr; return nullptr;
} }
@@ -37,7 +35,7 @@ namespace Configuration
bool matchesUninitialized(const char* name) override { return false; } bool matchesUninitialized(const char* name) override { return false; }
public: public:
RuntimeSetting(const char* runtimeSetting) : setting_(runtimeSetting + 1), start_(runtimeSetting+1) {} RuntimeSetting(const char* runtimeSetting) : setting_(runtimeSetting + 1), start_(runtimeSetting + 1) {}
void handle(const char* name, int& value) override; void handle(const char* name, int& value) override;
void handle(const char* name, double& value) override; void handle(const char* name, double& value) override;

View File

@@ -6,7 +6,7 @@
namespace Configuration { namespace Configuration {
Tokenizer::Tokenizer(const char* start, const char* end) : current_(start), end_(end), start_(start), token_() { Tokenizer::Tokenizer(const char* start, const char* end) : current_(start), end_(end), start_(start), token_() {
// If start is a yaml document start ('---' [newline]), skip that first. // If start is a yaml document start ('---' [newline]), skip that first.
if (EqualsCaseInsensitive("---")) { if (EqualsCaseInsensitive("---")) {
for (int i = 0; i < 3; ++i) { for (int i = 0; i < 3; ++i) {
@@ -39,164 +39,158 @@ namespace Configuration {
if (!Eof()) { if (!Eof()) {
switch (Current()) { switch (Current()) {
case '\t': case '\t':
// TODO FIXME: We can do tabs or spaces, not both. However, we *could* let the user decide. // TODO FIXME: We can do tabs or spaces, not both. However, we *could* let the user decide.
ParseError("Indentation through tabs is not allowed. Convert all tabs to spaces please."); ParseError("Indentation through tabs is not allowed. Convert all tabs to spaces please.");
break; break;
case '#': // Comment till end of line case '#': // Comment till end of line
Inc();
while (!Eof() && !IsEndLine()) {
Inc(); Inc();
} while (!Eof() && !IsEndLine()) {
return; Inc();
}
case '\r': return;
case '\n':
Inc();
if (!Eof() && Current() == '\n') {
Inc();
} // \r\n
goto parseAgain;
default:
if (!IsAlpha()) {
ParseError("Expected identifier.");
}
token_.keyStart_ = current_;
Inc();
while (!Eof() && (IsAlpha() || IsDigit() || Current() == '_')) {
Inc();
}
token_.keyEnd_ = current_;
// Skip whitespaces:
while (!Eof() && IsWhiteSpace()) {
Inc();
}
if (Current() != ':') {
ParseError("After a key or section name, we expect a colon character ':'.");
}
Inc();
// Skip whitespaces after the colon:
while (!Eof() && IsWhiteSpace()) {
Inc();
}
token_.indent_ = indent;
if (IsEndLine()) {
token_.kind_ = TokenKind::Section;
case '\r':
case '\n':
Inc(); Inc();
if (!Eof() && Current() == '\n') { if (!Eof() && Current() == '\n') {
Inc(); Inc();
} // \r\n } // \r\n
} goto parseAgain;
else {
switch (Current()) {
case '"':
case '\'': {
auto delimiter = Current();
token_.kind_ = TokenKind::String; default:
Inc(); if (!IsAlpha()) {
token_.sValueStart_ = current_; ParseError("Expected identifier.");
while (!Eof() && Current() != delimiter && !IsEndLine()) {
Inc();
}
token_.sValueEnd_ = current_;
if (Current() != delimiter) {
ParseError("Could not find matching delimiter in string value.");
}
Inc();
} break;
default:
if (EqualsCaseInsensitive("true")) {
token_.kind_ = TokenKind::Boolean;
token_.bValue_ = true;
for (auto i = 0; i < 4; ++i) {
Inc();
}
}
else if (EqualsCaseInsensitive("false")) {
token_.kind_ = TokenKind::Boolean;
token_.bValue_ = false;
for (auto i = 0; i < 5; ++i) {
Inc();
}
}
else if (IsDigit() || Current() == '-') {
auto doubleOrIntStart = current_;
int intValue = 0;
bool negative = false;
if (Current() == '-') {
Inc();
negative = true;
}
while (IsDigit()) {
intValue = intValue * 10 + int(Current() - '0');
Inc();
}
if (Current() == 'e' || Current() == 'E' || Current() == '.' || // markers
(current_ - doubleOrIntStart) >= 9) { // liberal interpretation of 'out of int range'
char* floatEnd;
token_.fValue_ = strtod(doubleOrIntStart, &floatEnd);
token_.kind_ = TokenKind::FloatingPoint;
current_ = floatEnd;
}
else {
if (negative) {
intValue = -intValue;
}
token_.iValue_ = intValue;
token_.kind_ = TokenKind::IntegerValue;
}
}
else {
// If it's not 'true', not 'false', and not a digit, we have a string delimited by a whitespace
token_.kind_ = TokenKind::String;
token_.sValueStart_ = current_;
while (!Eof() && !IsWhiteSpace() && !IsEndLine()) {
Inc();
}
token_.sValueEnd_ = current_;
}
break;
} }
// Skip more whitespaces token_.keyStart_ = current_;
Inc();
while (!Eof() && (IsAlpha() || IsDigit() || Current() == '_')) {
Inc();
}
token_.keyEnd_ = current_;
// Skip whitespaces:
while (!Eof() && IsWhiteSpace()) { while (!Eof() && IsWhiteSpace()) {
Inc(); Inc();
} }
// A comment after a key-value pair is allowed. if (Current() != ':') {
if (Current() == '#') { ParseError("After a key or section name, we expect a colon character ':'.");
}
Inc();
// Skip whitespaces after the colon:
while (!Eof() && IsWhiteSpace()) {
Inc(); Inc();
while (!Eof() && !IsEndLine()) {
Inc();
}
} }
// Should be EOL or EOF at this point. token_.indent_ = indent;
if (!IsEndLine() && !Eof()) { if (IsEndLine()) {
ParseError("Expected line end after key/value pair."); token_.kind_ = TokenKind::Section;
Inc();
if (!Eof() && Current() == '\n') {
Inc();
} // \r\n
} else {
switch (Current()) {
case '"':
case '\'': {
auto delimiter = Current();
token_.kind_ = TokenKind::String;
Inc();
token_.sValueStart_ = current_;
while (!Eof() && Current() != delimiter && !IsEndLine()) {
Inc();
}
token_.sValueEnd_ = current_;
if (Current() != delimiter) {
ParseError("Could not find matching delimiter in string value.");
}
Inc();
} break;
default:
if (EqualsCaseInsensitive("true")) {
token_.kind_ = TokenKind::Boolean;
token_.bValue_ = true;
for (auto i = 0; i < 4; ++i) {
Inc();
}
} else if (EqualsCaseInsensitive("false")) {
token_.kind_ = TokenKind::Boolean;
token_.bValue_ = false;
for (auto i = 0; i < 5; ++i) {
Inc();
}
} else if (IsDigit() || Current() == '-') {
auto doubleOrIntStart = current_;
int intValue = 0;
bool negative = false;
if (Current() == '-') {
Inc();
negative = true;
}
while (IsDigit()) {
intValue = intValue * 10 + int(Current() - '0');
Inc();
}
if (Current() == 'e' || Current() == 'E' || Current() == '.' || // markers
(current_ - doubleOrIntStart) >= 9) { // liberal interpretation of 'out of int range'
char* floatEnd;
token_.fValue_ = strtod(doubleOrIntStart, &floatEnd);
token_.kind_ = TokenKind::FloatingPoint;
current_ = floatEnd;
} else {
if (negative) {
intValue = -intValue;
}
token_.iValue_ = intValue;
token_.kind_ = TokenKind::IntegerValue;
}
} else {
// If it's not 'true', not 'false', and not a digit, we have a string delimited by a whitespace
token_.kind_ = TokenKind::String;
token_.sValueStart_ = current_;
while (!Eof() && !IsWhiteSpace() && !IsEndLine()) {
Inc();
}
token_.sValueEnd_ = current_;
}
break;
}
// Skip more whitespaces
while (!Eof() && IsWhiteSpace()) {
Inc();
}
// A comment after a key-value pair is allowed.
if (Current() == '#') {
Inc();
while (!Eof() && !IsEndLine()) {
Inc();
}
}
// Should be EOL or EOF at this point.
if (!IsEndLine() && !Eof()) {
ParseError("Expected line end after key/value pair.");
}
} }
}
} }
} } else {
else { token_.kind_ = TokenKind::Eof;
token_.kind_ = TokenKind::Eof;
token_.indent_ = 0; token_.indent_ = 0;
} }
} }

View File

@@ -4,10 +4,9 @@
#include <cstring> #include <cstring>
namespace Configuration namespace Configuration {
{
void Validator::handleDetail(const char* name, Configurable* value) { void Validator::handleDetail(const char* name, Configurable* value) {
value->validate(); value->validate();
value->handle(*this); value->handle(*this);
} }
} }

View File

@@ -5,28 +5,26 @@
#include "../Pin.h" #include "../Pin.h"
#include "HandlerBase.h" #include "HandlerBase.h"
namespace Configuration namespace Configuration {
{
class Configurable; class Configurable;
class Validator : public HandlerBase class Validator : public HandlerBase {
{
Validator(const Validator&) = delete; Validator(const Validator&) = delete;
Validator& operator=(const Validator&) = delete; Validator& operator=(const Validator&) = delete;
protected: protected:
void handleDetail(const char* name, Configurable* value) override; void handleDetail(const char* name, Configurable* value) override;
bool matchesUninitialized(const char* name) override { return false; } bool matchesUninitialized(const char* name) override { return false; }
HandlerType handlerType() override { return HandlerType::Validator; } HandlerType handlerType() override { return HandlerType::Validator; }
public: public:
Validator() = default; Validator() = default;
void handle(const char* name, bool& value) override { } void handle(const char* name, bool& value) override {}
void handle(const char* name, int& value) override { } void handle(const char* name, int& value) override {}
void handle(const char* name, float& value) override { } void handle(const char* name, float& value) override {}
void handle(const char* name, double& value) override { } void handle(const char* name, double& value) override {}
void handle(const char* name, StringRange& value) override { } void handle(const char* name, StringRange& value) override {}
void handle(const char* name, Pin& value) override { } void handle(const char* name, Pin& value) override {}
}; };
} }