OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "mojo/public/cpp/bindings/tests/validation_test_input_parser.h" | 5 #include "mojo/public/cpp/bindings/tests/validation_test_input_parser.h" |
6 | 6 |
7 #include <assert.h> | 7 #include <assert.h> |
8 #include <stdio.h> | 8 #include <stdio.h> |
9 #include <string.h> | 9 #include <string.h> |
10 | 10 |
11 #include <limits> | 11 #include <limits> |
12 #include <map> | 12 #include <map> |
13 #include <utility> | 13 #include <utility> |
14 | 14 |
15 #include "mojo/public/c/system/macros.h" | 15 #include "mojo/public/c/system/macros.h" |
16 | 16 |
17 namespace mojo { | 17 namespace mojo { |
18 namespace test { | 18 namespace test { |
19 namespace { | 19 namespace { |
20 | 20 |
21 class ValidationTestInputParser { | 21 class ValidationTestInputParser { |
22 public: | 22 public: |
23 ValidationTestInputParser(const std::string& input, | 23 ValidationTestInputParser(const std::string& input, |
24 std::vector<uint8_t>* parsed_input, | 24 std::vector<uint8_t>* data, |
| 25 size_t* num_handles, |
25 std::string* error_message); | 26 std::string* error_message); |
26 ~ValidationTestInputParser(); | 27 ~ValidationTestInputParser(); |
27 | 28 |
28 bool Run(); | 29 bool Run(); |
29 | 30 |
30 private: | 31 private: |
31 struct DataType; | 32 struct DataType; |
32 | 33 |
33 typedef std::pair<const char*, const char*> Range; | 34 typedef std::pair<const char*, const char*> Range; |
34 | 35 |
35 typedef bool (ValidationTestInputParser::*ParseDataFunc)( | 36 typedef bool (ValidationTestInputParser::*ParseDataFunc)( |
36 const DataType& type, const std::string& value_string); | 37 const DataType& type, const std::string& value_string); |
37 | 38 |
38 struct DataType { | 39 struct DataType { |
39 const char* name; | 40 const char* name; |
40 size_t name_size; | 41 size_t name_size; |
41 size_t data_size; | 42 size_t data_size; |
42 ParseDataFunc parse_data_func; | 43 ParseDataFunc parse_data_func; |
43 }; | 44 }; |
44 | 45 |
45 // A dist4/8 item that hasn't been matched with an anchr item. | 46 // A dist4/8 item that hasn't been matched with an anchr item. |
46 struct PendingDistanceItem { | 47 struct PendingDistanceItem { |
47 // Where this data item is located in |parsed_input_|. | 48 // Where this data item is located in |data_|. |
48 size_t pos; | 49 size_t pos; |
49 // Either 4 or 8 (bytes). | 50 // Either 4 or 8 (bytes). |
50 size_t data_size; | 51 size_t data_size; |
51 }; | 52 }; |
52 | 53 |
53 bool GetNextItem(Range* range); | 54 bool GetNextItem(Range* range); |
54 | 55 |
55 bool ParseItem(const Range& range); | 56 bool ParseItem(const Range& range); |
56 | 57 |
57 bool ParseUnsignedInteger(const DataType& type, | 58 bool ParseUnsignedInteger(const DataType& type, |
58 const std::string& value_string); | 59 const std::string& value_string); |
59 bool ParseSignedInteger(const DataType& type, | 60 bool ParseSignedInteger(const DataType& type, |
60 const std::string& value_string); | 61 const std::string& value_string); |
61 bool ParseFloat(const DataType& type, const std::string& value_string); | 62 bool ParseFloat(const DataType& type, const std::string& value_string); |
62 bool ParseDouble(const DataType& type, const std::string& value_string); | 63 bool ParseDouble(const DataType& type, const std::string& value_string); |
63 bool ParseBinarySequence(const DataType& type, | 64 bool ParseBinarySequence(const DataType& type, |
64 const std::string& value_string); | 65 const std::string& value_string); |
65 bool ParseDistance(const DataType& type, const std::string& value_string); | 66 bool ParseDistance(const DataType& type, const std::string& value_string); |
66 bool ParseAnchor(const DataType& type, const std::string& value_string); | 67 bool ParseAnchor(const DataType& type, const std::string& value_string); |
| 68 bool ParseHandles(const DataType& type, const std::string& value_string); |
67 | 69 |
68 bool StartsWith(const Range& range, const char* prefix, size_t prefix_length); | 70 bool StartsWith(const Range& range, const char* prefix, size_t prefix_length); |
69 | 71 |
| 72 bool ConvertToUnsignedInteger(const std::string& value_string, |
| 73 unsigned long long int* value); |
| 74 |
70 template <typename T> | 75 template <typename T> |
71 void AppendData(T data) { | 76 void AppendData(T data) { |
72 size_t pos = parsed_input_->size(); | 77 size_t pos = data_->size(); |
73 parsed_input_->resize(pos + sizeof(T)); | 78 data_->resize(pos + sizeof(T)); |
74 memcpy(&(*parsed_input_)[pos], &data, sizeof(T)); | 79 memcpy(&(*data_)[pos], &data, sizeof(T)); |
75 } | 80 } |
76 | 81 |
77 template <typename TargetType, typename InputType> | 82 template <typename TargetType, typename InputType> |
78 bool ConvertAndAppendData(InputType value) { | 83 bool ConvertAndAppendData(InputType value) { |
79 if (value > std::numeric_limits<TargetType>::max() || | 84 if (value > std::numeric_limits<TargetType>::max() || |
80 value < std::numeric_limits<TargetType>::min()) { | 85 value < std::numeric_limits<TargetType>::min()) { |
81 return false; | 86 return false; |
82 } | 87 } |
83 AppendData(static_cast<TargetType>(value)); | 88 AppendData(static_cast<TargetType>(value)); |
84 return true; | 89 return true; |
85 } | 90 } |
86 | 91 |
87 template <typename TargetType, typename InputType> | 92 template <typename TargetType, typename InputType> |
88 bool ConvertAndFillData(size_t pos, InputType value) { | 93 bool ConvertAndFillData(size_t pos, InputType value) { |
89 if (value > std::numeric_limits<TargetType>::max() || | 94 if (value > std::numeric_limits<TargetType>::max() || |
90 value < std::numeric_limits<TargetType>::min()) { | 95 value < std::numeric_limits<TargetType>::min()) { |
91 return false; | 96 return false; |
92 } | 97 } |
93 TargetType target_value = static_cast<TargetType>(value); | 98 TargetType target_value = static_cast<TargetType>(value); |
94 assert(pos + sizeof(TargetType) <= parsed_input_->size()); | 99 assert(pos + sizeof(TargetType) <= data_->size()); |
95 memcpy(&(*parsed_input_)[pos], &target_value, sizeof(TargetType)); | 100 memcpy(&(*data_)[pos], &target_value, sizeof(TargetType)); |
96 return true; | 101 return true; |
97 } | 102 } |
98 | 103 |
99 static const DataType kDataTypes[]; | 104 static const DataType kDataTypes[]; |
100 static const size_t kDataTypeCount; | 105 static const size_t kDataTypeCount; |
101 | 106 |
102 const std::string& input_; | 107 const std::string& input_; |
103 size_t input_cursor_; | 108 size_t input_cursor_; |
104 | 109 |
105 std::vector<uint8_t>* parsed_input_; | 110 std::vector<uint8_t>* data_; |
| 111 size_t* num_handles_; |
106 std::string* error_message_; | 112 std::string* error_message_; |
107 | 113 |
108 std::map<std::string, PendingDistanceItem> pending_distance_items_; | 114 std::map<std::string, PendingDistanceItem> pending_distance_items_; |
109 }; | 115 }; |
110 | 116 |
111 #define DATA_TYPE(name, data_size, parse_data_func) \ | 117 #define DATA_TYPE(name, data_size, parse_data_func) \ |
112 {name, sizeof(name) - 1, data_size, parse_data_func} | 118 {name, sizeof(name) - 1, data_size, parse_data_func} |
113 | 119 |
114 const ValidationTestInputParser::DataType | 120 const ValidationTestInputParser::DataType |
115 ValidationTestInputParser::kDataTypes[] = { | 121 ValidationTestInputParser::kDataTypes[] = { |
116 DATA_TYPE("[u1]", 1, &ValidationTestInputParser::ParseUnsignedInteger), | 122 DATA_TYPE("[u1]", 1, &ValidationTestInputParser::ParseUnsignedInteger), |
117 DATA_TYPE("[u2]", 2, &ValidationTestInputParser::ParseUnsignedInteger), | 123 DATA_TYPE("[u2]", 2, &ValidationTestInputParser::ParseUnsignedInteger), |
118 DATA_TYPE("[u4]", 4, &ValidationTestInputParser::ParseUnsignedInteger), | 124 DATA_TYPE("[u4]", 4, &ValidationTestInputParser::ParseUnsignedInteger), |
119 DATA_TYPE("[u8]", 8, &ValidationTestInputParser::ParseUnsignedInteger), | 125 DATA_TYPE("[u8]", 8, &ValidationTestInputParser::ParseUnsignedInteger), |
120 DATA_TYPE("[s1]", 1, &ValidationTestInputParser::ParseSignedInteger), | 126 DATA_TYPE("[s1]", 1, &ValidationTestInputParser::ParseSignedInteger), |
121 DATA_TYPE("[s2]", 2, &ValidationTestInputParser::ParseSignedInteger), | 127 DATA_TYPE("[s2]", 2, &ValidationTestInputParser::ParseSignedInteger), |
122 DATA_TYPE("[s4]", 4, &ValidationTestInputParser::ParseSignedInteger), | 128 DATA_TYPE("[s4]", 4, &ValidationTestInputParser::ParseSignedInteger), |
123 DATA_TYPE("[s8]", 8, &ValidationTestInputParser::ParseSignedInteger), | 129 DATA_TYPE("[s8]", 8, &ValidationTestInputParser::ParseSignedInteger), |
124 DATA_TYPE("[b]", 1, &ValidationTestInputParser::ParseBinarySequence), | 130 DATA_TYPE("[b]", 1, &ValidationTestInputParser::ParseBinarySequence), |
125 DATA_TYPE("[f]", 4, &ValidationTestInputParser::ParseFloat), | 131 DATA_TYPE("[f]", 4, &ValidationTestInputParser::ParseFloat), |
126 DATA_TYPE("[d]", 8, &ValidationTestInputParser::ParseDouble), | 132 DATA_TYPE("[d]", 8, &ValidationTestInputParser::ParseDouble), |
127 DATA_TYPE("[dist4]", 4, &ValidationTestInputParser::ParseDistance), | 133 DATA_TYPE("[dist4]", 4, &ValidationTestInputParser::ParseDistance), |
128 DATA_TYPE("[dist8]", 8, &ValidationTestInputParser::ParseDistance), | 134 DATA_TYPE("[dist8]", 8, &ValidationTestInputParser::ParseDistance), |
129 DATA_TYPE("[anchr]", 0, &ValidationTestInputParser::ParseAnchor) | 135 DATA_TYPE("[anchr]", 0, &ValidationTestInputParser::ParseAnchor), |
| 136 DATA_TYPE("[handles]", 0, &ValidationTestInputParser::ParseHandles) |
130 }; | 137 }; |
131 | 138 |
132 const size_t ValidationTestInputParser::kDataTypeCount = | 139 const size_t ValidationTestInputParser::kDataTypeCount = |
133 sizeof(ValidationTestInputParser::kDataTypes) / | 140 sizeof(ValidationTestInputParser::kDataTypes) / |
134 sizeof(ValidationTestInputParser::kDataTypes[0]); | 141 sizeof(ValidationTestInputParser::kDataTypes[0]); |
135 | 142 |
136 ValidationTestInputParser::ValidationTestInputParser( | 143 ValidationTestInputParser::ValidationTestInputParser( |
137 const std::string& input, | 144 const std::string& input, |
138 std::vector<uint8_t>* parsed_input, | 145 std::vector<uint8_t>* data, |
| 146 size_t* num_handles, |
139 std::string* error_message) | 147 std::string* error_message) |
140 : input_(input), | 148 : input_(input), |
141 input_cursor_(0), | 149 input_cursor_(0), |
142 parsed_input_(parsed_input), | 150 data_(data), |
| 151 num_handles_(num_handles), |
143 error_message_(error_message) { | 152 error_message_(error_message) { |
144 assert(parsed_input_); | 153 assert(data_); |
| 154 assert(num_handles_); |
145 assert(error_message_); | 155 assert(error_message_); |
146 parsed_input_->clear(); | 156 data_->clear(); |
| 157 *num_handles_ = 0; |
147 error_message_->clear(); | 158 error_message_->clear(); |
148 } | 159 } |
149 | 160 |
150 ValidationTestInputParser::~ValidationTestInputParser() { | 161 ValidationTestInputParser::~ValidationTestInputParser() { |
151 } | 162 } |
152 | 163 |
153 bool ValidationTestInputParser::Run() { | 164 bool ValidationTestInputParser::Run() { |
154 Range range; | 165 Range range; |
155 bool result = true; | 166 bool result = true; |
156 while (result && GetNextItem(&range)) | 167 while (result && GetNextItem(&range)) |
157 result = ParseItem(range); | 168 result = ParseItem(range); |
158 | 169 |
159 if (!result) { | 170 if (!result) { |
160 *error_message_ = "Error occurred when parsing " + | 171 *error_message_ = "Error occurred when parsing " + |
161 std::string(range.first, range.second); | 172 std::string(range.first, range.second); |
162 } else if (!pending_distance_items_.empty()) { | 173 } else if (!pending_distance_items_.empty()) { |
163 // We have parsed all the contents in |input_| successfully, but there are | 174 // We have parsed all the contents in |input_| successfully, but there are |
164 // unmatched dist4/8 items. | 175 // unmatched dist4/8 items. |
165 *error_message_ = "Error occurred when matching [dist4/8] and [anchr]."; | 176 *error_message_ = "Error occurred when matching [dist4/8] and [anchr]."; |
166 result = false; | 177 result = false; |
167 } | 178 } |
168 if (!result) | 179 if (!result) { |
169 parsed_input_->clear(); | 180 data_->clear(); |
170 else | 181 *num_handles_ = 0; |
| 182 } else { |
171 assert(error_message_->empty()); | 183 assert(error_message_->empty()); |
| 184 } |
172 | 185 |
173 return result; | 186 return result; |
174 } | 187 } |
175 | 188 |
176 bool ValidationTestInputParser::GetNextItem(Range* range) { | 189 bool ValidationTestInputParser::GetNextItem(Range* range) { |
177 const char kWhitespaceChars[] = " \t\n\r"; | 190 const char kWhitespaceChars[] = " \t\n\r"; |
178 const char kItemDelimiters[] = " \t\n\r/"; | 191 const char kItemDelimiters[] = " \t\n\r/"; |
179 const char kEndOfLineChars[] = "\n\r"; | 192 const char kEndOfLineChars[] = "\n\r"; |
180 while (true) { | 193 while (true) { |
181 // Skip leading whitespaces. | 194 // Skip leading whitespaces. |
(...skipping 30 matching lines...) Expand all Loading... |
212 } | 225 } |
213 | 226 |
214 // "[u1]" is optional. | 227 // "[u1]" is optional. |
215 return ParseUnsignedInteger(kDataTypes[0], | 228 return ParseUnsignedInteger(kDataTypes[0], |
216 std::string(range.first, range.second)); | 229 std::string(range.first, range.second)); |
217 } | 230 } |
218 | 231 |
219 bool ValidationTestInputParser::ParseUnsignedInteger( | 232 bool ValidationTestInputParser::ParseUnsignedInteger( |
220 const DataType& type, const std::string& value_string) { | 233 const DataType& type, const std::string& value_string) { |
221 unsigned long long int value; | 234 unsigned long long int value; |
222 const char* format = NULL; | 235 if (!ConvertToUnsignedInteger(value_string, &value)) |
223 if (value_string.find_first_of("xX") != std::string::npos) | |
224 format = "%llx"; | |
225 else | |
226 format = "%llu"; | |
227 if (sscanf(value_string.c_str(), format, &value) != 1) | |
228 return false; | 236 return false; |
229 | 237 |
230 switch (type.data_size) { | 238 switch (type.data_size) { |
231 case 1: | 239 case 1: |
232 return ConvertAndAppendData<uint8_t>(value); | 240 return ConvertAndAppendData<uint8_t>(value); |
233 case 2: | 241 case 2: |
234 return ConvertAndAppendData<uint16_t>(value); | 242 return ConvertAndAppendData<uint16_t>(value); |
235 case 4: | 243 case 4: |
236 return ConvertAndAppendData<uint32_t>(value); | 244 return ConvertAndAppendData<uint32_t>(value); |
237 case 8: | 245 case 8: |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
305 AppendData(value); | 313 AppendData(value); |
306 return true; | 314 return true; |
307 } | 315 } |
308 | 316 |
309 bool ValidationTestInputParser::ParseDistance(const DataType& type, | 317 bool ValidationTestInputParser::ParseDistance(const DataType& type, |
310 const std::string& value_string) { | 318 const std::string& value_string) { |
311 if (pending_distance_items_.find(value_string) != | 319 if (pending_distance_items_.find(value_string) != |
312 pending_distance_items_.end()) | 320 pending_distance_items_.end()) |
313 return false; | 321 return false; |
314 | 322 |
315 PendingDistanceItem item = {parsed_input_->size(), type.data_size}; | 323 PendingDistanceItem item = {data_->size(), type.data_size}; |
316 parsed_input_->resize(parsed_input_->size() + type.data_size); | 324 data_->resize(data_->size() + type.data_size); |
317 pending_distance_items_[value_string] = item; | 325 pending_distance_items_[value_string] = item; |
318 | 326 |
319 return true; | 327 return true; |
320 } | 328 } |
321 | 329 |
322 bool ValidationTestInputParser::ParseAnchor(const DataType& type, | 330 bool ValidationTestInputParser::ParseAnchor(const DataType& type, |
323 const std::string& value_string) { | 331 const std::string& value_string) { |
324 std::map<std::string, PendingDistanceItem>::iterator iter = | 332 std::map<std::string, PendingDistanceItem>::iterator iter = |
325 pending_distance_items_.find(value_string); | 333 pending_distance_items_.find(value_string); |
326 if (iter == pending_distance_items_.end()) | 334 if (iter == pending_distance_items_.end()) |
327 return false; | 335 return false; |
328 | 336 |
329 PendingDistanceItem dist_item = iter->second; | 337 PendingDistanceItem dist_item = iter->second; |
330 pending_distance_items_.erase(iter); | 338 pending_distance_items_.erase(iter); |
331 | 339 |
332 size_t distance = parsed_input_->size() - dist_item.pos; | 340 size_t distance = data_->size() - dist_item.pos; |
333 switch (dist_item.data_size) { | 341 switch (dist_item.data_size) { |
334 case 4: | 342 case 4: |
335 return ConvertAndFillData<uint32_t>(dist_item.pos, distance); | 343 return ConvertAndFillData<uint32_t>(dist_item.pos, distance); |
336 case 8: | 344 case 8: |
337 return ConvertAndFillData<uint64_t>(dist_item.pos, distance); | 345 return ConvertAndFillData<uint64_t>(dist_item.pos, distance); |
338 default: | 346 default: |
339 assert(false); | 347 assert(false); |
340 return false; | 348 return false; |
341 } | 349 } |
342 } | 350 } |
343 | 351 |
| 352 bool ValidationTestInputParser::ParseHandles(const DataType& type, |
| 353 const std::string& value_string) { |
| 354 // It should be the first item. |
| 355 if (!data_->empty()) |
| 356 return false; |
| 357 |
| 358 unsigned long long int value; |
| 359 if (!ConvertToUnsignedInteger(value_string, &value)) |
| 360 return false; |
| 361 |
| 362 if (value > std::numeric_limits<size_t>::max()) |
| 363 return false; |
| 364 |
| 365 *num_handles_ = static_cast<size_t>(value); |
| 366 return true; |
| 367 } |
| 368 |
344 bool ValidationTestInputParser::StartsWith(const Range& range, | 369 bool ValidationTestInputParser::StartsWith(const Range& range, |
345 const char* prefix, | 370 const char* prefix, |
346 size_t prefix_length) { | 371 size_t prefix_length) { |
347 if (static_cast<size_t>(range.second - range.first) < prefix_length) | 372 if (static_cast<size_t>(range.second - range.first) < prefix_length) |
348 return false; | 373 return false; |
349 | 374 |
350 return memcmp(range.first, prefix, prefix_length) == 0; | 375 return memcmp(range.first, prefix, prefix_length) == 0; |
351 } | 376 } |
352 | 377 |
| 378 bool ValidationTestInputParser::ConvertToUnsignedInteger( |
| 379 const std::string& value_string, |
| 380 unsigned long long int* value) { |
| 381 const char* format = NULL; |
| 382 if (value_string.find_first_of("xX") != std::string::npos) |
| 383 format = "%llx"; |
| 384 else |
| 385 format = "%llu"; |
| 386 return sscanf(value_string.c_str(), format, value) == 1; |
| 387 } |
| 388 |
353 } // namespace | 389 } // namespace |
354 | 390 |
355 bool ParseValidationTestInput(const std::string& input, | 391 bool ParseValidationTestInput(const std::string& input, |
356 std::vector<uint8_t>* parsed_input, | 392 std::vector<uint8_t>* data, |
| 393 size_t* num_handles, |
357 std::string* error_message) { | 394 std::string* error_message) { |
358 ValidationTestInputParser parser(input, parsed_input, error_message); | 395 ValidationTestInputParser parser(input, data, num_handles, error_message); |
359 return parser.Run(); | 396 return parser.Run(); |
360 } | 397 } |
361 | 398 |
362 } // namespace test | 399 } // namespace test |
363 } // namespace mojo | 400 } // namespace mojo |
OLD | NEW |