Gwf to scs improve#494
Conversation
There was a problem hiding this comment.
Caution
Changes requested ❌
Reviewed everything up to e7e2424 in 2 minutes and 38 seconds. Click for details.
- Reviewed
709lines of code in3files - Skipped
0files when reviewing. - Skipped posting
1draft comments. View those below. - Modify your settings and rules to customize what types of comments Ellipsis leaves. And don't forget to react with 👍 or 👎 to teach Ellipsis.
1. sc-tools/sc-builder/src/sc_scs_writer.cpp:242
- Draft comment:
The nested loop for attribute arc lookup could be optimized for performance if the element set is large. - Reason this comment was not posted:
Decided after close inspection that this draft comment was likely wrong and/or not actionable: usefulness confidence = 0% vs. threshold = 50% While the loop could potentially be optimized by using a different data structure, there's no evidence in the code that this is a performance bottleneck. The code already has an early break and the operation only happens for complex arcs. Without profiling data or clear evidence of performance issues, this seems like premature optimization. The comment could be valid if this code processes very large graphs where performance is critical. The current implementation is O(n) for each complex arc. However, the code appears to be part of a file writer/serializer which is likely not in a performance-critical path. The current implementation prioritizes readability and maintainability. The comment should be deleted as it suggests optimization without clear evidence of need, making it speculative rather than actionable.
Workflow ID: wflow_AzBo1HFyETNEoagk
You can customize by changing your verbosity settings, reacting with 👍 or 👎, replying to comments, or adding code review rules.
| std::ofstream output(outputFile, std::ios::binary); | ||
| if (!output.is_open()) | ||
| { | ||
| std::cout << "Error: Cannot open output file `" << outputFile << "`.\n"; |
There was a problem hiding this comment.
Consider using std::cerr for error messages instead of std::cout.
| std::cout << "Error: Cannot open output file `" << outputFile << "`.\n"; | |
| std::cerr << "Error: Cannot open output file `" << outputFile << "`.\n"; |
| auto link = std::dynamic_pointer_cast<SCgLink>(node); | ||
| if (link && link->GetContentType() != NO_CONTENT) | ||
| { | ||
| std::string contentTypeStr = link->GetContentType(); |
There was a problem hiding this comment.
Validate contentTypeStr before converting with std::stoi to avoid exceptions from malformed data.
| } | ||
| else if (contentType == 4) // IMAGE | ||
| { | ||
| std::string fileName = link->GetFileName(); |
There was a problem hiding this comment.
Sanitize fileName to prevent potential directory traversal issues when constructing file paths.
| std::string fileName = link->GetFileName(); | |
| std::string fileName = std::filesystem::path(link->GetFileName()).filename().string(); |
|
|
||
| if (!attrSourceId.empty()) | ||
| { | ||
| std::string connectorSymbol; |
There was a problem hiding this comment.
Consider refactoring the connector printing logic into a helper function to reduce code duplication.
| } | ||
| } | ||
|
|
||
| void SCsWriter::Write( |
There was a problem hiding this comment.
Consider splitting the lengthy Write() function into smaller helper functions to improve readability and maintainability.
| std::string contentTypeStr = link->GetContentType(); | ||
| int contentType = std::stoi(contentTypeStr); |
There was a problem hiding this comment.
⚠️ Edge Case: std::stoi on content type can throw and crash the tool
int contentType = std::stoi(link->GetContentType()); throws std::invalid_argument/std::out_of_range if the GWF content-type string is non-numeric or malformed. RunBuilder's function-try-block only catches utils::ScException, so this standard exception propagates uncaught and terminates the process. Validate the string or wrap the conversion and throw an ScException on failure.
Guard std::stoi so malformed content types raise an ScException instead of crashing.:
std::string contentTypeStr = link->GetContentType();
int contentType = 0;
try
{
contentType = std::stoi(contentTypeStr);
}
catch (std::exception const &)
{
SC_THROW_EXCEPTION(
utils::ExceptionInvalidParams,
"SCsWriter::Write: invalid link content type `" << contentTypeStr << "`.");
}
- Apply fix
Check the box to apply the fix or reply for a change | Was this helpful? React with 👍 / 👎
| for (auto const & [id, element] : elements) | ||
| { | ||
| size_t connectorsWrittenOnPreviousIteration = dependedConnectors.size(); | ||
| while (connectorsWrittenOnPreviousIteration != 0) | ||
| if (element->GetTag() == ARC || element->GetTag() == PAIR) | ||
| { | ||
| connectorsWrittenOnPreviousIteration = 0; | ||
| for (auto dependedConnector = dependedConnectors.cbegin(); dependedConnector != dependedConnectors.cend();) | ||
| if (writtenElements.count(element)) | ||
| continue; | ||
| if (attributeArcs.count(element)) | ||
| continue; | ||
| writtenElements.insert(element); | ||
|
|
||
| auto connector = std::dynamic_pointer_cast<SCgConnector>(element); | ||
| std::string sourceId = connector->GetSource()->GetIdentifier(); | ||
| std::string targetId = connector->GetTarget()->GetIdentifier(); | ||
| if (sourceId.empty()) | ||
| sourceId = NODE + UNDERSCORE + connector->GetSource()->GetId(); |
There was a problem hiding this comment.
💡 Performance: O(n^2) inner scan to find attribute-arc source
For every complex arc, the code rescans the entire elements map to locate the incoming attribute arc (lines 255-268), making arc writing O(arcs * elements). On large contours/graphs this is a needless hot-path cost. Precompute a map from target element to its incoming attribute arc in the Step-2 pass and look it up in O(1).
Build a target->attribute-arc index once instead of rescanning per complex arc.:
// Step 2: also record, for each complex arc, its incoming attribute arc
std::unordered_map<SCgElementPtr, SCgElementPtr> attrArcByTarget;
// ... when inserting: attrArcByTarget[target] = element;
// Step 3: replace the inner for-loop scan with:
auto attrIt = attrArcByTarget.find(element);
if (attrIt != attrArcByTarget.end()) { /* use attrIt->second's source */ }
- Apply fix
Check the box to apply the fix or reply for a change | Was this helpful? React with 👍 / 👎
| std::string attrSourceId; | ||
| for (auto const & [incomingId, incomingElement] : elements) | ||
| { | ||
| auto const & scsElement = SCsElementFactory::CreateSCsElementForSCgElement(*dependedConnector); | ||
| scsElement->ConvertFromSCgElement(*dependedConnector); | ||
| scsElement->Dump(filePath, buffer, depth, writtenElements); | ||
| writtenElements.insert(*dependedConnector); | ||
| ++connectorsWrittenOnPreviousIteration; | ||
| dependedConnector = dependedConnectors.erase(dependedConnector); | ||
| if (incomingElement->GetTag() == ARC || incomingElement->GetTag() == PAIR) | ||
| { | ||
| auto incConnector = std::dynamic_pointer_cast<SCgConnector>(incomingElement); | ||
| if (incConnector->GetTarget() == element) | ||
| { | ||
| attrSourceId = incConnector->GetSource()->GetIdentifier(); | ||
| if (attrSourceId.empty()) | ||
| attrSourceId = NODE + UNDERSCORE + incConnector->GetSource()->GetId(); | ||
| break; | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
💡 Edge Case: Only first attribute of a complex arc is emitted
The lookup loop breaks at the first incoming attribute arc, so if a single arc carries multiple attribute arcs (e.g. several role relations), all but one are silently dropped from the generated SCs, losing semantic information. Iterate all incoming attribute arcs and emit each attribute rather than stopping at the first match.
Was this helpful? React with 👍 / 👎
Code Review
|
| Auto-apply | Compact |
|
|
Was this helpful? React with 👍 / 👎 | Gitar
Important
Improves GWF-to-SCs translation with new command-line options and enhanced SCs file output handling in
sc_builder_runner.cppandsc_scs_writer.cpp.--gwf-to-scsand--gwf-outputoptions insc_builder_runner.cppfor translating GWF files to SCs.SCsWriter::Write()insc_scs_writer.cppto handle nodes, arcs, and contours more effectively.PrintHelpMessage()insc_builder_runner.cppupdated with new options for GWF-to-SCs translation.SCsWriter::Write()refactored to improve node and arc processing, including handling of SCgLinks and image content.SCsWriter::CollectNodes()to recursively gather nodes, including those in contours.sc_scg_to_scs_types_converter.hppinsc_scs_writer.cppfor type conversion.SCsWriter::SCgIdentifierCorrectormethods for identifier correction.This description was created by
for e7e2424. You can customize this summary. It will automatically update as commits are pushed.