Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP - remove scanf parsing in GPX date parser #1109

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

robertlipe
Copy link
Collaborator

Quit scanning the time string for '.' and special handling it as a string.
More experimental and marked as #if 0 for easy testing, move all the scanf parsing to QRegExp. I don't know if that's wise for CPU/memory costs, but it eliminates all the scanf stuff and the entire reason to convert the incoming QString to a C String.

@tsteven4 , I know you've fretted a lot about GPX date parsing recently. Is this overall direction better or worse? There are some additional cleanups this would enable, but this allows for easy flipping between old and new for now.

Quit scanning the time string for '.' and special handling it as a
string.
More experimental and marked as #if 0 for easy testing, move
all the scanf parsing to QRegExp. I don't know if that's wise
for CPU/memory costs, but it eliminates all the scanf stuff and
the entire reason to convert the incoming QString to a C String.
@robertlipe robertlipe requested a review from tsteven4 May 14, 2023 08:01
@codacy-production
Copy link

Coverage summary from Codacy

Merging #1109 (3450e58) into master (9dccbfc) - See PR on Codacy

Coverage variation Diff coverage
0.00% 100.00%
Coverage variation details
Coverable lines Covered lines Coverage
Common ancestor commit (9dccbfc) 24154 16373 67.79%
Head commit (3450e58) 24152 (-2) 16371 (-2) 67.78% (0.00%)

Coverage variation is the difference between the coverage for the head and common ancestor commits of the pull request branch: <coverage of head commit> - <coverage of common ancestor commit>

Diff coverage details
Coverable lines Covered lines Diff coverage
Pull request (#1109) 18 18 100.00%

Diff coverage is the percentage of lines that are covered by tests out of the coverable lines that the pull request added or modified: <covered lines added or modified>/<coverable lines added or modified> * 100%

See your quality gate settings    Change summary preferences

if (fsec) {
dt = dt.addMSecs(lround(fsec * 1000));
}
dt = QDateTime(date, time, Qt::UTC);

// Any offsets that were stuck at the end.
dt = dt.addSecs(-off_sign * off_hr * 3600 - off_sign * off_min * 60);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like the replacement of sscanf with QRegularExpression, and elimination of cstdio, cstring.

I had WIP, including a bunch of issues that appear with Qt 6.5.0, with an idea regarding offsets. Reviewing your ideas and incorporating mine got messy, a modified version to compare is attached. To use this also change the declaration in defs.h adding a default to match current code.
gpsbabel::DateTime xml_parse_time(const QString& dateTimeString, bool local_is_utc = true);

I modified the regular expressions based on https://www.w3.org/TR/xmlschema-2/#dateTime. I didn't fret over negative years, or years beyond 9999.

I do worry a bit about the offset regular expression matching something it shouldn't. I haven't thought of a way it could mismatch something besides a timezone from https://www.w3.org/TR/xmlschema-2/#isoformats

qRound and qRound64 let you round a double to a int or qint64.

It also got messy with the conditional code and keeping them both running, I did the lazy thing and chopped it.

I haven't tried the enhanced kml tests to see if they work with these changes.

I attached the modified gpx.cc, or a patch for both gpx.cc and defs.h:
gpx.cc.gz
xsddatetime.patch

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I knew we were about to collide. That's why I RFC'ed this to you before hand. The #if 0 mess was just to mark my before and after. It was on the chopping block for after your vague agreement that this was a sane thing to do anyway.

The regexes will definitely match theoretical things they shouldn't. But those things shouldn't be valid ISO/GPX/KML times. We could have fooled scanf, too.

I'll take your version of this, fix the rounding issues pushing us over a second and then calling Time.addSec() with the rest, and run with it.

Thanx for talking it through.

@tsteven4
Copy link
Collaborator

please merge in "add testing for kml:dateTimeType" #1112, which has been merged with the master branch. That may keep us honest.

@tsteven4
Copy link
Collaborator

BTW https://regex101.com/ is handy for manual testing of these PCREs, especially if you use raw string literals so you can just past them in.

@tsteven4
Copy link
Collaborator

There is an issue with my suggestion to round msecs. If we round .9999999 secs up to 1000 msecs it will be out of the legal range for QTime. If we set msecs to zero and increment secs it may be out of range ...

@tsteven4
Copy link
Collaborator

I'd just truncate the milliseconds. that is what I just caught in unicsv.cc. adding a second in anything but utc (or utcoffset) is expensive, it can require a double time zone conversion.

@tsteven4
Copy link
Collaborator

Whats a worse case truncation error of 0.5milliseconds among friends? osm just convinced me to drop all the fractional seconds! I don't think its worth the agony of dealing with it.

@GPSBabelDeveloper
Copy link
Collaborator

GPSBabelDeveloper commented May 15, 2023 via email

@tsteven4
Copy link
Collaborator

The rounding effects on test are all too believable, but on my system applying the patch below to the patch above doesn't cause any test failures. But there is a history of needing rounding to get tests to work across platforms, but usually that was windows vs. the rest of the world.

$ diff gpx.cc.p1 gpx.cc
425c425
<     int msec = qRound(1000.0 * match.captured(7).toDouble());
---
>     int msec = 1000.0 * match.captured(7).toDouble();

@tsteven4
Copy link
Collaborator

same change as above wrt rounding -> truncation, no test failures on macos either.

@tsteven4
Copy link
Collaborator

BTW, a similar change to truncate ms in UnicsvFormat::unicsv_parse_time didn't cause any failures on any platforms in CI. The base for test this was what is about to replace #1103 and #1106.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants