From aee178901d8bd03f9e0aeb50e3a5ed7570d9f910 Mon Sep 17 00:00:00 2001 From: dec05eba Date: Thu, 11 Jan 2018 19:33:38 +0100 Subject: Start with config object types, for git dependencies --- include/Conf.hpp | 18 ++++++- project.conf | 1 + src/CmakeModule.cpp | 4 +- src/Conf.cpp | 98 +++++++++++++++++++++++++++++++++-- src/Exec.cpp | 2 +- tests/src/confTest/confTest.cpp | 11 ++++ tests/src/confTest/gitDependency.conf | 9 ++++ 7 files changed, 134 insertions(+), 9 deletions(-) create mode 100644 tests/src/confTest/gitDependency.conf diff --git a/include/Conf.hpp b/include/Conf.hpp index 0b97960..90f150a 100644 --- a/include/Conf.hpp +++ b/include/Conf.hpp @@ -21,7 +21,8 @@ namespace sibs { NONE, SINGLE, - LIST + LIST, + OBJECT }; ConfigValue() : type(Type::NONE) {} @@ -37,10 +38,18 @@ namespace sibs values(_values) { + } + + ConfigValue(const std::unordered_map &_map) : + type(Type::OBJECT), + map(_map) + { + } bool isSingle() const { return type == Type::SINGLE; } bool isList() const { return type == Type::LIST; } + bool isObject() const { return type == Type::OBJECT; } StringView asSingle() const { @@ -53,9 +62,16 @@ namespace sibs assert(isList()); return values; } + + const std::unordered_map& asObject() const + { + assert(isObject()); + return map; + } private: Type type; std::vector values; + std::unordered_map map; }; class Parser; diff --git a/project.conf b/project.conf index 2271dbe..029cb9e 100644 --- a/project.conf +++ b/project.conf @@ -10,3 +10,4 @@ ignore_dirs = ["cmake", "cmake-build-debug", "build"] [dependencies] libcurl = "7.57.0" libarchive = "3.3.2" +libgit2 = "0.26.0" diff --git a/src/CmakeModule.cpp b/src/CmakeModule.cpp index 8606a42..106f2c6 100644 --- a/src/CmakeModule.cpp +++ b/src/CmakeModule.cpp @@ -181,10 +181,10 @@ namespace sibs { string buildPathUtf8 = toUtf8(buildPath); nprintf("Searching for libraries generate by cmake in build path: %s\n", buildPathUtf8.c_str()); - walkDirFiles(buildPath.c_str(), + walkDirFilesRecursive(buildPath.c_str(), [&config, &staticLinkerFlagCallbackFunc, &dynamicLinkerFlagCallbackFunc](tinydir_file *file) { - if(_tinydir_strcmp(file->extension, CONFIG_DYNAMIC_LIB_FILE_EXTENSION) == 0) + if(_tinydir_strcmp(file->extension, CONFIG_DYNAMIC_LIB_FILE_EXTENSION) == 0 || _tinydir_strcmp(file->extension, CONFIG_STATIC_LIB_FILE_EXTENSION) == 0) { string libFileUtf8 = toUtf8(file->path); nprintf("Library generated by cmake: %s\n", libFileUtf8.c_str()); diff --git a/src/Conf.cpp b/src/Conf.cpp index e8af27a..93ec6e7 100644 --- a/src/Conf.cpp +++ b/src/Conf.cpp @@ -25,6 +25,8 @@ namespace sibs IDENTIFIER, OPEN_BRACKET, CLOSING_BRACKET, + OPEN_BRACE, + CLOSING_BRACE, EQUALS, STRING, COMMA @@ -39,6 +41,8 @@ namespace sibs case Token::IDENTIFIER: return "identifier"; case Token::OPEN_BRACKET: return "["; case Token::CLOSING_BRACKET: return "]"; + case Token::OPEN_BRACE: return "{"; + case Token::CLOSING_BRACE: return "}"; case Token::EQUALS: return "="; case Token::STRING: return "string"; case Token::COMMA: return ","; @@ -50,7 +54,6 @@ namespace sibs { public: Tokenizer(const char *_code) : - currentToken(Token::NONE), code((char*)_code) { @@ -90,6 +93,16 @@ namespace sibs ++code; return Token::CLOSING_BRACKET; } + else if(c == '{') + { + ++code; + return Token::OPEN_BRACE; + } + else if(c == '}') + { + ++code; + return Token::CLOSING_BRACE; + } else if(c == '=') { ++code; @@ -172,9 +185,7 @@ namespace sibs return isAlpha(c) || isDigit(c) || c == '_' || c == '-' || c == '.'; } private: - Token currentToken; u8string code; - union { StringView identifier; @@ -276,6 +287,10 @@ namespace sibs { parseConfigFieldRhsList(fieldName); } + else if(token == Token::OPEN_BRACE) + { + parseConfigFieldRhsObject(fieldName); + } else { string errMsg = "Expected string on right-hand side of field '"; @@ -288,14 +303,24 @@ namespace sibs void parseConfigFieldRhsList(const StringView &fieldName) { + vector values; Token token = tokenizer.nextToken(); - if (token == Token::CLOSING_BRACKET) return; + if (token == Token::CLOSING_BRACKET) + { + callback->processField(fieldName, values); + return; + } - vector values; while (true) { if (token == Token::STRING) values.push_back(tokenizer.getString()); + else + { + string errMsg = "Expected list to contain string, got: "; + errMsg += getTokenName(token); + throw ParserException(errMsg); + } token = tokenizer.nextToken(); if (token == Token::COMMA) @@ -317,6 +342,69 @@ namespace sibs callback->processField(fieldName, values); } + + void parseConfigFieldRhsObject(const StringView &fieldName) + { + unordered_map fields; + Token token = tokenizer.nextToken(); + if (token == Token::CLOSING_BRACE) + { + callback->processField(fieldName, fields); + return; + } + + while (true) + { + if (token == Token::IDENTIFIER) + { + StringView objectKey = tokenizer.getIdentifier(); + token = tokenizer.nextToken(); + if(token == Token::EQUALS) + { + token = tokenizer.nextToken(); + if (token == Token::STRING) + fields[string(objectKey.data, objectKey.size)] = tokenizer.getString(); + else + { + string errMsg = "Expected object field value to be a string, got: "; + errMsg += getTokenName(token); + throw ParserException(errMsg); + } + } + else + { + string errMsg = "Expected object key to be followed by '=', got: "; + errMsg += getTokenName(token); + throw ParserException(errMsg); + } + } + else + { + string errMsg = "Expected object to contain key, got: "; + errMsg += getTokenName(token); + throw ParserException(errMsg); + } + + token = tokenizer.nextToken(); + if (token == Token::COMMA) + { + token = tokenizer.nextToken(); + continue; + } + else if (token == Token::CLOSING_BRACE) + { + break; + } + else + { + string errMsg = "Expected object field to be followed by '}' or ',', got: "; + errMsg += getTokenName(token); + throw ParserException(errMsg); + } + } + + callback->processField(fieldName, fields); + } void parseConfigObject() { diff --git a/src/Exec.cpp b/src/Exec.cpp index e0ae306..2eac8bc 100644 --- a/src/Exec.cpp +++ b/src/Exec.cpp @@ -99,4 +99,4 @@ namespace sibs } } #endif -} \ No newline at end of file +} diff --git a/tests/src/confTest/confTest.cpp b/tests/src/confTest/confTest.cpp index f3d9e2b..d24c460 100644 --- a/tests/src/confTest/confTest.cpp +++ b/tests/src/confTest/confTest.cpp @@ -104,3 +104,14 @@ TEST_CASE("parse config - define dynamic") REQUIRE(sibsConfig.getDefinedValue("BUILD_STATIC") == "0"); REQUIRE(sibsConfig.getDefinedValue("DEFINE_TYPE") == "DYNAMIC"); } + +TEST_CASE("parse config - git dependency") +{ + SibsConfig sibsConfig(Compiler::GCC, TINYDIR_STRING("tests/src/confTest"), OPT_LEV_DEBUG, false); + Result result = Config::readFromFile(TINYDIR_STRING("tests/src/confTest/gitDependency.conf"), sibsConfig); + if(result.isErr()) + { + fprintf(stderr, "%s", result.getErrMsg().c_str()); + exit(1); + } +} diff --git a/tests/src/confTest/gitDependency.conf b/tests/src/confTest/gitDependency.conf new file mode 100644 index 0000000..d18b267 --- /dev/null +++ b/tests/src/confTest/gitDependency.conf @@ -0,0 +1,9 @@ +[package] +name = "confTest" +version = "0.1.0" +type = "library" +platforms = ["linux64", "win64"] + +[dependencies] +xxhash = { git = "https://github.com/DEC05EBA/xxHash.git", branch = "master" } +catch2 = "1.0.0" -- cgit v1.2.3