๐Ÿ A very simple static Gemini server, now with Titan support!
cpp gemini titan gemini-protocol titan-protocol
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

format(maple): clang-format llvm style

Fuwn 7a93a670 4ce89095

+251 -296
+18 -22
maple/gemini.cc
··· 23 23 24 24 #include "gemini.hh" 25 25 26 - namespace maple::gemini { 27 - auto handle_client( 28 - std::vector<std::string> gemini_files, 29 - std::string path, 30 - std::stringstream &response 31 - ) -> void { 32 - // Check if the route is a file being served 33 - if (std::find( 34 - gemini_files.begin(), 35 - gemini_files.end(), 36 - ".maple/gmi" + path 37 - ) != gemini_files.end()) { 38 - // If the route is a file being served; get the file contents 26 + namespace maple { 27 + namespace gemini { 28 + auto handle_client(std::vector<std::string> gemini_files, std::string path, 29 + std::stringstream &response) -> void { 30 + // Check if the route is a file being served 31 + if (std::find(gemini_files.begin(), gemini_files.end(), 32 + ".maple/gmi" + path) != gemini_files.end()) { 33 + // If the route is a file being served; get the file contents 34 + response << "20 text/gemini\r\n" 35 + << std::ifstream(".maple/gmi" + path).rdbuf(); 36 + } else { 37 + if (path.empty() || path.at(path.length() - 1) == '/') { 39 38 response << "20 text/gemini\r\n" 40 - << std::ifstream(".maple/gmi" + path).rdbuf(); 39 + << std::ifstream(".maple/gmi" + path + "index.gmi").rdbuf(); 41 40 } else { 42 - if (path.empty() || path.at(path.length() - 1) == '/') { 43 - response << "20 text/gemini\r\n" 44 - << std::ifstream(".maple/gmi" + path + "index.gmi").rdbuf(); 45 - } else { 46 - response 41 + response 47 42 << "51 The server (Maple) could not find the specified file.\r\n"; 48 - } 49 43 } 50 - 51 - std::cout << "requested " << path << std::endl; 52 44 } 45 + 46 + std::cout << "requested " << path << std::endl; 53 47 } 48 + } // namespace gemini 49 + } // namespace maple
+5 -6
maple/gemini.hh
··· 24 24 #include <sstream> 25 25 #include <vector> 26 26 27 - namespace maple::gemini { 28 - auto handle_client( 29 - std::vector<std::string>, 30 - std::string, 31 - std::stringstream & 32 - ) -> void; 27 + namespace maple { 28 + namespace gemini { 29 + auto handle_client(std::vector<std::string>, std::string, std::stringstream &) 30 + -> void; 33 31 } 32 + } // namespace maple 34 33 35 34 #endif // GEMINI_HH
+107 -139
maple/maple.cc
··· 54 54 55 55 // Find and keep track of all Gemini files to serve 56 56 for (const std::filesystem::directory_entry &entry : 57 - std::filesystem::recursive_directory_iterator(".maple/gmi")) 58 - { 57 + std::filesystem::recursive_directory_iterator(".maple/gmi")) { 59 58 std::string file_extension = entry.path().string().substr( 60 - entry.path().string().find_last_of('.') + 1 61 - ); 59 + entry.path().string().find_last_of('.') + 1); 62 60 63 61 // Only keep track of file if it is a Gemini file 64 - if (std::equal( 65 - file_extension.begin(), 66 - file_extension.end(), 67 - GEMINI_FILE_EXTENSION.begin(), 68 - GEMINI_FILE_EXTENSION.end(), 69 - [](char a, char b) -> bool { return std::tolower(a) == std::tolower(b); } 70 - )) { 62 + if (std::equal(file_extension.begin(), file_extension.end(), 63 + GEMINI_FILE_EXTENSION.begin(), GEMINI_FILE_EXTENSION.end(), 64 + [](char a, char b) -> bool { 65 + return std::tolower(a) == std::tolower(b); 66 + })) { 71 67 gemini_files.push_back(entry.path()); 72 68 } 73 69 } ··· 78 74 } 79 75 80 76 // Setup SSL 81 - if (maple::setup_ssl() == EXIT_FAILURE) { return EXIT_FAILURE; } 77 + if (maple::setup_ssl() == EXIT_FAILURE) { 78 + return EXIT_FAILURE; 79 + } 82 80 83 81 // Listen and serve connections 84 82 for (;;) { 85 - sockaddr_in socket_address_ {}; 83 + sockaddr_in socket_address_{}; 86 84 unsigned int socket_address_length = sizeof(socket_address_); 87 85 SSL *ssl; 88 - int client = accept( 89 - maple::maple_socket, 90 - reinterpret_cast<sockaddr *>(&socket_address_), 91 - &socket_address_length 92 - ); 86 + int client = accept(maple::maple_socket, 87 + reinterpret_cast<sockaddr *>(&socket_address_), 88 + &socket_address_length); 93 89 94 90 if (client < 0) { 95 91 return maple::prepare_exit_with("unable to accept", false); ··· 106 102 size_t index_of_junk; 107 103 int request_scheme; // Gemini = 1, Titan = 2, Error = 0 108 104 size_t bytes_read; 109 - char request[1024] {}; 105 + char request[1024]{}; 110 106 111 107 SSL_read_ex(ssl, request, sizeof(request), &bytes_read); 112 108 ··· 139 135 size_t found_first = path.find_first_of('/'); 140 136 141 137 if (found_first != std::string::npos) { 142 - path = path.substr( 143 - found_first, 144 - path.size() - 1 145 - ); // Remove host 138 + path = path.substr(found_first, 139 + path.size() - 1); // Remove host 146 140 } else { 147 141 path = "/index.gmi"; 148 142 } ··· 152 146 index_of_junk = path.find_first_of('\n'); 153 147 154 148 if (index_of_junk != std::string::npos) { 155 - path.erase( 156 - path.find_first_of('\n') - 1, 157 - path.size() - 1 158 - ); 149 + path.erase(path.find_first_of('\n') - 1, path.size() - 1); 159 150 } 160 151 } 161 152 ··· 167 158 response << "20 text/gemini\r\nThe server (Maple) does not have " 168 159 "Titan support enabled!"; 169 160 } else { 170 - maple::titan::handle_client( 171 - response, 172 - path, 173 - titan_token, 174 - titan_max_size 175 - ); 161 + maple::titan::handle_client(response, path, titan_token, 162 + titan_max_size); 176 163 } 177 164 } 178 165 179 - SSL_write( 180 - ssl, 181 - response.str().c_str(), 182 - static_cast<int>(response.str().size()) 183 - ); 166 + SSL_write(ssl, response.str().c_str(), 167 + static_cast<int>(response.str().size())); 184 168 } else { 185 169 std::cout << "received a request with an unsupported url scheme" 186 - << std::endl; 170 + << std::endl; 187 171 } 188 172 } 189 173 ··· 194 178 } 195 179 196 180 namespace maple { 197 - auto prepare_exit_with(const char *message, bool ssl) -> int { 198 - perror(message); 199 - 200 - if (ssl) { ERR_print_errors_fp(stderr); } 181 + auto prepare_exit_with(const char *message, bool ssl) -> int { 182 + perror(message); 201 183 202 - return EXIT_FAILURE; 184 + if (ssl) { 185 + ERR_print_errors_fp(stderr); 203 186 } 204 187 205 - auto setup_environment( 206 - bool &titan, 207 - std::string &titan_token, 208 - size_t &titan_max_size 209 - ) -> int { 210 - char *titan_environment = std::getenv("TITAN"); 188 + return EXIT_FAILURE; 189 + } 211 190 212 - if (titan_environment == nullptr) { 213 - titan = false; 214 - } else { 215 - std::string valid_titan_environment(titan_environment); 191 + auto setup_environment(bool &titan, std::string &titan_token, 192 + size_t &titan_max_size) -> int { 193 + char *titan_environment = std::getenv("TITAN"); 216 194 217 - std::transform( 218 - valid_titan_environment.begin(), 219 - valid_titan_environment.end(), 220 - valid_titan_environment.begin(), 221 - [](unsigned char c) -> int { return std::tolower(c); } 222 - ); 195 + if (titan_environment == nullptr) { 196 + titan = false; 197 + } else { 198 + std::string valid_titan_environment(titan_environment); 223 199 224 - if (valid_titan_environment == "true" || valid_titan_environment == "1") { 225 - char *unvalidated_titan_token = std::getenv("TITAN_TOKEN"); 226 - char *unvalidated_titan_max_size = std::getenv("TITAN_MAX_SIZE"); 200 + std::transform(valid_titan_environment.begin(), 201 + valid_titan_environment.end(), 202 + valid_titan_environment.begin(), 203 + [](unsigned char c) -> int { return std::tolower(c); }); 227 204 228 - if (unvalidated_titan_token == nullptr) { 229 - titan_token = ""; 230 - } else { 231 - titan_token = std::string(unvalidated_titan_token); 232 - } 205 + if (valid_titan_environment == "true" || valid_titan_environment == "1") { 206 + char *unvalidated_titan_token = std::getenv("TITAN_TOKEN"); 207 + char *unvalidated_titan_max_size = std::getenv("TITAN_MAX_SIZE"); 233 208 234 - if (unvalidated_titan_max_size == nullptr) { 235 - titan_max_size = 1024; 209 + if (unvalidated_titan_token == nullptr) { 210 + titan_token = ""; 211 + } else { 212 + titan_token = std::string(unvalidated_titan_token); 213 + } 236 214 237 - std::cout << "no TITAN_MAX_SIZE set, defaulting to 1024" << std::endl; 238 - } else { 239 - try { 240 - titan_max_size = static_cast<size_t>( 241 - std::stoi(unvalidated_titan_max_size) 242 - ); 243 - } catch (...) { 244 - return maple::prepare_exit_with( 245 - "TITAN_MAX_SIZE could not be interpreted as an integer", 246 - false 247 - ); 248 - } 215 + if (unvalidated_titan_max_size == nullptr) { 216 + titan_max_size = 1024; 217 + 218 + std::cout << "no TITAN_MAX_SIZE set, defaulting to 1024" << std::endl; 219 + } else { 220 + try { 221 + titan_max_size = 222 + static_cast<size_t>(std::stoi(unvalidated_titan_max_size)); 223 + } catch (...) { 224 + return maple::prepare_exit_with( 225 + "TITAN_MAX_SIZE could not be interpreted as an integer", false); 249 226 } 250 - 251 - titan = true; 252 227 } 253 - } 254 228 255 - return 0; 229 + titan = true; 230 + } 256 231 } 257 232 258 - auto setup_ssl() -> int { 259 - sockaddr_in socket_address {}; 233 + return 0; 234 + } 260 235 261 - // Setup OpenSSL 262 - SSL_library_init(); 263 - SSL_load_error_strings(); 236 + auto setup_ssl() -> int { 237 + sockaddr_in socket_address{}; 264 238 265 - maple::ssl_context = SSL_CTX_new(TLS_server_method()); 239 + // Setup OpenSSL 240 + SSL_library_init(); 241 + SSL_load_error_strings(); 242 + 243 + maple::ssl_context = SSL_CTX_new(TLS_server_method()); 244 + 245 + if (!maple::ssl_context) { 246 + return maple::prepare_exit_with("unable to create ssl context", true); 247 + } 248 + 249 + if (SSL_CTX_use_certificate_file(maple::ssl_context, ".maple/public.pem", 250 + SSL_FILETYPE_PEM) <= 0) { 251 + return maple::prepare_exit_with("unable to use certificate file", true); 252 + } 266 253 267 - if (!maple::ssl_context) { 268 - return maple::prepare_exit_with("unable to create ssl context", true); 269 - } 254 + if (SSL_CTX_use_PrivateKey_file(maple::ssl_context, ".maple/private.pem", 255 + SSL_FILETYPE_PEM) <= 0) { 256 + return maple::prepare_exit_with("unable to use private key file", true); 257 + } 270 258 271 - if (SSL_CTX_use_certificate_file( 272 - maple::ssl_context, 273 - ".maple/public.pem", 274 - SSL_FILETYPE_PEM 275 - ) <= 0) { 276 - return maple::prepare_exit_with("unable to use certificate file", true); 277 - } 278 - if (SSL_CTX_use_PrivateKey_file( 279 - maple::ssl_context, 280 - ".maple/private.pem", 281 - SSL_FILETYPE_PEM 282 - ) <= 0) { 283 - return maple::prepare_exit_with("unable to use private key file", true); 284 - } 259 + socket_address.sin_family = AF_INET; 260 + socket_address.sin_port = htons(1965); 261 + socket_address.sin_addr.s_addr = htonl(INADDR_ANY); 285 262 286 - socket_address.sin_family = AF_INET; 287 - socket_address.sin_port = htons(1965); 288 - socket_address.sin_addr.s_addr = htonl(INADDR_ANY); 263 + maple::maple_socket = socket(AF_INET, SOCK_STREAM, 0); 289 264 290 - maple::maple_socket = socket(AF_INET, SOCK_STREAM, 0); 265 + if (maple::maple_socket < 0) { 266 + return maple::prepare_exit_with("unable to create socket", false); 267 + } 291 268 292 - if (maple::maple_socket < 0) { 293 - return maple::prepare_exit_with("unable to create socket", false); 294 - } 269 + // Reuse address. Allows the use of the address instantly after a SIGINT 270 + // without having to wait for the socket to die. 271 + int reuse_addr = 1; 295 272 296 - // Reuse address. Allows the use of the address instantly after a SIGINT 297 - // without having to wait for the socket to die. 298 - int reuse_addr = 1; 299 - if (setsockopt( 300 - maple::maple_socket, 301 - SOL_SOCKET, 302 - SO_REUSEADDR, 303 - &reuse_addr, 304 - sizeof(int) 305 - ) < 0) { 306 - return maple::prepare_exit_with("unable to set socket options (SO_LINGER)", false); 307 - } 273 + if (setsockopt(maple::maple_socket, SOL_SOCKET, SO_REUSEADDR, &reuse_addr, 274 + sizeof(int)) < 0) { 275 + return maple::prepare_exit_with("unable to set socket options (SO_LINGER)", 276 + false); 277 + } 308 278 309 - if (bind( 310 - maple::maple_socket, 311 - reinterpret_cast<sockaddr *>(&socket_address), 312 - sizeof(socket_address) 313 - ) < 0) { 314 - return maple::prepare_exit_with("unable to bind", false); 315 - } 316 - if (listen(maple::maple_socket, 1) < 0) { 317 - return maple::prepare_exit_with("unable to listen", false); 318 - } 279 + if (bind(maple::maple_socket, reinterpret_cast<sockaddr *>(&socket_address), 280 + sizeof(socket_address)) < 0) { 281 + return maple::prepare_exit_with("unable to bind", false); 282 + } 319 283 320 - return 0; 284 + if (listen(maple::maple_socket, 1) < 0) { 285 + return maple::prepare_exit_with("unable to listen", false); 321 286 } 287 + 288 + return 0; 322 289 } 290 + } // namespace maple
+7 -6
maple/maple.hh
··· 22 22 #define MAPLE_HH 23 23 24 24 #include <openssl/ssl.h> 25 + #include <string> 25 26 26 27 namespace maple { 27 - static int maple_socket; 28 - static SSL_CTX *ssl_context; 28 + static int maple_socket; 29 + static SSL_CTX *ssl_context; 29 30 30 - auto prepare_exit_with(const char *, bool) -> int; 31 - auto setup_environment(bool &, std::string &, size_t &) -> int; 32 - auto setup_ssl() -> int; 33 - } 31 + auto prepare_exit_with(const char *, bool) -> int; 32 + auto setup_environment(bool &, std::string &, size_t &) -> int; 33 + auto setup_ssl() -> int; 34 + } // namespace maple 34 35 35 36 #endif // MAPLE_HH
+103 -111
maple/titan.cc
··· 18 18 * SPDX-License-Identifier: GPL-3.0-only 19 19 */ 20 20 21 - #include <map> 22 21 #include <fstream> 22 + #include <map> 23 23 #include <vector> 24 24 25 25 #include "titan.hh" 26 26 27 - namespace maple::titan { 28 - auto parameters_to_map( 29 - const std::vector<std::string> &parameters 30 - ) -> std::map<std::string, std::string> { 31 - std::map<std::string, std::string> parameters_map; 27 + namespace maple { 28 + namespace titan { 29 + auto parameters_to_map(const std::vector<std::string> &parameters) 30 + -> std::map<std::string, std::string> { 31 + std::map<std::string, std::string> parameters_map; 32 32 33 - for (auto parameter : parameters) { 34 - // Find the key in `parameter` 35 - size_t parameter_delimiter_position = parameter.find('='); 36 - std::string key = parameter.substr( 37 - 0, 38 - parameter_delimiter_position 39 - ); 33 + for (auto parameter : parameters) { 34 + // Find the key in `parameter` 35 + size_t parameter_delimiter_position = parameter.find('='); 36 + std::string key = parameter.substr(0, parameter_delimiter_position); 40 37 41 - // Remove the key in `parameter` 42 - parameter.erase(0, parameter_delimiter_position + 1); 43 - 44 - // Add the key and value to `parameters_map` 45 - parameters_map[key] = parameter; 46 - } 38 + // Remove the key in `parameter` 39 + parameter.erase(0, parameter_delimiter_position + 1); 47 40 48 - return parameters_map; 41 + // Add the key and value to `parameters_map` 42 + parameters_map[key] = parameter; 49 43 } 50 44 51 - auto handle_client( 52 - std::stringstream &response, 53 - std::string path, 54 - const std::string &titan_token, 55 - size_t titan_max_size 56 - ) -> void { 57 - std::vector<std::string> parameters; 58 - // Find path in `path` 59 - size_t delimiter_position = path.find(';'); 60 - std::string update_path = path.substr(0, delimiter_position); 61 - std::string body = path.substr(path.find('\n') + 1, path.length() - 1); 45 + return parameters_map; 46 + } 62 47 63 - path.erase(path.find('\n') - 1, path.length() - 1); 64 - // parameters.push_back(update_path); 65 - path.erase(0, delimiter_position + 1); // Remove path from `path` 48 + auto handle_client(std::stringstream &response, std::string path, 49 + const std::string &titan_token, size_t titan_max_size) 50 + -> void { 51 + std::vector<std::string> parameters; 52 + // Find path in `path` 53 + size_t delimiter_position = path.find(';'); 54 + std::string update_path = path.substr(0, delimiter_position); 55 + std::string body = path.substr(path.find('\n') + 1, path.length() - 1); 66 56 67 - // Find mime parameter in `path` 68 - delimiter_position = path.find(';'); 57 + path.erase(path.find('\n') - 1, path.length() - 1); 58 + // parameters.push_back(update_path); 59 + path.erase(0, delimiter_position + 1); // Remove path from `path` 69 60 70 - parameters.push_back(path.substr(0, delimiter_position)); 71 - path.erase(0, delimiter_position + 1); // Remove mime parameter from `path` 61 + // Find mime parameter in `path` 62 + delimiter_position = path.find(';'); 72 63 73 - // Find size parameter in `path` 74 - delimiter_position = path.find(';'); 64 + parameters.push_back(path.substr(0, delimiter_position)); 65 + path.erase(0, delimiter_position + 1); // Remove mime parameter from `path` 75 66 76 - parameters.push_back(path.substr(0, delimiter_position)); 67 + // Find size parameter in `path` 68 + delimiter_position = path.find(';'); 77 69 78 - // Find token parameter in `path` 79 - delimiter_position = path.find(';'); 70 + parameters.push_back(path.substr(0, delimiter_position)); 80 71 81 - // Since the token is optional, only get and assign the token 82 - // parameters value if it exists. 83 - if (delimiter_position != std::string::npos) { 84 - parameters.push_back(path.substr( 85 - delimiter_position + 1, 86 - path.length() - 1 87 - )); 88 - } 72 + // Find token parameter in `path` 73 + delimiter_position = path.find(';'); 89 74 90 - /// Check if a parameter exists within a `std::vector` of Titan 91 - /// parameters. 92 - /* auto parameter_exists = []( 93 - const std::vector<std::string> &_parameters, 94 - const std::string &parameter 95 - ) -> bool { 96 - return std::any_of( 97 - _parameters.begin(), 98 - _parameters.end(), 99 - [&](const std::string &s) -> bool { 100 - return s.find(parameter) != std::string::npos; 101 - } 102 - ); 103 - }; */ 75 + // Since the token is optional, only get and assign the token 76 + // parameters value if it exists. 77 + if (delimiter_position != std::string::npos) { 78 + parameters.push_back( 79 + path.substr(delimiter_position + 1, path.length() - 1)); 80 + } 104 81 105 - std::map<std::string, std::string> parameters_map = 82 + /// Check if a parameter exists within a `std::vector` of Titan 83 + /// parameters. 84 + /* auto parameter_exists = []( 85 + const std::vector<std::string> &_parameters, 86 + const std::string &parameter 87 + ) -> bool { 88 + return std::any_of( 89 + _parameters.begin(), 90 + _parameters.end(), 91 + [&](const std::string &s) -> bool { 92 + return s.find(parameter) != std::string::npos; 93 + } 94 + ); 95 + }; */ 96 + 97 + std::map<std::string, std::string> parameters_map = 106 98 maple::titan::parameters_to_map(parameters); 107 99 108 - // Make sure all tokens have been supplied 109 - for (;;) { 110 - if (parameters_map.find("mime") == parameters_map.end()) { 111 - response << "20 text/gemini\r\nThe serve (Maple) did not " 112 - "receive a mime parameter!"; 113 - break; 114 - } 115 - if (parameters_map.find("size") == parameters_map.end()) { 116 - response << "20 text/gemini\r\nThe serve (Maple) did not " 117 - "receive a size parameter!"; 100 + // Make sure all tokens have been supplied 101 + for (;;) { 102 + if (parameters_map.find("mime") == parameters_map.end()) { 103 + response << "20 text/gemini\r\nThe serve (Maple) did not " 104 + "receive a mime parameter!"; 105 + break; 106 + } 118 107 119 - break; 120 - } 121 - if (!titan_token.empty() 122 - && parameters_map.find("token") == parameters_map.end()) 123 - { 124 - response << "20 text/gemini\r\nThe serve (Maple) did not " 125 - "receive a token parameter!"; 108 + if (parameters_map.find("size") == parameters_map.end()) { 109 + response << "20 text/gemini\r\nThe serve (Maple) did not " 110 + "receive a size parameter!"; 111 + 112 + break; 113 + } 126 114 127 - break; 128 - } 115 + if (!titan_token.empty() && 116 + parameters_map.find("token") == parameters_map.end()) { 117 + response << "20 text/gemini\r\nThe serve (Maple) did not " 118 + "receive a token parameter!"; 129 119 130 - try { 131 - size_t body_size = static_cast<size_t>( 132 - std::stoi(parameters_map["size"]) 133 - ); 120 + break; 121 + } 134 122 135 - if (body_size > titan_max_size) { 136 - response << "20 text/gemini\r\nThe server (Maple) received a body " 137 - << "which is larger than the maximum allowed body size (" 138 - << titan_max_size << ")."; 123 + try { 124 + size_t body_size = static_cast<size_t>(std::stoi(parameters_map["size"])); 139 125 140 - break; 141 - } 142 - } catch (...) { 143 - response << "20 text/gemini\r\nThe server (Maple) could not interpret " 144 - "the size parameter as an integer!"; 126 + if (body_size > titan_max_size) { 127 + response << "20 text/gemini\r\nThe server (Maple) received a body " 128 + << "which is larger than the maximum allowed body size (" 129 + << titan_max_size << ")."; 145 130 146 131 break; 147 132 } 133 + } catch (...) { 134 + response << "20 text/gemini\r\nThe server (Maple) could not interpret " 135 + "the size parameter as an integer!"; 148 136 149 - if (update_path == "/") { 150 - update_path = "/index.gmi"; 151 - } 137 + break; 138 + } 152 139 153 - if (parameters_map["token"] == titan_token) { 154 - std::ofstream file(".maple/gmi" + update_path); 140 + if (update_path == "/") { 141 + update_path = "/index.gmi"; 142 + } 155 143 156 - file << body; 144 + if (parameters_map["token"] == titan_token) { 145 + std::ofstream file(".maple/gmi" + update_path); 157 146 158 - response << "20 text/gemini\r\nSuccessfully wrote " 159 - << body.length() << " bytes to " << update_path << '!'; 160 - } else { 161 - response << "20 text/gemini\r\nThe server (Maple) wrote to " 162 - << update_path; 163 - } 147 + file << body; 164 148 165 - break; 149 + response << "20 text/gemini\r\nSuccessfully wrote " << body.length() 150 + << " bytes to " << update_path << '!'; 151 + } else { 152 + response << "20 text/gemini\r\nThe server (Maple) wrote to " 153 + << update_path; 166 154 } 155 + 156 + break; 167 157 } 168 158 } 159 + } // namespace titan 160 + } // namespace maple
+11 -12
maple/titan.hh
··· 21 21 #ifndef TITAN_HH 22 22 #define TITAN_HH 23 23 24 + #include <map> 24 25 #include <sstream> 26 + #include <vector> 25 27 26 - namespace maple::titan { 27 - /// Convert a `std::vector` of Titan parameters into a key/ value `std::map` 28 - auto parameters_to_map( 29 - const std::vector<std::string> & 30 - ) -> std::map<std::string, std::string>; 28 + namespace maple { 29 + namespace titan { 30 + /// Convert a `std::vector` of Titan parameters into a key/ value `std::map` 31 + auto parameters_to_map(const std::vector<std::string> &) 32 + -> std::map<std::string, std::string>; 31 33 32 - auto handle_client( 33 - std::stringstream &, 34 - std::string, 35 - const std::string &, 36 - size_t 37 - ) -> void; 38 - } 34 + auto handle_client(std::stringstream &, std::string, const std::string &, 35 + size_t) -> void; 36 + } // namespace titan 37 + } // namespace maple 39 38 40 39 #endif // TITAN_HH