]> git.sesse.net Git - cubemap/blob - parse.h
Create $(libdir) on make install.
[cubemap] / parse.h
1 #ifndef _PARSE_H
2 #define _PARSE_H
3
4 // Various routines that deal with parsing; both HTTP requests and more generic text.
5
6 #include <stddef.h>
7 #include <string>
8 #include <algorithm>
9 #include <string>
10 #include <unordered_map>
11 #include <vector>
12
13 // Locale-unaware tolower(); matches RFC 2616 no matter what the locale is set to.
14 static inline char ascii_tolower(const char ch)
15 {
16         if (ch >= 'A' && ch <= 'Z') {
17                 return ch + 'a' - 'A';
18         } else {
19                 return ch;
20         }
21 }
22
23 // Case-insensitive header comparison and hashing.
24 struct HTTPEqual {
25         bool operator() (const std::string &a, const std::string &b) const
26         {
27                 return a.size() == b.size() &&
28                         std::equal(
29                                 begin(a), end(a), begin(b),
30                                 [](char a, char b) {
31                                         return ascii_tolower(a) == ascii_tolower(b);
32                                 });
33         }
34 };
35 struct HTTPHash {
36         size_t operator() (const std::string &s) const
37         {
38                 std::string s_low = s;
39                 for (char &ch : s_low) { ch = ascii_tolower(ch); }
40                 return std::hash<std::string>() (s_low);
41         }
42 };
43 using HTTPHeaderMultimap = std::unordered_multimap<std::string, std::string, HTTPHash, HTTPEqual>;
44
45 // Split a line on whitespace, e.g. "foo  bar baz" -> {"foo", "bar", "baz"}.
46 std::vector<std::string> split_tokens(const std::string &line);
47
48 // Split a string on \n or \r\n, e.g. "foo\nbar\r\n\nbaz\r\n\r\n" -> {"foo", "bar", "baz"}.
49 std::vector<std::string> split_lines(const std::string &str);
50
51 // Extract HTTP headers from a request or response. Ignores the first line,
52 // where the verb or the return code is.
53 HTTPHeaderMultimap extract_headers(const std::vector<std::string> &lines, const std::string &log_context);
54
55 // Add the new data to an existing string, looking for \r\n\r\n
56 // (typical of HTTP requests and/or responses). Will return one
57 // of the given statuses.
58 //
59 // Note that if you give too much data in new_data_size, you could
60 // get an RP_OUT_OF_SPACE even if you expected RP_EXTRA_DATA.
61 // Be careful about how large reads you give in.
62 enum RequestParseStatus {
63         RP_OUT_OF_SPACE,       // If larger than 16 kB.
64         RP_NOT_FINISHED_YET,   // Did not get \r\n\r\n yet. 
65         RP_EXTRA_DATA,         // Got \r\n\r\n, but there was extra data behind it.
66         RP_FINISHED,           // Ended exactly in \r\n\r\n.
67 };
68 RequestParseStatus wait_for_double_newline(std::string *existing_data, const char *new_data, size_t new_data_size);
69
70 #endif  // !defined(_PARSE_H)