diff --git a/includes/ConfigParser.hpp b/includes/ConfigParser.hpp index 8ecac85..121115f 100644 --- a/includes/ConfigParser.hpp +++ b/includes/ConfigParser.hpp @@ -1,10 +1,11 @@ + // Copyright [2022] + #ifndef INCLUDES_CONFIGPARSER_HPP_ #define INCLUDES_CONFIGPARSER_HPP_ #include #include #include -#include "./HTTPmoduler.hpp" class ConfigParser { public : @@ -22,13 +23,17 @@ class ConfigParser { void parseMainContext(std::string& lines); void parseEventsBlock(std::string& lines); void parseHTTPBlock(std::string& lines); - void parseServerBlock(std::string& lines); - void showSizeDirectives(void); + void parseUpstreamBlock(std::string& lines); + void parseServerBlock(std::string& lines, + std::vector > >& a); + void test_map_data_print(void); const char *file_path_; - std::map mainDirectives; - std::map eventDirectives; - std::multimap httpDirectives; + std::map > mainDirectives; + std::map > eventDirectives; + std::map > httpDirectives; + std::map > upstreamDirectives; + std::vector > > serverBlocks; }; #endif // INCLUDES_CONFIGPARSER_HPP_ diff --git a/includes/testFunctions.hpp b/includes/testFunctions.hpp new file mode 100644 index 0000000..fb06d39 --- /dev/null +++ b/includes/testFunctions.hpp @@ -0,0 +1,22 @@ +#ifndef TESTFUNCTIONS_HPP +#define TESTFUNCTIONS_HPP + +#include +namespace test { + void showSizeDirectives(const std::map& m) { + std::cout << "size : " << m.size() << std::endl; + }; + void showParsedDirectives(std::map >& a) { + std::cout << "size : " << a.size() << std::endl; + for (std::map >::iterator it = a.begin(); it != a.end(); it++) { + std:: cout << it->first << " : [ "; + for (std::vector::iterator itv = it->second.begin(); itv != it->second.end(); itv++) { + std::cout << *itv << ", "; + } + std::cout << "]"<< std::endl; + } +}; + +} + +#endif // TESTFUNCTIONS_HPP \ No newline at end of file diff --git a/src/ConfigParser.cpp b/src/ConfigParser.cpp index afbacde..bc4cfe7 100644 --- a/src/ConfigParser.cpp +++ b/src/ConfigParser.cpp @@ -1,11 +1,12 @@ // Copyright [2022] -#include "../includes/ConfigParser.hpp" -#include "../includes/webserv.hpp" #include #include #include #include +#include "../includes/ConfigParser.hpp" +#include "../includes/testFunctions.hpp" +#include "../includes/webserv.hpp" #define space "\n\t " @@ -13,8 +14,7 @@ ConfigParser::ConfigParser() {} ConfigParser::ConfigParser(const char *file_path) { if (!*file_path) { file_path_ = DEFAULT_CONFIGFILE_PATH; - } - else { + } else { file_path_ = file_path; } } @@ -32,95 +32,83 @@ static void deleteComments(std::string& line) { } } -static bool isSpecialCharactersBlockKeyword(const char c) -{ - return (c == '~' || c == '^' || c == '/' || c == '(' || c == ')' || c == '_'); +static bool isSpecialCharactersBlockKeyword(const char c) { + return (c == '~' || c == '^' || c == '/' + || c == '(' || c == ')' || c == '_'); } -static std::string getConfigFileLines(std::ifstream& fs) -{ +static std::string getConfigFileLines(std::ifstream& fs) { std::string buf; std::string ret; - while (std::getline(fs, buf)) - { + while (std::getline(fs, buf)) { deleteComments(buf); ret += buf; } return ret; } -static bool isAllofBracketClosed(std::string& line) -{ +static bool isAllofBracketClosed(std::string& line) { std::stack bracket; - - if (line.find("{", 0) == STRING_NPOS) - return false; // needed throw exception needed http server config + if (line.find("{", 0) == STRING_NPOS) return false; // needed throw exception needed http server config for (std::string::iterator it = line.begin(); it != line.end(); it++) { - if (*it == '{') + if (*it == '{') { bracket.push(true); - else if (*it == '}') { - if (bracket.empty()) - return false; // throw exception unclosed bracket; + } else if (*it == '}') { + if (bracket.empty()) return false; // throw exception unclosed bracket; bracket.pop(); } } return bracket.empty() ? true : false; } -static size_t getLastBracketIndex(std::string& line) -{ +static size_t getLastBracketIndex(std::string& line) { size_t idx = 0; std::stack bracket; - while (idx < line.length()) { - if (line[idx] == '{') + if (line[idx] == '{') { bracket.push(true); - else if (line[idx] == '}') { + } else if (line[idx] == '}') { bracket.pop(); - if (bracket.empty()) { - break; - } + if (bracket.empty()) break; } idx++; } return idx; } +// 블록 파싱할 때 키워드 체크함수 +// 이곳에서 블록 키워드가 제대로 파싱이 안되어 있는 걸 체크합니다. +// 향후 허용되지 않는 키가 들어오는 경우는 여기에서 체크하도록 합시다. static bool isKeywordBlock(std::string& line) { std::string::iterator it = line.begin(); - for (; it != line.end(); it++) { - if (isalpha(*it)) - break ; - } - return it == line.end() ? false : true; + for (; it != line.end(); it++) if (isalpha(*it)) { break ; } + if (it == line.end()) + return false; + return true; } -static std::string getkeywordBlock(std::string& line) -{ +static std::string getkeywordBlock(std::string& line) { size_t start = 0; - while (!isalpha(line[start]) || line[start] == '}') - start++; + while (!isalpha(line[start]) || line[start] == '}') start++; size_t idx = line.find_first_of(" \t\r\n{", start); std::string ret = line.substr(start, idx - start); - if (!isKeywordBlock(ret)) - std::cout << "Error !!!!!!!!" << ret << "!!!!!!!!!!!" << std::endl; + if (!isKeywordBlock(ret)) std::cout << "Error !!!!!!!!" << ret << "!!!!!!!!!!!" << std::endl; // 키워드블록 파싱 에러 line.erase(0, ret.length()); return ret; } static std::string getvaluesBlock(std::string& lines) { size_t bracket_end_idx = getLastBracketIndex(lines); - std::string ret = lines.substr(lines.find('{', 0), bracket_end_idx); + size_t bracket_start_idx = lines.find('{', 0); + std::string ret = lines.substr(++bracket_start_idx, bracket_end_idx); lines.erase(0, ret.length()); return ret; } -static void parseDirectives(std::string& lines, std::map& map) -{ +static void parseDirectives(std::string& lines, std::map >& map) { std::size_t idx_first_block = lines.find("{", (lines[0] == '{')); std::string tmp, key, value; - for (std::size_t base = 0, found = 0;;) - { + for (std::size_t base = 0, found = 0;;) { while (isspace(lines[base])) base++; found = lines.find(";", base); if (found > idx_first_block || found == STRING_NPOS) { @@ -133,51 +121,24 @@ static void parseDirectives(std::string& lines, std::map& map) -{ - std::size_t idx_first_block = lines.find("{", 1); - std::string tmp, key, value; - for (std::size_t base = 0, found = 0;;) - { - while (isspace(lines[base])) base++; - found = lines.find(";", base); - if (found > idx_first_block || found == STRING_NPOS) { - lines.erase(0, base); - break; + if (map.find(key) == map.end()) { + std::vector bucket; + bucket.push_back(value); + map.insert(make_pair(key, bucket)); + } else { + map.find(key)->second.push_back(value); } - tmp = lines.substr(base, found - base); - std::string::iterator it = tmp.begin(); - while (isalpha(*it) || isSpecialCharactersBlockKeyword(*it)) { - key += *it; - it++; - } - while (isspace(*it)) - it++; - while (it != tmp.end()) { - value += *it; - it++; - } - map.insert(make_pair(key, value)); key.clear(); value.clear(); base = found + 1; } } - void ConfigParser::parseMainContext(std::string& lines) { parseDirectives(lines, this->mainDirectives); } @@ -186,6 +147,10 @@ void ConfigParser::parseEventsBlock(std::string& lines) { parseDirectives(lines, this->eventDirectives); } +void ConfigParser::parseUpstreamBlock(std::string& lines) { + parseDirectives(lines, this->upstreamDirectives); +} + void ConfigParser::parseHTTPBlock(std::string& lines) { parseDirectives(lines, this->httpDirectives); while (lines.find('{', 0) != STRING_NPOS) { @@ -193,23 +158,23 @@ void ConfigParser::parseHTTPBlock(std::string& lines) { } } - -void ConfigParser::parseServerBlock(std::string& lines) { +void ConfigParser::parseServerBlock(std::string& lines, + std::vector > >& a) { // 두번째 인자는 로직 입증을 위해 임시로 넣어둠 // 향후 구현 방향에 따라 서버 블록 내의 Directives를 저장할 수 있도록 알맞게 수정해야함. - parseDirectives(lines, this->eventDirectives); + std::map > t; + parseDirectives(lines, t); while (lines.find('{', 0) != STRING_NPOS) { parseBlock(lines); } - return ; + if (t.size() != 0) a.push_back(t); } -void ConfigParser::parseBlock (std::string& lines) { +void ConfigParser::parseBlock(std::string& lines) { std::pair blockContents = make_pair(getkeywordBlock(lines), getvaluesBlock(lines)); - if (blockContents.first.length() == 0) - { + if (blockContents.first.length() == 0) { std::cout << "ak!" << std::endl; - return ; + return; } std::cout << blockContents.first << std::endl; if (!blockContents.first.compare("events")) { @@ -219,39 +184,53 @@ void ConfigParser::parseBlock (std::string& lines) { parseHTTPBlock(blockContents.second); } if (!blockContents.first.compare("server")) { - parseServerBlock(blockContents.second); + parseServerBlock(blockContents.second, this->serverBlocks); } - if (blockContents.first.length() > 8 && !blockContents.first.find("location", 0, 8)) { - parseServerBlock(blockContents.second); + if (!blockContents.first.compare("upstream")) { + parseUpstreamBlock(blockContents.second); + } + if (blockContents.first.length() >= 8 && blockContents.first.find("location", 0) != STRING_NPOS) { + parseServerBlock(blockContents.second, this->serverBlocks); } } -void ConfigParser::showSizeDirectives(void) { - std::cout << "main :" << this->mainDirectives.size() << std::endl; - std::cout << "event :" << this->eventDirectives.size() << std::endl; - std::cout << "http :" << this->httpDirectives.size() << std::endl; -}; - void ConfigParser::parseConfigFile(void) { std::ifstream fs; std::string lines; - fs.open(file_path_, std::ios::in); - if (!fs.is_open()) - { + if (!fs.is_open()) { std::cerr << ERR_MSG_HAED << "file open err" << std::endl; - return ; + return; } lines = getConfigFileLines(fs); fs.close(); - if (isAllofBracketClosed(lines) == false) - { + if (isAllofBracketClosed(lines) == false) { std::cerr << ERR_MSG_HAED << "unclosed bracket" << std::endl; - return ; + return; } parseMainContext(lines); while (lines.find('{', 0) != STRING_NPOS) { parseBlock(lines); } - showSizeDirectives(); + test_map_data_print(); +} + +void test_serverBlock_print(std::vector > >& a) { + std::vector > >::iterator it = a.begin(); + for (; it != a.end(); it++) { + test::showParsedDirectives(*it); + } +} + +void ConfigParser::test_map_data_print(void) { + std::cout << "main -------------" << std::endl; + test::showParsedDirectives(this->mainDirectives); + std::cout << "events -------------" << std::endl; + test::showParsedDirectives(this->eventDirectives); + std::cout << "http -------------" << std::endl; + test::showParsedDirectives(this->httpDirectives); + std::cout << "upstream -------------" << std::endl; + test::showParsedDirectives(this->upstreamDirectives); + std::cout << "server -------------" << std::endl; + test_serverBlock_print(this->serverBlocks); }