]> git.sesse.net Git - cubemap/blobdiff - parse.cpp
Replace map with unordered_map nearly everywhere, for speed.
[cubemap] / parse.cpp
index d8706d3e4ec65ca999f505420c032cd57af139a7..bec742b8897e850795d2720fc4ab79cdf27e2628 100644 (file)
--- a/parse.cpp
+++ b/parse.cpp
@@ -1,11 +1,9 @@
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
 #include <ctype.h>
-#include <assert.h>
-#include <vector>
+#include <string.h>
 #include <string>
+#include <vector>
 
+#include "log.h"
 #include "parse.h"
 
 using namespace std;
@@ -58,118 +56,30 @@ vector<string> split_lines(const string &str)
        return ret;
 }
 
-vector<ConfigLine> parse_config(const string &filename)
+unordered_multimap<string, string> extract_headers(const vector<string> &lines, const string &log_context)
 {
-       vector<ConfigLine> ret;
-
-       FILE *fp = fopen(filename.c_str(), "r");
-       if (fp == NULL) {
-               perror(filename.c_str());
-               exit(1);
-       }
-
-       char buf[4096];
-       while (!feof(fp)) {
-               if (fgets(buf, sizeof(buf), fp) == NULL) {
-                       break;
-               }
-
-               // Chop off the string at the first #, \r or \n.
-               buf[strcspn(buf, "#\r\n")] = 0;
-
-               // Remove all whitespace from the end of the string.
-               size_t len = strlen(buf);
-               while (len > 0 && isspace(buf[len - 1])) {
-                       buf[--len] = 0;
-               }
-
-               // If the line is now all blank, ignore it.
-               if (len == 0) {
+       unordered_multimap<string, string> parameters;
+       for (size_t i = 1; i < lines.size(); ++i) {
+               size_t split = lines[i].find(":");
+               if (split == string::npos) {
+                       log(WARNING, "[%s] Ignoring malformed HTTP response line '%s'",
+                               log_context.c_str(), lines[i].c_str());
                        continue;
                }
 
-               vector<string> tokens = split_tokens(buf);
-               assert(!tokens.empty());
-               
-               ConfigLine line;
-               line.keyword = tokens[0];
-
-               for (size_t i = 1; i < tokens.size(); ++i) {
-                       // foo=bar is a parameter; anything else is an argument.
-                       size_t equals_pos = tokens[i].find_first_of('=');
-                       if (equals_pos == string::npos) {
-                               line.arguments.push_back(tokens[i]);
-                       } else {
-                               string key = tokens[i].substr(0, equals_pos);
-                               string value = tokens[i].substr(equals_pos + 1, string::npos);
-                               line.parameters.insert(make_pair(key, value));
-                       }
-               }
+               string key(lines[i].begin(), lines[i].begin() + split);
 
-               ret.push_back(line);
-       }
+               // Skip any spaces after the colon.
+               do {
+                       ++split;
+               } while (split < lines[i].size() && (lines[i][split] == ' ' || lines[i][split] == '\t'));
 
-       fclose(fp);
-       return ret;
-}
+               string value(lines[i].begin() + split, lines[i].end());
 
-string fetch_config_string(const vector<ConfigLine> &config, const string &keyword,
-                           ParameterType parameter_type, const string &default_value)
-{
-       assert(parameter_type == PARAMATER_MANDATORY || parameter_type == PARAMETER_OPTIONAL);
-       for (unsigned i = 0; i < config.size(); ++i) {
-               if (config[i].keyword != keyword) {
-                       continue;
-               }
-               if (config[i].parameters.size() > 0 ||
-                   config[i].arguments.size() != 1) {
-                       fprintf(stderr, "ERROR: '%s' takes one argument and no parameters\n", keyword.c_str());
-                       exit(1);
-               }
-               return config[i].arguments[0];
-       }
-       if (parameter_type == PARAMATER_MANDATORY) {
-               fprintf(stderr, "ERROR: Missing '%s' statement in config file.\n",
-                       keyword.c_str());
-               exit(1);
-       } else {
-               return default_value;
+               parameters.insert(make_pair(key, value));
        }
-}
 
-int fetch_config_int(const std::vector<ConfigLine> &config, const std::string &keyword,
-                     int min_limit, int max_limit,
-                     ParameterType parameter_type, int default_value)
-{
-       assert(parameter_type == PARAMATER_MANDATORY || parameter_type == PARAMETER_OPTIONAL);
-       bool value_found = false;
-       int value = -1;
-       for (unsigned i = 0; i < config.size(); ++i) {
-               if (config[i].keyword != keyword) {
-                       continue;
-               }
-               if (config[i].parameters.size() > 0 ||
-                   config[i].arguments.size() != 1) {
-                       fprintf(stderr, "ERROR: '%s' takes one argument and no parameters\n", keyword.c_str());
-                       exit(1);
-               }
-               value_found = true;
-               value = atoi(config[i].arguments[0].c_str());  // TODO: verify int validity.
-       }
-       if (!value_found) {
-               if (parameter_type == PARAMETER_OPTIONAL) {
-                       return default_value;
-               }
-               fprintf(stderr, "ERROR: Missing '%s' statement in config file.\n",
-                       keyword.c_str());
-               exit(1);
-       }
-       if (value < min_limit || value > max_limit) {
-               fprintf(stderr, "ERROR: '%s' is set to %d, must be in [%d,%d]\n",
-                       keyword.c_str(), value, min_limit, max_limit);
-               exit(1);
-       }
-       return value;
+       return parameters;
 }
 
 #define MAX_REQUEST_SIZE 16384  /* 16 kB. */
@@ -190,7 +100,7 @@ RequestParseStatus wait_for_double_newline(string *existing_data, const char *ne
        const char *ptr = reinterpret_cast<char *>(
                memmem(existing_data->data() + start_at, existing_data->size() - start_at,
                       "\r\n\r\n", 4));
-       if (ptr == NULL) {
+       if (ptr == nullptr) {
                return RP_NOT_FINISHED_YET;
        }
        if (ptr != existing_data->data() + existing_data->size() - 4) {