-
-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Fix m3u list parsing with /r/n end of line #4547
Conversation
This fixes a regression form mixxxdj@a006552
Wdyt about adding a test to make sure this regression does not happen again? Should be relatively straightforward. |
I don't spot any regression? Invoking TrackFile::checkExists() when needed instead of moving an anonymous boolean value around is safer and less error prone. |
I just had a closer look. The issue is that ParserCsv::parse() has now no existence check. Not existing tracks are leading to a debug assertion violation:
I have misread the code around ParserPls::parse() which also removes not existing tracks. Now I have found the check. The anonymous boolean was only a temporary solution, to show the issue. I think this requires some more refactoring to make the code testable and keep the code in a good shape at the same time. A creeping scope of this PR :-/ .. but OK, right? |
This fixes now also the debug assert with non existing csv entries. |
I have now introduced the named function: parseAllLocations() this is even better than the anonymous lambda. |
well, the lambda was basically the C++ workaround for what would otherwise just be a simple block expression in rust, but extracting it into a function is good too. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This PR seems done, right?
@Holzhaus we still need your approval/dismissal since you requested changes.
src/library/parserpls.cpp
Outdated
|
||
ParserPls::ParserPls() : Parser() { | ||
} | ||
QString getFilePath(QTextStream* stream) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why the ptr instead of a const-ref?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It modifies the stream (moves the seek position) so I think a ptr is semantically appropriate.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, right, so the text stream must be mutable, but that still does not explain why were passing a pointer instead of a (mutable) reference. AFAIK they are semantically the same, so is the pointer just used because it was there in the first place?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Keep in mind that this is not a request for changes, I'm must asking because I'd like improve my C++ knowledge.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will change "stream" to "pStream" ...
From the C++ rules we may pass here a non const reference:
QString getFilePath(QTextStream& stream);
But it is a matter of code style.
Than we see:
stream.readLine();
and not
pStream->readLine();
The later makes clear, that we do not have a local copy and all work with the pointed object will have an outside effect.
In case of QString getFilePath(cosnt QTextStream& stream);
it does not matter if it is a copy by value or a reference, It has never an outside effect, because of the constantnes
This a fundamental difference between C++ and Java or C#, where objects are always a references and where thy are no pointers.
This was also part of the Google style. However they have recently dropped the strict rule.
See also:
https://github.com/mixxxdj/mixxx/wiki/Coding-Guidelines#non-const-references
(I have updated the text linking the original google rule)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the explanation. From a type-safety perspective, when passing a pointer, while passing nullptr
would not make sense, it is still permitted. Wouldn't it make sense to use a mutable reference instead since those can't be null?
Moreover, in this particular case, we don't treat the incoming QTextStream as an output variable, but rather consume the textstream and expect it to not be used in the caller afterwards, correct? Because then the parameter rather seems like it should semantically be a turns out this assumption is wrong.QTextStream&&
. I'm aware that QTextStream does not have a move or copy constructor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't it make sense to use a mutable reference instead since those can't be null?
That is a valid argument for the other code style. Both styles are valid, we prefere the reliable value vs. pointer syntax style. By the way: in C++ a mutable reference can be null. It is only by convention never null. Pointers and references are exactly the same if you look at the produced assembler code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That is a valid argument for the other code style. Both styles are valid, we prefere the reliable value vs. pointer syntax style.
Thanks for the clarification. I guess I'd prefer the the other style but I can adopt the mixxx style as well.
By the way: in C++ a mutable reference can be null. It is only by convention never null. Pointers and references are exactly the same if you look at the produced assembler code.
I know, but I thought the compiler does not allow references to be set to null (at compile time, there aren't any runtime checks unless you use something like gsl::not_null
).
src/library/parsercsv.cpp
Outdated
//qDebug() << "ParserCsv: Starting to parse."; | ||
if (file.open(QIODevice::ReadOnly)) { | ||
QByteArray ba = file.readAll(); | ||
|
||
QList<QList<QString> > tokens = tokenize(ba, ','); | ||
|
||
// detect Location column | ||
int loc_coll = 0x7fffffff; | ||
int loc_col = -1; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you rename the variable anyway, let's name it locationColumnIndex
or something like that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
well the current naming is consistent with the entire function, so does it make sense to change just this one? Is worth to widen the scope yet again to rename all variables in that function?
src/library/parserpls.cpp
Outdated
|
||
ParserPls::ParserPls() : Parser() { | ||
} | ||
QString getFilePath(QTextStream* stream) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It modifies the stream (moves the seek position) so I think a ptr is semantically appropriate.
Yes, I just re-reviewed and chose comment instead of request changes to clarify I'm okay with merging. |
Thanks for clarification. For some reason, GitHub does not show that when you look into the reviewers section at the top right of the PR. Maybe you need to dismiss the review or overwrite it via an explicit approval? |
Done. |
src/library/parsercsv.h
Outdated
virtual ~ParserCsv(); | ||
/**Overwriting function parse in class Parser**/ | ||
QList<QString> parse(const QString&); | ||
class ParserCsv : Parser { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What is the consequence of leaving out the inheritance visibility specifier? Previously it was inheriting from Parser
publicly, now its defaulting to something (I don't know what without having to look it up).
From pure gut feeling, leaving the specifier out seems like bad style to me, though I have 0 idea in practice.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It defaults to private.
But to be honest, I have just forget to write it explicitly. I will fix it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, that was my concern. Seems like no outside component depends on the inheritance but I think it makes sense for the relationship to be public regardless.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
Any idea whats tripping up clang-format? Related to #4557? |
We now require |
It is probably a good idea to replace all occurrences of |
I have no interest to do that. The |
src/test/playlisttest.cpp
Outdated
@@ -56,3 +57,52 @@ TEST_F(PlaylistTest, Relative) { | |||
EXPECT_EQ(QString("base/folder/../../bar.mp3"), | |||
parser.playlistEntryToFilePath("../../bar.mp3", "base/folder")); | |||
} | |||
|
|||
TEST_F(PlaylistTest, m3uEndOfLine) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Everywhere else we use PascalCase for the test names, let's keep this pattern here:
TEST_F(PlaylistTest, m3uEndOfLine) { | |
TEST_F(PlaylistTest, M3UEndOfLine) { |
The space is unnecessary and clang-format complains about it. See mixxxdj#4547 (comment). This patch was created using: $ find src \( -name "*.h" -o -name "*.cpp" \) -exec sed -i 's/> >/>>/' {} \;
No problem, I took care of it here: #4559 |
Conflict resolved, merge? |
This fixes a regression form
a006552