mirror of https://gitee.com/bigwinds/arangodb
split header implementation (#8919)
This commit is contained in:
parent
9f09b2fb15
commit
257f036478
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue