diff --git a/Makefile b/Makefile index f659bb5..bbd72a6 100644 --- a/Makefile +++ b/Makefile @@ -11,19 +11,22 @@ SRC = $(wildcard ./src/*.cpp) SRC += $(wildcard ./src/*/*.cpp) HEADERS = $(wildcard ./includes/*.hpp) +HEADERS += $(wildcard src/Autoindex/*.hpp) +HEADERS += $(wildcard src/Header/*.hpp) +HEADERS += $(wildcard src/Server/*.hpp) HEADERS += $(wildcard src/config/*.hpp) -INCLUDES = ./includes/ +INCLUDES = ./includes/ -I src/Autoindex -I src/config -I src/Header -I src/Server OBJ = $(SRC:.cpp=.o) all: $(NAME) $(OBJ): %.o: %.cpp $(SRC) $(HEADERS) Makefile - $(CXX) $(CXXFLAGS) -c $< -I $(INCLUDES) -o $@ + $(CXX) $(CXXFLAGS) -c $< -I $(INCLUDES) -o $@ $(NAME): $(OBJ) $(HEADERS) - $(CXX) $(CXXFLAGS) $(OBJ) -o $(NAME) + $(CXX) $(CXXFLAGS) $(OBJ) -o $(NAME) clean: $(RM) $(OBJ) diff --git a/config/example.toml b/config/example.toml index b4bbdab..7e057f4 100644 --- a/config/example.toml +++ b/config/example.toml @@ -2,12 +2,16 @@ name = ["jopa.com", "popa.org"] host = "127.0.0.1" port = 8080 + body_size_limit = 10 [server.error_page] 404 = "/var/www/html/error_404.html" 405 = "/var/www/html/error_405.html" - body_size_limit = 10 + # error_404 = "error_404.html" + [server.error_page] + 400 = "error_400.html" + 401 = "error_401.html" [[server.location]] - redirect = [301, "http://localhost/secret"] + redirect = ["301", "http://localhost/secret"] location = "/" root = "/var/www/html/" methods = ["GET", "POST"] @@ -25,7 +29,7 @@ [[server]] name = "2222" - host = "10.0.0.1" + ip = "10.0.0.1" port = 8081 body_size_limit = 10 [[server.location]] diff --git a/config/simple.toml b/config/simple.toml index 4abbf7d..31d9ecb 100644 --- a/config/simple.toml +++ b/config/simple.toml @@ -2,8 +2,9 @@ name = "serv1" host = "127.0.0.1" port = 8080 - error_page = "error.html" body_size_limit = 10 + [server.error_page] + 404 = "error_404.html" [[server.location]] location = "/" root = "/var/www/html/jopa.html" @@ -22,8 +23,12 @@ name = "2222" host = "10.0.0.1" port = 8081 - error_page = "error2.html" body_size_limit = 10 + [server.error_page] + 404 = "error_404.html" + 405 = "error_405.html" + 406 = "error_406.html" + 407 = "error_407.html" [[server.location]] location = "/root2/" root = "/var/www/html/jopa.html" diff --git a/includes/webserv.hpp b/includes/webserv.hpp index f2b0f2e..54f5f8c 100644 --- a/includes/webserv.hpp +++ b/includes/webserv.hpp @@ -8,53 +8,39 @@ #define PINK "\033[35m" #define TURGUOISE "\033[36m" #define ZERO_C "\033[0m" + #define HOME "www" +#define BUFFSIZE 1024 +#define MAX_CLIENT 1000 #include #include -#include -#include -#include + #include #include #include +#include +#include +#include + + #include #include #include #include +#include +#include +#include + + #include #include #include #include -#include -#include #include #include -#include #include #include -#include "Socket.hpp" -#include "HeaderHandl.hpp" -#include "ServerConfig.hpp" -#include "Autoindex.hpp" -#include "Server.hpp" -#include "Header.hpp" - -#include -#include - -void parse(void); - -class toml_node; - -/* typedef std::vector TOMLArray; */ -/* typedef std::vector TOMLArrayOfMap; */ -typedef std::map TOMLMap; // = JSONObject -typedef std::vector TOMLMapArray; -typedef std::vector TOMLArray; - -void display(TOMLMap *config); - #endif diff --git a/src/Autoindex.cpp b/src/Autoindex/Autoindex.cpp similarity index 100% rename from src/Autoindex.cpp rename to src/Autoindex/Autoindex.cpp diff --git a/includes/Autoindex.hpp b/src/Autoindex/Autoindex.hpp similarity index 100% rename from includes/Autoindex.hpp rename to src/Autoindex/Autoindex.hpp diff --git a/src/Header.cpp b/src/Header/Header.cpp similarity index 100% rename from src/Header.cpp rename to src/Header/Header.cpp diff --git a/includes/Header.hpp b/src/Header/Header.hpp similarity index 95% rename from includes/Header.hpp rename to src/Header/Header.hpp index abcc2d7..de83fd3 100644 --- a/includes/Header.hpp +++ b/src/Header/Header.hpp @@ -2,6 +2,8 @@ # define HEADER_HPP #include "webserv.hpp" +#include "HeaderHandl.hpp" +#include "Autoindex.hpp" class Header { diff --git a/src/HeaderHandl.cpp b/src/Header/HeaderHandl.cpp similarity index 100% rename from src/HeaderHandl.cpp rename to src/Header/HeaderHandl.cpp diff --git a/includes/HeaderHandl.hpp b/src/Header/HeaderHandl.hpp similarity index 100% rename from includes/HeaderHandl.hpp rename to src/Header/HeaderHandl.hpp diff --git a/src/Server.cpp b/src/Server/Server.cpp similarity index 88% rename from src/Server.cpp rename to src/Server/Server.cpp index 1b35312..ace698a 100644 --- a/src/Server.cpp +++ b/src/Server/Server.cpp @@ -1,4 +1,5 @@ -#include "webserv.hpp" +#include "Server.hpp" + //----------------------------------------------Constructors----------------------------------------------------------------------------------- Server::Server() { @@ -17,6 +18,36 @@ Server::Server(std::string path) //----------------------------------------------Configuration----------------------------------------------------------------------------------- void Server::readConfig(void) { + TOMLMap *root = parse(); + + + TOMLMap *map; + TOMLMap::iterator it1; + TOMLMapArray *arr; + TOMLMapArray::iterator it; + + + arr = root->find("server")->second->getMapArray(); + it = arr->begin(); + + while (it != arr->end()) + { + std::cout << BLUE << *it << std::endl; + map = *it; + + it1 = map->begin(); + while (it1 != map->end()) + { + std::cout << TURGUOISE << it1->first << it1->second << ZERO_C << std::endl; + ++it1; + } + + + ++it; + } + + + } diff --git a/includes/Server.hpp b/src/Server/Server.hpp similarity index 82% rename from includes/Server.hpp rename to src/Server/Server.hpp index 0f5c3ac..d7ff9ab 100644 --- a/includes/Server.hpp +++ b/src/Server/Server.hpp @@ -2,9 +2,10 @@ #define SERVER_HPP #include "webserv.hpp" - -#define BUFFSIZE 1024 -#define MAX_CLIENT 1000 +#include "Header.hpp" +#include "ServerConfig.hpp" +#include "Socket.hpp" +#include "parse.hpp" class Header; @@ -17,6 +18,7 @@ private: struct epoll_event _events[MAX_CLIENT]; struct sockaddr_in _addres; std::string _ip; + std::vector _configs; private: void checkError(int fd, std::string str); diff --git a/src/ServerConfig.cpp b/src/Server/ServerConfig.cpp similarity index 100% rename from src/ServerConfig.cpp rename to src/Server/ServerConfig.cpp diff --git a/includes/ServerConfig.hpp b/src/Server/ServerConfig.hpp similarity index 100% rename from includes/ServerConfig.hpp rename to src/Server/ServerConfig.hpp diff --git a/src/Socket.cpp b/src/Server/Socket.cpp similarity index 100% rename from src/Socket.cpp rename to src/Server/Socket.cpp diff --git a/includes/Socket.hpp b/src/Server/Socket.hpp similarity index 100% rename from includes/Socket.hpp rename to src/Server/Socket.hpp diff --git a/src/config/TOMLNode.cpp b/src/config/TOMLNode.cpp new file mode 100644 index 0000000..3a32ec2 --- /dev/null +++ b/src/config/TOMLNode.cpp @@ -0,0 +1,165 @@ +#include "TOMLNode.hpp" + +/* toml_node::toml_node(void) */ +/* { */ +/* return; */ +/* } */ + +/* toml_node::toml_node(const toml_node &src) */ +/* { */ +/* *this = src; */ +/* return; */ +/* } */ + +/* toml_node::~toml_node(void) */ +/* { */ +/* return; */ +/* } */ + +/* toml_node &toml_node::operator=(const toml_node &rhs) */ +/* { */ +/* //code */ +/* return (*this); */ +/* } */ + +toml_node::e_type toml_node::get_type(void) +{ + return (type); +} + +TOMLMap *toml_node::getMap(void) +{ + return (value.map); +} + +TOMLMapArray *toml_node::getMapArray(void) +{ + return (value.map_array); +} + +void toml_node::setString(std::string *str) +{ + value.str = str; + type = STRING; +} + +void toml_node::setNumber(int num) +{ + value.integer = num; + type = NUM; +} + +void toml_node::setArr(TOMLArray *toml_array) +{ + value.array = toml_array; + type = ARRAY; +} +void toml_node::setBool(bool b) +{ + value.boolean = b; + type = BOOL; +} +void toml_node::setNil(void) +{ + type = NIL; +} + +void toml_node::setObject(TOMLMap *obj) +{ + value.map = obj; + type = MAP; +} + +void toml_node::setMapArray(TOMLMapArray *map_array) +{ + value.map_array = map_array; + type = MAPARRAY; +} + +std::string *toml_node::toString(void) const +{ + switch (type) + { + case STRING: + { + return (value.str); + } + case NUM: + { + std::stringstream ss; + ss << value.integer; + std::string *result = new std::string(); + ss >> *result; + return (result); + } + case ARRAY: + { + TOMLArray::iterator it; + std::string *result = new std::string("[ "); + for (it = value.array->begin(); it != value.array->end(); ++it) + { + *result += *((*it)->toString()); + *result += ", "; + } + *result += " ]"; + return (result); + } + case MAP: + { + return (TOMLMap_to_string(value.map)); + } + case MAPARRAY: + { + std::stringstream ss; + std::string *result = new std::string(); + TOMLMapArray::iterator it; + TOMLMapArray *map_array = value.map_array; + + ss << "[\n"; + for (it = map_array->begin(); it != map_array->end(); ++it) + { + ss << (*TOMLMap_to_string(*it)); + ss << ", " << std::endl; + } + ss << "]\n"; + + + /* ss >> *result; */ + *result = ss.str(); + return (result); + } + case BOOL: + { + std::string *result; + if (value.boolean) + result = new std::string("true"); + else + result = new std::string("false"); + return (result); + } + default: + return ( new std::string("Not implemented :)")); + } +} + +std::string *toml_node::TOMLMap_to_string(TOMLMap *map) +{ + std::stringstream ss; + std::string *result = new std::string(); + TOMLMap::iterator it; + + ss << "{\n"; + for (it = map->begin(); it != map->end(); ++it) + { + ss << it->first + << ": " + << *(it->second->toString()) + << std::endl; + } + + ss << "}" << std::endl; + + /* ss >> *result; */ + *result = ss.str(); + return (result); +} diff --git a/src/config/TOMLNode.hpp b/src/config/TOMLNode.hpp index 2cf2c64..6c7716a 100644 --- a/src/config/TOMLNode.hpp +++ b/src/config/TOMLNode.hpp @@ -2,6 +2,8 @@ #define TOMLNODE_HPP #include "webserv.hpp" +#include "tomlstuff.hpp" + #include #include #include @@ -11,9 +13,6 @@ #include #include - - - class toml_node { @@ -37,145 +36,23 @@ class toml_node STRING, NUM, BOOL, ARRAY, MAP, MAPARRAY, NIL } type; - enum e_type get_type(void) - { - return (type); - } + enum e_type get_type(void); - TOMLMap *getMap(void) - { - return (value.map); - } + TOMLMap *getMap(void); + TOMLMapArray *getMapArray(void); - TOMLMapArray *getMapArray(void) - { - return (value.map_array); - } + void setString(std::string *str); + void setNumber(int num); - void setString(std::string *str) - { - value.str = str; - type = STRING; - } + void setArr(TOMLArray *toml_array); + void setBool(bool b); + void setNil(void); + void setObject(TOMLMap *obj); + void setMapArray(TOMLMapArray *map_array); - void setNumber(int num) - { - value.integer = num; - type = NUM; - } - - void setArr(TOMLArray *toml_array) - { - value.array = toml_array; - type = ARRAY; - } - void setBool(bool b) - { - value.boolean = b; - type = BOOL; - } - void setNil(void) - { - type = NIL; - } - void setObject(TOMLMap *obj) - { - value.map = obj; - type = MAP; - } - void setMapArray(TOMLMapArray *map_array) - { - value.map_array = map_array; - type = MAPARRAY; - } - - static std::string *TOMLMap_to_string(TOMLMap *map) - { - std::stringstream ss; - std::string *result = new std::string(); - TOMLMap::iterator it; - - ss << "{\n"; - for (it = map->begin(); it != map->end(); ++it) - { - ss << it->first - << ": " - << *(it->second->toString()) - << std::endl; - } - - ss << "}" << std::endl; - - /* ss >> *result; */ - *result = ss.str(); - return (result); - } - - std::string *toString(void) const - { - switch (type) - { - case STRING: - { - return (value.str); - } - case NUM: - { - std::stringstream ss; - ss << value.integer; - std::string *result = new std::string(); - ss >> *result; - return (result); - } - case ARRAY: - { - TOMLArray::iterator it; - std::string *result = new std::string("[ "); - for (it = value.array->begin(); it != value.array->end(); ++it) - { - *result += *((*it)->toString()); - *result += ", "; - } - *result += " ]"; - return (result); - } - case MAP: - { - return (TOMLMap_to_string(value.map)); - } - case MAPARRAY: - { - std::stringstream ss; - std::string *result = new std::string(); - TOMLMapArray::iterator it; - TOMLMapArray *map_array = value.map_array; - - ss << "[\n"; - for (it = map_array->begin(); it != map_array->end(); ++it) - { - ss << (*TOMLMap_to_string(*it)); - ss << ", " << std::endl; - } - ss << "]\n"; - - - /* ss >> *result; */ - *result = ss.str(); - return (result); - } - case BOOL: - { - std::string *result; - if (value.boolean) - result = new std::string("true"); - else - result = new std::string("false"); - return (result); - } - default: - return ( new std::string("Not implemented :)")); - } - } + std::string *toString(void) const; + static std::string *TOMLMap_to_string(TOMLMap *map); }; + #endif diff --git a/src/config/TOMLParser.cpp b/src/config/TOMLParser.cpp new file mode 100644 index 0000000..e8b0b1b --- /dev/null +++ b/src/config/TOMLParser.cpp @@ -0,0 +1,482 @@ +#include "TOMLParser.hpp" + +/* -Template::-Template(void) */ +/* { */ +/* return; */ +/* } */ + +/* -Template::-Template(const -Template &src) */ +/* { */ +/* *this = src; */ +/* return; */ +/* } */ + +/* -Template::~-Template(void) */ +/* { */ +/* return; */ +/* } */ + +/* -Template &-Template::operator=(const -Template &rhs) */ +/* { */ +/* //code */ +/* return (*this); */ +/* } */ + +namespace config +{ + + TOMLParser::TOMLParser(const std::string filename) : tokenizer(filename) + {}; + + void TOMLParser::processMap(void) + { + std::cerr << "Processing map" << std::endl; + toml_node *map_node; + s_token current; + + try { current = tokenizer.getToken(); } + catch (std::logic_error e) + { + std::cerr << e.what() << std::endl; + return; + } + if (current.type == MAP_DECL) + { + if (tokenizer.getToken().type != NEWLINE) + throw std::logic_error("no newline after MAP_DECL"); + map_node = parseMap(); + } + else + throw std::logic_error("unexpected token in processMap"); + + std::cout << current.value << std::endl; + + std::vector full_name; + + full_name = split_name(current.value); + + put_to_subtable(root, full_name, map_node, toml_node::MAP); + + } + + toml_node *TOMLParser::parseMap(void) + { + std::cerr << "Parsing map" << std::endl; + toml_node *node = new toml_node; + TOMLMap *mapObject = new TOMLMap; + bool completed = false; + while (!completed) + { + if (tokenizer.hasMoreTokens()) + { + s_token nextToken; + try { nextToken = tokenizer.getToken(); } + catch (std::logic_error e) + { + std::cerr << e.what() << std::endl; + break; + } + if (nextToken.type == MAPARRAY_DECL) + { + tokenizer.rollBackToken(); + tokenizer.set_last(NEWLINE); + break; + } + else if (nextToken.type == MAP_DECL) + { + tokenizer.rollBackToken(); + tokenizer.set_last(NEWLINE); + break; + } + std::string key = nextToken.value; + std::cerr << key << std::endl; + if (tokenizer.getToken().type != ASSIGN) + throw std::logic_error("EXPECTED assign!"); + nextToken = tokenizer.getToken(); + switch (nextToken.type) + { + case STRING: + { + tokenizer.rollBackToken(); + (*mapObject)[key] = parseString(); + break; + } + case OPEN_BRACKET: + { + (*mapObject)[key] = parseArray(); + break; + } + case NUMBER: + { + tokenizer.rollBackToken(); + (*mapObject)[key] = parseNumber(); + break; + } + case BOOL: + { + tokenizer.rollBackToken(); + (*mapObject)[key] = parseBool(); + break; + } + case MAPARRAY_DECL: + { + std::cerr << "reached MAPARRAY_DECL in parseMap" << std::endl; + completed = true; + break; + } + default: + { + /* throw std::logic_error("jopa in parseMap"); */ + std::cerr << "Unknown token, marking as complete" << std::endl; + completed = true; + break; + } + } + if (tokenizer.hasMoreTokens()) + nextToken = tokenizer.getToken(); + else + break; + if (nextToken.type != NEWLINE) + { + throw std::logic_error("EXPECTED newline"); + } + } + else + { + throw std::logic_error("parseMap: no more tokens"); + } + } + node->setObject(mapObject); + return (node); + } + + void TOMLParser::processMapArray(void) + { + + std::cerr << "Parsing MapArray" << std::endl; + toml_node *map_node; + s_token current; + + try { current = tokenizer.getToken(); } + catch (std::logic_error e) + { + std::cerr << e.what() << std::endl; + return; + } + if (current.type == MAPARRAY_DECL) + { + if (tokenizer.getToken().type != NEWLINE) + throw std::logic_error("no newline after map_array declaration"); + map_node = parseMap(); + } + else + throw std::logic_error("unexpected token in processMapArray"); + + std::cout << current.value << std::endl; + + std::vector full_name; + + full_name = split_name(current.value); + + put_to_subtable(root, full_name, map_node, toml_node::MAPARRAY); + + } + + toml_node *TOMLParser::parseString(void) + { + /* toml_node *node; */ + toml_node *node = new toml_node; + std::string *sValue; + + std::cerr << "Parsing string" << std::endl; + s_token token = tokenizer.getToken(); + sValue = new std::string(token.value); + node->setString(sValue); + + return (node); + } + + toml_node *TOMLParser::parseNumber(void) + { + toml_node *node = new toml_node; + int value; + + std::cerr << "Parsing number" << std::endl; + s_token token = tokenizer.getToken(); + value = std::atoi(token.value.c_str()); + node->setNumber(value); + + return (node); + } + + toml_node *TOMLParser::parseArray(void) + { + std::cerr << "Parsing array" << std::endl; + toml_node *node; + toml_node *result = new toml_node; + TOMLArray *array = new TOMLArray; + bool completed = false; + s_token current; + + while (!completed) + { + if (!tokenizer.hasMoreTokens()) + throw std::logic_error("No more tokens"); + else + { + current = tokenizer.getToken(); + switch (current.type) + { + case OPEN_BRACKET: + { + node = parseArray(); + break; + } + case STRING: + { + tokenizer.rollBackToken(); + node = parseString(); + break; + } + case NUMBER: + { + tokenizer.rollBackToken(); + node = parseNumber(); + break; + } + case BOOL: + { + tokenizer.rollBackToken(); + node = parseBool(); + break; + } + case NIL: + { + node = parseNil(); + break; + } + default: + { + throw std::logic_error("unkown token in parseArray"); + } + + } + array->push_back(node); + current = tokenizer.getToken(); + if (current.type == COMMA) + continue; + else if (current.type == CLOSE_BRACKET) + completed = true; + else + throw std::invalid_argument("Unexpected token in array!"); + } + } + result->setArr(array); + return (result); + } + + toml_node *TOMLParser::parseBool(void) + { + toml_node *node = new toml_node; + bool value; + + std::cerr << "Parsing bool" << std::endl; + s_token token = tokenizer.getToken(); + if (token.value == "true") + value = true; + else if (token.value == "false") + value = false; + else + throw std::invalid_argument("Unexpected bool value"); + node->setBool(value); + + return (node); + } + + toml_node *TOMLParser::parseNil(void) + { + toml_node *node = new toml_node; + std::cerr << "Parsing NIL" << std::endl; + node->setNil(); + return (node); + } + + /* parse tha root ! */ + TOMLMap *TOMLParser::parse(void) + { + std::cerr << "Parsing ROOT" << std::endl; + root = new TOMLMap; + bool completed = false; + while (!completed) + { + if (tokenizer.hasMoreTokens()) + { + s_token current; + try { current = tokenizer.getToken(); } + catch (std::logic_error e) + { + std::cerr << e.what() << std::endl; + break; + } + if (current.type == MAPARRAY_DECL) + { + /* processMapArray(); */ + tokenizer.set_last(NEWLINE); + tokenizer.rollBackToken(); + processMapArray(); + } + else if (current.type == MAP_DECL) + { + std::cerr << "MAP_DECL value: " << current.value << std::endl; + tokenizer.set_last(NEWLINE); + tokenizer.rollBackToken(); + /* if (tokenizer.getToken().type != NEWLINE) */ + /* throw std::logic_error("no newline after MAP_DECL"); */ + /* (*mapObject)[nextToken.value] = parseMap(); */ + processMap(); + continue; + } + else + { + std::string key = current.value; + std::cerr << key << std::endl; + if (tokenizer.getToken().type != ASSIGN) + throw std::logic_error("EXPECTED assign!"); + current = tokenizer.getToken(); + switch (current.type) + { + case STRING: + { + tokenizer.rollBackToken(); + (*root)[key] = parseString(); + break; + } + case OPEN_BRACKET: + { + (*root)[key] = parseArray(); + break; + } + case NUMBER: + { + tokenizer.rollBackToken(); + (*root)[key] = parseNumber(); + break; + } + case BOOL: + { + tokenizer.rollBackToken(); + (*root)[key] = parseBool(); + break; + } + default: + { + /* throw std::logic_error("jopa in parseMap"); */ + std::cerr << "Unknown token, marking as complete" << std::endl; + completed = true; + break; + } + } + if (tokenizer.hasMoreTokens()) + current = tokenizer.getToken(); + else + break; + if (current.type != NEWLINE) + { + throw std::logic_error("EXPECTED newline"); + } + } + } + else + { + completed = true; + break; + } + } + return (root); + } + + std::vector TOMLParser::split_name(std::string name) + { + std::vector full_name; + size_t dot; + + while (1) + { + dot = name.find('.'); + if (dot == std::string::npos) + break; + /* std::cout << dot << std::endl; */ + full_name.push_back(name.substr(0, dot)); + name.erase(0, dot + 1); + } + full_name.push_back(name); + + for (size_t i = 0; i < full_name.size(); i++) + std::cout << full_name[i] << ", "; + std::cout << std::endl; + + return (full_name); + } + + void TOMLParser::put_to_subtable(TOMLMap *root, + std::vector full_name, + toml_node *map_node, toml_node::e_type type) + { + std::vector::iterator subname = full_name.begin(); + toml_node *maparr_node; + TOMLMap::iterator it; + + TOMLMap *local_root = root; + + while (1) + { + if (subname + 1 == full_name.end()) + { + it = local_root->find(*subname); + if (type == toml_node::MAPARRAY) + { + if (it == local_root->end()) + { + maparr_node = new toml_node; + TOMLMapArray *map_array = new TOMLMapArray; + map_array->push_back(map_node->getMap()); + maparr_node->setMapArray(map_array); + (*local_root)[*subname] = maparr_node; + } + else + (it->second)->getMapArray()->push_back(map_node->getMap()); + } + else if (type == toml_node::MAP) + { + if (it == local_root->end()) + { + (*local_root)[*subname] = map_node; + } + else + throw std::logic_error("map already in subtable!"); + } + break; + } + else + { + it = local_root->find(*subname); + + toml_node *map_node2; + map_node2 = new toml_node; + TOMLMap *map = new TOMLMap; + map_node2->setObject(map); + /* subname not found in local_root */ + if (it == local_root->end()) + { + (*local_root)[*subname] = map_node2; + local_root = map; + } + /* subname found in local_root */ + else + local_root = *((it->second)->getMapArray()->end() - 1); + + } + ++subname; + } + } +} diff --git a/src/config/TOMLParser.hpp b/src/config/TOMLParser.hpp index 556e898..114fe4f 100644 --- a/src/config/TOMLParser.hpp +++ b/src/config/TOMLParser.hpp @@ -1,8 +1,10 @@ #ifndef TOMLPARSER_HPP #define TOMLPARSER_HPP -#include "TOMLNode.hpp" +#include "webserv.hpp" +#include "tomlstuff.hpp" #include "Tokenizer.hpp" +#include "TOMLNode.hpp" #include namespace config @@ -15,380 +17,33 @@ namespace config /* toml_node *current; //node currently being parsed */ Tokenizer tokenizer; + static std::vector split_name(std::string name); + static void put_to_subtable(TOMLMap *root, + std::vector full_name, + toml_node *map_node, toml_node::e_type type); + public: - TOMLParser(const std::string filename) : tokenizer(filename) {} + TOMLParser(const std::string filename); TOMLMap *parse(void); - toml_node *parseMap(void) - { - std::cerr << "Parsing object" << std::endl; - toml_node *node = new toml_node; - TOMLMap *mapObject = new TOMLMap; - bool completed = false; - while (!completed) - { - if (tokenizer.hasMoreTokens()) - { - s_token nextToken; - try { nextToken = tokenizer.getToken(); } - catch (std::logic_error e) - { - std::cerr << e.what() << std::endl; - break; - } - if (nextToken.type == MAPARRAY_DECL) - { - tokenizer.rollBackToken(); - break; - } - std::string key = nextToken.value; - std::cerr << key << std::endl; - if (tokenizer.getToken().type != ASSIGN) - throw std::logic_error("EXPECTED assign!"); - nextToken = tokenizer.getToken(); - switch (nextToken.type) - { - case STRING: - { - tokenizer.rollBackToken(); - (*mapObject)[key] = parseString(); - break; - } - case ARR_OPEN: - { - (*mapObject)[key] = parseArray(); - break; - } - case NUMBER: - { - tokenizer.rollBackToken(); - (*mapObject)[key] = parseNumber(); - break; - } - case BOOL: - { - tokenizer.rollBackToken(); - (*mapObject)[key] = parseBool(); - break; - } - case MAPARRAY_DECL: - { - std::cerr << "reached MAPARRAY_DECL in parseMap" << std::endl; - completed = true; - break; - } - default: - { - /* throw std::logic_error("jopa in parseMap"); */ - std::cerr << "Unknown token, marking as complete" << std::endl; - completed = true; - break; - } - } - if (tokenizer.hasMoreTokens()) - nextToken = tokenizer.getToken(); - else - break; - if (nextToken.type != NEWLINE) - { - throw std::logic_error("EXPECTED newline"); - } - } - else - { - throw std::logic_error("parseMap: no more tokens"); - } - } - node->setObject(mapObject); - return (node); - } + toml_node *parseMap(void); + void processMap(void); - toml_node *parseString(void) - { - /* toml_node *node; */ - toml_node *node = new toml_node; - std::string *sValue; + void processMapArray(void); - std::cerr << "Parsing string" << std::endl; - s_token token = tokenizer.getToken(); - sValue = new std::string(token.value); - node->setString(sValue); + toml_node *parseString(void); - return (node); - } + toml_node *parseNumber(void); - toml_node *parseNumber(void) - { - toml_node *node = new toml_node; - int value; + toml_node *parseArray(void); - std::cerr << "Parsing number" << std::endl; - s_token token = tokenizer.getToken(); - value = std::atoi(token.value.c_str()); - node->setNumber(value); + toml_node *parseBool(void); - return (node); - } + toml_node *parseNil(void); - toml_node *parseArray(void) - { - std::cerr << "Parsing array" << std::endl; - toml_node *node; - toml_node *result = new toml_node; - TOMLArray *array = new TOMLArray; - bool completed = false; - s_token current; - - while (!completed) - { - if (!tokenizer.hasMoreTokens()) - throw std::logic_error("No more tokens"); - else - { - current = tokenizer.getToken(); - switch (current.type) - { - case ARR_OPEN: - { - node = parseArray(); - break; - } - case STRING: - { - tokenizer.rollBackToken(); - node = parseString(); - break; - } - case NUMBER: - { - tokenizer.rollBackToken(); - node = parseNumber(); - break; - } - case BOOL: - { - tokenizer.rollBackToken(); - node = parseBool(); - break; - } - case NIL: - { - node = parseNil(); - break; - } - default: - { - throw std::logic_error("unkown token in parseArray"); - } - - } - array->push_back(node); - current = tokenizer.getToken(); - if (current.type == COMMA) - continue; - else if (current.type == ARR_CLOSE) - completed = true; - else - throw std::invalid_argument("Unexpected token in array!"); - } - } - result->setArr(array); - return (result); - } - - toml_node *parseBool(void) - { - toml_node *node = new toml_node; - bool value; - - std::cerr << "Parsing bool" << std::endl; - s_token token = tokenizer.getToken(); - if (token.value == "true") - value = true; - else if (token.value == "false") - value = false; - else - throw std::invalid_argument("Unexpected bool value"); - node->setBool(value); - - return (node); - } - - toml_node *parseNil(void) - { - toml_node *node = new toml_node; - std::cerr << "Parsing NIL" << std::endl; - node->setNil(); - return (node); - } }; /* parse tha root ! */ - TOMLMap *TOMLParser::parse(void) - { - std::cerr << "Parsing ROOT" << std::endl; - root = new TOMLMap; - bool completed = false; - while (!completed) - { - if (tokenizer.hasMoreTokens()) - { - s_token current; - try { current = tokenizer.getToken(); } - catch (std::logic_error e) - { - std::cerr << e.what() << std::endl; - break; - } - if (current.type == MAPARRAY_DECL) - { - /* parseMapArray(); */ - tokenizer.rollBackToken(); - std::cerr << "Parsing MapArray" << std::endl; - toml_node *map_node; - toml_node *maparr_node; - s_token current; - - try { current = tokenizer.getToken(); } - catch (std::logic_error e) - { - std::cerr << e.what() << std::endl; - break; - } - if (current.type == MAPARRAY_DECL) - { - if (tokenizer.getToken().type != NEWLINE) - throw std::logic_error("no newline after map_array declaration"); - map_node = parseMap(); - } - else - throw std::logic_error("unexpected token in parseMapArray"); - - TOMLMap::iterator it; - std::cout << current.value << std::endl; - std::string name = current.value; - std::vector full_name; - size_t dot; - - while (1) - { - dot = name.find('.'); - if (dot == std::string::npos) - break; - /* std::cout << dot << std::endl; */ - full_name.push_back(name.substr(0, dot)); - name.erase(0, dot + 1); - } - full_name.push_back(name); - - for (size_t i = 0; i < full_name.size(); i++) - std::cout << full_name[i] << ", "; - std::cout << std::endl; - - /* throw std::logic_error("tha end"); */ - TOMLMap *local_root; - - std::vector::iterator subname = full_name.begin(); - local_root = root; - while (1) - { - if (subname + 1 == full_name.end()) - { - it = local_root->find(*subname); - if (it == local_root->end()) - { - maparr_node = new toml_node; - TOMLMapArray *map_array = new TOMLMapArray; - map_array->push_back(map_node->getMap()); - maparr_node->setMapArray(map_array); - (*local_root)[*subname] = maparr_node; - } - else - (it->second)->getMapArray()->push_back(map_node->getMap()); - break; - } - else - { - it = local_root->find(*subname); - - toml_node *map_node2; - map_node2 = new toml_node; - TOMLMap *map = new TOMLMap; - map_node2->setObject(map); - /* subname not found in local_root */ - if (it == local_root->end()) - { - (*local_root)[*subname] = map_node2; - local_root = map; - } - /* subname found in local_root */ - else - { - local_root = *((it->second)->getMapArray()->end() - 1); - } - - } - ++subname; - } - - } - else - { - std::string key = current.value; - std::cerr << key << std::endl; - if (tokenizer.getToken().type != ASSIGN) - throw std::logic_error("EXPECTED assign!"); - current = tokenizer.getToken(); - switch (current.type) - { - case STRING: - { - tokenizer.rollBackToken(); - (*root)[key] = parseString(); - break; - } - case ARR_OPEN: - { - (*root)[key] = parseArray(); - break; - } - case NUMBER: - { - tokenizer.rollBackToken(); - (*root)[key] = parseNumber(); - break; - } - case BOOL: - { - tokenizer.rollBackToken(); - (*root)[key] = parseBool(); - break; - } - default: - { - /* throw std::logic_error("jopa in parseMap"); */ - std::cerr << "Unknown token, marking as complete" << std::endl; - completed = true; - break; - } - } - if (tokenizer.hasMoreTokens()) - current = tokenizer.getToken(); - else - break; - if (current.type != NEWLINE) - { - throw std::logic_error("EXPECTED newline"); - } - } - } - else - { - completed = true; - break; - } - } - return (root); - } + /* TOMLMap *TOMLParser::parse(void); */ } #endif diff --git a/src/config/Tokenizer.cpp b/src/config/Tokenizer.cpp new file mode 100644 index 0000000..4d6f9c8 --- /dev/null +++ b/src/config/Tokenizer.cpp @@ -0,0 +1,223 @@ +#include "Tokenizer.hpp" + +/* -Template::-Template(void) */ +/* { */ +/* return; */ +/* } */ + +/* -Template::-Template(const -Template &src) */ +/* { */ +/* *this = src; */ +/* return; */ +/* } */ + +/* -Template::~-Template(void) */ +/* { */ +/* return; */ +/* } */ + +/* -Template &-Template::operator=(const -Template &rhs) */ +/* { */ +/* //code */ +/* return (*this); */ +/* } */ +namespace config +{ + bool isspace(char c) + { + if (c == ' ' || c == '\t') + return (true); + else + return (false); + } + + bool istomlkey(char c) + { + if (isalnum(c) || c == '-' || c == '_') + return (true); + else + return (false); + } + Tokenizer::Tokenizer(std::string filename) + { + file.open(filename.c_str(), std::ios::in); + if (!file.good()) + { + std::cerr << "file didn't open" << std::endl; + } + } + bool Tokenizer::firstToken() + { + // doesn't account for indent! + if (file.tellg() == 0 || file.tellg() == 1 || (last_token == NEWLINE)) + return (true); + else + return (false); + } + + struct s_token Tokenizer::getToken(void) + { + char c; + struct s_token token; + + if (file.eof()) + { + std::cout << "Tokens exhausted" << std::endl; + } + prev_pos = file.tellg(); + c = getWithoutWhiteSpace(); + + if (firstToken() && config::istomlkey(c)) + { + token.type = KEY; + while (config::istomlkey(c)) + { + token.value += c; + file.get(c); + } + } + else if (c == '"') + { + token.type = STRING; + token.value = ""; + /* TODO: maybe do-while? */ + file.get(c); + while (c != '"') + { + token.value += c; + file.get(c); + } + } + else if (c == '[' && firstToken()) + { + /* std::streampos prev_pos = file.tellg(); */ + file.get(c); + if (c == '[') + { + token.type = MAPARRAY_DECL; + file.get(c); + while (c != ']') + { + token.value += c; + file.get(c); + } + if (c == ']') + file.get(c); + if (c != ']') + throw std::logic_error("error in MAPARRAY_DECL"); + } + else + { + token.type = MAP_DECL; + token.value += c; + file.get(c); + while (c != ']') + { + token.value += c; + file.get(c); + } + if (c != ']') + throw std::logic_error("malformed MAP_DECL"); + } + } + else if (c == '[') + { + token.type = OPEN_BRACKET; + } + else if (c == ']') + token.type = CLOSE_BRACKET; + else if (c == '=') + token.type = ASSIGN; + else if (c == '\n') + token.type = NEWLINE; + else if (c == '-' || isdigit(c)) + { + std::streampos prevCharPos; + token.type = NUMBER; + token.value = ""; + token.value += c; + /* prevCharPos = file.tellg(); */ + while (c == '-' || c == '.' || isdigit(c)) + { + prevCharPos = file.tellg(); + file.get(c); + if (file.eof()) + break; + else + { + if (c == '-' || c == '.' || isdigit(c)) + token.value += c; + else + file.seekg(prevCharPos); + + } + } + } + else if (c == 'f') + { + token.type = BOOL; + token.value = "false"; + file.seekg(4, std::ios_base::cur); + + /* token.value = ""; */ + /* while (std::isalpha(c)) */ + /* { */ + /* token.value += c; */ + /* file.get(c); */ + /* } */ + std::cerr << "value is: " << token.value << std::endl; + std::cerr << "c is: " << c << std::endl; + } + else if (c == 't') + { + token.type = BOOL; + while (std::isalpha(c)) + { + token.value += c; + file.get(c); + } + /* file.seekg(3, std::ios_base::cur); */ + } + else if (c == 'n') + { + token.type = NIL; + file.seekg(3, std::ios_base::cur); + } + else if (c == ',') + token.type = COMMA; + last_token = token.type; + return (token); + } + char Tokenizer::getWithoutWhiteSpace(void) + { + char c = ' '; + while (config::isspace(c)) + { + file.get(c); + if ((c == ' ') && !file.good()) + { + throw std::logic_error("No more tokens!"); + } + else if (!file.good()) + return (c); + } + return (c); + } + + bool Tokenizer::hasMoreTokens(void) + { + return (!file.eof()); + } + + void Tokenizer::rollBackToken(void) + { + if (file.eof()) + file.clear(); + file.seekg(prev_pos); + } + + void Tokenizer::set_last(e_token type) + { + last_token = type; + } +} diff --git a/src/config/Tokenizer.hpp b/src/config/Tokenizer.hpp index 791f8a8..eec6321 100644 --- a/src/config/Tokenizer.hpp +++ b/src/config/Tokenizer.hpp @@ -2,6 +2,8 @@ #define TOKENIZER_HPP #include "webserv.hpp" +#include "tomlstuff.hpp" + #include #include #include @@ -9,6 +11,7 @@ #include #include + namespace config { enum e_token @@ -21,10 +24,9 @@ namespace config COMMA, BOOL, NIL, - ARR_OPEN, - ARR_CLOSE, - MAP_OPEN, - MAP_CLOSE, + OPEN_BRACKET, + CLOSE_BRACKET, + MAP_DECL, MAPARRAY_DECL }; @@ -35,21 +37,9 @@ namespace config /* std::string to_string(void); */ }; - bool isspace(char c) - { - if (c == ' ' || c == '\t') - return (true); - else - return (false); - } + bool isspace(char c); - bool istomlkey(char c) - { - if (isalnum(c) || c == '-' || c == '_') - return (true); - else - return (false); - } + bool istomlkey(char c); class Tokenizer { @@ -57,57 +47,18 @@ namespace config std::fstream file; size_t prev_pos; e_token last_token; + public: - Tokenizer(std::string filename) - { - file.open(filename.c_str(), std::ios::in); - if (!file.good()) - { - std::cerr << "file didn't open" << std::endl; - } - } + Tokenizer(std::string filename); char getWithoutWhiteSpace(); struct s_token getToken(); bool hasMoreTokens(); - bool firstToken() - { - // doesn't account for indent! - if (file.tellg() == 0 || file.tellg() == 1 || (last_token == NEWLINE)) - return (true); - else - return (false); - } + bool firstToken(); void rollBackToken(); + void set_last(e_token type); + }; - char Tokenizer::getWithoutWhiteSpace(void) - { - char c = ' '; - while (config::isspace(c)) - { - file.get(c); - if ((c == ' ') && !file.good()) - { - throw std::logic_error("No more tokens!"); - } - else if (!file.good()) - return (c); - } - return (c); - } - - bool Tokenizer::hasMoreTokens(void) - { - return (!file.eof()); - } - - void Tokenizer::rollBackToken(void) - { - if (file.eof()) - file.clear(); - file.seekg(prev_pos); - } - /* struct s_token Tokenizer::getKey(void) */ /* { */ /* char c; */ @@ -118,128 +69,6 @@ namespace config /* } */ /* } */ - struct s_token Tokenizer::getToken(void) - { - char c; - struct s_token token; - - if (file.eof()) - { - std::cout << "Tokens exhausted" << std::endl; - } - prev_pos = file.tellg(); - c = getWithoutWhiteSpace(); - - if (firstToken() && config::istomlkey(c)) - { - token.type = KEY; - while (config::istomlkey(c)) - { - token.value += c; - file.get(c); - } - } - else if (c == '"') - { - token.type = STRING; - token.value = ""; - /* TODO: maybe do-while? */ - file.get(c); - while (c != '"') - { - token.value += c; - file.get(c); - } - } - else if (c == '[') - { - std::streampos prev_pos = file.tellg(); - file.get(c); - if (c == '[') - { - token.type = MAPARRAY_DECL; - file.get(c); - while (c != ']') - { - token.value += c; - file.get(c); - } - if (c == ']') - file.get(c); - if (c != ']') - throw std::logic_error("error in MAPARRAY_DECL"); - } - else - { - token.type = ARR_OPEN; - file.seekg(prev_pos); - } - - } - else if (c == ']') - token.type = ARR_CLOSE; - else if (c == '=') - token.type = ASSIGN; - else if (c == '\n') - token.type = NEWLINE; - else if (c == '-' || isdigit(c)) - { - std::streampos prevCharPos; - token.type = NUMBER; - token.value = ""; - token.value += c; - /* prevCharPos = file.tellg(); */ - while (c == '-' || c == '.' || isdigit(c)) - { - prevCharPos = file.tellg(); - file.get(c); - if (file.eof()) - break; - else - { - if (c == '-' || c == '.' || isdigit(c)) - token.value += c; - else - file.seekg(prevCharPos); - - } - } - } - else if (c == 'f') - { - token.type = BOOL; - token.value = "false"; - file.seekg(4, std::ios_base::cur); - - /* token.value = ""; */ - /* while (std::isalpha(c)) */ - /* { */ - /* token.value += c; */ - /* file.get(c); */ - /* } */ - std::cerr << "value is: " << token.value << std::endl; - std::cerr << "c is: " << c << std::endl; - } - else if (c == 't') - { - token.type = BOOL; - while (std::isalpha(c)) - { - token.value += c; - file.get(c); - } - /* file.seekg(3, std::ios_base::cur); */ - } - else if (c == 'n') - { - token.type = NIL; - file.seekg(3, std::ios_base::cur); - } - else if (c == ',') - token.type = COMMA; - last_token = token.type; - return (token); - } } #endif diff --git a/src/config/parse.cpp b/src/config/parse.cpp index 90e806d..99ca42c 100644 --- a/src/config/parse.cpp +++ b/src/config/parse.cpp @@ -6,10 +6,7 @@ #include #include -#include "TOMLNode.hpp" -#include "TOMLParser.hpp" -#include "Tokenizer.hpp" - +#include "parse.hpp" /* struct location */ /* { */ /* std::string location; */ @@ -41,10 +38,11 @@ namespace config } } -void parse(void) +TOMLMap *parse(void) { std::string filename = "config/simple.toml"; config::TOMLParser parser(filename); TOMLMap *root = parser.parse(); config::display(root); + return (root); } diff --git a/src/config/parse.hpp b/src/config/parse.hpp new file mode 100644 index 0000000..72c0067 --- /dev/null +++ b/src/config/parse.hpp @@ -0,0 +1,13 @@ +#ifndef PARSE_HPP +#define PARSE_HPP + +#include "tomlstuff.hpp" + +#include "Tokenizer.hpp" +#include "TOMLNode.hpp" +#include "TOMLParser.hpp" + +TOMLMap *parse(void); +void display(TOMLMap *config); + +#endif diff --git a/src/config/tomlstuff.hpp b/src/config/tomlstuff.hpp new file mode 100644 index 0000000..d7c7d11 --- /dev/null +++ b/src/config/tomlstuff.hpp @@ -0,0 +1,11 @@ +#ifndef TOMLSTUFF_HPP +#define TOMLSTUFF_HPP + +class toml_node; + +typedef std::map TOMLMap; // = JSONObject +typedef std::vector TOMLMapArray; +typedef std::vector TOMLArray; + +#endif + diff --git a/src/main.cpp b/src/main.cpp index fe93062..d0fc116 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,4 +1,6 @@ #include "webserv.hpp" +#include "parse.hpp" +#include "Server.hpp" int main(int argc, char **argv) { @@ -8,10 +10,8 @@ int main(int argc, char **argv) Server server; server.readConfig(); - server.setupConfig(); - server.start(); - // parse(); - + // server.setupConfig(); + // server.start(); return (0);