Skip to content

Added functionality to import/export Graph from/to Binary File#554

Merged
ZigRazor merged 1 commit intoZigRazor:masterfrom
me-hem:feature/binary
Oct 23, 2025
Merged

Added functionality to import/export Graph from/to Binary File#554
ZigRazor merged 1 commit intoZigRazor:masterfrom
me-hem:feature/binary

Conversation

@me-hem
Copy link
Copy Markdown
Contributor

@me-hem me-hem commented Oct 23, 2025

This PR adds binary serialization and deserialization support for Graph objects (issue #5) to efficiently import/export large graphs to and from binary files, while maintaining structural and attribute consistency.

Changes made

  • Graph_decl.h – Added public writeToBinaryFile() and readFromBinaryFile() methods with private helpers. Defined binary format constants (magic number, version, flags) and is_binary_serializable type trait.
  • InputOperation_impl.hpp – Implemented binary deserialization with header validation, node/edge reconstruction, and support for optional features and weights.
  • OutputOperation_impl.hpp – Implemented binary serialization writing header metadata followed by node data and edge data with optional features/weights.
  • BinaryIOTest.cpp – Added comprehensive test suite covering various graph types, node features, edge weights, empty graphs, large graphs, error cases, and round-trip serialization.

Implementation details

Binary File Format:

  • Header: Magic number (4 bytes) + Version (4 bytes) + Node count (8 bytes) + Edge count (8 bytes) + Flags (8 bytes)
  • Nodes: For each node: ID (length-prefixed string) + Data size (4 bytes) + Data (if features enabled and type is trivially copyable)
  • Edges: For each edge: ID + Node1 ID + Node2 ID + Edge flags (directed/weighted bits) + Weight (8 bytes, if weighted and weights enabled)

Key Features:

  • Selective serialization of node features and edge weights via boolean flags
  • Type safety through the is_binary_serializable trait (only trivially copyable types serialized)
  • Support for all edge combinations: directed/undirected and weighted/unweighted
  • Robust error handling with specific error codes (-1: file error, -2: invalid format, -3: unsupported version, -4: read error)
  • Memory-efficient streaming I/O without loading the entire graph into memory

@me-hem me-hem marked this pull request as draft October 23, 2025 10:58
@me-hem me-hem marked this pull request as ready for review October 23, 2025 11:06
try {
// Read and verify header
uint32_t magic;
in.read(reinterpret_cast<char *>(&magic), sizeof(magic));

Check failure

Code scanning / Eslint-9 (reported by Codacy)

Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). Error

Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20).
}

uint32_t version;
in.read(reinterpret_cast<char *>(&version), sizeof(version));

Check failure

Code scanning / Eslint-9 (reported by Codacy)

Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). Error

Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20).
}

uint64_t numNodes, numEdges, flags;
in.read(reinterpret_cast<char *>(&numNodes), sizeof(numNodes));

Check failure

Code scanning / Eslint-9 (reported by Codacy)

Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). Error

Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20).

uint64_t numNodes, numEdges, flags;
in.read(reinterpret_cast<char *>(&numNodes), sizeof(numNodes));
in.read(reinterpret_cast<char *>(&numEdges), sizeof(numEdges));

Check failure

Code scanning / Eslint-9 (reported by Codacy)

Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). Error

Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20).
uint64_t numNodes, numEdges, flags;
in.read(reinterpret_cast<char *>(&numNodes), sizeof(numNodes));
in.read(reinterpret_cast<char *>(&numEdges), sizeof(numEdges));
in.read(reinterpret_cast<char *>(&flags), sizeof(flags));

Check failure

Code scanning / Eslint-9 (reported by Codacy)

Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). Error

Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20).
}
} else {
uint32_t dataSize;
in.read(reinterpret_cast<char *>(&dataSize), sizeof(dataSize));

Check failure

Code scanning / Eslint-9 (reported by Codacy)

Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). Error

Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20).
std::string node2Id = readBinaryString(in);

uint8_t edgeFlags;
in.read(reinterpret_cast<char *>(&edgeFlags), sizeof(edgeFlags));

Check failure

Code scanning / Eslint-9 (reported by Codacy)

Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). Error

Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20).
double weight = 0.0;
if (hasEdgeWeights && isWeighted) {
if (readEdgeWeights) {
in.read(reinterpret_cast<char *>(&weight), sizeof(weight));

Check failure

Code scanning / Eslint-9 (reported by Codacy)

Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). Error

Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20).
template <typename T>
std::string Graph<T>::readBinaryString(std::ifstream &in) const {
uint32_t len;
in.read(reinterpret_cast<char *>(&len), sizeof(len));

Check failure

Code scanning / Eslint-9 (reported by Codacy)

Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). Error

Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20).
uint32_t len;
in.read(reinterpret_cast<char *>(&len), sizeof(len));
std::string str(len, '\0');
in.read(&str[0], len);

Check failure

Code scanning / Eslint-9 (reported by Codacy)

Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20). Error

Check buffer boundaries if used in a loop including recursive loops (CWE-120, CWE-20).
@codecov
Copy link
Copy Markdown

codecov Bot commented Oct 23, 2025

Codecov Report

❌ Patch coverage is 96.86684% with 12 lines in your changes missing coverage. Please review.
✅ Project coverage is 97.02%. Comparing base (457b27d) to head (268318a).
⚠️ Report is 1 commits behind head on master.

Files with missing lines Patch % Lines
include/CXXGraph/Graph/IO/InputOperation_impl.hpp 86.95% 9 Missing ⚠️
include/CXXGraph/Graph/IO/OutputOperation_impl.hpp 94.44% 3 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master     #554      +/-   ##
==========================================
- Coverage   97.06%   97.02%   -0.04%     
==========================================
  Files          97       98       +1     
  Lines       11585    11968     +383     
  Branches      768      799      +31     
==========================================
+ Hits        11245    11612     +367     
- Misses        340      356      +16     
Flag Coverage Δ
unittests 97.02% <96.86%> (-0.04%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@ZigRazor ZigRazor linked an issue Oct 23, 2025 that may be closed by this pull request
@ZigRazor ZigRazor merged commit b0b5466 into ZigRazor:master Oct 23, 2025
15 of 20 checks passed
@me-hem me-hem deleted the feature/binary branch October 24, 2025 08:16
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.

Import/export of Graph in Binary File

3 participants