|
1 | 1 | #include <datadog/baggage.h> |
2 | 2 |
|
3 | | -#include <sstream> |
| 3 | +#include <cctype> |
4 | 4 |
|
5 | 5 | namespace datadog { |
6 | 6 | namespace tracing { |
7 | 7 |
|
8 | 8 | namespace { |
9 | 9 |
|
10 | | -std::string trim(const std::string& str) { |
11 | | - size_t start = str.find_first_not_of(' '); |
12 | | - size_t end = str.find_last_not_of(' '); |
13 | | - return (start == std::string::npos || end == std::string::npos) |
14 | | - ? "" |
15 | | - : str.substr(start, end - start + 1); |
16 | | -} |
17 | | - |
18 | 10 | Expected<std::unordered_map<std::string, std::string>, Baggage::Error> |
19 | 11 | parse_baggage(StringView input, size_t max_capacity) { |
20 | 12 | std::unordered_map<std::string, std::string> result; |
21 | | - std::stringstream ss(std::string{input}); |
22 | | - std::string pair; |
23 | | - |
24 | | - // Split by commas |
25 | | - while (std::getline(ss, pair, ',')) { |
26 | | - size_t equalPos = pair.find('='); |
| 13 | + if (input.empty()) return result; |
| 14 | + |
| 15 | + enum class state : char { |
| 16 | + leading_spaces_key, |
| 17 | + key, |
| 18 | + leading_spaces_value, |
| 19 | + value |
| 20 | + } internal_state = state::leading_spaces_key; |
| 21 | + |
| 22 | + size_t beg = 0; |
| 23 | + size_t tmp_end = 0; |
| 24 | + |
| 25 | + StringView key; |
| 26 | + StringView value; |
| 27 | + |
| 28 | + const size_t end = input.size(); |
| 29 | + |
| 30 | + for (size_t i = 0; i < end; ++i) { |
| 31 | + switch (internal_state) { |
| 32 | + case state::leading_spaces_key: { |
| 33 | + if (!std::isspace(input[i])) { |
| 34 | + if (result.size() == max_capacity) |
| 35 | + return Baggage::Error::MAXIMUM_CAPACITY_REACHED; |
| 36 | + |
| 37 | + beg = i; |
| 38 | + tmp_end = i; |
| 39 | + internal_state = state::key; |
| 40 | + } |
| 41 | + } break; |
| 42 | + |
| 43 | + case state::key: { |
| 44 | + if (input[i] == ',') { |
| 45 | + return Baggage::Error::MALFORMED_BAGGAGE_HEADER; |
| 46 | + } else if (input[i] == '=') { |
| 47 | + key = StringView{input.data() + beg, tmp_end - beg + 1}; |
| 48 | + internal_state = state::leading_spaces_value; |
| 49 | + } else if (!std::isspace(input[i])) { |
| 50 | + tmp_end = i; |
| 51 | + } |
| 52 | + } break; |
| 53 | + |
| 54 | + case state::leading_spaces_value: { |
| 55 | + if (!std::isspace(input[i])) { |
| 56 | + beg = i; |
| 57 | + tmp_end = i; |
| 58 | + internal_state = state::value; |
| 59 | + } |
| 60 | + } break; |
| 61 | + |
| 62 | + case state::value: { |
| 63 | + if (input[i] == ',') { |
| 64 | + value = StringView{input.data() + beg, tmp_end - beg + 1}; |
| 65 | + result.emplace(std::string(key), std::string(value)); |
| 66 | + beg = i; |
| 67 | + tmp_end = i; |
| 68 | + internal_state = state::leading_spaces_key; |
| 69 | + } else if (!std::isspace(input[i])) { |
| 70 | + tmp_end = i; |
| 71 | + } |
| 72 | + } break; |
| 73 | + } |
| 74 | + } |
27 | 75 |
|
28 | | - if (equalPos == std::string::npos) |
29 | | - return Baggage::Error::MALFORMED_BAGGAGE_HEADER; |
| 76 | + if (internal_state != state::value) { |
| 77 | + return Baggage::Error::MALFORMED_BAGGAGE_HEADER; |
| 78 | + } |
30 | 79 |
|
31 | | - // Extract key and value, then trim spaces |
32 | | - std::string key = trim(pair.substr(0, equalPos)); |
33 | | - if (key.empty()) return Baggage::Error::MALFORMED_BAGGAGE_HEADER; |
34 | | - if (result.size() == max_capacity) |
35 | | - return Baggage::Error::MAXIMUM_CAPACITY_REACHED; |
| 80 | + value = StringView{input.data() + beg, tmp_end - beg + 1}; |
| 81 | + result.emplace(std::string(key), std::string(value)); |
36 | 82 |
|
37 | | - std::string value = trim(pair.substr(equalPos + 1)); |
38 | | - result[key] = value; |
39 | | - } |
40 | 83 | return result; |
41 | 84 | } |
42 | 85 |
|
43 | | -/*constexpr bool is_space(char c) {*/ |
44 | | -/* return c == ' ' || c == '\f' || c == '\n' || c == '\r' || c == '\t' || c == |
45 | | - * '\v';*/ |
46 | | -/*}*/ |
47 | | - |
48 | | -/*Expected<std::unordered_map<std::string, std::string>, Baggage::Error>*/ |
49 | | -/*parse_baggage(StringView input, size_t max_capacity) {*/ |
50 | | -/* enum class state : char {*/ |
51 | | -/* swallow,*/ |
52 | | -/* key,*/ |
53 | | -/* value*/ |
54 | | -/* } internal_state = state::swallow;*/ |
55 | | -/**/ |
56 | | -/* std::unordered_map<std::string, std::string> result;*/ |
57 | | -/**/ |
58 | | -/* size_t beg = 0;*/ |
59 | | -/* size_t tmp_end = 0;*/ |
60 | | -/**/ |
61 | | -/* StringView key;*/ |
62 | | -/* StringView value;*/ |
63 | | -/**/ |
64 | | -/* const size_t end = input.size();*/ |
65 | | -/**/ |
66 | | -/* for (size_t i = 0; i < end; ++i) {*/ |
67 | | -/* switch(internal_state) {*/ |
68 | | -/* case state::swallow: {*/ |
69 | | -/* if (!is_space(input[i])) {*/ |
70 | | -/* beg = i;*/ |
71 | | -/* internal_state = state::key;*/ |
72 | | -/* }*/ |
73 | | -/* } break;*/ |
74 | | -/**/ |
75 | | -/* case state::key: {*/ |
76 | | -/* if (input[i] == '=') {*/ |
77 | | -/* if (result.size() == max_capacity) return |
78 | | - * Baggage::Error::MAXIMUM_CAPACITY_REACHED;*/ |
79 | | -/**/ |
80 | | -/* key = StringView{input.data() + beg, tmp_end - beg};*/ |
81 | | -/* beg = i;*/ |
82 | | -/* tmp_end = i;*/ |
83 | | -/* internal_state = state::value;*/ |
84 | | -/* } else if (!is_space(input[i])) {*/ |
85 | | -/* tmp_end = i;*/ |
86 | | -/* }*/ |
87 | | -/* } break;*/ |
88 | | -/**/ |
89 | | -/* case state::value: {*/ |
90 | | -/* if (input[i] == ',') {*/ |
91 | | -/* value = StringView{input.data() + beg, tmp_end - beg};*/ |
92 | | -/* result.emplace(std::string(key), std::string(value));*/ |
93 | | -/* beg = i;*/ |
94 | | -/* tmp_end = i;*/ |
95 | | -/* internal_state = state::swallow;*/ |
96 | | -/* } else if (!is_space(input[i])) {*/ |
97 | | -/* tmp_end = i;*/ |
98 | | -/* }*/ |
99 | | -/* } break;*/ |
100 | | -/**/ |
101 | | -/* }*/ |
102 | | -/* }*/ |
103 | | -/**/ |
104 | | -/* if (internal_state != state::value) {*/ |
105 | | -/* return Baggage::Error::MALFORMED_BAGGAGE_HEADER;*/ |
106 | | -/* }*/ |
107 | | -/**/ |
108 | | -/* value = StringView{input.data() + beg, tmp_end - beg};*/ |
109 | | -/* result.emplace(std::string(key), std::string(value));*/ |
110 | | -/**/ |
111 | | -/* return result;*/ |
112 | | -/*}*/ |
113 | | - |
114 | 86 | } // namespace |
115 | 87 |
|
116 | 88 | Baggage::Baggage(size_t max_capacity) : max_capacity_(max_capacity) {} |
|
0 commit comments