1
0
Fork 0

split header implementation (#8919)

This commit is contained in:
Wilfried Goesgens 2019-05-07 13:43:19 +02:00 committed by Jan
parent 9f09b2fb15
commit 257f036478
5 changed files with 183 additions and 139 deletions

View File

@ -243,6 +243,7 @@ add_library(${LIB_ARANGO} STATIC
ProgramOptions/ProgramOptions.cpp
ProgramOptions/Section.cpp
ProgramOptions/Translator.cpp
ProgramOptions/IniFileParser.cpp
Random/RandomFeature.cpp
Random/RandomGenerator.cpp
Random/UniformCharacter.cpp

View File

@ -0,0 +1,174 @@
////////////////////////////////////////////////////////////////////////////////
/// DISCLAIMER
///
/// Copyright 2016 ArangoDB GmbH, Cologne, Germany
///
/// Licensed under the Apache License, Version 2.0 (the "License");
/// you may not use this file except in compliance with the License.
/// You may obtain a copy of the License at
///
/// http://www.apache.org/licenses/LICENSE-2.0
///
/// Unless required by applicable law or agreed to in writing, software
/// distributed under the License is distributed on an "AS IS" BASIS,
/// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/// See the License for the specific language governing permissions and
/// limitations under the License.
///
/// Copyright holder is ArangoDB GmbH, Cologne, Germany
///
/// @author Jan Steemann
////////////////////////////////////////////////////////////////////////////////
#include "Basics/Common.h"
#include "Basics/StringUtils.h"
#include "Basics/FileUtils.h"
#include "Logger/Logger.h"
#include <sstream>
#include <unicode/unistr.h>
#include "ProgramOptions/IniFileParser.h"
namespace arangodb {
namespace options {
IniFileParser::IniFileParser(ProgramOptions* options) : _options(options) {
// a line with just comments, e.g. #... or ;...
_matchers.comment =
std::regex("^[ \t]*([#;].*)?$", std::regex::nosubs | std::regex::ECMAScript);
// a line that starts a section, e.g. [server]
_matchers.section =
std::regex("^[ \t]*\\[([-_A-Za-z0-9]*)\\][ \t]*$", std::regex::ECMAScript);
// a line that starts a community section, e.g. [server:community]
_matchers.communitySection =
std::regex("^[ \t]*\\[([-_A-Za-z0-9]*):community\\][ \t]*$", std::regex::ECMAScript);
// a line that starts an enterprise section, e.g. [server:enterprise]
_matchers.enterpriseSection =
std::regex("^[ \t]*\\[([-_A-Za-z0-9]*):enterprise\\][ \t]*$", std::regex::ECMAScript);
// a line that assigns a value to a named variable
_matchers.assignment = std::regex(
"^[ \t]*(([-_A-Za-z0-9]*\\.)?[-_A-Za-z0-9]*)[ \t]*=[ \t]*(.*?)?[ \t]*$",
std::regex::ECMAScript);
// an include line
_matchers.include =
std::regex("^[ \t]*@include[ \t]*([-_A-Za-z0-9/\\.]*)[ \t]*$", std::regex::ECMAScript);
}
// parse a config file. returns true if all is well, false otherwise
// errors that occur during parse are reported to _options
bool IniFileParser::parse(std::string const& filename, bool endPassAfterwards) {
if (filename.empty()) {
return _options->fail(
"unable to open configuration file: no configuration file specified");
}
std::string buf;
try {
buf = arangodb::basics::FileUtils::slurp(filename);
} catch (arangodb::basics::Exception const& ex) {
return _options->fail(std::string("Couldn't open configuration file: '") +
filename + "' - " + ex.what());
return true;
}
bool isCommunity = false;
bool isEnterprise = false;
std::string currentSection;
size_t lineNumber = 0;
std::istringstream iss(buf);
for (std::string line; std::getline(iss, line);) {
basics::StringUtils::trimInPlace(line);
++lineNumber;
if (std::regex_match(line, _matchers.comment)) {
// skip over comments
continue;
}
// set context for parsing (used in error messages)
_options->setContext("config file '" + filename + "', line #" +
std::to_string(lineNumber));
std::smatch match;
if (std::regex_match(line, match, _matchers.section)) {
// found section
currentSection = match[1].str();
isCommunity = false;
isEnterprise = false;
} else if (std::regex_match(line, match, _matchers.communitySection)) {
// found section
currentSection = match[1].str();
isCommunity = true;
isEnterprise = false;
} else if (std::regex_match(line, match, _matchers.enterpriseSection)) {
// found section
currentSection = match[1].str();
isCommunity = false;
isEnterprise = true;
} else if (std::regex_match(line, match, _matchers.include)) {
// found include
std::string include(match[1].str());
if (!basics::StringUtils::isSuffix(include, ".conf")) {
include += ".conf";
}
if (_seen.find(include) != _seen.end()) {
LOG_TOPIC("cc815", FATAL, Logger::CONFIG)
<< "recursive include of file '" << include << "'";
FATAL_ERROR_EXIT();
}
_seen.insert(include);
if (!basics::FileUtils::isRegularFile(include)) {
auto dn = basics::FileUtils::dirname(filename);
include = basics::FileUtils::buildFilename(dn, include);
}
LOG_TOPIC("36d6b", DEBUG, Logger::CONFIG) << "reading include file '" << include << "'";
parse(include, false);
} else if (std::regex_match(line, match, _matchers.assignment)) {
// found assignment
std::string option;
std::string value(match[3].str());
if (currentSection.empty() || !match[2].str().empty()) {
// use option as specified
option = match[1].str();
} else {
// use option prefixed with current section
option = currentSection + "." + match[1].str();
}
#ifdef USE_ENTERPRISE
if (isCommunity) {
continue;
}
#else
if (isEnterprise) {
continue;
}
#endif
if (!_options->setValue(option, value)) {
return false;
}
} else {
// unknown type of line. cannot handle it
return _options->fail("unknown line type");
}
}
isCommunity ^= isEnterprise;
// all is well
if (endPassAfterwards) {
_options->endPass();
}
return true;
}
} // namespace options
} // namespace arangodb

View File

@ -23,12 +23,8 @@
#ifndef ARANGODB_PROGRAM_OPTIONS_INI_FILE_PARSER_H
#define ARANGODB_PROGRAM_OPTIONS_INI_FILE_PARSER_H 1
#include "Basics/FileUtils.h"
#include <regex>
#include <sstream>
#include <unicode/unistr.h>
#include "ProgramOptions/ProgramOptions.h"
namespace arangodb {
@ -36,141 +32,11 @@ namespace options {
class IniFileParser {
public:
explicit IniFileParser(ProgramOptions* options) : _options(options) {
// a line with just comments, e.g. #... or ;...
_matchers.comment =
std::regex("^[ \t]*([#;].*)?$", std::regex::nosubs | std::regex::ECMAScript);
// a line that starts a section, e.g. [server]
_matchers.section =
std::regex("^[ \t]*\\[([-_A-Za-z0-9]*)\\][ \t]*$", std::regex::ECMAScript);
// a line that starts a community section, e.g. [server:community]
_matchers.communitySection =
std::regex("^[ \t]*\\[([-_A-Za-z0-9]*):community\\][ \t]*$", std::regex::ECMAScript);
// a line that starts an enterprise section, e.g. [server:enterprise]
_matchers.enterpriseSection =
std::regex("^[ \t]*\\[([-_A-Za-z0-9]*):enterprise\\][ \t]*$", std::regex::ECMAScript);
// a line that assigns a value to a named variable
_matchers.assignment = std::regex(
"^[ \t]*(([-_A-Za-z0-9]*\\.)?[-_A-Za-z0-9]*)[ \t]*=[ \t]*(.*?)?[ \t]*$",
std::regex::ECMAScript);
// an include line
_matchers.include =
std::regex("^[ \t]*@include[ \t]*([-_A-Za-z0-9/\\.]*)[ \t]*$", std::regex::ECMAScript);
}
explicit IniFileParser(ProgramOptions* options);
// parse a config file. returns true if all is well, false otherwise
// errors that occur during parse are reported to _options
bool parse(std::string const& filename, bool endPassAfterwards) {
if (filename.empty()) {
return _options->fail(
"unable to open configuration file: no configuration file specified");
}
std::string buf;
try {
buf = arangodb::basics::FileUtils::slurp(filename);
} catch (arangodb::basics::Exception const& ex) {
return _options->fail(std::string("Couldn't open configuration file: '") +
filename + "' - " + ex.what());
return true;
}
bool isCommunity = false;
bool isEnterprise = false;
std::string currentSection;
size_t lineNumber = 0;
std::istringstream iss(buf);
for (std::string line; std::getline(iss, line);) {
basics::StringUtils::trimInPlace(line);
++lineNumber;
if (std::regex_match(line, _matchers.comment)) {
// skip over comments
continue;
}
// set context for parsing (used in error messages)
_options->setContext("config file '" + filename + "', line #" +
std::to_string(lineNumber));
std::smatch match;
if (std::regex_match(line, match, _matchers.section)) {
// found section
currentSection = match[1].str();
isCommunity = false;
isEnterprise = false;
} else if (std::regex_match(line, match, _matchers.communitySection)) {
// found section
currentSection = match[1].str();
isCommunity = true;
isEnterprise = false;
} else if (std::regex_match(line, match, _matchers.enterpriseSection)) {
// found section
currentSection = match[1].str();
isCommunity = false;
isEnterprise = true;
} else if (std::regex_match(line, match, _matchers.include)) {
// found include
std::string include(match[1].str());
if (!basics::StringUtils::isSuffix(include, ".conf")) {
include += ".conf";
}
if (_seen.find(include) != _seen.end()) {
LOG_TOPIC("cc815", FATAL, Logger::CONFIG)
<< "recursive include of file '" << include << "'";
FATAL_ERROR_EXIT();
}
_seen.insert(include);
if (!basics::FileUtils::isRegularFile(include)) {
auto dn = basics::FileUtils::dirname(filename);
include = basics::FileUtils::buildFilename(dn, include);
}
LOG_TOPIC("36d6b", DEBUG, Logger::CONFIG) << "reading include file '" << include << "'";
parse(include, false);
} else if (std::regex_match(line, match, _matchers.assignment)) {
// found assignment
std::string option;
std::string value(match[3].str());
if (currentSection.empty() || !match[2].str().empty()) {
// use option as specified
option = match[1].str();
} else {
// use option prefixed with current section
option = currentSection + "." + match[1].str();
}
#ifdef USE_ENTERPRISE
if (isCommunity) {
continue;
}
#else
if (isEnterprise) {
continue;
}
#endif
if (!_options->setValue(option, value)) {
return false;
}
} else {
// unknown type of line. cannot handle it
return _options->fail("unknown line type");
}
}
isCommunity ^= isEnterprise;
// all is well
if (endPassAfterwards) {
_options->endPass();
}
return true;
}
bool parse(std::string const& filename, bool endPassAfterwards);
private:
ProgramOptions* _options;

View File

@ -26,9 +26,10 @@
#include "Basics/Common.h"
#include "ProgramOptions/Parameters.h"
#include <velocypack/Builder.h>
namespace arangodb {
namespace velocypack {
class Builder;
}
namespace options {
/// @brief option flags. these can be bit-ORed to combine multiple flags

View File

@ -28,9 +28,11 @@
#include "ProgramOptions/Option.h"
#include "ProgramOptions/Section.h"
#include <velocypack/Builder.h>
namespace arangodb {
namespace velocypack {
class Builder;
}
namespace options {
// program options data structure