History

TimeSeriesPlatformLibrary: Converter function pointer to standard function templates to support more versatile function registration, e.g, lambda expressions.

J. Ritchie Carroll committed 7 years ago

Commit 70535871 parent 0c9b55217 files · +346 −307Browse files

Showing the changes to Source/Libraries/TimeSeriesPlatformLibrary/Common/Convert.cpp (1 of 17 files). Show all

Unified · Split

Source/Libraries/TimeSeriesPlatformLibrary/Common/Convert.cpp+181−2
@@ -25,11 +25,12 @@ · 24 unmodified lines
25#include <sstream>25#include <sstream>
26#include <locale>26#include <locale>
27#include <codecvt>27#include <codecvt>
28#include <boost/uuid/string_generator.hpp>
29#include <boost/uuid/uuid_io.hpp>28#include <boost/uuid/uuid_io.hpp>
29#include <boost/uuid/string_generator.hpp>
30#include <boost/date_time/posix_time/posix_time.hpp>30#include <boost/date_time/posix_time/posix_time.hpp>
31#include <boost/date_time/gregorian/gregorian.hpp>31#include <boost/date_time/gregorian/gregorian.hpp>
32#include <boost/date_time/c_local_time_adjustor.hpp>32#include <boost/date_time/c_local_time_adjustor.hpp>
33#include <boost/algorithm/string.hpp>
33#include "Convert.h"34#include "Convert.h"
34 35
35using namespace std;36using namespace std;
@@ -232,7 +233,7 @@ uint32_t GSF::TicksToString(char* ptr, uint32_t maxsize, string format, int64_t · 196 unmodified lines
232 233
233DateTime GSF::LocalFromUtc(const DateTime& timestamp)234DateTime GSF::LocalFromUtc(const DateTime& timestamp)
234{235{
235 return DateTime(boost::date_time::c_local_adjustor<DateTime>::utc_to_local(timestamp));236 return boost::date_time::c_local_adjustor<DateTime>::utc_to_local(timestamp);
236}237}
237 238
238std::string GSF::ToString(const Guid& value)239std::string GSF::ToString(const Guid& value)
@@ -273,6 +274,48 @@ string GSF::ToUTF8(const wstring& value) · 34 unmodified lines
273 return converter.to_bytes(value);274 return converter.to_bytes(value);
274}275}
275 276
277bool GSF::ParseBoolean(const string& value)
278{
279 if (value.empty())
280 return false;
281
282 const string result = Trim(value);
283
284 if (result.empty())
285 {
286 if (IsEqual(result, "true"))
287 return true;
288
289 if (IsEqual(result, "false"))
290 return false;
291
292 try
293 {
294 return stoi(result) != 0;
295 }
296 catch (...)
297 {
298 const char first = toupper(result[0]);
299 return first == 'T' || first == 'Y';
300 }
301 }
302
303 return false;
304}
305
306bool GSF::TryParseDouble(const string& value, float64_t& result)
307{
308 try
309 {
310 result = stod(value);
311 return true;
312 }
313 catch (...)
314 {
315 return false;
316 }
317}
318
276std::string GSF::RegExEncode(const char value)319std::string GSF::RegExEncode(const char value)
277{320{
278 std::stringstream stream;321 std::stringstream stream;
@@ -380,3 +423,139 @@ DateTime GSF::ParseTimestamp(const char* time, bool parseAsUTC) · 101 unmodified lines
380 423
381 throw runtime_error("Failed to parse timestamp \"" + string(time) + "\"");424 throw runtime_error("Failed to parse timestamp \"" + string(time) + "\"");
382}425}
426
427StringMap<string> GSF::ParseKeyValuePairs(const string& value, const char parameterDelimiter, const char keyValueDelimiter, const char startValueDelimiter, const char endValueDelimiter)
428{
429 if (parameterDelimiter == keyValueDelimiter ||
430 parameterDelimiter == startValueDelimiter ||
431 parameterDelimiter == endValueDelimiter ||
432 keyValueDelimiter == startValueDelimiter ||
433 keyValueDelimiter == endValueDelimiter ||
434 startValueDelimiter == endValueDelimiter)
435 throw invalid_argument("All delimiters must be unique");
436
437 const string& escapedParameterDelimiter = RegExEncode(parameterDelimiter);
438 const string& escapedKeyValueDelimiter = RegExEncode(keyValueDelimiter);
439 const string& escapedStartValueDelimiter = RegExEncode(startValueDelimiter);
440 const string& escapedEndValueDelimiter = RegExEncode(endValueDelimiter);
441 const string& escapedBackslashDelimiter = RegExEncode('\\');
442 const string& parameterDelimiterStr = string(1, parameterDelimiter);
443 const string& keyValueDelimiterStr = string(1, keyValueDelimiter);
444 const string& startValueDelimiterStr = string(1, startValueDelimiter);
445 const string& endValueDelimiterStr = string(1, endValueDelimiter);
446 const string& backslashDelimiterStr = "\\";
447
448 StringMap<string> keyValuePairs;
449 vector<string> escapedValue;
450 bool valueEscaped = false;
451 uint32_t delimiterDepth = 0;
452
453 // Escape any parameter or key/value delimiters within tagged value sequences
454 // For example, the following string:
455 // "normalKVP=-1; nestedKVP={p1=true; p2=false}")
456 // would be encoded as:
457 // "normalKVP=-1; nestedKVP=p1\\u003dtrue\\u003b p2\\u003dfalse")
458 for (uint32_t i = 0; i < value.size(); i++)
459 {
460 const char character = value[i];
461
462 if (character == startValueDelimiter)
463 {
464 if (!valueEscaped)
465 {
466 valueEscaped = true;
467 continue; // Don't add tag start delimiter to final value
468 }
469
470 // Handle nested delimiters
471 delimiterDepth++;
472 }
473
474 if (character == endValueDelimiter)
475 {
476 if (valueEscaped)
477 {
478 if (delimiterDepth > 0)
479 {
480 // Handle nested delimiters
481 delimiterDepth--;
482 }
483 else
484 {
485 valueEscaped = false;
486 continue; // Don't add tag stop delimiter to final value
487 }
488 }
489 else
490 {
491 throw runtime_error("Failed to parse key/value pairs: invalid delimiter mismatch. Encountered end value delimiter '" + endValueDelimiterStr + "' before start value delimiter '" + startValueDelimiterStr + "'."); // NOLINT
492 }
493 }
494
495 if (valueEscaped)
496 {
497 // Escape any delimiter characters inside nested key/value pair
498 if (character == parameterDelimiter)
499 escapedValue.push_back(escapedParameterDelimiter);
500 else if (character == keyValueDelimiter)
501 escapedValue.push_back(escapedKeyValueDelimiter);
502 else if (character == startValueDelimiter)
503 escapedValue.push_back(escapedStartValueDelimiter);
504 else if (character == endValueDelimiter)
505 escapedValue.push_back(escapedEndValueDelimiter);
506 else if (character == '\\')
507 escapedValue.push_back(escapedBackslashDelimiter);
508 else
509 escapedValue.emplace_back(1, character);
510 }
511 else
512 {
513 if (character == '\\')
514 escapedValue.push_back(escapedBackslashDelimiter);
515 else
516 escapedValue.emplace_back(1, character);
517 }
518 }
519
520 if (delimiterDepth != 0 || valueEscaped)
521 {
522 // If value is still escaped, tagged expression was not terminated
523 if (valueEscaped)
524 delimiterDepth = 1;
525
526 const bool moreStartDelimiters = delimiterDepth > 0;
527
528 throw runtime_error(
529 "Failed to parse key/value pairs: invalid delimiter mismatch. Encountered more " +
530 (moreStartDelimiters ? "start value delimiters '" + startValueDelimiterStr + "'" : "end value delimiters '" + endValueDelimiterStr + "'") + " than " +
531 (moreStartDelimiters ? "end value delimiters '" + endValueDelimiterStr + "'" : "start value delimiters '" + startValueDelimiterStr + "'") + ".");
532 }
533
534 // Parse key/value pairs from escaped value
535 vector<string> pairs = Split(boost::algorithm::join(escapedValue, ""), parameterDelimiterStr, false);
536
537 for (uint32_t i = 0; i < pairs.size(); i++)
538 {
539 // Separate key from value
540 vector<string> elements = Split(pairs[i], keyValueDelimiterStr, false);
541
542 if (elements.size() == 2)
543 {
544 // Get key
545 const string key = Trim(elements[0]);
546
547 // Get unescaped value
548 const string unescapedValue = Replace(Replace(Replace(Replace(Replace(Trim(elements[1]),
549 escapedParameterDelimiter, parameterDelimiterStr, false),
550 escapedKeyValueDelimiter, keyValueDelimiterStr, false),
551 escapedStartValueDelimiter, startValueDelimiterStr, false),
552 escapedEndValueDelimiter, endValueDelimiterStr, false),
553 escapedBackslashDelimiter, backslashDelimiterStr, false);
554
555 // Add or replace key elements with unescaped value
556 keyValuePairs[key] = unescapedValue;
557 }
558 }
559
560 return keyValuePairs;
561}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t